From 8c5b719469bc61e33a451d9b3aeb66c7b0a6d68e Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Fri, 19 Jul 2024 03:51:23 -0400 Subject: Added savedata analyzer --- src/godot_variant.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 src/godot_variant.cpp (limited to 'src/godot_variant.cpp') diff --git a/src/godot_variant.cpp b/src/godot_variant.cpp new file mode 100644 index 0000000..152408f --- /dev/null +++ b/src/godot_variant.cpp @@ -0,0 +1,82 @@ +// Godot save decoder algorithm by Chris Souvey. + +#include "godot_variant.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +uint16_t ReadUint16(std::basic_istream& stream) { + uint16_t result; + stream.read(reinterpret_cast(&result), 2); + return result; +} + +uint32_t ReadUint32(std::basic_istream& stream) { + uint32_t result; + stream.read(reinterpret_cast(&result), 4); + return result; +} + +GodotVariant ParseVariant(std::basic_istream& stream) { + uint16_t type = ReadUint16(stream); + stream.ignore(2); + + switch (type) { + case 1: { + // bool + bool boolval = (ReadUint32(stream) == 1); + return {boolval}; + } + case 15: { + // nodepath + uint32_t name_length = ReadUint32(stream) & 0x7fffffff; + uint32_t subname_length = ReadUint32(stream) & 0x7fffffff; + uint32_t flags = ReadUint32(stream); + + std::vector result; + for (size_t i = 0; i < name_length + subname_length; i++) { + uint32_t char_length = ReadUint32(stream); + uint32_t padded_length = (char_length % 4 == 0) + ? char_length + : (char_length + 4 - (char_length % 4)); + std::vector next_bytes(padded_length); + stream.read(next_bytes.data(), padded_length); + std::string next_piece; + std::copy(next_bytes.begin(), + std::next(next_bytes.begin(), char_length), + std::back_inserter(next_piece)); + result.push_back(next_piece); + } + + return {result}; + } + case 19: { + // array + uint32_t length = ReadUint32(stream) & 0x7fffffff; + std::vector result; + for (size_t i = 0; i < length; i++) { + result.push_back(ParseVariant(stream)); + } + return {result}; + } + default: { + // eh + } + } +} + +} // namespace + +GodotVariant ParseGodotFile(std::string filename) { + std::ifstream file_stream(filename, std::ios_base::binary); + file_stream.ignore(4); + return ParseVariant(file_stream); +} -- cgit 1.4.1