From da1c2687e8cba54db29f994c315c89e9b07cffaa Mon Sep 17 00:00:00 2001 From: Surasia <74399067+Surasia@users.noreply.github.com> Date: Sat, 6 Jul 2024 17:33:03 +0200 Subject: [PATCH] patterns/hinf_*: Add Halo Infinite tag and module file patterns (#267) * patterns/hinf: Add Halo Infinite Tag and Module patterns * patterns/hinf_bitmap: remove pattern --- README.md | 3 +- patterns/hinf_bitmap.hexpat | 538 ------------------ patterns/hinf_module.hexpat | 77 +++ patterns/hinf_tag.hexpat | 168 ++++++ .../test_data/hinf_bitmap.hexpat.bitm | Bin 132052 -> 0 bytes .../test_data/hinf_module.hexpat.module | Bin 0 -> 39535 bytes tests/patterns/test_data/hinf_tag.hexpat.tag | Bin 0 -> 3120 bytes 7 files changed, 247 insertions(+), 539 deletions(-) delete mode 100644 patterns/hinf_bitmap.hexpat create mode 100644 patterns/hinf_module.hexpat create mode 100644 patterns/hinf_tag.hexpat delete mode 100644 tests/patterns/test_data/hinf_bitmap.hexpat.bitm create mode 100644 tests/patterns/test_data/hinf_module.hexpat.module create mode 100644 tests/patterns/test_data/hinf_tag.hexpat.tag diff --git a/README.md b/README.md index e33a0fc..d13ffd3 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,8 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | GGUF | | [`patterns/gguf.hexpat`](patterns/gguf.hexpat) | GGML Inference Models | | GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files | | GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format | -| Halo Bitmap || [`patterns/hinf_bitmap.hexpat`](patterns/hinf_bitmap.hexpat) | Halo Infinite Bitmap tag files | +| Halo Tag || [`patterns/hinf_tag.hexpat`](patterns/hinf_bitmap.hexpat) | Halo Infinite Tag Files | +| Halo Module || [`patterns/hinf_tag.hexpat`](patterns/hinf_bitmap.hexpat) | Halo Infinite Module Archive Files | | Halo HavokScript || [`patterns/hinf_luas.hexpat`](patterns/hinf_luas.hexpat) | Halo Infinite HavokScript 5.1 Bytecode | | ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files | | ID3 | `audio/mpeg` | [`patterns/id3.hexpat`](patterns/id3.hexpat) | ID3 tags in MP3 files | diff --git a/patterns/hinf_bitmap.hexpat b/patterns/hinf_bitmap.hexpat deleted file mode 100644 index c7c145c..0000000 --- a/patterns/hinf_bitmap.hexpat +++ /dev/null @@ -1,538 +0,0 @@ -#pragma description TODO - -import std.mem; -import std.io; -import std.string; - -struct Header { - u32 magic; - u32 version; - u64 RootStructAltGUID; - u64 AssetChecksum; - u32 DependencyCount; - s32 DataBlockCount; - s32 TagStructCount; - s32 DataReferenceCount; - s32 TagReferenceCount; - u32 StringTableSize; - u32 ZoneSetDataSize; - u32 Unk_0x34; - u32 HeaderSize; - u32 DataSize; - u32 ResourceDataSize; - u32 ActualResoureDataSize; - u8 HeaderAlignment; - u8 TagDataAlignment; - u8 ResourceDataAlignment; - u8 ActualResourceDataAlignment; - s32 IsResource; -}; - -enum curve_mode : u8 { - choose_best = 0x00, - force_FAST = 0x01, - force_PRETTY = 0x02, -}; - -enum BitmapForcedFormat : u16 { - Use_Default = 0x00, - Best_Compressed_Color_Format = 0x01, - Best_Uncompressed_Color_Format = 0x02, - Best_Compressed_Bump_Format = 0x03, - Best_Uncompressed_Bump_Format = 0x04, - Best_Compressed_Monochrome_Format = 0x05, - Best_Uncompressed_Monochrome_Format = 0x06, - Best_Compressed_Monochrome_Format_Without_Alpha = 0x07, - unused2 = 0x08, - unused3 = 0x09, - unused4 = 0x0A, - unused5 = 0x0B, - unused6 = 0x0C, - Color_And_Alpha_Formats = 0x0D, - bc1_unorm_DXT1_Compressed_Color_Key_Alpha = 0x0E, - bc2_unorm_DXT3_Compressed_Color_4bit_Alpha = 0x0F, - bc3_unorm_DXT5_Compressed_Color_Compressed_8bit_Alpha = 0x10, - Color_24bit_Alpha_8bit = 0x11, - Monochrome_8bit_Alpha_8bit = 0x12, - Channel_Mask_3bit_Color_1bit_Alpha = 0x13, - Color_30bit_Alpha_2bit = 0x14, - Color_48bit_Alpha_16bit = 0x15, - HALF_Color_Alpha = 0x16, - FLOAT_Color_Alpha = 0x17, - r8_unorm_8bit_Intensity_RGBA = 0x18, - DEPRECATED_DXT3A_4bit_Intensity_ARGB = 0x19, - bc4_unorm_rrrr_DXT5A_Compressed_Intensity_ARGB = 0x1A, - Compressed_Monochrome_Alpha = 0x1B, - b4g4r4a4_12bit_Color_4bit_Alpha = 0x1C, - Color_Only_Formats = 0x1D, - Monochrome_8bit = 0x1E, - Compressed_Color_24bit = 0x1F, - Color_32bit_R11G11B10 = 0x20, - Monochrome_16bit = 0x21, - Red_Green_Only_16bit = 0x22, - Signed_RGBA_16bit = 0x23, - HALF_Red_Only = 0x24, - FLOAT_Red_Only = 0x25, - HALF_Red_Green_Only = 0x26, - FLOAT_Red_Green_Only = 0x27, - HALF_Monochrome = 0x28, - DEPRECATED_Compressed_Monochrome_4bit = 0x29, - Compressed_Interpolated_Monochrome = 0x2A, - bc6h_uf16_HDR_RGB_Unsigned_Half_Float = 0x2B, - bc6h_sf16_HDR_RGB_Signed_Half_Float = 0x2C, - bc7_unorm_High_Quality_bc3 = 0x2D, - Alpha_Only_Formats = 0x2E, - DEPRECATED_DXT3A_4bit_Alpha = 0x2F, - bc4_unorm_000r_DXT5A_8bit_Compressed_Alpha = 0x30, - Alpha_8bit = 0x31, - unused28 = 0x32, - unused29 = 0x33, - unused30 = 0x34, - Normal_Map_Formats = 0x35, - bc5_snorm_DXN_Compressed_Normals_Better = 0x36, - DEPRECATED_CTX1_Compressed_Normals_Smaller = 0x37, - Normals_16bit = 0x38, - Normals_32bit = 0x39, - Vector_8bit_4_Channel = 0x3A, -}; - -enum BitmapDownsampleFilter : u8 { - point_sampled = 0x01, - box_filter = 0x02, - blackman_filter = 0x03, - lanczos_filter = 0x04, - nuttall_filter = 0x05, - blackman_harris_filter = 0x06, - blackman_nuttall_filter = 0x07, - flat_top_filter = 0x08, - extreme_filter = 0x09, - min_filter = 0x0A -}; - -enum BitmapType : u8 { - _2D_Texture = 0x00, - _3D_Texture = 0x01, - CubeMap = 0x02, - Array = 0x03, -}; - -enum BitmapColorSpace : u8 { - Automatic = 0x00, - Rec709 = 0x01, - DCI_P3 = 0x02, - Rec2020 = 0x03, -}; - -enum SignedDistanceFieldMethod : u8 { - Neighbors_Multithreaded = 0x00, - Neighbors = 0x01, - Cached_Euclidean_Multithreaded = 0x02, - Cached_Euclidean = 0x03, - SSEDT = 0x04, -}; - -enum BitmapFormat : u16 { - a8_unorm = 0x00, - r8_unorm_rrr1 = 0x01, - r8_unorm_rrrr = 0x02, - r8g8_unorm_rrrg = 0x03, - unused1 = 0x04, - unused2 = 0x05, - b5g6r5_unorm = 0x06, - unused3 = 0x07, - b5g6r5a1_unorm = 0x08, - b4g4r4a4_unorm = 0x09, - b8g8r8x8_unorm = 0x0A, - b8g8r8a8_unorm = 0x0B, - unused4 = 0x0C, - DEPRECATED_dxt5_bias_alpha = 0x0D, - bc1_unorm_dxt1 = 0x0E, - bc2_unorm_dxt3 = 0x0F, - bc3_unorm_dxt5 = 0x10, - DEPRECATED_a4r4g4b4_font = 0x11, - unused7 = 0x12, - unused8 = 0x13, - DEPRECATED_SOFTWARE_rgbfp32 = 0x14, - unused9 = 0x15, - r8g8_snorm_v8u8 = 0x16, - DEPRECATED_g8b8 = 0x17, - r32g32b32a32_float_abgrfp32 = 0x18, - r16g16b16a16_float_abgrfp16 = 0x19, - r16_float_rrr1_16f_mono = 0x1A, - r16_float_r000_16f_red = 0x1B, - r8g8b8a8_snorm_q8w8v8u8 = 0x1C, - r10g10b10a2_unorm_a2r10g10b10 = 0x1D, - r16g16b16a16_unorm_a16b16g16r16 = 0x1E, - r16g16_snorm_v16u16 = 0x1F, - r16_unorm_rrr0_L16 = 0x20, - r16g16_unorm_r16g16 = 0x21, - r16g16b16a16_snorm_signedr16g16b16a16 = 0x22, - DEPRECATED_dxt3a = 0x23, - bc4_unorm_rrrr_dxt5a = 0x24, - bc4_snorm_rrrr = 0x25, - DEPRECATED_dxt3a_1111 = 0x26, - bc5_snorm_dxn = 0x27, - DEPRECATED_ctx1 = 0x28, - DEPRECATED_dxt3a_alpha_only = 0x29, - DEPRECATED_dxt3a_monochrome_only = 0x2A, - bc4_unorm_000r_dxt5a_alpha = 0x2B, - bc4_unorm_rrr1_dxt5a_mono = 0x2C, - bc5_unorm_rrrg_dxn_mono_alpha = 0x2D, - bc5_snorm_rrrg_dxn_mono_alpha_signed = 0x2E, - bc6h_uf16 = 0x2F, - bc6h_sf16 = 0x30, - bc7_unorm = 0x31, - d24_unorm_s8_uint_depth_24 = 0x32, - r11g11b10_float = 0x33, - r16g16_float = 0x34, -}; - -enum BitmapCurve : u8 { - unknown = 0x00, - xRGB = 0x01, - gamma_2 = 0x02, - linear = 0x03, - offset_log = 0x04, - sRGB = 0x05, - Rec709 = 0x06, -}; - -enum BitmapUsageFlag : u8 { - ignore_curve_override = 0x00, - do_not_allow_size_optimization = 0x01, - swap_axes = 0x02, - pre_filter_cubemaps = 0x03, -}; - -enum BitmapSlicer : u8 { - automatically_determine_slicer = 0x00, - no_slicing = 0x01, - color_plate_slicer = 0x02, - cube_map_slicer = 0x03, - color_grading_slicer = 0x04, -}; - -enum BitmapPacker : u8 { - no_packing = 0x00, - sprite_packing = 0x01, - sprite_packing_if_needed = 0x02, - _3d_pack = 0x03, -}; - -enum BitmapSmallestMip : u8 { - _1_pixel = 0x00, - _2_pixel = 0x01, - _4_pixel = 0x02, - _8_pixel = 0x03, - _16_pixel = 0x04, - _32_pixel = 0x05, - _64_pixel = 0x06, - _128_pixel = 0x07, - _256_pixel = 0x08, - _512_pixel = 0x09, - _1024_pixel = 0x0A, -}; - -enum Swizzle : u8 { - default = 0x00, - source_red_channel = 0x01, - source_green_channel = 0x02, - source_blue_channel = 0x03, - source_alpha_channel = 0x04, - set_to_1 = 0x05, - set_to_0 = 0x06, - set_to_0_5 = 0x07, - Random = 0x08, - one_minus_source_red_channel = 0x09, - one_minus_source_green_channel = 0x0A, - one_minus_source_blue_channel = 0x0B, - one_minus_source_alpha_channel = 0x0C, - negative_source_red_channel = 0x0D, - negative_source_green_channel = 0x0E, - negative_source_blue_channel = 0x0F, - negative_source_alpha_channel = 0x10, -}; - -bitfield BitmapDicerFlag { - convert_plate_color_key_to_alpha_channel : 1; - rotate_cube_map_to_match_directX_format : 1; - sprites_shrink_elements_to_smallest_non_zero_alpha_region : 1; - sprites_shrink_elements_to_smallest_non_zero_color_and_alpha_region : 1; - unsigned_signed_scale_and_bias : 1; - color_grading_sRGB_correction : 1; - color_grading_Rec709_correction : 1; -}; - -bitfield BitmapDownsampleFlag { - sprites : 1; - pre_multiply_alpha : 1; - post_divide_alpha : 1; - height_map : 1; - detail_map : 1; - _signed : 1; - illum_map : 1; - zbump_map : 1; - cubemap : 1; - calculate_spec_power : 1; - downsample_bumps_in_angular_space : 1; - standard_orientation_of_normals_in_angular_space_and_renormalize : 1; - generate_rgb_luminance_into_alpha_channel : 1; -}; - -bitfield BitmapPackerFlag { - shrink_sprite_texture_pages_tightly_to_content : 1; -}; - -bitfield BitmapDataResourceFlags { - Contains_3D_Texture : 1; - CPU_Gameplay_Required : 1; - Single_Mip_Texture : 1; - UI_Texture : 1; -}; - - -bitfield BitmapGroupFlags { - bitmap_is_tiled : 1; - use_less_blurry_bump_map : 1; - dither_when_compressing : 1; - generate_random_sprites : 1; - ignore_alpha_channel : 1; - alpha_channel_stores_transparency : 1; - preserve_alpha_channel_in_mipmaps : 1; - only_use_on_demand : 1; - apply_max_resolution_after_slicing :1; - pre_filter_cubemaps : 1; - has_valid_min_and_max_values : 1; - SDF_Only_Store_Inside_values : 1; - SDF_Store_Direction : 1; - SDF_Store_Initial_Values_In_Alpha_Channel : 1; - Has_CUstom_Mipmaps : 1; - Validate_Has_Custom_Mipmaps : 1; - Is_Light_Probes : 1; - pad1 : 1; - pad2 : 1; - pad3 : 1; - pad4 : 1; - pad5 : 1; - pad6 : 1; - pad7 : 1; - pad8 : 1; -}; - -bitfield BitmapFlags { - power_of_two_dimension : 1; - compressed : 1; - swap_axes : 1; - mutable_at_runtime : 1; - pad1 : 1; - pad2 : 1; - pad3 : 1; - pad4 : 1; - pad5 : 1; - }; - -struct Data_Block { - u32 Size; - u16 Padding; - u16 Section; - u64 Offset; -}; - -struct Tag_Def_Structure { - s64 GUID_1; - s64 GUID_2; - u16 Type; - u16 Unk_0x12; - s32 TargetIndex; - s32 FieldBlock; - u32 FieldOffset; -}; - -struct Tag_Dependency { - char GroupTag[4] [[format("std::string::reverse")]]; - u32 NameOffset; - u64 AssetID; - u32 GlobalID; - u32 Unk_0x14; -}; - -struct Data_Reference { - s32 ParentStructIndex; - s32 Unk_0x04; - s32 TargetIndex; - s32 FieldBlock; - u32 FieldOffset; -}; - -struct TagReference { - s64 GlobalHandle; - s32 ref_id_int; - s32 ref_id_sub; - s32 ref_id_center_int; - char TagGroupRev[4] [[format("std::string::reverse")]]; - s32 local_handle; -}; - -struct Tag_Fixup_Reference { - s32 FieldBlock; - u32 FieldOffset; - u32 NameOffset; - s32 DependencyIndex; - TagReference tagreference @ header.HeaderSize + datablocks[FieldBlock].Offset + FieldOffset; -}; - - - -struct RealARgbColor { - float A; - float R; - float G; - float B; -}; - -struct RealRgbColor { - float R; - float G; - float B; -}; - -struct Bitmap_Resource_Handle { - s32 pixels[6]; // sum of these equals pixel count. - u32 hardware_format; - s8 tileMode; - s8 format; - BitmapDataResourceFlags bitmap_data_resource_flags; - s8 Alignment_Bits; - u8 highResMipCountAndFlags; - u8 mipCountPerArraySlice; - char generated_padff1b[6]; - s64 runtime_data; - char streamingData[20]; - s32 generated_padb266; -}; - -struct BitmapBlock { - u16 width; - u16 height; - u16 depth; - BitmapType Bitmap_Type; - u8 generated_paddca; - BitmapFormat bitmap_format; - BitmapFlags bitmap_flags; - s8 mipmap_count; - BitmapCurve bitmap_curve; - u16 generated_pad8fee; - float streaming_scale; - s16 source_width; - s16 source_height; - char bitmap_resource_handle_size[12]; - s32 bitmap_resource_handle_count; - Bitmap_Resource_Handle bitmap_resource_handle[bitmap_resource_handle_count]; -}; - -struct BitmapUsage { - s32 name; - s32 editor_group; - u32 source_gamma; - BitmapCurve bitmap_curve; - BitmapUsageFlag bitmap_usage_flag; - BitmapSlicer bitmap_slicer; - BitmapDicerFlag bitmap_dicer; - BitmapPacker bitmap_packer; - BitmapPackerFlag bitmap_packer_flags; - BitmapType bitmap_type; - s8 mipmap_limit; - BitmapSmallestMip bitmap_smallest_mip; - BitmapDownsampleFilter bitmap_downsample_filter; - s8 filter_radius_bias; - char generated_pad122e[1]; - BitmapDownsampleFlag bitmap_downsample_flag; - char generated_pad5ee3[2]; - RealRgbColor sprite_background_color; - Swizzle swizzle_red; - Swizzle swizzle_green; - Swizzle swizzle_blue; - Swizzle swizzle_alpha; - BitmapFormat bitmap_formats; - BitmapColorSpace source_color_space; - BitmapColorSpace target_color_space; -}; - -struct BitmapGroupSprite { - u32 bitmap_index; - char generated_pad2095[2]; - s32 left; - s32 right; - s32 top; - s32 bottom; - s64 real_point_2D; -}; - -struct BitmapGroupSequence { - char name[32]; - u32 first_bitmap_index; - u32 bitmap_count; - char sprites[16]; - s32 sprite_count; - BitmapGroupSprite Sprites[sprite_count]; -}; - - -struct Bitm { - u32 Usage; - s32 UsageID; - s32 Package; - s32 texture_group; - BitmapGroupFlags flags; - u16 sprite_spacing; - u16 mip_sample_count; - float bump_map_height; - float blur_factor; - u32 blur; - u32 mipmap_blur; - curve_mode curvemode; - s8 max_mipmap_level; - u16 max_resolution; - BitmapForcedFormat force_bitmap_format; - SignedDistanceFieldMethod sdfgeneration; - s8 target_platform; - u16 spread_factor; - u16 generated_pad8ed2; - char usage_override[16]; - s32 usage_override_count; - BitmapUsage bitmap_usage[usage_override_count]; - char manual_sequence[16]; - s32 manual_sequences_count; - BitmapGroupSequence manual_sequences[manual_sequences_count]; - char source_data[24]; - char source_path[20]; - u64 source_checksum; - RealARgbColor min_color; - RealARgbColor max_color; - char sequence[16]; - s32 sequences_count; - BitmapGroupSequence sequences[sequences_count]; - char bitmapstart[16]; - s32 bitmap_block_count; - BitmapBlock bitmap_block[bitmap_block_count]; - char RawDDSData[header.ActualResoureDataSize]; -}; - - -struct InternalStruct { - s64 vtablespace; - u32 global_tag_id; - char local_tag_handle[4]; -}; - - -// TAG LAYOUT -Header header @ 0x00; -Tag_Dependency Dependencies[header.DependencyCount] @ 0x50; -Data_Block datablocks[header.DataBlockCount] @ header.DependencyCount * 0x18 + 0x50; -Tag_Def_Structure tagdefstructure[header.TagStructCount] @ header.DependencyCount * 0x18 + 0x50 + header.DataBlockCount * 0x10; -Data_Reference Data_References[header.DataReferenceCount] @ header.DependencyCount * 0x18 + 0x50 + header.DataBlockCount * 0x10 + header.TagStructCount * 0x20; -Tag_Fixup_Reference tagfixupreference[header.TagReferenceCount] @ header.DependencyCount * 0x18 + 0x50 + header.DataBlockCount * 0x10 + header.TagStructCount * 0x20 + header.DataReferenceCount * 0x14; -char ZoneSet[header.ZoneSetDataSize] @ header.HeaderSize - header.ZoneSetDataSize; // zonesets kinda make no sense -InternalStruct internalstruct @ header.HeaderSize; -Bitm bitmap @ header.HeaderSize + 16; \ No newline at end of file diff --git a/patterns/hinf_module.hexpat b/patterns/hinf_module.hexpat new file mode 100644 index 0000000..ac18b11 --- /dev/null +++ b/patterns/hinf_module.hexpat @@ -0,0 +1,77 @@ +#pragma author Surasia +#pragma description Halo Infinite Module +#pragma array_limit 4294967295 +#pragma pattern_limit 4294967295 + +import std.string; + +struct ModuleHeader +{ + char magic[4]; + s32 version; + s64 moduleId; + u32 fileCount; + s32 manifest0Count; + s32 manifest1Count; + s32 manifest2Count; + s32 resourceIndex; + u32 stringSize; + u32 resourceCount; + u32 blockCount; + u64 buildVersion; + s64 hd1Delta; + u64 dataSize; +}; + + +struct ModuleFile +{ + u32 resourceCount; + s32 parentIndex; + s16 pad; + u16 blockCount; + s32 blockIndex; + s32 resourceIndex; + char class[4] [[format("std::string::reverse")]]; + u64 dataOffsetBytes; + u64 dataOffset = dataOffsetBytes & 0x0000FFFFFFFFFFFF [[export]]; + u16 dataOffsetFlags = dataOffsetBytes >> 48 [[export]]; + u32 totalCompressedSize; + u32 totalUncompressedSize; + u32 globalTagId; + u32 uncompressedHeaderSize; + u32 uncompressedTagDataSize; + u32 uncompressedResourceDataSize; + u32 uncompressedActualResourceDataSize; + u32 resourceBlockCount; + u32 nameOffset; + s32 parentResource; + u64 assetChecksum; + u64 assetId; +}; + + +struct ModuleBlock +{ + u32 compressedOffset; + u32 compressedSize; + u32 decompressedOffset; + u32 decompressedSize; + bool compressed; + s24 pad; +}; + + +struct Module +{ + ModuleHeader module_header; + ModuleFile files[module_header.fileCount]; + $ = $ + 8; + s32 resources[module_header.resourceCount]; + ModuleBlock blocks[module_header.blockCount]; + padding[while($[$] == 0)]; + std::print("Compressed Tag Data starts at: {}", $); +}; + + +Module module_root @ 0x00; \ No newline at end of file diff --git a/patterns/hinf_tag.hexpat b/patterns/hinf_tag.hexpat new file mode 100644 index 0000000..475f49f --- /dev/null +++ b/patterns/hinf_tag.hexpat @@ -0,0 +1,168 @@ +#pragma author Surasia +#pragma description Halo Infinite Tag File + +import std.string; +import type.guid; + +u32 fileStart = 0; + +enum TagSectionType : u16 +{ + header, + tagData, + resourceData +}; + + +enum TagStructType : u16 +{ + mainStruct, + tagBlock, + resource, + custom, + literal +}; + + +struct TagHeader +{ + char magic[4]; + s32 version; + u64 hash; + u64 checksum; + u32 dependencyCount; + u32 dataBlockCount; + u32 tagStructCount; + u32 dataReferenceCount; + u32 tagReferenceCount; + u32 stringTableSize; + u32 zoneSetDataSize; + u32 unknown0; + u32 headerSize; + fileStart = headerSize; + u32 dataSize; + u32 resourceDataSize; + u32 actualResourceDataSize; + u8 headerAlignment; + u8 tagDataAlignment; + u8 resourceDataAlignment; + u8 actualResourceAlignment; + u32 unknown1; +}; + + +struct TagDependency +{ + char tagGroup[4] [[format("std::string::reverse")]]; + u32 nameOffset; + u64 assetId; + u32 globalId; + u32 parentTag; +}; + + +struct TagDataBlock +{ + u32 entrySize; + u16 pad; + TagSectionType section; + u64 offset; + if (section == TagSectionType::tagData) + { + char dataBlock[entrySize] @ fileStart + offset; + } +}; + + +struct TagStruct +{ + type::GUID guid; + TagStructType type; + u16 unknown0; + s32 targetIndex; + s32 fieldBlockIndex; + u32 fieldOffset; +}; + + +struct TagDataReference +{ + s32 parentStructIndex; + s32 unknown0; + s32 targetIndex; + s32 fieldBlockIndex; + u32 fieldOffset; +}; + + +struct TagReference +{ + s32 fieldBlockIndex; + u32 fieldOffset; + u32 nameOffset; + s32 dependencyIndex; +}; + + +struct TagZonesetHeader +{ + s32 version; + u32 zonesetCount; + u32 footerCount; + s32 parentCount; +}; + + +struct TagZonesetInstanceHeader +{ + s32 stringId; + u32 tagCount; + u32 parentCount; + u32 footerCount; +}; + + +struct TagZonesetTag +{ + u32 globalId; + s32 stringId; + +}; + + +struct TagZonesetInstance +{ + TagZonesetInstanceHeader header; + TagZonesetTag tags[header.tagCount]; + TagZonesetTag footers[header.footerCount]; + s32 parents[header.parentCount]; + +}; + + +struct TagZoneset +{ + TagZonesetHeader zoneset_header; + TagZonesetInstance instances[zoneset_header.zonesetCount]; +}; + + +struct Tag +{ + TagHeader header; + TagDependency dependencies[header.dependencyCount]; + TagDataBlock data_blocks[header.dataBlockCount]; + TagStruct tag_structs[header.tagStructCount]; + TagDataReference data_references[header.dataReferenceCount]; + TagReference tag_references[header.tagReferenceCount]; + TagZoneset zonesets; + if (header.headerSize != $) + { + std::print("Header size is wrong, additional data in tag"); + $ = header.headerSize; + std::print("Data offset now at: {}", $); + } +}; + + +Tag tag_root @ 0x00; \ No newline at end of file diff --git a/tests/patterns/test_data/hinf_bitmap.hexpat.bitm b/tests/patterns/test_data/hinf_bitmap.hexpat.bitm deleted file mode 100644 index 64d989f09e655a9b528dd5b0216673fc51058913..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132052 zcmeIwOGs2v7y#hg7^W4}Mks3`jEi1WLJ(Mraj8L#{Ir!qgcTAs)t#OtEdgkSP_ydQ<7X zm`{?n(*4@gdB_GEin4@~vtdxx^?FTPI;iy`9r_R~+bA9LSMJ^wj5dVFGL zRXirG<-&T`nM~cA{kI;Bv>$ufFnG12yxtk=yYt&;zqWR*xi(ur(APM-E9W`LXo*v1ex(X{5jDLP%7Xl2Ivr7wMU?6wi2fqGKdo$7^|f{=4D2*cGOlVn@u!sMMeCD|VO( z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAn<<+ F`~tif?Gpe1 diff --git a/tests/patterns/test_data/hinf_module.hexpat.module b/tests/patterns/test_data/hinf_module.hexpat.module new file mode 100644 index 0000000000000000000000000000000000000000..fac17c3b16ad4dec81084a0d114fd444a68b379a GIT binary patch literal 39535 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 literal 0 HcmV?d00001