Improved my previous fix, Psychonaughts exhibited behaviour sudo mentioned (data not being grabbed from VU) so added a seperate SPR handler.

Removed an old check which is useless now and added a new replacement one.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2890 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction 2010-04-24 18:59:31 +00:00
parent e99837abaf
commit 662d589217
8 changed files with 65 additions and 39 deletions

View File

@ -627,6 +627,47 @@ static __forceinline bool inScratchpad(u32 addr)
return ((addr >=0x70000000) && (addr <= 0x70003fff));
}
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
static __forceinline tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write)
{
// if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); }
//Probably dont need these.
if (DMA_TAG(addr).SPR) return (tDMA_TAG*)&psS[addr & 0x3ff0];
// Need to check the physical address as well as just the "SPR" flag, as VTLB doesn't seem to handle it.--refraction
if (inScratchpad(addr))
{
//Console.Warning("Writing to the scratchpad without the SPR flag set!");
return (tDMA_TAG*)&psS[addr & 0x3ff0];
}
// FIXME: Why??? DMA uses physical addresses
if ((addr & 0x7ffffff0) >= 0x20000000)
{
Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
return NULL;
}
addr &= 0x1ffffff0;
if (addr >= 0x11004000 && addr < 0x11010000)
{
//Access for VU Memory
return (tDMA_TAG*)vtlb_GetPhyPtr(addr & 0x1FFFFFF0);
}
if (addr > Ps2MemSize::Base)
{
return (tDMA_TAG*)(write ? psMHW : psMHR);
}
return (tDMA_TAG*)&psM[addr];
}
// Note: Dma addresses are guaranteed to be aligned to 16 bytes (128 bits)
static __forceinline tDMA_TAG *dmaGetAddr(u32 addr, bool write)
{
@ -642,14 +683,16 @@ static __forceinline tDMA_TAG *dmaGetAddr(u32 addr, bool write)
}
// FIXME: Why??? DMA uses physical addresses
addr &= 0x3ffffff0;
if (addr >= 0x20000000)
if ((addr & 0x7ffffff0) >= 0x20000000)
{
Console.Error( "*PCSX2*: DMA error: %8.8x", addr);
return NULL;
}
addr &= 0x1ffffff0;
if (addr > Ps2MemSize::Base)
{
return (tDMA_TAG*)(write ? psMHW : psMHR);

View File

@ -75,10 +75,6 @@ __forceinline void gsInterrupt()
return;
}
// Champions: Return to Arms prints this a lot.
if((gif->chcr.MOD == CHAIN_MODE) && ((gif->chcr.TAG >> 12) & 0x7) != 0x0 && ((gif->chcr.TAG >> 12) & 0x7) != 0x7 && !((gif->chcr.TAG >> 12) & 0x8))
DevCon.Warning("GIF Ending when refe or end not set! CHCR = %x", gif->chcr._u32);
gspath3done = false;
gscycles = 0;
gif->chcr.STR = false;
@ -358,6 +354,7 @@ void dmaGIF()
//Halflife sets a QWC amount in chain mode, no tadr set.
if (gif->qwc > 0) gspath3done = true;
if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0) DevCon.Warning("GIF QWC on Chain CHCR = %x", gif->chcr);
GIFdma();
}

View File

