EE/DMA: Try to avoid very small DMA loops

This commit is contained in:
refractionpcsx2 2023-06-30 15:40:14 +01:00
parent c1c6bde429
commit 7d8d16091e
3 changed files with 70 additions and 32 deletions

View File

@ -54,6 +54,7 @@ R5900cpu *Cpu = NULL;
static const uint eeWaitCycles = 3072; static const uint eeWaitCycles = 3072;
bool eeEventTestIsActive = false; bool eeEventTestIsActive = false;
EE_intProcessStatus eeRunInterruptScan = INT_NOT_RUNNING;
u32 g_eeloadMain = 0, g_eeloadExec = 0, g_osdsys_str = 0; u32 g_eeloadMain = 0, g_eeloadExec = 0, g_osdsys_str = 0;
@ -277,6 +278,11 @@ static __fi bool _cpuTestInterrupts()
//Console.Write("DMAC Disabled or suspended"); //Console.Write("DMAC Disabled or suspended");
return false; return false;
} }
eeRunInterruptScan = INT_RUNNING;
while (eeRunInterruptScan == INT_RUNNING)
{
/* These are 'pcsx2 interrupts', they handle asynchronous stuff /* These are 'pcsx2 interrupts', they handle asynchronous stuff
that depends on the cycle timings */ that depends on the cycle timings */
TESTINT(VU_MTVU_BUSY, MTVUInterrupt); TESTINT(VU_MTVU_BUSY, MTVUInterrupt);
@ -308,6 +314,14 @@ static __fi bool _cpuTestInterrupts()
TESTINT(VIF_VU1_FINISH, vif1VUFinish); TESTINT(VIF_VU1_FINISH, vif1VUFinish);
} }
if (eeRunInterruptScan == INT_REQ_LOOP)
eeRunInterruptScan = INT_RUNNING;
else
break;
}
eeRunInterruptScan = INT_NOT_RUNNING;
if ((cpuRegs.interrupt & 0x1FFFF) & ~cpuRegs.dmastall) if ((cpuRegs.interrupt & 0x1FFFF) & ~cpuRegs.dmastall)
return true; return true;
else else
@ -391,6 +405,8 @@ __fi void _cpuEventTest_Shared()
// These are basically just DMAC-related events, which also piggy-back the same bits as // These are basically just DMAC-related events, which also piggy-back the same bits as
// the PS2's own DMA channel IRQs and IRQ Masks. // the PS2's own DMA channel IRQs and IRQ Masks.
if (cpuRegs.interrupt)
{
// This is a BIOS hack because the coding in the BIOS is terrible but the bug is masked by Data Cache // This is a BIOS hack because the coding in the BIOS is terrible but the bug is masked by Data Cache
// where a DMA buffer is overwritten without waiting for the transfer to end, which causes the fonts to get all messed up // where a DMA buffer is overwritten without waiting for the transfer to end, which causes the fonts to get all messed up
// so to fix it, we run all the DMA's instantly when in the BIOS. // so to fix it, we run all the DMA's instantly when in the BIOS.
@ -402,6 +418,7 @@ __fi void _cpuEventTest_Shared()
} }
else else
_cpuTestInterrupts(); _cpuTestInterrupts();
}
// ---- IOP ------------- // ---- IOP -------------
// * It's important to run a iopEventTest before calling ExecuteBlock. This // * It's important to run a iopEventTest before calling ExecuteBlock. This
@ -523,6 +540,17 @@ __fi void CPU_SET_DMASTALL(EE_EventType n, bool set)
__fi void CPU_INT( EE_EventType n, s32 ecycle) __fi void CPU_INT( EE_EventType n, s32 ecycle)
{ {
// If it's retunning too quick, just rerun the DMA, there's no point in running the EE for < 4 cycles.
// This causes a huge uplift in performance for ONI FMV's.
if (ecycle < 4 && !(cpuRegs.dmastall & (1 << n)) && eeRunInterruptScan != INT_NOT_RUNNING)
{
eeRunInterruptScan = INT_REQ_LOOP;
cpuRegs.interrupt |= 1 << n;
cpuRegs.sCycle[n] = cpuRegs.cycle;
cpuRegs.eCycle[n] = 0;
return;
}
// EE events happen 8 cycles in the future instead of whatever was requested. // EE events happen 8 cycles in the future instead of whatever was requested.
// This can be used on games with PATH3 masking issues for example, or when // This can be used on games with PATH3 masking issues for example, or when
// some FMV look bad. // some FMV look bad.

View File

@ -333,6 +333,13 @@ extern R5900cpu *Cpu;
extern R5900cpu intCpu; extern R5900cpu intCpu;
extern R5900cpu recCpu; extern R5900cpu recCpu;
enum EE_intProcessStatus
{
INT_NOT_RUNNING = 0,
INT_RUNNING,
INT_REQ_LOOP
};
enum EE_EventType enum EE_EventType
{ {
DMAC_VIF0 = 0, DMAC_VIF0 = 0,

View File

@ -341,7 +341,10 @@ __fi void vif1Interrupt()
} }
if (!vif1ch.chcr.STR) if (!vif1ch.chcr.STR)
{
Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32); Console.WriteLn("Vif1 running when CHCR == %x", vif1ch.chcr._u32);
return;
}
if (vif1.irq && vif1.vifstalled.enabled && vif1.vifstalled.value == VIF_IRQ_STALL) if (vif1.irq && vif1.vifstalled.enabled && vif1.vifstalled.value == VIF_IRQ_STALL)
{ {