mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-25 06:44:59 +00:00
VideoCommon: Fix out-of-bounds and disabled EFB access.
This commit is contained in:
parent
1981f22228
commit
e351f03cdf
7 changed files with 55 additions and 29 deletions
|
@ -47,9 +47,7 @@
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
|
||||||
#include "VideoCommon/AsyncRequests.h"
|
|
||||||
#include "VideoCommon/EFBInterface.h"
|
#include "VideoCommon/EFBInterface.h"
|
||||||
#include "VideoCommon/Statistics.h"
|
|
||||||
|
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
|
@ -111,18 +109,12 @@ static u32 EFB_Read(const u32 addr)
|
||||||
}
|
}
|
||||||
else if (addr & 0x00400000)
|
else if (addr & 0x00400000)
|
||||||
{
|
{
|
||||||
var = AsyncRequests::GetInstance()->PushBlockingEvent([&] {
|
var = g_efb_interface->PeekDepth(x, y);
|
||||||
INCSTAT(g_stats.this_frame.num_efb_peeks);
|
|
||||||
return g_efb_interface->PeekDepth(x, y);
|
|
||||||
});
|
|
||||||
DEBUG_LOG_FMT(MEMMAP, "EFB Z Read @ {}, {}\t= {:#010x}", x, y, var);
|
DEBUG_LOG_FMT(MEMMAP, "EFB Z Read @ {}, {}\t= {:#010x}", x, y, var);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var = AsyncRequests::GetInstance()->PushBlockingEvent([&] {
|
var = g_efb_interface->PeekColor(x, y);
|
||||||
INCSTAT(g_stats.this_frame.num_efb_peeks);
|
|
||||||
return g_efb_interface->PeekColor(x, y);
|
|
||||||
});
|
|
||||||
DEBUG_LOG_FMT(MEMMAP, "EFB Color Read @ {}, {}\t= {:#010x}", x, y, var);
|
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)
|
else if (addr & 0x00400000)
|
||||||
{
|
{
|
||||||
AsyncRequests::GetInstance()->PushEvent([x, y, data] {
|
g_efb_interface->PokeDepth(x, y, data);
|
||||||
INCSTAT(g_stats.this_frame.num_efb_pokes);
|
|
||||||
g_efb_interface->PokeDepth(x, y, data);
|
|
||||||
});
|
|
||||||
DEBUG_LOG_FMT(MEMMAP, "EFB Z Write {:08x} @ {}, {}", data, x, y);
|
DEBUG_LOG_FMT(MEMMAP, "EFB Z Write {:08x} @ {}, {}", data, x, y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AsyncRequests::GetInstance()->PushEvent([x, y, data] {
|
g_efb_interface->PokeColor(x, y, data);
|
||||||
INCSTAT(g_stats.this_frame.num_efb_pokes);
|
|
||||||
g_efb_interface->PokeColor(x, y, data);
|
|
||||||
});
|
|
||||||
DEBUG_LOG_FMT(MEMMAP, "EFB Color Write {:08x} @ {}, {}", data, x, y);
|
DEBUG_LOG_FMT(MEMMAP, "EFB Color Write {:08x} @ {}, {}", data, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,7 +108,7 @@ u32 NullEFBInterface::PeekColorInternal(u16 x, u16 y)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 NullEFBInterface::PeekDepth(u16 x, u16 y)
|
u32 NullEFBInterface::PeekDepthInternal(u16 x, u16 y)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class NullEFBInterface final : public EFBInterfaceBase
|
||||||
void PokeDepth(u16 x, u16 y, u32 depth) override;
|
void PokeDepth(u16 x, u16 y, u32 depth) override;
|
||||||
|
|
||||||
u32 PeekColorInternal(u16 x, u16 y) override;
|
u32 PeekColorInternal(u16 x, u16 y) override;
|
||||||
u32 PeekDepth(u16 x, u16 y) override;
|
u32 PeekDepthInternal(u16 x, u16 y) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Null
|
} // namespace Null
|
||||||
|
|
|
@ -742,7 +742,7 @@ u32 SWEFBInterface::PeekColorInternal(u16 x, u16 y)
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 SWEFBInterface::PeekDepth(u16 x, u16 y)
|
u32 SWEFBInterface::PeekDepthInternal(u16 x, u16 y)
|
||||||
{
|
{
|
||||||
return EfbInterface::GetDepth(x, y);
|
return EfbInterface::GetDepth(x, y);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,6 @@ class SWEFBInterface final : public EFBInterfaceBase
|
||||||
void PokeDepth(u16 x, u16 y, u32 depth) override;
|
void PokeDepth(u16 x, u16 y, u32 depth) override;
|
||||||
|
|
||||||
u32 PeekColorInternal(u16 x, u16 y) override;
|
u32 PeekColorInternal(u16 x, u16 y) override;
|
||||||
u32 PeekDepth(u16 x, u16 y) override;
|
u32 PeekDepthInternal(u16 x, u16 y) override;
|
||||||
};
|
};
|
||||||
} // namespace SW
|
} // namespace SW
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
|
||||||
|
#include "VideoCommon/AsyncRequests.h"
|
||||||
#include "VideoCommon/FramebufferManager.h"
|
#include "VideoCommon/FramebufferManager.h"
|
||||||
#include "VideoCommon/PixelEngine.h"
|
#include "VideoCommon/PixelEngine.h"
|
||||||
|
#include "VideoCommon/Statistics.h"
|
||||||
#include "VideoCommon/VideoBackendBase.h"
|
#include "VideoCommon/VideoBackendBase.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
#include "VideoCommon/VideoConfig.h"
|
#include "VideoCommon/VideoConfig.h"
|
||||||
|
@ -24,6 +26,11 @@ std::unique_ptr<EFBInterfaceBase> g_efb_interface;
|
||||||
|
|
||||||
EFBInterfaceBase::~EFBInterfaceBase() = default;
|
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)
|
void HardwareEFBInterface::ReinterpretPixelData(EFBReinterpretType convtype)
|
||||||
{
|
{
|
||||||
g_framebuffer_manager->ReinterpretPixelData(convtype);
|
g_framebuffer_manager->ReinterpretPixelData(convtype);
|
||||||
|
@ -31,7 +38,10 @@ void HardwareEFBInterface::ReinterpretPixelData(EFBReinterpretType convtype)
|
||||||
|
|
||||||
u32 HardwareEFBInterface::PeekColorInternal(u16 x, u16 y)
|
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
|
// a little-endian value is expected to be returned
|
||||||
color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000));
|
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)
|
u32 EFBInterfaceBase::PeekColor(u16 x, u16 y)
|
||||||
{
|
{
|
||||||
|
if (ShouldSkipAccess(x, y))
|
||||||
|
return 0;
|
||||||
|
|
||||||
u32 color = PeekColorInternal(x, y);
|
u32 color = PeekColorInternal(x, y);
|
||||||
|
|
||||||
// check what to do with the alpha channel (GX_PokeAlphaRead)
|
// 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
|
// Depth buffer is inverted for improved precision near far plane
|
||||||
float depth = g_framebuffer_manager->PeekEFBDepth(x, y);
|
|
||||||
if (!g_backend_info.bSupportsReversedDepthRange)
|
if (!g_backend_info.bSupportsReversedDepthRange)
|
||||||
depth = 1.0f - depth;
|
depth = 1.0f - depth;
|
||||||
|
|
||||||
|
@ -105,22 +122,42 @@ u32 HardwareEFBInterface::PeekDepth(u16 x, u16 y)
|
||||||
return z24depth;
|
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)
|
void HardwareEFBInterface::PokeColor(u16 x, u16 y, u32 poke_data)
|
||||||
{
|
{
|
||||||
|
if (ShouldSkipAccess(x, y))
|
||||||
|
return;
|
||||||
|
|
||||||
// Convert to expected format (BGRA->RGBA)
|
// Convert to expected format (BGRA->RGBA)
|
||||||
// TODO: Check alpha, depending on mode?
|
// TODO: Check alpha, depending on mode?
|
||||||
const u32 color =
|
const u32 color =
|
||||||
((poke_data & 0xFF00FF00) | ((poke_data >> 16) & 0xFF) | ((poke_data << 16) & 0xFF0000));
|
((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)
|
void HardwareEFBInterface::PokeDepth(u16 x, u16 y, u32 poke_data)
|
||||||
{
|
{
|
||||||
|
if (ShouldSkipAccess(x, y))
|
||||||
|
return;
|
||||||
|
|
||||||
// Convert to floating-point depth.
|
// Convert to floating-point depth.
|
||||||
float depth = float(poke_data & 0xFFFFFF) / 16777216.0f;
|
float depth = float(poke_data & 0xFFFFFF) / 16777216.0f;
|
||||||
if (!g_backend_info.bSupportsReversedDepthRange)
|
if (!g_backend_info.bSupportsReversedDepthRange)
|
||||||
depth = 1.0f - depth;
|
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);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,13 @@ public:
|
||||||
virtual void PokeDepth(u16 x, u16 y, u32 depth) = 0;
|
virtual void PokeDepth(u16 x, u16 y, u32 depth) = 0;
|
||||||
|
|
||||||
u32 PeekColor(u16 x, u16 y);
|
u32 PeekColor(u16 x, u16 y);
|
||||||
virtual u32 PeekDepth(u16 x, u16 y) = 0;
|
u32 PeekDepth(u16 x, u16 y);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool ShouldSkipAccess(u16 x, u16 y) const;
|
||||||
|
|
||||||
virtual u32 PeekColorInternal(u16 x, u16 y) = 0;
|
virtual u32 PeekColorInternal(u16 x, u16 y) = 0;
|
||||||
|
virtual u32 PeekDepthInternal(u16 x, u16 y) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HardwareEFBInterface final : public EFBInterfaceBase
|
class HardwareEFBInterface final : public EFBInterfaceBase
|
||||||
|
@ -34,7 +37,7 @@ class HardwareEFBInterface final : public EFBInterfaceBase
|
||||||
void PokeDepth(u16 x, u16 y, u32 depth) override;
|
void PokeDepth(u16 x, u16 y, u32 depth) override;
|
||||||
|
|
||||||
u32 PeekColorInternal(u16 x, u16 y) 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;
|
extern std::unique_ptr<EFBInterfaceBase> g_efb_interface;
|
||||||
|
|
Loading…
Add table
Reference in a new issue