mirror of
https://github.com/jpd002/Play-.git
synced 2025-04-28 13:47:57 +03:00
HDD dump work.
This commit is contained in:
parent
b852400139
commit
2fff103dbb
17 changed files with 568 additions and 14 deletions
|
@ -255,6 +255,13 @@ set(COMMON_SRC_FILES
|
|||
gs/GsPixelFormats.h
|
||||
gs/GsSpriteRegion.h
|
||||
gs/GsTextureCache.h
|
||||
hdd/ApaDefs.h
|
||||
hdd/ApaReader.cpp
|
||||
hdd/ApaReader.h
|
||||
hdd/HddDefs.h
|
||||
hdd/PfsDefs.h
|
||||
hdd/PfsReader.cpp
|
||||
hdd/PfsReader.h
|
||||
input/InputBindingManager.cpp
|
||||
input/InputBindingManager.h
|
||||
input/InputProvider.h
|
||||
|
@ -268,6 +275,8 @@ set(COMMON_SRC_FILES
|
|||
iop/ioman/McDumpDevice.h
|
||||
iop/ioman/HardDiskDevice.cpp
|
||||
iop/ioman/HardDiskDevice.h
|
||||
iop/ioman/HardDiskDumpDevice.cpp
|
||||
iop/ioman/HardDiskDumpDevice.h
|
||||
iop/ioman/OpticalMediaDevice.cpp
|
||||
iop/ioman/OpticalMediaDevice.h
|
||||
iop/ioman/OpticalMediaDirectoryIterator.cpp
|
||||
|
|
|
@ -427,8 +427,8 @@ void CPS2VM::ResetVM()
|
|||
iopOs->GetIoman()->RegisterDevice("host0", std::make_shared<Iop::Ioman::CPreferenceDirectoryDevice>(PREF_PS2_HOST_DIRECTORY));
|
||||
iopOs->GetIoman()->RegisterDevice("mc0", std::make_shared<Iop::Ioman::CPreferenceDirectoryDevice>(PREF_PS2_MC0_DIRECTORY));
|
||||
iopOs->GetIoman()->RegisterDevice("mc1", std::make_shared<Iop::Ioman::CPreferenceDirectoryDevice>(PREF_PS2_MC1_DIRECTORY));
|
||||
iopOs->GetIoman()->RegisterDevice("cdrom", Iop::CIoman::DevicePtr(new Iop::Ioman::COpticalMediaDevice(m_cdrom0)));
|
||||
iopOs->GetIoman()->RegisterDevice("cdrom0", Iop::CIoman::DevicePtr(new Iop::Ioman::COpticalMediaDevice(m_cdrom0)));
|
||||
iopOs->GetIoman()->RegisterDevice("cdrom", Iop::Ioman::DevicePtr(new Iop::Ioman::COpticalMediaDevice(m_cdrom0)));
|
||||
iopOs->GetIoman()->RegisterDevice("cdrom0", Iop::Ioman::DevicePtr(new Iop::Ioman::COpticalMediaDevice(m_cdrom0)));
|
||||
iopOs->GetIoman()->RegisterDevice("hdd0", std::make_shared<Iop::Ioman::CHardDiskDevice>());
|
||||
|
||||
iopOs->GetLoadcore()->SetLoadExecutableHandler(std::bind(&CPS2OS::LoadExecutable, m_ee->m_os, std::placeholders::_1, std::placeholders::_2));
|
||||
|
|
79
Source/hdd/ApaDefs.h
Normal file
79
Source/hdd/ApaDefs.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
namespace Hdd
|
||||
{
|
||||
enum
|
||||
{
|
||||
APA_HEADER_MAGIC = 0x415041,
|
||||
};
|
||||
|
||||
struct APA_TIME
|
||||
{
|
||||
uint8_t unused;
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
uint8_t hours;
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint16_t year;
|
||||
};
|
||||
static_assert(sizeof(APA_TIME) == 8);
|
||||
|
||||
struct APA_MBR
|
||||
{
|
||||
char magic[0x20];
|
||||
uint32_t version;
|
||||
uint32_t sectorCount;
|
||||
APA_TIME createdTime;
|
||||
uint32_t osdStart;
|
||||
uint32_t osdSize;
|
||||
char padding[200];
|
||||
};
|
||||
static_assert(sizeof(APA_MBR) == 0x100);
|
||||
|
||||
struct APA_SUBPART
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t count;
|
||||
};
|
||||
static_assert(sizeof(APA_SUBPART) == 8);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct APA_HEADER
|
||||
{
|
||||
enum
|
||||
{
|
||||
ID_SIZE = 32,
|
||||
PASSWORD_SIZE = 8,
|
||||
SUBPART_SIZE = 64,
|
||||
};
|
||||
|
||||
enum TYPE
|
||||
{
|
||||
TYPE_PFS = 0x100,
|
||||
};
|
||||
|
||||
uint32_t checksum;
|
||||
uint32_t magic;
|
||||
uint32_t next;
|
||||
uint32_t prev;
|
||||
char id[ID_SIZE];
|
||||
char rPassword[PASSWORD_SIZE];
|
||||
char fPassword[PASSWORD_SIZE];
|
||||
uint32_t start;
|
||||
uint32_t length;
|
||||
uint16_t type;
|
||||
uint16_t flags;
|
||||
uint32_t subPartCount;
|
||||
APA_TIME createdTime;
|
||||
uint32_t main;
|
||||
uint32_t number;
|
||||
uint32_t modVer;
|
||||
uint32_t padding1[7];
|
||||
uint8_t padding2[0x80];
|
||||
APA_MBR mbr;
|
||||
APA_SUBPART subParts[SUBPART_SIZE];
|
||||
};
|
||||
static_assert(sizeof(APA_HEADER) == 0x400);
|
||||
#pragma pack(pop)
|
||||
}
|
30
Source/hdd/ApaReader.cpp
Normal file
30
Source/hdd/ApaReader.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "ApaReader.h"
|
||||
#include "ApaDefs.h"
|
||||
#include "HddDefs.h"
|
||||
|
||||
using namespace Hdd;
|
||||
|
||||
CApaReader::CApaReader(Framework::CStream& stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32 CApaReader::FindPartition(const char* partitionId)
|
||||
{
|
||||
uint32_t lba = 0;
|
||||
while(1)
|
||||
{
|
||||
APA_HEADER header;
|
||||
m_stream.Seek(lba * g_sectorSize, Framework::STREAM_SEEK_SET);
|
||||
m_stream.Read(&header, sizeof(APA_HEADER));
|
||||
assert(header.magic == APA_HEADER_MAGIC);
|
||||
if(!strcmp(header.id, partitionId))
|
||||
{
|
||||
return header.start;
|
||||
}
|
||||
lba = header.next;
|
||||
if(lba == 0) break;
|
||||
}
|
||||
return -1;
|
||||
}
|
17
Source/hdd/ApaReader.h
Normal file
17
Source/hdd/ApaReader.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
|
||||
namespace Hdd
|
||||
{
|
||||
class CApaReader
|
||||
{
|
||||
public:
|
||||
CApaReader(Framework::CStream&);
|
||||
|
||||
uint32 FindPartition(const char*);
|
||||
|
||||
private:
|
||||
Framework::CStream& m_stream;
|
||||
};
|
||||
}
|
6
Source/hdd/HddDefs.h
Normal file
6
Source/hdd/HddDefs.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
namespace Hdd
|
||||
{
|
||||
static const uint64 g_sectorSize = 512;
|
||||
}
|
87
Source/hdd/PfsDefs.h
Normal file
87
Source/hdd/PfsDefs.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
namespace Hdd
|
||||
{
|
||||
enum
|
||||
{
|
||||
PFS_SUPERBLOCK_MAGIC = 0x50465300, //'/0sfp'
|
||||
PFS_INODE_SEGDESC_DIRECT_MAGIC = 0x53454744, //'dges'
|
||||
|
||||
PFS_SUPERBLOCK_LBA = 8192,
|
||||
|
||||
PFS_INODE_SIZE = 1024,
|
||||
PFS_BLOCK_SCALE = 1,
|
||||
};
|
||||
|
||||
struct PFS_BLOCKINFO
|
||||
{
|
||||
uint32_t number;
|
||||
uint16_t subPart;
|
||||
uint16_t count;
|
||||
};
|
||||
static_assert(sizeof(PFS_BLOCKINFO) == 0x8);
|
||||
|
||||
struct PFS_TIME
|
||||
{
|
||||
uint8_t unused;
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
uint8_t hours;
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint16_t year;
|
||||
};
|
||||
static_assert(sizeof(PFS_TIME) == 8);
|
||||
|
||||
struct PFS_SUPERBLOCK
|
||||
{
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint32_t modVer;
|
||||
uint32_t fsckStat;
|
||||
uint32_t zoneSize;
|
||||
uint32_t subPartCount;
|
||||
PFS_BLOCKINFO logBlock;
|
||||
PFS_BLOCKINFO rootBlock;
|
||||
};
|
||||
static_assert(sizeof(PFS_SUPERBLOCK) == 0x28);
|
||||
|
||||
struct PFS_INODE
|
||||
{
|
||||
enum
|
||||
{
|
||||
DATA_SIZE = 114,
|
||||
};
|
||||
|
||||
uint32_t checksum;
|
||||
uint32_t magic;
|
||||
PFS_BLOCKINFO inodeBlock;
|
||||
PFS_BLOCKINFO nextSegment;
|
||||
PFS_BLOCKINFO lastSegment;
|
||||
PFS_BLOCKINFO unused;
|
||||
PFS_BLOCKINFO data[DATA_SIZE];
|
||||
uint16_t mode;
|
||||
uint16_t attr;
|
||||
uint16_t uid;
|
||||
uint16_t gid;
|
||||
PFS_TIME atime;
|
||||
PFS_TIME ctime;
|
||||
PFS_TIME mtime;
|
||||
uint64_t size;
|
||||
uint32_t blockCount;
|
||||
uint32_t dataCount;
|
||||
uint32_t indirectCount;
|
||||
uint32_t subPart;
|
||||
uint32_t reserved[4];
|
||||
};
|
||||
static_assert(sizeof(PFS_INODE) == 1024);
|
||||
|
||||
struct PFS_DIRENTRY
|
||||
{
|
||||
uint32_t inode;
|
||||
uint8_t subPart;
|
||||
uint8_t pathLength;
|
||||
uint16_t allocatedLength;
|
||||
};
|
||||
static_assert(sizeof(PFS_DIRENTRY) == 8);
|
||||
}
|
154
Source/hdd/PfsReader.cpp
Normal file
154
Source/hdd/PfsReader.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
#include "PfsReader.h"
|
||||
#include "HddDefs.h"
|
||||
|
||||
using namespace Hdd;
|
||||
|
||||
static uint32_t GetScale(uint32_t num, uint32_t size)
|
||||
{
|
||||
uint32 scale = 0;
|
||||
while((size << scale) != num)
|
||||
{
|
||||
scale++;
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
||||
CPfsReader::CPfsReader(Framework::CStream& stream, uint32 baseLba)
|
||||
: m_stream(stream)
|
||||
, m_baseLba(baseLba)
|
||||
{
|
||||
uint32_t superBlockLba = m_baseLba + PFS_SUPERBLOCK_LBA;
|
||||
m_stream.Seek(superBlockLba * g_sectorSize, Framework::STREAM_SEEK_SET);
|
||||
m_stream.Read(&m_superBlock, sizeof(PFS_SUPERBLOCK));
|
||||
assert(m_superBlock.magic == PFS_SUPERBLOCK_MAGIC);
|
||||
m_inodeScale = GetScale(m_superBlock.zoneSize, PFS_INODE_SIZE);
|
||||
}
|
||||
|
||||
CPfsFileReader* CPfsReader::GetFileStream(const char* path)
|
||||
{
|
||||
assert(path[0] == '/');
|
||||
path++;
|
||||
assert(strchr(path, '/') == nullptr);
|
||||
|
||||
auto rootInode = ReadInode(m_superBlock.rootBlock.number, m_superBlock.rootBlock.subPart);
|
||||
assert(rootInode.dataCount == 2);
|
||||
uint32 dirLba = GetBlockLba(rootInode.data[1].number, rootInode.data[1].subPart);
|
||||
|
||||
static const uint32_t dirBlockSize = g_sectorSize << PFS_BLOCK_SCALE;
|
||||
uint8 dirBlock[dirBlockSize];
|
||||
m_stream.Seek(dirLba * g_sectorSize, Framework::STREAM_SEEK_SET);
|
||||
m_stream.Read(dirBlock, sizeof(dirBlock));
|
||||
auto dirBlockCurr = dirBlock;
|
||||
auto dirBlockEnd = dirBlock + dirBlockSize;
|
||||
while(1)
|
||||
{
|
||||
assert((dirBlockEnd - dirBlockCurr) >= sizeof(PFS_DIRENTRY));
|
||||
auto dirEntry = reinterpret_cast<const PFS_DIRENTRY*>(dirBlockCurr);
|
||||
uint32_t entryLength = dirEntry->allocatedLength & 0xFFF;
|
||||
if(entryLength == 0)
|
||||
{
|
||||
//We're done
|
||||
dirBlockCurr = dirBlockEnd;
|
||||
break;
|
||||
}
|
||||
assert((dirBlockEnd - dirBlockCurr) >= entryLength);
|
||||
std::string entryName;
|
||||
for(int i = 0; i < dirEntry->pathLength; i++)
|
||||
{
|
||||
entryName += dirBlockCurr[sizeof(PFS_DIRENTRY) + i];
|
||||
}
|
||||
if(!strcmp(entryName.c_str(), path))
|
||||
{
|
||||
break;
|
||||
}
|
||||
dirBlockCurr += entryLength;
|
||||
}
|
||||
|
||||
if(dirBlockCurr == dirBlockEnd)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto dirEntry = reinterpret_cast<const PFS_DIRENTRY*>(dirBlockCurr);
|
||||
auto fileInode = ReadInode(dirEntry->inode, dirEntry->subPart);
|
||||
return new CPfsFileReader(*this, m_stream, fileInode);
|
||||
}
|
||||
|
||||
uint32 CPfsReader::GetBlockLba(uint32 number, uint32 subPart)
|
||||
{
|
||||
assert(subPart == 0);
|
||||
return m_baseLba + ((number << m_inodeScale) << PFS_BLOCK_SCALE);
|
||||
}
|
||||
|
||||
PFS_INODE CPfsReader::ReadInode(uint32 number, uint32 subPart)
|
||||
{
|
||||
PFS_INODE result = {};
|
||||
uint32 inodeLba = GetBlockLba(number, subPart);
|
||||
m_stream.Seek(inodeLba * g_sectorSize, Framework::STREAM_SEEK_SET);
|
||||
m_stream.Read(&result, sizeof(PFS_INODE));
|
||||
assert(result.magic == PFS_INODE_SEGDESC_DIRECT_MAGIC);
|
||||
return result;
|
||||
}
|
||||
|
||||
CPfsFileReader::CPfsFileReader(CPfsReader& reader, Framework::CStream& stream, PFS_INODE inode)
|
||||
: m_reader(reader)
|
||||
, m_stream(stream)
|
||||
, m_inode(inode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CPfsFileReader::Seek(int64 position, Framework::STREAM_SEEK_DIRECTION whence)
|
||||
{
|
||||
uint64 fileSize = m_inode.size;
|
||||
switch(whence)
|
||||
{
|
||||
case Framework::STREAM_SEEK_SET:
|
||||
m_position = std::min<uint64>(position, fileSize);
|
||||
break;
|
||||
case Framework::STREAM_SEEK_CUR:
|
||||
m_position = std::min<uint64>(m_position + position, fileSize);
|
||||
break;
|
||||
case Framework::STREAM_SEEK_END:
|
||||
m_position = fileSize;
|
||||
break;
|
||||
}
|
||||
m_isEof = false;
|
||||
}
|
||||
|
||||
uint64_t CPfsFileReader::Tell()
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
uint64 CPfsFileReader::Read(void* buffer, uint64 length)
|
||||
{
|
||||
uint64 fileSize = m_inode.size;
|
||||
if(m_position >= fileSize)
|
||||
{
|
||||
m_isEof = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 remainFileSize = fileSize - m_position;
|
||||
length = std::min<uint64>(length, remainFileSize);
|
||||
|
||||
assert(m_inode.dataCount == 2);
|
||||
uint32 fileLba = m_reader.GetBlockLba(m_inode.data[1].number, m_inode.data[1].subPart);
|
||||
|
||||
m_stream.Seek(fileLba * g_sectorSize, Framework::STREAM_SEEK_SET);
|
||||
m_stream.Read(buffer, length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
uint64 CPfsFileReader::Write(const void*, uint64)
|
||||
{
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CPfsFileReader::IsEOF()
|
||||
{
|
||||
return m_isEof;
|
||||
}
|
47
Source/hdd/PfsReader.h
Normal file
47
Source/hdd/PfsReader.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "Stream.h"
|
||||
#include "PfsDefs.h"
|
||||
|
||||
namespace Hdd
|
||||
{
|
||||
class CPfsReader
|
||||
{
|
||||
public:
|
||||
CPfsReader(Framework::CStream&, uint32);
|
||||
|
||||
class CPfsFileReader* GetFileStream(const char*);
|
||||
|
||||
uint32 GetBlockLba(uint32, uint32);
|
||||
|
||||
private:
|
||||
PFS_INODE ReadInode(uint32, uint32);
|
||||
|
||||
Framework::CStream& m_stream;
|
||||
|
||||
uint32 m_baseLba = 0;
|
||||
PFS_SUPERBLOCK m_superBlock = {};
|
||||
uint32 m_inodeScale = 0;
|
||||
};
|
||||
|
||||
class CPfsFileReader : public Framework::CStream
|
||||
{
|
||||
public:
|
||||
CPfsFileReader(CPfsReader&, Framework::CStream&, PFS_INODE);
|
||||
~CPfsFileReader() = default;
|
||||
|
||||
void Seek(int64, Framework::STREAM_SEEK_DIRECTION) override;
|
||||
uint64 Tell() override;
|
||||
uint64 Read(void*, uint64) override;
|
||||
uint64 Write(const void*, uint64) override;
|
||||
bool IsEOF() override;
|
||||
|
||||
private:
|
||||
CPfsReader& m_reader;
|
||||
Framework::CStream& m_stream;
|
||||
PFS_INODE m_inode;
|
||||
|
||||
uint64 m_position = 0;
|
||||
bool m_isEof = false;
|
||||
};
|
||||
}
|
|
@ -29,10 +29,12 @@ namespace Iop
|
|||
{
|
||||
throw std::runtime_error("Directory creation not supported.");
|
||||
}
|
||||
virtual fs::path GetMountPath(const char*)
|
||||
virtual std::shared_ptr<CDevice> Mount(const char*)
|
||||
{
|
||||
throw std::runtime_error("Mounting not supported.");
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<CDevice> DevicePtr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ std::string CIoman::GetFunctionName(unsigned int functionId) const
|
|||
}
|
||||
}
|
||||
|
||||
void CIoman::RegisterDevice(const char* name, const DevicePtr& device)
|
||||
void CIoman::RegisterDevice(const char* name, const Ioman::DevicePtr& device)
|
||||
{
|
||||
m_devices[name] = device;
|
||||
}
|
||||
|
@ -530,8 +530,7 @@ int32 CIoman::Mount(const char* fsName, const char* devicePath)
|
|||
mountedDeviceName.erase(std::remove(mountedDeviceName.begin(), mountedDeviceName.end(), ':'), mountedDeviceName.end());
|
||||
assert(m_devices.find(mountedDeviceName) == std::end(m_devices));
|
||||
|
||||
auto partitionPath = device->GetMountPath(pathInfo.devicePath.c_str());
|
||||
auto mountedDevice = std::make_shared<Ioman::CPathDirectoryDevice>(partitionPath);
|
||||
auto mountedDevice = device->Mount(pathInfo.devicePath.c_str());
|
||||
m_devices[mountedDeviceName] = mountedDevice;
|
||||
}
|
||||
catch(const std::exception& except)
|
||||
|
|
|
@ -33,8 +33,6 @@ namespace Iop
|
|||
{
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Ioman::CDevice> DevicePtr;
|
||||
|
||||
CIoman(CIopBios&, uint8*);
|
||||
virtual ~CIoman();
|
||||
|
||||
|
@ -45,7 +43,7 @@ namespace Iop
|
|||
void SaveState(Framework::CZipArchiveWriter&) const override;
|
||||
void LoadState(Framework::CZipArchiveReader&) override;
|
||||
|
||||
void RegisterDevice(const char*, const DevicePtr&);
|
||||
void RegisterDevice(const char*, const Ioman::DevicePtr&);
|
||||
|
||||
uint32 Open(uint32, const char*);
|
||||
uint32 Close(uint32);
|
||||
|
@ -133,7 +131,7 @@ namespace Iop
|
|||
|
||||
typedef std::map<int32, FileInfo> FileMapType;
|
||||
typedef std::map<uint32, Ioman::DirectoryIteratorPtr> DirectoryMapType;
|
||||
typedef std::map<std::string, DevicePtr> DeviceMapType;
|
||||
typedef std::map<std::string, Ioman::DevicePtr> DeviceMapType;
|
||||
typedef std::map<std::string, uint32> UserDeviceMapType;
|
||||
|
||||
void PrepareOpenThunk();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "PathUtils.h"
|
||||
#include "PS2VM_Preferences.h"
|
||||
#include "StringUtils.h"
|
||||
#include "PathDirectoryDevice.h"
|
||||
#include "PathDirectoryIterator.h"
|
||||
|
||||
using namespace Iop::Ioman;
|
||||
|
@ -53,7 +54,7 @@ DirectoryIteratorPtr CHardDiskDevice::GetDirectory(const char* devicePath)
|
|||
return std::make_unique<CPathDirectoryIterator>(m_basePath);
|
||||
}
|
||||
|
||||
fs::path CHardDiskDevice::GetMountPath(const char* devicePath)
|
||||
DevicePtr CHardDiskDevice::Mount(const char* devicePath)
|
||||
{
|
||||
auto mountParams = StringUtils::Split(devicePath, ',', true);
|
||||
assert(!mountParams.empty());
|
||||
|
@ -62,7 +63,8 @@ fs::path CHardDiskDevice::GetMountPath(const char* devicePath)
|
|||
{
|
||||
throw std::runtime_error("Partition doesn't exist.");
|
||||
}
|
||||
return m_basePath / mountParams[0];
|
||||
auto mountPath = m_basePath / mountParams[0];
|
||||
return std::make_shared<CPathDirectoryDevice>(mountPath);
|
||||
}
|
||||
|
||||
void CHardDiskDevice::CreatePartition(const std::vector<std::string>& createParams)
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Iop
|
|||
|
||||
Framework::CStream* GetFile(uint32, const char*) override;
|
||||
DirectoryIteratorPtr GetDirectory(const char*) override;
|
||||
fs::path GetMountPath(const char*) override;
|
||||
DevicePtr Mount(const char*) override;
|
||||
|
||||
private:
|
||||
void CreatePartition(const std::vector<std::string>&);
|
||||
|
|
62
Source/iop/ioman/HardDiskDumpDevice.cpp
Normal file
62
Source/iop/ioman/HardDiskDumpDevice.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "HardDiskDumpDevice.h"
|
||||
#include "HardDiskDevice.h"
|
||||
#include "hdd/ApaReader.h"
|
||||
#include "StringUtils.h"
|
||||
#include "MemStream.h"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace Iop::Ioman;
|
||||
|
||||
CHardDiskDumpDevice::CHardDiskDumpDevice(std::unique_ptr<Framework::CStream> stream)
|
||||
: m_stream(std::move(stream))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Framework::CStream* CHardDiskDumpDevice::GetFile(uint32 flags, const char* path)
|
||||
{
|
||||
assert(flags == OPEN_FLAG_RDONLY);
|
||||
Hdd::CApaReader reader(*m_stream);
|
||||
uint32 partitionLba = reader.FindPartition(path);
|
||||
if(partitionLba == -1)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return new CHardDiskPartition();
|
||||
}
|
||||
|
||||
DirectoryIteratorPtr CHardDiskDumpDevice::GetDirectory(const char*)
|
||||
{
|
||||
return DirectoryIteratorPtr();
|
||||
}
|
||||
|
||||
DevicePtr CHardDiskDumpDevice::Mount(const char* path)
|
||||
{
|
||||
auto mountParams = StringUtils::Split(path, ',', true);
|
||||
Hdd::CApaReader reader(*m_stream);
|
||||
uint32 partitionLba = reader.FindPartition(mountParams[0].c_str());
|
||||
if(partitionLba == -1)
|
||||
{
|
||||
assert(false);
|
||||
return DevicePtr();
|
||||
}
|
||||
return std::make_shared<CHardDiskDumpPartitionDevice>(*m_stream, partitionLba);
|
||||
}
|
||||
|
||||
CHardDiskDumpPartitionDevice::CHardDiskDumpPartitionDevice(Framework::CStream& stream, uint32 partitionLba)
|
||||
: m_pfsReader(stream, partitionLba)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Framework::CStream* CHardDiskDumpPartitionDevice::GetFile(uint32 flags, const char* path)
|
||||
{
|
||||
assert((flags & OPEN_FLAG_ACCMODE) == OPEN_FLAG_RDONLY);
|
||||
return m_pfsReader.GetFileStream(path);
|
||||
}
|
||||
|
||||
DirectoryIteratorPtr CHardDiskDumpPartitionDevice::GetDirectory(const char*)
|
||||
{
|
||||
assert(false);
|
||||
return DirectoryIteratorPtr();
|
||||
}
|
37
Source/iop/ioman/HardDiskDumpDevice.h
Normal file
37
Source/iop/ioman/HardDiskDumpDevice.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Ioman_Device.h"
|
||||
#include "hdd/PfsReader.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
namespace Ioman
|
||||
{
|
||||
class CHardDiskDumpDevice : public CDevice
|
||||
{
|
||||
public:
|
||||
CHardDiskDumpDevice(std::unique_ptr<Framework::CStream>);
|
||||
virtual ~CHardDiskDumpDevice() = default;
|
||||
|
||||
Framework::CStream* GetFile(uint32, const char*) override;
|
||||
DirectoryIteratorPtr GetDirectory(const char*) override;
|
||||
DevicePtr Mount(const char*) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Framework::CStream> m_stream;
|
||||
};
|
||||
|
||||
class CHardDiskDumpPartitionDevice : public CDevice
|
||||
{
|
||||
public:
|
||||
CHardDiskDumpPartitionDevice(Framework::CStream&, uint32);
|
||||
virtual ~CHardDiskDumpPartitionDevice() = default;
|
||||
|
||||
Framework::CStream* GetFile(uint32, const char*) override;
|
||||
DirectoryIteratorPtr GetDirectory(const char*) override;
|
||||
|
||||
private:
|
||||
Hdd::CPfsReader m_pfsReader;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -9,7 +9,10 @@
|
|||
#include "AppConfig.h"
|
||||
#include "BootablesDbClient.h"
|
||||
#include "BootablesProcesses.h"
|
||||
#include "hdd/HddDefs.h"
|
||||
#include "discimages/ChdImageStream.h"
|
||||
#include "iop/ioman/McDumpDevice.h"
|
||||
#include "iop/ioman/HardDiskDumpDevice.h"
|
||||
#include "iop/Iop_NamcoArcade.h"
|
||||
#include "iop/namco_arcade/Iop_NamcoAcCdvd.h"
|
||||
#include "iop/namco_arcade/Iop_NamcoAcRam.h"
|
||||
|
@ -26,6 +29,7 @@ struct ARCADE_MACHINE_DEF
|
|||
std::string name;
|
||||
std::string dongleFileName;
|
||||
std::string cdvdFileName;
|
||||
std::string hddFileName;
|
||||
std::string boot;
|
||||
std::vector<PATCH> patches;
|
||||
};
|
||||
|
@ -69,6 +73,10 @@ ARCADE_MACHINE_DEF ReadArcadeMachineDefinition(const fs::path& arcadeDefPath)
|
|||
{
|
||||
def.cdvdFileName = defJson["cdvd"]["name"];
|
||||
}
|
||||
if(defJson.contains("hdd"))
|
||||
{
|
||||
def.hddFileName = defJson["hdd"]["name"];
|
||||
}
|
||||
def.boot = defJson["boot"];
|
||||
if(defJson.contains("patches"))
|
||||
{
|
||||
|
@ -89,7 +97,7 @@ void PrepareArcadeEnvironment(CPS2VM* virtualMachine, const ARCADE_MACHINE_DEF&
|
|||
throw std::runtime_error(string_format("Failed to find '%s' in arcade ROMs directory.", romArchiveFileName.c_str()));
|
||||
}
|
||||
|
||||
//Mount CDVD or HDD
|
||||
//Mount CDVD
|
||||
if(!def.cdvdFileName.empty())
|
||||
{
|
||||
fs::path cdvdPath = arcadeRomPath / def.id / def.cdvdFileName;
|
||||
|
@ -106,6 +114,23 @@ void PrepareArcadeEnvironment(CPS2VM* virtualMachine, const ARCADE_MACHINE_DEF&
|
|||
virtualMachine->CDROM0_SyncPath();
|
||||
}
|
||||
|
||||
//Mount HDD
|
||||
if(!def.hddFileName.empty())
|
||||
{
|
||||
fs::path hddPath = arcadeRomPath / def.id / def.hddFileName;
|
||||
if(!fs::exists(hddPath))
|
||||
{
|
||||
throw std::runtime_error(string_format("Failed to find '%s' in game's directory.", def.hddFileName.c_str()));
|
||||
}
|
||||
|
||||
auto imageStream = std::make_unique<CChdImageStream>(std::make_unique<Framework::CStdStream>(hddPath.string().c_str(), "rb"));
|
||||
assert(imageStream->GetUnitSize() == Hdd::g_sectorSize);
|
||||
auto device = std::make_shared<Iop::Ioman::CHardDiskDumpDevice>(std::move(imageStream));
|
||||
|
||||
auto iopBios = dynamic_cast<CIopBios*>(virtualMachine->m_iop->m_bios.get());
|
||||
iopBios->GetIoman()->RegisterDevice("hdd0", device);
|
||||
}
|
||||
|
||||
std::vector<uint8> mcDumpContents;
|
||||
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue