From b4bda080b3a71e573d65c1255feb0b9603255a6a Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 23 Oct 2014 00:09:22 +1100 Subject: These line endings will be the death of me. --- src/mame/video/n64.c | 7711 +++++++++++++++++++++++++------------------------- 1 file changed, 3855 insertions(+), 3856 deletions(-) diff --git a/src/mame/video/n64.c b/src/mame/video/n64.c index d66fdc0f0a3..6edb92cb2c9 100644 --- a/src/mame/video/n64.c +++ b/src/mame/video/n64.c @@ -1,3856 +1,3855 @@ -/****************************************************************************** - - - SGI/Nintendo Reality Display Processor - ------------------- - - by MooglyGuy - based on initial C code by Ville Linde - contains additional improvements from angrylion, Ziggy, Gonetz and Orkin - - -******************************************************************************* - -STATUS: - -Much behavior needs verification against real hardware. Many edge cases must -be verified on real hardware as well. - -TODO: - -- Further re-work class structure to avoid dependencies - -*******************************************************************************/ - -#include "emu.h" -//#include "includes/n64.h" -#include "video/n64.h" - -#define LOG_RDP_EXECUTION 0 - -static FILE *rdp_exec; - -UINT32 n64_rdp::s_special_9bit_clamptable[512]; - -bool n64_rdp::rdp_range_check(UINT32 addr) -{ - if(MiscState.FBSize == 0) return false; - - int fbcount = ((MiscState.FBWidth * Scissor.m_yl) << (MiscState.FBSize - 1)) * 3; - int fbaddr = MiscState.FBAddress & 0x007fffff; - if ((addr >= fbaddr) && (addr < (fbaddr + fbcount))) - { - return false; - } - - int zbcount = MiscState.FBWidth * Scissor.m_yl * 2; - int zbaddr = MiscState.ZBAddress & 0x007fffff; - if ((addr >= zbaddr) && (addr < (zbaddr + zbcount))) - { - return false; - } - - printf("Check failed: %08x vs. %08x-%08x, %08x-%08x (%d, %d)\n", addr, fbaddr, fbaddr + fbcount, zbaddr, zbaddr + zbcount, MiscState.FBWidth, Scissor.m_yl); - fflush(stdout); - return true; -} - -/*****************************************************************************/ - -// The functions in this file should be moved into the parent Processor class. -#include "rdpfiltr.inc" - -void n64_rdp::GetAlphaCvg(UINT8 *comb_alpha, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - INT32 temp = *comb_alpha; - INT32 temp2 = userdata->CurrentPixCvg; - INT32 temp3 = 0; - - if (object.OtherModes.cvg_times_alpha) - { - temp3 = (temp * temp2) + 4; - userdata->CurrentPixCvg = (temp3 >> 8) & 0xf; - } - if (object.OtherModes.alpha_cvg_select) - { - temp = (OtherModes.cvg_times_alpha) ? (temp3 >> 3) : (temp2 << 5); - } - if (temp > 0xff) - { - temp = 0xff; - } - *comb_alpha = temp; -} - -/*****************************************************************************/ - -void n64_rdp::VideoUpdate(n64_periphs *n64, bitmap_rgb32 &bitmap) -{ - switch(n64->vi_control & 0x3) - { - case PIXEL_SIZE_16BIT: - VideoUpdate16(n64, bitmap); - break; - - case PIXEL_SIZE_32BIT: - VideoUpdate32(n64, bitmap); - break; - - default: - //fatalerror("Unsupported framebuffer depth: m_fb_size=%d\n", MiscState.FBSize); - break; - } -} - -void n64_rdp::VideoUpdate16(n64_periphs *n64, bitmap_rgb32 &bitmap) -{ - //int fsaa = (((n64->vi_control >> 8) & 3) < 2); - //int divot = (n64->vi_control >> 4) & 1; - - //UINT32 prev_cvg = 0; - //UINT32 next_cvg = 0; - //int dither_filter = (n64->vi_control >> 16) & 1; - //int vibuffering = ((n64->vi_control & 2) && fsaa && divot); - - UINT16 *frame_buffer = (UINT16*)&rdram[(n64->vi_origin & 0xffffff) >> 2]; - //UINT32 hb = ((n64->vi_origin & 0xffffff) >> 2) >> 1; - //UINT8* hidden_buffer = &HiddenBits[hb]; - - INT32 hdiff = (n64->vi_hstart & 0x3ff) - ((n64->vi_hstart >> 16) & 0x3ff); - float hcoeff = ((float)(n64->vi_xscale & 0xfff) / (1 << 10)); - UINT32 hres = ((float)hdiff * hcoeff); - INT32 invisiblewidth = n64->vi_width - hres; - - INT32 vdiff = ((n64->vi_vstart & 0x3ff) - ((n64->vi_vstart >> 16) & 0x3ff)) >> 1; - float vcoeff = ((float)(n64->vi_yscale & 0xfff) / (1 << 10)); - UINT32 vres = ((float)vdiff * vcoeff); - - if (vdiff <= 0 || hdiff <= 0) - { - return; - } - - if (hres > 640) // Needed by Top Gear Overdrive (E) - { - invisiblewidth += (hres - 640); - hres = 640; - } - - if (vres > bitmap.height()) // makes Perfect Dark boot w/o crashing - { - vres = bitmap.height(); - } - - UINT32 pixels = 0; - - if (frame_buffer) - { - for(int j = 0; j < vres; j++) - { - UINT32 *d = &bitmap.pix32(j); - - for(int i = 0; i < hres; i++) - { - Color c; - //int r, g, b; - - UINT16 pix = frame_buffer[pixels ^ WORD_ADDR_XOR]; - //MiscState.CurrentPixCvg = ((pix & 1) << 2) | (hidden_buffer[pixels ^ BYTE_ADDR_XOR] & 3); - - //if(divot) - //{ - // if(i > 0 && i < (hres - 1)) - // { - // prev_cvg = ((frame_buffer[(pixels - 1)^WORD_ADDR_XOR] & 1) << 2) | (hidden_buffer[(pixels - 1)^BYTE_ADDR_XOR] & 3); - // next_cvg = ((frame_buffer[(pixels + 1)^WORD_ADDR_XOR] & 1) << 2) | (hidden_buffer[(pixels + 1)^BYTE_ADDR_XOR] & 3); - // } - //} - c.i.r = ((pix >> 8) & 0xf8) | (pix >> 13); - c.i.g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); - c.i.b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); - - //if(fsaa) - //{ - //if (/*!vibuffering &&*/ state->m_rdp.MiscState.CurrentPixCvg < 7 && i > 1 && j > 1 && i < (hres - 2) && j < (vres - 2)) - //{ - //video_filter16(&c.i.r, &c.i.g, &c.i.b, &frame_buffer[pixels ^ WORD_ADDR_XOR],&hidden_buffer[pixels ^ BYTE_ADDR_XOR], n64->vi_width); - //} - //} - //else if (dither_filter && state->m_rdp.MiscState.CurrentPixCvg == 7 && i > 0 && j > 0 && i < (hres - 1) && j < (vres - 1)) - //{ - //if (vibuffering) - //{ - // restore_filter16_buffer(&r, &g, &b, &ViBuffer[i][j], n64->vi_width); - //} - //else - //{ - //restore_filter16(&c.i.r, &c.i.g, &c.i.b, &frame_buffer[pixels ^ WORD_ADDR_XOR], pixels ^ WORD_ADDR_XOR, n64->vi_width); - //} - //} - //if(divot) - //{ - //if (i > 0 && i < (hres - 1) && (MiscState.CurrentPixCvg != 7 || prev_cvg != 7 || next_cvg != 7)) - //{ - //if (vibuffering) - //{ - // divot_filter16_buffer(&r, &g, &b, &ViBuffer[i][j]); - //} - //else - //{ - //divot_filter16(&c.i.r, &c.i.g, &c.i.b, &frame_buffer[pixels ^ WORD_ADDR_XOR], pixels ^ WORD_ADDR_XOR); - //} - //} - //} - - /* - if (gamma_dither) - { - dith = screen.machine().rand() & 0x3f; - } - if (gamma) - { - if (gamma_dither) - { - r = m_gamma_dither_table[(r << 6)|dith]; - g = m_gamma_dither_table[(g << 6)|dith]; - b = m_gamma_dither_table[(b << 6)|dith]; - } - else - { - r = m_gamma_table[r]; - g = m_gamma_table[g]; - b = m_gamma_table[b]; - } - } - else if (gamma_dither) - { - if (r < 255) - r += (dith & 1); - if (g < 255) - g += (dith & 1); - if (b < 255) - b += (dith & 1); - } - */ - pixels++; - - d[i] = c.c >> 8;//(r << 16) | (g << 8) | b; // Fix me for endianness - } - pixels +=invisiblewidth; - } - } -} - -void n64_rdp::VideoUpdate32(n64_periphs *n64, bitmap_rgb32 &bitmap) -{ - int gamma = (n64->vi_control >> 3) & 1; - int gamma_dither = (n64->vi_control >> 2) & 1; - //int vibuffering = ((n64->vi_control & 2) && fsaa && divot); - - UINT32 *frame_buffer32 = (UINT32*)&rdram[(n64->vi_origin & 0xffffff) >> 2]; - - const INT32 hdiff = (n64->vi_hstart & 0x3ff) - ((n64->vi_hstart >> 16) & 0x3ff); - const float hcoeff = ((float)(n64->vi_xscale & 0xfff) / (1 << 10)); - UINT32 hres = ((float)hdiff * hcoeff); - INT32 invisiblewidth = n64->vi_width - hres; - - const INT32 vdiff = ((n64->vi_vstart & 0x3ff) - ((n64->vi_vstart >> 16) & 0x3ff)) >> 1; - const float vcoeff = ((float)(n64->vi_yscale & 0xfff) / (1 << 10)); - const UINT32 vres = ((float)vdiff * vcoeff); - - if (vdiff <= 0 || hdiff <= 0) - { - return; - } - - if (hres > 640) // Needed by Top Gear Overdrive (E) - { - invisiblewidth += (hres - 640); - hres = 640; - } - - if (frame_buffer32) - { - for (int j = 0; j < vres; j++) - { - UINT32 *d = &bitmap.pix32(j); - for (int i = 0; i < hres; i++) - { - UINT32 pix = *frame_buffer32++; - if (gamma || gamma_dither) - { - int r = (pix >> 24) & 0xff; - int g = (pix >> 16) & 0xff; - int b = (pix >> 8) & 0xff; - int dith = 0; - if (gamma_dither) - { - dith = GetRandom() & 0x3f; - } - if (gamma) - { - if (gamma_dither) - { - r = m_gamma_dither_table[(r << 6)| dith]; - g = m_gamma_dither_table[(g << 6)| dith]; - b = m_gamma_dither_table[(b << 6)| dith]; - } - else - { - r = m_gamma_table[r]; - g = m_gamma_table[g]; - b = m_gamma_table[b]; - } - } - else if (gamma_dither) - { - if (r < 255) - r += (dith & 1); - if (g < 255) - g += (dith & 1); - if (b < 255) - b += (dith & 1); - } - pix = (r << 24) | (g << 16) | (b << 8); - } - - - d[i] = (pix >> 8); - } - frame_buffer32 += invisiblewidth; - } - } -} - -/*****************************************************************************/ - -void n64_rdp::TCDivNoPersp(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst) -{ - *sss = (SIGN16(ss)) & 0x1ffff; - *sst = (SIGN16(st)) & 0x1ffff; -} - -void n64_rdp::TCDiv(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst) -{ - int w_carry = 0; - if ((sw & 0x8000) || !(sw & 0x7fff)) - { - w_carry = 1; - } - - sw &= 0x7fff; - - int shift; - for (shift = 1; shift <= 14 && !((sw << shift) & 0x8000); shift++); - shift -= 1; - - int normout = (sw << shift) & 0x3fff; - int wnorm = (normout & 0xff) << 2; - normout >>= 8; - - int temppoint = m_norm_point_rom[normout]; - int tempslope = m_norm_slope_rom[normout]; - - int tlu_rcp = ((-(tempslope * wnorm)) >> 10) + temppoint; - - int sprod = SIGN16(ss) * tlu_rcp; - int tprod = SIGN16(st) * tlu_rcp; - int tempmask = ((1 << (shift + 1)) - 1) << (29 - shift); - int shift_value = 13 - shift; - - int outofbounds_s = sprod & tempmask; - int outofbounds_t = tprod & tempmask; - if (shift == 0xe) - { - *sss = sprod << 1; - *sst = tprod << 1; - } - else - { - *sss = sprod = (sprod >> shift_value); - *sst = tprod = (tprod >> shift_value); - } - //compute clamp flags - int under_s = 0; - int under_t = 0; - int over_s = 0; - int over_t = 0; - - if (outofbounds_s != tempmask && outofbounds_s != 0) - { - if (sprod & (1 << 29)) - { - under_s = 1; - } - else - { - over_s = 1; - } - } - - if (outofbounds_t != tempmask && outofbounds_t != 0) - { - if (tprod & (1 << 29)) - { - under_t = 1; - } - else - { - over_t = 1; - } - } - - over_s |= w_carry; - over_t |= w_carry; - - *sss = (*sss & 0x1ffff) | (over_s << 18) | (under_s << 17); - *sst = (*sst & 0x1ffff) | (over_t << 18) | (under_t << 17); -} - -INT32 n64_rdp::ColorCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d) -{ - a = KURT_AKELEY_SIGN9(a); - b = KURT_AKELEY_SIGN9(b); - c = SIGN9(c); - d = KURT_AKELEY_SIGN9(d); - a = (((a - b) * c) + (d << 8) + 0x80); - a = SIGN17(a) >> 8; - a = s_special_9bit_clamptable[a & 0x1ff]; - return a; -} - -INT32 n64_rdp::AlphaCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d) -{ - a = KURT_AKELEY_SIGN9(a); - b = KURT_AKELEY_SIGN9(b); - c = SIGN9(c); - d = KURT_AKELEY_SIGN9(d); - a = (((a - b) * c) + (d << 8) + 0x80) >> 8; - a = SIGN9(a); - a = s_special_9bit_clamptable[a & 0x1ff]; - return a; -} - -void n64_rdp::SetSubAInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) -{ - switch (code & 0xf) - { - case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; - case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; - case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; - case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; - case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; - case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; - case 6: *input_r = &OneColor.i.r; *input_g = &OneColor.i.g; *input_b = &OneColor.i.b; break; - case 7: *input_r = &userdata->NoiseColor.i.r; *input_g = &userdata->NoiseColor.i.g; *input_b = &userdata->NoiseColor.i.b; break; - case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: - { - *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; - } - } -} - -void n64_rdp::SetSubBInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) -{ - switch (code & 0xf) - { - case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; - case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; - case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; - case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; - case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; - case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; - case 6: fatalerror("SET_SUBB_RGB_INPUT: key_center\n"); - case 7: *input_r = (UINT8*)&m_k4; *input_g = (UINT8*)&m_k4; *input_b = (UINT8*)&m_k4; break; - case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: - { - *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; - } - } -} - -void n64_rdp::SetMulInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) -{ - switch (code & 0x1f) - { - case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; - case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; - case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; - case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; - case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; - case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; - case 6: *input_r = &userdata->KeyScale.i.r; *input_g = &userdata->KeyScale.i.g; *input_b = &userdata->KeyScale.i.b; break; - case 7: *input_r = &userdata->CombinedColor.i.a; *input_g = &userdata->CombinedColor.i.a; *input_b = &userdata->CombinedColor.i.a; break; - case 8: *input_r = &userdata->Texel0Color.i.a; *input_g = &userdata->Texel0Color.i.a; *input_b = &userdata->Texel0Color.i.a; break; - case 9: *input_r = &userdata->Texel1Color.i.a; *input_g = &userdata->Texel1Color.i.a; *input_b = &userdata->Texel1Color.i.a; break; - case 10: *input_r = &userdata->PrimColor.i.a; *input_g = &userdata->PrimColor.i.a; *input_b = &userdata->PrimColor.i.a; break; - case 11: *input_r = &userdata->ShadeColor.i.a; *input_g = &userdata->ShadeColor.i.a; *input_b = &userdata->ShadeColor.i.a; break; - case 12: *input_r = &userdata->EnvColor.i.a; *input_g = &userdata->EnvColor.i.a; *input_b = &userdata->EnvColor.i.a; break; - case 13: *input_r = &userdata->LODFraction; *input_g = &userdata->LODFraction; *input_b = &userdata->LODFraction; break; - case 14: *input_r = &userdata->PrimLODFraction; *input_g = &userdata->PrimLODFraction; *input_b = &userdata->PrimLODFraction; break; - case 15: *input_r = (UINT8*)&m_k5; *input_g = (UINT8*)&m_k5; *input_b = (UINT8*)&m_k5; break; - case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: - case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: - { - *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; - } - } -} - -void n64_rdp::SetAddInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) -{ - switch (code & 0x7) - { - case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; - case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; - case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; - case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; - case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; - case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; - case 6: *input_r = &OneColor.i.r; *input_g = &OneColor.i.g; *input_b = &OneColor.i.b; break; - case 7: *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; - } -} - -void n64_rdp::SetSubInputAlpha(UINT8 **input, int code, rdp_span_aux *userdata) -{ - switch (code & 0x7) - { - case 0: *input = &userdata->CombinedColor.i.a; break; - case 1: *input = &userdata->Texel0Color.i.a; break; - case 2: *input = &userdata->Texel1Color.i.a; break; - case 3: *input = &userdata->PrimColor.i.a; break; - case 4: *input = &userdata->ShadeColor.i.a; break; - case 5: *input = &userdata->EnvColor.i.a; break; - case 6: *input = &OneColor.i.a; break; - case 7: *input = &ZeroColor.i.a; break; - } -} - -void n64_rdp::SetMulInputAlpha(UINT8 **input, int code, rdp_span_aux *userdata) -{ - switch (code & 0x7) - { - case 0: *input = &userdata->LODFraction; break; - case 1: *input = &userdata->Texel0Color.i.a; break; - case 2: *input = &userdata->Texel1Color.i.a; break; - case 3: *input = &userdata->PrimColor.i.a; break; - case 4: *input = &userdata->ShadeColor.i.a; break; - case 5: *input = &userdata->EnvColor.i.a; break; - case 6: *input = &userdata->PrimLODFraction; break; - case 7: *input = &ZeroColor.i.a; break; - } -} - -void n64_rdp::SetBlenderInput(int cycle, int which, UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, UINT8 **input_a, int a, int b, rdp_span_aux *userdata) -{ - switch (a & 0x3) - { - case 0: - { - if (cycle == 0) - { - *input_r = &userdata->PixelColor.i.r; - *input_g = &userdata->PixelColor.i.g; - *input_b = &userdata->PixelColor.i.b; - } - else - { - *input_r = &userdata->BlendedPixelColor.i.r; - *input_g = &userdata->BlendedPixelColor.i.g; - *input_b = &userdata->BlendedPixelColor.i.b; - } - break; - } - - case 1: - { - *input_r = &userdata->MemoryColor.i.r; - *input_g = &userdata->MemoryColor.i.g; - *input_b = &userdata->MemoryColor.i.b; - break; - } - - case 2: - { - *input_r = &userdata->BlendColor.i.r; - *input_g = &userdata->BlendColor.i.g; - *input_b = &userdata->BlendColor.i.b; - break; - } - - case 3: - { - *input_r = &userdata->FogColor.i.r; - *input_g = &userdata->FogColor.i.g; - *input_b = &userdata->FogColor.i.b; - break; - } - } - - if (which == 0) - { - switch (b & 0x3) - { - case 0: *input_a = &userdata->PixelColor.i.a; break; - case 1: *input_a = &userdata->FogColor.i.a; break; - case 2: *input_a = &userdata->ShadeColor.i.a; break; - case 3: *input_a = &ZeroColor.i.a; break; - } - } - else - { - switch (b & 0x3) - { - case 0: *input_a = &userdata->InvPixelColor.i.a; break; - case 1: *input_a = &userdata->MemoryColor.i.a; break; - case 2: *input_a = &OneColor.i.a; break; - case 3: *input_a = &ZeroColor.i.a; break; - } - } -} - -const UINT8 n64_rdp::s_bayer_matrix[16] = -{ /* Bayer matrix */ - 0, 4, 1, 5, - 6, 2, 7, 3, - 1, 5, 0, 4, - 7, 3, 6, 2 -}; - -const UINT8 n64_rdp::s_magic_matrix[16] = -{ /* Magic square matrix */ - 0, 6, 1, 7, - 4, 2, 5, 3, - 3, 5, 2, 4, - 7, 1, 6, 0 -}; - -const n64_rdp::ZDecompressEntry n64_rdp::z_dec_table[8] = -{ - { 6, 0x00000 }, - { 5, 0x20000 }, - { 4, 0x30000 }, - { 3, 0x38000 }, - { 2, 0x3c000 }, - { 1, 0x3e000 }, - { 0, 0x3f000 }, - { 0, 0x3f800 }, -}; - -/*****************************************************************************/ - -void n64_rdp::z_build_com_table(void) -{ - UINT16 altmem = 0; - for(int z = 0; z < 0x40000; z++) - { - switch((z >> 11) & 0x7f) - { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - case 0x1b: - case 0x1c: - case 0x1d: - case 0x1e: - case 0x1f: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2a: - case 0x2b: - case 0x2c: - case 0x2d: - case 0x2e: - case 0x2f: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - case 0x3f: - altmem = (z >> 4) & 0x1ffc; - break; - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4a: - case 0x4b: - case 0x4c: - case 0x4d: - case 0x4e: - case 0x4f: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - altmem = ((z >> 3) & 0x1ffc) | 0x2000; - break; - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6a: - case 0x6b: - case 0x6c: - case 0x6d: - case 0x6e: - case 0x6f: - altmem = ((z >> 2) & 0x1ffc) | 0x4000; - break; - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - altmem = ((z >> 1) & 0x1ffc) | 0x6000; - break; - case 0x78://uncompressed z = 0x3c000 - case 0x79: - case 0x7a: - case 0x7b: - altmem = (z & 0x1ffc) | 0x8000; - break; - case 0x7c://uncompressed z = 0x3e000 - case 0x7d: - altmem = ((z << 1) & 0x1ffc) | 0xa000; - break; - case 0x7e://uncompressed z = 0x3f000 - altmem = ((z << 2) & 0x1ffc) | 0xc000; - break; - case 0x7f://uncompressed z = 0x3f000 - altmem = ((z << 2) & 0x1ffc) | 0xe000; - break; - } - - z_com_table[z] = altmem; - - } -} - -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 (int i = 0; i < 0x10000; i++) - { - 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 (int i = 0; i < 0x100; i++) - { - UINT16 mask = decompress_cvmask_frombyte(i); - cvarray[i].cvg = cvarray[i].cvbit = 0; - cvarray[i].cvbit = (i >> 7) & 1; - for (int k = 0; k < 8; k++) - { - cvarray[i].cvg += ((i >> k) & 1); - } - - UINT16 masky = 0; - for (int k = 0; k < 4; k++) - { - masky |= ((mask & (0xf000 >> (k << 2))) > 0) << k; - } - UINT8 offy = yarray[masky]; - - UINT16 maskx = (mask & (0xf000 >> (offy << 2))) >> ((offy ^ 3) << 2); - UINT8 offx = xarray[maskx]; - - cvarray[i].xoff = offx; - cvarray[i].yoff = offy; - } -} - -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; -} - -void n64_rdp::lookup_cvmask_derivatives(UINT32 mask, UINT8* offx, UINT8* offy, rdp_span_aux *userdata) -{ - UINT32 index = compressed_cvmasks[mask]; - userdata->CurrentPixCvg = cvarray[index].cvg; - userdata->CurrentCvgBit = cvarray[index].cvbit; - *offx = cvarray[index].xoff; - *offy = cvarray[index].yoff; -} - -void n64_rdp::ZStore(const rdp_poly_state &object, UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z, UINT32 enc) -{ - UINT16 zval = z_com_table[z & 0x3ffff]|(enc >> 2); - if(zcurpixel <= MEM16_LIMIT) - { - ((UINT16*)rdram)[zcurpixel ^ WORD_ADDR_XOR] = zval; - } - if(dzcurpixel <= MEM8_LIMIT) - { - HiddenBits[dzcurpixel ^ BYTE_ADDR_XOR] = enc & 3; - } -} - -INT32 n64_rdp::NormalizeDZPix(INT32 sum) -{ - if (sum & 0xc000) - { - return 0x8000; - } - if (!(sum & 0xffff)) - { - return 1; - } - for(int count = 0x2000; count > 0; count >>= 1) - { - if (sum & count) - { - return(count << 1); - } - } - return 0; -} - -UINT32 n64_rdp::ZDecompress(UINT32 zcurpixel) -{ - UINT32 zb = RREADIDX16(zcurpixel); - CHECK16(zcurpixel); - return z_complete_dec_table[(zb >> 2) & 0x3fff]; -} - -UINT32 n64_rdp::DZDecompress(UINT32 zcurpixel, UINT32 dzcurpixel) -{ - UINT16 zval = RREADIDX16(zcurpixel); - CHECK16(zcurpixel); - UINT8 dzval = (((dzcurpixel) <= 0x7fffff) ? (HiddenBits[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0); - UINT32 dz_compressed = ((zval & 3) << 2) | (dzval & 3); - return (1 << dz_compressed); -} - -UINT32 n64_rdp::DZCompress(UINT32 value) -{ - INT32 j = 0; - for (; value > 1; j++, value >>= 1); - return j; -} - -void n64_rdp::GetDitherValues(int x, int y, int* cdith, int* adith, const rdp_poly_state& object) -{ - int dithindex = ((y & 3) << 2) | (x & 3); - switch((object.OtherModes.rgb_dither_sel << 2) | object.OtherModes.alpha_dither_sel) - { - case 0: - *adith = *cdith = s_magic_matrix[dithindex]; - break; - case 1: - *cdith = s_magic_matrix[dithindex]; - *adith = (~(*cdith)) & 7; - break; - case 2: - *cdith = s_magic_matrix[dithindex]; - *adith = machine().rand() & 7; - break; - case 3: - *cdith = s_magic_matrix[dithindex]; - *adith = 0; - break; - case 4: - *adith = *cdith = s_bayer_matrix[dithindex]; - break; - case 5: - *cdith = s_bayer_matrix[dithindex]; - *adith = (~(*cdith)) & 7; - break; - case 6: - *cdith = s_bayer_matrix[dithindex]; - *adith = machine().rand() & 7; - break; - case 7: - *cdith = s_bayer_matrix[dithindex]; - *adith = 0; - break; - case 8: - *cdith = machine().rand() & 7; - *adith = s_magic_matrix[dithindex]; - break; - case 9: - *cdith = machine().rand() & 7; - *adith = (~s_magic_matrix[dithindex]) & 7; - break; - case 10: - *cdith = machine().rand() & 7; - *adith = (*cdith + 17) & 7; - break; - case 11: - *cdith = machine().rand() & 7; - *adith = 0; - break; - case 12: - *cdith = 0; - *adith = s_bayer_matrix[dithindex]; - break; - case 13: - *cdith = 0; - *adith = (~s_bayer_matrix[dithindex]) & 7; - break; - case 14: - *cdith = 0; - *adith = m_machine->rand() & 7; - break; - case 15: - *adith = *cdith = 0; - break; - } -} - -INT32 CLAMP(INT32 in, INT32 min, INT32 max) -{ - if(in < min) return min; - if(in > max) return max; - return in; -} - -bool n64_rdp::ZCompare(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 sz, UINT16 dzpix, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - bool force_coplanar = false; - sz &= 0x3ffff; - - UINT32 oz; - UINT32 dzmem; - UINT32 zval; - INT32 rawdzmem; - - if (object.OtherModes.z_compare_en) - { - oz = ZDecompress(zcurpixel); - dzmem = DZDecompress(zcurpixel, dzcurpixel); - zval = RREADIDX16(zcurpixel); - CHECK16(zcurpixel); - rawdzmem = ((zval & 3) << 2) | ((((dzcurpixel) <= 0x3fffff) ? (HiddenBits[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0) & 3); - } - else - { - oz = 0; - dzmem = 1 << 0xf; - zval = 0x3; - rawdzmem = 0xf; - } - - userdata->m_dzpix_enc = DZCompress(dzpix & 0xffff); - userdata->ShiftA = CLAMP(userdata->m_dzpix_enc - rawdzmem, 0, 4); - userdata->ShiftB = CLAMP(rawdzmem - userdata->m_dzpix_enc, 0, 4); - - int precision_factor = (zval >> 13) & 0xf; - if (precision_factor < 3) - { - int dzmemmodifier = 16 >> precision_factor; - if (dzmem == 0x8000) - { - force_coplanar = true; - } - dzmem <<= 1; - if (dzmem <= dzmemmodifier) - { - dzmem = dzmemmodifier; - } - if (!dzmem) - { - 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; - } - - bool overflow = ((userdata->CurrentMemCvg + userdata->CurrentPixCvg) & 8) > 0; - userdata->BlendEnable = (object.OtherModes.force_blend || (!overflow && object.OtherModes.antialias_en && farther)) ? 1 : 0; - userdata->PreWrap = overflow; - - int cvgcoeff = 0; - UINT32 dzenc = 0; - - if (object.OtherModes.z_mode == 1 && infront && farther && overflow) - { - dzenc = DZCompress(dznotshift & 0xffff); - cvgcoeff = ((oz >> dzenc) - (sz >> dzenc)) & 0xf; - userdata->CurrentPixCvg = ((cvgcoeff * userdata->CurrentPixCvg) >> 3) & 0xf; - } - - if (!object.OtherModes.z_compare_en) - { - return true; - } - - INT32 diff = (INT32)sz - (INT32)dznew; - bool nearer = diff <= (INT32)oz; - bool max = (oz == 0x3ffff); - if (force_coplanar) - { - nearer = true; - } - - switch(object.OtherModes.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); - } - - return false; -} - -UINT32 n64_rdp::GetLog2(UINT32 lod_clamp) -{ - if (lod_clamp < 2) - { - return 0; - } - else - { - for (int i = 7; i > 0; i--) - { - if ((lod_clamp >> i) & 1) - { - return i; - } - } - } - - return 0; -} - -/*****************************************************************************/ - -UINT32 n64_rdp::ReadData(UINT32 address) -{ - if (m_status & 0x1) // XBUS_DMEM_DMA enabled - { - return rsp_dmem[(address & 0xfff) / 4]; - } - else - { - return rdram[((address & 0xffffff) / 4)]; - } -} - -static const char *const image_format[] = { "RGBA", "YUV", "CI", "IA", "I", "???", "???", "???" }; -static const char *const image_size[] = { "4-bit", "8-bit", "16-bit", "32-bit" }; - -static const int rdp_command_length[64] = -{ - 8, // 0x00, No Op - 8, // 0x01, ??? - 8, // 0x02, ??? - 8, // 0x03, ??? - 8, // 0x04, ??? - 8, // 0x05, ??? - 8, // 0x06, ??? - 8, // 0x07, ??? - 32, // 0x08, Non-Shaded Triangle - 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle - 32+64, // 0x0a, Textured Triangle - 32+64+16, // 0x0b, Textured, Z-Buffered Triangle - 32+64, // 0x0c, Shaded Triangle - 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle - 32+64+64, // 0x0e, Shaded+Textured Triangle - 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle - 8, // 0x10, ??? - 8, // 0x11, ??? - 8, // 0x12, ??? - 8, // 0x13, ??? - 8, // 0x14, ??? - 8, // 0x15, ??? - 8, // 0x16, ??? - 8, // 0x17, ??? - 8, // 0x18, ??? - 8, // 0x19, ??? - 8, // 0x1a, ??? - 8, // 0x1b, ??? - 8, // 0x1c, ??? - 8, // 0x1d, ??? - 8, // 0x1e, ??? - 8, // 0x1f, ??? - 8, // 0x20, ??? - 8, // 0x21, ??? - 8, // 0x22, ??? - 8, // 0x23, ??? - 16, // 0x24, Texture_Rectangle - 16, // 0x25, Texture_Rectangle_Flip - 8, // 0x26, Sync_Load - 8, // 0x27, Sync_Pipe - 8, // 0x28, Sync_Tile - 8, // 0x29, Sync_Full - 8, // 0x2a, Set_Key_GB - 8, // 0x2b, Set_Key_R - 8, // 0x2c, Set_Convert - 8, // 0x2d, Set_Scissor - 8, // 0x2e, Set_Prim_Depth - 8, // 0x2f, Set_Other_Modes - 8, // 0x30, Load_TLUT - 8, // 0x31, ??? - 8, // 0x32, Set_Tile_Size - 8, // 0x33, Load_Block - 8, // 0x34, Load_Tile - 8, // 0x35, Set_Tile - 8, // 0x36, Fill_Rectangle - 8, // 0x37, Set_Fill_Color - 8, // 0x38, Set_Fog_Color - 8, // 0x39, Set_Blend_Color - 8, // 0x3a, Set_Prim_Color - 8, // 0x3b, Set_Env_Color - 8, // 0x3c, Set_Combine - 8, // 0x3d, Set_Texture_Image - 8, // 0x3e, Set_Mask_Image - 8 // 0x3f, Set_Color_Image -}; - -void n64_rdp::Dasm(char *buffer) -{ - int i; - int tile; - const char *format, *size; - char sl[32], tl[32], sh[32], th[32]; - char s[32], t[32], w[32]; - char dsdx[32], dtdx[32], dwdx[32]; - char dsdy[32], dtdy[32], dwdy[32]; - char dsde[32], dtde[32], dwde[32]; - char yl[32], yh[32], ym[32], xl[32], xh[32], xm[32]; - char dxldy[32], dxhdy[32], dxmdy[32]; - char rt[32], gt[32], bt[32], at[32]; - char drdx[32], dgdx[32], dbdx[32], dadx[32]; - char drdy[32], dgdy[32], dbdy[32], dady[32]; - char drde[32], dgde[32], dbde[32], dade[32]; - UINT32 r,g,b,a; - - UINT32 cmd[64]; - UINT32 length; - UINT32 command; - - length = m_cmd_ptr * 4; - if (length < 8) - { - sprintf(buffer, "ERROR: length = %d\n", length); - return; - } - - cmd[0] = m_cmd_data[m_cmd_cur+0]; - cmd[1] = m_cmd_data[m_cmd_cur+1]; - - tile = (cmd[1] >> 24) & 0x7; - sprintf(sl, "%4.2f", (float)((cmd[0] >> 12) & 0xfff) / 4.0f); - sprintf(tl, "%4.2f", (float)((cmd[0] >> 0) & 0xfff) / 4.0f); - sprintf(sh, "%4.2f", (float)((cmd[1] >> 12) & 0xfff) / 4.0f); - sprintf(th, "%4.2f", (float)((cmd[1] >> 0) & 0xfff) / 4.0f); - - format = image_format[(cmd[0] >> 21) & 0x7]; - size = image_size[(cmd[0] >> 19) & 0x3]; - - r = (cmd[1] >> 24) & 0xff; - g = (cmd[1] >> 16) & 0xff; - b = (cmd[1] >> 8) & 0xff; - a = (cmd[1] >> 0) & 0xff; - - command = (cmd[0] >> 24) & 0x3f; - switch (command) - { - case 0x00: sprintf(buffer, "No Op"); break; - case 0x08: // Tri_NoShade - { - int lft = (command >> 23) & 0x1; - - if (length != rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_NoShade length = %d\n", length); - return; - } - - cmd[2] = m_cmd_data[m_cmd_cur+2]; - cmd[3] = m_cmd_data[m_cmd_cur+3]; - cmd[4] = m_cmd_data[m_cmd_cur+4]; - cmd[5] = m_cmd_data[m_cmd_cur+5]; - cmd[6] = m_cmd_data[m_cmd_cur+6]; - cmd[7] = m_cmd_data[m_cmd_cur+7]; - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)(cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)(cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)(cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)(cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)(cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)(cmd[7] / 65536.0f)); - - sprintf(buffer, "Tri_NoShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - break; - } - case 0x09: // Tri_NoShadeZ - { - int lft = (command >> 23) & 0x1; - - if (length != rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_NoShadeZ length = %d\n", length); - return; - } - - cmd[2] = m_cmd_data[m_cmd_cur+2]; - cmd[3] = m_cmd_data[m_cmd_cur+3]; - cmd[4] = m_cmd_data[m_cmd_cur+4]; - cmd[5] = m_cmd_data[m_cmd_cur+5]; - cmd[6] = m_cmd_data[m_cmd_cur+6]; - cmd[7] = m_cmd_data[m_cmd_cur+7]; - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)(cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)(cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)(cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)(cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)(cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)(cmd[7] / 65536.0f)); - - sprintf(buffer, "Tri_NoShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - break; - } - case 0x0a: // Tri_Tex - { - int lft = (command >> 23) & 0x1; - - if (length < rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_Tex length = %d\n", length); - return; - } - - for (i=2; i < 24; i++) - { - cmd[i] = m_cmd_data[m_cmd_cur+i]; - } - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); - - sprintf(s, "%4.4f", (float)(INT32)((cmd[ 8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); - sprintf(t, "%4.4f", (float)(INT32)(((cmd[ 8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); - sprintf(w, "%4.4f", (float)(INT32)((cmd[ 9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); - sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); - sprintf(dwde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); - sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); - - - buffer+=sprintf(buffer, "Tri_Tex %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); - break; - } - case 0x0b: // Tri_TexZ - { - int lft = (command >> 23) & 0x1; - - if (length < rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_TexZ length = %d\n", length); - return; - } - - for (i=2; i < 24; i++) - { - cmd[i] = m_cmd_data[m_cmd_cur+i]; - } - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); - - sprintf(s, "%4.4f", (float)(INT32)((cmd[ 8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); - sprintf(t, "%4.4f", (float)(INT32)(((cmd[ 8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); - sprintf(w, "%4.4f", (float)(INT32)((cmd[ 9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); - sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); - sprintf(dwde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); - sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); - - - buffer+=sprintf(buffer, "Tri_TexZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); - break; - } - case 0x0c: // Tri_Shade - { - int lft = (command >> 23) & 0x1; - - if (length != rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_Shade length = %d\n", length); - return; - } - - for (i=2; i < 24; i++) - { - cmd[i] = m_cmd_data[i]; - } - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); - sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); - sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); - sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); - sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); - sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); - sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); - sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); - sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); - sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); - sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); - sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); - sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); - sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); - - buffer+=sprintf(buffer, "Tri_Shade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); - break; - } - case 0x0d: // Tri_ShadeZ - { - int lft = (command >> 23) & 0x1; - - if (length != rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_ShadeZ length = %d\n", length); - return; - } - - for (i=2; i < 24; i++) - { - cmd[i] = m_cmd_data[i]; - } - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); - sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); - sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); - sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); - sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); - sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); - sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); - sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); - sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); - sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); - sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); - sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); - sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); - sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); - - buffer+=sprintf(buffer, "Tri_ShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); - break; - } - case 0x0e: // Tri_TexShade - { - int lft = (command >> 23) & 0x1; - - if (length < rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_TexShade length = %d\n", length); - return; - } - - for (i=2; i < 40; i++) - { - cmd[i] = m_cmd_data[m_cmd_cur+i]; - } - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); - sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); - sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); - sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); - sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); - sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); - sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); - sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); - sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); - sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); - sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); - sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); - sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); - sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); - - sprintf(s, "%4.4f", (float)(INT32)((cmd[24] & 0xffff0000) | ((cmd[28] >> 16) & 0xffff)) / 65536.0f); - sprintf(t, "%4.4f", (float)(INT32)(((cmd[24] & 0xffff) << 16) | (cmd[28] & 0xffff)) / 65536.0f); - sprintf(w, "%4.4f", (float)(INT32)((cmd[25] & 0xffff0000) | ((cmd[29] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[26] & 0xffff0000) | ((cmd[30] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[26] & 0xffff) << 16) | (cmd[30] & 0xffff)) / 65536.0f); - sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[27] & 0xffff0000) | ((cmd[31] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsde, "%4.4f", (float)(INT32)((cmd[32] & 0xffff0000) | ((cmd[36] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[32] & 0xffff) << 16) | (cmd[36] & 0xffff)) / 65536.0f); - sprintf(dwde, "%4.4f", (float)(INT32)((cmd[33] & 0xffff0000) | ((cmd[37] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[34] & 0xffff0000) | ((cmd[38] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[34] & 0xffff) << 16) | (cmd[38] & 0xffff)) / 65536.0f); - sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[35] & 0xffff0000) | ((cmd[39] >> 16) & 0xffff)) / 65536.0f); - - - buffer+=sprintf(buffer, "Tri_TexShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); - - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); - break; - } - case 0x0f: // Tri_TexShadeZ - { - int lft = (command >> 23) & 0x1; - - if (length < rdp_command_length[command]) - { - sprintf(buffer, "ERROR: Tri_TexShadeZ length = %d\n", length); - return; - } - - for (i=2; i < 40; i++) - { - cmd[i] = m_cmd_data[m_cmd_cur+i]; - } - - sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); - sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); - sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); - sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); - sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); - sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); - sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); - sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); - sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); - sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); - sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); - sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); - sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); - sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); - sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); - sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); - sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); - sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); - sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); - sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); - sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); - sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); - sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); - - sprintf(s, "%4.4f", (float)(INT32)((cmd[24] & 0xffff0000) | ((cmd[28] >> 16) & 0xffff)) / 65536.0f); - sprintf(t, "%4.4f", (float)(INT32)(((cmd[24] & 0xffff) << 16) | (cmd[28] & 0xffff)) / 65536.0f); - sprintf(w, "%4.4f", (float)(INT32)((cmd[25] & 0xffff0000) | ((cmd[29] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[26] & 0xffff0000) | ((cmd[30] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[26] & 0xffff) << 16) | (cmd[30] & 0xffff)) / 65536.0f); - sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[27] & 0xffff0000) | ((cmd[31] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsde, "%4.4f", (float)(INT32)((cmd[32] & 0xffff0000) | ((cmd[36] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[32] & 0xffff) << 16) | (cmd[36] & 0xffff)) / 65536.0f); - sprintf(dwde, "%4.4f", (float)(INT32)((cmd[33] & 0xffff0000) | ((cmd[37] >> 16) & 0xffff)) / 65536.0f); - sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[34] & 0xffff0000) | ((cmd[38] >> 16) & 0xffff)) / 65536.0f); - sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[34] & 0xffff) << 16) | (cmd[38] & 0xffff)) / 65536.0f); - sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[35] & 0xffff0000) | ((cmd[39] >> 16) & 0xffff)) / 65536.0f); - - - buffer+=sprintf(buffer, "Tri_TexShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); - - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); - buffer+=sprintf(buffer, " "); - buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); - break; - } - case 0x24: - case 0x25: - { - if (length < 16) - { - sprintf(buffer, "ERROR: Texture_Rectangle length = %d\n", length); - return; - } - cmd[2] = m_cmd_data[m_cmd_cur+2]; - cmd[3] = m_cmd_data[m_cmd_cur+3]; - sprintf(s, "%4.4f", (float)(INT16)((cmd[2] >> 16) & 0xffff) / 32.0f); - sprintf(t, "%4.4f", (float)(INT16)((cmd[2] >> 0) & 0xffff) / 32.0f); - sprintf(dsdx, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f); - sprintf(dtdy, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f); - - if (command == 0x24) - sprintf(buffer, "Texture_Rectangle %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy); - else - sprintf(buffer, "Texture_Rectangle_Flip %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy); - - break; - } - case 0x26: sprintf(buffer, "Sync_Load"); break; - case 0x27: sprintf(buffer, "Sync_Pipe"); break; - case 0x28: sprintf(buffer, "Sync_Tile"); break; - case 0x29: sprintf(buffer, "Sync_Full"); break; - case 0x2d: sprintf(buffer, "Set_Scissor %s, %s, %s, %s", sl, tl, sh, th); break; - case 0x2e: sprintf(buffer, "Set_Prim_Depth %04X, %04X", (cmd[1] >> 16) & 0xffff, cmd[1] & 0xffff); break; - case 0x2f: sprintf(buffer, "Set_Other_Modes %08X %08X", cmd[0], cmd[1]); break; - case 0x30: sprintf(buffer, "Load_TLUT %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break; - case 0x32: sprintf(buffer, "Set_Tile_Size %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break; - case 0x33: sprintf(buffer, "Load_Block %d, %03X, %03X, %03X, %03X", tile, (cmd[0] >> 12) & 0xfff, cmd[0] & 0xfff, (cmd[1] >> 12) & 0xfff, cmd[1] & 0xfff); break; - case 0x34: sprintf(buffer, "Load_Tile %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break; - case 0x35: sprintf(buffer, "Set_Tile %d, %s, %s, %d, %04X", tile, format, size, ((cmd[0] >> 9) & 0x1ff) * 8, (cmd[0] & 0x1ff) * 8); break; - case 0x36: sprintf(buffer, "Fill_Rectangle %s, %s, %s, %s", sh, th, sl, tl); break; - case 0x37: sprintf(buffer, "Set_Fill_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; - case 0x38: sprintf(buffer, "Set_Fog_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; - case 0x39: sprintf(buffer, "Set_Blend_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; - case 0x3a: sprintf(buffer, "Set_Prim_Color %d, %d, R: %d, G: %d, B: %d, A: %d", (cmd[0] >> 8) & 0x1f, cmd[0] & 0xff, r, g, b, a); break; - case 0x3b: sprintf(buffer, "Set_Env_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; - case 0x3c: sprintf(buffer, "Set_Combine %08X %08X", cmd[0], cmd[1]); break; - case 0x3d: sprintf(buffer, "Set_Texture_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break; - case 0x3e: sprintf(buffer, "Set_Mask_Image %08X", cmd[1]); break; - case 0x3f: sprintf(buffer, "Set_Color_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break; - default: sprintf(buffer, "??? (%08X %08X)", cmd[0], cmd[1]); break; - } -} - -/*****************************************************************************/ - -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); -} - -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; - } -} - -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) -{ - INT32 purgestart = 0xfff; - INT32 purgeend = 0; - bool writablescanline = !(scanline & ~0x3ff); - INT32 scanlinespx = scanline << 2; - - if (!writablescanline) return; - - for(int i = 0; i < 4; i++) - { - if (minorxint[i] < purgestart) - { - purgestart = minorxint[i]; - } - if (majorxint[i] > purgeend) - { - purgeend = majorxint[i]; - } - } - - 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); - - for(int i = 0; i < 4; i++) - { - INT32 minorcur = minorx[i]; - INT32 majorcur = majorx[i]; - INT32 minorcurint = minorxint[i]; - INT32 majorcurint = majorxint[i]; - length = majorcurint - minorcurint; - - 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 (minorcurint != majorcurint) - { - if (!(minorcurint & ~0x3ff)) - { - userdata->m_cvg[minorcurint] |= (leftcvghex(minorcur, fmask) << maskshift); - } - if (!(majorcurint & ~0x3ff)) - { - userdata->m_cvg[majorcurint] |= (rightcvghex(majorcur, fmask) << maskshift); - } - } - else - { - if (!(majorcurint & ~0x3ff)) - { - INT32 samecvg = leftcvghex(minorcur, fmask) & rightcvghex(majorcur, fmask); - userdata->m_cvg[majorcurint] |= (samecvg << maskshift); - } - } - for (; fleft <= fright; fleft++) - { - userdata->m_cvg[fleft] |= 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) -{ - INT32 purgestart = 0xfff; - INT32 purgeend = 0; - bool writablescanline = !(scanline & ~0x3ff); - INT32 scanlinespx = scanline << 2; - - if(!writablescanline) return; - - for(int i = 0; i < 4; i++) - { - if (majorxint[i] < purgestart) - { - purgestart = majorxint[i]; - } - if (minorxint[i] > purgeend) - { - purgeend = minorxint[i]; - } - } - - purgestart = CLIP(purgestart, 0, 1023); - purgeend = CLIP(purgeend, 0, 1023); - - int 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); - - for(int i = 0; i < 4; i++) - { - INT32 minorcur = minorx[i]; - INT32 majorcur = majorx[i]; - INT32 minorcurint = minorxint[i]; - INT32 majorcurint = majorxint[i]; - length = minorcurint - majorcurint; - - 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 (minorcurint != majorcurint) - { - if (!(minorcurint & ~0x3ff)) - { - userdata->m_cvg[minorcurint] |= (rightcvghex(minorcur, fmask) << maskshift); - } - if (!(majorcurint & ~0x3ff)) - { - userdata->m_cvg[majorcurint] |= (leftcvghex(majorcur, fmask) << maskshift); - } - } - else - { - if (!(majorcurint & ~0x3ff)) - { - INT32 samecvg = rightcvghex(minorcur, fmask) & leftcvghex(majorcur, fmask); - userdata->m_cvg[majorcurint] |= (samecvg << maskshift); - } - } - for (; fleft <= fright; fleft++) - { - userdata->m_cvg[fleft] |= fmaskshifted; - } - } - } -} - -void n64_rdp::DrawTriangle(bool shade, bool texture, bool zbuffer, bool rect) -{ - UINT32 *cmd_data = rect ? m_temp_rect_data : m_cmd_data; - UINT32 fifo_index = rect ? 0 : m_cmd_cur; - UINT32 w1 = cmd_data[fifo_index + 0]; - UINT32 w2 = cmd_data[fifo_index + 1]; - - int flip = (w1 & 0x00800000) ? 1 : 0; - MiscState.MaxLevel = ((w1 >> 19) & 7); - int tilenum = (w1 >> 16) & 0x7; - - int dsdiff = 0, dtdiff = 0, dwdiff = 0, drdiff = 0, dgdiff = 0, dbdiff = 0, dadiff = 0, dzdiff = 0; - int dsdeh = 0, dtdeh = 0, dwdeh = 0, drdeh = 0, dgdeh = 0, dbdeh = 0, dadeh = 0, dzdeh = 0; - int dsdxh = 0, dtdxh = 0, dwdxh = 0, drdxh = 0, dgdxh = 0, dbdxh = 0, dadxh = 0, dzdxh = 0; - int 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; - - int shade_base = fifo_index + 8; - int texture_base = fifo_index + 8; - int zbuffer_base = fifo_index + 8; - if(shade) - { - texture_base += 16; - zbuffer_base += 16; - } - if(texture) - { - zbuffer_base += 16; - } - - UINT32 w3 = cmd_data[fifo_index + 2]; - UINT32 w4 = cmd_data[fifo_index + 3]; - UINT32 w5 = cmd_data[fifo_index + 4]; - UINT32 w6 = cmd_data[fifo_index + 5]; - UINT32 w7 = cmd_data[fifo_index + 6]; - UINT32 w8 = cmd_data[fifo_index + 7]; - - 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); - // Inverse slopes in 16.16 format - INT32 dxldy = (INT32)(w4); - INT32 dxhdy = (INT32)(w6); - INT32 dxmdy = (INT32)(w8); - - if (yl & 0x2000) yl |= 0xffffc000; - if (ym & 0x2000) ym |= 0xffffc000; - if (yh & 0x2000) yh |= 0xffffc000; - - if (xl & 0x20000000) xl |= 0xc0000000; - if (xm & 0x20000000) xm |= 0xc0000000; - if (xh & 0x20000000) xh |= 0xc0000000; - - int r = (cmd_data[shade_base+0 ] & 0xffff0000) | ((cmd_data[shade_base+4 ] >> 16) & 0x0000ffff); - int g = ((cmd_data[shade_base+0 ] << 16) & 0xffff0000) | (cmd_data[shade_base+4 ] & 0x0000ffff); - int b = (cmd_data[shade_base+1 ] & 0xffff0000) | ((cmd_data[shade_base+5 ] >> 16) & 0x0000ffff); - int a = ((cmd_data[shade_base+1 ] << 16) & 0xffff0000) | (cmd_data[shade_base+5 ] & 0x0000ffff); - int drdx = (cmd_data[shade_base+2 ] & 0xffff0000) | ((cmd_data[shade_base+6 ] >> 16) & 0x0000ffff); - int dgdx = ((cmd_data[shade_base+2 ] << 16) & 0xffff0000) | (cmd_data[shade_base+6 ] & 0x0000ffff); - int dbdx = (cmd_data[shade_base+3 ] & 0xffff0000) | ((cmd_data[shade_base+7 ] >> 16) & 0x0000ffff); - int dadx = ((cmd_data[shade_base+3 ] << 16) & 0xffff0000) | (cmd_data[shade_base+7 ] & 0x0000ffff); - int drde = (cmd_data[shade_base+8 ] & 0xffff0000) | ((cmd_data[shade_base+12] >> 16) & 0x0000ffff); - int dgde = ((cmd_data[shade_base+8 ] << 16) & 0xffff0000) | (cmd_data[shade_base+12] & 0x0000ffff); - int dbde = (cmd_data[shade_base+9 ] & 0xffff0000) | ((cmd_data[shade_base+13] >> 16) & 0x0000ffff); - int dade = ((cmd_data[shade_base+9 ] << 16) & 0xffff0000) | (cmd_data[shade_base+13] & 0x0000ffff); - int drdy = (cmd_data[shade_base+10] & 0xffff0000) | ((cmd_data[shade_base+14] >> 16) & 0x0000ffff); - int dgdy = ((cmd_data[shade_base+10] << 16) & 0xffff0000) | (cmd_data[shade_base+14] & 0x0000ffff); - int dbdy = (cmd_data[shade_base+11] & 0xffff0000) | ((cmd_data[shade_base+15] >> 16) & 0x0000ffff); - int dady = ((cmd_data[shade_base+11] << 16) & 0xffff0000) | (cmd_data[shade_base+15] & 0x0000ffff); - int s = (cmd_data[texture_base+0 ] & 0xffff0000) | ((cmd_data[texture_base+4 ] >> 16) & 0x0000ffff); - int t = ((cmd_data[texture_base+0 ] << 16) & 0xffff0000) | (cmd_data[texture_base+4 ] & 0x0000ffff); - int w = (cmd_data[texture_base+1 ] & 0xffff0000) | ((cmd_data[texture_base+5 ] >> 16) & 0x0000ffff); - int dsdx = (cmd_data[texture_base+2 ] & 0xffff0000) | ((cmd_data[texture_base+6 ] >> 16) & 0x0000ffff); - int dtdx = ((cmd_data[texture_base+2 ] << 16) & 0xffff0000) | (cmd_data[texture_base+6 ] & 0x0000ffff); - int dwdx = (cmd_data[texture_base+3 ] & 0xffff0000) | ((cmd_data[texture_base+7 ] >> 16) & 0x0000ffff); - int dsde = (cmd_data[texture_base+8 ] & 0xffff0000) | ((cmd_data[texture_base+12] >> 16) & 0x0000ffff); - int dtde = ((cmd_data[texture_base+8 ] << 16) & 0xffff0000) | (cmd_data[texture_base+12] & 0x0000ffff); - int dwde = (cmd_data[texture_base+9 ] & 0xffff0000) | ((cmd_data[texture_base+13] >> 16) & 0x0000ffff); - int dsdy = (cmd_data[texture_base+10] & 0xffff0000) | ((cmd_data[texture_base+14] >> 16) & 0x0000ffff); - int dtdy = ((cmd_data[texture_base+10] << 16) & 0xffff0000) | (cmd_data[texture_base+14] & 0x0000ffff); - int dwdy = (cmd_data[texture_base+11] & 0xffff0000) | ((cmd_data[texture_base+15] >> 16) & 0x0000ffff); - int z = cmd_data[zbuffer_base+0]; - int dzdx = cmd_data[zbuffer_base+1]; - int dzde = cmd_data[zbuffer_base+2]; - int dzdy = cmd_data[zbuffer_base+3]; - - int dzdy_dz = (dzdy >> 16) & 0xffff; - int dzdx_dz = (dzdx >> 16) & 0xffff; - - extent_t Spans[2048]; - - SpanBase.m_span_drdy = drdy; - SpanBase.m_span_dgdy = dgdy; - SpanBase.m_span_dbdy = dbdy; - SpanBase.m_span_dady = dady; - SpanBase.m_span_dzdy = OtherModes.z_source_sel ? 0 : dzdy; - - UINT32 temp_dzpix = ((dzdy_dz & 0x8000) ? ((~dzdy_dz) & 0x7fff) : dzdy_dz) + ((dzdx_dz & 0x8000) ? ((~dzdx_dz) & 0x7fff) : dzdx_dz); - SpanBase.m_span_dr = drdx & ~0x1f; - SpanBase.m_span_dg = dgdx & ~0x1f; - SpanBase.m_span_db = dbdx & ~0x1f; - SpanBase.m_span_da = dadx & ~0x1f; - SpanBase.m_span_ds = dsdx; - SpanBase.m_span_dt = dtdx; - SpanBase.m_span_dw = dwdx; - SpanBase.m_span_dz = OtherModes.z_source_sel ? 0 : dzdx; - SpanBase.m_span_dymax = 0; - SpanBase.m_span_dzpix = NormalizeDZPix(temp_dzpix & 0xffff) & 0xffff; - - int xleft_inc = (dxmdy >> 2) & ~1; - int xright_inc = (dxhdy >> 2) & ~1; - - int xright = xh & ~1; - int xleft = xm & ~1; - - int sign_dxhdy = (dxhdy & 0x80000000) ? 1 : 0; - int 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); - } - 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; - - INT32 ycur = yh & ~3; - INT32 ylfar = yl | 3; - INT32 ldflag = (sign_dxhdy ^ flip) ? 0 : 3; - INT32 majorx[4]; - INT32 minorx[4]; - INT32 majorxint[4]; - INT32 minorxint[4]; - bool valid_y = true; - - int xfrac = ((xright >> 8) & 0xff); - - int clipy1 = Scissor.m_yh; - int clipy2 = Scissor.m_yl; - - // Trivial reject - if((ycur >> 2) >= clipy2 && (ylfar >> 2) >= clipy2) - { - return; - } - if((ycur >> 2) < clipy1 && (ylfar >> 2) < clipy1) - { - return; - } - - bool new_object = true; - rdp_poly_state *object = NULL; - bool valid = false; - - if(flip) - { - for (int k = ycur; k <= ylfar; k++) - { - if (k == ym) - { - xleft = xl & ~1; - xleft_inc = (dxldy >> 2) & ~1; - } - - int xstart = xleft >> 16; // 319 - int xend = xright >> 16; // 0 - int j = k >> 2; - int spanidx = (k - ycur) >> 2; - int spix = k & 3; - valid_y = !(k < yh || k >= yl); - - if (spanidx >= 0 && spanidx < 2048) - { - majorxint[spix] = xend; // 0 - minorxint[spix] = xstart; // 319 - majorx[spix] = xright; // 0x00000000 - minorx[spix] = xleft; // 0x013f0000 - - if (spix == 0) - { - maxxmx = 0; - minxhx = 0xfff; - } - - if (valid_y) - { - maxxmx = (xstart > maxxmx) ? xstart : maxxmx; - minxhx = (xend < minxhx) ? xend : minxhx; - } - - 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*)AuxBuf + AuxBufPtr); - AuxBufPtr += sizeof(rdp_span_aux); - - if(AuxBufPtr >= EXTENT_AUX_COUNT) - { - fatalerror("n64_rdp::DrawTriangle: span aux buffer overflow\n"); - } - - rdp_span_aux *userdata = (rdp_span_aux*)Spans[spanidx].userdata; - valid = true; - - userdata->m_tmem = object->m_tmem; - - userdata->BlendColor = BlendColor; - userdata->PrimColor = PrimColor; - userdata->EnvColor = EnvColor; - userdata->FogColor = FogColor; - userdata->KeyScale = KeyScale; - userdata->LODFraction = LODFraction; - userdata->PrimLODFraction = PrimLODFraction; - - userdata->ColorInputs.combiner_rgbsub_a_r[0] = userdata->ColorInputs.combiner_rgbsub_a_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbsub_a_g[0] = userdata->ColorInputs.combiner_rgbsub_a_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbsub_a_b[0] = userdata->ColorInputs.combiner_rgbsub_a_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_rgbsub_b_r[0] = userdata->ColorInputs.combiner_rgbsub_b_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbsub_b_g[0] = userdata->ColorInputs.combiner_rgbsub_b_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbsub_b_b[0] = userdata->ColorInputs.combiner_rgbsub_b_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_rgbmul_r[0] = userdata->ColorInputs.combiner_rgbmul_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbmul_g[0] = userdata->ColorInputs.combiner_rgbmul_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbmul_b[0] = userdata->ColorInputs.combiner_rgbmul_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_rgbadd_r[0] = userdata->ColorInputs.combiner_rgbadd_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbadd_g[0] = userdata->ColorInputs.combiner_rgbadd_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbadd_b[0] = userdata->ColorInputs.combiner_rgbadd_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_alphasub_a[0] = userdata->ColorInputs.combiner_alphasub_a[1] = &OneColor.i.a; - userdata->ColorInputs.combiner_alphasub_b[0] = userdata->ColorInputs.combiner_alphasub_b[1] = &OneColor.i.a; - userdata->ColorInputs.combiner_alphamul[0] = userdata->ColorInputs.combiner_alphamul[1] = &OneColor.i.a; - userdata->ColorInputs.combiner_alphaadd[0] = userdata->ColorInputs.combiner_alphaadd[1] = &OneColor.i.a; - - userdata->ColorInputs.blender1a_r[0] = userdata->ColorInputs.blender1a_r[1] = &userdata->PixelColor.i.r; - userdata->ColorInputs.blender1a_g[0] = userdata->ColorInputs.blender1a_g[1] = &userdata->PixelColor.i.g; - userdata->ColorInputs.blender1a_b[0] = userdata->ColorInputs.blender1a_b[1] = &userdata->PixelColor.i.b; - userdata->ColorInputs.blender1b_a[0] = userdata->ColorInputs.blender1b_a[1] = &userdata->PixelColor.i.a; - userdata->ColorInputs.blender2a_r[0] = userdata->ColorInputs.blender2a_r[1] = &userdata->PixelColor.i.r; - userdata->ColorInputs.blender2a_g[0] = userdata->ColorInputs.blender2a_g[1] = &userdata->PixelColor.i.g; - userdata->ColorInputs.blender2a_b[0] = userdata->ColorInputs.blender2a_b[1] = &userdata->PixelColor.i.b; - userdata->ColorInputs.blender2b_a[0] = userdata->ColorInputs.blender2b_a[1] = &userdata->PixelColor.i.a; - - // Setup blender data for this scanline - SetBlenderInput(0, 0, &userdata->ColorInputs.blender1a_r[0], - &userdata->ColorInputs.blender1a_g[0], - &userdata->ColorInputs.blender1a_b[0], - &userdata->ColorInputs.blender1b_a[0], OtherModes.blend_m1a_0, OtherModes.blend_m1b_0, userdata); - SetBlenderInput(0, 1, &userdata->ColorInputs.blender2a_r[0], - &userdata->ColorInputs.blender2a_g[0], - &userdata->ColorInputs.blender2a_b[0], - &userdata->ColorInputs.blender2b_a[0], OtherModes.blend_m2a_0, OtherModes.blend_m2b_0, userdata); - SetBlenderInput(1, 0, &userdata->ColorInputs.blender1a_r[1], - &userdata->ColorInputs.blender1a_g[1], - &userdata->ColorInputs.blender1a_b[1], - &userdata->ColorInputs.blender1b_a[1], OtherModes.blend_m1a_1, OtherModes.blend_m1b_1, userdata); - SetBlenderInput(1, 1, &userdata->ColorInputs.blender2a_r[1], - &userdata->ColorInputs.blender2a_g[1], - &userdata->ColorInputs.blender2a_b[1], - &userdata->ColorInputs.blender2b_a[1], OtherModes.blend_m2a_1, OtherModes.blend_m2b_1, userdata); - - // Setup color combiner data for this scanline - SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[0], &userdata->ColorInputs.combiner_rgbsub_a_g[0], &userdata->ColorInputs.combiner_rgbsub_a_b[0], m_combine.sub_a_rgb0, userdata); - SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[0], &userdata->ColorInputs.combiner_rgbsub_b_g[0], &userdata->ColorInputs.combiner_rgbsub_b_b[0], m_combine.sub_b_rgb0, userdata); - SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[0], &userdata->ColorInputs.combiner_rgbmul_g[0], &userdata->ColorInputs.combiner_rgbmul_b[0], m_combine.mul_rgb0, userdata); - SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[0], &userdata->ColorInputs.combiner_rgbadd_g[0], &userdata->ColorInputs.combiner_rgbadd_b[0], m_combine.add_rgb0, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[0], m_combine.sub_a_a0, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[0], m_combine.sub_b_a0, userdata); - SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[0], m_combine.mul_a0, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[0], m_combine.add_a0, userdata); - - SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[1], &userdata->ColorInputs.combiner_rgbsub_a_g[1], &userdata->ColorInputs.combiner_rgbsub_a_b[1], m_combine.sub_a_rgb1, userdata); - SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[1], &userdata->ColorInputs.combiner_rgbsub_b_g[1], &userdata->ColorInputs.combiner_rgbsub_b_b[1], m_combine.sub_b_rgb1, userdata); - SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[1], &userdata->ColorInputs.combiner_rgbmul_g[1], &userdata->ColorInputs.combiner_rgbmul_b[1], m_combine.mul_rgb1, userdata); - SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[1], &userdata->ColorInputs.combiner_rgbadd_g[1], &userdata->ColorInputs.combiner_rgbadd_b[1], m_combine.add_rgb1, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[1], m_combine.sub_a_a1, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[1], m_combine.sub_b_a1, userdata); - SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[1], m_combine.mul_a1, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[1], m_combine.add_a1, userdata); - } - - if (spix == 3) - { - Spans[spanidx].startx = maxxmx; - Spans[spanidx].stopx = minxhx; - compute_cvg_flip(Spans, majorx, minorx, majorxint, minorxint, j, yh, yl, ycur >> 2); - } - - if (spix == ldflag) - { - ((rdp_span_aux*)Spans[spanidx].userdata)->m_unscissored_rx = xend; - xfrac = ((xright >> 8) & 0xff); - Spans[spanidx].param[SPAN_R].start = ((r >> 9) << 9) + drdiff - (xfrac * drdxh); - Spans[spanidx].param[SPAN_G].start = ((g >> 9) << 9) + dgdiff - (xfrac * dgdxh); - Spans[spanidx].param[SPAN_B].start = ((b >> 9) << 9) + dbdiff - (xfrac * dbdxh); - Spans[spanidx].param[SPAN_A].start = ((a >> 9) << 9) + dadiff - (xfrac * dadxh); - Spans[spanidx].param[SPAN_S].start = (((s >> 9) << 9) + dsdiff - (xfrac * dsdxh)) & ~0x1f; - Spans[spanidx].param[SPAN_T].start = (((t >> 9) << 9) + dtdiff - (xfrac * dtdxh)) & ~0x1f; - Spans[spanidx].param[SPAN_W].start = (((w >> 9) << 9) + dwdiff - (xfrac * dwdxh)) & ~0x1f; - Spans[spanidx].param[SPAN_Z].start = ((z >> 9) << 9) + dzdiff - (xfrac * dzdxh); - } - } - - 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 (int k = ycur; k <= ylfar; k++) - { - if (k == ym) - { - xleft = xl & ~1; - xleft_inc = (dxldy >> 2) & ~1; - } - - int xstart = xleft >> 16; - int xend = xright >> 16; - int j = k >> 2; - int spanidx = j - (ycur >> 2); - int spix = k & 3; - valid_y = !(k < yh || k >= yl); - - if (k >= 0 && k < 0x1000) - { - majorxint[spix] = xend; - minorxint[spix] = xstart; - majorx[spix] = xright; - minorx[spix] = xleft; - - if (spix == 0) - { - maxxhx = 0; - minxmx = 0xfff; - } - - if (valid_y) - { - minxmx = (xstart < minxmx) ? xstart : minxmx; - maxxhx = (xend > maxxhx) ? xend : maxxhx; - } - - 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*)AuxBuf + AuxBufPtr); - valid = true; - AuxBufPtr += sizeof(rdp_span_aux); - - if(AuxBufPtr >= EXTENT_AUX_COUNT) - { - fatalerror("n64_rdp::DrawTriangle: span aux buffer overflow\n"); - } - - rdp_span_aux *userdata = (rdp_span_aux*)Spans[spanidx].userdata; - userdata->m_tmem = object->m_tmem; - - userdata->BlendColor = BlendColor; - userdata->PrimColor = PrimColor; - userdata->EnvColor = EnvColor; - userdata->FogColor = FogColor; - userdata->KeyScale = KeyScale; - userdata->LODFraction = LODFraction; - userdata->PrimLODFraction = PrimLODFraction; - - userdata->ColorInputs.combiner_rgbsub_a_r[0] = userdata->ColorInputs.combiner_rgbsub_a_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbsub_a_g[0] = userdata->ColorInputs.combiner_rgbsub_a_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbsub_a_b[0] = userdata->ColorInputs.combiner_rgbsub_a_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_rgbsub_b_r[0] = userdata->ColorInputs.combiner_rgbsub_b_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbsub_b_g[0] = userdata->ColorInputs.combiner_rgbsub_b_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbsub_b_b[0] = userdata->ColorInputs.combiner_rgbsub_b_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_rgbmul_r[0] = userdata->ColorInputs.combiner_rgbmul_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbmul_g[0] = userdata->ColorInputs.combiner_rgbmul_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbmul_b[0] = userdata->ColorInputs.combiner_rgbmul_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_rgbadd_r[0] = userdata->ColorInputs.combiner_rgbadd_r[1] = &OneColor.i.r; - userdata->ColorInputs.combiner_rgbadd_g[0] = userdata->ColorInputs.combiner_rgbadd_g[1] = &OneColor.i.g; - userdata->ColorInputs.combiner_rgbadd_b[0] = userdata->ColorInputs.combiner_rgbadd_b[1] = &OneColor.i.b; - userdata->ColorInputs.combiner_alphasub_a[0] = userdata->ColorInputs.combiner_alphasub_a[1] = &OneColor.i.a; - userdata->ColorInputs.combiner_alphasub_b[0] = userdata->ColorInputs.combiner_alphasub_b[1] = &OneColor.i.a; - userdata->ColorInputs.combiner_alphamul[0] = userdata->ColorInputs.combiner_alphamul[1] = &OneColor.i.a; - userdata->ColorInputs.combiner_alphaadd[0] = userdata->ColorInputs.combiner_alphaadd[1] = &OneColor.i.a; - - userdata->ColorInputs.blender1a_r[0] = userdata->ColorInputs.blender1a_r[1] = &userdata->PixelColor.i.r; - userdata->ColorInputs.blender1a_g[0] = userdata->ColorInputs.blender1a_g[1] = &userdata->PixelColor.i.g; - userdata->ColorInputs.blender1a_b[0] = userdata->ColorInputs.blender1a_b[1] = &userdata->PixelColor.i.b; - userdata->ColorInputs.blender1b_a[0] = userdata->ColorInputs.blender1b_a[1] = &userdata->PixelColor.i.a; - userdata->ColorInputs.blender2a_r[0] = userdata->ColorInputs.blender2a_r[1] = &userdata->PixelColor.i.r; - userdata->ColorInputs.blender2a_g[0] = userdata->ColorInputs.blender2a_g[1] = &userdata->PixelColor.i.g; - userdata->ColorInputs.blender2a_b[0] = userdata->ColorInputs.blender2a_b[1] = &userdata->PixelColor.i.b; - userdata->ColorInputs.blender2b_a[0] = userdata->ColorInputs.blender2b_a[1] = &userdata->PixelColor.i.a; - - // Setup blender data for this scanline - SetBlenderInput(0, 0, &userdata->ColorInputs.blender1a_r[0], - &userdata->ColorInputs.blender1a_g[0], - &userdata->ColorInputs.blender1a_b[0], - &userdata->ColorInputs.blender1b_a[0], OtherModes.blend_m1a_0, OtherModes.blend_m1b_0, userdata); - SetBlenderInput(0, 1, &userdata->ColorInputs.blender2a_r[0], - &userdata->ColorInputs.blender2a_g[0], - &userdata->ColorInputs.blender2a_b[0], - &userdata->ColorInputs.blender2b_a[0], OtherModes.blend_m2a_0, OtherModes.blend_m2b_0, userdata); - SetBlenderInput(1, 0, &userdata->ColorInputs.blender1a_r[1], - &userdata->ColorInputs.blender1a_g[1], - &userdata->ColorInputs.blender1a_b[1], - &userdata->ColorInputs.blender1b_a[1], OtherModes.blend_m1a_1, OtherModes.blend_m1b_1, userdata); - SetBlenderInput(1, 1, &userdata->ColorInputs.blender2a_r[1], - &userdata->ColorInputs.blender2a_g[1], - &userdata->ColorInputs.blender2a_b[1], - &userdata->ColorInputs.blender2b_a[1], OtherModes.blend_m2a_1, OtherModes.blend_m2b_1, userdata); - - // Setup color combiner data for this scanline - SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[0], &userdata->ColorInputs.combiner_rgbsub_a_g[0], &userdata->ColorInputs.combiner_rgbsub_a_b[0], m_combine.sub_a_rgb0, userdata); - SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[0], &userdata->ColorInputs.combiner_rgbsub_b_g[0], &userdata->ColorInputs.combiner_rgbsub_b_b[0], m_combine.sub_b_rgb0, userdata); - SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[0], &userdata->ColorInputs.combiner_rgbmul_g[0], &userdata->ColorInputs.combiner_rgbmul_b[0], m_combine.mul_rgb0, userdata); - SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[0], &userdata->ColorInputs.combiner_rgbadd_g[0], &userdata->ColorInputs.combiner_rgbadd_b[0], m_combine.add_rgb0, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[0], m_combine.sub_a_a0, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[0], m_combine.sub_b_a0, userdata); - SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[0], m_combine.mul_a0, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[0], m_combine.add_a0, userdata); - - SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[1], &userdata->ColorInputs.combiner_rgbsub_a_g[1], &userdata->ColorInputs.combiner_rgbsub_a_b[1], m_combine.sub_a_rgb1, userdata); - SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[1], &userdata->ColorInputs.combiner_rgbsub_b_g[1], &userdata->ColorInputs.combiner_rgbsub_b_b[1], m_combine.sub_b_rgb1, userdata); - SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[1], &userdata->ColorInputs.combiner_rgbmul_g[1], &userdata->ColorInputs.combiner_rgbmul_b[1], m_combine.mul_rgb1, userdata); - SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[1], &userdata->ColorInputs.combiner_rgbadd_g[1], &userdata->ColorInputs.combiner_rgbadd_b[1], m_combine.add_rgb1, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[1], m_combine.sub_a_a1, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[1], m_combine.sub_b_a1, userdata); - SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[1], m_combine.mul_a1, userdata); - SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[1], m_combine.add_a1, userdata); - } - - if (spix == 3) - { - Spans[spanidx].startx = minxmx; - Spans[spanidx].stopx = maxxhx; - compute_cvg_noflip(Spans, majorx, minorx, majorxint, minorxint, j, yh, yl, ycur >> 2); - } - - if (spix == ldflag) - { - ((rdp_span_aux*)Spans[spanidx].userdata)->m_unscissored_rx = xend; - xfrac = ((xright >> 8) & 0xff); - Spans[spanidx].param[SPAN_R].start = ((r >> 9) << 9) + drdiff - (xfrac * drdxh); - Spans[spanidx].param[SPAN_G].start = ((g >> 9) << 9) + dgdiff - (xfrac * dgdxh); - Spans[spanidx].param[SPAN_B].start = ((b >> 9) << 9) + dbdiff - (xfrac * dbdxh); - Spans[spanidx].param[SPAN_A].start = ((a >> 9) << 9) + dadiff - (xfrac * dadxh); - Spans[spanidx].param[SPAN_S].start = (((s >> 9) << 9) + dsdiff - (xfrac * dsdxh)) & ~0x1f; - Spans[spanidx].param[SPAN_T].start = (((t >> 9) << 9) + dtdiff - (xfrac * dtdxh)) & ~0x1f; - Spans[spanidx].param[SPAN_W].start = (((w >> 9) << 9) + dwdiff - (xfrac * dwdxh)) & ~0x1f; - Spans[spanidx].param[SPAN_Z].start = ((z >> 9) << 9) + dzdiff - (xfrac * dzdxh); - } - } - - 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(!new_object && valid) - { - RenderSpans(yh >> 2, yl >> 2, tilenum, flip ? true : false, Spans, rect, object); - } - - //wait("DrawTriangle"); -} - -/*****************************************************************************/ - -//////////////////////// -// FB ACCESSORS -//////////////////////// -void n64_rdp::_Write16Bit_Cvg0_Blend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; - UINT32 hb = fb; - - UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); - UINT32 finalcvg = 0; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX16(fb) & 0xfffe; - CHECK16(fb); - } - - finalcvg = userdata->CurrentPixCvg + userdata->CurrentMemCvg; - if (finalcvg & 8) - { - finalcvg = 7; - } - RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); - HWRITEADDR8(hb, finalcvg & 3); -} - -void n64_rdp::_Write16Bit_Cvg0_NoBlend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; - UINT32 hb = fb; - - UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); - UINT32 finalcvg = 0; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX16(fb) & 0xfffe; - CHECK16(fb); - } - - finalcvg = (userdata->CurrentPixCvg - 1) & 7; - RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); - HWRITEADDR8(hb, finalcvg & 3); -} - -void n64_rdp::_Write16Bit_Cvg1(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; - UINT32 hb = fb; - - UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); - UINT32 finalcvg = 0; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX16(fb) & 0xfffe; - CHECK16(fb); - } - - finalcvg = (userdata->CurrentPixCvg + userdata->CurrentMemCvg) & 7; - RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); - HWRITEADDR8(hb, finalcvg & 3); -} - -void n64_rdp::_Write16Bit_Cvg2(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; - UINT32 hb = fb; - - UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX16(fb) & 0xfffe; - CHECK16(fb); - } - - RWRITEIDX16(fb, finalcolor | 1); - HWRITEADDR8(hb, 3); -} - -void n64_rdp::_Write16Bit_Cvg3(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; - UINT32 hb = fb; - - UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX16(fb) & 0xfffe; - CHECK16(fb); - } - - RWRITEIDX16(fb, finalcolor | ((userdata->CurrentMemCvg >> 2) & 1)); - HWRITEADDR8(hb, userdata->CurrentMemCvg & 3); -} - -void n64_rdp::_Write32Bit_Cvg0_Blend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; - UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; - UINT32 finalcvg = 0; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX32(fb) & 0xffffff00; - CHECK32(fb); - } - - finalcvg = userdata->CurrentPixCvg + userdata->CurrentMemCvg; - if (finalcvg & 8) - { - finalcvg = 7; - } - RWRITEIDX32(fb, finalcolor | (finalcvg << 5)); -} - -void n64_rdp::_Write32Bit_Cvg0_NoBlend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; - UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; - UINT32 finalcvg = 0; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX32(fb) & 0xffffff00; - CHECK32(fb); - } - - finalcvg = (userdata->CurrentPixCvg - 1) & 7; - RWRITEIDX32(fb, finalcolor | (finalcvg << 5)); -} - -void n64_rdp::_Write32Bit_Cvg1(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; - UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; - UINT32 finalcvg = 0; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX32(fb) & 0xffffff00; - CHECK32(fb); - } - - finalcvg = (userdata->CurrentPixCvg + userdata->CurrentMemCvg) & 7; - finalcolor |= (finalcvg << 5); - RWRITEIDX32(fb, finalcolor); -} - -void n64_rdp::_Write32Bit_Cvg2(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; - UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX32(fb) & 0xffffff00; - CHECK32(fb); - } - - RWRITEIDX32(fb, finalcolor | 0xE0); -} - -void n64_rdp::_Write32Bit_Cvg3(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; - UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; - - if (object.OtherModes.color_on_cvg && !userdata->PreWrap) - { - finalcolor = RREADIDX32(fb) & 0xffffff00; - CHECK32(fb); - } - - RWRITEIDX32(fb, finalcolor | (userdata->CurrentMemCvg << 5)); -} - - -void n64_rdp::_Read16Bit_ImgRead0(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT16 fword = RREADIDX16((object.MiscState.FBAddress >> 1) + curpixel); - CHECK16((object.MiscState.FBAddress >> 1) + curpixel); - userdata->MemoryColor.i.r = GETHICOL(fword); - userdata->MemoryColor.i.g = GETMEDCOL(fword); - userdata->MemoryColor.i.b = GETLOWCOL(fword); - userdata->MemoryColor.i.a = 0xff; - userdata->CurrentMemCvg = 7; -} - -void n64_rdp::_Read16Bit_ImgRead1(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT16 fword = RREADIDX16((object.MiscState.FBAddress >> 1) + curpixel); - CHECK16((object.MiscState.FBAddress >> 1) + curpixel); - UINT8 hbyte = HREADADDR8((object.MiscState.FBAddress >> 1) + curpixel); - userdata->MemoryColor.i.r = GETHICOL(fword); - userdata->MemoryColor.i.g = GETMEDCOL(fword); - userdata->MemoryColor.i.b = GETLOWCOL(fword); - userdata->MemoryColor.i.a = userdata->CurrentMemCvg << 5; - userdata->CurrentMemCvg = ((fword & 1) << 2) | (hbyte & 3); -} - -void n64_rdp::_Read32Bit_ImgRead0(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 mem = RREADIDX32((object.MiscState.FBAddress >> 2) + curpixel); - CHECK32((object.MiscState.FBAddress >> 2) + curpixel); - userdata->MemoryColor.i.r = (mem >> 24) & 0xff; - userdata->MemoryColor.i.g = (mem >> 16) & 0xff; - userdata->MemoryColor.i.b = (mem >> 8) & 0xff; - userdata->MemoryColor.i.a = 0xff; - userdata->CurrentMemCvg = 7; -} - -void n64_rdp::_Read32Bit_ImgRead1(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) -{ - UINT32 mem = RREADIDX32((object.MiscState.FBAddress >> 2) + curpixel); - CHECK32((object.MiscState.FBAddress >> 2) + curpixel); - userdata->MemoryColor.i.r = (mem >> 24) & 0xff; - userdata->MemoryColor.i.g = (mem >> 16) & 0xff; - userdata->MemoryColor.i.b = (mem >> 8) & 0xff; - userdata->MemoryColor.i.a = (mem) & 0xff; - userdata->CurrentMemCvg = (mem >> 5) & 7; -} - -void n64_rdp::_Copy16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, int CurrentPixCvg, const rdp_poly_state &object) -{ - UINT16 val = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1) | ((CurrentPixCvg >> 2) & 1); - RWRITEIDX16((object.MiscState.FBAddress >> 1) + curpixel, val); - HWRITEADDR8((object.MiscState.FBAddress >> 1) + curpixel, CurrentPixCvg & 3); - CHECK16((object.MiscState.FBAddress >> 1) + curpixel); -} - -void n64_rdp::_Copy32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, int CurrentPixCvg, const rdp_poly_state &object) -{ - UINT32 val = (r << 24) | (g << 16) | (b << 8) | (CurrentPixCvg << 5); - RWRITEIDX32((object.MiscState.FBAddress >> 2) + curpixel, val); - CHECK32((object.MiscState.FBAddress >> 2) + curpixel); -} - - -void n64_rdp::_Fill16Bit(UINT32 curpixel, const rdp_poly_state &object) -{ - UINT16 val; - if (curpixel & 1) - { - val = object.FillColor & 0xffff; - } - else - { - val = (object.FillColor >> 16) & 0xffff; - } - RWRITEIDX16((object.MiscState.FBAddress >> 1) + curpixel, val); - CHECK16((object.MiscState.FBAddress >> 1) + curpixel); - HWRITEADDR8((object.MiscState.FBAddress >> 1) + curpixel, ((val & 1) << 1) | (val & 1)); -} - -void n64_rdp::_Fill32Bit(UINT32 curpixel, const rdp_poly_state &object) -{ - UINT32 FillColor = object.FillColor; - RWRITEIDX32((object.MiscState.FBAddress >> 2) + curpixel, FillColor); - CHECK32((object.MiscState.FBAddress >> 2) + curpixel); - HWRITEADDR8((object.MiscState.FBAddress >> 1) + (curpixel << 1), (FillColor & 0x10000) ? 3 : 0); - HWRITEADDR8((object.MiscState.FBAddress >> 1) + (curpixel << 1) + 1, (FillColor & 0x1) ? 3 : 0); -} - -//////////////////////// -// RDP COMMANDS -//////////////////////// -void n64_rdp::Triangle(bool shade, bool texture, bool zbuffer) -{ - DrawTriangle(shade, texture, zbuffer, false); - m_pipe_clean = false; - //wait(); -} - -void n64_rdp::CmdTriangle(UINT32 w1, UINT32 w2) -{ - Triangle(false, false, false); -} - -void n64_rdp::CmdTriangleZ(UINT32 w1, UINT32 w2) -{ - Triangle(false, false, true); -} - -void n64_rdp::CmdTriangleT(UINT32 w1, UINT32 w2) -{ - Triangle(false, true, false); -} - -void n64_rdp::CmdTriangleTZ(UINT32 w1, UINT32 w2) -{ - Triangle(false, true, true); -} - -void n64_rdp::CmdTriangleS(UINT32 w1, UINT32 w2) -{ - Triangle(true, false, false); -} - -void n64_rdp::CmdTriangleSZ(UINT32 w1, UINT32 w2) -{ - Triangle(true, false, true); -} - -void n64_rdp::CmdTriangleST(UINT32 w1, UINT32 w2) -{ - Triangle(true, true, false); -} - -void n64_rdp::CmdTriangleSTZ(UINT32 w1, UINT32 w2) -{ - Triangle(true, true, true); -} - -void n64_rdp::CmdTexRect(UINT32 w1, UINT32 w2) -{ - //if(m_pending_mode_block) { wait("Block on pending mode-change"); m_pending_mode_block = false; } - - UINT32 *data = m_cmd_data + m_cmd_cur; - - UINT32 w3 = data[2]; - UINT32 w4 = data[3]; - - UINT32 tilenum = (w2 >> 24) & 0x7; - UINT32 xl = (w1 >> 12) & 0xfff; - UINT32 yl = (w1 >> 0) & 0xfff; - UINT32 xh = (w2 >> 12) & 0xfff; - UINT32 yh = (w2 >> 0) & 0xfff; - INT32 s = (w3 >> 16) & 0xffff; - INT32 t = (w3 >> 0) & 0xffff; - INT32 dsdx = (w4 >> 16) & 0xffff; - INT32 dtdy = (w4 >> 0) & 0xffff; - - dsdx = SIGN16(dsdx); - dtdy = SIGN16(dtdy); - - if (OtherModes.cycle_type == CYCLE_TYPE_FILL || OtherModes.cycle_type == CYCLE_TYPE_COPY) - { - yl |= 3; - } - - UINT32 xlint = (xl >> 2) & 0x3ff; - UINT32 xhint = (xh >> 2) & 0x3ff; - - UINT32* ewdata = m_temp_rect_data; - ewdata[0] = (0x24 << 24) | ((0x80 | tilenum) << 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, 16 * sizeof(UINT32)); // shade - ewdata[24] = (s << 16) | t; // s, t - ewdata[25] = 0; // w - ewdata[26] = ((dsdx >> 5) << 16); // dsdx, dtdx - ewdata[27] = 0; // dwdx - ewdata[28] = 0; // s frac, t frac - ewdata[29] = 0; // w frac - ewdata[30] = ((dsdx & 0x1f) << 11) << 16; // dsdx frac, dtdx frac - ewdata[31] = 0; // dwdx frac - ewdata[32] = (dtdy >> 5) & 0xffff;//dsde, dtde - ewdata[33] = 0;//dwde - ewdata[34] = (dtdy >> 5) & 0xffff;//dsdy, dtdy - ewdata[35] = 0;//dwdy - ewdata[36] = (dtdy & 0x1f) << 11;//dsde frac, dtde frac - ewdata[37] = 0;//dwde frac - ewdata[38] = (dtdy & 0x1f) << 11;//dsdy frac, dtdy frac - ewdata[39] = 0;//dwdy frac - memset(&ewdata[40], 0, 4 * sizeof(UINT32));//depth - - DrawTriangle(true, true, false, true); -} - -void n64_rdp::CmdTexRectFlip(UINT32 w1, UINT32 w2) -{ - //if(m_pending_mode_block) { wait("Block on pending mode-change"); m_pending_mode_block = false; } - - UINT32 *data = m_cmd_data + m_cmd_cur; - - UINT32 w3 = data[2]; - UINT32 w4 = data[3]; - - UINT32 tilenum = (w2 >> 24) & 0x7; - UINT32 xl = (w1 >> 12) & 0xfff; - UINT32 yl = (w1 >> 0) & 0xfff; - UINT32 xh = (w2 >> 12) & 0xfff; - UINT32 yh = (w2 >> 0) & 0xfff; - INT32 s = (w3 >> 16) & 0xffff; - INT32 t = (w3 >> 0) & 0xffff; - INT32 dsdx = (w4 >> 16) & 0xffff; - INT32 dtdy = (w4 >> 0) & 0xffff; - - dsdx = SIGN16(dsdx); - dtdy = SIGN16(dtdy); - - if (OtherModes.cycle_type == CYCLE_TYPE_FILL || OtherModes.cycle_type == CYCLE_TYPE_COPY) - { - yl |= 3; - } - - UINT32 xlint = (xl >> 2) & 0x3ff; - UINT32 xhint = (xh >> 2) & 0x3ff; - - UINT32* ewdata = m_temp_rect_data; - ewdata[0] = (0x25 << 24) | ((0x80 | tilenum) << 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, 16 * sizeof(UINT32));//shade - ewdata[24] = (s << 16) | t;//s, t - ewdata[25] = 0;//w - ewdata[26] = (dtdy >> 5) & 0xffff;//dsdx, dtdx - ewdata[27] = 0;//dwdx - ewdata[28] = 0;//s frac, t frac - ewdata[29] = 0;//w frac - ewdata[30] = ((dtdy & 0x1f) << 11);//dsdx frac, dtdx frac - ewdata[31] = 0;//dwdx frac - ewdata[32] = (dsdx >> 5) << 16;//dsde, dtde - ewdata[33] = 0;//dwde - ewdata[34] = (dsdx >> 5) << 16;//dsdy, dtdy - ewdata[35] = 0;//dwdy - ewdata[36] = (dsdx & 0x1f) << 27;//dsde frac, dtde frac - ewdata[37] = 0;//dwde frac - ewdata[38] = (dsdx & 0x1f) << 27;//dsdy frac, dtdy frac - ewdata[39] = 0;//dwdy frac - memset(&ewdata[40], 0, 4 * sizeof(UINT32));//depth - - DrawTriangle(true, true, false, true); -} - -void n64_rdp::CmdSyncLoad(UINT32 w1, UINT32 w2) -{ - //wait("SyncLoad"); -} - -void n64_rdp::CmdSyncPipe(UINT32 w1, UINT32 w2) -{ - //wait("SyncPipe"); -} - -void n64_rdp::CmdSyncTile(UINT32 w1, UINT32 w2) -{ - //wait("SyncTile"); -} - -void n64_rdp::CmdSyncFull(UINT32 w1, UINT32 w2) -{ - //wait("SyncFull"); - dp_full_sync(*m_machine); -} - -void n64_rdp::CmdSetKeyGB(UINT32 w1, UINT32 w2) -{ - KeyScale.i.b = w2 & 0xff; - KeyScale.i.g = (w2 >> 16) & 0xff; -} - -void n64_rdp::CmdSetKeyR(UINT32 w1, UINT32 w2) -{ - KeyScale.i.r = w2 & 0xff; -} - -void n64_rdp::CmdSetFillColor32(UINT32 w1, UINT32 w2) -{ - //wait("SetFillColor"); - FillColor = w2; -} - -void n64_rdp::CmdSetConvert(UINT32 w1, UINT32 w2) -{ - if(!m_pipe_clean) { m_pipe_clean = true; wait("SetConvert"); } - INT32 k0 = (w1 >> 13) & 0xff; - INT32 k1 = (w1 >> 4) & 0xff; - INT32 k2 = ((w1 & 7) << 5) | ((w2 >> 27) & 0x1f); - INT32 k3 = (w2 >> 18) & 0xff; - INT32 k4 = (w2 >> 9) & 0xff; - INT32 k5 = w2 & 0xff; - k0 = ((w1 >> 21) & 1) ? (-(0x100 - k0)) : k0; - k1 = ((w1 >> 12) & 1) ? (-(0x100 - k1)) : k1; - k2 = (w1 & 0xf) ? (-(0x100 - k2)) : k2; - k3 = ((w2 >> 26) & 1) ? (-(0x100 - k3)) : k3; - k4 = ((w2 >> 17) & 1) ? (-(0x100 - k4)) : k4; - k5 = ((w2 >> 8) & 1) ? (-(0x100 - k5)) : k5; - SetYUVFactors(k0, k1, k2, k3, k4, k5); -} - -void n64_rdp::CmdSetScissor(UINT32 w1, UINT32 w2) -{ - Scissor.m_xh = ((w1 >> 12) & 0xfff) >> 2; - Scissor.m_yh = ((w1 >> 0) & 0xfff) >> 2; - Scissor.m_xl = ((w2 >> 12) & 0xfff) >> 2; - Scissor.m_yl = ((w2 >> 0) & 0xfff) >> 2; - - // TODO: handle f & o? -} - -void n64_rdp::CmdSetPrimDepth(UINT32 w1, UINT32 w2) -{ - MiscState.PrimitiveZ = (UINT16)(w2 >> 16) & 0x7fff; - MiscState.PrimitiveDZ = (UINT16)(w1); -} - -void n64_rdp::CmdSetOtherModes(UINT32 w1, UINT32 w2) -{ - //wait("SetOtherModes"); - OtherModes.cycle_type = (w1 >> 20) & 0x3; // 01 - OtherModes.persp_tex_en = (w1 & 0x80000) ? 1 : 0; // 1 - OtherModes.detail_tex_en = (w1 & 0x40000) ? 1 : 0; // 0 - OtherModes.sharpen_tex_en = (w1 & 0x20000) ? 1 : 0; // 0 - OtherModes.tex_lod_en = (w1 & 0x10000) ? 1 : 0; // 0 - OtherModes.en_tlut = (w1 & 0x08000) ? 1 : 0; // 0 - OtherModes.tlut_type = (w1 & 0x04000) ? 1 : 0; // 0 - OtherModes.sample_type = (w1 & 0x02000) ? 1 : 0; // 1 - OtherModes.mid_texel = (w1 & 0x01000) ? 1 : 0; // 0 - OtherModes.bi_lerp0 = (w1 & 0x00800) ? 1 : 0; // 1 - OtherModes.bi_lerp1 = (w1 & 0x00400) ? 1 : 0; // 1 - OtherModes.convert_one = (w1 & 0x00200) ? 1 : 0; // 0 - OtherModes.key_en = (w1 & 0x00100) ? 1 : 0; // 0 - OtherModes.rgb_dither_sel = (w1 >> 6) & 0x3; // 00 - OtherModes.alpha_dither_sel = (w1 >> 4) & 0x3; // 01 - OtherModes.blend_m1a_0 = (w2 >> 30) & 0x3; // 11 - OtherModes.blend_m1a_1 = (w2 >> 28) & 0x3; // 00 - OtherModes.blend_m1b_0 = (w2 >> 26) & 0x3; // 10 - OtherModes.blend_m1b_1 = (w2 >> 24) & 0x3; // 00 - OtherModes.blend_m2a_0 = (w2 >> 22) & 0x3; // 00 - OtherModes.blend_m2a_1 = (w2 >> 20) & 0x3; // 01 - OtherModes.blend_m2b_0 = (w2 >> 18) & 0x3; // 00 - OtherModes.blend_m2b_1 = (w2 >> 16) & 0x3; // 01 - OtherModes.force_blend = (w2 >> 14) & 1; // 0 - OtherModes.alpha_cvg_select = (w2 >> 13) & 1; // 1 - OtherModes.cvg_times_alpha = (w2 >> 12) & 1; // 0 - OtherModes.z_mode = (w2 >> 10) & 0x3; // 00 - OtherModes.cvg_dest = (w2 >> 8) & 0x3; // 00 - OtherModes.color_on_cvg = (w2 >> 7) & 1; // 0 - OtherModes.image_read_en = (w2 >> 6) & 1; // 1 - OtherModes.z_update_en = (w2 >> 5) & 1; // 1 - OtherModes.z_compare_en = (w2 >> 4) & 1; // 1 - OtherModes.antialias_en = (w2 >> 3) & 1; // 1 - OtherModes.z_source_sel = (w2 >> 2) & 1; // 0 - OtherModes.dither_alpha_en = (w2 >> 1) & 1; // 0 - OtherModes.alpha_compare_en = (w2) & 1; // 0 -} - -void n64_rdp::CmdLoadTLUT(UINT32 w1, UINT32 w2) -{ - //wait("LoadTLUT"); - N64Tile* tile = m_tiles; - - int tilenum = (w2 >> 24) & 0x7; - int sl = tile[tilenum].sl = ((w1 >> 12) & 0xfff); - int tl = tile[tilenum].tl = w1 & 0xfff; - int sh = tile[tilenum].sh = ((w2 >> 12) & 0xfff); - int th = tile[tilenum].th = w2 & 0xfff; - - if (tl != th) - { - fatalerror("Load tlut: tl=%d, th=%d\n",tl,th); - } - - int count = (sh >> 2) - (sl >> 2) + 1; - count <<= 2; - - switch (MiscState.TISize) - { - case PIXEL_SIZE_16BIT: - { - if (tile[tilenum].tmem < 256) - { - fatalerror("rdp_load_tlut: loading tlut into low half at %d qwords\n",tile[tilenum].tmem); - } - UINT32 srcstart = (MiscState.TIAddress + (tl >> 2) * (MiscState.TIWidth << 1) + (sl >> 1)) >> 1; - UINT16 *dst = GetTMEM16(); - UINT32 dststart = tile[tilenum].tmem << 2; - - for (int i = 0; i < count; i += 4) - { - if (dststart < 2048) - { - dst[dststart] = U_RREADIDX16(srcstart); - dst[dststart + 1] = dst[dststart]; - dst[dststart + 2] = dst[dststart]; - dst[dststart + 3] = dst[dststart]; - dststart += 4; - srcstart += 1; - } - } - break; - } - default: fatalerror("RDP: load_tlut: size = %d\n", MiscState.TISize); - } -} - -void n64_rdp::CmdSetTileSize(UINT32 w1, UINT32 w2) -{ - //wait("SetTileSize"); - - const int tilenum = (w2 >> 24) & 0x7; - - m_tiles[tilenum].sl = (w1 >> 12) & 0xfff; - m_tiles[tilenum].tl = (w1 >> 0) & 0xfff; - m_tiles[tilenum].sh = (w2 >> 12) & 0xfff; - m_tiles[tilenum].th = (w2 >> 0) & 0xfff; -} - -void n64_rdp::CmdLoadBlock(UINT32 w1, UINT32 w2) -{ - //wait("LoadBlock"); - N64Tile* tile = m_tiles; - - int tilenum = (w2 >> 24) & 0x7; - UINT16* tc = GetTMEM16(); - - UINT16 sl, sh, tl; - tile[tilenum].sl = sl = ((w1 >> 12) & 0xfff); - tile[tilenum].tl = tl = ((w1 >> 0) & 0xfff); - tile[tilenum].sh = sh = ((w2 >> 12) & 0xfff); - UINT16 dxt = ((w2 >> 0) & 0xfff); - - if (sh < sl) - { - fatalerror("load_block: sh < sl\n"); - } - - INT32 width = (sh - sl) + 1; - - width = (width << MiscState.TISize) >> 1; - if (width & 7) - { - width = (width & ~7) + 8; - } - width >>= 3; - - UINT32 tb = tile[tilenum].tmem << 2; - - int tiwinwords = MiscState.TIWidth; - UINT32 slinwords = sl; - - tiwinwords = (tiwinwords << MiscState.TISize) >> 2; - slinwords = (slinwords << MiscState.TISize) >> 2; - - int ptr = 0, srcptr = 0; - UINT16 first, sec; - UINT32 src = (MiscState.TIAddress >> 1) + (tl * tiwinwords) + slinwords; - - if (dxt != 0) - { - int j = 0; - int t = 0; - int oldt = 0; - - if (tile[tilenum].size != PIXEL_SIZE_32BIT && tile[tilenum].format != FORMAT_YUV) - { - for (int i = 0; i < width; i ++) - { - oldt = t; - t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; - if (t != oldt) - { - i += tile[tilenum].line; - } - - ptr = tb + (i << 2); - srcptr = src + (i << 2); - - tc[(ptr ^ t) & 0x7ff] = U_RREADIDX16(srcptr); - tc[((ptr + 1) ^ t) & 0x7ff] = U_RREADIDX16(srcptr + 1); - tc[((ptr + 2) ^ t) & 0x7ff] = U_RREADIDX16(srcptr + 2); - tc[((ptr + 3) ^ t) & 0x7ff] = U_RREADIDX16(srcptr + 3); - j += dxt; - } - } - else if (tile[tilenum].format == FORMAT_YUV) - { - for (int i = 0; i < width; i ++) - { - oldt = t; - t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; - if (t != oldt) - { - i += tile[tilenum].line; - } - - ptr = ((tb + (i << 1)) ^ t) & 0x3ff; - srcptr = src + (i << 2); - - first = U_RREADIDX16(srcptr); - sec = U_RREADIDX16(srcptr + 1); - tc[ptr] = ((first >> 8) << 8) | (sec >> 8); - tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); - - ptr = ((tb + (i << 1) + 1) ^ t) & 0x3ff; - first = U_RREADIDX16(srcptr + 2); - sec = U_RREADIDX16(srcptr + 3); - tc[ptr] = ((first >> 8) << 8) | (sec >> 8); - tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); - - j += dxt; - } - } - else - { - for (int i = 0; i < width; i ++) - { - oldt = t; - t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; - if (t != oldt) - i += tile[tilenum].line; - - ptr = ((tb + (i << 1)) ^ t) & 0x3ff; - srcptr = src + (i << 2); - tc[ptr] = U_RREADIDX16(srcptr); - tc[ptr | 0x400] = U_RREADIDX16(srcptr + 1); - - ptr = ((tb + (i << 1) + 1) ^ t) & 0x3ff; - tc[ptr] = U_RREADIDX16(srcptr + 2); - tc[ptr | 0x400] = U_RREADIDX16(srcptr + 3); - - j += dxt; - } - } - tile[tilenum].th = tl + (j >> 11); - } - else - { - if (tile[tilenum].size != PIXEL_SIZE_32BIT && tile[tilenum].format != FORMAT_YUV) - { - for (int i = 0; i < width; i ++) - { - ptr = tb + (i << 2); - srcptr = src + (i << 2); - tc[(ptr ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr); - tc[((ptr + 1) ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr + 1); - tc[((ptr + 2) ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr + 2); - tc[((ptr + 3) ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr + 3); - } - } - else if (tile[tilenum].format == FORMAT_YUV) - { - for (int i = 0; i < width; i ++) - { - ptr = ((tb + (i << 1)) ^ WORD_ADDR_XOR) & 0x3ff; - srcptr = src + (i << 2); - first = U_RREADIDX16(srcptr); - sec = U_RREADIDX16(srcptr + 1); - tc[ptr] = ((first >> 8) << 8) | (sec >> 8);//UV pair - tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); - - ptr = ((tb + (i << 1) + 1) ^ WORD_ADDR_XOR) & 0x3ff; - first = U_RREADIDX16(srcptr + 2); - sec = U_RREADIDX16(srcptr + 3); - tc[ptr] = ((first >> 8) << 8) | (sec >> 8); - tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); - } - } - else - { - for (int i = 0; i < width; i ++) - { - ptr = ((tb + (i << 1)) ^ WORD_ADDR_XOR) & 0x3ff; - srcptr = src + (i << 2); - tc[ptr] = U_RREADIDX16(srcptr); - tc[ptr | 0x400] = U_RREADIDX16(srcptr + 1); - - ptr = ((tb + (i << 1) + 1) ^ WORD_ADDR_XOR) & 0x3ff; - tc[ptr] = U_RREADIDX16(srcptr + 2); - tc[ptr | 0x400] = U_RREADIDX16(srcptr + 3); - } - } - tile[tilenum].th = tl; - } -} - -void n64_rdp::CmdLoadTile(UINT32 w1, UINT32 w2) -{ - //wait("LoadTile"); - N64Tile* tile = m_tiles; - int tilenum = (w2 >> 24) & 0x7; - - tile[tilenum].sl = ((w1 >> 12) & 0xfff); - tile[tilenum].tl = ((w1 >> 0) & 0xfff); - tile[tilenum].sh = ((w2 >> 12) & 0xfff); - tile[tilenum].th = ((w2 >> 0) & 0xfff); - - UINT16 sl = tile[tilenum].sl >> 2; - UINT16 tl = tile[tilenum].tl >> 2; - UINT16 sh = tile[tilenum].sh >> 2; - UINT16 th = tile[tilenum].th >> 2; - - INT32 width = (sh - sl) + 1; - INT32 height = (th - tl) + 1; -/* - int topad; - if (MiscState.TISize < 3) - { - topad = (width * MiscState.TISize) & 0x7; - } - else - { - topad = (width << 2) & 0x7; - } - topad = 0; // ???? -*/ - switch (MiscState.TISize) - { - case PIXEL_SIZE_8BIT: - { - UINT32 src = MiscState.TIAddress; - UINT8 *tc = GetTMEM(); - int tb = tile[tilenum].tmem << 3; - - for (int j = 0; j < height; j++) - { - int tline = tb + ((tile[tilenum].line << 3) * j); - int s = ((j + tl) * MiscState.TIWidth) + sl; - - int xorval8 = ((j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); - for (int i = 0; i < width; i++) - { - tc[((tline + i) ^ xorval8) & 0xfff] = U_RREADADDR8(src + s + i); - } - } - break; - } - case PIXEL_SIZE_16BIT: - { - UINT32 src = MiscState.TIAddress >> 1; - UINT16 *tc = GetTMEM16(); - UINT16 yuvword; - - if (tile[tilenum].format != FORMAT_YUV) - { - for (int j = 0; j < height; j++) - { - int tb = tile[tilenum].tmem << 2; - int tline = tb + ((tile[tilenum].line << 2) * j); - int s = ((j + tl) * MiscState.TIWidth) + sl; - int xorval16 = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; - - for (int i = 0; i < width; i++) - { - UINT32 taddr = (tline + i) ^ xorval16; - tc[taddr & 0x7ff] = U_RREADIDX16(src + s + i); - } - } - } - else - { - for (int j = 0; j < height; j++) - { - int tb = tile[tilenum].tmem << 3; - int tline = tb + ((tile[tilenum].line << 3) * j); - int s = ((j + tl) * MiscState.TIWidth) + sl; - int xorval8 = (j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR; - - for (int i = 0; i < width; i++) - { - UINT32 taddr = ((tline + i) ^ xorval8) & 0x7ff; - yuvword = U_RREADIDX16(src + s + i); - GetTMEM()[taddr] = yuvword >> 8; - GetTMEM()[taddr | 0x800] = yuvword & 0xff; - } - } - } - break; - } - case PIXEL_SIZE_32BIT: - { - UINT32 src = MiscState.TIAddress >> 2; - UINT16 *tc16 = GetTMEM16(); - int tb = (tile[tilenum].tmem << 2); - - for (int j = 0; j < height; j++) - { - int tline = tb + ((tile[tilenum].line << 2) * j); - - int s = ((j + tl) * MiscState.TIWidth) + sl; - int xorval32cur = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; - for (int i = 0; i < width; i++) - { - UINT32 c = U_RREADIDX32(src + s + i); - UINT32 ptr = ((tline + i) ^ xorval32cur) & 0x3ff; - tc16[ptr] = c >> 16; - tc16[ptr | 0x400] = c & 0xffff; - } - } - break; - } - - default: fatalerror("RDP: load_tile: size = %d\n", MiscState.TISize); - } -} - -void n64_rdp::CmdSetTile(UINT32 w1, UINT32 w2) -{ - //wait("SetTile"); - - int tilenum = (w2 >> 24) & 0x7; - N64Tile* tex_tile = &m_tiles[tilenum]; - - tex_tile->format = (w1 >> 21) & 0x7; - tex_tile->size = (w1 >> 19) & 0x3; - tex_tile->line = (w1 >> 9) & 0x1ff; - tex_tile->tmem = (w1 >> 0) & 0x1ff; - tex_tile->palette = (w2 >> 20) & 0xf; - tex_tile->ct = (w2 >> 19) & 0x1; - tex_tile->mt = (w2 >> 18) & 0x1; - tex_tile->mask_t = (w2 >> 14) & 0xf; - tex_tile->shift_t = (w2 >> 10) & 0xf; - tex_tile->cs = (w2 >> 9) & 0x1; - tex_tile->ms = (w2 >> 8) & 0x1; - tex_tile->mask_s = (w2 >> 4) & 0xf; - tex_tile->shift_s = (w2 >> 0) & 0xf; - - if (tex_tile->format == FORMAT_I && tex_tile->size > PIXEL_SIZE_8BIT) - { - tex_tile->format = FORMAT_RGBA; // Used by Supercross 2000 (in-game) - } - if (tex_tile->format == FORMAT_CI && tex_tile->size > PIXEL_SIZE_8BIT) - { - tex_tile->format = FORMAT_RGBA; // Used by Clay Fighter - Sculptor's Cut - } - - if (tex_tile->format == FORMAT_RGBA && tex_tile->size < PIXEL_SIZE_16BIT) - { - tex_tile->format = FORMAT_CI; // Used by Exterem-G2, Madden Football 64, and Rat Attack - } - - //m_pending_mode_block = true; -} - -void n64_rdp::CmdFillRect(UINT32 w1, UINT32 w2) -{ - //if(m_pending_mode_block) { wait("Block on pending mode-change"); m_pending_mode_block = false; } - - UINT32 xl = (w1 >> 12) & 0xfff; - UINT32 yl = (w1 >> 0) & 0xfff; - UINT32 xh = (w2 >> 12) & 0xfff; - UINT32 yh = (w2 >> 0) & 0xfff; - - if (OtherModes.cycle_type == CYCLE_TYPE_FILL || OtherModes.cycle_type == CYCLE_TYPE_COPY) - { - yl |= 3; - } - - UINT32 xlint = (xl >> 2) & 0x3ff; - UINT32 xhint = (xh >> 2) & 0x3ff; - - UINT32* ewdata = m_temp_rect_data; - 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 - - DrawTriangle(false, false, false, true); -} - -void n64_rdp::CmdSetFogColor(UINT32 w1, UINT32 w2) -{ - FogColor.c = w2; -} - -void n64_rdp::CmdSetBlendColor(UINT32 w1, UINT32 w2) -{ - BlendColor.c = w2; -} - -void n64_rdp::CmdSetPrimColor(UINT32 w1, UINT32 w2) -{ - MiscState.MinLevel = (w1 >> 8) & 0x1f; - PrimLODFraction = w1 & 0xff; - PrimColor.c = w2; -} - -void n64_rdp::CmdSetEnvColor(UINT32 w1, UINT32 w2) -{ - EnvColor.c = w2; -} - -void n64_rdp::CmdSetCombine(UINT32 w1, UINT32 w2) -{ - m_combine.sub_a_rgb0 = (w1 >> 20) & 0xf; - m_combine.mul_rgb0 = (w1 >> 15) & 0x1f; - m_combine.sub_a_a0 = (w1 >> 12) & 0x7; - m_combine.mul_a0 = (w1 >> 9) & 0x7; - m_combine.sub_a_rgb1 = (w1 >> 5) & 0xf; - m_combine.mul_rgb1 = (w1 >> 0) & 0x1f; - - m_combine.sub_b_rgb0 = (w2 >> 28) & 0xf; - m_combine.sub_b_rgb1 = (w2 >> 24) & 0xf; - m_combine.sub_a_a1 = (w2 >> 21) & 0x7; - m_combine.mul_a1 = (w2 >> 18) & 0x7; - m_combine.add_rgb0 = (w2 >> 15) & 0x7; - m_combine.sub_b_a0 = (w2 >> 12) & 0x7; - m_combine.add_a0 = (w2 >> 9) & 0x7; - m_combine.add_rgb1 = (w2 >> 6) & 0x7; - m_combine.sub_b_a1 = (w2 >> 3) & 0x7; - m_combine.add_a1 = (w2 >> 0) & 0x7; -} - -void n64_rdp::CmdSetTextureImage(UINT32 w1, UINT32 w2) -{ - MiscState.TIFormat = (w1 >> 21) & 0x7; - MiscState.TISize = (w1 >> 19) & 0x3; - MiscState.TIWidth = (w1 & 0x3ff) + 1; - MiscState.TIAddress = w2 & 0x01ffffff; -} - -void n64_rdp::CmdSetMaskImage(UINT32 w1, UINT32 w2) -{ - //wait("SetMaskImage"); - - MiscState.ZBAddress = w2 & 0x01ffffff; -} - -void n64_rdp::CmdSetColorImage(UINT32 w1, UINT32 w2) -{ - //wait("SetColorImage"); - - MiscState.FBFormat = (w1 >> 21) & 0x7; - MiscState.FBSize = (w1 >> 19) & 0x3; - MiscState.FBWidth = (w1 & 0x3ff) + 1; - MiscState.FBAddress = w2 & 0x01ffffff; - - if (MiscState.FBFormat < 2 || MiscState.FBFormat > 32) // Jet Force Gemini sets the format to 4, Intensity. Protection? - { - MiscState.FBFormat = 2; - } -} - -UINT32 n64_rdp::AddRightCvg(UINT32 x, UINT32 k) -{ -//#undef FULL_SUBPIXELS -#define FULL_SUBPIXELS - UINT32 coveredsubpixels=((x >> 14) & 3); - if (!(x & 0xffff)) - { - return 0; - } -#ifdef FULL_SUBPIXELS - if (!coveredsubpixels) - { - return 0; - } - if (!(k & 1)) - { - return (coveredsubpixels<3) ? 1 : 2; - } - else - { - return (coveredsubpixels<2) ? 0 : 1; - } -#endif - if (!(k & 1)) - { - return (coveredsubpixels<2) ? 1 : 2; - } - else - { - if (coveredsubpixels<1) - { - return 0; - } - else if (coveredsubpixels<3) - { - return 1; - } - else - { - return 2; - } - } -} - -UINT32 n64_rdp::AddLeftCvg(UINT32 x, UINT32 k) -{ - UINT32 coveredsubpixels = 3 - ((x >> 14) & 3); - if (!(x & 0xffff)) - { - return 2; - } -#ifdef FULL_SUBPIXELS - if (!coveredsubpixels) - { - return 0; - } - if (!(k & 1)) - { - return (coveredsubpixels<2) ? 0 : 1; - } - else - { - return (coveredsubpixels<3) ? 1 : 2; - } -#endif - if (k & 1) - { - return (coveredsubpixels<2) ? 1 : 2; - } - else - { - if (coveredsubpixels < 1) - { - return 0; - } - else if (coveredsubpixels < 3) - { - return 1; - } - else - { - return 2; - } - } -} - -/*****************************************************************************/ - -void n64_rdp::CmdInvalid(UINT32 w1, UINT32 w2) -{ - fatalerror("n64_rdp::Invalid: %d, %08x %08x\n", (w1 >> 24) & 0x3f, w1, w2); -} - -void n64_rdp::CmdNoOp(UINT32 w1, UINT32 w2) -{ - // Do nothing -} - - -void n64_rdp::ProcessList() -{ - INT32 length = m_end - m_current; - - if(length < 0) - { - m_current = m_end; - return; - } - - // load command data - for(int i = 0; i < length; i += 4) - { - m_cmd_data[m_cmd_ptr++] = ReadData((m_current & 0x1fffffff) + i); - } - - m_current = m_end; - - UINT32 cmd = (m_cmd_data[0] >> 24) & 0x3f; - UINT32 cmd_length = (m_cmd_ptr + 1) * 4; - - SetStatusReg(GetStatusReg() &~ DP_STATUS_FREEZE); - - // check if more data is needed - if (cmd_length < rdp_command_length[cmd]) - { - return; - } - - while (m_cmd_cur < m_cmd_ptr) - { - cmd = (m_cmd_data[m_cmd_cur] >> 24) & 0x3f; - - if (((m_cmd_ptr - m_cmd_cur) * 4) < rdp_command_length[cmd]) - { - return; - //fatalerror("rdp_process_list: not enough rdp command data: cur = %d, ptr = %d, expected = %d\n", m_cmd_cur, m_cmd_ptr, rdp_command_length[cmd]); - } - - if (LOG_RDP_EXECUTION) - { - char string[4000]; - Dasm(string); - - fprintf(rdp_exec, "%08X: %08X %08X %s\n", m_start+(m_cmd_cur * 4), m_cmd_data[m_cmd_cur+0], m_cmd_data[m_cmd_cur+1], string); - fflush(rdp_exec); - } - - // execute the command - UINT32 w1 = m_cmd_data[m_cmd_cur+0]; - UINT32 w2 = m_cmd_data[m_cmd_cur+1]; - - switch(cmd) - { - case 0x00: CmdNoOp(w1, w2); break; - - case 0x08: CmdTriangle(w1, w2); break; - case 0x09: CmdTriangleZ(w1, w2); break; - case 0x0a: CmdTriangleT(w1, w2); break; - case 0x0b: CmdTriangleTZ(w1, w2); break; - case 0x0c: CmdTriangleS(w1, w2); break; - case 0x0d: CmdTriangleSZ(w1, w2); break; - case 0x0e: CmdTriangleST(w1, w2); break; - case 0x0f: CmdTriangleSTZ(w1, w2); break; - - case 0x24: CmdTexRect(w1, w2); break; - case 0x25: CmdTexRectFlip(w1, w2); break; - - case 0x26: CmdSyncLoad(w1, w2); break; - case 0x27: CmdSyncPipe(w1, w2); break; - case 0x28: CmdSyncTile(w1, w2); break; - case 0x29: CmdSyncFull(w1, w2); break; - - case 0x2a: CmdSetKeyGB(w1, w2); break; - case 0x2b: CmdSetKeyR(w1, w2); break; - - case 0x2c: CmdSetConvert(w1, w2); break; - case 0x3c: CmdSetCombine(w1, w2); break; - case 0x2d: CmdSetScissor(w1, w2); break; - case 0x2e: CmdSetPrimDepth(w1, w2); break; - case 0x2f: CmdSetOtherModes(w1, w2); break; - - case 0x30: CmdLoadTLUT(w1, w2); break; - case 0x33: CmdLoadBlock(w1, w2); break; - case 0x34: CmdLoadTile(w1, w2); break; - - case 0x32: CmdSetTileSize(w1, w2); break; - case 0x35: CmdSetTile(w1, w2); break; - - case 0x36: CmdFillRect(w1, w2); break; - - case 0x37: CmdSetFillColor32(w1, w2); break; - case 0x38: CmdSetFogColor(w1, w2); break; - case 0x39: CmdSetBlendColor(w1, w2); break; - case 0x3a: CmdSetPrimColor(w1, w2); break; - case 0x3b: CmdSetEnvColor(w1, w2); break; - - case 0x3d: CmdSetTextureImage(w1, w2); break; - case 0x3e: CmdSetMaskImage(w1, w2); break; - case 0x3f: CmdSetColorImage(w1, w2); break; - } - - m_cmd_cur += rdp_command_length[cmd] / 4; - }; - m_cmd_ptr = 0; - m_cmd_cur = 0; - - m_start = m_current = m_end; -} - -/*****************************************************************************/ - -n64_rdp::n64_rdp(n64_state &state) : poly_manager(state.machine()) -{ - AuxBufPtr = 0; - AuxBuf = NULL; - m_pipe_clean = true; - - m_pending_mode_block = false; - - m_cmd_ptr = 0; - m_cmd_cur = 0; - - m_start = 0; - m_end = 0; - m_current = 0; - m_status = 0x88; - - for (int i = 0; i < 8; i++) - { - m_tiles[i].num = i; - } - - OneColor.c = 0xffffffff; - ZeroColor.c = 0x00000000; - - m_tmem = NULL; - - m_machine = NULL; - - //memset(m_hidden_bits, 3, 8388608); - - PrimLODFraction = 0; - - for (int i = 0; i < 256; i++) - { - m_gamma_table[i] = sqrt((float)(i << 6)); - m_gamma_table[i] <<= 1; - } - - for (int i = 0; i < 0x4000; i++) - { - m_gamma_dither_table[i] = sqrt((float)i); - m_gamma_dither_table[i] <<= 1; - } - - z_build_com_table(); - - for (int i = 0; i < 0x4000; i++) - { - UINT32 exponent = (i >> 11) & 7; - UINT32 mantissa = i & 0x7ff; - z_complete_dec_table[i] = ((mantissa << z_dec_table[exponent].shift) + z_dec_table[exponent].add) & 0x3fffff; - } - - precalc_cvmask_derivatives(); - - for(int i = 0; i < 0x200; i++) - { - switch((i >> 7) & 3) - { - case 0: - case 1: - s_special_9bit_clamptable[i] = i & 0xff; - break; - case 2: - s_special_9bit_clamptable[i] = 0xff; - break; - case 3: - s_special_9bit_clamptable[i] = 0; - break; - } - } - - for(int i = 0; i < 32; i++) - { - ReplicatedRGBA[i] = (i << 3) | ((i >> 2) & 7); - } - - _Write[0] = &n64_rdp::_Write16Bit_Cvg0_NoBlend; - _Write[1] = &n64_rdp::_Write16Bit_Cvg0_Blend; - _Write[2] = &n64_rdp::_Write16Bit_Cvg1; - _Write[3] = &n64_rdp::_Write16Bit_Cvg1; - _Write[4] = &n64_rdp::_Write16Bit_Cvg2; - _Write[5] = &n64_rdp::_Write16Bit_Cvg2; - _Write[6] = &n64_rdp::_Write16Bit_Cvg3; - _Write[7] = &n64_rdp::_Write16Bit_Cvg3; - _Write[8] = &n64_rdp::_Write32Bit_Cvg0_NoBlend; - _Write[9] = &n64_rdp::_Write32Bit_Cvg0_Blend; - _Write[10] = &n64_rdp::_Write32Bit_Cvg1; - _Write[11] = &n64_rdp::_Write32Bit_Cvg1; - _Write[12] = &n64_rdp::_Write32Bit_Cvg2; - _Write[13] = &n64_rdp::_Write32Bit_Cvg2; - _Write[14] = &n64_rdp::_Write32Bit_Cvg3; - _Write[15] = &n64_rdp::_Write32Bit_Cvg3; - - _Read[0] = &n64_rdp::_Read16Bit_ImgRead0; - _Read[1] = &n64_rdp::_Read16Bit_ImgRead1; - _Read[2] = &n64_rdp::_Read32Bit_ImgRead0; - _Read[3] = &n64_rdp::_Read32Bit_ImgRead1; - - _Copy[0] = &n64_rdp::_Copy16Bit; - _Copy[1] = &n64_rdp::_Copy32Bit; - - _Fill[0] = &n64_rdp::_Fill16Bit; - _Fill[1] = &n64_rdp::_Fill32Bit; -} - -void n64_state::video_start() -{ - m_rdp = auto_alloc(machine(), n64_rdp(*this)); - - m_rdp->SetMachine(machine()); - m_rdp->InitInternalState(); - - m_rdp->Blender.SetMachine(machine()); - m_rdp->Blender.SetProcessor(m_rdp); - - m_rdp->TexPipe.SetMachine(machine()); - - m_rdp->AuxBuf = auto_alloc_array_clear(machine(), UINT8, EXTENT_AUX_COUNT); - - if (LOG_RDP_EXECUTION) - { - rdp_exec = fopen("rdp_execute.txt", "wt"); - } -} - -UINT32 n64_state::screen_update_n64(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - n64_periphs *n64 = machine().device("rcp"); - m_rdp->visarea = screen.visible_area(); - - //UINT16 *frame_buffer = (UINT16*)&rdram[(n64->vi_origin & 0xffffff) >> 2]; - //UINT8 *cvg_buffer = &m_rdp.HiddenBits[((n64->vi_origin & 0xffffff) >> 2) >> 1]; - //int vibuffering = ((n64->vi_control & 2) && fsaa && divot); - - //vibuffering = 0; // Disabled for now - - /* - if (vibuffering && ((n64->vi_control & 3) == 2)) - { - if (frame_buffer) - { - for (j=0; j < vres; j++) - { - for (i=0; i < hres; i++) - { - UINT16 pix; - pix = frame_buffer[pixels ^ WORD_ADDR_XOR]; - curpixel_cvg = ((pix & 1) << 2) | (cvg_buffer[pixels ^ BYTE_ADDR_XOR] & 3); // Reuse of this variable - if (curpixel_cvg < 7 && i > 1 && j > 1 && i < (hres - 2) && j < (vres - 2) && fsaa) - { - newc = video_filter16(&frame_buffer[pixels ^ WORD_ADDR_XOR], &cvg_buffer[pixels ^ BYTE_ADDR_XOR], n64->vi_width); - ViBuffer[i][j] = newc; - } - else - { - newc.i.r = ((pix >> 8) & 0xf8) | (pix >> 13); - newc.i.g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); - newc.i.b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); - ViBuffer[i][j] = newc; - } - pixels++; - } - pixels += invisiblewidth; - } - } - } - */ - - m_rdp->wait(); - m_rdp->AuxBufPtr = 0; - - if (n64->vi_blank) - { - bitmap.fill(0, m_rdp->visarea); - return 0; - } - - m_rdp->VideoUpdate(n64, bitmap); - - return 0; -} +/****************************************************************************** + + + SGI/Nintendo Reality Display Processor + ------------------- + + by MooglyGuy + based on initial C code by Ville Linde + contains additional improvements from angrylion, Ziggy, Gonetz and Orkin + + +******************************************************************************* + +STATUS: + +Much behavior needs verification against real hardware. Many edge cases must +be verified on real hardware as well. + +TODO: + +- Further re-work class structure to avoid dependencies + +*******************************************************************************/ + +#include "emu.h" +#include "video/n64.h" + +#define LOG_RDP_EXECUTION 0 + +static FILE *rdp_exec; + +UINT32 n64_rdp::s_special_9bit_clamptable[512]; + +bool n64_rdp::rdp_range_check(UINT32 addr) +{ + if(MiscState.FBSize == 0) return false; + + int fbcount = ((MiscState.FBWidth * Scissor.m_yl) << (MiscState.FBSize - 1)) * 3; + int fbaddr = MiscState.FBAddress & 0x007fffff; + if ((addr >= fbaddr) && (addr < (fbaddr + fbcount))) + { + return false; + } + + int zbcount = MiscState.FBWidth * Scissor.m_yl * 2; + int zbaddr = MiscState.ZBAddress & 0x007fffff; + if ((addr >= zbaddr) && (addr < (zbaddr + zbcount))) + { + return false; + } + + printf("Check failed: %08x vs. %08x-%08x, %08x-%08x (%d, %d)\n", addr, fbaddr, fbaddr + fbcount, zbaddr, zbaddr + zbcount, MiscState.FBWidth, Scissor.m_yl); + fflush(stdout); + return true; +} + +/*****************************************************************************/ + +// The functions in this file should be moved into the parent Processor class. +#include "rdpfiltr.inc" + +void n64_rdp::GetAlphaCvg(UINT8 *comb_alpha, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + INT32 temp = *comb_alpha; + INT32 temp2 = userdata->CurrentPixCvg; + INT32 temp3 = 0; + + if (object.OtherModes.cvg_times_alpha) + { + temp3 = (temp * temp2) + 4; + userdata->CurrentPixCvg = (temp3 >> 8) & 0xf; + } + if (object.OtherModes.alpha_cvg_select) + { + temp = (OtherModes.cvg_times_alpha) ? (temp3 >> 3) : (temp2 << 5); + } + if (temp > 0xff) + { + temp = 0xff; + } + *comb_alpha = temp; +} + +/*****************************************************************************/ + +void n64_rdp::VideoUpdate(n64_periphs *n64, bitmap_rgb32 &bitmap) +{ + switch(n64->vi_control & 0x3) + { + case PIXEL_SIZE_16BIT: + VideoUpdate16(n64, bitmap); + break; + + case PIXEL_SIZE_32BIT: + VideoUpdate32(n64, bitmap); + break; + + default: + //fatalerror("Unsupported framebuffer depth: m_fb_size=%d\n", MiscState.FBSize); + break; + } +} + +void n64_rdp::VideoUpdate16(n64_periphs *n64, bitmap_rgb32 &bitmap) +{ + //int fsaa = (((n64->vi_control >> 8) & 3) < 2); + //int divot = (n64->vi_control >> 4) & 1; + + //UINT32 prev_cvg = 0; + //UINT32 next_cvg = 0; + //int dither_filter = (n64->vi_control >> 16) & 1; + //int vibuffering = ((n64->vi_control & 2) && fsaa && divot); + + UINT16 *frame_buffer = (UINT16*)&rdram[(n64->vi_origin & 0xffffff) >> 2]; + //UINT32 hb = ((n64->vi_origin & 0xffffff) >> 2) >> 1; + //UINT8* hidden_buffer = &HiddenBits[hb]; + + INT32 hdiff = (n64->vi_hstart & 0x3ff) - ((n64->vi_hstart >> 16) & 0x3ff); + float hcoeff = ((float)(n64->vi_xscale & 0xfff) / (1 << 10)); + UINT32 hres = ((float)hdiff * hcoeff); + INT32 invisiblewidth = n64->vi_width - hres; + + INT32 vdiff = ((n64->vi_vstart & 0x3ff) - ((n64->vi_vstart >> 16) & 0x3ff)) >> 1; + float vcoeff = ((float)(n64->vi_yscale & 0xfff) / (1 << 10)); + UINT32 vres = ((float)vdiff * vcoeff); + + if (vdiff <= 0 || hdiff <= 0) + { + return; + } + + if (hres > 640) // Needed by Top Gear Overdrive (E) + { + invisiblewidth += (hres - 640); + hres = 640; + } + + if (vres > bitmap.height()) // makes Perfect Dark boot w/o crashing + { + vres = bitmap.height(); + } + + UINT32 pixels = 0; + + if (frame_buffer) + { + for(int j = 0; j < vres; j++) + { + UINT32 *d = &bitmap.pix32(j); + + for(int i = 0; i < hres; i++) + { + Color c; + //int r, g, b; + + UINT16 pix = frame_buffer[pixels ^ WORD_ADDR_XOR]; + //MiscState.CurrentPixCvg = ((pix & 1) << 2) | (hidden_buffer[pixels ^ BYTE_ADDR_XOR] & 3); + + //if(divot) + //{ + // if(i > 0 && i < (hres - 1)) + // { + // prev_cvg = ((frame_buffer[(pixels - 1)^WORD_ADDR_XOR] & 1) << 2) | (hidden_buffer[(pixels - 1)^BYTE_ADDR_XOR] & 3); + // next_cvg = ((frame_buffer[(pixels + 1)^WORD_ADDR_XOR] & 1) << 2) | (hidden_buffer[(pixels + 1)^BYTE_ADDR_XOR] & 3); + // } + //} + c.i.r = ((pix >> 8) & 0xf8) | (pix >> 13); + c.i.g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); + c.i.b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); + + //if(fsaa) + //{ + //if (/*!vibuffering &&*/ state->m_rdp.MiscState.CurrentPixCvg < 7 && i > 1 && j > 1 && i < (hres - 2) && j < (vres - 2)) + //{ + //video_filter16(&c.i.r, &c.i.g, &c.i.b, &frame_buffer[pixels ^ WORD_ADDR_XOR],&hidden_buffer[pixels ^ BYTE_ADDR_XOR], n64->vi_width); + //} + //} + //else if (dither_filter && state->m_rdp.MiscState.CurrentPixCvg == 7 && i > 0 && j > 0 && i < (hres - 1) && j < (vres - 1)) + //{ + //if (vibuffering) + //{ + // restore_filter16_buffer(&r, &g, &b, &ViBuffer[i][j], n64->vi_width); + //} + //else + //{ + //restore_filter16(&c.i.r, &c.i.g, &c.i.b, &frame_buffer[pixels ^ WORD_ADDR_XOR], pixels ^ WORD_ADDR_XOR, n64->vi_width); + //} + //} + //if(divot) + //{ + //if (i > 0 && i < (hres - 1) && (MiscState.CurrentPixCvg != 7 || prev_cvg != 7 || next_cvg != 7)) + //{ + //if (vibuffering) + //{ + // divot_filter16_buffer(&r, &g, &b, &ViBuffer[i][j]); + //} + //else + //{ + //divot_filter16(&c.i.r, &c.i.g, &c.i.b, &frame_buffer[pixels ^ WORD_ADDR_XOR], pixels ^ WORD_ADDR_XOR); + //} + //} + //} + + /* + if (gamma_dither) + { + dith = screen.machine().rand() & 0x3f; + } + if (gamma) + { + if (gamma_dither) + { + r = m_gamma_dither_table[(r << 6)|dith]; + g = m_gamma_dither_table[(g << 6)|dith]; + b = m_gamma_dither_table[(b << 6)|dith]; + } + else + { + r = m_gamma_table[r]; + g = m_gamma_table[g]; + b = m_gamma_table[b]; + } + } + else if (gamma_dither) + { + if (r < 255) + r += (dith & 1); + if (g < 255) + g += (dith & 1); + if (b < 255) + b += (dith & 1); + } + */ + pixels++; + + d[i] = c.c >> 8;//(r << 16) | (g << 8) | b; // Fix me for endianness + } + pixels +=invisiblewidth; + } + } +} + +void n64_rdp::VideoUpdate32(n64_periphs *n64, bitmap_rgb32 &bitmap) +{ + int gamma = (n64->vi_control >> 3) & 1; + int gamma_dither = (n64->vi_control >> 2) & 1; + //int vibuffering = ((n64->vi_control & 2) && fsaa && divot); + + UINT32 *frame_buffer32 = (UINT32*)&rdram[(n64->vi_origin & 0xffffff) >> 2]; + + const INT32 hdiff = (n64->vi_hstart & 0x3ff) - ((n64->vi_hstart >> 16) & 0x3ff); + const float hcoeff = ((float)(n64->vi_xscale & 0xfff) / (1 << 10)); + UINT32 hres = ((float)hdiff * hcoeff); + INT32 invisiblewidth = n64->vi_width - hres; + + const INT32 vdiff = ((n64->vi_vstart & 0x3ff) - ((n64->vi_vstart >> 16) & 0x3ff)) >> 1; + const float vcoeff = ((float)(n64->vi_yscale & 0xfff) / (1 << 10)); + const UINT32 vres = ((float)vdiff * vcoeff); + + if (vdiff <= 0 || hdiff <= 0) + { + return; + } + + if (hres > 640) // Needed by Top Gear Overdrive (E) + { + invisiblewidth += (hres - 640); + hres = 640; + } + + if (frame_buffer32) + { + for (int j = 0; j < vres; j++) + { + UINT32 *d = &bitmap.pix32(j); + for (int i = 0; i < hres; i++) + { + UINT32 pix = *frame_buffer32++; + if (gamma || gamma_dither) + { + int r = (pix >> 24) & 0xff; + int g = (pix >> 16) & 0xff; + int b = (pix >> 8) & 0xff; + int dith = 0; + if (gamma_dither) + { + dith = GetRandom() & 0x3f; + } + if (gamma) + { + if (gamma_dither) + { + r = m_gamma_dither_table[(r << 6)| dith]; + g = m_gamma_dither_table[(g << 6)| dith]; + b = m_gamma_dither_table[(b << 6)| dith]; + } + else + { + r = m_gamma_table[r]; + g = m_gamma_table[g]; + b = m_gamma_table[b]; + } + } + else if (gamma_dither) + { + if (r < 255) + r += (dith & 1); + if (g < 255) + g += (dith & 1); + if (b < 255) + b += (dith & 1); + } + pix = (r << 24) | (g << 16) | (b << 8); + } + + + d[i] = (pix >> 8); + } + frame_buffer32 += invisiblewidth; + } + } +} + +/*****************************************************************************/ + +void n64_rdp::TCDivNoPersp(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst) +{ + *sss = (SIGN16(ss)) & 0x1ffff; + *sst = (SIGN16(st)) & 0x1ffff; +} + +void n64_rdp::TCDiv(INT32 ss, INT32 st, INT32 sw, INT32* sss, INT32* sst) +{ + int w_carry = 0; + if ((sw & 0x8000) || !(sw & 0x7fff)) + { + w_carry = 1; + } + + sw &= 0x7fff; + + int shift; + for (shift = 1; shift <= 14 && !((sw << shift) & 0x8000); shift++); + shift -= 1; + + int normout = (sw << shift) & 0x3fff; + int wnorm = (normout & 0xff) << 2; + normout >>= 8; + + int temppoint = m_norm_point_rom[normout]; + int tempslope = m_norm_slope_rom[normout]; + + int tlu_rcp = ((-(tempslope * wnorm)) >> 10) + temppoint; + + int sprod = SIGN16(ss) * tlu_rcp; + int tprod = SIGN16(st) * tlu_rcp; + int tempmask = ((1 << (shift + 1)) - 1) << (29 - shift); + int shift_value = 13 - shift; + + int outofbounds_s = sprod & tempmask; + int outofbounds_t = tprod & tempmask; + if (shift == 0xe) + { + *sss = sprod << 1; + *sst = tprod << 1; + } + else + { + *sss = sprod = (sprod >> shift_value); + *sst = tprod = (tprod >> shift_value); + } + //compute clamp flags + int under_s = 0; + int under_t = 0; + int over_s = 0; + int over_t = 0; + + if (outofbounds_s != tempmask && outofbounds_s != 0) + { + if (sprod & (1 << 29)) + { + under_s = 1; + } + else + { + over_s = 1; + } + } + + if (outofbounds_t != tempmask && outofbounds_t != 0) + { + if (tprod & (1 << 29)) + { + under_t = 1; + } + else + { + over_t = 1; + } + } + + over_s |= w_carry; + over_t |= w_carry; + + *sss = (*sss & 0x1ffff) | (over_s << 18) | (under_s << 17); + *sst = (*sst & 0x1ffff) | (over_t << 18) | (under_t << 17); +} + +INT32 n64_rdp::ColorCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d) +{ + a = KURT_AKELEY_SIGN9(a); + b = KURT_AKELEY_SIGN9(b); + c = SIGN9(c); + d = KURT_AKELEY_SIGN9(d); + a = (((a - b) * c) + (d << 8) + 0x80); + a = SIGN17(a) >> 8; + a = s_special_9bit_clamptable[a & 0x1ff]; + return a; +} + +INT32 n64_rdp::AlphaCombinerEquation(INT32 a, INT32 b, INT32 c, INT32 d) +{ + a = KURT_AKELEY_SIGN9(a); + b = KURT_AKELEY_SIGN9(b); + c = SIGN9(c); + d = KURT_AKELEY_SIGN9(d); + a = (((a - b) * c) + (d << 8) + 0x80) >> 8; + a = SIGN9(a); + a = s_special_9bit_clamptable[a & 0x1ff]; + return a; +} + +void n64_rdp::SetSubAInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) +{ + switch (code & 0xf) + { + case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; + case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; + case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; + case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; + case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; + case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; + case 6: *input_r = &OneColor.i.r; *input_g = &OneColor.i.g; *input_b = &OneColor.i.b; break; + case 7: *input_r = &userdata->NoiseColor.i.r; *input_g = &userdata->NoiseColor.i.g; *input_b = &userdata->NoiseColor.i.b; break; + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: + { + *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; + } + } +} + +void n64_rdp::SetSubBInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) +{ + switch (code & 0xf) + { + case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; + case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; + case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; + case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; + case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; + case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; + case 6: fatalerror("SET_SUBB_RGB_INPUT: key_center\n"); + case 7: *input_r = (UINT8*)&m_k4; *input_g = (UINT8*)&m_k4; *input_b = (UINT8*)&m_k4; break; + case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: + { + *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; + } + } +} + +void n64_rdp::SetMulInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) +{ + switch (code & 0x1f) + { + case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; + case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; + case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; + case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; + case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; + case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; + case 6: *input_r = &userdata->KeyScale.i.r; *input_g = &userdata->KeyScale.i.g; *input_b = &userdata->KeyScale.i.b; break; + case 7: *input_r = &userdata->CombinedColor.i.a; *input_g = &userdata->CombinedColor.i.a; *input_b = &userdata->CombinedColor.i.a; break; + case 8: *input_r = &userdata->Texel0Color.i.a; *input_g = &userdata->Texel0Color.i.a; *input_b = &userdata->Texel0Color.i.a; break; + case 9: *input_r = &userdata->Texel1Color.i.a; *input_g = &userdata->Texel1Color.i.a; *input_b = &userdata->Texel1Color.i.a; break; + case 10: *input_r = &userdata->PrimColor.i.a; *input_g = &userdata->PrimColor.i.a; *input_b = &userdata->PrimColor.i.a; break; + case 11: *input_r = &userdata->ShadeColor.i.a; *input_g = &userdata->ShadeColor.i.a; *input_b = &userdata->ShadeColor.i.a; break; + case 12: *input_r = &userdata->EnvColor.i.a; *input_g = &userdata->EnvColor.i.a; *input_b = &userdata->EnvColor.i.a; break; + case 13: *input_r = &userdata->LODFraction; *input_g = &userdata->LODFraction; *input_b = &userdata->LODFraction; break; + case 14: *input_r = &userdata->PrimLODFraction; *input_g = &userdata->PrimLODFraction; *input_b = &userdata->PrimLODFraction; break; + case 15: *input_r = (UINT8*)&m_k5; *input_g = (UINT8*)&m_k5; *input_b = (UINT8*)&m_k5; break; + case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: + case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: + { + *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; + } + } +} + +void n64_rdp::SetAddInputRGB(UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, int code, rdp_span_aux *userdata) +{ + switch (code & 0x7) + { + case 0: *input_r = &userdata->CombinedColor.i.r; *input_g = &userdata->CombinedColor.i.g; *input_b = &userdata->CombinedColor.i.b; break; + case 1: *input_r = &userdata->Texel0Color.i.r; *input_g = &userdata->Texel0Color.i.g; *input_b = &userdata->Texel0Color.i.b; break; + case 2: *input_r = &userdata->Texel1Color.i.r; *input_g = &userdata->Texel1Color.i.g; *input_b = &userdata->Texel1Color.i.b; break; + case 3: *input_r = &userdata->PrimColor.i.r; *input_g = &userdata->PrimColor.i.g; *input_b = &userdata->PrimColor.i.b; break; + case 4: *input_r = &userdata->ShadeColor.i.r; *input_g = &userdata->ShadeColor.i.g; *input_b = &userdata->ShadeColor.i.b; break; + case 5: *input_r = &userdata->EnvColor.i.r; *input_g = &userdata->EnvColor.i.g; *input_b = &userdata->EnvColor.i.b; break; + case 6: *input_r = &OneColor.i.r; *input_g = &OneColor.i.g; *input_b = &OneColor.i.b; break; + case 7: *input_r = &ZeroColor.i.r; *input_g = &ZeroColor.i.g; *input_b = &ZeroColor.i.b; break; + } +} + +void n64_rdp::SetSubInputAlpha(UINT8 **input, int code, rdp_span_aux *userdata) +{ + switch (code & 0x7) + { + case 0: *input = &userdata->CombinedColor.i.a; break; + case 1: *input = &userdata->Texel0Color.i.a; break; + case 2: *input = &userdata->Texel1Color.i.a; break; + case 3: *input = &userdata->PrimColor.i.a; break; + case 4: *input = &userdata->ShadeColor.i.a; break; + case 5: *input = &userdata->EnvColor.i.a; break; + case 6: *input = &OneColor.i.a; break; + case 7: *input = &ZeroColor.i.a; break; + } +} + +void n64_rdp::SetMulInputAlpha(UINT8 **input, int code, rdp_span_aux *userdata) +{ + switch (code & 0x7) + { + case 0: *input = &userdata->LODFraction; break; + case 1: *input = &userdata->Texel0Color.i.a; break; + case 2: *input = &userdata->Texel1Color.i.a; break; + case 3: *input = &userdata->PrimColor.i.a; break; + case 4: *input = &userdata->ShadeColor.i.a; break; + case 5: *input = &userdata->EnvColor.i.a; break; + case 6: *input = &userdata->PrimLODFraction; break; + case 7: *input = &ZeroColor.i.a; break; + } +} + +void n64_rdp::SetBlenderInput(int cycle, int which, UINT8 **input_r, UINT8 **input_g, UINT8 **input_b, UINT8 **input_a, int a, int b, rdp_span_aux *userdata) +{ + switch (a & 0x3) + { + case 0: + { + if (cycle == 0) + { + *input_r = &userdata->PixelColor.i.r; + *input_g = &userdata->PixelColor.i.g; + *input_b = &userdata->PixelColor.i.b; + } + else + { + *input_r = &userdata->BlendedPixelColor.i.r; + *input_g = &userdata->BlendedPixelColor.i.g; + *input_b = &userdata->BlendedPixelColor.i.b; + } + break; + } + + case 1: + { + *input_r = &userdata->MemoryColor.i.r; + *input_g = &userdata->MemoryColor.i.g; + *input_b = &userdata->MemoryColor.i.b; + break; + } + + case 2: + { + *input_r = &userdata->BlendColor.i.r; + *input_g = &userdata->BlendColor.i.g; + *input_b = &userdata->BlendColor.i.b; + break; + } + + case 3: + { + *input_r = &userdata->FogColor.i.r; + *input_g = &userdata->FogColor.i.g; + *input_b = &userdata->FogColor.i.b; + break; + } + } + + if (which == 0) + { + switch (b & 0x3) + { + case 0: *input_a = &userdata->PixelColor.i.a; break; + case 1: *input_a = &userdata->FogColor.i.a; break; + case 2: *input_a = &userdata->ShadeColor.i.a; break; + case 3: *input_a = &ZeroColor.i.a; break; + } + } + else + { + switch (b & 0x3) + { + case 0: *input_a = &userdata->InvPixelColor.i.a; break; + case 1: *input_a = &userdata->MemoryColor.i.a; break; + case 2: *input_a = &OneColor.i.a; break; + case 3: *input_a = &ZeroColor.i.a; break; + } + } +} + +const UINT8 n64_rdp::s_bayer_matrix[16] = +{ /* Bayer matrix */ + 0, 4, 1, 5, + 6, 2, 7, 3, + 1, 5, 0, 4, + 7, 3, 6, 2 +}; + +const UINT8 n64_rdp::s_magic_matrix[16] = +{ /* Magic square matrix */ + 0, 6, 1, 7, + 4, 2, 5, 3, + 3, 5, 2, 4, + 7, 1, 6, 0 +}; + +const n64_rdp::ZDecompressEntry n64_rdp::z_dec_table[8] = +{ + { 6, 0x00000 }, + { 5, 0x20000 }, + { 4, 0x30000 }, + { 3, 0x38000 }, + { 2, 0x3c000 }, + { 1, 0x3e000 }, + { 0, 0x3f000 }, + { 0, 0x3f800 }, +}; + +/*****************************************************************************/ + +void n64_rdp::z_build_com_table(void) +{ + UINT16 altmem = 0; + for(int z = 0; z < 0x40000; z++) + { + switch((z >> 11) & 0x7f) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + case 0x2f: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + altmem = (z >> 4) & 0x1ffc; + break; + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + altmem = ((z >> 3) & 0x1ffc) | 0x2000; + break; + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6a: + case 0x6b: + case 0x6c: + case 0x6d: + case 0x6e: + case 0x6f: + altmem = ((z >> 2) & 0x1ffc) | 0x4000; + break; + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + altmem = ((z >> 1) & 0x1ffc) | 0x6000; + break; + case 0x78://uncompressed z = 0x3c000 + case 0x79: + case 0x7a: + case 0x7b: + altmem = (z & 0x1ffc) | 0x8000; + break; + case 0x7c://uncompressed z = 0x3e000 + case 0x7d: + altmem = ((z << 1) & 0x1ffc) | 0xa000; + break; + case 0x7e://uncompressed z = 0x3f000 + altmem = ((z << 2) & 0x1ffc) | 0xc000; + break; + case 0x7f://uncompressed z = 0x3f000 + altmem = ((z << 2) & 0x1ffc) | 0xe000; + break; + } + + z_com_table[z] = altmem; + + } +} + +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 (int i = 0; i < 0x10000; i++) + { + 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 (int i = 0; i < 0x100; i++) + { + UINT16 mask = decompress_cvmask_frombyte(i); + cvarray[i].cvg = cvarray[i].cvbit = 0; + cvarray[i].cvbit = (i >> 7) & 1; + for (int k = 0; k < 8; k++) + { + cvarray[i].cvg += ((i >> k) & 1); + } + + UINT16 masky = 0; + for (int k = 0; k < 4; k++) + { + masky |= ((mask & (0xf000 >> (k << 2))) > 0) << k; + } + UINT8 offy = yarray[masky]; + + UINT16 maskx = (mask & (0xf000 >> (offy << 2))) >> ((offy ^ 3) << 2); + UINT8 offx = xarray[maskx]; + + cvarray[i].xoff = offx; + cvarray[i].yoff = offy; + } +} + +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; +} + +void n64_rdp::lookup_cvmask_derivatives(UINT32 mask, UINT8* offx, UINT8* offy, rdp_span_aux *userdata) +{ + UINT32 index = compressed_cvmasks[mask]; + userdata->CurrentPixCvg = cvarray[index].cvg; + userdata->CurrentCvgBit = cvarray[index].cvbit; + *offx = cvarray[index].xoff; + *offy = cvarray[index].yoff; +} + +void n64_rdp::ZStore(const rdp_poly_state &object, UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 z, UINT32 enc) +{ + UINT16 zval = z_com_table[z & 0x3ffff]|(enc >> 2); + if(zcurpixel <= MEM16_LIMIT) + { + ((UINT16*)rdram)[zcurpixel ^ WORD_ADDR_XOR] = zval; + } + if(dzcurpixel <= MEM8_LIMIT) + { + HiddenBits[dzcurpixel ^ BYTE_ADDR_XOR] = enc & 3; + } +} + +INT32 n64_rdp::NormalizeDZPix(INT32 sum) +{ + if (sum & 0xc000) + { + return 0x8000; + } + if (!(sum & 0xffff)) + { + return 1; + } + for(int count = 0x2000; count > 0; count >>= 1) + { + if (sum & count) + { + return(count << 1); + } + } + return 0; +} + +UINT32 n64_rdp::ZDecompress(UINT32 zcurpixel) +{ + UINT32 zb = RREADIDX16(zcurpixel); + CHECK16(zcurpixel); + return z_complete_dec_table[(zb >> 2) & 0x3fff]; +} + +UINT32 n64_rdp::DZDecompress(UINT32 zcurpixel, UINT32 dzcurpixel) +{ + UINT16 zval = RREADIDX16(zcurpixel); + CHECK16(zcurpixel); + UINT8 dzval = (((dzcurpixel) <= 0x7fffff) ? (HiddenBits[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0); + UINT32 dz_compressed = ((zval & 3) << 2) | (dzval & 3); + return (1 << dz_compressed); +} + +UINT32 n64_rdp::DZCompress(UINT32 value) +{ + INT32 j = 0; + for (; value > 1; j++, value >>= 1); + return j; +} + +void n64_rdp::GetDitherValues(int x, int y, int* cdith, int* adith, const rdp_poly_state& object) +{ + int dithindex = ((y & 3) << 2) | (x & 3); + switch((object.OtherModes.rgb_dither_sel << 2) | object.OtherModes.alpha_dither_sel) + { + case 0: + *adith = *cdith = s_magic_matrix[dithindex]; + break; + case 1: + *cdith = s_magic_matrix[dithindex]; + *adith = (~(*cdith)) & 7; + break; + case 2: + *cdith = s_magic_matrix[dithindex]; + *adith = machine().rand() & 7; + break; + case 3: + *cdith = s_magic_matrix[dithindex]; + *adith = 0; + break; + case 4: + *adith = *cdith = s_bayer_matrix[dithindex]; + break; + case 5: + *cdith = s_bayer_matrix[dithindex]; + *adith = (~(*cdith)) & 7; + break; + case 6: + *cdith = s_bayer_matrix[dithindex]; + *adith = machine().rand() & 7; + break; + case 7: + *cdith = s_bayer_matrix[dithindex]; + *adith = 0; + break; + case 8: + *cdith = machine().rand() & 7; + *adith = s_magic_matrix[dithindex]; + break; + case 9: + *cdith = machine().rand() & 7; + *adith = (~s_magic_matrix[dithindex]) & 7; + break; + case 10: + *cdith = machine().rand() & 7; + *adith = (*cdith + 17) & 7; + break; + case 11: + *cdith = machine().rand() & 7; + *adith = 0; + break; + case 12: + *cdith = 0; + *adith = s_bayer_matrix[dithindex]; + break; + case 13: + *cdith = 0; + *adith = (~s_bayer_matrix[dithindex]) & 7; + break; + case 14: + *cdith = 0; + *adith = m_machine->rand() & 7; + break; + case 15: + *adith = *cdith = 0; + break; + } +} + +INT32 CLAMP(INT32 in, INT32 min, INT32 max) +{ + if(in < min) return min; + if(in > max) return max; + return in; +} + +bool n64_rdp::ZCompare(UINT32 zcurpixel, UINT32 dzcurpixel, UINT32 sz, UINT16 dzpix, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + bool force_coplanar = false; + sz &= 0x3ffff; + + UINT32 oz; + UINT32 dzmem; + UINT32 zval; + INT32 rawdzmem; + + if (object.OtherModes.z_compare_en) + { + oz = ZDecompress(zcurpixel); + dzmem = DZDecompress(zcurpixel, dzcurpixel); + zval = RREADIDX16(zcurpixel); + CHECK16(zcurpixel); + rawdzmem = ((zval & 3) << 2) | ((((dzcurpixel) <= 0x3fffff) ? (HiddenBits[(dzcurpixel) ^ BYTE_ADDR_XOR]) : 0) & 3); + } + else + { + oz = 0; + dzmem = 1 << 0xf; + zval = 0x3; + rawdzmem = 0xf; + } + + userdata->m_dzpix_enc = DZCompress(dzpix & 0xffff); + userdata->ShiftA = CLAMP(userdata->m_dzpix_enc - rawdzmem, 0, 4); + userdata->ShiftB = CLAMP(rawdzmem - userdata->m_dzpix_enc, 0, 4); + + int precision_factor = (zval >> 13) & 0xf; + if (precision_factor < 3) + { + int dzmemmodifier = 16 >> precision_factor; + if (dzmem == 0x8000) + { + force_coplanar = true; + } + dzmem <<= 1; + if (dzmem <= dzmemmodifier) + { + dzmem = dzmemmodifier; + } + if (!dzmem) + { + 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; + } + + bool overflow = ((userdata->CurrentMemCvg + userdata->CurrentPixCvg) & 8) > 0; + userdata->BlendEnable = (object.OtherModes.force_blend || (!overflow && object.OtherModes.antialias_en && farther)) ? 1 : 0; + userdata->PreWrap = overflow; + + int cvgcoeff = 0; + UINT32 dzenc = 0; + + if (object.OtherModes.z_mode == 1 && infront && farther && overflow) + { + dzenc = DZCompress(dznotshift & 0xffff); + cvgcoeff = ((oz >> dzenc) - (sz >> dzenc)) & 0xf; + userdata->CurrentPixCvg = ((cvgcoeff * userdata->CurrentPixCvg) >> 3) & 0xf; + } + + if (!object.OtherModes.z_compare_en) + { + return true; + } + + INT32 diff = (INT32)sz - (INT32)dznew; + bool nearer = diff <= (INT32)oz; + bool max = (oz == 0x3ffff); + if (force_coplanar) + { + nearer = true; + } + + switch(object.OtherModes.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); + } + + return false; +} + +UINT32 n64_rdp::GetLog2(UINT32 lod_clamp) +{ + if (lod_clamp < 2) + { + return 0; + } + else + { + for (int i = 7; i > 0; i--) + { + if ((lod_clamp >> i) & 1) + { + return i; + } + } + } + + return 0; +} + +/*****************************************************************************/ + +UINT32 n64_rdp::ReadData(UINT32 address) +{ + if (m_status & 0x1) // XBUS_DMEM_DMA enabled + { + return rsp_dmem[(address & 0xfff) / 4]; + } + else + { + return rdram[((address & 0xffffff) / 4)]; + } +} + +static const char *const image_format[] = { "RGBA", "YUV", "CI", "IA", "I", "???", "???", "???" }; +static const char *const image_size[] = { "4-bit", "8-bit", "16-bit", "32-bit" }; + +static const int rdp_command_length[64] = +{ + 8, // 0x00, No Op + 8, // 0x01, ??? + 8, // 0x02, ??? + 8, // 0x03, ??? + 8, // 0x04, ??? + 8, // 0x05, ??? + 8, // 0x06, ??? + 8, // 0x07, ??? + 32, // 0x08, Non-Shaded Triangle + 32+16, // 0x09, Non-Shaded, Z-Buffered Triangle + 32+64, // 0x0a, Textured Triangle + 32+64+16, // 0x0b, Textured, Z-Buffered Triangle + 32+64, // 0x0c, Shaded Triangle + 32+64+16, // 0x0d, Shaded, Z-Buffered Triangle + 32+64+64, // 0x0e, Shaded+Textured Triangle + 32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle + 8, // 0x10, ??? + 8, // 0x11, ??? + 8, // 0x12, ??? + 8, // 0x13, ??? + 8, // 0x14, ??? + 8, // 0x15, ??? + 8, // 0x16, ??? + 8, // 0x17, ??? + 8, // 0x18, ??? + 8, // 0x19, ??? + 8, // 0x1a, ??? + 8, // 0x1b, ??? + 8, // 0x1c, ??? + 8, // 0x1d, ??? + 8, // 0x1e, ??? + 8, // 0x1f, ??? + 8, // 0x20, ??? + 8, // 0x21, ??? + 8, // 0x22, ??? + 8, // 0x23, ??? + 16, // 0x24, Texture_Rectangle + 16, // 0x25, Texture_Rectangle_Flip + 8, // 0x26, Sync_Load + 8, // 0x27, Sync_Pipe + 8, // 0x28, Sync_Tile + 8, // 0x29, Sync_Full + 8, // 0x2a, Set_Key_GB + 8, // 0x2b, Set_Key_R + 8, // 0x2c, Set_Convert + 8, // 0x2d, Set_Scissor + 8, // 0x2e, Set_Prim_Depth + 8, // 0x2f, Set_Other_Modes + 8, // 0x30, Load_TLUT + 8, // 0x31, ??? + 8, // 0x32, Set_Tile_Size + 8, // 0x33, Load_Block + 8, // 0x34, Load_Tile + 8, // 0x35, Set_Tile + 8, // 0x36, Fill_Rectangle + 8, // 0x37, Set_Fill_Color + 8, // 0x38, Set_Fog_Color + 8, // 0x39, Set_Blend_Color + 8, // 0x3a, Set_Prim_Color + 8, // 0x3b, Set_Env_Color + 8, // 0x3c, Set_Combine + 8, // 0x3d, Set_Texture_Image + 8, // 0x3e, Set_Mask_Image + 8 // 0x3f, Set_Color_Image +}; + +void n64_rdp::Dasm(char *buffer) +{ + int i; + int tile; + const char *format, *size; + char sl[32], tl[32], sh[32], th[32]; + char s[32], t[32], w[32]; + char dsdx[32], dtdx[32], dwdx[32]; + char dsdy[32], dtdy[32], dwdy[32]; + char dsde[32], dtde[32], dwde[32]; + char yl[32], yh[32], ym[32], xl[32], xh[32], xm[32]; + char dxldy[32], dxhdy[32], dxmdy[32]; + char rt[32], gt[32], bt[32], at[32]; + char drdx[32], dgdx[32], dbdx[32], dadx[32]; + char drdy[32], dgdy[32], dbdy[32], dady[32]; + char drde[32], dgde[32], dbde[32], dade[32]; + UINT32 r,g,b,a; + + UINT32 cmd[64]; + UINT32 length; + UINT32 command; + + length = m_cmd_ptr * 4; + if (length < 8) + { + sprintf(buffer, "ERROR: length = %d\n", length); + return; + } + + cmd[0] = m_cmd_data[m_cmd_cur+0]; + cmd[1] = m_cmd_data[m_cmd_cur+1]; + + tile = (cmd[1] >> 24) & 0x7; + sprintf(sl, "%4.2f", (float)((cmd[0] >> 12) & 0xfff) / 4.0f); + sprintf(tl, "%4.2f", (float)((cmd[0] >> 0) & 0xfff) / 4.0f); + sprintf(sh, "%4.2f", (float)((cmd[1] >> 12) & 0xfff) / 4.0f); + sprintf(th, "%4.2f", (float)((cmd[1] >> 0) & 0xfff) / 4.0f); + + format = image_format[(cmd[0] >> 21) & 0x7]; + size = image_size[(cmd[0] >> 19) & 0x3]; + + r = (cmd[1] >> 24) & 0xff; + g = (cmd[1] >> 16) & 0xff; + b = (cmd[1] >> 8) & 0xff; + a = (cmd[1] >> 0) & 0xff; + + command = (cmd[0] >> 24) & 0x3f; + switch (command) + { + case 0x00: sprintf(buffer, "No Op"); break; + case 0x08: // Tri_NoShade + { + int lft = (command >> 23) & 0x1; + + if (length != rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_NoShade length = %d\n", length); + return; + } + + cmd[2] = m_cmd_data[m_cmd_cur+2]; + cmd[3] = m_cmd_data[m_cmd_cur+3]; + cmd[4] = m_cmd_data[m_cmd_cur+4]; + cmd[5] = m_cmd_data[m_cmd_cur+5]; + cmd[6] = m_cmd_data[m_cmd_cur+6]; + cmd[7] = m_cmd_data[m_cmd_cur+7]; + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)(cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)(cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)(cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)(cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)(cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)(cmd[7] / 65536.0f)); + + sprintf(buffer, "Tri_NoShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + break; + } + case 0x09: // Tri_NoShadeZ + { + int lft = (command >> 23) & 0x1; + + if (length != rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_NoShadeZ length = %d\n", length); + return; + } + + cmd[2] = m_cmd_data[m_cmd_cur+2]; + cmd[3] = m_cmd_data[m_cmd_cur+3]; + cmd[4] = m_cmd_data[m_cmd_cur+4]; + cmd[5] = m_cmd_data[m_cmd_cur+5]; + cmd[6] = m_cmd_data[m_cmd_cur+6]; + cmd[7] = m_cmd_data[m_cmd_cur+7]; + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)(cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)(cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)(cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)(cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)(cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)(cmd[7] / 65536.0f)); + + sprintf(buffer, "Tri_NoShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + break; + } + case 0x0a: // Tri_Tex + { + int lft = (command >> 23) & 0x1; + + if (length < rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_Tex length = %d\n", length); + return; + } + + for (i=2; i < 24; i++) + { + cmd[i] = m_cmd_data[m_cmd_cur+i]; + } + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); + + sprintf(s, "%4.4f", (float)(INT32)((cmd[ 8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); + sprintf(t, "%4.4f", (float)(INT32)(((cmd[ 8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); + sprintf(w, "%4.4f", (float)(INT32)((cmd[ 9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); + sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); + sprintf(dwde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); + sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); + + + buffer+=sprintf(buffer, "Tri_Tex %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); + break; + } + case 0x0b: // Tri_TexZ + { + int lft = (command >> 23) & 0x1; + + if (length < rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_TexZ length = %d\n", length); + return; + } + + for (i=2; i < 24; i++) + { + cmd[i] = m_cmd_data[m_cmd_cur+i]; + } + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); + + sprintf(s, "%4.4f", (float)(INT32)((cmd[ 8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); + sprintf(t, "%4.4f", (float)(INT32)(((cmd[ 8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); + sprintf(w, "%4.4f", (float)(INT32)((cmd[ 9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); + sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); + sprintf(dwde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); + sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); + + + buffer+=sprintf(buffer, "Tri_TexZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); + break; + } + case 0x0c: // Tri_Shade + { + int lft = (command >> 23) & 0x1; + + if (length != rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_Shade length = %d\n", length); + return; + } + + for (i=2; i < 24; i++) + { + cmd[i] = m_cmd_data[i]; + } + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); + sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); + sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); + sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); + sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); + sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); + sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); + sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); + sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); + sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); + sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); + sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); + sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); + sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); + + buffer+=sprintf(buffer, "Tri_Shade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); + break; + } + case 0x0d: // Tri_ShadeZ + { + int lft = (command >> 23) & 0x1; + + if (length != rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_ShadeZ length = %d\n", length); + return; + } + + for (i=2; i < 24; i++) + { + cmd[i] = m_cmd_data[i]; + } + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); + sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); + sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); + sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); + sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); + sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); + sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); + sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); + sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); + sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); + sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); + sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); + sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); + sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); + + buffer+=sprintf(buffer, "Tri_ShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); + break; + } + case 0x0e: // Tri_TexShade + { + int lft = (command >> 23) & 0x1; + + if (length < rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_TexShade length = %d\n", length); + return; + } + + for (i=2; i < 40; i++) + { + cmd[i] = m_cmd_data[m_cmd_cur+i]; + } + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); + sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); + sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); + sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); + sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); + sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); + sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); + sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); + sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); + sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); + sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); + sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); + sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); + sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); + + sprintf(s, "%4.4f", (float)(INT32)((cmd[24] & 0xffff0000) | ((cmd[28] >> 16) & 0xffff)) / 65536.0f); + sprintf(t, "%4.4f", (float)(INT32)(((cmd[24] & 0xffff) << 16) | (cmd[28] & 0xffff)) / 65536.0f); + sprintf(w, "%4.4f", (float)(INT32)((cmd[25] & 0xffff0000) | ((cmd[29] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[26] & 0xffff0000) | ((cmd[30] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[26] & 0xffff) << 16) | (cmd[30] & 0xffff)) / 65536.0f); + sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[27] & 0xffff0000) | ((cmd[31] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsde, "%4.4f", (float)(INT32)((cmd[32] & 0xffff0000) | ((cmd[36] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[32] & 0xffff) << 16) | (cmd[36] & 0xffff)) / 65536.0f); + sprintf(dwde, "%4.4f", (float)(INT32)((cmd[33] & 0xffff0000) | ((cmd[37] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[34] & 0xffff0000) | ((cmd[38] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[34] & 0xffff) << 16) | (cmd[38] & 0xffff)) / 65536.0f); + sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[35] & 0xffff0000) | ((cmd[39] >> 16) & 0xffff)) / 65536.0f); + + + buffer+=sprintf(buffer, "Tri_TexShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); + + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); + break; + } + case 0x0f: // Tri_TexShadeZ + { + int lft = (command >> 23) & 0x1; + + if (length < rdp_command_length[command]) + { + sprintf(buffer, "ERROR: Tri_TexShadeZ length = %d\n", length); + return; + } + + for (i=2; i < 40; i++) + { + cmd[i] = m_cmd_data[m_cmd_cur+i]; + } + + sprintf(yl, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f); + sprintf(ym, "%4.4f", (float)((cmd[1] >> 16) & 0x1fff) / 4.0f); + sprintf(yh, "%4.4f", (float)((cmd[1] >> 0) & 0x1fff) / 4.0f); + sprintf(xl, "%4.4f", (float)((INT32)cmd[2] / 65536.0f)); + sprintf(dxldy, "%4.4f", (float)((INT32)cmd[3] / 65536.0f)); + sprintf(xh, "%4.4f", (float)((INT32)cmd[4] / 65536.0f)); + sprintf(dxhdy, "%4.4f", (float)((INT32)cmd[5] / 65536.0f)); + sprintf(xm, "%4.4f", (float)((INT32)cmd[6] / 65536.0f)); + sprintf(dxmdy, "%4.4f", (float)((INT32)cmd[7] / 65536.0f)); + sprintf(rt, "%4.4f", (float)(INT32)((cmd[8] & 0xffff0000) | ((cmd[12] >> 16) & 0xffff)) / 65536.0f); + sprintf(gt, "%4.4f", (float)(INT32)(((cmd[8] & 0xffff) << 16) | (cmd[12] & 0xffff)) / 65536.0f); + sprintf(bt, "%4.4f", (float)(INT32)((cmd[9] & 0xffff0000) | ((cmd[13] >> 16) & 0xffff)) / 65536.0f); + sprintf(at, "%4.4f", (float)(INT32)(((cmd[9] & 0xffff) << 16) | (cmd[13] & 0xffff)) / 65536.0f); + sprintf(drdx, "%4.4f", (float)(INT32)((cmd[10] & 0xffff0000) | ((cmd[14] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdx, "%4.4f", (float)(INT32)(((cmd[10] & 0xffff) << 16) | (cmd[14] & 0xffff)) / 65536.0f); + sprintf(dbdx, "%4.4f", (float)(INT32)((cmd[11] & 0xffff0000) | ((cmd[15] >> 16) & 0xffff)) / 65536.0f); + sprintf(dadx, "%4.4f", (float)(INT32)(((cmd[11] & 0xffff) << 16) | (cmd[15] & 0xffff)) / 65536.0f); + sprintf(drde, "%4.4f", (float)(INT32)((cmd[16] & 0xffff0000) | ((cmd[20] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgde, "%4.4f", (float)(INT32)(((cmd[16] & 0xffff) << 16) | (cmd[20] & 0xffff)) / 65536.0f); + sprintf(dbde, "%4.4f", (float)(INT32)((cmd[17] & 0xffff0000) | ((cmd[21] >> 16) & 0xffff)) / 65536.0f); + sprintf(dade, "%4.4f", (float)(INT32)(((cmd[17] & 0xffff) << 16) | (cmd[21] & 0xffff)) / 65536.0f); + sprintf(drdy, "%4.4f", (float)(INT32)((cmd[18] & 0xffff0000) | ((cmd[22] >> 16) & 0xffff)) / 65536.0f); + sprintf(dgdy, "%4.4f", (float)(INT32)(((cmd[18] & 0xffff) << 16) | (cmd[22] & 0xffff)) / 65536.0f); + sprintf(dbdy, "%4.4f", (float)(INT32)((cmd[19] & 0xffff0000) | ((cmd[23] >> 16) & 0xffff)) / 65536.0f); + sprintf(dady, "%4.4f", (float)(INT32)(((cmd[19] & 0xffff) << 16) | (cmd[23] & 0xffff)) / 65536.0f); + + sprintf(s, "%4.4f", (float)(INT32)((cmd[24] & 0xffff0000) | ((cmd[28] >> 16) & 0xffff)) / 65536.0f); + sprintf(t, "%4.4f", (float)(INT32)(((cmd[24] & 0xffff) << 16) | (cmd[28] & 0xffff)) / 65536.0f); + sprintf(w, "%4.4f", (float)(INT32)((cmd[25] & 0xffff0000) | ((cmd[29] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdx, "%4.4f", (float)(INT32)((cmd[26] & 0xffff0000) | ((cmd[30] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdx, "%4.4f", (float)(INT32)(((cmd[26] & 0xffff) << 16) | (cmd[30] & 0xffff)) / 65536.0f); + sprintf(dwdx, "%4.4f", (float)(INT32)((cmd[27] & 0xffff0000) | ((cmd[31] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsde, "%4.4f", (float)(INT32)((cmd[32] & 0xffff0000) | ((cmd[36] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtde, "%4.4f", (float)(INT32)(((cmd[32] & 0xffff) << 16) | (cmd[36] & 0xffff)) / 65536.0f); + sprintf(dwde, "%4.4f", (float)(INT32)((cmd[33] & 0xffff0000) | ((cmd[37] >> 16) & 0xffff)) / 65536.0f); + sprintf(dsdy, "%4.4f", (float)(INT32)((cmd[34] & 0xffff0000) | ((cmd[38] >> 16) & 0xffff)) / 65536.0f); + sprintf(dtdy, "%4.4f", (float)(INT32)(((cmd[34] & 0xffff) << 16) | (cmd[38] & 0xffff)) / 65536.0f); + sprintf(dwdy, "%4.4f", (float)(INT32)((cmd[35] & 0xffff0000) | ((cmd[39] >> 16) & 0xffff)) / 65536.0f); + + + buffer+=sprintf(buffer, "Tri_TexShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " R: %s, G: %s, B: %s, A: %s\n", rt, gt, bt, at); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDX: %s, DGDX: %s, DBDX: %s, DADX: %s\n", drdx, dgdx, dbdx, dadx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDE: %s, DGDE: %s, DBDE: %s, DADE: %s\n", drde, dgde, dbde, dade); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DRDY: %s, DGDY: %s, DBDY: %s, DADY: %s\n", drdy, dgdy, dbdy, dady); + + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " S: %s, T: %s, W: %s\n", s, t, w); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDX: %s, DTDX: %s, DWDX: %s\n", dsdx, dtdx, dwdx); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDE: %s, DTDE: %s, DWDE: %s\n", dsde, dtde, dwde); + buffer+=sprintf(buffer, " "); + buffer+=sprintf(buffer, " DSDY: %s, DTDY: %s, DWDY: %s\n", dsdy, dtdy, dwdy); + break; + } + case 0x24: + case 0x25: + { + if (length < 16) + { + sprintf(buffer, "ERROR: Texture_Rectangle length = %d\n", length); + return; + } + cmd[2] = m_cmd_data[m_cmd_cur+2]; + cmd[3] = m_cmd_data[m_cmd_cur+3]; + sprintf(s, "%4.4f", (float)(INT16)((cmd[2] >> 16) & 0xffff) / 32.0f); + sprintf(t, "%4.4f", (float)(INT16)((cmd[2] >> 0) & 0xffff) / 32.0f); + sprintf(dsdx, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f); + sprintf(dtdy, "%4.4f", (float)(INT16)((cmd[3] >> 16) & 0xffff) / 1024.0f); + + if (command == 0x24) + sprintf(buffer, "Texture_Rectangle %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy); + else + sprintf(buffer, "Texture_Rectangle_Flip %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy); + + break; + } + case 0x26: sprintf(buffer, "Sync_Load"); break; + case 0x27: sprintf(buffer, "Sync_Pipe"); break; + case 0x28: sprintf(buffer, "Sync_Tile"); break; + case 0x29: sprintf(buffer, "Sync_Full"); break; + case 0x2d: sprintf(buffer, "Set_Scissor %s, %s, %s, %s", sl, tl, sh, th); break; + case 0x2e: sprintf(buffer, "Set_Prim_Depth %04X, %04X", (cmd[1] >> 16) & 0xffff, cmd[1] & 0xffff); break; + case 0x2f: sprintf(buffer, "Set_Other_Modes %08X %08X", cmd[0], cmd[1]); break; + case 0x30: sprintf(buffer, "Load_TLUT %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break; + case 0x32: sprintf(buffer, "Set_Tile_Size %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break; + case 0x33: sprintf(buffer, "Load_Block %d, %03X, %03X, %03X, %03X", tile, (cmd[0] >> 12) & 0xfff, cmd[0] & 0xfff, (cmd[1] >> 12) & 0xfff, cmd[1] & 0xfff); break; + case 0x34: sprintf(buffer, "Load_Tile %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break; + case 0x35: sprintf(buffer, "Set_Tile %d, %s, %s, %d, %04X", tile, format, size, ((cmd[0] >> 9) & 0x1ff) * 8, (cmd[0] & 0x1ff) * 8); break; + case 0x36: sprintf(buffer, "Fill_Rectangle %s, %s, %s, %s", sh, th, sl, tl); break; + case 0x37: sprintf(buffer, "Set_Fill_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; + case 0x38: sprintf(buffer, "Set_Fog_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; + case 0x39: sprintf(buffer, "Set_Blend_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; + case 0x3a: sprintf(buffer, "Set_Prim_Color %d, %d, R: %d, G: %d, B: %d, A: %d", (cmd[0] >> 8) & 0x1f, cmd[0] & 0xff, r, g, b, a); break; + case 0x3b: sprintf(buffer, "Set_Env_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break; + case 0x3c: sprintf(buffer, "Set_Combine %08X %08X", cmd[0], cmd[1]); break; + case 0x3d: sprintf(buffer, "Set_Texture_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break; + case 0x3e: sprintf(buffer, "Set_Mask_Image %08X", cmd[1]); break; + case 0x3f: sprintf(buffer, "Set_Color_Image %s, %s, %d, %08X", format, size, (cmd[0] & 0x1ff)+1, cmd[1]); break; + default: sprintf(buffer, "??? (%08X %08X)", cmd[0], cmd[1]); break; + } +} + +/*****************************************************************************/ + +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); +} + +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; + } +} + +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) +{ + INT32 purgestart = 0xfff; + INT32 purgeend = 0; + bool writablescanline = !(scanline & ~0x3ff); + INT32 scanlinespx = scanline << 2; + + if (!writablescanline) return; + + for(int i = 0; i < 4; i++) + { + if (minorxint[i] < purgestart) + { + purgestart = minorxint[i]; + } + if (majorxint[i] > purgeend) + { + purgeend = majorxint[i]; + } + } + + 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); + + for(int i = 0; i < 4; i++) + { + INT32 minorcur = minorx[i]; + INT32 majorcur = majorx[i]; + INT32 minorcurint = minorxint[i]; + INT32 majorcurint = majorxint[i]; + length = majorcurint - minorcurint; + + 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 (minorcurint != majorcurint) + { + if (!(minorcurint & ~0x3ff)) + { + userdata->m_cvg[minorcurint] |= (leftcvghex(minorcur, fmask) << maskshift); + } + if (!(majorcurint & ~0x3ff)) + { + userdata->m_cvg[majorcurint] |= (rightcvghex(majorcur, fmask) << maskshift); + } + } + else + { + if (!(majorcurint & ~0x3ff)) + { + INT32 samecvg = leftcvghex(minorcur, fmask) & rightcvghex(majorcur, fmask); + userdata->m_cvg[majorcurint] |= (samecvg << maskshift); + } + } + for (; fleft <= fright; fleft++) + { + userdata->m_cvg[fleft] |= 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) +{ + INT32 purgestart = 0xfff; + INT32 purgeend = 0; + bool writablescanline = !(scanline & ~0x3ff); + INT32 scanlinespx = scanline << 2; + + if(!writablescanline) return; + + for(int i = 0; i < 4; i++) + { + if (majorxint[i] < purgestart) + { + purgestart = majorxint[i]; + } + if (minorxint[i] > purgeend) + { + purgeend = minorxint[i]; + } + } + + purgestart = CLIP(purgestart, 0, 1023); + purgeend = CLIP(purgeend, 0, 1023); + + int 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); + + for(int i = 0; i < 4; i++) + { + INT32 minorcur = minorx[i]; + INT32 majorcur = majorx[i]; + INT32 minorcurint = minorxint[i]; + INT32 majorcurint = majorxint[i]; + length = minorcurint - majorcurint; + + 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 (minorcurint != majorcurint) + { + if (!(minorcurint & ~0x3ff)) + { + userdata->m_cvg[minorcurint] |= (rightcvghex(minorcur, fmask) << maskshift); + } + if (!(majorcurint & ~0x3ff)) + { + userdata->m_cvg[majorcurint] |= (leftcvghex(majorcur, fmask) << maskshift); + } + } + else + { + if (!(majorcurint & ~0x3ff)) + { + INT32 samecvg = rightcvghex(minorcur, fmask) & leftcvghex(majorcur, fmask); + userdata->m_cvg[majorcurint] |= (samecvg << maskshift); + } + } + for (; fleft <= fright; fleft++) + { + userdata->m_cvg[fleft] |= fmaskshifted; + } + } + } +} + +void n64_rdp::DrawTriangle(bool shade, bool texture, bool zbuffer, bool rect) +{ + UINT32 *cmd_data = rect ? m_temp_rect_data : m_cmd_data; + UINT32 fifo_index = rect ? 0 : m_cmd_cur; + UINT32 w1 = cmd_data[fifo_index + 0]; + UINT32 w2 = cmd_data[fifo_index + 1]; + + int flip = (w1 & 0x00800000) ? 1 : 0; + MiscState.MaxLevel = ((w1 >> 19) & 7); + int tilenum = (w1 >> 16) & 0x7; + + int dsdiff = 0, dtdiff = 0, dwdiff = 0, drdiff = 0, dgdiff = 0, dbdiff = 0, dadiff = 0, dzdiff = 0; + int dsdeh = 0, dtdeh = 0, dwdeh = 0, drdeh = 0, dgdeh = 0, dbdeh = 0, dadeh = 0, dzdeh = 0; + int dsdxh = 0, dtdxh = 0, dwdxh = 0, drdxh = 0, dgdxh = 0, dbdxh = 0, dadxh = 0, dzdxh = 0; + int 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; + + int shade_base = fifo_index + 8; + int texture_base = fifo_index + 8; + int zbuffer_base = fifo_index + 8; + if(shade) + { + texture_base += 16; + zbuffer_base += 16; + } + if(texture) + { + zbuffer_base += 16; + } + + UINT32 w3 = cmd_data[fifo_index + 2]; + UINT32 w4 = cmd_data[fifo_index + 3]; + UINT32 w5 = cmd_data[fifo_index + 4]; + UINT32 w6 = cmd_data[fifo_index + 5]; + UINT32 w7 = cmd_data[fifo_index + 6]; + UINT32 w8 = cmd_data[fifo_index + 7]; + + 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); + // Inverse slopes in 16.16 format + INT32 dxldy = (INT32)(w4); + INT32 dxhdy = (INT32)(w6); + INT32 dxmdy = (INT32)(w8); + + if (yl & 0x2000) yl |= 0xffffc000; + if (ym & 0x2000) ym |= 0xffffc000; + if (yh & 0x2000) yh |= 0xffffc000; + + if (xl & 0x20000000) xl |= 0xc0000000; + if (xm & 0x20000000) xm |= 0xc0000000; + if (xh & 0x20000000) xh |= 0xc0000000; + + int r = (cmd_data[shade_base+0 ] & 0xffff0000) | ((cmd_data[shade_base+4 ] >> 16) & 0x0000ffff); + int g = ((cmd_data[shade_base+0 ] << 16) & 0xffff0000) | (cmd_data[shade_base+4 ] & 0x0000ffff); + int b = (cmd_data[shade_base+1 ] & 0xffff0000) | ((cmd_data[shade_base+5 ] >> 16) & 0x0000ffff); + int a = ((cmd_data[shade_base+1 ] << 16) & 0xffff0000) | (cmd_data[shade_base+5 ] & 0x0000ffff); + int drdx = (cmd_data[shade_base+2 ] & 0xffff0000) | ((cmd_data[shade_base+6 ] >> 16) & 0x0000ffff); + int dgdx = ((cmd_data[shade_base+2 ] << 16) & 0xffff0000) | (cmd_data[shade_base+6 ] & 0x0000ffff); + int dbdx = (cmd_data[shade_base+3 ] & 0xffff0000) | ((cmd_data[shade_base+7 ] >> 16) & 0x0000ffff); + int dadx = ((cmd_data[shade_base+3 ] << 16) & 0xffff0000) | (cmd_data[shade_base+7 ] & 0x0000ffff); + int drde = (cmd_data[shade_base+8 ] & 0xffff0000) | ((cmd_data[shade_base+12] >> 16) & 0x0000ffff); + int dgde = ((cmd_data[shade_base+8 ] << 16) & 0xffff0000) | (cmd_data[shade_base+12] & 0x0000ffff); + int dbde = (cmd_data[shade_base+9 ] & 0xffff0000) | ((cmd_data[shade_base+13] >> 16) & 0x0000ffff); + int dade = ((cmd_data[shade_base+9 ] << 16) & 0xffff0000) | (cmd_data[shade_base+13] & 0x0000ffff); + int drdy = (cmd_data[shade_base+10] & 0xffff0000) | ((cmd_data[shade_base+14] >> 16) & 0x0000ffff); + int dgdy = ((cmd_data[shade_base+10] << 16) & 0xffff0000) | (cmd_data[shade_base+14] & 0x0000ffff); + int dbdy = (cmd_data[shade_base+11] & 0xffff0000) | ((cmd_data[shade_base+15] >> 16) & 0x0000ffff); + int dady = ((cmd_data[shade_base+11] << 16) & 0xffff0000) | (cmd_data[shade_base+15] & 0x0000ffff); + int s = (cmd_data[texture_base+0 ] & 0xffff0000) | ((cmd_data[texture_base+4 ] >> 16) & 0x0000ffff); + int t = ((cmd_data[texture_base+0 ] << 16) & 0xffff0000) | (cmd_data[texture_base+4 ] & 0x0000ffff); + int w = (cmd_data[texture_base+1 ] & 0xffff0000) | ((cmd_data[texture_base+5 ] >> 16) & 0x0000ffff); + int dsdx = (cmd_data[texture_base+2 ] & 0xffff0000) | ((cmd_data[texture_base+6 ] >> 16) & 0x0000ffff); + int dtdx = ((cmd_data[texture_base+2 ] << 16) & 0xffff0000) | (cmd_data[texture_base+6 ] & 0x0000ffff); + int dwdx = (cmd_data[texture_base+3 ] & 0xffff0000) | ((cmd_data[texture_base+7 ] >> 16) & 0x0000ffff); + int dsde = (cmd_data[texture_base+8 ] & 0xffff0000) | ((cmd_data[texture_base+12] >> 16) & 0x0000ffff); + int dtde = ((cmd_data[texture_base+8 ] << 16) & 0xffff0000) | (cmd_data[texture_base+12] & 0x0000ffff); + int dwde = (cmd_data[texture_base+9 ] & 0xffff0000) | ((cmd_data[texture_base+13] >> 16) & 0x0000ffff); + int dsdy = (cmd_data[texture_base+10] & 0xffff0000) | ((cmd_data[texture_base+14] >> 16) & 0x0000ffff); + int dtdy = ((cmd_data[texture_base+10] << 16) & 0xffff0000) | (cmd_data[texture_base+14] & 0x0000ffff); + int dwdy = (cmd_data[texture_base+11] & 0xffff0000) | ((cmd_data[texture_base+15] >> 16) & 0x0000ffff); + int z = cmd_data[zbuffer_base+0]; + int dzdx = cmd_data[zbuffer_base+1]; + int dzde = cmd_data[zbuffer_base+2]; + int dzdy = cmd_data[zbuffer_base+3]; + + int dzdy_dz = (dzdy >> 16) & 0xffff; + int dzdx_dz = (dzdx >> 16) & 0xffff; + + extent_t Spans[2048]; + + SpanBase.m_span_drdy = drdy; + SpanBase.m_span_dgdy = dgdy; + SpanBase.m_span_dbdy = dbdy; + SpanBase.m_span_dady = dady; + SpanBase.m_span_dzdy = OtherModes.z_source_sel ? 0 : dzdy; + + UINT32 temp_dzpix = ((dzdy_dz & 0x8000) ? ((~dzdy_dz) & 0x7fff) : dzdy_dz) + ((dzdx_dz & 0x8000) ? ((~dzdx_dz) & 0x7fff) : dzdx_dz); + SpanBase.m_span_dr = drdx & ~0x1f; + SpanBase.m_span_dg = dgdx & ~0x1f; + SpanBase.m_span_db = dbdx & ~0x1f; + SpanBase.m_span_da = dadx & ~0x1f; + SpanBase.m_span_ds = dsdx; + SpanBase.m_span_dt = dtdx; + SpanBase.m_span_dw = dwdx; + SpanBase.m_span_dz = OtherModes.z_source_sel ? 0 : dzdx; + SpanBase.m_span_dymax = 0; + SpanBase.m_span_dzpix = NormalizeDZPix(temp_dzpix & 0xffff) & 0xffff; + + int xleft_inc = (dxmdy >> 2) & ~1; + int xright_inc = (dxhdy >> 2) & ~1; + + int xright = xh & ~1; + int xleft = xm & ~1; + + int sign_dxhdy = (dxhdy & 0x80000000) ? 1 : 0; + int 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); + } + 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; + + INT32 ycur = yh & ~3; + INT32 ylfar = yl | 3; + INT32 ldflag = (sign_dxhdy ^ flip) ? 0 : 3; + INT32 majorx[4]; + INT32 minorx[4]; + INT32 majorxint[4]; + INT32 minorxint[4]; + bool valid_y = true; + + int xfrac = ((xright >> 8) & 0xff); + + int clipy1 = Scissor.m_yh; + int clipy2 = Scissor.m_yl; + + // Trivial reject + if((ycur >> 2) >= clipy2 && (ylfar >> 2) >= clipy2) + { + return; + } + if((ycur >> 2) < clipy1 && (ylfar >> 2) < clipy1) + { + return; + } + + bool new_object = true; + rdp_poly_state *object = NULL; + bool valid = false; + + if(flip) + { + for (int k = ycur; k <= ylfar; k++) + { + if (k == ym) + { + xleft = xl & ~1; + xleft_inc = (dxldy >> 2) & ~1; + } + + int xstart = xleft >> 16; // 319 + int xend = xright >> 16; // 0 + int j = k >> 2; + int spanidx = (k - ycur) >> 2; + int spix = k & 3; + valid_y = !(k < yh || k >= yl); + + if (spanidx >= 0 && spanidx < 2048) + { + majorxint[spix] = xend; // 0 + minorxint[spix] = xstart; // 319 + majorx[spix] = xright; // 0x00000000 + minorx[spix] = xleft; // 0x013f0000 + + if (spix == 0) + { + maxxmx = 0; + minxhx = 0xfff; + } + + if (valid_y) + { + maxxmx = (xstart > maxxmx) ? xstart : maxxmx; + minxhx = (xend < minxhx) ? xend : minxhx; + } + + 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*)AuxBuf + AuxBufPtr); + AuxBufPtr += sizeof(rdp_span_aux); + + if(AuxBufPtr >= EXTENT_AUX_COUNT) + { + fatalerror("n64_rdp::DrawTriangle: span aux buffer overflow\n"); + } + + rdp_span_aux *userdata = (rdp_span_aux*)Spans[spanidx].userdata; + valid = true; + + userdata->m_tmem = object->m_tmem; + + userdata->BlendColor = BlendColor; + userdata->PrimColor = PrimColor; + userdata->EnvColor = EnvColor; + userdata->FogColor = FogColor; + userdata->KeyScale = KeyScale; + userdata->LODFraction = LODFraction; + userdata->PrimLODFraction = PrimLODFraction; + + userdata->ColorInputs.combiner_rgbsub_a_r[0] = userdata->ColorInputs.combiner_rgbsub_a_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbsub_a_g[0] = userdata->ColorInputs.combiner_rgbsub_a_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbsub_a_b[0] = userdata->ColorInputs.combiner_rgbsub_a_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_rgbsub_b_r[0] = userdata->ColorInputs.combiner_rgbsub_b_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbsub_b_g[0] = userdata->ColorInputs.combiner_rgbsub_b_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbsub_b_b[0] = userdata->ColorInputs.combiner_rgbsub_b_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_rgbmul_r[0] = userdata->ColorInputs.combiner_rgbmul_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbmul_g[0] = userdata->ColorInputs.combiner_rgbmul_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbmul_b[0] = userdata->ColorInputs.combiner_rgbmul_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_rgbadd_r[0] = userdata->ColorInputs.combiner_rgbadd_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbadd_g[0] = userdata->ColorInputs.combiner_rgbadd_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbadd_b[0] = userdata->ColorInputs.combiner_rgbadd_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_alphasub_a[0] = userdata->ColorInputs.combiner_alphasub_a[1] = &OneColor.i.a; + userdata->ColorInputs.combiner_alphasub_b[0] = userdata->ColorInputs.combiner_alphasub_b[1] = &OneColor.i.a; + userdata->ColorInputs.combiner_alphamul[0] = userdata->ColorInputs.combiner_alphamul[1] = &OneColor.i.a; + userdata->ColorInputs.combiner_alphaadd[0] = userdata->ColorInputs.combiner_alphaadd[1] = &OneColor.i.a; + + userdata->ColorInputs.blender1a_r[0] = userdata->ColorInputs.blender1a_r[1] = &userdata->PixelColor.i.r; + userdata->ColorInputs.blender1a_g[0] = userdata->ColorInputs.blender1a_g[1] = &userdata->PixelColor.i.g; + userdata->ColorInputs.blender1a_b[0] = userdata->ColorInputs.blender1a_b[1] = &userdata->PixelColor.i.b; + userdata->ColorInputs.blender1b_a[0] = userdata->ColorInputs.blender1b_a[1] = &userdata->PixelColor.i.a; + userdata->ColorInputs.blender2a_r[0] = userdata->ColorInputs.blender2a_r[1] = &userdata->PixelColor.i.r; + userdata->ColorInputs.blender2a_g[0] = userdata->ColorInputs.blender2a_g[1] = &userdata->PixelColor.i.g; + userdata->ColorInputs.blender2a_b[0] = userdata->ColorInputs.blender2a_b[1] = &userdata->PixelColor.i.b; + userdata->ColorInputs.blender2b_a[0] = userdata->ColorInputs.blender2b_a[1] = &userdata->PixelColor.i.a; + + // Setup blender data for this scanline + SetBlenderInput(0, 0, &userdata->ColorInputs.blender1a_r[0], + &userdata->ColorInputs.blender1a_g[0], + &userdata->ColorInputs.blender1a_b[0], + &userdata->ColorInputs.blender1b_a[0], OtherModes.blend_m1a_0, OtherModes.blend_m1b_0, userdata); + SetBlenderInput(0, 1, &userdata->ColorInputs.blender2a_r[0], + &userdata->ColorInputs.blender2a_g[0], + &userdata->ColorInputs.blender2a_b[0], + &userdata->ColorInputs.blender2b_a[0], OtherModes.blend_m2a_0, OtherModes.blend_m2b_0, userdata); + SetBlenderInput(1, 0, &userdata->ColorInputs.blender1a_r[1], + &userdata->ColorInputs.blender1a_g[1], + &userdata->ColorInputs.blender1a_b[1], + &userdata->ColorInputs.blender1b_a[1], OtherModes.blend_m1a_1, OtherModes.blend_m1b_1, userdata); + SetBlenderInput(1, 1, &userdata->ColorInputs.blender2a_r[1], + &userdata->ColorInputs.blender2a_g[1], + &userdata->ColorInputs.blender2a_b[1], + &userdata->ColorInputs.blender2b_a[1], OtherModes.blend_m2a_1, OtherModes.blend_m2b_1, userdata); + + // Setup color combiner data for this scanline + SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[0], &userdata->ColorInputs.combiner_rgbsub_a_g[0], &userdata->ColorInputs.combiner_rgbsub_a_b[0], m_combine.sub_a_rgb0, userdata); + SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[0], &userdata->ColorInputs.combiner_rgbsub_b_g[0], &userdata->ColorInputs.combiner_rgbsub_b_b[0], m_combine.sub_b_rgb0, userdata); + SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[0], &userdata->ColorInputs.combiner_rgbmul_g[0], &userdata->ColorInputs.combiner_rgbmul_b[0], m_combine.mul_rgb0, userdata); + SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[0], &userdata->ColorInputs.combiner_rgbadd_g[0], &userdata->ColorInputs.combiner_rgbadd_b[0], m_combine.add_rgb0, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[0], m_combine.sub_a_a0, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[0], m_combine.sub_b_a0, userdata); + SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[0], m_combine.mul_a0, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[0], m_combine.add_a0, userdata); + + SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[1], &userdata->ColorInputs.combiner_rgbsub_a_g[1], &userdata->ColorInputs.combiner_rgbsub_a_b[1], m_combine.sub_a_rgb1, userdata); + SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[1], &userdata->ColorInputs.combiner_rgbsub_b_g[1], &userdata->ColorInputs.combiner_rgbsub_b_b[1], m_combine.sub_b_rgb1, userdata); + SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[1], &userdata->ColorInputs.combiner_rgbmul_g[1], &userdata->ColorInputs.combiner_rgbmul_b[1], m_combine.mul_rgb1, userdata); + SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[1], &userdata->ColorInputs.combiner_rgbadd_g[1], &userdata->ColorInputs.combiner_rgbadd_b[1], m_combine.add_rgb1, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[1], m_combine.sub_a_a1, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[1], m_combine.sub_b_a1, userdata); + SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[1], m_combine.mul_a1, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[1], m_combine.add_a1, userdata); + } + + if (spix == 3) + { + Spans[spanidx].startx = maxxmx; + Spans[spanidx].stopx = minxhx; + compute_cvg_flip(Spans, majorx, minorx, majorxint, minorxint, j, yh, yl, ycur >> 2); + } + + if (spix == ldflag) + { + ((rdp_span_aux*)Spans[spanidx].userdata)->m_unscissored_rx = xend; + xfrac = ((xright >> 8) & 0xff); + Spans[spanidx].param[SPAN_R].start = ((r >> 9) << 9) + drdiff - (xfrac * drdxh); + Spans[spanidx].param[SPAN_G].start = ((g >> 9) << 9) + dgdiff - (xfrac * dgdxh); + Spans[spanidx].param[SPAN_B].start = ((b >> 9) << 9) + dbdiff - (xfrac * dbdxh); + Spans[spanidx].param[SPAN_A].start = ((a >> 9) << 9) + dadiff - (xfrac * dadxh); + Spans[spanidx].param[SPAN_S].start = (((s >> 9) << 9) + dsdiff - (xfrac * dsdxh)) & ~0x1f; + Spans[spanidx].param[SPAN_T].start = (((t >> 9) << 9) + dtdiff - (xfrac * dtdxh)) & ~0x1f; + Spans[spanidx].param[SPAN_W].start = (((w >> 9) << 9) + dwdiff - (xfrac * dwdxh)) & ~0x1f; + Spans[spanidx].param[SPAN_Z].start = ((z >> 9) << 9) + dzdiff - (xfrac * dzdxh); + } + } + + 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 (int k = ycur; k <= ylfar; k++) + { + if (k == ym) + { + xleft = xl & ~1; + xleft_inc = (dxldy >> 2) & ~1; + } + + int xstart = xleft >> 16; + int xend = xright >> 16; + int j = k >> 2; + int spanidx = j - (ycur >> 2); + int spix = k & 3; + valid_y = !(k < yh || k >= yl); + + if (k >= 0 && k < 0x1000) + { + majorxint[spix] = xend; + minorxint[spix] = xstart; + majorx[spix] = xright; + minorx[spix] = xleft; + + if (spix == 0) + { + maxxhx = 0; + minxmx = 0xfff; + } + + if (valid_y) + { + minxmx = (xstart < minxmx) ? xstart : minxmx; + maxxhx = (xend > maxxhx) ? xend : maxxhx; + } + + 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*)AuxBuf + AuxBufPtr); + valid = true; + AuxBufPtr += sizeof(rdp_span_aux); + + if(AuxBufPtr >= EXTENT_AUX_COUNT) + { + fatalerror("n64_rdp::DrawTriangle: span aux buffer overflow\n"); + } + + rdp_span_aux *userdata = (rdp_span_aux*)Spans[spanidx].userdata; + userdata->m_tmem = object->m_tmem; + + userdata->BlendColor = BlendColor; + userdata->PrimColor = PrimColor; + userdata->EnvColor = EnvColor; + userdata->FogColor = FogColor; + userdata->KeyScale = KeyScale; + userdata->LODFraction = LODFraction; + userdata->PrimLODFraction = PrimLODFraction; + + userdata->ColorInputs.combiner_rgbsub_a_r[0] = userdata->ColorInputs.combiner_rgbsub_a_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbsub_a_g[0] = userdata->ColorInputs.combiner_rgbsub_a_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbsub_a_b[0] = userdata->ColorInputs.combiner_rgbsub_a_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_rgbsub_b_r[0] = userdata->ColorInputs.combiner_rgbsub_b_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbsub_b_g[0] = userdata->ColorInputs.combiner_rgbsub_b_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbsub_b_b[0] = userdata->ColorInputs.combiner_rgbsub_b_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_rgbmul_r[0] = userdata->ColorInputs.combiner_rgbmul_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbmul_g[0] = userdata->ColorInputs.combiner_rgbmul_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbmul_b[0] = userdata->ColorInputs.combiner_rgbmul_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_rgbadd_r[0] = userdata->ColorInputs.combiner_rgbadd_r[1] = &OneColor.i.r; + userdata->ColorInputs.combiner_rgbadd_g[0] = userdata->ColorInputs.combiner_rgbadd_g[1] = &OneColor.i.g; + userdata->ColorInputs.combiner_rgbadd_b[0] = userdata->ColorInputs.combiner_rgbadd_b[1] = &OneColor.i.b; + userdata->ColorInputs.combiner_alphasub_a[0] = userdata->ColorInputs.combiner_alphasub_a[1] = &OneColor.i.a; + userdata->ColorInputs.combiner_alphasub_b[0] = userdata->ColorInputs.combiner_alphasub_b[1] = &OneColor.i.a; + userdata->ColorInputs.combiner_alphamul[0] = userdata->ColorInputs.combiner_alphamul[1] = &OneColor.i.a; + userdata->ColorInputs.combiner_alphaadd[0] = userdata->ColorInputs.combiner_alphaadd[1] = &OneColor.i.a; + + userdata->ColorInputs.blender1a_r[0] = userdata->ColorInputs.blender1a_r[1] = &userdata->PixelColor.i.r; + userdata->ColorInputs.blender1a_g[0] = userdata->ColorInputs.blender1a_g[1] = &userdata->PixelColor.i.g; + userdata->ColorInputs.blender1a_b[0] = userdata->ColorInputs.blender1a_b[1] = &userdata->PixelColor.i.b; + userdata->ColorInputs.blender1b_a[0] = userdata->ColorInputs.blender1b_a[1] = &userdata->PixelColor.i.a; + userdata->ColorInputs.blender2a_r[0] = userdata->ColorInputs.blender2a_r[1] = &userdata->PixelColor.i.r; + userdata->ColorInputs.blender2a_g[0] = userdata->ColorInputs.blender2a_g[1] = &userdata->PixelColor.i.g; + userdata->ColorInputs.blender2a_b[0] = userdata->ColorInputs.blender2a_b[1] = &userdata->PixelColor.i.b; + userdata->ColorInputs.blender2b_a[0] = userdata->ColorInputs.blender2b_a[1] = &userdata->PixelColor.i.a; + + // Setup blender data for this scanline + SetBlenderInput(0, 0, &userdata->ColorInputs.blender1a_r[0], + &userdata->ColorInputs.blender1a_g[0], + &userdata->ColorInputs.blender1a_b[0], + &userdata->ColorInputs.blender1b_a[0], OtherModes.blend_m1a_0, OtherModes.blend_m1b_0, userdata); + SetBlenderInput(0, 1, &userdata->ColorInputs.blender2a_r[0], + &userdata->ColorInputs.blender2a_g[0], + &userdata->ColorInputs.blender2a_b[0], + &userdata->ColorInputs.blender2b_a[0], OtherModes.blend_m2a_0, OtherModes.blend_m2b_0, userdata); + SetBlenderInput(1, 0, &userdata->ColorInputs.blender1a_r[1], + &userdata->ColorInputs.blender1a_g[1], + &userdata->ColorInputs.blender1a_b[1], + &userdata->ColorInputs.blender1b_a[1], OtherModes.blend_m1a_1, OtherModes.blend_m1b_1, userdata); + SetBlenderInput(1, 1, &userdata->ColorInputs.blender2a_r[1], + &userdata->ColorInputs.blender2a_g[1], + &userdata->ColorInputs.blender2a_b[1], + &userdata->ColorInputs.blender2b_a[1], OtherModes.blend_m2a_1, OtherModes.blend_m2b_1, userdata); + + // Setup color combiner data for this scanline + SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[0], &userdata->ColorInputs.combiner_rgbsub_a_g[0], &userdata->ColorInputs.combiner_rgbsub_a_b[0], m_combine.sub_a_rgb0, userdata); + SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[0], &userdata->ColorInputs.combiner_rgbsub_b_g[0], &userdata->ColorInputs.combiner_rgbsub_b_b[0], m_combine.sub_b_rgb0, userdata); + SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[0], &userdata->ColorInputs.combiner_rgbmul_g[0], &userdata->ColorInputs.combiner_rgbmul_b[0], m_combine.mul_rgb0, userdata); + SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[0], &userdata->ColorInputs.combiner_rgbadd_g[0], &userdata->ColorInputs.combiner_rgbadd_b[0], m_combine.add_rgb0, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[0], m_combine.sub_a_a0, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[0], m_combine.sub_b_a0, userdata); + SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[0], m_combine.mul_a0, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[0], m_combine.add_a0, userdata); + + SetSubAInputRGB(&userdata->ColorInputs.combiner_rgbsub_a_r[1], &userdata->ColorInputs.combiner_rgbsub_a_g[1], &userdata->ColorInputs.combiner_rgbsub_a_b[1], m_combine.sub_a_rgb1, userdata); + SetSubBInputRGB(&userdata->ColorInputs.combiner_rgbsub_b_r[1], &userdata->ColorInputs.combiner_rgbsub_b_g[1], &userdata->ColorInputs.combiner_rgbsub_b_b[1], m_combine.sub_b_rgb1, userdata); + SetMulInputRGB(&userdata->ColorInputs.combiner_rgbmul_r[1], &userdata->ColorInputs.combiner_rgbmul_g[1], &userdata->ColorInputs.combiner_rgbmul_b[1], m_combine.mul_rgb1, userdata); + SetAddInputRGB(&userdata->ColorInputs.combiner_rgbadd_r[1], &userdata->ColorInputs.combiner_rgbadd_g[1], &userdata->ColorInputs.combiner_rgbadd_b[1], m_combine.add_rgb1, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_a[1], m_combine.sub_a_a1, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphasub_b[1], m_combine.sub_b_a1, userdata); + SetMulInputAlpha(&userdata->ColorInputs.combiner_alphamul[1], m_combine.mul_a1, userdata); + SetSubInputAlpha(&userdata->ColorInputs.combiner_alphaadd[1], m_combine.add_a1, userdata); + } + + if (spix == 3) + { + Spans[spanidx].startx = minxmx; + Spans[spanidx].stopx = maxxhx; + compute_cvg_noflip(Spans, majorx, minorx, majorxint, minorxint, j, yh, yl, ycur >> 2); + } + + if (spix == ldflag) + { + ((rdp_span_aux*)Spans[spanidx].userdata)->m_unscissored_rx = xend; + xfrac = ((xright >> 8) & 0xff); + Spans[spanidx].param[SPAN_R].start = ((r >> 9) << 9) + drdiff - (xfrac * drdxh); + Spans[spanidx].param[SPAN_G].start = ((g >> 9) << 9) + dgdiff - (xfrac * dgdxh); + Spans[spanidx].param[SPAN_B].start = ((b >> 9) << 9) + dbdiff - (xfrac * dbdxh); + Spans[spanidx].param[SPAN_A].start = ((a >> 9) << 9) + dadiff - (xfrac * dadxh); + Spans[spanidx].param[SPAN_S].start = (((s >> 9) << 9) + dsdiff - (xfrac * dsdxh)) & ~0x1f; + Spans[spanidx].param[SPAN_T].start = (((t >> 9) << 9) + dtdiff - (xfrac * dtdxh)) & ~0x1f; + Spans[spanidx].param[SPAN_W].start = (((w >> 9) << 9) + dwdiff - (xfrac * dwdxh)) & ~0x1f; + Spans[spanidx].param[SPAN_Z].start = ((z >> 9) << 9) + dzdiff - (xfrac * dzdxh); + } + } + + 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(!new_object && valid) + { + RenderSpans(yh >> 2, yl >> 2, tilenum, flip ? true : false, Spans, rect, object); + } + + //wait("DrawTriangle"); +} + +/*****************************************************************************/ + +//////////////////////// +// FB ACCESSORS +//////////////////////// +void n64_rdp::_Write16Bit_Cvg0_Blend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; + UINT32 hb = fb; + + UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); + UINT32 finalcvg = 0; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX16(fb) & 0xfffe; + CHECK16(fb); + } + + finalcvg = userdata->CurrentPixCvg + userdata->CurrentMemCvg; + if (finalcvg & 8) + { + finalcvg = 7; + } + RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); + HWRITEADDR8(hb, finalcvg & 3); +} + +void n64_rdp::_Write16Bit_Cvg0_NoBlend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; + UINT32 hb = fb; + + UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); + UINT32 finalcvg = 0; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX16(fb) & 0xfffe; + CHECK16(fb); + } + + finalcvg = (userdata->CurrentPixCvg - 1) & 7; + RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); + HWRITEADDR8(hb, finalcvg & 3); +} + +void n64_rdp::_Write16Bit_Cvg1(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; + UINT32 hb = fb; + + UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); + UINT32 finalcvg = 0; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX16(fb) & 0xfffe; + CHECK16(fb); + } + + finalcvg = (userdata->CurrentPixCvg + userdata->CurrentMemCvg) & 7; + RWRITEIDX16(fb, finalcolor | ((finalcvg >> 2) & 1)); + HWRITEADDR8(hb, finalcvg & 3); +} + +void n64_rdp::_Write16Bit_Cvg2(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; + UINT32 hb = fb; + + UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX16(fb) & 0xfffe; + CHECK16(fb); + } + + RWRITEIDX16(fb, finalcolor | 1); + HWRITEADDR8(hb, 3); +} + +void n64_rdp::_Write16Bit_Cvg3(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 1) + curpixel; + UINT32 hb = fb; + + UINT16 finalcolor = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1); + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX16(fb) & 0xfffe; + CHECK16(fb); + } + + RWRITEIDX16(fb, finalcolor | ((userdata->CurrentMemCvg >> 2) & 1)); + HWRITEADDR8(hb, userdata->CurrentMemCvg & 3); +} + +void n64_rdp::_Write32Bit_Cvg0_Blend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; + UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; + UINT32 finalcvg = 0; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX32(fb) & 0xffffff00; + CHECK32(fb); + } + + finalcvg = userdata->CurrentPixCvg + userdata->CurrentMemCvg; + if (finalcvg & 8) + { + finalcvg = 7; + } + RWRITEIDX32(fb, finalcolor | (finalcvg << 5)); +} + +void n64_rdp::_Write32Bit_Cvg0_NoBlend(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; + UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; + UINT32 finalcvg = 0; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX32(fb) & 0xffffff00; + CHECK32(fb); + } + + finalcvg = (userdata->CurrentPixCvg - 1) & 7; + RWRITEIDX32(fb, finalcolor | (finalcvg << 5)); +} + +void n64_rdp::_Write32Bit_Cvg1(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; + UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; + UINT32 finalcvg = 0; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX32(fb) & 0xffffff00; + CHECK32(fb); + } + + finalcvg = (userdata->CurrentPixCvg + userdata->CurrentMemCvg) & 7; + finalcolor |= (finalcvg << 5); + RWRITEIDX32(fb, finalcolor); +} + +void n64_rdp::_Write32Bit_Cvg2(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; + UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX32(fb) & 0xffffff00; + CHECK32(fb); + } + + RWRITEIDX32(fb, finalcolor | 0xE0); +} + +void n64_rdp::_Write32Bit_Cvg3(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 fb = (object.MiscState.FBAddress >> 2) + curpixel; + UINT32 finalcolor = (r << 24) | (g << 16) | (b << 8);//cvg as 3 MSBs of alpha channel; + + if (object.OtherModes.color_on_cvg && !userdata->PreWrap) + { + finalcolor = RREADIDX32(fb) & 0xffffff00; + CHECK32(fb); + } + + RWRITEIDX32(fb, finalcolor | (userdata->CurrentMemCvg << 5)); +} + + +void n64_rdp::_Read16Bit_ImgRead0(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT16 fword = RREADIDX16((object.MiscState.FBAddress >> 1) + curpixel); + CHECK16((object.MiscState.FBAddress >> 1) + curpixel); + userdata->MemoryColor.i.r = GETHICOL(fword); + userdata->MemoryColor.i.g = GETMEDCOL(fword); + userdata->MemoryColor.i.b = GETLOWCOL(fword); + userdata->MemoryColor.i.a = 0xff; + userdata->CurrentMemCvg = 7; +} + +void n64_rdp::_Read16Bit_ImgRead1(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT16 fword = RREADIDX16((object.MiscState.FBAddress >> 1) + curpixel); + CHECK16((object.MiscState.FBAddress >> 1) + curpixel); + UINT8 hbyte = HREADADDR8((object.MiscState.FBAddress >> 1) + curpixel); + userdata->MemoryColor.i.r = GETHICOL(fword); + userdata->MemoryColor.i.g = GETMEDCOL(fword); + userdata->MemoryColor.i.b = GETLOWCOL(fword); + userdata->MemoryColor.i.a = userdata->CurrentMemCvg << 5; + userdata->CurrentMemCvg = ((fword & 1) << 2) | (hbyte & 3); +} + +void n64_rdp::_Read32Bit_ImgRead0(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 mem = RREADIDX32((object.MiscState.FBAddress >> 2) + curpixel); + CHECK32((object.MiscState.FBAddress >> 2) + curpixel); + userdata->MemoryColor.i.r = (mem >> 24) & 0xff; + userdata->MemoryColor.i.g = (mem >> 16) & 0xff; + userdata->MemoryColor.i.b = (mem >> 8) & 0xff; + userdata->MemoryColor.i.a = 0xff; + userdata->CurrentMemCvg = 7; +} + +void n64_rdp::_Read32Bit_ImgRead1(UINT32 curpixel, rdp_span_aux *userdata, const rdp_poly_state &object) +{ + UINT32 mem = RREADIDX32((object.MiscState.FBAddress >> 2) + curpixel); + CHECK32((object.MiscState.FBAddress >> 2) + curpixel); + userdata->MemoryColor.i.r = (mem >> 24) & 0xff; + userdata->MemoryColor.i.g = (mem >> 16) & 0xff; + userdata->MemoryColor.i.b = (mem >> 8) & 0xff; + userdata->MemoryColor.i.a = (mem) & 0xff; + userdata->CurrentMemCvg = (mem >> 5) & 7; +} + +void n64_rdp::_Copy16Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, int CurrentPixCvg, const rdp_poly_state &object) +{ + UINT16 val = ((r >> 3) << 11) | ((g >> 3) << 6) | ((b >> 3) << 1) | ((CurrentPixCvg >> 2) & 1); + RWRITEIDX16((object.MiscState.FBAddress >> 1) + curpixel, val); + HWRITEADDR8((object.MiscState.FBAddress >> 1) + curpixel, CurrentPixCvg & 3); + CHECK16((object.MiscState.FBAddress >> 1) + curpixel); +} + +void n64_rdp::_Copy32Bit(UINT32 curpixel, UINT32 r, UINT32 g, UINT32 b, int CurrentPixCvg, const rdp_poly_state &object) +{ + UINT32 val = (r << 24) | (g << 16) | (b << 8) | (CurrentPixCvg << 5); + RWRITEIDX32((object.MiscState.FBAddress >> 2) + curpixel, val); + CHECK32((object.MiscState.FBAddress >> 2) + curpixel); +} + + +void n64_rdp::_Fill16Bit(UINT32 curpixel, const rdp_poly_state &object) +{ + UINT16 val; + if (curpixel & 1) + { + val = object.FillColor & 0xffff; + } + else + { + val = (object.FillColor >> 16) & 0xffff; + } + RWRITEIDX16((object.MiscState.FBAddress >> 1) + curpixel, val); + CHECK16((object.MiscState.FBAddress >> 1) + curpixel); + HWRITEADDR8((object.MiscState.FBAddress >> 1) + curpixel, ((val & 1) << 1) | (val & 1)); +} + +void n64_rdp::_Fill32Bit(UINT32 curpixel, const rdp_poly_state &object) +{ + UINT32 FillColor = object.FillColor; + RWRITEIDX32((object.MiscState.FBAddress >> 2) + curpixel, FillColor); + CHECK32((object.MiscState.FBAddress >> 2) + curpixel); + HWRITEADDR8((object.MiscState.FBAddress >> 1) + (curpixel << 1), (FillColor & 0x10000) ? 3 : 0); + HWRITEADDR8((object.MiscState.FBAddress >> 1) + (curpixel << 1) + 1, (FillColor & 0x1) ? 3 : 0); +} + +//////////////////////// +// RDP COMMANDS +//////////////////////// +void n64_rdp::Triangle(bool shade, bool texture, bool zbuffer) +{ + DrawTriangle(shade, texture, zbuffer, false); + m_pipe_clean = false; + //wait(); +} + +void n64_rdp::CmdTriangle(UINT32 w1, UINT32 w2) +{ + Triangle(false, false, false); +} + +void n64_rdp::CmdTriangleZ(UINT32 w1, UINT32 w2) +{ + Triangle(false, false, true); +} + +void n64_rdp::CmdTriangleT(UINT32 w1, UINT32 w2) +{ + Triangle(false, true, false); +} + +void n64_rdp::CmdTriangleTZ(UINT32 w1, UINT32 w2) +{ + Triangle(false, true, true); +} + +void n64_rdp::CmdTriangleS(UINT32 w1, UINT32 w2) +{ + Triangle(true, false, false); +} + +void n64_rdp::CmdTriangleSZ(UINT32 w1, UINT32 w2) +{ + Triangle(true, false, true); +} + +void n64_rdp::CmdTriangleST(UINT32 w1, UINT32 w2) +{ + Triangle(true, true, false); +} + +void n64_rdp::CmdTriangleSTZ(UINT32 w1, UINT32 w2) +{ + Triangle(true, true, true); +} + +void n64_rdp::CmdTexRect(UINT32 w1, UINT32 w2) +{ + //if(m_pending_mode_block) { wait("Block on pending mode-change"); m_pending_mode_block = false; } + + UINT32 *data = m_cmd_data + m_cmd_cur; + + UINT32 w3 = data[2]; + UINT32 w4 = data[3]; + + UINT32 tilenum = (w2 >> 24) & 0x7; + UINT32 xl = (w1 >> 12) & 0xfff; + UINT32 yl = (w1 >> 0) & 0xfff; + UINT32 xh = (w2 >> 12) & 0xfff; + UINT32 yh = (w2 >> 0) & 0xfff; + INT32 s = (w3 >> 16) & 0xffff; + INT32 t = (w3 >> 0) & 0xffff; + INT32 dsdx = (w4 >> 16) & 0xffff; + INT32 dtdy = (w4 >> 0) & 0xffff; + + dsdx = SIGN16(dsdx); + dtdy = SIGN16(dtdy); + + if (OtherModes.cycle_type == CYCLE_TYPE_FILL || OtherModes.cycle_type == CYCLE_TYPE_COPY) + { + yl |= 3; + } + + UINT32 xlint = (xl >> 2) & 0x3ff; + UINT32 xhint = (xh >> 2) & 0x3ff; + + UINT32* ewdata = m_temp_rect_data; + ewdata[0] = (0x24 << 24) | ((0x80 | tilenum) << 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, 16 * sizeof(UINT32)); // shade + ewdata[24] = (s << 16) | t; // s, t + ewdata[25] = 0; // w + ewdata[26] = ((dsdx >> 5) << 16); // dsdx, dtdx + ewdata[27] = 0; // dwdx + ewdata[28] = 0; // s frac, t frac + ewdata[29] = 0; // w frac + ewdata[30] = ((dsdx & 0x1f) << 11) << 16; // dsdx frac, dtdx frac + ewdata[31] = 0; // dwdx frac + ewdata[32] = (dtdy >> 5) & 0xffff;//dsde, dtde + ewdata[33] = 0;//dwde + ewdata[34] = (dtdy >> 5) & 0xffff;//dsdy, dtdy + ewdata[35] = 0;//dwdy + ewdata[36] = (dtdy & 0x1f) << 11;//dsde frac, dtde frac + ewdata[37] = 0;//dwde frac + ewdata[38] = (dtdy & 0x1f) << 11;//dsdy frac, dtdy frac + ewdata[39] = 0;//dwdy frac + memset(&ewdata[40], 0, 4 * sizeof(UINT32));//depth + + DrawTriangle(true, true, false, true); +} + +void n64_rdp::CmdTexRectFlip(UINT32 w1, UINT32 w2) +{ + //if(m_pending_mode_block) { wait("Block on pending mode-change"); m_pending_mode_block = false; } + + UINT32 *data = m_cmd_data + m_cmd_cur; + + UINT32 w3 = data[2]; + UINT32 w4 = data[3]; + + UINT32 tilenum = (w2 >> 24) & 0x7; + UINT32 xl = (w1 >> 12) & 0xfff; + UINT32 yl = (w1 >> 0) & 0xfff; + UINT32 xh = (w2 >> 12) & 0xfff; + UINT32 yh = (w2 >> 0) & 0xfff; + INT32 s = (w3 >> 16) & 0xffff; + INT32 t = (w3 >> 0) & 0xffff; + INT32 dsdx = (w4 >> 16) & 0xffff; + INT32 dtdy = (w4 >> 0) & 0xffff; + + dsdx = SIGN16(dsdx); + dtdy = SIGN16(dtdy); + + if (OtherModes.cycle_type == CYCLE_TYPE_FILL || OtherModes.cycle_type == CYCLE_TYPE_COPY) + { + yl |= 3; + } + + UINT32 xlint = (xl >> 2) & 0x3ff; + UINT32 xhint = (xh >> 2) & 0x3ff; + + UINT32* ewdata = m_temp_rect_data; + ewdata[0] = (0x25 << 24) | ((0x80 | tilenum) << 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, 16 * sizeof(UINT32));//shade + ewdata[24] = (s << 16) | t;//s, t + ewdata[25] = 0;//w + ewdata[26] = (dtdy >> 5) & 0xffff;//dsdx, dtdx + ewdata[27] = 0;//dwdx + ewdata[28] = 0;//s frac, t frac + ewdata[29] = 0;//w frac + ewdata[30] = ((dtdy & 0x1f) << 11);//dsdx frac, dtdx frac + ewdata[31] = 0;//dwdx frac + ewdata[32] = (dsdx >> 5) << 16;//dsde, dtde + ewdata[33] = 0;//dwde + ewdata[34] = (dsdx >> 5) << 16;//dsdy, dtdy + ewdata[35] = 0;//dwdy + ewdata[36] = (dsdx & 0x1f) << 27;//dsde frac, dtde frac + ewdata[37] = 0;//dwde frac + ewdata[38] = (dsdx & 0x1f) << 27;//dsdy frac, dtdy frac + ewdata[39] = 0;//dwdy frac + memset(&ewdata[40], 0, 4 * sizeof(UINT32));//depth + + DrawTriangle(true, true, false, true); +} + +void n64_rdp::CmdSyncLoad(UINT32 w1, UINT32 w2) +{ + //wait("SyncLoad"); +} + +void n64_rdp::CmdSyncPipe(UINT32 w1, UINT32 w2) +{ + //wait("SyncPipe"); +} + +void n64_rdp::CmdSyncTile(UINT32 w1, UINT32 w2) +{ + //wait("SyncTile"); +} + +void n64_rdp::CmdSyncFull(UINT32 w1, UINT32 w2) +{ + //wait("SyncFull"); + dp_full_sync(*m_machine); +} + +void n64_rdp::CmdSetKeyGB(UINT32 w1, UINT32 w2) +{ + KeyScale.i.b = w2 & 0xff; + KeyScale.i.g = (w2 >> 16) & 0xff; +} + +void n64_rdp::CmdSetKeyR(UINT32 w1, UINT32 w2) +{ + KeyScale.i.r = w2 & 0xff; +} + +void n64_rdp::CmdSetFillColor32(UINT32 w1, UINT32 w2) +{ + //wait("SetFillColor"); + FillColor = w2; +} + +void n64_rdp::CmdSetConvert(UINT32 w1, UINT32 w2) +{ + if(!m_pipe_clean) { m_pipe_clean = true; wait("SetConvert"); } + INT32 k0 = (w1 >> 13) & 0xff; + INT32 k1 = (w1 >> 4) & 0xff; + INT32 k2 = ((w1 & 7) << 5) | ((w2 >> 27) & 0x1f); + INT32 k3 = (w2 >> 18) & 0xff; + INT32 k4 = (w2 >> 9) & 0xff; + INT32 k5 = w2 & 0xff; + k0 = ((w1 >> 21) & 1) ? (-(0x100 - k0)) : k0; + k1 = ((w1 >> 12) & 1) ? (-(0x100 - k1)) : k1; + k2 = (w1 & 0xf) ? (-(0x100 - k2)) : k2; + k3 = ((w2 >> 26) & 1) ? (-(0x100 - k3)) : k3; + k4 = ((w2 >> 17) & 1) ? (-(0x100 - k4)) : k4; + k5 = ((w2 >> 8) & 1) ? (-(0x100 - k5)) : k5; + SetYUVFactors(k0, k1, k2, k3, k4, k5); +} + +void n64_rdp::CmdSetScissor(UINT32 w1, UINT32 w2) +{ + Scissor.m_xh = ((w1 >> 12) & 0xfff) >> 2; + Scissor.m_yh = ((w1 >> 0) & 0xfff) >> 2; + Scissor.m_xl = ((w2 >> 12) & 0xfff) >> 2; + Scissor.m_yl = ((w2 >> 0) & 0xfff) >> 2; + + // TODO: handle f & o? +} + +void n64_rdp::CmdSetPrimDepth(UINT32 w1, UINT32 w2) +{ + MiscState.PrimitiveZ = (UINT16)(w2 >> 16) & 0x7fff; + MiscState.PrimitiveDZ = (UINT16)(w1); +} + +void n64_rdp::CmdSetOtherModes(UINT32 w1, UINT32 w2) +{ + //wait("SetOtherModes"); + OtherModes.cycle_type = (w1 >> 20) & 0x3; // 01 + OtherModes.persp_tex_en = (w1 & 0x80000) ? 1 : 0; // 1 + OtherModes.detail_tex_en = (w1 & 0x40000) ? 1 : 0; // 0 + OtherModes.sharpen_tex_en = (w1 & 0x20000) ? 1 : 0; // 0 + OtherModes.tex_lod_en = (w1 & 0x10000) ? 1 : 0; // 0 + OtherModes.en_tlut = (w1 & 0x08000) ? 1 : 0; // 0 + OtherModes.tlut_type = (w1 & 0x04000) ? 1 : 0; // 0 + OtherModes.sample_type = (w1 & 0x02000) ? 1 : 0; // 1 + OtherModes.mid_texel = (w1 & 0x01000) ? 1 : 0; // 0 + OtherModes.bi_lerp0 = (w1 & 0x00800) ? 1 : 0; // 1 + OtherModes.bi_lerp1 = (w1 & 0x00400) ? 1 : 0; // 1 + OtherModes.convert_one = (w1 & 0x00200) ? 1 : 0; // 0 + OtherModes.key_en = (w1 & 0x00100) ? 1 : 0; // 0 + OtherModes.rgb_dither_sel = (w1 >> 6) & 0x3; // 00 + OtherModes.alpha_dither_sel = (w1 >> 4) & 0x3; // 01 + OtherModes.blend_m1a_0 = (w2 >> 30) & 0x3; // 11 + OtherModes.blend_m1a_1 = (w2 >> 28) & 0x3; // 00 + OtherModes.blend_m1b_0 = (w2 >> 26) & 0x3; // 10 + OtherModes.blend_m1b_1 = (w2 >> 24) & 0x3; // 00 + OtherModes.blend_m2a_0 = (w2 >> 22) & 0x3; // 00 + OtherModes.blend_m2a_1 = (w2 >> 20) & 0x3; // 01 + OtherModes.blend_m2b_0 = (w2 >> 18) & 0x3; // 00 + OtherModes.blend_m2b_1 = (w2 >> 16) & 0x3; // 01 + OtherModes.force_blend = (w2 >> 14) & 1; // 0 + OtherModes.alpha_cvg_select = (w2 >> 13) & 1; // 1 + OtherModes.cvg_times_alpha = (w2 >> 12) & 1; // 0 + OtherModes.z_mode = (w2 >> 10) & 0x3; // 00 + OtherModes.cvg_dest = (w2 >> 8) & 0x3; // 00 + OtherModes.color_on_cvg = (w2 >> 7) & 1; // 0 + OtherModes.image_read_en = (w2 >> 6) & 1; // 1 + OtherModes.z_update_en = (w2 >> 5) & 1; // 1 + OtherModes.z_compare_en = (w2 >> 4) & 1; // 1 + OtherModes.antialias_en = (w2 >> 3) & 1; // 1 + OtherModes.z_source_sel = (w2 >> 2) & 1; // 0 + OtherModes.dither_alpha_en = (w2 >> 1) & 1; // 0 + OtherModes.alpha_compare_en = (w2) & 1; // 0 +} + +void n64_rdp::CmdLoadTLUT(UINT32 w1, UINT32 w2) +{ + //wait("LoadTLUT"); + N64Tile* tile = m_tiles; + + int tilenum = (w2 >> 24) & 0x7; + int sl = tile[tilenum].sl = ((w1 >> 12) & 0xfff); + int tl = tile[tilenum].tl = w1 & 0xfff; + int sh = tile[tilenum].sh = ((w2 >> 12) & 0xfff); + int th = tile[tilenum].th = w2 & 0xfff; + + if (tl != th) + { + fatalerror("Load tlut: tl=%d, th=%d\n",tl,th); + } + + int count = (sh >> 2) - (sl >> 2) + 1; + count <<= 2; + + switch (MiscState.TISize) + { + case PIXEL_SIZE_16BIT: + { + if (tile[tilenum].tmem < 256) + { + fatalerror("rdp_load_tlut: loading tlut into low half at %d qwords\n",tile[tilenum].tmem); + } + UINT32 srcstart = (MiscState.TIAddress + (tl >> 2) * (MiscState.TIWidth << 1) + (sl >> 1)) >> 1; + UINT16 *dst = GetTMEM16(); + UINT32 dststart = tile[tilenum].tmem << 2; + + for (int i = 0; i < count; i += 4) + { + if (dststart < 2048) + { + dst[dststart] = U_RREADIDX16(srcstart); + dst[dststart + 1] = dst[dststart]; + dst[dststart + 2] = dst[dststart]; + dst[dststart + 3] = dst[dststart]; + dststart += 4; + srcstart += 1; + } + } + break; + } + default: fatalerror("RDP: load_tlut: size = %d\n", MiscState.TISize); + } +} + +void n64_rdp::CmdSetTileSize(UINT32 w1, UINT32 w2) +{ + //wait("SetTileSize"); + + const int tilenum = (w2 >> 24) & 0x7; + + m_tiles[tilenum].sl = (w1 >> 12) & 0xfff; + m_tiles[tilenum].tl = (w1 >> 0) & 0xfff; + m_tiles[tilenum].sh = (w2 >> 12) & 0xfff; + m_tiles[tilenum].th = (w2 >> 0) & 0xfff; +} + +void n64_rdp::CmdLoadBlock(UINT32 w1, UINT32 w2) +{ + //wait("LoadBlock"); + N64Tile* tile = m_tiles; + + int tilenum = (w2 >> 24) & 0x7; + UINT16* tc = GetTMEM16(); + + UINT16 sl, sh, tl; + tile[tilenum].sl = sl = ((w1 >> 12) & 0xfff); + tile[tilenum].tl = tl = ((w1 >> 0) & 0xfff); + tile[tilenum].sh = sh = ((w2 >> 12) & 0xfff); + UINT16 dxt = ((w2 >> 0) & 0xfff); + + if (sh < sl) + { + fatalerror("load_block: sh < sl\n"); + } + + INT32 width = (sh - sl) + 1; + + width = (width << MiscState.TISize) >> 1; + if (width & 7) + { + width = (width & ~7) + 8; + } + width >>= 3; + + UINT32 tb = tile[tilenum].tmem << 2; + + int tiwinwords = MiscState.TIWidth; + UINT32 slinwords = sl; + + tiwinwords = (tiwinwords << MiscState.TISize) >> 2; + slinwords = (slinwords << MiscState.TISize) >> 2; + + int ptr = 0, srcptr = 0; + UINT16 first, sec; + UINT32 src = (MiscState.TIAddress >> 1) + (tl * tiwinwords) + slinwords; + + if (dxt != 0) + { + int j = 0; + int t = 0; + int oldt = 0; + + if (tile[tilenum].size != PIXEL_SIZE_32BIT && tile[tilenum].format != FORMAT_YUV) + { + for (int i = 0; i < width; i ++) + { + oldt = t; + t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; + if (t != oldt) + { + i += tile[tilenum].line; + } + + ptr = tb + (i << 2); + srcptr = src + (i << 2); + + tc[(ptr ^ t) & 0x7ff] = U_RREADIDX16(srcptr); + tc[((ptr + 1) ^ t) & 0x7ff] = U_RREADIDX16(srcptr + 1); + tc[((ptr + 2) ^ t) & 0x7ff] = U_RREADIDX16(srcptr + 2); + tc[((ptr + 3) ^ t) & 0x7ff] = U_RREADIDX16(srcptr + 3); + j += dxt; + } + } + else if (tile[tilenum].format == FORMAT_YUV) + { + for (int i = 0; i < width; i ++) + { + oldt = t; + t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; + if (t != oldt) + { + i += tile[tilenum].line; + } + + ptr = ((tb + (i << 1)) ^ t) & 0x3ff; + srcptr = src + (i << 2); + + first = U_RREADIDX16(srcptr); + sec = U_RREADIDX16(srcptr + 1); + tc[ptr] = ((first >> 8) << 8) | (sec >> 8); + tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); + + ptr = ((tb + (i << 1) + 1) ^ t) & 0x3ff; + first = U_RREADIDX16(srcptr + 2); + sec = U_RREADIDX16(srcptr + 3); + tc[ptr] = ((first >> 8) << 8) | (sec >> 8); + tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); + + j += dxt; + } + } + else + { + for (int i = 0; i < width; i ++) + { + oldt = t; + t = ((j >> 11) & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; + if (t != oldt) + i += tile[tilenum].line; + + ptr = ((tb + (i << 1)) ^ t) & 0x3ff; + srcptr = src + (i << 2); + tc[ptr] = U_RREADIDX16(srcptr); + tc[ptr | 0x400] = U_RREADIDX16(srcptr + 1); + + ptr = ((tb + (i << 1) + 1) ^ t) & 0x3ff; + tc[ptr] = U_RREADIDX16(srcptr + 2); + tc[ptr | 0x400] = U_RREADIDX16(srcptr + 3); + + j += dxt; + } + } + tile[tilenum].th = tl + (j >> 11); + } + else + { + if (tile[tilenum].size != PIXEL_SIZE_32BIT && tile[tilenum].format != FORMAT_YUV) + { + for (int i = 0; i < width; i ++) + { + ptr = tb + (i << 2); + srcptr = src + (i << 2); + tc[(ptr ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr); + tc[((ptr + 1) ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr + 1); + tc[((ptr + 2) ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr + 2); + tc[((ptr + 3) ^ WORD_ADDR_XOR) & 0x7ff] = U_RREADIDX16(srcptr + 3); + } + } + else if (tile[tilenum].format == FORMAT_YUV) + { + for (int i = 0; i < width; i ++) + { + ptr = ((tb + (i << 1)) ^ WORD_ADDR_XOR) & 0x3ff; + srcptr = src + (i << 2); + first = U_RREADIDX16(srcptr); + sec = U_RREADIDX16(srcptr + 1); + tc[ptr] = ((first >> 8) << 8) | (sec >> 8);//UV pair + tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); + + ptr = ((tb + (i << 1) + 1) ^ WORD_ADDR_XOR) & 0x3ff; + first = U_RREADIDX16(srcptr + 2); + sec = U_RREADIDX16(srcptr + 3); + tc[ptr] = ((first >> 8) << 8) | (sec >> 8); + tc[ptr | 0x400] = ((first & 0xff) << 8) | (sec & 0xff); + } + } + else + { + for (int i = 0; i < width; i ++) + { + ptr = ((tb + (i << 1)) ^ WORD_ADDR_XOR) & 0x3ff; + srcptr = src + (i << 2); + tc[ptr] = U_RREADIDX16(srcptr); + tc[ptr | 0x400] = U_RREADIDX16(srcptr + 1); + + ptr = ((tb + (i << 1) + 1) ^ WORD_ADDR_XOR) & 0x3ff; + tc[ptr] = U_RREADIDX16(srcptr + 2); + tc[ptr | 0x400] = U_RREADIDX16(srcptr + 3); + } + } + tile[tilenum].th = tl; + } +} + +void n64_rdp::CmdLoadTile(UINT32 w1, UINT32 w2) +{ + //wait("LoadTile"); + N64Tile* tile = m_tiles; + int tilenum = (w2 >> 24) & 0x7; + + tile[tilenum].sl = ((w1 >> 12) & 0xfff); + tile[tilenum].tl = ((w1 >> 0) & 0xfff); + tile[tilenum].sh = ((w2 >> 12) & 0xfff); + tile[tilenum].th = ((w2 >> 0) & 0xfff); + + UINT16 sl = tile[tilenum].sl >> 2; + UINT16 tl = tile[tilenum].tl >> 2; + UINT16 sh = tile[tilenum].sh >> 2; + UINT16 th = tile[tilenum].th >> 2; + + INT32 width = (sh - sl) + 1; + INT32 height = (th - tl) + 1; +/* + int topad; + if (MiscState.TISize < 3) + { + topad = (width * MiscState.TISize) & 0x7; + } + else + { + topad = (width << 2) & 0x7; + } + topad = 0; // ???? +*/ + switch (MiscState.TISize) + { + case PIXEL_SIZE_8BIT: + { + UINT32 src = MiscState.TIAddress; + UINT8 *tc = GetTMEM(); + int tb = tile[tilenum].tmem << 3; + + for (int j = 0; j < height; j++) + { + int tline = tb + ((tile[tilenum].line << 3) * j); + int s = ((j + tl) * MiscState.TIWidth) + sl; + + int xorval8 = ((j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR); + for (int i = 0; i < width; i++) + { + tc[((tline + i) ^ xorval8) & 0xfff] = U_RREADADDR8(src + s + i); + } + } + break; + } + case PIXEL_SIZE_16BIT: + { + UINT32 src = MiscState.TIAddress >> 1; + UINT16 *tc = GetTMEM16(); + UINT16 yuvword; + + if (tile[tilenum].format != FORMAT_YUV) + { + for (int j = 0; j < height; j++) + { + int tb = tile[tilenum].tmem << 2; + int tline = tb + ((tile[tilenum].line << 2) * j); + int s = ((j + tl) * MiscState.TIWidth) + sl; + int xorval16 = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; + + for (int i = 0; i < width; i++) + { + UINT32 taddr = (tline + i) ^ xorval16; + tc[taddr & 0x7ff] = U_RREADIDX16(src + s + i); + } + } + } + else + { + for (int j = 0; j < height; j++) + { + int tb = tile[tilenum].tmem << 3; + int tline = tb + ((tile[tilenum].line << 3) * j); + int s = ((j + tl) * MiscState.TIWidth) + sl; + int xorval8 = (j & 1) ? BYTE_XOR_DWORD_SWAP : BYTE_ADDR_XOR; + + for (int i = 0; i < width; i++) + { + UINT32 taddr = ((tline + i) ^ xorval8) & 0x7ff; + yuvword = U_RREADIDX16(src + s + i); + GetTMEM()[taddr] = yuvword >> 8; + GetTMEM()[taddr | 0x800] = yuvword & 0xff; + } + } + } + break; + } + case PIXEL_SIZE_32BIT: + { + UINT32 src = MiscState.TIAddress >> 2; + UINT16 *tc16 = GetTMEM16(); + int tb = (tile[tilenum].tmem << 2); + + for (int j = 0; j < height; j++) + { + int tline = tb + ((tile[tilenum].line << 2) * j); + + int s = ((j + tl) * MiscState.TIWidth) + sl; + int xorval32cur = (j & 1) ? WORD_XOR_DWORD_SWAP : WORD_ADDR_XOR; + for (int i = 0; i < width; i++) + { + UINT32 c = U_RREADIDX32(src + s + i); + UINT32 ptr = ((tline + i) ^ xorval32cur) & 0x3ff; + tc16[ptr] = c >> 16; + tc16[ptr | 0x400] = c & 0xffff; + } + } + break; + } + + default: fatalerror("RDP: load_tile: size = %d\n", MiscState.TISize); + } +} + +void n64_rdp::CmdSetTile(UINT32 w1, UINT32 w2) +{ + //wait("SetTile"); + + int tilenum = (w2 >> 24) & 0x7; + N64Tile* tex_tile = &m_tiles[tilenum]; + + tex_tile->format = (w1 >> 21) & 0x7; + tex_tile->size = (w1 >> 19) & 0x3; + tex_tile->line = (w1 >> 9) & 0x1ff; + tex_tile->tmem = (w1 >> 0) & 0x1ff; + tex_tile->palette = (w2 >> 20) & 0xf; + tex_tile->ct = (w2 >> 19) & 0x1; + tex_tile->mt = (w2 >> 18) & 0x1; + tex_tile->mask_t = (w2 >> 14) & 0xf; + tex_tile->shift_t = (w2 >> 10) & 0xf; + tex_tile->cs = (w2 >> 9) & 0x1; + tex_tile->ms = (w2 >> 8) & 0x1; + tex_tile->mask_s = (w2 >> 4) & 0xf; + tex_tile->shift_s = (w2 >> 0) & 0xf; + + if (tex_tile->format == FORMAT_I && tex_tile->size > PIXEL_SIZE_8BIT) + { + tex_tile->format = FORMAT_RGBA; // Used by Supercross 2000 (in-game) + } + if (tex_tile->format == FORMAT_CI && tex_tile->size > PIXEL_SIZE_8BIT) + { + tex_tile->format = FORMAT_RGBA; // Used by Clay Fighter - Sculptor's Cut + } + + if (tex_tile->format == FORMAT_RGBA && tex_tile->size < PIXEL_SIZE_16BIT) + { + tex_tile->format = FORMAT_CI; // Used by Exterem-G2, Madden Football 64, and Rat Attack + } + + //m_pending_mode_block = true; +} + +void n64_rdp::CmdFillRect(UINT32 w1, UINT32 w2) +{ + //if(m_pending_mode_block) { wait("Block on pending mode-change"); m_pending_mode_block = false; } + + UINT32 xl = (w1 >> 12) & 0xfff; + UINT32 yl = (w1 >> 0) & 0xfff; + UINT32 xh = (w2 >> 12) & 0xfff; + UINT32 yh = (w2 >> 0) & 0xfff; + + if (OtherModes.cycle_type == CYCLE_TYPE_FILL || OtherModes.cycle_type == CYCLE_TYPE_COPY) + { + yl |= 3; + } + + UINT32 xlint = (xl >> 2) & 0x3ff; + UINT32 xhint = (xh >> 2) & 0x3ff; + + UINT32* ewdata = m_temp_rect_data; + 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 + + DrawTriangle(false, false, false, true); +} + +void n64_rdp::CmdSetFogColor(UINT32 w1, UINT32 w2) +{ + FogColor.c = w2; +} + +void n64_rdp::CmdSetBlendColor(UINT32 w1, UINT32 w2) +{ + BlendColor.c = w2; +} + +void n64_rdp::CmdSetPrimColor(UINT32 w1, UINT32 w2) +{ + MiscState.MinLevel = (w1 >> 8) & 0x1f; + PrimLODFraction = w1 & 0xff; + PrimColor.c = w2; +} + +void n64_rdp::CmdSetEnvColor(UINT32 w1, UINT32 w2) +{ + EnvColor.c = w2; +} + +void n64_rdp::CmdSetCombine(UINT32 w1, UINT32 w2) +{ + m_combine.sub_a_rgb0 = (w1 >> 20) & 0xf; + m_combine.mul_rgb0 = (w1 >> 15) & 0x1f; + m_combine.sub_a_a0 = (w1 >> 12) & 0x7; + m_combine.mul_a0 = (w1 >> 9) & 0x7; + m_combine.sub_a_rgb1 = (w1 >> 5) & 0xf; + m_combine.mul_rgb1 = (w1 >> 0) & 0x1f; + + m_combine.sub_b_rgb0 = (w2 >> 28) & 0xf; + m_combine.sub_b_rgb1 = (w2 >> 24) & 0xf; + m_combine.sub_a_a1 = (w2 >> 21) & 0x7; + m_combine.mul_a1 = (w2 >> 18) & 0x7; + m_combine.add_rgb0 = (w2 >> 15) & 0x7; + m_combine.sub_b_a0 = (w2 >> 12) & 0x7; + m_combine.add_a0 = (w2 >> 9) & 0x7; + m_combine.add_rgb1 = (w2 >> 6) & 0x7; + m_combine.sub_b_a1 = (w2 >> 3) & 0x7; + m_combine.add_a1 = (w2 >> 0) & 0x7; +} + +void n64_rdp::CmdSetTextureImage(UINT32 w1, UINT32 w2) +{ + MiscState.TIFormat = (w1 >> 21) & 0x7; + MiscState.TISize = (w1 >> 19) & 0x3; + MiscState.TIWidth = (w1 & 0x3ff) + 1; + MiscState.TIAddress = w2 & 0x01ffffff; +} + +void n64_rdp::CmdSetMaskImage(UINT32 w1, UINT32 w2) +{ + //wait("SetMaskImage"); + + MiscState.ZBAddress = w2 & 0x01ffffff; +} + +void n64_rdp::CmdSetColorImage(UINT32 w1, UINT32 w2) +{ + //wait("SetColorImage"); + + MiscState.FBFormat = (w1 >> 21) & 0x7; + MiscState.FBSize = (w1 >> 19) & 0x3; + MiscState.FBWidth = (w1 & 0x3ff) + 1; + MiscState.FBAddress = w2 & 0x01ffffff; + + if (MiscState.FBFormat < 2 || MiscState.FBFormat > 32) // Jet Force Gemini sets the format to 4, Intensity. Protection? + { + MiscState.FBFormat = 2; + } +} + +UINT32 n64_rdp::AddRightCvg(UINT32 x, UINT32 k) +{ +//#undef FULL_SUBPIXELS +#define FULL_SUBPIXELS + UINT32 coveredsubpixels=((x >> 14) & 3); + if (!(x & 0xffff)) + { + return 0; + } +#ifdef FULL_SUBPIXELS + if (!coveredsubpixels) + { + return 0; + } + if (!(k & 1)) + { + return (coveredsubpixels<3) ? 1 : 2; + } + else + { + return (coveredsubpixels<2) ? 0 : 1; + } +#endif + if (!(k & 1)) + { + return (coveredsubpixels<2) ? 1 : 2; + } + else + { + if (coveredsubpixels<1) + { + return 0; + } + else if (coveredsubpixels<3) + { + return 1; + } + else + { + return 2; + } + } +} + +UINT32 n64_rdp::AddLeftCvg(UINT32 x, UINT32 k) +{ + UINT32 coveredsubpixels = 3 - ((x >> 14) & 3); + if (!(x & 0xffff)) + { + return 2; + } +#ifdef FULL_SUBPIXELS + if (!coveredsubpixels) + { + return 0; + } + if (!(k & 1)) + { + return (coveredsubpixels<2) ? 0 : 1; + } + else + { + return (coveredsubpixels<3) ? 1 : 2; + } +#endif + if (k & 1) + { + return (coveredsubpixels<2) ? 1 : 2; + } + else + { + if (coveredsubpixels < 1) + { + return 0; + } + else if (coveredsubpixels < 3) + { + return 1; + } + else + { + return 2; + } + } +} + +/*****************************************************************************/ + +void n64_rdp::CmdInvalid(UINT32 w1, UINT32 w2) +{ + fatalerror("n64_rdp::Invalid: %d, %08x %08x\n", (w1 >> 24) & 0x3f, w1, w2); +} + +void n64_rdp::CmdNoOp(UINT32 w1, UINT32 w2) +{ + // Do nothing +} + + +void n64_rdp::ProcessList() +{ + INT32 length = m_end - m_current; + + if(length < 0) + { + m_current = m_end; + return; + } + + // load command data + for(int i = 0; i < length; i += 4) + { + m_cmd_data[m_cmd_ptr++] = ReadData((m_current & 0x1fffffff) + i); + } + + m_current = m_end; + + UINT32 cmd = (m_cmd_data[0] >> 24) & 0x3f; + UINT32 cmd_length = (m_cmd_ptr + 1) * 4; + + SetStatusReg(GetStatusReg() &~ DP_STATUS_FREEZE); + + // check if more data is needed + if (cmd_length < rdp_command_length[cmd]) + { + return; + } + + while (m_cmd_cur < m_cmd_ptr) + { + cmd = (m_cmd_data[m_cmd_cur] >> 24) & 0x3f; + + if (((m_cmd_ptr - m_cmd_cur) * 4) < rdp_command_length[cmd]) + { + return; + //fatalerror("rdp_process_list: not enough rdp command data: cur = %d, ptr = %d, expected = %d\n", m_cmd_cur, m_cmd_ptr, rdp_command_length[cmd]); + } + + if (LOG_RDP_EXECUTION) + { + char string[4000]; + Dasm(string); + + fprintf(rdp_exec, "%08X: %08X %08X %s\n", m_start+(m_cmd_cur * 4), m_cmd_data[m_cmd_cur+0], m_cmd_data[m_cmd_cur+1], string); + fflush(rdp_exec); + } + + // execute the command + UINT32 w1 = m_cmd_data[m_cmd_cur+0]; + UINT32 w2 = m_cmd_data[m_cmd_cur+1]; + + switch(cmd) + { + case 0x00: CmdNoOp(w1, w2); break; + + case 0x08: CmdTriangle(w1, w2); break; + case 0x09: CmdTriangleZ(w1, w2); break; + case 0x0a: CmdTriangleT(w1, w2); break; + case 0x0b: CmdTriangleTZ(w1, w2); break; + case 0x0c: CmdTriangleS(w1, w2); break; + case 0x0d: CmdTriangleSZ(w1, w2); break; + case 0x0e: CmdTriangleST(w1, w2); break; + case 0x0f: CmdTriangleSTZ(w1, w2); break; + + case 0x24: CmdTexRect(w1, w2); break; + case 0x25: CmdTexRectFlip(w1, w2); break; + + case 0x26: CmdSyncLoad(w1, w2); break; + case 0x27: CmdSyncPipe(w1, w2); break; + case 0x28: CmdSyncTile(w1, w2); break; + case 0x29: CmdSyncFull(w1, w2); break; + + case 0x2a: CmdSetKeyGB(w1, w2); break; + case 0x2b: CmdSetKeyR(w1, w2); break; + + case 0x2c: CmdSetConvert(w1, w2); break; + case 0x3c: CmdSetCombine(w1, w2); break; + case 0x2d: CmdSetScissor(w1, w2); break; + case 0x2e: CmdSetPrimDepth(w1, w2); break; + case 0x2f: CmdSetOtherModes(w1, w2); break; + + case 0x30: CmdLoadTLUT(w1, w2); break; + case 0x33: CmdLoadBlock(w1, w2); break; + case 0x34: CmdLoadTile(w1, w2); break; + + case 0x32: CmdSetTileSize(w1, w2); break; + case 0x35: CmdSetTile(w1, w2); break; + + case 0x36: CmdFillRect(w1, w2); break; + + case 0x37: CmdSetFillColor32(w1, w2); break; + case 0x38: CmdSetFogColor(w1, w2); break; + case 0x39: CmdSetBlendColor(w1, w2); break; + case 0x3a: CmdSetPrimColor(w1, w2); break; + case 0x3b: CmdSetEnvColor(w1, w2); break; + + case 0x3d: CmdSetTextureImage(w1, w2); break; + case 0x3e: CmdSetMaskImage(w1, w2); break; + case 0x3f: CmdSetColorImage(w1, w2); break; + } + + m_cmd_cur += rdp_command_length[cmd] / 4; + }; + m_cmd_ptr = 0; + m_cmd_cur = 0; + + m_start = m_current = m_end; +} + +/*****************************************************************************/ + +n64_rdp::n64_rdp(n64_state &state) : poly_manager(state.machine()) +{ + AuxBufPtr = 0; + AuxBuf = NULL; + m_pipe_clean = true; + + m_pending_mode_block = false; + + m_cmd_ptr = 0; + m_cmd_cur = 0; + + m_start = 0; + m_end = 0; + m_current = 0; + m_status = 0x88; + + for (int i = 0; i < 8; i++) + { + m_tiles[i].num = i; + } + + OneColor.c = 0xffffffff; + ZeroColor.c = 0x00000000; + + m_tmem = NULL; + + m_machine = NULL; + + //memset(m_hidden_bits, 3, 8388608); + + PrimLODFraction = 0; + + for (int i = 0; i < 256; i++) + { + m_gamma_table[i] = sqrt((float)(i << 6)); + m_gamma_table[i] <<= 1; + } + + for (int i = 0; i < 0x4000; i++) + { + m_gamma_dither_table[i] = sqrt((float)i); + m_gamma_dither_table[i] <<= 1; + } + + z_build_com_table(); + + for (int i = 0; i < 0x4000; i++) + { + UINT32 exponent = (i >> 11) & 7; + UINT32 mantissa = i & 0x7ff; + z_complete_dec_table[i] = ((mantissa << z_dec_table[exponent].shift) + z_dec_table[exponent].add) & 0x3fffff; + } + + precalc_cvmask_derivatives(); + + for(int i = 0; i < 0x200; i++) + { + switch((i >> 7) & 3) + { + case 0: + case 1: + s_special_9bit_clamptable[i] = i & 0xff; + break; + case 2: + s_special_9bit_clamptable[i] = 0xff; + break; + case 3: + s_special_9bit_clamptable[i] = 0; + break; + } + } + + for(int i = 0; i < 32; i++) + { + ReplicatedRGBA[i] = (i << 3) | ((i >> 2) & 7); + } + + _Write[0] = &n64_rdp::_Write16Bit_Cvg0_NoBlend; + _Write[1] = &n64_rdp::_Write16Bit_Cvg0_Blend; + _Write[2] = &n64_rdp::_Write16Bit_Cvg1; + _Write[3] = &n64_rdp::_Write16Bit_Cvg1; + _Write[4] = &n64_rdp::_Write16Bit_Cvg2; + _Write[5] = &n64_rdp::_Write16Bit_Cvg2; + _Write[6] = &n64_rdp::_Write16Bit_Cvg3; + _Write[7] = &n64_rdp::_Write16Bit_Cvg3; + _Write[8] = &n64_rdp::_Write32Bit_Cvg0_NoBlend; + _Write[9] = &n64_rdp::_Write32Bit_Cvg0_Blend; + _Write[10] = &n64_rdp::_Write32Bit_Cvg1; + _Write[11] = &n64_rdp::_Write32Bit_Cvg1; + _Write[12] = &n64_rdp::_Write32Bit_Cvg2; + _Write[13] = &n64_rdp::_Write32Bit_Cvg2; + _Write[14] = &n64_rdp::_Write32Bit_Cvg3; + _Write[15] = &n64_rdp::_Write32Bit_Cvg3; + + _Read[0] = &n64_rdp::_Read16Bit_ImgRead0; + _Read[1] = &n64_rdp::_Read16Bit_ImgRead1; + _Read[2] = &n64_rdp::_Read32Bit_ImgRead0; + _Read[3] = &n64_rdp::_Read32Bit_ImgRead1; + + _Copy[0] = &n64_rdp::_Copy16Bit; + _Copy[1] = &n64_rdp::_Copy32Bit; + + _Fill[0] = &n64_rdp::_Fill16Bit; + _Fill[1] = &n64_rdp::_Fill32Bit; +} + +void n64_state::video_start() +{ + m_rdp = auto_alloc(machine(), n64_rdp(*this)); + + m_rdp->SetMachine(machine()); + m_rdp->InitInternalState(); + + m_rdp->Blender.SetMachine(machine()); + m_rdp->Blender.SetProcessor(m_rdp); + + m_rdp->TexPipe.SetMachine(machine()); + + m_rdp->AuxBuf = auto_alloc_array_clear(machine(), UINT8, EXTENT_AUX_COUNT); + + if (LOG_RDP_EXECUTION) + { + rdp_exec = fopen("rdp_execute.txt", "wt"); + } +} + +UINT32 n64_state::screen_update_n64(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + n64_periphs *n64 = machine().device("rcp"); + m_rdp->visarea = screen.visible_area(); + + //UINT16 *frame_buffer = (UINT16*)&rdram[(n64->vi_origin & 0xffffff) >> 2]; + //UINT8 *cvg_buffer = &m_rdp.HiddenBits[((n64->vi_origin & 0xffffff) >> 2) >> 1]; + //int vibuffering = ((n64->vi_control & 2) && fsaa && divot); + + //vibuffering = 0; // Disabled for now + + /* + if (vibuffering && ((n64->vi_control & 3) == 2)) + { + if (frame_buffer) + { + for (j=0; j < vres; j++) + { + for (i=0; i < hres; i++) + { + UINT16 pix; + pix = frame_buffer[pixels ^ WORD_ADDR_XOR]; + curpixel_cvg = ((pix & 1) << 2) | (cvg_buffer[pixels ^ BYTE_ADDR_XOR] & 3); // Reuse of this variable + if (curpixel_cvg < 7 && i > 1 && j > 1 && i < (hres - 2) && j < (vres - 2) && fsaa) + { + newc = video_filter16(&frame_buffer[pixels ^ WORD_ADDR_XOR], &cvg_buffer[pixels ^ BYTE_ADDR_XOR], n64->vi_width); + ViBuffer[i][j] = newc; + } + else + { + newc.i.r = ((pix >> 8) & 0xf8) | (pix >> 13); + newc.i.g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07); + newc.i.b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07); + ViBuffer[i][j] = newc; + } + pixels++; + } + pixels += invisiblewidth; + } + } + } + */ + + m_rdp->wait(); + m_rdp->AuxBufPtr = 0; + + if (n64->vi_blank) + { + bitmap.fill(0, m_rdp->visarea); + return 0; + } + + m_rdp->VideoUpdate(n64, bitmap); + + return 0; +} -- cgit v1.2.3