Compare commits

..

16 Commits

Author SHA1 Message Date
WerWolv
4299243e95 includes/std: Added hex::dec::lz4_decompress() 2024-07-07 15:51:40 +02:00
Surasia
23b3c2b5d0 git: Fix hinf_tag and hinf_module links in readme (#268) 2024-07-07 13:44:04 +02:00
Surasia
da1c2687e8 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
2024-07-06 17:33:03 +02:00
WerWolv
18f968df5b includes/std: Drastically improved std::mem::MagicSearch, added find_string and find_string_in_range 2024-07-04 20:47:39 +02:00
WerWolv
f797c711ca includes/std: Optimize std::bit::popcount 2024-07-04 17:58:12 +02:00
WerWolv
5380877da4 tests: Added error message when no description is used 2024-07-04 08:28:20 +02:00
Marc Butler
bb46276bde patterns: Added Password Safe Version 3 pattern (#266)
* Add password safe V3

* Added description pragma

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-07-04 08:27:51 +02:00
Nik
4242869ac1 patterns/zlib: Cast bitfield enums to integers before doing math with them 2024-07-03 22:48:15 +02:00
WerWolv
8bdcd814a9 includes/std: Added std::unimplemented() 2024-07-02 18:00:52 +02:00
WerWolv
d7811ff5e9 patterns: Replaced old bitfield order attributes with new ones
Fixes #265
2024-07-02 18:00:41 +02:00
WerWolv
4d0b3e21bc includes/std: Added better documentation to std::mem::current_bit_offset() 2024-07-02 18:00:05 +02:00
WerWolv
acd6903b21 includes/std: Added crc8, crc16 and crc64 functions
Fixes #226
2024-07-02 17:59:40 +02:00
WerWolv
8d2a39f7d4 git: Added build folders to gitignore 2024-07-02 17:58:47 +02:00
Nik
65ef3a7783 includes/std: Removed cyclic dependency between std.mem and std.string 2024-07-01 23:47:09 +02:00
Nik
21a0b99eac includes/std: Added missing string include to std::mem 2024-06-29 23:25:58 +02:00
Rebuild
a33b68921d patterns: Added ttf/otf format (#263)
* Add ttf/otf format

* ttf: Put cff to preprocessing
2024-06-29 22:52:21 +02:00
24 changed files with 1143 additions and 580 deletions

3
.gitignore vendored
View File

@@ -1,5 +1,6 @@
tests/cmake-build-debug/
tests/cmake*/
tests/build*/
.idea/
.DS_Store

View File

@@ -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_tag.hexpat) | Halo Infinite Tag Files |
| Halo Module || [`patterns/hinf_module.hexpat`](patterns/hinf_module.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 |
@@ -96,6 +97,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files |
| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO |
| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding |
| psafe3 | | [`patterns/psafe3.hexpat`](patterns/psafe3.hexpat`) | Password Safe V3 |
| PyInstaller | | [`patterns/pyinstaller.hexpat`](patterns/pyinstaller.hexpat) | PyInstaller binray files |
| PYC | | [`patterns/pyc.hexpat`](patterns/pyc.hexpat) | Python bytecode files |
| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file |
@@ -112,6 +114,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format |
| TIFF | `image/tiff` | [`patterns/tiff.hexpat`](patterns/tiff.hexpat) | Tag Image File Format |
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
| TTF | `font/ttf`, `font/otf` | [`patterns/ttf.hexpat`](patterns/ttf.hexpat) | TrueType and OpenType font format |
| Ubiquiti | | [`patterns/ubiquiti.hexpat`](patterns/ubiquiti.hexpat) | Ubiquiti Firmware (update) image |
| UEFI | | [`patterns/uefi.hexpat`](patterns/uefi.hexpat)` | UEFI structs for parsing efivars |
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |

View File

@@ -60,5 +60,16 @@ namespace auto hex::dec {
fn zstd_decompress(ref auto pattern, std::mem::Section section) {
return builtin::hex::dec::zstd_decompress(pattern, section);
};
/**
Decompresses the bytes of a pattern into a section using the lz4 algorithm
@param pattern The pattern whose bytes should be decompressed
@param section The section to decompress the data into
@param frame Whether the data is framed or not
@return true if successful, false otherwise
*/
fn lz4_decompress(ref auto pattern, std::mem::Section section, bool frame = true) {
return builtin::hex::dec::lz4_decompress(pattern, section, frame);
};
}

View File

@@ -14,9 +14,13 @@ namespace auto std::bit {
@return The number of bits set to 1 in `x`
*/
fn popcount(u128 x) {
x = (x & (std::limits::u128_max() / 3)) + ((x >> 1) & (std::limits::u128_max() / 3));
x = (x & (std::limits::u128_max() / 5)) + ((x >> 2) & (std::limits::u128_max() / 5));
x = (x & (std::limits::u128_max() / 17)) + ((x >> 4) & (std::limits::u128_max() / 17));
const u128 a = 0x55555555555555555555555555555555;
const u128 b = 0x33333333333333333333333333333333;
const u128 c = 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F;
x = (x & a) + ((x >> 1) & a);
x = (x & b) + ((x >> 2) & b);
x = (x & c) + ((x >> 4) & c);
return x % 0xFF;
};

View File

@@ -6,9 +6,37 @@
namespace auto std::hash {
/**
Calculates the CRC8 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the CRC8 hash of
@param init The CRC8 init value
@param poly The CRC8 polynomial
@param xorout The CRC8 XOR-Out value
@param reflect_in Whether or not the input bytes should be reflected
@param reflect_out Whether or not the output should be reflected
@return Calculated CRC8 hash
*/
fn crc8(ref auto pattern, u8 init, u8 poly, u8 xorout, bool reflect_in, bool reflect_out) {
return builtin::std::hash::crc8(pattern, init, poly, xorout, reflect_in, reflect_out);
};
/**
Calculates the CRC16 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the CRC16 hash of
@param init The CRC16 init value
@param poly The CRC16 polynomial
@param xorout The CRC16 XOR-Out value
@param reflect_in Whether or not the input bytes should be reflected
@param reflect_out Whether or not the output should be reflected
@return Calculated CRC16 hash
*/
fn crc16(ref auto pattern, u16 init, u16 poly, u16 xorout, bool reflect_in, bool reflect_out) {
return builtin::std::hash::crc16(pattern, init, poly, xorout, reflect_in, reflect_out);
};
/**
Calculates the CRC32 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the crc32 hash of
@param pattern The pattern to calculate the CRC32 hash of
@param init The CRC32 init value
@param poly The CRC32 polynomial
@param xorout The CRC32 XOR-Out value
@@ -20,4 +48,18 @@ namespace auto std::hash {
return builtin::std::hash::crc32(pattern, init, poly, xorout, reflect_in, reflect_out);
};
/**
Calculates the CRC64 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the CRC64 hash of
@param init The CRC64 init value
@param poly The CRC64 polynomial
@param xorout The CRC64 XOR-Out value
@param reflect_in Whether or not the input bytes should be reflected
@param reflect_out Whether or not the output should be reflected
@return Calculated CRC64 hash
*/
fn crc64(ref auto pattern, u64 init, u64 poly, u64 xorout, bool reflect_in, bool reflect_out) {
return builtin::std::hash::crc64(pattern, init, poly, xorout, reflect_in, reflect_out);
};
}

View File

@@ -317,8 +317,8 @@ namespace auto std::math {
*/
enum AccumulateOperation : u8 {
Add = 0,
Multiply = 1,
Modulo = 2,
Multiply = 1,
Modulo = 2,
Min = 3,
Max = 4
};

View File

@@ -9,18 +9,15 @@ namespace auto std::mem {
namespace impl {
struct MagicSearchImpl<auto Magic, T> {
if ($ < (std::mem::base_address() + std::mem::size() - std::string::length(Magic) - 1)) {
char __potentialMagic__[std::string::length(Magic)] [[hidden, no_unique_address]];
if (__potentialMagic__ == Magic) {
T data [[inline]];
} else {
padding[1];
continue;
}
} else {
padding[1];
continue;
s128 address = builtin::std::mem::find_string_in_range(0, $, builtin::std::mem::size(), Magic);
if (address < 0)
break;
$ = address;
try {
T data [[inline]];
} catch {
T data;
}
};
@@ -63,7 +60,7 @@ namespace auto std::mem {
/**
Gets the base address of the memory
Gets the base address of the data
@return The base address of the memory
*/
fn base_address() {
@@ -71,7 +68,7 @@ namespace auto std::mem {
};
/**
Gets the size of the memory
Gets the size of the data
@return The size of the memory
*/
fn size() {
@@ -79,17 +76,18 @@ namespace auto std::mem {
};
/**
Finds a sequence of bytes in the memory
Finds a sequence of bytes in the data
@param occurrence_index The index of the occurrence to find
@param bytes The bytes to find
@return The address of the sequence
*/
fn find_sequence(u128 occurrence_index, auto ... bytes) {
return builtin::std::mem::find_sequence_in_range(occurrence_index, builtin::std::mem::base_address(), builtin::std::mem::size(), bytes);
const u128 address = builtin::std::mem::base_address();
return builtin::std::mem::find_sequence_in_range(occurrence_index, address, address + builtin::std::mem::size(), bytes);
};
/**
Finds a sequence of bytes in a specific region of the memory
Finds a sequence of bytes in a specific region of the data
@param occurrence_index The index of the occurrence to find
@param offsetFrom The offset from which to start searching
@param offsetTo The offset to which to search
@@ -100,6 +98,30 @@ namespace auto std::mem {
return builtin::std::mem::find_sequence_in_range(occurrence_index, offsetFrom, offsetTo, bytes);
};
/**
Finds a string in the data
@param occurrence_index The index of the occurrence to find
@param string The string to find
@return The address of the sequence
*/
fn find_string(u128 occurrence_index, str string) {
const u128 address = builtin::std::mem::base_address();
return builtin::std::mem::find_string_in_range(occurrence_index, address, address + builtin::std::mem::size(), string);
};
/**
Finds a string in a specific region of the data
@param occurrence_index The index of the occurrence to find
@param offsetFrom The offset from which to start searching
@param offsetTo The offset to which to search
@param string The string to find
@return The address of the sequence
*/
fn find_string_in_range(u128 occurrence_index, u128 offsetFrom, u128 offsetTo, str string) {
return builtin::std::mem::find_string_in_range(occurrence_index, offsetFrom, offsetTo, string);
};
/**
Reads a unsigned value from the memory
@param address The address to read from
@@ -132,14 +154,6 @@ namespace auto std::mem {
return builtin::std::mem::read_string(address, size);
};
/**
Gets the current bit offset within the current byte that a bitfield will read.
*/
fn current_bit_offset() {
return builtin::std::mem::current_bit_offset();
};
/**
Reads a number of bits from the specified bit offset within the specified byte
@param byteOffset The byte offset within the data
@@ -211,6 +225,14 @@ namespace auto std::mem {
builtin::std::mem::copy_value_to_section(value, to_section, to_address);
};
/**
Returns the current bit offset when inside of a bitfield.
@return The current bit offset between 0 and 7
*/
fn current_bit_offset() {
return builtin::std::mem::current_bit_offset();
};
/**
Searches for a sequence of bytes and places the given type at that address

View File

@@ -49,4 +49,11 @@ namespace auto std {
return builtin::std::sizeof_pack(pack);
};
/**
Throws an error notifying the developer that the current codepath is not implemented currently.
*/
fn unimplemented() {
std::error("Unimplemented code path reached!");
};
}

View File

@@ -1,6 +1,7 @@
#pragma once
import std.io;
import std.core;
/*!
Types to display single bytes using various different representations
@@ -20,7 +21,7 @@ namespace auto type {
bit5 : 1;
bit6 : 1;
bit7 : 1;
} [[format("type::impl::format_bits"), right_to_left]];
} [[format("type::impl::format_bits"), bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 8)]];
/**
Type visualizing the value of the two nibbles

View File

@@ -498,12 +498,12 @@ bitfield SHF {
bitfield ELF32_R_INFO {
SYM : 8;
TYPE : 8;
} [[left_to_right]];
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 16)]];
bitfield ELF64_R_INFO {
SYM : 32;
TYPE : 32;
} [[left_to_right]];
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 64)]];
bitfield PF {
X : 1;

View File

@@ -52,7 +52,7 @@ namespace fat32 {
lastLogical : 1;
padding : 1;
number : 5;
} [[left_to_right]];
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
enum EntryStatus : u8 {
Regular = 0x00,
@@ -73,7 +73,7 @@ namespace fat32 {
subdirectory : 1;
archive : 1;
padding : 2;
} [[right_to_left]];
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 8)]];
struct DirEntry {
char fileName[8];

View File

@@ -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;

View File

@@ -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;

168
patterns/hinf_tag.hexpat Normal file
View File

@@ -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;

33
patterns/psafe3.hexpat Normal file
View File

@@ -0,0 +1,33 @@
// Password Safe V3
// Only a small part of the file is unencrypted.
#pragma endian little
#pragma description Password Safe V3
import std.mem;
import std.sys;
struct Prologue {
u8 SALT[32];
u32 ITER;
u8 HPP[32] [[name("H(P')")]];
u8 B1[16];
u8 B2[16];
u8 B3[16];
u8 B4[16];
u8 IV[16];
};
struct EOF {
u8 HMAC[32];
};
char magic[4] @ 0x00;
std::assert(magic == "PWS3", "Invalid file: bad tag!");
char marker[16] @ std::mem::size() - 48;
std::assert(marker == "PWS3-EOFPWS3-EOF", "Invalid file: bad end marker!");
Prologue prologue @ 0x04;
u8 HMAC[32] @ std::mem::size() - 32;
EOF eof @ std::mem::size() - 48;

726
patterns/ttf.hexpat Normal file
View File

@@ -0,0 +1,726 @@
#pragma author Shimogawa (aka Rebuild)
#pragma description TrueType and OpenType font format
#pragma endian big
#pragma MIME font/ttf
#pragma MIME font/otf
#pragma pattern_limit 1000000
import std.mem;
import std.string;
import std.time;
import std.io;
struct TableDirectory {
char tag[4];
u32 checkSum;
u32 offset;
u32 length;
};
fn format_fixed32(auto fp32) {
return fp32.integer + fp32.fraction / 65536.0;
};
fn format_f2dot14(auto f) {
return f.integer + f.fraction / 16384.0;
};
using FWord = s16;
using UFWord = u16;
struct FixedPoint32 {
u16 integer;
u16 fraction;
} [[format("format_fixed32")]];
bitfield F2Dot14 {
integer : 2;
fraction : 14;
} [[format("format_f2dot14")]];
fn format_longdatetime(auto t) {
return std::time::format(std::time::to_utc(u32(t.time - 2082844800)));
};
struct LongDatetime {
s64 time;
} [[format("format_longdatetime")]];
using HeadTable;
u64 currentOffset;
u64 currentLength;
u64 glyfStart;
bool hasPostScriptOutlines = false;
u16 numHMetrics;
u16 gNumGlyphs;
HeadTable headTable;
// begin avar
struct AxisValueMap {
F2Dot14 fromCoord;
F2Dot14 toCoord;
};
struct ShortFracSegment {
u16 positionMapCount;
AxisValueMap axisValueMaps[positionMapCount];
};
struct AvarTable {
FixedPoint32 version;
s32 axisCount;
ShortFracSegment segments[axisCount];
};
// end avar
// begin cmap
u64 startOfCmapTable = 0;
struct BaseCmapSubtable {
u64 start = $;
u16 format;
};
struct CmapSubtable0 : BaseCmapSubtable {
u16 length;
u16 language;
u8 glyphIndexArr[256];
};
struct CmapSubtable2 : BaseCmapSubtable {
u16 length;
u16 language;
u16 subHeaderKeys[256];
u8 data[length - 516];
};
struct CmapSubtable4 : BaseCmapSubtable {
u16 length;
u64 end = start + length;
u16 language;
u16 segCountX2;
u16 segCount = segCountX2 / 2;
u16 searchRange;
u16 entrySelector;
u16 rangeShift;
u16 endCode[segCount];
u16 reserved;
u16 startCode[segCount];
s16 idDelta[segCount];
u16 idRangeOffset[segCount];
u16 glyphIdArr[(end - $) / sizeof(u16)];
};
struct CmapSubtable6 : BaseCmapSubtable {
u16 length;
u16 language;
u16 firstCode;
u16 entryCount;
u16 glyphIdArr[entryCount];
};
struct SequentialMapGroup {
u32 startCharCode;
u32 endCharCode;
u32 startGlyphId;
};
struct CmapSubtable8 : BaseCmapSubtable {
u16 reserved;
u32 length;
u32 language;
u8 is32[8192];
u32 numGroups;
SequentialMapGroup groups[numGroups];
};
struct CmapSubtable10 : BaseCmapSubtable {
u16 reserved;
u32 length;
u64 end = start + length;
u32 language;
u32 startCharCode;
u32 numChars;
u16 glyphIdArr[(end - $) / sizeof(u16)];
};
struct CmapSubtable12 : BaseCmapSubtable {
u16 reserved;
u32 length;
u32 language;
u32 numGroups;
SequentialMapGroup groups[numGroups];
};
struct CmapSubtable {
u16 format = std::mem::read_unsigned($, 2, std::mem::Endian::Big);
match (format) {
(0): CmapSubtable0 table [[inline]];
(2): CmapSubtable2 table [[inline]];
(4): CmapSubtable4 table [[inline]];
(6): CmapSubtable6 table [[inline]];
(8): CmapSubtable8 table [[inline]];
(10): CmapSubtable10 table [[inline]];
(12): CmapSubtable12 table [[inline]];
(_): BaseCmapSubtable table [[inline]];
}
} [[name(std::format("Subtable Format {}", format))]];
enum CmapPlatform : u16 {
Unicode = 0,
Macintosh = 1,
ISO = 2,
Microsoft = 3,
Custom = 4,
};
struct EncodingRecord {
CmapPlatform platformId;
u16 encodingId;
u32 offset;
u64 endEncodingRecord = $;
$ = startOfCmapTable + offset;
CmapSubtable subtable;
$ = endEncodingRecord;
};
struct CmapTable {
startOfCmapTable = $;
u16 version;
u16 numSubtables;
EncodingRecord encodingRecords[numSubtables];
};
// end cmap
// begin cvt
struct CvtTable {
u64 size = currentLength / sizeof(FWord);
FWord controlValues[size];
};
// end cvt
// begin gasp
bitfield RangeGaspBehavior {
padding : 12;
symmetricSmoothing : 1;
symmetricGridfit : 1;
doGray : 1;
gridFit : 1;
};
struct GaspRange {
u16 rangeMaxPPEM;
RangeGaspBehavior rangeGaspBehavior;
};
struct GaspTable {
u16 version;
u16 numRanges;
GaspRange gaspRanges[numRanges];
};
// end gasp
// begin glyf
struct GlyphTableHeader {
u64 startOffset = $;
s16 numContours;
FWord xMin;
FWord yMin;
FWord xMax;
FWord yMax;
};
bitfield OutlineFlag {
padding : 2;
ySameOrPositive : 1;
xSameOrPositive : 1;
repeat : 1;
yShort : 1;
xShort : 1;
onCurve : 1;
};
u32 pIdx = 0;
u32 curGlyfSize;
struct SimpleGlyphFlag {
pIdx += 1;
OutlineFlag flag;
if (flag.repeat) {
pIdx += 1;
u8 repeatTimes;
}
};
struct SimpleGlyphTable : GlyphTableHeader {
u16 endPtsOfContours[numContours];
u32 numPoints = numContours == 0 ? 0 : endPtsOfContours[numContours - 1];
u16 instructionLength;
u8 instructions[instructionLength];
pIdx = 0;
SimpleGlyphFlag flags[while(pIdx < numPoints)] [[single_color]];
u8 data[startOffset + curGlyfSize - $];
};
bitfield CompositeGlyphFlag {
padding : 3;
unscaledComponentOffset : 1;
scaledComponentOffset : 1;
overlapCompound : 1;
useMyMetrics : 1;
weHaveInstructions : 1;
weHaveA2x2 : 1;
weHaveAnXAndYScale : 1;
moreComponents : 1;
padding : 1;
weHaveAScale : 1;
roundXYToGrid : 1;
argsAreXYValues : 1;
arg1And2AreWords : 1;
};
bool componentGlyphHasMoreComponents;
bool componentGlyphHasInstruction;
struct ComponentGlyphRecord {
CompositeGlyphFlag flags;
u16 glyphIndex;
if (flags.arg1And2AreWords) {
FWord arg1;
FWord arg2;
} else {
u8 arg1;
u8 arg2;
}
if (flags.weHaveAScale) {
F2Dot14 scale;
} else if (flags.weHaveAnXAndYScale) {
F2Dot14 xScale;
F2Dot14 yScale;
} else if (flags.weHaveA2x2) {
F2Dot14 xScale;
F2Dot14 scale01;
F2Dot14 scale10;
F2Dot14 yScale;
}
componentGlyphHasMoreComponents = flags.moreComponents;
componentGlyphHasInstruction = flags.weHaveInstructions;
};
struct CompositeGlyphTable : GlyphTableHeader {
componentGlyphHasMoreComponents = true;
componentGlyphHasInstruction = false;
ComponentGlyphRecord records[while (componentGlyphHasMoreComponents)];
if (componentGlyphHasInstruction) {
u16 instructionLength;
u8 instructions[instructionLength];
}
};
struct GlyfTable {
s16 type = std::mem::read_signed($, 2, std::mem::Endian::Big);
if (type >= 0) {
SimpleGlyphTable table [[inline]];
} else {
CompositeGlyphTable table [[inline]];
}
} [[name(std::format("glyf ({})", table.numContours < 0 ? "Composite" : "Simple"))]];
// end glyf
// begin hdmx
struct DeviceRecord {
u8 pixelSize;
u8 maxWidth;
u8 widths[gNumGlyphs];
};
struct HdmxTable {
u16 version;
u16 numRecords;
u32 sizeDeviceRecord;
DeviceRecord records[numRecords];
};
// end hdmx
// begin head
bitfield HeadFlag {
padding : 1;
lastResort : 1;
clearTypeOptimized : 1;
converted : 1;
lossless : 1;
indicStyleRearr : 1;
RTLGlyph : 1;
AATFont : 1;
linguisticRender : 1;
padding : 1;
verticalLayout : 1;
instrMayAlterAW : 1;
integerScaling : 1;
differentPointSize : 1;
xLBlackBitIsLSB : 1;
yZeroIsBaseline : 1;
};
bitfield MacStyle {
padding : 9;
extended : 1;
condensed : 1;
shadow : 1;
outline : 1;
underline : 1;
italic : 1;
bold : 1;
};
struct HeadTable {
FixedPoint32 version;
FixedPoint32 fontRevision;
u32 checksumAdjustment;
u32 magic;
HeadFlag flags;
u16 unitsPerEm;
LongDatetime created;
LongDatetime modified;
FWord xMin;
FWord yMin;
FWord xMax;
FWord yMax;
MacStyle macStyle;
u16 lowestRecPPEM;
s16 fontDirectionHint;
s16 indexToLocFormat;
s16 glyphDataFormat;
};
// end head
// begin hhea
struct HheaTable {
FixedPoint32 version;
FWord ascent;
FWord descent;
FWord lineGap;
UFWord advanceWidthMax;
FWord minLeftSideBearing;
FWord minRightSideBearing;
FWord xMaxExtent;
s16 caretSlopeRise;
s16 caretSlopeRun;
s16 caretOffset;
s16 reserved[4];
s16 metricDataFormat;
u16 numberOfHMetrics;
numHMetrics = numberOfHMetrics;
};
// end hhea
// begin hmtx
struct LongHorMetric {
UFWord advanceWidth;
FWord lsb;
};
struct HmtxTable {
LongHorMetric hMetrics[numHMetrics];
FWord leftSideBearings[gNumGlyphs - numHMetrics];
};
// end hmtx
// begin loca
// loca contains offsets for glyf tables, so
// we put glyf arrays here also.
struct GlyfWithOffset<auto longOffset> {
if (longOffset) {
u32 offset;
u32 realOffset = offset;
u32 nextOff = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
} else {
u16 offset;
u32 realOffset = u32(offset) * 2;
u32 nextOff = u32(std::mem::read_unsigned($, 2, std::mem::Endian::Big)) * 2;
}
curGlyfSize = nextOff - realOffset;
u64 prev = $;
$ = glyfStart + realOffset;
if (curGlyfSize != 0) {
GlyfTable glyf;
}
$ = prev;
};
struct LocaTable {
if (headTable.indexToLocFormat == 1) {
//u32 offsets[gNumGlyphs + 1];
GlyfWithOffset<true> glyfs[gNumGlyphs];
} else {
// u16 offsets[gNumGlyphs + 1];
GlyfWithOffset<false> glyfs[gNumGlyphs];
}
};
// end loca
// begin maxp
struct MaxpTable {
FixedPoint32 version;
u16 numGlyphs;
gNumGlyphs = numGlyphs;
if (!hasPostScriptOutlines) {
u16 maxPoints;
u16 maxContours;
u16 maxComponentPoints;
u16 maxComponentContours;
u16 maxZones;
u16 maxTwilightPoints;
u16 maxStorage;
u16 maxFunctionDefs;
u16 maxInstructionDefs;
u16 maxStackElements;
u16 maxSizeOfElements;
u16 maxComponentDepth;
}
};
// end maxp
// begin name
u64 curStorageOffset;
struct NameRecord {
u16 platformId;
u16 encodingId;
u16 languageId;
u16 nameId;
u16 length;
u16 stringOffset;
u64 cur = $;
$ = curStorageOffset + stringOffset;
char16 string[length / 2];
$ = cur;
};
struct LangTagRecord {
u16 length;
u16 langTagOffset;
u64 cur = $;
$ = curStorageOffset + langTagOffset;
char16 langTag[length / 2];
$ = cur;
};
struct NameTableV0 {
u64 startOfNameTable = $;
u16 version;
u16 count;
u16 storageOffset;
curStorageOffset = startOfNameTable + storageOffset;
NameRecord nameRecords[count];
};
struct NameTableV1 : NameTableV0 {
u16 langTagCount;
LangTagRecord langTagRecords[langTagCount];
};
struct NameTable {
u16 version = std::mem::read_unsigned($, 2, std::mem::Endian::Big);
match (version) {
(0): NameTableV0 table [[inline]];
(_): NameTableV1 table [[inline]];
}
};
// end name
// begin OS/2
struct OS2TableV0 {
u16 version;
FWord xAvgCharWidth;
u16 usWeightClass;
u16 usWidthClass;
u16 fsType;
FWord ySubscriptXSize;
FWord ySubscriptYSize;
FWord SubscriptXOffset;
FWord SubscriptYOffset;
FWord ySuperscriptXSize;
FWord ySuperscriptYSize;
FWord SuperscriptXOffset;
FWord SuperscriptYOffset;
FWord yStrikeoutSize;
FWord yStrikeoutPosition;
s16 sFamilyClass;
u8 panose[10];
u32 ulUnicodeRange[4];
u8 achVendID[4];
u16 fsSelection;
u16 usFirstCharIndex;
u16 usLastCharIndex;
FWord sTypoAscender;
FWord sTypoDescender;
FWord sTypoLineGap;
UFWord usWinAscent;
UFWord usWinDescent;
};
struct OS2TableV1 : OS2TableV0 {
u32 ulCodePageRange[2];
};
struct OS2TableV4 : OS2TableV1 {
FWord sxHeight;
FWord sCapHeight;
u16 usDefaultChar;
u16 usBreakChar;
u16 usMaxContent;
};
struct OS2TableV5 : OS2TableV4 {
u16 usLowerOpticalPointSize;
u16 usUpperOpticalPointSize;
};
struct OS2Table {
u16 version = std::mem::read_unsigned($, 2, std::mem::Endian::Big);
match (version) {
(0): OS2TableV0 table [[inline]];
(1): OS2TableV1 table [[inline]];
(2 | 3 | 4): OS2TableV4 table [[inline]];
(_): OS2TableV5 table [[inline]];
}
};
// end OS/2
// begin post
struct PostTableV1 {
u64 startOfTable = $;
FixedPoint32 version;
FixedPoint32 italicAngle;
FWord underlinePosition;
FWord underlineThickness;
u32 isFixedPitch;
u32 minMemType42;
u32 maxMemType42;
u32 minMemType1;
u32 maxMemType1;
};
struct PostTableV2 : PostTableV1 {
u16 numGlyphs;
u16 glyphNameIndex[numGlyphs];
std::string::SizedString<u8> stringData[while ($ < startOfTable + currentLength)];
};
struct PostTable {
u16 major = std::mem::read_unsigned($, 2, std::mem::Endian::Big);
u16 minor = std::mem::read_unsigned($ + 2, 2, std::mem::Endian::Big);
match (major, minor) {
(2, 0): PostTableV2 table [[inline]];
(_, _): PostTableV1 table [[inline]];
}
};
// end post
struct HiddenForPreprocessing {
u64 defStart = $;
TableDirectory td;
$ = td.offset;
currentOffset = td.offset;
currentLength = td.length;
match (td.tag) {
("CFF "): {
hasPostScriptOutlines = true;
}
("maxp"): MaxpTable table;
("head"): {
HeadTable table;
headTable = table;
}
("glyf"): {
glyfStart = $;
}
}
$ = defStart + sizeof(TableDirectory);
} [[hidden]];
struct Table {
u64 defStart = $;
TableDirectory td [[inline]];
$ = td.offset;
currentOffset = td.offset;
currentLength = td.length;
match (td.tag) {
("avar"): AvarTable table;
("bhed"): HeadTable table;
("cmap"): CmapTable table;
("cvt "): CvtTable table;
("gasp"): GaspTable table;
// ("glyf"): GlyfTable table;
// glyf will be contained in loca.
("glyf"): {}
("hdmx"): HdmxTable table;
("head"): HeadTable table;
("hhea"): HheaTable table;
("hmtx"): HmtxTable table;
("loca"): LocaTable table;
("maxp"): MaxpTable table;
("name"): NameTable table;
("OS/2"): OS2Table table;
("post"): PostTable table;
(_): u8 data[td.length];
}
$ = defStart + sizeof(TableDirectory);
} [[name(std::format("Table({})", td.tag))]];
struct TTF {
u32 scalarType;
u16 numTables;
u16 searchRange;
u16 entrySelector;
u16 rangeShift;
u64 start = $;
HiddenForPreprocessing hidden[numTables] [[hidden]];
$ = start;
Table tables[numTables];
};
TTF ttf @ 0x0;

View File

@@ -231,7 +231,7 @@ struct DeviceQualifierDescriptor {
bitfield OTGAttributes {
SRPSupport : 1;
HNPSupport : 1;
} [[right_to_left]];
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 2)]];
struct OTGDescriptor {
OTGAttributes bmAttributes;

View File

@@ -47,11 +47,11 @@ bitfield Header {
fn validate_hdr_checksum(Header hdr) {
// Reassemble as a 2-byte big endian value
u16 value = (
(hdr.method << 8) +
(u8(hdr.method) << 8) +
(hdr.info << 12) +
(hdr.fcheck << 0) +
(hdr.fdict << 5) +
(hdr.flevel << 6)
(u8(hdr.flevel) << 6)
);
if (value % 31 == 0) {

View File

@@ -83,5 +83,11 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
return hasDescription ? EXIT_SUCCESS : EXIT_FAILURE;
if (!hasDescription) {
fmt::print("No description pragma found in pattern file\n");
fmt::print("Please add a #pragma description <your description> tag to the pattern!\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.