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)
This commit is contained in:
Gregory Hainaut 2016-09-04 12:21:12 +02:00
parent e0961d81a0
commit b34243fa7b
1 changed files with 28 additions and 2 deletions

View File

@ -821,7 +821,8 @@ void GSState::GIFRegHandlerXYZ2(const GIFReg* RESTRICT r)
template<int i> 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<int i> 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<int i> 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()