Play-/Source/saves/SaveExporter.cpp

133 lines
3.4 KiB
C++
Raw Normal View History

2019-08-17 13:51:31 -04:00
#include <cstring>
#include "SaveExporter.h"
#include "StdStream.h"
#include "StdStreamUtils.h"
2019-10-16 20:51:11 -04:00
void CSaveExporter::ExportPSU(Framework::CStream& outputStream, const fs::path& savePath)
{
uint32 nSector = 0x18D;
2019-10-16 20:51:11 -04:00
auto baseTime = fs::last_write_time(savePath);
//Save base directory entry
{
PSUENTRY Entry;
memset(&Entry, 0, sizeof(PSUENTRY));
Entry.nSize = 2;
2019-10-16 20:51:11 -04:00
const fs::directory_iterator itEnd;
for(fs::directory_iterator itElement(savePath);
2018-04-30 21:01:23 +01:00
itElement != itEnd;
itElement++)
{
2019-10-16 20:51:11 -04:00
if(fs::is_directory(*itElement)) continue;
Entry.nSize++;
}
2018-04-30 21:01:23 +01:00
Entry.nFlags = 0x8427;
Entry.nSector = nSector;
2018-04-30 21:01:23 +01:00
PSU_CopyTime(&Entry.CreationTime, baseTime);
PSU_CopyTime(&Entry.ModificationTime, baseTime);
strncpy(reinterpret_cast<char*>(Entry.sName), savePath.filename().string().c_str(), 0x1C0);
outputStream.Write(&Entry, sizeof(PSUENTRY));
}
2018-04-30 21:01:23 +01:00
static const char* sRelDirName[2] =
{
".",
"..",
};
//Save "relative" directories
for(unsigned int i = 0; i < 2; i++)
{
PSUENTRY Entry;
memset(&Entry, 0, sizeof(PSUENTRY));
2018-04-30 21:01:23 +01:00
Entry.nFlags = 0x8427;
Entry.nSector = 0;
2018-04-30 21:01:23 +01:00
PSU_CopyTime(&Entry.CreationTime, baseTime);
PSU_CopyTime(&Entry.ModificationTime, baseTime);
strncpy(reinterpret_cast<char*>(Entry.sName), sRelDirName[i], 0x1C0);
outputStream.Write(&Entry, sizeof(PSUENTRY));
}
nSector += 2;
//Save individual file entries
2019-10-16 20:51:11 -04:00
const fs::directory_iterator itEnd;
for(fs::directory_iterator itElement(savePath);
2018-04-30 21:01:23 +01:00
itElement != itEnd;
itElement++)
{
2019-10-16 20:51:11 -04:00
if(fs::is_directory(*itElement)) continue;
2019-10-16 20:51:11 -04:00
fs::path saveItemPath(*itElement);
2019-10-16 20:51:11 -04:00
auto itemTime = fs::last_write_time(saveItemPath);
PSUENTRY Entry;
memset(&Entry, 0, sizeof(PSUENTRY));
2018-04-30 21:01:23 +01:00
Entry.nFlags = 0x8497;
2019-10-16 20:51:11 -04:00
Entry.nSize = static_cast<uint32>(fs::file_size(saveItemPath));
2018-04-30 21:01:23 +01:00
Entry.nSector = nSector;
2018-04-30 21:01:23 +01:00
PSU_CopyTime(&Entry.CreationTime, itemTime);
PSU_CopyTime(&Entry.ModificationTime, itemTime);
strncpy(reinterpret_cast<char*>(Entry.sName), saveItemPath.filename().string().c_str(), 0x1C0);
outputStream.Write(&Entry, sizeof(PSUENTRY));
//Write file contents
{
auto itemStream(Framework::CreateInputStdStream(saveItemPath.native()));
uint32 nSize = Entry.nSize;
while(nSize != 0)
{
const uint32 bufferSize = 0x1000;
char sBuffer[bufferSize];
uint32 nRead = std::min<uint32>(nSize, bufferSize);
itemStream.Read(sBuffer, nRead);
outputStream.Write(sBuffer, nRead);
nSize -= nRead;
}
}
//Align on 0x400 boundary
{
char sBuffer[0x400];
unsigned int nPosition = Entry.nSize;
memset(sBuffer, 0, 0x400);
2018-04-30 21:01:23 +01:00
outputStream.Write(sBuffer, 0x400 - (nPosition & 0x3FF));
}
nSector += (Entry.nSize + 0x3FF) / 0x400;
}
}
2019-10-16 20:51:11 -04:00
void CSaveExporter::PSU_CopyTime(PSUENTRY::TIME* pDst, const fs::file_time_type& fileTime)
{
2019-10-16 20:51:11 -04:00
auto systemTime = std::chrono::system_clock::now() + (fileTime - fs::file_time_type::clock::now());
auto tm = std::chrono::system_clock::to_time_t(systemTime);
const auto pSrc = std::localtime(&tm);
pDst->nSecond = static_cast<uint8>(pSrc->tm_sec);
pDst->nMinute = static_cast<uint8>(pSrc->tm_min);
pDst->nHour = static_cast<uint8>(pSrc->tm_hour);
pDst->nDay = static_cast<uint8>(pSrc->tm_mday);
pDst->nMonth = static_cast<uint8>(pSrc->tm_mon);
pDst->nYear = pSrc->tm_year;
}