serialization stuff

This commit is contained in:
Asuro
2025-03-24 14:21:31 +01:00
parent 551796e7ad
commit fa93abe1ec
6 changed files with 97 additions and 114 deletions

View File

@@ -105,9 +105,8 @@ namespace Game
LOG("Loading %s", fullPath.getCPtr()); LOG("Loading %s", fullPath.getCPtr());
Generated::Deserializer ser; Generated::Deserializer ser;
ser.Init(fullPath);
Generated::PuzzleData dataBuf; Generated::PuzzleData dataBuf;
if (ser.ReadT("PZZL", dataBuf)) if (ser.Init(fullPath, "PZZL") && ser.ReadT(dataBuf))
{ {
if (dataBuf.ID >= BX_COUNTOF(Puzzles)) if (dataBuf.ID >= BX_COUNTOF(Puzzles))
{ {

View File

@@ -42,8 +42,7 @@ namespace Puzzle
void LoadStaticPuzzleData() void LoadStaticPuzzleData()
{ {
Deserializer ser; Deserializer ser;
ser.Init("game/data/static/puzzle.dat"); if (ser.Init("game/data/static/puzzle.dat", "SPUZ") && ser.ReadT(StaticData))
if (ser.ReadT("SPUZ", StaticData))
{ {
LOG("Successfully loaded static puzzle data!"); LOG("Successfully loaded static puzzle data!");
} }
@@ -54,8 +53,7 @@ namespace Puzzle
{ {
auto& data = GetStaticPuzzleData(); auto& data = GetStaticPuzzleData();
Serializer ser; Serializer ser;
ser.Init("game/data/static/puzzle.dat"); if (ser.Init("game/data/static/puzzle.dat", "SPUZ") && ser.WriteT(GetStaticPuzzleData()))
if (ser.WriteT("SPUZ", GetStaticPuzzleData()))
{ {
LOG("Successfully saved static puzzle data!"); LOG("Successfully saved static puzzle data!");
} }
@@ -576,8 +574,7 @@ namespace Puzzle
char path[128]{0}; char path[128]{0};
WritePuzzleFilePath(path, sizeof(path), obj.ID); WritePuzzleFilePath(path, sizeof(path), obj.ID);
Serializer ser; Serializer ser;
ser.Init(path); if (ser.Init(path, "PZZL") && ser.WriteT(obj))
if (ser.WriteT("PZZL", obj))
{ {
LOG("Saved to %s", path); LOG("Saved to %s", path);
} }

View File

@@ -1,5 +1,4 @@
#pragma once #pragma once
#include "Serial.h"
#include <cstdint> #include <cstdint>
#include <imgui.h> #include <imgui.h>

View File

@@ -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)
{
}

View File

@@ -1,32 +0,0 @@
#include <cstdint>
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);

View File

@@ -8,32 +8,49 @@
namespace Generated namespace Generated
{ {
struct EmbeddedTypeDef
{
uint32_t Size = sizeof(Def::DefinitionFile);
Def::DefinitionFile Data;
};
struct Serializer struct Serializer
{ {
bx::Error Err; bx::Error Err;
bx::FilePath Path; bx::FilePath Path;
bx::FileWriter Writer; 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; 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(); return Err.isOk();
} }
template <typename T> bool WriteT(const char* _4cc, const T& data) template <typename T> bool WriteT(const T& data)
{ {
if (!Write(_4cc, 4)) return false;
uint32_t hash = data.Hash; uint32_t hash = data.Hash;
if (!Write(&hash, sizeof(hash))) return false; 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); uint32_t size = sizeof(T);
if (!Write(&size, sizeof(size))) return false; if (!Write(&size, sizeof(size))) return false;
@@ -51,6 +68,11 @@ namespace Generated
{ {
Writer.close(); Writer.close();
} }
~Serializer()
{
Writer.close();
}
}; };
struct Deserializer struct Deserializer
@@ -59,11 +81,32 @@ namespace Generated
bx::FilePath Path; bx::FilePath Path;
bx::FileReader Reader; bx::FileReader Reader;
bool Init(const bx::FilePath& path) bool Init(const bx::FilePath& path, const char* _4cc)
{ {
Path = path; Path = path;
Reader.open(path, &Err); if (!Reader.open(path, &Err))
return Err.isOk(); {
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) bool Read(void* data, uint32_t size)
@@ -73,40 +116,44 @@ namespace Generated
return Err.isOk(); return Err.isOk();
} }
template <typename T> bool ReadT(const char* _4cc, T& data) template <typename T> 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; uint32_t hash = 0;
if (!Read(&hash, sizeof(hash))) return false; if (!Read(&hash, sizeof(hash))) return false;
uint32_t defSize = 0;
if (!Read(&defSize, sizeof(defSize))) return false;
if (data.Hash != hash) if (data.Hash != hash)
{ {
LOG_ERROR("Hash mismatch! %u != %u", data.Hash, hash); LOG_WARN("Hash mismatch! %u != %u", data.Hash, hash);
return false;
// 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; return true;
} }
@@ -114,6 +161,11 @@ namespace Generated
{ {
Reader.close(); Reader.close();
} }
~Deserializer()
{
Reader.close();
}
}; };
template <typename T> bool Save(const T* obj, uint32_t count, Serializer& serializer); template <typename T> bool Save(const T* obj, uint32_t count, Serializer& serializer);