diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 256503b22e..d4c8ac42da 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -149,9 +149,7 @@ static int Replace_memcpy_swizzled() { u32 pitch = PARAM(2); u32 h = PARAM(4); if (Memory::IsVRAMAddress(srcPtr)) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - gpu->PerformMemoryCopy(srcPtr ^ 0x00400000, srcPtr, pitch * h); + gpu->PerformMemoryDownload(srcPtr, pitch * h); } u8 *dstp = Memory::GetPointerUnchecked(destPtr); const u8 *srcp = Memory::GetPointerUnchecked(srcPtr); @@ -465,9 +463,7 @@ static int Hook_godseaterburst_blit_texture() { const u32 fb_info = Memory::Read_U32(fb_infoaddr); const u32 fb_address = Memory::Read_U32(fb_info); if (Memory::IsVRAMAddress(fb_address)) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - gpu->PerformMemoryCopy(fb_address ^ 0x00400000, fb_address, 0x00048000); + gpu->PerformMemoryDownload(fb_address, 0x00048000); CBreakPoints::ExecMemCheck(fb_address, true, 0x00048000, currentMIPS->pc); } return 0; @@ -481,9 +477,7 @@ static int Hook_hexyzforce_monoclome_thread() { const u32 fb_address = Memory::Read_U32(fb_info); if (Memory::IsVRAMAddress(fb_address)) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - gpu->PerformMemoryCopy(fb_address ^ 0x00400000, fb_address, 0x00088000); + gpu->PerformMemoryDownload(fb_address, 0x00088000); CBreakPoints::ExecMemCheck(fb_address, true, 0x00088000, currentMIPS->pc); } return 0; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 712071e138..f11335a76d 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -1325,6 +1325,11 @@ bool DIRECTX9_GPU::PerformMemorySet(u32 dest, u8 v, int size) { return false; } +bool DIRECTX9_GPU::PerformMemoryDownload(u32 dest, int size) { + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + return false; +} + void DIRECTX9_GPU::ClearCacheNextFrame() { textureCache_.ClearNextFrame(); } diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index b7bd893906..a0124529af 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -48,6 +48,7 @@ public: virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type); virtual bool PerformMemoryCopy(u32 dest, u32 src, int size); virtual bool PerformMemorySet(u32 dest, u8 v, int size); + virtual bool PerformMemoryDownload(u32 dest, int size); virtual void ClearCacheNextFrame(); virtual void DeviceLost(); // Only happens on Android. Drop all textures and shaders. diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index af47aad550..a8a412dd9d 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -2048,6 +2048,12 @@ bool GLES_GPU::PerformMemorySet(u32 dest, u8 v, int size) { return false; } +bool GLES_GPU::PerformMemoryDownload(u32 dest, int size) { + // Cheat a bit to force a download of the framebuffer. + // VRAM + 0x00400000 is simply a VRAM mirror. + return gpu->PerformMemoryCopy(dest ^ 0x00400000, dest, size); +} + void GLES_GPU::ClearCacheNextFrame() { textureCache_.ClearNextFrame(); } diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index 22b59d8208..f60bdd73d6 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -47,6 +47,7 @@ public: virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type); virtual bool PerformMemoryCopy(u32 dest, u32 src, int size); virtual bool PerformMemorySet(u32 dest, u8 v, int size); + virtual bool PerformMemoryDownload(u32 dest, int size); virtual void ClearCacheNextFrame(); virtual void DeviceLost(); // Only happens on Android. Drop all textures and shaders. diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index b7250dc682..9b29072c73 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -243,6 +243,7 @@ public: // Update either RAM from VRAM, or VRAM from RAM... or even VRAM from VRAM. virtual bool PerformMemoryCopy(u32 dest, u32 src, int size) = 0; virtual bool PerformMemorySet(u32 dest, u8 v, int size) = 0; + virtual bool PerformMemoryDownload(u32 dest, int size) = 0; // Will cause the texture cache to be cleared at the start of the next frame. virtual void ClearCacheNextFrame() = 0; diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index c9731e1aa1..d718cb4059 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -668,3 +668,9 @@ bool NullGPU::PerformMemorySet(u32 dest, u8 v, int size) { InvalidateCache(dest, size, GPU_INVALIDATE_HINT); return false; } + +bool NullGPU::PerformMemoryDownload(u32 dest, int size) { + // Nothing to update. + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + return false; +} diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index c0d92a55f6..724403be5a 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -36,6 +36,7 @@ public: virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type); virtual bool PerformMemoryCopy(u32 dest, u32 src, int size); virtual bool PerformMemorySet(u32 dest, u8 v, int size); + virtual bool PerformMemoryDownload(u32 dest, int size); virtual void ClearCacheNextFrame() {}; virtual void DeviceLost() {} diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 2e3f0e1f1b..20db506252 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -869,6 +869,13 @@ bool SoftGPU::PerformMemorySet(u32 dest, u8 v, int size) return false; } +bool SoftGPU::PerformMemoryDownload(u32 dest, int size) +{ + // Nothing to update. + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + return false; +} + bool SoftGPU::FramebufferDirty() { if (g_Config.bSeparateCPUThread) { // Allow it to process fully before deciding if it's dirty. diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 6844c3161e..8144f870ee 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -61,6 +61,7 @@ public: virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type); virtual bool PerformMemoryCopy(u32 dest, u32 src, int size); virtual bool PerformMemorySet(u32 dest, u8 v, int size); + virtual bool PerformMemoryDownload(u32 dest, int size); virtual void ClearCacheNextFrame() {}; virtual void DeviceLost() {}