From 26fece951069c63e4623f7e9fda929fcbee99bf5 Mon Sep 17 00:00:00 2001 From: refraction Date: Tue, 22 Jun 2010 23:10:40 +0000 Subject: [PATCH] Summary of fixes Games - Resident Evil Dead Aim flickering graphics fixed. - Flatout games should now boot everytime (instead of randomly) - Sega Superstar Tennis flashing fixed - Destruction Derby graphics fixed (NTSC confirmed, PAL unsure) - Tenchu Fatal Shadows flickering textures fixed, Issue 748 - Spyro Hero's Tail should boot again, Issue 746 General Info - General reworking of the GS paths with all paths prioritizing more correctly. - XGKICK can stall if another GS transfer is in progress - Major reworking of Path3 masking, could still be combined with normal Path3 transfers, but lets get it working first :P - Taken in to account a few conditions which could have caused VIF to lock up/crash when stalling on ends. - Unreversed GIF and SPR and VIF so its the normal way round - all DMA paths should now resume correctly after being stopped by hardware - GIF FIFO now actually transfers stuff :P - VIF CMD's simulated by the length of the interrupts at the end. Phew, i think that's everything :S git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3274 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/Dmac.h | 7 + pcsx2/FiFo.cpp | 41 +++++- pcsx2/GS.cpp | 19 ++- pcsx2/GS.h | 6 +- pcsx2/Gif.cpp | 246 ++++++++++++++++++++++------------- pcsx2/Gif.h | 22 +++- pcsx2/Hw.cpp | 29 +++-- pcsx2/HwRead.cpp | 4 +- pcsx2/HwWrite.cpp | 183 +++++++++++++++++++++++++- pcsx2/IopDma.cpp | 14 +- pcsx2/MTGS.cpp | 11 +- pcsx2/R5900.cpp | 23 ++-- pcsx2/SPR.cpp | 145 +++++++++++---------- pcsx2/Sif0.cpp | 26 ++-- pcsx2/Sif1.cpp | 28 ++-- pcsx2/VUops.cpp | 2 +- pcsx2/Vif.cpp | 33 +++-- pcsx2/Vif.h | 5 +- pcsx2/Vif0_Dma.cpp | 78 +++++++---- pcsx2/Vif1_Dma.cpp | 195 +++++++++++++++++++++------ pcsx2/Vif1_MFIFO.cpp | 93 +++++++------ pcsx2/Vif_Codes.cpp | 193 +++++++++++++++++++-------- pcsx2/Vif_Dma.h | 8 +- pcsx2/Vif_Transfer.cpp | 28 +++- pcsx2/Vif_Unpack.cpp | 5 +- pcsx2/ps2/GIFpath.cpp | 91 ++++++++----- pcsx2/x86/microVU_Lower.inl | 58 +++++++-- pcsx2/x86/newVif.h | 1 + pcsx2/x86/newVif_Dynarec.cpp | 2 +- pcsx2/x86/sVU_Lower.cpp | 63 ++++++--- 30 files changed, 1172 insertions(+), 487 deletions(-) diff --git a/pcsx2/Dmac.h b/pcsx2/Dmac.h index 6c988989b1..f3303e3d18 100644 --- a/pcsx2/Dmac.h +++ b/pcsx2/Dmac.h @@ -628,6 +628,13 @@ static __forceinline tDMA_TAG *SPRdmaGetAddr(u32 addr, bool write) { // if (addr & 0xf) { DMA_LOG("*PCSX2*: DMA address not 128bit aligned: %8.8x", addr); } + + //For some reason Getaway references SPR Memory from itself using SPR0, oh well, let it i guess... + if((addr & 0x70000000) == 0x70000000) + { + return (tDMA_TAG*)&psS[addr & 0x3ff0]; + } + // FIXME: Why??? DMA uses physical addresses addr &= 0x1ffffff0; diff --git a/pcsx2/FiFo.cpp b/pcsx2/FiFo.cpp index f42372c886..8c693e7c21 100644 --- a/pcsx2/FiFo.cpp +++ b/pcsx2/FiFo.cpp @@ -129,7 +129,18 @@ void __fastcall WriteFIFO_page_4(u32 mem, const mem128_t *value) psHu64(VIF0_FIFO + 8) = value[1]; vif0ch->qwc += 1; - bool ret = VIF0transfer((u32*)value, 4, true); + if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 FIFO start!"); + bool ret = VIF0transfer((u32*)value, 4); + + if (vif0.cmd) + { + if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING; + } + else + { + vif0Regs->stat.VPS = VPS_IDLE; + } + pxAssertDev( ret, "vif stall code not implemented" ); } @@ -148,12 +159,23 @@ void __fastcall WriteFIFO_page_5(u32 mem, const mem128_t *value) DevCon.Warning("writing to vif1 fifo when stalled"); vif1ch->qwc += 1; - bool ret = VIF1transfer((u32*)value, 4, false); + if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 FIFO start!"); + bool ret = VIF1transfer((u32*)value, 4); + + if (vif1.cmd) + { + if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING; + } + else + { + vif1Regs->stat.VPS = VPS_IDLE; + } + pxAssertDev( ret, "vif stall code not implemented" ); } // Dummy GIF-TAG Packet to Guarantee Count = 1 -__aligned16 u32 nloop0_packet[4] = {0x8000, 0, 0, 0}; +__aligned16 u32 nloop0_packet[4] = {0, 0, 0, 0}; void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value) { @@ -163,12 +185,23 @@ void __fastcall WriteFIFO_page_6(u32 mem, const mem128_t *value) psHu64(GIF_FIFO) = value[0]; psHu64(GIF_FIFO + 8) = value[1]; + nloop0_packet[0] = psHu32(GIF_FIFO); + nloop0_packet[1] = psHu32(GIF_FIFO + 4); + nloop0_packet[2] = psHu32(GIF_FIFO + 8); + nloop0_packet[3] = psHu32(GIF_FIFO + 12); Registers::Freeze(); - GetMTGS().PrepDataPacket(GIF_PATH_3, nloop0_packet, 1); + gifRegs->stat.APATH = GIF_APATH3; + GetMTGS().PrepDataPacket(GIF_PATH_3, nloop0_packet, 1, false); u64* data = (u64*)GetMTGS().GetDataPacketPtr(); data[0] = value[0]; data[1] = value[1]; GetMTGS().SendDataPacket(); + if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE) + { + GSTransferStatus.PTH3 = STOPPED_MODE; + gifRegs->stat.APATH = GIF_APATH_IDLE; + if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false; + } Registers::Thaw(); } diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 3d12b2a68c..7356a3af61 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; + GSTransferStatus = (STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE; memzero(g_RealGSMem); GSCSRr = 0x551B4000; // Set the FINISH bit to 1 for now @@ -98,17 +98,15 @@ void gsCSRwrite(u32 value) GSCSRr = 0x551B4000; // Set the FINISH bit to 1 - GS is always at a finish state as we don't have a FIFO(saqib) GSIMR = 0x7F00; //This is bits 14-8 thats all that should be 1 } - else if( value & 0x100 ) // FLUSH + if( value & 0x100 ) // FLUSH { // Our emulated GS has no FIFO, but if it did, it would flush it here... //Console.WriteLn("GS_CSR FLUSH GS fifo: %x (CSRr=%x)", value, GSCSRr); } - else - { + CSRw |= value & 0x1f; GetMTGS().SendSimplePacket( GS_RINGTYPE_WRITECSR, CSRw, 0, 0 ); GSCSRr = ((GSCSRr&~value)&0x1f)|(GSCSRr&~0x1f); - } } @@ -224,6 +222,17 @@ void __fastcall gsWrite64_page_01( u32 mem, const mem64_t* value ) switch( mem ) { + case 0x12001040: //busdir + gsWrite64_generic( mem, value ); + + //This is probably a complete hack, however writing to BUSDIR "should" start a transfer (Bleach Blade Battlers) + //Only problem is it kills killzone :( leaving it commented out for now. + //========================================================================= + //gifRegs->stat.OPH = true; + //========================================================================= + gifRegs->stat.DIR = (u32)value; + + return; case GS_CSR: gsCSRwrite((u32)value[0]); return; diff --git a/pcsx2/GS.h b/pcsx2/GS.h index 3d9544ed39..3ce386295f 100644 --- a/pcsx2/GS.h +++ b/pcsx2/GS.h @@ -157,7 +157,7 @@ enum GIF_PATH GIF_PATH_3, }; -extern int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size); +extern int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly); extern void GIFPath_Reset(); extern void GIFPath_Clear( GIF_PATH pathidx ); @@ -252,8 +252,8 @@ public: void WaitGS(); void ResetGS(); - int PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size ); - int PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size ); + int PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size, bool TestOnly ); + int PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size, bool TestOnly ); void SendDataPacket(); void SendGameCRC( u32 crc ); void WaitForOpen(); diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index 0983d8164b..879f184fbe 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -35,6 +35,11 @@ static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0; static u32 gifqwc = 0; static bool gifmfifoirq = false; +//Just some temporary bits to store Path1 transfers if another is in progress. +u8 Path1Buffer[0x1000000]; +u32 Path1WritePos = 0; +u32 Path1ReadPos = 0; + static __forceinline void clearFIFOstuff(bool full) { GSCSRr &= ~0xC000; //Clear FIFO stuff @@ -45,10 +50,51 @@ static __forceinline void clearFIFOstuff(bool full) GSCSRr |= 0x4000; //FIFO empty } +void gsPath1Interrupt() +{ + //DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos); + + + + if((gifRegs->stat.APATH == GIF_APATH_IDLE || gifRegs->stat.APATH == GIF_APATH1) && Path1WritePos > 0 && !gifRegs->stat.PSE) + { + Registers::Freeze(); + u32 size = GetMTGS().PrepDataPacket(GIF_PATH_1, Path1Buffer + (Path1ReadPos*16), (Path1WritePos - Path1ReadPos), false); + u8* pDest = GetMTGS().GetDataPacketPtr(); + //DevCon.Warning("Flush Size = %x", size); + + gifRegs->stat.APATH = GIF_APATH1; + memcpy_aligned(pDest, Path1Buffer + (Path1ReadPos * 16), size*16); + GetMTGS().SendDataPacket(); + Path1ReadPos += size; + if(Path1ReadPos == Path1WritePos) + { + Path1WritePos = Path1ReadPos = 0; + } + Registers::Thaw(); + CPU_INT(28, 16); //Should be size * BIAS (probably) but Tony Hawk doesnt like this, probably to do with vif flush stalling + } + else + { + if(Path1WritePos == 0) + { + gifRegs->stat.P1Q = false; + gifRegs->stat.APATH = GIF_APATH_IDLE; + } + else + { + if(gifRegs->stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL"); + CPU_INT(28, 16); + } + } + +} __forceinline void gsInterrupt() { GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle); + + if (!(gif->chcr.STR)) { //Console.WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", gif->chcr._u32, gif->qwc, done); @@ -56,11 +102,6 @@ __forceinline void gsInterrupt() } - if (GSTransferStatus.PTH3 == STOPPED_MODE) - { - gifRegs->stat.clear_flags(GIF_STAT_APATH3); - } - if ((gif->qwc > 0) || (!gspath3done)) { if (!dmacRegs->ctrl.DMAE) @@ -78,18 +119,16 @@ __forceinline void gsInterrupt() gspath3done = false; gscycles = 0; gif->chcr.STR = false; - vif1Regs->stat.VGW = false; - if(GSTransferStatus.PTH3 == 3) GSTransferStatus.PTH3 = STOPPED_MODE; - gifRegs->stat.clear_flags(GIF_STAT_APATH3 | GIF_STAT_FQC); - + //gifRegs->stat.OPH = false; + gifRegs->stat.clear_flags(GIF_STAT_FQC); clearFIFOstuff(false); hwDmacIrq(DMAC_GIF); - GIF_LOG("GIF DMA end"); + //DevCon.Warning("GIF DMA end"); } static u32 WRITERING_DMA(u32 *pMem, u32 qwc) { - int size = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc); + int size = GetMTGS().PrepDataPacket(GIF_PATH_3, pMem, qwc, false); u8* pgsmem = GetMTGS().GetDataPacketPtr(); memcpy_aligned(pgsmem, pMem, size<<4); @@ -106,6 +145,7 @@ static u32 WRITERING_DMA(tDMA_TAG *pMem, u32 qwc) int _GIFchain() { tDMA_TAG *pMem; + int qwc = 0; pMem = dmaGetAddr(gif->madr, false); if (pMem == NULL) @@ -120,7 +160,12 @@ int _GIFchain() return -1; } - return WRITERING_DMA(pMem, gif->qwc); + //in Intermittent Mode it enabled, IMAGE_MODE transfers are sliced. + + if(gifRegs->stat.IMT && GSTransferStatus.PTH3 == IMAGE_MODE) qwc = min((int)gif->qwc, 8); + else qwc = gif->qwc; + + return WRITERING_DMA(pMem, qwc); } static __forceinline void GIFchain() @@ -129,7 +174,7 @@ static __forceinline void GIFchain() // qwc check now done outside this function // Voodoocycles // >> 2 so Drakan and Tekken 5 don't mess up in some PATH3 transfer. Cycles to interrupt were getting huge.. - /*if (gif->qwc)*/ gscycles+= ( _GIFchain() >> 2 ); /* guessing */ + /*if (gif->qwc)*/ gscycles+= ( _GIFchain() * BIAS); /* guessing */ Registers::Thaw(); } @@ -169,6 +214,43 @@ static __forceinline tDMA_TAG* ReadTag2() return ptag; } +bool CheckPaths(int Channel) +{ + if(GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->mode.IMT) + { + if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3)) + { + if((vif1.cmd & 0x7f) != 0x51 || gifRegs->stat.P1Q == true) + { + if(gifRegs->stat.APATH == GIF_APATH3) + { + gifRegs->stat.APATH = GIF_APATH_IDLE; + } + gifRegs->stat.IP3 = true; + CPU_INT(DMAC_GIF, 16); + return false; + } + } + } + else if((GSTransferStatus.PTH3 >= IDLE_MODE)) + { + //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed). + if((gifRegs->stat.P1Q == true || gifRegs->stat.P2Q == true) || (gifRegs->stat.APATH > GIF_APATH_IDLE && gifRegs->stat.APATH < GIF_APATH3)) + { + if(gifRegs->stat.APATH == GIF_APATH3) + { + gifRegs->stat.APATH = GIF_APATH_IDLE; + } + gifRegs->stat.IP3 = true; + CPU_INT(DMAC_GIF, 16); + return false; + } + } + + gifRegs->stat.IP3 = false; + return true; +} + void GIFdma() { tDMA_TAG *ptag; @@ -177,7 +259,8 @@ void GIFdma() if (gifRegs->ctrl.PSE) // temporarily stop { - Console.WriteLn("Gif dma temp paused?"); + Console.WriteLn("Gif dma temp paused? (non MFIFO GIF)"); + CPU_INT(DMAC_GIF, 16); return; } @@ -199,24 +282,14 @@ void GIFdma() clearFIFOstuff(true); gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] - //Path2 gets priority in intermittent 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, GSTransferStatus.PTH3); - gifRegs->stat.set_flags(GIF_STAT_P3Q); - CPU_INT(DMAC_GIF, 16); - return; - } - gifRegs->stat.clear_flags(GIF_STAT_P3Q); - gifRegs->stat.APATH = GIF_APATH3; - + if (vif1Regs->mskpath3 || gifRegs->mode.M3R) { if (gif->qwc == 0) { if ((gif->chcr.MOD == CHAIN_MODE) && gif->chcr.STR) { + //DevCon.Warning("GIF Reading Tag Masked MSK = %x", vif1Regs->mskpath3); ptag = ReadTag(); gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] if (ptag == NULL) return; @@ -226,25 +299,41 @@ void GIFdma() if (checkTieBit(ptag)) GIF_LOG("PATH3 MSK dmaIrq Set"); } } + - if (GSTransferStatus.PTH3 == STOPPED_MODE) /*|| (vif1Regs->stat._u32 |= VIF1_STAT_VGW) == 0*/ + if (GSTransferStatus.PTH3 == STOPPED_MODE) { GIF_LOG("PTH3 MASK Paused by VIF"); - vif1Regs->stat.VGW = false; - if (gif->qwc == 0) CPU_INT(DMAC_GIF, 16); + + //DevCon.Warning("GIF Paused by Mask MSK = %x", vif1Regs->mskpath3); + + if(gif->qwc == 0) gsInterrupt(); + else gifRegs->stat.set_flags(GIF_STAT_P3Q); return; } + + + + //gifRegs->stat.OPH = true; gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] //Check with Path3 masking games if (gif->qwc > 0) { + gifRegs->stat.set_flags(GIF_STAT_P3Q); + if(CheckPaths(DMAC_GIF) == false) return; + gifRegs->stat.clear_flags(GIF_STAT_P3Q); GIF_LOG("PTH3 MASK Transferring"); - GIFchain(); + GIFchain(); + /*if(GSTransferStatus.PTH3 == PENDINGSTOP_MODE && gifRegs->stat.APATH == GIF_APATH_IDLE) + { + GSTransferStatus.PTH3 = STOPPED_MODE; + }*/ }//else DevCon.WriteLn("GIFdma() case 1, but qwc = 0!"); //Don't do 0 GIFchain and then return - CPU_INT(DMAC_GIF, gscycles * BIAS); + CPU_INT(DMAC_GIF, gscycles); return; } - + + //gifRegs->stat.OPH = true; // Transfer Dn_QWC from Dn_MADR to GIF if ((gif->chcr.MOD == NORMAL_MODE) || (gif->qwc > 0)) // Normal Mode { @@ -255,13 +344,18 @@ void GIFdma() } gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] //Check with Path3 masking games + //DevCon.Warning("GIF Transferring Normal/ChainQWC MSK = %x", vif1Regs->mskpath3); + + + if (gif->qwc > 0) { + gifRegs->stat.set_flags(GIF_STAT_P3Q); + if(CheckPaths(DMAC_GIF) == false) return; + gifRegs->stat.clear_flags(GIF_STAT_P3Q); GIFchain(); //Transfers the data set by the switch - CPU_INT(DMAC_GIF, gscycles * BIAS); + CPU_INT(DMAC_GIF, gscycles); return; - } else { //Else it really is a normal transfer and we want to quit, else it gets confused with chains - gspath3done = 1; - } + } else DevCon.Warning("GIF Normalmode or QWC going to invalid case? CHCR %x", gif->chcr); //else DevCon.WriteLn("GIFdma() case 2, but qwc = 0!"); //Don't do 0 GIFchain and then return, fixes Dual Hearts } @@ -270,6 +364,7 @@ void GIFdma() { ptag = ReadTag(); if (ptag == NULL) return; + //DevCon.Warning("GIF Reading Tag MSK = %x", vif1Regs->mskpath3); GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr); gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] if (dmacRegs->ctrl.STD == STD_GIF) @@ -290,65 +385,48 @@ void GIFdma() } checkTieBit(ptag); + /*if(gif->qwc == 0) + { + gsInterrupt(); + return; + }*/ } prevcycles = 0; - - if ((!gspath3done) && (gif->qwc == 0)) - { - ptag = dmaGetAddr(gif->tadr, false); //Set memory pointer to TADR - gif->unsafeTransfer(ptag); - gif->madr = ptag[1]._u32; - - gspath3done = hwDmacSrcChainWithStack(gif, ptag->ID); - - checkTieBit(ptag); - - GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr); - CPU_INT(DMAC_GIF, gscycles * BIAS); - } - else - { - CPU_INT(DMAC_GIF, gscycles * BIAS); - gscycles = 0; - } - gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // APATH=3] + CPU_INT(DMAC_GIF, gscycles); + gifRegs->stat.FQC = min((u16)0x10, gif->qwc);// FQC=31, hack ;) (for values of 31 that equal 16) [ used to be 0xE00; // OPH=1 | APATH=3] } void dmaGIF() { //We used to add wait time for the buffer to fill here, fixing some timing problems in path 3 masking //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); + //DevCon.Warning("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); - //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; gifRegs->stat.FQC |= 0x10; // hack ;) + if (gif->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(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0) + { + //DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc()); + if(((gif->chcr.TAG >> 12) & 0x7) == 0x0 || ((gif->chcr.TAG >> 12) & 0x7) == 0x7) + { + gspath3done = true; + } + } + if (dmacRegs->ctrl.MFD == MFD_GIF) // GIF MFIFO { //Console.WriteLn("GIF MFIFO"); gifMFIFOInterrupt(); return; - } - - if ((gif->qwc == 0) && (gif->chcr.MOD != NORMAL_MODE)) - { - tDMA_TAG* ptag = ReadTag2(); - GIF_LOG("gifdmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx tadr=%lx", ptag[1]._u32, ptag[0]._u32, gif->qwc, ptag->ID, gif->madr, gif->tadr); - - checkTieBit(ptag); - GIFdma(); - return; - } - - //Halflife sets a QWC amount in chain mode, no tadr set. - if (gif->qwc > 0) gspath3done = true; - if(gif->chcr.MOD == CHAIN_MODE && gif->qwc > 0) DevCon.Warning(L"GIF QWC on Chain " + gif->chcr.desc()); + } GIFdma(); } @@ -447,7 +525,12 @@ void mfifoGIFtransfer(int qwc) gifempty = false; } - GIF_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr); + if (gifRegs->ctrl.PSE) // temporarily stop + { + Console.WriteLn("Gif dma temp paused?"); + CPU_INT(11, 16); + return; + } if (gif->qwc == 0) { @@ -540,11 +623,7 @@ void gifMFIFOInterrupt() gifRegs->stat.APATH = GIF_APATH_IDLE; } - if ((spr0->chcr.STR) && (spr0->qwc == 0)) - { - spr0->chcr.STR = false; - hwDmacIrq(DMAC_FROM_SPR); - } + if(CheckPaths(11) == false) return; if (!(gif->chcr.STR)) { @@ -553,13 +632,6 @@ void gifMFIFOInterrupt() return; } - 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), GSTransferStatus.PTH3); - CPU_INT(11,mfifocycles); - return; - } - if (!(gifstate & GIF_STATE_STALL)) { if (gifqwc <= 0) diff --git a/pcsx2/Gif.h b/pcsx2/Gif.h index 8e5211dccb..8533cdc98d 100644 --- a/pcsx2/Gif.h +++ b/pcsx2/Gif.h @@ -26,17 +26,20 @@ enum gifstate_t enum GSTransferModes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet { - IMAGE_MODE = 0, - TRANSFER_MODE = 1, - STOPPED_MODE = 2 + PENDINGIMAGE_MODE = 0, + IMAGE_MODE = 1, + TRANSFER_MODE = 2, + PENDINGSTOP_MODE = 3, + IDLE_MODE = 4, + STOPPED_MODE = 5 }; 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 PTH1 : 4; // Resets Vif(0/1) when written. + u32 PTH2 : 4; // Causes a Forcebreak to Vif((0/1) when true. (Stall) + u32 PTH3 : 4; // Stops after the end of the Vifcode in progress when true. (Stall) + u32 reserved : 20; }; u32 _u32; @@ -285,4 +288,9 @@ extern void dmaGIF(); extern void mfifoGIFtransfer(int qwc); extern void gifMFIFOInterrupt(); +//Just some temporary bits to store Path1 transfers if another is in progress. +extern void gsPath1Interrupt(); +extern u8 Path1Buffer[0x1000000]; +extern u32 Path1WritePos; +extern u32 Path1ReadPos; #endif diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index d21e0d3a6e..7f9b8b3074 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -75,13 +75,15 @@ void hwReset() __forceinline void intcInterrupt() { - if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return; - if ((psHu32(INTC_STAT)) == 0) { - DevCon.Warning("*PCSX2*: intcInterrupt already cleared"); + //DevCon.Warning("*PCSX2*: intcInterrupt already cleared"); return; } - if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return; + if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) + { + //DevCon.Warning("*PCSX2*: No valid interrupt INTC_MASK: %x INTC_STAT: %x", psHu32(INTC_MASK), psHu32(INTC_STAT)); + return; + } HW_LOG("intcInterrupt %x", psHu32(INTC_STAT) & psHu32(INTC_MASK)); if(psHu32(INTC_STAT) & 0x2){ @@ -94,13 +96,18 @@ __forceinline void intcInterrupt() __forceinline void dmacInterrupt() { - if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return; - if( ((psHu16(DMAC_STAT + 2) & psHu16(DMAC_STAT)) == 0 ) && - ( psHu16(DMAC_STAT) & 0x8000) == 0 ) return; - - if (!(dmacRegs->ctrl.DMAE)) return; + ( psHu16(DMAC_STAT) & 0x8000) == 0 ) + { + //DevCon.Warning("No valid DMAC interrupt MASK %x STAT %x", psHu16(DMAC_STAT+2), psHu16(DMAC_STAT)); + return; + } + if (!(dmacRegs->ctrl.DMAE) || psHu8(DMAC_ENABLER+2) == 1) + { + //DevCon.Warning("DMAC Suspended or Disabled on interrupt"); + return; + } HW_LOG("dmacInterrupt %x", (psHu16(DMAC_STAT + 2) & psHu16(DMAC_STAT) | psHu16(DMAC_STAT) & 0x8000)); @@ -110,13 +117,13 @@ __forceinline void dmacInterrupt() void hwIntcIrq(int n) { psHu32(INTC_STAT) |= 1<= 0x3800) HW_LOG("VIF%x Register Read32 at 0x%x, value=0x%x", (masked_mem < 0x3c00) ? 0 : 1, mem, psHu32(mem) ); + else HW_LOG("GIF Register Read32 at 0x%x, value=0x%x", mem, psHu32(mem) ); + break; case 0x04: case 0x05: case 0x06: diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp index 3af691ea2d..b59ec0085b 100644 --- a/pcsx2/HwWrite.cpp +++ b/pcsx2/HwWrite.cpp @@ -75,8 +75,19 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value ) if(value == 0) { //DevCon.Warning(L"8bit %s DMA Stopped on Suspend", ChcrName(mem & ~0xf)); + if(ChannelNumber(mem & ~0xf) == 1) + { + cpuClearInt( 10 ); + QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel + } + else if(ChannelNumber(mem & ~0xf) == 2) + { + cpuClearInt( 11 ); + QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel + } + cpuClearInt( ChannelNumber(mem & ~0xf) ); - QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf)); + QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf)); //Clear any queued DMA requests for this channel; } //Here we update the CHCR STR (Busy) bit, we don't touch anything else. reg->chcr.STR = value; @@ -93,8 +104,20 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value ) //DevCon.Warning(L"8bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem & ~0xf), reg->chcr._u32, value); reg->chcr.STR = value; //We need to clear any existing DMA loops that are in progress else they will continue! - cpuClearInt( ChannelNumber(mem&~0xf) ); - QueuedDMA._u16 &= ~(1 << ChannelNumber(mem&~0xf)); //Clear any queued DMA requests for this channel + + if(ChannelNumber(mem & ~0xf) == 1) + { + cpuClearInt( 10 ); + QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel + } + else if(ChannelNumber(mem & ~0xf) == 2) + { + cpuClearInt( 11 ); + QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel + } + + cpuClearInt( ChannelNumber(mem & ~0xf) ); + QueuedDMA._u16 &= ~(1 << ChannelNumber(mem & ~0xf)); //Clear any queued DMA requests for this channel } //else DevCon.Warning(L"8bit Attempted to stop %s DMA without suspend, ignoring", ChcrName(mem & ~0xf)); return; @@ -132,6 +155,17 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value ) if(chcr.STR == 0) { //DevCon.Warning(L"16bit %s DMA Stopped on Suspend", ChcrName(mem)); + if(ChannelNumber(mem) == 1) + { + cpuClearInt( 10 ); + QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel + } + else if(ChannelNumber(mem) == 2) + { + cpuClearInt( 11 ); + QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel + } + cpuClearInt( ChannelNumber(mem) ); QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel } @@ -150,6 +184,18 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value ) //DevCon.Warning(L"16bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32); reg->chcr.STR = 0; //We need to clear any existing DMA loops that are in progress else they will continue! + + if(ChannelNumber(mem) == 1) + { + cpuClearInt( 10 ); + QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel + } + else if(ChannelNumber(mem) == 2) + { + cpuClearInt( 11 ); + QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel + } + cpuClearInt( ChannelNumber(mem) ); QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel } @@ -189,8 +235,19 @@ static void DmaExec( void (*func)(), u32 mem, u32 value ) if(chcr.STR == 0) { //DevCon.Warning(L"32bit %s DMA Stopped on Suspend", ChcrName(mem)); - QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel + if(ChannelNumber(mem) == 1) + { + cpuClearInt( 10 ); + QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel + } + else if(ChannelNumber(mem) == 2) + { + cpuClearInt( 11 ); + QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel + } + cpuClearInt( ChannelNumber(mem) ); + QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel } //Sanity Check for possible future bug fix0rs ;p //Spams on Persona 4 opening. @@ -211,6 +268,18 @@ static void DmaExec( void (*func)(), u32 mem, u32 value ) //DevCon.Warning(L"32bit Force Stopping %s (Current CHCR %x) while DMA active", ChcrName(mem), reg->chcr._u32, chcr._u32); reg->chcr.STR = 0; //We need to clear any existing DMA loops that are in progress else they will continue! + + if(ChannelNumber(mem) == 1) + { + cpuClearInt( 10 ); + QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel + } + else if(ChannelNumber(mem) == 2) + { + cpuClearInt( 11 ); + QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel + } + cpuClearInt( ChannelNumber(mem) ); QueuedDMA._u16 &= ~(1 << ChannelNumber(mem)); //Clear any queued DMA requests for this channel } @@ -282,6 +351,31 @@ void hwWrite8(u32 mem, u8 value) case RCNT3_MODE + 1: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break; case RCNT3_TARGET: rcntWtarget(3, value); break; + case GIF_CTRL: + psHu32(mem) = value & 0x8; + DevCon.Warning("GIFCTRL 8 = %x", value); + if (value & 0x1) + gsGIFReset(); + + if ( value & 8 ) + gifRegs->stat.PSE = true; + else + gifRegs->stat.PSE = false; + break; + + case GIF_MODE: + { + // need to set GIF_MODE (hamster ball) + gifRegs->mode.write(value); + + // set/clear bits 0 and 2 as per the GIF_MODE value. + const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT; + psHu32(GIF_STAT) &= ~bitmask; + psHu32(GIF_STAT) |= (u32)value & bitmask; + if(value & GIF_MODE_M3R) DevCon.Warning("8bit GIFMODE M3R write %x", value); + //if(value & GIF_MODE_IMT) DevCon.Warning("8bit GIFMODE INT write %x", value); + } + break; case SIO_TXFIFO: { // Terminate lines on CR or full buffers, and ignore \n's if the string contents @@ -394,6 +488,13 @@ void hwWrite8(u32 mem, u8 value) psHu8(mem) = value; break; + case DMAC_STAT: + case DMAC_STAT + 1: + case DMAC_STAT + 2: + case DMAC_STAT + 3: + DevCon.Warning("8bit dmac stat! %x", mem); + break; + case DMAC_ENABLEW + 2: oldvalue = psHu8(DMAC_ENABLEW + 2); psHu8(DMAC_ENABLEW + 2) = value; @@ -403,6 +504,18 @@ void hwWrite8(u32 mem, u8 value) if (!QueuedDMA.empty()) StartQueuedDMA(); } break; + case DMAC_CTRL+2: + oldvalue = psHu8(mem); + if ((oldvalue & 0x3) != (value & 0x3)) + { + DevCon.Warning("8 Stall Source Changed to %x", (value & 0x30) >> 4); + } + if ((oldvalue & 0xC) != (value & 0xC)) + { + DevCon.Warning("8 Stall Destination Changed to %x", (value & 0xC0) >> 4); + } + psHu8(mem) = value; + break; case SBUS_F200: // SIF(?) psHu8(mem) = value; @@ -474,6 +587,32 @@ __forceinline void hwWrite16(u32 mem, u16 value) case RCNT3_MODE: rcntWmode(3, value); break; case RCNT3_TARGET: rcntWtarget(3, value); break; + case GIF_CTRL: + psHu32(mem) = value & 0x8; + DevCon.Warning("GIFCTRL 16 %x", value); + if (value & 0x1) + gsGIFReset(); + + if ( value & 8 ) + gifRegs->stat.PSE = true; + else + gifRegs->stat.PSE = false; + break; + + case GIF_MODE: + { + // need to set GIF_MODE (hamster ball) + gifRegs->mode.write(value); + + // set/clear bits 0 and 2 as per the GIF_MODE value. + const u32 bitmask = GIF_MODE_M3R | GIF_MODE_IMT; + psHu32(GIF_STAT) &= ~bitmask; + psHu32(GIF_STAT) |= (u32)value & bitmask; + if(value & GIF_MODE_M3R) DevCon.Warning("16bit GIFMODE M3R write %x", value); + //if(value & GIF_MODE_IMT) DevCon.Warning("16bit GIFMODE INT write %x", value); + + } + break; case D0_CHCR: // dma0 - vif0 DMA_LOG("VIF0dma %lx", value); DmaExec16(dmaVIF0, mem, value); @@ -667,6 +806,10 @@ __forceinline void hwWrite16(u32 mem, u16 value) //DevCon.Warning(L"16bit CHCR TAG changed to %x from %x on %s DMA", value, psHu32(mem), ChcrName(mem & ~0xf)); psHu16(mem) = value; break; + case DMAC_STAT: + case DMAC_STAT + 2: + DevCon.Warning("16bit dmac stat! %x", mem); + break; case DMAC_ENABLEW + 2: oldvalue = psHu8(DMAC_ENABLEW + 2); @@ -677,7 +820,18 @@ __forceinline void hwWrite16(u32 mem, u16 value) if (!QueuedDMA.empty()) StartQueuedDMA(); } break; - + case DMAC_CTRL: + oldvalue = psHu16(mem); + if ((oldvalue & 0x30) != (value & 0x30)) + { + DevCon.Warning("Stall Source Changed to %x", (value & 0x30) >> 4); + } + if ((oldvalue & 0xC0) != (value & 0xC0)) + { + DevCon.Warning("Stall Destination Changed to %x", (value & 0xC0) >> 4); + } + psHu16(mem) = value; + break; case SIO_ISR: case SIO_ISR + 2: case 0x1000f410: @@ -786,7 +940,8 @@ void __fastcall hwWrite32_page_03( u32 mem, u32 value ) if (value & 0x1) gsGIFReset(); - else if ( value & 8 ) + + if ( value & 8 ) gifRegs->stat.PSE = true; else gifRegs->stat.PSE = false; @@ -866,6 +1021,14 @@ void __fastcall hwWrite32_page_0E( u32 mem, u32 value ) { if (!QueuedDMA.empty()) StartQueuedDMA(); } + if ((oldvalue & 0x30) != (value & 0x30)) + { + DevCon.Warning("Stall Source Changed to %x", (value & 0x30) >> 4); + } + if ((oldvalue & 0xC0) != (value & 0xC0)) + { + DevCon.Warning("Stall Destination Changed to %x", (value & 0xC0) >> 4); + } break; } @@ -1127,6 +1290,14 @@ void __fastcall hwWrite64_page_0E( u32 mem, const mem64_t* srcval ) { if (!QueuedDMA.empty()) StartQueuedDMA(); } + if ((oldvalue & 0x30) != (value & 0x30)) + { + DevCon.Warning("Stall Source Changed to %x", (value & 0x30) >> 4); + } + if ((oldvalue & 0xC0) != (value & 0xC0)) + { + DevCon.Warning("Stall Destination Changed to %x", (value & 0xC0) >> 4); + } break; } diff --git a/pcsx2/IopDma.cpp b/pcsx2/IopDma.cpp index 07710a4fb9..4ad83cd388 100644 --- a/pcsx2/IopDma.cpp +++ b/pcsx2/IopDma.cpp @@ -197,12 +197,14 @@ void psxDma9(u32 madr, u32 bcr, u32 chcr) sif0.iop.busy = true; psHu32(SBUS_F240) |= 0x2000; - if (sif0.ee.busy) - { + /*if (sif0.ee.busy) + {*/ + XMMRegisters::Freeze(); SIF0Dma(); psHu32(SBUS_F240) &= ~0x20; psHu32(SBUS_F240) &= ~0x2000; - } + XMMRegisters::Thaw(); + //} } void psxDma10(u32 madr, u32 bcr, u32 chcr) @@ -212,15 +214,15 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr) sif1.iop.busy = true; psHu32(SBUS_F240) |= 0x4000; - if (sif1.ee.busy) - { + /*if (sif1.ee.busy) + {*/ XMMRegisters::Freeze(); SIF1Dma(); psHu32(SBUS_F240) &= ~0x40; psHu32(SBUS_F240) &= ~0x100; psHu32(SBUS_F240) &= ~0x4000; XMMRegisters::Thaw(); - } + //} } /* psxDma11 & psxDma 12 are in IopSio2.cpp, along with the appropriate interrupt functions. */ diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index 94a111d5f5..d4d0aa6393 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -594,9 +594,9 @@ void SysMtgsThread::SendDataPacket() //m_PacketLocker.Release(); } -int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size ) +int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u32* srcdata, u32 size, bool TestOnly ) { - return PrepDataPacket( pathidx, (u8*)srcdata, size ); + return PrepDataPacket( pathidx, (u8*)srcdata, size, TestOnly ); } #ifdef PCSX2_GSRING_TX_STATS @@ -614,7 +614,7 @@ static u32 ringtx_inf_s[32]; // around VU memory instead of having buffer overflow... // Parameters: // size - size of the packet data, in smd128's -int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size ) +int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size, bool TestOnly ) { //m_PacketLocker.Acquire(); @@ -674,9 +674,10 @@ int SysMtgsThread::PrepDataPacket( GIF_PATH pathidx, const u8* srcdata, u32 size pxAssert( size < RingBufferSize ); pxAssert( writepos < RingBufferSize ); - m_packet_size = GIFPath_ParseTag(pathidx, srcdata, size); + m_packet_size = GIFPath_ParseTag(pathidx, srcdata, size, TestOnly); + if( TestOnly == true) return m_packet_size; size = m_packet_size + 1; // takes into account our command qword. - + if( writepos + size < RingBufferSize ) { // generic gs wait/stall. diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 35b2e689c4..1332fafd80 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -294,8 +294,9 @@ static __forceinline void _cpuTestInterrupts() /* These are 'pcsx2 interrupts', they handle asynchronous stuff that depends on the cycle timings */ - TESTINT(1, vif1Interrupt); - TESTINT(2, gsInterrupt); + TESTINT(28, gsPath1Interrupt); + TESTINT(1, vif1Interrupt); + TESTINT(2, gsInterrupt); TESTINT(5, EEsif0Interrupt); TESTINT(6, EEsif1Interrupt); @@ -351,10 +352,12 @@ static __forceinline void _cpuTestPERF() // them out. Exceptions while the exception handler is active (EIE), or exceptions of any // level other than 0 are ignored here. -static bool cpuIntsEnabled() +static bool cpuIntsEnabled(int Interrupt) { + int IntType = cpuRegs.CP0.n.Status.val & Interrupt; //Choose either INTC or DMAC, depending on what called it + return cpuRegs.CP0.n.Status.b.EIE && cpuRegs.CP0.n.Status.b.IE && - !cpuRegs.CP0.n.Status.b.EXL && (cpuRegs.CP0.n.Status.b.ERL == 0); + !cpuRegs.CP0.n.Status.b.EXL && (cpuRegs.CP0.n.Status.b.ERL == 0) && Interrupt; } // if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates @@ -480,18 +483,15 @@ __forceinline void _cpuBranchTest_Shared() // exceptions. //if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) - if( cpuIntsEnabled() ) - { - TESTINT(30, intcInterrupt); - TESTINT(31, dmacInterrupt); - } + if( cpuIntsEnabled(0x400) ) TESTINT(30, intcInterrupt); + if( cpuIntsEnabled(0x800) ) TESTINT(31, dmacInterrupt); } __releaseinline void cpuTestINTCInts() { if( cpuRegs.interrupt & (1 << 30) ) return; //if( (cpuRegs.CP0.n.Status.val & 0x10407) != 0x10401 ) return; - if( !cpuIntsEnabled() ) return; + if( !cpuIntsEnabled(0x400) ) return; if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) return; cpuRegs.interrupt|= 1 << 30; @@ -512,7 +512,8 @@ __releaseinline void cpuTestINTCInts() __forceinline void cpuTestDMACInts() { if ( cpuRegs.interrupt & (1 << 31) ) return; - if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return; + + if( !cpuIntsEnabled(0x800) ) return; if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) && ( (psHu16(0xe010) & 0x8000) == 0) ) return; diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index 0859b7dd09..8c20cd36ff 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -81,12 +81,12 @@ int _SPR0chain() spr0->sadr += spr0->qwc << 4; - return (spr0->qwc) * BIAS; // bus is 1/2 the ee speed + return (spr0->qwc); // bus is 1/2 the ee speed } __forceinline void SPR0chain() { - _SPR0chain(); + CPU_INT(DMAC_FROM_SPR, _SPR0chain() / BIAS); spr0->qwc = 0; } @@ -102,6 +102,8 @@ void _SPR0interleave() SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx", spr0->qwc, tqwc, sqwc, spr0->madr, spr0->sadr); + CPU_INT(DMAC_FROM_SPR, qwc / BIAS); + while (qwc > 0) { spr0->qwc = std::min(tqwc, qwc); @@ -150,12 +152,11 @@ static __forceinline void _dmaSPR0() case CHAIN_MODE: { tDMA_TAG *ptag; - bool done = FALSE; + bool done = false; if (spr0->qwc > 0) { SPR0chain(); - spr0finished = true; return; } // Destination Chain Mode @@ -198,13 +199,6 @@ static __forceinline void _dmaSPR0() } spr0finished = done; - - if (!done) - { - ptag = (tDMA_TAG*)&psSu32(spr0->sadr); //Set memory pointer to SADR - CPU_INT(DMAC_FROM_SPR, /*ptag[0].QWC / BIAS*/ 4 ); // the lower 16bits of the tag / BIAS); - return; - } SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", ptag[1]._u32, ptag[0]._u32, spr0->qwc, ptag->ID, spr0->madr); break; @@ -220,37 +214,39 @@ static __forceinline void _dmaSPR0() void SPRFROMinterrupt() { - _dmaSPR0(); - - if(mfifotransferred != 0) + + if (!spr0finished || spr0->qwc > 0) { - switch (dmacRegs->ctrl.MFD) + _dmaSPR0(); + + if(mfifotransferred != 0) { - case MFD_VIF1: // Most common case. + switch (dmacRegs->ctrl.MFD) { - if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area"); - spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); - //Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr); - mfifoVIF1transfer(mfifotransferred); - mfifotransferred = 0; - if (vif1ch->chcr.STR) return; - break; + case MFD_VIF1: // Most common case. + { + if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("VIF MFIFO Write outside MFIFO area"); + spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); + //Console.WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", vif1ch->chcr._u32, vif1ch->madr, vif1ch->tadr); + mfifoVIF1transfer(mfifotransferred); + mfifotransferred = 0; + break; + } + case MFD_GIF: + { + if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area"); + spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); + //Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr); + mfifoGIFtransfer(mfifotransferred); + mfifotransferred = 0; + break; + } + default: + break; } - case MFD_GIF: - { - if ((spr0->madr & ~dmacRegs->rbsr.RMSK) != dmacRegs->rbor.ADDR) Console.WriteLn("GIF MFIFO Write outside MFIFO area"); - spr0->madr = dmacRegs->rbor.ADDR + (spr0->madr & dmacRegs->rbsr.RMSK); - //Console.WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr._u32, gif->madr, gif->tadr); - mfifoGIFtransfer(mfifotransferred); - mfifotransferred = 0; - if (gif->chcr.STR) return; - break; - } - default: - break; } + return; } - if (!spr0finished) return; spr0->chcr.STR = false; @@ -262,18 +258,23 @@ void dmaSPR0() // fromSPR SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx", spr0->chcr._u32, spr0->madr, spr0->qwc, spr0->sadr); - if ((spr0->chcr.MOD == CHAIN_MODE) && spr0->qwc == 0) + + spr0finished = false; //Init + + if(spr0->chcr.MOD == CHAIN_MODE && spr0->qwc > 0) { - tDMA_TAG *ptag; - ptag = (tDMA_TAG*)&psSu32(spr0->sadr); //Set memory pointer to SADR - CPU_INT(DMAC_FROM_SPR, /*ptag[0].QWC / BIAS*/ 4 ); - return; + //DevCon.Warning(L"SPR0 QWC on Chain " + spr0->chcr.desc()); + if(((spr0->chcr.TAG >> 12) & 0x7) == 0x7) + { + spr0finished = true; + } + else + { + spr0finished = false; + } } - if(spr0->chcr.MOD == CHAIN_MODE && spr0->qwc > 0) DevCon.Warning(L"SPR0 QWC on Chain " + spr0->chcr.desc()); - // COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values - // It merely assumes that the last one has finished then starts another one (broke with the DMA fix) - // This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction) - CPU_INT(DMAC_FROM_SPR, /*spr0->qwc / BIAS*/ 4 ); + + SPRFROMinterrupt(); } __forceinline static void SPR1transfer(u32 *data, int size) @@ -295,12 +296,12 @@ int _SPR1chain() SPR1transfer((u32*)pMem, spr1->qwc << 2); spr1->madr += spr1->qwc << 4; - return (spr1->qwc) * BIAS; + return (spr1->qwc); } __forceinline void SPR1chain() { - _SPR1chain(); + CPU_INT(DMAC_TO_SPR, _SPR1chain() / BIAS); spr1->qwc = 0; } @@ -314,7 +315,7 @@ void _SPR1interleave() if (tqwc == 0) tqwc = qwc; SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx", spr1->qwc, tqwc, sqwc, spr1->madr, spr1->sadr); - + CPU_INT(DMAC_TO_SPR, qwc / BIAS); while (qwc > 0) { spr1->qwc = std::min(tqwc, qwc); @@ -348,9 +349,9 @@ void _dmaSPR1() // toSPR work function if (spr1->qwc > 0) { + SPR_LOG("spr1 Normal or in Progress size=%d, addr=%lx taddr=%lx saddr=%lx", spr1->qwc, spr1->madr, spr1->tadr, spr1->sadr); // Transfer Dn_QWC from Dn_MADR to SPR1 SPR1chain(); - spr1finished = true; return; } // Chain Mode @@ -372,8 +373,8 @@ void _dmaSPR1() // toSPR work function SPR1transfer((u32*)ptag, 4); //Transfer Tag } - SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx", - ptag[1]._u32, ptag[0]._u32, spr1->qwc, ptag->ID, spr1->madr); + SPR_LOG("spr1 dmaChain %8.8x_%8.8x size=%d, id=%d, addr=%lx taddr=%lx saddr=%lx", + ptag[1]._u32, ptag[0]._u32, spr1->qwc, ptag->ID, spr1->madr, spr1->tadr, spr1->sadr); done = (hwDmacSrcChain(spr1, ptag->ID)); SPR1chain(); //Transfers the data set by the switch @@ -387,11 +388,6 @@ void _dmaSPR1() // toSPR work function } spr1finished = done; - if (!done) - { - ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR - CPU_INT(DMAC_TO_SPR, /*(ptag[0].QWC / BIAS)*/ 4 );// the lower 16 bits of the tag / BIAS); - } break; } //case INTERLEAVE_MODE: @@ -409,26 +405,35 @@ void dmaSPR1() // toSPR " tadr = 0x%x, sadr = 0x%x", spr1->chcr._u32, spr1->madr, spr1->qwc, spr1->tadr, spr1->sadr); - - if ((spr1->chcr.MOD == CHAIN_MODE) && (spr1->qwc == 0)) + + spr1finished = false; //Init + + if(spr1->chcr.MOD == CHAIN_MODE && spr1->qwc > 0) { - tDMA_TAG *ptag; - ptag = SPRdmaGetAddr(spr1->tadr, false); //Set memory pointer to TADR - CPU_INT(DMAC_TO_SPR, /*ptag[0].QWC / BIAS*/ 4 ); - return; + //DevCon.Warning(L"SPR1 QWC on Chain " + spr1->chcr.desc()); + if(((spr1->chcr.TAG >> 12) & 0x7) == 0x7 || ((spr1->chcr.TAG >> 12) & 0x7) == 0x0) + { + spr1finished = true; + } + else + { + spr1finished = false; + } } - if(spr1->chcr.MOD == CHAIN_MODE && spr1->qwc > 0) DevCon.Warning(L"SPR1 QWC on Chain " + spr1->chcr.desc()); - // COMPLETE HACK!!! For now at least.. FFX Videos dont rely on interrupts or reading DMA values - // It merely assumes that the last one has finished then starts another one (broke with the DMA fix) - // This "shouldn't" cause any problems as SPR is generally faster than the other DMAS anyway. (Refraction) - CPU_INT(DMAC_TO_SPR, /*spr1->qwc / BIAS*/ 4 ); + + SPRTOinterrupt(); } void SPRTOinterrupt() { - _dmaSPR1(); - if (!spr1finished) return; + SPR_LOG("SPR1 Interrupt"); + if (!spr1finished || spr1->qwc > 0) + { + _dmaSPR1(); + return; + } + SPR_LOG("SPR1 End"); spr1->chcr.STR = false; hwDmacIrq(DMAC_TO_SPR); } diff --git a/pcsx2/Sif0.cpp b/pcsx2/Sif0.cpp index 2784ccb163..d71e5eca02 100644 --- a/pcsx2/Sif0.cpp +++ b/pcsx2/Sif0.cpp @@ -73,7 +73,7 @@ static __forceinline bool WriteIOPtoFifo() hw_dma(9).madr += writeSize << 2; // iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords). - sif0.iop.cycles += (writeSize >> 2) * BIAS; // fixme : should be >> 4 + sif0.iop.cycles += (writeSize >> 2)/* * BIAS*/; // fixme : should be >> 4 sif0.iop.counter -= writeSize; return true; @@ -298,15 +298,21 @@ __forceinline void SIF0Dma() if (sif0.iop.busy) { - if(sif0.fifo.free() > 0) BusyCheck++; - HandleIOPTransfer(); + if(sif0.fifo.free() > 0 || (sif0.iop.end == true && sif0.iop.counter == 0)) + { + BusyCheck++; + HandleIOPTransfer(); + } } if (sif0.ee.busy) { - if(sif0.fifo.size >= 4) BusyCheck++; - HandleEETransfer(); + if(sif0.fifo.size >= 4 || (sif0.ee.end == true && sif0dma->qwc == 0)) + { + BusyCheck++; + HandleEETransfer(); + } } - } while (!done && BusyCheck > 0); // Substituting (sif0.ee.busy || sif0.iop.busy) breaks things. + } while (/*!done && */BusyCheck > 0); // Substituting (sif0.ee.busy || sif0.iop.busy) breaks things. Sif0End(); } @@ -332,17 +338,17 @@ __forceinline void dmaSIF0() SIF_LOG("warning, sif0.fifoReadPos != sif0.fifoWritePos"); } - if(sif0dma->chcr.MOD == CHAIN_MODE && sif0dma->qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma->chcr.desc()); + //if(sif0dma->chcr.MOD == CHAIN_MODE && sif0dma->qwc > 0) DevCon.Warning(L"SIF0 QWC on Chain CHCR " + sif0dma->chcr.desc()); psHu32(SBUS_F240) |= 0x2000; sif0.ee.busy = true; - if (sif0.iop.busy) - { + /*if (sif0.iop.busy) + {*/ XMMRegisters::Freeze(); hwIntcIrq(INTC_SBUS); SIF0Dma(); psHu32(SBUS_F240) &= ~0x20; psHu32(SBUS_F240) &= ~0x2000; XMMRegisters::Thaw(); - } + //} } diff --git a/pcsx2/Sif1.cpp b/pcsx2/Sif1.cpp index f833cd2c2d..4edf16ffef 100644 --- a/pcsx2/Sif1.cpp +++ b/pcsx2/Sif1.cpp @@ -176,7 +176,7 @@ static __forceinline void EndEE() } - CPU_INT(DMAC_SIF1, min((int)(sif1.ee.cycles*BIAS), 384)); + CPU_INT(DMAC_SIF1, /*min((int)(*/sif1.ee.cycles*BIAS/*), 384)*/); } // Stop processing IOP, and signal an interrupt. @@ -197,7 +197,7 @@ static __forceinline void EndIOP() sif1.iop.cycles = 1; } // iop is 1/8th the clock rate of the EE and psxcycles is in words (not quadwords) - PSX_INT(IopEvt_SIF1, min((sif1.iop.cycles * 26), 1024)); + PSX_INT(IopEvt_SIF1, /*min((*/sif1.iop.cycles/* * 26*//*), 1024)*/); } // Handle the EE transfer. @@ -292,17 +292,23 @@ __forceinline void SIF1Dma() if (sif1.ee.busy) { - if(sif1.fifo.free() > 0) BusyCheck++; - HandleEETransfer(); + if(sif1.fifo.free() > 0 || (sif1.ee.end == true && sif1dma->qwc == 0)) + { + BusyCheck++; + HandleEETransfer(); + } } if (sif1.iop.busy) { - if(sif1.fifo.size >= 4) BusyCheck++; - HandleIOPTransfer(); + if(sif1.fifo.size >= 4 || (sif1.iop.end == true && sif1.iop.counter == 0)) + { + BusyCheck++; + HandleIOPTransfer(); + } } - } while (!done && BusyCheck > 0); + } while (/*!done &&*/ BusyCheck > 0); Sif1End(); } @@ -330,18 +336,18 @@ __forceinline void dmaSIF1() SIF_LOG("warning, sif1.fifoReadPos != sif1.fifoWritePos"); } - if(sif1dma->chcr.MOD == CHAIN_MODE && sif1dma->qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma->chcr.desc()); + //if(sif1dma->chcr.MOD == CHAIN_MODE && sif1dma->qwc > 0) DevCon.Warning(L"SIF1 QWC on Chain CHCR " + sif1dma->chcr.desc()); psHu32(SBUS_F240) |= 0x4000; sif1.ee.busy = true; - if (sif1.iop.busy) - { + /*if (sif1.iop.busy) + {*/ XMMRegisters::Freeze(); SIF1Dma(); psHu32(SBUS_F240) &= ~0x40; psHu32(SBUS_F240) &= ~0x100; psHu32(SBUS_F240) &= ~0x4000; XMMRegisters::Thaw(); - } + //} } diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index 6baaacebad..b0e17132b9 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -2057,7 +2057,7 @@ void _vuXGKICK(VURegs * VU) u8* data = ((u8*)VU->Mem + ((VU->VI[_Is_].US[0]*16) & 0x3fff)); u32 size; - size = GetMTGS().PrepDataPacket( GIF_PATH_1, data, (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4); + size = GetMTGS().PrepDataPacket( GIF_PATH_1, data, (0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff)) >> 4, false); u8* pmem = GetMTGS().GetDataPacketPtr(); if((size << 4) > (u32)(0x4000-((VU->VI[_Is_].US[0]*16) & 0x3fff))) diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index 3fe205c904..4ac29e764d 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -23,7 +23,7 @@ vifStruct vif0; vifStruct vif1; -tGSTransferStatus GSTransferStatus((STOPPED_MODE<<4) | (STOPPED_MODE<<2) | STOPPED_MODE); +tGSTransferStatus GSTransferStatus((STOPPED_MODE<<8) | (STOPPED_MODE<<4) | STOPPED_MODE); void vif0Reset() { @@ -140,8 +140,8 @@ _f void vif0FBRST(u32 value) { g_vifCycles = 0; // loop necessary for spiderman - vif0ch->chcr.STR = true; - CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout + //vif0ch->chcr.STR = true; + if(vif0ch->chcr.STR == true) CPU_INT(DMAC_VIF0, 0); // Gets the timing right - Flatout } } } @@ -153,21 +153,28 @@ _f void vif1FBRST(u32 value) { if (FBRST(value).RST) // Reset Vif. { memzero(vif1); - cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's - vif1ch->qwc = 0; //? + //cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's + vif1ch->qwc -= min((int)vif1ch->qwc, 16); //? psHu64(VIF1_FIFO) = 0; psHu64(VIF1_FIFO + 8) = 0; - vif1.done = false; + //vif1.done = false; - if(vif1Regs->mskpath3) + + //DevCon.Warning("VIF FBRST Reset MSK = %x", vif1Regs->mskpath3); + if(vif1Regs->mskpath3 == 1 && GSTransferStatus.PTH3 == STOPPED_MODE && gif->chcr.STR == true) { - vif1Regs->mskpath3 = 0; - gifRegs->stat.IMT = false; - if (gif->chcr.STR) CPU_INT(DMAC_GIF, 4); + //DevCon.Warning("VIF Path3 Resume on FBRST MSK = %x", vif1Regs->mskpath3); + gsInterrupt(); + vif1Regs->mskpath3 = false; + gifRegs->stat.M3P = 0; } + vif1Regs->mskpath3 = false; + gifRegs->stat.M3P = 0; vif1Regs->err.reset(); vif1.inprogress = 0; + vif1.cmd = 0; + vif1.vifstalled = false; vif1Regs->stat.FQC = 0; vif1Regs->stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS); } @@ -217,18 +224,18 @@ _f void vif1FBRST(u32 value) { { case MFD_VIF1: //Console.WriteLn("MFIFO Stall"); - CPU_INT(10, 0); + if(vif1ch->chcr.STR == true) CPU_INT(10, 0); break; case NO_MFD: case MFD_RESERVED: case MFD_GIF: // Wonder if this should be with VIF? // Gets the timing right - Flatout - CPU_INT(DMAC_VIF1, 0); + if(vif1ch->chcr.STR == true) CPU_INT(DMAC_VIF1, 0); break; } - vif1ch->chcr.STR = true; + //vif1ch->chcr.STR = true; } } } diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h index 2b33f086b4..89236340d9 100644 --- a/pcsx2/Vif.h +++ b/pcsx2/Vif.h @@ -227,6 +227,7 @@ extern VIFregisters *vifRegs; extern void dmaVIF0(); extern void dmaVIF1(); extern void mfifoVIF1transfer(int qwc); -extern bool VIF0transfer(u32 *data, int size, bool istag); -extern bool VIF1transfer(u32 *data, int size, bool istag); +extern bool VIF0transfer(u32 *data, int size); +extern bool VIF1transfer(u32 *data, int size); extern void vifMFIFOInterrupt(); +extern bool CheckPath2GIF(int channel); diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index 3b0006dd5f..37633c202d 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -23,10 +23,31 @@ // because its vif stalling not the EE core... __forceinline void vif0FLUSH() { + if(g_packetsizeonvu > vif0.vifpacketsize && g_vu0Cycles > 0) + { + //DevCon.Warning("Adding on same packet"); + if( ((g_packetsizeonvu - vif0.vifpacketsize) >> 1) > g_vu0Cycles) + g_vu0Cycles -= (g_packetsizeonvu - vif0.vifpacketsize) >> 1; + else g_vu0Cycles = 0; + } + if(g_vu0Cycles > 0) + { + //DevCon.Warning("Adding %x cycles to VIF0", g_vu1Cycles * BIAS); + g_vifCycles += g_vu0Cycles; + g_vu0Cycles = 0; + } + g_vu0Cycles = 0; if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return; + if(VU0.flags & VUFLAG_MFLAGSET) + { + vif0.vifstalled = true; + return; + } int _cycles = VU0.cycle; vu0Finish(); + //DevCon.Warning("VIF0 adding %x cycles", (VU0.cycle - _cycles) * BIAS); g_vifCycles += (VU0.cycle - _cycles) * BIAS; + return; } bool _VIF0chain() @@ -52,9 +73,9 @@ bool _VIF0chain() vif0ch->qwc, vif0ch->madr, vif0ch->tadr); if (vif0.vifstalled) - return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset, false); + return VIF0transfer(pMem + vif0.irqoffset, vif0ch->qwc * 4 - vif0.irqoffset); else - return VIF0transfer(pMem, vif0ch->qwc * 4, false); + return VIF0transfer(pMem, vif0ch->qwc * 4); } __forceinline void vif0SetupTransfer() @@ -89,9 +110,9 @@ __forceinline void vif0SetupTransfer() bool ret; if (vif0.vifstalled) - ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, true); //Transfer Tag on stall + ret = VIF0transfer((u32*)ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset); //Transfer Tag on stall else - ret = VIF0transfer((u32*)ptag + 2, 2, true); //Transfer Tag + ret = VIF0transfer((u32*)ptag + 2, 2); //Transfer Tag if ((ret == false) && vif0.irqoffset < 2) { @@ -124,6 +145,15 @@ __forceinline void vif0Interrupt() if (!(vif0ch->chcr.STR)) Console.WriteLn("vif0 running when CHCR == %x", vif0ch->chcr._u32); + if (vif0.cmd) + { + if(vif0.done == true && vif0ch->qwc == 0) vif0Regs->stat.VPS = VPS_WAITING; + } + else + { + vif0Regs->stat.VPS = VPS_IDLE; + } + if (vif0.irq && vif0.tag.size == 0) { vif0Regs->stat.INT = true; @@ -134,25 +164,15 @@ __forceinline void vif0Interrupt() vif0Regs->stat.FQC = 0; // One game doesn't like vif stalling at end, can't remember what. Spiderman isn't keen on it tho - vif0ch->chcr.STR = false; - return; - } - else if ((vif0ch->qwc > 0) || (vif0.irqoffset > 0)) - { - if (vif0.stallontag) - vif0SetupTransfer(); - else - _VIF0chain();//CPU_INT(DMAC_STALL_SIS, vif0ch->qwc * BIAS); + //vif0ch->chcr.STR = false; + if(vif0ch->qwc > 0 || !vif0.done) return; } } if (vif0.inprogress & 0x1) { _VIF0chain(); - // 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); + CPU_INT(DMAC_VIF0, g_vifCycles); return; } @@ -182,7 +202,6 @@ __forceinline void vif0Interrupt() if (vif0.cmd != 0) Console.WriteLn("vif0.cmd still set %x tag size %x", vif0.cmd, vif0.tag.size); #endif - vif0Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands; vif0ch->chcr.STR = false; g_vifCycles = 0; hwDmacIrq(DMAC_VIF0); @@ -197,24 +216,35 @@ void dmaVIF0() vif0ch->tadr, vif0ch->asr0, vif0ch->asr1); g_vifCycles = 0; + g_vu0Cycles = 0; + if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start!"); + vif0.irqoffset = 0; + vif0.vifstalled = false; vif0.inprogress = 0; + vif0.done = false; if ((vif0ch->chcr.MOD == NORMAL_MODE) || vif0ch->qwc > 0) // Normal Mode { vif0.dmamode = VIF_NORMAL_TO_MEM_MODE; - if(vif0ch->chcr.MOD == CHAIN_MODE && vif0ch->qwc > 0) DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch->chcr.desc()); + + if(vif0ch->chcr.MOD == CHAIN_MODE && vif0ch->qwc > 0) + { + vif0.dmamode = VIF_CHAIN_MODE; + //DevCon.Warning(L"VIF0 QWC on Chain CHCR " + vif0ch->chcr.desc()); + vif0.inprogress |= 0x1; + if(((vif0ch->chcr.TAG >> 12) & 0x7) == 0x0 || ((vif0ch->chcr.TAG >> 12) & 0x7) == 0x7) + { + vif0.done = true; + } + } } else { vif0.dmamode = VIF_CHAIN_MODE; } - if (vif0.dmamode != VIF_NORMAL_FROM_MEM_MODE) - vif0Regs->stat.FQC = 0x8; - else - vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc); + vif0Regs->stat.FQC = min((u16)0x8, vif0ch->qwc); // Chain Mode - vif0.done = false; vif0Interrupt(); } diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index a7dec8c378..04d90c8d9f 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -21,12 +21,38 @@ #include "VUmicro.h" #include "newVif.h" + __forceinline void vif1FLUSH() { - if (!(VU0.VI[REG_VPU_STAT].UL & 0x100)) return; - int _cycles = VU1.cycle; - vu1Finish(); - g_vifCycles += (VU1.cycle - _cycles) * BIAS; + if(g_packetsizeonvu > vif1.vifpacketsize && g_vu1Cycles > 0) + { + //DevCon.Warning("Adding on same packet"); + if( ((g_packetsizeonvu - vif1.vifpacketsize) >> 1) > g_vu1Cycles) + g_vu1Cycles -= (g_packetsizeonvu - vif1.vifpacketsize) >> 1; + else g_vu1Cycles = 0; + } + if(g_vu1Cycles > 0) + { + //DevCon.Warning("Adding %x cycles to VIF1", g_vu1Cycles * BIAS); + g_vifCycles += g_vu1Cycles; + g_vu1Cycles = 0; + + } + g_vu1Cycles = 0;//else DevCon.Warning("VIF1 Different Packet, how can i work this out :/"); + if (VU0.VI[REG_VPU_STAT].UL & 0x100) + { + int _cycles = VU1.cycle; + vu1Finish(); + //DevCon.Warning("VIF1 adding %x cycles", (VU1.cycle - _cycles) * BIAS); + g_vifCycles += (VU1.cycle - _cycles) * BIAS; + } + if(gifRegs->stat.P1Q == true && (vif1.cmd & 0x7f) != 0x14 && (vif1.cmd & 0x7f) != 0x17) + { + vif1.vifstalled = true; + vif1Regs->stat.VGW = true; + vif1.GifWaitState = 2; + } + } void vif1TransferToMemory() @@ -128,6 +154,7 @@ bool _VIF1chain() if (vif1ch->qwc == 0) { vif1.inprogress = 0; + vif1.irqoffset = 0; return true; } @@ -152,9 +179,9 @@ bool _VIF1chain() vif1ch->qwc, vif1ch->madr, vif1ch->tadr); if (vif1.vifstalled) - return VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, false); + return VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset); else - return VIF1transfer(pMem, vif1ch->qwc * 4, false); + return VIF1transfer(pMem, vif1ch->qwc * 4); } __forceinline void vif1SetupTransfer() @@ -201,15 +228,16 @@ __forceinline void vif1SetupTransfer() bool ret; if (vif1.vifstalled) - ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on stall + ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on stall else - ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag - + ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag + if ((ret == false) && 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 - } + return; //IRQ set by VIFTransfer + + } //else vif1.vifstalled = false; } vif1.irqoffset = 0; @@ -228,12 +256,92 @@ __forceinline void vif1SetupTransfer() } } +bool CheckPath2GIF(int channel) +{ + if ((vif1Regs->stat.VGW)) + { + if( vif1.GifWaitState == 0 ) //DIRECT/HL Check + { + if(GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q == true) + { + if(gifRegs->stat.IMT && GSTransferStatus.PTH3 <= IMAGE_MODE && (vif1.cmd & 0x7f) == 0x50 && gifRegs->stat.P1Q == false) + { + vif1Regs->stat.VGW = false; + } + else + { + //DevCon.Warning("VIF1-0 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); + CPU_INT(channel, 8); + return false; + } + } + else + { + vif1Regs->stat.VGW = false; + } + } + else if( vif1.GifWaitState == 1 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish + { + if(gifRegs->stat.P1Q == true) + { + //DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); + CPU_INT(channel, 8); + return false; + } + + if (GSTransferStatus.PTH3 < PENDINGSTOP_MODE) + { + //DevCon.Warning("VIF1-11 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); + //DevCon.Warning("PTH3 %x P1Q %x P3Q %x IP3 %x", GSTransferStatus.PTH3, gifRegs->stat.P1Q, gifRegs->stat.P3Q, gifRegs->stat.IP3 ); + CPU_INT(channel, 8); + return false; + } + else + { + vif1Regs->stat.VGW = false; + } + } + else if( vif1.GifWaitState == 3 ) // Else we're flushing path3 :), but of course waiting for the microprogram to finish + { + if (gifRegs->ctrl.PSE) + { + //DevCon.Warning("VIF1-1 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); + CPU_INT(channel, 8); + return false; + } + else + { + vif1Regs->stat.VGW = false; + } + } + else //Normal Flush + { + if(gifRegs->stat.P1Q == true) + { + //DevCon.Warning("VIF1-2 stall P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs->stat.P1Q, gifRegs->stat.P2Q, gifRegs->stat.APATH, GSTransferStatus.PTH3, vif1.cmd); + CPU_INT(channel, 8); + return false; + } + else + { + vif1Regs->stat.VGW = false; + } + } + } + return true; +} __forceinline void vif1Interrupt() { VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle); g_vifCycles = 0; + if (schedulepath3msk & 0x10) + { + Vif1MskPath3(); + CPU_INT(DMAC_VIF1, 8); + return; + } //Some games (Fahrenheit being one) start vif first, let it loop through blankness while it sets MFIFO mode, so we need to check it here. if (dmacRegs->ctrl.MFD == MFD_VIF1) // VIF MFIFO { @@ -245,31 +353,31 @@ __forceinline void vif1Interrupt() return; } + if(vif1ch->chcr.DIR && CheckPath2GIF(DMAC_VIF1) == false) return; //We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing) 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) + + if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE) { - gifRegs->stat.APATH = GIF_APATH_IDLE; + GSTransferStatus.PTH2 = STOPPED_MODE; + /*gifRegs->stat.APATH = GIF_APATH_IDLE; + if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;*/ } - if (schedulepath3msk & 0x10) Vif1MskPath3(); - - if ((vif1Regs->stat.VGW)) - { - if (GSTransferStatus.PTH3 < STOPPED_MODE || GSTransferStatus.PTH1 != STOPPED_MODE) - { - CPU_INT(DMAC_VIF1, 4); - return; - } - else - { - vif1Regs->stat.VGW = false; - } - } + if (!(vif1ch->chcr.STR)) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch->chcr._u32); + if (vif1.cmd) + { + if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING; + } + else + { + vif1Regs->stat.VPS = VPS_IDLE; + } + if (vif1.irq && vif1.tag.size == 0) { vif1Regs->stat.INT = true; @@ -279,16 +387,9 @@ __forceinline void vif1Interrupt() { //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; - return; - } - else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0)) - { - if (vif1.stallontag) - vif1SetupTransfer(); - else - _VIF1chain();//CPU_INT(DMAC_STALL_SIS, vif1ch->qwc * BIAS); + //NFSHPS stalls when the whole packet has gone across (it stalls int he last 32bit cmd) + //In this case VIF will end + if(vif1ch->qwc > 0 || !vif1.done) return; } } @@ -330,13 +431,15 @@ __forceinline void vif1Interrupt() if (vif1.cmd != 0) Console.WriteLn("vif1.cmd still set %x tag size %x", vif1.cmd, vif1.tag.size); #endif - vif1Regs->stat.VPS = VPS_IDLE; //Vif goes idle as the stall happened between commands; + if((vif1ch->chcr.DIR == VIF_NORMAL_TO_MEM_MODE) && vif1.GSLastDownloadSize <= 16) { //Reverse fifo has finished and nothing is left, so lets clear the outputting flag gifRegs->stat.OPH = false; } vif1ch->chcr.STR = false; + vif1.vifstalled = false; g_vifCycles = 0; + g_vu1Cycles = 0; VIF_LOG("VIF1 End"); hwDmacIrq(DMAC_VIF1); @@ -350,7 +453,12 @@ void dmaVIF1() vif1ch->tadr, vif1ch->asr0, vif1ch->asr1); vif1.done = false; + + if(vif1.irqoffset != 0 && vif1.vifstalled == true) DevCon.Warning("Offset on VIF1 start!"); + vif1.irqoffset = 0; + vif1.vifstalled = false; g_vifCycles = 0; + g_vu1Cycles = 0; vif1.inprogress = 0; #ifdef PCSX2_DEVBUILD @@ -371,7 +479,16 @@ void dmaVIF1() else vif1.dmamode = VIF_NORMAL_TO_MEM_MODE; - if(vif1ch->chcr.MOD == CHAIN_MODE && vif1ch->qwc > 0) DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch->chcr.desc()); + if(vif1ch->chcr.MOD == CHAIN_MODE && vif1ch->qwc > 0) + { + vif1.dmamode = VIF_CHAIN_MODE; + //DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch->chcr.desc()); + vif1.inprogress |= 0x1; + if(((vif1ch->chcr.TAG >> 12) & 0x7) == 0x0 || ((vif1ch->chcr.TAG >> 12) & 0x7) == 0x7) + { + vif1.done = true; + } + } } else { diff --git a/pcsx2/Vif1_MFIFO.cpp b/pcsx2/Vif1_MFIFO.cpp index 12bb22318f..3bd46552e1 100644 --- a/pcsx2/Vif1_MFIFO.cpp +++ b/pcsx2/Vif1_MFIFO.cpp @@ -22,11 +22,19 @@ VIFregisters *vifRegs; vifStruct *vif; u16 vifqwc = 0; -int g_vifCycles = 0; +u32 g_vifCycles = 0; +u32 g_vu0Cycles = 0; +u32 g_vu1Cycles = 0; +u32 g_packetsizeonvu = 0; __aligned16 VifMaskTypes g_vifmask; -extern int g_vifCycles; +extern u32 g_vifCycles; + +static u32 qwctag(u32 mask) +{ + return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK)); +} static __forceinline bool mfifoVIF1rbTransfer() { @@ -48,10 +56,12 @@ static __forceinline bool mfifoVIF1rbTransfer() if (src == NULL) return false; if (vif1.vifstalled) - ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset, false); + ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset); else - ret = VIF1transfer(src, s1, false); + ret = VIF1transfer(src, s1); + vif1ch->madr = qwctag(vif1ch->madr); + if (ret) { /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ @@ -59,8 +69,10 @@ static __forceinline bool mfifoVIF1rbTransfer() src = (u32*)PSM(maddr); if (src == NULL) return false; - VIF1transfer(src, ((mfifoqwc << 2) - s1), false); + VIF1transfer(src, ((mfifoqwc << 2) - s1)); } + vif1ch->madr = qwctag(vif1ch->madr); + } else { @@ -71,9 +83,12 @@ static __forceinline bool mfifoVIF1rbTransfer() if (src == NULL) return false; if (vif1.vifstalled) - ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset, false); + ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset); else - ret = VIF1transfer(src, mfifoqwc << 2, false); + ret = VIF1transfer(src, mfifoqwc << 2); + + vif1ch->madr = qwctag(vif1ch->madr); + } return ret; } @@ -83,7 +98,7 @@ static __forceinline bool mfifo_VIF1chain() bool ret; /* Is QWC = 0? if so there is nothing to transfer */ - if ((vif1ch->qwc == 0) && (!vif1.vifstalled)) + if ((vif1ch->qwc == 0)) { vif1.inprogress &= ~1; return true; @@ -95,6 +110,7 @@ static __forceinline bool mfifo_VIF1chain() u16 startqwc = vif1ch->qwc; ret = mfifoVIF1rbTransfer(); vifqwc -= startqwc - vif1ch->qwc; + } else { @@ -104,17 +120,14 @@ static __forceinline bool mfifo_VIF1chain() if (pMem == NULL) return false; if (vif1.vifstalled) - ret = VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, false); + ret = VIF1transfer((u32*)pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset); else - ret = VIF1transfer((u32*)pMem, vif1ch->qwc << 2, false); + ret = VIF1transfer((u32*)pMem, vif1ch->qwc << 2); } return ret; } -static u32 qwctag(u32 mask) -{ - return (dmacRegs->rbor.ADDR + (mask & dmacRegs->rbsr.RMSK)); -} + void mfifoVIF1transfer(int qwc) { @@ -148,19 +161,20 @@ void mfifoVIF1transfer(int qwc) { bool ret; - if (vif1.stallontag) - ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, true); //Transfer Tag on Stall + if (vif1.vifstalled) + ret = VIF1transfer((u32*)ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset); //Transfer Tag on Stall else - ret = VIF1transfer((u32*)ptag + 2, 2, true); //Transfer Tag + ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag - if (!(ret)) + if ((ret == false) && vif1.irqoffset < 2) { - VIF_LOG("MFIFO Stall on tag"); - vif1.stallontag = true; return; //IRQ set by VIFTransfer - } + + } //else vif1.vifstalled = false; } + vif1.irqoffset = 0; + vif1ch->unsafeTransfer(ptag); vif1ch->madr = ptag[1]._u32; @@ -224,29 +238,25 @@ void vifMFIFOInterrupt() if (schedulepath3msk & 0x10) Vif1MskPath3(); - if(gifRegs->stat.APATH == GIF_APATH2 && (vif1.cmd & 0x70) != 0x50) + if(vif1ch->chcr.DIR && CheckPath2GIF(10) == false) return; + //We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing) + + //Simulated GS transfer time done, clear the flags + + if(GSTransferStatus.PTH2 == PENDINGSTOP_MODE) { - gifRegs->stat.APATH = GIF_APATH_IDLE; + GSTransferStatus.PTH2 = STOPPED_MODE; + /*gifRegs->stat.APATH = GIF_APATH_IDLE; + if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false;*/ } - if ((vif1Regs->stat.VGW)) + if (vif1.cmd) { - if (GSTransferStatus.PTH3 < STOPPED_MODE || GSTransferStatus.PTH1 != STOPPED_MODE) - { - CPU_INT(10, 4); - return; - } - else - { - vif1Regs->stat.VGW = false; - } - + if(vif1.done == true && vif1ch->qwc == 0) vif1Regs->stat.VPS = VPS_WAITING; } - - if ((spr0->chcr.STR) && (spr0->qwc == 0)) + else { - spr0->chcr.STR = false; - hwDmacIrq(DMAC_FROM_SPR); + vif1Regs->stat.VPS = VPS_IDLE; } if (vif1.irq && vif1.tag.size == 0) @@ -257,9 +267,9 @@ void vifMFIFOInterrupt() if (vif1Regs->stat.test(VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) { - vif1Regs->stat.FQC = 0; // FQC=0 - vif1ch->chcr.STR = false; - return; + /*vif1Regs->stat.FQC = 0; // FQC=0 + vif1ch->chcr.STR = false;*/ + if(vif1ch->qwc > 0 || !vif1.done) return; } } @@ -302,6 +312,7 @@ void vifMFIFOInterrupt() hwDmacIrq(DMAC_MFIFO_EMPTY); }*/ + vif1.vifstalled = false; vif1.done = 1; g_vifCycles = 0; vif1ch->chcr.STR = false; diff --git a/pcsx2/Vif_Codes.cpp b/pcsx2/Vif_Codes.cpp index d096adc9e6..b631d95907 100644 --- a/pcsx2/Vif_Codes.cpp +++ b/pcsx2/Vif_Codes.cpp @@ -39,7 +39,10 @@ static _f void vifFlush(int idx) { static _f void vuExecMicro(int idx, u32 addr) { VURegs* VU = nVif[idx].VU; - vifFlush(idx); + int startcycles = 0; + //vifFlush(idx); + + //if(vifX.vifstalled == true) return; if (VU->vifRegs->itops > (idx ? 0x3ffu : 0xffu)) { Console.WriteLn("VIF%d ITOP overrun! %x", idx, VU->vifRegs->itops); @@ -65,8 +68,16 @@ static _f void vuExecMicro(int idx, u32 addr) { } } + if(!idx)startcycles = VU0.cycle; + else startcycles = VU1.cycle; + if (!idx) vu0ExecMicro(addr); else vu1ExecMicro(addr); + + if(!idx) { g_vu0Cycles += (VU0.cycle-startcycles) * BIAS; g_packetsizeonvu = vif0.vifpacketsize; } + else { g_vu1Cycles += (VU1.cycle-startcycles) * BIAS; g_packetsizeonvu = vif1.vifpacketsize; } + //DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x", idx, g_vu0Cycles, g_vu1Cycles); + vifX.vifstalled = true; } u8 schedulepath3msk = 0; @@ -74,17 +85,20 @@ u8 schedulepath3msk = 0; void Vif1MskPath3() { vif1Regs->mskpath3 = schedulepath3msk & 0x1; - //Console.WriteLn("VIF MSKPATH3 %x", vif1Regs->mskpath3); + //Console.WriteLn("VIF MSKPATH3 %x gif str %x path3 status %x", vif1Regs->mskpath3, gif->chcr.STR, GSTransferStatus.PTH3); gifRegs->stat.M3P = vif1Regs->mskpath3; - if (!vif1Regs->mskpath3) { - //Let the Gif know it can transfer again (making sure any vif stall isnt unset prematurely) - if(gif->chcr.STR == true) - { - GSTransferStatus.PTH3 = 3; - CPU_INT(DMAC_GIF, 4); - } - } + if (!vif1Regs->mskpath3) + { + //if(GSTransferStatus.PTH3 > TRANSFER_MODE && gif->chcr.STR) GSTransferStatus.PTH3 = TRANSFER_MODE; + //DevCon.Warning("Mask off"); + if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE) GSTransferStatus.PTH3 = IDLE_MODE; + if(gifRegs->stat.P3Q) + { + gsInterrupt();//gsInterrupt(); + } + + } else if(!gif->chcr.STR && GSTransferStatus.PTH3 == IDLE_MODE) GSTransferStatus.PTH3 = STOPPED_MODE;//else DevCon.Warning("Mask on"); schedulepath3msk = 0; } @@ -105,24 +119,46 @@ template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { vif1Only(); int vifImm = (u16)vif1Regs->code; vif1.tag.size = vifImm ? (vifImm*4) : (65536*4); - return 1; + vif1.vifstalled = true; + gifRegs->stat.P2Q = true; + if (gifRegs->stat.PSE) // temporarily stop + { + Console.WriteLn("Gif dma temp paused? VIF DIRECT"); + vif1.GifWaitState = 3; + vif1Regs->stat.VGW = true; + } + //Should cause this to split here to try and time PATH3 right. + return 0; } 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 (GSTransferStatus.PTH3 < STOPPED_MODE || GSTransferStatus.PTH1 != STOPPED_MODE) + + if (GSTransferStatus.PTH3 < IDLE_MODE || gifRegs->stat.P1Q == true) { - /*if(!isDirectHL) DevCon.WriteLn("Direct: Waiting for Path3 to finish!"); - else DevCon.WriteLn("DirectHL: Waiting for Path3 to finish!");*/ - //VIF_LOG("Mask %x, GIF STR %x, PTH1 %x, PTH2 %x, PTH3 %x", vif1Regs->mskpath3, gif->chcr.STR, GSTransferStatus.PTH1, GSTransferStatus.PTH2, GSTransferStatus.PTH3); - vif1Regs->stat.VGW = true; // PATH3 is in image mode, so wait for end of transfer - vif1.vifstalled = true; + if(gifRegs->stat.APATH == GIF_APATH2 || ((GSTransferStatus.PTH3 <= IMAGE_MODE && gifRegs->stat.IMT && (vif1.cmd & 0x7f) == 0x50)) && gifRegs->stat.P1Q == false) + { + //Do nothing, allow it + vif1Regs->stat.VGW = false; + //if(gifRegs->stat.APATH != GIF_APATH2)DevCon.Warning("Continue DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q); + } + else + { + //DevCon.Warning("Stall DIRECT/HL %x P3 %x APATH %x P1Q %x", vif1.cmd, GSTransferStatus.PTH3, gifRegs->stat.APATH, gifRegs->stat.P1Q); + vif1Regs->stat.VGW = true; // PATH3 is in image mode (DIRECTHL), or busy (BOTH no IMT) + vif1.GifWaitState = 0; + vif1.vifstalled = true; + return 0; + } + } + if (gifRegs->stat.PSE) // temporarily stop + { + Console.WriteLn("Gif dma temp paused? VIF DIRECT"); + vif1.GifWaitState = 3; + vif1Regs->stat.VGW = true; return 0; } - //} + + gifRegs->stat.clear_flags(GIF_STAT_P2Q); Registers::Freeze(); @@ -131,31 +167,72 @@ template _f int _vifCode_Direct(int pass, u8* data, bool isDirectHL) { u32 size = ret << 2; gifRegs->stat.APATH = GIF_APATH2; //Flag is cleared in vif1interrupt to simulate it being in progress. - - if (ret == v.vif->tag.size) { // Full Transfer - if (v.bSize) { // Last transfer was partial - memcpy_fast(&v.buffer[v.bSize], data, size); - v.bSize += size; - data = v.buffer; - size = v.bSize; - } + + //In the original code we were saving this data, it seems if it does happen, its just blank, so we ignore it. + if (!size) { DevCon.WriteLn("Path2: No Data Transfer?"); } - const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, size >> 4); - memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4); - GetMTGS().SendDataPacket(); - vif1.tag.size = 0; - vif1.cmd = 0; - v.bSize = 0; - } - else { // Partial Transfer - //DevCon.WriteLn("DirectHL: Partial Transfer [%d]", size); - memcpy_fast(&v.buffer[v.bSize], data, size); - v.bSize += size; - vif1.tag.size -= ret; - } + - Registers::Thaw(); - return ret; + if(vif1.vifpacketsize < 4 && v.bSize < 16) + { + nVifStruct& v = nVif[idx]; + + memcpy(&v.buffer[v.bPtr], data, vif1.vifpacketsize << 2); + v.bSize += vif1.vifpacketsize << 2; + v.bPtr += vif1.vifpacketsize << 2; + vif1.tag.size -= vif1.vifpacketsize; + Registers::Thaw(); + if(vif1.tag.size == 0) + { + DevCon.Warning("Missaligned packet on DIRECT end!"); + vif1.cmd = 0; + } + return vif1.vifpacketsize; + } + else + { + nVifStruct& v = nVif[idx]; + if(v.bSize) + { + int ret = 0; + + if(v.bSize < 16) + { + if(((16 - v.bSize) >> 2) > vif1.vifpacketsize) DevCon.Warning("Not Enough Data!"); + ret = (16 - v.bSize) >> 2; + memcpy(&v.buffer[v.bPtr], data, ret << 2); + vif1.tag.size -= ret; + v.bSize = 0; + v.bPtr = 0; + } + const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, v.buffer, 1, false); + memcpy_fast(GetMTGS().GetDataPacketPtr(), v.buffer, count << 4); + GetMTGS().SendDataPacket(); + + if(vif1.tag.size == 0) + { + vif1.cmd = 0; + } + vif1.vifstalled = true; + Registers::Thaw(); + return ret; + } + else + { + const uint count = GetMTGS().PrepDataPacket(GIF_PATH_2, data, size >> 4, false); + memcpy_fast(GetMTGS().GetDataPacketPtr(), data, count << 4); + GetMTGS().SendDataPacket(); + vif1.tag.size -= count << 2; + if(vif1.tag.size == 0) + { + vif1.cmd = 0; + } + vif1.vifstalled = true; + Registers::Thaw(); + return count << 2; + } + } + } return 0; } @@ -173,7 +250,7 @@ vifOp(vifCode_DirectHL) { // ToDo: FixMe vifOp(vifCode_Flush) { vif1Only(); - pass1 { vifFlush(idx); vifX.cmd = 0; } + pass1 { vifFlush(idx); vifX.cmd = 0; } pass3 { DevCon.WriteLn("vifCode_Flush"); } return 0; } @@ -182,16 +259,22 @@ vifOp(vifCode_Flush) { vifOp(vifCode_FlushA) { vif1Only(); pass1 { + vifFlush(idx); // Gif is already transferring so wait for it. - if (GSTransferStatus.PTH3 < STOPPED_MODE) { + if (gifRegs->stat.P1Q == true || GSTransferStatus.PTH3 < PENDINGSTOP_MODE) { + //DevCon.Warning("VIF FlushA Wait MSK = %x", vif1Regs->mskpath3); + // + //DevCon.WriteLn("FlushA path3 Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR); vif1Regs->stat.VGW = true; + vif1.GifWaitState = 1; vifX.vifstalled = true; - } - vifFlush(idx); - vifX.cmd = 0; + } // else DevCon.WriteLn("FlushA path3 no Wait! PTH3 MD %x STR %x", GSTransferStatus.PTH3, gif->chcr.STR); + + } pass3 { DevCon.WriteLn("vifCode_FlushA"); } + vifX.cmd = 0; return 0; } @@ -234,10 +317,10 @@ vifOp(vifCode_MPG) { int vifNum = (u8)(vifXRegs->code >> 16); vifX.tag.addr = (u16)(vifXRegs->code << 3) & (idx ? 0x3fff : 0xfff); vifX.tag.size = vifNum ? (vifNum*2) : 512; + //vifFlush(idx); return 1; } pass2 { - vifFlush(idx); if (vifX.vifpacketsize < vifX.tag.size) { // Partial Transfer if((vifX.tag.addr + vifX.vifpacketsize) > (idx ? 0x4000 : 0x1000)) { DevCon.Warning("Vif%d MPG Split Overflow", idx); @@ -263,19 +346,19 @@ vifOp(vifCode_MPG) { } vifOp(vifCode_MSCAL) { - pass1 { vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; } + pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0;} pass3 { DevCon.WriteLn("vifCode_MSCAL"); } return 0; } vifOp(vifCode_MSCALF) { - pass1 { vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; } + pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs->code) << 3); vifX.cmd = 0; } pass3 { DevCon.WriteLn("vifCode_MSCALF"); } return 0; } vifOp(vifCode_MSCNT) { - pass1 { vuExecMicro(idx, -1); vifX.cmd = 0; } + pass1 { vifFlush(idx); vuExecMicro(idx, -1); vifX.cmd = 0; } pass3 { DevCon.WriteLn("vifCode_MSCNT"); } return 0; } @@ -284,7 +367,7 @@ vifOp(vifCode_MSCNT) { vifOp(vifCode_MskPath3) { vif1Only(); pass1 { - if (vif1ch->chcr.STR) { + if (vif1ch->chcr.STR && vifX.lastcmd != 0x13) { schedulepath3msk = 0x10 | ((vif1Regs->code >> 15) & 0x1); vif1.vifstalled = true; } diff --git a/pcsx2/Vif_Dma.h b/pcsx2/Vif_Dma.h index 707f9febd1..363008d9f4 100644 --- a/pcsx2/Vif_Dma.h +++ b/pcsx2/Vif_Dma.h @@ -75,7 +75,9 @@ struct vifStruct { u32 savedtag; // need this for backwards compat with save states u32 vifpacketsize; u8 inprogress; + u32 lastcmd; u8 dmamode; + u8 GifWaitState; // 0 = General PATH checking, 1 = Flush path 3, 2 == Wait for VU1 }; extern vifStruct* vif; @@ -110,8 +112,10 @@ enum VifModes static const unsigned int VIF0intc = 4; static const unsigned int VIF1intc = 5; -extern int g_vifCycles; - +extern u32 g_vifCycles; +extern u32 g_vu0Cycles; +extern u32 g_vu1Cycles; +extern u32 g_packetsizeonvu; extern void vif0FLUSH(); extern void vif1FLUSH(); diff --git a/pcsx2/Vif_Transfer.cpp b/pcsx2/Vif_Transfer.cpp index 91a07661f5..a5f80db686 100644 --- a/pcsx2/Vif_Transfer.cpp +++ b/pcsx2/Vif_Transfer.cpp @@ -69,6 +69,7 @@ _vifT void vifTransferLoop(u32* &data) { while (pSize > 0 && !vifX.vifstalled) { if(!vifX.cmd) { // Get new VifCode + vifX.lastcmd = (vifXRegs->code >> 24) & 0x7f; vifXRegs->code = data[0]; vifX.cmd = data[0] >> 24; iBit = data[0] >> 31; @@ -84,8 +85,7 @@ _vifT void vifTransferLoop(u32* &data) { pSize -= ret; if (analyzeIbit(data, iBit)) break; } - if (vifX.cmd) vifXRegs->stat.VPS = VPS_WAITING; - else vifXRegs->stat.VPS = VPS_IDLE; + if (pSize) vifX.vifstalled = true; } @@ -97,14 +97,30 @@ _vifT _f bool vifTransfer(u32 *data, int size) { vifX.vifstalled = false; vifX.stallontag = false; vifX.vifpacketsize = size; - + g_packetsizeonvu = size; vifTransferLoop(data); + transferred += size - vifX.vifpacketsize; - g_vifCycles +=(transferred >> 2) * BIAS; /* guessing */ + + g_vifCycles +=((transferred * BIAS) >> 2) ; /* guessing */ + + if(!idx && g_vu0Cycles > 0) + { + if(g_vifCycles < g_vu0Cycles) g_vu0Cycles -= g_vifCycles; + else if(g_vifCycles >= g_vu0Cycles)g_vu0Cycles = 0; + } + else if(idx && g_vu1Cycles > 0) + { + if(g_vifCycles < g_vu1Cycles) g_vu1Cycles -= g_vifCycles; + else if(g_vifCycles >= g_vu1Cycles)g_vu1Cycles = 0; + } + + vifX.irqoffset = transferred % 4; // cannot lose the offset transferred = transferred >> 2; + vifXch->madr +=(transferred << 4); vifXch->qwc -= transferred; @@ -125,9 +141,9 @@ _vifT _f bool vifTransfer(u32 *data, int size) { return !vifX.vifstalled; } -bool VIF0transfer(u32 *data, int size, bool istag) { +bool VIF0transfer(u32 *data, int size) { return vifTransfer<0>(data, size); } -bool VIF1transfer(u32 *data, int size, bool istag) { +bool VIF1transfer(u32 *data, int size) { return vifTransfer<1>(data, size); } diff --git a/pcsx2/Vif_Unpack.cpp b/pcsx2/Vif_Unpack.cpp index f647d058e7..7a09cedc18 100644 --- a/pcsx2/Vif_Unpack.cpp +++ b/pcsx2/Vif_Unpack.cpp @@ -306,7 +306,8 @@ _vifT void vifUnpackSetup(u32 *data) { return; // Skipping write and 0 write-cycles, so do nothing! } - if (!idx) vif0FLUSH(); // Only VU0? + + //if (!idx) vif0FLUSH(); // Only VU0? vifX.usn = (vifXRegs->code >> 14) & 0x01; int vifNum = (vifXRegs->code >> 16) & 0xff; @@ -330,6 +331,8 @@ _vifT void vifUnpackSetup(u32 *data) { if (idx && ((addr>>15)&1)) addr += vif1Regs->tops; vifX.tag.addr = (addr<<4) & (idx ? 0x3ff0 : 0xff0); + VIF_LOG("Unpack VIF%x, QWC %x tagsize %x", idx, vifNum, vif0.tag.size); + vifX.cl = 0; vifX.tag.cmd = vifX.cmd; vifXRegs->offset = 0; diff --git a/pcsx2/ps2/GIFpath.cpp b/pcsx2/ps2/GIFpath.cpp index 314e3b7e33..df1bfd7ae2 100644 --- a/pcsx2/ps2/GIFpath.cpp +++ b/pcsx2/ps2/GIFpath.cpp @@ -100,7 +100,7 @@ struct GIFPath bool StepReg(); u8 GetReg(); - int ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size); + int ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly); }; typedef void (__fastcall *GIFRegHandler)(const u32* data); @@ -280,9 +280,13 @@ static __forceinline void gsHandler(const u8* pMem) const int reg = pMem[8]; if (reg == 0x50) + { vif1.BITBLTBUF._u64 = *(u64*)pMem; + } else if (reg == 0x52) + { vif1.TRXREG._u64 = *(u64*)pMem; + } else if (reg == 0x53) { // local -> host @@ -316,7 +320,6 @@ static __forceinline void gsHandler(const u8* pMem) // qwords, rounded down; any extra bits are lost // games must take care to ensure transfer rectangles are exact multiples of a qword vif1.GSLastDownloadSize = vif1.TRXREG.RRW * vif1.TRXREG.RRH * bpp >> 7; - VIF_LOG("GS Download size %x", vif1.GSLastDownloadSize); gifRegs->stat.OPH = true; } } @@ -341,10 +344,9 @@ static __forceinline void gsHandler(const u8* pMem) // Parameters: // size (path1) - difference between the end of VU memory and pMem. // size (path2/3) - max size of incoming data stream, in qwc (simd128) -__forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) +__forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly) { const u8* vuMemEnd = pMem + (size<<4); // End of VU1 Mem - if (pathidx==GIF_PATH_1) size = 0x400; // VU1 mem size u32 startSize = size; // Start Size while (size > 0) { @@ -352,27 +354,36 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) SetTag(pMem); incTag(16, 1); - - //if (pathidx == GIF_PATH_3) { - switch(pathidx) + + + if(nloop > 0) { - 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; + 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; + } + if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = true; + gifRegs->stat.APATH = pathidx + 1; } - //} + if(pathidx == GIF_PATH_3) break; } else { + + gifRegs->stat.APATH = pathidx + 1; + if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = true; switch(tag.FLG) { case GIF_FLG_PACKED: GIF_LOG("Packed Mode"); @@ -409,7 +420,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) } if(pathidx == GIF_PATH_1) { - if(nloop > 0 && size == 0 && !tag.EOP) //Need to check all of this, some cases VU will send info (like the BIOS) but be incomplete + if(size == 0 && (!tag.EOP || nloop > 0)) //Need to check all of this, some cases VU will send info (like the BIOS) but be incomplete { switch(tag.FLG) { @@ -433,39 +444,45 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) } } } - if (tag.EOP && !nloop) { - if (pathidx != GIF_PATH_2) { - break; - } - } + + if (tag.EOP && !nloop) break; } - /*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 (tag.EOP && !nloop) { - //Console.Warning("Finishing path %x", pathidx); + if (tag.EOP && nloop <= 16) { + if(pathidx == 2 && nloop > 0) + { + if(GSTransferStatus.PTH3 != IDLE_MODE) GSTransferStatus.PTH3 = PENDINGSTOP_MODE; + } + else if(nloop == 0) + { + if(gifRegs->stat.DIR == 0)gifRegs->stat.OPH = false; + gifRegs->stat.APATH = GIF_APATH_IDLE; switch(pathidx) { case GIF_PATH_1: GSTransferStatus.PTH1 = STOPPED_MODE; break; case GIF_PATH_2: - GSTransferStatus.PTH2 = STOPPED_MODE; + GSTransferStatus.PTH2 = PENDINGSTOP_MODE; break; case GIF_PATH_3: - GSTransferStatus.PTH3 = STOPPED_MODE; + if(GSTransferStatus.PTH3 != IDLE_MODE) GSTransferStatus.PTH3 = STOPPED_MODE; break; } } + } + else if(nloop <= 16 && GSTransferStatus.PTH3 == IMAGE_MODE && pathidx == 2) + { + GSTransferStatus.PTH3 = PENDINGIMAGE_MODE; + } + if (pathidx == GIF_PATH_3 && gif->chcr.STR) { //Make sure we are really doing a DMA and not using FIFO //GIF_LOG("Path3 end EOP %x NLOOP %x Status %x", tag.EOP, nloop, GSTransferStatus.PTH3); gif->madr += size * 16; gif->qwc -= size; - } else if (pathidx == GIF_PATH_2 && !nloop) { //Path2 is odd, but always provides the correct size - GSTransferStatus.PTH2 = STOPPED_MODE; } return size; @@ -476,7 +493,7 @@ __forceinline int GIFPath::ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) // runs potentially several frames behind. // Parameters: // size - max size of incoming data stream, in qwc (simd128) -__forceinline int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) +__forceinline int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size, bool TestOnly) { #ifdef PCSX2_GSRING_SAMPLING_STATS static uptr profStartPtr = 0; @@ -492,7 +509,7 @@ __forceinline int GIFPath_ParseTag(GIF_PATH pathidx, const u8* pMem, u32 size) } #endif - int retSize = s_gifPath[pathidx].ParseTag(pathidx, pMem, size); + int retSize = s_gifPath[pathidx].ParseTag(pathidx, pMem, size, TestOnly); #ifdef PCSX2_GSRING_SAMPLING_STATS __asm @@ -515,6 +532,8 @@ void GIFPath_Reset() __forceinline void GIFPath_Clear( GIF_PATH pathidx ) { memzero(s_gifPath.path[pathidx]); + GSTransferStatus._u32 &= ~(0xf << (pathidx * 4)); + GSTransferStatus._u32 |= (0x5 << (pathidx * 4)); if( GSgifSoftReset == NULL ) return; GetMTGS().SendSimplePacket( GS_RINGTYPE_SOFTRESET, (1<Mem + (addr*16); u32 diff = 0x400 - addr; - u32 size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff); - u8* pDest = GetMTGS().GetDataPacketPtr(); + u32 size; + u8* pDest; - if (size > diff) { - // fixme: one of these days the following *16's will get cleaned up when we introduce - // a special qwc/simd16 optimized version of memcpy_aligned. :) - //DevCon.Status("XGkick Wrap!"); - memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), diff*16); - size -= diff; - pDest += diff*16; - memcpy_aligned(pDest, microVU1.regs->Mem, size*16); + if(gifRegs->stat.APATH == GIF_APATH_IDLE) + { + size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, false); + pDest = GetMTGS().GetDataPacketPtr(); + if (size > diff) { + // fixme: one of these days the following *16's will get cleaned up when we introduce + // a special qwc/simd16 optimized version of memcpy_aligned. :) + //DevCon.Status("XGkick Wrap!"); + memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), diff*16); + size -= diff; + pDest += diff*16; + memcpy_aligned(pDest, microVU1.regs->Mem, size*16); + } + else { + memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), size*16); + } + GetMTGS().SendDataPacket(); } - else { - memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), size*16); + else + { + //DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs->stat.APATH, Path1WritePos, Path1ReadPos); + size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, true); + pDest = &Path1Buffer[Path1WritePos*16]; + + + + //DevCon.Warning("Storing size %x PATH 1", size); + if (size > diff) { + // fixme: one of these days the following *16's will get cleaned up when we introduce + // a special qwc/simd16 optimized version of memcpy_aligned. :) + //DevCon.Status("XGkick Wrap!"); + memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), diff*16); + Path1WritePos += size; + size -= diff; + pDest += diff*16; + memcpy_aligned(pDest, microVU1.regs->Mem, size*16); + } + else { + memcpy_aligned(pDest, microVU1.regs->Mem + (addr*16), size*16); + Path1WritePos += size; + } + if(!gifRegs->stat.P1Q) CPU_INT(28, 16); + gifRegs->stat.P1Q = true; } - GetMTGS().SendDataPacket(); } _f void mVU_XGKICK_DELAY(mV, bool memVI) { diff --git a/pcsx2/x86/newVif.h b/pcsx2/x86/newVif.h index 49e291d3f0..61cea776b4 100644 --- a/pcsx2/x86/newVif.h +++ b/pcsx2/x86/newVif.h @@ -87,6 +87,7 @@ struct nVifStruct { u8* vuMemEnd; // End of VU Memory u32 vuMemLimit; // Use for fast AND u32 bSize; // Size of 'buffer' + u32 bPtr; u8 buffer[_1mb]; // Buffer for partial transfers u8* recPtr; // Cur Pos to recompile to u8* recEnd; // 'Safe' End of Rec Cache diff --git a/pcsx2/x86/newVif_Dynarec.cpp b/pcsx2/x86/newVif_Dynarec.cpp index db57d8ec48..cfcbb0c9e4 100644 --- a/pcsx2/x86/newVif_Dynarec.cpp +++ b/pcsx2/x86/newVif_Dynarec.cpp @@ -173,7 +173,7 @@ void VifUnpackSSE_Dynarec::CompileRoutine() { if (++vCL == blockSize) vCL = 0; } else if (isFill) { - DevCon.WriteLn("filling mode!"); + //DevCon.WriteLn("filling mode!"); VifUnpackSSE_Dynarec fill( VifUnpackSSE_Dynarec::FillingWrite( *this ) ); fill.xUnpack(upkNum); fill.xMovDest(); diff --git a/pcsx2/x86/sVU_Lower.cpp b/pcsx2/x86/sVU_Lower.cpp index 21d60f243d..0559d7bb90 100644 --- a/pcsx2/x86/sVU_Lower.cpp +++ b/pcsx2/x86/sVU_Lower.cpp @@ -26,6 +26,7 @@ #include "sVU_Micro.h" #include "sVU_Debug.h" #include "sVU_zerorec.h" +#include "Gif.h" //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -1971,27 +1972,57 @@ void recVUMI_XTOP( VURegs *VU, int info ) //------------------------------------------------------------------ void __fastcall VU1XGKICK_MTGSTransfer(u32 *pMem, u32 addr) { + addr &= 0x3fff; + u8* data = VU1.Mem + (addr); + u32 diff = 0x400 - (addr / 16); u32 size; - u8* data = ((u8*)pMem + (addr&0x3fff)); + u8* pDest; - size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, (0x4000-(addr&0x3fff)) / 16); - jASSUME( size > 0 ); - - u8* pmem = GetMTGS().GetDataPacketPtr(); - - if((size << 4) > (0x4000-(addr&0x3fff))) + if(gifRegs->stat.APATH == GIF_APATH_IDLE) { - //DevCon.Warning("addr + Size = 0x%x, transferring %x then doing %x", (addr&0x3fff) + (size << 4), (0x4000-(addr&0x3fff)) >> 4, size - ((0x4000-(addr&0x3fff)) >> 4)); - memcpy_aligned(pmem, (u8*)pMem+addr, 0x4000-(addr&0x3fff)); - size -= (0x4000-(addr&0x3fff)) >> 4; - //DevCon.Warning("Size left %x", size); - pmem += 0x4000-(addr&0x3fff); - memcpy_aligned(pmem, (u8*)pMem, size<<4); + size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, false); + pDest = GetMTGS().GetDataPacketPtr(); + if (size > diff) { + // fixme: one of these days the following *16's will get cleaned up when we introduce + // a special qwc/simd16 optimized version of memcpy_aligned. :) + + memcpy_aligned(pDest, VU1.Mem + addr, diff*16); + size -= diff; + pDest += diff*16; + memcpy_aligned(pDest, VU1.Mem, size*16); + } + else { + memcpy_aligned(pDest, VU1.Mem + addr, size*16); + } + GetMTGS().SendDataPacket(); } - else { - memcpy_aligned(pmem, (u8*)pMem+addr, size<<4); + else + { + //DevCon.Warning("GIF APATH busy %x Holding for later W %x, R %x", gifRegs->stat.APATH, Path1WritePos, Path1ReadPos); + size = GetMTGS().PrepDataPacket(GIF_PATH_1, data, diff, true); + pDest = &Path1Buffer[Path1WritePos*16]; + + + + //DevCon.Warning("Storing size %x PATH 1", size); + if (size > diff) { + // fixme: one of these days the following *16's will get cleaned up when we introduce + // a special qwc/simd16 optimized version of memcpy_aligned. :) + //DevCon.Status("XGkick Wrap!"); + memcpy_aligned(pDest, VU1.Mem + addr, diff*16); + Path1WritePos += size; + size -= diff; + pDest += diff*16; + memcpy_aligned(pDest, VU1.Mem, size*16); + } + else { + memcpy_aligned(pDest, VU1.Mem + addr, size*16); + Path1WritePos += size; + } + if(!gifRegs->stat.P1Q) CPU_INT(28, 16); + gifRegs->stat.P1Q = true; } - GetMTGS().SendDataPacket(); + } //------------------------------------------------------------------