#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