diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index fb9d770d8b..dd483a9639 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -134,6 +134,7 @@ GSState::GSState() PRIM = &m_env.PRIM; //CSR->rREV = 0x20; m_env.PRMODECONT.AC = 1; + tex_flushed = true; Reset(); @@ -899,6 +900,10 @@ void GSState::GIFRegHandlerTEX0(const GIFReg* RESTRICT r) GIFRegTEX0 TEX0 = r->TEX0; + bool MTBA_reload = false; + if ((m_env.CTXT[i].TEX0.TBP0 != TEX0.TBP0 || tex_flushed) && m_env.CTXT[i].TEX1.MTBA) + MTBA_reload = true; + // Spec max is 10 // // Yakuza (minimap) @@ -915,7 +920,8 @@ void GSState::GIFRegHandlerTEX0(const GIFReg* RESTRICT r) ApplyTEX0(TEX0); - if (m_env.CTXT[i].TEX1.MTBA) + // Textures must be of equal width/height and a minimum of 32x32 + if (MTBA_reload && TEX0.TW == TEX0.TH && TEX0.TW >= 5) { // NOTE 1: TEX1.MXL must not be automatically set to 3 here. // NOTE 2: Mipmap levels are tightly packed, if (tbw << 6) > (1 << tw) then the left-over space to the right is used. (common for PSM_PSMT4) @@ -925,36 +931,46 @@ void GSState::GIFRegHandlerTEX0(const GIFReg* RESTRICT r) u32 bw = TEX0.TBW; u32 w = 1u << TEX0.TW; u32 h = 1u << TEX0.TH; + u32 minwidth = m_context->TEX1.MMIN >= 4 ? 8 : 1; const u32 bpp = GSLocalMemory::m_psm[TEX0.PSM].bpp; - if (h < w) - h = w; + bp += (int)((w * h * ((float)bpp / 8))) >> 8; - bp += ((w * h * bpp >> 3) + 255) >> 8; - bw = std::max(bw >> 1, 1); - w = std::max(w >> 1, 1); - h = std::max(h >> 1, 1); + if (w > minwidth) + { + bw = std::max(bw >> 1, 1); + w = std::max(w >> 1, 1); + h = std::max(h >> 1, 1); + } m_env.CTXT[i].MIPTBP1.TBP1 = bp; m_env.CTXT[i].MIPTBP1.TBW1 = bw; - bp += ((w * h * bpp >> 3) + 255) >> 8; - bw = std::max(bw >> 1, 1); - w = std::max(w >> 1, 1); - h = std::max(h >> 1, 1); + bp += (int)((w * h * ((float)bpp / 8))) >> 8; + + if (w > minwidth) + { + bw = std::max(bw >> 1, 1); + w = std::max(w >> 1, 1); + h = std::max(h >> 1, 1); + } m_env.CTXT[i].MIPTBP1.TBP2 = bp; m_env.CTXT[i].MIPTBP1.TBW2 = bw; - bp += ((w * h * bpp >> 3) + 255) >> 8; - bw = std::max(bw >> 1, 1); - w = std::max(w >> 1, 1); - h = std::max(h >> 1, 1); + bp += (int)((w * h * ((float)bpp / 8))) >> 8; + if (w > minwidth) + { + bw = std::max(bw >> 1, 1); + } + m_env.CTXT[i].MIPTBP1.TBP3 = bp; m_env.CTXT[i].MIPTBP1.TBW3 = bw; } + + tex_flushed = false; } template @@ -1115,6 +1131,7 @@ void GSState::GIFRegHandlerFOGCOL(const GIFReg* RESTRICT r) void GSState::GIFRegHandlerTEXFLUSH(const GIFReg* RESTRICT r) { GL_REG("TEXFLUSH = 0x%x_%x", r->U32[1], r->U32[0]); + tex_flushed = true; } template @@ -2891,7 +2908,7 @@ bool GSState::IsOpaque() bool GSState::IsMipMapDraw() { - return m_context->TEX1.MXL > 0 && m_context->TEX1.MMIN >= 2 && m_context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0; + return m_context->TEX1.MXL > 0 && m_context->TEX1.MMIN >= 2 && m_context->TEX1.MMIN <= 5 && m_vt.m_lod.y > 0 && (!m_context->TEX1.MTBA || m_context->TEX0.TH == m_context->TEX0.TW); } bool GSState::IsMipMapActive() diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index 2d1eb20a7b..9051079fcf 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -157,6 +157,7 @@ protected: float m_q; GSVector4i m_scissor; GSVector4i m_ofxy; + bool tex_flushed; struct {