2019-08-17 13:51:31 -04:00
|
|
|
#include <cstring>
|
2012-10-09 01:25:44 +00:00
|
|
|
#include "XpsSaveImporter.h"
|
|
|
|
#include "StdStreamUtils.h"
|
|
|
|
|
2019-10-16 20:51:11 -04:00
|
|
|
void CXpsSaveImporter::Import(Framework::CStream& input, const fs::path& outputPath)
|
2012-10-09 01:25:44 +00:00
|
|
|
{
|
|
|
|
input.Seek(4, Framework::STREAM_SEEK_SET);
|
|
|
|
|
|
|
|
{
|
|
|
|
char sHeaderSig[0x0E];
|
|
|
|
input.Read(sHeaderSig, 0x0D);
|
|
|
|
sHeaderSig[0x0D] = 0;
|
|
|
|
|
|
|
|
if(strcmp(sHeaderSig, "SharkPortSave"))
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Invalid X-Port save file.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
input.Seek(0x15, Framework::STREAM_SEEK_SET);
|
|
|
|
|
|
|
|
//Skip file title
|
|
|
|
{
|
|
|
|
uint32 nStringLength = input.Read32();
|
|
|
|
input.Seek(nStringLength, Framework::STREAM_SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Skip file date
|
|
|
|
{
|
|
|
|
uint32 nStringLength = input.Read32();
|
|
|
|
input.Seek(nStringLength, Framework::STREAM_SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Skip comment?
|
|
|
|
{
|
|
|
|
uint32 nStringLength = input.Read32();
|
|
|
|
input.Seek(nStringLength, Framework::STREAM_SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 nArchiveSize = input.Read32();
|
|
|
|
nArchiveSize += static_cast<uint32>(input.Tell());
|
|
|
|
|
|
|
|
ExtractFiles(input, outputPath, nArchiveSize);
|
|
|
|
}
|
|
|
|
|
2019-10-16 20:51:11 -04:00
|
|
|
void CXpsSaveImporter::ExtractFiles(Framework::CStream& input, const fs::path& basePath, uint32 nArchiveSize)
|
2012-10-09 01:25:44 +00:00
|
|
|
{
|
2019-10-16 20:51:11 -04:00
|
|
|
if(!fs::exists(basePath))
|
2012-10-09 01:25:44 +00:00
|
|
|
{
|
2019-10-16 20:51:11 -04:00
|
|
|
fs::create_directory(basePath);
|
2012-10-09 01:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while(!input.IsEOF() && (static_cast<uint32>(input.Tell()) < nArchiveSize))
|
|
|
|
{
|
|
|
|
uint16 nDescriptorLength = input.Read16();
|
|
|
|
|
|
|
|
char sName[0x41];
|
|
|
|
memset(sName, 0, sizeof(sName));
|
|
|
|
input.Read(sName, 0x40);
|
|
|
|
|
|
|
|
uint32 nLength = input.Read32();
|
|
|
|
input.Seek(8, Framework::STREAM_SEEK_CUR);
|
|
|
|
uint32 nAttributes = input.Read32();
|
|
|
|
|
|
|
|
input.Seek(nDescriptorLength - (0x40 + 4 + 4 + 8 + 2), Framework::STREAM_SEEK_CUR);
|
|
|
|
|
2019-10-16 20:51:11 -04:00
|
|
|
fs::path outputPath(basePath / sName);
|
2012-10-09 01:25:44 +00:00
|
|
|
|
|
|
|
if(nAttributes & 0x2000)
|
|
|
|
{
|
|
|
|
ExtractFiles(input, outputPath, nArchiveSize);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(!CanExtractFile(outputPath))
|
|
|
|
{
|
|
|
|
input.Seek(nLength, Framework::STREAM_SEEK_CUR);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto output(Framework::CreateOutputStdStream(outputPath.native()));
|
|
|
|
|
|
|
|
while(nLength != 0)
|
|
|
|
{
|
|
|
|
const int bufferSize = 1024;
|
|
|
|
char sBuffer[bufferSize];
|
|
|
|
|
|
|
|
unsigned int nRead = std::min<unsigned int>(nLength, bufferSize);
|
|
|
|
input.Read(sBuffer, nRead);
|
|
|
|
output.Write(sBuffer, nRead);
|
|
|
|
|
|
|
|
nLength -= nRead;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|