diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index 3659d4fb80..da7f89b1be 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -417,6 +417,11 @@ bool CoreTimingManager::GetVISkip() const return m_throttle_disable_vi_int && g_ActiveConfig.bVISkip && !Core::WantsDeterminism(); } +bool CoreTimingManager::UseSyncOnSkipIdle() const +{ + return m_config_sync_on_skip_idle; +} + void CoreTimingManager::LogPendingEvents() const { auto clone = m_event_queue; diff --git a/Source/Core/Core/CoreTiming.h b/Source/Core/Core/CoreTiming.h index 1ddb13f948..525b7e8913 100644 --- a/Source/Core/Core/CoreTiming.h +++ b/Source/Core/Core/CoreTiming.h @@ -150,6 +150,8 @@ public: TimePoint GetCPUTimePoint(s64 cyclesLate) const; // Used by Dolphin Analytics bool GetVISkip() const; // Used By VideoInterface + bool UseSyncOnSkipIdle() const; + private: Globals m_globals; diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index 3174c2983a..70682941df 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -12,6 +12,7 @@ #include "Common/CommonTypes.h" #include "Common/Flag.h" #include "Common/Logging/Log.h" +#include "Common/MsgHandler.h" #include "Core/ConfigManager.h" #include "Core/CoreTiming.h" #include "Core/HW/GPFifo.h" @@ -695,16 +696,50 @@ void CommandProcessorManager::HandleUnknownOpcode(Core::System& system, u8 cmd_b { m_is_fifo_error_seen = true; - // TODO(Omega): Maybe dump FIFO to file on this error + // The panic alert contains an explanatory part that's worded differently depending on the + // user's settings, so as to offer the most relevant advice to the user. + const char* advice; + if (IsOnThread(system) && !system.GetFifo().UseDeterministicGPUThread()) + { + if (!system.GetCoreTiming().UseSyncOnSkipIdle() && !system.GetFifo().UseSyncGPU()) + { +// The SyncOnSkipIdle setting is only in the Android GUI, so we use the INI name on other platforms. +// +// TODO: Mark the Android string as translatable once we have translations on Android. It's +// currently untranslatable so translators won't try to look up how they translated "Synchronize +// GPU Thread" and "On Idle Skipping" and then not find those strings and become confused. +#ifdef ANDROID + advice = "Please change the \"Synchronize GPU Thread\" setting to \"On Idle Skipping\"! " + "It's currently set to \"Never\", which makes this problem very likely to happen."; +#else + // i18n: Please leave SyncOnSkipIdle and True untranslated. + // The user needs to enter these terms as-is in an INI file. + advice = _trans("Please change the \"SyncOnSkipIdle\" setting to \"True\"! " + "It's currently disabled, which makes this problem very likely to happen."); +#endif + } + else + { + advice = _trans( + "This error is usually caused by the emulated GPU desyncing with the emulated CPU. " + "Turn off the \"Dual Core\" setting to avoid this."); + } + } + else + { + advice = _trans( + "This error is usually caused by the emulated GPU desyncing with the emulated CPU, " + "but your current settings make this unlikely to happen. If this error is stopping the " + "game from working, please report it to the developers."); + } + PanicAlertFmtT("GFX FIFO: Unknown Opcode ({0:#04x} @ {1}, preprocess={2}).\n" - "This means one of the following:\n" - "* The emulated GPU got desynced, disabling dual core can help\n" - "* Command stream corrupted by some spurious memory bug\n" - "* This really is an unknown opcode (unlikely)\n" - "* Some other sort of bug\n\n" - "Further errors will be sent to the Video Backend log and\n" + "\n" + "{3}\n" + "\n" + "Further errors will be sent to the Video Backend log and " "Dolphin will now likely crash or hang.", - cmd_byte, fmt::ptr(buffer), preprocess); + cmd_byte, fmt::ptr(buffer), preprocess, Common::GetStringT(advice)); } } diff --git a/Source/Core/VideoCommon/Fifo.h b/Source/Core/VideoCommon/Fifo.h index 1db91eeb91..20648562b4 100644 --- a/Source/Core/VideoCommon/Fifo.h +++ b/Source/Core/VideoCommon/Fifo.h @@ -54,6 +54,7 @@ public: void PauseAndLock(Core::System& system, bool doLock, bool unpauseOnUnlock); void UpdateWantDeterminism(Core::System& system, bool want); bool UseDeterministicGPUThread() const { return m_use_deterministic_gpu_thread; } + bool UseSyncGPU() const { return m_config_sync_gpu; } // In deterministic GPU thread mode this waits for the GPU to be done with pending work. void SyncGPU(SyncGPUReason reason, bool may_move_read_ptr = true);