From 2d92bfca1366cfd9ce7629f4b40d84235387f306 Mon Sep 17 00:00:00 2001 From: Jack Manning Date: Sat, 3 Jan 2026 14:23:53 -0500 Subject: [PATCH] pattern: Add Chromium pak file (#474) * Add Chromium pak file pattern * Show aliases & fix brotli check bug * Add decompressed size * Add notes * Add PakEncoding enum --- README.md | 1 + patterns/chromium_pak.hexpat | 81 ++++++++++++++++++ .../chromium_pak.hexpat/kEmptyPakContents.pak | Bin 0 -> 15 bytes .../kSampleCompressPakContentsV5.pak | Bin 0 -> 105 bytes .../kSampleCompressScaledPakContents.pak | Bin 0 -> 79 bytes .../kSamplePakContents2x.pak | Bin 0 -> 36 bytes .../kSamplePakContentsV4.pak | Bin 0 -> 63 bytes 7 files changed, 82 insertions(+) create mode 100644 patterns/chromium_pak.hexpat create mode 100644 tests/patterns/test_data/chromium_pak.hexpat/kEmptyPakContents.pak create mode 100644 tests/patterns/test_data/chromium_pak.hexpat/kSampleCompressPakContentsV5.pak create mode 100644 tests/patterns/test_data/chromium_pak.hexpat/kSampleCompressScaledPakContents.pak create mode 100644 tests/patterns/test_data/chromium_pak.hexpat/kSamplePakContents2x.pak create mode 100644 tests/patterns/test_data/chromium_pak.hexpat/kSamplePakContentsV4.pak diff --git a/README.md b/README.md index 3492223..c90c17d 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi | CDA | | [`patterns/cda.hexpat`](patterns/cda.hexpat) | Compact Disc Audio track | | CHD | | [`patterns/chd.hexpat`](patterns/chd.hexpat) | MAME Compressed Hunks of Data file | | CHM | `application/vnd.ms-htmlhelp` | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) | +| Chromium Pak | | [`patterns/chromium_pak.hexpat`](patterns/chromium_pak.hexpat) | Chromium pak file | | COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable | | CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format | | CrashLvl | | [`patterns/Crashlvl.hexpat`](patterns/Crashlvl.hexpat) | Crash Bandicoot - Back in Time (fan game) User created level format | diff --git a/patterns/chromium_pak.hexpat b/patterns/chromium_pak.hexpat new file mode 100644 index 0000000..d609b9e --- /dev/null +++ b/patterns/chromium_pak.hexpat @@ -0,0 +1,81 @@ +#pragma author East_Arctica +#pragma description Chromium Pak File + +import std.core; +import std.io; + +struct IndexEntry { + u16 id; + u32 offset; +}; + +struct AliasEntry { + u16 id; + u16 index; +}; + +struct ResourceView { + u32 i = std::core::array_index(); + + u16 id = parent.entries[i].id; + u32 start = parent.entries[i].offset; + u32 end = parent.entries[i + 1].offset; + u32 length = (end >= start) ? (end - start) : 0; + + u8 data[length] @ start; + + // pak_util.py implies that this may also be gzip with a header of 0x1f 0x8b + bool is_brotli = (length > 8 && data[0] == 0x1e && data[1] == 0x9b); + if (is_brotli) { + u8 magic[2] @ start; + u48 decompressed_size @ start + 2; + // TODO: If brotli decompression is added to ImHex, add it here. + } +}; + +struct AliasResourceView { + u32 i = std::core::array_index(); + + u16 id = parent.aliases[i].id; + u16 idx = parent.aliases[i].index; + + bool valid = (idx < parent.resource_count); + u32 start = valid ? parent.entries[idx].offset : 0; + u32 end = valid ? parent.entries[idx + 1].offset : 0; + u32 length = (valid && end >= start) ? (end - start) : 0; + + u8 data[length] @ start; + +}; + +enum PakEncoding : u8 { + binary = 0, + utf8 = 1, + utf16 = 2 +}; + +struct Pak { + u32 version; + if (version == 4) { + u32 resource_count; + PakEncoding encoding; + + IndexEntry entries[resource_count + 1]; + ResourceView resources[resource_count]; + } else if (version == 5) { + PakEncoding encoding; + padding[3]; + u16 resource_count; + u16 alias_count; + + IndexEntry entries[resource_count + 1]; + AliasEntry aliases[alias_count]; + ResourceView resources[resource_count]; + AliasResourceView alias_resources[alias_count]; + } else { + std::error("Unsupported pak version"); + } +}; + +// Some pack files are stored gzipped and need to be gunzipped first +Pak pak @ 0x00; diff --git a/tests/patterns/test_data/chromium_pak.hexpat/kEmptyPakContents.pak b/tests/patterns/test_data/chromium_pak.hexpat/kEmptyPakContents.pak new file mode 100644 index 0000000000000000000000000000000000000000..85cf8b5b58b1fe95b139ff17b3cb1bed06cee946 GIT binary patch literal 15 QcmZQ!fB;4Y27Vw50052v6#xJL literal 0 HcmV?d00001 diff --git a/tests/patterns/test_data/chromium_pak.hexpat/kSampleCompressPakContentsV5.pak b/tests/patterns/test_data/chromium_pak.hexpat/kSampleCompressPakContentsV5.pak new file mode 100644 index 0000000000000000000000000000000000000000..ce5470b9d8801849483e11f550443e3a0dd39a59 GIT binary patch literal 105 zcmZQ&U|?VbVrC%8!k__Uu`!qcNe%`dAj!ax3B+7LT#}JltN=nO3MO*1c|cMO{j3de l;SdEg7Wr-thTxgmX5nZ*hql%imwU{nDBFR}## literal 0 HcmV?d00001 diff --git a/tests/patterns/test_data/chromium_pak.hexpat/kSamplePakContentsV4.pak b/tests/patterns/test_data/chromium_pak.hexpat/kSamplePakContentsV4.pak new file mode 100644 index 0000000000000000000000000000000000000000..1996f57cc87cfea5ea31987b859862b574ab131c GIT binary patch literal 63 tcmZQ!U|?VYVn#*=bube|vN0F~NiGI^AjtqGOENNx6+kFO!32qI3ILR02?+oI literal 0 HcmV?d00001