2008-08-24 21:28:42 +00:00
|
|
|
#include "../AppConfig.h"
|
2008-01-15 20:27:44 +00:00
|
|
|
#include "Iop_Ioman.h"
|
|
|
|
#include "StdStream.h"
|
2014-08-07 02:34:03 -04:00
|
|
|
#include "../Log.h"
|
2008-01-15 20:27:44 +00:00
|
|
|
#include <stdexcept>
|
2018-04-19 09:14:30 -04:00
|
|
|
#include <cctype>
|
2008-01-15 20:27:44 +00:00
|
|
|
|
|
|
|
using namespace Iop;
|
|
|
|
|
2014-08-07 02:34:03 -04:00
|
|
|
#define LOG_NAME "iop_ioman"
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
#define PREF_IOP_FILEIO_STDLOGGING ("iop.fileio.stdlogging")
|
|
|
|
|
2018-04-30 21:01:23 +01:00
|
|
|
#define FUNCTION_ADDDRV "AddDrv"
|
|
|
|
#define FUNCTION_DELDRV "DelDrv"
|
2016-12-08 00:25:07 -05:00
|
|
|
|
2018-09-20 19:18:55 -04:00
|
|
|
//Directories have "group read" only permissions? This is required by PS2PSXe.
|
|
|
|
#define STAT_MODE_DIR (0747 | (1 << 12)) //File mode + Dir type (1)
|
|
|
|
#define STAT_MODE_FILE (0777 | (2 << 12)) //File mode + File type (2)
|
|
|
|
|
2018-04-19 09:14:30 -04:00
|
|
|
static std::string RightTrim(std::string inputString)
|
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
auto nonSpaceEnd = std::find_if(inputString.rbegin(), inputString.rend(), [](int ch) { return !std::isspace(ch); });
|
2018-04-19 09:14:30 -04:00
|
|
|
inputString.erase(nonSpaceEnd.base(), inputString.end());
|
|
|
|
return inputString;
|
|
|
|
}
|
|
|
|
|
2018-09-20 19:19:25 -04:00
|
|
|
struct PATHINFO
|
|
|
|
{
|
|
|
|
std::string deviceName;
|
|
|
|
std::string devicePath;
|
|
|
|
};
|
|
|
|
|
|
|
|
static PATHINFO SplitPath(const char* path)
|
|
|
|
{
|
|
|
|
std::string fullPath(path);
|
|
|
|
auto position = fullPath.find(":");
|
|
|
|
if(position == std::string::npos)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Invalid path.");
|
|
|
|
}
|
|
|
|
PATHINFO result;
|
|
|
|
result.deviceName = std::string(fullPath.begin(), fullPath.begin() + position);
|
|
|
|
result.devicePath = std::string(fullPath.begin() + position + 1, fullPath.end());
|
|
|
|
//Some games (Street Fighter EX3) provide paths with trailing spaces
|
|
|
|
result.devicePath = RightTrim(result.devicePath);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2016-12-07 21:59:07 -05:00
|
|
|
CIoman::CIoman(uint8* ram)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_ram(ram)
|
|
|
|
, m_nextFileHandle(3)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2008-08-24 21:28:42 +00:00
|
|
|
CAppConfig::GetInstance().RegisterPreferenceBoolean(PREF_IOP_FILEIO_STDLOGGING, false);
|
2008-01-15 20:27:44 +00:00
|
|
|
|
|
|
|
//Insert standard files if requested.
|
2014-08-02 21:18:07 -04:00
|
|
|
if(CAppConfig::GetInstance().GetPreferenceBoolean(PREF_IOP_FILEIO_STDLOGGING)
|
|
|
|
#ifdef DEBUGGER_INCLUDED
|
2018-04-30 21:01:23 +01:00
|
|
|
|| true
|
2014-08-02 21:18:07 -04:00
|
|
|
#endif
|
2018-04-30 21:01:23 +01:00
|
|
|
)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2014-08-02 21:18:07 -04:00
|
|
|
auto stdoutPath = CAppConfig::GetBasePath() / "ps2_stdout.txt";
|
|
|
|
auto stderrPath = CAppConfig::GetBasePath() / "ps2_stderr.txt";
|
|
|
|
|
|
|
|
m_files[FID_STDOUT] = new Framework::CStdStream(fopen(stdoutPath.string().c_str(), "ab"));
|
|
|
|
m_files[FID_STDERR] = new Framework::CStdStream(fopen(stderrPath.string().c_str(), "ab"));
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
|
|
|
//Humm, some error occured when opening these files...
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CIoman::~CIoman()
|
|
|
|
{
|
2012-05-26 18:37:09 +00:00
|
|
|
for(auto fileIterator(std::begin(m_files));
|
2018-04-30 21:01:23 +01:00
|
|
|
std::end(m_files) != fileIterator; fileIterator++)
|
2012-05-26 18:37:09 +00:00
|
|
|
{
|
|
|
|
delete fileIterator->second;
|
|
|
|
}
|
2008-11-04 03:47:36 +00:00
|
|
|
m_devices.clear();
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string CIoman::GetId() const
|
|
|
|
{
|
2012-05-26 18:37:09 +00:00
|
|
|
return "ioman";
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
std::string CIoman::GetFunctionName(unsigned int functionId) const
|
2008-11-28 23:46:52 +00:00
|
|
|
{
|
2012-11-10 22:53:43 +00:00
|
|
|
switch(functionId)
|
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
return "open";
|
|
|
|
break;
|
2016-01-09 18:47:54 -05:00
|
|
|
case 5:
|
|
|
|
return "close";
|
|
|
|
break;
|
2012-11-10 22:53:43 +00:00
|
|
|
case 6:
|
|
|
|
return "read";
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
return "seek";
|
|
|
|
break;
|
2016-07-09 21:20:52 -04:00
|
|
|
case 16:
|
|
|
|
return "getstat";
|
|
|
|
break;
|
2016-12-08 00:25:07 -05:00
|
|
|
case 20:
|
|
|
|
return FUNCTION_ADDDRV;
|
|
|
|
break;
|
|
|
|
case 21:
|
|
|
|
return FUNCTION_DELDRV;
|
|
|
|
break;
|
2012-11-10 22:53:43 +00:00
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
break;
|
|
|
|
}
|
2008-11-28 23:46:52 +00:00
|
|
|
}
|
|
|
|
|
2008-11-04 03:47:36 +00:00
|
|
|
void CIoman::RegisterDevice(const char* name, const DevicePtr& device)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2012-05-26 18:37:09 +00:00
|
|
|
m_devices[name] = device;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CIoman::Open(uint32 flags, const char* path)
|
|
|
|
{
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Open(flags = 0x%08X, path = '%s');\r\n", flags, path);
|
2014-08-07 02:34:03 -04:00
|
|
|
|
2016-08-12 22:29:01 -04:00
|
|
|
if(flags == 0)
|
|
|
|
{
|
|
|
|
//If no flags provided, assume we want to open the file
|
|
|
|
//Required by Capcom Arcade Collection
|
|
|
|
flags = Ioman::CDevice::OPEN_FLAG_RDONLY;
|
|
|
|
}
|
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
uint32 handle = 0xFFFFFFFF;
|
|
|
|
try
|
|
|
|
{
|
2018-09-20 19:19:25 -04:00
|
|
|
auto pathInfo = SplitPath(path);
|
|
|
|
auto deviceIterator = m_devices.find(pathInfo.deviceName);
|
2016-12-31 20:03:10 -05:00
|
|
|
if(deviceIterator == m_devices.end())
|
2012-05-26 18:37:09 +00:00
|
|
|
{
|
|
|
|
throw std::runtime_error("Device not found.");
|
|
|
|
}
|
2018-09-20 19:19:25 -04:00
|
|
|
auto stream = deviceIterator->second->GetFile(flags, pathInfo.devicePath.c_str());
|
2016-12-31 20:03:10 -05:00
|
|
|
if(!stream)
|
2012-05-26 18:37:09 +00:00
|
|
|
{
|
|
|
|
throw std::runtime_error("File not found.");
|
|
|
|
}
|
|
|
|
handle = m_nextFileHandle++;
|
|
|
|
m_files[handle] = stream;
|
|
|
|
}
|
|
|
|
catch(const std::exception& except)
|
|
|
|
{
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "%s: Error occured while trying to open file : %s\r\n", __FUNCTION__, except.what());
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
return handle;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CIoman::Close(uint32 handle)
|
|
|
|
{
|
2014-08-07 02:34:03 -04:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Close(handle = %d);\r\n", handle);
|
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
uint32 result = 0xFFFFFFFF;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
auto file(m_files.find(handle));
|
|
|
|
if(file == std::end(m_files))
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Invalid file handle.");
|
|
|
|
}
|
|
|
|
delete file->second;
|
|
|
|
m_files.erase(file);
|
2016-12-11 16:57:50 -05:00
|
|
|
//Returns handle instead of 0 (needed by Naruto: Ultimate Ninja 2)
|
|
|
|
result = handle;
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
catch(const std::exception& except)
|
|
|
|
{
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "%s: Error occured while trying to close file : %s\r\n", __FUNCTION__, except.what());
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
return result;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CIoman::Read(uint32 handle, uint32 size, void* buffer)
|
|
|
|
{
|
2014-08-07 02:34:03 -04:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Read(handle = %d, size = 0x%X, buffer = ptr);\r\n", handle, size);
|
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
uint32 result = 0xFFFFFFFF;
|
|
|
|
try
|
|
|
|
{
|
2018-04-09 09:41:12 -04:00
|
|
|
auto stream = GetFileStream(handle);
|
2018-02-06 19:03:31 -05:00
|
|
|
if(stream->IsEOF())
|
|
|
|
{
|
|
|
|
result = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = static_cast<uint32>(stream->Read(buffer, size));
|
|
|
|
}
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
catch(const std::exception& except)
|
|
|
|
{
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "%s: Error occured while trying to read file : %s\r\n", __FUNCTION__, except.what());
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
return result;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2014-08-02 21:18:07 -04:00
|
|
|
uint32 CIoman::Write(uint32 handle, uint32 size, const void* buffer)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2014-08-07 02:34:03 -04:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Write(handle = %d, size = 0x%X, buffer = ptr);\r\n", handle, size);
|
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
uint32 result = 0xFFFFFFFF;
|
|
|
|
try
|
|
|
|
{
|
2018-04-09 09:41:12 -04:00
|
|
|
auto stream = GetFileStream(handle);
|
2012-05-26 18:37:09 +00:00
|
|
|
result = static_cast<uint32>(stream->Write(buffer, size));
|
2014-08-02 21:18:07 -04:00
|
|
|
if((handle == FID_STDOUT) || (handle == FID_STDERR))
|
|
|
|
{
|
|
|
|
//Force flusing stdout and stderr
|
|
|
|
stream->Flush();
|
|
|
|
}
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
catch(const std::exception& except)
|
|
|
|
{
|
2014-08-02 21:18:07 -04:00
|
|
|
if((handle != FID_STDOUT) && (handle != FID_STDERR))
|
|
|
|
{
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "%s: Error occured while trying to write file : %s\r\n", __FUNCTION__, except.what());
|
2014-08-02 21:18:07 -04:00
|
|
|
}
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
return result;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CIoman::Seek(uint32 handle, uint32 position, uint32 whence)
|
|
|
|
{
|
2018-04-30 21:01:23 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Seek(handle = %d, position = 0x%X, whence = %d);\r\n",
|
|
|
|
handle, position, whence);
|
2014-08-07 02:34:03 -04:00
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
uint32 result = 0xFFFFFFFF;
|
|
|
|
try
|
|
|
|
{
|
2018-04-09 09:41:12 -04:00
|
|
|
auto stream = GetFileStream(handle);
|
2012-05-26 18:37:09 +00:00
|
|
|
switch(whence)
|
|
|
|
{
|
2014-11-08 21:44:56 -05:00
|
|
|
case SEEK_DIR_SET:
|
2012-05-26 18:37:09 +00:00
|
|
|
whence = Framework::STREAM_SEEK_SET;
|
|
|
|
break;
|
2014-11-08 21:44:56 -05:00
|
|
|
case SEEK_DIR_CUR:
|
2012-05-26 18:37:09 +00:00
|
|
|
whence = Framework::STREAM_SEEK_CUR;
|
|
|
|
break;
|
2014-11-08 21:44:56 -05:00
|
|
|
case SEEK_DIR_END:
|
2012-05-26 18:37:09 +00:00
|
|
|
whence = Framework::STREAM_SEEK_END;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->Seek(position, static_cast<Framework::STREAM_SEEK_DIRECTION>(whence));
|
|
|
|
result = static_cast<uint32>(stream->Tell());
|
|
|
|
}
|
|
|
|
catch(const std::exception& except)
|
|
|
|
{
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "%s: Error occured while trying to seek file : %s\r\n", __FUNCTION__, except.what());
|
2012-05-26 18:37:09 +00:00
|
|
|
}
|
|
|
|
return result;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2018-09-20 19:05:24 -04:00
|
|
|
int32 CIoman::Dopen(const char* path)
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Dopen(path = '%s');\r\n",
|
|
|
|
path);
|
|
|
|
int32 handle = -1;
|
|
|
|
try
|
|
|
|
{
|
2018-09-20 19:19:25 -04:00
|
|
|
auto pathInfo = SplitPath(path);
|
|
|
|
auto deviceIterator = m_devices.find(pathInfo.deviceName);
|
2018-09-20 19:05:24 -04:00
|
|
|
if(deviceIterator == m_devices.end())
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Device not found.");
|
|
|
|
}
|
2018-09-20 19:19:25 -04:00
|
|
|
auto directory = deviceIterator->second->GetDirectory(pathInfo.devicePath.c_str());
|
2018-09-20 19:05:24 -04:00
|
|
|
handle = m_nextFileHandle++;
|
|
|
|
m_directories[handle] = directory;
|
|
|
|
}
|
|
|
|
catch(const std::exception& except)
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "%s: Error occured while trying to open directory : %s\r\n", __FUNCTION__, except.what());
|
|
|
|
}
|
|
|
|
return handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32 CIoman::Dclose(uint32 handle)
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Dclose(handle = %d);\r\n",
|
|
|
|
handle);
|
|
|
|
|
|
|
|
auto directoryIterator = m_directories.find(handle);
|
|
|
|
if(directoryIterator == std::end(m_directories))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_directories.erase(directoryIterator);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32 CIoman::Dread(uint32 handle, DIRENTRY* dirEntry)
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "Dread(handle = %d, entry = ptr);\r\n",
|
|
|
|
handle);
|
|
|
|
|
|
|
|
auto directoryIterator = m_directories.find(handle);
|
|
|
|
if(directoryIterator == std::end(m_directories))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto& directory = directoryIterator->second;
|
|
|
|
if(directory == Ioman::Directory())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto itemPath = directory->path();
|
|
|
|
auto name = itemPath.leaf().string();
|
|
|
|
strncpy(dirEntry->name, name.c_str(), DIRENTRY::NAME_SIZE);
|
|
|
|
dirEntry->name[DIRENTRY::NAME_SIZE - 1] = 0;
|
|
|
|
|
|
|
|
auto& stat = dirEntry->stat;
|
|
|
|
memset(&stat, 0, sizeof(STAT));
|
|
|
|
if(boost::filesystem::is_directory(itemPath))
|
|
|
|
{
|
2018-09-20 19:18:55 -04:00
|
|
|
stat.mode = STAT_MODE_DIR;
|
2018-09-20 19:05:24 -04:00
|
|
|
stat.attr = 0x8427;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-20 19:18:55 -04:00
|
|
|
stat.mode = STAT_MODE_FILE;
|
2018-09-20 19:05:24 -04:00
|
|
|
stat.loSize = boost::filesystem::file_size(itemPath);
|
|
|
|
stat.attr = 0x8497;
|
|
|
|
}
|
|
|
|
|
|
|
|
directory++;
|
|
|
|
|
|
|
|
return strlen(dirEntry->name);
|
|
|
|
}
|
|
|
|
|
2015-12-29 17:42:02 -05:00
|
|
|
uint32 CIoman::GetStat(const char* path, STAT* stat)
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Print(LOG_NAME, "GetStat(path = '%s', stat = ptr);\r\n", path);
|
|
|
|
|
2018-09-20 19:18:55 -04:00
|
|
|
//Try with a file
|
2015-12-29 17:42:02 -05:00
|
|
|
{
|
2018-09-20 19:18:55 -04:00
|
|
|
int32 fd = Open(Ioman::CDevice::OPEN_FLAG_RDONLY, path);
|
|
|
|
if(fd >= 0)
|
|
|
|
{
|
|
|
|
uint32 size = Seek(fd, 0, SEEK_DIR_END);
|
|
|
|
Close(fd);
|
|
|
|
memset(stat, 0, sizeof(STAT));
|
|
|
|
stat->mode = STAT_MODE_FILE;
|
|
|
|
stat->loSize = size;
|
|
|
|
return 0;
|
|
|
|
}
|
2015-12-29 17:42:02 -05:00
|
|
|
}
|
2018-09-20 19:18:55 -04:00
|
|
|
|
|
|
|
//Try with a directory
|
|
|
|
{
|
|
|
|
int32 fd = Dopen(path);
|
|
|
|
if(fd >= 0)
|
|
|
|
{
|
|
|
|
Dclose(fd);
|
|
|
|
memset(stat, 0, sizeof(STAT));
|
|
|
|
stat->mode = STAT_MODE_DIR;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
2015-12-29 17:42:02 -05:00
|
|
|
}
|
|
|
|
|
2012-05-29 01:08:09 +00:00
|
|
|
uint32 CIoman::AddDrv(uint32 drvPtr)
|
|
|
|
{
|
2017-05-29 06:01:32 +01:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, FUNCTION_ADDDRV "(drvPtr = 0x%08X);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
drvPtr);
|
2012-05-29 01:08:09 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-12-09 09:43:29 -05:00
|
|
|
uint32 CIoman::DelDrv(uint32 drvNamePtr)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2016-12-09 09:43:29 -05:00
|
|
|
CLog::GetInstance().Print(LOG_NAME, FUNCTION_DELDRV "(drvNamePtr = %s);\r\n",
|
2018-04-30 21:01:23 +01:00
|
|
|
PrintStringParameter(m_ram, drvNamePtr).c_str());
|
2012-05-26 18:37:09 +00:00
|
|
|
return -1;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
Framework::CStream* CIoman::GetFileStream(uint32 handle)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2012-05-26 18:37:09 +00:00
|
|
|
auto file(m_files.find(handle));
|
|
|
|
if(file == std::end(m_files))
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Invalid file handle.");
|
|
|
|
}
|
|
|
|
return file->second;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2015-04-10 00:07:32 -04:00
|
|
|
void CIoman::SetFileStream(uint32 handle, Framework::CStream* stream)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto prevStreamIterator = m_files.find(handle);
|
|
|
|
if(prevStreamIterator != std::end(m_files))
|
|
|
|
{
|
|
|
|
delete prevStreamIterator->second;
|
|
|
|
m_files.erase(prevStreamIterator);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_files[handle] = stream;
|
|
|
|
}
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
//IOP Invoke
|
|
|
|
void CIoman::Invoke(CMIPS& context, unsigned int functionId)
|
|
|
|
{
|
2012-05-26 18:37:09 +00:00
|
|
|
switch(functionId)
|
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Open(
|
2018-04-30 21:01:23 +01:00
|
|
|
context.m_State.nGPR[CMIPS::A1].nV[0],
|
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV[0]])));
|
2012-05-26 18:37:09 +00:00
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Close(
|
2018-04-30 21:01:23 +01:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV[0]));
|
2012-05-26 18:37:09 +00:00
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Read(
|
2018-04-30 21:01:23 +01:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV[0],
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV[0],
|
|
|
|
&m_ram[context.m_State.nGPR[CMIPS::A1].nV[0]]));
|
2012-05-26 18:37:09 +00:00
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Seek(
|
2018-04-30 21:01:23 +01:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV[0],
|
|
|
|
context.m_State.nGPR[CMIPS::A1].nV[0],
|
|
|
|
context.m_State.nGPR[CMIPS::A2].nV[0]));
|
2012-05-26 18:37:09 +00:00
|
|
|
break;
|
2016-07-09 21:20:52 -04:00
|
|
|
case 16:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(GetStat(
|
2018-04-30 21:01:23 +01:00
|
|
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV[0]]),
|
|
|
|
reinterpret_cast<STAT*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV[0]])));
|
2016-07-09 21:20:52 -04:00
|
|
|
break;
|
2012-05-29 01:08:09 +00:00
|
|
|
case 20:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(AddDrv(
|
2018-04-30 21:01:23 +01:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0));
|
2012-05-29 01:08:09 +00:00
|
|
|
break;
|
2012-05-26 18:37:09 +00:00
|
|
|
case 21:
|
|
|
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(DelDrv(
|
2018-04-30 21:01:23 +01:00
|
|
|
context.m_State.nGPR[CMIPS::A0].nV0));
|
2012-05-26 18:37:09 +00:00
|
|
|
break;
|
|
|
|
default:
|
2018-05-24 12:59:15 -04:00
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "%s(%08X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
2012-05-26 18:37:09 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 04:14:13 +00:00
|
|
|
//--------------------------------------------------
|
|
|
|
// CFile
|
|
|
|
//--------------------------------------------------
|
|
|
|
|
2012-05-26 18:37:09 +00:00
|
|
|
CIoman::CFile::CFile(uint32 handle, CIoman& ioman)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_handle(handle)
|
|
|
|
, m_ioman(ioman)
|
2008-10-20 04:14:13 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CIoman::CFile::~CFile()
|
|
|
|
{
|
2012-05-26 18:37:09 +00:00
|
|
|
m_ioman.Close(m_handle);
|
2008-10-20 04:14:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CIoman::CFile::operator uint32()
|
|
|
|
{
|
2012-05-26 18:37:09 +00:00
|
|
|
return m_handle;
|
2008-10-20 04:14:13 +00:00
|
|
|
}
|