Make sync DiskReady command flush pending async commands.

Fixes hang when booting Castlevania Curse of Darkness.
This commit is contained in:
Jean-Philip Desjardins 2025-03-14 14:38:18 -04:00
parent 30568a057d
commit fe8a7a0561
3 changed files with 83 additions and 57 deletions

View file

@ -1916,7 +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_cdvdfsv->CountTicks(ticks);
m_mcserv->CountTicks(ticks, m_sifMan.get());
m_usbd->CountTicks(ticks);
#endif

View file

@ -24,7 +24,8 @@ using namespace Iop;
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_sifMan(sif)
, m_cdvdman(cdvdman)
, m_iopRam(iopRam)
{
m_module592 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke592, this,
@ -61,7 +62,7 @@ std::string CCdvdfsv::GetFunctionName(unsigned int) const
return "unknown";
}
void CCdvdfsv::CountTicks(uint32 ticks, CSifMan* sifMan)
void CCdvdfsv::CountTicks(uint32 ticks)
{
if(m_pendingCommand != COMMAND_NONE)
{
@ -71,10 +72,18 @@ void CCdvdfsv::CountTicks(uint32 ticks, CSifMan* sifMan)
return;
}
FinishPendingCommand();
}
}
void CCdvdfsv::FinishPendingCommand()
{
assert(m_pendingCommand != COMMAND_NONE);
static const uint32 sectorSize = 0x800;
uint8* eeRam = nullptr;
if(auto sifManPs2 = dynamic_cast<CSifManPs2*>(sifMan))
if(auto sifManPs2 = dynamic_cast<CSifManPs2*>(&m_sifMan))
{
eeRam = sifManPs2->GetEeRam();
}
@ -121,10 +130,17 @@ void CCdvdfsv::CountTicks(uint32 ticks, CSifMan* sifMan)
{
//Nothing to do, everything has been read already
}
else if(m_pendingCommand == COMMAND_PAUSE)
{
//Nothing to do
}
else
{
assert(false);
}
m_pendingCommand = COMMAND_NONE;
sifMan->SendCallReply(MODULE_ID_4, nullptr);
}
m_sifMan.SendCallReply(MODULE_ID_4, nullptr);
}
void CCdvdfsv::SetOpticalMedia(COpticalMedia* opticalMedia)
@ -387,6 +403,13 @@ bool CCdvdfsv::Invoke59C(uint32 method, uint32* args, uint32 argsSize, uint32* r
assert(argsSize >= 4);
uint32 mode = args[0x00];
CLog::GetInstance().Print(LOG_NAME, "DiskReady(mode = %i);\r\n", mode);
//When this is called, it seems we need to make sure that no pending command is
//remaining. Castlevania: Curse of Darkness issues a Pause command then uses
//DiskReady without acknowledging the pause and assumes it can use GetToc after.
if(m_pendingCommand != COMMAND_NONE)
{
FinishPendingCommand();
}
ret[0x00] = 2;
}
break;

View file

@ -21,7 +21,7 @@ namespace Iop
std::string GetFunctionName(unsigned int) const override;
void Invoke(CMIPS&, unsigned int) override;
void CountTicks(uint32, CSifMan*);
void CountTicks(uint32);
void SetOpticalMedia(COpticalMedia*);
void LoadState(Framework::CZipArchiveReader&) override;
@ -51,6 +51,8 @@ namespace Iop
COMMAND_PAUSE,
};
void FinishPendingCommand();
bool Invoke592(uint32, uint32*, uint32, uint32*, uint32, uint8*);
bool Invoke593(uint32, uint32*, uint32, uint32*, uint32, uint8*);
bool Invoke595(uint32, uint32*, uint32, uint32*, uint32, uint8*);
@ -67,6 +69,7 @@ namespace Iop
void ReadChain(uint32*, uint32, uint32*, uint32, uint8*);
void SearchFile(uint32*, uint32, uint32*, uint32, uint8*);
CSifMan& m_sifMan;
CCdvdman& m_cdvdman;
uint8* m_iopRam = nullptr;
COpticalMedia* m_opticalMedia = nullptr;