diff options
Diffstat (limited to 'src/mame/video/xbox_nv2a.cpp')
-rw-r--r-- | src/mame/video/xbox_nv2a.cpp | 201 |
1 files changed, 137 insertions, 64 deletions
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) |