#include "fallout76savegame.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 "gamefallout76.h" Fallout76SaveGame::Fallout76SaveGame(QString const& fileName, GameFallout76 const* game) : GamebryoSaveGame(fileName, game, true) { FileWrapper file(fileName, "FO76_SAVEGAME"); FILETIME ftime; fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); // 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(&ftime, &ctime); setCreationTime(ctime); } void Fallout76SaveGame::fetchInformationFields(FileWrapper& file, QString playerName, unsigned short playerLevel, QString playerLocation, unsigned long saveNumber, FILETIME& creationTime) const { file.skip(); // header size file.skip(); // header version file.read(saveNumber); file.read(playerName); unsigned long 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 FILETIME ftime; file.read(ftime); } std::unique_ptr Fallout76SaveGame::fetchDataFields() const { FileWrapper file(getFilepath(), "TESV_SAVEGAME"); // 10bytes { FILETIME ftime; fetchInformationFields(file, m_PCName, m_PCLevel, m_PCLocation, m_SaveNumber, ftime); } std::unique_ptr fields = std::make_unique(); file.readImage(384, true); uint8_t saveGameVersion = file.readChar(); QString ignore; file.read(ignore); // game version file.skip(); // plugin info size file.readPlugins(); if (saveGameVersion >= 68) { file.readLightPlugins(); } return fields; }