mirror of https://github.com/PCSX2/pcsx2.git
VIF: Reworked the VU delays in to scheduled events to simulate VU run time without killing Metal Saga or Fahrenheit. Adjusted the COP checks on the VU's to use the same method as the VPU_STAT is never set essentially so the VU is never "running".
Path3 Masking: Fixed a bug which caused persona 3 not to boot, previous a hack had been put in place to get around this. VIF: Fixed a VIF error with the rare game Realta Nua, now goes through the prologue correctly. Game requires the EE timing hack to get rid of most of the noise (Path3 masking problem with new GIF unit, unfixable). Expecting bugs, I will be monitoring this. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5147 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
2e22e56b48
commit
d29a30c265
|
@ -22,17 +22,20 @@
|
||||||
|
|
||||||
using namespace R5900;
|
using namespace R5900;
|
||||||
using namespace R5900::Interpreter;
|
using namespace R5900::Interpreter;
|
||||||
|
//#define CP2COND (((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1))
|
||||||
|
#define CP2COND (vif1Regs.stat.VEW)
|
||||||
|
|
||||||
#define CP2COND (((VU0.VI[REG_VPU_STAT].US[0] >> 8) & 1))
|
//Run the FINISH either side of the VCALL's as we have no control over it past here.
|
||||||
|
|
||||||
void VCALLMS() {
|
void VCALLMS() {
|
||||||
vu0Finish();
|
vu0Finish();
|
||||||
vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF) * 8);
|
vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF) * 8);
|
||||||
|
vif0Regs.stat.VEW = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCALLMSR() {
|
void VCALLMSR() {
|
||||||
vu0Finish();
|
vu0Finish();
|
||||||
vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0] * 8);
|
vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0] * 8);
|
||||||
|
vif0Regs.stat.VEW = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BC2F()
|
void BC2F()
|
||||||
|
|
|
@ -583,7 +583,8 @@ struct Gif_Unit {
|
||||||
|
|
||||||
bool CanDoP3Slice() { return stat.IMT == 1 && gifPath[GIF_PATH_3].state == GIF_PATH_IMAGE; }
|
bool CanDoP3Slice() { return stat.IMT == 1 && gifPath[GIF_PATH_3].state == GIF_PATH_IMAGE; }
|
||||||
bool CanDoGif() { return stat.PSE == 0 && (CHECK_GIFREVERSEHACK ? 1 : stat.DIR == 0) && gsSIGNAL.queued == 0; }
|
bool CanDoGif() { return stat.PSE == 0 && (CHECK_GIFREVERSEHACK ? 1 : stat.DIR == 0) && gsSIGNAL.queued == 0; }
|
||||||
bool Path3Masked() { return stat.M3R || stat.M3P; }
|
//Mask stops the next packet which hasnt started from transferring
|
||||||
|
bool Path3Masked() { return ((stat.M3R || stat.M3P) && (gifPath[GIF_PATH_3].state == GIF_PATH_IDLE)); }
|
||||||
|
|
||||||
void PrintInfo(bool printP1=1, bool printP2=1, bool printP3=1) {
|
void PrintInfo(bool printP1=1, bool printP2=1, bool printP3=1) {
|
||||||
u32 a = checkPaths(1,1,1), b = checkQueued(1,1,1);
|
u32 a = checkPaths(1,1,1), b = checkQueued(1,1,1);
|
||||||
|
|
|
@ -292,7 +292,7 @@ static __fi void _cpuTestInterrupts()
|
||||||
// The following ints are rarely called. Encasing them in a conditional
|
// The following ints are rarely called. Encasing them in a conditional
|
||||||
// as follows helps speed up most games.
|
// as follows helps speed up most games.
|
||||||
|
|
||||||
if( cpuRegs.interrupt & 0xF19 ) // Bits 0 3 4 8 9 10 11 ( 111100011001 )
|
if( cpuRegs.interrupt & 0x60F19 ) // Bits 0 3 4 8 9 10 11 17 18( 1100000111100011001 )
|
||||||
{
|
{
|
||||||
TESTINT(DMAC_VIF0, vif0Interrupt);
|
TESTINT(DMAC_VIF0, vif0Interrupt);
|
||||||
|
|
||||||
|
@ -304,6 +304,9 @@ static __fi void _cpuTestInterrupts()
|
||||||
|
|
||||||
TESTINT(DMAC_MFIFO_VIF, vifMFIFOInterrupt);
|
TESTINT(DMAC_MFIFO_VIF, vifMFIFOInterrupt);
|
||||||
TESTINT(DMAC_MFIFO_GIF, gifMFIFOInterrupt);
|
TESTINT(DMAC_MFIFO_GIF, gifMFIFOInterrupt);
|
||||||
|
|
||||||
|
TESTINT(VIF_VU0_FINISH, vif0VUFinish);
|
||||||
|
TESTINT(VIF_VU1_FINISH, vif1VUFinish);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -405,8 +405,10 @@ enum EE_EventType
|
||||||
DMAC_STALL_SIS = 13, // SIS
|
DMAC_STALL_SIS = 13, // SIS
|
||||||
DMAC_MFIFO_EMPTY = 14, // MEIS
|
DMAC_MFIFO_EMPTY = 14, // MEIS
|
||||||
DMAC_BUS_ERROR = 15, // BEIS
|
DMAC_BUS_ERROR = 15, // BEIS
|
||||||
|
|
||||||
DMAC_GIF_UNIT
|
DMAC_GIF_UNIT,
|
||||||
|
VIF_VU0_FINISH,
|
||||||
|
VIF_VU1_FINISH
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void CPU_INT( EE_EventType n, s32 ecycle );
|
extern void CPU_INT( EE_EventType n, s32 ecycle );
|
||||||
|
|
|
@ -46,6 +46,7 @@ void __fastcall vu0ExecMicro(u32 addr) {
|
||||||
|
|
||||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF;
|
VU0.VI[REG_VPU_STAT].UL &= ~0xFF;
|
||||||
VU0.VI[REG_VPU_STAT].UL |= 0x01;
|
VU0.VI[REG_VPU_STAT].UL |= 0x01;
|
||||||
|
vif0Regs.stat.VEW = true;
|
||||||
|
|
||||||
if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr;
|
if ((s32)addr != -1) VU0.VI[REG_TPC].UL = addr;
|
||||||
_vuExecMicroDebug(VU0);
|
_vuExecMicroDebug(VU0);
|
||||||
|
|
|
@ -50,9 +50,10 @@ void vu1Finish() {
|
||||||
|
|
||||||
void __fastcall vu1ExecMicro(u32 addr)
|
void __fastcall vu1ExecMicro(u32 addr)
|
||||||
{
|
{
|
||||||
|
vif1Regs.stat.VEW = true;
|
||||||
|
|
||||||
if (THREAD_VU1) {
|
if (THREAD_VU1) {
|
||||||
vu1Thread.ExecuteVU(addr, vif1Regs.top, vif1Regs.itop);
|
vu1Thread.ExecuteVU(addr, vif1Regs.top, vif1Regs.itop);
|
||||||
vif1Regs.stat.VEW = false;
|
|
||||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -64,7 +65,6 @@ void __fastcall vu1ExecMicro(u32 addr)
|
||||||
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
VU0.VI[REG_VPU_STAT].UL &= ~0xFF00;
|
||||||
VU0.VI[REG_VPU_STAT].UL |= 0x0100;
|
VU0.VI[REG_VPU_STAT].UL |= 0x0100;
|
||||||
|
|
||||||
vif1Regs.stat.VEW = true;
|
|
||||||
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
|
if ((s32)addr != -1) VU1.VI[REG_TPC].UL = addr;
|
||||||
_vuExecMicroDebug(VU1);
|
_vuExecMicroDebug(VU1);
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,6 @@ void SaveStateBase::vif0Freeze()
|
||||||
FreezeTag("VIF0dma");
|
FreezeTag("VIF0dma");
|
||||||
|
|
||||||
Freeze(g_vif0Cycles);
|
Freeze(g_vif0Cycles);
|
||||||
Freeze(g_vu0Cycles);
|
|
||||||
Freeze(g_packetsizeonvu0);
|
|
||||||
|
|
||||||
Freeze(vif0);
|
Freeze(vif0);
|
||||||
|
|
||||||
|
@ -61,8 +59,6 @@ void SaveStateBase::vif1Freeze()
|
||||||
FreezeTag("VIF1dma");
|
FreezeTag("VIF1dma");
|
||||||
|
|
||||||
Freeze(g_vif1Cycles);
|
Freeze(g_vif1Cycles);
|
||||||
Freeze(g_vu1Cycles);
|
|
||||||
Freeze(g_packetsizeonvu1);
|
|
||||||
|
|
||||||
Freeze(vif1);
|
Freeze(vif1);
|
||||||
|
|
||||||
|
|
|
@ -25,31 +25,11 @@ u32 g_vif0Cycles = 0;
|
||||||
// because its vif stalling not the EE core...
|
// because its vif stalling not the EE core...
|
||||||
__fi void vif0FLUSH()
|
__fi void vif0FLUSH()
|
||||||
{
|
{
|
||||||
if(g_packetsizeonvu0 > vif0.vifpacketsize && g_vu0Cycles > 0)
|
if(vif0Regs.stat.VEW == true)
|
||||||
{
|
|
||||||
//DevCon.Warning("Adding on same packet");
|
|
||||||
if( ((g_packetsizeonvu0 - vif0.vifpacketsize) >> 1) > g_vu0Cycles)
|
|
||||||
g_vu0Cycles -= (g_packetsizeonvu0 - vif0.vifpacketsize) >> 1;
|
|
||||||
else g_vu0Cycles = 0;
|
|
||||||
}
|
|
||||||
if(g_vu0Cycles > 0)
|
|
||||||
{
|
|
||||||
//DevCon.Warning("Adding %x cycles to VIF0", g_vu0Cycles * BIAS);
|
|
||||||
g_vif0Cycles += g_vu0Cycles;
|
|
||||||
g_vu0Cycles = 0;
|
|
||||||
}
|
|
||||||
g_vu0Cycles = 0;
|
|
||||||
|
|
||||||
if (!(VU0.VI[REG_VPU_STAT].UL & 1)) return;
|
|
||||||
if(VU0.flags & VUFLAG_MFLAGSET)
|
|
||||||
{
|
{
|
||||||
|
vif0.waitforvu = true;
|
||||||
vif0.vifstalled = true;
|
vif0.vifstalled = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
int _cycles = VU0.cycle;
|
|
||||||
vu0Finish();
|
|
||||||
//DevCon.Warning("VIF0 adding %x cycles", (VU0.cycle - _cycles) * BIAS);
|
|
||||||
g_vif0Cycles += (VU0.cycle - _cycles) * BIAS;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,6 +140,27 @@ __fi void vif0SetupTransfer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__fi void vif0VUFinish()
|
||||||
|
{
|
||||||
|
if ((VU0.VI[REG_VPU_STAT].UL & 1))
|
||||||
|
{
|
||||||
|
int _cycles = VU0.cycle;
|
||||||
|
//DevCon.Warning("Finishing VU0");
|
||||||
|
vu0Finish();
|
||||||
|
_cycles = VU0.cycle - _cycles;
|
||||||
|
//DevCon.Warning("Finishing VU0 %d cycles", _cycles);
|
||||||
|
CPU_INT(VIF_VU0_FINISH, _cycles * BIAS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vif0Regs.stat.VEW = false;
|
||||||
|
if(vif0.waitforvu == true)
|
||||||
|
{
|
||||||
|
vif0.waitforvu = false;
|
||||||
|
ExecuteVU(0);
|
||||||
|
}
|
||||||
|
//DevCon.Warning("VU0 state cleared");
|
||||||
|
}
|
||||||
|
|
||||||
__fi void vif0Interrupt()
|
__fi void vif0Interrupt()
|
||||||
{
|
{
|
||||||
VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle);
|
VIF_LOG("vif0Interrupt: %8.8x", cpuRegs.cycle);
|
||||||
|
@ -190,6 +191,12 @@ __fi void vif0Interrupt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(vif0.waitforvu == true)
|
||||||
|
{
|
||||||
|
//DevCon.Warning("Waiting on VU0");
|
||||||
|
CPU_INT(DMAC_VIF0, 16);
|
||||||
|
return;
|
||||||
|
}
|
||||||
//Must go after the Stall, incase it's still in progress, GTC africa likes to see it still transferring.
|
//Must go after the Stall, incase it's still in progress, GTC africa likes to see it still transferring.
|
||||||
if (vif0.cmd)
|
if (vif0.cmd)
|
||||||
{
|
{
|
||||||
|
@ -250,7 +257,6 @@ void dmaVIF0()
|
||||||
vif0ch.tadr, vif0ch.asr0, vif0ch.asr1);
|
vif0ch.tadr, vif0ch.asr0, vif0ch.asr1);
|
||||||
|
|
||||||
g_vif0Cycles = 0;
|
g_vif0Cycles = 0;
|
||||||
g_vu0Cycles = 0;
|
|
||||||
//if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start! offset %x, Progress %x", vif0.irqoffset, vif0.vifstalled);
|
//if(vif0.irqoffset != 0 && vif0.vifstalled == true) DevCon.Warning("Offset on VIF0 start! offset %x, Progress %x", vif0.irqoffset, vif0.vifstalled);
|
||||||
/*vif0.irqoffset = 0;
|
/*vif0.irqoffset = 0;
|
||||||
vif0.vifstalled = false;
|
vif0.vifstalled = false;
|
||||||
|
|
|
@ -25,27 +25,10 @@ u32 g_vif1Cycles = 0;
|
||||||
|
|
||||||
__fi void vif1FLUSH()
|
__fi void vif1FLUSH()
|
||||||
{
|
{
|
||||||
if(g_packetsizeonvu1 > vif1.vifpacketsize && g_vu1Cycles > 0)
|
if(vif1Regs.stat.VEW == true)
|
||||||
{
|
{
|
||||||
//DevCon.Warning("Adding on same packet");
|
vif1.waitforvu = true;
|
||||||
if( ((g_packetsizeonvu1 - vif1.vifpacketsize) >> 1) > g_vu1Cycles)
|
vif1.vifstalled = true;
|
||||||
g_vu1Cycles -= (g_packetsizeonvu1 - vif1.vifpacketsize) >> 1;
|
|
||||||
else g_vu1Cycles = 0;
|
|
||||||
}
|
|
||||||
if(g_vu1Cycles > 0)
|
|
||||||
{
|
|
||||||
//DevCon.Warning("Adding %x cycles to VIF1", g_vu1Cycles * BIAS);
|
|
||||||
g_vif1Cycles += 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_vif1Cycles += (VU1.cycle - _cycles) * BIAS;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,9 +213,30 @@ __fi void vif1SetupTransfer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__fi void vif1VUFinish()
|
||||||
|
{
|
||||||
|
if (VU0.VI[REG_VPU_STAT].UL & 0x100)
|
||||||
|
{
|
||||||
|
int _cycles = VU1.cycle;
|
||||||
|
//DevCon.Warning("Finishing VU1");
|
||||||
|
vu1Finish();
|
||||||
|
CPU_INT(VIF_VU1_FINISH, (VU1.cycle - _cycles) * BIAS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vif1Regs.stat.VEW = false;
|
||||||
|
if(vif1.waitforvu == true)
|
||||||
|
{
|
||||||
|
vif1.waitforvu = false;
|
||||||
|
ExecuteVU(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//DevCon.Warning("VU1 state cleared");
|
||||||
|
}
|
||||||
|
|
||||||
__fi void vif1Interrupt()
|
__fi void vif1Interrupt()
|
||||||
{
|
{
|
||||||
VIF_LOG("vif1Interrupt: %8.8x", cpuRegs.cycle);
|
VIF_LOG("vif1Interrupt: %8.8x chcr %x, done %x, qwc %x", cpuRegs.cycle, vif1ch.chcr._u32, vif1.done, vif1ch.qwc);
|
||||||
|
|
||||||
g_vif1Cycles = 0;
|
g_vif1Cycles = 0;
|
||||||
|
|
||||||
|
@ -262,6 +266,12 @@ __fi void vif1Interrupt()
|
||||||
//Simulated GS transfer time done, clear the flags
|
//Simulated GS transfer time done, clear the flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(vif1.waitforvu == true)
|
||||||
|
{
|
||||||
|
//DevCon.Warning("Waiting on VU1");
|
||||||
|
CPU_INT(DMAC_VIF1, 16);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!vif1ch.chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);
|
if (!vif1ch.chcr.STR) Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);
|
||||||
|
|
||||||
if (vif1.irq && vif1.tag.size == 0)
|
if (vif1.irq && vif1.tag.size == 0)
|
||||||
|
@ -294,19 +304,7 @@ __fi void vif1Interrupt()
|
||||||
{
|
{
|
||||||
vif1Regs.stat.VPS = VPS_IDLE;
|
vif1Regs.stat.VPS = VPS_IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vif1.inprogress & 0x1)
|
|
||||||
{
|
|
||||||
_VIF1chain();
|
|
||||||
// VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
|
|
||||||
// Timesplitters 2 depends on this beeing a bit higher than 128.
|
|
||||||
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
|
||||||
// Refraction - Removing voodoo timings for now, completely messes a lot of Path3 masked games.
|
|
||||||
/*if (vif1.dmamode == VIF_NORMAL_FROM_MEM_MODE ) CPU_INT(DMAC_VIF1, 1024);
|
|
||||||
else */CPU_INT(DMAC_VIF1, g_vif1Cycles /*VifCycleVoodoo*/);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vif1.done)
|
if (!vif1.done)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -318,9 +316,23 @@ __fi void vif1Interrupt()
|
||||||
|
|
||||||
if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
|
if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer();
|
||||||
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
||||||
CPU_INT(DMAC_VIF1, g_vif1Cycles);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (vif1.inprogress & 0x1)
|
||||||
|
{
|
||||||
|
_VIF1chain();
|
||||||
|
// VIF_NORMAL_FROM_MEM_MODE is a very slow operation.
|
||||||
|
// Timesplitters 2 depends on this being a bit higher than 128.
|
||||||
|
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(g_vif1Cycles > 0 || vif1ch.qwc)
|
||||||
|
{
|
||||||
|
CPU_INT(DMAC_VIF1, max((int)g_vif1Cycles, 8));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if(vif1Regs.stat.VPS == VPS_TRANSFERRING) DevCon.Warning("Cycles %x, cmd %x, qwc %x, waitonvu %x", g_vif1Cycles, vif1.cmd, vif1ch.qwc, vif1.waitforvu);
|
||||||
|
|
||||||
if (vif1.vifstalled && vif1.irq)
|
if (vif1.vifstalled && vif1.irq)
|
||||||
{
|
{
|
||||||
|
@ -344,7 +356,6 @@ __fi void vif1Interrupt()
|
||||||
vif1ch.chcr.STR = false;
|
vif1ch.chcr.STR = false;
|
||||||
vif1.vifstalled = false;
|
vif1.vifstalled = false;
|
||||||
g_vif1Cycles = 0;
|
g_vif1Cycles = 0;
|
||||||
g_vu1Cycles = 0;
|
|
||||||
DMA_LOG("VIF1 DMA End");
|
DMA_LOG("VIF1 DMA End");
|
||||||
hwDmacIrq(DMAC_VIF1);
|
hwDmacIrq(DMAC_VIF1);
|
||||||
|
|
||||||
|
@ -364,7 +375,6 @@ void dmaVIF1()
|
||||||
vif1.vifstalled = false;
|
vif1.vifstalled = false;
|
||||||
vif1.inprogress = 0;*/
|
vif1.inprogress = 0;*/
|
||||||
g_vif1Cycles = 0;
|
g_vif1Cycles = 0;
|
||||||
g_vu1Cycles = 0;
|
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
if (dmacRegs.ctrl.STD == STD_VIF1)
|
if (dmacRegs.ctrl.STD == STD_VIF1)
|
||||||
|
@ -410,7 +420,7 @@ void dmaVIF1()
|
||||||
{
|
{
|
||||||
vif1.dmamode = VIF_CHAIN_MODE;
|
vif1.dmamode = VIF_CHAIN_MODE;
|
||||||
vif1.done = false;
|
vif1.done = false;
|
||||||
vif1.inprogress = 0;
|
vif1.inprogress &= ~0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
|
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);
|
||||||
|
|
|
@ -20,10 +20,6 @@
|
||||||
#include "Vif_Dma.h"
|
#include "Vif_Dma.h"
|
||||||
|
|
||||||
u16 vifqwc = 0;
|
u16 vifqwc = 0;
|
||||||
u32 g_vu0Cycles = 0;
|
|
||||||
u32 g_vu1Cycles = 0;
|
|
||||||
u32 g_packetsizeonvu0 = 0;
|
|
||||||
u32 g_packetsizeonvu1 = 0;
|
|
||||||
|
|
||||||
static u32 qwctag(u32 mask)
|
static u32 qwctag(u32 mask)
|
||||||
{
|
{
|
||||||
|
@ -267,6 +263,12 @@ void vifMFIFOInterrupt()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(vif1.waitforvu == true)
|
||||||
|
{
|
||||||
|
// DevCon.Warning("Waiting on VU1 MFIFO");
|
||||||
|
CPU_INT(DMAC_MFIFO_VIF, 16);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We need to check the direction, if it is downloading from the GS,
|
// We need to check the direction, if it is downloading from the GS,
|
||||||
// we handle that separately (KH2 for testing)
|
// we handle that separately (KH2 for testing)
|
||||||
|
|
|
@ -76,12 +76,28 @@ static __fi void vuExecMicro(int idx, u32 addr) {
|
||||||
if (!idx) vu0ExecMicro(addr);
|
if (!idx) vu0ExecMicro(addr);
|
||||||
else vu1ExecMicro(addr);
|
else vu1ExecMicro(addr);
|
||||||
|
|
||||||
if (!idx || !THREAD_VU1) {
|
if (!idx) { startcycles = ((VU0.cycle-startcycles) + ( vif0ch.qwc - (vif0.vifpacketsize >> 2) )); CPU_INT(VIF_VU0_FINISH, startcycles * BIAS); }
|
||||||
if (!idx) { g_vu0Cycles += (VU0.cycle-startcycles); g_packetsizeonvu0 = vif0.vifpacketsize; }
|
else { startcycles = ((VU1.cycle-startcycles) + ( vif1ch.qwc - (vif1.vifpacketsize >> 2) )); CPU_INT(VIF_VU1_FINISH, startcycles * BIAS); }
|
||||||
else { g_vu1Cycles += (VU1.cycle-startcycles); g_packetsizeonvu1 = vif1.vifpacketsize; }
|
|
||||||
}
|
|
||||||
//DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x, start %x cycle %x", idx, g_vu0Cycles, g_vu1Cycles, startcycles, VU1.cycle);
|
//DevCon.Warning("Ran VU%x, VU0 Cycles %x, VU1 Cycles %x, start %x cycle %x", idx, g_vu0Cycles, g_vu1Cycles, startcycles, VU1.cycle);
|
||||||
GetVifX.vifstalled = true;
|
//GetVifX.vifstalled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecuteVU(int idx)
|
||||||
|
{
|
||||||
|
vifStruct& vifX = GetVifX;
|
||||||
|
|
||||||
|
if((vifX.cmd & 0x7f) == 0x17)
|
||||||
|
{
|
||||||
|
vuExecMicro(idx, -1);
|
||||||
|
vifX.cmd = 0;
|
||||||
|
}
|
||||||
|
else if((vifX.cmd & 0x7f) == 0x14 || (vifX.cmd & 0x7f) == 0x15)
|
||||||
|
{
|
||||||
|
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
||||||
|
vifX.cmd = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -174,14 +190,14 @@ vifOp(vifCode_FlushA) {
|
||||||
//p3.state= GIF_PATH_IDLE; // Does any game need this anymore?
|
//p3.state= GIF_PATH_IDLE; // Does any game need this anymore?
|
||||||
DevCon.Warning("Vif FlushA - path3 has no more data, but didn't EOP");
|
DevCon.Warning("Vif FlushA - path3 has no more data, but didn't EOP");
|
||||||
}
|
}
|
||||||
else { // Path 3 hasn't finished its current gs packet
|
/*else { // Path 3 hasn't finished its current gs packet
|
||||||
if (gifUnit.stat.APATH != 3 && gifUnit.Path3Masked()) {
|
if (gifUnit.stat.APATH != 3 && gifUnit.Path3Masked()) {
|
||||||
gifUnit.stat.APATH = 3; // Hack: Force path 3 to finish (persona 3 needs this)
|
gifUnit.stat.APATH = 3; // Hack: Force path 3 to finish (persona 3 needs this)
|
||||||
//DevCon.Warning("Vif FlushA - Forcing path3 to finish current packet");
|
//DevCon.Warning("Vif FlushA - Forcing path3 to finish current packet");
|
||||||
}
|
}
|
||||||
gifInterrupt(); // Feed path3 some gif dma data
|
gifInterrupt(); // Feed path3 some gif dma data
|
||||||
gifUnit.Execute(); // Execute path3 in-case gifInterrupt() didn't...
|
gifUnit.Execute(); // Execute path3 in-case gifInterrupt() didn't...
|
||||||
}
|
}*/
|
||||||
if (p3.state != GIF_PATH_IDLE) {
|
if (p3.state != GIF_PATH_IDLE) {
|
||||||
doStall = true; // If path3 still isn't finished...
|
doStall = true; // If path3 still isn't finished...
|
||||||
}
|
}
|
||||||
|
@ -245,7 +261,7 @@ vifOp(vifCode_MPG) {
|
||||||
int vifNum = (u8)(vifXRegs.code >> 16);
|
int vifNum = (u8)(vifXRegs.code >> 16);
|
||||||
vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff);
|
vifX.tag.addr = (u16)(vifXRegs.code << 3) & (idx ? 0x3fff : 0xfff);
|
||||||
vifX.tag.size = vifNum ? (vifNum*2) : 512;
|
vifX.tag.size = vifNum ? (vifNum*2) : 512;
|
||||||
//vifFlush(idx);
|
vifFlush(idx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
pass2 {
|
pass2 {
|
||||||
|
@ -275,7 +291,15 @@ vifOp(vifCode_MPG) {
|
||||||
|
|
||||||
vifOp(vifCode_MSCAL) {
|
vifOp(vifCode_MSCAL) {
|
||||||
vifStruct& vifX = GetVifX;
|
vifStruct& vifX = GetVifX;
|
||||||
pass1 { vifFlush(idx); vuExecMicro(idx, (u16)(vifXRegs.code) << 3); vifX.cmd = 0;}
|
pass1 {
|
||||||
|
vifFlush(idx);
|
||||||
|
|
||||||
|
if(vifX.waitforvu == false)
|
||||||
|
{
|
||||||
|
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
||||||
|
vifX.cmd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
pass3 { VifCodeLog("MSCAL"); }
|
pass3 { VifCodeLog("MSCAL"); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -290,7 +314,8 @@ vifOp(vifCode_MSCALF) {
|
||||||
vif1Regs.stat.VGW = true;
|
vif1Regs.stat.VGW = true;
|
||||||
vifX.vifstalled = true;
|
vifX.vifstalled = true;
|
||||||
}
|
}
|
||||||
else {
|
if(vifX.waitforvu == false)
|
||||||
|
{
|
||||||
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
vuExecMicro(idx, (u16)(vifXRegs.code) << 3);
|
||||||
vifX.cmd = 0;
|
vifX.cmd = 0;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +326,14 @@ vifOp(vifCode_MSCALF) {
|
||||||
|
|
||||||
vifOp(vifCode_MSCNT) {
|
vifOp(vifCode_MSCNT) {
|
||||||
vifStruct& vifX = GetVifX;
|
vifStruct& vifX = GetVifX;
|
||||||
pass1 { vifFlush(idx); vuExecMicro(idx, -1); vifX.cmd = 0; }
|
pass1 {
|
||||||
|
vifFlush(idx);
|
||||||
|
if(vifX.waitforvu == false)
|
||||||
|
{
|
||||||
|
vuExecMicro(idx, -1);
|
||||||
|
vifX.cmd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
pass3 { VifCodeLog("MSCNT"); }
|
pass3 { VifCodeLog("MSCNT"); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct vifStruct {
|
||||||
bool done;
|
bool done;
|
||||||
bool vifstalled;
|
bool vifstalled;
|
||||||
bool stallontag;
|
bool stallontag;
|
||||||
|
bool waitforvu;
|
||||||
|
|
||||||
// GS registers used for calculating the size of the last local->host transfer initiated on the GS
|
// GS registers used for calculating the size of the last local->host transfer initiated on the GS
|
||||||
// Transfer size calculation should be restricted to GS emulation in the future
|
// Transfer size calculation should be restricted to GS emulation in the future
|
||||||
|
@ -89,11 +90,13 @@ extern __aligned16 vifStruct vif0, vif1;
|
||||||
|
|
||||||
_vifT extern u32 vifRead32(u32 mem);
|
_vifT extern u32 vifRead32(u32 mem);
|
||||||
_vifT extern bool vifWrite32(u32 mem, u32 value);
|
_vifT extern bool vifWrite32(u32 mem, u32 value);
|
||||||
|
void ExecuteVU(int idx);
|
||||||
extern void vif0Interrupt();
|
extern void vif0Interrupt();
|
||||||
|
extern void vif0VUFinish();
|
||||||
extern void vif0Reset();
|
extern void vif0Reset();
|
||||||
|
|
||||||
extern void vif1Interrupt();
|
extern void vif1Interrupt();
|
||||||
|
extern void vif1VUFinish();
|
||||||
extern void vif1Reset();
|
extern void vif1Reset();
|
||||||
|
|
||||||
typedef int __fastcall FnType_VifCmdHandler(int pass, const u32 *data);
|
typedef int __fastcall FnType_VifCmdHandler(int pass, const u32 *data);
|
||||||
|
@ -119,10 +122,6 @@ static const unsigned int VIF1intc = 5;
|
||||||
|
|
||||||
extern u32 g_vif0Cycles;
|
extern u32 g_vif0Cycles;
|
||||||
extern u32 g_vif1Cycles;
|
extern u32 g_vif1Cycles;
|
||||||
extern u32 g_vu0Cycles;
|
|
||||||
extern u32 g_vu1Cycles;
|
|
||||||
extern u32 g_packetsizeonvu0;
|
|
||||||
extern u32 g_packetsizeonvu1;
|
|
||||||
|
|
||||||
extern void vif0FLUSH();
|
extern void vif0FLUSH();
|
||||||
extern void vif1FLUSH();
|
extern void vif1FLUSH();
|
||||||
|
|
|
@ -122,14 +122,13 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) {
|
||||||
|
|
||||||
transferred += size - vifX.vifpacketsize;
|
transferred += size - vifX.vifpacketsize;
|
||||||
|
|
||||||
if (!idx) {
|
//Make this a minimum of 1 cycle so if it's the end of the packet it doesnt just fall through.
|
||||||
g_packetsizeonvu0 = size;
|
//Metal Saga can do this, just to be safe :)
|
||||||
g_vif0Cycles +=((transferred * BIAS) >> 2) ; /* guessing */
|
if (!idx) g_vif0Cycles += max(1, (int)((transferred * BIAS) >> 2));
|
||||||
}
|
else g_vif1Cycles += max(1, (int)((transferred * BIAS) >> 2));
|
||||||
else {
|
|
||||||
g_packetsizeonvu1 = size;
|
|
||||||
g_vif1Cycles +=((transferred * BIAS) >> 2) ; /* guessing */
|
/*
|
||||||
}
|
|
||||||
if(!idx && g_vu0Cycles > 0) {
|
if(!idx && g_vu0Cycles > 0) {
|
||||||
if (g_vif0Cycles < g_vu0Cycles) g_vu0Cycles -= g_vif0Cycles;
|
if (g_vif0Cycles < g_vu0Cycles) g_vu0Cycles -= g_vif0Cycles;
|
||||||
elif(g_vif0Cycles >= g_vu0Cycles) g_vu0Cycles = 0;
|
elif(g_vif0Cycles >= g_vu0Cycles) g_vu0Cycles = 0;
|
||||||
|
@ -138,7 +137,8 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) {
|
||||||
if (g_vif1Cycles < g_vu1Cycles) g_vu1Cycles -= g_vif1Cycles;
|
if (g_vif1Cycles < g_vu1Cycles) g_vu1Cycles -= g_vif1Cycles;
|
||||||
elif(g_vif1Cycles >= g_vu1Cycles) g_vu1Cycles = 0;
|
elif(g_vif1Cycles >= g_vu1Cycles) g_vu1Cycles = 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
vifX.irqoffset = transferred % 4; // cannot lose the offset
|
vifX.irqoffset = transferred % 4; // cannot lose the offset
|
||||||
|
|
||||||
if (!TTE) {// *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4)
|
if (!TTE) {// *WARNING* - Tags CAN have interrupts! so lets just ignore the dma modifying stuffs (GT4)
|
||||||
|
|
|
@ -79,7 +79,7 @@ void mVUendProgram(mV, microFlagCycles* mFC, int isEbit) {
|
||||||
if (isEbit || isVU1) { // Clear 'is busy' Flags
|
if (isEbit || isVU1) { // Clear 'is busy' Flags
|
||||||
if (!mVU.index || !THREAD_VU1) {
|
if (!mVU.index || !THREAD_VU1) {
|
||||||
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
xAND(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? ~0x100 : ~0x001)); // VBS0/VBS1 flag
|
||||||
xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
|
//xAND(ptr32[&mVU.getVifRegs().stat], ~VIF1_STAT_VEW); // Clear VU 'is busy' signal for vif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,8 @@ INTERPRETATE_COP2_FUNC(CALLMSR);
|
||||||
void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) {
|
void _setupBranchTest(u32*(jmpType)(u32), bool isLikely) {
|
||||||
printCOP2("COP2 Branch");
|
printCOP2("COP2 Branch");
|
||||||
_eeFlushAllUnused();
|
_eeFlushAllUnused();
|
||||||
TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100);
|
TEST32ItoM((uptr)&vif1Regs.stat._u32, 0x4);
|
||||||
|
//TEST32ItoM((uptr)&VU0.VI[REG_VPU_STAT].UL, 0x100);
|
||||||
recDoBranchImm(jmpType(0), isLikely);
|
recDoBranchImm(jmpType(0), isLikely);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2721,7 +2721,7 @@ static void SuperVURecompile()
|
||||||
pxAssert(pchild->blocks.size() == 0);
|
pxAssert(pchild->blocks.size() == 0);
|
||||||
|
|
||||||
AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag
|
AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag
|
||||||
AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW);
|
//AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW);
|
||||||
|
|
||||||
MOV32ItoM((uptr)&VU->VI[REG_TPC], pchild->endpc);
|
MOV32ItoM((uptr)&VU->VI[REG_TPC], pchild->endpc);
|
||||||
JMP32((uptr)SuperVUEndProgram - ((uptr)x86Ptr + 5));
|
JMP32((uptr)SuperVUEndProgram - ((uptr)x86Ptr + 5));
|
||||||
|
@ -2994,7 +2994,7 @@ void VuBaseBlock::Recompile()
|
||||||
_freeXMMregs();
|
_freeXMMregs();
|
||||||
_freeX86regs();
|
_freeX86regs();
|
||||||
AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag
|
AND32ItoM((uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu ? ~0x100 : ~0x001); // E flag
|
||||||
AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW);
|
//AND32ItoM((uptr)&VU->GetVifRegs().stat, ~VIF1_STAT_VEW);
|
||||||
|
|
||||||
if (!branch) MOV32ItoM((uptr)&VU->VI[REG_TPC], endpc);
|
if (!branch) MOV32ItoM((uptr)&VU->VI[REG_TPC], endpc);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue