From 06215996280e8c39e175d7731240939bf4320b65 Mon Sep 17 00:00:00 2001 From: Jean-Philip Desjardins Date: Fri, 13 Sep 2024 15:43:47 -0400 Subject: [PATCH] Improve the way we track command delays in CDVDFSV. --- Source/iop/IopBios.cpp | 2 +- Source/iop/Iop_Cdvdfsv.cpp | 16 +++++++++++++++- Source/iop/Iop_Cdvdfsv.h | 3 ++- Source/iop/Iop_Cdvdman.cpp | 8 ++++---- Source/iop/Iop_Cdvdman.h | 4 ++++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/Source/iop/IopBios.cpp b/Source/iop/IopBios.cpp index a6c8a50ff6..ad7bb79b7a 100644 --- a/Source/iop/IopBios.cpp +++ b/Source/iop/IopBios.cpp @@ -1916,6 +1916,7 @@ void CIopBios::CountTicks(uint32 ticks) m_sifMan->CountTicks(ticks); #ifdef _IOP_EMULATE_MODULES m_cdvdman->CountTicks(ticks); + m_cdvdfsv->CountTicks(ticks, m_sifMan.get()); m_mcserv->CountTicks(ticks, m_sifMan.get()); m_usbd->CountTicks(ticks); #endif @@ -1946,7 +1947,6 @@ void CIopBios::NotifyVBlankEnd() } } #ifdef _IOP_EMULATE_MODULES - m_cdvdfsv->ProcessCommands(m_sifMan.get()); m_fileIo->ProcessCommands(m_sifMan.get()); #endif } diff --git a/Source/iop/Iop_Cdvdfsv.cpp b/Source/iop/Iop_Cdvdfsv.cpp index 203cfbaa6e..1ad6fe0776 100644 --- a/Source/iop/Iop_Cdvdfsv.cpp +++ b/Source/iop/Iop_Cdvdfsv.cpp @@ -4,6 +4,7 @@ #include "Iop_Cdvdfsv.h" #include "Iop_Cdvdman.h" #include "Iop_SifManPs2.h" +#include "TimeUtils.h" using namespace Iop; @@ -20,6 +21,8 @@ using namespace Iop; #define STATE_STREAMPOS ("StreamPos") #define STATE_STREAMBUFFERSIZE ("StreamBufferSize") +constexpr uint64 COMMAND_DEFAULT_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 16666); + CCdvdfsv::CCdvdfsv(CSifMan& sif, CCdvdman& cdvdman, uint8* iopRam) : m_cdvdman(cdvdman) , m_iopRam(iopRam) @@ -58,10 +61,16 @@ std::string CCdvdfsv::GetFunctionName(unsigned int) const return "unknown"; } -void CCdvdfsv::ProcessCommands(CSifMan* sifMan) +void CCdvdfsv::CountTicks(uint32 ticks, CSifMan* sifMan) { if(m_pendingCommand != COMMAND_NONE) { + m_pendingCommandDelay -= std::min(m_pendingCommandDelay, ticks); + if(m_pendingCommandDelay != 0) + { + return; + } + static const uint32 sectorSize = 0x800; uint8* eeRam = nullptr; @@ -400,6 +409,7 @@ void CCdvdfsv::Read(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, assert(m_pendingCommand == COMMAND_NONE); m_pendingCommand = COMMAND_READ; + m_pendingCommandDelay = CCdvdman::COMMAND_READ_BASE_DELAY + (count * CCdvdman::COMMAND_READ_SECTOR_DELAY); m_pendingReadSector = sector; m_pendingReadCount = count; m_pendingReadAddr = dstAddr & 0x1FFFFFFF; @@ -422,6 +432,7 @@ void CCdvdfsv::ReadIopMem(uint32* args, uint32 argsSize, uint32* ret, uint32 ret assert(m_pendingCommand == COMMAND_NONE); m_pendingCommand = COMMAND_READIOP; + m_pendingCommandDelay = COMMAND_DEFAULT_DELAY; m_pendingReadSector = sector; m_pendingReadCount = count; m_pendingReadAddr = dstAddr & 0x1FFFFFFF; @@ -454,6 +465,7 @@ bool CCdvdfsv::StreamCmd(uint32* args, uint32 argsSize, uint32* ret, uint32 retS case 2: //Read m_pendingCommand = COMMAND_STREAM_READ; + m_pendingCommandDelay = COMMAND_DEFAULT_DELAY; m_pendingReadSector = 0; m_pendingReadCount = count; m_pendingReadAddr = dstAddr & (PS2::EE_RAM_SIZE - 1); @@ -509,6 +521,7 @@ bool CCdvdfsv::NDiskReady(uint32* args, uint32 argsSize, uint32* ret, uint32 ret { //Delay command (required by Downhill Domination) m_pendingCommand = COMMAND_NDISKREADY; + m_pendingCommandDelay = COMMAND_DEFAULT_DELAY; ret[0x00] = 2; return false; } @@ -544,6 +557,7 @@ void CCdvdfsv::ReadChain(uint32* args, uint32 argsSize, uint32* ret, uint32 retS //DBZ: Budokai Tenkaichi hangs in its loading screen if this command's result is not delayed. m_pendingCommand = COMMAND_READCHAIN; + m_pendingCommandDelay = COMMAND_DEFAULT_DELAY; } void CCdvdfsv::SearchFile(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram) diff --git a/Source/iop/Iop_Cdvdfsv.h b/Source/iop/Iop_Cdvdfsv.h index 8de0a703da..2252103d44 100644 --- a/Source/iop/Iop_Cdvdfsv.h +++ b/Source/iop/Iop_Cdvdfsv.h @@ -21,7 +21,7 @@ namespace Iop std::string GetFunctionName(unsigned int) const override; void Invoke(CMIPS&, unsigned int) override; - void ProcessCommands(CSifMan*); + void CountTicks(uint32, CSifMan*); void SetOpticalMedia(COpticalMedia*); void LoadState(Framework::CZipArchiveReader&) override; @@ -71,6 +71,7 @@ namespace Iop COpticalMedia* m_opticalMedia = nullptr; COMMAND m_pendingCommand = COMMAND_NONE; + int32 m_pendingCommandDelay = 0; uint32 m_pendingReadSector = 0; uint32 m_pendingReadCount = 0; uint32 m_pendingReadAddr = 0; diff --git a/Source/iop/Iop_Cdvdman.cpp b/Source/iop/Iop_Cdvdman.cpp index c89cfb5909..89a9b27cb9 100644 --- a/Source/iop/Iop_Cdvdman.cpp +++ b/Source/iop/Iop_Cdvdman.cpp @@ -42,12 +42,12 @@ #define FUNCTION_CDREADDVDDUALINFO "CdReadDvdDualInfo" #define FUNCTION_CDLAYERSEARCHFILE "CdLayerSearchFile" -constexpr uint64 COMMAND_READ_BASE_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 100); -constexpr uint64 COMMAND_READ_SECTOR_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 500); -constexpr uint64 COMMAND_SEEK_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 100); - using namespace Iop; +const uint64 CCdvdman::COMMAND_READ_BASE_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 100); +const uint64 CCdvdman::COMMAND_READ_SECTOR_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 500); +const uint64 CCdvdman::COMMAND_SEEK_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 100); + CCdvdman::CCdvdman(CIopBios& bios, uint8* ram) : m_bios(bios) , m_ram(ram) diff --git a/Source/iop/Iop_Cdvdman.h b/Source/iop/Iop_Cdvdman.h index e3b975c0e2..2b77368369 100644 --- a/Source/iop/Iop_Cdvdman.h +++ b/Source/iop/Iop_Cdvdman.h @@ -67,6 +67,10 @@ namespace Iop uint32 CdGetDiskTypeDirect(COpticalMedia*); uint32 CdLayerSearchFileDirect(COpticalMedia*, FILEINFO*, const char*, uint32); + static const uint64 COMMAND_READ_BASE_DELAY; + static const uint64 COMMAND_READ_SECTOR_DELAY; + static const uint64 COMMAND_SEEK_DELAY; + private: enum COMMAND : uint32 {