diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index 45684b16e1..747708bbd6 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -24,7 +24,7 @@ // the lower 16 bit value. IF the change is breaking of all compatibility with old // states, increment the upper 16 bit value, and clear the lower 16 bits to 0. -static const u32 g_SaveVersion = (0x9A0A << 16) | 0x0000; +static const u32 g_SaveVersion = (0x9A0B << 16) | 0x0000; // this function is meant to be used in the place of GSfreeze, and provides a safe layer // between the GS saving function and the MTGS's needs. :) diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index c313a36a51..13db69cf63 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -98,11 +98,12 @@ __fi void vif0FBRST(u32 value) { psHu64(VIF0_FIFO) = 0; psHu64(VIF0_FIFO + 8) = 0; vif0.vifstalled.enabled = false; - vif1.irqoffset.enabled = false; + vif0.irqoffset.enabled = false; vif0.inprogress = 0; vif0.cmd = 0; vif0.done = true; vif0ch.chcr.STR = false; + vif0.LoadedMicroProgs = 0; vif0Regs.err.reset(); vif0Regs.stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0 } @@ -177,6 +178,7 @@ __fi void vif1FBRST(u32 value) { psHu64(VIF1_FIFO) = 0; psHu64(VIF1_FIFO + 8) = 0; vif1.done = true; + vif1.LoadedMicroProgs = 0; vif1ch.chcr.STR = false; #if USE_OLD_GIF == 1 // ... diff --git a/pcsx2/Vif0_Dma.cpp b/pcsx2/Vif0_Dma.cpp index b540052e42..ecd8a4978c 100644 --- a/pcsx2/Vif0_Dma.cpp +++ b/pcsx2/Vif0_Dma.cpp @@ -162,7 +162,7 @@ __fi void vif0VUFinish() vif0.waitforvu = false; ExecuteVU(0); //Make sure VIF0 isnt already scheduled to spin. - if(!(cpuRegs.interrupt & 0x1) && vif0ch.chcr.STR == true) + if(!(cpuRegs.interrupt & 0x1) && vif0ch.chcr.STR == true && !vif0Regs.stat.INT) vif0Interrupt(); } //DevCon.Warning("VU0 state cleared"); diff --git a/pcsx2/Vif1_Dma.cpp b/pcsx2/Vif1_Dma.cpp index b3388d42d5..0b3724af9b 100644 --- a/pcsx2/Vif1_Dma.cpp +++ b/pcsx2/Vif1_Dma.cpp @@ -235,7 +235,7 @@ __fi void vif1VUFinish() vif1.waitforvu = false; ExecuteVU(1); //Check if VIF is already scheduled to interrupt, if it's waiting, kick it :P - if((cpuRegs.interrupt & (1<> 16); vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff); vifX.tag.size = vifNum ? (vifNum*2) : 512; vifFlush(idx); + + //Make a note of the VU programs we're loading, checked in VIF Unpacks + for( u32 i = 0; i < vifX.LoadedMicroProgs; i++ ) + { + if(vifX.MicroProgAddrS[i] == vifX.tag.addr) + { + bProgramExists = true; + vifX.MicroProgAddrS[i] = vifX.tag.addr; + vifX.MicroProgAddrE[i] = vifX.tag.addr + (vifX.tag.size * 4); + break; + } + } + if(bProgramExists == false) + { + vifX.MicroProgAddrS[vifX.LoadedMicroProgs] = vifX.tag.addr; + vifX.MicroProgAddrE[vifX.LoadedMicroProgs] = vifX.tag.addr + (vifX.tag.size * 4); + vifX.LoadedMicroProgs++; + } + if(vifX.vifstalled.enabled == true) return 0; else { diff --git a/pcsx2/Vif_Dma.h b/pcsx2/Vif_Dma.h index 14d20a1d1d..ac2e6ea25e 100644 --- a/pcsx2/Vif_Dma.h +++ b/pcsx2/Vif_Dma.h @@ -93,6 +93,9 @@ struct vifStruct { bool queued_program; u32 queued_pc; + u32 LoadedMicroProgs; //Note how many microprograms we have on the VU. + u32 MicroProgAddrS[100]; //Start Addresses + u32 MicroProgAddrE[100]; //End Addresses }; extern __aligned16 vifStruct vif0, vif1; diff --git a/pcsx2/Vif_Unpack.cpp b/pcsx2/Vif_Unpack.cpp index bf76364cc7..f6ff281674 100644 --- a/pcsx2/Vif_Unpack.cpp +++ b/pcsx2/Vif_Unpack.cpp @@ -185,7 +185,7 @@ __aligned16 const UNPACKFUNCTYPE VIFfuncTable[2][3][4 * 4 * 2 * 2] = //---------------------------------------------------------------------------- _vifT void vifUnpackSetup(const u32 *data) { - + bool bModifyingVUProg = false; vifStruct& vifX = GetVifX; if ((vifXRegs.cycle.wl == 0) && (vifXRegs.cycle.wl < vifXRegs.cycle.cl)) { @@ -226,6 +226,25 @@ _vifT void vifUnpackSetup(const u32 *data) { if (idx && ((addr>>15)&1)) addr += vif1Regs.tops; vifX.tag.addr = (addr<<4) & (idx ? 0x3ff0 : 0xff0); + //The Snowblind Engine modifies VU programs with unpacks (seemingly), + //however some games (like everblue) don't like the vu waiting until the + //last minute, so as long as the unpack isn't editing a microprogram, we're safe. + if(vifX.queued_program == true && vifX.LoadedMicroProgs > 0) + { + for(u32 i = 0; i < vifX.LoadedMicroProgs; i++) + { + if(vifX.MicroProgAddrS[i] <= vifX.tag.addr && vifX.MicroProgAddrE[i] > vifX.tag.addr) + { + bModifyingVUProg = true; + break; + } + } + if(bModifyingVUProg == false) + vifExecQueue(idx); + } + + + VIF_LOG("Unpack VIF%x, QWC %x tagsize %x", idx, vifNum, vif0.tag.size); vifX.cl = 0;