diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index 8b06f48617..b64b877c84 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -58,6 +58,8 @@ static Event *eventPool = 0; // Downcount has been moved to currentMIPS, to save a couple of clocks in every ARM JIT block // as we can already reach that structure through a register. int slicelength; +// How much of the current slice the other CPUs have already run (CatchUpOtherCPUs). +static int otherCPUsRan = 0; alignas(16) static s64 globalTimer; static s64 idledCycles; @@ -218,6 +220,7 @@ void UnregisterAllEvents() { void Init(MIPSState *mips) { mips->downcount = INITIAL_SLICE_LENGTH; slicelength = INITIAL_SLICE_LENGTH; + otherCPUsRan = 0; globalTimer = 0; idledCycles = 0; lastGlobalTimeTicks = 0; @@ -417,7 +420,16 @@ void ProcessEvents() { // The Media Engine catches up with the main CPU. static void RunOtherCPUs(int cycles) { if (MeCore::g_meState) { - MeCore::RunFor(cycles); + MeCore::RunFor(cycles - otherCPUsRan); + } + otherCPUsRan = 0; +} + +void CatchUpOtherCPUs(MIPSState *mips) { + const int ran = slicelength - mips->downcount; + if (MeCore::g_meState && ran > otherCPUsRan) { + MeCore::RunFor(ran - otherCPUsRan); + otherCPUsRan = ran; } } @@ -553,6 +565,8 @@ void DoState(PointerWrap &p) { auto s = p.Section("CoreTiming", 1, 3); if (!s) return; + // States are saved between slices. + otherCPUsRan = 0; int n = (int)event_types.size(); int current = n; diff --git a/Core/CoreTiming.h b/Core/CoreTiming.h index bc52e6cc38..0a4cf2870c 100644 --- a/Core/CoreTiming.h +++ b/Core/CoreTiming.h @@ -127,6 +127,9 @@ namespace CoreTiming { bool IsScheduled(int event_type); void Advance(MIPSState *mips); void ForceCheck(MIPSState *mips); + // Runs the other CPUs (the Media Engine) up to where this one is in the slice, as they otherwise + // run at its end: for when this one looks at what they share, such as the boot page. + void CatchUpOtherCPUs(MIPSState *mips); // Pretend that the main CPU has executed enough cycles to reach the next event. void Idle(MIPSState *mips, int maxIdle = 0); diff --git a/Core/HW/MMIO.cpp b/Core/HW/MMIO.cpp index 0aeb93e564..5e3dfa451d 100644 --- a/Core/HW/MMIO.cpp +++ b/Core/HW/MMIO.cpp @@ -21,6 +21,7 @@ #include "Common/Log.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" +#include "Core/CoreTiming.h" #include "Core/HW/GpioMMIO.h" #include "Core/HW/MMIO.h" #include "Core/HW/MeMMIO.h" @@ -37,6 +38,9 @@ public: bool Read(MIPSState *mips, u32 offset, int size, u32 *value) override { if (offset + size > Memory::BOOT_PAGE_SIZE) return false; + // What the ME has written by now: a main CPU polling a mailbox here sees it as on a PSP. + if (mips == currentMIPS) + CoreTiming::CatchUpOtherCPUs(mips); const u8 *ptr = Memory::GetBootPage() + offset; switch (size) { case 1: *value = *ptr; break;