MFIFO: Added protection on MADR when it is on the edge of the ring buffer when setting the DMA Tag where the data follows the Tag.

Fixes Front Mission 4.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5585 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction@gmail.com 2013-03-11 16:02:56 +00:00
parent e8b09949f8
commit b7d28572a2
2 changed files with 57 additions and 1 deletions

View File

@ -360,7 +360,7 @@ static __fi bool mfifoGIFchain()
if (gifch.qwc == 0) return true;
if (gifch.madr >= dmacRegs.rbor.ADDR &&
gifch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
{
bool ret = true;
// if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF");
@ -390,6 +390,32 @@ static u32 qwctag(u32 mask) {
return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
}
void mfifoGifMaskMem(int id)
{
switch (id) {
//These five transfer data following the tag, need to check its within the buffer (Front Mission 4)
case TAG_CNT:
case TAG_NEXT:
case TAG_CALL:
case TAG_RET:
case TAG_END:
if(gifch.madr < dmacRegs.rbor.ADDR) //probably not needed but we will check anyway.
{
//DevCon.Warning("GIF MFIFO MADR below bottom of ring buffer, wrapping GIF MADR = %x Ring Bottom %x", gifch.madr, dmacRegs.rbor.ADDR);
gifch.madr = qwctag(gifch.madr);
}
if(gifch.madr > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4)
{
//DevCon.Warning("GIF MFIFO MADR outside top of ring buffer, wrapping GIF MADR = %x Ring Top %x", gifch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16);
gifch.madr = qwctag(gifch.madr);
}
break;
default:
//Do nothing as the MADR could be outside
break;
}
}
void mfifoGIFtransfer(int qwc)
{
tDMA_TAG *ptag;
@ -426,6 +452,8 @@ void mfifoGIFtransfer(int qwc)
gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
mfifoGifMaskMem(ptag->ID);
if(gspath3done == true) gifstate = GIF_STATE_DONE;
else gifstate = GIF_STATE_READY;

View File

@ -145,6 +145,32 @@ static __fi void mfifo_VIF1chain()
}
}
void mfifoVifMaskMem(int id)
{
switch (id) {
//These five transfer data following the tag, need to check its within the buffer (Front Mission 4)
case TAG_CNT:
case TAG_NEXT:
case TAG_CALL:
case TAG_RET:
case TAG_END:
if(vif1ch.madr < dmacRegs.rbor.ADDR) //probably not needed but we will check anyway.
{
//DevCon.Warning("VIF MFIFO MADR below bottom of ring buffer, wrapping VIF MADR = %x Ring Bottom %x", vif1ch.madr, dmacRegs.rbor.ADDR);
vif1ch.madr = qwctag(vif1ch.madr);
}
if(vif1ch.madr > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)) //Usual scenario is the tag is near the end (Front Mission 4)
{
//DevCon.Warning("VIF MFIFO MADR outside top of ring buffer, wrapping VIF MADR = %x Ring Top %x", vif1ch.madr, (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)+16);
vif1ch.madr = qwctag(vif1ch.madr);
}
break;
default:
//Do nothing as the MADR could be outside
break;
}
}
void mfifoVIF1transfer(int qwc)
{
tDMA_TAG *ptag;
@ -223,6 +249,8 @@ void mfifoVIF1transfer(int qwc)
vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
mfifoVifMaskMem(ptag->ID);
if (vif1ch.chcr.TIE && ptag->IRQ)
{
VIF_LOG("dmaIrq Set");