#include #include "XpsSaveImporter.h" #include "StdStreamUtils.h" void CXpsSaveImporter::Import(Framework::CStream& input, const fs::path& outputPath) { 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(input.Tell()); ExtractFiles(input, outputPath, nArchiveSize); } void CXpsSaveImporter::ExtractFiles(Framework::CStream& input, const fs::path& basePath, uint32 nArchiveSize) { if(!fs::exists(basePath)) { fs::create_directory(basePath); } while(!input.IsEOF() && (static_cast(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); fs::path outputPath(basePath / sName); 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(nLength, bufferSize); input.Read(sBuffer, nRead); output.Write(sBuffer, nRead); nLength -= nRead; } } } } }