diff --git a/pcsx2/GS/GSLocalMemory.h b/pcsx2/GS/GSLocalMemory.h index c495f529b5..6ea5dd875a 100644 --- a/pcsx2/GS/GSLocalMemory.h +++ b/pcsx2/GS/GSLocalMemory.h @@ -460,7 +460,7 @@ public: typedef u32 (GSLocalMemory::*readPixelAddr)(u32 addr) const; typedef u32 (GSLocalMemory::*readTexelAddr)(u32 addr, const GIFRegTEXA& TEXA) const; typedef void (*writeImage)(GSLocalMemory& mem, int& tx, int& ty, const u8* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); - typedef void (*readImage)(const GSLocalMemory& mem, int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); + typedef void (*readImage)(const GSLocalMemory& mem, int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); typedef void (*readTexture)(GSLocalMemory& mem, const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); typedef void (*readTextureBlock)(const GSLocalMemory& mem, u32 bp, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); @@ -1123,9 +1123,9 @@ public: return ReadTexel16(PixelAddress16SZ(x, y, TEX0.TBP0, TEX0.TBW), TEXA); } - __forceinline void ReadImageX(int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) const + __forceinline void ReadImageX(int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) const { - m_readImageX(*this, tx, ty, dst, len, BITBLTBUF, TRXPOS, TRXREG); + m_readImageX(*this, tx, ty, offset, dst, len, BITBLTBUF, TRXPOS, TRXREG); } void ReadTexture(const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); diff --git a/pcsx2/GS/GSLocalMemoryMultiISA.cpp b/pcsx2/GS/GSLocalMemoryMultiISA.cpp index 67a0b3e2d0..5469df06c6 100644 --- a/pcsx2/GS/GSLocalMemoryMultiISA.cpp +++ b/pcsx2/GS/GSLocalMemoryMultiISA.cpp @@ -87,7 +87,7 @@ class CURRENT_ISA::GSLocalMemoryFunctions static void ReadTexture(GSLocalMemory& mem, const GSOffset& off, const GSVector4i& r, u8* dst, int dstpitch, const GIFRegTEXA& TEXA); public: - static void ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); + static void ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG); static void PopulateFunctions(GSLocalMemory& mem); }; @@ -931,7 +931,7 @@ void GSLocalMemoryFunctions::WriteImageX(GSLocalMemory& mem, int& tx, int& ty, c // -void GSLocalMemoryFunctions::ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) +void GSLocalMemoryFunctions::ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, int& offset, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) { if (len <= 0) return; @@ -1005,16 +1005,23 @@ void GSLocalMemoryFunctions::ReadImageX(const GSLocalMemory& mem, int& tx, int& case PSM_PSMCT24: case PSM_PSMZ24: - readWriteHelper(mem.vm32(), tx, ty, len / 3, 1, sx, w, off.assertSizesMatch(GSLocalMemory::swizzle32), [&](auto& pa, int x) + { + const int length = len / 3; + const int aligned_length = (len + 2) / 3; + if (length != aligned_length) { - u32 c = *pa.value(x); - pb[0] = (u8)(c); - pb[1] = (u8)(c >> 8); - pb[2] = (u8)(c >> 16); - pb += 3; - }); + offset = 3 - (len - (length * 3)); + } + readWriteHelper(mem.vm32(), tx, ty, aligned_length, 1, sx, w, off.assertSizesMatch(GSLocalMemory::swizzle32), [&](auto& pa, int x) + { + u32 c = *pa.value(x); + pb[0] = (u8)(c); + pb[1] = (u8)(c >> 8); + pb[2] = (u8)(c >> 16); + pb += 3; + }); break; - + } case PSM_PSMCT16: case PSM_PSMCT16S: case PSM_PSMZ16: diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index d1421479e5..d2e5bfb5c5 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -1845,7 +1845,9 @@ void GSState::Read(u8* mem, int len) if (!m_tr.Update(w, h, bpp, len)) return; - m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); + mem += m_tr.offset; + len -= m_tr.offset; + m_mem.ReadImageX(m_tr.x, m_tr.y, m_tr.offset, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); if (GSConfig.DumpGSData && GSConfig.SaveRT && s_n >= GSConfig.SaveN) { @@ -2136,7 +2138,9 @@ void GSState::ReadLocalMemoryUnsync(u8* mem, int qwc, GIFRegBITBLTBUF BITBLTBUF, if (!tb.Update(w, h, bpp, len)) return; - m_mem.ReadImageX(tb.x, tb.y, mem, len, BITBLTBUF, TRXPOS, TRXREG); + mem += tb.offset; + len -= tb.offset; + m_mem.ReadImageX(tb.x, tb.y, tb.offset, mem, len, BITBLTBUF, TRXPOS, TRXREG); } void GSState::PurgePool() @@ -3900,6 +3904,7 @@ void GSState::GSTransferBuffer::Init(int tx, int ty, const GIFRegBITBLTBUF& blit x = tx; y = ty; total = 0; + offset = 0; m_blit = blit; } diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index 4141db857e..887527dcc8 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -123,6 +123,7 @@ private: { int x = 0, y = 0; int start = 0, end = 0, total = 0; + int offset = 0; u8* buff = nullptr; GIFRegBITBLTBUF m_blit = {};