diff options
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 |
commit | c6a5c50f27bdad67d31a31a788b674f5d7ec0dfd (patch) | |
tree | 3f585882b9769b3fde692631db9e52e6003cef43 | |
parent | 8140ea9b158a10b1274295c6af496f4227dbc410 (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.h | 1 | ||||
-rw-r--r-- | src/mame/includes/xbox_nv2a.h | 33 | ||||
-rw-r--r-- | src/mame/machine/xbox.cpp | 21 | ||||
-rw-r--r-- | src/mame/video/xbox_nv2a.cpp | 201 |
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) |