diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index b7cd68795e..b9028de2ee 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -113,12 +113,22 @@ static __forceinline void gsCSRwrite( const tGS_CSR& csr ) // SIGNAL : What's not known here is whether or not the SIGID register should be updated // here or when the IMR is cleared (below). - GIF_LOG("GS SIGNAL (pending) data=%x_%x IMR=%x CSRr=%x\n",SIGNAL_Data_Pending[0], SIGNAL_Data_Pending[1], GSIMR, GSCSRr); - GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~SIGNAL_Data_Pending[1])|(SIGNAL_Data_Pending[0]&SIGNAL_Data_Pending[1]); + if(SIGNAL_IMR_Pending == true) + { + //DevCon.Warning("Firing pending signal"); + GIF_LOG("GS SIGNAL (pending) data=%x_%x IMR=%x CSRr=%x\n",SIGNAL_Data_Pending[0], SIGNAL_Data_Pending[1], GSIMR, GSCSRr); + GSSIGLBLID.SIGID = (GSSIGLBLID.SIGID&~SIGNAL_Data_Pending[1])|(SIGNAL_Data_Pending[0]&SIGNAL_Data_Pending[1]); - CSRreg.SIGNAL = false; + if (!(GSIMR&0x100)) + gsIrq(); + + CSRreg.SIGNAL = true; //Just to be sure :P + } + else CSRreg.SIGNAL = false; - // [TODO] (SIGNAL) : Re-enable GIFpath DMAs here! + SIGNAL_IMR_Pending = false; + + if(gifRegs->stat.P1Q && gifRegs->stat.APATH <= GIF_APATH1) gsPath1Interrupt(); } if(csr.FINISH) CSRreg.FINISH = false; diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index b9f000cd1a..7c8b803bd4 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -89,10 +89,20 @@ void gsPath1Interrupt() } } + +extern bool SIGNAL_IMR_Pending; + __forceinline void gsInterrupt() { GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle); + if(SIGNAL_IMR_Pending == true) + { + //DevCon.Warning("Path 3 Paused"); + CPU_INT(DMAC_GIF, 128); + return; + } + if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs->stat.APATH == GIF_APATH3 ) { gifRegs->stat.OPH = false; @@ -100,6 +110,7 @@ __forceinline void gsInterrupt() gifRegs->stat.APATH = GIF_APATH_IDLE; if(gifRegs->stat.P1Q) gsPath1Interrupt(); } + if (!(gif->chcr.STR)) { diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 7f0d1e52a1..c7e42ad814 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -255,6 +255,8 @@ __forceinline void vif1SetupTransfer() } } +extern bool SIGNAL_IMR_Pending; + bool CheckPath2GIF(int channel) { if ((vif1Regs->stat.VGW)) @@ -327,6 +329,12 @@ bool CheckPath2GIF(int channel) } } } + if(SIGNAL_IMR_Pending == true && (vif1.cmd & 0x7e) == 0x50) + { + //DevCon.Warning("Path 2 Paused"); + CPU_INT(channel, 128); + return false; + } return true; } __forceinline void vif1Interrupt() diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index 4a4a368d45..fb2fb3a9f9 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -114,6 +114,8 @@ vifOp(vifCode_Base) { return 0; } +extern bool SIGNAL_IMR_Pending; + template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { pass1 { vif1Only(); @@ -150,13 +152,21 @@ template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { return 0; } } + if(SIGNAL_IMR_Pending == true) + { + DevCon.Warning("Path 2 Paused (At start)"); + vif1.vifstalled = true; + return 0; + } if (gifRegs->stat.PSE) // temporarily stop { Console.WriteLn("Gif dma temp paused? VIF DIRECT"); vif1.GifWaitState = 3; + vif1.vifstalled = true; vif1Regs->stat.VGW = true; return 0; } + gifRegs->stat.clear_flags(GIF_STAT_P2Q); diff --git a/pcsx2/ps2/GIFpath.cpp b/pcsx2/ps2/GIFpath.cpp index d50be071ed..7bec0eef6f 100644 --- a/pcsx2/ps2/GIFpath.cpp +++ b/pcsx2/ps2/GIFpath.cpp @@ -147,7 +147,7 @@ static void __fastcall RegHandlerSIGNAL(const u32* data) // Time to ignore all subsequent drawing operations. (which is not yet supported) if (!SIGNAL_IMR_Pending) { - DevCon.WriteLn( Color_StrongOrange, "GS SIGNAL double throw encountered!" ); + //DevCon.WriteLn( Color_StrongOrange, "GS SIGNAL double throw encountered!" ); SIGNAL_IMR_Pending = true; SIGNAL_Data_Pending[0] = data[0]; SIGNAL_Data_Pending[1] = data[1]; @@ -572,7 +572,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) gsHandler(pMem); } incTag(16, 1); - } while(StepReg() && size > 0); + } while(StepReg() && size > 0 && SIGNAL_IMR_Pending == false); } else { @@ -680,6 +680,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) // FINISH is *not* a per-path register, and it seems to pretty clearly indicate that all active // drawing *and* image transfer actions must be finished before the IRQ raises. + if(gifRegs->stat.P1Q || gifRegs->stat.P2Q || gifRegs->stat.P3Q) DevCon.Warning("Early FINISH signal! P1 %x P2 %x P3 %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.P3Q); if (!(GSIMR&0x200) && !s_gifPath.path[0].IsActive() && !s_gifPath.path[1].IsActive() && !s_gifPath.path[2].IsActive()) { gsIrq(); @@ -687,6 +688,11 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) } break; } + if(SIGNAL_IMR_Pending == true) + { + //DevCon.Warning("Path %x", pathidx + 1); + break; + } } size = (startSize - size); diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 2c66144c4d..2fceaafd5d 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -1101,7 +1101,10 @@ mVUop(mVU_XITOP) { //------------------------------------------------------------------ // XGkick //------------------------------------------------------------------ + extern void gsPath1Interrupt(); +extern bool SIGNAL_IMR_Pending; + void __fastcall mVU_XGKICK_(u32 addr) { addr &= 0x3ff; u8* data = microVU1.regs->Mem + (addr*16); @@ -1109,7 +1112,7 @@ void __fastcall mVU_XGKICK_(u32 addr) { u32 size; u8* pDest; - if(gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.APATH == GIF_APATH3 && gifRegs->stat.IP3 == true)) + if(gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.APATH == GIF_APATH3 && gifRegs->stat.IP3 == true) && SIGNAL_IMR_Pending == false) { if(Path1WritePos != 0) diff --git a/pcsx2/x86/sVU_Lower.cpp b/pcsx2/x86/sVU_Lower.cpp index 1a565859f2..c8d103477b 100644 --- a/pcsx2/x86/sVU_Lower.cpp +++ b/pcsx2/x86/sVU_Lower.cpp @@ -1970,6 +1970,8 @@ void recVUMI_XTOP( VURegs *VU, int info ) //------------------------------------------------------------------ // VU1XGKICK_MTGSTransfer() - Called by ivuZerorec.cpp //------------------------------------------------------------------ +extern bool SIGNAL_IMR_Pending; + void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) { addr &= 0x3fff; @@ -1978,7 +1980,7 @@ void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) u32 size; u8* pDest; - if(gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.APATH == GIF_APATH3 && gifRegs->stat.IP3 == true)) + if(gifRegs->stat.APATH <= GIF_APATH1 || (gifRegs->stat.APATH == GIF_APATH3 && gifRegs->stat.IP3 == true) && SIGNAL_IMR_Pending == false) { if(Path1WritePos != 0)