@ -52,7 +52,7 @@ int _SPR0chain()
tDMA_TAG *pMem;
if (spr0->qwc == 0) return 0;
pMem = dmaGetAddr(spr0->madr, true);
pMem = SPRdmaGetAddr(spr0->madr, true);
if (pMem == NULL) return -1;
switch (dmacRegs->ctrl.MFD)
@ -106,7 +106,7 @@ void _SPR0interleave()
{
spr0->qwc = std::min(tqwc, qwc);
qwc -= spr0->qwc;
pMem = dmaGetAddr(spr0->madr, true);
pMem = SPRdmaGetAddr(spr0->madr, true);
switch (dmacRegs->ctrl.MFD)
{
@ -252,8 +252,6 @@ void SPRFROMinterrupt()
}
if (!spr0finished) return;
if((spr0->chcr.MOD == CHAIN_MODE) && ((spr0->chcr.TAG >> 12) & 0x7) != 0x0 && ((spr0->chcr.TAG >> 12) & 0x7) != 0x7 && !((spr0->chcr.TAG >> 12) & 0x8))
DevCon.Warning("SPR0 Ending when refe or end not set! CHCR = %x", spr0->chcr._u32);
spr0->chcr.STR = false;
hwDmacIrq(DMAC_FROM_SPR);
@ -271,6 +269,7 @@ void dmaSPR0() // fromSPR
CPU_INT(DMAC_FROM_SPR, /*ptag[0].QWC / BIAS*/ 4 );
return;
}
if(spr0->chcr.MOD == CHAIN_MODE && spr0->qwc > 0) DevCon.Warning("SPR0 QWC on Chain CHCR = %x", spr0->chcr);
// COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values
// It merely assumes that the last one has finished then starts another one (broke with the DMA fix)
// This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction)
@ -290,7 +289,7 @@ int _SPR1chain()
if (spr1->qwc == 0) return 0;
pMem = dmaGetAddr(spr1->madr, false);
pMem = SPRdmaGetAddr(spr1->madr, false);
if (pMem == NULL) return -1;
SPR1transfer((u32*)pMem, spr1->qwc << 2);
@ -320,7 +319,7 @@ void _SPR1interleave()
{
spr1->qwc = std::min(tqwc, qwc);
qwc -= spr1->qwc;
pMem = dmaGetAddr(spr1->madr, false);
pMem = SPRdmaGetAddr(spr1->madr, false);
memcpy_fast(&psSu8(spr1->sadr), (u8*)pMem, spr1->qwc << 4);
spr1->sadr += spr1->qwc * 16;
spr1->madr += (sqwc + spr1->qwc) * 16;
@ -356,7 +355,7 @@ void _dmaSPR1() // toSPR work function
}
// Chain Mode
ptag = dmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
if (!spr1->transfer("SPR1 Tag", ptag))
{
@ -390,7 +389,7 @@ void _dmaSPR1() // toSPR work function
spr1finished = done;
if (!done)
{
ptag = dmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
CPU_INT(DMAC_TO_SPR, /*(ptag[0].QWC / BIAS)*/ 4 );// the lower 16 bits of the tag / BIAS);
}
break;
@ -414,10 +413,11 @@ void dmaSPR1() // toSPR
if ((spr1->chcr.MOD == CHAIN_MODE) && (spr1->qwc == 0))
{
tDMA_TAG *ptag;
ptag = dmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR
CPU_INT(DMAC_TO_SPR, /*ptag[0].QWC / BIAS*/ 4 );
return;
}
if(spr1->chcr.MOD == CHAIN_MODE && spr1->qwc > 0) DevCon.Warning("SPR1 QWC on Chain CHCR = %x", spr1->chcr);
// COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values
// It merely assumes that the last one has finished then starts another one (broke with the DMA fix)
// This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction)
@ -429,9 +429,6 @@ void SPRTOinterrupt()
_dmaSPR1();
if (!spr1finished) return;
if((spr1->chcr.MOD == CHAIN_MODE) && ((spr1->chcr.TAG >> 12) & 0x7) != 0x0 && ((spr1->chcr.TAG >> 12) & 0x7) != 0x7 && !((spr1->chcr.TAG >> 12) & 0x8))
DevCon.Warning("SPR1 Ending when refe or end not set! CHCR = %x", spr1->chcr._u32);
spr1->chcr.STR = false;
hwDmacIrq(DMAC_TO_SPR);
}

View File

@ -151,8 +151,6 @@ static __forceinline void EndEE()
SIF_LOG("SIF0 EE: cycles = 0");
sif0.ee.cycles = 1;
}
if((sif0dma->chcr.MOD == CHAIN_MODE) && ((sif0dma->chcr.TAG >> 12) & 0x7) != 0x0 && ((sif0dma->chcr.TAG >> 12) & 0x7) != 0x7 && !((sif0dma->chcr.TAG >> 12) & 0x8))
DevCon.Warning("SIF0 Ending when refe or end not set! CHCR = %x", sif0dma->chcr._u32);
CPU_INT(DMAC_SIF0, sif0.ee.cycles*BIAS);
}
@ -314,6 +312,7 @@ __forceinline void dmaSIF0()
SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos");
}
if(sif0dma->chcr.MOD == CHAIN_MODE && sif0dma->qwc > 0) DevCon.Warning("SIF0 QWC on Chain CHCR = %x", sif0dma->chcr);
psHu32(SBUS_F240) |= 0x2000;
sif0.ee.busy = true;

