#include "fallout4vrsavegame.h" #ifdef _WIN32 #include #else #include #include using SYSTEMTIME = _SYSTEMTIME; static void FileTimeToSystemTime(const FILETIME* ft, SYSTEMTIME* st) { const uint64_t ticks = (static_cast(ft->dwHighDateTime) << 32) | static_cast(ft->dwLowDateTime); const int64_t unixSecs = static_cast(ticks / 10000000ULL) - 11644473600LL; const uint64_t remainderHns = ticks % 10000000ULL; const QDateTime dt = QDateTime::fromSecsSinceEpoch(unixSecs, QTimeZone::UTC); const QDate d = dt.date(); const QTime t = dt.time(); st->wYear = static_cast(d.year()); st->wMonth = static_cast(d.month()); st->wDayOfWeek = static_cast(d.dayOfWeek() % 7); st->wDay = static_cast(d.day()); st->wHour = static_cast(t.hour()); st->wMinute = static_cast(t.minute()); st->wSecond = static_cast(t.second()); st->wMilliseconds = static_cast(remainderHns / 10000); } #endif #include "gamefallout4vr.h" Fallout4VRSaveGame::Fallout4VRSaveGame(QString const& fileName, GameFallout4VR const* game) : GamebryoSaveGame(fileName, game, true) { FileWrapper file(getFilepath(), "FO4_SAVEGAME"); FILETIME creationTime; fetchInformationFields(file, m_SaveNumber, m_PCName, m_PCLevel, m_PCLocation, creationTime); // A file time is a 64-bit value that represents the number of 100-nanosecond // intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal // Time (UTC). So we need to convert that to something useful SYSTEMTIME ctime; ::FileTimeToSystemTime(&creationTime, &ctime); setCreationTime(ctime); } void Fallout4VRSaveGame::fetchInformationFields( FileWrapper& file, uint32_t& saveNumber, QString& playerName, unsigned short& playerLevel, QString& playerLocation, FILETIME& creationTime) const { file.skip(); // header size file.skip(); // header version file.read(saveNumber); file.read(playerName); uint32_t temp; file.read(temp); playerLevel = static_cast(temp); file.read(playerLocation); QString ignore; file.read(ignore); // playtime as ascii hh.mm.ss file.read(ignore); // race name (i.e. BretonRace) file.skip(); // Player gender (0 = male) file.skip(2); // experience gathered, experience required file.read(creationTime); } std::unique_ptr Fallout4VRSaveGame::fetchDataFields() const { FileWrapper file(getFilepath(), "FO4_SAVEGAME"); // 10bytes { QString dummyName, dummyLocation; unsigned short dummyLevel; uint32_t dummySaveNumber; FILETIME dummyTime; fetchInformationFields(file, dummySaveNumber, dummyName, dummyLevel, dummyLocation, dummyTime); } QString ignore; std::unique_ptr fields = std::make_unique(); fields->Screenshot = file.readImage(384, true); uint8_t saveGameVersion = file.readChar(); file.read(ignore); // game version file.skip(); // plugin info size fields->Plugins = file.readPlugins(); if (saveGameVersion >= 68) { fields->LightPlugins = file.readLightPlugins(); } return fields; }