diff --git a/pcsx2/GS/GSClut.cpp b/pcsx2/GS/GSClut.cpp index 10d2f6ff4c..68da5194da 100644 --- a/pcsx2/GS/GSClut.cpp +++ b/pcsx2/GS/GSClut.cpp @@ -108,8 +108,15 @@ void GSClut::Invalidate() m_write.dirty = true; } -// This checks the whole page! Some games (like We Love Katamari) have the CLUT 1 block ahead of the DBP during a transfer. -// Safer to check if the whole page is being written anyway since it could modify only part of the CLUT. +void GSClut::InvalidateRange(u32 start_block, u32 end_block) +{ + if (m_write.TEX0.CBP >= start_block && m_write.TEX0.CBP <= end_block) + { + m_write.dirty = true; + } +} + +// Check the whole page, if the CLUT is slightly offset from a page boundary it could miss it. void GSClut::Invalidate(u32 block) { if (!((block ^ m_write.TEX0.CBP) & ~0x1F)) diff --git a/pcsx2/GS/GSClut.h b/pcsx2/GS/GSClut.h index 7f1425ab92..24fe065728 100644 --- a/pcsx2/GS/GSClut.h +++ b/pcsx2/GS/GSClut.h @@ -102,6 +102,7 @@ public: void Invalidate(); void Invalidate(u32 block); + void InvalidateRange(u32 start_block, u32 end_block); bool WriteTest(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT); void Write(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT); //void Read(const GIFRegTEX0& TEX0); diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index 6a03d920a9..e330295ed6 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -1957,7 +1957,12 @@ void GSState::Write(const u8* mem, int len) FlushWrite(); } - m_mem.m_clut.Invalidate(blit.DBP); + int page_width = std::max(1, (w / psm.pgs.x)); + int page_height = std::max(1, (h / psm.pgs.y)); + int pitch = (std::max(1U, blit.DBW) * 64) / psm.pgs.x; + + // Try to avoid flushing draws if it doesn't cross paths + m_mem.m_clut.InvalidateRange(blit.DBP, blit.DBP + ((page_width << 5) + ((page_height * pitch) << 5))); } void GSState::InitReadFIFO(u8* mem, int len) @@ -2202,7 +2207,12 @@ void GSState::Move() }); } - m_mem.m_clut.Invalidate(m_env.BITBLTBUF.DBP); + int page_width = std::max(1, (w / dpsm.pgs.x)); + int page_height = std::max(1, (h / dpsm.pgs.y)); + int pitch = (std::max(1, dbw) * 64) / dpsm.pgs.x; + + // Try to avoid flushing draws if it doesn't cross paths + m_mem.m_clut.InvalidateRange(dbp, dbp + ((page_width << 5) + ((page_height * pitch) << 5))); } void GSState::SoftReset(u32 mask)