diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 8e832d8e28..2ab2146c06 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -74,7 +74,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -constexpr u32 STATE_VERSION = 130; // Last changed in PR 9545 +constexpr u32 STATE_VERSION = 131; // Last changed in PR 9773 // Maps savestate versions to Dolphin versions. // Versions after 42 don't need to be added to this list, diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 8754152fe9..810cb4e129 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -445,11 +445,8 @@ static void BPWritten(const BPCmd& bp) const u8 offset = bp.address & 2; BoundingBox::Enable(); - if (g_ActiveConfig.backend_info.bSupportsBBox && g_ActiveConfig.bBBoxEnable) - { - g_renderer->BBoxWrite(offset, bp.newvalue & 0x3ff); - g_renderer->BBoxWrite(offset + 1, bp.newvalue >> 10); - } + g_renderer->BBoxWrite(offset, bp.newvalue & 0x3ff); + g_renderer->BBoxWrite(offset + 1, bp.newvalue >> 10); } return; case BPMEM_TEXINVALIDATE: diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index f93d498fc6..5422d26e94 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -187,11 +187,20 @@ void Renderer::ReinterpretPixelData(EFBReinterpretType convtype) u16 Renderer::BBoxRead(int index) { + if (!g_ActiveConfig.bBBoxEnable || !g_ActiveConfig.backend_info.bSupportsBBox) + return m_bounding_box_fallback[index]; + return BBoxReadImpl(index); } void Renderer::BBoxWrite(int index, u16 value) { + if (!g_ActiveConfig.bBBoxEnable || !g_ActiveConfig.backend_info.bSupportsBBox) + { + m_bounding_box_fallback[index] = value; + return; + } + BBoxWriteImpl(index, value); } @@ -1748,6 +1757,7 @@ void Renderer::DoState(PointerWrap& p) p.Do(m_last_xfb_width); p.Do(m_last_xfb_stride); p.Do(m_last_xfb_height); + p.DoArray(m_bounding_box_fallback); if (p.GetMode() == PointerWrap::MODE_READ) { diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 1deedd4f76..e07fbbc5fd 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -394,6 +394,18 @@ private: u32 m_last_xfb_stride = 0; u32 m_last_xfb_height = 0; + // Nintendo's SDK seems to write "default" bounding box values before every draw (1023 0 1023 0 + // are the only values encountered so far, which happen to be the extents allowed by the BP + // registers) to reset the registers for comparison in the pixel engine, and presumably to detect + // whether GX has updated the registers with real values. + // + // We can store these values when Bounding Box emulation is disabled and return them on read, + // which the game will interpret as "no pixels have been drawn" + // + // This produces much better results than just returning garbage, which can cause games like + // Ultimate Spider-Man to crash + std::array m_bounding_box_fallback = {}; + // NOTE: The methods below are called on the framedumping thread. void FrameDumpThreadFunc(); bool StartFrameDumpToFFMPEG(const FrameDump::FrameData&); diff --git a/Source/Core/VideoCommon/VideoBackendBase.cpp b/Source/Core/VideoCommon/VideoBackendBase.cpp index 2f7e92664a..f38601dcd7 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.cpp +++ b/Source/Core/VideoCommon/VideoBackendBase.cpp @@ -168,10 +168,8 @@ u16 VideoBackendBase::Video_GetBoundingBox(int index) "for this game."); } warn_once = false; - return 0; } - - if (!g_ActiveConfig.backend_info.bSupportsBBox) + else if (!g_ActiveConfig.backend_info.bSupportsBBox) { static bool warn_once = true; if (warn_once) @@ -182,7 +180,6 @@ u16 VideoBackendBase::Video_GetBoundingBox(int index) "freezes while running this game."); } warn_once = false; - return 0; } Fifo::SyncGPU(Fifo::SyncGPUReason::BBox);