From 1a3b53253059e6a3974bb123d84d4a589e63384b Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Fri, 2 Oct 2020 15:44:48 +0100 Subject: [PATCH] SIF: Transfer SIF0 junk for partial QW transfers from IOP Fixes True Crime: Streets of LA --- pcsx2/Sif.h | 22 +++++++++++++++++++++- pcsx2/Sif0.cpp | 22 +++++++++++++++------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/pcsx2/Sif.h b/pcsx2/Sif.h index 8ce56a70ea..8561b2a41c 100644 --- a/pcsx2/Sif.h +++ b/pcsx2/Sif.h @@ -37,6 +37,7 @@ struct sifData struct sifFifo { u32 data[FIFO_SIF_W]; + u32 junk[4]; s32 readPos; s32 writePos; s32 size; @@ -52,7 +53,10 @@ struct sifFifo { const int wP0 = std::min((FIFO_SIF_W - writePos), words); const int wP1 = words - wP0; - + if (size < 4) + { + memcpy(&junk[size], from, (4 - size) << 2); + } memcpy(&data[writePos], from, wP0 << 2); memcpy(&data[0], &from[wP0], wP1 << 2); @@ -62,6 +66,22 @@ struct sifFifo SIF_LOG(" SIF + %d = %d (pos=%d)", words, size, writePos); } + void writeJunk(int words) + { + if (words > 0) + { + const int wP0 = std::min((FIFO_SIF_W - writePos), words); + const int wP1 = words - wP0; + + memcpy(&data[writePos], &junk[4-words], wP0 << 2); + memcpy(&data[0], &junk[(4 - words)+wP0], wP1 << 2); + + writePos = (writePos + words) & (FIFO_SIF_W - 1); + size += words; + } + SIF_LOG(" SIF + %d = %d (pos=%d)", words, size, writePos); + } + void read(u32 *to, int words) { if (words > 0) diff --git a/pcsx2/Sif0.cpp b/pcsx2/Sif0.cpp index 05a814a61b..5c86646b33 100644 --- a/pcsx2/Sif0.cpp +++ b/pcsx2/Sif0.cpp @@ -23,6 +23,7 @@ _sif sif0; static bool done = false; +static int writeJunk = 0; static __fi void Sif0Init() { @@ -83,6 +84,12 @@ static __fi bool WriteIOPtoFifo() sif0.iop.cycles += (writeSize >> 2)/* * BIAS*/; // fixme : should be >> 4 sif0.iop.counter -= writeSize; + if (sif0.iop.counter == 0 && writeJunk) + { + SIF_LOG("Writing Junk %d", writeJunk); + sif0.fifo.writeJunk(writeJunk); + writeJunk = 0; + } return true; } @@ -92,7 +99,7 @@ static __fi bool ProcessEETag() static __aligned16 u32 tag[4]; tDMA_TAG& ptag(*(tDMA_TAG*)tag); - sif0.fifo.read((u32*)&tag[0], 4); // Tag + sif0.fifo.read((u32*)&tag[0], 2); // Tag SIF_LOG("SIF0 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]); sif0ch.unsafeTransfer(&ptag); @@ -128,26 +135,27 @@ static __fi bool ProcessIOPTag() { // Process DMA tag at hw_dma9.tadr sif0.iop.data = *(sifData *)iopPhysMem(hw_dma9.tadr); - sif0.iop.data.words = (sif0.iop.data.words + 3) & 0xfffffffc; // Round up to nearest 4. + sif0.iop.data.words = sif0.iop.data.words; // send the EE's side of the DMAtag. The tag is only 64 bits, with the upper 64 bits // ignored by the EE. sif0.fifo.write((u32*)iopPhysMem(hw_dma9.tadr + 8), 2); - sif0.fifo.writePos = (sif0.fifo.writePos + 2) & (FIFO_SIF_W - 1); // iggy on the upper 64. - sif0.fifo.size += 2; + //sif0.fifo.writePos = (sif0.fifo.writePos + 2) & (FIFO_SIF_W - 1); // iggy on the upper 64. + //sif0.fifo.size += 2; hw_dma9.tadr += 16; ///hw_dma9.madr + 16 + sif0.sifData.words << 2; // We're only copying the first 24 bits. Bits 30 and 31 (checked below) are Stop/IRQ bits. hw_dma9.madr = sif0data & 0xFFFFFF; - if (sif0words > 0xFFFFC) DevCon.Warning("SIF0 Overrun %x", sif0words); + if (sif0words > 0xFFFFF) DevCon.Warning("SIF0 Overrun %x", sif0words); //Maximum transfer amount 1mb-16 also masking out top part which is a "Mode" cache stuff, we don't care :) - sif0.iop.counter = sif0words & 0xFFFFC; + sif0.iop.counter = sif0words & 0xFFFFF; + writeJunk = (sif0.iop.counter & 0x3) ? (4 - sif0.iop.counter & 0x3) : 0; // IOP tags have an IRQ bit and an End of Transfer bit: if (sif0tag.IRQ || (sif0tag.ID & 4)) sif0.iop.end = true; - SIF_LOG("SIF0 IOP Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X)", hw_dma9.madr, hw_dma9.tadr, sif0.iop.counter, sif0words, sif0data); + SIF_LOG("SIF0 IOP Tag: madr=%lx, tadr=%lx, counter=%lx (%08X_%08X) Junk %d", hw_dma9.madr, hw_dma9.tadr, sif0.iop.counter, sif0words, sif0data, writeJunk); return true; }