diff --git a/src/ARM.cpp b/src/ARM.cpp index ed3780b0..1d552889 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -161,6 +161,7 @@ void ARM::Reset() DataCycles = 0; IRQ = 0; + IRQTimestamp = -1; for (int i = 0; i < 16; i++) R[i] = 0; @@ -705,7 +706,7 @@ void ARMv5::StartExecTHUMB() else NullFetch = false; PC = R[15]; - if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); + if ((NDS.ARM9Timestamp >= IRQTimestamp) && !(CPSR & 0x80)) TriggerIRQ(); else if (CurInstr > 0xFFFFFFFF) [[unlikely]] // handle aborted instructions { PrefetchAbort(); @@ -728,7 +729,7 @@ void ARMv5::StartExecARM() NullFetch = false; PC = R[15]; - if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); + if ((NDS.ARM9Timestamp >= IRQTimestamp) && !(CPSR & 0x80)) TriggerIRQ(); else if (CurInstr & ((u64)1<<63)) [[unlikely]] // handle aborted instructions { PrefetchAbort(); @@ -775,9 +776,9 @@ void ARMv5::Execute() { #ifdef JIT_ENABLED if constexpr (mode == CPUExecuteMode::JIT) TriggerIRQ(); - else + //else #endif - IRQ = 1; + //IRQ = 1; } } else @@ -921,7 +922,7 @@ void ARMv4::StartExecTHUMB() CodeRead16(R[15]); QueueFunction(&ARMv4::UpdateNextInstr1); - if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); + if ((NDS.ARM7Timestamp >= IRQTimestamp) && !(CPSR & 0x80)) TriggerIRQ(); else { // actually execute @@ -939,7 +940,7 @@ void ARMv4::StartExecARM() CodeRead32(R[15]); QueueFunction(&ARMv4::UpdateNextInstr1); - if (IRQ && !(CPSR & 0x80)) TriggerIRQ(); + if ((NDS.ARM7Timestamp >= IRQTimestamp) && !(CPSR & 0x80)) TriggerIRQ(); else if (CheckCondition(CurInstr >> 28)) // actually execute { u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); @@ -968,9 +969,9 @@ void ARMv4::Execute() { #ifdef JIT_ENABLED if constexpr (mode == CPUExecuteMode::JIT) TriggerIRQ(); - else + //else #endif - IRQ = 1; + //IRQ = 1; } } else diff --git a/src/ARM.h b/src/ARM.h index 49030d78..dfc81ff1 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -255,6 +255,8 @@ public: u8 abt; u64 iter; + u64 IRQTimestamp; + u8 FuncQueueFill; u8 FuncQueueEnd; u8 FuncQueueProg; diff --git a/src/DSi.cpp b/src/DSi.cpp index 195b6588..4b97dc12 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -1288,6 +1288,7 @@ void DSi::Set_SCFG_Clock9(u16 val) } ARM9.TimestampMemory >>= ARM9ClockShift; ARM9.ITCMTimestamp >>= ARM9ClockShift; + ARM9.IRQTimestamp >>= ARM9ClockShift; ARM9.WBTimestamp >>= ARM9ClockShift; ARM9.WBDelay >>= ARM9ClockShift; ARM9.WBReleaseTS >>= ARM9ClockShift; @@ -1311,6 +1312,7 @@ void DSi::Set_SCFG_Clock9(u16 val) } ARM9.TimestampMemory <<= ARM9ClockShift; ARM9.ITCMTimestamp <<= ARM9ClockShift; + ARM9.IRQTimestamp <<= ARM9ClockShift; ARM9.WBTimestamp <<= ARM9ClockShift; ARM9.WBDelay <<= ARM9ClockShift; ARM9.WBReleaseTS <<= ARM9ClockShift; diff --git a/src/NDS.cpp b/src/NDS.cpp index 37b31453..7918b5d5 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1851,6 +1851,7 @@ u32 NDS::RunFrame() } } + CurCPU = 2; RunSystem(ARM7Target); if (CPUStop & CPUStop_Sleep) @@ -2170,17 +2171,48 @@ void NDS::SetGBASlotTimings() void NDS::UpdateIRQ(u32 cpu) { ARM& arm = cpu ? (ARM&)ARM7 : (ARM&)ARM9; + u64 time; - if (IME[cpu] & 0x1) + if (CurCPU == 0) { - arm.IRQ = !!(IE[cpu] & IF[cpu]); - if ((ConsoleType == 1) && cpu) - arm.IRQ |= !!(IE2 & IF2); + time = (std::max(ARM9Timestamp, DMA9Timestamp) >> ARM9ClockShift) + 4; + } + else if (CurCPU == 1) + { + time = ARM7Timestamp + 4; } else { - arm.IRQ = 0; + time = SysTimestamp + 4; } + + if (IME[cpu] & 0x1) + { + /*arm.IRQ = !!(IE[cpu] & IF[cpu]); + if ((ConsoleType == 1) && cpu) + arm.IRQ |= !!(IE2 & IF2);*/ + + { + if ((IE[cpu] & IF[cpu])) + { + if (time < arm.IRQTimestamp) arm.IRQTimestamp = time; + } + else if (((ConsoleType == 1) && cpu) && (IE2 & IF2)) + { + if (time < arm.IRQTimestamp) arm.IRQTimestamp = time; + } + else + { + arm.IRQTimestamp = UINT64_MAX; + } + } + } + else + { + arm.IRQTimestamp = UINT64_MAX; + } + + if (cpu == 0) arm.IRQTimestamp <<= ARM9ClockShift; } void NDS::SetIRQ(u32 cpu, u32 irq)