From d718a430e07dbe56f1fb6fdbecc4762f1a77a041 Mon Sep 17 00:00:00 2001 From: "Chris Forseth (C4)" Date: Mon, 9 May 2022 17:02:02 -0500 Subject: [PATCH] Get up to member reading - but haven't made sense of it yet; --- LegoBlobReader/LegoBlobReader.cpp | 267 +++++++++++++++++++++++++++--- 1 file changed, 243 insertions(+), 24 deletions(-) diff --git a/LegoBlobReader/LegoBlobReader.cpp b/LegoBlobReader/LegoBlobReader.cpp index 2021b3d..65edc4c 100644 --- a/LegoBlobReader/LegoBlobReader.cpp +++ b/LegoBlobReader/LegoBlobReader.cpp @@ -6,62 +6,281 @@ #include #include #include +#include +#include typedef unsigned char byte; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef __int64 int64; static char const* FILE_NAME = "GAMEPROGRESS.broke.blob"; -byte* ReadFileToBuffer(char const* filename, size_t* file_len) +//-------------------------------------------------------------------------------------------------------- +static void FlipBytes(void* data, size_t buffer_len) +{ + byte* buffer = (byte*)data; + size_t flip_count = buffer_len >> 1; + for (size_t i = 0; i < flip_count; ++i) { + std::swap(buffer[i], buffer[buffer_len - i - 1]); + } +} + +//-------------------------------------------------------------------------------------------------------- +struct type_info_t +{ + std::string name; + size_t byte_size; + + inline bool is_valid() const { return byte_size > 0; } +}; + +//-------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------- +class BinaryReader +{ + public: + BinaryReader(char const* filename); + ~BinaryReader(); + + bool is_valid() const { return (nullptr != m_buffer); } + + public: // accessors + size_t get_byte_size() const { return m_byte_size; } + size_t get_read_offset() const { return m_offset; } + size_t get_bytes_remaining() const { return get_byte_size() - get_read_offset(); } + + byte* get_read_head() const { return m_buffer + m_offset; } + + public: // functions + bool skip(size_t num_bytes); + bool read_bytes(void* dst, size_t num_bytes); + + std::string read_string(); + + template + T read(T const& def_value) + { + T val; + if (read_bytes(&val, sizeof(T))) { + // FlipBytes(&val, sizeof(T)); + return val; + } else { + return def_value; + } + } + + bool read_type_info(type_info_t* out); + + + public: // operators + byte operator[](size_t offset) const { return m_buffer[offset]; } + + public: + byte* m_buffer = nullptr; + size_t m_byte_size = 0; + size_t m_offset = 0; +}; + +//-------------------------------------------------------------------------------------------------------- +// BinearyReader implementation +//-------------------------------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------------------------------- +BinaryReader::BinaryReader(char const* filename) { FILE* fp = nullptr; - ::fopen_s(&fp, filename, "r"); + ::fopen_s(&fp, filename, "rb"); if (nullptr == fp) { - return nullptr; + return; } ::fseek(fp, 0, SEEK_END); size_t eof = ::ftell(fp); ::fseek(fp, 0, SEEK_SET); - byte* buffer = (byte*) ::malloc(eof); - if (nullptr != buffer) { - *file_len = ::fread(buffer, 1, eof, fp); + m_buffer = (byte*) ::malloc(eof); + if (nullptr != m_buffer) { + m_byte_size = ::fread(m_buffer, 1, eof, fp); } ::fclose(fp); - return buffer; } -static void DisplayProgress(byte* buffer, size_t len, size_t offset) +//-------------------------------------------------------------------------------------------------------- +BinaryReader::~BinaryReader() { - size_t bytes_to_show = len - offset; + if (nullptr != m_buffer) { + delete m_buffer; + m_buffer = nullptr; + } +} + +//-------------------------------------------------------------------------------------------------------- +bool BinaryReader::skip(size_t num_bytes) +{ + if (get_bytes_remaining() < num_bytes) { + return false; + } + + m_offset += num_bytes; + return true; +} + +//-------------------------------------------------------------------------------------------------------- +bool BinaryReader::read_bytes(void* dst, size_t num_bytes) +{ + byte* src = get_read_head(); + if (!skip(num_bytes)) { + return false; + } + + ::memcpy(dst, src, num_bytes); + return true; +} + +//-------------------------------------------------------------------------------------------------------- +std::string BinaryReader::read_string() +{ + uint32 len = read(0); + std::string str; + + if (len > 0) { + str.resize(len + 1); + read_bytes(&str[0], len); + str[len] = 0; + } + + return str; +} + +//-------------------------------------------------------------------------------------------------------- +bool BinaryReader::read_type_info(type_info_t* out) +{ + read(0); // offset to next + read_string(); // "type" + + out->name = read_string(); + out->byte_size = read(0); + + return out->is_valid(); +} + + +//-------------------------------------------------------------------------------------------------------- +// termination function for file reading - just prints where we left off +//-------------------------------------------------------------------------------------------------------- +static void DisplayProgress(BinaryReader const& reader) +{ + size_t bytes_to_show = reader.get_bytes_remaining(); bytes_to_show = std::min(bytes_to_show, 16); - printf("At %u (0x%08x) into buffer... Next %u byte(s) are...\n> ", offset, offset, bytes_to_show); + size_t offset = reader.get_read_offset(); + printf("\nAt %u (0x%08x) into buffer... Next %u byte(s) are...\n> ", offset, offset, bytes_to_show); for (size_t i = 0; i < bytes_to_show; ++i) { - byte b = buffer[offset + i]; + byte b = reader[offset + i]; printf("%02X ", b); } + printf("<\n"); } -static void ParseBuffer(byte* buffer, size_t len) +//-------------------------------------------------------------------------------------------------------- +// main file reading function +//-------------------------------------------------------------------------------------------------------- +static void ParseBuffer(BinaryReader& reader) { - size_t offset = 0; - DisplayProgress(buffer, len, offset); -} + uint32 version = reader.read(0); + printf("Version: %u\n", version); -int main() -{ - size_t file_len; - byte* buffer = ReadFileToBuffer(FILE_NAME, &file_len); - if (nullptr == buffer) { - printf("Failed to open file.\n"); + std::string streaminfo = reader.read_string(); + printf("Label: %s\n", streaminfo.c_str()); + + uint32 unknown0 = reader.read(0); // 0x33 + uint32 unknown1 = reader.read(0); // 0x01 + uint32 unknown2 = reader.read(0); // 0x00 + + // reading a type infos + uint32 type_block_size = reader.read(0); // 0x02f4 + std::string typelist = reader.read_string(); + uint32 type_count = reader.read(0); // 0x1A?std::vector types; + printf("\nType List (%u total types)...\n", type_count); + + std::vector types; + for (uint32 i = 0; i < type_count; ++i) { + type_info_t type; + reader.read_type_info(&type); + + // push even bad types in to keep the index + types.push_back(type); + if (type.is_valid()) { + printf("> Type [%02u]: %s (%u B)\n", i, type.name.c_str(), type.byte_size); + } else { + printf("> Type [%02u]: REDACTED\n", i); + } } - ParseBuffer(buffer, file_len); + // read class infos + uint32 class_block_size = reader.read(0); + std::string classlist = reader.read_string(); + uint32 class_count = reader.read(0); - free(buffer); - printf("\n\n\n"); + printf("\nClass List (%u total classes)...\n", class_count); + for (uint32 i = 0; i < class_count; ++i) { + uint32 class_size = reader.read(0); // to skip to end of this class + std::string class_id = reader.read_string(); // "Class" + std::string class_name = reader.read_string(); + printf("> Class: %s\n:", class_name.c_str()); + + uint32 some_count = reader.read(0); + std::string ver_str = reader.read_string(); // "Version" + uint32 ver_num_maybe = reader.read(0); + uint32 offset_maybe = reader.read(0); + + std::string types_str = reader.read_string(); // "Types" + + reader.skip(1); // 0 + uint32 mem_count = reader.read(0); // 0x07 ? + printf(">> member count: %u\n", mem_count); + + for (uint32 mi = 0; mi < mem_count; ++mi) { + uint32 type_idx = reader.read(0); // 0x02 ? + type_info_t const& type = types[mi]; + + std::string mem_name = reader.read_string(); + printf(">> %s : %s;\n", mem_name.c_str(), type.name.c_str()); + + // uint16 skip_to_next = reader.read(0); + + /* + uint32 type_size = type.byte_size; + if (type_size != ~0U) { + reader.skip(type_size); // def value - based on type + } + */ + + uint32 const STOP_VALUE = 0x80'00'00'00; + uint32 val = reader.read(STOP_VALUE); + while (val != STOP_VALUE) { + val = reader.read(STOP_VALUE); + } + reader.skip(8); // usually (0, 0), or (0, -1) + } + } + + + DisplayProgress(reader); +} + +//-------------------------------------------------------------------------------------------------------- +// main +//-------------------------------------------------------------------------------------------------------- +int main() +{ + BinaryReader reader(FILE_NAME); + if (reader.is_valid()) { + ParseBuffer(reader); + } + + printf("\n\n\nPress Any Key...\n"); _getch(); }