2008-01-20 23:08:56 +00:00
|
|
|
#include <assert.h>
|
2025-03-11 12:48:26 -04:00
|
|
|
#include "Log.h"
|
2008-01-20 23:08:56 +00:00
|
|
|
#include "../Ps2Const.h"
|
2014-10-16 03:19:04 -04:00
|
|
|
#include "Iop_Cdvdfsv.h"
|
2015-12-29 16:35:07 -05:00
|
|
|
#include "Iop_Cdvdman.h"
|
2014-10-16 03:33:59 -04:00
|
|
|
#include "Iop_SifManPs2.h"
|
2024-09-13 15:43:47 -04:00
|
|
|
#include "TimeUtils.h"
|
2008-01-20 23:08:56 +00:00
|
|
|
|
|
|
|
using namespace Iop;
|
|
|
|
|
|
|
|
#define LOG_NAME "iop_cdvdfsv"
|
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
#define STATE_FILENAME ("iop_cdvdfsv/state.xml")
|
2017-09-09 18:54:40 -04:00
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
#define STATE_PENDINGCOMMAND ("PendingCommand")
|
2017-09-09 18:54:40 -04:00
|
|
|
#define STATE_PENDINGREADSECTOR ("PendingReadSector")
|
2018-04-30 21:01:23 +01:00
|
|
|
#define STATE_PENDINGREADCOUNT ("PendingReadCount")
|
|
|
|
#define STATE_PENDINGREADADDR ("PendingReadAddr")
|
2017-09-09 18:54:40 -04:00
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
#define STATE_STREAMING ("Streaming")
|
|
|
|
#define STATE_STREAMPOS ("StreamPos")
|
|
|
|
#define STATE_STREAMBUFFERSIZE ("StreamBufferSize")
|
2017-09-09 18:54:40 -04:00
|
|
|
|
2024-09-13 15:43:47 -04:00
|
|
|
constexpr uint64 COMMAND_DEFAULT_DELAY = TimeUtils::UsecsToCycles(PS2::IOP_CLOCK_OVER_FREQ, 16666);
|
|
|
|
|
2015-12-29 16:35:07 -05:00
|
|
|
CCdvdfsv::CCdvdfsv(CSifMan& sif, CCdvdman& cdvdman, uint8* iopRam)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_cdvdman(cdvdman)
|
|
|
|
, m_iopRam(iopRam)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
2013-08-16 13:13:33 +00:00
|
|
|
m_module592 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke592, this,
|
2018-04-30 21:01:23 +01:00
|
|
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
2013-03-05 08:21:13 +00:00
|
|
|
m_module593 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke593, this,
|
2018-04-30 21:01:23 +01:00
|
|
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
2013-03-05 08:21:13 +00:00
|
|
|
m_module595 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke595, this,
|
2018-04-30 21:01:23 +01:00
|
|
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
2016-01-11 22:36:35 -05:00
|
|
|
m_module596 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke596, this,
|
2018-04-30 21:01:23 +01:00
|
|
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
2013-03-05 08:21:13 +00:00
|
|
|
m_module597 = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke597, this,
|
2018-04-30 21:01:23 +01:00
|
|
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
2013-03-05 08:21:13 +00:00
|
|
|
m_module59A = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke59A, this,
|
2018-04-30 21:01:23 +01:00
|
|
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
2013-03-05 08:21:13 +00:00
|
|
|
m_module59C = CSifModuleAdapter(std::bind(&CCdvdfsv::Invoke59C, this,
|
2018-04-30 21:01:23 +01:00
|
|
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6));
|
2012-03-11 20:16:15 +00:00
|
|
|
|
|
|
|
sif.RegisterModule(MODULE_ID_1, &m_module592);
|
|
|
|
sif.RegisterModule(MODULE_ID_2, &m_module593);
|
|
|
|
sif.RegisterModule(MODULE_ID_4, &m_module595);
|
2016-01-11 22:36:35 -05:00
|
|
|
sif.RegisterModule(MODULE_ID_5, &m_module596);
|
2012-03-11 20:16:15 +00:00
|
|
|
sif.RegisterModule(MODULE_ID_6, &m_module597);
|
|
|
|
sif.RegisterModule(MODULE_ID_7, &m_module59A);
|
|
|
|
sif.RegisterModule(MODULE_ID_8, &m_module59C);
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2012-03-11 20:16:15 +00:00
|
|
|
std::string CCdvdfsv::GetId() const
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
2012-03-11 20:16:15 +00:00
|
|
|
return "cdvdfsv";
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2012-03-11 20:16:15 +00:00
|
|
|
std::string CCdvdfsv::GetFunctionName(unsigned int) const
|
2008-11-30 02:30:05 +00:00
|
|
|
{
|
2012-03-11 20:16:15 +00:00
|
|
|
return "unknown";
|
2008-11-30 02:30:05 +00:00
|
|
|
}
|
|
|
|
|
2024-09-13 15:43:47 -04:00
|
|
|
void CCdvdfsv::CountTicks(uint32 ticks, CSifMan* sifMan)
|
2014-10-16 03:33:59 -04:00
|
|
|
{
|
|
|
|
if(m_pendingCommand != COMMAND_NONE)
|
|
|
|
{
|
2024-09-13 15:43:47 -04:00
|
|
|
m_pendingCommandDelay -= std::min<uint32>(m_pendingCommandDelay, ticks);
|
|
|
|
if(m_pendingCommandDelay != 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
static const uint32 sectorSize = 0x800;
|
|
|
|
|
2016-08-31 18:47:02 -04:00
|
|
|
uint8* eeRam = nullptr;
|
|
|
|
if(auto sifManPs2 = dynamic_cast<CSifManPs2*>(sifMan))
|
2014-10-16 03:33:59 -04:00
|
|
|
{
|
2016-08-31 18:47:02 -04:00
|
|
|
eeRam = sifManPs2->GetEeRam();
|
|
|
|
}
|
2014-10-16 03:33:59 -04:00
|
|
|
|
2016-08-31 18:47:02 -04:00
|
|
|
if(m_pendingCommand == COMMAND_READ)
|
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
if(m_opticalMedia != nullptr)
|
2014-10-16 03:33:59 -04:00
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
2014-10-16 03:33:59 -04:00
|
|
|
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
fileSystem->ReadBlock(m_pendingReadSector + i, eeRam + (m_pendingReadAddr + (i * sectorSize)));
|
2014-10-16 03:33:59 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(m_pendingCommand == COMMAND_READIOP)
|
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
if(m_opticalMedia != nullptr)
|
2014-10-16 03:33:59 -04:00
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
2014-10-16 03:33:59 -04:00
|
|
|
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
fileSystem->ReadBlock(m_pendingReadSector + i, m_iopRam + (m_pendingReadAddr + (i * sectorSize)));
|
2014-10-16 03:33:59 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-31 18:47:02 -04:00
|
|
|
else if(m_pendingCommand == COMMAND_STREAM_READ)
|
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
if(m_opticalMedia != nullptr)
|
2016-08-31 18:47:02 -04:00
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
2016-08-31 18:47:02 -04:00
|
|
|
for(unsigned int i = 0; i < m_pendingReadCount; i++)
|
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
fileSystem->ReadBlock(m_streamPos, eeRam + (m_pendingReadAddr + (i * sectorSize)));
|
2016-08-31 18:47:02 -04:00
|
|
|
m_streamPos++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-06-22 13:33:05 -04:00
|
|
|
else if(m_pendingCommand == COMMAND_NDISKREADY)
|
|
|
|
{
|
|
|
|
//Result already set, just return normally
|
|
|
|
}
|
2022-12-21 14:13:18 -05:00
|
|
|
else if(m_pendingCommand == COMMAND_READCHAIN)
|
|
|
|
{
|
|
|
|
//Nothing to do, everything has been read already
|
|
|
|
}
|
2014-10-16 03:33:59 -04:00
|
|
|
|
|
|
|
m_pendingCommand = COMMAND_NONE;
|
|
|
|
sifMan->SendCallReply(MODULE_ID_4, nullptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-16 19:54:38 -04:00
|
|
|
void CCdvdfsv::SetOpticalMedia(COpticalMedia* opticalMedia)
|
2008-11-10 01:46:02 +00:00
|
|
|
{
|
2017-05-16 19:54:38 -04:00
|
|
|
m_opticalMedia = opticalMedia;
|
2008-11-10 01:46:02 +00:00
|
|
|
}
|
|
|
|
|
2017-09-09 18:54:40 -04:00
|
|
|
void CCdvdfsv::LoadState(Framework::CZipArchiveReader& archive)
|
|
|
|
{
|
|
|
|
auto registerFile = CRegisterStateFile(*archive.BeginReadFile(STATE_FILENAME));
|
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
m_pendingCommand = static_cast<COMMAND>(registerFile.GetRegister32(STATE_PENDINGCOMMAND));
|
2017-09-09 18:54:40 -04:00
|
|
|
m_pendingReadSector = registerFile.GetRegister32(STATE_PENDINGREADSECTOR);
|
2018-04-30 21:01:23 +01:00
|
|
|
m_pendingReadCount = registerFile.GetRegister32(STATE_PENDINGREADCOUNT);
|
|
|
|
m_pendingReadAddr = registerFile.GetRegister32(STATE_PENDINGREADADDR);
|
2017-09-09 18:54:40 -04:00
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
m_streaming = registerFile.GetRegister32(STATE_STREAMING) != 0;
|
|
|
|
m_streamPos = registerFile.GetRegister32(STATE_STREAMPOS);
|
2017-09-09 18:54:40 -04:00
|
|
|
m_streamBufferSize = registerFile.GetRegister32(STATE_STREAMBUFFERSIZE);
|
|
|
|
}
|
|
|
|
|
2020-09-22 17:20:14 -04:00
|
|
|
void CCdvdfsv::SaveState(Framework::CZipArchiveWriter& archive) const
|
2017-09-09 18:54:40 -04:00
|
|
|
{
|
2023-07-23 17:22:18 -04:00
|
|
|
auto registerFile = std::make_unique<CRegisterStateFile>(STATE_FILENAME);
|
2017-09-09 18:54:40 -04:00
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
registerFile->SetRegister32(STATE_PENDINGCOMMAND, m_pendingCommand);
|
2017-09-09 18:54:40 -04:00
|
|
|
registerFile->SetRegister32(STATE_PENDINGREADSECTOR, m_pendingReadSector);
|
2018-04-30 21:01:23 +01:00
|
|
|
registerFile->SetRegister32(STATE_PENDINGREADCOUNT, m_pendingReadCount);
|
|
|
|
registerFile->SetRegister32(STATE_PENDINGREADADDR, m_pendingReadAddr);
|
2017-09-09 18:54:40 -04:00
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
registerFile->SetRegister32(STATE_STREAMING, m_streaming);
|
|
|
|
registerFile->SetRegister32(STATE_STREAMPOS, m_streamPos);
|
2017-09-09 18:54:40 -04:00
|
|
|
registerFile->SetRegister32(STATE_STREAMBUFFERSIZE, m_streamBufferSize);
|
|
|
|
|
2023-07-23 17:22:18 -04:00
|
|
|
archive.InsertFile(std::move(registerFile));
|
2017-09-09 18:54:40 -04:00
|
|
|
}
|
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
void CCdvdfsv::Invoke(CMIPS& context, unsigned int functionId)
|
|
|
|
{
|
2012-03-11 20:16:15 +00:00
|
|
|
throw std::runtime_error("Not implemented.");
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
bool CCdvdfsv::Invoke592(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
|
|
|
switch(method)
|
|
|
|
{
|
|
|
|
case 0:
|
2018-04-30 21:01:23 +01:00
|
|
|
{
|
|
|
|
//Init
|
|
|
|
assert(argsSize >= 4);
|
|
|
|
uint32 mode = args[0x00];
|
|
|
|
if(retSize != 0)
|
2012-03-11 20:16:15 +00:00
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
assert(retSize >= 0x10);
|
2020-05-10 16:27:23 +01:00
|
|
|
// ret[1]; // cdvdfsv Ver
|
|
|
|
// ret[2]; // cdvdman Ver
|
2018-04-30 21:01:23 +01:00
|
|
|
ret[0x03] = 0xFF;
|
2012-03-11 20:16:15 +00:00
|
|
|
}
|
2018-04-30 21:01:23 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Init(mode = %d);\r\n", mode);
|
|
|
|
}
|
|
|
|
break;
|
2008-01-20 23:08:56 +00:00
|
|
|
default:
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Unknown method invoked (0x%08X, 0x%08X).\r\n", 0x592, method);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-10-16 03:33:59 -04:00
|
|
|
return true;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
bool CCdvdfsv::Invoke593(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
|
|
|
switch(method)
|
|
|
|
{
|
2011-07-04 03:50:06 +00:00
|
|
|
case 0x01:
|
2018-04-30 21:01:23 +01:00
|
|
|
{
|
|
|
|
assert(retSize >= 0xC);
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ReadClock();\r\n");
|
2011-07-04 03:50:06 +00:00
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
auto clockBuffer = reinterpret_cast<uint8*>(ret + 1);
|
|
|
|
(*ret) = m_cdvdman.CdReadClockDirect(clockBuffer);
|
|
|
|
}
|
|
|
|
break;
|
2011-07-04 03:50:06 +00:00
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
case 0x03:
|
|
|
|
assert(retSize >= 4);
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "GetDiskType();\r\n");
|
2017-05-16 21:08:44 -04:00
|
|
|
ret[0x00] = m_cdvdman.CdGetDiskTypeDirect(m_opticalMedia);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x04:
|
|
|
|
assert(retSize >= 4);
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "GetError();\r\n");
|
|
|
|
ret[0x00] = 0x00;
|
|
|
|
break;
|
|
|
|
|
2017-03-02 18:29:40 -05:00
|
|
|
case 0x05:
|
2018-04-30 21:01:23 +01:00
|
|
|
{
|
|
|
|
assert(argsSize >= 4);
|
|
|
|
assert(retSize >= 8);
|
|
|
|
uint32 mode = args[0x00];
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "TrayReq(mode = %d);\r\n", mode);
|
|
|
|
ret[0x00] = 0x01; //Result
|
|
|
|
ret[0x01] = 0x00; //Tray check
|
|
|
|
}
|
|
|
|
break;
|
2017-03-02 18:29:40 -05:00
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
case 0x0C:
|
|
|
|
//Status
|
|
|
|
assert(retSize >= 4);
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Status();\r\n");
|
2017-05-19 22:27:40 -04:00
|
|
|
ret[0x00] = m_streaming ? CCdvdman::CDVD_STATUS_SEEK : CCdvdman::CDVD_STATUS_PAUSED;
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
|
2015-04-25 01:01:21 -04:00
|
|
|
case 0x16:
|
|
|
|
//Break
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Break();\r\n");
|
|
|
|
ret[0x00] = 1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
case 0x22:
|
2018-04-30 21:01:23 +01:00
|
|
|
{
|
|
|
|
//Set Media Mode (1 - CDROM, 2 - DVDROM)
|
|
|
|
assert(argsSize >= 4);
|
|
|
|
assert(retSize >= 4);
|
|
|
|
uint32 mode = args[0x00];
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SetMediaMode(mode = %i);\r\n", mode);
|
|
|
|
ret[0x00] = 1;
|
|
|
|
}
|
|
|
|
break;
|
2018-10-04 09:13:53 -04:00
|
|
|
case 0x27:
|
|
|
|
{
|
|
|
|
//ReadDvdDualInfo
|
2022-04-07 13:36:12 -04:00
|
|
|
assert(retSize >= 0x08);
|
2018-10-04 09:13:53 -04:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ReadDvdDualInfo();\r\n");
|
|
|
|
ret[0] = 1;
|
|
|
|
ret[1] = (m_opticalMedia && m_opticalMedia->GetDvdIsDualLayer()) ? 1 : 0;
|
2022-04-07 13:36:12 -04:00
|
|
|
//Some games (Xenosaga) have a different version of this call which returns only 8 bytes
|
|
|
|
if(retSize >= 0x0C)
|
|
|
|
{
|
|
|
|
ret[2] = m_opticalMedia ? m_opticalMedia->GetDvdSecondLayerStart() : 0;
|
|
|
|
}
|
2018-10-04 09:13:53 -04:00
|
|
|
}
|
|
|
|
break;
|
2008-01-20 23:08:56 +00:00
|
|
|
|
|
|
|
default:
|
2018-10-04 09:11:55 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Unknown method invoked (0x%08X, 0x%08X).\r\n", 0x593, method);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-10-16 03:33:59 -04:00
|
|
|
return true;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
bool CCdvdfsv::Invoke595(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
|
|
|
switch(method)
|
|
|
|
{
|
2013-03-05 08:21:13 +00:00
|
|
|
case 0x01:
|
2008-01-20 23:08:56 +00:00
|
|
|
Read(args, argsSize, ret, retSize, ram);
|
2014-10-16 03:33:59 -04:00
|
|
|
return false;
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
|
2013-03-05 08:21:13 +00:00
|
|
|
case 0x04:
|
2018-04-30 21:01:23 +01:00
|
|
|
{
|
|
|
|
//GetToc
|
|
|
|
assert(argsSize >= 4);
|
|
|
|
assert(retSize >= 4);
|
|
|
|
uint32 nBuffer = args[0x00];
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "GetToc(buffer = 0x%08X);\r\n", nBuffer);
|
|
|
|
ret[0x00] = 1;
|
|
|
|
}
|
|
|
|
break;
|
2008-01-20 23:08:56 +00:00
|
|
|
|
2013-03-05 08:21:13 +00:00
|
|
|
case 0x05:
|
2018-04-30 21:01:23 +01:00
|
|
|
{
|
|
|
|
assert(argsSize >= 4);
|
|
|
|
uint32 seekSector = args[0];
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Seek(sector = 0x%08X);\r\n", seekSector);
|
|
|
|
}
|
|
|
|
break;
|
2013-03-05 08:21:13 +00:00
|
|
|
|
2025-02-18 13:28:41 -05:00
|
|
|
case 0x08:
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Pause();\r\n");
|
|
|
|
assert(m_pendingCommand == COMMAND_NONE);
|
|
|
|
m_pendingCommand = COMMAND_PAUSE;
|
|
|
|
m_pendingCommandDelay = COMMAND_DEFAULT_DELAY;
|
|
|
|
return false;
|
|
|
|
|
2013-03-05 08:21:13 +00:00
|
|
|
case 0x09:
|
2016-08-31 18:47:02 -04:00
|
|
|
return StreamCmd(args, argsSize, ret, retSize, ram);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
|
2012-03-11 20:16:15 +00:00
|
|
|
case 0x0D:
|
|
|
|
ReadIopMem(args, argsSize, ret, retSize, ram);
|
2014-10-16 03:33:59 -04:00
|
|
|
return false;
|
2012-03-11 20:16:15 +00:00
|
|
|
break;
|
2009-02-27 02:34:17 +00:00
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
case 0x0E:
|
2018-06-22 13:33:05 -04:00
|
|
|
return NDiskReady(args, argsSize, ret, retSize, ram);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
|
2022-01-31 16:33:46 -05:00
|
|
|
case 0x0F:
|
|
|
|
ReadChain(args, argsSize, ret, retSize, ram);
|
2022-12-21 14:13:18 -05:00
|
|
|
return false;
|
2022-01-31 16:33:46 -05:00
|
|
|
break;
|
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
default:
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Unknown method invoked (0x%08X, 0x%08X).\r\n", 0x595, method);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-10-16 03:33:59 -04:00
|
|
|
return true;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 22:36:35 -05:00
|
|
|
bool CCdvdfsv::Invoke596(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
|
|
|
{
|
|
|
|
switch(method)
|
|
|
|
{
|
2024-02-22 11:23:53 -05:00
|
|
|
case 0x01:
|
|
|
|
//SetPowerOffCallback
|
|
|
|
//Some versions of the EE CDVD library will invoke this in CdInit. It seems to be called in a no-wait mode,
|
|
|
|
//and it's possible that the reply to this call is only sent once. Sending it always seems to cause
|
|
|
|
//problems in some games (Hunter x Hunter: Ryuumyaku no Saidan) that use CD callbacks and call CdInit
|
|
|
|
//many times.
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SetPowerOffCallback();\r\n");
|
|
|
|
return false;
|
|
|
|
break;
|
2016-01-11 22:36:35 -05:00
|
|
|
default:
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Unknown method invoked (0x%08X, 0x%08X).\r\n", 0x596, method);
|
2016-01-11 22:36:35 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
bool CCdvdfsv::Invoke597(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
|
|
|
switch(method)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
SearchFile(args, argsSize, ret, retSize, ram);
|
|
|
|
break;
|
|
|
|
default:
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Unknown method invoked (0x%08X, 0x%08X).\r\n", 0x597, method);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-10-16 03:33:59 -04:00
|
|
|
return true;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
bool CCdvdfsv::Invoke59A(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
2009-09-30 00:48:49 +00:00
|
|
|
{
|
2014-10-16 03:33:59 -04:00
|
|
|
return Invoke59C(method, args, argsSize, ret, retSize, ram);
|
2009-09-30 00:48:49 +00:00
|
|
|
}
|
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
bool CCdvdfsv::Invoke59C(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
|
|
|
switch(method)
|
|
|
|
{
|
|
|
|
case 0:
|
2018-04-30 21:01:23 +01:00
|
|
|
{
|
|
|
|
//DiskReady (returns 2 if ready, 6 if not ready)
|
|
|
|
assert(retSize >= 4);
|
|
|
|
assert(argsSize >= 4);
|
|
|
|
uint32 mode = args[0x00];
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "DiskReady(mode = %i);\r\n", mode);
|
|
|
|
ret[0x00] = 2;
|
|
|
|
}
|
|
|
|
break;
|
2008-01-20 23:08:56 +00:00
|
|
|
default:
|
2018-10-04 09:11:55 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Unknown method invoked (0x%08X, 0x%08X).\r\n", 0x59C, method);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-10-16 03:33:59 -04:00
|
|
|
return true;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CCdvdfsv::Read(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
uint32 sector = args[0x00];
|
|
|
|
uint32 count = args[0x01];
|
|
|
|
uint32 dstAddr = args[0x02];
|
|
|
|
uint32 mode = args[0x03];
|
2008-01-20 23:08:56 +00:00
|
|
|
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Read(sector = 0x%08X, count = 0x%08X, addr = 0x%08X, mode = 0x%08X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
sector, count, dstAddr, mode);
|
2008-01-20 23:08:56 +00:00
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
//We write the result now, but ideally should be only written
|
|
|
|
//when pending read is completed
|
2008-01-20 23:08:56 +00:00
|
|
|
if(retSize >= 4)
|
|
|
|
{
|
|
|
|
ret[0] = 0;
|
|
|
|
}
|
2013-03-05 08:21:13 +00:00
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
assert(m_pendingCommand == COMMAND_NONE);
|
|
|
|
m_pendingCommand = COMMAND_READ;
|
2024-09-13 15:43:47 -04:00
|
|
|
m_pendingCommandDelay = CCdvdman::COMMAND_READ_BASE_DELAY + (count * CCdvdman::COMMAND_READ_SECTOR_DELAY);
|
2014-10-16 03:33:59 -04:00
|
|
|
m_pendingReadSector = sector;
|
|
|
|
m_pendingReadCount = count;
|
2015-02-08 05:15:43 -05:00
|
|
|
m_pendingReadAddr = dstAddr & 0x1FFFFFFF;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
|
|
|
|
2009-02-27 02:34:17 +00:00
|
|
|
void CCdvdfsv::ReadIopMem(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
uint32 sector = args[0x00];
|
|
|
|
uint32 count = args[0x01];
|
|
|
|
uint32 dstAddr = args[0x02];
|
|
|
|
uint32 mode = args[0x03];
|
2014-10-15 03:22:14 -04:00
|
|
|
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ReadIopMem(sector = 0x%08X, count = 0x%08X, addr = 0x%08X, mode = 0x%08X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
sector, count, dstAddr, mode);
|
2014-10-15 03:22:14 -04:00
|
|
|
|
2012-03-11 20:16:15 +00:00
|
|
|
if(retSize >= 4)
|
|
|
|
{
|
|
|
|
ret[0] = 0;
|
|
|
|
}
|
2013-03-05 08:21:13 +00:00
|
|
|
|
2014-10-16 03:33:59 -04:00
|
|
|
assert(m_pendingCommand == COMMAND_NONE);
|
|
|
|
m_pendingCommand = COMMAND_READIOP;
|
2024-09-13 15:43:47 -04:00
|
|
|
m_pendingCommandDelay = COMMAND_DEFAULT_DELAY;
|
2014-10-16 03:33:59 -04:00
|
|
|
m_pendingReadSector = sector;
|
|
|
|
m_pendingReadCount = count;
|
2015-02-08 05:15:43 -05:00
|
|
|
m_pendingReadAddr = dstAddr & 0x1FFFFFFF;
|
2009-02-27 02:34:17 +00:00
|
|
|
}
|
|
|
|
|
2016-08-31 18:47:02 -04:00
|
|
|
bool CCdvdfsv::StreamCmd(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
2016-08-31 18:47:02 -04:00
|
|
|
bool immediateReply = true;
|
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
uint32 sector = args[0x00];
|
|
|
|
uint32 count = args[0x01];
|
|
|
|
uint32 dstAddr = args[0x02];
|
|
|
|
uint32 cmd = args[0x03];
|
|
|
|
uint32 mode = args[0x04];
|
2008-01-20 23:08:56 +00:00
|
|
|
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StreamCmd(sector = 0x%08X, count = 0x%08X, addr = 0x%08X, cmd = 0x%08X, mode = 0x%08X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
sector, count, dstAddr, cmd, mode);
|
2008-01-20 23:08:56 +00:00
|
|
|
|
2016-08-31 18:47:02 -04:00
|
|
|
assert(m_pendingCommand == COMMAND_NONE);
|
|
|
|
|
2014-10-15 03:22:14 -04:00
|
|
|
switch(cmd)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
//Start
|
2014-10-15 03:22:14 -04:00
|
|
|
m_streamPos = sector;
|
2008-01-20 23:08:56 +00:00
|
|
|
ret[0] = 1;
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StreamStart(pos = 0x%08X);\r\n", sector);
|
2016-02-20 22:30:52 -05:00
|
|
|
m_streaming = true;
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
//Read
|
2018-04-30 21:01:23 +01:00
|
|
|
m_pendingCommand = COMMAND_STREAM_READ;
|
2024-09-13 15:43:47 -04:00
|
|
|
m_pendingCommandDelay = COMMAND_DEFAULT_DELAY;
|
2016-08-31 18:47:02 -04:00
|
|
|
m_pendingReadSector = 0;
|
2018-04-30 21:01:23 +01:00
|
|
|
m_pendingReadCount = count;
|
|
|
|
m_pendingReadAddr = dstAddr & (PS2::EE_RAM_SIZE - 1);
|
2014-10-15 03:22:14 -04:00
|
|
|
ret[0] = count;
|
2016-08-31 18:47:02 -04:00
|
|
|
immediateReply = false;
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StreamRead(count = 0x%08X, dest = 0x%08X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
count, dstAddr);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
2014-05-03 00:47:57 -04:00
|
|
|
case 3:
|
|
|
|
//Stop
|
|
|
|
ret[0] = 1;
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StreamStop();\r\n");
|
2016-02-20 22:30:52 -05:00
|
|
|
m_streaming = false;
|
2014-05-03 00:47:57 -04:00
|
|
|
break;
|
2008-01-20 23:08:56 +00:00
|
|
|
case 5:
|
|
|
|
//Init
|
|
|
|
ret[0] = 1;
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StreamInit(bufsize = 0x%08X, numbuf = 0x%08X, buf = 0x%08X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
sector, count, dstAddr);
|
2017-05-20 22:36:49 -04:00
|
|
|
m_streamBufferSize = sector;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
//Status
|
|
|
|
ret[0] = m_streamBufferSize;
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StreamStat();\r\n");
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
case 9:
|
|
|
|
//Seek
|
2014-10-15 03:22:14 -04:00
|
|
|
m_streamPos = sector;
|
2008-01-20 23:08:56 +00:00
|
|
|
ret[0] = 1;
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "StreamSeek(pos = 0x%08X);\r\n", sector);
|
2008-01-20 23:08:56 +00:00
|
|
|
break;
|
2012-03-11 20:16:15 +00:00
|
|
|
default:
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Unknown stream command used.\r\n");
|
2012-03-11 20:16:15 +00:00
|
|
|
break;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
2016-08-31 18:47:02 -04:00
|
|
|
|
|
|
|
return immediateReply;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
2018-06-22 13:33:05 -04:00
|
|
|
|
|
|
|
bool CCdvdfsv::NDiskReady(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
|
|
|
{
|
|
|
|
//DiskReady (returns 2 if ready, 6 if not ready)
|
|
|
|
assert(retSize >= 4);
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "NDiskReady();\r\n");
|
|
|
|
if(m_pendingCommand != COMMAND_NONE)
|
|
|
|
{
|
|
|
|
ret[0x00] = 6;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-01-29 07:43:32 -05:00
|
|
|
//Delay command (required by Downhill Domination)
|
2018-06-22 13:33:05 -04:00
|
|
|
m_pendingCommand = COMMAND_NDISKREADY;
|
2024-09-13 15:43:47 -04:00
|
|
|
m_pendingCommandDelay = COMMAND_DEFAULT_DELAY;
|
2018-06-22 13:33:05 -04:00
|
|
|
ret[0x00] = 2;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2008-01-20 23:08:56 +00:00
|
|
|
|
2022-01-31 16:33:46 -05:00
|
|
|
void CCdvdfsv::ReadChain(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
|
|
|
{
|
|
|
|
assert(argsSize >= 788);
|
|
|
|
assert(retSize == 0);
|
|
|
|
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "ReadChain(...);\r\n");
|
|
|
|
|
|
|
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
|
|
|
static const uint32 sectorSize = 0x800;
|
|
|
|
|
|
|
|
static const uint32 maxTupleCount = 64;
|
|
|
|
for(uint32 tuple = 0; tuple < maxTupleCount; tuple++)
|
|
|
|
{
|
|
|
|
uint32 tupleBase = (tuple * 3);
|
|
|
|
uint32 sectorPos = args[tupleBase + 0];
|
|
|
|
uint32 sectorCount = args[tupleBase + 1];
|
|
|
|
uint32 dstAddress = args[tupleBase + 2];
|
|
|
|
if((sectorPos == ~0U) || (sectorCount == ~0U) || (dstAddress == ~0U))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
assert((dstAddress & 1) == 0);
|
|
|
|
for(unsigned int sector = 0; sector < sectorCount; sector++)
|
|
|
|
{
|
|
|
|
fileSystem->ReadBlock(sectorPos + sector, ram + (dstAddress + (sector * sectorSize)));
|
|
|
|
}
|
|
|
|
}
|
2022-12-21 14:13:18 -05:00
|
|
|
|
|
|
|
//DBZ: Budokai Tenkaichi hangs in its loading screen if this command's result is not delayed.
|
|
|
|
m_pendingCommand = COMMAND_READCHAIN;
|
2024-09-13 15:43:47 -04:00
|
|
|
m_pendingCommandDelay = COMMAND_DEFAULT_DELAY;
|
2022-01-31 16:33:46 -05:00
|
|
|
}
|
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
void CCdvdfsv::SearchFile(uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
|
|
|
{
|
2018-10-08 00:04:04 -04:00
|
|
|
uint32 layer = 0;
|
2012-04-14 21:18:59 +00:00
|
|
|
uint32 pathOffset = 0x24;
|
|
|
|
if(argsSize == 0x128)
|
|
|
|
{
|
|
|
|
pathOffset = 0x24;
|
|
|
|
}
|
|
|
|
else if(argsSize == 0x124)
|
|
|
|
{
|
|
|
|
pathOffset = 0x20;
|
|
|
|
}
|
2018-10-08 00:04:04 -04:00
|
|
|
else if(argsSize == 0x12C)
|
|
|
|
{
|
|
|
|
//Used by:
|
|
|
|
//- Xenosaga (dual layer)
|
|
|
|
pathOffset = 0x24;
|
|
|
|
layer = args[0x128 / 4];
|
|
|
|
}
|
2012-04-14 21:18:59 +00:00
|
|
|
else
|
|
|
|
{
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Warning: Using unknown structure size (%d bytes);\r\n", argsSize);
|
2012-04-14 21:18:59 +00:00
|
|
|
}
|
|
|
|
|
2008-01-20 23:08:56 +00:00
|
|
|
assert(retSize == 4);
|
|
|
|
|
2017-05-16 19:54:38 -04:00
|
|
|
if(!m_opticalMedia)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
|
|
|
ret[0] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//0x12C structure
|
|
|
|
//00 - Block Num
|
|
|
|
//04 - Size
|
|
|
|
//08
|
|
|
|
//0C
|
|
|
|
//10
|
|
|
|
//14
|
|
|
|
//18
|
|
|
|
//1C
|
|
|
|
//20 - Unknown
|
|
|
|
//24 - Path
|
|
|
|
|
2015-02-01 05:08:08 -05:00
|
|
|
const char* path = reinterpret_cast<const char*>(args) + pathOffset;
|
2018-10-08 00:04:04 -04:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "SearchFile(layer = %d, path = '%s');\r\n", layer, path);
|
2008-01-20 23:08:56 +00:00
|
|
|
|
2021-03-19 11:41:11 -04:00
|
|
|
CCdvdman::FILEINFO fileInfo = {};
|
|
|
|
uint32 result = m_cdvdman.CdLayerSearchFileDirect(m_opticalMedia, &fileInfo, path, layer);
|
|
|
|
if(result)
|
2008-01-20 23:08:56 +00:00
|
|
|
{
|
2021-03-19 11:41:11 -04:00
|
|
|
args[0x00] = fileInfo.sector;
|
|
|
|
args[0x01] = fileInfo.size;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|
2021-03-19 11:41:11 -04:00
|
|
|
ret[0] = result;
|
2008-01-20 23:08:56 +00:00
|
|
|
}
|