GS/HW: Handle texture shuffles using region repeat

Ace Combat 04 reads RG, writes to RGBA by setting a MINU of 1015.
This commit is contained in:
Stenzek 2023-05-11 22:33:50 +10:00 committed by refractionpcsx2
parent 1811955fce
commit 61f344dd66
1 changed files with 27 additions and 1 deletions

View File

@ -360,6 +360,20 @@ void GSRendererHW::ConvertSpriteTextureShuffle(bool& write_ba, bool& read_ba)
tex_pos &= 0xFF;
read_ba = (tex_pos > 112 && tex_pos < 144);
// Another way of selecting whether to read RG/BA is to use region repeat.
// Ace Combat 04 reads RG, writes to RGBA by setting a MINU of 1015.
if (m_cached_ctx.CLAMP.WMS == CLAMP_REGION_REPEAT)
{
GL_INS("REGION_REPEAT clamp with texture shuffle, FBMSK=%08x, MINU=%u, MINV=%u, MAXU=%u, MAXV=%u",
m_cached_ctx.FRAME.FBMSK, m_cached_ctx.CLAMP.MINU, m_cached_ctx.CLAMP.MINV, m_cached_ctx.CLAMP.MAXU,
m_cached_ctx.CLAMP.MAXV);
// offset coordinates swap around RG/BA.
const bool invert = read_ba; // (tex_pos > 112 && tex_pos < 144), i.e. 8 fixed point
const u32 minu = (m_cached_ctx.CLAMP.MINU & 8) ^ (invert ? 8 : 0);
read_ba = ((minu & 8) != 0);
}
if (m_split_texture_shuffle_pages > 0)
{
// Input vertices might be bad, so rewrite them.
@ -2628,7 +2642,19 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask()
const u32 fbmask = ((m >> 3) & 0x1F) | ((m >> 6) & 0x3E0) | ((m >> 9) & 0x7C00) | ((m >> 16) & 0x8000);
// r = rb mask, g = ga mask
const GSVector2i rb_ga_mask = GSVector2i(fbmask & 0xFF, (fbmask >> 8) & 0xFF);
m_conf.colormask.wrgba = 0;
// Ace Combat 04 sets FBMSK to 0 for the shuffle, duplicating RG across RGBA.
// Given how touchy texture shuffles are, I'm not ready to make it 100% dependent on the real FBMSK yet.
// TODO: Remove this if, and see what breaks.
if (fbmask != 0)
{
m_conf.colormask.wrgba = 0;
}
else
{
m_conf.colormask.wr = m_conf.colormask.wg = (rb_ga_mask.r != 0xFF);
m_conf.colormask.wb = m_conf.colormask.wa = (rb_ga_mask.g != 0xFF);
}
// 2 Select the new mask
if (rb_ga_mask.r != 0xFF)