summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author yz70s <yz70s@users.noreply.github.com>2016-12-31 18:44:25 +0100
committer yz70s <yz70s@users.noreply.github.com>2016-12-31 18:47:08 +0100
commitc6a5c50f27bdad67d31a31a788b674f5d7ec0dfd (patch)
tree3f585882b9769b3fde692631db9e52e6003cef43
parent8140ea9b158a10b1274295c6af496f4227dbc410 (diff)
xbox: graphic improvements: (nw)
add support for packed float vertex color r11g11b10f corrected drawing of indexed vertices primitives add "xbox nv2a_wclipping" debug command
-rw-r--r--src/mame/includes/xbox.h1
-rw-r--r--src/mame/includes/xbox_nv2a.h33
-rw-r--r--src/mame/machine/xbox.cpp21
-rw-r--r--src/mame/video/xbox_nv2a.cpp201
4 files changed, 178 insertions, 78 deletions
diff --git a/src/mame/includes/xbox.h b/src/mame/includes/xbox.h
index 6bd4a9cbac0..38748c224bd 100644
--- a/src/mame/includes/xbox.h
+++ b/src/mame/includes/xbox.h
@@ -132,6 +132,7 @@ private:
void threadlist_command(int ref, int params, const char **param);
void generate_irq_command(int ref, int params, const char **param);
void nv2a_combiners_command(int ref, int params, const char **param);
+ void nv2a_wclipping_command(int ref, int params, const char **param);
void waitvblank_command(int ref, int params, const char **param);
void grab_texture_command(int ref, int params, const char **param);
void grab_vprog_command(int ref, int params, const char **param);
diff --git a/src/mame/includes/xbox_nv2a.h b/src/mame/includes/xbox_nv2a.h
index c8f70948202..8f1f83af0c2 100644
--- a/src/mame/includes/xbox_nv2a.h
+++ b/src/mame/includes/xbox_nv2a.h
@@ -102,13 +102,22 @@ public:
// input vertex
vertex_nv *input;
// input parameters
- union constant {
+ struct constant {
float fv[4];
- unsigned int iv[4];
+ void iv(int idx, uint32_t value)
+ {
+ union
+ {
+ uint32_t i;
+ float f;
+ } cnv;
+
+ cnv.i = value;
+ fv[idx] = cnv.f;
+ }
} c_constant[192];
union temp {
float fv[4];
- unsigned int iv[4];
} r_temp[32];
// output vertex
vertex_nv *output;
@@ -224,11 +233,11 @@ public:
TEX3 = 12
};
enum class NV2A_VTXBUF_TYPE {
- UBYTE2 = 0, // what is the difference with UBYTE ?
+ UBYTE_D3D = 0, // what is the difference with opengl UBYTE ?
FLOAT = 2,
- UBYTE = 4,
+ UBYTE_OGL = 4,
USHORT = 5,
- UNKNOWN_6 = 6 // used for vertex color
+ FLOAT_PACKED = 6 // used for vertex color
};
enum class NV2A_TEX_FORMAT {
L8 = 0x0,
@@ -428,7 +437,8 @@ public:
puller_waiting = 0;
debug_grab_texttype = -1;
debug_grab_textfile = nullptr;
- waitvblank_used = 1;
+ enable_waitvblank = true;
+ enable_clipping_w = false;
memset(vertex_attribute_words, 0, sizeof(vertex_attribute_words));
memset(vertex_attribute_offset, 0, sizeof(vertex_attribute_offset));
memset(&persistvertexattr, 0, sizeof(persistvertexattr));
@@ -479,8 +489,9 @@ public:
uint32_t dilate0(uint32_t value, int bits);
uint32_t dilate1(uint32_t value, int bits);
void computedilated(void);
- int toggle_register_combiners_usage();
- int toggle_wait_vblank_support();
+ bool toggle_register_combiners_usage();
+ bool toggle_wait_vblank_support();
+ bool toggle_clipping_w_support();
void debug_grab_texture(int type, const char *filename);
void debug_grab_vertex_program_slot(int slot, uint32_t *instruction);
void start(address_space *cpu_space);
@@ -488,6 +499,7 @@ public:
void compute_supersample_factors(float &horizontal, float &vertical);
void compute_limits_rendertarget(uint32_t chanel, uint32_t subchannel);
void compute_size_rendertarget(uint32_t chanel, uint32_t subchannel);
+ void extract_packed_float(uint32_t data, float &first, float &second, float &third);
void read_vertex(address_space & space, offs_t address, vertex_nv &vertex, int attrib);
int read_vertices_0x1800(address_space & space, vertex_nv *destination, uint32_t address, int limit);
int read_vertices_0x1808(address_space & space, vertex_nv *destination, uint32_t address, int limit);
@@ -743,5 +755,6 @@ public:
nvidia_object_data *objectdata;
int debug_grab_texttype;
char *debug_grab_textfile;
- int waitvblank_used;
+ bool enable_waitvblank;
+ bool enable_clipping_w;
};
diff --git a/src/mame/machine/xbox.cpp b/src/mame/machine/xbox.cpp
index 4405046c13a..753a1406c77 100644
--- a/src/mame/machine/xbox.cpp
+++ b/src/mame/machine/xbox.cpp
@@ -344,18 +344,28 @@ void xbox_base_state::generate_irq_command(int ref, int params, const char **par
void xbox_base_state::nv2a_combiners_command(int ref, int params, const char **param)
{
debugger_console &con = machine().debugger().console();
- int en = nvidia_nv2a->toggle_register_combiners_usage();
- if (en != 0)
+ bool en = nvidia_nv2a->toggle_register_combiners_usage();
+ if (en == true)
con.printf("Register combiners enabled\n");
else
con.printf("Register combiners disabled\n");
}
+void xbox_base_state::nv2a_wclipping_command(int ref, int params, const char **param)
+{
+ debugger_console &con = machine().debugger().console();
+ bool en = nvidia_nv2a->toggle_clipping_w_support();
+ if (en == true)
+ con.printf("W clipping enabled\n");
+ else
+ con.printf("W clipping disabled\n");
+}
+
void xbox_base_state::waitvblank_command(int ref, int params, const char **param)
{
debugger_console &con = machine().debugger().console();
- int en = nvidia_nv2a->toggle_wait_vblank_support();
- if (en != 0)
+ bool en = nvidia_nv2a->toggle_wait_vblank_support();
+ if (en == true)
con.printf("Vblank method enabled\n");
else
con.printf("Vblank method disabled\n");
@@ -458,6 +468,7 @@ void xbox_base_state::help_command(int ref, int params, const char **param)
con.printf(" xbox threadlist -- list of currently active threads\n");
con.printf(" xbox irq,<number> -- Generate interrupt with irq number 0-15\n");
con.printf(" xbox nv2a_combiners -- Toggle use of register combiners\n");
+ con.printf(" xbox nv2a_wclipping -- Toggle use of negative w vertex clipping\n");
con.printf(" xbox waitvblank -- Toggle support for wait vblank method\n");
con.printf(" xbox grab_texture,<type>,<filename> -- Save to <filename> the next used texture of type <type>\n");
con.printf(" xbox grab_vprog,<filename> -- save current vertex program instruction slots to <filename>\n");
@@ -487,6 +498,8 @@ void xbox_base_state::xbox_debug_commands(int ref, int params, const char **para
generate_irq_command(ref, params - 1, param + 1);
else if (strcmp("nv2a_combiners", param[0]) == 0)
nv2a_combiners_command(ref, params - 1, param + 1);
+ else if (strcmp("nv2a_wclipping", param[0]) == 0)
+ nv2a_wclipping_command(ref, params - 1, param + 1);
else if (strcmp("waitvblank", param[0]) == 0)
waitvblank_command(ref, params - 1, param + 1);
else if (strcmp("grab_texture", param[0]) == 0)
diff --git a/src/mame/video/xbox_nv2a.cpp b/src/mame/video/xbox_nv2a.cpp
index 0d0e2a9d6e1..fd3c3888103 100644
--- a/src/mame/video/xbox_nv2a.cpp
+++ b/src/mame/video/xbox_nv2a.cpp
@@ -2216,6 +2216,103 @@ void dumpcombiners(uint32_t *m)
}
#endif
+void nv2a_renderer::extract_packed_float(uint32_t data, float &first, float &second, float &third)
+{
+ int32_t p1, p2, p3;
+ int32_t e1, e2, e3;
+ int32_t m1, m2, m3;
+ float scale, decimal;
+ union
+ {
+ float f;
+ uint32_t i;
+ } i2f;
+
+ // convert r11g11b10f to 3 float values
+ // each 32 bit words contains 2 11 bit float values and one 10 bit float value
+ p1 = data & 0b11111111111;
+ p2 = (data >> 11) & 0b11111111111;
+ p3 = (data >> 22) & 0b1111111111;
+ // 11 bit values have 6 bits of mantissa and 5 of exponent, 10 bit values have 5 bits of mantissa and 5 of exponent
+ m1 = p1 & 0b111111;
+ e1 = (p1 >> 6) & 0b11111;
+ m2 = p2 & 0b111111;
+ e2 = (p2 >> 6) & 0b11111;
+ m3 = p3 & 0b11111;
+ e3 = (p3 >> 5) & 0b11111;
+ // the fopllowing is based on routine UF11toF32 in appendix G of the "OpenGL Programming Guide 8th edition" book
+ if (e1 == 0) {
+ if (m1 != 0) {
+ scale = 1.0 / (1 << 20);
+ first = scale * m1;
+ }
+ else
+ first = 0;
+ }
+ else if (e1 == 31) {
+ i2f.i = 0x7f800000 | m1;
+ first = i2f.f;
+ }
+ else {
+ e1 -= 15;
+ if (e1 < 0) {
+ scale = 1.0 / (1 << -e1);
+ }
+ else {
+ scale = 1 << e1;
+ }
+ decimal = 1.0 + (float)m1 / 64;
+ first = scale * decimal;
+ }
+ if (e2 == 0) {
+ if (m2 != 0) {
+ scale = 1.0 / (1 << 20);
+ second = scale * m2;
+ }
+ else
+ second = 0;
+ }
+ else if (e2 == 31) {
+ i2f.i = 0x7f800000 | m2;
+ second = i2f.f;
+ }
+ else {
+ e2 -= 15;
+ if (e2 < 0) {
+ scale = 1.0 / (1 << -e2);
+ }
+ else {
+ scale = 1 << e2;
+ }
+ decimal = 1.0 + (float)m2 / 64;
+ second = scale * decimal;
+ }
+ if (e3 == 0) {
+ if (m3 != 0) {
+ scale = 1.0 / (1 << 20);
+ third = scale * m3;
+ }
+ else
+ third = 0;
+ }
+ else if (e3 == 31) {
+ i2f.i = 0x7f800000 | m3;
+ third = i2f.f;
+ }
+ else {
+ e3 -= 15;
+ if (e3 < 0) {
+ scale = 1.0 / (1 << -e3);
+ }
+ else {
+ scale = 1 << e3;
+ }
+ decimal = 1.0 + (float)m3 / 32;
+ third = scale * decimal;
+ }
+}
+
+
void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv &vertex, int attrib)
{
uint32_t u;
@@ -2233,26 +2330,24 @@ void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv
d = d + 4;
}
break;
- case NV2A_VTXBUF_TYPE::UBYTE:
+ case NV2A_VTXBUF_TYPE::UBYTE_OGL:
u = space.read_dword(address + 0);
for (c = l-1; c >= 0; c--) {
vertex.attribute[attrib].fv[c] = (u & 0xff) / 255.0;
u = u >> 8;
}
break;
- case NV2A_VTXBUF_TYPE::UBYTE2:
+ case NV2A_VTXBUF_TYPE::UBYTE_D3D:
u = space.read_dword(address + 0);
for (c = 0; c < l; c++) {
vertex.attribute[attrib].fv[c] = (u & 0xff) / 255.0;
u = u >> 8;
}
break;
- case NV2A_VTXBUF_TYPE::UNKNOWN_6: // ???
+ case NV2A_VTXBUF_TYPE::FLOAT_PACKED: // 3 floating point numbers packed into 32 bits
u = space.read_dword(address + 0);
- vertex.attribute[attrib].fv[0] = (u & 0xff) / 255.0; // b
- vertex.attribute[attrib].fv[1] = ((u & 0xff00) >> 8) / 255.0; // g
- vertex.attribute[attrib].fv[2] = ((u & 0xff0000) >> 16) / 255.0; // r
- vertex.attribute[attrib].fv[3] = ((u & 0xff000000) >> 24) / 255.0; // a
+ extract_packed_float(u, vertex.attribute[attrib].fv[0], vertex.attribute[attrib].fv[1], vertex.attribute[attrib].fv[2]);
+ vertex.attribute[attrib].fv[3] = 1.0;
break;
default:
vertex.attribute[attrib].fv[0] = 0;
@@ -2266,24 +2361,13 @@ void nv2a_renderer::read_vertex(address_space & space, offs_t address, vertex_nv
/* Read vertices data from system memory. Method 0x1800 */
int nv2a_renderer::read_vertices_0x1800(address_space & space, vertex_nv *destination, uint32_t address, int limit)
{
- uint32_t data;
- uint32_t m, i, c;
+ uint32_t m;
int a, b;
#ifdef MAME_DEBUG
memset(destination, 0, sizeof(vertex_nv)*limit);
#endif
- c = 0;
for (m = 0; m < limit; m++) {
- if (indexesleft_count == 0) {
- data = space.read_dword(address);
- i = indexesleft_first + indexesleft_count;
- indexesleft[i & 1023] = data & 0xffff;
- indexesleft[(i + 1) & 1023] = (data >> 16) & 0xffff;
- indexesleft_count = indexesleft_count + 2;
- address += 4;
- c++;
- }
memcpy(&destination[m], &persistvertexattr, sizeof(persistvertexattr));
b = enabled_vertex_attributes;
for (a = 0; a < 16; a++) {
@@ -2295,29 +2379,19 @@ int nv2a_renderer::read_vertices_0x1800(address_space & space, vertex_nv *destin
indexesleft_first = (indexesleft_first + 1) & 1023;
indexesleft_count--;
}
- return (int)c;
+ return limit;
}
/* Read vertices data from system memory. Method 0x1808 */
int nv2a_renderer::read_vertices_0x1808(address_space & space, vertex_nv *destination, uint32_t address, int limit)
{
- uint32_t data;
- uint32_t m, i, c;
+ uint32_t m;
int a, b;
#ifdef MAME_DEBUG
memset(destination, 0, sizeof(vertex_nv)*limit);
#endif
- c = 0;
for (m = 0; m < limit; m++) {
- if (indexesleft_count == 0) {
- data = space.read_dword(address);
- i = indexesleft_first + indexesleft_count;
- indexesleft[i & 1023] = data;
- indexesleft_count = indexesleft_count + 1;
- address += 4;
- c++;
- }
memcpy(&destination[m], &persistvertexattr, sizeof(persistvertexattr));
b = enabled_vertex_attributes;
for (a = 0; a < 16; a++) {
@@ -2329,7 +2403,7 @@ int nv2a_renderer::read_vertices_0x1808(address_space & space, vertex_nv *destin
indexesleft_first = (indexesleft_first + 1) & 1023;
indexesleft_count--;
}
- return (int)c;
+ return limit;
}
/* Read vertices data from system memory. Method 0x1810 */
@@ -2753,15 +2827,16 @@ int nv2a_renderer::clip_triangle_w(nv2avertex_t *vi[3], nv2avertex_t *vo)
uint32_t nv2a_renderer::render_triangle_clipping(const rectangle &cliprect, render_delegate callback, int paramcount, nv2avertex_t &_v1, nv2avertex_t &_v2, nv2avertex_t &_v3)
{
-#if 0
nv2avertex_t *vi[3];
- nv2avertex_t vo[16];
+ nv2avertex_t vo[8];
int nv;
-#endif
if ((_v1.w > 0) && (_v2.w > 0) && (_v3.w > 0))
return render_triangle_culling(cliprect, callback, paramcount, _v1, _v2, _v3);
-#if 0
+ if (enable_clipping_w == false)
+ return 0;
+ if ((_v1.w <= 0) && (_v2.w <= 0) && (_v3.w <= 0))
+ return 0;
// assign the elements of the array
vi[0] = &_v1;
vi[1] = &_v2;
@@ -2816,7 +2891,6 @@ uint32_t nv2a_renderer::render_triangle_clipping(const rectangle &cliprect, rend
}
for (int n = 1; n <= (nv - 2); n++)
render_triangle_culling(cliprect, callback, paramcount, vo[0], vo[n], vo[n + 1]);
-#endif
return 0;
}
@@ -2930,6 +3004,7 @@ void nv2a_renderer::assemble_primitive(vertex_nv *source, int count, render_dele
machine().logerror("Unsupported primitive %d\n", int(primitive_type));
vertex_count++;
}
+ source++;
}
primitives_total_count += primitives_count - pc;
}
@@ -3028,20 +3103,6 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
// vertices are selected from the vertex buffer using an array of indexes
// each dword after 1800 contains two 16 bit index values to select the vartices
// each dword after 1808 contains a 32 bit index value to select the vartices
- while (1) {
- int c;
-
- if ((countlen * mult + indexesleft_count) < 4)
- break;
- if (mult == 1)
- c = read_vertices_0x1808(space, vertex_software + vertex_first, address, 1);
- else
- c = read_vertices_0x1800(space, vertex_software + vertex_first, address, 1);
- address = address + c * 4;
- countlen = countlen - c;
- assemble_primitive(vertex_software + vertex_first, 1, render_spans_callback);
- vertex_first = (vertex_first + 4) & 1023;
- }
while (countlen > 0) {
int n;
@@ -3058,6 +3119,12 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
}
address += 4;
countlen--;
+ if (mult == 1)
+ read_vertices_0x1808(space, vertex_software + vertex_first, address, 1);
+ else
+ read_vertices_0x1800(space, vertex_software + vertex_first, address, 2);
+ assemble_primitive(vertex_software + vertex_first, mult, render_spans_callback);
+ vertex_first = (vertex_first + mult) & 1023;
}
}
if (maddress == 0x1818) {
@@ -3078,7 +3145,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
}
address = address + c * 4;
assemble_primitive(vertex_software + vertex_first, 1, render_spans_callback);
- vertex_first = (vertex_first + 4) & 1023;
+ vertex_first = (vertex_first + 1) & 1023;
}
}
if ((maddress >= 0x1880) && (maddress < 0x1900))
@@ -3175,19 +3242,19 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
vertexbuffer_kind[bit] = (NV2A_VTXBUF_TYPE)(data & 15);
vertexbuffer_size[bit] = (data >> 4) & 15;
switch (vertexbuffer_kind[bit]) {
- case NV2A_VTXBUF_TYPE::UBYTE2:
+ case NV2A_VTXBUF_TYPE::UBYTE_D3D:
vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 1) >> 2;
break;
case NV2A_VTXBUF_TYPE::FLOAT:
vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 4) >> 2;
break;
- case NV2A_VTXBUF_TYPE::UBYTE:
+ case NV2A_VTXBUF_TYPE::UBYTE_OGL:
vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 1) >> 2;
break;
case NV2A_VTXBUF_TYPE::USHORT:
vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 2) >> 2;
break;
- case NV2A_VTXBUF_TYPE::UNKNOWN_6:
+ case NV2A_VTXBUF_TYPE::FLOAT_PACKED:
vertex_attribute_words[bit] = (vertexbuffer_size[bit] * 4) >> 2;
break;
default:
@@ -3345,7 +3412,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
}
if (maddress == 0x0130) {
countlen--;
- if (waitvblank_used == 1)
+ if (enable_waitvblank == true)
return 1; // block until next vblank
else
return 0;
@@ -3617,7 +3684,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
maddress = (maddress - 0x0a20) / 4;
*(uint32_t *)(&matrix.translate[maddress]) = data;
// set corresponding vertex shader constant too
- vertexprogram.exec.c_constant[59].iv[maddress] = data; // constant -37
+ vertexprogram.exec.c_constant[59].iv(maddress, data); // constant -37
#ifdef LOG_NV2A
if (maddress == 3)
machine().logerror("viewport translate = {%f %f %f %f}\n", matrix.translate[0], matrix.translate[1], matrix.translate[2], matrix.translate[3]);
@@ -3629,7 +3696,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
maddress = (maddress - 0x0af0) / 4;
*(uint32_t *)(&matrix.scale[maddress]) = data;
// set corresponding vertex shader constant too
- vertexprogram.exec.c_constant[58].iv[maddress] = data; // constant -38
+ vertexprogram.exec.c_constant[58].iv(maddress, data); // constant -38
#ifdef LOG_NV2A
if (maddress == 3)
machine().logerror("viewport scale = {%f %f %f %f}\n", matrix.scale[0], matrix.scale[1], matrix.scale[2], matrix.scale[3]);
@@ -3688,7 +3755,7 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
if ((maddress >= 0x0b80) && (maddress < 0x0c00)) {
//machine().logerror("VP_UPLOAD_CONST\n");
if (vertexprogram.upload_parameter_index < 192) {
- vertexprogram.exec.c_constant[vertexprogram.upload_parameter_index].iv[vertexprogram.upload_parameter_component] = data;
+ vertexprogram.exec.c_constant[vertexprogram.upload_parameter_index].iv(vertexprogram.upload_parameter_component, data);
}
else
machine().logerror("Need to increase size of vertexprogram.parameter to %d\n\r", vertexprogram.upload_parameter_index);
@@ -3831,16 +3898,22 @@ int nv2a_renderer::geforce_exec_method(address_space & space, uint32_t chanel, u
return 0;
}
-int nv2a_renderer::toggle_register_combiners_usage()
+bool nv2a_renderer::toggle_register_combiners_usage()
{
combiner.used = 1 - combiner.used;
- return combiner.used;
+ return combiner.used != 0;
+}
+
+bool nv2a_renderer::toggle_wait_vblank_support()
+{
+ enable_waitvblank = !enable_waitvblank;
+ return enable_waitvblank;
}
-int nv2a_renderer::toggle_wait_vblank_support()
+bool nv2a_renderer::toggle_clipping_w_support()
{
- waitvblank_used = 1 - waitvblank_used;
- return waitvblank_used;
+ enable_clipping_w = !enable_clipping_w;
+ return enable_clipping_w;
}
void nv2a_renderer::debug_grab_texture(int type, const char *filename)