Created
July 27, 2024 17:07
-
-
Save playday3008/3a3b20d95bb1f31fc289272065c63905 to your computer and use it in GitHub Desktop.
ProfileOptions file pattern using ImHex (FBCHUNKS)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <type/magic.pat> | |
| #include <std/io.pat> | |
| #include <std/hash.pat> | |
| #include <std/sys.pat> | |
| #include <std/mem.pat> | |
| #pragma loop_limit 131072 | |
| #define CRC32POLY_ZIP 0xEDB88320 | |
| /// ======= CRC32 ======= | |
| fn byte_lookup_uint32_lsb_first(u32 poly) { | |
| std::mem::Section lookup_crc32_zip = std::mem::create_section("lookup_crc32_zip"); | |
| std::mem::set_section_size(lookup_crc32_zip, 0x100); | |
| u32 lookup[0x100] @ 0x00 in lookup_crc32_zip; | |
| for (u32 b = 0, b < 256, b = b + 1) { | |
| u32 x = b; | |
| for (u32 i = 0, i < 8, i = i + 1) { | |
| x = (x >> 1) ^ ((x & 1) == 0 ? 0 : poly); | |
| } | |
| lookup[b] = x; | |
| } | |
| return lookup_crc32_zip; | |
| }; | |
| std::mem::Section lookup_crc32_zip = byte_lookup_uint32_lsb_first(CRC32POLY_ZIP); | |
| fn crc32_lsb_first(u32 addr, u32 size, u32 crc, std::mem::Section lookup_crc32_zip) { | |
| u32 lookup[0x100] @ 0x00 in lookup_crc32_zip; | |
| str data = std::mem::read_string(addr, size); | |
| for (u32 i = 0, i < size, i = i + 1) { | |
| u8 b = u8(data[i]); | |
| crc = (crc >> 8) ^ lookup[u8(crc) ^ b]; | |
| } | |
| return crc; | |
| }; | |
| fn crc32_zip(u32 addr, u32 size, u32 crc = 0) { | |
| return ~crc32_lsb_first(addr, size, ~crc, lookup_crc32_zip); | |
| }; | |
| fn fb_crc32(str name, u32 expected, u32 address, u32 size) { | |
| str pattern = std::mem::read_string(address, size); | |
| u32 checksum = crc32_zip(address, size, 0x12345678); | |
| std::assert_warn( | |
| checksum == expected, | |
| std::format("{:} expected checksum 0x{:08X}, actual 0x{:08X}", name, expected, checksum) | |
| ); | |
| }; | |
| /// ======= Data ======= | |
| enum DataType : u32 { | |
| Int = 0x1, | |
| Float = 0x2, | |
| }; | |
| struct Setting { | |
| DataType type; | |
| u32 name_size; | |
| char name[name_size]; | |
| u32 value_size; | |
| char value[value_size]; | |
| std::assert_warn( | |
| type == DataType::Int | |
| || type == DataType::Float, | |
| std::format("DataType is {:d} ({:}) at address 0x{:X}", u32(type), type, addressof(type)) | |
| ); | |
| }; | |
| struct Group { | |
| u32 count; | |
| Setting settings[count]; | |
| }; | |
| struct Header { | |
| u32 checksum; | |
| u32 group_count; | |
| fb_crc32("Header", checksum, addressof(this) + sizeof(checksum), sizeof(this) - sizeof(checksum)); | |
| }; | |
| u32 data_total_size; | |
| u32 data_groups_count; | |
| struct Data { | |
| u32 checksum; | |
| Group groups[data_groups_count]; | |
| padding[data_total_size - sizeof(this)]; | |
| fb_crc32(std::format("Data<{}>", data_groups_count), checksum, addressof(this) + sizeof(checksum), sizeof(this) - sizeof(checksum)); | |
| }; | |
| struct ProfileOptions { | |
| type::Magic<"FBCHUNKS"> magic; | |
| u16 version; | |
| u32 header_size; | |
| u32 data_size; | |
| Header header; | |
| std::assert_warn( | |
| sizeof(header) == header_size, | |
| std::format("Header size mismatch, actual {} expected {}", sizeof(header), header_size) | |
| ); | |
| data_total_size = data_size; | |
| data_groups_count = header.group_count; | |
| Data data; | |
| std::assert_warn( | |
| sizeof(data) == data_size, | |
| std::format("Data size mismatch, actual {} expected {}", sizeof(data), data_size) | |
| ); | |
| }; | |
| ProfileOptions profile_options @ 0x0; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment