From b34243fa7bf7e7ce9643840e5ea75b0988ee0b1b Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Sun, 4 Sep 2016 12:21:12 +0200 Subject: [PATCH] gsdx state: TEX0 write behavior might depends on the context Game: harley davidson * write tex0 ctx0 * write tex0 ctx1 * draw ctx 0 Previous GSdx behavior will load the clut every write of TEX0. In the above case the draw will take the wrong clut. To be honest, it could be a wrong emulation on the EE core emulation. The hardware likely got a single clut (1KB cache is quite expensive) So clut loading must be skipped if the context is wrong. Next draw will use the ctx1 clut so I apply TEX0 when the context is switched Please test harley davidson :) v2: detect context switch from UpdateContext function V3: always set m_env.CTXT[i].offset.tex, avoid crash (Thanks to FlatOutPS2 that spot the issue) V4: move bad psm correction code (rebase put it in the wrong place) --- plugins/GSdx/GSState.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 8104910d50..ff4ca1440e 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -821,7 +821,8 @@ void GSState::GIFRegHandlerXYZ2(const GIFReg* RESTRICT r) template void GSState::ApplyTEX0(GIFRegTEX0& TEX0) { - // even if TEX0 did not change, a new palette may have been uploaded and will overwrite the currently queued for drawing + // Mask invalid bit before any comparison + TEX0.CPSM &= 0xa; // 1010b // Handle invalid PSM here switch (TEX0.PSM) { @@ -832,6 +833,20 @@ template void GSState::ApplyTEX0(GIFRegTEX0& TEX0) break; } + if (PRIM->CTXT != i) { + // Context isn't current. Only update the register value. + // Handling (real write of the clut buffer) will be done when ctxt will be switched + if((TEX0.u32[0] ^ m_env.CTXT[i].TEX0.u32[0]) & 0x3ffffff) // TBP0 TBW PSM + { + m_env.CTXT[i].offset.tex = m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM); + } + + m_env.CTXT[i].TEX0 = (GSVector4i)TEX0; + return; + } + + // even if TEX0 did not change, a new palette may have been uploaded and will overwrite the currently queued for drawing + bool wt = m_mem.m_clut.WriteTest(TEX0, m_env.TEXCLUT); // clut loading already covered with WriteTest, for drawing only have to check CPSM and CSA (MGS3 intro skybox would be drawn piece by piece without this) @@ -843,7 +858,6 @@ template void GSState::ApplyTEX0(GIFRegTEX0& TEX0) Flush(); } - TEX0.CPSM &= 0xa; // 1010b if((TEX0.u32[0] ^ m_env.CTXT[i].TEX0.u32[0]) & 0x3ffffff) // TBP0 TBW PSM { @@ -2416,9 +2430,21 @@ void GSState::SetGameCRC(uint32 crc, int options) void GSState::UpdateContext() { + bool context_switch = (m_context != &m_env.CTXT[PRIM->CTXT]); + m_context = &m_env.CTXT[PRIM->CTXT]; UpdateScissor(); + + if (context_switch) { + // Harley davidson sets TEX0 register before the context. Re-apply it now + // so clut is properly loaded + if (m_context == &m_env.CTXT[1]) { + ApplyTEX0<1>(m_env.CTXT[PRIM->CTXT].TEX0); + } else { + ApplyTEX0<0>(m_env.CTXT[PRIM->CTXT].TEX0); + } + } } void GSState::UpdateScissor()