mirror of https://github.com/PCSX2/pcsx2.git
VU Int: Combine XGKick handling in to one function
Also fixed a situation where PATH3 could transfer a packet to the GIF and finish its DMA while PATH1 was busy, so PATH3 never finished transferring properly as it relies on the DMA to handle the pretend timing of PATH3.
This commit is contained in:
parent
b4eaf3722f
commit
c2af477758
|
@ -183,14 +183,13 @@ void incGifChAddr(u32 qwc)
|
|||
DevCon.Error("incGifAddr() Error!");
|
||||
}
|
||||
|
||||
__fi void gifCheckPathStatus()
|
||||
__fi void gifCheckPathStatus(bool calledFromGIF)
|
||||
{
|
||||
|
||||
if (gifRegs.stat.APATH == 3)
|
||||
{
|
||||
gifRegs.stat.APATH = 0;
|
||||
gifRegs.stat.OPH = 0;
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||
if (!calledFromGIF && (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE || gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT))
|
||||
{
|
||||
if (gifUnit.checkPaths(1, 1, 0))
|
||||
gifUnit.Execute(false, true);
|
||||
|
@ -200,12 +199,31 @@ __fi void gifCheckPathStatus()
|
|||
// Required for Path3 Masking timing!
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT)
|
||||
gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE;
|
||||
|
||||
// GIF DMA isn't running but VIF might be waiting on PATH3 so resume it here
|
||||
if (calledFromGIF && gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
{
|
||||
if (vif1Regs.stat.VGW)
|
||||
{
|
||||
// Check if VIF is in a cycle or is currently "idle" waiting for GIF to come back.
|
||||
if (!(cpuRegs.interrupt & (1 << DMAC_VIF1)))
|
||||
CPU_INT(DMAC_VIF1, 1);
|
||||
|
||||
// Make sure it loops if the GIF packet is empty to prepare for the next packet
|
||||
// or end if it was the end of a packet.
|
||||
// This must trigger after VIF retriggers as VIf might instantly mask Path3
|
||||
if ((!gifUnit.Path3Masked() || gifch.qwc == 0) && (gifch.chcr.STR || gif_fifo.fifoSize))
|
||||
{
|
||||
GifDMAInt(16);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__fi void gifInterrupt()
|
||||
{
|
||||
GIF_LOG("gifInterrupt caught qwc=%d fifo=%d apath=%d oph=%d state=%d!", gifch.qwc, gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state);
|
||||
gifCheckPathStatus();
|
||||
gifCheckPathStatus(false);
|
||||
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
{
|
||||
|
@ -249,7 +267,7 @@ __fi void gifInterrupt()
|
|||
if (readSize)
|
||||
GifDMAInt(readSize * BIAS);
|
||||
|
||||
gifCheckPathStatus();
|
||||
gifCheckPathStatus(false);
|
||||
// Double check as we might have read the fifo as it's ending the DMA
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
{
|
||||
|
@ -292,7 +310,7 @@ __fi void gifInterrupt()
|
|||
|
||||
if (gif_fifo.fifoSize)
|
||||
GifDMAInt(8 * BIAS);
|
||||
GIF_LOG("GIF DMA End QWC in fifo %x APATH = %x OPH = %x state = %x", gifRegs.stat.FQC, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state);
|
||||
GIF_LOG("GIF DMA End QWC in fifo %x (%x) APATH = %x OPH = %x state = %x", gifRegs.stat.FQC, gif_fifo.fifoSize, gifRegs.stat.APATH, gifRegs.stat.OPH, gifUnit.gifPath[GIF_PATH_3].state);
|
||||
}
|
||||
|
||||
static u32 WRITERING_DMA(u32* pMem, u32 qwc)
|
||||
|
@ -703,7 +721,7 @@ void gifMFIFOInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
gifCheckPathStatus();
|
||||
gifCheckPathStatus(false);
|
||||
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
{
|
||||
|
@ -730,7 +748,7 @@ void gifMFIFOInterrupt()
|
|||
return;
|
||||
}
|
||||
|
||||
gifCheckPathStatus();
|
||||
gifCheckPathStatus(false);
|
||||
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
{
|
||||
|
@ -759,7 +777,7 @@ void gifMFIFOInterrupt()
|
|||
if (readSize)
|
||||
GifDMAInt(readSize * BIAS);
|
||||
|
||||
gifCheckPathStatus();
|
||||
gifCheckPathStatus(false);
|
||||
// Double check as we might have read the fifo as it's ending the DMA
|
||||
if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)
|
||||
{
|
||||
|
|
|
@ -287,3 +287,4 @@ extern void dmaGIF();
|
|||
extern void mfifoGIFtransfer();
|
||||
extern void gifMFIFOInterrupt();
|
||||
extern void clearFIFOstuff(bool full);
|
||||
extern void gifCheckPathStatus(bool calledFromGIF);
|
|
@ -775,6 +775,9 @@ struct Gif_Unit
|
|||
}
|
||||
else
|
||||
{
|
||||
// If PATH3 was stalled due to another transfer but the DMA ended, it'll never check this
|
||||
// So lets quickly check if it's currently set to path3
|
||||
gifCheckPathStatus(true);
|
||||
if (isResume || curPath == 0)
|
||||
{
|
||||
stat.APATH = 0;
|
||||
|
|
|
@ -212,44 +212,7 @@ static void _vu1Exec(VURegs* VU)
|
|||
|
||||
if (VU->xgkickenable && (VU1.cycle - VU->xgkicklastcycle) >= 2)
|
||||
{
|
||||
if (VU->xgkicksizeremaining == 0)
|
||||
{
|
||||
u32 size = gifUnit.GetGSPacketSize(GIF_PATH_1, VU->Mem, VU->xgkickaddr);
|
||||
VU->xgkicksizeremaining = size & 0xFFFF;
|
||||
VU->xgkickendpacket = size >> 31;
|
||||
|
||||
if (VU->xgkicksizeremaining == 0)
|
||||
{
|
||||
VUM_LOG("Invalid GS packet size returned, cancelling XGKick");
|
||||
VU->xgkickenable = false;
|
||||
}
|
||||
else
|
||||
VUM_LOG("XGKICK New tag size %d bytes EOP %d", VU->xgkicksizeremaining, VU->xgkickendpacket);
|
||||
}
|
||||
u32 transfersize = std::min(VU->xgkicksizeremaining / 0x10, (VU1.cycle - VU->xgkicklastcycle) / 2);
|
||||
transfersize = std::min(transfersize, VU->xgkickdiff / 0x10);
|
||||
|
||||
if (transfersize)
|
||||
{
|
||||
VUM_LOG("XGKICK Transferring %x bytes from %x size left %x", transfersize * 0x10, VU->xgkickaddr, VU->xgkicksizeremaining);
|
||||
if ((transfersize * 0x10) > VU->xgkicksizeremaining)
|
||||
gifUnit.gifPath[GIF_PATH_1].CopyGSPacketData(&VU->Mem[VU->xgkickaddr], transfersize * 0x10, true);
|
||||
else
|
||||
gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &VU->Mem[VU->xgkickaddr], transfersize * 0x10, true);
|
||||
|
||||
VU->xgkickaddr = (VU->xgkickaddr + (transfersize * 0x10)) & 0x3FFF;
|
||||
VU->xgkicksizeremaining -= (transfersize * 0x10);
|
||||
VU->xgkickdiff = 0x4000 - VU->xgkickaddr;
|
||||
VU->xgkicklastcycle += std::max(transfersize * 2, 2U);
|
||||
|
||||
if (VU->xgkicksizeremaining || !VU->xgkickendpacket)
|
||||
VUM_LOG("XGKICK next addr %x left size %x", VU->xgkickaddr, VU->xgkicksizeremaining);
|
||||
else
|
||||
{
|
||||
VUM_LOG("XGKICK transfer finished");
|
||||
VU->xgkickenable = false;
|
||||
}
|
||||
}
|
||||
_vuXGKICKTransfer(VU, (VU1.cycle - VU->xgkicklastcycle), false);
|
||||
}
|
||||
|
||||
// Progress the write position of the FMAC pipeline by one place
|
||||
|
|
|
@ -39,44 +39,7 @@ void BaseVUmicroCPU::ExecuteBlock(bool startUp)
|
|||
{
|
||||
if (VU1.xgkickenable && (cpuRegs.cycle - VU1.xgkicklastcycle) >= 2)
|
||||
{
|
||||
if (VU1.xgkicksizeremaining == 0)
|
||||
{
|
||||
u32 size = gifUnit.GetGSPacketSize(GIF_PATH_1, VU1.Mem, VU1.xgkickaddr);
|
||||
VU1.xgkicksizeremaining = size & 0xFFFF;
|
||||
VU1.xgkickendpacket = size >> 31;
|
||||
VUM_LOG("XGKICK New packet size %x", VU1.xgkicksizeremaining);
|
||||
|
||||
if (VU1.xgkicksizeremaining == 0)
|
||||
{
|
||||
VUM_LOG("Invalid GS packet size returned, cancelling XGKick");
|
||||
VU1.xgkickenable = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
u32 transfersize = std::min(VU1.xgkicksizeremaining / 0x10, (cpuRegs.cycle - VU1.xgkicklastcycle) / 2);
|
||||
transfersize = std::min(transfersize, VU1.xgkickdiff / 0x10);
|
||||
|
||||
if (transfersize)
|
||||
{
|
||||
VUM_LOG("XGKICK Transferring %x bytes from %x size left %x", transfersize * 0x10, VU1.xgkickaddr, VU1.xgkicksizeremaining);
|
||||
if ((transfersize * 0x10) > VU1.xgkicksizeremaining)
|
||||
gifUnit.gifPath[GIF_PATH_1].CopyGSPacketData(&VU1.Mem[VU1.xgkickaddr], transfersize * 0x10, true);
|
||||
else
|
||||
gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &VU1.Mem[VU1.xgkickaddr], transfersize * 0x10, true);
|
||||
|
||||
VU1.xgkickaddr = (VU1.xgkickaddr + (transfersize * 0x10)) & 0x3FFF;
|
||||
VU1.xgkicksizeremaining -= (transfersize * 0x10);
|
||||
VU1.xgkickdiff = 0x4000 - VU1.xgkickaddr;
|
||||
VU1.xgkicklastcycle += std::max(transfersize * 2, 2U);
|
||||
|
||||
if (VU1.xgkicksizeremaining || !VU1.xgkickendpacket)
|
||||
VUM_LOG("XGKICK next addr %x left size %x", VU1.xgkickaddr, VU1.xgkicksizeremaining);
|
||||
else
|
||||
{
|
||||
VU1.xgkickenable = false;
|
||||
VUM_LOG("XGKICK transfer finished");
|
||||
}
|
||||
}
|
||||
_vuXGKICKTransfer(&VU1, (cpuRegs.cycle - VU1.xgkicklastcycle), false);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -2317,10 +2317,15 @@ static __ri void _vuXITOP(VURegs * VU) {
|
|||
else VU->VI[_It_].US[0] = VU->GetVifRegs().itop;
|
||||
}
|
||||
|
||||
void _vuXGKICKFlush(VURegs* VU)
|
||||
void _vuXGKICKTransfer(VURegs* VU, u32 cycles, bool flush)
|
||||
{
|
||||
if (!VU->xgkickenable)
|
||||
return;
|
||||
|
||||
while (!VU->xgkickendpacket || VU->xgkicksizeremaining > 0)
|
||||
{
|
||||
u32 transfersize = 0;
|
||||
|
||||
if (VU->xgkicksizeremaining == 0)
|
||||
{
|
||||
u32 size = gifUnit.GetGSPacketSize(GIF_PATH_1, VU->Mem, VU->xgkickaddr);
|
||||
|
@ -2338,30 +2343,52 @@ void _vuXGKICKFlush(VURegs* VU)
|
|||
VUM_LOG("XGKICK New tag size %d bytes EOP %d", VU->xgkicksizeremaining, VU->xgkickendpacket);
|
||||
}
|
||||
|
||||
VUM_LOG("XGKICK Force Transferring %x bytes from %x size left %x", VU->xgkicksizeremaining, VU->xgkickaddr, VU->xgkicksizeremaining);
|
||||
|
||||
if (VU->xgkicksizeremaining > VU->xgkickdiff) {
|
||||
//VUM_LOG( "VU1 Int: XGkick Wrap!");
|
||||
gifUnit.gifPath[GIF_PATH_1].CopyGSPacketData(&VU->Mem[VU->xgkickaddr], VU->xgkickdiff, true);
|
||||
gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &VU->Mem[0], VU->xgkicksizeremaining - VU->xgkickdiff, true);
|
||||
if (!flush)
|
||||
{
|
||||
transfersize = std::min(VU->xgkicksizeremaining / 0x10, cycles / 2);
|
||||
transfersize = std::min(transfersize, VU->xgkickdiff / 0x10);
|
||||
}
|
||||
else {
|
||||
gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &VU->Mem[VU->xgkickaddr], VU->xgkicksizeremaining, true);
|
||||
}
|
||||
|
||||
VU->xgkickaddr = (VU->xgkickaddr + VU->xgkicksizeremaining) & 0x3fff;
|
||||
|
||||
if (VU0.VI[REG_VPU_STAT].UL & 0x100)
|
||||
VU->cycle += VU->xgkicksizeremaining / 2;
|
||||
|
||||
VU->xgkicksizeremaining = 0;
|
||||
|
||||
if (!VU->xgkickendpacket)
|
||||
VUM_LOG("XGKICK next addr %x left size %x EOP %d", VU->xgkickaddr, VU->xgkicksizeremaining, VU->xgkickendpacket);
|
||||
else
|
||||
VUM_LOG("XGKICK transfer finished");
|
||||
{
|
||||
transfersize = VU->xgkicksizeremaining / 0x10;
|
||||
transfersize = std::min(transfersize, VU->xgkickdiff / 0x10);
|
||||
}
|
||||
|
||||
VUM_LOG("XGKICK Transferring %x bytes from %x size %x", transfersize * 0x10, VU->xgkickaddr, VU->xgkicksizeremaining);
|
||||
|
||||
if ((transfersize * 0x10) < VU->xgkicksizeremaining)
|
||||
gifUnit.gifPath[GIF_PATH_1].CopyGSPacketData(&VU->Mem[VU->xgkickaddr], transfersize * 0x10, true);
|
||||
else
|
||||
gifUnit.TransferGSPacketData(GIF_TRANS_XGKICK, &VU->Mem[VU->xgkickaddr], transfersize * 0x10, true);
|
||||
|
||||
if ((VU0.VI[REG_VPU_STAT].UL & 0x100) && flush)
|
||||
VU->cycle += transfersize * 2;
|
||||
|
||||
cycles -= transfersize * 2;
|
||||
|
||||
VU->xgkickaddr = (VU->xgkickaddr + (transfersize * 0x10)) & 0x3FFF;
|
||||
VU->xgkicksizeremaining -= (transfersize * 0x10);
|
||||
VU->xgkickdiff = 0x4000 - VU->xgkickaddr;
|
||||
VU->xgkicklastcycle += std::max(transfersize * 2, 2U);
|
||||
|
||||
if (VU->xgkicksizeremaining || !VU->xgkickendpacket)
|
||||
VUM_LOG("XGKICK next addr %x left size %x", VU->xgkickaddr, VU->xgkicksizeremaining);
|
||||
else
|
||||
{
|
||||
VUM_LOG("XGKICK transfer finished");
|
||||
VU->xgkickenable = false;
|
||||
// Check if VIF is waiting for the GIF to not be busy
|
||||
if (vif1Regs.stat.VGW)
|
||||
{
|
||||
vif1Regs.stat.VGW = false;
|
||||
CPU_INT(DMAC_VIF1, 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (!flush && cycles < 2)
|
||||
return;
|
||||
}
|
||||
VUM_LOG("Disabling XGKICK");
|
||||
VU->xgkickenable = false;
|
||||
_vuTestPipes(VU);
|
||||
}
|
||||
|
@ -2370,7 +2397,7 @@ static __ri void _vuXGKICK(VURegs * VU)
|
|||
{
|
||||
if (VU->xgkickenable)
|
||||
{
|
||||
_vuXGKICKFlush(VU);
|
||||
_vuXGKICKTransfer(VU, 0, true);
|
||||
}
|
||||
|
||||
u32 addr = (VU->VI[_Is_].US[0] & 0x3ff) * 16;
|
||||
|
|
|
@ -59,3 +59,4 @@ extern void _vuTestUpperStalls(VURegs * VU, _VURegsNum *VUregsn);
|
|||
extern void _vuTestLowerStalls(VURegs * VU, _VURegsNum *VUregsn);
|
||||
extern void _vuAddUpperStalls(VURegs * VU, _VURegsNum *VUregsn);
|
||||
extern void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn);
|
||||
extern void _vuXGKICKTransfer(VURegs* VU, u32 cycles, bool flush);
|
||||
|
|
|
@ -32,7 +32,7 @@ _vifT void vifTransferLoop(u32* &data) {
|
|||
|
||||
vifXRegs.stat.VPS |= VPS_TRANSFERRING;
|
||||
vifXRegs.stat.ER1 = false;
|
||||
if(!idx)VIF_LOG("Starting VIF0 loop, pSize = %x, stalled = %x", pSize, vifX.vifstalled.enabled );
|
||||
//VIF_LOG("Starting VIF%d loop, pSize = %x, stalled = %x", idx, pSize, vifX.vifstalled.enabled );
|
||||
while (pSize > 0 && !vifX.vifstalled.enabled) {
|
||||
|
||||
if(!vifX.cmd) { // Get new VifCode
|
||||
|
|
Loading…
Reference in New Issue