Skip to content

Commit

Permalink
SPR: Wrap transfers which would have read outside of SPR memory
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Jan 20, 2021
1 parent 99f8d2f commit 2ffc6b3
Showing 1 changed file with 26 additions and 14 deletions.
40 changes: 26 additions & 14 deletions pcsx2/SPR.cpp
Expand Up @@ -104,7 +104,16 @@ int _SPR0chain()

if(spr0ch.madr >= dmacRegs.rbor.ADDR && spr0ch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u))
{
partialqwc = spr0ch.qwc;
if (dmacRegs.rbsr.RMSK == 0) // Shortcut when MFIFO isn't set up with a size (Hitman series)
{
spr0ch.madr += spr0ch.qwc << 4;
spr0ch.sadr += spr0ch.qwc << 4;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.qwc = 0;
}
else
{
partialqwc = std::min(spr0ch.qwc, 0x400 - ((spr0ch.sadr & 0x3fff) >> 4));

if ((spr0ch.madr & ~dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR)
Console.WriteLn("SPR MFIFO Write outside MFIFO area");
Expand All @@ -117,24 +126,24 @@ int _SPR0chain()
spr0ch.sadr += partialqwc << 4;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.qwc -= partialqwc;

spr0finished = true;
}
spr0finished = true;
}
else
{

// Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of
// the cycle delay out of the way before the end.
partialqwc = spr0ch.qwc;
memcpy_from_spr((u8*)pMem, spr0ch.sadr, partialqwc*16);
// Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of
// the cycle delay out of the way before the end.
partialqwc = std::min(spr0ch.qwc, 0x400 - ((spr0ch.sadr & 0x3fff) >> 4));
memcpy_from_spr((u8*)pMem, spr0ch.sadr, partialqwc*16);

// Clear VU mem also!
TestClearVUs(spr0ch.madr, partialqwc, true);
// Clear VU mem also!
TestClearVUs(spr0ch.madr, partialqwc, true);

spr0ch.madr += partialqwc << 4;
spr0ch.sadr += partialqwc << 4;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.qwc -= partialqwc;
spr0ch.madr += partialqwc << 4;
spr0ch.sadr += partialqwc << 4;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.qwc -= partialqwc;

}

Expand Down Expand Up @@ -176,6 +185,9 @@ void _SPR0interleave()
qwc -= spr0ch.qwc;
pMem = SPRdmaGetAddr(spr0ch.madr, true);

if(spr0ch.qwc > (0x400 - ((spr0ch.sadr & 0x3fff) >> 4)))
DevCon.Warning("Warning! Interleave on SPR0 going outside of SPR memory!");

switch (dmacRegs.ctrl.MFD)
{
case MFD_VIF1:
Expand Down Expand Up @@ -364,7 +376,7 @@ int _SPR1chain()
int partialqwc = 0;
// Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of
// the cycle delay out of the way before the end.
partialqwc = spr1ch.qwc;
partialqwc = std::min(spr1ch.qwc, 0x400u);

SPR1transfer(pMem, partialqwc);
spr1ch.madr += partialqwc * 16;
Expand Down

0 comments on commit 2ffc6b3

Please sign in to comment.