From 44378b31f7e41d7fae38b121c698f354bcc31be0 Mon Sep 17 00:00:00 2001 From: refraction Date: Mon, 25 May 2009 07:07:59 +0000 Subject: [PATCH] Path3 Masking mystery solved, Simpsons (Issue 24) GT4 (Issue 211), tenchu and many many other path3 masking games should be fixed. This will only work on MTGS. Also semi-removed my gifsplit thing to resolve the tekken 5 menus Issue 209 Note: GT4 is still missing its logo, this is down to a really bizzare timing issue i cant pinpoint. Removed redundant path3hack git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1257 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Elfheader.cpp | 5 -- pcsx2/GS.cpp | 2 - pcsx2/Gif.cpp | 135 ++++++++++++++++++++------------------- pcsx2/MTGS.cpp | 41 +++++++++--- pcsx2/Patch.cpp | 6 -- pcsx2/Patch.h | 2 - pcsx2/VifDma.cpp | 68 ++++++++------------ pcsx2/VifDma.h | 2 +- pcsx2/x86/iVUzerorec.cpp | 4 +- 9 files changed, 133 insertions(+), 132 deletions(-) diff --git a/pcsx2/Elfheader.cpp b/pcsx2/Elfheader.cpp index c264f53a38..5bf94204b3 100644 --- a/pcsx2/Elfheader.cpp +++ b/pcsx2/Elfheader.cpp @@ -571,7 +571,6 @@ int loadElfFile(const char *filename) } #include "VU.h" -extern bool path3hack; int g_VUGameFixes = 0; // fixme - this should be moved to patches or eliminated @@ -584,9 +583,5 @@ void LoadGameSpecificSettings() case 0xb99379b7: // erementar gerad (discolored chars) g_VUGameFixes |= VUFIX_XGKICKDELAY2; // Tested - still needed - arcum42 break; - //case 0xa08c4057: //Sprint Cars (SLUS) - //case 0x8b0725d5: //Flinstones Bedrock Racing (SLES) - //path3hack = TRUE; // We can move this to patch files right now - //break; } } diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 24b440538e..8b8fe7e958 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -243,8 +243,6 @@ void gsReset() memzero_obj(g_RealGSMem); - Path3transfer = FALSE; - GSCSRr = 0x551B400F; // Set the FINISH bit to 1 for now GSIMR = 0x7f00; psHu32(GIF_STAT) = 0; diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index edb8ee7069..9e189856ae 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -28,7 +28,7 @@ using std::min; -#define gifsplit 64 +#define gifsplit 0x10000 enum gifstate_t { GIF_STATE_READY = 0, @@ -57,6 +57,9 @@ __forceinline void gsInterrupt() { //Console::WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", params gif->chcr, gif->qwc, done); return; } + + if(Path3progress == 2) vif1Regs->stat &= ~VIF1_STAT_VGW; + if (gif->qwc > 0 || gspath3done == 0) { if (!(psHu32(DMAC_CTRL) & 0x1)) { Console::Notice("gs dma masked, re-scheduling..."); @@ -66,19 +69,11 @@ __forceinline void gsInterrupt() { } GIFdma(); -#ifdef GSPATH3FIX - // re-raise the IRQ as part of the mysterious Path3fix. - // fixme - this hack *should* have the gs_irq raised from the VIF, I think. It would be - // more efficient and more correct. (air) - /*if (!(vif1Regs->mskpath3 && (vif1ch->chcr & 0x100)) || (psHu32(GIF_MODE) & 0x1)) - CPU_INT( 2, 64 );*/ -#endif - if(gspath3done == 0 || gif->qwc > 0) return; + return; } gspath3done = 0; gscycles = 0; - Path3transfer = FALSE; gif->chcr &= ~0x100; GSCSRr &= ~0xC000; //Clear FIFO stuff GSCSRr |= 0x4000; //FIFO empty @@ -89,12 +84,10 @@ __forceinline void gsInterrupt() { } -static void WRITERING_DMA(u32 *pMem, u32 qwc) +static u32 WRITERING_DMA(u32 *pMem, u32 qwc) { psHu32(GIF_STAT) |= 0xE00; - // Path3 transfer will be set to false by the GIFtag handler. - Path3transfer = TRUE; if( mtgsThread != NULL ) { @@ -114,15 +107,14 @@ static void WRITERING_DMA(u32 *pMem, u32 qwc) memcpy_aligned(pgsmem, pMem, sizetoread<<4); mtgsThread->SendDataPacket(); + return sizetoread; } else { GSGIFTRANSFER3(pMem, qwc); - if (GSgetLastTag != NULL) - { - GSgetLastTag(&s_gstag); - if (s_gstag == 1) Path3transfer = FALSE; /* fixes SRS and others */ - } + gif->madr+= qwc*16; + gif->qwc -= qwc; + return qwc; } } @@ -145,11 +137,11 @@ int _GIFchain() { Console::Notice( "Hackfix - NULL GIFchain" ); return -1; } - WRITERING_DMA(pMem, qwc); + qwc = WRITERING_DMA(pMem, qwc); - gif->madr+= qwc*16; - gif->qwc -= qwc; - return (qwc)*2; + /*gif->madr+= qwc*16; + gif->qwc -= qwc;*/ + return (qwc); } static __forceinline void GIFchain() @@ -161,10 +153,7 @@ static __forceinline void GIFchain() static __forceinline void dmaGIFend() { - if ((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0) - CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/); - else - CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/); + CPU_INT(2, 2); } // These could probably be consolidated into one function, @@ -172,10 +161,10 @@ static __forceinline void dmaGIFend() // not to do the gif->qwc != 0 check. --arcum42 static __forceinline void GIFdmaEnd() { - if (psHu32(GIF_MODE) & 0x4) - CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/); - else - CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/); + //if (psHu32(GIF_MODE) & 0x4) + CPU_INT(2, gscycles * BIAS); + /*else + CPU_INT(2, min( gifsplit, (int)gif->qwc ) * BIAS);*/ } void GIFdma() @@ -183,7 +172,7 @@ void GIFdma() u32 *ptag; u32 id; - gscycles= prevcycles ? prevcycles: gscycles; + gscycles= prevcycles ? prevcycles: 0; if ((psHu32(GIF_CTRL) & 8)) { // temporarily stop Console::WriteLn("Gif dma temp paused?"); @@ -219,6 +208,13 @@ void GIFdma() GSCSRr |= 0x8000; //FIFO full psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [ used to be 0xE00; // OPH=1 | APATH=3] + if(((psHu32(GIF_STAT) & 0x100) || (vif1.cmd & 0x7f) == 0x50) && (psHu32(GIF_MODE) & 0x4) && Path3progress == 0) //Path2 gets priority in intermittent mode + { + //GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", psHu32(GIF_STAT) & 0x100, (vif1.cmd & 0x7f), psHu32(GIF_MODE), Path3progress); + dmaGIFend(); + return; + } + #ifdef GSPATH3FIX if (vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1)) { if(gif->qwc == 0) { @@ -243,28 +239,26 @@ void GIFdma() gspath3done |= 1; } } + } + + if(Path3progress == 2/* && gif->qwc != 0*/) + { + dmaGIFend(); + return; } - - GIFchain(); - if((gif->qwc == 0) && ((gspath3done == 1) || (gif->chcr & 0xc) == 0)){ - gspath3done = 0; - gif->chcr &= ~0x100; - GSCSRr &= ~0xC000; - GSCSRr |= 0x4000; - Path3transfer = FALSE; - psHu32(GIF_STAT)&= ~0x1F000E00; // OPH=0 | APATH=0 | QFC=0 - hwDmacIrq(DMAC_GIF); - } - //Dont unfreeze xmm regs here, Masked PATH3 can only be called by VIF, which is already handling it. + GIFchain(); + GIFdmaEnd(); return; } #endif // Transfer Dn_QWC from Dn_MADR to GIF if ((gif->chcr & 0xc) == 0 || gif->qwc > 0) { // Normal Mode + if ((((psHu32(DMAC_CTRL) & 0xC0) == 0x80) && ((gif->chcr & 0xc) == 0))) { Console::WriteLn("DMA Stall Control on GIF normal"); } + GIFchain(); //Transfers the data set by the switch if (((gif->qwc == 0) && (gif->chcr & 0xc) == 0)) @@ -272,9 +266,8 @@ void GIFdma() else if(gif->qwc > 0) { GIFdmaEnd(); - return; - - } + return; + } } if ((gif->chcr & 0xc) == 0x4 && gspath3done == 0) { @@ -322,23 +315,23 @@ void GIFdma() prevcycles = 0; if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) { - if (gspath3done == 0 || gif->qwc > 0) + if (gspath3done == 0 && gif->qwc == 0) { - if (gif->qwc != 0) - { - GIFdmaEnd(); - } - else - { - ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR - gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag - gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 - - GIFdmaEnd(); - gif->qwc = 0; - return; + + ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR + gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 + gif->madr = ptag[1]; + + gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7); + if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag + GIF_LOG("dmaIrq Set"); + gspath3done = 1; } - } + GIFdmaEnd(); + return; + + } else GIFdmaEnd(); gscycles = 0; } } @@ -358,23 +351,33 @@ void dmaGIF() { GSCSRr &= ~0xC000; //Clear FIFO stuff GSCSRr |= 0x8000; //FIFO full psHu32(GIF_STAT)|= 0x10000000; // FQC=31, hack ;) [used to be 0xE00; // OPH=1 | APATH=3] + Path3progress = 2; if ((gif->qwc == 0) && ((gif->chcr & 0xc) != 0)){ u32 *ptag; ptag = (u32*)dmaGetAddr(gif->tadr); gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 - - //gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7); - GIFdmaEnd(); - gif->qwc = 0; + gif->madr = ptag[1]; + + GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1], ptag[0], gif->qwc, (ptag[0] >> 28), gif->madr); + + + gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7); + if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag + GIF_LOG("dmaIrq Set"); + gspath3done = 1; + } + + GIFdma(); + //gif->qwc = 0; return; } //Halflife sets a QWC amount in chain mode, no tadr set. if((gif->qwc > 0) && ((gif->chcr & 0x4) == 0x4)) gspath3done = 1; - dmaGIFend(); + GIFdma(); } // called from only one location, so forceinline it: diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index d2e22bdd2f..25560e85b0 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -287,9 +287,11 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u pMem += sizeof(GIFTAG); --size; - if(pathidx == 2 && path.tag.eop) - { - Path3transfer = FALSE; + if(pathidx == 2) + { + if(path.tag.flg != GIF_FLG_IMAGE)Path3progress = 1; //Other mode + else Path3progress = 0; //IMAGE mode + //if(pathidx == 2) GIF_LOG("Set Giftag NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress); } if( pathidx == 0 ) @@ -305,11 +307,11 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u return ++size; } } - } - else + }else { // NOTE: size > 0 => do {} while(size > 0); should be faster than while(size > 0) {} - + + //if(pathidx == 2) GIF_LOG("PATH3 NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress); switch(path.tag.flg) { case GIF_FLG_PACKED: @@ -371,11 +373,12 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u } } - - if(pathidx == 0) + + if(pathidx == 0 || pathidx == 2) { if(path.tag.eop && path.tag.nloop == 0) { + //if(pathidx == 2) GIF_LOG("BREAK PATH3 NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress); break; } } @@ -392,6 +395,23 @@ __forceinline u32 mtgsThreadObject::_gifTransferDummy( GIF_PATH pathidx, const u // along the way (often means curreg was in a bad state or something) } } + + + if(pathidx == 2) + { + if(path.tag.nloop == 0 ) + { + //DevCon::Notice("Finishing Giftag NLoop %d EOP %x Mode %d nregs %d Path3progress %d Vifstat VGW %x", + //params path.tag.nloop, path.tag.eop, path.tag.flg, path.tag.nreg, Path3progress, vif1Regs->stat & VIF1_STAT_VGW); + if(path.tag.eop) + { + Path3progress = 2; + //GIF_LOG("Set progress NLoop %d EOP %x Mode %d Path3msk %x Path3progress %x ", path.tag.nloop, path.tag.eop, path.tag.flg, vif1Regs->mskpath3, Path3progress); + } + + } + + } #ifdef PCSX2_GSRING_SAMPLING_STATS __asm { @@ -838,6 +858,11 @@ int mtgsThreadObject::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 s // enough room for size - retval: int retval = _gifTransferDummy( pathidx, srcdata, size ); + if(pathidx == 2) + { + gif->madr += (size - retval) * 16; + gif->qwc -= size - retval; + } size = size - retval; m_packet_size = size; size++; // takes into account our command qword. diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index 9262dcf3b0..618e6f5041 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -57,7 +57,6 @@ PatchTextTable commands[] = // X - EE rounding mode (default is NEAR) // Y - VU rounding mode (default is CHOP) { "zerogs", 6, patchFunc_zerogs }, // zerogs=hex - { "path3hack", 7, patchFunc_path3hack }, { "vunanmode",8, patchFunc_vunanmode }, { "ffxhack",9, patchFunc_ffxhack}, { "xkickdelay",10, patchFunc_xkickdelay}, @@ -674,11 +673,6 @@ void patchFunc_vunanmode( char * cmd, char * param ) // Doesn't do anything anymore } -void patchFunc_path3hack( char * cmd, char * param ) -{ - path3hack = TRUE; -} - void patchFunc_roundmode( char * cmd, char * param ) { int index; diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h index b077ae67fd..cd3e100e44 100644 --- a/pcsx2/Patch.h +++ b/pcsx2/Patch.h @@ -82,7 +82,6 @@ void patchFunc_comment( char * text1, char * text2 ); void patchFunc_gametitle( char * text1, char * text2 ); void patchFunc_patch( char * text1, char * text2 ); void patchFunc_fastmemory( char * text1, char * text2 ); -void patchFunc_path3hack( char * text1, char * text2 ); void patchFunc_roundmode( char * text1, char * text2 ); void patchFunc_zerogs( char * text1, char * text2 ); void patchFunc_vunanmode( char * text1, char * text2 ); @@ -109,7 +108,6 @@ int AddPatch(int Mode, int Place, int Address, int Size, u64 data); extern void SetFastMemory(int); // iR5900LoadStore.c -extern bool path3hack; //extern int g_VUGameFixes; extern int g_ZeroGSOptions; extern u32 g_sseMXCSR; diff --git a/pcsx2/VifDma.cpp b/pcsx2/VifDma.cpp index c1de89843c..8adc7586bd 100644 --- a/pcsx2/VifDma.cpp +++ b/pcsx2/VifDma.cpp @@ -58,8 +58,7 @@ static const unsigned int VIF0dmanum = 0; static const unsigned int VIF1dmanum = 1; int g_vifCycles = 0; -bool path3hack = false; -bool Path3transfer = false; +int Path3progress = 2; //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet u32 splittransfer[4]; u32 splitptr = 0; @@ -1891,6 +1890,7 @@ static int __fastcall Vif1TransDirectHL(u32 *data) } else { + psHu32(GIF_STAT) &= ~0x80; ret = vif1.tag.size; vif1.tag.size = 0; vif1.cmd = 0; @@ -2019,22 +2019,11 @@ static void Vif1CMDMskPath3() // MSKPATH3 #ifdef GSPATH3FIX if ((vif1Regs->code >> 15) & 0x1) { - - while ((gif->chcr & 0x100)) //Can be done 2 different ways, depends on the game/company - { - if (!path3hack && !Path3transfer && (gif->qwc == 0)) break; - - gsInterrupt(); - - if (path3hack && (gif->qwc == 0)) break; //add games not working with it to elfheader.c to enable this instead - - } psHu32(GIF_STAT) |= 0x2; } else { - // fixme: This is the *only* reason 'transferred' is global. Otherwise it'd be local to Vif1Transfer. - if (gif->chcr & 0x100) CPU_INT(2, (transferred >> 2) * BIAS); // Restart Path3 on its own, time it right! + Path3progress = 1; //Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely) psHu32(GIF_STAT) &= ~0x2; } #else @@ -2068,11 +2057,10 @@ static void Vif1CMDFlush() // FLUSH/E/A if((vif1.cmd & 0x7f) == 0x13) { - while ((gif->chcr & 0x100)) - { - if (!Path3transfer && gif->qwc == 0) break; - gsInterrupt(); - } + if(Path3progress != 2 && gif->chcr & 0x100) // Gif is already transferring so wait for it. + { + vif1Regs->stat |= VIF1_STAT_VGW; + } } vif1.cmd &= ~0x7f; @@ -2123,13 +2111,16 @@ static void Vif1CMDDirectHL() // DIRECT/HL vif1.tag.size = vifImm << 2; - if((gif->chcr & 0x100) && (vif1.cmd & 0x7f) == 0x51) + if((vif1.cmd & 0x7f) == 0x51) { - //if(vif1Regs->mskpath3)CPU_INT(2, vif1ch->qwc - (vif1.vifpacketsize >> 2) * BIAS); - //DirectHL flushes the lot - vif1Regs->stat |= VIF1_STAT_VGW; + if(gif->chcr & 0x100 && Path3progress == 0) //PATH3 is in image mode, so wait for end of transfer + { + //DevCon::Notice("DirectHL gif chcr %x gif qwc %x mskpth3 %x", params gif->chcr, gif->qwc, vif1Regs->mskpath3); + vif1Regs->stat |= VIF1_STAT_VGW; + } } + psHu32(GIF_STAT) |= 0x80; } static void Vif1CMDNull() // invalid opcode @@ -2215,7 +2206,6 @@ int VIF1transfer(u32 *data, int size, int istag) if (vif1.tag.size != 0) DevCon::Error("no vif1 cmd but tag size is left last cmd read %x", params vif1Regs->code); if (vif1.irq) break; - if(vif1Regs->stat & VIF1_STAT_VGW) break; vif1.cmd = (data[0] >> 24); vif1Regs->code = data[0]; @@ -2459,7 +2449,7 @@ __forceinline void vif1SetupTransfer() else ret = VIF1transfer(vif1ptag + 2, 2, 1); //Transfer Tag - if (ret < 0) + if (ret < 0 && vif1.irqoffset < 2) { vif1.inprogress = 0; //Better clear this so it has to do it again (Jak 1) return; //There has been an error or an interrupt @@ -2485,22 +2475,18 @@ __forceinline void vif1Interrupt() VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle); g_vifCycles = 0; - if((vif1Regs->stat & VIF1_STAT_VGW) && - (gif->chcr & 0x100)) + + if((vif1Regs->stat & VIF1_STAT_VGW)) { - int delay = 0; - - if ((psHu32(GIF_MODE) & 0x1)) - delay = min( 8, (int)gif->qwc ); - else - delay = gif->qwc * BIAS; - - //else CPU_INT(2, min( 64, (int)gif->qwc ) * BIAS); - CPU_INT(1, delay); - return; - } - vif1Regs->stat &= ~VIF1_STAT_VGW; + if(gif->chcr & 0x100) + { + CPU_INT(1, 2); + return; + } + else vif1Regs->stat &= ~VIF1_STAT_VGW; + } + if ((vif1ch->chcr & 0x100) == 0) Console::WriteLn("Vif1 running when CHCR == %x", params vif1ch->chcr); @@ -2539,7 +2525,7 @@ __forceinline void vif1Interrupt() if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer(); - CPU_INT(1, (vif1ch->qwc * BIAS) - (vif1.vifpacketsize >> 1)); + CPU_INT(1, g_vifCycles); return; } @@ -2606,7 +2592,7 @@ void dmaVIF1() // Chain Mode vif1.done = false; - CPU_INT(1, 0); + vif1Interrupt(); } diff --git a/pcsx2/VifDma.h b/pcsx2/VifDma.h index 21d45e4a4e..f210d49e2c 100644 --- a/pcsx2/VifDma.h +++ b/pcsx2/VifDma.h @@ -47,7 +47,7 @@ struct vifStruct { }; extern vifStruct vif0, vif1; -extern bool Path3transfer; +extern int Path3progress; void __fastcall UNPACK_S_32( u32 *dest, u32 *data, int size ); diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index 39b0930833..4dbb9c6e3e 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -4409,7 +4409,7 @@ void recVUMI_XGKICK_(VURegs *VU) CALLFunc((uptr)GSgifTransfer1); #endif } - + psHu32(GIF_STAT) &= ~0x100; s_ScheduleXGKICK = 0; } @@ -4430,6 +4430,8 @@ void recVUMI_XGKICK(VURegs *VU, int info) SHL32ItoR(isreg, 4); AND32ItoR(isreg, 0x3fff); s_XGKICKReg = isreg; + psHu32(GIF_STAT) |= 0x100; + if (!SUPERVU_XGKICKDELAY || pc == s_pCurBlock->endpc) {