summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2021-06-27 17:24:53 +0200
committerJosJuice <josjuice@gmail.com>2021-06-28 09:48:04 +0200
commitc6ede090350c9f413b1df8a4de850da5345797e2 (patch)
treece6363ccd2da169dd3a49a130aa9e2f282fcce8b /Source/Core
parentc77a5f7e3246398aeb1d520d7bbc0bfdf5787754 (diff)
DVDInterface: Don't evict cache block i unless block i + 2 was read
Intends to fix https://bugs.dolphin-emu.org/issues/12279. I have hardware tested the behavior, but I haven't tested the game.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/DVD/DVDInterface.cpp29
1 files changed, 20 insertions, 9 deletions
diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp
index dd9a2c0ccf..018492319e 100644
--- a/Source/Core/Core/HW/DVD/DVDInterface.cpp
+++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp
@@ -1512,27 +1512,38 @@ static void ScheduleReads(u64 offset, u32 length, const DiscIO::Partition& parti
dvd_offset += DVD_ECC_BLOCK_SIZE;
} while (length > 0);
- // Update the buffer based on this read. Based on experimental testing,
- // we will only reuse the old buffer while reading forward. Note that the
- // buffer start we calculate here is not the actual start of the buffer -
- // it is just the start of the portion we need to read.
+ // Evict blocks from the buffer which are unlikely to be used again after this read,
+ // so that the buffer gets space for prefetching new blocks. Based on hardware testing,
+ // the blocks which are kept are the most recently accessed block, the block immediately
+ // before it, and all blocks after it.
+ //
+ // If the block immediately before the most recently accessed block is not kept, loading
+ // screens in Pitfall: The Lost Expedition are longer than they should be.
+ // https://bugs.dolphin-emu.org/issues/12279
const u64 last_block = dvd_offset;
- if (last_block == buffer_start + DVD_ECC_BLOCK_SIZE && buffer_start != buffer_end)
+ constexpr u32 BUFFER_BACKWARD_SEEK_LIMIT = DVD_ECC_BLOCK_SIZE * 2;
+ if (last_block - buffer_start <= BUFFER_BACKWARD_SEEK_LIMIT && buffer_start != buffer_end)
{
- // Special case: reading less than one block at the start of the
- // buffer won't change the buffer state
+ // Special case: reading the first two blocks of the buffer doesn't change the buffer state
}
else
{
+ // Note that the s_read_buffer_start_offset value we calculate here is not the
+ // actual start of the buffer - it is just the start of the portion we need to read.
+ // The actual start of the buffer is s_read_buffer_end_offset - STREAMING_BUFFER_SIZE.
if (last_block >= buffer_end)
+ {
// Full buffer read
s_read_buffer_start_offset = last_block;
+ }
else
+ {
// Partial buffer read
s_read_buffer_start_offset = buffer_end;
+ }
- s_read_buffer_end_offset = last_block + STREAMING_BUFFER_SIZE - DVD_ECC_BLOCK_SIZE;
- // Assume the buffer starts reading right after the end of the last operation
+ s_read_buffer_end_offset = last_block + STREAMING_BUFFER_SIZE - BUFFER_BACKWARD_SEEK_LIMIT;
+ // Assume the buffer starts prefetching new blocks right after the end of the last operation
s_read_buffer_start_time = current_time + ticks_until_completion;
s_read_buffer_end_time =
s_read_buffer_start_time +