mirror of
https://github.com/libretro/Play-.git
synced 2025-02-19 19:10:42 +00:00
Add basic support for directory read functions in IOMAN.
This commit is contained in:
parent
2dcc319b2b
commit
c7eca744bd
@ -62,3 +62,14 @@ Framework::CStream* CDirectoryDevice::GetFile(uint32 accessType, const char* dev
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Directory CDirectoryDevice::GetDirectory(const char* devicePath)
|
||||
{
|
||||
auto basePath = CAppConfig::GetInstance().GetPreferencePath(m_basePathPreferenceName.c_str());
|
||||
auto path = basePath / devicePath;
|
||||
if(!boost::filesystem::is_directory(path))
|
||||
{
|
||||
throw std::runtime_error("Not a directory.");
|
||||
}
|
||||
return boost::filesystem::directory_iterator(path);
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ namespace Iop
|
||||
public:
|
||||
CDirectoryDevice(const char*);
|
||||
virtual ~CDirectoryDevice() = default;
|
||||
|
||||
Framework::CStream* GetFile(uint32, const char*) override;
|
||||
Directory GetDirectory(const char*) override;
|
||||
|
||||
private:
|
||||
std::string m_basePathPreferenceName;
|
||||
|
@ -1,11 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
namespace Ioman
|
||||
{
|
||||
typedef boost::filesystem::directory_iterator Directory;
|
||||
|
||||
class CDevice
|
||||
{
|
||||
public:
|
||||
@ -22,6 +25,7 @@ namespace Iop
|
||||
|
||||
virtual ~CDevice() = default;
|
||||
virtual Framework::CStream* GetFile(uint32, const char*) = 0;
|
||||
virtual Directory GetDirectory(const char*) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,18 @@ void CFileIoHandler1000::Invoke(uint32 method, uint32* args, uint32 argsSize, ui
|
||||
assert(retSize == 4);
|
||||
*ret = m_ioman->Seek(args[0], args[1], args[2]);
|
||||
break;
|
||||
case 9:
|
||||
assert(retSize == 4);
|
||||
*ret = m_ioman->Dopen(reinterpret_cast<const char*>(&args[0]));
|
||||
break;
|
||||
case 10:
|
||||
assert(retSize == 4);
|
||||
*ret = m_ioman->Dclose(args[0]);
|
||||
break;
|
||||
case 11:
|
||||
assert(retSize == 4);
|
||||
*ret = m_ioman->Dread(args[0], reinterpret_cast<Iop::CIoman::DIRENTRY*>(ram + args[1]));
|
||||
break;
|
||||
case 12:
|
||||
assert(retSize == 4);
|
||||
*ret = m_ioman->GetStat(reinterpret_cast<const char*>(&args[1]), reinterpret_cast<Iop::CIoman::STAT*>(ram + args[0]));
|
||||
|
@ -249,6 +249,96 @@ uint32 CIoman::Seek(uint32 handle, uint32 position, uint32 whence)
|
||||
return result;
|
||||
}
|
||||
|
||||
int32 CIoman::Dopen(const char* path)
|
||||
{
|
||||
CLog::GetInstance().Print(LOG_NAME, "Dopen(path = '%s');\r\n",
|
||||
path);
|
||||
int32 handle = -1;
|
||||
try
|
||||
{
|
||||
std::string fullPath(path);
|
||||
auto position = fullPath.find(":");
|
||||
if(position == std::string::npos)
|
||||
{
|
||||
throw std::runtime_error("Invalid path.");
|
||||
}
|
||||
auto deviceName = std::string(fullPath.begin(), fullPath.begin() + position);
|
||||
auto devicePath = std::string(fullPath.begin() + position + 1, fullPath.end());
|
||||
auto deviceIterator = m_devices.find(deviceName);
|
||||
if(deviceIterator == m_devices.end())
|
||||
{
|
||||
throw std::runtime_error("Device not found.");
|
||||
}
|
||||
//Some games (Street Fighter EX3) provide paths with trailing spaces
|
||||
devicePath = RightTrim(devicePath);
|
||||
auto directory = deviceIterator->second->GetDirectory(devicePath.c_str());
|
||||
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))
|
||||
{
|
||||
//Directories have "group read" only permissions? This is required by PS2PSXe.
|
||||
stat.mode = 0747 | (1 << 12); //File mode + Dir type (1)
|
||||
stat.attr = 0x8427;
|
||||
}
|
||||
else
|
||||
{
|
||||
stat.mode = 0777 | (2 << 12); //File mode + File type (2)
|
||||
stat.loSize = boost::filesystem::file_size(itemPath);
|
||||
stat.attr = 0x8497;
|
||||
}
|
||||
|
||||
directory++;
|
||||
|
||||
return strlen(dirEntry->name);
|
||||
}
|
||||
|
||||
uint32 CIoman::GetStat(const char* path, STAT* stat)
|
||||
{
|
||||
CLog::GetInstance().Print(LOG_NAME, "GetStat(path = '%s', stat = ptr);\r\n", path);
|
||||
|
@ -33,9 +33,23 @@ namespace Iop
|
||||
uint8 lastAccessTime[8];
|
||||
uint8 lastModificationTime[8];
|
||||
uint32 hiSize;
|
||||
uint32 reserved[6];
|
||||
//Reserved (private) fields to be used in later versions of IOMAN
|
||||
//uint32 reserved[6];
|
||||
};
|
||||
static_assert(sizeof(STAT) == 64, "STAT structure must be 64 bytes long.");
|
||||
static_assert(sizeof(STAT) == 40, "STAT structure must be 40 bytes long.");
|
||||
|
||||
struct DIRENTRY
|
||||
{
|
||||
enum
|
||||
{
|
||||
NAME_SIZE = 256,
|
||||
};
|
||||
|
||||
STAT stat;
|
||||
char name[NAME_SIZE];
|
||||
uint32 privatePtr;
|
||||
};
|
||||
static_assert(sizeof(DIRENTRY) == 0x12C, "DIRENTRY structure must be 300 bytes long");
|
||||
|
||||
class CFile
|
||||
{
|
||||
@ -68,6 +82,9 @@ namespace Iop
|
||||
uint32 Read(uint32, uint32, void*);
|
||||
uint32 Write(uint32, uint32, const void*);
|
||||
uint32 Seek(uint32, uint32, uint32);
|
||||
int32 Dopen(const char*);
|
||||
int32 Dread(uint32, DIRENTRY*);
|
||||
int32 Dclose(uint32);
|
||||
uint32 GetStat(const char*, STAT*);
|
||||
uint32 AddDrv(uint32);
|
||||
uint32 DelDrv(uint32);
|
||||
@ -77,9 +94,11 @@ namespace Iop
|
||||
|
||||
private:
|
||||
typedef std::map<uint32, Framework::CStream*> FileMapType;
|
||||
typedef std::map<uint32, Ioman::Directory> DirectoryMapType;
|
||||
typedef std::map<std::string, DevicePtr> DeviceMapType;
|
||||
|
||||
FileMapType m_files;
|
||||
DirectoryMapType m_directories;
|
||||
DeviceMapType m_devices;
|
||||
uint8* m_ram;
|
||||
uint32 m_nextFileHandle;
|
||||
|
@ -24,3 +24,8 @@ Framework::CStream* COpticalMediaDevice::GetFile(uint32 mode, const char* device
|
||||
auto fileSystem = m_opticalMedia->GetFileSystem();
|
||||
return fileSystem->Open(fixedString.c_str());
|
||||
}
|
||||
|
||||
Directory COpticalMediaDevice::GetDirectory(const char* devicePath)
|
||||
{
|
||||
throw std::runtime_error("Not supported.");
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ namespace Iop
|
||||
virtual ~COpticalMediaDevice() = default;
|
||||
|
||||
Framework::CStream* GetFile(uint32, const char*) override;
|
||||
Directory GetDirectory(const char*) override;
|
||||
|
||||
private:
|
||||
static char FixSlashes(char);
|
||||
|
@ -20,3 +20,8 @@ Framework::CStream* CPsfDevice::GetFile(uint32 mode, const char* path)
|
||||
Framework::CStream* result = m_fileSystem.GetFile(path);
|
||||
return result;
|
||||
}
|
||||
|
||||
Iop::Ioman::Directory CPsfDevice::GetDirectory(const char* path)
|
||||
{
|
||||
throw std::runtime_error("Not supported.");
|
||||
}
|
@ -16,6 +16,7 @@ namespace PS2
|
||||
|
||||
void AppendArchive(const CPsfBase&);
|
||||
Framework::CStream* GetFile(uint32, const char*) override;
|
||||
Iop::Ioman::Directory GetDirectory(const char*) override;
|
||||
|
||||
private:
|
||||
CPsfFs m_fileSystem;
|
||||
|
Loading…
x
Reference in New Issue
Block a user