summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-03-28 18:43:57 -0400
committerGitHub <noreply@github.com>2025-03-28 18:43:57 -0400
commit932b4abdcfab9bbef0583f2d820b0139afa94221 (patch)
tree18f0567f7d2414386d74dc60ffcc6cdddd95e2dc /Source/Core
parent7d794897c4043b9ee8b278340cfeff02923512f4 (diff)
parente351f03cdf9371f63423fdda1ff168e0daff6966 (diff)
Merge pull request #13457 from jordan-woyak/efb-access-fix
VideoCommon: Fix out-of-bounds and disabled EFB access.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/MMU.cpp22
-rw-r--r--Source/Core/VideoBackends/Null/NullGfx.cpp2
-rw-r--r--Source/Core/VideoBackends/Null/NullGfx.h2
-rw-r--r--Source/Core/VideoBackends/Software/SWEfbInterface.cpp2
-rw-r--r--Source/Core/VideoBackends/Software/SWEfbInterface.h2
-rw-r--r--Source/Core/VideoCommon/EFBInterface.cpp47
-rw-r--r--Source/Core/VideoCommon/EFBInterface.h7
7 files changed, 55 insertions, 29 deletions
diff --git a/Source/Core/Core/PowerPC/MMU.cpp b/Source/Core/Core/PowerPC/MMU.cpp
index a9fd5ede4b..58f668d006 100644
--- a/Source/Core/Core/PowerPC/MMU.cpp
+++ b/Source/Core/Core/PowerPC/MMU.cpp
@@ -47,9 +47,7 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
-#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/EFBInterface.h"
-#include "VideoCommon/Statistics.h"
namespace PowerPC
{
@@ -111,18 +109,12 @@ static u32 EFB_Read(const u32 addr)
}
else if (addr & 0x00400000)
{
- var = AsyncRequests::GetInstance()->PushBlockingEvent([&] {
- INCSTAT(g_stats.this_frame.num_efb_peeks);
- return g_efb_interface->PeekDepth(x, y);
- });
+ var = g_efb_interface->PeekDepth(x, y);
DEBUG_LOG_FMT(MEMMAP, "EFB Z Read @ {}, {}\t= {:#010x}", x, y, var);
}
else
{
- var = AsyncRequests::GetInstance()->PushBlockingEvent([&] {
- INCSTAT(g_stats.this_frame.num_efb_peeks);
- return g_efb_interface->PeekColor(x, y);
- });
+ var = g_efb_interface->PeekColor(x, y);
DEBUG_LOG_FMT(MEMMAP, "EFB Color Read @ {}, {}\t= {:#010x}", x, y, var);
}
@@ -142,18 +134,12 @@ static void EFB_Write(u32 data, u32 addr)
}
else if (addr & 0x00400000)
{
- AsyncRequests::GetInstance()->PushEvent([x, y, data] {
- INCSTAT(g_stats.this_frame.num_efb_pokes);
- g_efb_interface->PokeDepth(x, y, data);
- });
+ g_efb_interface->PokeDepth(x, y, data);
DEBUG_LOG_FMT(MEMMAP, "EFB Z Write {:08x} @ {}, {}", data, x, y);
}
else
{
- AsyncRequests::GetInstance()->PushEvent([x, y, data] {
- INCSTAT(g_stats.this_frame.num_efb_pokes);
- g_efb_interface->PokeColor(x, y, data);
- });
+ g_efb_interface->PokeColor(x, y, data);
DEBUG_LOG_FMT(MEMMAP, "EFB Color Write {:08x} @ {}, {}", data, x, y);
}
}
diff --git a/Source/Core/VideoBackends/Null/NullGfx.cpp b/Source/Core/VideoBackends/Null/NullGfx.cpp
index ab60339d0b..61822d3c83 100644
--- a/Source/Core/VideoBackends/Null/NullGfx.cpp
+++ b/Source/Core/VideoBackends/Null/NullGfx.cpp
@@ -108,7 +108,7 @@ u32 NullEFBInterface::PeekColorInternal(u16 x, u16 y)
return 0;
}
-u32 NullEFBInterface::PeekDepth(u16 x, u16 y)
+u32 NullEFBInterface::PeekDepthInternal(u16 x, u16 y)
{
return 0;
}
diff --git a/Source/Core/VideoBackends/Null/NullGfx.h b/Source/Core/VideoBackends/Null/NullGfx.h
index 43d20a45a2..a84b3743d4 100644
--- a/Source/Core/VideoBackends/Null/NullGfx.h
+++ b/Source/Core/VideoBackends/Null/NullGfx.h
@@ -46,7 +46,7 @@ class NullEFBInterface final : public EFBInterfaceBase
void PokeDepth(u16 x, u16 y, u32 depth) override;
u32 PeekColorInternal(u16 x, u16 y) override;
- u32 PeekDepth(u16 x, u16 y) override;
+ u32 PeekDepthInternal(u16 x, u16 y) override;
};
} // namespace Null
diff --git a/Source/Core/VideoBackends/Software/SWEfbInterface.cpp b/Source/Core/VideoBackends/Software/SWEfbInterface.cpp
index d269e8435a..1bfc00b938 100644
--- a/Source/Core/VideoBackends/Software/SWEfbInterface.cpp
+++ b/Source/Core/VideoBackends/Software/SWEfbInterface.cpp
@@ -742,7 +742,7 @@ u32 SWEFBInterface::PeekColorInternal(u16 x, u16 y)
return value;
}
-u32 SWEFBInterface::PeekDepth(u16 x, u16 y)
+u32 SWEFBInterface::PeekDepthInternal(u16 x, u16 y)
{
return EfbInterface::GetDepth(x, y);
}
diff --git a/Source/Core/VideoBackends/Software/SWEfbInterface.h b/Source/Core/VideoBackends/Software/SWEfbInterface.h
index 5f866ad227..1182d3b5e0 100644
--- a/Source/Core/VideoBackends/Software/SWEfbInterface.h
+++ b/Source/Core/VideoBackends/Software/SWEfbInterface.h
@@ -69,6 +69,6 @@ class SWEFBInterface final : public EFBInterfaceBase
void PokeDepth(u16 x, u16 y, u32 depth) override;
u32 PeekColorInternal(u16 x, u16 y) override;
- u32 PeekDepth(u16 x, u16 y) override;
+ u32 PeekDepthInternal(u16 x, u16 y) override;
};
} // namespace SW
diff --git a/Source/Core/VideoCommon/EFBInterface.cpp b/Source/Core/VideoCommon/EFBInterface.cpp
index 9b88a58d0d..6ce256ff47 100644
--- a/Source/Core/VideoCommon/EFBInterface.cpp
+++ b/Source/Core/VideoCommon/EFBInterface.cpp
@@ -14,8 +14,10 @@
#include "Core/ConfigManager.h"
#include "Core/System.h"
+#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/FramebufferManager.h"
#include "VideoCommon/PixelEngine.h"
+#include "VideoCommon/Statistics.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
@@ -24,6 +26,11 @@ std::unique_ptr<EFBInterfaceBase> g_efb_interface;
EFBInterfaceBase::~EFBInterfaceBase() = default;
+bool EFBInterfaceBase::ShouldSkipAccess(u16 x, u16 y) const
+{
+ return !g_ActiveConfig.bEFBAccessEnable || x >= EFB_WIDTH || y >= EFB_HEIGHT;
+}
+
void HardwareEFBInterface::ReinterpretPixelData(EFBReinterpretType convtype)
{
g_framebuffer_manager->ReinterpretPixelData(convtype);
@@ -31,7 +38,10 @@ void HardwareEFBInterface::ReinterpretPixelData(EFBReinterpretType convtype)
u32 HardwareEFBInterface::PeekColorInternal(u16 x, u16 y)
{
- u32 color = g_framebuffer_manager->PeekEFBColor(x, y);
+ u32 color = AsyncRequests::GetInstance()->PushBlockingEvent([&] {
+ INCSTAT(g_stats.this_frame.num_efb_peeks);
+ return g_framebuffer_manager->PeekEFBColor(x, y);
+ });
// a little-endian value is expected to be returned
color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000));
@@ -54,6 +64,9 @@ u32 HardwareEFBInterface::PeekColorInternal(u16 x, u16 y)
u32 EFBInterfaceBase::PeekColor(u16 x, u16 y)
{
+ if (ShouldSkipAccess(x, y))
+ return 0;
+
u32 color = PeekColorInternal(x, y);
// check what to do with the alpha channel (GX_PokeAlphaRead)
@@ -78,10 +91,14 @@ u32 EFBInterfaceBase::PeekColor(u16 x, u16 y)
}
}
-u32 HardwareEFBInterface::PeekDepth(u16 x, u16 y)
+u32 HardwareEFBInterface::PeekDepthInternal(u16 x, u16 y)
{
+ float depth = AsyncRequests::GetInstance()->PushBlockingEvent([&] {
+ INCSTAT(g_stats.this_frame.num_efb_peeks);
+ return g_framebuffer_manager->PeekEFBDepth(x, y);
+ });
+
// Depth buffer is inverted for improved precision near far plane
- float depth = g_framebuffer_manager->PeekEFBDepth(x, y);
if (!g_backend_info.bSupportsReversedDepthRange)
depth = 1.0f - depth;
@@ -105,22 +122,42 @@ u32 HardwareEFBInterface::PeekDepth(u16 x, u16 y)
return z24depth;
}
+u32 EFBInterfaceBase::PeekDepth(u16 x, u16 y)
+{
+ if (ShouldSkipAccess(x, y))
+ return 0;
+
+ return PeekDepthInternal(x, y);
+}
+
void HardwareEFBInterface::PokeColor(u16 x, u16 y, u32 poke_data)
{
+ if (ShouldSkipAccess(x, y))
+ return;
+
// Convert to expected format (BGRA->RGBA)
// TODO: Check alpha, depending on mode?
const u32 color =
((poke_data & 0xFF00FF00) | ((poke_data >> 16) & 0xFF) | ((poke_data << 16) & 0xFF0000));
- g_framebuffer_manager->PokeEFBColor(x, y, color);
+ AsyncRequests::GetInstance()->PushEvent([x, y, color] {
+ INCSTAT(g_stats.this_frame.num_efb_pokes);
+ g_framebuffer_manager->PokeEFBColor(x, y, color);
+ });
}
void HardwareEFBInterface::PokeDepth(u16 x, u16 y, u32 poke_data)
{
+ if (ShouldSkipAccess(x, y))
+ return;
+
// Convert to floating-point depth.
float depth = float(poke_data & 0xFFFFFF) / 16777216.0f;
if (!g_backend_info.bSupportsReversedDepthRange)
depth = 1.0f - depth;
- g_framebuffer_manager->PokeEFBDepth(x, y, depth);
+ AsyncRequests::GetInstance()->PushEvent([x, y, depth] {
+ INCSTAT(g_stats.this_frame.num_efb_pokes);
+ g_framebuffer_manager->PokeEFBDepth(x, y, depth);
+ });
}
diff --git a/Source/Core/VideoCommon/EFBInterface.h b/Source/Core/VideoCommon/EFBInterface.h
index a3ee947dd9..414b84c436 100644
--- a/Source/Core/VideoCommon/EFBInterface.h
+++ b/Source/Core/VideoCommon/EFBInterface.h
@@ -20,10 +20,13 @@ public:
virtual void PokeDepth(u16 x, u16 y, u32 depth) = 0;
u32 PeekColor(u16 x, u16 y);
- virtual u32 PeekDepth(u16 x, u16 y) = 0;
+ u32 PeekDepth(u16 x, u16 y);
protected:
+ bool ShouldSkipAccess(u16 x, u16 y) const;
+
virtual u32 PeekColorInternal(u16 x, u16 y) = 0;
+ virtual u32 PeekDepthInternal(u16 x, u16 y) = 0;
};
class HardwareEFBInterface final : public EFBInterfaceBase
@@ -34,7 +37,7 @@ class HardwareEFBInterface final : public EFBInterfaceBase
void PokeDepth(u16 x, u16 y, u32 depth) override;
u32 PeekColorInternal(u16 x, u16 y) override;
- u32 PeekDepth(u16 x, u16 y) override;
+ u32 PeekDepthInternal(u16 x, u16 y) override;
};
extern std::unique_ptr<EFBInterfaceBase> g_efb_interface;