From b1954edc3d6bb8e691cff37e26601ddf8b076050 Mon Sep 17 00:00:00 2001 From: refraction Date: Thu, 15 Apr 2010 00:32:58 +0000 Subject: [PATCH] - Better implementation of Reverse FIFO (Fatal Frame QWC Warning and more!) - Improved handling of suspended DMA's, Also some traps in case DMA values are changed during suspend (please report if they don't start with 5 or 6) - Better handling of GS Path priorities, this improves many Path3 Masked games such as Star Wars Episode 3, Gran Turismo 4 (slightly) and Videos like Digital Devil Saga/FFX - Removed Voodoo Cycles - Doesn't kill everything this time :P git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2853 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Dmac.h | 2 +- pcsx2/FiFo.cpp | 11 +- pcsx2/GS.cpp | 2 +- pcsx2/Gif.cpp | 61 +++++----- pcsx2/Gif.h | 22 +++- pcsx2/Hw.h | 2 +- pcsx2/HwWrite.cpp | 256 +++++++++++++++++++++++++---------------- pcsx2/IPU/IPU.cpp | 102 ++++++++++------ pcsx2/R5900.cpp | 5 + pcsx2/SPR.cpp | 8 ++ pcsx2/Sif0.cpp | 3 + pcsx2/Sif1.cpp | 4 + pcsx2/Vif.cpp | 17 ++- pcsx2/Vif0_Dma.cpp | 7 +- pcsx2/Vif1_Dma.cpp | 39 ++++--- pcsx2/Vif1_MFIFO.cpp | 5 +- pcsx2/Vif_Codes.cpp | 17 +-- pcsx2/Vif_Dma.h | 16 ++- pcsx2/Vif_Transfer.cpp | 2 +- pcsx2/ps2/GIFpath.cpp | 80 +++++++++++-- 20 files changed, 443 insertions(+), 218 deletions(-) diff --git a/pcsx2/Dmac.h b/pcsx2/Dmac.h index 1b5c7689f7..a912ec8e0a 100644 --- a/pcsx2/Dmac.h +++ b/pcsx2/Dmac.h @@ -401,7 +401,7 @@ static __forceinline const wxChar* ChcrName(u32 addr) case D6_CHCR: return L"Sif 1"; case D7_CHCR: return L"Sif 2"; case D8_CHCR: return L"SPR 0"; - case SPR1_CHCR: return L"SPR 1"; + case D9_CHCR: return L"SPR 1"; default: return L"???"; } } diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index d8c5c75ba6..90ac8c6d01 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -60,10 +60,15 @@ void __fastcall ReadFIFO_page_5(u32 mem, u64 *out) if (vif1Regs->stat.test(VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS) ) DevCon.Warning( "Reading from vif1 fifo when stalled" ); + if(vif1Regs->stat.FQC == 0) Console.Warning("FQC = 0 on VIF FIFO READ!"); if (vif1Regs->stat.FDR) { - if (--psHu32(D1_QWC) == 0) - vif1Regs->stat.FQC = 0; + if (vif1Regs->stat.FQC > 0) + { + GetMTGS().WaitGS(); + GSreadFIFO(&psHu64(VIF1_FIFO)); + } + if(vif1Regs->stat.FQC > 0)--vif1Regs->stat.FQC; } out[0] = psHu64(VIF1_FIFO); @@ -184,4 +189,4 @@ void __fastcall WriteFIFO_page_7(u32 mem, const mem128_t *value) Threading::Timeslice(); } } -} \ No newline at end of file +} diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index ad43ac8852..9c6d256897 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -59,7 +59,7 @@ void gsReset() GetMTGS().ResetGS(); UpdateVSyncRate(); - + GSTransferStatus = (STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE; memzero(g_RealGSMem); GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index dfa555cb48..bdc6603ae0 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -56,22 +56,7 @@ __forceinline void gsInterrupt() } - - if ((vif1.cmd & 0x7e) == 0x50) // DIRECT/HL - { - - //original behaviour here - if (Path3progress != IMAGE_MODE) vif1Regs->stat.VGW = false; - - // Transfer in progress on VIF and GIF has finished so let VIF do its bit - if (Path3progress == STOPPED_MODE) - { - vif1Regs->stat.VGW = false; - CPU_INT( DMAC_GIF, 4 ); - return; - } - } - - if (Path3progress == STOPPED_MODE) + if (GSTransferStatus.PTH3 == STOPPED_MODE) { gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_OPH); } @@ -90,12 +75,15 @@ __forceinline void gsInterrupt() return; } + if((gif->chcr.MOD == CHAIN_MODE) && ((gif->chcr.TAG >> 12) & 0x7) != 0x0 && ((gif->chcr.TAG >> 12) & 0x7) != 0x7 && !((gif->chcr.TAG >> 12) & 0x8)) + DevCon.Warning("GIF Ending when refe or end not set! CHCR = %x", gif->chcr._u32); + gspath3done = false; gscycles = 0; gif->chcr.STR = false; vif1Regs->stat.VGW = false; - gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_P3Q | GIF_STAT_FQC); + gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_OPH | GIF_STAT_FQC); clearFIFOstuff(false); hwDmacIrq(DMAC_GIF); @@ -104,9 +92,6 @@ __forceinline void gsInterrupt() static u32 WRITERING_DMA(u32 *pMem, u32 qwc) { - gifRegs->stat.APATH = GIF_APATH3; - gifRegs->stat.OPH = true; - int size = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc); u8* pgsmem = GetMTGS().GetDataPacketPtr(); @@ -216,16 +201,24 @@ void GIFdma() } clearFIFOstuff(true); - gifRegs->stat.FQC |= 0x10;// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] + gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] //Path2 gets priority in intermittent mode - if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7e) == 0x50) && gifRegs->mode.IMT && (Path3progress == STOPPED_MODE)) + if (GSTransferStatus.PTH1 != STOPPED_MODE || GSTransferStatus.PTH2 != STOPPED_MODE) { // We are in image mode doing DIRECTHL, Path 1 is in queue, and in intermittant mode. - GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", gifRegs->stat.P1Q, (vif1.cmd & 0x7f), gifRegs->mode._u32, Path3progress); + //GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", gifRegs->stat.P1Q, (vif1.cmd & 0x7f), gifRegs->mode._u32, GSTransferStatus.PTH3); + /*if(GSTransferStatus.PTH3 == STOPPED_MODE) + { + + } else Console.Warning("PATH3 Transfer in action while another one path is running, Path3 mode %x", GSTransferStatus.PTH3);*/ + gifRegs->stat.set_flags(GIF_STAT_P2Q); CPU_INT(DMAC_GIF, 16); return; } + gifRegs->stat.clear_flags(GIF_STAT_P2Q); + gifRegs->stat.APATH = GIF_APATH3; + gifRegs->stat.OPH = true; if (vif1Regs->mskpath3 || gifRegs->mode.M3R) { @@ -234,6 +227,7 @@ void GIFdma() if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR) { ptag = ReadTag(); + gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] if (ptag == NULL) return; GIF_LOG("PTH3 MASK gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr); @@ -242,15 +236,17 @@ void GIFdma() } } - if (Path3progress == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/ + if (GSTransferStatus.PTH3 == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/ { + GIF_LOG("PTH3 MASK Continuing VIF"); vif1Regs->stat.VGW = false; if (gif->qwc == 0) CPU_INT(DMAC_GIF, 16); return; } - + gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] //Check with Path3 masking games if (gif->qwc > 0) { + GIF_LOG("PTH3 MASK Transferring", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr); GIFchain(); CPU_INT(DMAC_GIF, gscycles * BIAS); return; @@ -266,7 +262,7 @@ void GIFdma() { Console.WriteLn("DMA Stall Control on GIF normal"); } - + gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] //Check with Path3 masking games if (gif->qwc > 0) { GIFchain(); //Transfers the data set by the switch @@ -284,7 +280,7 @@ void GIFdma() ptag = ReadTag(); if (ptag == NULL) return; GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr); - + gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] if (dmacRegs->ctrl.STD == STD_GIF) { // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall @@ -325,6 +321,7 @@ void GIFdma() CPU_INT(DMAC_GIF, gscycles * BIAS); gscycles = 0; } + gifRegs->stat.FQC = max((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] } void dmaGIF() @@ -333,7 +330,7 @@ void dmaGIF() //It takes the time of 24 QW for the BUS to become ready - The Punisher And Streetball GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr._u32, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1); - Path3progress = STOPPED_MODE; + GSTransferStatus.PTH3 = STOPPED_MODE; gspath3done = false; // For some reason this doesn't clear? So when the system starts the thread, we will clear it :) gifRegs->stat.P3Q = true; @@ -546,7 +543,7 @@ void gifMFIFOInterrupt() //Console.WriteLn("gifMFIFOInterrupt"); mfifocycles = 0; - if (Path3progress == STOPPED_MODE) + if (GSTransferStatus.PTH3 == STOPPED_MODE) { gifRegs->stat.APATH = GIF_APATH_IDLE; gifRegs->stat.OPH = false; @@ -565,9 +562,9 @@ void gifMFIFOInterrupt() return; } - if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7f) == 0x50) && gifRegs->mode.IMT && Path3progress == IMAGE_MODE) //Path2 gets priority in intermittent mode + if ((gifRegs->stat.P1Q || (vif1.cmd & 0x7f) == 0x50) && gifRegs->mode.IMT && GSTransferStatus.PTH3 == IMAGE_MODE) //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); + //GIF_LOG("Waiting VU %x, PATH2 %x, GIFMODE %x Progress %x", psHu32(GIF_STAT) & 0x100, (vif1.cmd & 0x7f), psHu32(GIF_MODE), GSTransferStatus.PTH3); CPU_INT(11,mfifocycles); return; } @@ -620,4 +617,4 @@ void SaveStateBase::gifFreeze() Freeze( gscycles ); //Freeze(gifempty); // Note: mfifocycles is not a persistent var, so no need to save it here. -} \ No newline at end of file +} diff --git a/pcsx2/Gif.h b/pcsx2/Gif.h index d4f08c72fd..c79a1cc949 100644 --- a/pcsx2/Gif.h +++ b/pcsx2/Gif.h @@ -26,13 +26,29 @@ enum gifstate_t GIF_STATE_EMPTY = 0x10 }; -enum Path3Modes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet +enum GSTransferModes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet { IMAGE_MODE = 0, TRANSFER_MODE = 1, STOPPED_MODE = 2 }; +union tGSTransferStatus { + struct { + u32 PTH1 : 2; // Resets Vif(0/1) when written. + u32 PTH2 : 2; // Causes a Forcebreak to Vif((0/1) when true. (Stall) + u32 PTH3 : 2; // Stops after the end of the Vifcode in progress when true. (Stall) + u32 reserved : 26; + }; + u32 _u32; + + tGSTransferStatus(u32 val) { _u32 = val; } + bool test (u32 flags) const { return !!(_u32 & flags); } + void set_flags (u32 flags) { _u32 |= flags; } + void clear_flags(u32 flags) { _u32 &= ~flags; } + void reset() { _u32 = 0; } + wxString desc() const { return wxsFormat(L"GSTransferStatus.PTH3: 0x%x", _u32); } +}; //GIF_STAT enum gif_stat_flags { @@ -262,7 +278,7 @@ struct GIFregisters #define gifRegs ((GIFregisters*)(PS2MEM_HW+0x3000)) -extern Path3Modes Path3progress; +extern tGSTransferStatus GSTransferStatus; extern void gsInterrupt(); extern int _GIFchain(); @@ -271,4 +287,4 @@ extern void dmaGIF(); extern void mfifoGIFtransfer(int qwc); extern void gifMFIFOInterrupt(); -#endif \ No newline at end of file +#endif diff --git a/pcsx2/Hw.h b/pcsx2/Hw.h index 228def8a76..c67e1c091f 100644 --- a/pcsx2/Hw.h +++ b/pcsx2/Hw.h @@ -186,7 +186,7 @@ enum EERegisterAddresses D8_MADR = 0x1000D010, D8_QWC = 0x1000D020, D8_SADR = 0x1000D080, - SPR1_CHCR = 0x1000D400, + D9_CHCR = 0x1000D400, DMAC_CTRL = 0x1000E000, DMAC_STAT = 0x1000E010, diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp index a7251cd127..0ef807d528 100644 --- a/pcsx2/HwWrite.cpp +++ b/pcsx2/HwWrite.cpp @@ -46,7 +46,7 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value ) } psHu8(mem) = (u8)value; - if ((psHu8(mem) & 0x1) && dmacRegs->ctrl.DMAE) + if ((psHu8(mem) & 0x1) && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2)) { /*Console.WriteLn("Running DMA 8 %x", psHu32(mem & ~0x1));*/ func(); @@ -80,7 +80,7 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value ) } psHu16(mem) = chcr.lower(); - if (reg->chcr.STR && dmacRegs->ctrl.DMAE) + if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2)) { //Console.WriteLn("16bit DMA Start"); func(); @@ -97,10 +97,13 @@ static void DmaExec( void (*func)(), u32 mem, u32 value ) //It's invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC if (chcr.STR && reg->chcr.STR && dmacRegs->ctrl.DMAE) { - DevCon.Warning(L"DMAExec32 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem); + if((reg->chcr._u32 & 0xff) == (chcr._u32 & 0xff)) //Tried to start another DMA in the same mode + DevCon.Warning(L"DMAExec32 Attempt to run DMA while one is already active in %s(%x)", ChcrName(mem), mem); + else //Just trying to change mode without stopping the DMA, so we dont care really :P + HW_LOG("Attempted to change modes while DMA active, ignoring"); // When DMA is active only STR field is writable, so we just // call the dma transfer function w/o modifying CHCR contents... - func(); + //func(); Registers::Thaw(); return; // Test with Gust games and fatal frame } @@ -122,17 +125,53 @@ static void DmaExec( void (*func)(), u32 mem, u32 value ) else /* Else (including Normal mode etc) write whatever the hardware sends*/ reg->chcr.set(value); - if (reg->chcr.STR && dmacRegs->ctrl.DMAE) func(); + if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2)) func(); Registers::Thaw(); } +static bool QuickDmaExec( void (*func)(), u32 mem) +{ + bool ret = false; + + Registers::Freeze(); + + DMACh *reg = &psH_DMACh(mem); + + if (reg->chcr.STR && dmacRegs->ctrl.DMAE && !psHu8(DMAC_ENABLER+2)) + { + func(); + ret = true; + } + + Registers::Thaw(); + return ret; +} + + +tDMAC_QUEUE QueuedDMA(0); +u32 oldvalue = 0; + +void __fastcall StartQueuedDMA() +{ + if (QueuedDMA.VIF0) { DMA_LOG("Resuming DMA for VIF0"); if(QuickDmaExec(dmaVIF0, D0_CHCR) == true) QueuedDMA.VIF0 = false; } + if (QueuedDMA.VIF1) { DMA_LOG("Resuming DMA for VIF1"); if(QuickDmaExec(dmaVIF1, D1_CHCR) == true) QueuedDMA.VIF0 = false; } + if (QueuedDMA.GIF ) { DMA_LOG("Resuming DMA for GIF" ); if(QuickDmaExec(dmaGIF , D2_CHCR) == true) QueuedDMA.GIF = false; } + if (QueuedDMA.IPU0) { DMA_LOG("Resuming DMA for IPU0"); if(QuickDmaExec(dmaIPU0, D3_CHCR) == true) QueuedDMA.IPU0 = false; } + if (QueuedDMA.IPU1) { DMA_LOG("Resuming DMA for IPU1"); if(QuickDmaExec(dmaIPU1, D4_CHCR) == true) QueuedDMA.IPU1 = false; } + if (QueuedDMA.SIF0) { DMA_LOG("Resuming DMA for SIF0"); if(QuickDmaExec(dmaSIF0, D5_CHCR) == true) QueuedDMA.SIF0 = false; } + if (QueuedDMA.SIF1) { DMA_LOG("Resuming DMA for SIF1"); if(QuickDmaExec(dmaSIF1, D6_CHCR) == true) QueuedDMA.SIF1 = false; } + if (QueuedDMA.SIF2) { DMA_LOG("Resuming DMA for SIF2"); if(QuickDmaExec(dmaSIF2, D7_CHCR) == true) QueuedDMA.SIF2 = false; } + if (QueuedDMA.SPR0) { DMA_LOG("Resuming DMA for SPR0"); if(QuickDmaExec(dmaSPR0, D8_CHCR) == true) QueuedDMA.SPR0 = false; } + if (QueuedDMA.SPR1) { DMA_LOG("Resuming DMA for SPR1"); if(QuickDmaExec(dmaSPR1, D9_CHCR) == true) QueuedDMA.SPR1 = false; } +} + ///////////////////////////////////////////////////////////////////////// // Hardware WRITE 8 bit char sio_buffer[1024]; int sio_count; -tDMAC_QUEUE QueuedDMA(0); + void hwWrite8(u32 mem, u8 value) { @@ -200,9 +239,9 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("VIF0dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit VIF0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit VIF0 DMA Start while DMAC Disabled\n"); QueuedDMA.VIF0 = true; - } + } else QueuedDMA.VIF0 = false; DmaExec8(dmaVIF0, mem, value); break; @@ -210,9 +249,9 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("VIF1dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit VIF1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit VIF1 DMA Start while DMAC Disabled\n"); QueuedDMA.VIF1 = true; - } + } else QueuedDMA.VIF1 = false; if(value & 0x1) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO DmaExec8(dmaVIF1, mem, value); break; @@ -221,9 +260,9 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("GSdma EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit GIF DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit GIF DMA Start while DMAC Disabled\n"); QueuedDMA.GIF = true; - } + } else QueuedDMA.GIF = false; DmaExec8(dmaGIF, mem, value); break; @@ -231,9 +270,9 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("IPU0dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit IPU0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit IPU0 DMA Start while DMAC Disabled\n"); QueuedDMA.IPU0 = true; - } + } else QueuedDMA.IPU0 = false; DmaExec8(dmaIPU0, mem, value); break; @@ -241,9 +280,9 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("IPU1dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit IPU1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit IPU1 DMA Start while DMAC Disabled\n"); QueuedDMA.IPU1 = true; - } + } else QueuedDMA.IPU1 = false; DmaExec8(dmaIPU1, mem, value); break; @@ -252,9 +291,9 @@ void hwWrite8(u32 mem, u8 value) // if (value == 0) psxSu32(0x30) = 0x40000; if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit SIF0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit SIF0 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF0 = true; - } + } else QueuedDMA.SIF0 = false; DmaExec8(dmaSIF0, mem, value); break; @@ -262,9 +301,9 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("SIF1dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit SIF1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit SIF1 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF1 = true; - } + } else QueuedDMA.SIF1 = false; DmaExec8(dmaSIF1, mem, value); break; @@ -272,9 +311,9 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("SIF2dma EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit SIF2 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit SIF2 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF2 |= true; - } + } else QueuedDMA.SIF2 = false; DmaExec8(dmaSIF2, mem, value); break; @@ -282,25 +321,30 @@ void hwWrite8(u32 mem, u8 value) DMA_LOG("fromSPRdma8 EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit SPR0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit SPR0 DMA Start while DMAC Disabled\n"); QueuedDMA.SPR0 = true; - } + } else QueuedDMA.SPR0 = false; DmaExec8(dmaSPR0, mem, value); break; - case SPR1_CHCR + 1: // dma9 - toSPR + case D9_CHCR + 1: // dma9 - toSPR DMA_LOG("toSPRdma8 EXECUTE, value=0x%x", value); if ((value & 0x1) && !dmacRegs->ctrl.DMAE) { - DevCon.Warning("8 bit SPR1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("8 bit SPR1 DMA Start while DMAC Disabled\n"); QueuedDMA .SPR1 = true; - } + } else QueuedDMA.SPR1 = false; DmaExec8(dmaSPR1, mem, value); break; case DMAC_ENABLEW + 2: + oldvalue = psHu8(DMAC_ENABLEW + 2); psHu8(DMAC_ENABLEW + 2) = value; psHu8(DMAC_ENABLER + 2) = value; + if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0)) + { + if (!QueuedDMA.empty()) StartQueuedDMA(); + } break; case SBUS_F200: // SIF(?) @@ -375,21 +419,21 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D0_CHCR: // dma0 - vif0 DMA_LOG("VIF0dma %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit VIF0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit VIF0 DMA Start while DMAC Disabled\n"); QueuedDMA.VIF0 = true; - } + } else QueuedDMA.VIF0 = false; DmaExec16(dmaVIF0, mem, value); break; case D1_CHCR: // dma1 - vif1 - chcr DMA_LOG("VIF1dma CHCR %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit VIF1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit VIF1 DMA Start while DMAC Disabled\n"); QueuedDMA.VIF1 = true; - } + } else QueuedDMA.VIF1 = false; if (CHCR(value).STR) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO DmaExec16(dmaVIF1, mem, value); @@ -430,11 +474,11 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D2_CHCR: // dma2 - gif DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit GIF DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit GIF DMA Start while DMAC Disabled\n"); QueuedDMA.GIF = true; - } + } else QueuedDMA.GIF = false; DmaExec16(dmaGIF, mem, value); break; @@ -472,11 +516,11 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D3_CHCR: // dma3 - fromIPU DMA_LOG("IPU0dma %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit IPU0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit IPU0 DMA Start while DMAC Disabled\n"); QueuedDMA.IPU0 = true; - } + } else QueuedDMA.IPU0 = false; DmaExec16(dmaIPU0, mem, value); break; @@ -504,11 +548,11 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D4_CHCR: // dma4 - toIPU DMA_LOG("IPU1dma %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit IPU1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit IPU1 DMA Start while DMAC Disabled\n"); QueuedDMA.IPU1 = true; - } + } else QueuedDMA.IPU1 = false; DmaExec16(dmaIPU1, mem, value); break; @@ -536,11 +580,11 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D5_CHCR: // dma5 - sif0 DMA_LOG("SIF0dma %lx", value); // if (value == 0) psxSu32(0x30) = 0x40000; - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit SIF0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit SIF0 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF0 = true; - } + } else QueuedDMA.SIF0 = false; DmaExec16(dmaSIF0, mem, value); break; @@ -550,11 +594,11 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D6_CHCR: // dma6 - sif1 DMA_LOG("SIF1dma %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit SIF1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit SIF1 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF1 = true; - } + } else QueuedDMA.SIF1 = false; DmaExec16(dmaSIF1, mem, value); break; @@ -582,11 +626,11 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D7_CHCR: // dma7 - sif2 DMA_LOG("SIF2dma %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit SIF2 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit SIF2 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF2 = true; - } + } else QueuedDMA.SIF2 = false; DmaExec16(dmaSIF2, mem, value); break; @@ -596,27 +640,32 @@ __forceinline void hwWrite16(u32 mem, u16 value) case D8_CHCR: // dma8 - fromSPR DMA_LOG("fromSPRdma %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit SPR0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit SPR0 DMA Start while DMAC Disabled\n"); QueuedDMA.SPR0 = true; - } + } else QueuedDMA.SPR0 = false; DmaExec16(dmaSPR0, mem, value); break; - case SPR1_CHCR: // dma9 - toSPR + case D9_CHCR: // dma9 - toSPR DMA_LOG("toSPRdma %lx", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("16 bit SPR1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("16 bit SPR1 DMA Start while DMAC Disabled\n"); QueuedDMA.SPR1 = true; - } + } else QueuedDMA.SPR1 = false; DmaExec16(dmaSPR1, mem, value); break; case DMAC_ENABLEW + 2: + oldvalue = psHu8(DMAC_ENABLEW + 2); psHu16(DMAC_ENABLEW + 2) = value; psHu16(DMAC_ENABLER + 2) = value; + if (((oldvalue & 0x1) == 1) && ((value & 0x1) == 0)) + { + if (!QueuedDMA.empty()) StartQueuedDMA(); + } break; case SIO_ISR: @@ -764,11 +813,11 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value ) { case D3_CHCR: // dma3 - fromIPU DMA_LOG("IPU0dma EXECUTE, value=0x%x\n", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit IPU0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit IPU0 DMA Start while DMAC Disabled\n"); QueuedDMA.IPU0 = true; - } + } else QueuedDMA.IPU0 = false; DmaExec(dmaIPU0, mem, value); return; @@ -781,11 +830,11 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value ) case D4_CHCR: // dma4 - toIPU DMA_LOG("IPU1dma EXECUTE, value=0x%x\n", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit IPU1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit IPU1 DMA Start while DMAC Disabled\n"); QueuedDMA.IPU1 = true; - } + } else QueuedDMA.IPU1 = false; DmaExec(dmaIPU1, mem, value); return; @@ -799,19 +848,7 @@ void __fastcall hwWrite32_page_0B( u32 mem, u32 value ) psHu32(mem) = value; } -void __fastcall StartQueuedDMA() -{ - if (QueuedDMA.VIF0) { QueuedDMA.VIF0 = false; dmaVIF0(); } - if (QueuedDMA.VIF1) { QueuedDMA.VIF1 = false; dmaVIF1(); } - if (QueuedDMA.GIF ) { QueuedDMA.GIF = false; dmaGIF(); } - if (QueuedDMA.IPU0) { QueuedDMA.IPU0 = false; dmaIPU0(); } - if (QueuedDMA.IPU1) { QueuedDMA.IPU1 = false; dmaIPU1(); } - if (QueuedDMA.SIF0) { QueuedDMA.SIF0 = false; dmaSIF0(); } - if (QueuedDMA.SIF1) { QueuedDMA.SIF1 = false; dmaSIF1(); } - if (QueuedDMA.SIF2) { QueuedDMA.SIF2 = false; dmaSIF2(); } - if (QueuedDMA.SPR0) { QueuedDMA.SPR0 = false; dmaSPR0(); } - if (QueuedDMA.SPR1) { QueuedDMA.SPR1 = false; dmaSPR1(); } -} + void __fastcall hwWrite32_page_0E( u32 mem, u32 value ) { @@ -907,8 +944,13 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value ) case HELPSWITCH(DMAC_ENABLEW): HW_LOG("DMAC_ENABLEW Write 32bit %lx", value); + oldvalue = psHu8(DMAC_ENABLEW + 2); psHu32(DMAC_ENABLEW) = value; psHu32(DMAC_ENABLER) = value; + if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0)) + { + if (!QueuedDMA.empty()) StartQueuedDMA(); + } break; //------------------------------------------------------------------ @@ -932,11 +974,11 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) case D0_CHCR: // dma0 - vif0 DMA_LOG("VIF0dma EXECUTE, value=0x%x", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit VIF0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit VIF0 DMA Start while DMAC Disabled\n"); QueuedDMA.VIF0 = true; - } + } else QueuedDMA.VIF0 = false; DmaExec(dmaVIF0, mem, value); return; @@ -945,11 +987,11 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) case D1_CHCR: // dma1 - vif1 - chcr DMA_LOG("VIF1dma EXECUTE, value=0x%x", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit VIF1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit VIF1 DMA Start while DMAC Disabled\n"); QueuedDMA.VIF1 = true; - } + } else QueuedDMA.VIF1 = false; if (CHCR(value).STR) { @@ -973,11 +1015,11 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) //------------------------------------------------------------------ case D2_CHCR: // dma2 - gif DMA_LOG("GIFdma EXECUTE, value=0x%x", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit GIF DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit GIF DMA Start while DMAC Disabled\n"); QueuedDMA.GIF = true; - } + } else QueuedDMA.GIF = false; DmaExec(dmaGIF, mem, value); return; @@ -992,21 +1034,21 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) case D5_CHCR: // dma5 - sif0 DMA_LOG("SIF0dma EXECUTE, value=0x%x", value); //if (value == 0) psxSu32(0x30) = 0x40000; - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit SIF0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit SIF0 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF0 = true; - } + } else QueuedDMA.SIF0 = false; DmaExec(dmaSIF0, mem, value); return; //------------------------------------------------------------------ case D6_CHCR: // dma6 - sif1 DMA_LOG("SIF1dma EXECUTE, value=0x%x", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit SIF1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit SIF1 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF1 = true; - } + } else QueuedDMA.SIF1 = false; DmaExec(dmaSIF1, mem, value); return; @@ -1017,31 +1059,31 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) //------------------------------------------------------------------ case D7_CHCR: // dma7 - sif2 DMA_LOG("SIF2dma EXECUTE, value=0x%x", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit SIF2 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit SIF2 DMA Start while DMAC Disabled\n"); QueuedDMA.SIF2 = true; - } + } else QueuedDMA.SIF2 = false; DmaExec(dmaSIF2, mem, value); return; //------------------------------------------------------------------ case D8_CHCR: // dma8 - fromSPR DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit SPR0 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit SPR0 DMA Start while DMAC Disabled\n"); QueuedDMA.SPR0 = true; - } + } else QueuedDMA.SPR0 = false; DmaExec(dmaSPR0, mem, value); return; //------------------------------------------------------------------ - case SPR1_CHCR: // dma9 - toSPR + case D9_CHCR: // dma9 - toSPR DMA_LOG("SPR1dma EXECUTE (toSPR), value=0x%x", value); - if (CHCR(value).STR && !dmacRegs->ctrl.DMAE) + if (CHCR(value).STR && (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2))) { - DevCon.Warning("32 bit SPR1 DMA Start while DMAC Disabled\n"); + //DevCon.Warning("32 bit SPR1 DMA Start while DMAC Disabled\n"); QueuedDMA.SPR1 = true; - } + } else QueuedDMA.SPR1 = false; DmaExec(dmaSPR1, mem, value); return; } @@ -1189,8 +1231,13 @@ void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval ) break; case DMAC_ENABLEW: // DMAC_ENABLEW + oldvalue = psHu8(DMAC_ENABLEW + 2); psHu32(DMAC_ENABLEW) = value; psHu32(DMAC_ENABLER) = value; + if (((oldvalue & 0x1) == 1) && (((value >> 16) & 0x1) == 0)) + { + if (!QueuedDMA.empty()) StartQueuedDMA(); + } break; default: @@ -1222,8 +1269,13 @@ void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval) break; case DMAC_ENABLEW: // DMAC_ENABLEW + oldvalue = psHu8(DMAC_ENABLEW + 2); psHu32(DMAC_ENABLEW) = srcval[0]; psHu32(DMAC_ENABLER) = srcval[0]; + if (((oldvalue & 0x1) == 1) && (((srcval[0] >> 16) & 0x1) == 0)) + { + if (!QueuedDMA.empty()) StartQueuedDMA(); + } break; case SIO_ISR: diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 1595c66e97..ccea2e9bc2 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -796,7 +796,7 @@ void IPUCMD_WRITE(u32 val) // have to resort to the thread ipu_cmd.current = val >> 28; ipuRegs->ctrl.BUSY = 1; - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); } void IPUWorker() @@ -808,7 +808,7 @@ void IPUWorker() case SCE_IPU_VDEC: if (!ipuVDEC(ipuRegs->cmd.DATA)) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } ipuRegs->cmd.BUSY = 0; @@ -818,7 +818,7 @@ void IPUWorker() case SCE_IPU_FDEC: if (!ipuFDEC(ipuRegs->cmd.DATA)) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } ipuRegs->cmd.BUSY = 0; @@ -828,7 +828,7 @@ void IPUWorker() case SCE_IPU_SETIQ: if (!ipuSETIQ(ipuRegs->cmd.DATA)) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } break; @@ -836,7 +836,7 @@ void IPUWorker() case SCE_IPU_SETVQ: if (!ipuSETVQ(ipuRegs->cmd.DATA)) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } break; @@ -844,7 +844,7 @@ void IPUWorker() case SCE_IPU_CSC: if (!ipuCSC(ipuRegs->cmd.DATA)) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } if (ipu0dma->qwc > 0 && ipu0dma->chcr.STR) IPU_INT0_FROM(); @@ -853,7 +853,7 @@ void IPUWorker() case SCE_IPU_PACK: if (!ipuPACK(ipuRegs->cmd.DATA)) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } break; @@ -862,7 +862,7 @@ void IPUWorker() so_call(s_routine); if (!s_RoutineDone) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } @@ -881,7 +881,7 @@ void IPUWorker() so_call(s_routine); if (!s_RoutineDone) { - hwIntcIrq(INTC_IPU); + if(ipu1dma->qwc == 0) hwIntcIrq(INTC_IPU); return; } @@ -1276,6 +1276,30 @@ static __forceinline void ipuDmacSrcChain() } } +static __forceinline bool WaitGSPaths() +{ + if (dmacRegs->ctrl.STD != STD_GIF || (gif->madr + (gif->qwc * 16)) < dmacRegs->stadr.ADDR) + { + if(gif->chcr.STR && (vif1Regs->mskpath3 == 0) && GSTransferStatus.PTH3 != STOPPED_MODE) + { + GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc); + //DevCon.WriteLn("Waiting for GIF"); + return false; + } + } + if(GSTransferStatus.PTH2 != STOPPED_MODE) + { + //DevCon.WriteLn("Waiting for VIF"); + return false; + } + if(GSTransferStatus.PTH1 != STOPPED_MODE) + { + //DevCon.WriteLn("Waiting for VU"); + return false; + } + return true; +} + static __forceinline int IPU1chain() { int totalqwc = 0; @@ -1304,7 +1328,7 @@ static __forceinline int IPU1chain() { //If the transfer has finished or we have room in the FIFO, schedule to the interrupt code. if(IPU1Status.DMAFinished == true || g_BP.IFC < 8) { - IPU_INT_TO(totalqwc*BIAS); + IPU_INT_TO(4); } //No data left IPU1Status.InProgress = false; @@ -1314,7 +1338,7 @@ static __forceinline int IPU1chain() { return totalqwc; } -//static __forceinline bool flushGIF() +//static __forceinline bool WaitGSPaths() //{ // //Wait for all GS paths to be clear // if (GSTransferStatus._u32 != 0x2a) @@ -1327,17 +1351,7 @@ static __forceinline int IPU1chain() { // return true; //} -static __forceinline void flushGIF() -{ - if (dmacRegs->ctrl.STD != STD_GIF || (gif->madr + (gif->qwc * 16)) < dmacRegs->stadr.ADDR) - { - while(gif->chcr.STR && (vif1Regs->mskpath3 == 0) && Path3progress != STOPPED_MODE) - { - GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr._u32, gif->tadr, gif->madr, gif->qwc); - gsInterrupt(); - } - } -} + int IPU1dma() { @@ -1346,9 +1360,9 @@ int IPU1dma() int totalqwc = 0; //We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos - //if(!flushGIF()) return totalqwc; + //if(!WaitGSPaths()) return totalqwc; + - flushGIF(); // legacy flushGIF() for now DMA_LOG("IPU1 DMA Called QWC %x Finished %d In Progress %d tadr %x", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress, ipu1dma->tadr); @@ -1356,6 +1370,11 @@ int IPU1dma() { case DMA_MODE_NORMAL: { + if(!WaitGSPaths()) + { // legacy WaitGSPaths() for now + if(totalqwc == 0)IPU_INT_TO(4); //Give it a short wait. + return totalqwc; + } DMA_LOG("Processing Normal QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress); if(IPU1Status.InProgress == true) totalqwc += IPU1chain(); } @@ -1365,6 +1384,11 @@ int IPU1dma() { if(IPU1Status.InProgress == true) //No transfer is ready to go so we need to set one up { + if(!WaitGSPaths()) + { // legacy WaitGSPaths() for now + if(totalqwc == 0)IPU_INT_TO(4); //Give it a short wait. + return totalqwc; + } DMA_LOG("Processing Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress); totalqwc += IPU1chain(); //Set the TADR forward @@ -1449,7 +1473,11 @@ int IPU1dma() IPU1Status.DMAFinished = true; - + if(!WaitGSPaths() && ipu1dma->qwc > 0) + { // legacy WaitGSPaths() for now + if(totalqwc == 0)IPU_INT_TO(4); //Give it a short wait. + return totalqwc; + } DMA_LOG("Processing Start Chain QWC left %x Finished %d In Progress %d", ipu1dma->qwc, IPU1Status.DMAFinished, IPU1Status.InProgress); totalqwc += IPU1chain(); //Set the TADR forward @@ -1469,15 +1497,6 @@ int IPU0dma() static int totalsize = 0; tDMA_TAG* pMem; - // Note: pad is the padding right above qwc, so we're testing whether qwc - // has overflowed into pad. - if (ipu0dma->pad != 0) - { - DevCon.Warning(L"IPU0dma's upper 16 bits set to %x\n", ipu0dma->pad); - ipu0dma->qwc = ipu0dma->pad = 0; - //return 0; - } - if ((!(ipu0dma->chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma->qwc == 0)) return 0; @@ -1533,6 +1552,16 @@ int IPU0dma() __forceinline void dmaIPU0() // fromIPU { + if (ipu0dma->pad != 0) + { + // Note: pad is the padding right above qwc, so we're testing whether qwc + // has overflowed into pad. + DevCon.Warning(L"IPU0dma's upper 16 bits set to %x\n", ipu0dma->pad); + ipu0dma->qwc = ipu0dma->pad = 0; + //If we are going to clear down IPU0, we should end it too. Going to test this scenario on the PS2 mind - Refraction + ipu0dma->chcr.STR = false; + hwDmacIrq(DMAC_FROM_IPU); + } if (ipuRegs->ctrl.BUSY) IPUWorker(); } @@ -1556,7 +1585,6 @@ __forceinline void dmaIPU1() // toIPU } IPU1Status.DMAMode = DMA_MODE_CHAIN; - IPU1dma(); if (ipuRegs->ctrl.BUSY) IPUWorker(); } @@ -1582,9 +1610,7 @@ __forceinline void dmaIPU1() // toIPU IPU1dma(); if (ipuRegs->ctrl.BUSY) IPUWorker(); } - } - - + } } extern void GIFdma(); diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index ddbff98334..fa89de024e 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -270,6 +270,11 @@ static __forceinline void TESTINT( u8 n, void (*callback)() ) static __forceinline void _cpuTestInterrupts() { + if (!dmacRegs->ctrl.DMAE || psHu16(DMAC_ENABLER + 2)) + { + //Console.Write("DMAC Disabled or suspended"); + return; + } /* These are 'pcsx2 interrupts', they handle asynchronous stuff that depends on the cycle timings */ diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index c2915027e0..6106d218e6 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -251,6 +251,10 @@ void SPRFROMinterrupt() } } if (!spr0finished) return; + + if((spr0->chcr.MOD == CHAIN_MODE) && ((spr0->chcr.TAG >> 12) & 0x7) != 0x0 && ((spr0->chcr.TAG >> 12) & 0x7) != 0x7 && !((spr0->chcr.TAG >> 12) & 0x8)) + DevCon.Warning("SPR0 Ending when refe or end not set! CHCR = %x", spr0->chcr._u32); + spr0->chcr.STR = false; hwDmacIrq(DMAC_FROM_SPR); } @@ -424,6 +428,10 @@ void SPRTOinterrupt() { _dmaSPR1(); if (!spr1finished) return; + + if((spr1->chcr.MOD == CHAIN_MODE) && ((spr1->chcr.TAG >> 12) & 0x7) != 0x0 && ((spr1->chcr.TAG >> 12) & 0x7) != 0x7 && !((spr1->chcr.TAG >> 12) & 0x8)) + DevCon.Warning("SPR1 Ending when refe or end not set! CHCR = %x", spr1->chcr._u32); + spr1->chcr.STR = false; hwDmacIrq(DMAC_TO_SPR); } diff --git a/pcsx2/Sif0.cpp b/pcsx2/Sif0.cpp index 9574b08f51..905506185f 100644 --- a/pcsx2/Sif0.cpp +++ b/pcsx2/Sif0.cpp @@ -151,6 +151,9 @@ static __forceinline void EndEE() SIF_LOG("SIF0 EE: cycles = 0"); sif0.ee.cycles = 1; } + if((sif0dma->chcr.MOD == CHAIN_MODE) && ((sif0dma->chcr.TAG >> 12) & 0x7) != 0x0 && ((sif0dma->chcr.TAG >> 12) & 0x7) != 0x7 && !((sif0dma->chcr.TAG >> 12) & 0x8)) + DevCon.Warning("SIF0 Ending when refe or end not set! CHCR = %x", sif0dma->chcr._u32); + CPU_INT(DMAC_SIF0, sif0.ee.cycles*BIAS); } diff --git a/pcsx2/Sif1.cpp b/pcsx2/Sif1.cpp index 0e0a868b07..0135218ed1 100644 --- a/pcsx2/Sif1.cpp +++ b/pcsx2/Sif1.cpp @@ -174,6 +174,10 @@ static __forceinline void EndEE() SIF_LOG("SIF1 EE: cycles = 0"); sif1.ee.cycles = 1; } + + if((sif1dma->chcr.MOD == CHAIN_MODE) && ((sif1dma->chcr.TAG >> 12) & 0x7) != 0x0 && ((sif1dma->chcr.TAG >> 12) & 0x7) != 0x7 && !((sif1dma->chcr.TAG >> 12) & 0x8)) + DevCon.Warning("SIF0 Ending when refe or end not set! CHCR = %x", sif1dma->chcr._u32); + CPU_INT(DMAC_SIF1, min((int)(sif1.ee.cycles*BIAS), 384)); } diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index a52268276c..00611b420d 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -23,7 +23,7 @@ vifStruct vif0; vifStruct vif1; -Path3Modes Path3progress = STOPPED_MODE; +tGSTransferStatus GSTransferStatus = (STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE; void vif0Init() { initNewVif(0); } void vif1Init() { initNewVif(1); } @@ -253,13 +253,20 @@ _f void vif1STAT(u32 value) { if (vif1Regs->stat.FDR) // Vif transferring to memory. { // Hack but it checks this is true before transfer? (fatal frame) - vif1Regs->stat.FQC = 0x1; + // Update Refraction: Use of this function has been investigated and understood. + // Before this ever happens, a DIRECT/HL command takes place sending the transfer info to the GS + // One of the registers told about this is TRXREG which tells us how much data is going to transfer (th x tw) in words + // As far as the GS is concerned, the transfer starts as soon as TRXREG is accessed, which is why fatal frame + // was expecting data, the GS should already be sending it over (buffering in the FIFO) + + vif1Regs->stat.FQC = max((u32)16, vif1.GSLastTRXPOS); + //Console.Warning("Reversing VIF Transfer for %x QWC", vif1.GSLastTRXPOS); + } else // Memory transferring to Vif. { - vif1ch->qwc = 0; - vif1.vifstalled = false; - vif1.done = true; + //Sometimes the value from the GS is bigger than vif wanted, so it just sets it back and cancels it. + //Other times it can read it off ;) vif1Regs->stat.FQC = 0; } } diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index 4fe446f57a..4ed52994d4 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -152,7 +152,7 @@ __forceinline void vif0Interrupt() // VIF_NORMAL_FROM_MEM_MODE is a very slow operation. // Timesplitters 2 depends on this beeing a bit higher than 128. if (vif0.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF0, 1024); - else CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo); + else CPU_INT(DMAC_VIF0, g_vifCycles); return; } @@ -167,7 +167,7 @@ __forceinline void vif0Interrupt() if ((vif0.inprogress & 0x1) == 0) vif0SetupTransfer(); - CPU_INT(DMAC_VIF0, /*g_vifCycles*/ VifCycleVoodoo); + CPU_INT(DMAC_VIF0, g_vifCycles); return; } @@ -182,6 +182,9 @@ __forceinline void vif0Interrupt() if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size); #endif + /*if(vif0.dmamode == VIF_CHAIN_MODE && ((vif0ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif0ch->chcr.TAG >> 12) & 0x7) != 0x7 && !((vif0ch->chcr.TAG >> 12) & 0x8)) + DevCon.Warning("VIF0 Ending when refe or end not set! CHCR = %x", vif0ch->chcr._u32);*/ + vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands; vif0ch->chcr.STR = false; g_vifCycles = 0; diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index 22aab79652..13c794560a 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -50,7 +50,7 @@ void vif1TransferFromMemory() // MTGS concerns: The MTGS is inherently disagreeable with the idea of downloading // stuff from the GS. The *only* way to handle this case safely is to flush the GS // completely and execute the transfer there-after. - + //Console.Warning("Real QWC %x", vif1ch->qwc); XMMRegisters::Freeze(); if (GSreadFIFO2 == NULL) @@ -81,6 +81,11 @@ void vif1TransferFromMemory() g_vifCycles += vif1ch->qwc * 2; vif1ch->madr += vif1ch->qwc * 16; // mgs3 scene changes + if(vif1.GSLastTRXPOS > vif1ch->qwc) + vif1Regs->stat.FQC = vif1.GSLastTRXPOS - vif1ch->qwc; + else + vif1Regs->stat.FQC = 0; + vif1ch->qwc = 0; } @@ -195,12 +200,18 @@ __forceinline void vif1Interrupt() VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle); g_vifCycles = 0; + if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); + //Simulated GS transfer time done, clear the flags + if(gifRegs->stat.APATH == GIF_APATH2 && (vif1.cmd & 0x70) != 0x50) + { + gifRegs->stat.clear_flags(GIF_STAT_APATH2|GIF_STAT_OPH); + } if (schedulepath3msk) Vif1MskPath3(); if ((vif1Regs->stat.VGW)) { - if (gif->chcr.STR && (Path3progress != STOPPED_MODE)) + if ((gif->chcr.STR && (GSTransferStatus.PTH3 != STOPPED_MODE)) || (GSTransferStatus.PTH1 != STOPPED_MODE)) { CPU_INT(DMAC_VIF1, 4); return; @@ -220,7 +231,7 @@ __forceinline void vif1Interrupt() --vif1.irq; if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) { - vif1Regs->stat.FQC = 0; + //vif1Regs->stat.FQC = 0; // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho vif1ch->chcr.STR = false; @@ -240,8 +251,10 @@ __forceinline void vif1Interrupt() _VIF1chain(); // VIF_NORMAL_FROM_MEM_MODE is a very slow operation. // Timesplitters 2 depends on this beeing a bit higher than 128. - if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024); - else CPU_INT(DMAC_VIF1, /*g_vifCycles*/ VifCycleVoodoo); + if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); + // Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games. + /*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024); + else */CPU_INT(DMAC_VIF1, g_vifCycles /*VifCycleVoodoo*/); return; } @@ -255,8 +268,8 @@ __forceinline void vif1Interrupt() } if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer(); - - CPU_INT(DMAC_VIF1, /*g_vifCycles*/ VifCycleVoodoo); + if (vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); + CPU_INT(DMAC_VIF1, g_vifCycles); return; } @@ -275,12 +288,14 @@ __forceinline void vif1Interrupt() vif1ch->chcr.STR = false; g_vifCycles = 0; hwDmacIrq(DMAC_VIF1); - + + /*if(vif1.dmamode == VIF_CHAIN_MODE && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x7 && !((vif1ch->chcr.TAG >> 12) & 0x8)) + DevCon.Warning("VIF1 Ending when refe or end not set! CHCR = %x", vif1ch->chcr._u32);*/ //Im not totally sure why Path3 Masking makes it want to see stuff in the fifo //Games effected by setting, Fatal Frame, KH2, Shox, Crash N Burn, GT3/4 possibly //Im guessing due to the full gs fifo before the reverse? (Refraction) //Note also this is only the condition for reverse fifo mode, normal direction clears it as normal - if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat.FQC = 0; + //if (!vif1Regs->mskpath3 || vif1ch->chcr.DIR) vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); } void dmaVIF1() @@ -298,6 +313,7 @@ void dmaVIF1() //Console.WriteLn("VIFMFIFO\n"); // Test changed because the Final Fantasy 12 opening somehow has the tag in *Undefined* mode, which is not in the documentation that I saw. if (vif1ch->chcr.MOD == NORMAL_MODE) Console.WriteLn("MFIFO mode is normal (which isn't normal here)! %x", vif1ch->chcr._u32); + vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc); vifMFIFOInterrupt(); return; } @@ -325,10 +341,7 @@ void dmaVIF1() vif1.dmamode = VIF_CHAIN_MODE; } - if (vif1.dmamode != VIF_NORMAL_FROM_MEM_MODE) - vif1Regs->stat.FQC = 0x10; - else - vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc); + vif1Regs->stat.FQC = min((u16)0x10, vif1ch->qwc); // Chain Mode vif1.done = false; diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index 23e2bf4c97..d94e49a53a 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -210,7 +210,7 @@ void mfifoVIF1transfer(int qwc) vif1.done = true; } } - + vif1Regs->stat.FQC = min(vif1ch->qwc, (u16)16); vif1.inprogress |= 1; SPR_LOG("mfifoVIF1transfer end %x madr %x, tadr %x vifqwc %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr, vifqwc); @@ -295,6 +295,9 @@ void vifMFIFOInterrupt() hwDmacIrq(DMAC_MFIFO_EMPTY); }*/ + if(((vif1ch->chcr.TAG >> 12) & 0x7) != 0x0 && ((vif1ch->chcr.TAG >> 12) & 0x7) != 0x7) + DevCon.Warning("VIF1 MFIFO Ending when refe or end not set! CHCR = %x", vif1ch->chcr._u32); + vif1.done = 1; g_vifCycles = 0; vif1ch->chcr.STR = false; diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index 2fcdf19185..146f290e63 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -78,9 +78,9 @@ void Vif1MskPath3() { if (!vif1Regs->mskpath3) { //Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely) - Path3progress = TRANSFER_MODE; + GSTransferStatus.PTH3 = TRANSFER_MODE; gifRegs->stat.IMT = false; - CPU_INT(DMAC_GIF, 4); + if(gif->chcr.STR == true) CPU_INT(DMAC_GIF, 4); } else gifRegs->stat.M3P = true; @@ -108,10 +108,10 @@ template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { pass2 { vif1Only(); //return vifTrans_DirectHL((u32*)data); - + gifRegs->stat.P2Q = true; //Should probably do this for both types of transfer seen as the GS hates taking 2 seperate chunks //if (isDirectHL) { - if (gif->chcr.STR && (!vif1Regs->mskpath3 && (Path3progress != STOPPED_MODE))) + if ((gif->chcr.STR && (!vif1Regs->mskpath3 && (GSTransferStatus.PTH3 != STOPPED_MODE))) || GSTransferStatus.PTH1 != STOPPED_MODE) { /*if(!isDirectHL) DevCon.WriteLn("Direct: Waiting for Path3 to finish!"); else DevCon.WriteLn("DirectHL: Waiting for Path3 to finish!");*/ @@ -121,11 +121,14 @@ template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { return 0; } //} + gifRegs->stat.clear_flags(GIF_STAT_P2Q); + gifRegs->stat.APATH = GIF_APATH2; + gifRegs->stat.OPH = true; Registers::Freeze(); nVifStruct& v = nVif[1]; const int ret = aMin(vif1.vifpacketsize, vif1.tag.size); - s32 size = ret << 2; + u32 size = ret << 2; if (ret == v.vif->tag.size) { // Full Transfer if (v.bSize) { // Last transfer was partial @@ -180,7 +183,7 @@ vifOp(vifCode_FlushA) { vif1Only(); pass1 { // Gif is already transferring so wait for it. - if (((Path3progress != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR) { + if (((GSTransferStatus.PTH3 != STOPPED_MODE) || !vif1Regs->mskpath3) && gif->chcr.STR) { //DevCon.WriteLn("FlushA path3 Wait!"); vif1Regs->stat.VGW = true; vifX.vifstalled = true; @@ -467,4 +470,4 @@ int (__fastcall *vif1Code[128])(int pass, u32 *data) = { vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1>, /*0x68*/ vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1>, /*0x70*/ vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Null<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> , vifCode_Unpack<1> /*0x78*/ -}; \ No newline at end of file +}; diff --git a/pcsx2/Vif_Dma.h b/pcsx2/Vif_Dma.h index 75887a82c6..2510806fb0 100644 --- a/pcsx2/Vif_Dma.h +++ b/pcsx2/Vif_Dma.h @@ -24,6 +24,18 @@ struct vifCode { u16 cl; }; +union tBITBLT { + struct { + u32 reserved : 8; + u32 BLTDIVIDE : 8; // This is the value we want to work out the divider for the reverse transfer + u32 reserved2 : 6; + u32 TRXPOS : 16; + }; + u32 _u32; + + +}; + // NOTE, if debugging vif stalls, use sega classics, spyro, gt4, and taito struct vifStruct { vifCode tag; @@ -36,7 +48,10 @@ struct vifStruct { bool done; bool vifstalled; bool stallontag; + tBITBLT TRXPOS; //used for reversed fifo operations, sometimes only the GS knows how big (like on HW register fifo read)! + u32 GSLastTRXPOS; + u8 irqoffset; // 32bit offset where next vif code is u32 savedtag; // need this for backwards compat with save states u32 vifpacketsize; @@ -47,7 +62,6 @@ struct vifStruct { extern vifStruct* vif; extern vifStruct vif0, vif1; extern u8 schedulepath3msk; -static const int VifCycleVoodoo = 4; extern void vif0Init(); extern void vif0Interrupt(); diff --git a/pcsx2/Vif_Transfer.cpp b/pcsx2/Vif_Transfer.cpp index 8c97fed5c1..e4c9425b59 100644 --- a/pcsx2/Vif_Transfer.cpp +++ b/pcsx2/Vif_Transfer.cpp @@ -130,4 +130,4 @@ bool VIF0transfer(u32 *data, int size, bool istag) { } bool VIF1transfer(u32 *data, int size, bool istag) { return vifTransfer<1>(data, size); -} \ No newline at end of file +} diff --git a/pcsx2/ps2/GIFpath.cpp b/pcsx2/ps2/GIFpath.cpp index 2f18a0a62b..8009d6a9fe 100644 --- a/pcsx2/ps2/GIFpath.cpp +++ b/pcsx2/ps2/GIFpath.cpp @@ -18,6 +18,7 @@ #include "GS.h" #include "Gif.h" #include "Vif_Dma.h" +#include "vif.h" // -------------------------------------------------------------------------------------- // GIFpath -- the GIFtag Parser @@ -277,6 +278,40 @@ void SaveStateBase::gifPathFreeze() static __forceinline void gsHandler(const u8* pMem) { const int handler = pMem[8]; + + if(handler == 0x50) + { + const u16* pMem16 = (const u16*)pMem; + + vif1.TRXPOS._u32 = pMem16[1]; + //Console.Warning("BLITBUF = %x %x_%x_%x_%x", vif1.TRXPOS.BLTDIVIDE, pMem16[0], pMem16[1], pMem16[2], pMem16[3]); + switch(vif1.TRXPOS.BLTDIVIDE & 0x3) + { + case 0x3: + VIF_LOG("8bit"); + vif1.TRXPOS.BLTDIVIDE = 16; //8bit + break; + case 0x2: + VIF_LOG("16bit"); + vif1.TRXPOS.BLTDIVIDE = 8; //16bit + break; + case 0x1: + VIF_LOG("24bit"); + vif1.TRXPOS.BLTDIVIDE = 5; //24bit + break; + default: + VIF_LOG("32bit"); + vif1.TRXPOS.BLTDIVIDE = 4; //32bit + break; + } + } + if(handler == 0x52) + { + const u16* pMem16 = (const u16*)pMem; + VIF_LOG("TRX REG = %x_%x_%x_%x", pMem16[0], pMem16[1], pMem16[2], pMem16[3]); + vif1.GSLastTRXPOS = (pMem16[0] * pMem16[2]) / (u8)vif1.TRXPOS.BLTDIVIDE; + + } if (handler >= 0x60) { // Question: What happens if an app writes to uncharted register space on real PS2 @@ -310,14 +345,28 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) SetTag(pMem); incTag(16, 1); - if (pathidx == GIF_PATH_3) { - if (tag.FLG&2) Path3progress = IMAGE_MODE; - else Path3progress = TRANSFER_MODE; + //if (pathidx == GIF_PATH_3) { + switch(pathidx) + { + case GIF_PATH_1: + if (tag.FLG&2) GSTransferStatus.PTH1 = IMAGE_MODE; + else GSTransferStatus.PTH1 = TRANSFER_MODE; + break; + case GIF_PATH_2: + if (tag.FLG&2) GSTransferStatus.PTH2 = IMAGE_MODE; + else GSTransferStatus.PTH2 = TRANSFER_MODE; + break; + case GIF_PATH_3: + if (tag.FLG&2) GSTransferStatus.PTH3 = IMAGE_MODE; + else GSTransferStatus.PTH3 = TRANSFER_MODE; + break; } + //} } else { switch(tag.FLG) { case GIF_FLG_PACKED: + GIF_LOG("Packed Mode"); PrepPackedRegs(); do { if (GetReg() == 0xe) { @@ -328,6 +377,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) break; case GIF_FLG_REGLIST: { + GIF_LOG("Reglist Mode"); size *= 2; do { incTag(8, 1); } @@ -340,6 +390,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) case GIF_FLG_IMAGE: case GIF_FLG_IMAGE2: { + GIF_LOG("IMAGE Mode"); int len = aMin(size, nloop); incTag(( len * 16 ), len); nloop -= len; @@ -354,17 +405,32 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) } } } + /*if(((GSTransferStatus.PTH1 & 0x2) + (GSTransferStatus.PTH2 & 0x2) + ((GSTransferStatus.PTH3 & 0x2) && !vif1Regs->mskpath3)) < 0x4 ) + Console.Warning("CHK PTH1 %x, PTH2 %x, PTH3 %x", GSTransferStatus.PTH1, GSTransferStatus.PTH2, GSTransferStatus.PTH3);*/ size = (startSize - size); - if (pathidx == GIF_PATH_3) { + if (tag.EOP && !nloop) { - Path3progress = STOPPED_MODE; + //Console.Warning("Finishing path %x", pathidx); + switch(pathidx) + { + case GIF_PATH_1: + GSTransferStatus.PTH1 = STOPPED_MODE; + break; + case GIF_PATH_2: + GSTransferStatus.PTH2 = STOPPED_MODE; + break; + case GIF_PATH_3: + GSTransferStatus.PTH3 = STOPPED_MODE; + break; + } } + if (pathidx == GIF_PATH_3) { gif->madr += size * 16; gif->qwc -= size; - } - + } + return size; }