2017-05-16 19:54:38 -04:00
|
|
|
#include "OpticalMediaDevice.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <string>
|
2022-02-25 17:32:56 -05:00
|
|
|
#include "OpticalMediaDirectoryIterator.h"
|
2017-05-16 19:54:38 -04:00
|
|
|
|
|
|
|
using namespace Iop::Ioman;
|
|
|
|
|
|
|
|
COpticalMediaDevice::COpticalMediaDevice(OpticalMediaPtr& opticalMedia)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_opticalMedia(opticalMedia)
|
2017-05-16 19:54:38 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
char COpticalMediaDevice::FixSlashes(char input)
|
|
|
|
{
|
|
|
|
if(input == '\\') return '/';
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2021-01-20 09:27:11 -05:00
|
|
|
std::string COpticalMediaDevice::RemoveExtraVersionSpecifiers(const std::string& path)
|
|
|
|
{
|
|
|
|
//Some games (Samurai Legend Musashi, while saving) will use a path that has two version specifiers
|
|
|
|
//ex.: "myfile.bin;1;1". Looks like a bug in the game, assuming the driver doesn't care about that
|
|
|
|
auto fixedPath = path;
|
|
|
|
auto semiColonPos = fixedPath.find(';');
|
|
|
|
if(semiColonPos != std::string::npos)
|
|
|
|
{
|
|
|
|
auto nextSemiColonPos = fixedPath.find(';', semiColonPos + 1);
|
|
|
|
if(nextSemiColonPos != std::string::npos)
|
|
|
|
{
|
|
|
|
fixedPath = std::string(std::begin(fixedPath), std::begin(fixedPath) + nextSemiColonPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fixedPath;
|
|
|
|
}
|
|
|
|
|
2017-05-16 19:54:38 -04:00
|
|
|
Framework::CStream* COpticalMediaDevice::GetFile(uint32 mode, const char* devicePath)
|
|
|
|
{
|
|
|
|
if(!m_opticalMedia) return nullptr;
|
|
|
|
std::string fixedString(devicePath);
|
2021-01-20 09:27:11 -05:00
|
|
|
std::transform(fixedString.begin(), fixedString.end(), fixedString.begin(), &COpticalMediaDevice::FixSlashes);
|
|
|
|
fixedString = RemoveExtraVersionSpecifiers(fixedString);
|
2017-05-16 19:54:38 -04:00
|
|
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
2023-01-12 16:28:23 -05:00
|
|
|
auto fileStream = std::unique_ptr<Framework::CStream>(fileSystem->Open(fixedString.c_str()));
|
|
|
|
if(!fileStream)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return new COpticalMediaFile(std::move(fileStream));
|
2017-05-16 19:54:38 -04:00
|
|
|
}
|
2018-09-20 19:05:24 -04:00
|
|
|
|
2022-02-25 17:32:56 -05:00
|
|
|
DirectoryIteratorPtr COpticalMediaDevice::GetDirectory(const char* devicePath)
|
2018-09-20 19:05:24 -04:00
|
|
|
{
|
2022-02-25 17:32:56 -05:00
|
|
|
if(!m_opticalMedia) return nullptr;
|
|
|
|
std::string fixedString(devicePath);
|
|
|
|
std::transform(fixedString.begin(), fixedString.end(), fixedString.begin(), &COpticalMediaDevice::FixSlashes);
|
2022-03-01 17:48:28 +01:00
|
|
|
fixedString.erase(fixedString.find_last_not_of('.') + 1); // Remove trailing dot, if there is any
|
|
|
|
|
2022-02-25 17:32:56 -05:00
|
|
|
auto fileSystem = m_opticalMedia->GetFileSystem();
|
|
|
|
auto directoryStream = fileSystem->OpenDirectory(fixedString.c_str());
|
|
|
|
if(directoryStream == nullptr)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Directory not found.");
|
|
|
|
}
|
|
|
|
return std::make_unique<COpticalMediaDirectoryIterator>(directoryStream);
|
2018-09-20 19:05:24 -04:00
|
|
|
}
|
2023-01-12 16:28:23 -05:00
|
|
|
|
|
|
|
COpticalMediaFile::COpticalMediaFile(std::unique_ptr<Framework::CStream> baseStream)
|
|
|
|
: m_baseStream(std::move(baseStream))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void COpticalMediaFile::Seek(int64 offset, Framework::STREAM_SEEK_DIRECTION whence)
|
|
|
|
{
|
|
|
|
if((whence == Framework::STREAM_SEEK_END) && (offset > 0))
|
|
|
|
{
|
|
|
|
//Some games from Phoenix Games relies on a positive offset seeking backwards when using SEEK_END:
|
|
|
|
//- Shadow of Ganymede
|
|
|
|
//- Guerrilla Strike
|
|
|
|
offset = -offset;
|
|
|
|
}
|
|
|
|
m_baseStream->Seek(offset, whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 COpticalMediaFile::Tell()
|
|
|
|
{
|
|
|
|
return m_baseStream->Tell();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 COpticalMediaFile::Read(void* buffer, uint64 size)
|
|
|
|
{
|
|
|
|
return m_baseStream->Read(buffer, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 COpticalMediaFile::Write(const void* buffer, uint64 size)
|
|
|
|
{
|
|
|
|
return m_baseStream->Write(buffer, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool COpticalMediaFile::IsEOF()
|
|
|
|
{
|
|
|
|
return m_baseStream->IsEOF();
|
|
|
|
}
|