DMA: Invalidate code pages on CD-ROM DMA write

Avoids page faulting by invalidating the pages in advance.

Might help with frame time spikes on super low-spec devices.
This commit is contained in:
Stenzek 2025-06-19 21:14:56 +10:00
parent fa0a926133
commit 6c6cc910e6
No known key found for this signature in database
3 changed files with 15 additions and 7 deletions

View File

@ -699,11 +699,6 @@ bool Bus::CanUseFastmemForAddress(VirtualMemoryAddress address)
}
}
bool Bus::IsRAMCodePage(u32 index)
{
return g_ram_code_bits[index];
}
void Bus::SetRAMCodePage(u32 index)
{
if (g_ram_code_bits[index])

View File

@ -170,7 +170,10 @@ ALWAYS_INLINE static u32 GetRAMCodePageIndex(PhysicalMemoryAddress address)
}
/// Returns true if the specified page contains code.
bool IsRAMCodePage(u32 index);
ALWAYS_INLINE static bool IsRAMCodePage(u32 index)
{
return g_ram_code_bits[index];
}
/// Flags a RAM region as code, so we know when to invalidate blocks.
void SetRAMCodePage(u32 index);
@ -188,7 +191,7 @@ bool IsCodePageAddress(PhysicalMemoryAddress address);
bool HasCodePagesInRange(PhysicalMemoryAddress start_address, u32 size);
/// Returns the number of cycles stolen by DMA RAM access.
ALWAYS_INLINE TickCount GetDMARAMTickCount(u32 word_count)
ALWAYS_INLINE static TickCount GetDMARAMTickCount(u32 word_count)
{
// DMA is using DRAM Hyper Page mode, allowing it to access DRAM rows at 1 clock cycle per word (effectively around
// 17 clks per 16 words, due to required row address loading, probably plus some further minimal overload due to

View File

@ -4,6 +4,7 @@
#include "dma.h"
#include "bus.h"
#include "cdrom.h"
#include "cpu_code_cache.h"
#include "cpu_core.h"
#include "gpu.h"
#include "gpu_dump.h"
@ -895,6 +896,15 @@ TickCount DMA::TransferDeviceToMemory(u32 address, u32 increment, u32 word_count
s_state.transfer_buffer.resize(word_count);
dest_pointer = s_state.transfer_buffer.data();
}
else if constexpr (channel == Channel::CDROM)
{
const u32 end_page = (address + (increment * word_count) - 1) >> HOST_PAGE_SHIFT;
for (u32 page = address >> HOST_PAGE_SHIFT; page <= end_page; page++)
{
if (Bus::IsRAMCodePage(page))
CPU::CodeCache::InvalidateBlocksWithPageIndex(page);
}
}
// Read from device.
switch (channel)