mirror of https://github.com/PCSX2/pcsx2.git
SIF: Correct junk data behaviour. Fixes True Crime Streets of LA
This commit is contained in:
parent
2695ddc9fc
commit
72f9bf83fd
62
pcsx2/Sif.h
62
pcsx2/Sif.h
|
@ -50,12 +50,6 @@ struct sifFifo
|
|||
if ((FIFO_SIF_W - size) < words)
|
||||
DevCon.Warning("Not enough space in SIF0 FIFO!\n");
|
||||
|
||||
if (size < 4)
|
||||
{
|
||||
u32 amt = std::min(4 - size, words);
|
||||
memcpy(&junk[size], from, amt << 2);
|
||||
}
|
||||
|
||||
const int wP0 = std::min((FIFO_SIF_W - writePos), words);
|
||||
const int wP1 = words - wP0;
|
||||
|
||||
|
@ -68,22 +62,66 @@ struct sifFifo
|
|||
SIF_LOG(" SIF + %d = %d (pos=%d)", words, size, writePos);
|
||||
}
|
||||
|
||||
// Junk data writing
|
||||
//
|
||||
// If there is not enough data produced from the IOP, it will always use the previous full quad word to
|
||||
// fill in the missing data.
|
||||
// One thing to note, when the IOP transfers the EE tag, it transfers a whole QW of data, which will include
|
||||
// the EE Tag and the next IOP tag, since the EE reads 1QW of data for DMA tags.
|
||||
//
|
||||
// So the data used will be as follows:
|
||||
// Less than 1QW = Junk data is made up of the EE tag + address (64 bits) and the following IOP tag (64 bits).
|
||||
// More than 1QW = Junk data is made up of the last complete QW of data that was transferred in this packet.
|
||||
//
|
||||
// Data is always offset in to the junk by the amount the IOP actually transferred, so if it sent 2 words
|
||||
// it will read words 3 and 4 out of the junk to fill the space.
|
||||
//
|
||||
// PS2 test results:
|
||||
//
|
||||
// Example of less than 1QW being sent with the only data being set being 0x69
|
||||
//
|
||||
// addr 0x1500a0 value 0x69 <-- actual data (junk behind this would be the EE tag)
|
||||
// addr 0x1500a4 value 0x1500a0 <-- EE address
|
||||
// addr 0x1500a8 value 0x8001a170 <-- following IOP tag
|
||||
// addr 0x1500ac value 0x10 <-- following IOP tag word count
|
||||
//
|
||||
// Example of more than 1QW being sent with the data going from 0x20 to 0x25
|
||||
//
|
||||
// addr 0x150080 value 0x21 <-- start of previously completed QW
|
||||
// addr 0x150084 value 0x22
|
||||
// addr 0x150088 value 0x23
|
||||
// addr 0x15008c value 0x24 <-- end of previously completed QW
|
||||
// addr 0x150090 value 0x25 <-- end of recorded data
|
||||
// addr 0x150094 value 0x22 <-- from position 2 of the previously completed quadword
|
||||
// addr 0x150098 value 0x23 <-- from position 3 of the previously completed quadword
|
||||
// addr 0x15009c value 0x24 <-- from position 4 of the previously completed quadword
|
||||
|
||||
void writeJunk(int words)
|
||||
{
|
||||
if (words > 0)
|
||||
{
|
||||
if ((FIFO_SIF_W - size) < words)
|
||||
DevCon.Warning("Not enough Junk space in SIF0 FIFO!\n");
|
||||
// Get the start position of the previously completed whole QW.
|
||||
// Position is in word (32bit) units.
|
||||
const int transferredWords = 4 - words;
|
||||
const int prevQWPos = (writePos - (4 + transferredWords)) & (FIFO_SIF_W - 1);
|
||||
|
||||
// Read the old data in to our junk array in case of wrapping.
|
||||
const int rP0 = std::min((FIFO_SIF_W - prevQWPos), 4);
|
||||
const int rP1 = 4 - rP0;
|
||||
memcpy(&junk[0], &data[prevQWPos], rP0 << 2);
|
||||
memcpy(&junk[rP0], &data[0], rP1 << 2);
|
||||
|
||||
// Fill the missing words to fill the QW.
|
||||
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);
|
||||
memcpy(&data[writePos], &junk[4- wP0], wP0 << 2);
|
||||
memcpy(&data[0], &junk[wP0], wP1 << 2);
|
||||
|
||||
writePos = (writePos + words) & (FIFO_SIF_W - 1);
|
||||
size += words;
|
||||
|
||||
SIF_LOG(" SIF + %d = %d Junk (pos=%d)", words, size, writePos);
|
||||
}
|
||||
SIF_LOG(" SIF + %d = %d (pos=%d)", words, size, writePos);
|
||||
}
|
||||
|
||||
void read(u32 *to, int words)
|
||||
|
|
|
@ -95,7 +95,7 @@ static __fi bool ProcessEETag()
|
|||
alignas(16) static u32 tag[4];
|
||||
tDMA_TAG& ptag(*(tDMA_TAG*)tag);
|
||||
|
||||
sif0.fifo.read((u32*)&tag[0], 2); // Tag
|
||||
sif0.fifo.read((u32*)&tag[0], 4); // Tag
|
||||
SIF_LOG("SIF0 EE read tag: %x %x %x %x", tag[0], tag[1], tag[2], tag[3]);
|
||||
|
||||
sif0ch.unsafeTransfer(&ptag);
|
||||
|
@ -133,14 +133,13 @@ static __fi bool ProcessIOPTag()
|
|||
sif0.iop.data = *(sifData *)iopPhysMem(hw_dma9.tadr);
|
||||
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.
|
||||
// send the EE's side of the DMAtag. The tag is only 64 bits, with the upper 64 bits being the next IOP tag
|
||||
// ignored by the EE, however required for alignment and used as junk data in small packets.
|
||||
sif0.fifo.write((u32*)iopPhysMem(hw_dma9.tadr + 8), 4);
|
||||
|
||||
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;
|
||||
|
||||
hw_dma9.tadr += 16; ///hw_dma9.madr + 16 + sif0.sifData.words << 2;
|
||||
// I know we just sent 1QW, because of the size of the EE read, but only 64bits was valid
|
||||
// so we advance by 64bits after the EE tag to get the next IOP tag.
|
||||
hw_dma9.tadr += 16;
|
||||
|
||||
// We're only copying the first 24 bits. Bits 30 and 31 (checked below) are Stop/IRQ bits.
|
||||
hw_dma9.madr = sif0data & 0xFFFFFF;
|
||||
|
@ -148,7 +147,9 @@ static __fi bool ProcessIOPTag()
|
|||
//Maximum transfer amount 1mb-16 also masking out top part which is a "Mode" cache stuff, we don't care :)
|
||||
sif0.iop.counter = sif0words & 0xFFFFF;
|
||||
|
||||
// Save the number of words we need to write to make up 1QW from this packet. (See "Junk data writing" in Sif.h)
|
||||
sif0.iop.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) Junk %d", hw_dma9.madr, hw_dma9.tadr, sif0.iop.counter, sif0words, sif0data, sif0.iop.writeJunk);
|
||||
|
|
Loading…
Reference in New Issue