summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/n64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/n64.c')
-rw-r--r--src/mame/video/n64.c7711
1 files 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<UINT32, rdp_poly_state, 8, 32000>(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<n64_periphs>("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<UINT32, rdp_poly_state, 8, 32000>(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<n64_periphs>("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;
+}