From 68ab68d17bf3f44d8e97de74e5932c57e59131eb Mon Sep 17 00:00:00 2001 From: "therealmogminer@gmail.com" Date: Fri, 31 Jul 2015 23:44:38 +0200 Subject: nw, initial merge of angrylion's RDP changes. --- src/mame/video/n64.c | 1581 +++++++++++++++++++++++++++++---------------- src/mame/video/n64.h | 64 +- src/mame/video/n64types.h | 52 +- src/mame/video/rdptpipe.c | 630 ++++++++++++++++-- src/mame/video/rdptpipe.h | 9 + 5 files changed, 1720 insertions(+), 616 deletions(-) diff --git a/src/mame/video/n64.c b/src/mame/video/n64.c index 6bac63f5745..0515f4543e5 100644 --- a/src/mame/video/n64.c +++ b/src/mame/video/n64.c @@ -361,6 +361,7 @@ INT32 n64_rdp::alpha_combiner_equation(INT32 a, INT32 b, INT32 c, INT32 d) void n64_rdp::set_suba_input_rgb(color_t** input, INT32 code, rdp_span_aux* userdata) { + userdata->m_noise_used = false; switch (code & 0xf) { case 0: *input = &userdata->m_combined_color; break; @@ -370,7 +371,7 @@ void n64_rdp::set_suba_input_rgb(color_t** input, INT32 code, rdp_span_aux* user case 4: *input = &userdata->m_shade_color; break; case 5: *input = &userdata->m_env_color; break; case 6: *input = &m_one; break; - case 7: *input = &userdata->m_noise_color; break; + case 7: *input = &userdata->m_noise_color; userdata->m_noise_used = true; break; case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: { *input = &m_zero; break; @@ -706,12 +707,6 @@ void n64_rdp::precalc_cvmask_derivatives(void) const UINT8 yarray[16] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; const UINT8 xarray[16] = {0, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; - for (INT32 i = 0; i < 0x10000; i++) - { - m_compressed_cvmasks[i] = (i & 1) | ((i & 4) >> 1) | ((i & 0x20) >> 3) | ((i & 0x80) >> 4) | - ((i & 0x100) >> 4) | ((i & 0x400) >> 5) | ((i & 0x2000) >> 7) | ((i & 0x8000) >> 8); - } - for (INT32 i = 0; i < 0x100; i++) { UINT16 mask = decompress_cvmask_frombyte(i); @@ -739,31 +734,21 @@ void n64_rdp::precalc_cvmask_derivatives(void) UINT16 n64_rdp::decompress_cvmask_frombyte(UINT8 x) { - UINT16 y = (x & 1) | ((x & 2) << 1) | ((x & 4) << 3) | ((x & 8) << 4) | - ((x & 0x10) << 4) | ((x & 0x20) << 5) | ((x & 0x40) << 7) | ((x & 0x80) << 8); - return y; + return (x & 1) | ((x & 2) << 4) | (x & 4) | ((x & 8) << 4) | ((x & 0x10) << 4) | ((x & 0x20) << 8) | ((x & 0x40) << 4) | ((x & 0x80) << 8); } void n64_rdp::lookup_cvmask_derivatives(UINT32 mask, UINT8* offx, UINT8* offy, rdp_span_aux* userdata) { - const UINT32 index = m_compressed_cvmasks[mask]; - userdata->m_current_pix_cvg = cvarray[index].cvg; - userdata->m_current_cvg_bit = cvarray[index].cvbit; - *offx = cvarray[index].xoff; - *offy = cvarray[index].yoff; + userdata->m_current_pix_cvg = cvarray[mask].cvg; + userdata->m_current_cvg_bit = cvarray[mask].cvbit; + *offx = cvarray[mask].xoff; + *offy = cvarray[mask].yoff; } -void n64_rdp::z_store(const rdp_poly_state &object, UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z, UINT32 enc) +void n64_rdp::z_store(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z, UINT32 dzpix_enc) { - UINT16 zval = m_z_com_table[z & 0x3ffff]|(enc >> 2); - if(zcurpixel <= MEM16_LIMIT) - { - ((UINT16*)rdram)[zcurpixel ^ WORD_ADDR_XOR] = zval; - } - if(dzcurpixel <= MEM8_LIMIT) - { - m_hidden_bits[dzcurpixel ^ BYTE_ADDR_XOR] = enc & 3; - } + RWRITEIDX16(zcurpixel, m_z_com_table[z & 0x3ffff] | (dzpix_enc >> 2)); + HWRITEADDR8(dzcurpixel, dzpix_enc & 3); } INT32 n64_rdp::normalize_dzpix(INT32 sum) @@ -776,6 +761,10 @@ INT32 n64_rdp::normalize_dzpix(INT32 sum) { return 1; } + if (sum == 1) + { + return 3; + } for(INT32 count = 0x2000; count > 0; count >>= 1) { if (sum & count) @@ -791,18 +780,25 @@ UINT32 n64_rdp::z_decompress(UINT32 zcurpixel) return m_z_complete_dec_table[(RREADIDX16(zcurpixel) >> 2) & 0x3fff]; } -UINT32 n64_rdp::dz_decompress(UINT32 zcurpixel, UINT32 dzcurpixel) -{ - const UINT16 zval = RREADIDX16(zcurpixel); - const UINT8 dzval = (((dzcurpixel) <= 0x7fffff) ? (m_hidden_bits[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0); - const UINT32 dz_compressed = ((zval & 3) << 2) | (dzval & 3); - return (1 << dz_compressed); -} - UINT32 n64_rdp::dz_compress(UINT32 value) { INT32 j = 0; - for (; value > 1; j++, value >>= 1); + if (value & 0xff00) + { + j |= 8; + } + if (value & 0xf0f0) + { + j |= 4; + } + if (value & 0xcccc) + { + j |= 2; + } + if (value & 0xaaaa) + { + j |= 1; + } return j; } @@ -895,97 +891,110 @@ bool n64_rdp::z_compare(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 sz, UINT16 d if (object.m_other_modes.z_compare_en) { oz = z_decompress(zcurpixel); - dzmem = dz_decompress(zcurpixel, dzcurpixel); zval = RREADIDX16(zcurpixel); - rawdzmem = ((zval & 3) << 2) | ((((dzcurpixel) <= 0x3fffff) ? (m_hidden_bits[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0) & 3); - } - else - { - oz = 0; - dzmem = 1 << 0xf; - zval = 0x3; - rawdzmem = 0xf; - } + UINT32 hval = HREADADDR8(dzcurpixel); + rawdzmem = ((zval & 3) << 2) | hval; + dzmem = 1 << rawdzmem; - userdata->m_dzpix_enc = dz_compress(dzpix & 0xffff); - userdata->m_shift_a = CLAMP(userdata->m_dzpix_enc - rawdzmem, 0, 4); - userdata->m_shift_b = CLAMP(rawdzmem - userdata->m_dzpix_enc, 0, 4); + userdata->m_shift_a = CLAMP(userdata->m_dzpix_enc - rawdzmem, 0, 4); + userdata->m_shift_b = CLAMP(rawdzmem - userdata->m_dzpix_enc, 0, 4); - INT32 precision_factor = (zval >> 13) & 0xf; - if (precision_factor < 3) - { - INT32 dzmemmodifier = 16 >> precision_factor; - if (dzmem == 0x8000) + if(object.m_other_modes.cycle_type == CYCLE_TYPE_2) { - force_coplanar = true; + userdata->m_prev_shift_a = CLAMP(userdata->m_dzpix_enc - userdata->m_prev_raw_dzmem, 0, 4); + userdata->m_prev_shift_b = CLAMP(userdata->m_prev_raw_dzmem - userdata->m_dzpix_enc, 0, 4); } - dzmem <<= 1; - if (dzmem <= dzmemmodifier) - { - dzmem = dzmemmodifier; - } - if (!dzmem) + userdata->m_prev_raw_dzmem = rawdzmem; + + INT32 precision_factor = (zval >> 13) & 0xf; + if (precision_factor < 3) { - dzmem = 0xffff; + if (dzmem != 0x8000) + { + UINT32 dzmemmodifier = 16 >> precision_factor; + dzmem <<= 1; + if (dzmem < dzmemmodifier) + { + dzmem = dzmemmodifier; + } + } + else + { + force_coplanar = true; + dzmem = 0xffff; + } } - } - if (dzmem > 0x8000) - { - dzmem = 0xffff; - } - - UINT32 dznew = (dzmem > dzpix) ? dzmem : (UINT32)dzpix; - UINT32 dznotshift = dznew; - dznew <<= 3; - bool farther = (sz + dznew) >= oz; - bool infront = sz < oz; - - if (force_coplanar) - { - farther = true; - } + UINT32 dznew = m_dz_compare_lut[dzpix | dzmem]; + UINT32 dznotshift = dznew; + dznew <<= 3; - bool overflow = ((userdata->m_current_mem_cvg + userdata->m_current_pix_cvg) & 8) > 0; - userdata->m_blend_enable = (object.m_other_modes.force_blend || (!overflow && object.m_other_modes.antialias_en && farther)) ? 1 : 0; - userdata->m_pre_wrap = overflow; + bool farther = force_coplanar || (sz + dznew) >= oz; - INT32 cvgcoeff = 0; - UINT32 dzenc = 0; + bool overflow = ((userdata->m_current_mem_cvg + userdata->m_current_pix_cvg) & 8) > 0; + userdata->m_blend_enable = (object.m_other_modes.force_blend || (!overflow && object.m_other_modes.antialias_en && farther)) ? 1 : 0; + userdata->m_pre_wrap = overflow; - if (object.m_other_modes.z_mode == 1 && infront && farther && overflow) - { - dzenc = dz_compress(dznotshift & 0xffff); - cvgcoeff = ((oz >> dzenc) - (sz >> dzenc)) & 0xf; - userdata->m_current_pix_cvg = ((cvgcoeff * userdata->m_current_pix_cvg) >> 3) & 0xf; + switch(object.m_other_modes.z_mode) + { + case ZMODE_OPAQUE: + { + bool infront = sz < oz; + INT32 diff = (INT32)sz - (INT32)dznew; + bool nearer = force_coplanar || (diff <= (INT32)oz); + bool max = oz == 0x3ffff; + return (max || (overflow ? infront : nearer)); + } + case ZMODE_INTERPENETRATING: + { + bool infront = sz < oz; + if (!infront || !farther || !overflow) + { + INT32 diff = (INT32)sz - (INT32)dznew; + bool nearer = force_coplanar || (diff <= (INT32)oz); + bool max = oz == 0x3ffff; + return (max || (overflow ? infront : nearer)); + } + else + { + UINT32 dzenc = dz_compress(dznotshift & 0xffff); + INT32 cvgcoeff = ((oz >> dzenc) - (sz >> dzenc)) & 0xf; + userdata->m_current_pix_cvg = ((cvgcoeff * userdata->m_current_pix_cvg) >> 3) & 0xf; + return true; + } + break; + } + case ZMODE_TRANSLUCENT: + { + return (sz < oz || oz == 0x3ffff); + } + case ZMODE_DECAL: + { + INT32 diff = (INT32)sz - (INT32)dznew; + bool nearer = force_coplanar || (diff <= (INT32)oz); + bool max = oz == 0x3ffff; + return farther && nearer && !max; + } + } } - - if (!object.m_other_modes.z_compare_en) + else { - return true; - } + userdata->m_shift_a = 0; + userdata->m_shift_b = (userdata->m_dzpix_enc < 0xb) ? 4 : (0xf - userdata->m_dzpix_enc); - INT32 diff = (INT32)sz - (INT32)dznew; - bool nearer = diff <= (INT32)oz; - bool max = (oz == 0x3ffff); - if (force_coplanar) - { - nearer = true; - } + if(object.m_other_modes.cycle_type == CYCLE_TYPE_2) + { + userdata->m_prev_shift_a = 0; + userdata->m_prev_shift_b = userdata->m_shift_b; + } + userdata->m_prev_raw_dzmem = 0xf; - switch(object.m_other_modes.z_mode) - { - case 0: - return (max || (overflow ? infront : nearer)); - case 1: - return (max || (overflow ? infront : nearer)); - case 2: - return (infront || max); - case 3: - return (farther && nearer && !max); + bool overflow = ((userdata->m_current_mem_cvg + userdata->m_current_pix_cvg) & 8) > 0; + userdata->m_blend_enable = (object.m_other_modes.force_blend || (!overflow && object.m_other_modes.antialias_en)) ? 1 : 0; + userdata->m_pre_wrap = overflow; } - return false; + return true; } UINT32 n64_rdp::get_log2(UINT32 lod_clamp) @@ -1603,183 +1612,152 @@ void n64_rdp::disassemble(char* buffer) static UINT32 rightcvghex(UINT32 x, UINT32 fmask) { - UINT32 stickybit = ((x >> 1) & 0x1fff) > 0; - UINT32 covered = ((x >> 14) & 3) + stickybit; - covered = (0xf0 >> covered) & 0xf; - return (covered & fmask); + return (0xf0 >> (((x & 7) + 1) >> 1)) & fmask; } static UINT32 leftcvghex(UINT32 x, UINT32 fmask) { - UINT32 stickybit = ((x >> 1) & 0x1fff) > 0; - UINT32 covered = ((x >> 14) & 3) + stickybit; - covered = 0xf >> covered; - return (covered & fmask); -} - -static INT32 CLIP(INT32 value,INT32 min,INT32 max) -{ - if (value < min) - { - return min; - } - else if (value > max) - { - return max; - } - else - { - return value; - } + return (0xf >> (((x & 7) + 1) >> 1)) & fmask; } -void n64_rdp::compute_cvg_noflip(extent_t* spans, INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl, INT32 base) +void n64_rdp::compute_cvg_noflip(rdp_span_aux* data, UINT32 lx, UINT32 rx) { - INT32 purgestart = 0xfff; - INT32 purgeend = 0; - const bool writablescanline = !(scanline & ~0x3ff); - const INT32 scanlinespx = scanline << 2; - - if (!writablescanline) return; + UINT8* cvgbuf = data->m_cvg; + INT32 purgestart = lx; + INT32 purgeend = rx; + INT32 length = purgeend - purgestart; - for(INT32 i = 0; i < 4; i++) + if (length < 0) { - if (minorxint[i] < purgestart) - { - purgestart = minorxint[i]; - } - if (majorxint[i] > purgeend) - { - purgeend = majorxint[i]; - } + return; } - purgestart = CLIP(purgestart, 0, 1023); - purgeend = CLIP(purgeend, 0, 1023); - INT32 length = purgeend - purgestart; - - if (length < 0) return; - - rdp_span_aux* userdata = (rdp_span_aux*)spans[scanline - base].userdata; - memset(&userdata->m_cvg[purgestart], 0, (length + 1) << 1); + memset(&cvgbuf[purgestart], 0xff, length + 1); for(INT32 i = 0; i < 4; i++) { - INT32 minorcur = minorx[i]; - INT32 majorcur = majorx[i]; - INT32 minorcurint = minorxint[i]; - INT32 majorcurint = majorxint[i]; - length = majorcurint - minorcurint; + const INT32 fmask = 0xa >> (i & 1); + const INT32 maskshift = (i - 2) & 4; + const INT32 fmaskshifted = fmask << maskshift; - INT32 fmask = (i & 1) ? 5 : 0xa; - INT32 maskshift = (i ^ 3) << 2; - INT32 fmaskshifted = fmask << maskshift; - INT32 fleft = CLIP(minorcurint + 1, 0, 647); - INT32 fright = CLIP(majorcurint - 1, 0, 647); - bool valid_y = ((scanlinespx + i) >= yh && (scanlinespx + i) < yl); - if (valid_y && length >= 0) + if (!data->m_invalid_y[i]) { - if (minorcurint != majorcurint) + INT32 minorcur = data->m_minorx[i]; + INT32 majorcur = data->m_majorx[i]; + INT32 minorcurint = minorcur >> 3; + INT32 majorcurint = majorcur >> 3; + + for (INT32 k = purgestart; k <= minorcurint; k++) { - if (!(minorcurint & ~0x3ff)) - { - userdata->m_cvg[minorcurint] |= (leftcvghex(minorcur, fmask) << maskshift); - } - if (!(majorcurint & ~0x3ff)) - { - userdata->m_cvg[majorcurint] |= (rightcvghex(majorcur, fmask) << maskshift); - } + cvgbuf[k] &= ~fmaskshifted; } - else + for (INT32 k = majorcurint; k <= purgeend; k++) { - if (!(majorcurint & ~0x3ff)) - { - INT32 samecvg = leftcvghex(minorcur, fmask) & rightcvghex(majorcur, fmask); - userdata->m_cvg[majorcurint] |= (samecvg << maskshift); - } + cvgbuf[k] &= ~fmaskshifted; + } + + if (majorcurint > minorcurint) + { + cvgbuf[minorcurint] |= leftcvghex(minorcur, fmask) << maskshift; + cvgbuf[majorcurint] |= rightcvghex(majorcur, fmask) << maskshift; } - for (; fleft <= fright; fleft++) + else if (majorcurint == minorcurint) { - userdata->m_cvg[fleft] |= fmaskshifted; + INT32 samecvg = leftcvghex(minorcur, fmask) & rightcvghex(majorcur, fmask); + cvgbuf[majorcurint] |= samecvg << maskshift; + } + } + else + { + for (INT32 k = purgestart; k <= purgeend; k++) + { + cvgbuf[k] &= ~fmaskshifted; } } } } -void n64_rdp::compute_cvg_flip(extent_t* spans, INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl, INT32 base) +void n64_rdp::compute_cvg_flip(rdp_span_aux* data, UINT32 lx, UINT32 rx) { - INT32 purgestart = 0xfff; - INT32 purgeend = 0; - const bool writablescanline = !(scanline & ~0x3ff); - const INT32 scanlinespx = scanline << 2; - - if(!writablescanline) return; + UINT8* cvgbuf = data->m_cvg; + INT32 purgestart = rx; + INT32 purgeend = lx; + INT32 length = purgeend - purgestart; - for(INT32 i = 0; i < 4; i++) + if (length < 0) { - if (majorxint[i] < purgestart) - { - purgestart = majorxint[i]; - } - if (minorxint[i] > purgeend) - { - purgeend = minorxint[i]; - } + return; } - purgestart = CLIP(purgestart, 0, 1023); - purgeend = CLIP(purgeend, 0, 1023); - - INT32 length = purgeend - purgestart; - - if (length < 0) return; - - rdp_span_aux* userdata = (rdp_span_aux*)spans[scanline - base].userdata; - memset(&userdata->m_cvg[purgestart], 0, (length + 1) << 1); + memset(&cvgbuf[purgestart], 0xff, length + 1); for(INT32 i = 0; i < 4; i++) { - INT32 minorcur = minorx[i]; - INT32 majorcur = majorx[i]; - INT32 minorcurint = minorxint[i]; - INT32 majorcurint = majorxint[i]; - length = minorcurint - majorcurint; + const INT32 fmask = 0xa >> (i & 1); + const INT32 maskshift = (i - 2) & 4; + const INT32 fmaskshifted = fmask << maskshift; - INT32 fmask = (i & 1) ? 5 : 0xa; - INT32 maskshift = (i ^ 3) << 2; - INT32 fmaskshifted = fmask << maskshift; - INT32 fleft = CLIP(majorcurint + 1, 0, 647); - INT32 fright = CLIP(minorcurint - 1, 0, 647); - bool valid_y = ((scanlinespx + i) >= yh && (scanlinespx + i) < yl); - if (valid_y && length >= 0) + if (!data->m_invalid_y[i]) { - if (minorcurint != majorcurint) + INT32 minorcur = data->m_minorx[i]; + INT32 majorcur = data->m_majorx[i]; + INT32 minorcurint = minorcur >> 3; + INT32 majorcurint = majorcur >> 3; + + for (INT32 k = purgestart; k <= majorcurint; k++) { - if (!(minorcurint & ~0x3ff)) - { - userdata->m_cvg[minorcurint] |= (rightcvghex(minorcur, fmask) << maskshift); - } - if (!(majorcurint & ~0x3ff)) - { - userdata->m_cvg[majorcurint] |= (leftcvghex(majorcur, fmask) << maskshift); - } + cvgbuf[k] &= ~fmaskshifted; } - else + for (INT32 k = minorcurint; k <= purgeend; k++) { - if (!(majorcurint & ~0x3ff)) - { - INT32 samecvg = rightcvghex(minorcur, fmask) & leftcvghex(majorcur, fmask); - userdata->m_cvg[majorcurint] |= (samecvg << maskshift); - } + cvgbuf[k] &= ~fmaskshifted; + } + + if (minorcurint > majorcurint) + { + cvgbuf[minorcurint] |= rightcvghex(minorcur, fmask) << maskshift; + cvgbuf[majorcurint] |= leftcvghex(majorcur, fmask) << maskshift; } - for (; fleft <= fright; fleft++) + else if (minorcurint == majorcurint) { - userdata->m_cvg[fleft] |= fmaskshifted; + INT32 samecvg = rightcvghex(minorcur, fmask) & leftcvghex(majorcur, fmask); + cvgbuf[majorcurint] |= samecvg << maskshift; + } + } + else + { + for (INT32 k = purgestart; k <= purgeend; k++) + { + cvgbuf[k] &= ~fmaskshifted; } } } } +void n64_rdp::get_span_userdata(void** userdata) +{ + *userdata = (void*)((UINT8*)m_aux_buf + m_aux_buf_ptr); + m_aux_buf_ptr += sizeof(rdp_span_aux); + rdp_span_aux* data = (rdp_span_aux*)*userdata; + data->m_valid_line = true; +} + +void n64_rdp::deduce_derivatives(rdp_span_aux *userdata) +{ + m_mode_derivs.m_partial_reject_1cycle = (userdata->m_color_inputs.blender2b_a[0] == &userdata->m_inv_pixel_color && userdata->m_color_inputs.blender1b_a[0] == &userdata->m_pixel_color); + m_mode_derivs.m_partial_reject_2cycle = (userdata->m_color_inputs.blender2b_a[1] == &userdata->m_inv_pixel_color && userdata->m_color_inputs.blender1b_a[1] == &userdata->m_pixel_color); + + m_mode_derivs.m_special_bsel0 = (userdata->m_color_inputs.blender2b_a[0] == &userdata->m_memory_color); + m_mode_derivs.m_special_bsel1 = (userdata->m_color_inputs.blender2b_a[1] == &userdata->m_memory_color); + + m_mode_derivs.m_rgb_alpha_dither = (m_other_modes.rgb_dither_sel << 2) | m_other_modes.alpha_dither_sel; + + const bool lod_frac_used_in_cycle1 = (userdata->m_color_inputs.combiner_rgbmul[0] == &userdata->m_lod_fraction) || (userdata->m_color_inputs.combiner_alphamul[0] == &userdata->m_lod_fraction); + const bool lod_frac_used_in_cycle2 = (userdata->m_color_inputs.combiner_rgbmul[1] == &userdata->m_lod_fraction) || (userdata->m_color_inputs.combiner_alphamul[1] == &userdata->m_lod_fraction); + const bool lod_frac_used = (m_other_modes.cycle_type == CYCLE_TYPE_2 && (lod_frac_used_in_cycle1 || lod_frac_used_in_cycle2)) || (m_other_modes.cycle_type == CYCLE_TYPE_1 && lod_frac_used_in_cycle2); + m_mode_derivs.m_do_lod = m_other_modes.tex_lod_en || lod_frac_used; +} + void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) { const UINT32* cmd_data = rect ? m_temp_rect_data : m_cmd_data; @@ -1796,11 +1774,6 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) INT32 dsdxh = 0, dtdxh = 0, dwdxh = 0, drdxh = 0, dgdxh = 0, dbdxh = 0, dadxh = 0, dzdxh = 0; INT32 dsdyh = 0, dtdyh = 0, dwdyh = 0, drdyh = 0, dgdyh = 0, dbdyh = 0, dadyh = 0, dzdyh = 0; - INT32 maxxmx = 0; // maxxmx / minxhx very opaque names, consider re-naming - INT32 minxmx = 0; - INT32 maxxhx = 0; - INT32 minxhx = 0; - INT32 shade_base = fifo_index + 8; INT32 texture_base = fifo_index + 8; INT32 zbuffer_base = fifo_index + 8; @@ -1821,12 +1794,12 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) UINT32 w7 = cmd_data[fifo_index + 6]; UINT32 w8 = cmd_data[fifo_index + 7]; - INT32 yl = (w1 & 0x3fff); + INT32 yl = w1 & 0x3fff; INT32 ym = ((w2 >> 16) & 0x3fff); - INT32 yh = ((w2 >> 0) & 0x3fff); - INT32 xl = (INT32)(w3 & 0x3fffffff); - INT32 xh = (INT32)(w5 & 0x3fffffff); - INT32 xm = (INT32)(w7 & 0x3fffffff); + INT32 yh = w2 & 0x3fff; + INT32 xl = w3 & 0x3fffffff; + INT32 xh = w5 & 0x3fffffff; + INT32 xm = w7 & 0x3fffffff; // Inverse slopes in 16.16 format INT32 dxldy = (INT32)(w4); INT32 dxhdy = (INT32)(w6); @@ -1873,30 +1846,39 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) const INT32 dzde = cmd_data[zbuffer_base+2]; const INT32 dzdy = cmd_data[zbuffer_base+3]; - const INT32 dzdy_dz = (dzdy >> 16) & 0xffff; - const INT32 dzdx_dz = (dzdx >> 16) & 0xffff; - extent_t spans[2048]; #ifdef MAME_DEBUG memset(spans, 0xcc, sizeof(spans)); #endif - m_span_base.m_span_drdy = drdy; - m_span_base.m_span_dgdy = dgdy; - m_span_base.m_span_dbdy = dbdy; - m_span_base.m_span_dady = dady; - m_span_base.m_span_dzdy = m_other_modes.z_source_sel ? 0 : dzdy; - - UINT32 temp_dzpix = ((dzdy_dz & 0x8000) ? ((~dzdy_dz) & 0x7fff) : dzdy_dz) + ((dzdx_dz & 0x8000) ? ((~dzdx_dz) & 0x7fff) : dzdx_dz); + m_span_base.m_span_ds = dsdx & ~0x1f; + m_span_base.m_span_dt = dtdx & ~0x1f; + m_span_base.m_span_dw = dwdx & ~0x1f; m_span_base.m_span_dr = drdx & ~0x1f; m_span_base.m_span_dg = dgdx & ~0x1f; m_span_base.m_span_db = dbdx & ~0x1f; m_span_base.m_span_da = dadx & ~0x1f; - m_span_base.m_span_ds = dsdx; - m_span_base.m_span_dt = dtdx; - m_span_base.m_span_dw = dwdx; - m_span_base.m_span_dz = m_other_modes.z_source_sel ? 0 : dzdx; - m_span_base.m_span_dymax = 0; + m_span_base.m_span_dz = dzdx; + + m_span_base.m_span_drdy = SIGN13(drdy >> 14); + m_span_base.m_span_dgdy = SIGN13(dgdy >> 14); + m_span_base.m_span_dbdy = SIGN13(dbdy >> 14); + m_span_base.m_span_dady = SIGN13(dady >> 14); + m_span_base.m_span_dzdy = dzdy >> 10; + m_span_base.m_span_cdr = SIGN13(m_span_base.m_span_dr >> 14); + m_span_base.m_span_cdg = SIGN13(m_span_base.m_span_dg >> 14); + m_span_base.m_span_cdb = SIGN13(m_span_base.m_span_db >> 14); + m_span_base.m_span_cda = SIGN13(m_span_base.m_span_da >> 14); + m_span_base.m_span_cdz = SIGN22(m_span_base.m_span_dz >> 10); + + m_span_base.m_span_dsdy = dsdy & ~0x7fff; + m_span_base.m_span_dtdy = dtdy & ~0x7fff; + m_span_base.m_span_dwdy = dwdy & ~0x7fff; + + const INT32 dzdy_dz = (dzdy >> 16) & 0xffff; + const INT32 dzdx_dz = (dzdx >> 16) & 0xffff; + + const UINT32 temp_dzpix = ((dzdy_dz & 0x8000) ? ((~dzdy_dz) & 0x7fff) : dzdy_dz) + ((dzdx_dz & 0x8000) ? ((~dzdx_dz) & 0x7fff) : dzdx_dz); m_span_base.m_span_dzpix = m_dzpix_normalize[temp_dzpix & 0xffff]; INT32 xleft_inc = (dxmdy >> 2) & ~1; @@ -1906,74 +1888,448 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) INT32 xleft = xm & ~1; const INT32 sign_dxhdy = (dxhdy & 0x80000000) ? 1 : 0; - const INT32 do_offset = !(sign_dxhdy ^ (flip)); + const INT32 do_offset = !(sign_dxhdy ^ flip); if (do_offset) { - dsdeh = dsde >> 9; dsdyh = dsdy >> 9; - dtdeh = dtde >> 9; dtdyh = dtdy >> 9; - dwdeh = dwde >> 9; dwdyh = dwdy >> 9; - drdeh = drde >> 9; drdyh = drdy >> 9; - dgdeh = dgde >> 9; dgdyh = dgdy >> 9; - dbdeh = dbde >> 9; dbdyh = dbdy >> 9; - dadeh = dade >> 9; dadyh = dady >> 9; - dzdeh = dzde >> 9; dzdyh = dzdy >> 9; - - dsdiff = (dsdeh << 8) + (dsdeh << 7) - (dsdyh << 8) - (dsdyh << 7); - dtdiff = (dtdeh << 8) + (dtdeh << 7) - (dtdyh << 8) - (dtdyh << 7); - dwdiff = (dwdeh << 8) + (dwdeh << 7) - (dwdyh << 8) - (dwdyh << 7); - drdiff = (drdeh << 8) + (drdeh << 7) - (drdyh << 8) - (drdyh << 7); - dgdiff = (dgdeh << 8) + (dgdeh << 7) - (dgdyh << 8) - (dgdyh << 7); - dbdiff = (dbdeh << 8) + (dbdeh << 7) - (dbdyh << 8) - (dbdyh << 7); - dadiff = (dadeh << 8) + (dadeh << 7) - (dadyh << 8) - (dadyh << 7); - dzdiff = (dzdeh << 8) + (dzdeh << 7) - (dzdyh << 8) - (dzdyh << 7); + dsdeh = dsde & ~0x1ff; + dtdeh = dtde & ~0x1ff; + dwdeh = dwde & ~0x1ff; + drdeh = drde & ~0x1ff; + dgdeh = dgde & ~0x1ff; + dbdeh = dbde & ~0x1ff; + dadeh = dade & ~0x1ff; + dzdeh = dzde & ~0x1ff; + + dsdyh = dsdy & ~0x1ff; + dtdyh = dtdy & ~0x1ff; + dwdyh = dwdy & ~0x1ff; + drdyh = drdy & ~0x1ff; + dgdyh = dgdy & ~0x1ff; + dbdyh = dbdy & ~0x1ff; + dadyh = dady & ~0x1ff; + dzdyh = dzdy & ~0x1ff; + + dsdiff = (dsdeh - dsdyh) - (dsdiff >> 2); + dtdiff = (dtdeh - dtdyh) - (dtdiff >> 2); + dwdiff = (dwdeh - dwdyh) - (dwdiff >> 2); + drdiff = (drdeh - drdyh) - (drdiff >> 2); + dgdiff = (dgdeh - dgdyh) - (dgdiff >> 2); + dbdiff = (dbdeh - dbdyh) - (dbdiff >> 2); + dadiff = (dadeh - dadyh) - (dadiff >> 2); + dzdiff = (dzdeh - dzdyh) - (dzdiff >> 2); } else { dsdiff = dtdiff = dwdiff = drdiff = dgdiff = dbdiff = dadiff = dzdiff = 0; } - dsdxh = dsdx >> 8; - dtdxh = dtdx >> 8; - dwdxh = dwdx >> 8; - drdxh = drdx >> 8; - dgdxh = dgdx >> 8; - dbdxh = dbdx >> 8; - dadxh = dadx >> 8; - dzdxh = dzdx >> 8; + if (m_other_modes.cycle_type != CYCLE_TYPE_COPY) + { + dsdxh = (dsdx >> 8) & ~1; + dtdxh = (dtdx >> 8) & ~1; + dwdxh = (dwdx >> 8) & ~1; + drdxh = (drdx >> 8) & ~1; + dgdxh = (dgdx >> 8) & ~1; + dbdxh = (dbdx >> 8) & ~1; + dadxh = (dadx >> 8) & ~1; + dzdxh = (dzdx >> 8) & ~1; + } + else + { + dsdxh = dtdxh = dwdxh = drdxh = dgdxh = dbdxh = dadxh = dzdxh = 0; + } + + INT32 maxxmx = 0; + INT32 minxmx = 0; + INT32 maxxhx = 0; + INT32 minxhx = 0; + + rdp_poly_state* object = &object_data_alloc(); + memcpy(object->m_tmem, m_tmem, 0x1000); const INT32 ycur = yh & ~3; - const INT32 ylfar = yl | 3; const INT32 ldflag = (sign_dxhdy ^ flip) ? 0 : 3; - INT32 majorx[4]; - INT32 minorx[4]; - INT32 majorxint[4]; - INT32 minorxint[4]; - INT32 xfrac = ((xright >> 8) & 0xff); + bool invalid_y = true; + bool limited_yl = false; + INT32 yllimit = 0; + if (yl & 0x2000) + { + limited_yl = true; + } + else if (yl & 0x1000) + { + limited_yl = false; + } + else + { + limited_yl = (yl & 0xfff) < m_scissor.m_yl; + } + yllimit = limited_yl ? yl : m_scissor.m_yl; - const INT32 clipy1 = m_scissor.m_yh; - const INT32 clipy2 = m_scissor.m_yl; + INT32 invalid_index = -1; + INT32 ylfar = yllimit | 3; + if ((yl >> 2) > (ylfar >> 2)) + { + ylfar += 4; + } + else if((yllimit >> 2) >= 0 && (yllimit >> 2) < 0x3ff) + { + INT32 idx = (yllimit >> 2) + 1; + get_span_userdata(&spans[idx].userdata); + ((rdp_span_aux*)spans[idx].userdata)->m_valid_line = false; + invalid_index = idx; + } - // Trivial reject - if((ycur >> 2) >= clipy2 && (ylfar >> 2) >= clipy2) + bool limited_yh = false; + INT32 yhlimit = 0; + if (yh & 0x2000) { - return; + limited_yh = false; } - if((ycur >> 2) < clipy1 && (ylfar >> 2) < clipy1) + else if (yh & 0x1000) { - return; + limited_yh = true; } + else + { + limited_yh = (yh >= m_scissor.m_yh); + } + yhlimit = limited_yh ? yh : m_scissor.m_yh; + + INT32 yhclose = yhlimit & ~3; + + INT32 clipxlshift = m_scissor.m_xl << 1; + INT32 clipxhshift = m_scissor.m_xh << 1; + + bool allover = true; + bool allunder = true; + bool bothinvalid = true; + bool anyvalid = false; + bool first_line = true; + + INT32 xfrac = ((xright >> 8) & 0xff); + + if (flip) + { + for (INT32 k = ycur; k <= ylfar; k++) + { + if (k == ym) + { + xleft = xl & ~1; + xleft_inc = (dxldy >> 2) & ~1; + } + + INT32 spix = k & 3; + + if (k >= yhclose) + { + invalid_y = k < yhlimit || k >= yllimit; + + INT32 j = k >> 2; + const INT32 spanidx = j - (ycur >> 2); - bool new_object = true; - rdp_poly_state* object = NULL; - bool valid = false; + if (spix == 0) + { + maxxmx = 0; + minxhx = 0xfff; + allover = allunder = bothinvalid = true; + } + + if (spix == 0 || k == ycur) + { + get_span_userdata(&spans[spanidx].userdata); - INT32* minx = flip ? &minxhx : &minxmx; - INT32* maxx = flip ? &maxxmx : &maxxhx; - INT32* startx = flip ? maxx : minx; - INT32* endx = flip ? minx : maxx; + rdp_span_aux* userdata = (rdp_span_aux*)spans[spanidx].userdata; + if (j == invalid_index) + { + userdata->m_valid_line = false; + } + userdata->m_tmem = object->m_tmem; + + userdata->m_blend_color = m_blend_color; + userdata->m_prim_color = m_prim_color; + userdata->m_env_color = m_env_color; + userdata->m_fog_color = m_fog_color; + userdata->m_prim_alpha = m_prim_alpha; + userdata->m_env_alpha = m_env_alpha; + userdata->m_key_scale = m_key_scale; + userdata->m_lod_fraction = m_lod_fraction; + userdata->m_prim_lod_fraction = m_prim_lod_fraction; + + // Setup blender data for this scanline + set_blender_input(0, 0, &userdata->m_color_inputs.blender1a_rgb[0], &userdata->m_color_inputs.blender1b_a[0], m_other_modes.blend_m1a_0, m_other_modes.blend_m1b_0, userdata); + set_blender_input(0, 1, &userdata->m_color_inputs.blender2a_rgb[0], &userdata->m_color_inputs.blender2b_a[0], m_other_modes.blend_m2a_0, m_other_modes.blend_m2b_0, userdata); + set_blender_input(1, 0, &userdata->m_color_inputs.blender1a_rgb[1], &userdata->m_color_inputs.blender1b_a[1], m_other_modes.blend_m1a_1, m_other_modes.blend_m1b_1, userdata); + set_blender_input(1, 1, &userdata->m_color_inputs.blender2a_rgb[1], &userdata->m_color_inputs.blender2b_a[1], m_other_modes.blend_m2a_1, m_other_modes.blend_m2b_1, userdata); + + // Setup color combiner data for this scanline + set_suba_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_a[0], m_combine.sub_a_rgb0, userdata); + set_subb_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_b[0], m_combine.sub_b_rgb0, userdata); + set_mul_input_rgb(&userdata->m_color_inputs.combiner_rgbmul[0], m_combine.mul_rgb0, userdata); + set_add_input_rgb(&userdata->m_color_inputs.combiner_rgbadd[0], m_combine.add_rgb0, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_a[0], m_combine.sub_a_a0, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_b[0], m_combine.sub_b_a0, userdata); + set_mul_input_alpha(&userdata->m_color_inputs.combiner_alphamul[0], m_combine.mul_a0, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphaadd[0], m_combine.add_a0, userdata); + + set_suba_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_a[1], m_combine.sub_a_rgb1, userdata); + set_subb_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_b[1], m_combine.sub_b_rgb1, userdata); + set_mul_input_rgb(&userdata->m_color_inputs.combiner_rgbmul[1], m_combine.mul_rgb1, userdata); + set_add_input_rgb(&userdata->m_color_inputs.combiner_rgbadd[1], m_combine.add_rgb1, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_a[1], m_combine.sub_a_a1, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_b[1], m_combine.sub_b_a1, userdata); + set_mul_input_alpha(&userdata->m_color_inputs.combiner_alphamul[1], m_combine.mul_a1, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphaadd[1], m_combine.add_a1, userdata); + + deduce_derivatives(userdata); + } + rdp_span_aux* userdata = (rdp_span_aux*)spans[spanidx].userdata; + INT32 stickybit = ((xright >> 1) & 0x1fff) > 0 ? 1 : 0; + UINT32 xsrc = ((xright >> 13) & 0x1ffe) | stickybit; + bool curunder = (xright & 0x8000000) || xsrc < clipxhshift; + xsrc = curunder ? clipxhshift : (((xright >> 13) & 0x3ffe) | stickybit); + bool curover = (xsrc & 0x2000) != 0 || (xsrc & 0x1fff) > clipxlshift; + xsrc = curover ? clipxlshift : xsrc; + userdata->m_majorx[spix] = xsrc & 0x1fff; + allover = allover && curover; + allunder = allunder && curunder; + + stickybit = ((xleft >> 1) & 0x1fff) > 0 ? 1 : 0; + UINT32 xlsc = ((xleft >> 13) & 0x1ffe) | stickybit; + curunder = (xleft & 0x8000000) || xlsc < clipxhshift; + xlsc = curunder ? clipxhshift : (((xleft >> 13) & 0x3ffe) | stickybit); + curover = (xlsc & 0x2000) != 0 || (xlsc & 0x1fff) > clipxlshift; + xlsc = curover ? clipxlshift : xlsc; + userdata->m_minorx[spix] = xlsc & 0x1fff; + allover = allover && curover; + allunder = allunder && curunder; + + bool curcross = ((xleft ^ (1 << 27)) & (0x3fff << 14)) < ((xright ^ (1 << 27)) & (0x3fff << 14)); + + invalid_y = invalid_y || curcross; + userdata->m_invalid_y[spix] = invalid_y; + bothinvalid = bothinvalid && invalid_y; + + if (!invalid_y) + { + maxxmx = (((xlsc >> 3) & 0xfff) > maxxmx) ? (xlsc >> 3) & 0xfff : maxxmx; + minxhx = (((xsrc >> 3) & 0xfff) < minxhx) ? (xsrc >> 3) & 0xfff : minxhx; + } + + if (spix == ldflag) + { + userdata->m_unscissored_rx = xright >> 16; + xfrac = (xright >> 8) & 0xff; + spans[spanidx].param[SPAN_R].start = ((r & ~0x1ff) + drdiff - (xfrac * drdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_G].start = ((g & ~0x1ff) + dgdiff - (xfrac * dgdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_B].start = ((b & ~0x1ff) + dbdiff - (xfrac * dbdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_A].start = ((a & ~0x1ff) + dadiff - (xfrac * dadxh)) & ~0x3ff; + spans[spanidx].param[SPAN_S].start = ((s & ~0x1ff) + dsdiff - (xfrac * dsdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_T].start = ((t & ~0x1ff) + dtdiff - (xfrac * dtdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_W].start = ((w & ~0x1ff) + dwdiff - (xfrac * dwdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_Z].start = ((z & ~0x1ff) + dzdiff - (xfrac * dzdxh)) & ~0x3ff; + } + + if (spix == 3) + { + spans[spanidx].startx = maxxmx; + spans[spanidx].stopx = minxhx; + bool even_line = j & 1; + userdata->m_valid_line = !bothinvalid && !allover && !allunder && (!m_scissor.m_field || (m_scissor.m_field && !(m_scissor.m_keep_odd ^ even_line))); + if (!first_line && spans[spanidx-1].userdata != NULL) + { + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_valid = true; + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_s = spans[spanidx].param[SPAN_S].start; + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_t = spans[spanidx].param[SPAN_T].start; + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_w = spans[spanidx].param[SPAN_W].start; + } + else + { + first_line = false; + } + anyvalid = anyvalid || !bothinvalid; + } + } + + if (spix == 3) + { + r += drde; + g += dgde; + b += dbde; + a += dade; + s += dsde; + t += dtde; + w += dwde; + z += dzde; + } + + xleft += xleft_inc; + xright += xright_inc; + } + } + else + { + for (INT32 k = ycur; k <= ylfar; k++) + { + if (k == ym) + { + xleft = xl & ~1; + xleft_inc = (dxldy >> 2) & ~1; + } + + INT32 spix = k & 3; + + if (k >= yhclose) + { + bool invalid_y = k < yhlimit || k >= yllimit; + + INT32 j = k >> 2; + const INT32 spanidx = j - (ycur >> 2); + + if (spix == 0) + { + maxxhx = 0; + minxmx = 0xfff; + allover = allunder = bothinvalid = true; + } + + if (spix == 0 || k == ycur) + { + get_span_userdata(&spans[spanidx].userdata); + + rdp_span_aux* userdata = (rdp_span_aux*)spans[spanidx].userdata; + if (j == invalid_index) + { + userdata->m_valid_line = false; + } + userdata->m_tmem = object->m_tmem; + + userdata->m_blend_color = m_blend_color; + userdata->m_prim_color = m_prim_color; + userdata->m_env_color = m_env_color; + userdata->m_fog_color = m_fog_color; + userdata->m_prim_alpha = m_prim_alpha; + userdata->m_env_alpha = m_env_alpha; + userdata->m_key_scale = m_key_scale; + userdata->m_lod_fraction = m_lod_fraction; + userdata->m_prim_lod_fraction = m_prim_lod_fraction; + + // Setup blender data for this scanline + set_blender_input(0, 0, &userdata->m_color_inputs.blender1a_rgb[0], &userdata->m_color_inputs.blender1b_a[0], m_other_modes.blend_m1a_0, m_other_modes.blend_m1b_0, userdata); + set_blender_input(0, 1, &userdata->m_color_inputs.blender2a_rgb[0], &userdata->m_color_inputs.blender2b_a[0], m_other_modes.blend_m2a_0, m_other_modes.blend_m2b_0, userdata); + set_blender_input(1, 0, &userdata->m_color_inputs.blender1a_rgb[1], &userdata->m_color_inputs.blender1b_a[1], m_other_modes.blend_m1a_1, m_other_modes.blend_m1b_1, userdata); + set_blender_input(1, 1, &userdata->m_color_inputs.blender2a_rgb[1], &userdata->m_color_inputs.blender2b_a[1], m_other_modes.blend_m2a_1, m_other_modes.blend_m2b_1, userdata); + + // Setup color combiner data for this scanline + set_suba_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_a[0], m_combine.sub_a_rgb0, userdata); + set_subb_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_b[0], m_combine.sub_b_rgb0, userdata); + set_mul_input_rgb(&userdata->m_color_inputs.combiner_rgbmul[0], m_combine.mul_rgb0, userdata); + set_add_input_rgb(&userdata->m_color_inputs.combiner_rgbadd[0], m_combine.add_rgb0, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_a[0], m_combine.sub_a_a0, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_b[0], m_combine.sub_b_a0, userdata); + set_mul_input_alpha(&userdata->m_color_inputs.combiner_alphamul[0], m_combine.mul_a0, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphaadd[0], m_combine.add_a0, userdata); + + set_suba_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_a[1], m_combine.sub_a_rgb1, userdata); + set_subb_input_rgb(&userdata->m_color_inputs.combiner_rgbsub_b[1], m_combine.sub_b_rgb1, userdata); + set_mul_input_rgb(&userdata->m_color_inputs.combiner_rgbmul[1], m_combine.mul_rgb1, userdata); + set_add_input_rgb(&userdata->m_color_inputs.combiner_rgbadd[1], m_combine.add_rgb1, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_a[1], m_combine.sub_a_a1, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphasub_b[1], m_combine.sub_b_a1, userdata); + set_mul_input_alpha(&userdata->m_color_inputs.combiner_alphamul[1], m_combine.mul_a1, userdata); + set_sub_input_alpha(&userdata->m_color_inputs.combiner_alphaadd[1], m_combine.add_a1, userdata); + + deduce_derivatives(userdata); + } + + rdp_span_aux* userdata = (rdp_span_aux*)spans[spanidx].userdata; + INT32 stickybit = ((xright >> 1) & 0x1fff) > 0 ? 1 : 0; + UINT32 xsrc = ((xright >> 13) & 0x1ffe) | stickybit; + bool curunder = (xright & 0x8000000) || xsrc < clipxhshift; + xsrc = curunder ? clipxhshift : (((xright >> 13) & 0x3ffe) | stickybit); + bool curover = (xsrc & 0x2000) != 0 || (xsrc & 0x1fff) > clipxlshift; + xsrc = curover ? clipxlshift : xsrc; + userdata->m_majorx[spix] = xsrc & 0x1fff; + allover = allover && curover; + allunder = allunder && curunder; + + stickybit = ((xleft >> 1) & 0x1fff) > 0 ? 1 : 0; + UINT32 xlsc = ((xleft >> 13) & 0x1ffe) | stickybit; + curunder = (xleft & 0x8000000) || xlsc < clipxhshift; + xlsc = curunder ? clipxhshift : (((xleft >> 13) & 0x3ffe) | stickybit); + curover = (xlsc & 0x2000) != 0 || (xlsc & 0x1fff) > clipxlshift; + xlsc = curover ? clipxlshift : xlsc; + userdata->m_minorx[spix] = xlsc & 0x1fff; + allover = allover && curover; + allunder = allunder && curunder; + + bool curcross = ((xright ^ (1 << 27)) & (0x3fff << 14)) < ((xleft ^ (1 << 27)) & (0x3fff << 14)); + + invalid_y = invalid_y || curcross; + userdata->m_invalid_y[spix] = invalid_y; + bothinvalid = bothinvalid && invalid_y; + + if (!invalid_y) + { + minxmx = (((xlsc >> 3) & 0xfff) > minxmx) ? (xlsc >> 3) & 0xfff : minxmx; + maxxhx = (((xsrc >> 3) & 0xfff) < maxxhx) ? (xsrc >> 3) & 0xfff : maxxhx; + } + + if (spix == ldflag) + { + userdata->m_unscissored_rx = xright >> 16; + xfrac = (xright >> 8) & 0xff; + spans[spanidx].param[SPAN_R].start = ((r & ~0x1ff) + drdiff - (xfrac * drdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_G].start = ((g & ~0x1ff) + dgdiff - (xfrac * dgdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_B].start = ((b & ~0x1ff) + dbdiff - (xfrac * dbdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_A].start = ((a & ~0x1ff) + dadiff - (xfrac * dadxh)) & ~0x3ff; + spans[spanidx].param[SPAN_S].start = ((s & ~0x1ff) + dsdiff - (xfrac * dsdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_T].start = ((t & ~0x1ff) + dtdiff - (xfrac * dtdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_W].start = ((w & ~0x1ff) + dwdiff - (xfrac * dwdxh)) & ~0x3ff; + spans[spanidx].param[SPAN_Z].start = ((z & ~0x1ff) + dzdiff - (xfrac * dzdxh)) & ~0x3ff; + } + + if (spix == 3) + { + spans[spanidx].startx = minxmx; + spans[spanidx].stopx = maxxhx; + bool even_line = j & 1; + userdata->m_valid_line = !bothinvalid && !allover && !allunder && (!m_scissor.m_field || (m_scissor.m_field && !(m_scissor.m_keep_odd ^ even_line))); + if (!first_line && spans[spanidx-1].userdata != NULL) + { + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_valid = true; + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_s = spans[spanidx].param[SPAN_S].start; + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_t = spans[spanidx].param[SPAN_T].start; + ((rdp_span_aux*)spans[spanidx-1].userdata)->m_next_w = spans[spanidx].param[SPAN_W].start; + } + else + { + first_line = false; + } + anyvalid = anyvalid || !bothinvalid; + } + } + + if (spix == 3) + { + r += drde; + g += dgde; + b += dbde; + a += dade; + s += dsde; + t += dtde; + w += dwde; + z += dzde; + } + + xleft += xleft_inc; + xright += xright_inc; + } + } +#if 0 for (INT32 k = ycur; k <= ylfar; k++) { if (k == ym) @@ -2018,16 +2374,7 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) if (spix == 0) { - if(new_object) - { - object = &object_data_alloc(); - memcpy(object->m_tmem, m_tmem, 0x1000); - new_object = false; - } - - spans[spanidx].userdata = (void*)((UINT8*)m_aux_buf + m_aux_buf_ptr); valid = true; - m_aux_buf_ptr += sizeof(rdp_span_aux); if(m_aux_buf_ptr >= EXTENT_AUX_COUNT) { @@ -2077,7 +2424,8 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) { spans[spanidx].startx = *startx; spans[spanidx].stopx = *endx; - ((this)->*(m_compute_cvg[flip]))(spans, majorx, minorx, majorxint, minorxint, j, yh, yl, ycur >> 2); + bool even_line = j & 1; + userdata->m_valid_line = !allinvalid && !allover && !allunder && (!m_scissor.m_field || (m_scissor.m_field && !(m_scissor.m_keep_odd ^ even_line))); } if (spix == ldflag) @@ -2109,10 +2457,11 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect) xleft += xleft_inc; xright += xright_inc; } +#endif - if(!new_object && valid) + if(anyvalid) { - render_spans(yh >> 2, yl >> 2, tilenum, flip ? true : false, spans, rect, object); + render_spans(yhlimit >> 2, yllimit >> 2, tilenum, flip ? true : false, spans, rect, object); } //wait("draw_triangle"); @@ -2337,17 +2686,18 @@ void n64_rdp::cmd_set_convert(UINT32 w1, UINT32 w2) k2 = (SIGN9(k2) << 1) + 1; k3 = (SIGN9(k3) << 1) + 1; - set_yuv_factors(rgbaint_t(0, k0, k2, k3), rgbaint_t(0, 0, k1, 0), rgbaint_t(k4, k4, k4, k4), rgbaint_t(k5, k5, k5, k5)); + set_yuv_factors(rgbaint_t(0, k0, k2, 0), rgbaint_t(0, 0, k1, k3), rgbaint_t(k4, k4, k4, k4), rgbaint_t(k5, k5, k5, k5)); } void n64_rdp::cmd_set_scissor(UINT32 w1, UINT32 w2) { - m_scissor.m_xh = ((w1 >> 12) & 0xfff) >> 2; - m_scissor.m_yh = ((w1 >> 0) & 0xfff) >> 2; - m_scissor.m_xl = ((w2 >> 12) & 0xfff) >> 2; - m_scissor.m_yl = ((w2 >> 0) & 0xfff) >> 2; + m_scissor.m_xh = (w1 >> 12) & 0xfff; + m_scissor.m_yh = (w1 >> 0) & 0xfff; + m_scissor.m_xl = (w2 >> 12) & 0xfff; + m_scissor.m_yl = (w2 >> 0) & 0xfff; - // TODO: handle f & o? + m_scissor.m_field = (w2 >> 25) & 1; + m_scissor.m_keep_odd = (w2 >> 24) & 1; } void n64_rdp::cmd_set_prim_depth(UINT32 w1, UINT32 w2) @@ -2827,11 +3177,8 @@ void n64_rdp::cmd_fill_rect(UINT32 w1, UINT32 w2) ewdata[0] = (0x3680 << 16) | yl;//command, flipped, tile, yl ewdata[1] = (yl << 16) | yh;//ym, yh ewdata[2] = (xlint << 16) | ((xl & 3) << 14);//xl, xl frac - ewdata[3] = 0;//dxldy, dxldy frac ewdata[4] = (xhint << 16) | ((xh & 3) << 14);//xh, xh frac - ewdata[5] = 0;//dxhdy, dxhdy frac ewdata[6] = (xlint << 16) | ((xl & 3) << 14);//xm, xm frac - ewdata[7] = 0;//dxmdy, dxmdy frac memset(&ewdata[8], 0, 36 * sizeof(UINT32));//shade, texture, depth draw_triangle(false, false, false, true); @@ -3211,8 +3558,8 @@ void n64_state::screen_eof_n64(screen_device &screen, bool state) void n64_rdp::render_spans(INT32 start, INT32 end, INT32 tilenum, bool flip, extent_t* spans, bool rect, rdp_poly_state* object) { - const INT32 clipy1 = m_scissor.m_yh; - const INT32 clipy2 = m_scissor.m_yl; + const INT32 clipy1 = m_scissor.m_yh >> 2; + const INT32 clipy2 = m_scissor.m_yl >> 2; INT32 offset = 0; if (clipy2 <= 0) @@ -3244,15 +3591,18 @@ void n64_rdp::render_spans(INT32 start, INT32 end, INT32 tilenum, bool flip, ext memcpy(&object->m_other_modes, &m_other_modes, sizeof(other_modes_t)); memcpy(&object->m_span_base, &m_span_base, sizeof(span_base_t)); memcpy(&object->m_scissor, &m_scissor, sizeof(rectangle_t)); + memcpy(&object->m_mode_derivs, &m_mode_derivs, sizeof(mode_derivs_t)); memcpy(&object->m_tiles, &m_tiles, 8 * sizeof(n64_tile_t)); object->tilenum = tilenum; object->flip = flip; object->m_fill_color = m_fill_color; object->rect = rect; + //printf("%d", m_other_modes.cycle_type); switch(m_other_modes.cycle_type) { case CYCLE_TYPE_1: + //printf("%d, %d\n", start, end); render_triangle_custom(m_visarea, render_delegate(FUNC(n64_rdp::span_draw_1cycle), this), start, (end - start) + 1, spans + offset); break; @@ -3271,26 +3621,7 @@ void n64_rdp::render_spans(INT32 start, INT32 end, INT32 tilenum, bool flip, ext //wait(); } -void n64_rdp::rgbaz_clip(INT32 sr, INT32 sg, INT32 sb, INT32 sa, INT32* sz, rdp_span_aux* userdata) -{ - userdata->m_shade_color.set(sa, sr, sg, sb); - userdata->m_shade_color.clamp_and_clear(0xfffffe00); - UINT32 a = userdata->m_shade_color.get_a(); - userdata->m_shade_alpha.set(a, a, a, a); - - INT32 zanded = (*sz) & 0x60000; - - zanded >>= 17; - switch(zanded) - { - case 0: *sz &= 0x3ffff; break; - case 1: *sz &= 0x3ffff; break; - case 2: *sz = 0x3ffff; break; - case 3: *sz = 0x3ffff; break; - } -} - -void n64_rdp::rgbaz_correct_triangle(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z, rdp_span_aux* userdata, const rdp_poly_state &object) +void n64_rdp::rgbaz_correct_clip(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z, rdp_span_aux* userdata, const rdp_poly_state &object) { if (userdata->m_current_pix_cvg == 8) { @@ -3298,27 +3629,35 @@ void n64_rdp::rgbaz_correct_triangle(INT32 offx, INT32 offy, INT32* r, INT32* g, *g >>= 2; *b >>= 2; *a >>= 2; - *z = (*z >> 3) & 0x7ffff; + *z >>= 3; } else { - INT32 summand_xr = offx * SIGN13(object.m_span_base.m_span_dr >> 14); - INT32 summand_yr = offy * SIGN13(object.m_span_base.m_span_drdy >> 14); - INT32 summand_xb = offx * SIGN13(object.m_span_base.m_span_db >> 14); - INT32 summand_yb = offy * SIGN13(object.m_span_base.m_span_dbdy >> 14); - INT32 summand_xg = offx * SIGN13(object.m_span_base.m_span_dg >> 14); - INT32 summand_yg = offy * SIGN13(object.m_span_base.m_span_dgdy >> 14); - INT32 summand_xa = offx * SIGN13(object.m_span_base.m_span_da >> 14); - INT32 summand_ya = offy * SIGN13(object.m_span_base.m_span_dady >> 14); + const INT32 summand_r = offx * object.m_span_base.m_span_cdr + offy * object.m_span_base.m_span_drdy; + const INT32 summand_g = offx * object.m_span_base.m_span_cdg + offy * object.m_span_base.m_span_dgdy; + const INT32 summand_b = offx * object.m_span_base.m_span_cdb + offy * object.m_span_base.m_span_dbdy; + const INT32 summand_a = offx * object.m_span_base.m_span_cda + offy * object.m_span_base.m_span_dady; + const INT32 summand_z = offx * object.m_span_base.m_span_cdz + offy * object.m_span_base.m_span_dzdy; + + *r = ((*r << 2) + summand_r) >> 4; + *g = ((*g << 2) + summand_g) >> 4; + *b = ((*b << 2) + summand_b) >> 4; + *a = ((*a << 2) + summand_a) >> 4; + *z = ((*z << 2) + summand_z) >> 5; + } - INT32 summand_xz = offx * SIGN22(object.m_span_base.m_span_dz >> 10); - INT32 summand_yz = offy * SIGN22(object.m_span_base.m_span_dzdy >> 10); + userdata->m_shade_color.set(*r, *g, *b, *a); + userdata->m_shade_color.clamp_and_clear(0xfffffe00); + userdata->m_shade_alpha.set(*a, *a, *a, *a); - *r = ((*r << 2) + summand_xr + summand_yr) >> 4; - *g = ((*g << 2) + summand_xg + summand_yg) >> 4; - *b = ((*b << 2) + summand_xb + summand_yb) >> 4; - *a = ((*a << 2) + summand_xa + summand_ya) >> 4; - *z = (((*z << 2) + summand_xz + summand_yz) >> 5) & 0x7ffff; + const INT32 zanded = ((*z) & 0x60000) >> 17; + + switch(zanded) + { + case 0: *z &= 0x3ffff; break; + case 1: *z &= 0x3ffff; break; + case 2: *z = 0x3ffff; break; + case 3: *z = 0; break; } } @@ -3502,11 +3841,6 @@ void n64_rdp::span_draw_1cycle(INT32 scanline, const extent_t &extent, const rdp { assert(object.m_misc_state.m_fb_size >= 2 && object.m_misc_state.m_fb_size < 4); - const INT32 clipx1 = object.m_scissor.m_xh; - const INT32 clipx2 = object.m_scissor.m_xl; - const INT32 tilenum = object.tilenum; - const bool flip = object.flip; - span_param_t r; r.w = extent.param[SPAN_R].start; span_param_t g; g.w = extent.param[SPAN_G].start; span_param_t b; b.w = extent.param[SPAN_B].start; @@ -3526,10 +3860,17 @@ void n64_rdp::span_draw_1cycle(INT32 scanline, const extent_t &extent, const rdp #endif rdp_span_aux* userdata = (rdp_span_aux*)extent.userdata; - m_tex_pipe.calculate_clamp_diffs(tilenum, userdata, object); + if (!userdata->m_valid_line) + { + return; + } - const bool partialreject = (userdata->m_color_inputs.blender2b_a[0] == &userdata->m_inv_pixel_color && userdata->m_color_inputs.blender1b_a[0] == &userdata->m_pixel_color); - const INT32 sel0 = (userdata->m_color_inputs.blender2b_a[0] == &userdata->m_memory_color) ? 1 : 0; + const INT32 tilenum = object.tilenum; + const INT32 prim_tile = tilenum; + INT32 tile1 = tilenum; + INT32 newtile = tilenum; + + const bool flip = object.flip; INT32 drinc, dginc, dbinc, dainc; INT32 dzinc, dzpix; @@ -3561,25 +3902,55 @@ void n64_rdp::span_draw_1cycle(INT32 scanline, const extent_t &extent, const rdp xinc = 1; } + if(object.m_other_modes.z_source_sel) + { + z.w = object.m_misc_state.m_primitive_z; + dzpix = object.m_misc_state.m_primitive_dz; + dzinc = 0; + } + else + { + dzpix = object.m_span_base.m_span_dzpix; + } + userdata->m_dzpix_enc = dz_compress(dzpix); + + m_tex_pipe.calculate_clamp_diffs(tilenum, userdata, object); + + const bool partialreject = (userdata->m_color_inputs.blender2b_a[0] == &userdata->m_inv_pixel_color && userdata->m_color_inputs.blender1b_a[0] == &userdata->m_pixel_color); + const INT32 sel0 = (userdata->m_color_inputs.blender2b_a[0] == &userdata->m_memory_color) ? 1 : 0; + const INT32 fb_index = object.m_misc_state.m_fb_width * scanline; const INT32 xstart = extent.startx; const INT32 xend = userdata->m_unscissored_rx; const INT32 xend_scissored = extent.stopx; - INT32 x = xend; - - const INT32 length = flip ? (xstart - xend) : (xend - xstart); + INT32 x = xend_scissored; - if(object.m_other_modes.z_source_sel) + INT32 length, scdiff; + if (flip) { - z.w = object.m_misc_state.m_primitive_z; - dzpix = object.m_misc_state.m_primitive_dz; - dzinc = 0; + compute_cvg_flip(userdata, extent.startx, extent.stopx); + length = xstart - xend_scissored; + scdiff = xend_scissored - xend; } else { - dzpix = object.m_span_base.m_span_dzpix; + compute_cvg_noflip(userdata, extent.startx, extent.stopx); + length = xend_scissored - xstart; + scdiff = xend - xend_scissored; + } + + if (scdiff) + { + r.w += (drinc * scdiff); + g.w += (dginc * scdiff); + b.w += (dbinc * scdiff); + a.w += (dainc * scdiff); + z.w += (dzinc * scdiff); + s.w += (dsinc * scdiff); + t.w += (dtinc * scdiff); + w.w += (dwinc * scdiff); } if (object.m_misc_state.m_fb_size < 2 || object.m_misc_state.m_fb_size > 4) @@ -3591,105 +3962,160 @@ void n64_rdp::span_draw_1cycle(INT32 scanline, const extent_t &extent, const rdp INT32 sss = 0; INT32 sst = 0; - if (object.m_other_modes.persp_tex_en) - { - tc_div(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); - } - else - { - tc_div_no_perspective(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); - } + INT32 news, newt; + INT32 prelodfrac; userdata->m_start_span = true; + userdata->m_long_span = (length > 7); + userdata->m_mid_span = (length == 7); + userdata->m_almost_mid_span = (length == 6); + + INT32 nexts, nextt, nextw; + for (INT32 j = 0; j <= length; j++) { INT32 sr = r.w >> 14; INT32 sg = g.w >> 14; INT32 sb = b.w >> 14; INT32 sa = a.w >> 14; + INT32 ss = s.w >> 16; + INT32 st = t.w >> 16; + INT32 sw = w.w >> 16; INT32 sz = (z.w >> 10) & 0x3fffff; - const bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored); - if (x >= clipx1 && x < clipx2 && valid_x) + userdata->m_end_span = (j == length); + userdata->m_pre_end_span = (j == (length - 1)); + + UINT8 offx, offy; + lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); + + if (!userdata->m_end_span || !userdata->m_long_span || !userdata->m_next_valid) + { + nexts = (s.w + dsinc) >> 16; + nextt = (t.w + dtinc) >> 16; + nextw = (w.w + dwinc) >> 16; + } + else { - UINT8 offx, offy; - lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); + nexts = userdata->m_next_s >> 16; + nextt = userdata->m_next_t >> 16; + nextw = userdata->m_next_w >> 16; + } - m_tex_pipe.lod_1cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, userdata, object); + if (object.m_other_modes.persp_tex_en) + { + tc_div(nexts, nextt, nextw, &news, &newt); + } + else + { + tc_div_no_perspective(nexts, nextt, nextw, &news, &newt); + } - rgbaz_correct_triangle(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object); - rgbaz_clip(sr, sg, sb, sa, &sz, userdata); + if (!userdata->m_start_span) + { + userdata->m_texel0_color.set(userdata->m_texel1_color); + userdata->m_texel1_alpha.set(userdata->m_texel1_alpha); + userdata->m_lod_fraction.set(prelodfrac, prelodfrac, prelodfrac, prelodfrac); + } + else + { + if (object.m_other_modes.persp_tex_en) + { + tc_div(ss, st, sw, &sss, &sst); + } + else + { + tc_div_no_perspective(ss, st, sw, &sss, &sst); + } + + m_tex_pipe.tclod_1cycle_current(&sss, &sst, news, newt, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &tile1, userdata, object); ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tilenum, 0, userdata, object); - UINT32 t0a = userdata->m_texel0_color.get_a(); - userdata->m_texel0_alpha.set(t0a, t0a, t0a, t0a); + userdata->m_start_span = false; + } + + userdata->m_next_span = userdata->m_end_span; + userdata->m_end_span = userdata->m_pre_end_span; + userdata->m_pre_end_span = (j == (length - 2)); + + s.w += dsinc; + t.w += dtinc; + w.w += dwinc; + + m_tex_pipe.tclod_1cycle_next(&news, &newt, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &newtile, &prelodfrac, userdata, object); + + ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel1_color, &userdata->m_texel1_color, news, newt, tilenum, 0, userdata, object); + + rgbaz_correct_clip(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object); + + UINT32 t0a = userdata->m_texel0_color.get_a(); + userdata->m_texel0_alpha.set(t0a, t0a, t0a, t0a); + + if (userdata->m_noise_used) + { const UINT8 noise = rand() << 3; // Not accurate userdata->m_noise_color.set(0, noise, noise, noise); + } - rgbaint_t rgbsub_a(*userdata->m_color_inputs.combiner_rgbsub_a[1]); - rgbaint_t rgbsub_b(*userdata->m_color_inputs.combiner_rgbsub_b[1]); - rgbaint_t rgbmul(*userdata->m_color_inputs.combiner_rgbmul[1]); - rgbaint_t rgbadd(*userdata->m_color_inputs.combiner_rgbadd[1]); - - rgbsub_a.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_a[1]); - rgbsub_b.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_b[1]); - rgbmul.merge_alpha(*userdata->m_color_inputs.combiner_alphamul[1]); - rgbadd.merge_alpha(*userdata->m_color_inputs.combiner_alphaadd[1]); + rgbaint_t rgbsub_a(*userdata->m_color_inputs.combiner_rgbsub_a[1]); + rgbaint_t rgbsub_b(*userdata->m_color_inputs.combiner_rgbsub_b[1]); + rgbaint_t rgbmul(*userdata->m_color_inputs.combiner_rgbmul[1]); + rgbaint_t rgbadd(*userdata->m_color_inputs.combiner_rgbadd[1]); - rgbsub_a.sign_extend(0x180, 0xfffffe00); - rgbsub_b.sign_extend(0x180, 0xfffffe00); - rgbadd.sign_extend(0x180, 0xfffffe00); + rgbsub_a.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_a[1]); + rgbsub_b.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_b[1]); + rgbmul.merge_alpha(*userdata->m_color_inputs.combiner_alphamul[1]); + rgbadd.merge_alpha(*userdata->m_color_inputs.combiner_alphaadd[1]); - rgbadd.shl_imm(8); - rgbsub_a.sub(rgbsub_b); - rgbsub_a.mul(rgbmul); - rgbsub_a.add(rgbadd); - rgbsub_a.add_imm(0x0080); - rgbsub_a.sra_imm(8); - rgbsub_a.clamp_and_clear(0xfffffe00); + rgbsub_a.sign_extend(0x180, 0xfffffe00); + rgbsub_b.sign_extend(0x180, 0xfffffe00); + rgbadd.sign_extend(0x180, 0xfffffe00); - userdata->m_pixel_color = rgbsub_a; + rgbadd.shl_imm(8); + rgbsub_a.sub(rgbsub_b); + rgbsub_a.mul(rgbmul); + rgbsub_a.add(rgbadd); + rgbsub_a.add_imm(0x0080); + rgbsub_a.sra_imm(8); + rgbsub_a.clamp_and_clear(0xfffffe00); - //Alpha coverage combiner - userdata->m_pixel_color.set_a(get_alpha_cvg(userdata->m_pixel_color.get_a(), userdata, object)); + userdata->m_pixel_color = rgbsub_a; + userdata->m_pixel_color.set_a(get_alpha_cvg(userdata->m_pixel_color.get_a(), userdata, object)); - const UINT32 curpixel = fb_index + x; - const UINT32 zbcur = zb + curpixel; - const UINT32 zhbcur = zhb + curpixel; + const UINT32 curpixel = fb_index + x; + const UINT32 zbcur = zb + curpixel; + const UINT32 zhbcur = zhb + curpixel; - read_pixel(curpixel, userdata, object); + //printf("%d, %d\n", x, scanline); + read_pixel(curpixel, userdata, object); - if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object)) - { - INT32 cdith = 0; - INT32 adith = 0; - get_dither_values(scanline, j, &cdith, &adith, object); + if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object)) + { + INT32 cdith = 0; + INT32 adith = 0; + get_dither_values(scanline, j, &cdith, &adith, object); - color_t blended_pixel; - bool rendered = ((&m_blender)->*(m_blender.blend1[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, userdata, object); + color_t blended_pixel; + bool rendered = ((&m_blender)->*(m_blender.blend1[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, userdata, object); - if (rendered) + if (rendered) + { + write_pixel(curpixel, blended_pixel, userdata, object); + if (object.m_other_modes.z_update_en) { - write_pixel(curpixel, blended_pixel, userdata, object); - if (object.m_other_modes.z_update_en) - { - z_store(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); - } + z_store(zbcur, zhbcur, sz, userdata->m_dzpix_enc); } } - - sss = userdata->m_precomp_s; - sst = userdata->m_precomp_t; } + sss = userdata->m_precomp_s; + sst = userdata->m_precomp_t; + r.w += drinc; g.w += dginc; b.w += dbinc; a.w += dainc; - s.w += dsinc; - t.w += dtinc; - w.w += dwinc; z.w += dzinc; x += xinc; @@ -3700,8 +4126,6 @@ void n64_rdp::span_draw_2cycle(INT32 scanline, const extent_t &extent, const rdp { assert(object.m_misc_state.m_fb_size >= 2 && object.m_misc_state.m_fb_size < 4); - const INT32 clipx1 = object.m_scissor.m_xh; - const INT32 clipx2 = object.m_scissor.m_xl; const INT32 tilenum = object.tilenum; const bool flip = object.flip; @@ -3722,8 +4146,7 @@ void n64_rdp::span_draw_2cycle(INT32 scanline, const extent_t &extent, const rdp const UINT32 prim_tile = tilenum; INT32 newtile1 = tile1; - INT32 news = 0; - INT32 newt = 0; + INT32 newtile2 = tile2; #ifdef PTR64 assert(extent.userdata != (const void *)0xcccccccccccccccc); @@ -3779,7 +4202,31 @@ void n64_rdp::span_draw_2cycle(INT32 scanline, const extent_t &extent, const rdp INT32 x = xend; - const INT32 length = flip ? (xstart - xend) : (xend - xstart); + INT32 length, scdiff; + if (flip) + { + compute_cvg_flip(userdata, extent.startx, extent.stopx); + length = xstart - xend_scissored; + scdiff = xend_scissored - xend; + } + else + { + compute_cvg_noflip(userdata, extent.startx, extent.stopx); + length = xend_scissored - xstart; + scdiff = xend - xend_scissored; + } + + if (scdiff) + { + r.w += (drinc * scdiff); + g.w += (dginc * scdiff); + b.w += (dbinc * scdiff); + a.w += (dainc * scdiff); + z.w += (dzinc * scdiff); + s.w += (dsinc * scdiff); + t.w += (dtinc * scdiff); + w.w += (dwinc * scdiff); + } if(object.m_other_modes.z_source_sel) { @@ -3802,144 +4249,175 @@ void n64_rdp::span_draw_2cycle(INT32 scanline, const extent_t &extent, const rdp INT32 sss = 0; INT32 sst = 0; - if (object.m_other_modes.persp_tex_en) - { - tc_div(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); - } - else - { - tc_div_no_perspective(s.w >> 16, t.w >> 16, w.w >> 16, &sss, &sst); - } + INT32 news, newt; + INT32 prelodfrac; + + userdata->m_start_span = true; + userdata->m_long_span = (length > 7); + userdata->m_mid_span = (length == 7); + userdata->m_almost_mid_span = (length == 6); + + INT32 nexts, nextt, nextw; userdata->m_start_span = true; + for (INT32 j = 0; j <= length; j++) { INT32 sr = r.w >> 14; INT32 sg = g.w >> 14; INT32 sb = b.w >> 14; INT32 sa = a.w >> 14; + INT32 ss = s.w >> 16; + INT32 st = t.w >> 16; + INT32 sw = w.w >> 16; INT32 sz = (z.w >> 10) & 0x3fffff; - color_t c1; - color_t c2; - const bool valid_x = (flip) ? (x >= xend_scissored) : (x <= xend_scissored); + userdata->m_end_span = (j == length); + userdata->m_pre_end_span = (j == (length - 1)); - if (x >= clipx1 && x < clipx2 && valid_x) - { - const UINT32 compidx = m_compressed_cvmasks[userdata->m_cvg[x]]; - userdata->m_current_pix_cvg = cvarray[compidx].cvg; - userdata->m_current_cvg_bit = cvarray[compidx].cvbit; - const UINT8 offx = cvarray[compidx].xoff; - const UINT8 offy = cvarray[compidx].yoff; - //lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); + UINT8 offx, offy; + lookup_cvmask_derivatives(userdata->m_cvg[x], &offx, &offy, userdata); + + nexts = (s.w + dsinc) >> 16; + nextt = (t.w + dtinc) >> 16; + nextw = (w.w + dwinc) >> 16; - m_tex_pipe.lod_2cycle(&sss, &sst, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &tile1, &tile2, userdata, object); + if (object.m_other_modes.persp_tex_en) + { + tc_div(nexts, nextt, nextw, &news, &newt); + } + else + { + tc_div_no_perspective(nexts, nextt, nextw, &news, &newt); + } - news = userdata->m_precomp_s; - newt = userdata->m_precomp_t; - m_tex_pipe.lod_2cycle_limited(&news, &newt, s.w + dsinc, t.w + dtinc, w.w + dwinc, dsinc, dtinc, dwinc, prim_tile, &newtile1, object); + if (!userdata->m_start_span) + { + userdata->m_texel0_color.set(userdata->m_next_texel0_color); + userdata->m_texel1_color.set(userdata->m_next_texel1_color); + userdata->m_texel0_alpha.set(userdata->m_next_texel0_alpha); + userdata->m_texel1_alpha.set(userdata->m_next_texel1_alpha); + userdata->m_lod_fraction.set(prelodfrac, prelodfrac, prelodfrac, prelodfrac); + } + else + { + if (object.m_other_modes.persp_tex_en) + { + tc_div(ss, st, sw, &sss, &sst); + } + else + { + tc_div_no_perspective(ss, st, sw, &sss, &sst); + } - rgbaz_correct_triangle(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object); - rgbaz_clip(sr, sg, sb, sa, &sz, userdata); + m_tex_pipe.tclod_2cycle_current(&sss, &sst, news, newt, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &tile1, &tile2, userdata, object); ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tile1, 0, userdata, object); ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle1]))(&userdata->m_texel1_color, &userdata->m_texel0_color, sss, sst, tile2, 1, userdata, object); - ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle1]))(&userdata->m_next_texel_color, &userdata->m_next_texel_color, sss, sst, tile2, 1, userdata, object); - UINT32 t0a = userdata->m_texel0_color.get_a(); - UINT32 t1a = userdata->m_texel1_color.get_a(); - UINT32 tna = userdata->m_next_texel_color.get_a(); - userdata->m_texel0_alpha.set(t0a, t0a, t0a, t0a); - userdata->m_texel1_alpha.set(t1a, t1a, t1a, t1a); - userdata->m_next_texel_alpha.set(tna, tna, tna, tna); + userdata->m_start_span = false; + } + s.w += dsinc; + t.w += dtinc; + w.w += dwinc; + + m_tex_pipe.tclod_2cycle_next(&news, &newt, s.w, t.w, w.w, dsinc, dtinc, dwinc, prim_tile, &newtile1, &newtile2, &prelodfrac, userdata, object); + + ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_next_texel0_color, &userdata->m_texel0_color, news, newt, newtile1, 0, userdata, object); + ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle1]))(&userdata->m_next_texel1_color, &userdata->m_texel1_color, news, newt, newtile2, 1, userdata, object); + + rgbaz_correct_clip(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object); + + if (userdata->m_noise_used) + { const UINT8 noise = rand() << 3; // Not accurate userdata->m_noise_color.set(0, noise, noise, noise); + } - rgbaint_t rgbsub_a(*userdata->m_color_inputs.combiner_rgbsub_a[0]); - rgbaint_t rgbsub_b(*userdata->m_color_inputs.combiner_rgbsub_b[0]); - rgbaint_t rgbmul(*userdata->m_color_inputs.combiner_rgbmul[0]); - rgbaint_t rgbadd(*userdata->m_color_inputs.combiner_rgbadd[0]); + rgbaint_t rgbsub_a(*userdata->m_color_inputs.combiner_rgbsub_a[0]); + rgbaint_t rgbsub_b(*userdata->m_color_inputs.combiner_rgbsub_b[0]); + rgbaint_t rgbmul(*userdata->m_color_inputs.combiner_rgbmul[0]); + rgbaint_t rgbadd(*userdata->m_color_inputs.combiner_rgbadd[0]); - rgbsub_a.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_a[0]); - rgbsub_b.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_b[0]); - rgbmul.merge_alpha(*userdata->m_color_inputs.combiner_alphamul[0]); - rgbadd.merge_alpha(*userdata->m_color_inputs.combiner_alphaadd[0]); + rgbsub_a.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_a[0]); + rgbsub_b.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_b[0]); + rgbmul.merge_alpha(*userdata->m_color_inputs.combiner_alphamul[0]); + rgbadd.merge_alpha(*userdata->m_color_inputs.combiner_alphaadd[0]); - rgbsub_a.sign_extend(0x180, 0xfffffe00); - rgbsub_b.sign_extend(0x180, 0xfffffe00); - rgbadd.sign_extend(0x180, 0xfffffe00); + rgbsub_a.sign_extend(0x180, 0xfffffe00); + rgbsub_b.sign_extend(0x180, 0xfffffe00); + rgbadd.sign_extend(0x180, 0xfffffe00); - rgbadd.shl_imm(8); - rgbsub_a.sub(rgbsub_b); - rgbsub_a.mul(rgbmul); + rgbadd.shl_imm(8); + rgbsub_a.sub(rgbsub_b); + rgbsub_a.mul(rgbmul); - rgbsub_a.add(rgbadd); - rgbsub_a.add_imm(0x0080); - rgbsub_a.sra_imm(8); - rgbsub_a.clamp_and_clear(0xfffffe00); + rgbsub_a.add(rgbadd); + rgbsub_a.add_imm(0x0080); + rgbsub_a.sra_imm(8); + rgbsub_a.clamp_and_clear(0xfffffe00); - userdata->m_combined_color.set(rgbsub_a); - userdata->m_texel0_color.set(userdata->m_texel1_color); - userdata->m_texel1_color.set(userdata->m_next_texel_color); + userdata->m_combined_color.set(rgbsub_a); + userdata->m_texel0_color.set(userdata->m_texel1_color); + userdata->m_texel1_color.set(userdata->m_next_texel0_color); - UINT32 ca = userdata->m_combined_color.get_a(); - userdata->m_combined_alpha.set(ca, ca, ca, ca); - userdata->m_texel0_alpha.set(userdata->m_texel1_alpha); - userdata->m_texel1_alpha.set(userdata->m_next_texel_alpha); + UINT32 ca = userdata->m_combined_color.get_a(); + userdata->m_combined_alpha.set(ca, ca, ca, ca); + userdata->m_texel0_alpha.set(userdata->m_texel1_alpha); + userdata->m_texel1_alpha.set(userdata->m_next_texel0_alpha); - rgbsub_a.set(*userdata->m_color_inputs.combiner_rgbsub_a[1]); - rgbsub_b.set(*userdata->m_color_inputs.combiner_rgbsub_b[1]); - rgbmul.set(*userdata->m_color_inputs.combiner_rgbmul[1]); - rgbadd.set(*userdata->m_color_inputs.combiner_rgbadd[1]); + rgbsub_a.set(*userdata->m_color_inputs.combiner_rgbsub_a[1]); + rgbsub_b.set(*userdata->m_color_inputs.combiner_rgbsub_b[1]); + rgbmul.set(*userdata->m_color_inputs.combiner_rgbmul[1]); + rgbadd.set(*userdata->m_color_inputs.combiner_rgbadd[1]); - rgbsub_a.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_a[1]); - rgbsub_b.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_b[1]); - rgbmul.merge_alpha(*userdata->m_color_inputs.combiner_alphamul[1]); - rgbadd.merge_alpha(*userdata->m_color_inputs.combiner_alphaadd[1]); + rgbsub_a.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_a[1]); + rgbsub_b.merge_alpha(*userdata->m_color_inputs.combiner_alphasub_b[1]); + rgbmul.merge_alpha(*userdata->m_color_inputs.combiner_alphamul[1]); + rgbadd.merge_alpha(*userdata->m_color_inputs.combiner_alphaadd[1]); - rgbsub_a.sign_extend(0x180, 0xfffffe00); - rgbsub_b.sign_extend(0x180, 0xfffffe00); - rgbadd.sign_extend(0x180, 0xfffffe00); + rgbsub_a.sign_extend(0x180, 0xfffffe00); + rgbsub_b.sign_extend(0x180, 0xfffffe00); + rgbadd.sign_extend(0x180, 0xfffffe00); - rgbadd.shl_imm(8); - rgbsub_a.sub(rgbsub_b); - rgbsub_a.mul(rgbmul); - rgbsub_a.add(rgbadd); - rgbsub_a.add_imm(0x0080); - rgbsub_a.sra_imm(8); - rgbsub_a.clamp_and_clear(0xfffffe00); + rgbadd.shl_imm(8); + rgbsub_a.sub(rgbsub_b); + rgbsub_a.mul(rgbmul); + rgbsub_a.add(rgbadd); + rgbsub_a.add_imm(0x0080); + rgbsub_a.sra_imm(8); + rgbsub_a.clamp_and_clear(0xfffffe00); - userdata->m_pixel_color.set(rgbsub_a); + userdata->m_pixel_color.set(rgbsub_a); - //Alpha coverage combiner - userdata->m_pixel_color.set_a(get_alpha_cvg(userdata->m_pixel_color.get_a(), userdata, object)); + //Alpha coverage combiner + userdata->m_pixel_color.set_a(get_alpha_cvg(userdata->m_pixel_color.get_a(), userdata, object)); - const UINT32 curpixel = fb_index + x; - const UINT32 zbcur = zb + curpixel; - const UINT32 zhbcur = zhb + curpixel; + const UINT32 curpixel = fb_index + x; + const UINT32 zbcur = zb + curpixel; + const UINT32 zhbcur = zhb + curpixel; - read_pixel(curpixel, userdata, object); + read_pixel(curpixel, userdata, object); - if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object)) - { - get_dither_values(scanline, j, &cdith, &adith, object); + if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object)) + { + get_dither_values(scanline, j, &cdith, &adith, object); - color_t blended_pixel; - bool rendered = ((&m_blender)->*(m_blender.blend2[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, sel1, userdata, object); + color_t blended_pixel; + bool rendered = ((&m_blender)->*(m_blender.blend2[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, sel1, userdata, object); - if (rendered) + if (rendered) + { + write_pixel(curpixel, blended_pixel, userdata, object); + if (object.m_other_modes.z_update_en) { - write_pixel(curpixel, blended_pixel, userdata, object); - if (object.m_other_modes.z_update_en) - { - z_store(object, zbcur, zhbcur, sz, userdata->m_dzpix_enc); - } + z_store(zbcur, zhbcur, sz, userdata->m_dzpix_enc); } } - sss = userdata->m_precomp_s; - sst = userdata->m_precomp_t; } + sss = userdata->m_precomp_s; + sst = userdata->m_precomp_t; r.w += drinc; g.w += dginc; @@ -3956,12 +4434,13 @@ void n64_rdp::span_draw_2cycle(INT32 scanline, const extent_t &extent, const rdp void n64_rdp::span_draw_copy(INT32 scanline, const extent_t &extent, const rdp_poly_state &object, INT32 threadid) { - const INT32 clipx1 = object.m_scissor.m_xh; - const INT32 clipx2 = object.m_scissor.m_xl; + const INT32 clipx1 = object.m_scissor.m_xh >> 2; + const INT32 clipx2 = object.m_scissor.m_xl >> 2; const INT32 tilenum = object.tilenum; const bool flip = object.flip; rdp_span_aux* userdata = (rdp_span_aux*)extent.userdata; + const INT32 xstart = extent.startx; const INT32 xend = userdata->m_unscissored_rx; const INT32 xend_scissored = extent.stopx; @@ -4009,8 +4488,8 @@ void n64_rdp::span_draw_fill(INT32 scanline, const extent_t &extent, const rdp_p const bool flip = object.flip; - const INT32 clipx1 = object.m_scissor.m_xh; - const INT32 clipx2 = object.m_scissor.m_xl; + const INT32 clipx1 = object.m_scissor.m_xh >> 2; + const INT32 clipx2 = object.m_scissor.m_xl >> 2; const INT32 xinc = flip ? 1 : -1; diff --git a/src/mame/video/n64.h b/src/mame/video/n64.h index 3900bc72048..bc7ffa8d35f 100644 --- a/src/mame/video/n64.h +++ b/src/mame/video/n64.h @@ -39,6 +39,15 @@ #define FORMAT_IA 3 #define FORMAT_I 4 +#define ZMODE_OPAQUE 0 +#define ZMODE_INTERPENETRATING 1 +#define ZMODE_TRANSLUCENT 2 +#define ZMODE_DECAL 3 + +#define SPAN_UNINITIALIZED 0 +#define SPAN_VALID 1 +#define SPAN_INVALID 2 + #ifdef LSB_FIRST #define BYTE_XOR_DWORD_SWAP 7 #define WORD_XOR_DWORD_SWAP 3 @@ -98,13 +107,13 @@ #define HWRITEADDR8(in, val) /*{if ((in) <= MEM8_LIMIT) */m_hidden_bits[(in) ^ BYTE_ADDR_XOR] = val;/*}*/ //sign-extension macros -#define SIGN22(x) (((x & 0x00200000) * 0x7ff) | (x & 0x1fffff)) -#define SIGN17(x) (((x & 0x00010000) * 0xffff) | (x & 0xffff)) -#define SIGN16(x) (((x & 0x00008000) * 0x1ffff) | (x & 0x7fff)) -#define SIGN13(x) (((x & 0x00001000) * 0xfffff) | (x & 0xfff)) -#define SIGN11(x) (((x & 0x00000400) * 0x3fffff) | (x & 0x3ff)) -#define SIGN9(x) (((x & 0x00000100) * 0xffffff) | (x & 0xff)) -#define SIGN8(x) (((x & 0x00000080) * 0x1ffffff) | (x & 0x7f)) +#define SIGN22(x) ((((x) & 0x00200000) * 0x7ff) | ((x) & 0x1fffff)) +#define SIGN17(x) ((((x) & 0x00010000) * 0xffff) | ((x) & 0xffff)) +#define SIGN16(x) ((((x) & 0x00008000) * 0x1ffff) | ((x) & 0x7fff)) +#define SIGN13(x) ((((x) & 0x00001000) * 0xfffff) | ((x) & 0xfff)) +#define SIGN11(x) ((((x) & 0x00000400) * 0x3fffff) | ((x) & 0x3ff)) +#define SIGN9(x) ((((x) & 0x00000100) * 0xffffff) | ((x) & 0xff)) +#define SIGN8(x) ((((x) & 0x00000080) * 0x1ffffff) | ((x) & 0x7f)) #define KURT_AKELEY_SIGN9(x) ((((x) & 0x180) == 0x180) ? ((x) | ~0x1ff) : ((x) & 0x1ff)) @@ -117,7 +126,7 @@ #define SPAN_W (6) #define SPAN_Z (7) -#define EXTENT_AUX_COUNT (sizeof(rdp_span_aux)*(480*192)) // Screen coverage *192, more or less +#define EXTENT_AUX_COUNT (sizeof(rdp_span_aux)*(480*4096)) // Screen coverage *192, more or less /*****************************************************************************/ @@ -160,6 +169,19 @@ public: m_tiles[i].invmm = rgbaint_t(~0, ~0, ~0, ~0); m_tiles[i].invmask = rgbaint_t(~0, ~0, ~0, ~0); } + + m_dz_compare_lut[0] = 0; + for (INT32 i = 1; i < 0x10000; i++) + { + for (INT32 k = 15; k >= 0; k--) + { + if (i & (1 << k)) + { + m_dz_compare_lut[i] = 1 << k; + break; + } + } + } } void process_command_list(); @@ -199,9 +221,9 @@ public: UINT8 get_random() { return m_misc_state.m_random_seed += 0x13; } // YUV Factors - void set_yuv_factors(color_t k023, color_t k1, color_t k4, color_t k5) { m_k023 = k023; m_k1 = k1; m_k4 = k4; m_k5 = k5; } - color_t& get_k023() { return m_k023; } - color_t& get_k1() { return m_k1; } + void set_yuv_factors(color_t k02, color_t k13, color_t k4, color_t k5) { m_k02 = k02; m_k13 = k13; m_k4 = k4; m_k5 = k5; } + color_t& get_k02() { return m_k02; } + color_t& get_k13() { return m_k13; } // Blender-related (move into RDP::Blender) void set_blender_input(INT32 cycle, INT32 which, color_t** input_rgb, color_t** input_a, INT32 a, INT32 b, rdp_span_aux* userdata); @@ -219,9 +241,8 @@ public: void render_spans(INT32 start, INT32 end, INT32 tilenum, bool flip, extent_t* spans, bool rect, rdp_poly_state* object); INT32 get_alpha_cvg(INT32 comb_alpha, rdp_span_aux* userdata, const rdp_poly_state &object); - void z_store(const rdp_poly_state &object, UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z, UINT32 enc); + void z_store(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z, UINT32 enc); UINT32 z_decompress(UINT32 zcurpixel); - UINT32 dz_decompress(UINT32 zcurpixel, UINT32 dzcurpixel); UINT32 dz_compress(UINT32 value); INT32 normalize_dzpix(INT32 sum); bool z_compare(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 sz, UINT16 dzpix, rdp_span_aux* userdata, const rdp_poly_state &object); @@ -268,8 +289,7 @@ public: void cmd_set_mask_image(UINT32 w1, UINT32 w2); void cmd_set_color_image(UINT32 w1, UINT32 w2); - void rgbaz_clip(INT32 sr, INT32 sg, INT32 sb, INT32 sa, INT32* sz, rdp_span_aux* userdata); - void rgbaz_correct_triangle(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z, rdp_span_aux* userdata, const rdp_poly_state &object); + void rgbaz_correct_clip(INT32 offx, INT32 offy, INT32* r, INT32* g, INT32* b, INT32* a, INT32* z, rdp_span_aux* userdata, const rdp_poly_state &object); void triangle(bool shade, bool texture, bool zbuffer); @@ -324,8 +344,10 @@ public: n64_tile_t m_tiles[8]; private: - void compute_cvg_noflip(extent_t* spans, INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl, INT32 base); - void compute_cvg_flip(extent_t* spans, INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl, INT32 base); + void deduce_derivatives(rdp_span_aux *userdata); + void get_span_userdata(void** userdata); + void compute_cvg_noflip(rdp_span_aux* data, UINT32 lx, UINT32 rx); + void compute_cvg_flip(rdp_span_aux* data, UINT32 lx, UINT32 rx); void write_pixel(UINT32 curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object); void read_pixel(UINT32 curpixel, rdp_span_aux* userdata, const rdp_poly_state &object); @@ -338,12 +360,13 @@ private: void video_update16(n64_periphs* n64, bitmap_rgb32 &bitmap); void video_update32(n64_periphs* n64, bitmap_rgb32 &bitmap); - typedef void (n64_rdp::*compute_cvg_t) (extent_t* spans, INT32* majorx, INT32* minorx, INT32* majorxint, INT32* minorxint, INT32 scanline, INT32 yh, INT32 yl, INT32 base); + typedef void (n64_rdp::*compute_cvg_t) (rdp_span_aux* data, UINT32 lx, UINT32 rx); compute_cvg_t m_compute_cvg[2]; running_machine* m_machine; combine_modes_t m_combine; + mode_derivs_t m_mode_derivs; bool m_pending_mode_block; bool m_pipe_clean; @@ -367,8 +390,8 @@ private: UINT8* m_tmem; // YUV factors - color_t m_k023; - color_t m_k1; + color_t m_k02; + color_t m_k13; color_t m_k4; color_t m_k5; @@ -378,6 +401,7 @@ private: INT32 m_gamma_table[256]; INT32 m_gamma_dither_table[0x4000]; + UINT32 m_dz_compare_lut[0x10000]; static UINT32 s_special_9bit_clamptable[512]; static const z_decompress_entry_t m_z_dec_table[8]; diff --git a/src/mame/video/n64types.h b/src/mame/video/n64types.h index fedac9e0225..6984f80243c 100644 --- a/src/mame/video/n64types.h +++ b/src/mame/video/n64types.h @@ -143,13 +143,20 @@ struct span_base_t INT32 m_span_dt; INT32 m_span_dw; INT32 m_span_dz; - INT32 m_span_dymax; - INT32 m_span_dzpix; INT32 m_span_drdy; INT32 m_span_dgdy; INT32 m_span_dbdy; INT32 m_span_dady; + INT32 m_span_dsdy; + INT32 m_span_dtdy; + INT32 m_span_dwdy; INT32 m_span_dzdy; + INT32 m_span_dzpix; + INT32 m_span_cdr; + INT32 m_span_cdg; + INT32 m_span_cdb; + INT32 m_span_cda; + INT32 m_span_cdz; }; struct combine_modes_t @@ -242,6 +249,20 @@ struct rectangle_t UINT16 m_yl; // 10.2 fixed-point UINT16 m_xh; // 10.2 fixed-point UINT16 m_yh; // 10.2 fixed-point + + bool m_field; + bool m_keep_odd; +}; + +struct mode_derivs_t +{ + bool m_stale_derivs; + bool m_do_lod; + bool m_partial_reject_1cycle; + bool m_partial_reject_2cycle; + bool m_special_bsel0; + bool m_special_bsel1; + INT32 m_rgb_alpha_dither; }; struct rdp_poly_state @@ -252,6 +273,7 @@ struct rdp_poly_state other_modes_t m_other_modes; /* miscellaneous rasterizer bits (2) */ span_base_t m_span_base; /* span initial values for triangle rasterization */ rectangle_t m_scissor; /* screen-space scissor bounds */ + mode_derivs_t m_mode_derivs; UINT32 m_fill_color; /* poly fill color */ n64_tile_t m_tiles[8]; /* texture tile state */ UINT8 m_tmem[0x1000]; /* texture cache */ @@ -266,7 +288,7 @@ struct rdp_poly_state struct rdp_span_aux { UINT32 m_unscissored_rx; - UINT16 m_cvg[RDP_CVG_SPAN_MAX]; + UINT8 m_cvg[RDP_CVG_SPAN_MAX]; color_t m_memory_color; color_t m_pixel_color; color_t m_inv_pixel_color; @@ -278,8 +300,10 @@ struct rdp_span_aux color_t m_texel0_alpha; color_t m_texel1_color; color_t m_texel1_alpha; - color_t m_next_texel_color; - color_t m_next_texel_alpha; + color_t m_next_texel0_color; + color_t m_next_texel0_alpha; + color_t m_next_texel1_color; + color_t m_next_texel1_alpha; color_t m_blend_color; /* constant blend color */ color_t m_prim_color; /* flat primitive color */ color_t m_prim_alpha; /* flat primitive alpha */ @@ -300,6 +324,9 @@ struct rdp_span_aux UINT32 m_current_cvg_bit; INT32 m_shift_a; INT32 m_shift_b; + INT32 m_prev_shift_a; + INT32 m_prev_shift_b; + INT32 m_prev_raw_dzmem; INT32 m_precomp_s; INT32 m_precomp_t; INT32 m_blend_enable; @@ -308,6 +335,21 @@ struct rdp_span_aux UINT8* m_tmem; /* pointer to texture cache for this polygon */ bool m_start_span; rgbaint_t m_clamp_diff[8]; + bool m_noise_used; + INT32 m_majorx[4]; + INT32 m_minorx[4]; + bool m_valid_line; + bool m_next_valid; + INT32 m_next_s; + INT32 m_next_t; + INT32 m_next_w; + bool m_invalid_y[4]; + bool m_long_span; + bool m_mid_span; + bool m_almost_mid_span; + bool m_end_span; + bool m_pre_end_span; + bool m_next_span; }; struct z_decompress_entry_t 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) { diff --git a/src/mame/video/rdptpipe.h b/src/mame/video/rdptpipe.h index 81898fb1432..b8c947f4cc1 100644 --- a/src/mame/video/rdptpipe.h +++ b/src/mame/video/rdptpipe.h @@ -99,6 +99,12 @@ class n64_texture_pipe_t void copy(color_t* TEX, INT32 SSS, INT32 SST, UINT32 tilenum, const rdp_poly_state& object, rdp_span_aux* userdata); void calculate_clamp_diffs(UINT32 prim_tile, rdp_span_aux* userdata, const rdp_poly_state& object); + void tclod_tcclamp(INT32* sss, INT32* sst); + void 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); + void 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); + void 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); + void 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); + void lodfrac_lodtile_signals(bool lodclamp, INT32 lod, UINT32* l_tile, bool* magnify, bool* distant, rdp_span_aux* userdata, const rdp_poly_state& object); void lod_1cycle(INT32* sss, INT32* sst, const INT32 s, const INT32 t, const INT32 w, const INT32 dsinc, const INT32 dtinc, const INT32 dwinc, rdp_span_aux* userdata, const rdp_poly_state& object); void lod_2cycle(INT32* sss, INT32* sst, const INT32 s, const INT32 t, const INT32 w, const INT32 dsinc, const INT32 dtinc, const INT32 dwinc, const INT32 prim_tile, INT32* t1, INT32* t2, rdp_span_aux* userdata, const rdp_poly_state& object); void lod_2cycle_limited(INT32* sss, INT32* sst, const INT32 s, const INT32 t, INT32 w, const INT32 dsinc, const INT32 dtinc, const INT32 dwinc, const INT32 prim_tile, INT32* t1, const rdp_poly_state& object); @@ -108,6 +114,7 @@ class n64_texture_pipe_t bool m_start_span; private: + void tclod_4x17_to_15(INT32 scurr, INT32 snext, INT32 tcurr, INT32 tnext, INT32 previous, INT32* lod); void mask(rgbaint_t& sstt, const n64_tile_t& tile); rgbaint_t shift_cycle(rgbaint_t& st, const n64_tile_t& tile); @@ -158,9 +165,11 @@ class n64_texture_pipe_t INT32 m_maskbits_table[16]; color_t m_expand_16to32_table[0x10000]; UINT16 m_lod_lookup[0x80000]; + INT32 m_log2_table[0x100]; rgbaint_t m_st2_add; rgbaint_t m_v1; + rgbaint_t m_yuv1; }; #endif // _VIDEO_RDPTEXPIPE_H_ -- cgit v1.2.3