mirror of https://github.com/PCSX2/pcsx2.git
-Fixed a small bug in the unpack dynarec causing it to drop back to the interpreter (MGS3 - now about 10fps faster!)
-Rewrote VIF0 DMA to work like VIF1, report any breakage from it. -Tweaked a couple of cycle bits when stalling VIF git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2766 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
b1e6094408
commit
928816732b
|
@ -143,13 +143,8 @@ _f void vif0FBRST(u32 value) {
|
|||
g_vifCycles = 0;
|
||||
|
||||
// loop necessary for spiderman
|
||||
if (vif0.stallontag)
|
||||
_chainVIF0();
|
||||
else
|
||||
_VIF0chain();
|
||||
|
||||
vif0ch->chcr.STR = true;
|
||||
CPU_INT(DMAC_VIF0, g_vifCycles); // Gets the timing right - Flatout
|
||||
CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -225,14 +220,14 @@ _f void vif1FBRST(u32 value) {
|
|||
{
|
||||
case MFD_VIF1:
|
||||
//Console.WriteLn("MFIFO Stall");
|
||||
CPU_INT(10, vif1ch->qwc * BIAS);
|
||||
CPU_INT(10, 0);
|
||||
break;
|
||||
|
||||
case NO_MFD:
|
||||
case MFD_RESERVED:
|
||||
case MFD_GIF: // Wonder if this should be with VIF?
|
||||
// Gets the timing right - Flatout
|
||||
CPU_INT(DMAC_VIF1, vif1ch->qwc * BIAS);
|
||||
CPU_INT(DMAC_VIF1, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,15 @@ __forceinline void vif0FLUSH()
|
|||
g_vifCycles += (VU0.cycle - _cycles) * BIAS;
|
||||
}
|
||||
|
||||
bool _VIF0chain()
|
||||
bool _VIF0chain()
|
||||
{
|
||||
u32 *pMem;
|
||||
|
||||
if ((vif0ch->qwc == 0) && !vif0.vifstalled) return true;
|
||||
if (vif0ch->qwc == 0)
|
||||
{
|
||||
vif0.inprogress = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
pMem = (u32*)dmaGetAddr(vif0ch->madr);
|
||||
if (pMem == NULL)
|
||||
|
@ -44,88 +48,115 @@ bool _VIF0chain()
|
|||
return true;
|
||||
}
|
||||
|
||||
VIF_LOG("VIF0chain size=%d, madr=%lx, tadr=%lx",
|
||||
vif0ch->qwc, vif0ch->madr, vif0ch->tadr);
|
||||
|
||||
if (vif0.vifstalled)
|
||||
return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset, false);
|
||||
else
|
||||
return VIF0transfer(pMem, vif0ch->qwc * 4, false);
|
||||
}
|
||||
|
||||
bool _chainVIF0()
|
||||
__forceinline void vif0SetupTransfer()
|
||||
{
|
||||
tDMA_TAG *ptag;
|
||||
|
||||
ptag = dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR
|
||||
|
||||
if (!(vif0ch->transfer("Vif0 Tag", ptag))) return false;
|
||||
|
||||
vif0ch->madr = ptag[1]._u32; // MADR = ADDR field + SPR
|
||||
g_vifCycles += 1; // Increase the QW read for the tag
|
||||
|
||||
VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, vif0ch->qwc, ptag->ID, vif0ch->madr, vif0ch->tadr);
|
||||
|
||||
// Transfer dma tag if tte is set
|
||||
if (vif0ch->chcr.TTE)
|
||||
switch (vif0.dmamode)
|
||||
{
|
||||
bool ret;
|
||||
case VIF_NORMAL_TO_MEM_MODE:
|
||||
vif0.inprogress = 1;
|
||||
vif0.done = true;
|
||||
g_vifCycles = 2;
|
||||
break;
|
||||
|
||||
if (vif0.vifstalled)
|
||||
ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, true); //Transfer Tag on stall
|
||||
else
|
||||
ret = VIF0transfer((u32*)ptag + 2, 2, true); //Transfer Tag
|
||||
case VIF_CHAIN_MODE:
|
||||
ptag = dmaGetAddr(vif0ch->tadr); //Set memory pointer to TADR
|
||||
|
||||
if (!(ret)) return false; //IRQ set by VIFTransfer
|
||||
if (!(vif0ch->transfer("vif0 Tag", ptag))) return;
|
||||
|
||||
vif0ch->madr = ptag[1]._u32; //MADR = ADDR field + SPR
|
||||
g_vifCycles += 1; // Add 1 g_vifCycles from the QW read for the tag
|
||||
|
||||
// Transfer dma tag if tte is set
|
||||
|
||||
VIF_LOG("vif0 Tag %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx\n",
|
||||
ptag[1]._u32, ptag[0]._u32, vif0ch->qwc, ptag->ID, vif0ch->madr, vif0ch->tadr);
|
||||
|
||||
vif0.inprogress = 1;
|
||||
|
||||
if (vif0ch->chcr.TTE)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (vif0.vifstalled)
|
||||
ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, true); //Transfer Tag on stall
|
||||
else
|
||||
ret = VIF0transfer((u32*)ptag + 2, 2, true); //Transfer Tag
|
||||
|
||||
if ((ret == false) && vif0.irqoffset < 2)
|
||||
{
|
||||
vif0.inprogress = 0; //Better clear this so it has to do it again (Jak 1)
|
||||
return; //There has been an error or an interrupt
|
||||
}
|
||||
}
|
||||
|
||||
vif0.irqoffset = 0;
|
||||
vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
|
||||
|
||||
//Check TIE bit of CHCR and IRQ bit of tag
|
||||
if (vif0ch->chcr.TIE && ptag->IRQ)
|
||||
{
|
||||
VIF_LOG("dmaIrq Set");
|
||||
|
||||
//End Transfer
|
||||
vif0.done = true;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vif0.done |= hwDmacSrcChainWithStack(vif0ch, ptag->ID);
|
||||
|
||||
VIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx",
|
||||
ptag[1]._u32, ptag[0]._u32, vif0ch->qwc, ptag->ID, vif0ch->madr, vif0ch->tadr);
|
||||
|
||||
_VIF0chain(); //Transfers the data set by the switch
|
||||
|
||||
if (vif0ch->chcr.TIE && ptag->IRQ) //Check TIE bit of CHCR and IRQ bit of tag
|
||||
{
|
||||
VIF_LOG("dmaIrq Set\n");
|
||||
vif0.done = true; //End Transfer
|
||||
}
|
||||
|
||||
return vif0.done;
|
||||
}
|
||||
|
||||
void vif0Interrupt()
|
||||
__forceinline void vif0Interrupt()
|
||||
{
|
||||
g_vifCycles = 0; //Reset the cycle count, Wouldn't reset on stall if put lower down.
|
||||
VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle);
|
||||
|
||||
if (vif0.irq && (vif0.tag.size == 0))
|
||||
g_vifCycles = 0;
|
||||
|
||||
if (!(vif0ch->chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch->chcr._u32);
|
||||
|
||||
if (vif0.irq && vif0.tag.size == 0)
|
||||
{
|
||||
vif0Regs->stat.INT = true;
|
||||
hwIntcIrq(VIF0intc);
|
||||
--vif0.irq;
|
||||
|
||||
if (vif0Regs->stat.test(VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS))
|
||||
{
|
||||
vif0Regs->stat.FQC = 0;
|
||||
|
||||
// One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho
|
||||
vif0ch->chcr.STR = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (vif0ch->qwc > 0 || vif0.irqoffset > 0)
|
||||
else if ((vif0ch->qwc > 0) || (vif0.irqoffset > 0))
|
||||
{
|
||||
if (vif0.stallontag)
|
||||
_chainVIF0();
|
||||
vif0SetupTransfer();
|
||||
else
|
||||
_VIF0chain();
|
||||
|
||||
CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
return;
|
||||
_VIF0chain();//CPU_INT(DMAC_STALL_SIS, vif0ch->qwc * BIAS);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vif0ch->chcr.STR) Console.WriteLn("Vif0 running when CHCR = %x", vif0ch->chcr._u32);
|
||||
if (vif0.inprogress & 0x1)
|
||||
{
|
||||
_VIF0chain();
|
||||
// VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
|
||||
// Timesplitters 2 depends on this beeing a bit higher than 128.
|
||||
if (vif0.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF0, 1024);
|
||||
else CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((vif0ch->chcr.MOD == CHAIN_MODE) && (!vif0.done))
|
||||
if (!vif0.done)
|
||||
{
|
||||
|
||||
if (!(dmacRegs->ctrl.DMAE))
|
||||
|
@ -134,19 +165,26 @@ void vif0Interrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
if (vif0ch->qwc > 0)
|
||||
_VIF0chain();
|
||||
else
|
||||
_chainVIF0();
|
||||
if ((vif0.inprogress & 0x1) == 0) vif0SetupTransfer();
|
||||
|
||||
CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vif0ch->qwc > 0) Console.WriteLn("VIF0 Ending with QWC left");
|
||||
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x", vif0.cmd);
|
||||
if (vif0.vifstalled && vif0.irq)
|
||||
{
|
||||
DevCon.WriteLn("VIF0 looping on stall\n");
|
||||
CPU_INT(DMAC_VIF0, 0);
|
||||
return; //Dont want to end if vif is stalled.
|
||||
}
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
if (vif0ch->qwc > 0) Console.WriteLn("vif0 Ending with %x QWC left");
|
||||
if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size);
|
||||
#endif
|
||||
|
||||
vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands;
|
||||
vif0ch->chcr.STR = false;
|
||||
g_vifCycles = 0;
|
||||
hwDmacIrq(DMAC_VIF0);
|
||||
vif0Regs->stat.FQC = 0;
|
||||
}
|
||||
|
@ -154,30 +192,28 @@ void vif0Interrupt()
|
|||
void dmaVIF0()
|
||||
{
|
||||
VIF_LOG("dmaVIF0 chcr = %lx, madr = %lx, qwc = %lx\n"
|
||||
" tadr = %lx, asr0 = %lx, asr1 = %lx\n",
|
||||
" tadr = %lx, asr0 = %lx, asr1 = %lx",
|
||||
vif0ch->chcr._u32, vif0ch->madr, vif0ch->qwc,
|
||||
vif0ch->tadr, vif0ch->asr0, vif0ch->asr1);
|
||||
|
||||
g_vifCycles = 0;
|
||||
vif0.inprogress = 0;
|
||||
|
||||
vif0Regs->stat.FQC = 0x8; // FQC=8
|
||||
|
||||
if (!(vif0ch->chcr.MOD & 0x1) || vif0ch->qwc > 0) // Normal Mode
|
||||
if ((vif0ch->chcr.MOD == NORMAL_MODE) || vif0ch->qwc > 0) // Normal Mode
|
||||
{
|
||||
if (!_VIF0chain())
|
||||
{
|
||||
Console.WriteLn(L"Stall on normal vif0 " + vif0Regs->stat.desc());
|
||||
|
||||
vif0.vifstalled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
vif0.done = true;
|
||||
CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo);
|
||||
return;
|
||||
vif0.dmamode = VIF_NORMAL_TO_MEM_MODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
vif0.dmamode = VIF_CHAIN_MODE;
|
||||
}
|
||||
|
||||
if (vif0.dmamode != VIF_NORMAL_FROM_MEM_MODE)
|
||||
vif0Regs->stat.FQC = 0x8;
|
||||
else
|
||||
vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc);
|
||||
|
||||
// Chain Mode
|
||||
vif0.done = false;
|
||||
CPU_INT(DMAC_VIF0, 0);
|
||||
}
|
||||
vif0Interrupt();
|
||||
}
|
|
@ -262,6 +262,7 @@ __forceinline void vif1Interrupt()
|
|||
|
||||
if (vif1.vifstalled && vif1.irq)
|
||||
{
|
||||
DevCon.WriteLn("VIF1 looping on stall\n");
|
||||
CPU_INT(DMAC_VIF1, 0);
|
||||
return; //Dont want to end if vif is stalled.
|
||||
}
|
||||
|
|
|
@ -186,12 +186,16 @@ static _f u8* dVifsetVUptr(const nVifStruct& v, int cl, int wl, bool isFill) {
|
|||
if (!isFill) { // Account for skip-cycles
|
||||
int skipSize = cl - wl;
|
||||
int blocks = _vBlock.num / wl;
|
||||
int skips = (blocks * skipSize + _vBlock.num) * 16;
|
||||
int skips = (blocks * skipSize + _vBlock.num) * 16;
|
||||
|
||||
//We must do skips - 1 here else skip calculation adds an extra skip which can overflow
|
||||
//causing the emu to drop back to the interpreter (do not need to skip on last block write) - Refraction
|
||||
if(skipSize > 0) skips -= skipSize * 16;
|
||||
endPtr = ptr + skips;
|
||||
}
|
||||
else endPtr = ptr + (_vBlock.num * 16);
|
||||
if ( endPtr > v.vuMemEnd ) {
|
||||
DevCon.WriteLn("nVif - VU Mem Ptr Overflow; falling back to interpreter.");
|
||||
DevCon.WriteLn("nVif%x - VU Mem Ptr Overflow; falling back to interpreter. Start = %x End = %x num = %x, wl = %x, cl = %x", v.idx, v.vif->tag.addr, v.vif->tag.addr + (_vBlock.num * 16), _vBlock.num, wl, cl);
|
||||
ptr = NULL; // Fall Back to Interpreters which have wrap-around logic
|
||||
}
|
||||
return ptr;
|
||||
|
|
Loading…
Reference in New Issue