From fa93abe1ec9b22aa441a07bcbb13b5687da89ceb Mon Sep 17 00:00:00 2001 From: Asuro Date: Mon, 24 Mar 2025 14:21:31 +0100 Subject: [PATCH] serialization stuff --- src/game/Level.cpp | 3 +- src/game/Puzzle.cpp | 9 +-- src/game/Puzzle.h | 1 - src/game/Serial.cpp | 32 ----------- src/game/Serial.h | 32 ----------- src/gen/Def.h | 134 ++++++++++++++++++++++++++++++-------------- 6 files changed, 97 insertions(+), 114 deletions(-) delete mode 100644 src/game/Serial.cpp delete mode 100644 src/game/Serial.h diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 81c4872..bf76178 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -105,9 +105,8 @@ namespace Game LOG("Loading %s", fullPath.getCPtr()); Generated::Deserializer ser; - ser.Init(fullPath); Generated::PuzzleData dataBuf; - if (ser.ReadT("PZZL", dataBuf)) + if (ser.Init(fullPath, "PZZL") && ser.ReadT(dataBuf)) { if (dataBuf.ID >= BX_COUNTOF(Puzzles)) { diff --git a/src/game/Puzzle.cpp b/src/game/Puzzle.cpp index d922193..8367d3d 100644 --- a/src/game/Puzzle.cpp +++ b/src/game/Puzzle.cpp @@ -42,8 +42,7 @@ namespace Puzzle void LoadStaticPuzzleData() { Deserializer ser; - ser.Init("game/data/static/puzzle.dat"); - if (ser.ReadT("SPUZ", StaticData)) + if (ser.Init("game/data/static/puzzle.dat", "SPUZ") && ser.ReadT(StaticData)) { LOG("Successfully loaded static puzzle data!"); } @@ -54,8 +53,7 @@ namespace Puzzle { auto& data = GetStaticPuzzleData(); Serializer ser; - ser.Init("game/data/static/puzzle.dat"); - if (ser.WriteT("SPUZ", GetStaticPuzzleData())) + if (ser.Init("game/data/static/puzzle.dat", "SPUZ") && ser.WriteT(GetStaticPuzzleData())) { LOG("Successfully saved static puzzle data!"); } @@ -576,8 +574,7 @@ namespace Puzzle char path[128]{0}; WritePuzzleFilePath(path, sizeof(path), obj.ID); Serializer ser; - ser.Init(path); - if (ser.WriteT("PZZL", obj)) + if (ser.Init(path, "PZZL") && ser.WriteT(obj)) { LOG("Saved to %s", path); } diff --git a/src/game/Puzzle.h b/src/game/Puzzle.h index 299e937..ce4daf0 100644 --- a/src/game/Puzzle.h +++ b/src/game/Puzzle.h @@ -1,5 +1,4 @@ #pragma once -#include "Serial.h" #include #include diff --git a/src/game/Serial.cpp b/src/game/Serial.cpp deleted file mode 100644 index fc97eb1..0000000 --- a/src/game/Serial.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "Global.h" -#include "Log.h" -#include "Serial.h" -#include "bx/bx.h" -#include "bx/file.h" -#include "bx/filepath.h" - -void SerializeStruct(void* data, uint64_t size, const char* path) -{ - bx::Error err; - bx::FilePath filePath{path}; - bx::FileWriter writer; - if (writer.open(filePath, false, &err)) - { - if (!writer.write(data, size, &err)) - { - LOG_ERROR("Failed to write to file %s: %s", path, err.getMessage().getCPtr()); - writer.close(); - return; - } - } - else - { - LOG_ERROR("Failed to open file %s: %s", path, err.getMessage().getCPtr()); - return; - } - LOG("Successful serialization"); -} - -void DeserializeStruct(void* data, SerializationHeader& expectedHeader, const char* path) -{ -} diff --git a/src/game/Serial.h b/src/game/Serial.h deleted file mode 100644 index 49899b4..0000000 --- a/src/game/Serial.h +++ /dev/null @@ -1,32 +0,0 @@ -#include - -struct SerializationHeader -{ - uint8_t _ID0 = 0; - uint8_t _ID1 = 0; - uint8_t _ID2 = 0; - uint8_t _ID3 = 0; - uint8_t HeaderVersion = 0; - uint8_t VersionNum = 0; - uint8_t Reserved0 = 0; - uint8_t Reserved1 = 0; -}; - -#define SER_HEADER(Version, FCC) \ - SerializationHeader __Header{ \ - FCC[0], \ - FCC[1], \ - FCC[2], \ - FCC[3], \ - 1, \ - Version, \ - 0, \ - 0, \ - }; \ - bool VersionMatches(uint8_t headerVersion, uint8_t versionNum) \ - { \ - return headerVersion == 1 && versionNum == Version; \ - } - -void SerializeStruct(void* data, uint64_t size, const char* path); -void DeserializeStruct(void* data, SerializationHeader& expectedHeader, const char* path); diff --git a/src/gen/Def.h b/src/gen/Def.h index 256a56c..0cfcefe 100644 --- a/src/gen/Def.h +++ b/src/gen/Def.h @@ -8,32 +8,49 @@ namespace Generated { - struct EmbeddedTypeDef - { - uint32_t Size = sizeof(Def::DefinitionFile); - Def::DefinitionFile Data; - }; - struct Serializer { bx::Error Err; bx::FilePath Path; bx::FileWriter Writer; - bool Init(const bx::FilePath& path) + bool Init(const bx::FilePath& path, const char* _4cc) { + if (_4cc == nullptr) + { + LOG_ERROR("Provided invalid 4cc!"); + return false; + } + if (path.isEmpty()) + { + LOG_ERROR("Provided empty path!"); + return false; + } Path = path; - Writer.open(path, false, &Err); + if (!Writer.open(path, false, &Err)) + { + LOG_ERROR("Failed to open file %s: %s", path.getCPtr(), Err.getMessage().getCPtr()); + return false; + } + Writer.write(_4cc, 4, &Err); + if (!Err.isOk()) + { + LOG_ERROR("Failed to write to file %s: %s", path.getCPtr(), Err.getMessage().getCPtr()); + } return Err.isOk(); } - template bool WriteT(const char* _4cc, const T& data) + template bool WriteT(const T& data) { - if (!Write(_4cc, 4)) return false; - uint32_t hash = data.Hash; if (!Write(&hash, sizeof(hash))) return false; + uint32_t defSize = 0; + if (!Write(&defSize, sizeof(defSize))) return false; + + // auto& definitions = GetDefinitions(); + // if (!Write(&definitions, sizeof(definitions))) return false; + uint32_t size = sizeof(T); if (!Write(&size, sizeof(size))) return false; @@ -51,6 +68,11 @@ namespace Generated { Writer.close(); } + + ~Serializer() + { + Writer.close(); + } }; struct Deserializer @@ -59,11 +81,32 @@ namespace Generated bx::FilePath Path; bx::FileReader Reader; - bool Init(const bx::FilePath& path) + bool Init(const bx::FilePath& path, const char* _4cc) { Path = path; - Reader.open(path, &Err); - return Err.isOk(); + if (!Reader.open(path, &Err)) + { + LOG_ERROR("Failed to open file %s: %s", path.getCPtr(), Err.getMessage().getCPtr()); + return false; + } + char read4cc[4]{0}; + int32_t readAmount = Reader.read(read4cc, 4, &Err); + if (!Err.isOk()) + { + LOG_ERROR("Failed to read from file %s: %s", path.getCPtr(), Err.getMessage().getCPtr()); + return false; + } + if (readAmount < 4) + { + LOG_ERROR("Failed to read enough bytes from file %s", path.getCPtr()); + return false; + } + if (read4cc[0] != _4cc[0] || read4cc[1] != _4cc[1] || read4cc[2] != _4cc[2] || read4cc[3] != _4cc[3]) + { + LOG_ERROR("4CC mismatch! %.4s != %.4s", read4cc, _4cc); + return false; + } + return true; } bool Read(void* data, uint32_t size) @@ -73,40 +116,44 @@ namespace Generated return Err.isOk(); } - template bool ReadT(const char* _4cc, T& data) + template bool ReadT(T& data) { - char magic[5]{0}; - if (!Read(magic, 4)) return false; - - bx::StringView given{_4cc, 4}; - bx::StringView loaded{magic, 4}; - if (bx::strCmp(given, loaded) != 0) - { - LOG_ERROR("Magic mismatch! %s != %s", _4cc, magic); - return false; - } - uint32_t hash = 0; if (!Read(&hash, sizeof(hash))) return false; + + uint32_t defSize = 0; + if (!Read(&defSize, sizeof(defSize))) return false; + if (data.Hash != hash) { - LOG_ERROR("Hash mismatch! %u != %u", data.Hash, hash); - return false; + LOG_WARN("Hash mismatch! %u != %u", data.Hash, hash); + + // TODO: figure out upgrade data + data = {}; + return true; + } + else + { + LOG("Hash match!"); + + // Skip definitions, we know they match + Reader.seek(defSize); + + uint32_t size = 0; + if (!Read(&size, sizeof(size))) return false; + if (sizeof(T) != size) + { + LOG_ERROR("Size mismatch! %u != %u", sizeof(T), size); + return false; + } + + if (!Load(&data, 1, *this)) + { + LOG_ERROR("Failed to load: %s", Err.getMessage().getCPtr()); + return false; + } } - uint32_t size = 0; - if (!Read(&size, sizeof(size))) return false; - if (sizeof(T) != size) - { - LOG_ERROR("Size mismatch! %u != %u", sizeof(T), size); - return false; - } - - if (!Load(&data, 1, *this)) - { - LOG_ERROR("Failed to load: %s", Err.getMessage().getCPtr()); - return false; - } return true; } @@ -114,6 +161,11 @@ namespace Generated { Reader.close(); } + + ~Deserializer() + { + Reader.close(); + } }; template bool Save(const T* obj, uint32_t count, Serializer& serializer);