mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Carefully allow move to create new targets
Xenosaga I does a move from BP 1C00 to E00, then from E00 to 2A00 a few frames later for its cutscene transitions. 2A00 then gets used as a texture and blended on top of the later frames. Because there's no target at 2A00, the move falls back to the CPU, and E00 contains junk which gets moved and eventually preloaded instead. Gradius V uses moves for a screen move/wobble-like effect, by moving chunks of the framebuffer out, then using those as a texture. It's not broken at the moment, but it does readback (slow), and break upscaling.
This commit is contained in:
parent
06db8eec48
commit
80dce398e0
|
@ -1579,6 +1579,24 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
|
|||
// Look for an exact match on the targets.
|
||||
GSTextureCache::Target* src = GetExactTarget(SBP, SBW, SPSM);
|
||||
GSTextureCache::Target* dst = GetExactTarget(DBP, DBW, DPSM);
|
||||
|
||||
// Beware of the case where a game might create a larger texture by moving a bunch of chunks around.
|
||||
// We use dx/dy == 0 and the TBW check as a safeguard to make sure these go through to local memory.
|
||||
// Good test case for this is the Xenosaga I cutscene transitions, or Gradius V.
|
||||
if (src && !dst && dx == 0 && dy == 0 && ((static_cast<u32>(w) + 63) / 64) == DBW)
|
||||
{
|
||||
GIFRegTEX0 new_TEX0 = {};
|
||||
new_TEX0.TBP0 = DBP;
|
||||
new_TEX0.TBW = DBW;
|
||||
new_TEX0.PSM = DPSM;
|
||||
|
||||
const int real_height = GetTargetHeight(DBP, DBW, DPSM, h);
|
||||
const GSVector2 scale(src->m_texture->GetScale());
|
||||
dst = LookupTarget(new_TEX0, GSVector2i(static_cast<int>(w * scale.x), static_cast<int>(real_height * scale.y)), src->m_type, true);
|
||||
if (dst)
|
||||
dst->m_texture->SetScale(scale);
|
||||
}
|
||||
|
||||
if (!src || !dst || src->m_texture->GetScale() != dst->m_texture->GetScale())
|
||||
return false;
|
||||
|
||||
|
|
Loading…
Reference in New Issue