VIF/VU: Fixes for Everblue and Hitman 2 from r5404, details below. Savestate bump needed, sorry. Also fixed a copy/paste bug i noticed along the way in vif0FBRST.

Everblue: Slightly messy fix, not as nice as id hope, but it seems to work, we need to remember VU programs written to the VU so we can check if an unpack is modifying it.  This retains the behaviour of the Snowblind engines whilst fixing everblue.

Hitman 2: Our vif0/1VUFinish() routing which works in conjunction with the delays wasn't paying attention to if the VIF was stalled or not and reran it before the game wanted it to, now fixed.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5544 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
refraction@gmail.com 2013-02-05 00:42:44 +00:00
parent 580f7a2e3d
commit c30f67b767
7 changed files with 49 additions and 5 deletions

View File

@ -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. :)

View File

@ -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 // ...

View File

@ -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");

View File

@ -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<<DMAC_VIF1 | 1 << DMAC_MFIFO_VIF)) == 0 && vif1ch.chcr.STR == true)
if((cpuRegs.interrupt & (1<<DMAC_VIF1 | 1 << DMAC_MFIFO_VIF)) == 0 && vif1ch.chcr.STR == true && !vif1Regs.stat.INT)
{
if(dmacRegs.ctrl.MFD == MFD_VIF1)
vifMFIFOInterrupt();

View File

@ -306,10 +306,30 @@ static __fi void _vifCode_MPG(int idx, u32 addr, const u32 *data, int size) {
vifOp(vifCode_MPG) {
vifStruct& vifX = GetVifX;
pass1 {
bool bProgramExists = false;
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);
//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
{

View File

@ -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;

View File

@ -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;