#include "emu.h" #include "includes/n64.h" #include "video/n64.h" namespace N64 { namespace RDP { bool Blender::Blend1Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel) { ColorInputs* ci = m_rdp->GetColorInputs(); INT32 r, g, b; if (!m_other_modes->alpha_cvg_select) { DitherA(&m_rdp->GetPixelColor()->i.a, adseed); } DitherA(&m_rdp->GetShadeColor()->i.a, adseed); if (!AlphaCompare(m_rdp->GetPixelColor()->i.a)) { return false; } if (m_other_modes->antialias_en ? (!m_misc_state->m_curpixel_cvg) : (!m_misc_state->m_curpixel_cvbit)) { return false; } bool dontblend = (partialreject && m_rdp->GetPixelColor()->i.a >= 0xff); if (!m_blend_enable || dontblend) { r = *ci->blender1a_r[0]; g = *ci->blender1a_g[0]; b = *ci->blender1a_b[0]; } else { m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[0]; BlendEquationCycle0(&r, &g, &b, special_bsel); } if (m_other_modes->rgb_dither_sel < 3) { DitherRGB(&r, &g, &b, dith); } *fr = r; *fg = g; *fb = b; return true; } bool Blender::Blend2Cycle(UINT32* fr, UINT32* fg, UINT32* fb, int dith, int adseed, int partialreject, int special_bsel0, int special_bsel1) { ColorInputs* ci = m_rdp->GetColorInputs(); if (!m_other_modes->alpha_cvg_select) { DitherA(&m_rdp->GetPixelColor()->i.a, adseed); } DitherA(&m_rdp->GetShadeColor()->i.a, adseed); if (!AlphaCompare(m_rdp->GetPixelColor()->i.a)) { return false; } if (m_other_modes->antialias_en ? (!m_misc_state->m_curpixel_cvg) : (!m_misc_state->m_curpixel_cvbit)) { return false; } m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[0]; INT32 r, g, b; BlendEquationCycle0(&r, &g, &b, special_bsel0); m_rdp->GetBlendedColor()->i.r = r; m_rdp->GetBlendedColor()->i.g = g; m_rdp->GetBlendedColor()->i.b = b; m_rdp->GetBlendedColor()->i.a = m_rdp->GetPixelColor()->i.a; bool dontblend = (partialreject && m_rdp->GetPixelColor()->i.a >= 0xff); if (!m_blend_enable || dontblend) { r = *ci->blender1a_r[1]; g = *ci->blender1a_g[1]; b = *ci->blender1a_b[1]; } else { m_rdp->GetInvPixelColor()->i.a = 0xff - *ci->blender1b_a[1]; BlendEquationCycle1(&r, &g, &b, special_bsel1); } if (m_other_modes->rgb_dither_sel < 3) { DitherRGB(&r, &g, &b, dith); } *fr = r; *fg = g; *fb = b; return true; } void Blender::BlendEquationCycle0(int* r, int* g, int* b, int bsel_special) { ColorInputs* ci = m_rdp->GetColorInputs(); UINT8 blend1a = *ci->blender1b_a[0] >> 3; UINT8 blend2a = *ci->blender2b_a[0] >> 3; if (bsel_special) { blend1a = (blend1a >> m_shift_a) & 0x1C; blend2a = (blend2a >> m_shift_b) & 0x1C; } UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf; *r = (((int)(*ci->blender1a_r[0]) * (int)(blend1a))) + (((int)(*ci->blender2a_r[0]) * (int)(blend2a))); *g = (((int)(*ci->blender1a_g[0]) * (int)(blend1a))) + (((int)(*ci->blender2a_g[0]) * (int)(blend2a))); *b = (((int)(*ci->blender1a_b[0]) * (int)(blend1a))) + (((int)(*ci->blender2a_b[0]) * (int)(blend2a))); if (bsel_special) { *r += (((int)*ci->blender2a_r[0]) << 2); *g += (((int)*ci->blender2a_g[0]) << 2); *b += (((int)*ci->blender2a_b[0]) << 2); } else { *r += (int)*ci->blender2a_r[0]; *g += (int)*ci->blender2a_g[0]; *b += (int)*ci->blender2a_b[0]; } *r >>= 2; *g >>= 2; *b >>= 2; if (m_other_modes->force_blend) { *r >>= 3; *g >>= 3; *b >>= 3; } else { if (sum) { *r /= sum; *g /= sum; *b /= sum; } else { *r = *g = *b = 0xff; } } if (*r > 255) *r = 255; if (*g > 255) *g = 255; if (*b > 255) *b = 255; } void Blender::BlendEquationCycle1(INT32* r, INT32* g, INT32* b, int bsel_special) { ColorInputs* ci = m_rdp->GetColorInputs(); UINT8 blend1a = *ci->blender1b_a[1] >> 3; UINT8 blend2a = *ci->blender2b_a[1] >> 3; if (bsel_special) { blend1a = (blend1a >> m_shift_a) & 0x1C; blend2a = (blend2a >> m_shift_b) & 0x1C; } UINT32 sum = ((blend1a >> 2) + (blend2a >> 2) + 1) & 0xf; *r = (((int)(*ci->blender1a_r[1]) * (int)(blend1a))) + (((int)(*ci->blender2a_r[1]) * (int)(blend2a))); *g = (((int)(*ci->blender1a_g[1]) * (int)(blend1a))) + (((int)(*ci->blender2a_g[1]) * (int)(blend2a))); *b = (((int)(*ci->blender1a_b[1]) * (int)(blend1a))) + (((int)(*ci->blender2a_b[1]) * (int)(blend2a))); if (bsel_special) { *r += (((int)*ci->blender2a_r[1]) << 2); *g += (((int)*ci->blender2a_g[1]) << 2); *b += (((int)*ci->blender2a_b[1]) << 2); } else { *r += (int)*ci->blender2a_r[1]; *g += (int)*ci->blender2a_g[1]; *b += (int)*ci->blender2a_b[1]; } *r >>= 2; *g >>= 2; *b >>= 2; if (m_other_modes->force_blend) { *r >>= 3; *g >>= 3; *b >>= 3; } else { if (sum) { *r /= sum; *g /= sum; *b /= sum; } else { *r = *g = *b = 0xff; } } if (*r > 255) *r = 255; if (*g > 255) *g = 255; if (*b > 255) *b = 255; } bool Blender::AlphaCompare(UINT8 alpha) { INT32 threshold; if (m_other_modes->alpha_compare_en) { threshold = (m_other_modes->dither_alpha_en) ? (machine().rand() & 0xff) : m_rdp->GetBlendColor()->i.a; if (alpha < threshold) { return false; } return true; } return true; } void Blender::DitherA(UINT8 *a, int dith) { INT32 new_a = *a + dith; if(new_a & 0x100) { new_a = 0xff; } *a = (UINT8)new_a; } void Blender::DitherRGB(INT32 *r, INT32 *g, INT32 *b, int dith) { if ((*r & 7) > dith) { *r = (*r & 0xf8) + 8; if (*r > 247) { *r = 255; } } if ((*g & 7) > dith) { *g = (*g & 0xf8) + 8; if (*g > 247) { *g = 255; } } if ((*b & 7) > dith) { *b = (*b & 0xf8) + 8; if (*b > 247) { *b = 255; } } } } // namespace RDP } // namespace N64