mirror of
https://github.com/jpd002/Play-.git
synced 2025-04-28 13:47:57 +03:00
Make sync DiskReady command flush pending async commands.
Fixes hang when booting Castlevania Curse of Darkness.
This commit is contained in:
parent
30568a057d
commit
fe8a7a0561
3 changed files with 83 additions and 57 deletions
|
@ -1916,7 +1916,7 @@ void CIopBios::CountTicks(uint32 ticks)
|
||||||
m_sifMan->CountTicks(ticks);
|
m_sifMan->CountTicks(ticks);
|
||||||
#ifdef _IOP_EMULATE_MODULES
|
#ifdef _IOP_EMULATE_MODULES
|
||||||
m_cdvdman->CountTicks(ticks);
|
m_cdvdman->CountTicks(ticks);
|
||||||
m_cdvdfsv->CountTicks(ticks, m_sifMan.get());
|
m_cdvdfsv->CountTicks(ticks);
|
||||||
m_mcserv->CountTicks(ticks, m_sifMan.get());
|
m_mcserv->CountTicks(ticks, m_sifMan.get());
|
||||||
m_usbd->CountTicks(ticks);
|
m_usbd->CountTicks(ticks);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,7 +24,8 @@ using namespace Iop;
|
||||||
constexpr uint64 COMMAND_DEFAULT_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 16666);
|
constexpr uint64 COMMAND_DEFAULT_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 16666);
|
||||||
|
|
||||||
CCdvdfsv::CCdvdfsv(CSifMan& sif, CCdvdman& cdvdman, uint8* iopRam)
|
CCdvdfsv::CCdvdfsv(CSifMan& sif, CCdvdman& cdvdman, uint8* iopRam)
|
||||||
: m_cdvdman(cdvdman)
|
: m_sifMan(sif)
|
||||||
|
, m_cdvdman(cdvdman)
|
||||||
, m_iopRam(iopRam)
|
, m_iopRam(iopRam)
|
||||||
{
|
{
|
||||||
m_module592 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke592, this,
|
m_module592 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke592, this,
|
||||||
|
@ -61,7 +62,7 @@ std::string CCdvdfsv::GetFunctionName(unsigned int) const
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCdvdfsv::CountTicks(uint32 ticks, CSifMan* sifMan)
|
void CCdvdfsv::CountTicks(uint32 ticks)
|
||||||
{
|
{
|
||||||
if(m_pendingCommand != COMMAND_NONE)
|
if(m_pendingCommand != COMMAND_NONE)
|
||||||
{
|
{
|
||||||
|
@ -71,62 +72,77 @@ void CCdvdfsv::CountTicks(uint32 ticks, CSifMan* sifMan)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint32 sectorSize = 0x800;
|
FinishPendingCommand();
|
||||||
|
|
||||||
uint8* eeRam = nullptr;
|
|
||||||
if(auto sifManPs2 = dynamic_cast<CSifManPs2*>(sifMan))
|
|
||||||
{
|
|
||||||
eeRam = sifManPs2->GetEeRam();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_pendingCommand == COMMAND_READ)
|
|
||||||
{
|
|
||||||
if(m_opticalMedia != nullptr)
|
|
||||||
{
|
|
||||||
auto fileSystem = m_opticalMedia->GetFileSystem();
|
|
||||||
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
|
||||||
{
|
|
||||||
fileSystem->ReadBlock(m_pendingReadSector + i, eeRam + (m_pendingReadAddr + (i * sectorSize)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(m_pendingCommand == COMMAND_READIOP)
|
|
||||||
{
|
|
||||||
if(m_opticalMedia != nullptr)
|
|
||||||
{
|
|
||||||
auto fileSystem = m_opticalMedia->GetFileSystem();
|
|
||||||
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
|
||||||
{
|
|
||||||
fileSystem->ReadBlock(m_pendingReadSector + i, m_iopRam + (m_pendingReadAddr + (i * sectorSize)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(m_pendingCommand == COMMAND_STREAM_READ)
|
|
||||||
{
|
|
||||||
if(m_opticalMedia != nullptr)
|
|
||||||
{
|
|
||||||
auto fileSystem = m_opticalMedia->GetFileSystem();
|
|
||||||
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
|
||||||
{
|
|
||||||
fileSystem->ReadBlock(m_streamPos, eeRam + (m_pendingReadAddr + (i * sectorSize)));
|
|
||||||
m_streamPos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(m_pendingCommand == COMMAND_NDISKREADY)
|
|
||||||
{
|
|
||||||
//Result already set, just return normally
|
|
||||||
}
|
|
||||||
else if(m_pendingCommand == COMMAND_READCHAIN)
|
|
||||||
{
|
|
||||||
//Nothing to do, everything has been read already
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pendingCommand = COMMAND_NONE;
|
|
||||||
sifMan->SendCallReply(MODULE_ID_4, nullptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCdvdfsv::FinishPendingCommand()
|
||||||
|
{
|
||||||
|
assert(m_pendingCommand != COMMAND_NONE);
|
||||||
|
|
||||||
|
static const uint32 sectorSize = 0x800;
|
||||||
|
|
||||||
|
uint8* eeRam = nullptr;
|
||||||
|
if(auto sifManPs2 = dynamic_cast<CSifManPs2*>(&m_sifMan))
|
||||||
|
{
|
||||||
|
eeRam = sifManPs2->GetEeRam();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_pendingCommand == COMMAND_READ)
|
||||||
|
{
|
||||||
|
if(m_opticalMedia != nullptr)
|
||||||
|
{
|
||||||
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
||||||
|
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
||||||
|
{
|
||||||
|
fileSystem->ReadBlock(m_pendingReadSector + i, eeRam + (m_pendingReadAddr + (i * sectorSize)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_pendingCommand == COMMAND_READIOP)
|
||||||
|
{
|
||||||
|
if(m_opticalMedia != nullptr)
|
||||||
|
{
|
||||||
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
||||||
|
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
||||||
|
{
|
||||||
|
fileSystem->ReadBlock(m_pendingReadSector + i, m_iopRam + (m_pendingReadAddr + (i * sectorSize)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_pendingCommand == COMMAND_STREAM_READ)
|
||||||
|
{
|
||||||
|
if(m_opticalMedia != nullptr)
|
||||||
|
{
|
||||||
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
||||||
|
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
||||||
|
{
|
||||||
|
fileSystem->ReadBlock(m_streamPos, eeRam + (m_pendingReadAddr + (i * sectorSize)));
|
||||||
|
m_streamPos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_pendingCommand == COMMAND_NDISKREADY)
|
||||||
|
{
|
||||||
|
//Result already set, just return normally
|
||||||
|
}
|
||||||
|
else if(m_pendingCommand == COMMAND_READCHAIN)
|
||||||
|
{
|
||||||
|
//Nothing to do, everything has been read already
|
||||||
|
}
|
||||||
|
else if(m_pendingCommand == COMMAND_PAUSE)
|
||||||
|
{
|
||||||
|
//Nothing to do
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pendingCommand = COMMAND_NONE;
|
||||||
|
m_sifMan.SendCallReply(MODULE_ID_4, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void CCdvdfsv::SetOpticalMedia(COpticalMedia* opticalMedia)
|
void CCdvdfsv::SetOpticalMedia(COpticalMedia* opticalMedia)
|
||||||
{
|
{
|
||||||
m_opticalMedia = opticalMedia;
|
m_opticalMedia = opticalMedia;
|
||||||
|
@ -387,6 +403,13 @@ bool CCdvdfsv::Invoke59C(uint32 method, uint32* args, uint32 argsSize, uint32* r
|
||||||
assert(argsSize >= 4);
|
assert(argsSize >= 4);
|
||||||
uint32 mode = args[0x00];
|
uint32 mode = args[0x00];
|
||||||
CLog::GetInstance().Print(LOG_NAME, "DiskReady(mode = %i);\r\n", mode);
|
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;
|
ret[0x00] = 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace Iop
|
||||||
std::string GetFunctionName(unsigned int) const override;
|
std::string GetFunctionName(unsigned int) const override;
|
||||||
void Invoke(CMIPS&, unsigned int) override;
|
void Invoke(CMIPS&, unsigned int) override;
|
||||||
|
|
||||||
void CountTicks(uint32, CSifMan*);
|
void CountTicks(uint32);
|
||||||
void SetOpticalMedia(COpticalMedia*);
|
void SetOpticalMedia(COpticalMedia*);
|
||||||
|
|
||||||
void LoadState(Framework::CZipArchiveReader&) override;
|
void LoadState(Framework::CZipArchiveReader&) override;
|
||||||
|
@ -51,6 +51,8 @@ namespace Iop
|
||||||
COMMAND_PAUSE,
|
COMMAND_PAUSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void FinishPendingCommand();
|
||||||
|
|
||||||
bool Invoke592(uint32, uint32*, uint32, uint32*, uint32, uint8*);
|
bool Invoke592(uint32, uint32*, uint32, uint32*, uint32, uint8*);
|
||||||
bool Invoke593(uint32, uint32*, uint32, uint32*, uint32, uint8*);
|
bool Invoke593(uint32, uint32*, uint32, uint32*, uint32, uint8*);
|
||||||
bool Invoke595(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 ReadChain(uint32*, uint32, uint32*, uint32, uint8*);
|
||||||
void SearchFile(uint32*, uint32, uint32*, uint32, uint8*);
|
void SearchFile(uint32*, uint32, uint32*, uint32, uint8*);
|
||||||
|
|
||||||
|
CSifMan& m_sifMan;
|
||||||
CCdvdman& m_cdvdman;
|
CCdvdman& m_cdvdman;
|
||||||
uint8* m_iopRam = nullptr;
|
uint8* m_iopRam = nullptr;
|
||||||
COpticalMedia* m_opticalMedia = nullptr;
|
COpticalMedia* m_opticalMedia = nullptr;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue