SIF: Transfer SIF0 junk for partial QW transfers from IOP

Fixes True Crime: Streets of LA
This commit is contained in:
refractionpcsx2 2020-10-02 15:44:48 +01:00
parent 435b7dcd2b
commit 1a3b532530
2 changed files with 36 additions and 8 deletions

View File

@ -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)

View File

@ -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;
}