View File

@ -175,8 +175,6 @@ static __forceinline void EndEE()
sif1.ee.cycles = 1;
}
if((sif1dma->chcr.MOD == CHAIN_MODE) && ((sif1dma->chcr.TAG >> 12) & 0x7) != 0x0 && ((sif1dma->chcr.TAG >> 12) & 0x7) != 0x7 && !((sif1dma->chcr.TAG >> 12) & 0x8))
DevCon.Warning("SIF0 Ending when refe or end not set! CHCR = %x", sif1dma->chcr._u32);
CPU_INT(DMAC_SIF1, min((int)(sif1.ee.cycles*BIAS), 384));
}
@ -311,6 +309,8 @@ __forceinline void dmaSIF1()
SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos");
}
if(sif1dma->chcr.MOD == CHAIN_MODE && sif1dma->qwc > 0) DevCon.Warning("SIF1 QWC on Chain CHCR = %x", sif1dma->chcr);
psHu32(SBUS_F240) |= 0x4000;
sif1.ee.busy = true;

View File

@ -182,9 +182,6 @@ __forceinline void vif0Interrupt()
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
#endif
/*if(vif0.dmamode == VIF_CHAIN_MODE && ((vif0ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif0ch->chcr.TAG >> 12) & 0x7) != 0x7 && !((vif0ch->chcr.TAG >> 12) & 0x8))
DevCon.Warning("VIF0 Ending when refe or end not set! CHCR = %x", vif0ch->chcr._u32);*/
vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
vif0ch->chcr.STR = false;
g_vifCycles = 0;
@ -205,6 +202,7 @@ void dmaVIF0()
if ((vif0ch->chcr.MOD == NORMAL_MODE) || vif0ch->qwc > 0) // Normal Mode
{
vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
if(vif0ch->chcr.MOD == CHAIN_MODE && vif0ch->qwc > 0) DevCon.Warning("VIF0 QWC on Chain CHCR = %x", vif0ch->chcr);
}
else
{

View File

@ -302,13 +302,6 @@ __forceinline void vif1Interrupt()
g_vifCycles = 0;
hwDmacIrq(DMAC_VIF1);
/*if(vif1.dmamode == VIF_CHAIN_MODE && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x7 && !((vif1ch->chcr.TAG >> 12) & 0x8))
DevCon.Warning("VIF1 Ending when refe or end not set! CHCR = %x", vif1ch->chcr._u32);*/
//Im not totally sure why Path3 Masking makes it want to see stuff in the fifo
//Games effected by setting, Fatal Frame, KH2, Shox, Crash N Burn, GT3/4 possibly
//Im guessing due to the full gs fifo before the reverse? (Refraction)
//Note also this is only the condition for reverse fifo mode, normal direction clears it as normal
//if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16);
}
void dmaVIF1()
@ -339,6 +332,8 @@ void dmaVIF1()
vif1.dmamode = VIF_NORMAL_FROM_MEM_MODE;
else
vif1.dmamode = VIF_NORMAL_TO_MEM_MODE;
if(vif1ch->chcr.MOD == CHAIN_MODE && vif1ch->qwc > 0) DevCon.Warning("VIF1 QWC on Chain CHCR = %x", vif1ch->chcr);
}
else
{

View File

@ -297,9 +297,6 @@ void vifMFIFOInterrupt()
hwDmacIrq(DMAC_MFIFO_EMPTY);
}*/
if(((vif1ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x7)
DevCon.Warning("VIF1 MFIFO Ending when refe or end not set! CHCR = %x", vif1ch->chcr._u32);
vif1.done = 1;
g_vifCycles = 0;
vif1ch->chcr.STR = false;