diff --git a/pcsx2/GS/GSDrawingContext.cpp b/pcsx2/GS/GSDrawingContext.cpp index 8a446af870..bcb71e91cf 100644 --- a/pcsx2/GS/GSDrawingContext.cpp +++ b/pcsx2/GS/GSDrawingContext.cpp @@ -120,7 +120,12 @@ GIFRegTEX0 GSDrawingContext::GetSizeFixedTEX0(const GSVector4& st, bool linear, th = extend(uv.y, th); } - if (GSConfig.Renderer == GSRendererType::SW && ((int)TEX0.TW != tw || (int)TEX0.TH != th)) + GIFRegTEX0 res = TEX0; + + res.TW = std::clamp(tw, 0, 10); + res.TH = std::clamp(th, 0, 10); + + if (GSConfig.Renderer == GSRendererType::SW && (TEX0.TW != res.TW || TEX0.TH != res.TH)) { GL_DBG("FixedTEX0 %05x %d %d tw %d=>%d th %d=>%d st (%.0f,%.0f,%.0f,%.0f) uvmax %d,%d wm %d,%d (%d,%d,%d,%d)", (int)TEX0.TBP0, (int)TEX0.TBW, (int)TEX0.PSM, @@ -130,11 +135,6 @@ GIFRegTEX0 GSDrawingContext::GetSizeFixedTEX0(const GSVector4& st, bool linear, wms, wmt, minu, maxu, minv, maxv); } - GIFRegTEX0 res = TEX0; - - res.TW = tw; - res.TH = th; - return res; } @@ -142,7 +142,6 @@ void GSDrawingContext::ComputeFixedTEX0(const GSVector4& st) { // It is quite complex to handle rescaling so this function is less stricter than GetSizeFixedTEX0, // therefore we remove the reduce optimization and we don't handle bilinear filtering which might create wrong interpolation at the border. - int tw = TEX0.TW; int th = TEX0.TH; @@ -156,8 +155,8 @@ void GSDrawingContext::ComputeFixedTEX0(const GSVector4& st) GSVector4i uv = GSVector4i(st.floor().xyzw(st.ceil())); - uv.x = findmax(uv.x, uv.z, (1 << TEX0.TW) - 1, wms, minu, maxu); - uv.y = findmax(uv.y, uv.w, (1 << TEX0.TH) - 1, wmt, minv, maxv); + uv.x = findmax(uv.x, uv.z, (1 << tw) - 1, wms, minu, maxu); + uv.y = findmax(uv.y, uv.w, (1 << th) - 1, wmt, minv, maxv); if (wms == CLAMP_REGION_CLAMP || wms == CLAMP_REGION_REPEAT) tw = extend(uv.x, tw); @@ -165,6 +164,9 @@ void GSDrawingContext::ComputeFixedTEX0(const GSVector4& st) if (wmt == CLAMP_REGION_CLAMP || wmt == CLAMP_REGION_REPEAT) th = extend(uv.y, th); + tw = std::clamp(tw, 0, 10); + th = std::clamp(th, 0, 10); + if ((tw != (int)TEX0.TW) || (th != (int)TEX0.TH)) { m_fixed_tex0 = true; diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index 0acad175bf..6b2b738ab9 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -1099,7 +1099,9 @@ void GSState::GIFRegHandlerTEX0(const GIFReg* RESTRICT r) // Max allowed MTBA size for 32bit swizzled textures (including 8H 4HL etc) is 512, 16bit and normal 8/4bit formats can be 1024 const u32 maxTex = (GSLocalMemory::m_psm[TEX0.PSM].bpp < 32) ? 10 : 9; - // Spec max is 10 + // Spec max is 10, but bitfield allows for up to 15 + // However STQ calculations expect the written size to be used for denormalization (Simple 2000 Series Vol 105 The Maid) + // This is clamped to 10 in the FixedTEX0 functions so texture sizes don't exceed 1024x1024, but STQ can calculate properly (with invalid_tex0) // // Yakuza (minimap) // Sets TW/TH to 0 @@ -1110,8 +1112,8 @@ void GSState::GIFRegHandlerTEX0(const GIFReg* RESTRICT r) // Sets TW/TH to 0 // there used to be a case to force this to 10 // but GetSizeFixedTEX0 sorts this now - TEX0.TW = std::clamp(TEX0.TW, 0, 10); - TEX0.TH = std::clamp(TEX0.TH, 0, 10); + TEX0.TW = std::clamp(TEX0.TW, 0, 15); + TEX0.TH = std::clamp(TEX0.TH, 0, 15); // MTBA loads are triggered by writes to TEX0 (but not TEX2!) // Textures MUST be a minimum width of 32 pixels