diff options
Diffstat (limited to 'src/mame/video/rdptpipe.c')
-rw-r--r-- | src/mame/video/rdptpipe.c | 630 |
1 files changed, 590 insertions, 40 deletions
diff --git a/src/mame/video/rdptpipe.c b/src/mame/video/rdptpipe.c index d574cd13133..b69384cc84e 100644 --- a/src/mame/video/rdptpipe.c +++ b/src/mame/video/rdptpipe.c @@ -59,8 +59,565 @@ void n64_texture_pipe_t::set_machine(running_machine &machine) } } + m_log2_table[0] = m_log2_table[1] = 0; + for (INT32 i = 2; i < 256; i++) + { + for (INT32 k = 7; k > 0; k--) + { + if ((i >> k) & 1) + { + m_log2_table[i] = k; + break; + } + } + } + m_st2_add.set(1, 0, 1, 0); m_v1.set(1, 1, 1, 1); + m_yuv1.set(1, 0, 0, 0); +} + +void n64_texture_pipe_t::tclod_tcclamp(INT32* sss, INT32* sst) +{ + INT32 temps = *sss; + INT32 tempt = *sst; + + if (!(temps & 0x40000)) + { + if (!(temps & 0x20000)) + { + const INT32 tempanded = temps & 0x18000; + if (tempanded != 0x8000) + { + if (tempanded != 0x10000) + { + *sss &= 0xffff; + } + else + { + *sss = 0x8000; + } + } + else + { + *sss = 0x7fff; + } + } + else + { + *sss = 0x8000; + } + } + else + { + *sss = 0x7fff; + } + + if (!(tempt & 0x40000)) + { + if (!(tempt & 0x20000)) + { + const INT32 tempanded = tempt & 0x18000; + if (tempanded != 0x8000) + { + if (tempanded != 0x10000) + { + *sst &= 0xffff; + } + else + { + *sst = 0x8000; + } + } + else + { + *sst = 0x7fff; + } + } + else + { + *sst = 0x8000; + } + } + else + { + *sst = 0x7fff; + } +} + +void n64_texture_pipe_t::tclod_1cycle_current(INT32* sss, INT32* sst, INT32 nexts, INT32 nextt, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1, rdp_span_aux* userdata, const rdp_poly_state& object) +{ + tclod_tcclamp(sss, sst); + + if (object.m_mode_derivs.m_do_lod) + { + INT32 fars, fart, farw; + if (userdata->m_next_valid) + { + if (!userdata->m_end_span || !userdata->m_long_span) + { + if (!(userdata->m_pre_end_span && userdata->m_long_span) && !(userdata->m_end_span && userdata->m_mid_span)) + { + fars = (s + (dsinc << 1)) >> 16; + fart = (t + (dtinc << 1)) >> 16; + farw = (w + (dwinc << 1)) >> 16; + } + else + { + fars = (s - dsinc) >> 16; + fart = (t - dtinc) >> 16; + farw = (w - dwinc) >> 16; + } + } + else + { + fars = (userdata->m_next_s + dsinc) >> 16; + fart = (userdata->m_next_t + dtinc) >> 16; + farw = (userdata->m_next_w + dwinc) >> 16; + } + } + else + { + fars = (s + (dsinc << 1)) >> 16; + fart = (t + (dtinc << 1)) >> 16; + farw = (w + (dwinc << 1)) >> 16; + } + + if (object.m_other_modes.persp_tex_en) + { + m_rdp->tc_div(fars, fart, farw, &fars, &fart); + } + else + { + m_rdp->tc_div_no_perspective(fars, fart, farw, &fars, &fart); + } + + const bool lodclamp = ((fars | nexts | fart | nextt) & 0x60000) ? true : false; + + INT32 lod; + tclod_4x17_to_15(nexts, fars, nextt, fart, 0, &lod); + + bool magnify, distant; + UINT32 l_tile; + lodfrac_lodtile_signals(lodclamp, lod, &l_tile, &magnify, &distant, userdata, object); + + if (object.m_other_modes.tex_lod_en) + { + if (distant) + { + l_tile = object.m_misc_state.m_max_level; + } + + if (object.m_other_modes.detail_tex_en || magnify) + { + *t1 = (prim_tile + l_tile) & 7; + } + else + { + *t1 = (prim_tile + l_tile + 1) & 7; + } + } + } +} + +void n64_texture_pipe_t::tclod_2cycle_current(INT32* sss, INT32* sst, INT32 nexts, INT32 nextt, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1, INT32* t2, rdp_span_aux* userdata, const rdp_poly_state& object) +{ + tclod_tcclamp(sss, sst); + + if (object.m_mode_derivs.m_do_lod) + { + INT32 nextys = (s + object.m_span_base.m_span_dsdy) >> 16; + INT32 nextyt = (t + object.m_span_base.m_span_dtdy) >> 16; + INT32 nextyw = (w + object.m_span_base.m_span_dwdy) >> 16; + + if (object.m_other_modes.persp_tex_en) + { + m_rdp->tc_div(nextys, nextyt, nextyw, &nextys, &nextyt); + } + else + { + m_rdp->tc_div_no_perspective(nextys, nextyt, nextyw, &nextys, &nextyt); + } + + INT32 inits = *sss; + INT32 initt = *sst; + const bool lodclamp = ((inits | nexts | nextys | initt | nextt | nextyt) & 0x60000) ? true : false; + + INT32 lod; + tclod_4x17_to_15(inits, nexts, initt, nextt, 0, &lod); + tclod_4x17_to_15(inits, nextys, initt, nextyt, lod, &lod); + + bool magnify, distant; + UINT32 l_tile; + lodfrac_lodtile_signals(lodclamp, lod, &l_tile, &magnify, &distant, userdata, object); + + if (object.m_other_modes.tex_lod_en) + { + if (distant) + { + l_tile = object.m_misc_state.m_max_level; + } + + if (!object.m_other_modes.detail_tex_en) + { + *t1 = (prim_tile + l_tile) & 7; + if (!(distant || (!object.m_other_modes.sharpen_tex_en && magnify))) + { + *t2 = (*t1 + 1) & 7; + } + else + { + *t2 = *t1; + } + } + else + { + if (!magnify) + { + *t1 = prim_tile + l_tile + 1; + } + else + { + *t1 = prim_tile + l_tile; + } + *t1 &= 7; + + if (!distant && !magnify) + { + *t2 = prim_tile + l_tile + 2; + } + else + { + *t2 = prim_tile + l_tile + 1; + } + *t2 &= 7; + } + } + } +} + +void n64_texture_pipe_t::tclod_1cycle_next(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1, INT32* pre_lod_frac, rdp_span_aux* userdata, const rdp_poly_state& object) +{ + tclod_tcclamp(sss, sst); + + if (object.m_mode_derivs.m_do_lod) + { + INT32 nexts, nextt, nextw, fars, fart, farw; + if (userdata->m_next_valid) + { + if (userdata->m_next_span) + { + if (!userdata->m_end_span || !userdata->m_long_span) + { + nexts = (s + dsinc)>> 16; + nextt = (t + dtinc)>> 16; + nextw = (w + dwinc)>> 16; + + if (!(userdata->m_pre_end_span && userdata->m_long_span) && !(userdata->m_end_span && userdata->m_mid_span)) + { + fars = (s + (dsinc << 1)) >> 16; + fart = (t + (dtinc << 1)) >> 16; + farw = (w + (dwinc << 1)) >> 16; + } + else + { + fars = (s - dsinc) >> 16; + fart = (t - dtinc) >> 16; + farw = (w - dwinc) >> 16; + } + } + else + { + nexts = userdata->m_next_s; + nextt = userdata->m_next_t; + nextw = userdata->m_next_w; + + fars = (nexts + dsinc) >> 16; + fart = (nextt + dtinc) >> 16; + farw = (nextw + dwinc) >> 16; + + nexts >>= 16; + nextt >>= 16; + nextw >>= 16; + } + } + else + { + if (!userdata->m_almost_mid_span) + { + nexts = userdata->m_next_s + dsinc; + nextt = userdata->m_next_t + dtinc; + nextw = userdata->m_next_w + dwinc; + + fars = (nexts + dsinc) >> 16; + fart = (nextt + dtinc) >> 16; + farw = (nextw + dwinc) >> 16; + + nexts >>= 16; + nextt >>= 16; + nextw >>= 16; + } + else + { + nexts = (s + dsinc) >> 16; + nextt = (t + dtinc) >> 16; + nextw = (w + dwinc) >> 16; + + fars = (s - dsinc) >> 16; + fart = (t - dtinc) >> 16; + farw = (w - dwinc) >> 16; + } + } + } + else + { + nexts = (s + dsinc) >> 16; + nextt = (t + dtinc) >> 16; + nextw = (w + dwinc) >> 16; + + fars = (s + (dsinc << 1)) >> 16; + fart = (t + (dtinc << 1)) >> 16; + farw = (w + (dwinc << 1)) >> 16; + } + + if (object.m_other_modes.persp_tex_en) + { + m_rdp->tc_div(fars, fart, farw, &fars, &fart); + m_rdp->tc_div(nexts, nextt, nextw, &nexts, &nextt); + } + else + { + m_rdp->tc_div_no_perspective(fars, fart, farw, &fars, &fart); + m_rdp->tc_div_no_perspective(nexts, nextt, nextw, &nexts, &nextt); + } + + const bool lodclamp = ((fars | nexts | fart | nextt) & 0x60000) ? true : false; + + INT32 lod; + tclod_4x17_to_15(nexts, fars, nextt, fart, 0, &lod); + + if ((lod & 0x4000) || lodclamp) + { + lod = 0x7fff; + } + else if (lod < object.m_misc_state.m_min_level) + { + lod = object.m_misc_state.m_min_level; + } + + const bool magnify = (lod < 32); + UINT32 l_tile = m_log2_table[(lod >> 5) & 0xff]; + const bool distant = (lod & 0x6000) || (l_tile >= object.m_misc_state.m_max_level); + + *pre_lod_frac = ((lod << 3) >> l_tile) & 0xff; + + if (!object.m_other_modes.sharpen_tex_en && !object.m_other_modes.detail_tex_en) + { + if (distant) + { + *pre_lod_frac = 0xff; + } + else + { + *pre_lod_frac = 0; + } + } + + if (object.m_other_modes.sharpen_tex_en && magnify) + { + *pre_lod_frac |= 0x100; + } + + if (object.m_other_modes.tex_lod_en) + { + if (distant) + { + l_tile = object.m_misc_state.m_max_level; + } + + if (!object.m_other_modes.detail_tex_en || magnify) + { + *t1 = (prim_tile + l_tile) & 7; + } + else + { + *t1 = (prim_tile + l_tile + 1) & 7; + } + } + } +} + +void n64_texture_pipe_t::tclod_2cycle_next(INT32* sss, INT32* sst, INT32 s, INT32 t, INT32 w, INT32 dsinc, INT32 dtinc, INT32 dwinc, INT32 prim_tile, INT32* t1, INT32* t2, INT32* pre_lod_frac, rdp_span_aux* userdata, const rdp_poly_state& object) +{ + tclod_tcclamp(sss, sst); + + if (object.m_mode_derivs.m_do_lod) + { + INT32 inits = *sss; + INT32 initt = *sst; + + INT32 nexts = (s + dsinc) >> 16; + INT32 nextt = (t + dtinc) >> 16; + INT32 nextw = (w + dwinc) >> 16; + + INT32 nextys = (s + object.m_span_base.m_span_dsdy) >> 16; + INT32 nextyt = (t + object.m_span_base.m_span_dtdy) >> 16; + INT32 nextyw = (w + object.m_span_base.m_span_dwdy) >> 16; + + if (object.m_other_modes.persp_tex_en) + { + m_rdp->tc_div(nexts, nextt, nextw, &nexts, &nextt); + m_rdp->tc_div(nextys, nextyt, nextyw, &nextys, &nextyt); + } + else + { + m_rdp->tc_div_no_perspective(nexts, nextt, nextw, &nexts, &nextt); + m_rdp->tc_div_no_perspective(nextys, nextyt, nextyw, &nextys, &nextyt); + } + + const bool lodclamp = ((inits | nexts | nextys | initt | nextt | nextyt) & 0x60000) ? true : false; + + INT32 lod; + tclod_4x17_to_15(inits, nexts, initt, nextt, 0, &lod); + tclod_4x17_to_15(inits, nextys, initt, nextyt, lod, &lod); + + if ((lod & 0x4000) || lodclamp) + { + lod = 0x7fff; + } + else if (lod < object.m_misc_state.m_min_level) + { + lod = object.m_misc_state.m_min_level; + } + + const bool magnify = (lod < 32); + UINT32 l_tile = m_log2_table[(lod >> 5) & 0xff]; + const bool distant = (lod & 0x6000) || (l_tile >= object.m_misc_state.m_max_level); + + *pre_lod_frac = ((lod << 3) >> l_tile) & 0xff; + + if (!object.m_other_modes.sharpen_tex_en && !object.m_other_modes.detail_tex_en) + { + if (distant) + { + *pre_lod_frac = 0xff; + } + else + { + *pre_lod_frac = 0; + } + } + + if (object.m_other_modes.sharpen_tex_en && magnify) + { + *pre_lod_frac |= 0x100; + } + + if (object.m_other_modes.tex_lod_en) + { + if (distant) + { + l_tile = object.m_misc_state.m_max_level; + } + + if (!object.m_other_modes.detail_tex_en) + { + *t1 = (prim_tile + l_tile) & 7; + if (!(distant || (!object.m_other_modes.sharpen_tex_en && magnify))) + { + *t2 = (*t1 + 1) & 7; + } + else + { + *t2 = *t1; + } + } + else + { + if (!magnify) + { + *t1 = prim_tile + l_tile + 1; + } + else + { + *t1 = prim_tile + l_tile; + } + *t1 &= 7; + + if (!distant && !magnify) + { + *t2 = prim_tile + l_tile + 2; + } + else + { + *t2 = prim_tile + l_tile + 1; + } + *t2 &= 7; + } + } + } +} + +void n64_texture_pipe_t::lodfrac_lodtile_signals(bool lodclamp, INT32 lod, UINT32* l_tile, bool* magnify, bool* distant, rdp_span_aux* userdata, const rdp_poly_state& object) +{ + if ((lod & 0x4000) || lodclamp) + { + lod = 0x7fff; + } + else if (lod < object.m_misc_state.m_min_level) + { + lod = object.m_misc_state.m_min_level; + } + + const bool mag = (lod < 32); + UINT32 ltil = m_log2_table[(lod >> 5) & 0xff]; + const bool dis = (lod & 0x6000) || (ltil >= object.m_misc_state.m_max_level); + + INT32 lf = ((lod << 3) >> ltil) & 0xff; + + if (object.m_other_modes.sharpen_tex_en && !object.m_other_modes.detail_tex_en) + { + if (dis) + { + lf = 0xff; + } + else + { + lf = 0; + } + } + + if (object.m_other_modes.sharpen_tex_en && mag) + { + lf |= 0x100; + } + + *distant = dis; + *l_tile = ltil; + *magnify = mag; + userdata->m_lod_fraction.set(lf, lf, lf, lf); +} + +void n64_texture_pipe_t::tclod_4x17_to_15(INT32 scurr, INT32 snext, INT32 tcurr, INT32 tnext, INT32 previous, INT32* lod) +{ + INT32 dels = SIGN17(snext) - SIGN17(scurr); + INT32 delt = SIGN17(tnext) - SIGN17(tcurr); + if (dels & 0x20000) + { + dels = ~dels & 0x1ffff; + } + if (delt & 0x20000) + { + delt = ~delt & 0x1ffff; + } + + dels = (dels > delt) ? dels : delt; + dels = (previous > dels) ? previous : dels; + *lod = dels & 0x7fff; + if (dels & 0x1c000) + { + *lod |= 0x4000; + } } void n64_texture_pipe_t::mask(rgbaint_t& sstt, const n64_tile_t& tile) @@ -197,14 +754,17 @@ void n64_texture_pipe_t::cycle_nearest(color_t* TEX, color_t* prev, INT32 SSS, I t0.set(*prev); } - t0.sign_extend(0x00000100, 0xffffff00); + if (tile.format == FORMAT_YUV) + { + t0.sign_extend(0x00000100, 0xffffff00); + } - rgbaint_t k1r(m_rdp->get_k1()); - k1r.mul_imm(t0.get_r32()); + rgbaint_t k13r(m_rdp->get_k13()); + k13r.mul_imm(t0.get_r32()); - TEX->set(m_rdp->get_k023()); + TEX->set(m_rdp->get_k02()); TEX->mul_imm(t0.get_g32()); - TEX->add(k1r); + TEX->add(k13r); TEX->add_imm(0x80); TEX->shr_imm(8); TEX->add_imm(t0.get_b32()); @@ -224,6 +784,12 @@ void n64_texture_pipe_t::cycle_nearest_lerp(color_t* TEX, color_t* prev, INT32 S UINT32 tbase = tile.tmem + ((tile.line * st.get_b32()) & 0x1ff); ((this)->*(m_texel_fetch[index]))(*TEX, st.get_r32(), st.get_b32(), tbase, tile.palette, userdata); + + if (object.m_other_modes.convert_one && cycle) + { + const UINT32 prev_b = prev->get_b32(); + TEX->set(prev_b, prev_b, prev_b, prev_b); + } } void n64_texture_pipe_t::cycle_linear(color_t* TEX, color_t* prev, INT32 SSS, INT32 SST, UINT32 tilenum, UINT32 cycle, rdp_span_aux* userdata, const rdp_poly_state& object) @@ -242,22 +808,6 @@ void n64_texture_pipe_t::cycle_linear(color_t* TEX, color_t* prev, INT32 SSS, IN const UINT32 tbase = tile.tmem + ((tile.line * st.get_b32()) & 0x1ff); - bool upper = ((stfrac.get_r32() + stfrac.get_b32()) >= 0x20); - - rgbaint_t invstf; - if (upper) - { - invstf.set(stfrac); - invstf.subr_imm(0x20); - invstf.shl_imm(3); - } - else - { - invstf.set(0, 0, 0, 0); - } - - stfrac.shl_imm(3); - rgbaint_t t0; ((this)->*(m_texel_fetch[index]))(t0, st.get_r32(), st.get_b32(), tbase, tile.palette, userdata); if (object.m_other_modes.convert_one && cycle) @@ -267,12 +817,12 @@ void n64_texture_pipe_t::cycle_linear(color_t* TEX, color_t* prev, INT32 SSS, IN t0.sign_extend(0x00000100, 0xffffff00); - rgbaint_t k1r(m_rdp->get_k1()); - k1r.mul_imm(t0.get_r32()); + rgbaint_t k13r(m_rdp->get_k13()); + k13r.mul_imm(t0.get_r32()); - TEX->set(m_rdp->get_k023()); + TEX->set(m_rdp->get_k02()); TEX->mul_imm(t0.get_g32()); - TEX->add(k1r); + TEX->add(k13r); TEX->add_imm(0x80); TEX->shr_imm(8); TEX->add_imm(t0.get_b32()); @@ -300,28 +850,22 @@ void n64_texture_pipe_t::cycle_linear_lerp(color_t* TEX, color_t* prev, INT32 SS const UINT32 tbase1 = tile.tmem + ((tile.line * sstt.get_b32()) & 0x1ff); const UINT32 tbase2 = tile.tmem + ((tile.line * sstt.get_g32()) & 0x1ff); - bool upper = ((stfrac.get_r32() + stfrac.get_b32()) >= 0x20); - - rgbaint_t invstf; - if (upper) - { - invstf.set(stfrac); - invstf.subr_imm(0x20); - invstf.shl_imm(3); - } - - stfrac.shl_imm(3); - - bool center = (stfrac.get_r32() == 0x10) && (stfrac.get_b32() == 0x10) && object.m_other_modes.mid_texel; + const UINT32 sfrac = stfrac.get_r32(); + const UINT32 tfrac = stfrac.get_b32(); rgbaint_t t2; ((this)->*(m_texel_fetch[index]))(*TEX, sstt.get_a32(), sstt.get_b32(), tbase1, tpal, userdata); ((this)->*(m_texel_fetch[index]))(t2, sstt.get_r32(), sstt.get_g32(), tbase2, tpal, userdata); - if (!center) + if ((sfrac != 0x10) || (tfrac != 0x10) || !object.m_other_modes.mid_texel) { - if (upper) + if ((sfrac + tfrac) >= 0x20) { + rgbaint_t invstf(stfrac); + invstf.set(stfrac); + invstf.subr_imm(0x20); + invstf.shl_imm(3); + rgbaint_t t3; ((this)->*(m_texel_fetch[index]))(t3, sstt.get_a32(), sstt.get_g32(), tbase2, tpal, userdata); @@ -338,6 +882,8 @@ void n64_texture_pipe_t::cycle_linear_lerp(color_t* TEX, color_t* prev, INT32 SS } else { + stfrac.shl_imm(3); + rgbaint_t t0; ((this)->*(m_texel_fetch[index]))(t0, sstt.get_r32(), sstt.get_b32(), tbase1, tpal, userdata); @@ -647,6 +1193,10 @@ void n64_texture_pipe_t::lod_2cycle_limited(INT32* sss, INT32* sst, const INT32 void n64_texture_pipe_t::calculate_clamp_diffs(UINT32 prim_tile, rdp_span_aux* userdata, const rdp_poly_state& object) { + if (userdata == NULL) + { + printf("Whoa, userdata is NULL!\n"); fflush(stdout); + } const n64_tile_t* tiles = object.m_tiles; if (object.m_other_modes.cycle_type == CYCLE_TYPE_2) { |