mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-31 05:15:54 -05:00
Compare commits
31 Commits
ImHex-v1.2
...
ImHex-v1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f53be98204 | ||
|
|
ee95990225 | ||
|
|
ac28d9d029 | ||
|
|
372a0e5bba | ||
|
|
544cadbcca | ||
|
|
1471b02abd | ||
|
|
73cde21254 | ||
|
|
f730d8b0cc | ||
|
|
13183769f8 | ||
|
|
5eda5a15bf | ||
|
|
8e6248aa2d | ||
|
|
75fd40442b | ||
|
|
5a3036149c | ||
|
|
b160e99b63 | ||
|
|
f32db1745f | ||
|
|
7842c974df | ||
|
|
e2c191b7c9 | ||
|
|
71ee41fe2c | ||
|
|
69feadfc09 | ||
|
|
e79d512b2b | ||
|
|
e876270a08 | ||
|
|
8f39ecd879 | ||
|
|
ba36826e2d | ||
|
|
ac0b77540d | ||
|
|
683e78d9c3 | ||
|
|
110b498d7b | ||
|
|
9887da7af5 | ||
|
|
01a1bd0d9f | ||
|
|
fbb6a84323 | ||
|
|
4cdf3c11cf | ||
|
|
a9ada89bd0 |
16
README.md
16
README.md
@@ -11,6 +11,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed
|
||||
| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files |
|
||||
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
|
||||
| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
|
||||
| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
|
||||
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
|
||||
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
|
||||
| WAV | `audio/wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
|
||||
@@ -46,6 +47,21 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed
|
||||
| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format |
|
||||
| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files |
|
||||
| ID3 | `audio/mpeg` | [`patterns/id3tag.hexpat`](patterns/id3tag.hexpat) | ID3 tags in MP3 files |
|
||||
| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format |
|
||||
| CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format |
|
||||
| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob |
|
||||
| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive |
|
||||
| NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format |
|
||||
| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format |
|
||||
| GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format |
|
||||
| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) |
|
||||
| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cardridge ROM |
|
||||
| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive |
|
||||
| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files |
|
||||
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
|
||||
| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable |
|
||||
| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable |
|
||||
| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) |
|
||||
|
||||
### Scripts
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
00=
|
||||
08=\b
|
||||
09=\t
|
||||
0A=\n
|
||||
0B=\v
|
||||
0C=\f
|
||||
0D=\r
|
||||
08=␈
|
||||
09=␉
|
||||
0A=␊
|
||||
0B=␋
|
||||
0C=␌
|
||||
0D=␍
|
||||
20=
|
||||
21=!
|
||||
22="
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace std::limits {
|
||||
};
|
||||
|
||||
fn s8_max() {
|
||||
return s8((u8_max() / 2));
|
||||
return s8((std::limits::u8_max() / 2));
|
||||
};
|
||||
|
||||
fn u16_min() {
|
||||
@@ -31,7 +31,7 @@ namespace std::limits {
|
||||
};
|
||||
|
||||
fn s16_max() {
|
||||
return s16((u16_max() / 2));
|
||||
return s16((std::limits::u16_max() / 2));
|
||||
};
|
||||
|
||||
fn u32_min() {
|
||||
@@ -47,7 +47,7 @@ namespace std::limits {
|
||||
};
|
||||
|
||||
fn s32_max() {
|
||||
return s32((u32_max() / 2));
|
||||
return s32((std::limits::u32_max() / 2));
|
||||
};
|
||||
|
||||
fn u64_min() {
|
||||
@@ -63,7 +63,7 @@ namespace std::limits {
|
||||
};
|
||||
|
||||
fn s64_max() {
|
||||
return s64((u64_max() / 2));
|
||||
return s64((std::limits::u64_max() / 2));
|
||||
};
|
||||
|
||||
fn u128_min() {
|
||||
@@ -79,7 +79,7 @@ namespace std::limits {
|
||||
};
|
||||
|
||||
fn s128_max() {
|
||||
return s128((u128_max() / 2));
|
||||
return s128((std::limits::u128_max() / 2));
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace std::mem {
|
||||
};
|
||||
|
||||
fn copy_section_to_section(Section from_section, u64 from_address, Section to_section, u64 to_address, u64 size) {
|
||||
builtin::std::mem::get_section_size(from_section, from_address, to_section, to_address, size);
|
||||
builtin::std::mem::copy_to_section(from_section, from_address, to_section, to_address, size);
|
||||
};
|
||||
|
||||
fn copy_value_to_section(ref auto value, Section to_section, u64 to_address) {
|
||||
@@ -92,5 +92,9 @@ namespace std::mem {
|
||||
From from;
|
||||
To to;
|
||||
};
|
||||
|
||||
struct AlignTo<auto Alignment> {
|
||||
padding[Alignment - ((($ - 1) % Alignment) + 1)];
|
||||
} [[hidden, sealed]];
|
||||
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ namespace type {
|
||||
|
||||
namespace impl {
|
||||
|
||||
fn format_number(auto value, str fmt) {
|
||||
bool negative = value < 0;
|
||||
fn format_number(auto value, str fmt) {
|
||||
bool negative = value < 0;
|
||||
|
||||
if (negative)
|
||||
return std::format("-" + fmt, std::math::abs(value));
|
||||
else
|
||||
return std::format(fmt, value);
|
||||
};
|
||||
if (negative)
|
||||
return std::format("-" + fmt, std::math::abs(value));
|
||||
else
|
||||
return std::format(fmt, value);
|
||||
};
|
||||
|
||||
fn format_hex(auto value) { return format_number(value, "0x{:02X}"); };
|
||||
fn format_oct(auto value) { return format_number(value, "0o{:03o}"); };
|
||||
fn format_dec(auto value) { return format_number(value, "{}"); };
|
||||
fn format_bin(auto value) { return format_number(value, "0b{:08b}"); };
|
||||
fn format_hex(auto value) { return type::impl::format_number(value, "0x{:02X}"); };
|
||||
fn format_oct(auto value) { return type::impl::format_number(value, "0o{:03o}"); };
|
||||
fn format_dec(auto value) { return type::impl::format_number(value, "{}"); };
|
||||
fn format_bin(auto value) { return type::impl::format_number(value, "0b{:08b}"); };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
29
includes/type/bcd.pat
Normal file
29
includes/type/bcd.pat
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
namespace type {
|
||||
|
||||
struct BCD<auto Digits> {
|
||||
u8 bytes[Digits];
|
||||
} [[sealed, format_read("type::impl::format_bcd")]];
|
||||
|
||||
namespace impl {
|
||||
|
||||
fn format_bcd(ref auto bcd) {
|
||||
str result;
|
||||
|
||||
for (u32 i = 0, i < sizeof(bcd.bytes), i += 1) {
|
||||
u8 byte = bcd.bytes[i];
|
||||
if (byte >= 10)
|
||||
return "Invalid";
|
||||
|
||||
result += std::format("{}", byte);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
19
includes/type/magic.pat
Normal file
19
includes/type/magic.pat
Normal file
@@ -0,0 +1,19 @@
|
||||
#include <std/string.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
namespace type {
|
||||
|
||||
struct Magic<auto ExpectedValue> {
|
||||
char value[std::string::length(ExpectedValue)];
|
||||
std::assert(value == ExpectedValue, std::format("Invalid magic value! Expected \"{}\", got \"{}\".", ExpectedValue, value));
|
||||
} [[sealed, format("type::impl::format_magic")]];
|
||||
|
||||
namespace impl {
|
||||
|
||||
fn format_magic(ref auto magic) {
|
||||
return magic.value;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
395
patterns/chm.hexpat
Normal file
395
patterns/chm.hexpat
Normal file
@@ -0,0 +1,395 @@
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
#include <type/guid.pat>
|
||||
#include <type/leb128.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
enum WindowsLanguageId : u32 {
|
||||
Arabic_SaudiArabia = 0x401,
|
||||
Arabic_Iraq = 0x801,
|
||||
Arabic_Egypt = 0xc01,
|
||||
Arabic_Libya = 0x1001,
|
||||
Arabic_Algeria = 0x1401,
|
||||
Arabic_Morocco = 0x1801,
|
||||
Arabic_Tunisia = 0x1c01,
|
||||
Arabic_Oman = 0x2001,
|
||||
Arabic_Yemen = 0x2401,
|
||||
Arabic_Syria = 0x2801,
|
||||
Arabic_Jordan = 0x2c01,
|
||||
Arabic_Lebanon = 0x3001,
|
||||
Arabic_Kuwait = 0x3401,
|
||||
Arabic_UAE = 0x3801,
|
||||
Arabic_Bahrain = 0x3c01,
|
||||
Arabic_Qatar = 0x4001,
|
||||
Bulgarian = 0x402,
|
||||
Catalan = 0x403,
|
||||
Valencian = 0x803,
|
||||
Chinese_Taiwan = 0x404,
|
||||
Chinese_PRC = 0x804,
|
||||
Chinese_HongKongSAR = 0xc04,
|
||||
Chinese_Singapore = 0x1004,
|
||||
Chinese_MacaoSAR = 0x1404,
|
||||
Czech = 0x405,
|
||||
Danish = 0x406,
|
||||
German_Germany = 0x407,
|
||||
German_Switzerland = 0x807,
|
||||
German_Austria = 0xc07,
|
||||
German_Luxembourg = 0x1007,
|
||||
German_Liechtenstein = 0x1407,
|
||||
Greek = 0x408,
|
||||
English_UnitedStates = 0x409,
|
||||
English_UnitedKingdom = 0x809,
|
||||
English_Australia = 0xc09,
|
||||
English_Canada = 0x1009,
|
||||
English_NewZealand = 0x1409,
|
||||
English_Ireland = 0x1809,
|
||||
English_SouthAfrica = 0x1c09,
|
||||
English_Jamaica = 0x2009,
|
||||
English_Caribbean = 0x2409,
|
||||
English_Belize = 0x2809,
|
||||
English_TrinidadandTobago = 0x2c09,
|
||||
English_Zimbabwe = 0x3009,
|
||||
English_Philippines = 0x3409,
|
||||
English_Indonesia = 0x3809,
|
||||
English_HongKongSAR = 0x3c09,
|
||||
English_India = 0x4009,
|
||||
English_Malaysia = 0x4409,
|
||||
English_Singapore = 0x4809,
|
||||
Spanish_SpainTraditionalSort = 0x40a,
|
||||
Spanish_Mexico = 0x80a,
|
||||
Spanish_Spain = 0xc0a,
|
||||
Spanish_Guatemala = 0x100a,
|
||||
Spanish_CostaRica = 0x140a,
|
||||
Spanish_Panama = 0x180a,
|
||||
Spanish_DominicanRepublic = 0x1c0a,
|
||||
Spanish_Venezuela = 0x200a,
|
||||
Spanish_Colombia = 0x240a,
|
||||
Spanish_Peru = 0x280a,
|
||||
Spanish_Argentina = 0x2c0a,
|
||||
Spanish_Ecuador = 0x300a,
|
||||
Spanish_Chile = 0x340a,
|
||||
Spanish_Uruguay = 0x380a,
|
||||
Spanish_Paraguay = 0x3c0a,
|
||||
Spanish_Bolivia = 0x400a,
|
||||
Spanish_ElSalvador = 0x440a,
|
||||
Spanish_Honduras = 0x480a,
|
||||
Spanish_Nicaragua = 0x4c0a,
|
||||
Spanish_PuertoRico = 0x500a,
|
||||
Spanish_UnitedStates = 0x540a,
|
||||
Spanish_LatinAmerica = 0x580a,
|
||||
Finnish = 0x40b,
|
||||
French_France = 0x40c,
|
||||
French_Belgium = 0x80c,
|
||||
French_Canada = 0xc0c,
|
||||
French_Switzerland = 0x100c,
|
||||
French_Luxembourg = 0x140c,
|
||||
French_Monaco = 0x180c,
|
||||
French_Caribbean = 0x1c0c,
|
||||
French_Reunion = 0x200c,
|
||||
French_CongoDRC = 0x240c,
|
||||
French_Senegal = 0x280c,
|
||||
French_Cameroon = 0x2c0c,
|
||||
French_CoteDIvoire = 0x300c,
|
||||
French_Mali = 0x340c,
|
||||
French_Morocco = 0x380c,
|
||||
French_Haiti = 0x3c0c,
|
||||
Hebrew = 0x40d,
|
||||
Hungarian = 0x40e,
|
||||
Icelandic = 0x40f,
|
||||
Italian_Italy = 0x410,
|
||||
Italian_Switzerland = 0x810,
|
||||
Japanese = 0x411,
|
||||
Korean = 0x412,
|
||||
Dutch_Netherlands = 0x413,
|
||||
Dutch_Belgium = 0x813,
|
||||
Norwegian_Bokmal = 0x414,
|
||||
Norwegian_Nynorsk = 0x814,
|
||||
Polish = 0x415,
|
||||
Portuguese_Brazil = 0x416,
|
||||
Portuguese_Portugal = 0x816,
|
||||
Romansh = 0x417,
|
||||
Romanian = 0x418,
|
||||
Romanian_Moldova = 0x818,
|
||||
Russian = 0x419,
|
||||
Russian_Moldova = 0x819,
|
||||
Croatian_Croatia = 0x41a,
|
||||
Serbian_LatinSerbiaandMontenegroFormer = 0x81a,
|
||||
Serbian_CyrillicSerbiaAndMontenegroFormer = 0xc1a,
|
||||
Croatian_BosniaAndHerzegovina = 0x101a,
|
||||
Bosnian_Latin = 0x141a,
|
||||
Serbian_LatinBosniaAndHerzegovina = 0x181a,
|
||||
Serbian_CyrillicBosniaAndHerzegovina = 0x1c1a,
|
||||
Bosnian_Cyrillic = 0x201a,
|
||||
Serbian_LatinSerbia = 0x241a,
|
||||
Serbian_CyrillicSerbia = 0x281a,
|
||||
Serbian_LatinMontenegro = 0x2c1a,
|
||||
Serbian_CyrillicMontenegro = 0x301a,
|
||||
Slovak = 0x41b,
|
||||
Albanian = 0x41c,
|
||||
Swedish_Sweden = 0x41d,
|
||||
Swedish_Finland = 0x81d,
|
||||
Thai = 0x41e,
|
||||
Turkish = 0x41f,
|
||||
Urdu_Pakistan = 0x420,
|
||||
Urdu_India = 0x820,
|
||||
Indonesian = 0x421,
|
||||
Ukrainian = 0x422,
|
||||
Belarusian = 0x423,
|
||||
Slovenian = 0x424,
|
||||
Estonian = 0x425,
|
||||
Latvian = 0x426,
|
||||
Lithuanian = 0x427,
|
||||
Tajik = 0x428,
|
||||
Persian = 0x429,
|
||||
Vietnamese = 0x42a,
|
||||
Armenian = 0x42b,
|
||||
Azerbaijani_Latin = 0x42c,
|
||||
Azerbaijani_Cyrillic = 0x82c,
|
||||
Basque = 0x42d,
|
||||
UpperSorbian = 0x42e,
|
||||
LowerSorbian = 0x82e,
|
||||
Macedonian = 0x42f,
|
||||
Sesotho_SouthAfrica = 0x430,
|
||||
Xitsonga = 0x431,
|
||||
Setswana_SouthAfrica = 0x432,
|
||||
Setswana_Botswana = 0x832,
|
||||
Venda = 0x433,
|
||||
isiXhosa = 0x434,
|
||||
isiZulu = 0x435,
|
||||
Afrikaans = 0x436,
|
||||
Georgian = 0x437,
|
||||
Faroese = 0x438,
|
||||
Hindi = 0x439,
|
||||
Maltese = 0x43a,
|
||||
NorthernSami_Norway = 0x43b,
|
||||
NorthernSami_Sweden = 0x83b,
|
||||
NorthernSami_Finland = 0xc3b,
|
||||
LuleSami_Norway = 0x103b,
|
||||
LuleSami_Sweden = 0x143b,
|
||||
SouthernSami_Norway = 0x183b,
|
||||
SouthernSami_Sweden = 0x1c3b,
|
||||
SkoltSami_Finland = 0x203b,
|
||||
InariSami_Finland = 0x243b,
|
||||
Irish = 0x83c,
|
||||
Yiddish = 0x43d,
|
||||
Malay_Malaysia = 0x43e,
|
||||
Malay_BruneiDarussalam = 0x83e,
|
||||
Kazakh = 0x43f,
|
||||
Kyrgyz = 0x440,
|
||||
Kiswahili = 0x441,
|
||||
Turkmen = 0x442,
|
||||
Uzbek_Latin = 0x443,
|
||||
Uzbek_Cyrillic = 0x843,
|
||||
Tatar = 0x444,
|
||||
Bangla_India = 0x445,
|
||||
Bangla_Bangladesh = 0x845,
|
||||
Punjabi_India = 0x446,
|
||||
Punjabi_Pakistan = 0x846,
|
||||
Gujarati = 0x447,
|
||||
Odia = 0x448,
|
||||
Tamil_India = 0x449,
|
||||
Tamil_SriLanka = 0x849,
|
||||
Telugu = 0x44a,
|
||||
Kannada = 0x44b,
|
||||
Malayalam = 0x44c,
|
||||
Assamese = 0x44d,
|
||||
Marathi = 0x44e,
|
||||
Sanskrit = 0x44f,
|
||||
Mongolian_Cyrillic = 0x450,
|
||||
Mongolian_TraditionalMongolianPRC = 0x850,
|
||||
Mongolian_TraditionalMongolianMongolia = 0xc50,
|
||||
Tibetan_PRC = 0x451,
|
||||
Welsh = 0x452,
|
||||
Khmer = 0x453,
|
||||
Lao = 0x454,
|
||||
Burmese = 0x455,
|
||||
Galician = 0x456,
|
||||
Konkani = 0x457,
|
||||
Manipuri = 0x458,
|
||||
Sindhi_Devanagari = 0x459,
|
||||
Sindhi_Arabic = 0x859,
|
||||
Syriac = 0x45a,
|
||||
Sinhala = 0x45b,
|
||||
Cherokee_Cherokee = 0x45c,
|
||||
Inuktitut_Syllabics = 0x45d,
|
||||
Inuktitut_Latin = 0x85d,
|
||||
Amharic = 0x45e,
|
||||
Tamazight_ArabicMorocco = 0x45f,
|
||||
Tamazight_LatinAlgeria = 0x85f,
|
||||
Tamazight_TifinaghMorocco = 0x105f,
|
||||
Kashmiri_Arabic = 0x460,
|
||||
Kashmiri = 0x860,
|
||||
Nepali = 0x461,
|
||||
Nepali_India = 0x861,
|
||||
Frisian = 0x462,
|
||||
Pashto = 0x463,
|
||||
Filipino = 0x464,
|
||||
Divehi = 0x465,
|
||||
Edo = 0x466,
|
||||
Fulah_Nigeria = 0x467,
|
||||
Fulah_LatinSenegal = 0x867,
|
||||
Hausa = 0x468,
|
||||
Ibibio_Nigeria = 0x469,
|
||||
Yoruba = 0x46a,
|
||||
Quechua_Bolivia = 0x46b,
|
||||
Quechua_Ecuador = 0x86b,
|
||||
Quechua_Peru = 0xc6b,
|
||||
SesothoSaLeboa = 0x46c,
|
||||
Bashkir = 0x46d,
|
||||
Luxembourgish = 0x46e,
|
||||
Greenlandic = 0x46f,
|
||||
Igbo = 0x470,
|
||||
Kanuri = 0x471,
|
||||
Oromo = 0x472,
|
||||
Tigrinya_Ethiopia = 0x473,
|
||||
Tigrinya_Eritrea = 0x873,
|
||||
Guarani = 0x474,
|
||||
Hawaiian = 0x475,
|
||||
Latin = 0x476,
|
||||
Somali = 0x477,
|
||||
Yi_PRC = 0x478,
|
||||
Papiamentu = 0x479,
|
||||
Mapudungun = 0x47a,
|
||||
Mohawk = 0x47c,
|
||||
Breton = 0x47e,
|
||||
Uyghur_PRC = 0x480,
|
||||
Maori = 0x481,
|
||||
Occitan = 0x482,
|
||||
Corsican = 0x483,
|
||||
Alsatian = 0x484,
|
||||
Sakha = 0x485,
|
||||
Kiche = 0x486,
|
||||
Kinyarwanda = 0x487,
|
||||
Wolof = 0x488,
|
||||
Dari = 0x48c,
|
||||
ScottishGaelic_UnitedKingdom = 0x491,
|
||||
CentralKurdish_Iraq = 0x492
|
||||
};
|
||||
|
||||
struct DirectoryListingEntry {
|
||||
type::LEB128 nameLength;
|
||||
char name[nameLength];
|
||||
type::LEB128 contentSection;
|
||||
type::LEB128 offset;
|
||||
type::LEB128 length;
|
||||
};
|
||||
|
||||
struct DirectoryIndexEntry {
|
||||
type::LEB128 nameLength;
|
||||
char name[nameLength];
|
||||
type::LEB128 directoryListingChunk;
|
||||
};
|
||||
|
||||
struct ListingChunk {
|
||||
char magic[4];
|
||||
|
||||
if (magic == "PMGL") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
u32;
|
||||
u32 prevChunkNumber, nextChunkNumber;
|
||||
|
||||
u16 directoryListingEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryListingEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
DirectoryListingEntry directories[directoryListingEntryCount];
|
||||
|
||||
$ = addressof(directoryListingEntryCount) + sizeof(directoryListingEntryCount);
|
||||
} else if (magic == "PMGI") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
|
||||
u16 directoryIndexEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryIndexEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
DirectoryIndexEntry indexes[directoryIndexEntryCount];
|
||||
|
||||
$ = addressof(directoryIndexEntryCount) + sizeof(directoryIndexEntryCount);
|
||||
} else {
|
||||
std::error("Invalid chunk magic!");
|
||||
}
|
||||
};
|
||||
|
||||
struct HeaderSection {
|
||||
char magic[4];
|
||||
|
||||
if (magic == "\xFE\x01\x00\x00") {
|
||||
u32;
|
||||
type::Size<u64> fileSize;
|
||||
u32;
|
||||
u32;
|
||||
} else if (magic == "ITSP") {
|
||||
u32 version;
|
||||
type::Size<u32> directoryHeaderLength1;
|
||||
u32;
|
||||
u32 directoryChunkSize;
|
||||
u32 quickRefSectionDensity;
|
||||
u32 indexTreeDepth;
|
||||
u32 rootIndexChunkNumber;
|
||||
u32 firstPMGLChunkNumber;
|
||||
u32 lastPMGLChunkNumber;
|
||||
u32;
|
||||
u32 directoryChunkCount;
|
||||
WindowsLanguageId languageId;
|
||||
type::GUID guid;
|
||||
type::Size<u32> directoryHeaderLength2;
|
||||
u32;
|
||||
u32;
|
||||
u32;
|
||||
|
||||
ListingChunk chunk[directoryChunkCount];
|
||||
} else {
|
||||
std::error("Invalid header section magic!");
|
||||
}
|
||||
};
|
||||
|
||||
struct HeaderSectionTableEntry {
|
||||
u64 offset;
|
||||
type::Size<u64> size;
|
||||
|
||||
HeaderSection headerSection @ offset;
|
||||
};
|
||||
|
||||
struct NameListEntry {
|
||||
type::Size<u16> nameLength;
|
||||
char16 name[nameLength];
|
||||
padding[2];
|
||||
};
|
||||
|
||||
struct NameListFile {
|
||||
u16 fileLengthWords;
|
||||
u16 entriesInFile;
|
||||
|
||||
NameListEntry nameList[entriesInFile];
|
||||
|
||||
padding[0x2E];
|
||||
};
|
||||
|
||||
struct SectionData {
|
||||
u32 fileLengthWords;
|
||||
type::Magic<"LZXC"> magic;
|
||||
u32 version;
|
||||
u32 lzxResetInterval;
|
||||
type::Size<u32> windowSize;
|
||||
type::Size<u32> cacheSize;
|
||||
u32;
|
||||
};
|
||||
|
||||
struct Content {
|
||||
NameListFile nameListFile;
|
||||
SectionData sectionData;
|
||||
};
|
||||
|
||||
struct CHM {
|
||||
type::Magic<"ITSF"> magic;
|
||||
u32 version;
|
||||
type::Size<u32> headerSize;
|
||||
u32;
|
||||
be u32 timeStamp;
|
||||
WindowsLanguageId languageId;
|
||||
type::GUID guids[2];
|
||||
|
||||
HeaderSectionTableEntry headerSectionTable[2];
|
||||
|
||||
Content *dataOffset : u64;
|
||||
};
|
||||
|
||||
CHM chm @ 0x00;
|
||||
209
patterns/coff.hexpat
Normal file
209
patterns/coff.hexpat
Normal file
@@ -0,0 +1,209 @@
|
||||
#pragma MIME application/x-coff
|
||||
|
||||
#include <type/time.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
enum Machine : u16 {
|
||||
Unknown = 0x0000,
|
||||
AM33 = 0x01D3,
|
||||
AMD64 = 0x8664,
|
||||
ARM = 0x01C0,
|
||||
ARM64 = 0xAA64,
|
||||
ARMNT = 0x01C4,
|
||||
EBC = 0x0EBC,
|
||||
I386 = 0x014C,
|
||||
IA64 = 0x0200,
|
||||
LOONGARCH32 = 0x6232,
|
||||
LOONGARCH64 = 0x6264,
|
||||
M32R = 0x9041,
|
||||
MIPS16 = 0x0226,
|
||||
MIPSFPU = 0x0366,
|
||||
MIPSFPU16 = 0x0466,
|
||||
POWERPC = 0x01F0,
|
||||
POWERPCFP = 0x01F0,
|
||||
R4000 = 0x0166,
|
||||
RISCV32 = 0x5032,
|
||||
RISCV64 = 0x5064,
|
||||
RISCV128 = 0x5128,
|
||||
SH3 = 0x01A2,
|
||||
SH3DSP = 0x01A3,
|
||||
SH4 = 0x01A6,
|
||||
SH5 = 0x01A8,
|
||||
THUMB = 0x01C2,
|
||||
WCEMIPSV2 = 0x0169
|
||||
};
|
||||
|
||||
bitfield Characteristics {
|
||||
relocsStripped : 1;
|
||||
executableImage : 1;
|
||||
lineNumsStripped : 1;
|
||||
localSymsStripped : 1;
|
||||
aggressiveWsTrim : 1;
|
||||
largeAddressAware : 1;
|
||||
padding : 1;
|
||||
bytesReversedLo : 1;
|
||||
_32BitMachine : 1;
|
||||
debugStripped : 1;
|
||||
removableRunFromSwap : 1;
|
||||
netRunFromSwap : 1;
|
||||
system : 1;
|
||||
dll : 1;
|
||||
upSystemOnly : 1;
|
||||
bytesReversedHi : 1;
|
||||
} [[right_to_left]];
|
||||
|
||||
enum Type : u16 {
|
||||
Null = 0,
|
||||
Void = 1,
|
||||
Char = 2,
|
||||
Short = 3,
|
||||
Int = 4,
|
||||
Long = 5,
|
||||
Float = 6,
|
||||
Double = 7,
|
||||
Struct = 8,
|
||||
Union = 9,
|
||||
Enum = 10,
|
||||
MOE = 11,
|
||||
Byte = 12,
|
||||
Word = 13,
|
||||
UInt = 14,
|
||||
DWord = 15
|
||||
};
|
||||
|
||||
enum StorageClass : u8 {
|
||||
EndOfFunction = 0xFF,
|
||||
Null = 0,
|
||||
Automatic = 1,
|
||||
External = 2,
|
||||
Static = 3,
|
||||
Register = 4,
|
||||
ExternalDef = 5,
|
||||
Label = 6,
|
||||
UndefinedLabel = 7,
|
||||
MemberOfStruct = 8,
|
||||
Argument = 9,
|
||||
StructTag = 10,
|
||||
MemberOfUnion = 11,
|
||||
UnionTag = 12,
|
||||
TypeDefinition = 13,
|
||||
UndefinedStatic = 14,
|
||||
EnumTag = 15,
|
||||
MemberOfEnum = 16,
|
||||
RegisterParam = 17,
|
||||
BitField = 18,
|
||||
Block = 100,
|
||||
Function = 101,
|
||||
EndOfStruct = 102,
|
||||
File = 103,
|
||||
Section = 104,
|
||||
WeakExternal = 105,
|
||||
CLRToken = 107
|
||||
};
|
||||
|
||||
struct AuxSymbol {
|
||||
u8 data[18];
|
||||
};
|
||||
|
||||
u32 countedSymbols = 0;
|
||||
struct SymbolTable {
|
||||
char name[8];
|
||||
u32 value;
|
||||
u16 sectionNumber;
|
||||
Type type;
|
||||
StorageClass storageClass;
|
||||
u8 numberOfAuxSymbols;
|
||||
|
||||
countedSymbols += 1 + numberOfAuxSymbols;
|
||||
|
||||
AuxSymbol auxSymbols[numberOfAuxSymbols];
|
||||
|
||||
if (countedSymbols >= parent.header.numberOfSymbols)
|
||||
break;
|
||||
};
|
||||
|
||||
struct String {
|
||||
char value[];
|
||||
};
|
||||
|
||||
struct StringTable {
|
||||
u32 size;
|
||||
String strings[while($ < addressof(size) + size)];
|
||||
};
|
||||
|
||||
bitfield SectionFlags {
|
||||
padding : 3;
|
||||
typeNoPad : 1;
|
||||
padding : 1;
|
||||
cntCode : 1;
|
||||
initializedData : 1;
|
||||
uninitializedData : 1;
|
||||
lnkOther : 1;
|
||||
lnkInfo : 1;
|
||||
padding : 1;
|
||||
lnkRemove : 1;
|
||||
lnkCOMDAT : 1;
|
||||
padding : 2;
|
||||
gprel : 1;
|
||||
padding : 1;
|
||||
memPurgeable : 1;
|
||||
memLocked : 1;
|
||||
memPreload : 1;
|
||||
alignment : 4 [[format("format_alignment")]];
|
||||
lnkNrelocOvfl : 1;
|
||||
memDiscardable : 1;
|
||||
memNotCached : 1;
|
||||
memNotPaged : 1;
|
||||
memShared : 1;
|
||||
memExecute : 1;
|
||||
memRead : 1;
|
||||
memWrite : 1;
|
||||
} [[right_to_left]];
|
||||
|
||||
fn format_alignment(u8 alignment) {
|
||||
return 1 << alignment;
|
||||
};
|
||||
|
||||
struct Relocations {
|
||||
u32 virtualAddress;
|
||||
u32 symbolTableIndex;
|
||||
Type type;
|
||||
};
|
||||
|
||||
struct Section {
|
||||
char name[8];
|
||||
type::Size<u32> virtualSize;
|
||||
u32 virtualAddress;
|
||||
type::Size<u32> sizeOfRawData;
|
||||
u32 pointerToRawData;
|
||||
u32 pointerToRelocations;
|
||||
u32 pointerToLineNumbers;
|
||||
u16 numberOfRelocations;
|
||||
u16 numberOfLineNumbers;
|
||||
SectionFlags characteristics;
|
||||
|
||||
u8 rawData[sizeOfRawData] @ pointerToRawData [[sealed]];
|
||||
Relocations relocations[numberOfRelocations] @ pointerToRelocations;
|
||||
};
|
||||
|
||||
struct Header {
|
||||
Machine machine;
|
||||
u16 numberOfSections;
|
||||
type::time32_t timeDateStamp;
|
||||
u32 pointerToSymbolTable;
|
||||
u32 numberOfSymbols;
|
||||
u16 sizeOfOptionalHeader;
|
||||
Characteristics characteristics;
|
||||
};
|
||||
|
||||
|
||||
struct COFF {
|
||||
Header header;
|
||||
|
||||
Section sectionTable[header.numberOfSections];
|
||||
|
||||
SymbolTable symbolTable[header.numberOfSymbols] @ header.pointerToSymbolTable;
|
||||
StringTable stringTable @ addressof(symbolTable) + sizeof(symbolTable);
|
||||
};
|
||||
|
||||
COFF coff @ 0x00;
|
||||
66
patterns/cpio.pat
Normal file
66
patterns/cpio.pat
Normal file
@@ -0,0 +1,66 @@
|
||||
#include <type/base.pat>
|
||||
|
||||
#include <std/time.pat>
|
||||
#include <std/core.pat>
|
||||
#include <std/sys.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
#pragma MIME application/x-cpio
|
||||
|
||||
namespace old_binary {
|
||||
|
||||
using Time = u32 [[format("old_binary::format_time")]];
|
||||
|
||||
fn swap_32bit(u32 value) {
|
||||
return ((value >> 16) & 0xFFFF) | ((value & 0xFFFF) << 16);
|
||||
};
|
||||
|
||||
fn format_time(u32 value) {
|
||||
return std::time::format(std::time::to_utc(swap_32bit(value)));
|
||||
};
|
||||
|
||||
using SwappedU32 = u32 [[transform("old_binary::swap_32bit"), format("old_binary::swap_32bit")]];
|
||||
|
||||
bitfield Mode {
|
||||
file_type : 4;
|
||||
suid : 1;
|
||||
sgid : 1;
|
||||
sticky : 1;
|
||||
r : 3;
|
||||
w : 3;
|
||||
x : 3;
|
||||
} [[left_to_right]];
|
||||
|
||||
struct CpioHeader {
|
||||
type::Oct<u16> magic;
|
||||
if (magic == be u16(0o070707))
|
||||
std::core::set_endian(std::mem::Endian::Big);
|
||||
else if (magic == le u16(0o070707))
|
||||
std::core::set_endian(std::mem::Endian::Little);
|
||||
else
|
||||
std::error("Invalid CPIO Magic!");
|
||||
|
||||
u16 dev;
|
||||
u16 ino;
|
||||
Mode mode;
|
||||
u16 uid;
|
||||
u16 gid;
|
||||
u16 nlink;
|
||||
u16 rdev;
|
||||
Time mtime;
|
||||
u16 namesize;
|
||||
SwappedU32 filesize;
|
||||
};
|
||||
|
||||
struct Cpio {
|
||||
CpioHeader header;
|
||||
char pathname[header.namesize % 2 == 0 ? header.namesize : header.namesize + 1];
|
||||
u8 data[header.filesize % 2 == 0 ? header.filesize : header.filesize + 1];
|
||||
|
||||
if (pathname == "TRAILER!!!\x00\x00")
|
||||
break;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
old_binary::Cpio cpio[while(true)] @ 0x00;
|
||||
70
patterns/fdt.pat
Normal file
70
patterns/fdt.pat
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma endian big
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/io.pat>
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
struct FDTHeader {
|
||||
type::Magic<"\xD0\x0D\xFE\xED"> magic;
|
||||
u32 totalsize;
|
||||
u32 off_dt_struct;
|
||||
u32 off_dt_strings;
|
||||
u32 off_mem_rsvmap;
|
||||
u32 version;
|
||||
u32 last_comp_version;
|
||||
u32 boot_cpuid_phys;
|
||||
u32 size_dt_strings;
|
||||
u32 size_dt_struct;
|
||||
};
|
||||
|
||||
struct AlignTo<auto Alignment> {
|
||||
padding[Alignment- ((($ - 1) % Alignment) + 1)];
|
||||
};
|
||||
|
||||
struct FDTReserveEntry {
|
||||
u64 address;
|
||||
type::Size<u64> size;
|
||||
|
||||
if (address == 0x00 && size == 0x00)
|
||||
break;
|
||||
};
|
||||
|
||||
enum FDTToken : u32 {
|
||||
FDT_BEGIN_NODE = 0x00000001,
|
||||
FDT_END_NODE = 0x00000002,
|
||||
FDT_PROP = 0x00000003,
|
||||
FDT_NOP = 0x00000004,
|
||||
FDT_END = 0x00000009
|
||||
};
|
||||
|
||||
struct FDTStructureBlock {
|
||||
FDTToken token;
|
||||
if (token == FDTToken::FDT_BEGIN_NODE) {
|
||||
char nodeName[];
|
||||
AlignTo<4>;
|
||||
} else if (token == FDTToken::FDT_END) {
|
||||
break;
|
||||
} else if (token == FDTToken::FDT_PROP) {
|
||||
u32 len;
|
||||
u32 nameoff;
|
||||
char value[len];
|
||||
AlignTo<4>;
|
||||
char name[] @ parent.header.off_dt_strings + nameoff;
|
||||
} else if (token == FDTToken::FDT_NOP || token == FDTToken::FDT_END_NODE) {
|
||||
// Nothing to do
|
||||
} else {
|
||||
std::error(std::format("Invalid token at address 0x{:02X}", addressof(token)));
|
||||
}
|
||||
};
|
||||
|
||||
struct FDT {
|
||||
FDTHeader header;
|
||||
std::assert(header.version == 17, "Unsupported format version");
|
||||
|
||||
FDTStructureBlock structureBlocks[while(true)] @ header.off_dt_struct;
|
||||
FDTReserveEntry reserveEntries[while(true)] @ header.off_mem_rsvmap;
|
||||
};
|
||||
|
||||
FDT fdt @ 0x00;
|
||||
153
patterns/gif.hexpat
Normal file
153
patterns/gif.hexpat
Normal file
@@ -0,0 +1,153 @@
|
||||
#include <std/mem.pat>
|
||||
|
||||
#pragma MIME image/gif
|
||||
|
||||
#pragma bitfield_order left_to_right
|
||||
|
||||
// gif89a
|
||||
|
||||
struct data_subblock_t {
|
||||
u8 block_size;
|
||||
u8 data_values[block_size];
|
||||
};
|
||||
|
||||
struct data_subblocks_t {
|
||||
data_subblock_t data[while (std::mem::read_unsigned($, 1) != 0x00)];
|
||||
u8 block_terminator; // 0x00
|
||||
} [[inline]];
|
||||
|
||||
struct header_t {
|
||||
char header[3];
|
||||
char version[3];
|
||||
};
|
||||
|
||||
bitfield lsd_fields_t {
|
||||
global_color_table_flag : 1;
|
||||
color_resolution : 3;
|
||||
sort_flag : 1;
|
||||
size_of_global_color_table : 3;
|
||||
} [[inline]];
|
||||
|
||||
struct logical_screen_descriptor_t {
|
||||
u16 width;
|
||||
u16 height;
|
||||
lsd_fields_t fields;
|
||||
u8 background_color_index;
|
||||
u8 pixel_aspect_ratio;
|
||||
};
|
||||
|
||||
struct color_table_entry_t {
|
||||
u8 red;
|
||||
u8 green;
|
||||
u8 blue;
|
||||
};
|
||||
|
||||
bitfield gce_fields_t {
|
||||
padding : 3;
|
||||
disposal_method : 3;
|
||||
user_input_flag : 1;
|
||||
transparent_color_flag : 1;
|
||||
} [[inline]];
|
||||
|
||||
struct graphic_coltrol_extension_t {
|
||||
u8 extension_introducer; // 0x21
|
||||
u8 graphic_control_label; // 0xf9
|
||||
u8 block_size;
|
||||
gce_fields_t fields;
|
||||
u16 delay_time;
|
||||
u8 transparent_color_index;
|
||||
u8 block_terminator;
|
||||
};
|
||||
|
||||
struct comment_extension_t {
|
||||
u8 extension_introducer; // 0x21
|
||||
u8 comment_label; // 0xfe
|
||||
data_subblocks_t comment_data;
|
||||
};
|
||||
|
||||
struct plaintext_extension_t {
|
||||
u8 extension_introducer; // 0x21
|
||||
u8 plain_text_label; // 0x01
|
||||
|
||||
u8 block_size; // 12
|
||||
u16 text_grid_left_position;
|
||||
u16 text_grid_top_position;
|
||||
u16 text_grid_width;
|
||||
u16 text_grid_height;
|
||||
u8 character_cell_width;
|
||||
u8 character_cell_height;
|
||||
u8 text_foreground_color_index;
|
||||
u8 text_background_color_index;
|
||||
data_subblocks_t plain_text_data;
|
||||
};
|
||||
|
||||
struct application_extension_t {
|
||||
u8 extension_introducer; // 0x21
|
||||
u8 extension_label; // 0xff
|
||||
|
||||
u8 block_size; // 11
|
||||
u8 application_identifier[8];
|
||||
u8 application_authentication_code[3];
|
||||
|
||||
data_subblocks_t data;
|
||||
};
|
||||
|
||||
bitfield id_fields_t {
|
||||
local_color_table : 1;
|
||||
interlace_flag : 1;
|
||||
sort_fla : 1;
|
||||
padding : 2;
|
||||
size_of_local_color_table : 3;
|
||||
} [[inline]];
|
||||
|
||||
struct image_descriptor_t {
|
||||
u8 image_separator; // 0x2c
|
||||
u16 image_left_position;
|
||||
u16 image_top_position;
|
||||
u16 image_width;
|
||||
u16 image_height;
|
||||
id_fields_t fields;
|
||||
};
|
||||
|
||||
struct table_based_image_t {
|
||||
u8 lzw_minimum_code_size;
|
||||
data_subblocks_t data;
|
||||
};
|
||||
|
||||
struct gif_block_t {
|
||||
if (std::mem::read_unsigned($, 1) == 0x21) {
|
||||
if (std::mem::read_unsigned($+1, 1) == 0x01) {
|
||||
plaintext_extension_t plaintext_extension;
|
||||
}
|
||||
else if (std::mem::read_unsigned($+1, 1) == 0xf9) {
|
||||
graphic_coltrol_extension_t graphic_coltrol_extension;
|
||||
}
|
||||
else if (std::mem::read_unsigned($+1, 1) == 0xfe) {
|
||||
comment_extension_t comment;
|
||||
} else {
|
||||
application_extension_t application_extension;
|
||||
}
|
||||
}
|
||||
else if (std::mem::read_unsigned($, 1) == 0x2c) {
|
||||
image_descriptor_t image_descriptor;
|
||||
if (image_descriptor.fields.local_color_table) {
|
||||
color_table_entry_t local_color_table[1<<(image_descriptor.fields.size_of_local_color_table + 1)];
|
||||
}
|
||||
table_based_image_t image;
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
struct gif_t {
|
||||
header_t header;
|
||||
logical_screen_descriptor_t logical_screen_descriptor;
|
||||
if (logical_screen_descriptor.fields.global_color_table_flag) {
|
||||
color_table_entry_t global_color_table[1<<(logical_screen_descriptor.fields.size_of_global_color_table + 1)];
|
||||
}
|
||||
|
||||
gif_block_t blocks[while (std::mem::read_unsigned($, 1) != 0x3b)];
|
||||
|
||||
u8 trailer; // 0x3b
|
||||
};
|
||||
|
||||
gif_t gif @ 0x00;
|
||||
|
||||
77
patterns/gzip.hexpat
Normal file
77
patterns/gzip.hexpat
Normal file
@@ -0,0 +1,77 @@
|
||||
#pragma MIME application/gzip
|
||||
|
||||
#include <type/time.pat>
|
||||
#include <type/size.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
bitfield Flags {
|
||||
FTEXT : 1;
|
||||
FHCRC : 1;
|
||||
FEXTRA : 1;
|
||||
FNAME : 1;
|
||||
FCOMMENT : 1;
|
||||
padding : 3;
|
||||
} [[right_to_left]];
|
||||
|
||||
bitfield ExtraFlags {
|
||||
padding : 1;
|
||||
maximumCompression : 1;
|
||||
fastestCompression : 1;
|
||||
padding : 5;
|
||||
};
|
||||
|
||||
enum CompressionMethod : u8 {
|
||||
Reserved = 0 ... 7,
|
||||
Deflate = 8
|
||||
};
|
||||
|
||||
enum OperatingSystemID : u8 {
|
||||
FATFileSystem = 0x00,
|
||||
Amiga = 0x01,
|
||||
VMS = 0x02,
|
||||
Unix = 0x03,
|
||||
VM_CMS = 0x04,
|
||||
AtariTOS = 0x05,
|
||||
HPFSFileSystem = 0x06,
|
||||
Macintosh = 0x07,
|
||||
ZSystem = 0x08,
|
||||
CP_M = 0x09,
|
||||
TOPS_20 = 0x0A,
|
||||
NTFSFileSystem = 0x0B,
|
||||
QDOS = 0x0C,
|
||||
AcordRISCOS = 0x0D,
|
||||
Unknown = 0xFF
|
||||
};
|
||||
|
||||
struct GZip {
|
||||
u16 signature;
|
||||
CompressionMethod compressionMethod;
|
||||
Flags flags;
|
||||
type::time32_t modificationTime;
|
||||
ExtraFlags extraFlags;
|
||||
OperatingSystemID operatingSystemId;
|
||||
|
||||
if (flags.FEXTRA) {
|
||||
u16 extraLength;
|
||||
u8 extraField[extraLength];
|
||||
}
|
||||
|
||||
if (flags.FNAME) {
|
||||
char originalFileName[];
|
||||
}
|
||||
|
||||
if (flags.FCOMMENT) {
|
||||
char comment[];
|
||||
}
|
||||
|
||||
if (flags.FHCRC) {
|
||||
u16 crc16;
|
||||
}
|
||||
|
||||
u8 data[while($ < std::mem::size() - 8)] [[sealed]];
|
||||
|
||||
u32 crc32;
|
||||
type::Size<u32> isize;
|
||||
};
|
||||
|
||||
GZip gzip @ 0x00;
|
||||
383
patterns/macho.hexpat
Normal file
383
patterns/macho.hexpat
Normal file
@@ -0,0 +1,383 @@
|
||||
#pragma MIME application/x-mach-binary
|
||||
|
||||
#include <type/size.pat>
|
||||
|
||||
enum Magic : u32 {
|
||||
_32BitMagic = 0xFEEDFACE,
|
||||
_64BitMagic = 0xFEEDFACF
|
||||
};
|
||||
|
||||
enum CpuType : u32 {
|
||||
VAX = 1,
|
||||
ROMP = 2,
|
||||
BS32032 = 4,
|
||||
BS32332 = 5,
|
||||
MC680x0 = 6,
|
||||
I386 = 7,
|
||||
X86_64 = CpuType::I386 | 0x100'0000,
|
||||
MIPS = 8,
|
||||
NS32532 = 9,
|
||||
HPPA = 11,
|
||||
ARM = 12,
|
||||
MC88000 = 13,
|
||||
SPARC = 14,
|
||||
I860 = be u32(15),
|
||||
I860_LITTLE = 16,
|
||||
RS6000 = 17,
|
||||
MC980000 = 18,
|
||||
POWERPC = 18,
|
||||
POWERPC64 = CpuType::POWERPC | 0x100'0000,
|
||||
VEO = 255
|
||||
};
|
||||
|
||||
enum SubCpuTypeVAX : u24 {
|
||||
ALL = 0,
|
||||
VAX780 = 1,
|
||||
VAX785 = 2,
|
||||
VAX750 = 3,
|
||||
VAX730 = 4,
|
||||
UVAXI = 5,
|
||||
UVAXII = 6,
|
||||
VAX8200 = 7,
|
||||
VAX8500 = 8,
|
||||
VAX8600 = 9,
|
||||
VAX8650 = 10,
|
||||
VAX8800 = 11,
|
||||
UVAXIII = 12
|
||||
};
|
||||
|
||||
enum SubCpuTypeROMP : u24 {
|
||||
ALL = 0,
|
||||
PC = 1,
|
||||
APC = 2,
|
||||
_135 = 3
|
||||
};
|
||||
|
||||
enum SubCpuType32XXX : u24 {
|
||||
ALL = 0,
|
||||
MMAX_DPC = 1,
|
||||
SQT = 2,
|
||||
MMAX_APC_FPU = 3,
|
||||
MMAX_APC_FPA = 4,
|
||||
MMAX_XPC = 5
|
||||
};
|
||||
|
||||
enum SubCpuTypeI386 : u24 {
|
||||
_386 = 3,
|
||||
_486 = 4,
|
||||
_486SX = SubCpuTypeI386::_486 + 128,
|
||||
_586 = 5,
|
||||
IntelPentium = 5 + (0 << 4),
|
||||
IntelPentiumPro = 6 + (1 << 4),
|
||||
IntelPentiumIIM3 = 6 + (3 << 4),
|
||||
IntelPentiumIIM5 = 6 + (5 << 4),
|
||||
IntelPentium4 = 10 + (0 << 4),
|
||||
};
|
||||
|
||||
enum SubCpuTypeMips : u24 {
|
||||
ALL = 0,
|
||||
R2300 = 1,
|
||||
R2600 = 2,
|
||||
R2800 = 3,
|
||||
R2000a = 4
|
||||
};
|
||||
|
||||
enum SubCpuType680x0 : u24 {
|
||||
ALL = 1,
|
||||
MC68030 = 1,
|
||||
MC68040 = 2,
|
||||
MC68030_Only = 3
|
||||
};
|
||||
|
||||
enum SubCpuTypeHPPA : u24 {
|
||||
ALL = 0,
|
||||
_7100 = 0,
|
||||
_7100LC = 1
|
||||
};
|
||||
|
||||
enum SubCpuTypeARM : u24 {
|
||||
ALL = 0,
|
||||
A500_ARCH = 1,
|
||||
A500 = 2,
|
||||
A440 = 3,
|
||||
M4 = 4,
|
||||
V4T = 5,
|
||||
V6 = 6,
|
||||
V5TEJ = 7,
|
||||
XSCALE = 8,
|
||||
V7 = 9,
|
||||
V7F = 10, /* Cortex A9 */
|
||||
V7S = 11, /* Swift */
|
||||
V7K = 12 /* Kirkwood40 */
|
||||
};
|
||||
|
||||
enum SubCpuTypeMC88000 : u24 {
|
||||
ALL = 0,
|
||||
MMAX_JPC = 1,
|
||||
MC88100 = 1,
|
||||
MC88110 = 2
|
||||
};
|
||||
|
||||
enum SubCpuTypeMC98000 : u24 {
|
||||
ALL = 0,
|
||||
MC98601 = 1
|
||||
};
|
||||
|
||||
enum SubCpuTypeI860 : u24 {
|
||||
ALL = 0,
|
||||
_860 = 1
|
||||
};
|
||||
|
||||
enum SubCpuTypeI860Little : u24 {
|
||||
ALL = 0 ... 1
|
||||
};
|
||||
|
||||
enum SubCpuTypeRS6000 : u24 {
|
||||
ALL = 0 ... 1
|
||||
};
|
||||
|
||||
enum SubCpuTypeSparc : u24 {
|
||||
ALL = 0,
|
||||
_260 = 1,
|
||||
_110 = 2
|
||||
};
|
||||
|
||||
enum SubCpuTypePowerPC : u24 {
|
||||
ALL = 0,
|
||||
_601 = 1,
|
||||
_602 = 2,
|
||||
_603 = 3,
|
||||
_603e = 4,
|
||||
_603ev = 5,
|
||||
_604 = 6,
|
||||
_604e = 7,
|
||||
_620 = 8,
|
||||
_750 = 9,
|
||||
_7400 = 10,
|
||||
_7450 = 11,
|
||||
_970 = 100
|
||||
};
|
||||
|
||||
enum SubCpuTypeVEO : u24 {
|
||||
_1 = 1,
|
||||
_2 = 2,
|
||||
_3 = 3,
|
||||
_4 = 4,
|
||||
ALL = SubCpuTypeVEO::_2
|
||||
};
|
||||
|
||||
bitfield Capabilities {
|
||||
padding : 7;
|
||||
lib64 : 1;
|
||||
} [[right_to_left]];
|
||||
|
||||
enum FileType : u32 {
|
||||
Object = 1,
|
||||
Execute = 2,
|
||||
FVMLib = 3,
|
||||
Core = 4,
|
||||
Preload = 5,
|
||||
DyLib = 6,
|
||||
DyLinker = 7,
|
||||
Bundle = 8,
|
||||
DyLibStub = 9,
|
||||
DSym = 10,
|
||||
KExtBundle = 11,
|
||||
};
|
||||
|
||||
bitfield Flags {
|
||||
noUndefs : 1;
|
||||
incrLink : 1;
|
||||
dyldLink : 1;
|
||||
binDatLoad : 1;
|
||||
prebound : 1;
|
||||
splitSegs : 1;
|
||||
lazyInit : 1;
|
||||
twoLevel : 1;
|
||||
forceFlat : 1;
|
||||
noMultiDefs : 1;
|
||||
noFixPrebinding : 1;
|
||||
prebindable : 1;
|
||||
allModsBound : 1;
|
||||
subSectionsViaSymbols : 1;
|
||||
canonical : 1;
|
||||
weakDefines : 1;
|
||||
bindsToWeak : 1;
|
||||
allowStackExecution : 1;
|
||||
rootSafe : 1;
|
||||
setuidSafe : 1;
|
||||
noReexportedDylibs : 1;
|
||||
pie : 1;
|
||||
deadStrippableDylib : 1;
|
||||
hasTlvDescriptors : 1;
|
||||
noHeapExecution : 1;
|
||||
appExtensionSafe : 1;
|
||||
nlistOutOfSyncWithDyldinof : 1;
|
||||
simSupport : 1;
|
||||
} [[right_to_left]];
|
||||
|
||||
struct Header {
|
||||
Magic magic;
|
||||
CpuType cpuType;
|
||||
if (cpuType == CpuType::VAX) SubCpuTypeVAX subCpuType;
|
||||
else if (cpuType == CpuType::ROMP) SubCpuTypeROMP subCpuType;
|
||||
else if (cpuType == CpuType::BS32032 || cpuType == CpuType::BS32332 || cpuType == CpuType::NS32532) SubCpuType32XXX subCpuType;
|
||||
else if (cpuType == CpuType::I386 || cpuType == CpuType::X86_64) SubCpuTypeI386 subCpuType;
|
||||
else if (cpuType == CpuType::MIPS) SubCpuTypeMips subCpuType;
|
||||
else if (cpuType == CpuType::HPPA) SubCpuTypeHPPA subCpuType;
|
||||
else if (cpuType == CpuType::ARM) SubCpuTypeARM subCpuType;
|
||||
else if (cpuType == CpuType::MC88000) SubCpuTypeMC88000 subCpuType;
|
||||
else if (cpuType == CpuType::MC98000) SubCpuTypeMC98000 subCpuType;
|
||||
else if (cpuType == CpuType::I860 || cpuType == CpuType::I860_LITTLE) SubCpuTypeI860 subCpuType;
|
||||
else if (cpuType == CpuType::SPARC) SubCpuTypeSparc subCpuType;
|
||||
else if (cpuType == CpuType::POWERPC || cpuType == CpuType::POWERPC64) SubCpuTypePowerPC subCpuType;
|
||||
else if (cpuType == CpuType::VEO) SubCpuTypeVEO subCpuType;
|
||||
else u24 subCpuType;
|
||||
Capabilities capabilities;
|
||||
FileType fileType;
|
||||
u32 numCommands;
|
||||
type::Size<u32> sizeOfCommands;
|
||||
Flags flags;
|
||||
|
||||
if (magic == Magic::_64BitMagic) padding[sizeof(u32)];
|
||||
};
|
||||
|
||||
enum Command : u32 {
|
||||
ReqDyLd = 0x8000'0000,
|
||||
|
||||
Segment = 0x01,
|
||||
SymTab = 0x02,
|
||||
SymSeg = 0x03,
|
||||
Thread = 0x04,
|
||||
UnixThread = 0x05,
|
||||
LoadFVMLib = 0x06,
|
||||
IdFVMLib = 0x07,
|
||||
Ident = 0x08,
|
||||
FVMFile = 0x09,
|
||||
PrePage = 0x0A,
|
||||
DySymTab = 0x0B,
|
||||
LoadDyLib = 0x0C,
|
||||
IdDyLib = 0x0D,
|
||||
LoadDyLinker = 0x0E,
|
||||
IdDyLinker = 0x0F,
|
||||
PreboundDyLib = 0x10,
|
||||
Routines = 0x11,
|
||||
SubFramework = 0x12,
|
||||
SubUmbrella = 0x13,
|
||||
SubClient = 0x14,
|
||||
SubLibrary = 0x15,
|
||||
TwoLevelHints = 0x16,
|
||||
PrebindCksum = 0x17,
|
||||
LoadWeakDyLib = 0x18 | Command::ReqDyLd,
|
||||
Segment64 = 0x19,
|
||||
Routines64 = 0x1A,
|
||||
UUID = 0x1B,
|
||||
RPath = 0x1C | 0x8000'0000,
|
||||
CodeSignature = 0x1D,
|
||||
SegmentSplitInfo = 0x1E,
|
||||
ReExportDyLib = 0x1F | Command::ReqDyLd,
|
||||
LazyLoadDyLib = 0x20,
|
||||
EncryptionInfo = 0x21,
|
||||
DyLdInfo = 0x22,
|
||||
DyLdInfoOnly = 0x22 | Command::ReqDyLd,
|
||||
LoadUpwardDyLib = 0x23 | Command::ReqDyLd,
|
||||
VersionMinMacOSX = 0x24,
|
||||
VersionMinIPhoneOS = 0x25,
|
||||
FunctionStarts = 0x26,
|
||||
DyLdEnvironment = 0x27,
|
||||
Main = 0x28 | Command::ReqDyLd,
|
||||
DataInCode = 0x29,
|
||||
SourceVersion = 0x2A,
|
||||
DyLibCodeSignDRS = 0x2B
|
||||
};
|
||||
|
||||
struct CommandUUID {
|
||||
u128 uuid;
|
||||
};
|
||||
|
||||
struct Section {
|
||||
char sectionName[16];
|
||||
char segmentName[16];
|
||||
u32 address;
|
||||
type::Size<u32> size;
|
||||
u32 offset;
|
||||
u32 align;
|
||||
u32 reloff;
|
||||
u32 numRelocs;
|
||||
u32 flags;
|
||||
padding[8];
|
||||
|
||||
if (offset > 0)
|
||||
u8 data[size] @ offset [[sealed]];
|
||||
};
|
||||
|
||||
struct CommandSegment {
|
||||
char segmentName[16];
|
||||
u32 vmAddress;
|
||||
type::Size<u32> vmSize;
|
||||
u32 fileOffset;
|
||||
type::Size<u32> fileSize;
|
||||
u32 maxProtection;
|
||||
u32 initProtection;
|
||||
u32 numSections;
|
||||
u32 flags;
|
||||
|
||||
Section sections[numSections];
|
||||
|
||||
if (fileOffset > 0)
|
||||
u8 data[fileSize] @ fileOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct Section64 {
|
||||
char sectionName[16];
|
||||
char segmentName[16];
|
||||
u64 address;
|
||||
type::Size<u64> size;
|
||||
u32 offset;
|
||||
u32 align;
|
||||
u32 reloff;
|
||||
u32 numRelocs;
|
||||
u32 flags;
|
||||
padding[12];
|
||||
|
||||
if (offset > 0)
|
||||
u8 data[size] @ offset [[sealed]];
|
||||
};
|
||||
|
||||
struct CommandSegment64 {
|
||||
char segmentName[16];
|
||||
u64 vmAddress;
|
||||
type::Size<u64> vmSize;
|
||||
u64 fileOffset;
|
||||
type::Size<u64> fileSize;
|
||||
u32 maxProtection;
|
||||
u32 initProtection;
|
||||
u32 numSections;
|
||||
u32 flags;
|
||||
|
||||
Section64 sections[numSections];
|
||||
|
||||
if (fileOffset > 0)
|
||||
u8 data[fileSize] @ fileOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct LoadCommand {
|
||||
Command command;
|
||||
type::Size<u32> commandSize;
|
||||
|
||||
if (command == Command::UUID)
|
||||
CommandUUID data;
|
||||
else if (command == Command::Segment)
|
||||
CommandSegment data;
|
||||
else if (command == Command::Segment64)
|
||||
CommandSegment64 data;
|
||||
else
|
||||
u8 data[commandSize - 8] [[sealed]];
|
||||
};
|
||||
|
||||
struct MachO {
|
||||
Header header;
|
||||
LoadCommand loadCommands[header.numCommands];
|
||||
};
|
||||
|
||||
MachO macho @ 0x00;
|
||||
70
patterns/nbt.hexpat
Normal file
70
patterns/nbt.hexpat
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <std/sys.pat>
|
||||
|
||||
#pragma endian big
|
||||
|
||||
enum Tag : u8 {
|
||||
End = 0,
|
||||
Byte = 1,
|
||||
Short = 2,
|
||||
Int = 3,
|
||||
Long = 4,
|
||||
Float = 5,
|
||||
Double = 6,
|
||||
ByteArray = 7,
|
||||
String = 8,
|
||||
List = 9,
|
||||
Compound = 10,
|
||||
IntArray = 11,
|
||||
LongArray = 12
|
||||
};
|
||||
|
||||
using Element;
|
||||
|
||||
struct Value {
|
||||
if (parent.tag == Tag::Byte)
|
||||
s8 value;
|
||||
else if (parent.tag == Tag::Short)
|
||||
s16 value;
|
||||
else if (parent.tag == Tag::Int)
|
||||
s32 value;
|
||||
else if (parent.tag == Tag::Long)
|
||||
s64 value;
|
||||
else if (parent.tag == Tag::Float)
|
||||
float value;
|
||||
else if (parent.tag == Tag::Double)
|
||||
double value;
|
||||
else if (parent.tag == Tag::ByteArray) {
|
||||
s32 arrayLength;
|
||||
s8 value[arrayLength] [[sealed]];
|
||||
} else if (parent.tag == Tag::String) {
|
||||
u16 stringLength;
|
||||
char value[stringLength];
|
||||
} else if (parent.tag == Tag::List) {
|
||||
Tag tag;
|
||||
s32 listLength;
|
||||
Value values[listLength] [[static]];
|
||||
} else if (parent.tag == Tag::Compound) {
|
||||
Element values[while(true)];
|
||||
} else {
|
||||
std::error(std::format("Invalid tag {:02X}", TypeTag));
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
struct Element {
|
||||
Tag tag;
|
||||
if (tag == Tag::End)
|
||||
break;
|
||||
else {
|
||||
|
||||
u16 nameLength;
|
||||
char name[nameLength];
|
||||
|
||||
Value value;
|
||||
}
|
||||
};
|
||||
|
||||
struct NBT {
|
||||
Element element[while(true)] [[inline]];
|
||||
};
|
||||
|
||||
NBT nbt @ 0x00;
|
||||
264
patterns/ne.hexpat
Normal file
264
patterns/ne.hexpat
Normal file
@@ -0,0 +1,264 @@
|
||||
#include <std/mem.pat>
|
||||
|
||||
#pragma bitfield_order right_to_left
|
||||
|
||||
struct DOSHeader {
|
||||
char signature[2];
|
||||
u16 lastPageSize;
|
||||
u16 numberOfPages;
|
||||
u16 relocations;
|
||||
u16 headerSizeInParagraphs;
|
||||
u16 minimumAllocatedParagraphs;
|
||||
u16 maximumAllocatedParagraphs;
|
||||
u16 initialSSValue;
|
||||
u16 initialRelativeSPValue;
|
||||
u16 checksum;
|
||||
u16 initialRelativeIPValue;
|
||||
u16 initialCSValue;
|
||||
u16 relocationsTablePointer;
|
||||
u16 overlayNumber;
|
||||
u8 overlayInformation[0x20];
|
||||
u32 neHeaderPointer;
|
||||
};
|
||||
|
||||
u16 dosMessageOffset;
|
||||
u16 pointedCodeOffset;
|
||||
|
||||
fn finddosmessage() {
|
||||
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
|
||||
if (std::mem::read_unsigned($+i, 1) == 0xBA) { // MOV instruction
|
||||
dosMessageOffset = std::mem::read_unsigned($+i+1, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn findpointingcode() {
|
||||
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
|
||||
if (std::mem::read_unsigned($+i, 1) == 0xE8) { // CALL instruction
|
||||
pointedCodeOffset = std::mem::read_unsigned($+i+1, 2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
fn isdosdata(char c) {
|
||||
return c == 0x0D || c == '$';
|
||||
};
|
||||
|
||||
struct DOSStub {
|
||||
if (findpointingcode()) {
|
||||
u8 pointingCode[3];
|
||||
u8 code[while(std::mem::read_unsigned($, 1) != 0x00)] @ addressof(this) + pointedCodeOffset + 3;
|
||||
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
|
||||
char data[while(std::mem::read_string($-1, 1) != "$")];
|
||||
}
|
||||
else {
|
||||
finddosmessage();
|
||||
if (dosMessageOffset > 0) {
|
||||
u8 code[while($ != addressof(this) + dosMessageOffset)];
|
||||
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
|
||||
char data[while(std::mem::read_string($-1, 1) != "$")];
|
||||
}
|
||||
else {
|
||||
char code[while(std::mem::read_unsigned($, 1) != 0x00)];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FileHeader {
|
||||
DOSHeader dosHeader;
|
||||
DOSStub dosStub @ dosHeader.headerSizeInParagraphs * 16;
|
||||
};
|
||||
|
||||
FileHeader fileHeader @ 0x00;
|
||||
|
||||
enum DGroupType : u8 {
|
||||
NoAutoData,
|
||||
SingleData,
|
||||
MultipleData,
|
||||
Null
|
||||
};
|
||||
|
||||
fn formatDGroupType(u8 value) {
|
||||
DGroupType dgroup = value;
|
||||
|
||||
return dgroup;
|
||||
};
|
||||
|
||||
enum AppType : u8 {
|
||||
None,
|
||||
Fullscreen,
|
||||
WinPMCompatible,
|
||||
UsesWinPM
|
||||
};
|
||||
|
||||
fn formatAppType(u8 value) {
|
||||
AppType app = value;
|
||||
|
||||
return app;
|
||||
};
|
||||
|
||||
bitfield ProgramFlags {
|
||||
dGroupType : 2 [[format("formatDGroupType")]];
|
||||
globalInitialization : 1;
|
||||
protectedModeOnly : 1;
|
||||
instructions86 : 1;
|
||||
instructions286 : 1;
|
||||
instructions386 : 1;
|
||||
instructionsX87 : 1;
|
||||
};
|
||||
|
||||
bitfield ApplicationFlags {
|
||||
applicationType : 2 [[format("formatAppType")]];
|
||||
padding : 1;
|
||||
os2Application : 1;
|
||||
reserved : 1;
|
||||
imageError : 1;
|
||||
nonConforming : 1;
|
||||
dll : 1;
|
||||
};
|
||||
|
||||
enum OSType : u8 {
|
||||
Unknown = 0x00,
|
||||
OS2 = 0x01,
|
||||
Win16 = 0x02,
|
||||
DOS4 = 0x03,
|
||||
Win32 = 0x04,
|
||||
BorlandOSServices = 0x05,
|
||||
PharlapDOSExtenderOS2 = 0x81,
|
||||
PharlapDOSExtenderWindows = 0x82
|
||||
};
|
||||
|
||||
bitfield OS2EXEFlags {
|
||||
longFilename : 1;
|
||||
protectedMode : 1;
|
||||
proportionalFonts : 1;
|
||||
gangloadArea : 1;
|
||||
};
|
||||
|
||||
struct NEHeader {
|
||||
char signature[2];
|
||||
u8 majorLinkerVersion;
|
||||
u8 minorLinkerVersion;
|
||||
u16 entryTableOffset;
|
||||
u16 entryTableLength;
|
||||
u32 fileCRC;
|
||||
ProgramFlags programFlags;
|
||||
ApplicationFlags appFlags;
|
||||
u16 autoDataSegmentIndex;
|
||||
u16 initHeapSize;
|
||||
u16 initStackSize;
|
||||
u32 entryPoint;
|
||||
u32 initialStackPointer;
|
||||
u16 segmentCount;
|
||||
u16 moduleReferenceCount;
|
||||
u16 nonResidentNamesTableSize;
|
||||
u16 segmentTableOffset;
|
||||
u16 resourceTableOffset;
|
||||
u16 residentNamesTableOffset;
|
||||
u16 moduleReferenceTableOffset;
|
||||
u16 importedNamesTableOffset;
|
||||
u8 *nonResidentNamesTablePointer[nonResidentNamesTableSize] : u32;
|
||||
u16 moveableEntryCount;
|
||||
u16 fileAlignmentSizeShiftCount;
|
||||
u16 resourceCount;
|
||||
OSType targetOS;
|
||||
OS2EXEFlags os2ExeFlags;
|
||||
u16 thunksReturnOffset;
|
||||
u16 segmentReferenceThunksOffset;
|
||||
u16 minimumCodeSwapAreaSize;
|
||||
u8 expectedMinorWindowsVersion;
|
||||
u8 expectedMajorWindowsVersion;
|
||||
};
|
||||
|
||||
NEHeader neHeader @ fileHeader.dosHeader.neHeaderPointer;
|
||||
|
||||
bitfield SegmentTableFlags {
|
||||
dataSegment : 1;
|
||||
typeMask : 2;
|
||||
padding : 1;
|
||||
moveable : 1;
|
||||
padding : 1;
|
||||
preloaded : 1;
|
||||
padding : 1;
|
||||
containsRelocationInfo : 1;
|
||||
padding : 1;
|
||||
discardPriority : 4;
|
||||
} [[right_to_left]];
|
||||
|
||||
struct SegmentTable {
|
||||
u16 segmentDataPointer;
|
||||
u16 segmentLength;
|
||||
SegmentTableFlags segmentTableFlags;
|
||||
u16 minimumAllocationSize;
|
||||
};
|
||||
|
||||
SegmentTable segmentTable[neHeader.segmentCount] @ addressof(neHeader) + neHeader.segmentTableOffset;
|
||||
|
||||
bitfield BlockFlags {
|
||||
padding : 4;
|
||||
moveable : 1;
|
||||
shared : 1;
|
||||
preload : 1;
|
||||
padding : 9;
|
||||
};
|
||||
|
||||
struct ResourceTypeInformationBlock {
|
||||
u8 *resourcePointer : u16;
|
||||
u16 resourceLength;
|
||||
BlockFlags flags;
|
||||
u16 resourceID;
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
struct ResourceRecord {
|
||||
u16 typeID;
|
||||
u16 numberOfResources;
|
||||
u32 reserved;
|
||||
ResourceTypeInformationBlock blocks[numberOfResources];
|
||||
};
|
||||
|
||||
struct ResourceTable {
|
||||
u16 alignmentShiftCount;
|
||||
ResourceRecord records[neHeader.resourceTableEntryCount];
|
||||
u8 stringLength;
|
||||
char string[stringLength];
|
||||
};
|
||||
|
||||
ResourceTable resourceTable[neHeader.resourceCount] @ addressof(neHeader) + neHeader.resourceTableOffset;
|
||||
|
||||
struct ResidentName {
|
||||
u8 stringLength;
|
||||
char string[stringLength];
|
||||
u16 ordinalNumber;
|
||||
};
|
||||
|
||||
ResidentName residentNameTable[while($+1 < addressof(neHeader) + neHeader.moduleReferenceTableOffset)] @ addressof(neHeader) + neHeader.residentNamesTableOffset;
|
||||
|
||||
struct ModuleReference {
|
||||
u16 moduleNameOffset;
|
||||
};
|
||||
|
||||
ModuleReference moduleReferenceTable[neHeader.moduleReferenceCount] @ addressof(neHeader) + neHeader.moduleReferenceTableOffset;
|
||||
|
||||
struct ImportedNameTable {
|
||||
u8 stringLength;
|
||||
char string[stringLength];
|
||||
};
|
||||
|
||||
ImportedNameTable importedNameTable[while($ < addressof(neHeader) + neHeader.entryTableOffset)] @ addressof(neHeader) + neHeader.importedNamesTableOffset;
|
||||
|
||||
enum EntryDataType : u8 {
|
||||
Unused,
|
||||
Fixed = 0x01 ... 0xFE,
|
||||
Moveable
|
||||
};
|
||||
|
||||
struct EntryTable {
|
||||
u8 entryCount;
|
||||
EntryDataType segmentIndicator;
|
||||
};
|
||||
|
||||
EntryTable entryTable[neHeader.entryTableLength/2] @ addressof(neHeader) + neHeader.entryTableOffset;
|
||||
30
patterns/pbzx.hexpat
Normal file
30
patterns/pbzx.hexpat
Normal file
@@ -0,0 +1,30 @@
|
||||
// pbzx compression stream
|
||||
// Used by Apple on .xip files and OTA updates.
|
||||
//
|
||||
// Copyright (c) 2022 Nicolás Alvarez <nicolas.alvarez@gmail.com>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
#pragma endian big
|
||||
|
||||
#define SHOW_DATA 0
|
||||
|
||||
struct Chunk {
|
||||
u64 uncompressed_size;
|
||||
u64 compressed_size;
|
||||
if (SHOW_DATA) {
|
||||
u8 data[compressed_size] [[sealed]];
|
||||
} else {
|
||||
padding[compressed_size];
|
||||
}
|
||||
};
|
||||
|
||||
struct PBZX {
|
||||
char magic[4];
|
||||
u64 chunk_size;
|
||||
Chunk chunks[while(!std::mem::eof())];
|
||||
};
|
||||
|
||||
PBZX pbzx @ 0;
|
||||
52
patterns/pcx.hexpat
Normal file
52
patterns/pcx.hexpat
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma MIME application/x-pcx
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
enum Encoding : u8 {
|
||||
NoEncoding = 0x00,
|
||||
RunLengthEncoding = 0x01
|
||||
};
|
||||
|
||||
enum PaletteType : u16 {
|
||||
MonochromeOrColorInformation = 0x01,
|
||||
GrayscaleInformation = 0x02
|
||||
};
|
||||
|
||||
enum Version : u8 {
|
||||
V2_5 = 0x00,
|
||||
V2_8WithPalette = 0x02,
|
||||
V2_8_WithoutPalette = 0x03,
|
||||
PaintbrushForWindows = 0x04,
|
||||
V3_0 = 0x05
|
||||
};
|
||||
|
||||
struct Header {
|
||||
u8 magic;
|
||||
Version version;
|
||||
Encoding encoding;
|
||||
u8 bitsPerPixel;
|
||||
u16 xMin, yMin;
|
||||
u16 xMax, yMax;
|
||||
u16 hdpi, vdpi;
|
||||
};
|
||||
|
||||
struct RGB8 {
|
||||
u8 r, g, b;
|
||||
} [[sealed, color(std::format("{:02X}{:02X}{:02X}", this.r, this.g, this.b))]];
|
||||
|
||||
struct Palette {
|
||||
RGB8 color[16];
|
||||
};
|
||||
|
||||
struct PCX {
|
||||
Header header;
|
||||
Palette palette;
|
||||
padding[1];
|
||||
u8 numPlanes;
|
||||
u16 bytesPerLine;
|
||||
PaletteType paletteType;
|
||||
u16 hres, vres;
|
||||
padding[54];
|
||||
};
|
||||
|
||||
PCX pcx @ 0x00;
|
||||
38
patterns/pfs0.hexpat
Normal file
38
patterns/pfs0.hexpat
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
#include <std/core.pat>
|
||||
|
||||
struct FileEntry {
|
||||
u64 dataOffset;
|
||||
type::Size<u64> dataSize;
|
||||
u32 nameOffset;
|
||||
padding[4];
|
||||
};
|
||||
|
||||
struct String {
|
||||
char value[];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
type::Magic<"PFS0"> magic;
|
||||
u32 numFiles;
|
||||
type::Size<u32> stringTableSize;
|
||||
padding[4];
|
||||
|
||||
FileEntry fileEntryTable[numFiles];
|
||||
String strings[numFiles];
|
||||
};
|
||||
|
||||
struct File {
|
||||
char name[] @ addressof(parent.header.strings) + parent.header.fileEntryTable[std::core::array_index()].nameOffset;
|
||||
u8 data[parent.header.fileEntryTable[std::core::array_index()].dataSize] @ parent.header.fileEntryTable[std::core::array_index()].dataOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct PFS0 {
|
||||
Header header;
|
||||
|
||||
File files[header.numFiles];
|
||||
};
|
||||
|
||||
PFS0 pfs0 @ 0x00;
|
||||
@@ -87,33 +87,6 @@ fn text_len() {
|
||||
return len;
|
||||
};
|
||||
|
||||
enum BlendOp: u8 {
|
||||
Source = 0x0,
|
||||
Over
|
||||
};
|
||||
|
||||
enum DisposeOp: u8 {
|
||||
None = 0x0,
|
||||
Background,
|
||||
Previous
|
||||
};
|
||||
|
||||
struct fctl_t {
|
||||
u32 sequence_no [[comment("Sequence №")]];
|
||||
u32 width [[comment("Frame width")]];
|
||||
u32 height [[comment("Frame height")]];
|
||||
u32 xoff;
|
||||
u32 yoff;
|
||||
u16 delay_num [[comment("Frame delay fraction numerator")]];
|
||||
u16 delay_den [[comment("Frame delay fraction denominator")]];
|
||||
DisposeOp dispose_op;
|
||||
BlendOp blend_op;
|
||||
};
|
||||
|
||||
struct fdat_t {
|
||||
u32 sequence_no;
|
||||
};
|
||||
|
||||
struct itxt_t {
|
||||
char keyword[];
|
||||
u8 compression_flag;
|
||||
@@ -171,15 +144,15 @@ struct chunk_t {
|
||||
sRGB srgb;
|
||||
} else if (name == pHYs_k) {
|
||||
phys_t phys;
|
||||
} else if (type == acTL_k) {
|
||||
} else if (name == acTL_k) {
|
||||
actl_t actl [[comment("Animation control chunk")]];
|
||||
} else if (type == fcTL_k) {
|
||||
} else if (name == fcTL_k) {
|
||||
fctl_t fctl [[comment("Frame control chunk")]];
|
||||
} else if (type == iTXt_k) {
|
||||
} else if (name == iTXt_k) {
|
||||
itxt_t text;
|
||||
} else if (type == gAMA_k) {
|
||||
} else if (name == gAMA_k) {
|
||||
u32 gamma [[name("image gamma"), comment("4 byte unsigned integer representing gamma times 100000")]];
|
||||
} else if (type == iCCP_k) {
|
||||
} else if (name == iCCP_k) {
|
||||
iccp_t iccp;
|
||||
} else if (name == tEXt_k) {
|
||||
text_t text;
|
||||
|
||||
115
patterns/sit5.hexpat
Normal file
115
patterns/sit5.hexpat
Normal file
@@ -0,0 +1,115 @@
|
||||
// Based on https://github.com/mietek/theunarchiver/wiki/StuffIt5Format and https://github.com/ParksProjets/Maconv/blob/master/docs/stuffit/Stuffit_v5.md
|
||||
|
||||
#pragma endian big
|
||||
#pragma MIME application/x-stuffit
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/time.pat>
|
||||
|
||||
namespace v5 {
|
||||
|
||||
bitfield Flags1 {
|
||||
padding : 1;
|
||||
folder : 1;
|
||||
encrypted : 1;
|
||||
padding : 5;
|
||||
} [[left_to_right]];
|
||||
|
||||
bitfield Flags2 {
|
||||
padding : 7;
|
||||
resource_fork : 1;
|
||||
padding : 8;
|
||||
} [[left_to_right]];
|
||||
|
||||
using MacOSHFSPlusDate = u32 [[format("v5::format_macos_date")]];
|
||||
|
||||
fn format_macos_date(MacOSHFSPlusDate date) {
|
||||
return std::time::format(std::time::to_utc(date - 2082844800));
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char magic[0x50];
|
||||
u32 unknown1;
|
||||
u32 archiveSize;
|
||||
u32 entriesOffset;
|
||||
u32 unknown2;
|
||||
};
|
||||
|
||||
struct EntryHeader {
|
||||
u32 magic;
|
||||
u8 version;
|
||||
u8 unknown1;
|
||||
u16 headerSize;
|
||||
u8 unknown2;
|
||||
Flags1 flags;
|
||||
MacOSHFSPlusDate creationDate, modificationDate;
|
||||
u32 prevEntryOffset, nextEntryOffset, parentEntryOffset;
|
||||
u16 nameSize;
|
||||
u16 headerChecksum;
|
||||
|
||||
u32 dataForkUncompressedLength, dataForkCompressedLength;
|
||||
u16 dataForkChecksum;
|
||||
u16 unknown3;
|
||||
};
|
||||
|
||||
enum CompressionMethod : u8 {
|
||||
None = 0x00, // No compression
|
||||
Rle90 = 0x01, // Run length encoding
|
||||
Compress = 0x02, // Compress LZW algorithm, 14 bit max code length, block mode
|
||||
StuffIt3 = 0x03, // Simple Huffman encoding for individual bytes
|
||||
StuffIt5 = 0x05, // LZAH
|
||||
StuffIt8 = 0x08, // Miller-Wegman
|
||||
StuffIt13 = 0x0D, // LZSS and Huffman
|
||||
Stuffit14 = 0x0E, // Unknown
|
||||
StuffItArsenic = 0x0F // BWT and arithmetic coding
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
EntryHeader header;
|
||||
if (header.flags.folder) {
|
||||
u16 numFiles;
|
||||
|
||||
if (header.dataForkUncompressedLength)
|
||||
std::print("Folder entry {} is special!", std::core::array_index());
|
||||
} else {
|
||||
CompressionMethod compressionMethod;
|
||||
}
|
||||
|
||||
u8 passwordDataLength;
|
||||
u8 passwordInformation[passwordDataLength];
|
||||
char fileName[header.nameSize];
|
||||
u16 commentSize;
|
||||
u16 unknown2;
|
||||
char comment[commentSize];
|
||||
|
||||
if (!header.flags.folder) {
|
||||
Flags2 flags;
|
||||
u16 unknown3;
|
||||
char fileType[4];
|
||||
u32 fileCreator;
|
||||
u16 macOSFinderFlags;
|
||||
u32 unknown4;
|
||||
u32 unknown5;
|
||||
u8 unknown6[6];
|
||||
|
||||
if (header.version == 1)
|
||||
u32 unknown7;
|
||||
|
||||
u8 compressedData[header.dataForkCompressedLength] [[sealed]];
|
||||
|
||||
if (header.nextEntryOffset == 0x00)
|
||||
break;
|
||||
else
|
||||
$ = header.nextEntryOffset;
|
||||
}
|
||||
};
|
||||
|
||||
struct StuffIt {
|
||||
Header header;
|
||||
|
||||
Entry entries[while(true)] @ header.entriesOffset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
v5::StuffIt stuffIt @ 0x00;
|
||||
88
patterns/tar.hexpat
Normal file
88
patterns/tar.hexpat
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma MIME application/tar
|
||||
#pragma MIME application/x-tar
|
||||
|
||||
#pragma endian little
|
||||
|
||||
#include <std/string.pat>
|
||||
#include <std/time.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
|
||||
#define HEADER "ustar "
|
||||
#define NULL "\x00"
|
||||
|
||||
fn octal_to_decimal(str value) {
|
||||
return std::string::parse_int(value, 8);
|
||||
};
|
||||
|
||||
fn get_time(str time) {
|
||||
std::time::EpochTime epochtime = octal_to_decimal(time);
|
||||
std::time::Time localtime = std::time::to_local(epochtime);
|
||||
return std::time::format(localtime, "%c");
|
||||
};
|
||||
|
||||
enum typeflagenum : char {
|
||||
regular = '0',
|
||||
also_regular = '\x00',
|
||||
link_to_another_file_already_archived = '1',
|
||||
symbolic_link = '2',
|
||||
character_special_device = '3',
|
||||
block_special_device = '4',
|
||||
directory = '5',
|
||||
fifo_special_file = '6',
|
||||
reserved = '7'
|
||||
};
|
||||
|
||||
struct posix_header {
|
||||
char name[100] [[name("file name")]];
|
||||
char mode[8] [[name("file mode")]];
|
||||
char uid[8] [[name("user id of the file")]];
|
||||
char gid[8] [[name("group if of the file")]];
|
||||
char size[12] [[name("size of the file in octal")]];
|
||||
char mtime[12] [[name("modified time of file in epoch time")]];
|
||||
char chksum[8] [[name("checksum")]];
|
||||
typeflagenum typeflag [[name("type of file")]];
|
||||
char linkname[100] [[name("name of link")]];
|
||||
char magic[6] [[name("magic bytes that identifies the 'file version'")]];
|
||||
char version[2] [[name("version (also used with magic bytes)")]];
|
||||
char uname[32] [[name("username of the owner of the file")]];
|
||||
char gname[32] [[name("group name of the owner of the file")]];
|
||||
char devmajor[8] [[name("major device numbers")]];
|
||||
char devminor[8] [[name("minor device numbers")]];
|
||||
char prefix[155] [[name("filename prefix")]];
|
||||
char reserved[12] [[name("reserved")]];
|
||||
};
|
||||
|
||||
|
||||
struct tar {
|
||||
posix_header header_raw;
|
||||
char file[octal_to_decimal(header_raw.size)];
|
||||
|
||||
std::print("-" * 50);
|
||||
std::print("File Name: {}", header_raw.name);
|
||||
std::print("File Permissions: {}" , header_raw.mode);
|
||||
std::print("UID: {}", header_raw.uid);
|
||||
std::print("GUID: {}", header_raw.gid);
|
||||
std::print("Size: {} bytes", octal_to_decimal(header_raw.size));
|
||||
std::print("Modified Time: {}", get_time(header_raw.mtime));
|
||||
std::print("Checksum: {}", header_raw.chksum);
|
||||
std::print("Type of File: {}", header_raw.typeflag);
|
||||
std::print("Magic Bytes: {}", header_raw.magic);
|
||||
std::print("Version: {}", header_raw.version);
|
||||
std::print("uname: {}", header_raw.uname);
|
||||
std::print("gname: {}", header_raw.gname);
|
||||
std::print("devmajor: {}", header_raw.devmajor);
|
||||
std::print("devminor: {}", header_raw.devminor);
|
||||
std::print("prefix: {}", header_raw.prefix);
|
||||
|
||||
char empty[while (std::mem::read_string($, 1) == NULL && !std::mem::eof())];
|
||||
if (std::mem::eof()) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
char magic[6] @ 0x00000101 [[hidden]];
|
||||
std::assert(magic == HEADER, "Magic bytes are not correct! Perhaps wrong file?");
|
||||
|
||||
tar tar[while(!std::mem::eof())] @ 0x000;
|
||||
24
patterns/wad.hexpat
Normal file
24
patterns/wad.hexpat
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
enum WADType : char {
|
||||
Internal = 'I',
|
||||
Patch = 'P'
|
||||
};
|
||||
|
||||
struct FileLump {
|
||||
u32 filePos;
|
||||
type::Size<u32> size;
|
||||
char name[8];
|
||||
|
||||
u8 data[size] @ filePos [[sealed]];
|
||||
};
|
||||
|
||||
struct WAD {
|
||||
WADType type;
|
||||
type::Magic<"WAD"> identification;
|
||||
u32 numLumps;
|
||||
FileLump *infoTable[numLumps] : u32;
|
||||
};
|
||||
|
||||
WAD wad @ 0x00;
|
||||
97
patterns/xci.hexpat
Normal file
97
patterns/xci.hexpat
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <std/core.pat>
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
#define PAGE_SIZE 0x200
|
||||
|
||||
enum RomSize : u8 {
|
||||
_1GB = 0xFA,
|
||||
_2GB = 0xF8,
|
||||
_4GB = 0xF0,
|
||||
_8GB = 0xE0,
|
||||
_16GB = 0xE1,
|
||||
_32GB = 0xE2
|
||||
};
|
||||
|
||||
bitfield Index {
|
||||
titleKeyDecIndex : 4;
|
||||
kekIndex : 4;
|
||||
};
|
||||
|
||||
bitfield Flags {
|
||||
autoBoot : 1;
|
||||
historyErase : 1;
|
||||
repairTool : 1;
|
||||
differentRegionCupToTerraDevice : 1;
|
||||
differentRegionCupToGlobalDevice : 1;
|
||||
padding : 2;
|
||||
hasNewCardHeader : 1;
|
||||
};
|
||||
|
||||
struct SelSec {
|
||||
u16 t1, t2;
|
||||
};
|
||||
|
||||
struct CardHeader {
|
||||
u8 headerSignature[0x100];
|
||||
type::Magic<"HEAD"> magic;
|
||||
u32 romAreaStartPageAddress;
|
||||
u32 backupAreaStartPageAddress;
|
||||
Index index [[inline]];
|
||||
RomSize romSize;
|
||||
u8 cardHeaderVersion;
|
||||
Flags flags;
|
||||
u64 packageId;
|
||||
u32 validDataEndAddress;
|
||||
padding[4];
|
||||
u8 iv[0x10];
|
||||
u64 partitionFsHeaderAddress;
|
||||
type::Size<u64> partitionFsHeaderSize;
|
||||
u8 partitionFsHeaderHash[0x20];
|
||||
u8 initialDataHash[0x20];
|
||||
SelSec selSec;
|
||||
u32 selT1Key;
|
||||
u32 selKey;
|
||||
u32 limArea;
|
||||
|
||||
u8 cardHeaderEncryptedData[0x70];
|
||||
};
|
||||
|
||||
struct FileEntry {
|
||||
u64 dataOffset;
|
||||
type::Size<u64> dataSize;
|
||||
u32 fileNameOffset;
|
||||
type::Size<u32> hashedRegionSize;
|
||||
padding[8];
|
||||
u8 hash[0x20];
|
||||
};
|
||||
|
||||
struct String {
|
||||
char string[];
|
||||
};
|
||||
|
||||
struct File {
|
||||
String fileName @ addressof(parent.stringTable) + parent.fileEntryTable[std::core::array_index()].fileNameOffset;
|
||||
u8 data[parent.fileEntryTable[std::core::array_index()].dataSize] @ addressof(parent.stringTable) + sizeof(parent.stringTable) + parent.fileEntryTable[std::core::array_index()].dataOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct PartitionFs {
|
||||
type::Magic<"HFS0"> magic;
|
||||
u32 fileCount;
|
||||
type::Size<u32> stringTableSize;
|
||||
padding[4];
|
||||
FileEntry fileEntryTable[fileCount];
|
||||
String stringTable[while($ < (addressof(fileEntryTable) + sizeof(fileEntryTable) + stringTableSize))];
|
||||
|
||||
File files[fileCount];
|
||||
};
|
||||
|
||||
struct XCI {
|
||||
CardHeader header;
|
||||
|
||||
PartitionFs x @ header.romAreaStartPageAddress * PAGE_SIZE;
|
||||
|
||||
};
|
||||
|
||||
XCI xci @ 0x00;
|
||||
@@ -1,46 +1,60 @@
|
||||
#pragma MIME application/zip
|
||||
|
||||
#include <std/mem.pat>
|
||||
#include <std/math.pat>
|
||||
|
||||
struct EndOfCentralDirectory{
|
||||
u32 headerSignature [[color("00000000")]];
|
||||
u16 diskNum [[comment("Number of this disk "), name("Disk Number")]];
|
||||
u16 diskStart [[comment("Disk where central directory starts "), name("Central Directory Disk Number")]];
|
||||
u16 CDRCount [[comment("Number of central directory records on this disk"), name("Central Directory Entries")]];
|
||||
u16 CentralDirectoryRecordCount [[comment("Total number of entries in the central directory"), name("Total Central Directory Entries")]];
|
||||
u32 CDSize [[comment("Size of central directory (bytes)"), name("Central Directory Size")]];
|
||||
u32 CDOffset [[comment("Offset of start of central directory, relative to start of archive"), name("Central Directory Offset")]];
|
||||
u16 commentLength [[color("00000000")]];
|
||||
char coment[commentLength] [[name("Comment")]];
|
||||
struct EndOfCentralDirectory {
|
||||
u32 headerSignature [[color("00000000")]];
|
||||
u16 diskNum [[comment("Number of this disk "), name("Disk Number")]];
|
||||
u16 diskStart [[comment("Disk where central directory starts "), name("Central Directory Disk Number")]];
|
||||
u16 CDRCount [[comment("Number of central directory records on this disk"), name("Central Directory Entries")]];
|
||||
u16 CentralDirectoryRecordCount [[comment("Total number of entries in the central directory"), name("Total Central Directory Entries")]];
|
||||
u32 CDSize [[comment("Size of central directory (bytes)"), name("Central Directory Size")]];
|
||||
u32 CDOffset [[comment("Offset of start of central directory, relative to start of archive"), name("Central Directory Offset")]];
|
||||
u16 commentLength [[color("00000000")]];
|
||||
char coment[commentLength] [[name("Comment")]];
|
||||
};
|
||||
|
||||
EndOfCentralDirectory fileInfo @ std::mem::find_sequence(0,0x50,0x4B,0x05,0x06) [[name("End of Central Directory Record")]];
|
||||
|
||||
struct CentralDirectoryEntry{
|
||||
|
||||
fn find_eocd() {
|
||||
// If there is no zip comment, which is the common case,
|
||||
// the end-of-central-directory record will be 22 bytes long
|
||||
// at the end of the file; check if size-22 has the signature.
|
||||
if (std::mem::read_unsigned(std::mem::size()-22, 4, std::mem::Endian::Little) == 0x06054B50) {
|
||||
return std::mem::size()-22;
|
||||
} else {
|
||||
// If it's not there, then there's probably a zip comment;
|
||||
// search the last 64KB of the file for the signature.
|
||||
// This is not entirely reliable, since the signature could
|
||||
// randomly appear in compressed data before the actual EOCD,
|
||||
// but it should be good enough...
|
||||
u128 last64k = std::math::max(0, std::mem::size()-65536-22);
|
||||
return std::mem::find_sequence_in_range(0, last64k, std::mem::size(), 0x50,0x4B,0x05,0x06);
|
||||
}
|
||||
};
|
||||
|
||||
struct CentralDirectoryFileHeader{
|
||||
u32 headerSignature [[color("00000000")]];
|
||||
u16 versionMade [[comment("Version file made by")]];
|
||||
u16 versionExtract [[comment("Minimum version needed to extract")]];
|
||||
u16 generalFlag [[comment("General purpose bit flag"), color("00000000")]];
|
||||
u16 compressionMethod;
|
||||
u16 fileLastModifyTime [[comment("File last modification time")]];
|
||||
u16 fileLastModifyDate [[comment("File last modification date")]];
|
||||
u32 crc32 [[comment("CRC-32 of uncompressed data"), color("00000000")]];
|
||||
u32 compressedSize;
|
||||
u32 uncompressedSize;
|
||||
u16 fileNameLength [[color("00000000")]];
|
||||
u16 extraFieldLength [[color("00000000")]];
|
||||
u16 fileCommentLength [[color("00000000")]];
|
||||
u16 diskNumber [[comment("Disk number where file starts ")]];
|
||||
u16 internalFileAttributes;
|
||||
u32 externalFileAttributes;
|
||||
u32 fileOffset [[comment("Relative offset of local file header. This is the number of bytes between the start of the first disk on which the file occurs, and the start of the local file header. This allows software reading the central directory to locate the position of the file inside the ZIP file.")]];
|
||||
char fileName[fileNameLength];
|
||||
u8 extraField[extraFieldLength];
|
||||
char comment[fileCommentLength];
|
||||
EndOfCentralDirectory fileInfo @ find_eocd() [[name("End of Central Directory Record")]];
|
||||
|
||||
struct CentralDirectoryFileHeader {
|
||||
u32 headerSignature [[color("00000000")]];
|
||||
u16 versionMade [[comment("Version file made by")]];
|
||||
u16 versionExtract [[comment("Minimum version needed to extract")]];
|
||||
u16 generalFlag [[comment("General purpose bit flag"), color("00000000")]];
|
||||
u16 compressionMethod;
|
||||
u16 fileLastModifyTime [[comment("File last modification time")]];
|
||||
u16 fileLastModifyDate [[comment("File last modification date")]];
|
||||
u32 crc32 [[comment("CRC-32 of uncompressed data"), color("00000000")]];
|
||||
u32 compressedSize;
|
||||
u32 uncompressedSize;
|
||||
u16 fileNameLength [[color("00000000")]];
|
||||
u16 extraFieldLength [[color("00000000")]];
|
||||
u16 fileCommentLength [[color("00000000")]];
|
||||
u16 diskNumber [[comment("Disk number where file starts")]];
|
||||
u16 internalFileAttributes;
|
||||
u32 externalFileAttributes;
|
||||
u32 fileOffset [[comment("Offset of local file header, relative to the start of the first disk on which the file occurs.")]];
|
||||
char fileName[fileNameLength];
|
||||
u8 extraField[extraFieldLength];
|
||||
char comment[fileCommentLength];
|
||||
};
|
||||
|
||||
CentralDirectoryFileHeader centralDirHeaders[fileInfo.CDRCount] @ (fileInfo.CDOffset) [[name("Files")]];
|
||||
|
||||
115
patterns/zstd.hexpat
Normal file
115
patterns/zstd.hexpat
Normal file
@@ -0,0 +1,115 @@
|
||||
// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
|
||||
|
||||
#pragma MIME application/zstd
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
#define ZSTD_MAGIC_NUMBER 0xFD2FB528
|
||||
|
||||
bitfield frame_header_descriptor_t {
|
||||
frame_content_size_flag : 2;
|
||||
single_segment_flag : 1;
|
||||
unused_bit : 1;
|
||||
reserved_bit : 1;
|
||||
content_checksum_flag : 1;
|
||||
dictionary_id_flag : 2;
|
||||
} [[left_to_right]];
|
||||
|
||||
bitfield window_descriptor_t {
|
||||
exponent : 5;
|
||||
mantissa : 3;
|
||||
} [[left_to_right]];
|
||||
|
||||
fn window_size(window_descriptor_t window_descriptor) {
|
||||
u64 window_log = 10 + window_descriptor.exponent;
|
||||
u64 window_base = 1 << window_log;
|
||||
u64 window_add = (window_base / 8) * window_descriptor.mantissa;
|
||||
u64 window_size = window_base + window_add;
|
||||
return window_size;
|
||||
};
|
||||
|
||||
struct frame_header_t {
|
||||
frame_header_descriptor_t frame_header_descriptor;
|
||||
|
||||
if (!frame_header_descriptor.single_segment_flag){
|
||||
window_descriptor_t window_descriptor;
|
||||
}
|
||||
|
||||
if (frame_header_descriptor.dictionary_id_flag == 1) {
|
||||
le u8 dictionary_id;
|
||||
}
|
||||
else if (frame_header_descriptor.dictionary_id_flag == 2) {
|
||||
le u16 dictionary_id;
|
||||
}
|
||||
else if (frame_header_descriptor.dictionary_id_flag == 3) {
|
||||
le u32 dictionary_id;
|
||||
}
|
||||
|
||||
if (frame_header_descriptor.frame_content_size_flag == 0) { // 0
|
||||
if (frame_header_descriptor.single_segment_flag) {
|
||||
le u8 content_size;
|
||||
}
|
||||
}
|
||||
else if (frame_header_descriptor.frame_content_size_flag == 1) {
|
||||
le u16 content_size;
|
||||
}
|
||||
else if (frame_header_descriptor.frame_content_size_flag == 2) {
|
||||
le u32 content_size;
|
||||
}
|
||||
else {
|
||||
le u64 content_size;
|
||||
}
|
||||
};
|
||||
|
||||
bitfield block_header_t {
|
||||
block_size : 21;
|
||||
block_type : 2;
|
||||
last_block : 1;
|
||||
} [[left_to_right]];
|
||||
|
||||
enum block_type : u8 {
|
||||
raw_block = 0,
|
||||
rle_block = 1,
|
||||
compressed_block = 2,
|
||||
reserved = 3
|
||||
};
|
||||
|
||||
struct data_block_t {
|
||||
block_header_t block_header;
|
||||
|
||||
if (block_header.last_block) {
|
||||
last_block_flag = true;
|
||||
}
|
||||
|
||||
if (block_header.block_type == block_type::raw_block) {
|
||||
le u8 block_content[block_header.block_size];
|
||||
}
|
||||
else if (block_header.block_type == block_type::rle_block) {
|
||||
le u8 block_content[1];
|
||||
}
|
||||
else if (block_header.block_type == block_type::compressed_block) {
|
||||
le u8 block_content[block_header.block_size];
|
||||
}
|
||||
else {
|
||||
std::error("The data block seems to be corrupted!");
|
||||
}
|
||||
};
|
||||
|
||||
struct content_checksum_t {
|
||||
le u32 xxh64_hash;
|
||||
};
|
||||
|
||||
struct zstd_frame_t {
|
||||
le u32 magic_number;
|
||||
std::assert(magic_number == ZSTD_MAGIC_NUMBER, "Invalid magic number!");
|
||||
frame_header_t frame_header;
|
||||
data_block_t data_block[while(!last_block_flag)];
|
||||
if (frame_header.frame_header_descriptor.content_checksum_flag) {
|
||||
content_checksum_t content_checksum;
|
||||
}
|
||||
};
|
||||
|
||||
bool last_block_flag = false;
|
||||
zstd_frame_t zstd_frame @ 0x00;
|
||||
@@ -15,7 +15,7 @@ add_executable(includes_test
|
||||
)
|
||||
|
||||
target_include_directories(includes_test PRIVATE include)
|
||||
target_link_libraries(includes_test libpl)
|
||||
target_link_libraries(includes_test PRIVATE libpl fmt)
|
||||
|
||||
set_target_properties(includes_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
|
||||
@@ -34,9 +34,11 @@ int main(int argc, char **argv) {
|
||||
return false;
|
||||
};
|
||||
|
||||
runtime.setDataSource([&](pl::u64 address, pl::u8 *data, size_t size) {
|
||||
pl::core::err::E0011.throwError("Include files should never read from memory directly!");
|
||||
}, 0x00, 0x100000);
|
||||
runtime.setDataSource(0x00, 0x100000,
|
||||
[&](pl::u64 address, pl::u8 *data, size_t size) {
|
||||
pl::core::err::E0011.throwError("Include files should never read from memory directly!");
|
||||
}
|
||||
);
|
||||
runtime.setDangerousFunctionCallHandler([]{ return true; });
|
||||
runtime.setIncludePaths({ includePath });
|
||||
|
||||
@@ -73,4 +75,4 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(MAGIC libmagic>=5.39)
|
||||
|
||||
target_include_directories(magic_test PRIVATE include)
|
||||
target_link_libraries(magic_test libpl magic)
|
||||
target_link_libraries(magic_test PRIVATE libpl magic fmt)
|
||||
|
||||
set_target_properties(magic_test PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ add_executable(patterns_tests
|
||||
)
|
||||
|
||||
target_include_directories(patterns_tests PRIVATE include)
|
||||
target_link_libraries(patterns_tests libpl)
|
||||
target_link_libraries(patterns_tests PRIVATE libpl fmt)
|
||||
|
||||
set_target_properties(patterns_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
|
||||
@@ -41,10 +41,12 @@ int main(int argc, char **argv) {
|
||||
{
|
||||
constexpr auto DummyPragmaHandler = [](const auto&, const auto&){ return true; };
|
||||
|
||||
runtime.setDataSource([&](pl::u64 address, pl::u8 *data, size_t size) {
|
||||
testFile.seek(address);
|
||||
testFile.readBuffer(data, size);
|
||||
}, 0x00, testFile.getSize());
|
||||
runtime.setDataSource(0x00, testFile.getSize(),
|
||||
[&](pl::u64 address, pl::u8 *data, size_t size) {
|
||||
testFile.seek(address);
|
||||
testFile.readBuffer(data, size);
|
||||
}
|
||||
);
|
||||
runtime.setDangerousFunctionCallHandler([]{ return true; });
|
||||
runtime.setIncludePaths({ includePath });
|
||||
runtime.addPragma("MIME", DummyPragmaHandler);
|
||||
@@ -74,4 +76,4 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
BIN
tests/patterns/test_data/ar.hexpat.ar
Normal file
BIN
tests/patterns/test_data/ar.hexpat.ar
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/bmp.hexpat.bmp
Normal file
BIN
tests/patterns/test_data/bmp.hexpat.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
tests/patterns/test_data/chm.hexpat.chm
Normal file
BIN
tests/patterns/test_data/chm.hexpat.chm
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/coff.hexpat.obj
Normal file
BIN
tests/patterns/test_data/coff.hexpat.obj
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/cpio.hexpat.cpio
Normal file
BIN
tests/patterns/test_data/cpio.hexpat.cpio
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/fdt.hexpat.dtb
Normal file
BIN
tests/patterns/test_data/fdt.hexpat.dtb
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/flac.hexpat.flac
Normal file
BIN
tests/patterns/test_data/flac.hexpat.flac
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/gif.hexpat.gif
Normal file
BIN
tests/patterns/test_data/gif.hexpat.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
BIN
tests/patterns/test_data/gzip.hexpat.gz
Normal file
BIN
tests/patterns/test_data/gzip.hexpat.gz
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/macho.hexpat.o
Normal file
BIN
tests/patterns/test_data/macho.hexpat.o
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/nbt.hexpat.nbt
Normal file
BIN
tests/patterns/test_data/nbt.hexpat.nbt
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/ne.hexpat.exe
Normal file
BIN
tests/patterns/test_data/ne.hexpat.exe
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/nro.hexpat.nro
Normal file
BIN
tests/patterns/test_data/nro.hexpat.nro
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/ogg.hexpat.ogg
Normal file
BIN
tests/patterns/test_data/ogg.hexpat.ogg
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/pcx.hexpat.pcx
Normal file
BIN
tests/patterns/test_data/pcx.hexpat.pcx
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/png.hexpat.png
Normal file
BIN
tests/patterns/test_data/png.hexpat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
tests/patterns/test_data/protobuf.hexpat.bin
Normal file
BIN
tests/patterns/test_data/protobuf.hexpat.bin
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/stl.hexpat.stl
Normal file
BIN
tests/patterns/test_data/stl.hexpat.stl
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/tar.hexpat.tar
Normal file
BIN
tests/patterns/test_data/tar.hexpat.tar
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/tga.hexpat.tga
Normal file
BIN
tests/patterns/test_data/tga.hexpat.tga
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/wav.hexpat.wav
Normal file
BIN
tests/patterns/test_data/wav.hexpat.wav
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/zip.hexpat.zip
Normal file
BIN
tests/patterns/test_data/zip.hexpat.zip
Normal file
Binary file not shown.
BIN
tests/patterns/test_data/zstd.hexpat.zst
Normal file
BIN
tests/patterns/test_data/zstd.hexpat.zst
Normal file
Binary file not shown.
Reference in New Issue
Block a user