__fi void gifInterrupt() { GIF_LOG("gifInterrupt caught!"); 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); //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) { GifDMAInt(16); } return; } } if (dmacRegs.ctrl.MFD == MFD_GIF) { // GIF MFIFO //Console.WriteLn("GIF MFIFO"); gifMFIFOInterrupt(); return; } if (CHECK_GIFFIFOHACK) { if (int amtRead = gif_fifo.read(true)) { 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"); GifDMAInt(128); return; } if (!(gifch.chcr.STR)) return; if ((gifch.qwc > 0) || (!gspath3done)) { if (!dmacRegs.ctrl.DMAE) { Console.Warning("gs dma masked, re-scheduling..."); // re-raise the int shortly in the future GifDMAInt( 64 ); return; } GIFdma(); return; } //Double check as we might have read the fifo as it's ending the DMA 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); } } } if (!CHECK_GIFFIFOHACK) { gifRegs.stat.FQC = 0; clearFIFOstuff(false); } gscycles = 0; gspath3done = false; gifch.chcr.STR = 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); }
__fi void gifInterrupt() { GIF_LOG("gifInterrupt caught!"); 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(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; 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); //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); return; } } if (dmacRegs.ctrl.MFD == MFD_GIF) { // GIF MFIFO //Console.WriteLn("GIF MFIFO"); gifMFIFOInterrupt(); return; } if (gifUnit.gsSIGNAL.queued) { //DevCon.WriteLn("Path 3 Paused"); CPU_INT(DMAC_GIF, 128); return; } if (!(gifch.chcr.STR)) return; if ((gifch.qwc > 0) || (!gspath3done)) { if (!dmacRegs.ctrl.DMAE) { Console.Warning("gs dma masked, re-scheduling..."); // re-raise the int shortly in the future CPU_INT( DMAC_GIF, 64 ); return; } GIFdma(); return; } gifRegs.stat.FQC = 0; gscycles = 0; gspath3done = false; gifch.chcr.STR = false; clearFIFOstuff(false); hwDmacIrq(DMAC_GIF); DMA_LOG("GIF DMA End"); }