diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index f28aed00e1..be2f0bed46 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -57,25 +57,11 @@ void gsReset() static __fi void gsCSRwrite( const tGS_CSR& csr ) { if (csr.RESET) { -#if USE_OLD_GIF == 1 // ... - // perform a soft reset -- which is a clearing of all GIFpaths -- and fall back to doing - // a full reset if the plugin doesn't support soft resets. - - if (GSgifSoftReset != NULL) { - GIFPath_Clear( GIF_PATH_1 ); - GIFPath_Clear( GIF_PATH_2 ); - GIFPath_Clear( GIF_PATH_3 ); - } - else GetMTGS().SendSimplePacket( GS_RINGTYPE_RESET, 0, 0, 0 ); - - SIGNAL_IMR_Pending = false; -#else GUNIT_WARN("GUNIT_WARN: csr.RESET"); //Console.Warning( "csr.RESET" ); //gifUnit.Reset(true); // Don't think gif should be reset... gifUnit.gsSIGNAL.queued = false; GetMTGS().SendSimplePacket(GS_RINGTYPE_RESET, 0, 0, 0); -#endif CSRreg.Reset(); GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1 diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index cb0785bf38..3ee7f7a599 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -33,8 +33,32 @@ static bool gifmfifoirq = false; __aligned16 GIF_Fifo gif_fifo; +static __fi void GifDMAInt(int cycles) { + if (dmacRegs.ctrl.MFD == MFD_GIF) { + if (!(cpuRegs.interrupt & (1 << DMAC_MFIFO_GIF)) || cpuRegs.eCycle[DMAC_MFIFO_GIF] < (u32)cycles) + { + CPU_INT(DMAC_MFIFO_GIF, cycles); + } + } else if (!(cpuRegs.interrupt & (1 << DMAC_GIF)) || cpuRegs.eCycle[DMAC_GIF] < (u32)cycles) + { + CPU_INT(DMAC_GIF, cycles); + } +} static __fi void clearFIFOstuff(bool full) { - CSRreg.FIFO = full ? CSR_FIFO_FULL : CSR_FIFO_EMPTY; + CSRreg.FIFO = full ? CSR_FIFO_FULL : CSR_FIFO_EMPTY; +} + +//I suspect this is GS side which should really be handled by the GS plugin which also doesn't current have a fifo, but we can guess from our fifo +static __fi void CalculateFIFOCSR() { + if (gifRegs.stat.FQC >= 15) { + CSRreg.FIFO = CSR_FIFO_FULL; + } + else if (gifRegs.stat.FQC == 0) { + CSRreg.FIFO = CSR_FIFO_EMPTY; + } + else { + CSRreg.FIFO = CSR_FIFO_NORMAL; + } } void GIF_Fifo::init() @@ -50,6 +74,10 @@ void GIF_Fifo::init() int GIF_Fifo::write(u32* pMem, int size) { + if (gifRegs.stat.FQC == 16) { + //DevCon.Warning("Full"); + return 0; + } int transsize; int firsttrans = std::min(size, 16 - (int)gifRegs.stat.FQC); @@ -64,32 +92,28 @@ int GIF_Fifo::write(u32* pMem, int size) pMem += 4; } - + CalculateFIFOCSR(); return firsttrans; } int GIF_Fifo::read(bool calledFromDMA) { + + if (!gifUnit.CanDoPath3() || gifRegs.stat.FQC == 0) + { + //DevCon.Warning("Path3 not masked"); + if (gifch.chcr.STR == true && !(cpuRegs.interrupt & (1 << DMAC_GIF)) && calledFromDMA == false) { + GifDMAInt(16); + } + //DevCon.Warning("P3 Masked"); + return 0; + } + int valueWritePos = 0; uint sizeRead; uint fifoSize = gifRegs.stat.FQC; int oldReadPos = readpos; - if (!gifUnit.CanDoPath3()) - { - //DevCon.Warning("P3 Masked"); - return 0; - } - if (gifRegs.stat.FQC == 0) - { - //If the GIF isn't stalled and it is waiting to go, fire it off (usually after a path3 mask) - if (gifch.chcr.STR == true && !(cpuRegs.interrupt & (1 << DMAC_GIF)) && calledFromDMA == false) { - CPU_INT(DMAC_GIF, 16); - } - return 0; - } - valueWritePos = 0; - while (gifRegs.stat.FQC) { CopyQWC(&readdata[valueWritePos], &data[readpos]); readpos = (readpos + 4) & 63; @@ -101,13 +125,14 @@ int GIF_Fifo::read(bool calledFromDMA) if (sizeRead < fifoSize) { readpos = (oldReadPos + (sizeRead * 4)) & 63; //if we read less than what was in the fifo, move the read position back - gifRegs.stat.FQC = fifoSize - sizeRead; + gifRegs.stat.FQC = fifoSize - sizeRead; } if (calledFromDMA == false) { - CPU_INT(DMAC_GIF, 16); - } - + GifDMAInt(sizeRead * BIAS); + } + + CalculateFIFOCSR(); return gifRegs.stat.FQC; } @@ -121,6 +146,7 @@ void incGifChAddr(u32 qwc) { } __fi void gifCheckPathStatus() { + if (gifRegs.stat.APATH == 3) { gifRegs.stat.APATH = 0; @@ -129,13 +155,13 @@ __fi void gifCheckPathStatus() { { if (gifUnit.checkPaths(1, 1, 0)) gifUnit.Execute(false, true); } - } //Required for Path3 Masking timing! if (gifUnit.gifPath[GIF_PATH_3].state == GIF_PATH_WAIT) gifUnit.gifPath[GIF_PATH_3].state = GIF_PATH_IDLE; } + __fi void gifInterrupt() { GIF_LOG("gifInterrupt caught!"); @@ -151,8 +177,10 @@ __fi void gifInterrupt() //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. - if(!gifUnit.Path3Masked() || gifch.qwc == 0) - CPU_INT(DMAC_GIF, 16); + //This must trigger after VIF retriggers as VIf might instantly mask Path3 + if (!gifUnit.Path3Masked() || gifch.qwc == 0) { + GifDMAInt(16); + } return; } @@ -166,25 +194,31 @@ __fi void gifInterrupt() if (CHECK_GIFFIFOHACK) { - if (gif_fifo.read(true)) { - CPU_INT(DMAC_GIF, 128); - } + if (int amtRead = gif_fifo.read(true)) { - if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16) - { - if (gifch.qwc > 0 || gspath3done == false) { - if (!gifUnit.Path3Masked()) { - CPU_INT(DMAC_GIF, 128); - } + if (!gifUnit.Path3Masked() || gifRegs.stat.FQC < 16) { + GifDMAInt(amtRead * BIAS); return; } } + else { + + if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16) + { + if (gifch.qwc > 0 || gspath3done == false) { + if (!gifUnit.Path3Masked()) { + GifDMAInt(128); + } + return; + } + } + } } if (gifUnit.gsSIGNAL.queued) { GIF_LOG("Path 3 Paused"); - CPU_INT(DMAC_GIF, 128); + GifDMAInt(128); return; } @@ -194,7 +228,7 @@ __fi void gifInterrupt() if (!dmacRegs.ctrl.DMAE) { Console.Warning("gs dma masked, re-scheduling..."); // re-raise the int shortly in the future - CPU_INT( DMAC_GIF, 64 ); + GifDMAInt( 64 ); return; } GIFdma(); @@ -215,11 +249,15 @@ __fi void gifInterrupt() } } } - if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = 0; + if (!CHECK_GIFFIFOHACK) + { + gifRegs.stat.FQC = 0; + clearFIFOstuff(false); + } gscycles = 0; gspath3done = false; gifch.chcr.STR = false; - clearFIFOstuff(false); + hwDmacIrq(DMAC_GIF); 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); } @@ -252,11 +290,6 @@ int _GIFchain() pMem = dmaGetAddr(gifch.madr, false); if (pMem == NULL) { - -#if USE_OLD_GIF == 1 // d - // reset path3, fixes dark cloud 2 - GIFPath_Clear( GIF_PATH_3 ); -#endif //must increment madr and clear qwc, else it loops gifch.madr += gifch.qwc * 16; gifch.qwc = 0; @@ -291,8 +324,8 @@ static __fi tDMA_TAG* ReadTag() if (!(gifch.transfer("Gif", ptag))) return NULL; - gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR - gscycles += 2; // Add 1 cycles from the QW read for the tag + gifch.madr = ptag[1]._u32; //MADR = ADDR field + SPR + gscycles += 2; // Add 1 cycles from the QW read for the tag gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID); return ptag; @@ -309,14 +342,14 @@ static __fi tDMA_TAG* ReadTag2() return ptag; } -bool CheckPaths(EE_EventType Channel) { +bool CheckPaths() { // Can't do Path 3, so try dma again later... if (!CHECK_GIFFIFOHACK) { if (!gifUnit.CanDoPath3()) { if (!gifUnit.Path3Masked()) { GIF_LOG("Path3 stalled"); - CPU_INT(Channel, 128); + GifDMAInt(128); } return false; } @@ -331,14 +364,14 @@ void GIFdma() if (gifRegs.ctrl.PSE) { // temporarily stop Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)"); - CPU_INT(DMAC_GIF, 16); + GifDMAInt(16); return; } if ((dmacRegs.ctrl.STD == STD_GIF) && (prevcycles != 0)) { //Console.WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3, gifch.madr, psHu32(DMAC_STADR)); if ((gifch.madr + (gifch.qwc * 16)) > dmacRegs.stadr.ADDR) { - CPU_INT(DMAC_GIF, 4); + GifDMAInt(4); gscycles = 0; return; } @@ -365,7 +398,7 @@ void GIFdma() gifch.tadr -= 16; gifch.qwc = 0; hwDmacIrq(DMAC_STALL_SIS); - CPU_INT(DMAC_GIF, gscycles); + GifDMAInt(gscycles); gscycles = 0; return; } @@ -378,36 +411,27 @@ void GIFdma() Console.WriteLn("GIF DMA Stall in Normal mode not implemented - Report which game to PCSX2 Team"); } - clearFIFOstuff(true); - if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] -#if USE_OLD_GIF == 1 // ... - if (vif1Regs.mskpath3 || gifRegs.mode.M3R) { - if (GSTransferStatus.PTH3 == STOPPED_MODE) { - MSKPATH3_LOG("Path3 Paused by VIF QWC %x", gifch.qwc); - - if(gifch.qwc == 0) CPU_INT(DMAC_GIF, 4); - else gifRegs.stat.set_flags(GIF_STAT_P3Q); - return; - } + if (!CHECK_GIFFIFOHACK) { + gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] + clearFIFOstuff(true); } -#endif // Transfer Dn_QWC from Dn_MADR to GIF if (gifch.qwc > 0) // Normal Mode { - if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] - - if (!CheckPaths(DMAC_GIF)) return; + if (CheckPaths() == false) return; GIFchain(); //Transfers the data set by the switch - CPU_INT(DMAC_GIF, gscycles); + //if (gscycles < 8) DevCon.Warning("GSCycles = %d", gscycles); + GifDMAInt(gscycles); return; } else if(!gspath3done) GIFdma(); //Loop round if there was a blank tag, causes hell otherwise with P3 masking games. + //QWC == 0 && gspath3done == true - End of DMA prevcycles = 0; - CPU_INT(DMAC_GIF, gscycles); - if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC = std::min((u16)0x10, gifch.qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] + //if (gscycles < 8) DevCon.Warning("1 GSCycles = %d", gscycles); + GifDMAInt(16); } void dmaGIF() @@ -418,12 +442,15 @@ void dmaGIF() gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :) - if (!CHECK_GIFFIFOHACK)gifRegs.stat.FQC |= 0x10; // hack ;) + if (!CHECK_GIFFIFOHACK) { + gifRegs.stat.FQC |= 0x10; // hack ;) + clearFIFOstuff(true); + } if (gifch.chcr.MOD == NORMAL_MODE) { //Else it really is a normal transfer and we want to quit, else it gets confused with chains gspath3done = true; } - clearFIFOstuff(true); + if(gifch.chcr.MOD == CHAIN_MODE && gifch.qwc > 0) { //DevCon.Warning(L"GIF QWC on Chain " + gifch.chcr.desc()); @@ -461,29 +488,43 @@ static __fi bool mfifoGIFrbTransfer() u16 mfifoqwc = std::min(QWCinGIFMFIFO(gifch.madr), gifch.qwc); if (mfifoqwc == 0) return true; //Lets skip all this, we don't have the data - if(!gifUnit.CanDoPath3()) { + /*if(!gifUnit.CanDoPath3()) { DevCon.Warning("mfifoGIFrbTransfer() - Can't do path3"); + GifDMAInt(16); return true; // Skip if can't do path3 - } + }*/ bool needWrap = (gifch.madr + (mfifoqwc * 16u)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u); uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4; uint s2 = mfifoqwc - s1; uint s3 = needWrap ? s1 : mfifoqwc; - + u32 t1, t2; gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK); u8* src = (u8*)PSM(gifch.madr); if (src == NULL) return false; - u32 t1 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s3*16) / 16; // First part + + if (CHECK_GIFFIFOHACK) { + t1 = gif_fifo.write((u32*)src, s3); + } + else { + t1 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s3 * 16) / 16; // First part + } + incGifChAddr(t1); mfifocycles += t1 * 2; // guessing - if (needWrap && t1) { // Need to do second transfer to wrap around + if (needWrap && t1 == s1) { // Need to do second transfer to wrap around GUNIT_WARN("mfifoGIFrbTransfer() - Wrap"); src = (u8*)PSM(dmacRegs.rbor.ADDR); gifch.madr = dmacRegs.rbor.ADDR; if (src == NULL) return false; - u32 t2 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s2*16) / 16; // Second part + if (CHECK_GIFFIFOHACK) { + t2 = gif_fifo.write((u32*)src, s2); + } + else { + t2 = gifUnit.TransferGSPacketData(GIF_TRANS_DMA, src, s2 * 16) / 16; // First part + } + incGifChAddr(t2); mfifocycles += t2 * 2; // guessing } @@ -494,9 +535,9 @@ static __fi bool mfifoGIFchain() { /* Is QWC = 0? if so there is nothing to transfer */ if (gifch.qwc == 0) return true; - + if (gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u)) DevCon.Warning("Edge Case?"); if (gifch.madr >= dmacRegs.rbor.ADDR && - gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u)) + gifch.madr < (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16u)) { bool ret = true; // if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF"); @@ -557,14 +598,17 @@ void mfifoGIFtransfer(int qwc) tDMA_TAG *ptag; mfifocycles = 0; gifmfifoirq = false; - DevCon.Warning("GIF MFIFO"); + //DevCon.Warning("GIF MFIFO"); if (qwc > 0 ) { if ((gifstate & GIF_STATE_EMPTY)) { - if(gifch.chcr.STR && !(cpuRegs.interrupt & (1< 0) return; + if (!gifUnit.Path3Masked() || gifRegs.stat.FQC < 16) { + GifDMAInt(amtRead * BIAS); + return; + } + } + else { + + if (!gifUnit.CanDoPath3() && gifRegs.stat.FQC == 16) + { + if (gifch.qwc > 0 || gspath3done == false) { + if (!gifUnit.Path3Masked()) { + GifDMAInt(128); + } + return; + } + } } - } if (dmacRegs.ctrl.MFD != MFD_GIF) { @@ -670,12 +715,14 @@ void gifMFIFOInterrupt() if (gifUnit.gsSIGNAL.queued) { //DevCon.WriteLn("Path 3 Paused"); - CPU_INT(DMAC_MFIFO_GIF, 128); + GifDMAInt(128); return; } if((gifstate & GIF_STATE_EMPTY)) { FireMFIFOEmpty(); + if (CHECK_GIFFIFOHACK) + GifDMAInt(128); if(!(gifstate & GIF_STATE_STALL)) return; } @@ -691,7 +738,9 @@ void gifMFIFOInterrupt() if (QWCinGIFMFIFO(gifch.tadr) == 0) { gifstate |= GIF_STATE_EMPTY; - CPU_INT(DMAC_MFIFO_GIF, 4); + GifDMAInt(4); + if (CHECK_GIFFIFOHACK) + GifDMAInt(128); return; } mfifoGIFtransfer(0); @@ -703,20 +752,41 @@ void gifMFIFOInterrupt() return; } + if (gifRegs.stat.FQC > 0) { + //DevCon.Warning("GIF Ending with stuff still in it?"); + GifDMAInt(16); + return; + } + //if(gifqwc > 0) Console.WriteLn("GIF MFIFO ending with stuff in it %x", gifqwc); if (!gifmfifoirq) gifqwc = 0; gspath3done = false; gscycles = 0; - gifRegs.stat.FQC = 0; + if (!CHECK_GIFFIFOHACK) + { + gifRegs.stat.FQC = 0; + clearFIFOstuff(false); + } //vif1Regs.stat.VGW = false; // old code had this + gifCheckPathStatus(); + + if (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); + } + } + gifch.chcr.STR = false; gifstate = GIF_STATE_READY; hwDmacIrq(DMAC_GIF); DMA_LOG("GIF MFIFO DMA End"); - clearFIFOstuff(false); } void SaveStateBase::gifDmaFreeze() { diff --git a/pcsx2/Gif.h b/pcsx2/Gif.h index 4ab58026ac..2828ee4ce2 100644 --- a/pcsx2/Gif.h +++ b/pcsx2/Gif.h @@ -15,7 +15,6 @@ #pragma once -#define USE_OLD_GIF 0 #define COPY_GS_PACKET_TO_MTGS 0 #define PRINT_GIF_PACKET 0 diff --git a/pcsx2/Gif_Unit.h b/pcsx2/Gif_Unit.h index a2fb25cae6..43955af02a 100644 --- a/pcsx2/Gif_Unit.h +++ b/pcsx2/Gif_Unit.h @@ -592,12 +592,11 @@ struct Gif_Unit { break; // Not finished with GS packet } //DevCon.WriteLn("Adding GS Packet for path %d", stat.APATH); - AddCompletedGSPacket(gsPack, (GIF_PATH)(stat.APATH-1)); - /*if (path.curSize == path.curOffset) - curPath = 0;*/ + if (gifPath[curPath].state == GIF_PATH_WAIT || gifPath[curPath].state == GIF_PATH_IDLE) { + AddCompletedGSPacket(gsPack, (GIF_PATH)(stat.APATH - 1)); + } } - if (!gsSIGNAL.queued && !gifPath[0].isDone()) { stat.APATH = 1; stat.P1Q = 0; @@ -623,11 +622,10 @@ struct Gif_Unit { break; } } - //Some loaders/Refresh Rate selectors and things dont issue "End of Packet" commands //So we look and see if the end of the last tag is all there, if so, stick it in the buffer for the GS :) //(Invisible Screens on Terminator 3 and Growlanser 2/3) - if(gifPath[curPath].curOffset == gifPath[curPath].curSize) + if(gifPath[curPath].curOffset == gifPath[curPath].curSize) { FlushToMTGS(); } diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 71ab3034c3..e6dbd90719 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -200,15 +200,7 @@ __fi void vif1FBRST(u32 value) { if(gifUnit.checkPaths(1,0,1)) gifUnit.Execute(false, true); } } - -#if USE_OLD_GIF == 1 // ... - if(vif1Regs.mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gifch.chcr.STR) { - DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs.mskpath3); - gifInterrupt(); - vif1Regs.mskpath3 = false; - gifRegs.stat.M3P = false; - } -#endif + GUNIT_WARN(Color_Red, "VIF FBRST Reset MSK = %x", vif1Regs.mskpath3); vif1Regs.mskpath3 = false; gifRegs.stat.M3P = 0; diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index fe74d91dcf..b9d60d7706 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -406,14 +406,11 @@ vifOp(vifCode_MskPath3) { pass1 { vif1Regs.mskpath3 = (vif1Regs.code >> 15) & 0x1; gifRegs.stat.M3P = (vif1Regs.code >> 15) & 0x1; - GUNIT_LOG("Vif1 - MskPath3 [p3 = %s]", vif1Regs.mskpath3 ? "disabled" : "enabled"); + GUNIT_LOG("Vif1 - MskPath3 [p3 = %s]", vif1Regs.mskpath3 ? "masked" : "enabled"); if(!vif1Regs.mskpath3) { - //if(!gifUnit.gifPath[GIF_PATH_3].isDone() || gifRegs.stat.P3Q || gifRegs.stat.IP3) { - GUNIT_WARN("Path3 triggering!"); - if(CHECK_GIFFIFOHACK)gif_fifo.read(false); - else gifInterrupt(); - GIF_LOG("GIF state on mskpth3 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); - //} + GUNIT_WARN("Path3 triggering!"); + if(CHECK_GIFFIFOHACK)gif_fifo.read(false); + else gifInterrupt(); } vif1.cmd = 0; vif1.pass = 0;