From 6a920b268e8b0a79b5f51fe61b8a3dec413f3d33 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 19 Jul 2024 15:31:50 +1000 Subject: [PATCH] CDROM: Handle BFRD clears inbetween DMA transfers Fixes disc detection in Metal Gear Solid: Special Missions. --- src/core/cdrom.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index 2807bbdec..e223c4063 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -1006,10 +1006,21 @@ void CDROM::WriteRegister(u32 offset, u8 value) s_request_register.bits = rr.bits; - if (s_request_register.BFRD) + SectorBuffer& sb = s_sector_buffers[s_current_read_sector_buffer]; + DEBUG_LOG("{} BFRD buffer={} pos={} size={}", s_request_register.BFRD ? "Set" : "Clear", + s_current_read_sector_buffer, sb.position, sb.size); + + if (!s_request_register.BFRD) { - const SectorBuffer& sb = s_sector_buffers[s_current_read_sector_buffer]; - DEV_LOG("BFRD buffer={} pos={} size={}", s_current_read_sector_buffer, sb.position, sb.size); + // Clearing BFRD needs to reset the position of the current buffer. + // Metal Gear Solid: Special Missions (PAL) clears BFRD inbetween two DMAs during its disc detection, and needs + // the buffer to reset. But during the actual game, it doesn't clear, and needs the pointer to increment. + sb.position = 0; + } + else + { + if (sb.size == 0) + WARNING_LOG("Setting BFRD without a buffer ready."); } UpdateStatusRegister(); @@ -2991,7 +3002,7 @@ ALWAYS_INLINE_RELEASE void CDROM::ProcessDataSector(const u8* raw_sector, const // TODO: How does XA relate to this buffering? SectorBuffer* sb = &s_sector_buffers[sb_num]; - if (sb->position == 0 && sb->size == 0) + if (sb->position == 0 && sb->size > 0) { DEV_LOG("Sector buffer {} was not read, previous sector dropped", (s_current_write_sector_buffer - 1) % NUM_SECTOR_BUFFERS);