Compare commits

..

114 Commits

Author SHA1 Message Date
EvelynTSMG
5942897c29 patterns/ffx: Pull in latest updates (#209)
* Add Final Fantasy X patterns

* Update README

* Fix: github dum

* Add Bastion patterns

* git: update submodules

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2023-12-22 14:02:37 +01:00
utkumaden
a7e6209791 patterns: Added gITF pattern(#205)
* Create gltf.hexpat

Added glTF binary file pattern.

* Add a test file for the glTF pattern.

* Renamed the test file to fit the pattern file name.

* Fixed typo in documentation.
2023-12-07 17:09:25 +01:00
EvelynTSMG
294f69fa36 patterns: Add Bastion patterns (#207)
* Add Final Fantasy X patterns

* Update README

* Fix: github dum

* Add Bastion patterns

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2023-12-07 16:38:32 +01:00
gmestanley
1ea12cd4bd patterns/pe: Bringing over the massively improved version of pe.hexpat (#204)
* Add files via upload

* Update README.md

Added nes.hexpat to list of hex patterns

* Fix indenting of hex patterns list

Moved nes.hexpat below NE.hexpat

* Update README.md

Fixed indenting of PP pattern file's description being wrong

* Added x-msdownload MIME type to PE description

* Made indenting & code of ips.hexpat better

* Improvements to gb.hexpat

* Urgent fix to ips.hexpat

* Urgent fix to gb.hexpat

* Massive pe.hexpat improvement

* Replaced virtualDifference with relativeVirtualDifference

* Fixing unnecessary pattern_limit
2023-12-07 16:36:50 +01:00
Surasia
8129504dcb patterns/hinf_luas: Added pattern for reading HavokScript 5.1 Bytecode from Halo Infinite (#203)
* patterns/hinf_luas: Added pattern for reading HavokScript 5.1 Bytecode from Halo Infinite

* Parses Header and Structures of the parent tag
* Reads Bytecode types and arguments
* Reads Constants and Debug Info
* Reads Referenced Tags in the File

* readme: fix relative link
2023-12-07 16:36:27 +01:00
klirktag
22e30cfef9 patterns/mp4: Add STBL-box children (#202)
add STBL-box children
2023-12-07 16:36:07 +01:00
EvelynTSMG
9b819cf392 patterns: Add Final Fantasy X patterns (#197)
* Add Final Fantasy X patterns

* Update README

* Fix: github dum
2023-11-20 11:54:56 +01:00
klirktag
3277821153 patterns/mp4: Support mp4a and avc1 codec boxes (#195)
add support for mp4a and avc1 codec boxes, and sample-time-to-sample box
2023-11-15 22:26:10 +01:00
paxcut
f23dbbb565 includes/std: Fixed std::string::replace not replacing sequences correctly (#198)
fix:  [Bug] std::string::replace("aa", "aa", "") returns "a" #1408
2023-11-15 22:25:34 +01:00
Surasia
52f7d9e77a patterns/hinf_bitmap: Added pattern for parsing Halo Infinite bitmap files (#194)
* patterns/hinf_bitmap: Added pattern for parsing Halo Infinite bitmap files

* Parses the header of all Halo Infinite files which includes related "dependencies", datablocks, structure references
* Read bitmap sequence data, including bitmap index, complete index, sprite info
* Find the width/height and DDS Format of the raw texture, which can then be parsed into usable DDS textures
* Locates raw DDS block info

* Nulled out the DDS section of the bitmap
2023-11-14 00:20:32 +01:00
klirktag
99df77baf2 patterns/mp4: Add childbox support for STBL boxes (#192)
* find childboxes in stbl

* add implementation for SampleDescriptionBox
2023-11-14 00:06:50 +01:00
klirktag
d7b0819ff0 patterns/mp4: Make handler_type into a char[4], which reflects how it is used (#193)
make handler_type into a char[4], which reflects how it is used
2023-11-14 00:06:31 +01:00
Nik
70f491d2fa includes/type: Fixed formatting of time_t values in big endian patterns 2023-11-12 22:18:46 +01:00
Hugo
08680a6544 patterns/bplist: Added pattern file for Apple’s binary property list format (bplist) (#190)
* Added pattern file for Apple’s binary property list format (bplist)

* renamed some stuff and improved error messages

* added error handling for object size special case (0x0F)
2023-11-12 01:02:50 +01:00
Ange Albertini
23bc36c4bd patterns/selinux: Detailed SELinux config bitfield (#188) 2023-11-06 16:30:53 +01:00
Ange Albertini
8ae778944d patterns/se: Increased array limit (#187)
Increased array limit
2023-11-01 20:19:10 +01:00
klirktag
7e6a5d3bfa patterns/mp4: Added stbl box (#185) 2023-10-29 19:54:23 +01:00
Hugo
27e55d2e6d patterns/zip: Added parsing of extra field (#182)
* zip pattern: Improved fallback method for finding eocd. Added test data to cover this edge case

* zip pattern: added parsing of extra field
2023-10-29 19:47:11 +01:00
Benjamin Gilbert
e0a602c10a patterns/jpeg: Small improvements (#184)
* patterns/jpeg: exclude EOI marker from SOS image data

* patterns/jpeg: use type::Magic for magic numbers

* patterns/jpeg: add RGB component IDs

* patterns/jpeg: add struct for APP14 marker

* patterns/jpeg: add definition for COM marker

* patterns/jpeg: add some format_read() for better legibility
2023-10-29 19:46:51 +01:00
AdventureT
8748646016 patterns/CrashLvl: Update Crash Back in Time level format (#186)
* Working on new Version

* Needs testing

* Updated CrashLvl script to support version 0.94c

* Update README.md

* Added TestData and author to script

* Delete tests/patterns/test_data/CrashLvl.hexpat.bin
2023-10-29 19:46:28 +01:00
iTrooz
4a52ee4cf8 patterns: add UEFI Boot Entry pattern (#183)
add uefi_boot_entry pattern
2023-10-24 23:04:49 +02:00
iTrooz
e517e3534b patterns: fix description pragmas (#181) 2023-10-24 17:25:43 +02:00
DmitriLeon2000
edd0aa9a2f patterns: Add .fas and .was pattern files (Oska DeskMates) (#176)
* Add .fas and .was pattern files (Oska DeskMates)

* Update .was pattern file

* Update .was/.wa3 pattern file

* Update README.md

* Update README.md

* Update .fas & .was pattern files

* Update README.md

* Update fas_oskasoftware_old.hexpat

* Added WAS test file

* Update WAS test file

* Update was_oskasoftware.hexpat
2023-10-24 07:35:38 +02:00
Hugo
a992d1ba92 patterns/zip: Improved fallback method for finding eocd (#177)
zip pattern: Improved fallback method for finding eocd. Added test data to cover this edge case
2023-10-24 07:35:02 +02:00
leen
6fbdcac556 patterns/ip: Fix payload size when ip header or tcp header has options in ip.hexpat (#178) 2023-10-24 07:34:35 +02:00
itsmeow
47fce1628f patterns: Add ARIA2 Control format (#179) 2023-10-24 07:33:56 +02:00
Nik
9b152ae560 includes/std: Fixed doc comment of std::math::atan2 2023-10-22 21:25:14 +02:00
Nik
6b136b7fc6 includes/std: Fixed std::math::atan2 not taking correct arguments 2023-10-22 21:23:51 +02:00
gmestanley
93494a19a4 patterns: Better code + credit given for ips.hexpat & better readme (#174)
* Add files via upload

* Update README.md

Added nes.hexpat to list of hex patterns

* Fix indenting of hex patterns list

Moved nes.hexpat below NE.hexpat

* Update README.md

Fixed indenting of PP pattern file's description being wrong

* Added x-msdownload MIME type to PE description

* Made indenting & code of ips.hexpat better

* Improvements to gb.hexpat

* Urgent fix to ips.hexpat

* Urgent fix to gb.hexpat
2023-10-15 21:21:19 +02:00
H0L0
4fd710e23e patterns/flac: Fix SEEKTABLE metadata block (#173)
Add SEEKTABLE to blocktype check
2023-10-15 21:19:34 +02:00
Nik
44842dc44b includes/std: Added std::mem::set_section_size (#175) 2023-10-15 21:15:12 +02:00
HalfInner
056035c540 patterns/zip: Add parsing local file header with minor adjustment (#172)
patterns/zip: add parsing local file header, and another adjustmenst

Add missing parsing for local file headers
Add compression method
Minor adjustments: removed black colors, marked magic ids
2023-10-06 12:20:30 +02:00
Diego
5ad8e15afc patterns/shp: Added ESRI patterns (#170)
* add .shp and .shx patterns

* add tests
2023-10-06 12:20:11 +02:00
Nik
39c4d11404 patterns/uefi: Remove invalid MIME pragma 2023-10-05 08:54:59 +02:00
Benjamin Gilbert
815bd5f7f3 git: Minor readme fixes (#168) 2023-09-26 16:51:31 +02:00
Benjamin Gilbert
917b05a9f2 patterns: Add DICOM (#162)
DICOM files specify a "transfer syntax" which defines the image
compression format, the encoding rules for the entire file, and any
special-case encoding rules for particular fields.  Many transfer syntaxes
have common design features, but a transfer syntax is allowed to use
completely custom encoding rules, and need not be publicly documented.

Explicitly reject transfer syntaxes we know we don't support: implicit VR
(uncommon), explicit VR big-endian (deprecated), deflate-compressed.
In all other cases, follow some general rules and hope it works out.

The large lookup functions were generated by a script, but I haven't
included the code here, since its input is hand-massaged data copied from
HTML tables.

Add a JPEG WSI test case from the WG26 2021 hackathon (CC0 license) and a
synthetic LE Explicit VLP case produced with img2dcm.
2023-09-26 16:51:02 +02:00
brliron
46a2cef993 patterns: Added Android VBMeta image pattern (#169) 2023-09-26 14:03:24 +02:00
Nik
bca25b1a78 includes/hex: Fixed duplicate variable name in hex::core::get_selection() function
Fixes #167
2023-09-25 07:22:06 +02:00
Benjamin Gilbert
7ecd6d87dd patterns/tiff: Support BigTIFF and tiled TIFF; bugfixes and cleanups (#159)
* patterns/tiff: show TIFF tag name/number in DirectoryEntry array

Don't require unfolding the array entry to see what tag it contains.

* patterns/tiff: show IFD number in IFD list

* patterns/tiff: add JPEGTables tag; correct name of ICC Profile tag

* patterns/tiff: add TIFFRational type

Rationals, uniquely, are primitives with two fields.  Add a struct to
represent this, rather than inlining them.

* patterns/tiff: use correct types for fields smaller than 4 bytes

Small fields are always left-aligned in the 4-byte Value Offset.  On
little-endian TIFFs we currently cheat this by declaring a 32-bit value
and letting little-endianness handle the semantics.  However, this adds
some extra conditionals, and misrepresents the resulting field as 32 bits.
Drop the cheat.

* patterns/tiff: add ValueOffset abstraction

We were using the field type to make assumptions about whether the Value
Offset is a Value or an Offset, which is incorrect.  If the Count
multiplied by the field size is larger than 4, the field is an Offset;
otherwise it's a Value.

Add display sugar for single-element arrays to avoid extra nesting.

* patterns/tiff: drop dead code

get_ifds_offsets() and BIG/LITTLE aren't used at all.  get_total_IFDs()
is only used for declaring the length of TIFFFile.IFDs, and isn't needed
because IFDs are structured as a linked list.

* patterns/tiff: drop set_endian()

The call in TIFFFile is redundant.  Drop both calls and open-code the
check at the top level, before executing any code.  The BigTIFF check
will eventually be added alongside this one.

Fail if we don't recognize the magic number.

* patterns/tiff: minor cleanups

* patterns/tiff: drop strip offset/byte count arrays from struct IFD

They're redundant with the fields in the DirectoryEntry array.  Also
they're buggy: they assume the field Value Offsets are always offsets,
which isn't true for single-strip IFDs, and they ignore a partial last
strip in multiple-strip IFDs.

* patterns/tiff: rewrite strip array generation

We're making extra work for ourselves by avoiding the type system.  Also,
by calculating the number of strips we expect rather than the number of
strips we actually have, we're miscounting and omitting any partial last
strip.

Instead, read the strip offsets and byte counts directly from the
IFDEntry array.

* patterns/tiff: add ImageData array for tiled IFDs

* patterns/tiff: increase variable widths for BigTIFF

Use 64-bit temporary variables for values that can be 64 bits in BigTIFF.

* patterns/tiff: support BigTIFF

* tests/patterns/test_data: add more TIFF tests
2023-09-24 20:04:20 +02:00
dn-ln
bf0d96db5f patterns/id3: Fix the error No variable named 'n' found. (#160) 2023-09-24 20:03:49 +02:00
paxcut
705900d38b includes/std: Fixed std::string::replace (#163)
The submitted fix may have been a work in progress version instead of the tested solution I intended to submit. Hopefully this time I'll get it right.
2023-09-24 19:58:04 +02:00
gmestanley
734afdf500 patterns: Added .nes pattern file (#166)
* Add files via upload

* Update README.md

Added nes.hexpat to list of hex patterns

* Fix indenting of hex patterns list

Moved nes.hexpat below NE.hexpat
2023-09-24 19:57:20 +02:00
Benjamin Gilbert
c0c117ac19 tests/patterns: support multiple test files for a pattern (#161)
Allow either a single test file in tests/patterns/${pattern}.hexpat.${ext},
as we do now, or multiple files in tests/patterns/${pattern}.hexpat/*.

Closes #158.
2023-09-10 09:56:25 +02:00
paxcut
7fba66a444 includes/std: Fixed std::string::replace truncating output incorrectly (#157) 2023-09-10 09:40:29 +02:00
Yury Ershov
8eed75d783 patterns/bson: Support for multiple documents per file (#156)
* BSON support multiple documents per file

BSON files can contain consecutive documents glued one after another. An example of these is MongoDB FTDC metrics export.

[`bsondump`](https://github.com/mongodb/mongo-tools/blob/master/bsondump/bsondump.go) can unpack this type of BSON documents.

* Add accidentally deleted lines
2023-09-10 09:39:32 +02:00
Kenichi Saita
81f4978656 patterns/vhdx: Various improvements (#154)
* Replaced right_to_left to bitfield_order

* Fixed type of ParentLocatorEntry (char -> char16)

* Fixed item address of MetadataTableEntry

* Improved RegionTableEntry# Please enter the commit message for your changes. Lines starting
2023-09-10 09:39:04 +02:00
iTrooz
b6e0557a1d patterns: put author and description inside each pattern (#155) 2023-08-28 12:32:23 +02:00
gmestanley
ba14dd0cb2 patterns: Adding IPS pattern and fixed PE magic file (#153)
* Update pe.hexpat

New improvement

* Add ips.hexpat via upload

* Add ips.hexpat.ips via upload

* Added IPS to README

* Mentioned Windows in portable_executable_magic
2023-08-27 00:38:30 +02:00
MatrixEditor
86f93dfdaf patterns: Added Ubiquiti firmware pattern (#145)
* Ubiquiti firmware pattern

* Added padding and crc32 fields

* Added unit test file

+ Renamed fields in partition struct
2023-08-16 23:28:01 +02:00
Justus Garbe
001900e3c2 patterns/pyc: Add a pattern for pyc files
Change name
2023-08-15 09:30:19 +02:00
Nik
6baae92553 includes/std: Added missing mem library include in ptr libary 2023-08-04 22:56:03 +02:00
Jason Shirk
520f9bcb22 patterns/pe: Fix DebugDirectory version field types (#146) 2023-08-04 01:14:49 +02:00
vikke1234
44b0392b78 patterns/fdt: Unflatten FDT (#144)
In order to have a better time viewing FDTs in the visualizer
scanner will now unflatten the FDT.

It could still be improved slightly by modifying FDTProps to
make their values be `u32`s and possibly detect whether they
should be u64s.
2023-08-04 01:11:20 +02:00
Nik
df2bd4e3f9 git: Run PatternLanguage webpage CI 2023-07-29 12:12:33 +02:00
Nik
7723cf55c6 patterns: Fixed wrong extensions for some patterns 2023-07-24 16:14:37 +02:00
Nik
caa2b6aaa6 patterns/fdt: Improved visualizing of data 2023-07-24 16:13:34 +02:00
lopqto
7344df7ff6 patterns/pyinstaller: Added PyInstaller pattern (#142) 2023-07-16 20:21:59 +02:00
Nik
df649d2e62 patterns/elf: Speed up section name querying 2023-07-14 21:52:47 +02:00
Nik
8710b9e66f scripts: Added basic Kaitai to ImHex Pattern converter 2023-07-14 17:08:49 +02:00
vikke1234
665c942329 patterns/fdt: Fixed typo (#141) 2023-07-14 12:18:27 +02:00
vikke1234
50f93d14ff patterns/fdt: Fix flattened device tree parsing (#140)
* Fix flattened device tree parsing

Fix parsing to support multiple FDTs in a file and
non-zero base addresses.

* Fix string parsing

Parent offset wasn't being taken into account
when looking for prop names.
2023-07-13 14:38:52 +02:00
Nik
ab43516517 includes/std: Allow std::mem::MagicSearch to work with non-zero base addresses 2023-07-13 12:10:54 +02:00
Nik
4587b465d4 includes/std: Fixed std::mem::eof() not working correctly with non-zero base addresses 2023-07-13 12:08:25 +02:00
Nik
75b2c7be7e includes/std: Fixed MagicSearch type 2023-07-13 12:06:02 +02:00
Ange Albertini
19dd39e7c0 patterns: Added SE Linux binary format pattern (#139)
* SE Linux policy binary

module, base, kernel and packages

* Updated README with SELinux patterns

* SELinux test files
2023-07-12 20:25:47 +02:00
Nik
ecd34d35b2 patterns/elf: Fixed p_data definition in Phdr structs 2023-07-12 14:10:01 +02:00
Nik
06366839aa includes/std: Added std::ByteSizedArray 2023-07-12 00:13:02 +02:00
Nik
e3c387d0cf patterns/3ds: Added 3DS Max pattern 2023-07-10 16:36:49 +02:00
brliron
5a7077412c patterns/bmp: Various improvements (#138)
- Add various version of the BitmapInfoHeader struct, and autodetect
  the correct one.
- Fix palette detection.
- Use BitmapInfoHeader::biSize to find the position of the palette / data.
2023-07-10 11:31:07 +02:00
WerWolv
d8a37b0579 tests: Added WAD test file 2023-07-09 10:05:47 +02:00
WerWolv
1f1b2b9c5b tests: Fixed name of afe2 test file 2023-07-09 10:05:40 +02:00
Nik
d1645d2dc2 patterns:/intel_hex: Allow Intel Hex pattern to support files with linux line endings 2023-07-09 00:39:23 +02:00
WerWolv
61ef68b12a tests: Added more test files 2023-07-09 00:31:48 +02:00
WerWolv
c52e5b959b patterns: Fixed intel hex pattern 2023-07-09 00:14:58 +02:00
WerWolv
4a62892411 tests: Added various new test files 2023-07-09 00:14:49 +02:00
Nemoumbra
fc9b4cdbc2 tests: Added ico test file (#137) 2023-07-08 23:33:20 +02:00
Nik
daa556db31 tests: Fixed name of jpeg test pattern 2023-07-08 23:15:42 +02:00
Nik
e01a832fab patterns/lua54: Fixed parameter named const 2023-07-08 23:07:05 +02:00
Nik
759708d446 patterns/png: Automatically name PNG chunks 2023-07-03 22:06:48 +02:00
Trevor Gross
82560e6d9d patterns: Add a pattern for zlib compression (#135)
Add a pattern for RFC 1950 zlib compression
2023-07-02 18:58:19 +02:00
Nik
1a2d785093 patterns/java_class: Added MIME type 2023-06-24 11:05:10 +02:00
Nik
addec74d91 type/leb128: Fixed type always displaying 0 2023-06-22 17:35:59 +02:00
jfsbrito
ce83eedf02 patterns/7z: Added CompressData length and other improvements (#134)
* Update 7z.hexpat - v1.01

v1.01
--Minor changes.
--CompressData lenght added
--Output optimization

* Update 7z.hexpat v1.02

-Minor Changes
-Added Bzip2 verification
2023-06-22 07:27:31 +02:00
Doriel Rivalet
463ddcc62e themes: Add Catppuccin themes (#132)
* docs(README): add catppuccin theme

* themes: add catppuccin flavors

* chore: rename catppuccin files

* docs(README): update catppuccin file names
2023-06-19 23:09:16 +02:00
jfsbrito
13b97fc976 patterns/7z: Added 7Zip pattern (#128)
* 7z.hexpat

This repository contains a custom pattern for the ImHex tool that enables the analysis of 7zip files. The pattern allows for a structured view of 7zip files within ImHex, providing insights into various aspects of the file structure.

- Identification of 7zip files: The custom pattern detects and identifies 7zip file types based on their signature.
- Extraction of key information: The pattern extracts important details from the 7zip file, such as the format version, CRC values, relative offset of the end header, and file size.
- Differentiation of compression methods: The pattern distinguishes between LZMA and LZMA2 compression methods used within the 7zip file.
- Visualization of start and end headers: The pattern helps in visualizing the start and end headers of the 7zip file, making it easier to navigate through its structure.

To use the custom pattern for analyzing 7zip files in ImHex, follow these steps:

1. Install ImHex: Ensure that you have ImHex installed on your system.
2. Open a 7zip file: Launch ImHex and open the 7zip file you want to analyze.
3. Apply the custom pattern: In the "Pattern" menu, select the custom pattern for 7zip file analysis and apply it.
4. Explore the file structure: ImHex will display the matched patterns, allowing you to explore the structure of the 7zip file with the extracted information.

Please note that this custom pattern is designed specifically for 7zip files and may not be suitable for other file formats.

Contributions to this custom pattern for 7zip file analysis are welcome. If you have any improvements, bug fixes, or suggestions, feel free to submit a pull request.

This custom pattern for ImHex is licensed under the [MIT License](LICENSE.md). You are free to modify and distribute this pattern as per the terms of the license.

We would like to acknowledge the developers of ImHex for providing an excellent tool for binary file analysis. The custom pattern for 7zip file analysis in this repository builds upon the capabilities of ImHex to enhance the understanding of 7zip file structures.

---

We hope you find this custom pattern useful for analyzing 7zip files using ImHex. If you encounter any issues or have any questions, please feel free to raise them in the "Issues" section of this repository.

Thanks!

* Added test file

---------
2023-06-19 23:08:42 +02:00
luisfilipe23lol
55e4283432 patterns/cda: Added CDA pattern (#133)
* Create cda.hexpat

pattern language created for .cda files

* added test file for cda pattern

* Delete cda.hexpat.cda.cda

* Add test file cda

test file for cda pattern

* Update README.md

Add cda file in read.me
2023-06-19 14:22:17 +02:00
Nik
ea225edf12 git: Disable coverage information for now 2023-06-17 15:20:01 +02:00
blondecake433
bb19cb43ee patterns:/mp4: Added mp4 pattern (#129) 2023-06-17 15:07:08 +02:00
Nik
8f8ad0e2d5 git: Try fix Coveralls heap out of memory 2023-06-17 15:02:53 +02:00
Nik
3ad1f3969f includes/std: Fixed documentation of copy_value_to_section function 2023-06-15 22:58:44 +02:00
cryptax
5451d45158 patterns/dex: Fix pattern to see data section of DEX files + Link_data (#127) 2023-06-15 18:48:47 +02:00
Nik
e6a731fa1d includes/type: Added Base64 type 2023-06-15 17:34:20 +02:00
Jackson Barreto
8a62001705 patterns: Added TIFF pattern (#126)
* Create tiff.hexpat

* Update README.md

Update readme to include tiff hexpat

* added file to test the pattern

---------

Co-authored-by: joelalves <joel.17.alves@gmail.com>
2023-06-15 08:08:39 +02:00
Nik
1f8710b586 patterns/ntag: Fixed Length type transform function 2023-06-13 13:36:53 +02:00
Nik
acd2d4abb8 includes/std: Fixed description of array library (#125) 2023-06-12 08:10:48 +02:00
qufb
032f3c7c01 pattern/midi: Support multiple tracks (#124)
* pattern/midi: Support multiple tracks

* pattern/midi: Replace custom type used to index array
2023-06-11 13:09:23 +02:00
无以铭川
3841ff51ef pattern/java_class: Format byte code instruction (#123) 2023-06-08 23:39:39 +02:00
Nik
622721403f patterns/flac: Fixed typo 2023-06-06 08:26:01 +02:00
Nik
11291d1ebb tests: Added JPG test file 2023-06-05 10:59:12 +02:00
Nik
92e61ccf5d tests: Fixed build with new pattern language changes 2023-06-05 10:03:55 +02:00
Nik
062edfe527 includes/std: Fixed std::fxpt::to_fixed conversion issue 2023-06-05 09:48:33 +02:00
paxcut
5b32941801 patterns: Added visualizers to image patterns (#117)
* Added image visualizers to image patterns that were supported

* missing include files

* Small style fixes

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2023-06-04 22:38:25 +02:00
Nik
e99ab5b59b patterns/java_class: Fixed duplicate variables 2023-06-02 10:54:09 +02:00
Feitong Chen
775c836766 patterns/macho: Fix macho CpuType error and add CpuType::ARM64 and CpuType::ARM64_32 (#115) 2023-06-01 16:38:34 +02:00
blondecake433
43058b4c45 pattern/gif: Improved GIF pattern (#114) 2023-05-26 09:28:18 +02:00
Justus Garbe
0128ea87db patterns/java_class: Added Java SE 20 Attributes, added value displaying (#113)
greatly enchanced the java pattern
2023-05-19 17:59:15 +02:00
WerWolv
fe231436d9 patterns/gb: Added Gameboy ROM pattern (#89)
* Added gameboy format

* Add mime type

* Add test

* Avoid DMCA :sweating:
2023-05-19 16:09:14 +02:00
gmestanley
7a9ac44577 patterns/pe: Improved PE pattern (#112)
New improvement
2023-05-16 11:03:07 +02:00
Nick Bitounis
74e9d8f2e7 patterns: Added pattern file for M.A.X. v1.04 game files. (#111)
* Added pattern file for M.A.X. v1.04 game files.

* * Added MAX pattern in list of patterns.
* Added MAX sample game save file.
* Reordered the list of patterns to ascending name.

---------

Co-authored-by: n.bitounis <n.bitounis@xe.gr>
2023-05-08 16:17:19 +02:00
Nik
2f39a62d85 includes/std: Added support for writing patterns to files 2023-05-02 20:38:21 +02:00
AdventureT
e21063d58b patterns: Added Crash Bandicoot - Back in time level format (#110)
* Added Crash Bandicoot - Back in time level format

* Update README.md

* Fix README.md
2023-04-25 21:44:02 +02:00
paxcut
8f1a6bdd75 includes/std: Added std::math::exp(), fixed std::math::ln comment (#106)
Removed extraneous argument base to ln function and added the necessary definition in include file to access previously builtin function exp.
2023-04-17 22:19:47 +02:00
Nik
b9af43e08b patterns: Fixed WAV MIME type in readme 2023-04-16 21:37:40 +02:00
Nik
2ffa4e0161 patterns/wav: Fixed MIME type 2023-04-06 12:33:46 +02:00
173 changed files with 19181 additions and 3573 deletions

View File

@@ -45,3 +45,12 @@ jobs:
repo: Documentation
owner: WerWolv
event_type: update_pl_docs
- name: ✉️ Update PatternLanguage Website
if: ${{ env.DISPATCH_TOKEN != '' }}
uses: mvasigh/dispatch-action@main
with:
token: ${{ secrets.DISPATCH_TOKEN }}
repo: PatternLanguageWeb
owner: WerWolv
event_type: rebuild_wasm

View File

@@ -59,16 +59,18 @@ jobs:
cd tests/build
ctest --output-on-failure
- name: ⚗️ Generate Coverage Report
run: |
cd tests/build
lcov -d ./_deps/pattern_language-build/lib --gcov-tool /usr/bin/gcov-12 -c -o coverage.info
#- name: ⚗️ Generate Coverage Report
# run: |
# cd tests/build
# lcov -d ./_deps/pattern_language-build/lib --gcov-tool /usr/bin/gcov-12 -c -o coverage.info
- name: ⬆️ Upload Coverage Report
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: tests/build/coverage.info
#- name: ⬆️ Upload Coverage Report
# uses: coverallsapp/github-action@master
# env:
# NODE_OPTIONS: --max-old-space-size=8000
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
# path-to-lcov: tests/build/coverage.info
- name: 📎 Validate JSON Files
run: |

8
.gitmodules vendored
View File

@@ -1,4 +1,10 @@
[submodule "rules"]
path = yara/official_rules
url = https://github.com/Yara-Rules/rules
branch = master
branch = master
[submodule "patterns/ffx"]
path = patterns/ffx
url = https://gitlab.com/EvelynTSMG/imhex-ffx-pats.git
[submodule "patterns/bastion"]
path = patterns/bastion
url = https://gitlab.com/EvelynTSMG/imhex-bastion-pats.git

159
README.md
View File

@@ -22,75 +22,102 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| Name | MIME | Path | Description |
|------|------|------|-------------|
| 3DS | | [`patterns/3ds.hexpat`](patterns/3ds.hexpat) | Autodesk 3DS Max Model file |
| 7Z | | [`patterns/7z.hexpat`](patterns/7z.hexpat) | 7z File Format |
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
| AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files |
| ARIA2 | | [`patterns/aria2.hexpat`](patterns/aria2.hexpat) | ARIA2 Download Manager Control files |
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
| Bastion | | [`patterns/bastion/*`](https://gitlab.com/EvelynTSMG/imhex-bastion-pats) | Various [Bastion](https://en.wikipedia.org/wiki/Bastion_(video_game)) files |
| Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files |
| 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 |
| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers |
| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets |
| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions |
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
| AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files |
| NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files |
| NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files |
| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO |
| Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files |
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
| ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files |
| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files |
| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files |
| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface |
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
| ISO | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system |
| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files |
| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) |
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System |
| Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files |
| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding |
| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format |
| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format |
| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format |
| NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC |
| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format |
| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams |
| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format |
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
| 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/id3.hexpat`](patterns/id3.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) |
| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) |
| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable |
| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file |
| BIN | | [`patterns/selinux.hexpat`](patterns/selinux.pat) | SE Linux modules |
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
| bplist | | [`patterns/bplist.hexpat`](patterns/bplist.hexpat) | Apple's binary property list format (bplist) |
| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) |
| CCHVA | | [`patterns/cchva.hexpat`](patterns/cchva.hexpat) | Command and Conquer Voxel Animation |
| CCVXL | | [`patterns/ccvxl.hexpat`](patterns/ccvxl.hexpat) | Command and Conquer Voxel Model |
| CCPAL | | [`patterns/ccpal.hexpat`](patterns/ccpal.hexpat) | Command and Conquer Voxel Palette |
| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format |
| CDA | | [`patterns/cda.hexpat`](patterns/cda.hexpat) | Compact Disc Audio track |
| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) |
| 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 |
| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface |
| DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format |
| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) |
| DS_Store | | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format |
| DTA | | [`patterns/max_v104.hexpat`](patterns/max_v104.hexpat) | Mechanized Assault and Exploration v1.04 (strategy game) save file format |
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log |
| FAS | | [`patterns/fas_oskasoftware.hexpat`](patterns/fas_oskasoftware.hexpat) [`patterns/fas_oskasoftware_old.hexpat`](patterns/fas_oskasoftware_old.hexpat) (Old versions of Oska DeskMate) | Oska Software DeskMates FAS (Frames and Sequences) file |
| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob |
| FFX | | [`patterns/ffx/*`](https://gitlab.com/EvelynTSMG/imhex-ffx-pats) | Various Final Fantasy X files |
| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System |
| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format |
| GB | `application/x-gameboy-rom` | [`patterns/gb.hexpat`](patterns/gb.hexpat) | Gameboy ROM |
| 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 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 |
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) |
| IPS | | [`patterns/ips.hexpat`](patterns/ips.hexpat) | IPS (International Patching System) files |
| ISO | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system |
| Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files |
| JPEG | `image/jpeg` | [`patterns/jpeg.hexpat`](patterns/jpeg.hexpat) | JPEG Image Format |
| Lua 5.4 | | [`patterns/lua54.hexpat`](patterns/lua54.hexpat) | Lua 5.4 bytecode |
| DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format |
| DS_Store | `application/octet-stream` | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format |
| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable |
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files |
| mp4 | `video/mp4` | [`patterns/mp4.hexpat`](patterns/mp4.hexpat) | MPEG-4 Part 14 digital multimedia container format |
| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format |
| NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files |
| NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format |
| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
| nes | | [`patterns/nes.hexpat`](patterns/nes.hexpat) | .nes file format |
| NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files |
| NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC |
| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format |
| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets |
| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format |
| PE | `application/x-dosexec` `application/x-msdownload` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
| PP | | [`patterns/selinuxpp.hexpat`](patterns/selinuxpp.pat) | SE Linux package |
| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) |
| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format |
| 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 |
| 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 |
| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files |
| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format |
| shp | | [`patterns/shp.hexpat`](patterns/shp.hexpat) | ESRI shape file |
| shx | | [`patterns/shx.hexpat`](patterns/shx.hexpat) | ESRI index file |
| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions |
| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format |
| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive |
| 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 |
| Ubiquiti | | [`patterns/ubiquiti.hexpat`](patterns/ubiquiti.hexpat) | Ubiquiti Firmware (update) image |
| UEFI | | [`patterns/uefi.hexpat`](patterns/uefi.hexpat)` | UEFI structs for parsing efivars |
| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log |
| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) |
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
| VBMeta | | [`patterns/vbmeta.hexpat`](patterns/vbmeta.hexpat) | Android VBMeta image |
| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files |
| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format |
| WAV | `audio/x-wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
| WAS | | [`patterns\was_oskasoftware.hexpat`](patterns\was_oskasoftware.hexpat) | Oska Software DeskMates WAS/WA3 (WAVE/MP3 Set) file
| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive |
| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable |
| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cardridge ROM |
| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams |
| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers |
| ZLIB | `application/zlib` | [`patterns/zlib.hexpat`](patterns/zlib.hexpat) | ZLIB compressed data format |
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
### Scripts
@@ -103,9 +130,9 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| Name | Path | Description |
|------|------|-------------|
| libstd | [`includes/std/*`](includes/std) | Pattern Language Standard Libaray |
| libtype | [`includes/type/*`](includes/type) | Various custom types with special formatters |
| libhex | [`includes/hex/*`](includes/hex) | Functions to interact with ImHex |
| libstd | [`includes/std/*`](includes/std) | Pattern Language Standard Library |
| libtype | [`includes/type/*`](includes/type) | Various custom types with special formatters |
### Yara rules
@@ -179,3 +206,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|------|------|-------------|
| Visual Studio Dark | [`themes/vs_dark.json`](themes/vs_dark.json) | Theme similar to Visual Studio's Dark theme |
| Solarized Dark | [`themes/solarized_dark.json`](themes/solarized_dark.json) | Solarized Dark Theme |
| Catppuccin Latte | [`themes/catppuccin-latte.json`](themes/catppuccin-latte.json) | Catppuccin Latte Flavor (Light Theme) |
| Catppuccin Frappe | [`themes/catppuccin-frappe.json`](themes/catppuccin-frappe.json) | Catppuccin Frappe Flavor (Dark Theme) |
| Catppuccin Macchiato | [`themes/catppuccin-macchiato.json`](themes/catppuccin-macchiato.json) | Catppuccin Macchiato Flavor (Dark Theme) |
| Catppuccin Mocha | [`themes/catppuccin-mocha.json`](themes/catppuccin-mocha.json) | Catppuccin Mocha Flavor (Dark Theme) |

View File

@@ -21,20 +21,20 @@ namespace hex::core {
@return The current selection
*/
fn get_selection() {
u128 result = builtin::hex::core::get_selection();
u128 selection = builtin::hex::core::get_selection();
Selection result;
if (result == u128(-1)) {
if (selection == u128(-1)) {
result.valid = false;
result.address = 0x00;
result.size = 0x00;
} else {
result.valid = true;
result.address = result >> 64;
result.size = result & u64(-1);
result.address = selection >> 64;
result.size = selection & u64(-1);
}
return result;
};
}
}

View File

@@ -1,8 +1,10 @@
#pragma once
#include <std/sys.pat>
/*!
The array library contains various helper functions and types to make
it easier to work with Arrays.
The array library contains a helper type to make it easier to create multi-dimensional arrays
and pass arrays to functions as parameters.
*/
namespace std {
@@ -10,10 +12,30 @@ namespace std {
/**
Simple one dimensional array wrapper
@tparam T The array types
@tparam Size Size of the array
@tparam Size Number of entries in the array
*/
struct Array<T, auto Size> {
T data[Size] [[inline]];
};
} [[format("std::impl::format_array")]];
}
/**
Simple array wrapper for an array with a size in bytes
@tparam T The array types
@tparam NumBytes Number of bytes the array contains
*/
struct ByteSizedArray<T, auto NumBytes> {
u64 startAddress = $;
T array[while($ - startAddress < NumBytes)] [[inline]];
std::assert($ - startAddress == NumBytes, "Not enough bytes available to fit a whole number of types");
} [[format("std::impl::format_array")]];
namespace impl {
fn format_array(ref auto array) {
return "[ ... ]";
};
}
}

View File

@@ -59,9 +59,9 @@ namespace std::file {
/**
Writes the content of a string into a file
@param handle The file handle to write to
@param data String to write to the file
@param data String or Pattern to write to the file
*/
fn write(Handle handle, str data) {
fn write(Handle handle, auto data) {
builtin::std::file::write(handle, data);
};

View File

@@ -28,7 +28,7 @@ namespace std::fxpt {
@return The fixed point representation of flt
*/
fn to_fixed(double flt, u32 precision) {
return fixed((flt * (1 << precision)));
return s128((flt * (1 << precision)));
};
/**

View File

@@ -178,7 +178,6 @@ namespace std::math {
/**
Calculates the natural logarithm of `value`.
@param value Value
@param base Base
@return Logarithm of `value` with base `e`
*/
fn ln(auto value) { return builtin::std::math::ln(value); };
@@ -198,6 +197,13 @@ namespace std::math {
*/
fn pow(auto base, auto exp) { return builtin::std::math::pow(base, exp); };
/**
Calculates the value of the natural number `e` raised to the power of `value`.
@param value Exponent
@return `e` raised to the power of `value`
*/
fn exp(auto value) { return builtin::std::math::exp(value); };
/**
Calculates the square root of `value`.
@param value Value
@@ -256,10 +262,11 @@ namespace std::math {
/**
Calculates the arc tangent of `value`.
@param value Value
@param y Value representing the proportion of the y-coordinate
@param x Value representing the proportion of the x-coordinate.
@return Arc tangent of `value` in radians between `-pi` and `pi`
*/
fn atan2(auto value) { return builtin::std::math::atan2(value); };
fn atan2(auto y, auto x) { return builtin::std::math::atan2(y, x); };
/**
Calculates the hyperbolic sine of `value`.

View File

@@ -5,7 +5,27 @@
*/
namespace 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;
}
};
}
/**
A Handle for a custom Section
*/
@@ -26,7 +46,7 @@ namespace std::mem {
@return True if the cursor is at the end of the memory
*/
fn eof() {
return $ >= std::mem::size();
return $ >= (std::mem::base_address() + std::mem::size());
};
/**
@@ -160,6 +180,15 @@ namespace std::mem {
return builtin::std::mem::get_section_size(section);
};
/**
Changes the size of a custom section
@param section The handle to the section
@param size The new size of the section
*/
fn set_section_size(Section section, u128 size) {
builtin::std::mem::set_section_size(section, size);
};
/**
Copies a range of bytes from one section into another
@param from_section The section to copy from
@@ -174,10 +203,9 @@ namespace std::mem {
/**
Copies a range of bytes from the main section into a custom section
@param from_section The section to copy from
@param from_address The address to copy from
@param value The pattern whose bytes should be copied
@param to_section The section to copy to
@param to_address The address to copy to
@param size The size of the range to copy
*/
fn copy_value_to_section(ref auto value, Section to_section, u64 to_address) {
builtin::std::mem::copy_value_to_section(value, to_section, to_address);
@@ -190,19 +218,7 @@ namespace std::mem {
@tparam T The type to place at the address
*/
struct MagicSearch<auto Magic, T> {
if ($ < (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;
}
std::mem::impl::MagicSearchImpl<Magic, T> impl[while(!std::mem::eof())] [[inline]];
};
/**

View File

@@ -1,5 +1,7 @@
#pragma once
#include <std/mem.pat>
/*!
The Pointer library contains helper functions to deal with pointer types.
The `relative_to` functions are meant to be used with the `[[pointer_base]]` attribute
@@ -64,4 +66,4 @@ namespace std::ptr {
PointeeTy *data : PointerTy;
}
};
}
}

View File

@@ -209,30 +209,27 @@ namespace std::string {
@param replace The substring to replace with.
@return The string with the replacements.
*/
fn replace(str string, str pattern, str replace) {
u32 string_len, pattern_len, replace_len;
string_len = std::string::length(string);
pattern_len = std::string::length(pattern);
replace_len = std::string::length(replace);
if (pattern_len > string_len)
return string;
fn replace(str string, str pattern, str replace) {
s32 string_len = std::string::length(string);
s32 pattern_len = std::string::length(pattern);
if (pattern_len > string_len || pattern_len * string_len == 0 )
return string;
str result;
u32 i;
while (i <= (string_len - pattern_len)) {
if (std::string::substr(string, i, pattern_len) == pattern) {
result = result + replace;
i = i + pattern_len;
} else {
result = result + std::string::at(string, i);
i = i + 1;
s32 string_index;
s32 remaining_len = string_len;
while (pattern_len <= remaining_len) {
if (std::string::substr(string, string_index, pattern_len) == pattern) {
result += replace;
string_index += pattern_len;
} else {
result += std::string::at(string, string_index);
string_index += 1;
}
remaining_len = string_len - string_index;
}
result += std::string::substr(string, string_index, remaining_len );
return result;
};
}

View File

@@ -34,7 +34,7 @@ namespace std::time {
/**
A type to represent a time in seconds since the epoch.
*/
using EpochTime = u128;
using EpochTime = u32;
/**
A type to represent a time zone.
@@ -91,7 +91,7 @@ namespace std::time {
@return The local time.
*/
fn to_local(EpochTime epoch_time) {
TimeConverter converter;
le TimeConverter converter;
converter.value = builtin::std::time::to_local(epoch_time);
@@ -104,7 +104,7 @@ namespace std::time {
@return The UTC time.
*/
fn to_utc(EpochTime epoch_time) {
TimeConverter converter;
le TimeConverter converter;
converter.value = builtin::std::time::to_utc(epoch_time);
@@ -117,7 +117,7 @@ namespace std::time {
@return The current time in the specified time zone.
*/
fn now(TimeZone time_zone = TimeZone::Local) {
TimeConverter converter;
le TimeConverter converter;
if (time_zone == TimeZone::Local)
converter.value = builtin::std::time::to_local(std::time::epoch());
@@ -135,7 +135,7 @@ namespace std::time {
@return The DOS date.
*/
fn to_dos_date(u16 value) {
impl::DOSDateConverter converter;
le impl::DOSDateConverter converter;
converter.value = value;
@@ -148,13 +148,22 @@ namespace std::time {
@return The DOS time.
*/
fn to_dos_time(u16 value) {
impl::DOSTimeConverter converter;
le impl::DOSTimeConverter converter;
converter.value = value;
return converter.time;
};
/**
Converts a FILETIME to unix time.
@param value The value to convert.
@return Timestamp formatted as unix time.
*/
fn filetime_to_unix(u64 value) {
return value / 10000000 - 11644473600;
};
/**
Formats a time according to the specified format string.
@param time The time to format.
@@ -162,7 +171,7 @@ namespace std::time {
@return The formatted time.
*/
fn format(Time time, str format_string = "%c") {
TimeConverter converter;
le TimeConverter converter;
converter.time = time;
return builtin::std::time::format(format_string, converter.value);

63
includes/type/base64.pat Normal file
View File

@@ -0,0 +1,63 @@
#include <std/io.pat>
#include <std/string.pat>
#include <std/mem.pat>
/*!
Type representing a Base64 encoded string
*/
namespace type {
/**
Type representing a Base64 encoded string
@tparam T String type
*/
struct Base64<T> {
T string;
} [[sealed, format("type::impl::transform_base64")]];
namespace impl {
fn get_decoded_value(char c) {
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return -1; // Invalid character
};
fn decode_base64(str input) {
u64 inputLength = std::string::length(input);
str result;
s32 val = 0;
s32 bits = -8;
for (u32 i = 0, i < inputLength, i += 1) {
char c = input[i];
if (c == '=')
break;
s32 index = type::impl::get_decoded_value(c);
if (index == -1)
continue;
val = (val << 6) + index;
bits += 6;
if (bits >= 0) {
result += char((val >> bits) & 0xFF);
bits -= 8;
}
}
return result;
};
fn transform_base64(ref auto base64) {
return type::impl::decode_base64(base64.string);
};
}
}

View File

@@ -33,7 +33,7 @@ namespace type {
namespace impl {
fn transform_uleb128_array(auto array) {
fn transform_uleb128_array(ref auto array) {
u128 res = array[0] & 0x7f;
for(u8 i = 1, array[i-1] & 0x80 != 0, i+=1) {
res |= u128(array[i] & 0x7f) << 7 * i;
@@ -41,7 +41,7 @@ namespace type {
return res;
};
fn transform_sleb128_array(auto array) {
fn transform_sleb128_array(ref auto array) {
s128 res = type::impl::transform_uleb128_array(array);
if (res & 0x40 != 0) {
res |= ~0 << (sizeof(array) / sizeof(u8)) * 7;
@@ -49,21 +49,21 @@ namespace type {
return res;
};
fn format_uleb128(auto leb128) {
fn format_uleb128(ref auto leb128) {
u128 res = type::impl::transform_uleb128_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_uleb128(auto leb128) {
fn transform_uleb128(ref auto leb128) {
return type::impl::transform_uleb128_array(leb128.array);
};
fn format_sleb128(auto leb128) {
fn format_sleb128(ref auto leb128) {
s128 res = type::impl::transform_sleb128_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_sleb128(auto leb128) {
fn transform_sleb128(ref auto leb128) {
return type::impl::transform_sleb128_array(leb128.array);
};

View File

@@ -34,6 +34,11 @@ namespace type {
*/
using DOSTime = u16 [[format("type::impl::format_dostime")]];
/**
A 64bit FILETIME value
*/
using FILETIME = u64 [[format("type::impl::format_filetime_as_unix")]];
namespace impl {
fn format_time_t(u128 value) {
@@ -48,6 +53,10 @@ namespace type {
return std::time::format_dos_time(std::time::to_dos_time(value));
};
fn format_filetime_as_unix(u64 value) {
return std::time::filetime_to_unix(value);
};
}
}

View File

@@ -1,4 +1,4 @@
# A libmagic database containing definition for PE files used by MS-DOS based systems
# A libmagic database containing definition for PE files used by MS-DOS/Windows based systems
# MS-DOS Portable Executable
0x0 string/b MZ MS-DOS Binary

1141
patterns/3ds.hexpat Normal file

File diff suppressed because it is too large Load Diff

101
patterns/7z.hexpat Normal file
View File

@@ -0,0 +1,101 @@
#pragma description 7z File Format
#include <std/io.pat>
#include <std/mem.pat>
#include <std/math.pat>
enum Type:u8{
startPosition = 0x00, // Start position
sizeStartHeader = 0x20, // Size of start Header
};
enum TypeB:u48{
sevenZipSignature = 0x1C27AFBC7A37, // Defining 7z signature
};
struct StartHeader {
// File signature
u48 signature [[color("FF0000")] ];
// Version format
u16 formatVersion [[color("00FF00")]];
// CRC start header
u32 crcOfTheFollowing20Bytes [[color("0000FF")]];
// Relative offset of End Header
u64 relativeOffsetEndHeader [[color("FFFF00")]];
// Length of End Header
u64 theLengthOfEndHeader [[color("00FFFF")]];
// CRC of End Ender
u32 crcOftheEndHeader [[color("FF00FF")]];
// File size calculation
u64 fileSize = relativeOffsetEndHeader + theLengthOfEndHeader + Type::sizeStartHeader;
// Absolute offset calculation End Header
u64 startEndHeader = relativeOffsetEndHeader + Type::sizeStartHeader;
};
StartHeader startheader @ Type::startPosition;
struct CompressedData {
// Start of compressed data
u8 startOfCompressedData[4] [[color("C0C0C0")]];
};
CompressedData compresseddata @ Type::sizeStartHeader;
struct EndHeader {
// Set padding to place End Header in right position
padding[startheader.relativeOffsetEndHeader];
// Mark link to meta block
u8 linkToMetaBlock [[color("FF0000")]];
// Mark all End Header
char fullEndHeader[startheader.theLengthOfEndHeader] [[color("63954A")]];
// Detect LZMA signature
u64 lzmaSignaturePosition = std::mem::find_sequence_in_range(0, addressof(fullEndHeader), addressof(fullEndHeader) + sizeof(fullEndHeader), 0x23, 0x03, 0x01, 0x01, 0x05, 0x5D);
// Mark positions if LZMA signature was detected
if(lzmaSignaturePosition != 0xFFFFFFFFFFFFFFFF){
u48 lzmaSignature @ lzmaSignaturePosition [[color("0000FF")]];
}
};
EndHeader endheader @ Type::sizeStartHeader;
// Check 7z type
if(startheader.signature == TypeB::sevenZipSignature){
std::print("It is a 7z File Type");
}else{
std::print("The file is not 7z type");
}
std::print("Format Version {} ",startheader.formatVersion);
// Version verification
if(startheader.formatVersion == 0x0400){
std::print("Major Version 0x00 || 0 - Minor Version 0x04 || 4");
}
// Verification of the compressed method is LZMA, Bzip2 or LZMA2
if(compresseddata.startOfCompressedData[0] == Type::startPosition){
std::print("Compressed Method LZMA");
}else if(compresseddata.startOfCompressedData[0] == 0x42){
std::print("Compressed Method Bzip2");
}else{
std::print("Compressed Method LZMA2");
}
std::print("CRC Start Header 0x{:X}",startheader.crcOfTheFollowing20Bytes);
std::print("CRC End Header 0x{:X} ", startheader.crcOftheEndHeader);
std::print("CompressedData length 0x{:X} || {} bytes ",startheader.relativeOffsetEndHeader, startheader.relativeOffsetEndHeader);
std::print("Relative Offset of End Header 0x{:X} || {} bytes",startheader.relativeOffsetEndHeader, startheader.relativeOffsetEndHeader);
std::print("Offset to start End Header 0x{:X} || {} bytes",startheader.startEndHeader,startheader.startEndHeader);
std::print("End Header length 0x{:X} || {} bytes",startheader.theLengthOfEndHeader,startheader.theLengthOfEndHeader);
std::print("File size 0x{:X} || {} bytes",startheader.fileSize, startheader.fileSize);

244
patterns/Crashlvl.hexpat Normal file
View File

@@ -0,0 +1,244 @@
#pragma author AdventureT
#pragma description Crash Bandicoot - Back in Time (fan game) User created level format
// Supports all versions till 0.94c, newer versions might be compatible!
#include <type/magic.pat>
#include <std/string.pat>
#include <std/array.pat>
struct Header {
type::Magic<"CRASHLVL"> magic;
u8 version;
if (version >= 4) {
std::string::SizedString<u8> gameVersion;
}
std::string::SizedString<u8> levelName;
std::string::SizedString<u8> author;
};
Header header @ 0x0;
// Background Music
enum BGM : u32 {
None,
BonusBGM,
CrashCreatorBGM,
MainMenuBGM,
WarpRoomBGM,
Level01BGM,
Level02BGM,
Level03BGM,
Level04BGM,
Level05BGM,
SewerBGM,
EgyptBGM,
NBrioBGM
};
enum BGMV2 : u32 {
None,
N_TropyBGM,
CrashCreatorBGM,
MainMenuBGM,
WarpRoomBGM,
Jungle01BGM,
SnowBGM,
RiverBGM,
FutureBGM,
LabBGM,
SewerBGM,
EgyptBGM,
NBrioBGM,
AdventureBGM,
SpyBGM,
ChaseBGM,
TrialsBGM,
SpaceBGM,
Jungle02BGM,
RipperBGM,
TheGreatWallBGM,
RoadToSomewhereBGM,
LavaKoalaBGM,
CortexBGM,
CyberCortexBGM,
ArabicBGM,
N_Tropy2BGM,
JazzBGM,
Space2BGM,
TawnaBonusBGM,
CortexPowerBGM,
ArabicBonusBGM,
EgyptBonusBGM,
FutureBonusBGM,
LostCityBGM,
PolarBGM,
RiverBonusBGM,
RuinsBonusBGM,
SewerBonusBGM,
SnowBonusBGM,
RoadToRuinBGM,
NGinBGM,
Arabia01BGM,
Arabia02BGM,
BashBGM,
Cortex02BGM,
};
enum Type : u32 {
Unset,
Flashback,
Trial,
};
enum TypeV2 : u32 {
Practice,
Flashback,
Trial,
Adventure
};
enum Skybox : u32 {
Night,
Day,
Storm,
Dawn
};
enum SkyboxV2 : u32 {
Default = 1,
Briolab,
Fort,
Moon,
Toxic,
AboutRight,
Crash1Island,
Arabia,
RoadToRuin,
Black
};
enum Scenery : u32 {
None,
FutureTense,
Forest,
Waterfall,
Snow,
Fortress,
};
enum SceneryV2 : u32 {
None,
FutureTense,
Forest,
Waterfall,
None2,
Fortress,
None3,
Lava,
TheGreatGate,
Mountain,
KoalaKong,
SunsetVista,
HangemHigh,
Sphynxinator,
Tunnel,
Pipes
};
enum SceneryV4 : u32 {
None,
FutureTense,
Forest,
Waterfall,
Snow,
Fortress,
None2,
Lava,
TheGreatGate,
Mountain,
KoalaKong,
SunsetVista,
HangemHigh,
Sphynxinator,
Tunnel,
Pipes
};
enum Weather : u32 {
Default,
Snow,
Rain
};
struct Options {
if (header.version > 1)
TypeV2 type;
else
Type type;
if (header.version > 1)
SkyboxV2 skybox;
else
Skybox skybox;
if (header.version == 1)
Scenery scenery;
else if (header.version > 1 && header.version < 4)
SceneryV2 scenery;
else
SceneryV4 scenery;
if (header.version > 2)
{
Weather weather;
}
if (header.version > 1)
BGMV2 bgm;
else
BGM bgm;
if (type == Type::Trial)
{
u32 timeTrialTicksBronze;
u32 timeTrialTicksSilver;
u32 timeTrialTicksGold;
}
};
struct Object {
std::string::SizedString<u8> objName;
if (header.version > 1)
{
u16 x;
u16 y;
bool hasMetafields;
if (hasMetafields)
{
u16 numOfMetafields;
u8 metafields[numOfMetafields];
}
}
else
{
u32 x;
u32 y;
}
};
struct Objects{
u32 objCount;
std::Array<Object, objCount> objArray;
};
Options options @ $;
Objects objects @ $;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Nintendo Switch Atmosphère CFW Fatal Error log
#pragma endian little
#include <std/io.pat>

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Static library archive files
#pragma MIME application/x-archive
#include <std/string.pat>

36
patterns/aria2.hexpat Normal file
View File

@@ -0,0 +1,36 @@
#pragma author itsmeow
#pragma description aria2 Control File
#pragma endian big
/*
Format sourced from:
https://aria2.github.io/manual/en/html/technical-notes.html#control-file-aria2-format
Version 0 files are not supported by default
However parsing one is as simple as changing to #pragma endian ittle
and resolving any errors resulting from that by adding be prefixes to struct fields.
*/
struct AriaInFlight {
u32 index;
u32 length;
u32 bitfield_piece_length;
u8 bitfield_p[bitfield_piece_length];
};
struct AriaHeader {
u16 version;
u32 extension;
u32 infohash_length;
u8 infohash[infohash_length];
u32 piece_length;
u64 total_length;
u64 upload_length;
u32 bitfield_length;
u8 bitfield_d[bitfield_length];
u32 inflight_count;
AriaInFlight inflights[inflight_count];
};
AriaHeader aria_header @ 0x00;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description ARM Cortex M Vector Table Layout
#pragma endian little
#include <std/io.pat>

1
patterns/bastion Submodule

Submodule patterns/bastion added at e6deed433c

View File

@@ -1,73 +1,76 @@
#pragma MIME application/x-bittorrent
#include <std/ctype.pat>
#include <std/mem.pat>
#include <std/string.pat>
namespace bencode {
struct ASCIIDecimal {
char value[while(std::ctype::isdigit(std::mem::read_unsigned($, 1)))];
} [[sealed, format("bencode::format_ascii_decimal"), transform("bencode::format_ascii_decimal")]];
fn format_ascii_decimal(ASCIIDecimal adsasd) {
return std::string::parse_int(adsasd.value, 10);
};
enum Type : u8 {
Integer = 'i',
Dictionary = 'd',
List = 'l',
String0 = '0',
String1 = '1',
String2 = '2',
String3 = '3',
String4 = '4',
String5 = '5',
String6 = '6',
String7 = '7',
String8 = '8',
String9 = '9'
};
struct String {
ASCIIDecimal length;
char separator [[hidden]];
char value[length];
} [[sealed, format("bencode::format_string"), transform("bencode::format_string")]];
fn format_string(String string) {
return string.value;
};
using Bencode;
using Value;
struct DictionaryEntry {
String key;
Value value;
};
struct Value {
Type type;
if (type == Type::Dictionary) {
DictionaryEntry entry[while(std::mem::read_unsigned($, 1) != 'e')];
} else if (type == Type::Integer) {
ASCIIDecimal value;
char end;
} else {
$ -= 1;
String value;
}
};
struct Bencode {
Value value[while(!std::mem::eof())] [[inline]];
char end;
};
}
bencode::Bencode bencode @ 0x00;
#pragma author WerWolv
#pragma description Bencode encoding, used by Torrent files
#pragma MIME application/x-bittorrent
#include <std/ctype.pat>
#include <std/mem.pat>
#include <std/string.pat>
namespace bencode {
struct ASCIIDecimal {
char value[while(std::ctype::isdigit(std::mem::read_unsigned($, 1)))];
} [[sealed, format("bencode::format_ascii_decimal"), transform("bencode::format_ascii_decimal")]];
fn format_ascii_decimal(ASCIIDecimal adsasd) {
return std::string::parse_int(adsasd.value, 10);
};
enum Type : u8 {
Integer = 'i',
Dictionary = 'd',
List = 'l',
String0 = '0',
String1 = '1',
String2 = '2',
String3 = '3',
String4 = '4',
String5 = '5',
String6 = '6',
String7 = '7',
String8 = '8',
String9 = '9'
};
struct String {
ASCIIDecimal length;
char separator [[hidden]];
char value[length];
} [[sealed, format("bencode::format_string"), transform("bencode::format_string")]];
fn format_string(String string) {
return string.value;
};
using Bencode;
using Value;
struct DictionaryEntry {
String key;
Value value;
};
struct Value {
Type type;
if (type == Type::Dictionary) {
DictionaryEntry entry[while(std::mem::read_unsigned($, 1) != 'e')];
} else if (type == Type::Integer) {
ASCIIDecimal value;
char end;
} else {
$ -= 1;
String value;
}
};
struct Bencode {
Value value[while(!std::mem::eof())] [[inline]];
char end;
};
}
bencode::Bencode bencode @ 0x00;

View File

@@ -1,5 +1,8 @@
#pragma description OS2/Windows Bitmap files
#pragma MIME image/bmp
#pragma endian little
#include <std/mem.pat>
struct BitmapFileHeader {
u8 bfType[2];
@@ -9,13 +12,38 @@ struct BitmapFileHeader {
u32 bfOffBits;
};
struct BitmapInfoHeader {
enum Compression : u32 {
BI_RGB,
BI_RLE8,
BI_RLE4,
BI_BITFIELDS,
BI_JPEG,
BI_PNG,
BI_ALPHABITFIELDS,
BI_CMYK,
BI_CMYKRLE8,
BI_CMYKRLE4,
};
struct CIEXYZ {
u32 ciexyzX;
u32 ciexyzY;
u32 ciexyzZ;
};
struct CIEXYZTRIPLE {
CIEXYZ ciexyzRed;
CIEXYZ ciexyzGreen;
CIEXYZ ciexyzBlue;
};
struct BitmapInfoHeaderV1 {
u32 biSize;
s32 biWidth;
s32 biHeight;
u16 biPlanes;
u16 biBitCount;
u32 biCompression;
Compression biCompression;
u32 biSizeImage;
s32 biXPelsPerMeter;
s32 biYPelsPerMeter;
@@ -23,6 +51,31 @@ struct BitmapInfoHeader {
u32 biClrImportant;
};
struct BitmapInfoHeaderV2 : BitmapInfoHeaderV1 {
u32 biRedMask;
u32 biGreenMask;
u32 biBlueMask;
};
struct BitmapInfoHeaderV3 : BitmapInfoHeaderV2 {
u32 biAlphaMask;
};
struct BitmapInfoHeaderV4 : BitmapInfoHeaderV3 {
u32 biCSType;
CIEXYZTRIPLE biEndpoints;
u32 biGammaRed;
u32 biGammaGreen;
u32 biGammaBlue;
};
struct BitmapInfoHeaderV5 : BitmapInfoHeaderV4 {
u32 biIntent;
u32 biProfileData;
u32 biProfileSize;
u32 biReserved;
};
struct Colors {
u8 blue;
u8 green;
@@ -31,10 +84,21 @@ struct Colors {
};
struct Bitmap {
u8 data[std::mem::size()] [[no_unique_address, hidden]];
BitmapFileHeader bmfh;
BitmapInfoHeader bmih;
// Deduce the header version from its size
u32 bmInfoHeaderSize [[hidden, no_unique_address]];
match (bmInfoHeaderSize) {
(40): BitmapInfoHeaderV1 bmih;
(52): BitmapInfoHeaderV2 bmih;
(56): BitmapInfoHeaderV3 bmih;
(108): BitmapInfoHeaderV4 bmih;
(124): BitmapInfoHeaderV5 bmih;
(_): BitmapInfoHeaderV1 bmih;
}
padding[bmih.biSize - sizeof(bmih)];
if ((bmih.biBitCount != 24) && (bmih.biBitCount != 32))
if (bmih.biBitCount <= 8)
{
if (bmih.biClrUsed > 0 )
Colors rgbq[bmih.biClrUsed];
@@ -46,6 +110,6 @@ struct Bitmap {
u8 lineData[bmih.biSizeImage];
else
u8 lineData[bmfh.bfSize - $];
};
} [[hex::visualize("image", this.data)]];
Bitmap bitmap @ 0x00;

271
patterns/bplist.hexpat Normal file
View File

@@ -0,0 +1,271 @@
#include <std/math.pat>
#include <std/core.pat>
#include <type/magic.pat>
#include <type/time.pat>
using CFBinaryPlistObject;
enum Marker : u8 {
Null = 0x00,
False = 0x08,
True = 0x09,
Fill = 0x0F,
Int = 0x10,
Real = 0x20,
Date = 0x30,
Data = 0x40,
ASCIIString = 0x50,
Unicode16String = 0x60,
UNK_0x70 = 0x70,
UID = 0x80,
UNK_0x90 = 0x90,
Array = 0xA0,
UNK_0xB0 = 0xB0,
Set = 0xC0,
Dict = 0xD0,
UNK_0xE0 = 0xE0,
UNK_0xF0 = 0xF0
};
fn get_marker_name(u8 marker) {
if (marker == Marker::Null){// null 0000 0000
return "Null ";
}else if (marker == Marker::False){ //bool 0000 1000 // false
return "False";
}else if (marker == Marker::True){//bool 0000 1001 // true
return "True";
}else if (marker == Marker::Fill){ //fill 0000 1111 // fill byte
return "Fill";
}else if (marker & 0xF0 == Marker::Int){ //int 0001 nnnn ... // # of bytes is 2^nnnn, big-endian bytes
return "Int";
}else if (marker & 0xF0 == Marker:: Real){ //real 0010 nnnn ... // # of bytes is 2^nnnn, big-endian bytes
return "Real";
}else if (marker == Marker::Date){ //date 0011 0011 ... // 8 byte float follows, big-endian bytes
return "Date";
}else if (marker & 0xF0 == Marker::Data){ //data 0100 nnnn [int] ... // nnnn is number of bytes unless 1111 then int count follows, followed by bytes
return "Data";
}else if (marker & 0xF0 == Marker::ASCIIString){ //string 0101 nnnn [int] ... // ASCII string, nnnn is # of chars, else 1111 then int count, then bytes
return "ASCIIString";
}else if (marker & 0xF0 == Marker::Unicode16String){ //string 0110 nnnn [int] ... // Unicode string, nnnn is # of chars, else 1111 then int count, then big-endian 2-byte
return "Unicode16String";
}else if (marker & 0xF0 == Marker::UNK_0x70){ //0111 xxxx // unused
return "UNK_0x70";
}else if (marker & 0xF0 == Marker::UID){ //uid 1000 nnnn ... // nnnn+1 is # of bytes
return "UID";
}else if (marker & 0xF0 == Marker::UNK_0x90){ // 1001 xxxx // unused
return "UNK_0x90";
}else if (marker & 0xF0 == Marker::Array){ //array 1010 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows
return "Array";
}else if (marker & 0xF0 == Marker::UNK_0xB0){ //1011 xxxx // unused
return "UNK_0xB0";
}else if (marker & 0xF0 == Marker::Set){ //set 1100 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows
return "Set";
}else if (marker & 0xF0 == Marker::Dict){ //dict 1101 nnnn [int] keyref* objref* // nnnn is count, unless '1111', then int count follows
return "Dict";
}else if (marker & 0xF0 == Marker::UNK_0xE0){ // 1110 xxxx // unused
return "UNK_0xE0";
}else if (marker & 0xF0 == Marker::UNK_0xF0){ //1111 xxxx // unused
return "UNK_0xF0";
}
};
fn format_tag(u8 marker) {
return std::format("{}", get_marker(marker));
};
fn coredata_to_date (double val){
return type::impl::format_time_t(978307200 + val);
};
struct DictElement {
CFBinaryPlistObject key @ offsetTable[parent.objReference.key_refs[std::core::array_index()]].offset;
CFBinaryPlistObject value @ offsetTable[parent.objReference.value_refs[std::core::array_index()]].offset;
};
struct ArrayElement {
CFBinaryPlistObject value @ offsetTable[parent.objReference.value_refs[std::core::array_index()]].offset;
};
struct ObjectReference{
match(trailer.objectRefSize){
(1): {
be u8 key_refs[parent.ObjectLen.size];
be u8 value_refs[parent.ObjectLen.size];
}
(2): {
be u16 key_refs[parent.ObjectLen.size];
be u16 value_refs[parent.ObjectLen.size];
}
(4): {
be u32 key_refs[parent.ObjectLen.size];
be u32 value_refs[parent.ObjectLen.size];
}
(8): {
be u64 key_refs[parent.ObjectLen.size];
be u64 value_refs[parent.ObjectLen.size];
}
}
};
struct ObjectReferenceArray{
match(trailer.objectRefSize){
(1): be u8 value_refs[parent.ObjectLen.size];
(2): be u16 value_refs[parent.ObjectLen.size];
(4): be u32 value_refs[parent.ObjectLen.size];
(8): be u64 value_refs[parent.ObjectLen.size];
}
};
struct ObjectLen{
if (parent.marker_lsb != 0x0F){
u8 size = parent.marker_lsb [[export]];
}else{
CFBinaryPlistObject obj;
if (obj.marker & 0xF0 != Marker::Int){
std::error(std::format("Expects a 'Int' marker. Got 0x{:x} marker, with value {}", obj.marker, obj.value));
}
u128 size = obj.value [[export]];
}
};
struct CFBinaryPlistOffset{
match (trailer.offsetIntSize){
(1): be u8 offset;
(2): be u16 offset;
(4): be u32 offset;
(8): be u64 offset;
}
};
struct CFBinaryPlistObject{
u8 marker [[format("get_marker_name")]];
u8 marker_msb = marker & 0xF0;
u8 marker_lsb = marker & 0x0F;
match (marker_msb){
(0x0): {
match (marker_lsb){
(Marker::Null): {
u8 value = 0x00 [[export]];
}
(Marker::False): {
bool value = false [[export]];
}
(Marker::True): {
bool value = true [[export]];
}
(Marker::Fill): {
//I think the correct implementation is to do nothing here. The marker will be used as padding (Fill) ???
}
(_): {
std::error("Detected unknown marker {}.", marker_msb);
}
}
}
(Marker::Int): {
be u8 size = std::math::pow(2, marker_lsb);
// in format version '00', 1, 2, and 4-byte integers have to be interpreted as unsigned,
// whereas 8-byte integers are signed (and 16-byte when available)
// negative 1, 2, 4-byte integers are always emitted as 8 bytes in format '00'
// integers are not required to be in the most compact possible representation, but only the last 64 bits are significant currently
// Source: https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c
match (size) {
(1): be u8 value;
(2): be u16 value;
(4): be u32 value;
(8): be s64 value;
(16): be s128 value;
(_): std::error(std::format("Invalid size detected for 'Int' marker. Got size: {}.", size));
}
}
(Marker::Real): {
be u8 size = std::math::pow(2, marker_lsb);
match (size){
(4): be float value;
(8): be double value;
(_): std::error(std::format("Invalid size detected for 'Real' marker. Got size: {}.", size));
}
}
(Marker::Date): {
be double value [[format("coredata_to_date")]];
}
(Marker::Data): {
ObjectLen ObjectLen;
u8 value[ObjectLen.size];
}
(Marker::ASCIIString): {
ObjectLen ObjectLen;
char value[ObjectLen.size];
}
(Marker::Unicode16String): {
ObjectLen ObjectLen;
be char16 value[ObjectLen.size];
}
(Marker::UID): {
//Not 100% sure if this is correct for UID. Need more testing
u8 size = marker_lsb+1;
match (size) {
(1): be u8 value;
(2): be u16 value;
(4): be u32 value;
(8): be u64 value;
(16): be u128 value;
(_): std::error(std::format("Invalid size detected for 'UID' marker. Got size: {}.", size));
}
}
(Marker::Set | Marker::Array): {
ObjectLen ObjectLen;
ObjectReferenceArray objReference;
ArrayElement value[ObjectLen.size];
}
(Marker::Dict): {
ObjectLen ObjectLen;
ObjectReference objReference;
DictElement value[ObjectLen.size];
}
(Marker::UNK_0x70 | Marker::UNK_0x90 | Marker::UNK_0xB0 | Marker::UNK_0xE0 | Marker::UNK_0xF0): {
std::error(std::format("Got unused marker 0x{:x}", marker));
}
(_): {
std::error(std::format("Got unknown marker 0x{:x}", marker));
}
}
};
struct CFBinaryPlistHeader{
type::Magic<"bplist"> magic;
u16 version;
if (version != 0x3030){
std::error("Unsupported version detected. Only version 00 is supported (bplist00).");
}
};
struct CFBinaryPlistTrailer {
u8 unused[5];
u8 sortVersion;
be u8 offsetIntSize;
match (offsetIntSize){
(1|2|4|8): {}
(_): {std::error("Invalid offsetIntSize.");}
}
be u8 objectRefSize;
match (objectRefSize){
(1|2|4|8): {}
(_): {std::error("Invalid objectRefSize.");}
}
be u64 numObjects;
be u64 topObject;
be u64 offsetTableOffset;
};
CFBinaryPlistHeader header @ 0x00;
CFBinaryPlistTrailer trailer @ std::mem::size()-32;
CFBinaryPlistOffset offsetTable[trailer.numObjects] @ trailer.offsetTableOffset;
CFBinaryPlistObject objectTable @ offsetTable[trailer.topObject].offset;

View File

@@ -1,128 +1,132 @@
#pragma MIME application/bson
#include <type/time.pat>
enum Type : u8 {
Double = 0x01,
String = 0x02,
EmbeddedDocument = 0x03,
Array = 0x04,
Binary = 0x05,
Undefined = 0x06,
ObjectId = 0x07,
Boolean = 0x08,
UTCDatetime = 0x09,
Null = 0x0A,
Regex = 0x0B,
DBPointer = 0x0C,
JavaScript = 0x0D,
Symbol = 0x0E,
JavaScriptWithScope = 0x0F,
Int32 = 0x10,
Timestamp = 0x11,
Int64 = 0x12,
Decimal128 = 0x13,
MinKey = 0xFF,
MaxKey = 0x7F
};
enum Subtype : u8 {
GenericBinarySubtype = 0x00,
Function = 0x01,
BinaryOld = 0x02,
UUIDOld = 0x03,
UUID = 0x04,
MD5 = 0x05,
EncryptedBSONValue = 0x06,
CompressedBSONColumn = 0x07,
UserDefined = 0x80
};
struct Binary {
s32 length;
Subtype subtype;
u8 data[length];
};
struct String {
u32 length [[hidden]];
char value[length];
} [[sealed, format("format_string")]];
struct CString {
char value[];
} [[sealed, format("format_string")]];
fn format_string(auto string) {
return string.value;
};
struct ObjectId {
type::time32_t timestamp;
u8 randomValue[5];
u24 counter;
};
struct DBPointer {
String name;
ObjectId value;
};
using Document;
struct Element {
Type type;
CString name;
if (type == Type::Double) {
double value;
} else if (type == Type::String) {
String value;
} else if (type == Type::EmbeddedDocument) {
Document value;
} else if (type == Type::Array) {
Document value;
} else if (type == Type::Binary) {
Binary value;
} else if (type == Type::Undefined) {
/* undefined */
} else if (type == Type::ObjectId) {
ObjectId value;
} else if (type == Type::Boolean) {
bool value;
} else if (type == Type::UTCDatetime) {
type::time64_t value;
} else if (type == Type::Null) {
/* null */
} else if (type == Type::Regex) {
CString regexPattern;
CString regexOptions;
} else if (type == Type::DBPointer) {
DBPointer value;
} else if (type == Type::JavaScript) {
String value;
} else if (type == Type::Symbol) {
String value;
} else if (type == Type::JavaScriptWithScope) {
String value;
} else if (type == Type::Int32) {
s32 value;
} else if (type == Type::Timestamp) {
u64 value;
} else if (type == Type::Int64) {
s64 value;
} else if (type == Type::Decimal128) {
u128 value;
}
};
struct Document {
s32 listLength;
Element elements[while($ < ((addressof(this) + listLength) - 1))];
padding[1];
};
Document document @ 0x00;
#pragma author WerWolv
#pragma description BSON (Binary JSON) format
#pragma MIME application/bson
#include <std/mem.pat>
#include <type/time.pat>
enum Type : u8 {
Double = 0x01,
String = 0x02,
EmbeddedDocument = 0x03,
Array = 0x04,
Binary = 0x05,
Undefined = 0x06,
ObjectId = 0x07,
Boolean = 0x08,
UTCDatetime = 0x09,
Null = 0x0A,
Regex = 0x0B,
DBPointer = 0x0C,
JavaScript = 0x0D,
Symbol = 0x0E,
JavaScriptWithScope = 0x0F,
Int32 = 0x10,
Timestamp = 0x11,
Int64 = 0x12,
Decimal128 = 0x13,
MinKey = 0xFF,
MaxKey = 0x7F
};
enum Subtype : u8 {
GenericBinarySubtype = 0x00,
Function = 0x01,
BinaryOld = 0x02,
UUIDOld = 0x03,
UUID = 0x04,
MD5 = 0x05,
EncryptedBSONValue = 0x06,
CompressedBSONColumn = 0x07,
UserDefined = 0x80
};
struct Binary {
s32 length;
Subtype subtype;
u8 data[length];
};
struct String {
u32 length [[hidden]];
char value[length];
} [[sealed, format("format_string")]];
struct CString {
char value[];
} [[sealed, format("format_string")]];
fn format_string(auto string) {
return string.value;
};
struct ObjectId {
type::time32_t timestamp;
u8 randomValue[5];
u24 counter;
};
struct DBPointer {
String name;
ObjectId value;
};
using Document;
struct Element {
Type type;
CString name;
if (type == Type::Double) {
double value;
} else if (type == Type::String) {
String value;
} else if (type == Type::EmbeddedDocument) {
Document value;
} else if (type == Type::Array) {
Document value;
} else if (type == Type::Binary) {
Binary value;
} else if (type == Type::Undefined) {
/* undefined */
} else if (type == Type::ObjectId) {
ObjectId value;
} else if (type == Type::Boolean) {
bool value;
} else if (type == Type::UTCDatetime) {
type::time64_t value;
} else if (type == Type::Null) {
/* null */
} else if (type == Type::Regex) {
CString regexPattern;
CString regexOptions;
} else if (type == Type::DBPointer) {
DBPointer value;
} else if (type == Type::JavaScript) {
String value;
} else if (type == Type::Symbol) {
String value;
} else if (type == Type::JavaScriptWithScope) {
String value;
} else if (type == Type::Int32) {
s32 value;
} else if (type == Type::Timestamp) {
u64 value;
} else if (type == Type::Int64) {
s64 value;
} else if (type == Type::Decimal128) {
u128 value;
}
};
struct Document {
s32 listLength;
Element elements[while($ < ((addressof(this) + listLength) - 1))];
padding[1];
};
Document documents[while(!std::mem::eof())] @ 0x00 [[inline]];

View File

@@ -1,3 +1,5 @@
#pragma description GoldSrc engine maps format (used in Half-Life 1)
#include <std/ptr.pat>
#include <std/mem.pat>
#include <std/sys.pat>

View File

@@ -1,3 +1,5 @@
#pragma description Command and Conquer Voxel Animation
// Command and conquer voxel animation format
struct vec4_s {

View File

@@ -1,3 +1,5 @@
#pragma description Command and Conquer Voxel Palette
// Command and conquer palette format
struct Color {

View File

@@ -1,3 +1,5 @@
#pragma description Command and Conquer Voxel Model
// Command and Conquer voxel model format
struct vec4_s {

31
patterns/cda.hexpat Normal file
View File

@@ -0,0 +1,31 @@
#pragma description Compact Disc Audio track
struct Header {
u32 RIFF;
s32 size;
u32 CDDA;
u32 fmt;
u32 lenghtofthechunck;
u16 versionofcdformat;
u16 numberofrange;
u32 identifier;
};
struct DataInfo {
u32 range;
u32 duration;
u8 rangepositionframes;
u8 rangepositionseconds;
u8 rangepositionminutes;
u8 nullbyte;
u8 durationtrackframes;
u8 durationtrackseconds;
u8 durationtrackminutes;
u8 nullbytee;
};
Header header @ 0;
DataInfo data @ 0x1C;

View File

@@ -1,395 +1,398 @@
#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;
#pragma author WerWolv
#pragma description Windows HtmlHelp Data (ITSF / CHM)
#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;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Common Object File Format (COFF) executable
#pragma MIME application/x-coff
#include <type/time.pat>

View File

@@ -1,66 +1,69 @@
#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 {
x : 3;
w : 3;
r : 3;
sticky : 1;
sgid : 1;
suid : 1;
file_type : 4;
};
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;
#pragma author WerWolv
#pragma description Old Binary CPIO Format
#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 {
x : 3;
w : 3;
r : 3;
sticky : 1;
sgid : 1;
suid : 1;
file_type : 4;
};
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;

View File

@@ -1,3 +1,5 @@
#pragma description DirectDraw Surface
#pragma MIME image/vnd-ms.dds
#pragma endian little

View File

@@ -1,3 +1,5 @@
#pragma description Dalvik EXecutable Format
#include <type/leb128.pat>
struct header_item {
@@ -170,5 +172,8 @@ struct Dex {
field_id_item field_ids[header.field_ids_size] @ header.field_ids_off;
method_id_item method_ids[header.method_ids_size] @ header.method_ids_off;
class_def_item class_defs[header.class_defs_size] @ header.class_defs_off;
u8 data[header.data_size] @header.data_off;
map_list map_list @ header.map_off;
u8 link_data[header.link_size] @ header.link_off;
};
Dex dex @ 0x00;
Dex dex @ 0x00;

5594
patterns/dicom.hexpat Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,5 @@
#pragma description Apple Disk Image Trailer (DMG)
#pragma endian big
#include <type/magic.pat>

View File

@@ -1,3 +1,5 @@
#pragma description .DS_Store file format
// Apple macOS .DS_Store format
#pragma endian big
#include <std/io.pat>

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description ELF header in elf binaries
#pragma MIME application/x-executable
#pragma MIME application/x-elf
#pragma MIME application/x-coredump
@@ -563,7 +566,7 @@ struct Elf32_Phdr {
PF p_flags;
Elf32_Word p_align;
if (p_offset > 0 && p_filesz > 0 && (p_offset + p_filesz) < std::mem::size() && p_filesz < std::mem::size())
if (p_offset >= 0 && p_filesz > 0 && (p_offset + p_filesz) <= std::mem::size() && p_filesz <= std::mem::size())
u8 p_data[p_filesz] @ p_offset [[sealed]];
};
@@ -577,7 +580,7 @@ struct Elf64_Phdr {
Elf64_Xword p_memsz;
Elf64_Xword p_align;
if (p_offset > 0 && p_filesz > 0 && (p_offset + p_filesz) < std::mem::size() && p_filesz < std::mem::size())
if (p_offset >= 0 && p_filesz > 0 && (p_offset + p_filesz) <= std::mem::size() && p_filesz <= std::mem::size())
u8 p_data[p_filesz] @ p_offset [[sealed]];
};
@@ -714,14 +717,9 @@ fn format_section_header(auto shdr) {
u32 i = 0;
u32 nameAddress = addressof(elf.shdr[stringTableIndex].stringTable) + shdr.sh_name;
while (i < std::core::member_count(elf.shdr[stringTableIndex].stringTable)) {
if (nameAddress >= addressof(elf.shdr[stringTableIndex].stringTable[i]) && nameAddress < (addressof(elf.shdr[stringTableIndex].stringTable[i]) + sizeof(elf.shdr[stringTableIndex].stringTable[i])))
break;
i += 1;
}
String string @ nameAddress;
return elf.shdr[stringTableIndex].stringTable[i].value;
return string;
};
@@ -819,4 +817,4 @@ fn main() {
);
}
}
};
};

View File

@@ -1,3 +1,5 @@
#pragma description MS Windows Vista Event Log
#pragma endian little
struct Header {

View File

@@ -0,0 +1,111 @@
#pragma author DmitriLeon2000
#pragma description Oska Software DeskMates FAS (Frames and Sequences) file
#pragma endian little
enum Compression : u32 {
BI_RGB,
BI_RLE8,
BI_RLE4,
BI_BITFIELDS,
BI_JPEG,
BI_PNG,
BI_ALPHABITFIELDS,
BI_CMYK,
BI_CMYKRLE8,
BI_CMYKRLE4,
};
struct Colors {
u8 blue;
u8 green;
u8 red;
u8 reserved;
};
struct FASHeader {
char name[50]; // name of the pack, may include garbage data
u16 version; // Format version number
s16 frameIDFirst; // assigned ID of the first frame
s16 frameIDLast; // assigned ID of the last frame
s32 width; // width of the animation (in pixels)
s32 height; // height of the animation (in pixels)
u16 frameSize; // size of the animation ((frameWidth * BPP + 31) // 32 * 4 * frameHeight)
u16 DblHeaderCount; // amount of BitmapInfoHeader pairs (one for color, one for masking)
};
struct BitmapInfoHeader { // bog-standard BitmapInfoHeaderV1
u32 biSize;
s32 biWidth;
s32 biHeight;
u16 biPlanes;
u16 biBitCount;
Compression compression;
u32 biSizeImage;
s32 biXPelsPerMeter;
s32 biYPelsPerMeter;
u32 biClrUsed;
u32 biClrImportant;
};
struct BitmapInfo {
BitmapInfoHeader header;
Colors colorMap[header.biClrUsed == 0 ?
1 << header.biBitCount : header.biClrUsed];
};
struct ExtraSprite {
char name[];
};
struct AnimSequence {
char name[];
char sequence[];
};
struct SeqHeader {
le u32 size;
le u32 count;
le u32 strPointers[count*2];
};
struct Bitmap {
u8 byte[fas.fasHeader.version >= 3 ? fas.fasHeader.frameSize + (fas.frameSizeHigh << 16) : fas.fasHeader.frameSize];
};
struct FramesHeader {
le u32 count;
le s16 frameID[count];
u8 frameDblHdrID[count];
};
struct FAS {
FASHeader fasHeader;
BitmapInfo dibHeaders[fasHeader.DblHeaderCount * 2];
if (fasHeader.version >= 1)
u8 charID;
if (fasHeader.version >= 2)
{
u32 extraEndOffset;
u16 extraSpritesCount;
if (extraSpritesCount)
// char extraSpriteList[touchOffset - 6];
ExtraSprite extraSprites[extraSpritesCount];
}
if (fasHeader.version >= 3)
le u16 frameSizeHigh;
le u16 touchColors;
if (touchColors)
{
u32 touchColorMap[touchColors];
u16 touchWidth;
u8 touchBitmap[this.touchWidth * fasHeader.height];
}
SeqHeader seqHeader;
if (fasHeader.version >= 1)
u8 filenameChecksum; // a checksum for a filename in ASCII
AnimSequence sequences[seqHeader.count];
FramesHeader framesHeader;
};
FAS fas @ 0x00;
Bitmap framesBitmap[fas.framesHeader.count] @ $;

View File

@@ -0,0 +1,87 @@
#pragma author DmitriLeon2000
#pragma description Oska Software DeskMates FAS (Frames and Sequences) file (Oska DeskMate versions 1.3 and 2.06)
#pragma endian little
enum Compression : u32 {
BI_RGB,
BI_RLE8,
BI_RLE4,
BI_BITFIELDS,
BI_JPEG,
BI_PNG,
BI_ALPHABITFIELDS,
BI_CMYK,
BI_CMYKRLE8,
BI_CMYKRLE4,
};
struct Colors {
u8 blue;
u8 green;
u8 red;
u8 reserved;
};
struct FASHeader {
s32 width; // width of the animation (in pixels)
s32 height; // height of the animation (in pixels)
u16 reserved1;
u16 reserved2;
u16 frameSizeCombined; // a sum of frameSizeColor and frameSizeMask
u16 frameSizeColor; // size of the animation ((frameWidth * 4 + 31) // 32 * 4 * frameHeight)
u16 frameSizeMask; // size of the animation's mask ((frameWidth * 1 + 31) // 32 * 4 * frameHeight)
u16 headerCount; // amount of DIB headers
};
struct BitmapInfoHeader { // bog-standard BitmapInfoHeaderV1
u32 biSize;
s32 biWidth;
s32 biHeight;
u16 biPlanes;
u16 biBitCount;
Compression compression;
u32 biSizeImage;
s32 biXPelsPerMeter;
s32 biYPelsPerMeter;
u32 biClrUsed;
u32 biClrImportant;
};
struct BitmapInfo {
BitmapInfoHeader header;
le u32 colorMap[header.biClrUsed == 0 ?
1 << header.biBitCount : header.biClrUsed];
};
struct AnimSequence {
char name[];
char sequence[];
};
struct SeqHeader {
le u32 size;
le u32 count;
le u32 strPointers[count*2];
};
struct Frame {
u8 colorBitmap[fas.fasHeader.frameSizeColor];
u8 maskBitmap[fas.fasHeader.frameSizeMask];
};
struct FramesHeader {
le u32 count;
le s16 frameID[count];
};
struct FAS {
FASHeader fasHeader;
BitmapInfo dibHeaders[fasHeader.headerCount];
SeqHeader seqHeader;
AnimSequence sequences[seqHeader.count];
FramesHeader framesHeader;
};
FAS fas @ 0x00;
Frame frames[fas.framesHeader.count] @ $;

125
patterns/fdt.hexpat Normal file
View File

@@ -0,0 +1,125 @@
#pragma author WerWolv
#pragma description Flat Linux Device Tree blob
#pragma endian big
#include <std/sys.pat>
#include <std/io.pat>
#include <std/core.pat>
#include <type/magic.pat>
#include <type/size.pat>
// These are used in order for the children to be able to find strings
u64 fdt_addr;
u64 str_offset;
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)];
} [[hidden]];
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
};
union FDTPropValue<auto len> {
u32 prop_array[len / sizeof(u32)];
char string[len];
};
struct FDTProp {
FDTToken tok[[hidden]];
u32 len [[hidden]];
u32 nameoff [[hidden]];
if (len > 0) {
// if len is zero, value is absent and no need to include it
FDTPropValue<len> value;
}
AlignTo<4>;
char name[] @ fdt_addr + str_offset + nameoff;
std::core::set_display_name(this, name);
std::print(std::format("{:x} token {} len {} {}",
$, tok, len,nameoff));
FDTToken token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
if (token != FDTToken::FDT_PROP) {
break;
}
};
struct FDTNode {
FDTToken token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
if (token == FDTToken::FDT_BEGIN_NODE) {
FDTToken tok[[hidden]];
char name[];
AlignTo<4>;
std::core::set_display_name(this, name[0] ? name : "/");
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
if(token == FDTToken::FDT_PROP) {
FDTProp props[while(true)];
}
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
if(token == FDTToken::FDT_END_NODE) {
FDTToken[[hidden]];
break;
}
FDTNode children[while(true)][[inline]];
} else if(token == FDTToken::FDT_NOP) {
// TODO this may break the pattern, I've so far not encountered it
}
// ew duplication
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
if(token == FDTToken::FDT_END_NODE) {
FDTToken[[hidden]];
break;
}
};
struct FDTStructureBlock {
FDTNode;
};
struct FDT {
FDTHeader header;
std::assert(header.version == 17, "Unsupported format version");
fdt_addr = addressof(this);
str_offset = header.off_dt_strings;
FDTStructureBlock structureBlocks @ fdt_addr + header.off_dt_struct;
FDTReserveEntry reserveEntries[while(true)] @ fdt_addr + header.off_mem_rsvmap;
};
std::mem::MagicSearch<"\xD0\x0D\xFE\xED", FDT> fdt @ std::mem::base_address();

View File

@@ -1,70 +0,0 @@
#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;

1
patterns/ffx Submodule

Submodule patterns/ffx added at ad18b0259f

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Free Lossless Audio Codec, FLAC Audio Format
#include <std/sys.pat>
#include <std/core.pat>
#include <std/io.pat>
@@ -138,7 +141,7 @@ enum PICTURE_TYPE : u32 {
struct METADATA_BLOCK_PICTURE {
PICTURE_TYPE pictureType;
u32 mimeTypeLength;
char mimeType[mineTypeLength];
char mimeType[mimeTypeLength];
u32 descriptionLength;
char description[descriptionLength];
u32 width, height;
@@ -304,6 +307,8 @@ struct METADATA_BLOCK {
METADATA_BLOCK_PADDING data;
else if (header.blockType == BLOCK_TYPE::APPLICATION)
METADATA_BLOCK_APPLICATION data;
else if (header.blockType == BLOCK_TYPE::SEEKTABLE)
METADATA_BLOCK_SEEKTABLE data;
else if (header.blockType == BLOCK_TYPE::VORBIS_COMMENT)
METADATA_BLOCK_VORBIS_COMMENT data;
else if (header.blockType == BLOCK_TYPE::CUESHEET)
@@ -320,4 +325,4 @@ struct STREAM {
//FRAME frames[while(!std::mem::eof())];
};
STREAM stream @ 0x00;
STREAM stream @ 0x00;

View File

@@ -1,168 +1,171 @@
#include <std/io.pat>
struct DiskTimeStamp {
u8 seconds, minutes, hours;
};
enum DiskProtection : u16 {
None = 0x0000,
CopyProtected = 0x5A5A
};
bitfield CHS {
h : 8;
s : 6;
c : 10;
} [[format("chs_formatter")]];
fn chs_formatter(CHS chs) {
return std::format("({:X}, {:X}, {:X}) | 0x{:X}", chs.c, chs.h, chs.s, (chs.c * 16 + chs.h) * 63 + (chs.s - 1));
};
enum PartitionStatus : u8 {
None = 0x00,
Active = 0x80
};
enum PartitionType : u8 {
EmptyPartitionEntry = 0x00,
FAT32_CHS = 0x0B,
FAT32_LBA = 0x0C
};
namespace fat32 {
u64 bytesPerCluster;
struct FSInfo {
u32 leadSignature;
padding[480];
u32 structSignature;
u32 freeClusterCount;
u32 nextFreeCluster;
padding[12];
u32 trailSignature;
};
bitfield SequenceNumber {
padding : 1;
lastLogical : 1;
padding : 1;
number : 5;
} [[left_to_right]];
enum EntryStatus : u8 {
Regular = 0x00,
DotEntry = 0x2E,
DeletedEntry = 0xE5
};
union EntryStatusOrSequenceNumber {
EntryStatus entryStatus;
SequenceNumber sequenceNumber;
};
bitfield Attributes {
readOnly : 1;
hidden : 1;
systemFile : 1;
volumeLabel : 1;
subdirectory : 1;
archive : 1;
padding : 2;
} [[right_to_left]];
struct DirEntry {
char fileName[8];
char extension[3];
Attributes attributes;
u8 reserved[10];
u16 time, date;
u16 startingCluster;
u32 fileSize;
u8 data[fileSize] @ startingCluster * bytesPerCluster;
};
struct VFATDirEntry {
EntryStatusOrSequenceNumber entryStatusOrSequenceNumber;
char16 name1[5];
Attributes attributes;
u8 type;
u8 nameChecksum;
char16 name2[6];
u16 startingCluster;
char16 name3[2];
if (entryStatusOrSequenceNumber.sequenceNumber.number > 1)
VFATDirEntry nextLogicalEntry;
else
DirEntry physicalEntry;
};
struct Partition {
u8 jmpCode[3];
char oemName[8];
u16 bytesPerSector;
u8 sectorsPerCluster;
u16 reservedAreaSize;
u8 numFats;
u16 rootEntryCount;
u16 numSectors;
u8 mediaType;
u16 fatSize;
u16 sectorsPerTrack;
u16 numHeads;
u32 numHiddenSectors;
u32 numFsSectors;
u32 numFatSectors;
u16 extFlags;
u16 fsVersion;
u32 rootCluster;
u16 fsInfoSector;
u16 backupBootSector;
padding[12];
u8 driveNumber;
padding[1];
u8 bootSignature;
u32 volumeID;
char volumeLabel[11];
char fsType[8];
u8 bootstrapCode[420];
u16 signature;
bytesPerCluster = (sectorsPerCluster * 1024) * bytesPerSector;
FSInfo fsInfo @ addressof(this) + fsInfoSector * bytesPerSector;
VFATDirEntry rootDirEntry @ addressof(this) + rootCluster * bytesPerCluster;
};
}
struct PartitionEntry {
PartitionStatus status;
CHS chsFirstSectorAddress;
PartitionType type;
CHS chsLastSectorAddress;
u32 lbaFirstSectorAddress;
u32 numSectors;
if (type == PartitionType::EmptyPartitionEntry)
continue;
else if (type == PartitionType::FAT32_CHS || type == PartitionType::FAT32_LBA)
fat32::Partition partition @ lbaFirstSectorAddress * 512;
};
struct MasterBootRecord {
u8 bootstrapCodeArea1[218];
padding[2];
u8 originalPhysicalDrive;
DiskTimeStamp diskTimeStamp;
u8 bootstrapCodeArea2[216];
u32 diskSignature;
DiskProtection diskProtection;
PartitionEntry partitionEntries[4];
u16 bootSignature;
};
#pragma author WerWolv
#pragma description Drive File System
#include <std/io.pat>
struct DiskTimeStamp {
u8 seconds, minutes, hours;
};
enum DiskProtection : u16 {
None = 0x0000,
CopyProtected = 0x5A5A
};
bitfield CHS {
h : 8;
s : 6;
c : 10;
} [[format("chs_formatter")]];
fn chs_formatter(CHS chs) {
return std::format("({:X}, {:X}, {:X}) | 0x{:X}", chs.c, chs.h, chs.s, (chs.c * 16 + chs.h) * 63 + (chs.s - 1));
};
enum PartitionStatus : u8 {
None = 0x00,
Active = 0x80
};
enum PartitionType : u8 {
EmptyPartitionEntry = 0x00,
FAT32_CHS = 0x0B,
FAT32_LBA = 0x0C
};
namespace fat32 {
u64 bytesPerCluster;
struct FSInfo {
u32 leadSignature;
padding[480];
u32 structSignature;
u32 freeClusterCount;
u32 nextFreeCluster;
padding[12];
u32 trailSignature;
};
bitfield SequenceNumber {
padding : 1;
lastLogical : 1;
padding : 1;
number : 5;
} [[left_to_right]];
enum EntryStatus : u8 {
Regular = 0x00,
DotEntry = 0x2E,
DeletedEntry = 0xE5
};
union EntryStatusOrSequenceNumber {
EntryStatus entryStatus;
SequenceNumber sequenceNumber;
};
bitfield Attributes {
readOnly : 1;
hidden : 1;
systemFile : 1;
volumeLabel : 1;
subdirectory : 1;
archive : 1;
padding : 2;
} [[right_to_left]];
struct DirEntry {
char fileName[8];
char extension[3];
Attributes attributes;
u8 reserved[10];
u16 time, date;
u16 startingCluster;
u32 fileSize;
u8 data[fileSize] @ startingCluster * bytesPerCluster;
};
struct VFATDirEntry {
EntryStatusOrSequenceNumber entryStatusOrSequenceNumber;
char16 name1[5];
Attributes attributes;
u8 type;
u8 nameChecksum;
char16 name2[6];
u16 startingCluster;
char16 name3[2];
if (entryStatusOrSequenceNumber.sequenceNumber.number > 1)
VFATDirEntry nextLogicalEntry;
else
DirEntry physicalEntry;
};
struct Partition {
u8 jmpCode[3];
char oemName[8];
u16 bytesPerSector;
u8 sectorsPerCluster;
u16 reservedAreaSize;
u8 numFats;
u16 rootEntryCount;
u16 numSectors;
u8 mediaType;
u16 fatSize;
u16 sectorsPerTrack;
u16 numHeads;
u32 numHiddenSectors;
u32 numFsSectors;
u32 numFatSectors;
u16 extFlags;
u16 fsVersion;
u32 rootCluster;
u16 fsInfoSector;
u16 backupBootSector;
padding[12];
u8 driveNumber;
padding[1];
u8 bootSignature;
u32 volumeID;
char volumeLabel[11];
char fsType[8];
u8 bootstrapCode[420];
u16 signature;
bytesPerCluster = (sectorsPerCluster * 1024) * bytesPerSector;
FSInfo fsInfo @ addressof(this) + fsInfoSector * bytesPerSector;
VFATDirEntry rootDirEntry @ addressof(this) + rootCluster * bytesPerCluster;
};
}
struct PartitionEntry {
PartitionStatus status;
CHS chsFirstSectorAddress;
PartitionType type;
CHS chsLastSectorAddress;
u32 lbaFirstSectorAddress;
u32 numSectors;
if (type == PartitionType::EmptyPartitionEntry)
continue;
else if (type == PartitionType::FAT32_CHS || type == PartitionType::FAT32_LBA)
fat32::Partition partition @ lbaFirstSectorAddress * 512;
};
struct MasterBootRecord {
u8 bootstrapCodeArea1[218];
padding[2];
u8 originalPhysicalDrive;
DiskTimeStamp diskTimeStamp;
u8 bootstrapCodeArea2[216];
u32 diskSignature;
DiskProtection diskProtection;
PartitionEntry partitionEntries[4];
u16 bootSignature;
};
MasterBootRecord mbr @ 0x00;

361
patterns/gb.hexpat Normal file
View File

@@ -0,0 +1,361 @@
#pragma author WerWolv
#pragma description Gameboy ROM
#pragma MIME application/x-gameboy-rom
#include <type/size.pat>
#include <std/string.pat>
#include <std/mem.pat>
bool uppercaseROMFeatures in;
bool brandedROMFeatures in;
bitfield CGB {
padding : 2;
PGB_MODE : 2;
padding : 2;
CGB_ONLY : 1 [[comment("gbcOnly")]];
CGB_SUPPORT : 1 [[comment("supportsGBC")]];
} [[comment("GBCFlags")]];
namespace format {
fn cart_size(u8 cartSizeType) {
u32 romSize = 32768 * (1 << cartSizeType);
u16 romBanks = 2 * (1 << cartSizeType);
if (cartSizeType == 0x52) {
romSize = 1153434;
romBanks = 72;
}
if (cartSizeType == 0x53) {
romSize = 1258291;
romBanks = 80;
}
return std::format("size: {}, banks: {}", type::impl::size_formatter(romSize), romBanks);
};
fn ram_type(u8 ramType) {
u16 ramSize;
u16 ramBanks;
if(ramType == 2) {
ramSize = 8192;
ramBanks = 1;
}
if(ramType == 3) {
ramSize = 32768;
ramBanks = 4;
}
if(ramType == 4) {
ramSize = 131072;
ramBanks = 16;
}
if(ramType == 5) {
ramSize = 65536;
ramBanks = 8;
}
return std::format("size: {}, banks: {}", type::impl::size_formatter(ramSize), ramBanks);
};
fn rom_features(u8 type) {
str result = "( ";
if (brandedROMFeatures) match(type) {
(0xFC): result += "pocket ";
(0xFD): result += "bandai ";
}
match(type) {
(0x00): result += "no_mbc";
(0x01): result += "mbc1";
(0x02): result += "mbc1 | ram";
(0x03): result += "mbc1 | ram | battery";
(0x05): result += "mbc2";
(0x06): result += "mbc2 | battery";
(0x08): result += "no_mbc | ram";
(0x09): result += "no_mbc | ram | battery";
(0x0B): result += "mmm01";
(0x0C): result += "mmm01 | ram";
(0x0D): result += "mmm01 | ram | battery";
(0x0F): result += "mbc3 | timer | battery";
(0x10): result += "mbc3 | timer | ram | battery";
(0x11): result += "mbc3";
(0x12): result += "mbc3 | ram";
(0x13): result += "mbc3 | ram | battery";
(0x19): result += "mbc5";
(0x1A): result += "mbc5 | ram";
(0x1B): result += "mbc5 | ram | battery";
(0x1C): result += "mbc5 | rumble";
(0x1D): result += "mbc5 | rumble | ram";
(0x1E): result += "mbc5 | rumble | ram | battery";
(0x20): result += "mbc6";
(0x22): result += "mbc7 | sensor | rumble";
(0xFC): result += "camera";
(0xFD): result += "tama5";
(0xFE): result += "huc3";
(0xFF): result += "huc1 | ram | battery";
}
if (uppercaseROMFeatures) result = std::string::to_upper(result);
return result + " )";
};
fn licensee_code(u8 code) {
match(code) {
(0x00): return "None";
(0x01 | 0x31): return "Nintendo";
(0x08 | 0x38): return "Capcom";
(0x09): return "Hot-B";
(0x0A | 0xE0): return "Jaleco";
(0x0B): return "Coconuts Japan";
(0x0C | 0x6E): return "Elite Systems";
(0x13 | 0x69): return "EA (Electronic Arts)";
(0x18): return "Hudsonsoft";
(0x19): return "ITC Entertainment";
(0x1A): return "Yanoman";
(0x1D): return "Japan Clary";
(0x1F | 0x4A | 0x61): return "Virgin Interactive";
(0x24): return "PCM Complete";
(0x25): return "San-X";
(0x28): return "Kotobuki Systems";
(0x29): return "Seta";
(0x30 | 0x70): return "Infogrames";
(0x32 | 0xA2 | 0xB2 | 0xC4): return "Bandai";
(0x33): return "See new licensee code";
(0x34 | 0xA4): return "Konami";
(0x35): return "HectorSoft";
(0x39 | 0x9D): return "Banpresto";
(0x3C): return ".Entertainment i";
(0x3E): return "Gremlin";
(0x41): return "Ubisoft";
(0x42 | 0xEB): return "Atlus";
(0x44 | 0x4D): return "Malibu";
(0x46 | 0xCF): return "Angel";
(0x47): return "Spectrum Holoby";
(0x49): return "Irem";
(0x50): return "Absolute";
(0x51 | 0xB0): return "Acclaim";
(0x52): return "Activision";
(0x53): return "American Sammy";
(0x54): return "GameTek";
(0x55): return "Park Place";
(0x56 | 0xDB | 0xFF): return "LJN";
(0x57): return "Matchbox";
(0x59): return "Milton Bradley";
(0x5A): return "Mindscape";
(0x5B): return "Romstar";
(0x5C | 0xD6): return "Naxat Soft";
(0x5D): return "Tradewest";
(0x60): return "Titus";
(0x67): return "Ocean Interactive";
(0x6F): return "Electro Brain";
(0x71): return "Interplay";
(0x72 | 0xAA): return "Broderbund";
(0x73): return "Sculptered Soft";
(0x75): return "The Sales Curve";
(0x78): return "t.hq";
(0x79): return "Accolade";
(0x7A): return "Triffix Entertainment";
(0x7C): return "Microprose";
(0x7F | 0xC2): return "Kemco";
(0x80): return "Misawa Entertainment";
(0x83): return "Lozc";
(0x86 | 0xC4): return "Tokuma Shoten Intermedia";
(0x8B): return "Bullet-Proof Software";
(0x8C): return "Vic Tokai";
(0x8E): return "Ape";
(0x8F): return "I'Max";
(0x91): return "Chunksoft Co.";
(0x92): return "Video System";
(0x93): return "Tsubaraya Productions Co.";
(0x95): return "Varie Corporation";
(0x96): return "Yonezawa/SPal";
(0x97): return "Kaneko";
(0x99): return "Arc";
(0x9A): return "Nihon Bussan";
(0x9B): return "Tecmo";
(0x9C): return "Imagineer";
(0x9F): return "Nova";
(0xA1): return "Hori Electric";
(0xA6): return "Kawada";
(0xA7): return "Takara";
(0xA9): return "Technos Japan";
(0xAC): return "Toei Animation";
(0xAD): return "Toho";
(0xAF): return "Namco";
(0xB1): return "ASCII or Nexsoft";
(0xB4): return "Square Enix";
(0xB6): return "HAL Laboratory";
(0xB7): return "SNK";
(0xB9 | 0xCE): return "Pony Canyon";
(0xBA): return "Culture Brain";
(0xBB): return "Sunsoft";
(0xBD): return "Sony Imagesoft";
(0xBF): return "Sammy";
(0xC0 | 0xD0): return "Taito";
(0xC3): return "Squaresoft";
(0xC5): return "Data East";
(0xC6): return "Tonkinhouse";
(0xC8): return "Koei";
(0xC9): return "UFL";
(0xCA): return "Ultra";
(0xCB): return "Vap";
(0xCC): return "Use Corporation";
(0xCD): return "Meldac";
(0xD1): return "Sofel";
(0xD2): return "Quest";
(0xD3): return "Sigma Enterprises";
(0xD4): return "ASK Kodansha Co.";
(0xD7): return "Copya System";
(0xDA): return "Tomy";
(0xDD): return "NCS";
(0xDE): return "Human";
(0xDF): return "Altron";
(0xE1): return "Towa Chiki";
(0xE2): return "Yutaka";
(0xE3): return "Varie";
(0xE5): return "Epoch";
(0xE7): return "Athena";
(0xE8): return "Asmik";
(0xE9): return "Natsume";
(0xEA): return "King Records";
(0xEE): return "IGS";
(0xF0): return "A Wave";
(0xF3): return "Extreme Entertainment";
}
return "Unknown Licensee";
};
fn new_licensee_code(str a) {
if (std::mem::read_unsigned(0x14B, 1) != 0x33) return "See old licensee code";
match(a) {
("00"): return "None";
("01"): return "Nintendo R&D1";
("08"): return "Capcom";
("13"): return "Electronic Arts";
("18"): return "Hudson Soft";
("19"): return "b-ai";
("20"): return "KSS";
("22"): return "pow";
("24"): return "PCM Complete";
("25"): return "san-x";
("28"): return "Kemco Japan";
("29"): return "seta";
("30"): return "Viacom";
("31"): return "Nintendo";
("32"): return "Bandai";
("33"): return "Ocean/Acclaim";
("34"): return "Konami";
("35"): return "Hector";
("37"): return "Taito";
("38"): return "Hudson";
("39"): return "Banpresto";
("41"): return "Ubi Soft";
("42"): return "Atlus";
("44"): return "Malibu";
("46"): return "Angel";
("47"): return "Bullet-Proof Software";
("49"): return "irem";
("50"): return "Absolute";
("51"): return "Acclaim";
("52"): return "Activision";
("53"): return "American Sammy";
("54"): return "Konami";
("55"): return "Hi tech entertainment";
("56"): return "LJN";
("57"): return "Matchbox";
("58"): return "Mattel";
("59"): return "Milton Bradley";
("60"): return "Titus";
("61"): return "Virgin";
("64"): return "LucasArts";
("67"): return "Ocean";
("69"): return "Electronic Arts";
("70"): return "Infogrames";
("71"): return "Interplay";
("72"): return "Broderbund";
("73"): return "sculptured";
("75"): return "sci";
("78"): return "THQ";
("79"): return "Accolade";
("80"): return "misawa";
("83"): return "lozc";
("86"): return "Tokuma Shoten Intermedia";
("87"): return "Tsukuda Original";
("91"): return "Chunksoft";
("92"): return "Video system";
("93"): return "Ocean/Acclaim";
("95"): return "Varie";
("96"): return "Yonezawa/spal";
("97"): return "Kaneko";
("99"): return "Pack in soft";
("A4"): return "Konami (Yu-Gi-Oh!)";
}
return "Unknown";
};
using CGB;
fn null_cgb_flags(CGB flags) {
return "NO_CGB";
};
}
enum DestinationType : u8 {
Japanese,
NonJapanese
};
enum SGBFlagType : u8 {
NoSGBFunctionality,
SGBFunctionality = 0x03
};
struct Header {
char title[16-(std::mem::read_unsigned(addressof(this)+15, 1) >= 0x80)];
if (std::mem::read_unsigned(addressof(this)+15, 1) == 0)
CGB gbcFlags @ $-1 [[format("format::null_cgb_flags")]];
else if (std::mem::read_unsigned(addressof(this)+15, 1) >= 0x80)
CGB gbcFlags;
char newLicenseeCode[2] [[format("format::new_licensee_code")]];
SGBFlagType sgbFlag;
u8 romType [[format("format::rom_features")]];
u8 cartSize [[format("format::cart_size")]];
u8 ramType [[format("format::ram_type")]];
DestinationType destination;
u8 licenseeCode [[format("format::licensee_code")]];
u8 maskROMVersionNumber;
u8 headerChecksum [[comment("Checksum for: $134-$14C")]];
u16 globalChecksum [[comment("Checksum for entire range")]];
};
bitfield pixel_packed {
p1 : 1;
p2 : 1;
p3 : 1;
p4 : 1;
p5 : 1;
p6 : 1;
p7 : 1;
p8 : 1;
};
struct CartridgeStart {
u8 entryCode[4];
pixel_packed logo[0x30];
Header header;
};
struct JumpVectors {
u8 rst1[8] [[comment("rst $1")]];
u8 rst2[8] [[comment("rst $2")]];
u8 rst3[8] [[comment("rst $3")]];
u8 rst4[8] [[comment("rst $4")]];
u8 rst5[8] [[comment("rst $5")]];
u8 rst6[8] [[comment("rst $6")]];
u8 rst7[8] [[comment("rst $7")]];
u8 rst8[8] [[comment("rst $8")]];
u8 int1[8] [[comment("vblank")]];
u8 int2[8] [[comment("lcd stat")]];
u8 int3[8] [[comment("timer")]];
u8 int4[8] [[comment("serial")]];
u8 int5[8] [[comment("joypad")]];
};
JumpVectors jumpVectors @ 0x00 [[comment("Instructions called on interrupts or RST instructions")]];
CartridgeStart cartridgeStart @ 0x100;

View File

@@ -1,20 +1,25 @@
#pragma description GIF image files
#pragma MIME image/gif
// Extension Labels
#define LABEL_GC 0xF9
#define LABEL_COMMENT 0xFE
#define LABEL_APPLICATION 0xFF
#define LABEL_PLAINTEXT 0x01
#define LABEL_APPLICATION_NETSCAPE "NETSCAPE"
#define CODE_FRAME 0x2C
#define CODE_EXTENSION 0x21
#define CODE_TRAILER 0x3B
#define MAX_BLOCKS 4096
#define GCT_ACCESS parent.parent.parent.parent.header.gct
// Indentifier Magics
#define IMAGE_SEPERATOR_MAGIC 0x2C
#define EXTENSION_INTRODUCER_MAGIC 0x21
#define GIF_TRAILER_MAGIC 0x3B
#include <std/io.pat>
#include <std/core.pat>
#include <std/mem.pat>
#include <std/string.pat>
#include <std/math.pat>
#pragma MIME image/gif
#include <type/magic.pat>
bitfield GCT_Flags {
size : 3 [[comment("physical size = 2^(flags.size + 1)")]];
@@ -23,106 +28,114 @@ bitfield GCT_Flags {
enabled : 1;
};
bitfield LCT_Flags {
size : 3 [[comment("physical size = 2^(flags.size + 1)")]];
padding : 2;
sort : 1 [[comment("Indicates if the table is sorted by importance")]];
interlace : 1;
enable : 1;
bitfield ImageDescriptorFlags {
lctSize: 3;
reserved: 2;
lctSort: 1;
interlaceFlag: 1;
lctEnable: 1;
};
bitfield GC_Flags {
bitfield GCE_Flags {
transparent : 1;
userInput : 1;
disposalMode : 3 [[format("format::dispose_enum")]];
reserved : 3;
};
struct color {
u8 r, g, b;
} [[color(std::format("{:02X}{:02X}{:02X}", r, g, b))]];
struct Color {
u8 red;
u8 green;
u8 blue;
} [[color(std::format("{:02X}{:02X}{:02X}", red, green, blue))]];
struct subblock {
u8 size;
if(size == 0) break;
u8 data[size];
struct _SubBlocks {
u8 data_size;
u8 data[data_size];
};
struct block {
subblock blocks[MAX_BLOCKS];
};
fn exp2(auto n) {
return 1 << n;
struct DataSubBlocks {
_SubBlocks subBlocks[while(std::mem::read_unsigned($, 1) != 0)];
};
struct Header {
char magic[3];
type::Magic<"GIF"> magic;
char version[3];
};
struct LogicalScreenDescriptor {
u16 width;
u16 height;
GCT_Flags gctFlags;
u8 bgColorIndex;
u8 pixelAscpet;
if (gctFlags.enabled) {
color gct[(exp2(gctFlags.size + 1))];
color bgColor = gct[bgColorIndex];
Color gct[std::math::pow(2, gctFlags.size + 1)];
}
};
};
struct frame {
u16 x;
u16 y;
u16 width;
u16 height;
LCT_Flags lctFlags;
if(lctFlags.enable) {
color lct[(exp2(lctFlags.size + 1))];
struct ImageDescriptor {
u16 imageLeftPosition;
u16 imageTopPosition;
u16 imageWidth;
u16 imageHeight;
ImageDescriptorFlags flags;
if(flags.lctEnable) {
Color lct[std::math::pow(2, flags.lctSize + 1)];
}
u8 lzwMinCode [[comment("This byte determines the initial number of bits used for LZW codes in the image data")]];
block lzwCompressedData [[comment("Data is pallet indecies either into current LDC or GCT and is compressed using LZW")]];
DataSubBlocks lzwCompressedData [[comment("Data is pallet indecies either into current LDC or GCT and is compressed using LZW")]];
};
struct comment {
block data [[hidden]];
char comment[] @ addressof(data.blocks) + 1; // TODO : need to find a better way of doing this
struct CommentExtension {
DataSubBlocks commentData;
};
struct application {
u8 blockSize [[hidden]];
char identifier[8] [[comment("Only known are: NETSCAPE")]];
char version[3] [[comment("Only known for NETSCAPE: '2.0'")]];
block b [[hidden]];
if(identifier == LABEL_APPLICATION_NETSCAPE) {
u16 loopcount @ addressof(b.blocks[0].data) + 1 [[comment("0, = Forever")]];
}
struct ApplicationExtension {
u8 blockSize;
char identifier[8];
char authenticationCode[3];
DataSubBlocks applicationData;
};
struct plaintext {
u8 blockSize [[hidden]];
u16 gridLeftPos;
u16 gridTopPos;
u16 gridWidth;
u16 gridHeight;
u8 cellWidth;
u8 cellHeight;
u8 textForegroundColorIndex [[hidden]];
u8 textBackgroundColorIndex [[hidden]];
color textForegroundColor @ addressof(GCT_ACCESS[textForegroundColorIndex]);
color textBackgroundColor @ addressof(GCT_ACCESS[textBackgroundColorIndex]);
block data [[hidden]];
char text[] @ addressof(data.blocks) + 1;
//char text[data.blocks[std::core::array_index()].size] @ addressof(data.blocks[std::core::array_index()].data);
struct PlainTextExtension {
u8 blockSize;
u16 textGridLeftPos;
u16 textGridTopPos;
u16 textGridWidth;
u16 textGridHeight;
u8 charCellWidth;
u8 charCellHeight;
u8 textForegroundColorIndex;
u8 textBackgroundColorIndex;
DataSubBlocks plainTextData;
};
struct graphical_control {
u8 blockSize [[hidden]];
GC_Flags flags;
struct GraphicControlExtension {
u8 blockSize;
std::assert_warn(blockSize == 4, "Unexpected GCE block size");
GCE_Flags flags;
u16 delay [[format("format::delay")]];
u8 transparentColorIndex;
block b [[hidden]];
};
struct Extension {
u8 label [[format("format::extension_name")]];
if(label == LABEL_GC) GraphicControlExtension gce [[inline]];
if(label == LABEL_COMMENT) CommentExtension c [[inline]];
if(label == LABEL_APPLICATION) ApplicationExtension a [[inline]];
if(label == LABEL_PLAINTEXT) PlainTextExtension p [[inline]];
};
struct Block {
u8 identifier [[format("format::identifier_name")]];
if(identifier == IMAGE_SEPERATOR_MAGIC) ImageDescriptor i [[inline]];
if(identifier == EXTENSION_INTRODUCER_MAGIC) Extension e [[inline]];
if(identifier == GIF_TRAILER_MAGIC) break;
u8 blockTerminator;
} [[format("format::block_name")]];
namespace format {
fn dispose_enum(u8 value) {
if(value == 0x00) return "Do nothing";
@@ -139,11 +152,18 @@ namespace format {
return "Unknown Extension";
};
fn content_name(ref frame f) {
if(f.code == CODE_FRAME) return "Frame";
if(f.code == CODE_EXTENSION) return "Extension";
if(f.code == CODE_TRAILER) return "End";
return "Unknown Content";
fn block_name(ref Block b) {
if(b.identifier == IMAGE_SEPERATOR_MAGIC) return "Image Descriptor";
if(b.identifier == EXTENSION_INTRODUCER_MAGIC) return "Extension";
if(b.identifier == GIF_TRAILER_MAGIC) return "Trailer";
return "Unknown Block Type";
};
fn identifier_name(u8 identifier) {
if(identifier == IMAGE_SEPERATOR_MAGIC) return "Image Separator";
if(identifier == EXTENSION_INTRODUCER_MAGIC) return "Extension Introducer";
if(identifier == GIF_TRAILER_MAGIC) return "GIF Trailer";
return "Unknown Identifier";
};
fn delay(u16 delay) {
@@ -154,28 +174,12 @@ namespace format {
};
}
struct extension {
u8 label [[format("format::extension_name")]];
if(label == LABEL_GC) graphical_control gc [[inline]];
if(label == LABEL_COMMENT) comment c [[inline]];
if(label == LABEL_APPLICATION) application a [[inline]];
if(label == LABEL_PLAINTEXT) plaintext [[inline]];
};
struct content {
u8 code [[hidden]];
if(code == CODE_FRAME) frame f [[inline]];
if(code == CODE_EXTENSION) extension e [[inline]];
if(code == CODE_TRAILER) break;
} [[format("format::content_name")]];
struct Data {
content contents[while(!std::mem::eof())] [[inline]];
};
struct Gif {
u8 data[std::mem::size()] [[no_unique_address, hidden]];
Header header;
Data data;
};
std::assert_warn(header.version == "89a" || header.version == "87a", "Unsupported format version");
LogicalScreenDescriptor logicalScreenDescriptor;
Block blocks[while(!std::mem::eof())];
} [[hex::visualize("image", this.data)]];
Gif gif @ 0x00;

66
patterns/gltf.hexpat Normal file
View File

@@ -0,0 +1,66 @@
/**
* @file <gltf.pat> ImHex Pattern for glTF binary files.
*
* Copyright (c) 2023 H. Utku Maden <utkumaden@hotmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <std/mem.pat>
#include <std/io.pat>
/**
* @brief The glTF magic section.
*/
struct gltf_magic_t {
char magic[4]; /**< The magic value. Must be "glTF" */
u32 version; /**< The version. Must be 2 for glTF 2.0. */
u32 length; /**< Length of the file in bytes, including magic section. */
};
/**
* @brief Enumeration of well defined glTF chunks.
*/
enum gltf_chunk_type_t : u32 {
JSON = 1313821514 /* "JSON" */, /**< JSON chunk. */
BIN = 5130562 /* "BIN\0" */, /**< Binary data chunk. Could be an image or model data. */
};
/**
* @brief A glTF chunk.
*/
struct gltf_chunk_t {
u32 length; /**< Length of this chunk. */
gltf_chunk_type_t type [[format("gltf_format")]]; /**< Type of the chunk. JSON or BIN expected. */
u8 string[length]; /**< The chunk data. */
};
fn gltf_format(gltf_chunk_type_t x)
{
if (x == gltf_chunk_type_t::JSON) return "JSON";
else if (x == gltf_chunk_type_t::BIN) return "BIN";
return "";
};
gltf_magic_t magic @ 0x00;
gltf_chunk_t chunks[while(!std::mem::eof())] @ $;
if (magic.magic != "glTF")
std::error("This file might not be a glTF file, expected \"glTF\", got %s", magic.magic);

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description GZip compressed data format
#pragma MIME application/gzip
#include <type/time.pat>

536
patterns/hinf_bitmap.hexpat Normal file
View File

@@ -0,0 +1,536 @@
#include <std/mem.pat>
#include <std/io.pat>
#include <std/string.pat>
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;

441
patterns/hinf_luas.hexpat Normal file
View File

@@ -0,0 +1,441 @@
#pragma author Surasia
#pragma description Halo Infinite HavokScript 5.1 "luas" file
#include <std/io.pat>
#include <std/mem.pat>
#include <std/core.pat>
#include <std/string.pat>
struct String32 {
s32 length;
if (length != 0) {
char s[length - 1];
u8 endbyte;
}
};
struct String64 {
s64 length;
if (length != 0) {
char s[length - 1];
u8 endbyte;
}
};
enum lua_endian : u8 {
little_endian = 1,
big_endian = 0,
};
enum lua_numbertype : u8 {
_float = 0,
_int32 = 1,
};
struct lua_enum {
s32 value;
String32 string;
};
struct LuaEnum {
s32 count;
lua_enum entries[count];
};
enum HksOpCode : s8 {
GETFIELD,
TEST,
CALL_I,
CALL_C,
EQ,
EQ_BK,
GETGLOBAL,
MOVE,
SELF,
RETURN,
GETTABLE_S,
GETTABLE_N,
GETTABLE,
LOADBOOL,
TFORLOOP,
SETFIELD,
SETTABLE_S,
SETTABLE_S_BK,
SETTABLE_N,
SETTABLE_N_BK,
SETTABLE,
SETTABLE_BK,
TAILCALL_I,
TAILCALL_C,
TAILCALL_M,
LOADK,
LOADNIL,
SETGLOBAL,
JMP,
CALL_M,
CALL,
INTRINSIC_INDEX,
INTRINSIC_NEWINDEX,
INTRINSIC_SELF,
INTRINSIC_LITERAL,
INTRINSIC_NEWINDEX_LITERAL,
INTRINSIC_SELF_LITERAL,
TAILCALL,
GETUPVAL,
SETUPVAL,
ADD,
ADD_BK,
SUB,
SUB_BK,
MUL,
MUL_BK,
DIV,
DIV_BK,
MOD,
MOD_BK,
POW,
POW_BK,
NEWTABLE,
UNM,
NOT,
LEN,
LT,
LT_BK,
LE,
LE_BK,
CONCAT,
TESTSET,
FORPREP,
FORLOOP,
SETLIST,
CLOSE,
CLOSURE,
VARARG,
TAILCALL_I_R1,
CALL_I_R1,
SETUPVAL_R1,
TEST_R1,
NOT_R1,
GETFIELD_R1,
SETFIELD_R1,
NEWSTRUCT,
DATA,
SETSLOTN,
SETSLOTI,
SETSLOT,
SETSLOTS,
SETSLOTMT,
CHECKTYPE,
CHECKTYPES,
GETSLOT,
GETSLOTMT,
SELFSLOT,
SELFSLOTMT,
GETFIELD_MM,
CHECKTYPE_D,
GETSLOT_D,
GETGLOBAL_MEM,
};
enum HksType : u8
{
TNIL,
TBOOLEAN,
TLIGHTUSERDATA,
TNUMBER,
TSTRING,
TTABLE,
TFUNCTION,
TUSERDATA,
TTHREAD,
TIFUNCTION,
TCFUNCTION,
TUI64,
TSTRUCT
};
bitfield REG_CONST_UNUSED {
argB : 17 & 0x1ffff;
argA : 8 & 0xff;
};
bitfield REG_NUM_NUM {
argC : 9 & 0x1ff;
argB : 8 & 0xff;
argA : 8 & 0xff;
};
bitfield REG_NUM_UNUSED {
argB : 8 & 0xff;
argA : 8 & 0xff;
argC : 9 & 0x1ff;
};
bitfield UNUSED_OFFSET_UNUSED {
argA : 8 & 0xff;
argB : 9 & 0x1ff;
argC : 8 & 0xff;
};
bitfield LuaBitfield {
HksOpCode OpCode : 7;
//Arguments : 25; // read on how to process them at https://raw.githubusercontent.com/soupstream/havok-script-tools/main/HavokScriptToolsCommon/HksOpCodes.cs
match(OpCode) {
(HksOpCode::LOADK) : REG_CONST_UNUSED arguments;
(HksOpCode::SETGLOBAL) : REG_CONST_UNUSED arguments;
(HksOpCode::NEWTABLE) : REG_NUM_NUM arguments;
(HksOpCode::CLOSURE) : REG_CONST_UNUSED arguments;
(HksOpCode::RETURN) : REG_NUM_UNUSED arguments;
(HksOpCode::NEWSTRUCT) : REG_NUM_NUM arguments;
(HksOpCode::DATA) : UNUSED_OFFSET_UNUSED arguments;
(_): arguments : 25;
}
};
struct LuaInstruction {
LuaBitfield OpCode;
};
struct LuaConstant {
HksType type;
if (type == HksType::TNIL) {
}
else if (type == HksType::TSTRING) {
String64 string;
}
else if (type == HksType::TNUMBER) {
float number;
}
else if (type == HksType::TBOOLEAN) {
bool boolean;
}
else if (type == HksType::TLIGHTUSERDATA) {
s64 userdata;
}
else {
s64 data;
}
};
struct HksLocal {
String64 string;
u32 start;
u32 end;
};
struct LuaFunction {
s32 upvaluecount;
s32 paramcount;
s8 isVarArg;
s32 slotCount;
s32 unk;
s32 instruction_count;
if ($ % 4 != 0) {
$ += (4 - ($ % 4));
}
LuaInstruction instructions[instruction_count];
s32 constantCount;
LuaConstant constants[constantCount];;
s32 HasDebugInfo;
if (HasDebugInfo != 0) {
u32 LineCount;
u32 LocalsCount;
u32 UpValueCount;
u32 LineBegin;
u32 LineEnd;
String64 path;
String64 functionName;
s32 Lines[LineCount];
HksLocal Locals[LocalsCount];
String64 UpValues[UpValueCount];
}
s32 function_count;
LuaFunction children[function_count];
};
struct LuaStructHeader {
String64 name;
s32 structID;
s32 pad;
s24 unk1;
HksType type;
s32 unk2;
};
struct LuaStructMember {
s32 pad;
LuaStructHeader header;
s32 index;
};
struct LuaStruct {
try {
u32 unk;
LuaStructHeader ExtendedStructHeader;
s64 ExtendedStructMemberCount;
LuaStructMember ExtendedStructMembers[ExtendedStructMemberCount];
u32 unk2;
} catch {
std::print("WARNING: this file does not support structs.");
}
try {
LuaStructHeader StructHeader;
s64 StructMemberCount;
LuaStructMember StructMembers[StructMemberCount];
} catch {
std::print("WARNING: this file does not support multiple structs.");
}
};
struct LuaHeader {
char luaheader[4];
u8 version;
u8 format;
lua_endian Endianness;
if (Endianness == lua_endian::big_endian) {
std::core::set_endian(std::mem::Endian::Big);
} else {
std::core::set_endian(std::mem::Endian::Little);
}
u8 intSize;
u8 size_tSize;
u8 instruction_size;
u8 number_size;
lua_numbertype numberType;
u8 flags;
u8 unknown;
LuaEnum enums;
LuaFunction LuaFunctions;
LuaStruct LuaStructures;
};
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;
};
struct _s_tagblock {
char tagblock[16];
s32 count;
};
struct _s_resource {
char resource[12];
s32 count;
};
struct _s_data {
char data[24];
};
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 _s_tagref {
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;
_s_tagref tagreference @ header.HeaderSize + datablocks[FieldBlock].Offset + FieldOffset;
};
struct InternalStruct {
s64 vtablespace;
u32 global_tag_id;
char local_tag_handle[4];
};
struct LuaReferencedTagContainer {
_s_tagref tagReference;
};
struct LuaScriptTagDefinition {
u32 luaFileName;
_s_data luaFileData;
char luaFileNameString[256];
_s_tagblock referencedTags_count;
LuaHeader lua_header;
try {
char pad[14];
LuaReferencedTagContainer referencedTags[referencedTags_count.count];
} catch {
std::print("This file does not support referenced Tags.");
}
};
// 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;
InternalStruct internalstruct @ header.HeaderSize;
LuaScriptTagDefinition lua_script @ header.HeaderSize + 16;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Icon (.ico) or Cursor (.cur) files
#pragma endian little
#include <std/sys.pat>

View File

@@ -1,3 +1,5 @@
#pragma description ID3 tags in MP3 files
#pragma MIME audio/mpeg
#include <std/mem.pat>
@@ -24,10 +26,10 @@ namespace v2 {
u8 bytes[4];
} [[sealed, static, format("v2::ssi_value"), transform("v2::ssi_value")]];
fn ssi_value(ref SyncSafeInt n) {
fn ssi_value(ref SyncSafeInt size) {
u32 result = 0;
for (u8 i = 0, i < 4, i = i + 1) {
u8 byteval = n.bytes[i] & 0x7F;
u8 byteval = size.bytes[i] & 0x7F;
u8 shift = 7 * (4 - i - 1);
result = result | (byteval << shift);
}

View File

@@ -1,3 +1,5 @@
#pragma description Intel hexadecimal object file format definition
/* If you have no delimiters between data records then remove
* the null_bytes field in the data_packet struct.
* Set the array at the bottom to the highest index + 1 in the Pattern Data view
@@ -6,6 +8,8 @@
*/
#pragma endian big
#include <std/mem.pat>
enum FileType: u16 {
Data = 0x3030,
EOF = 0x3031,
@@ -45,7 +49,9 @@ struct data_packet {
}
u16 checksum [[color("0045F0DF")]];
u16 null_bytes [[color("005E565A")]];
u8 line_ending_1 [[color("005E565A")]];
if (line_ending_1 == '\r')
u8 line_ending_2 [[color("005E565A")]];
};
data_packet data[1418] @ 0x00;
data_packet data[while(!std::mem::eof())] @ 0x00;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Ethernet II Frames (IP Packets)
#pragma endian big
#include <std/sys.pat>
@@ -129,7 +132,7 @@ namespace ip {
if (flags.data_offset > 5)
u8 options[(flags.data_offset - 5) * sizeof(u32)];
u8 data[parent.parent.header.total_length - 40];
u8 data[parent.parent.header.total_length - parent.parent.header.ihl * 4 - flags.data_offset * 4];
};
}

28
patterns/ips.hexpat Normal file
View File

@@ -0,0 +1,28 @@
#pragma author gmestanley
#pragma description IPS (International Patching System) files
#pragma endian big
#include <std/mem.pat>
#include <std/string.pat>
struct Hunk {
u24 offset;
u16 length;
if (!length) {
u16 runCount;
u8 payload;
}
else {
u8 payload[length];
}
};
struct IPS {
char signature[5];
Hunk hunks[while($ < std::mem::size() - (3 + 3 * (std::mem::read_string(std::mem::size()-3, 3) != "EOF")))];
char eof[3];
u24 truncatedSize[3+(std::mem::read_string(std::mem::size()-3, 3) != "EOF")>3];
};
IPS ips @ 0x00;

View File

@@ -1,3 +1,5 @@
#pragma description ISO 9660 file system
#pragma endian little
#include <std/io.pat>

File diff suppressed because it is too large Load Diff

View File

@@ -1,122 +1,156 @@
#include <std/mem.pat>
#pragma endian big
#pragma MIME image/jpeg
enum Marker : u8 {
TEM = 0x01,
SOF0 = 0xC0,
SOF1 = 0xC1,
SOF2 = 0xC2,
SOF3 = 0xC3,
DHT = 0xC4,
SOF5 = 0xC5,
SOF6 = 0xC6,
SOF7 = 0xC7,
SOI = 0xD8,
EOI = 0xD9,
SOS = 0xDA,
DQT = 0xDB,
DNL = 0xDC,
DRI = 0xDD,
DHP = 0xDE,
APP0 = 0xE0,
APP1 = 0xE1,
APP2 = 0xE2,
APP3 = 0xE3,
APP4 = 0xE4,
APP5 = 0xE5,
APP6 = 0xE6,
APP7 = 0xE7,
APP8 = 0xE8,
APP9 = 0xE9,
APP10 = 0xEA,
APP11 = 0xEB,
APP12 = 0xEC,
APP13 = 0xED,
APP14 = 0xEE,
APP15 = 0xEF,
COM = 0xFE
};
enum DensityUnit : u8 {
NoUnit = 0x00,
PixelsPerInch = 0x01,
PixelsPerCm = 0x02
};
struct Pixel {
u8 r, g, b;
} [[sealed, transform("transform_pixel")]];
fn transform_pixel(Pixel pixel) {
return (0xFF << 24) | (pixel.b << 16) | (pixel.g << 8) | (pixel.r << 0);
};
struct APP0 {
char magic[5];
u8 versionMajor, versionMinor;
DensityUnit densityUnit;
u16 densityX, densityY;
u8 thumbnailX, thumbnailY;
Pixel thumbnail[thumbnailX * thumbnailY] [[sealed]];
};
enum ComponentId : u8 {
Y = 1,
CB = 2,
CR = 3,
I = 4,
Q = 5
};
struct SOF0Component {
ComponentId componentId;
u8 samplingFactors;
u8 quantizationTableId;
};
struct SOF0 {
u8 bitsPerSample;
u16 imageHeight, imageWidth;
u8 numComponents;
SOF0Component components[numComponents];
};
struct SOSComponent {
ComponentId componentId;
u8 huffmanTable;
};
struct SOS {
u8 numComponents;
SOSComponent components[numComponents];
u8 startSpectralSelection;
u8 endSpectral;
u8 apprBitPos;
u8 image_data[while(!std::mem::eof())] [[sealed]];
};
struct Segment {
u8 magic;
Marker marker;
if (marker == Marker::SOI || marker == Marker::EOI) {
} else {
u16 length;
if (marker == Marker::APP0) {
APP0 data;
} else if (marker == Marker::SOF0) {
SOF0 data;
} else if (marker == Marker::SOS) {
SOS data;
} else {
u8 data[length - sizeof(length)] [[sealed]];
}
}
};
Segment segments[while(!std::mem::eof())] @ 0x00;
#pragma author WerWolv
#pragma description JPEG Image Format
#include <std/io.pat>
#include <std/mem.pat>
#include <type/magic.pat>
#pragma endian big
#pragma MIME image/jpeg
enum Marker : u8 {
TEM = 0x01,
SOF0 = 0xC0,
SOF1 = 0xC1,
SOF2 = 0xC2,
SOF3 = 0xC3,
DHT = 0xC4,
SOF5 = 0xC5,
SOF6 = 0xC6,
SOF7 = 0xC7,
SOI = 0xD8,
EOI = 0xD9,
SOS = 0xDA,
DQT = 0xDB,
DNL = 0xDC,
DRI = 0xDD,
DHP = 0xDE,
APP0 = 0xE0,
APP1 = 0xE1,
APP2 = 0xE2,
APP3 = 0xE3,
APP4 = 0xE4,
APP5 = 0xE5,
APP6 = 0xE6,
APP7 = 0xE7,
APP8 = 0xE8,
APP9 = 0xE9,
APP10 = 0xEA,
APP11 = 0xEB,
APP12 = 0xEC,
APP13 = 0xED,
APP14 = 0xEE,
APP15 = 0xEF,
COM = 0xFE
};
enum DensityUnit : u8 {
NoUnit = 0x00,
PixelsPerInch = 0x01,
PixelsPerCm = 0x02
};
enum ColorTransform : u8 {
Unknown = 0x00,
YCbCr = 0x01,
YCCK = 0x02
};
struct Pixel {
u8 r, g, b;
} [[sealed, transform("transform_pixel")]];
fn transform_pixel(Pixel pixel) {
return (0xFF << 24) | (pixel.b << 16) | (pixel.g << 8) | (pixel.r << 0);
};
struct APP0 {
type::Magic<"JFIF\x00"> magic;
u8 versionMajor, versionMinor;
DensityUnit densityUnit;
u16 densityX, densityY;
u8 thumbnailX, thumbnailY;
Pixel thumbnail[thumbnailX * thumbnailY] [[sealed]];
};
struct APP14 {
type::Magic<"Adobe"> magic;
u16 version;
u16 flags0;
u16 flags1;
ColorTransform transform;
};
enum ComponentId : u8 {
Y = 1,
CB = 2,
CR = 3,
I = 4,
Q = 5,
B = 66,
G = 71,
R = 82
};
struct SOF0Component {
ComponentId componentId;
u8 samplingFactors;
u8 quantizationTableId;
} [[format_read("sof0_component_read")]];
fn sof0_component_read(SOF0Component c) {
return std::format("({}, {}, {})", c.componentId, c.samplingFactors, c.quantizationTableId);
};
struct SOF0 {
u8 bitsPerSample;
u16 imageHeight, imageWidth;
u8 numComponents;
SOF0Component components[numComponents];
};
struct SOSComponent {
ComponentId componentId;
u8 huffmanTable;
};
struct SOS {
u8 numComponents;
SOSComponent components[numComponents];
u8 startSpectralSelection;
u8 endSpectral;
u8 apprBitPos;
u8 image_data[std::mem::size() - $ - 2] [[sealed]];
};
struct Segment {
type::Magic<"\xff"> magic;
Marker marker;
if (marker == Marker::SOI || marker == Marker::EOI) {
} else {
u16 length;
if (marker == Marker::APP0) {
APP0 data;
} else if (marker == Marker::APP14) {
APP14 data;
} else if (marker == Marker::COM) {
char data[length - sizeof(length)];
} else if (marker == Marker::SOF0) {
SOF0 data;
} else if (marker == Marker::SOS) {
SOS data;
} else {
u8 data[length - sizeof(length)] [[sealed]];
}
}
} [[format_read("segment_read")]];
fn segment_read(Segment s) {
return std::format("{}", s.marker);
};
Segment segments[while(!std::mem::eof())] @ 0x00 [[hex::visualize("image", this)]];

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Windows Shell Link file format
#pragma MIME application/x-ms-shortcut
#include <std/core.pat>

View File

@@ -1,3 +1,5 @@
#pragma description Lua 5.4 bytecode
#include <std/io.pat>
#include <std/mem.pat>
@@ -30,8 +32,8 @@ namespace impl {
return std::format("\"{}\"", string.data);
};
fn format_Constant(auto const) {
return const.data;
fn format_Constant(auto constant) {
return constant.data;
};
fn format_Version(auto ver) {
@@ -132,4 +134,4 @@ struct LuaFile {
LuaFunction func;
};
LuaFile file @ 0;
LuaFile file @ 0;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Mach-O executable
#pragma MIME application/x-mach-binary
#include <type/size.pat>
@@ -8,6 +11,7 @@ enum Magic : u32 {
};
enum CpuType : u32 {
ANY = -1,
VAX = 1,
ROMP = 2,
BS32032 = 4,
@@ -17,14 +21,16 @@ enum CpuType : u32 {
X86_64 = CpuType::I386 | 0x100'0000,
MIPS = 8,
NS32532 = 9,
MC98000 = 10,
HPPA = 11,
ARM = 12,
ARM64 = CpuType::ARM | 0x100'0000,
ARM64_32 = CpuType::ARM | 0x200'0000,
MC88000 = 13,
SPARC = 14,
I860 = be u32(15),
I860_LITTLE = 16,
RS6000 = 17,
MC980000 = 18,
POWERPC = 18,
POWERPC64 = CpuType::POWERPC | 0x100'0000,
VEO = 255

833
patterns/max_v104.hexpat Normal file
View File

@@ -0,0 +1,833 @@
#pragma description Mechanized Assault and Exploration v1.04 (strategy game) save file format
#include <std/sys.pat>
#include <std/mem.pat>
#pragma array_limit 12544
#pragma pattern_limit 2000000
#pragma eval_depth 32
enum FileType : u8
{
Custom,
Tutorial,
Campaign,
Hot_seat,
Multiplayer,
Demo,
Debug,
Text,
Scenario,
Multi_scenario
};
enum PlanetType : u8
{
Snowcrab,
Frigia,
Ice_Berg,
The_Cooler,
Ultima_Thule,
Long_Floes,
Iron_Cross,
Splatterscape,
Peak_a_boo,
Valentines_Planet,
Three_Rings,
Great_divide,
New_Luzon,
Middle_Sea,
High_Impact,
Sanctuary,
Islandia,
Hammerhead,
Freckles,
Sandspit,
Great_Circle,
Long_Passage,
Flash_Point,
Bottleneck
};
enum TeamType : u8
{
None = 0,
Human = 1,
Computer = 2,
Remote = 3,
Eliminated = 4
};
enum TeamIndex : u8
{
Red = 0,
Green = 1,
Blue = 2,
Gray = 3
};
enum TeamIndex16 : u16
{
Red = 0,
Green = 1,
Blue = 2,
Gray = 3
};
enum PlayMode : u8
{
Turn_Based = 0,
Simultaneous_Moves = 1
};
enum TeamClan : u8
{
None = 0,
The_Chosen = 1,
Crimson_Path = 2,
Von_Griffin = 3,
Ayers_Hand = 4,
Musashi = 5,
Sacred_Eights = 6,
Seven_Knights = 7,
Axis_Inc = 8
};
enum OpponentType : u8
{
Clueless = 0,
Apprentice = 1,
Average = 2,
Expert = 3,
Master = 4,
God = 5
};
enum VictoryType : u8
{
Duration = 0,
Score = 1
};
struct IniOptions
{
s32 world;
s32 turn_timer;
s32 endturn;
s32 start_gold;
s32 play_mode;
s32 victory_type;
s32 victory_limit;
s32 opponent;
s32 raw_resource;
s32 fuel_resource;
s32 gold_resource;
s32 alien_derelicts;
};
struct IniPreferences
{
s32 effects;
s32 click_scroll;
s32 quick_scroll;
s32 fast_movement;
s32 follow_unit;
s32 auto_select;
s32 enemy_halt;
};
enum SurfaceType : u8
{
Land = 1,
Water = 2,
Coast = 4,
Air = 8
};
enum AiStrategy : u8
{
Random,
Defensive,
Missiles,
Air,
Sea,
Scout_horde,
Tank_horde,
Fast_attack,
Combined_arms,
Espionage
};
bitfield GridResourceMapEntry
{
padding : 2;
team_visibility_gray : 1;
team_visibility_blue : 1;
team_visibility_green : 1;
team_visibility_red : 1;
padding : 2;
cargo_amount : 5;
cargo_type_fuel : 1;
cargo_type_gold : 1;
cargo_type_material : 1;
};
bitfield UnitFlags
{
// MSB
requires_slab: 1;
turret_sprite: 1;
sentry_unit: 1;
spinning_turret: 1;
padding: 4;
hovering: 1;
has_firing_sprite: 1;
fires_missiles: 1;
constructor_unit: 1;
padding: 1;
electronic_unit: 1;
selectable: 1;
standalone: 1;
mobile_land_unit: 1;
stationary: 1;
padding: 4;
upgradeable: 1;
padding: 1;
// LSB
ground_cover : 1;
exploding: 1;
animated: 1;
connector_unit: 1;
building: 1;
missile_unit: 1;
mobile_air_unit: 1;
mobile_sea_unit: 1;
};
struct Point
{
s16 x;
s16 y;
};
struct ResearchTopicInfo
{
u32 research_level;
u32 turns_to_complete;
s32 allocation;
};
struct ScreenLocation
{
s8 x;
s8 y;
};
struct TeamInfo
{
Point markers[10];
TeamType team_type;
s8 field_41;
TeamClan team_clan;
ResearchTopicInfo research_topics[8];
u32 victory_points;
u16 next_unit_id;
u8 unit_counters[93];
ScreenLocation screen_location[6];
u16 score_graph[50];
u16 selected_unit;
u16 zoom_level;
Point screen_position;
bool gui_button_state_range;
bool gui_button_state_scan;
bool gui_button_state_status;
bool gui_button_state_colors;
bool gui_button_state_hits;
bool gui_button_state_ammo;
bool gui_button_state_names;
bool gui_button_state_minimap_2x;
bool gui_button_state_minimap_tnt;
bool gui_button_state_grid;
bool gui_button_state_survey;
u16 stats_factories_built;
u16 stats_mines_built;
u16 stats_buildings_built;
u16 stats_units_built;
u16 casualties[93];
u16 stats_gold_spent_on_upgrades;
};
struct UnitValues
{
u16 object_index;
if(CheckObjectId(object_index, true) == true)
{
u16 class_type;
u16 turns;
u16 hits;
u16 armor;
u16 attack;
u16 speed;
u16 range;
u16 rounds;
bool move_and_fire;
u16 scan;
u16 storage;
u16 ammo;
u16 attack_radius;
u16 agent_adjust;
u16 version;
u8 units_built;
}
};
struct Complex
{
u16 object_index;
if(CheckObjectId(object_index, true) == true)
{
u16 class_type;
s16 material;
s16 fuel;
s16 gold;
s16 power;
s16 workers;
s16 buildings;
s16 id;
}
};
struct TeamUnits
{
s16 gold;
UnitValues base_unit_values[93];
UnitValues current_unit_values[93];
u16 complex_count;
Complex complexes[complex_count];
};
enum UnitType : u16
{
UNIT_TYPE_GOLD_REFINERY = 0,
UNIT_TYPE_POWER_STATION = 1,
UNIT_TYPE_POWER_GENERATOR = 2,
UNIT_TYPE_BARRACKS = 3,
UNIT_TYPE_ALIEN_BUILDING_1 = 4,
UNIT_TYPE_RADAR = 5,
UNIT_TYPE_STORAGE_UNIT = 6,
UNIT_TYPE_FUEL_TANK = 7,
UNIT_TYPE_GOLD_VAULT = 8,
UNIT_TYPE_DEPOT = 9,
UNIT_TYPE_HANGAR = 10,
UNIT_TYPE_DOCK = 11,
UNIT_TYPE_CONNECTOR = 12,
UNIT_TYPE_LARGE_RUBBLE_1 = 13,
UNIT_TYPE_SMALL_RUBBLE_1 = 14,
UNIT_TYPE_LARGE_TAPE = 15,
UNIT_TYPE_SMALL_TAPE = 16,
UNIT_TYPE_LARGE_SLAB = 17,
UNIT_TYPE_SMALL_SLAB = 18,
UNIT_TYPE_LARGE_CONES = 19,
UNIT_TYPE_SMALL_CONES = 20,
UNIT_TYPE_ROAD = 21,
UNIT_TYPE_LANDING_PAD = 22,
UNIT_TYPE_SHIPYARD = 23,
UNIT_TYPE_LIGHT_VEHICLE_PLANT = 24,
UNIT_TYPE_HEAVY_VEHICLE_PLANT = 25,
UNIT_TYPE_ALIEN_BUILDING_2 = 26,
UNIT_TYPE_AIR_UNITS_PLANT = 27,
UNIT_TYPE_HABITAT = 28,
UNIT_TYPE_RESEARCH_CENTER = 29,
UNIT_TYPE_ECOSPHERE = 30,
UNIT_TYPE_ALIEN_BUILDING_3 = 31,
UNIT_TYPE_TRAINING_HALL = 32,
UNIT_TYPE_WATER_PLATFORM = 33,
UNIT_TYPE_GUN_TURRET = 34,
UNIT_TYPE_ANTI_AIRCRAFT = 35,
UNIT_TYPE_ARTILLERY = 36,
UNIT_TYPE_MISSILE_LAUNCHER = 37,
UNIT_TYPE_CONCRETE_BLOCK = 38,
UNIT_TYPE_BRIDGE = 39,
UNIT_TYPE_MINING_STATION = 40,
UNIT_TYPE_LAND_MINE = 41,
UNIT_TYPE_SEA_MINE = 42,
UNIT_TYPE_LAND_EXPLOSION = 43,
UNIT_TYPE_AIR_EXPLOSION = 44,
UNIT_TYPE_SEA_EXPLOSION = 45,
UNIT_TYPE_BUILDING_EXPLOSION = 46,
UNIT_TYPE_HIT_EXPLOSION = 47,
UNIT_TYPE_MASTER_BUILDER = 48,
UNIT_TYPE_CONSTRUCTOR = 49,
UNIT_TYPE_SCOUT = 50,
UNIT_TYPE_TANK = 51,
UNIT_TYPE_ASSAULT_GUN = 52,
UNIT_TYPE_ROCKET_LAUNCHER = 53,
UNIT_TYPE_MISSILE_CRAWLER = 54,
UNIT_TYPE_MOBILE_ANTI_AIRCRAFT = 55,
UNIT_TYPE_MINE_LAYER = 56,
UNIT_TYPE_SURVEYOR = 57,
UNIT_TYPE_SCANNER = 58,
UNIT_TYPE_SUPPLY_TRUCK = 59,
UNIT_TYPE_GOLD_TRUCK = 60,
UNIT_TYPE_ENGINEER = 61,
UNIT_TYPE_BULLDOZER = 62,
UNIT_TYPE_REPAIR_UNIT = 63,
UNIT_TYPE_FUEL_TRUCK = 64,
UNIT_TYPE_PERSONNEL_CARRIER = 65,
UNIT_TYPE_INFILTRATOR = 66,
UNIT_TYPE_INFANTRY = 67,
UNIT_TYPE_ESCORT = 68,
UNIT_TYPE_CORVETTE = 69,
UNIT_TYPE_GUNBOAT = 70,
UNIT_TYPE_SUBMARINE = 71,
UNIT_TYPE_SEA_TRANSPORT = 72,
UNIT_TYPE_MISSILE_CRUISER = 73,
UNIT_TYPE_SEA_MINE_LAYER = 74,
UNIT_TYPE_CARGO_SHIP = 75,
UNIT_TYPE_FIGHTER = 76,
UNIT_TYPE_GROUND_ATTACK_PLANE = 77,
UNIT_TYPE_AIR_TRANSPORT = 78,
UNIT_TYPE_AWAC = 79,
UNIT_TYPE_ALIEN_GUNBOAT = 80,
UNIT_TYPE_ALIEN_TANK = 81,
UNIT_TYPE_ALIEN_ASSAULT_GUN = 82,
UNIT_TYPE_ALIEN_ATTACK_PLANE = 83,
UNIT_TYPE_MISSILE = 84,
UNIT_TYPE_TORPEDO = 85,
UNIT_TYPE_ALIEN_MISSILE = 86,
UNIT_TYPE_TANK_PLASMA_BALL = 87,
UNIT_TYPE_ARTILLERY_PLASMA_BALL = 88,
UNIT_TYPE_SMOKE_TRAIL = 89,
UNIT_TYPE_BUBBLE_TRAIL = 90,
UNIT_TYPE_HARVESTER = 91,
UNIT_TYPE_DEAD_WALDO = 92
};
enum OrderType : u8
{
ORDER_TYPE_AWAITING = 0x0,
ORDER_TYPE_TRANSFORMING = 0x1,
ORDER_TYPE_MOVING = 0x2,
ORDER_TYPE_FIRING = 0x3,
ORDER_TYPE_ORDER_BUILDING = 0x4,
ORDER_TYPE_ACTIVATE_ORDER = 0x5,
ORDER_TYPE_NEW_ALLOCATE_ORDER = 0x6,
ORDER_TYPE_POWER_ON = 0x7,
ORDER_TYPE_POWER_OFF = 0x8,
ORDER_TYPE_EXPLODING = 0x9,
ORDER_TYPE_UNLOADING = 0xA,
ORDER_TYPE_CLEARING = 0xB,
ORDER_TYPE_SENTRY = 0xC,
ORDER_TYPE_LANDING = 0xD,
ORDER_TYPE_TAKING_OFF = 0xE,
ORDER_TYPE_LOADING = 0xF,
ORDER_TYPE_IDLE = 0x10,
ORDER_TYPE_REPAIRING = 0x11,
ORDER_TYPE_REFUELING = 0x12,
ORDER_TYPE_RELOADING = 0x13,
ORDER_TYPE_TRANSFERRING = 0x14,
ORDER_TYPE_AWAITING_21 = 0x15,
ORDER_TYPE_AWAITING_22 = 0x16,
ORDER_TYPE_AWAITING_23 = 0x17,
ORDER_TYPE_AWAITING_24 = 0x18,
ORDER_TYPE_AWAITING_25 = 0x19,
ORDER_TYPE_DISABLED = 0x1A,
ORDER_TYPE_MOVING_27 = 0x1B,
ORDER_TYPE_REPAIRING_28 = 0x1C,
ORDER_TYPE_TRANSFERRING_29 = 0x1D,
ORDER_TYPE_ATTACKING = 0x1E,
ORDER_TYPE_BUILDING_HALTED = 0x1F
};
struct Rect
{
s32 ulx;
s32 uly;
s32 lrx;
s32 lry;
};
struct PathStep
{
s8 x;
s8 y;
};
struct Path
{
u16 object_index;
if(CheckObjectId(object_index, true) == true)
{
u16 class_type;
// Air path
if (class_type == 1)
{
s16 length;
u8 angle;
Point pixel_start;
Point pixel_end;
s32 x_step;
s32 y_step;
s32 delta_x;
s32 delta_y;
}
// Ground path
else if (class_type == 4)
{
Point pixel_end;
s16 index;
s16 steps_count;
PathStep steps[steps_count];
}
// Builder path
else if (class_type == 2)
{
Point coordinate;
}
else
{
std::assert(0, "Unknown path class");
}
}
};
struct UnitTypeArray
{
u16 object_count;
UnitType array[object_count];
};
struct UnitInfo
{
u16 object_index;
if(CheckObjectId(object_index, true) == true)
{
u16 class_type;
UnitType unit_type;
if (unit_type == UnitType::UNIT_TYPE_DEAD_WALDO)
{
std::print("Found Waldo!");
}
u16 hash_id;
UnitFlags flags;
Point pixel_position;
Point grid_position;
u16 name_length;
s8 name[name_length];
Point shadow_offset;
TeamIndex team;
u8 name_index;
u8 brightness;
u8 angle;
u8 visible_to_team[5];
u8 spotted_by_team[5];
u8 max_velocity;
u8 velocity;
u8 sound;
u8 scaler_adjust;
Rect sprite_bounds;
Rect shadow_bounds;
u8 turret_angle;
s8 turret_offset_x;
s8 turret_offset_y;
u16 total_images;
u16 image_base;
u16 turret_image_base;
u16 firing_image_base;
u16 connector_image_base;
u16 image_index;
u16 turret_image_index;
u16 image_index_max;
OrderType orders;
u8 state;
OrderType prior_orders;
u8 prior_state;
u8 laying_state;
Point target_grid;
u8 build_time;
u8 total_mining;
u8 raw_mining;
u8 fuel_mining;
u8 gold_mining;
u8 raw_mining_max;
u8 gold_mining_max;
u8 fuel_mining_max;
u8 hits;
u8 speed;
u8 shots;
u8 move_and_fire;
u16 storage;
u8 ammo;
u8 targeting_mode;
u8 enter_mode;
u8 cursor;
u8 recoil_delay;
u8 delayed_reaction;
u8 damaged_this_turn;
u8 research_topic;
u8 moved;
u8 bobbed;
u8 shake_effect_state;
u8 engine;
u8 weapon;
u8 comm;
u8 fuel_distance;
u8 move_fraction;
u8 energized;
u8 repeat_build;
u16 build_rate;
u8 disabled_reaction_fire;
u8 auto_survey;
u32 field_221;
Path path;
u16 connectors;
UnitValues base_values;
Complex complex;
UnitInfo parent_unit;
UnitInfo enemy_unit;
UnitTypeArray build_list;
}
};
struct UnitInfoList
{
u16 unitinfo_count;
UnitInfo units[unitinfo_count];
};
struct HashMapUnitInfo
{
u16 hash_size;
UnitInfoList map[hash_size];
};
struct MapHash
{
Point coordinates;
UnitInfoList units;
};
struct MapHashList
{
u16 maphash_count;
MapHash objects[maphash_count];
};
struct HashMapMapHash
{
u16 hash_size;
s16 x_shift;
MapHashList map[hash_size];
};
struct TeamHeatMaps
{
u8 heatmap_complete[12544];
u8 heatmap_stealth_sea[12544];
u8 heatmap_stealth_land[12544];
};
struct MessageLog
{
s16 length;
char text[length];
UnitInfo unit;
Point coordinates;
bool is_alert_message;
u16 resource_id;
};
struct MessageLogList
{
u16 message_log_count;
MessageLog entires[message_log_count];
};
struct AiMap
{
UnitInfo unit;
TeamIndex16 team;
bool visible_to_team;
Point point;
};
struct AiMapList
{
u16 ai_map_count;
AiMap objects[ai_map_count];
};
struct AiPlayer
{
TeamIndex16 team;
AiStrategy strategy;
s16 field_3;
s16 field_5;
s16 field_7;
TeamIndex16 target_team;
AiMapList map_list;
u16 has_info_map;
if (has_info_map)
{
u8 info_map[12544];
}
u16 has_mine_map;
if (has_mine_map)
{
u8 mine_map[12544];
}
Point target_location;
};
u16 last_object_index;
bool context;
fn Init()
{
context = false;
last_object_index = 0;
};
fn CheckObjectId(u16 index, bool caller)
{
bool result = false;
// ImHex bug workaround
if (context) { context = false; return result; }
// null object?
if (index == 0)
{
return false;
}
// already serialized object?
if (last_object_index < index)
{
last_object_index = index;
result = true;
}
return result;
};
struct SaveFile
{
Init();
s16 version;
FileType save_file_type;
char save_game_name[30];
PlanetType planet;
s16 mission_index;
char team_name_red[30];
char team_name_green[30];
char team_name_blue[30];
char team_name_gray[30];
TeamType team_type_red;
TeamType team_type_green;
TeamType team_type_blue;
TeamType team_type_gray;
TeamType team_type_alien;
TeamClan team_clan_red;
TeamClan team_clan_green;
TeamClan team_clan_blue;
TeamClan team_clan_gray;
TeamClan team_clan_alien;
u32 rng_seed;
OpponentType opponent;
s16 turn_timer;
s16 endturn;
PlayMode play_mode;
IniOptions options;
SurfaceType surface_map[12544];
GridResourceMapEntry GridResourceMap[12544];
TeamInfo team_info_red;
TeamInfo team_info_green;
TeamInfo team_info_blue;
TeamInfo team_info_gray;
TeamIndex active_turn_team;
TeamIndex player_team;
s32 turn_counter;
s16 game_state;
u16 turn_timer_;
IniPreferences preferences;
TeamUnits team_units_red;
TeamUnits team_units_green;
TeamUnits team_units_blue;
TeamUnits team_units_gray;
UnitInfoList unit_info_list_ground_cover_units;
UnitInfoList unit_info_list_mobile_land_sea_units;
UnitInfoList unit_info_list_stationary_units;
UnitInfoList unit_info_list_mobile_air_units;
UnitInfoList unit_info_list_particles;
HashMapUnitInfo hash_map_unit_info;
HashMapMapHash hash_map_map_hash;
if (team_type_red != TeamType::None)
{
TeamHeatMaps heat_maps_red;
}
if (team_type_green != TeamType::None)
{
TeamHeatMaps heat_maps_green;
}
if (team_type_blue != TeamType::None)
{
TeamHeatMaps heat_maps_blue;
}
if (team_type_gray != TeamType::None)
{
TeamHeatMaps heat_maps_gray;
}
MessageLogList message_log_red;
MessageLogList message_log_green;
MessageLogList message_log_blue;
MessageLogList message_log_gray;
if (team_type_red == TeamType::Computer)
{
AiPlayer ai_player_red;
}
if (team_type_green == TeamType::Computer)
{
AiPlayer ai_player_green;
}
if (team_type_blue == TeamType::Computer)
{
AiPlayer ai_player_blue;
}
if (team_type_gray == TeamType::Computer)
{
AiPlayer ai_player_gray;
}
};
SaveFile save @ 0x0;
std::assert($ == std::mem::size(), "Extra data found after parsed data");

View File

@@ -1,72 +1,280 @@
#pragma description MIDI header, event fields provided
#include <std/core.pat>
#pragma MIME audio/midi
#pragma endian big
using Delta = u8;
using NoteValue = u8;
using Velocity = u8;
using EOF = u8;
// this is just for debugging midi file generation
// I'm testing a known good file against a bad one
// the file is hard coded in file format 0, and if
// you're expecting meta events anywhere add a specific
// call for those
// Only supports format 0
// https://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html
enum NoteEvent : u8 {
NoteOn = 0x90,
NoteOff = 0x80
bool g_has_more_messages = true;
bool g_has_more_tracks = true;
fn signed14(s16 n) {
// Converts to 14-bit in range 0..16383. Note that MIDI data bytes
// have their first (most significant) bit clear (0), thus each byte
// is in range 0..127
n = ((n & 0x7f) << 7) | ((n >> 8) & 0x7f);
if (n >= 0) {
n -= 0x2000;
}
return n;
};
enum MetaFlag : u16 {
Footer = 0xFF2F,
KeySigEvent = 0xFF59,
TimeSigEvent = 0xFF58,
TempoEvent = 0xFF51,
TrackNameEvent = 0xFF03
fn u32ify(u32 vlq) {
// Converts from variable-length quantity to u32. These numbers are
// represented 7 bits per byte, most significant bits first. All bytes
// except the last have bit 7 set, and the last byte has bit 7 clear.
// If the number is in range 0..127, it is thus represented exactly
// as one byte.
u32 n = vlq & 0x7f;
if (vlq & 0x8000 == 0x8000) {
n += ((vlq & 0x7f00) >> 8) * 0x80;
}
if (vlq & 0x800000 == 0x800000) {
n += ((vlq & 0x7f0000) >> 8 * 2) * 0x80 * 0x80;
}
if (vlq & 0x80000000 == 0x80000000) {
n += ((vlq & 0x7f000000) >> 8 * 3) * 0x80 * 0x80 * 0x80;
}
return n;
};
enum Status : u8 {
NoteOff = 0x80 ... 0x8F,
NoteOn = 0x90 ... 0x9F,
PolyphonicAfterTouch = 0xA0 ... 0xAF,
ControlChange = 0xB0 ... 0xBF,
ProgramChange = 0xC0 ... 0xCF,
ChannelAfterTouch = 0xD0 ... 0xDF,
PitchWheel = 0xE0 ... 0xEF,
SysEx = 0xF0,
TimeCodeQtrFrame = 0xF1,
SongPositionPointer = 0xF2,
SongSelect = 0xF3,
Undefined = 0xF4 ... 0xF5,
TuneRequest = 0xF6,
EndOfSysEx = 0xF7,
TimingClock = 0xF8,
Undefined = 0xF9,
Start = 0xFA,
Continue = 0xFB,
Stop = 0xFC,
Undefined = 0xFD,
ActiveSensing = 0xFE,
MetaEvent = 0xFF,
};
Status g_next_status;
enum MetaType : u8 {
SequenceNumber = 0x00,
Text = 0x01,
CopyrightNotice = 0x02,
TrackName = 0x03,
InstrumentName = 0x04,
Lyric = 0x05,
Marker = 0x06,
CuePoint = 0x07,
ChannelPrefix = 0x20,
EndOfTrack = 0x2F,
SetTempo = 0x51,
SMPTEOffset = 0x54,
TimeSignature = 0x58,
KeySignature = 0x59,
SequencerSpecific = 0x7F
};
enum ControlChangeType : u8 {
Bank_Select_MSB = 0,
Modulation_Wheel_MSB = 1,
Breath_Controller_MSB = 2,
Undefined_MSB = 3,
Foot_Pedal_MSB = 4,
Portamento_Time_MSB = 5,
Data_Entry_MSB = 6,
Volume_MSB = 7,
Balance_MSB = 8,
Undefined_MSB = 9,
Pan_MSB = 10,
Expression_MSB = 11,
Effect_Controller_1_MSB = 12,
Effect_Controller_2_MSB = 13,
Undefined_MSB = 14,
Undefined_MSB = 15,
General_Purpose_MSB = 16 ... 19,
Undefined_MSB = 20 ... 31,
Bank_Select_LSB = 32,
Modulation_Wheel_LSB = 33,
Breath_Controller_LSB = 34,
Undefined_LSB = 35,
Foot_Pedal_LSB = 36,
Portamento_Time_LSB = 37,
Data_Entry_LSB = 38,
Volume_LSB = 39,
Balance_LSB = 40,
Undefined_LSB = 41,
Pan_LSB = 42,
Expression_LSB = 43,
Effect_Controller_1_LSB = 44,
Effect_Controller_2_LSB = 45,
Undefined_LSB = 46,
Undefined_LSB = 47,
General_Purpose_LSB = 48 ... 51,
Undefined_LSB = 52 ... 63,
Damper_Pedal = 64,
Portamento = 65,
Sostenuto_Pedal = 66,
Soft_Pedal = 67,
Legato_FootSwitch = 68,
Hold_2 = 69,
Sound_Controller_1 = 70,
Sound_Controller_2 = 71,
Sound_Controller_3 = 72,
Sound_Controller_4 = 73,
Sound_Controller_6 = 75,
Sound_Controller_7 = 76,
Sound_Controller_8 = 77,
Sound_Controller_9 = 78,
Sound_Controller_10 = 79,
General_Purpose_CC_Control = 80 ... 83,
Portamento_CC_Control = 84,
Undefined = 85 ... 87,
High_Resolution_Velocity_Prefix = 88,
Effect_2_Depth = 92,
Effect_3_Depth = 93,
Effect_4_Depth = 94,
Effect_5_Depth = 95,
Data_Increment = 96,
Data_Decrement = 97,
Non_Registered_Parameter_Number_LSB = 98,
Non_Registered_Parameter_Number_MSB = 99,
Registered_Parameter_Number_LSB = 100,
Registered_Parameter_Number_MSB = 101,
Undefined = 102 ... 119,
All_Sound_Off = 120,
Reset_All_Controllers = 121,
Local_Switch = 122,
All_Notes_Off = 123,
Omni_Mode_Off = 124,
Omni_Mode_On = 125,
Mono_Mode = 126,
Poly_Mode = 127,
};
enum HeaderFlag : u32 {
MThd = 0x4D546864
};
enum TrackChunk : u32 {
enum TrackFlag : u32 {
MTrk = 0x4D54726B
};
struct TimeSigEvent {
Delta delta;
MetaFlag flag;
u16 numerator;
u8 denominator;
u8 ticks_per_click; // not used
u8 thirty_second_notes_per_crotchet;
struct VariableLengthQuantity<auto name> {
if (std::mem::read_unsigned($, 1) & 0x80 == 0x80) {
if (std::mem::read_unsigned($ + 1, 1) & 0x80 == 0x80) {
if (std::mem::read_unsigned($ + 2, 1) & 0x80 == 0x80) {
u32 value [[format("u32ify"), name(name)]];
} else {
u24 value [[format("u32ify"), name(name)]];
}
} else {
u16 value [[format("u32ify"), name(name)]];
}
} else {
u8 value [[format("u32ify"), name(name)]];
}
};
struct KeySigEvent {
Delta delta;
MetaFlag flag;
u16 key;
u8 mode;
struct MessageData {
match (u8(g_next_status) & 0xf0) {
(Status::NoteOff | Status::NoteOn): {
u8 note_number;
u8 velocity;
}
(Status::PolyphonicAfterTouch): {
u8 note_number;
u8 amount;
}
(Status::ControlChange): {
ControlChangeType cc_number;
u8 value;
}
(Status::ProgramChange): {
u8 program_number;
}
(Status::ChannelAfterTouch): {
u8 amount;
}
(Status::PitchWheel): {
s16 value [[format("signed14")]];
}
}
match (g_next_status) {
(Status::SysEx | Status::EndOfSysEx): {
// "EndOfSysEx" can appear as the last data byte in a
// system exclusive message, or as the starting byte in
// multi-packet messages
VariableLengthQuantity<"sysex_length"> sysex_length [[inline]];
u8 sysex_data[sysex_length.value];
}
(Status::SongPositionPointer): {
u8 lsb;
u8 msb;
}
(Status::SongSelect): {
u8 song_number;
}
(Status::MetaEvent): {
MetaType meta_type;
VariableLengthQuantity<"meta_length"> meta_length [[inline]];
match (meta_type) {
(MetaType::EndOfTrack): {
g_has_more_messages = false;
g_has_more_tracks = std::mem::read_unsigned($, 4) == le u32(TrackFlag::MTrk);
}
(MetaType::Text
| MetaType::CopyrightNotice
| MetaType::TrackName
| MetaType::InstrumentName
| MetaType::Lyric
| MetaType::Marker
| MetaType::CuePoint): {
char text[meta_length.value];
}
(MetaType::TimeSignature): {
u8 numerator;
u8 denominator;
u8 ticks_per_click;
u8 thirty_second_notes_per_crotchet;
}
(MetaType::KeySignature): {
u8 key;
u8 mode;
}
(MetaType::SetTempo): {
u24 micro_seconds_per_click; // default 1 million
}
(_): {
u8 meta_data[meta_length.value];
}
}
}
}
};
struct TempoEvent {
Delta delta;
MetaFlag flag;
u32 micro_seconds_per_click; // default 1 million
};
struct Message {
VariableLengthQuantity<"delta"> delta [[inline]];
struct TrackNameEvent {
Delta delta;
MetaFlag flag;
u8 length;
u8 text;
};
// Status bytes of MIDI channel messages may be omitted if the
// preceding event is a MIDI channel message with the same status
if (std::mem::read_unsigned($, 1) > 0x7f) {
Status status;
g_next_status = status;
}
struct Note {
Delta delta;
NoteEvent ne;
NoteValue note;
Velocity vel;
MessageData data [[inline]];
};
struct HeaderChunk {
@@ -75,21 +283,18 @@ struct HeaderChunk {
u16 mode;
u16 num_tracks;
u16 ticks_per_quarter;
TrackChunk chunk;
u32 track_length;
};
struct Footer {
Delta d;
MetaFlag m;
EOF eof;
struct TrackChunk {
TrackFlag flag;
u32 length;
g_has_more_messages = true;
Message messages[while(g_has_more_messages)];
};
struct MidiFile {
HeaderChunk header;
// whatever meta flags can be in here
Note notes[12]; //however many notes you're looking at
Footer f;
TrackChunk tracks[while(g_has_more_tracks)];
};
MidiFile midi_file @ 0x00;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Windows MiniDump files
#pragma MIME application/x-dmp
#include <type/time.pat>

424
patterns/mp4.hexpat Normal file
View File

@@ -0,0 +1,424 @@
#pragma description MPEG-4 Part 14 digital multimedia container format
#pragma endian big
#pragma MIME audio/mp4
#pragma MIME video/mp4
#pragma MIME application/mp4
#include <std/io.pat>
#include <std/mem.pat>
#include <std/string.pat>
fn to_string(auto var) {
return str(var);
};
fn format_string(auto string) {
return string.value;
};
struct FixedPoint16 {
u8 integer;
u8 fraction;
};
struct FixedPoint32 {
u16 integer;
u16 fraction;
};
struct string {
char value[std::mem::find_sequence_in_range(0, $, std::mem::size(), 0x00) - $];
} [[sealed, format("format_string")]];
struct BaseBox {
u64 boxSize = 0;
u64 startOffset = $;
u64 endOffset = 0;
u32 size;
char type[4];
// Calculate the size of the current box
// 1. If the size is equal to 1 -> the box size is equal to 'largeSize' attribute.
// 2. If the size is equal to 0 -> The box extends to the end of the file.
// 3. Otherwise, size is equaly to the 'size' attribute.
if (this.size == 1) {
u64 largeSize;
boxSize = largeSize;
endOffset = startOffset + boxSize;
} else if (this.size == 0) {
boxSize = std::mem::size() - startOffset;
endOffset = std::mem::size();
} else {
boxSize = size;
endOffset = startOffset + boxSize;
}
if (this.type == "uuid") {
char usertype[16];
}
};
struct FullBox : BaseBox {
u8 version;
u24 flags;
};
struct UnknownBox : BaseBox {
u8 unk[while($ != endOffset)];
};
using brand = u32 [[format("to_string")]];
struct FileTypeBox : BaseBox {
brand major_brand;
u32 minor_version;
brand compatible_brands[(endOffset - $) / sizeof(brand)];
};
struct MovieHeaderBox : FullBox {
if (this.version == 1) {
u64 creation_time;
u64 modification_time;
u32 timescale;
u64 duration;
} else { // version == 0
u32 creation_time;
u32 modification_time;
u32 timescale;
u32 duration;
}
FixedPoint32 rate;
FixedPoint16 volume;
u8 reserved[10] [[sealed]];
u32 matrix[9];
u32 preview_time;
u32 preview_duration;
u32 poster_time;
u32 selection_time;
u32 selection_duration;
u32 current_time;
u32 next_track_id;
};
struct TrackHeaderBox : FullBox {
if (this.version == 1) {
u64 creation_time;
u64 modification_time;
u32 track_id;
u32 reserved;
u64 duration;
} else { // version == 0
u32 creation_time;
u32 modification_time;
u32 track_id;
u32 reserved;
u32 duration;
}
u32 reserved_2[2] [[sealed]];
s16 layer;
s16 alternate_group;
s16 volume;
u16 reserved_3;
s32 matrix[9];
u32 width;
u32 height;
};
struct DataEntryBox : FullBox {
if (std::string::contains(this.type, "url")) {
string location;
} else if (std::string::contains(this.type, "urn")) {
string name;
string location;
} else {
std::error("Invalid DataEntryBox");
}
};
struct DataReferenceBox : FullBox {
u32 entry_count;
DataEntryBox data_entries[this.entry_count];
};
struct SubDataInformationBox {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("dref"): DataReferenceBox box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("DataInformationBox({})", box.type))]];
struct DataInformationBox : BaseBox {
SubDataInformationBox box[while($ < endOffset)] [[inline]];
};
struct HandlerBox : FullBox {
u32 component_type;
char handler_type[4];
u32 reserved[3];
char name[endOffset - $];
};
struct VideoMediaHeaderBox : FullBox {
u16 graphicsmode;
u16 opcolor[3];
};
struct Avc1Box : BaseBox {
u48 reserved;
u16 data_reference_index;
u16 version;
u16 revision_level;
u32 max_packet_size;
if (this.version == 0 || this.version == 1) {
u32 temporal_quality;
u32 spatial_quality;
u16 width;
u16 height;
FixedPoint32 horizontal_resolution;
FixedPoint32 vertical_resolution;
u32 data_size;
u16 frame_count;
char compressor_name[32];
u16 depth;
s16 color_table_id;
}
u8 unk[while($ != endOffset)];
};
struct Mp4aBox : BaseBox {
u48 reserved;
u16 data_reference_index;
u16 version;
u16 revision_level;
u32 max_packet_size;
if (this.version == 0) {
u16 num_audio_channels;
u16 sample_size;
u16 compression_id;
u16 packet_size;
FixedPoint32 sample_rate;
}
u8 unk[while($ != endOffset)];
};
struct SubSampleDescriptionBox {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("mp4a"): Mp4aBox box [[inline]];
("avc1"): Avc1Box box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("SubSampleDescriptionBox({})", box.type))]];
struct SampleDescriptionBox : FullBox {
u32 entry_count;
SubSampleDescriptionBox box[while($ < endOffset)] [[inline]];
};
struct SampleTimeToSampleEntry {
u32 sample_count;
u32 sample_delta;
};
struct SampleTimeToSampleBox: FullBox {
u32 entry_count;
SampleTimeToSampleEntry entry_list[this.entry_count];
u8 unk[while($ != endOffset)];
};
struct SampleToChunkEntry {
u32 first_chunk;
u32 samples_per_chunk;
u32 sample_description_index;
};
struct SampleToChunkBox: FullBox {
u32 entry_count;
SampleToChunkEntry entry_list[this.entry_count];
u8 unk[while($ != endOffset)];
};
struct ChunkOffsetBox: FullBox {
u32 entry_count;
u32 chunk_offset[this.entry_count];
u8 unk[while($ != endOffset)];
};
struct SyncSampleBox: FullBox {
u32 entry_count;
u32 sample_number[this.entry_count];
u8 unk[while($ != endOffset)];
};
struct CompositionOffsetEntryV0 {
u32 sample_count;
u32 sample_offset;
};
struct CompositionOffsetEntryV1 {
u32 sample_count;
s32 sample_offset;
};
struct CompositionOffsetBox: FullBox {
u32 entry_count;
if(this.version == 0) {
CompositionOffsetEntryV0 entry_list[this.entry_count];
}
else if (this.version == 1) {
CompositionOffsetEntryV1 entry_list[this.entry_count];
}
};
struct SubSampleBoxTable {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("stsd"): SampleDescriptionBox box [[inline]];
("stts"): SampleTimeToSampleBox box [[inline]];
("stsc"): SampleToChunkBox box [[inline]];
("stco"): ChunkOffsetBox box [[inline]];
("stss"): SyncSampleBox box [[inline]];
("ctts"): CompositionOffsetBox box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("SubSampleBoxTable({})", box.type))]];
struct SampleBoxTable : BaseBox {
SubSampleBoxTable box[while($ < endOffset)] [[inline]];
};
struct SubMediaInformationBox {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("vmhd"): VideoMediaHeaderBox box [[inline]];
("hdlr"): HandlerBox box [[inline]];
("dinf"): DataInformationBox box [[inline]];
("stbl"): SampleBoxTable box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("MediaInformationBox({})", box.type))]];
struct MediaInformationBox : BaseBox {
SubMediaInformationBox box[while($ < endOffset)] [[inline]];
};
struct MediaHeaderBox : FullBox {
if (this.version == 1) {
u64 creation_time;
u64 modification_time;
u32 timescale;
u64 duration;
} else { // version==0
u32 creation_time;
u32 modification_time;
u32 timescale;
u32 duration;
}
u16 language [[comment("ISO-639-2/T language code")]];
u16 quality;
};
struct SubMediaBox {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("mdhd"): MediaHeaderBox box [[inline]];
("hdlr"): HandlerBox box [[inline]];
("minf"): MediaInformationBox box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("MediaBox({})", box.type))]];
struct MediaBox : BaseBox {
SubMediaBox box[while($ < endOffset)] [[inline]];
};
struct EditListEntry64 {
u64 segment_duration;
s64 media_time;
s16 media_rate_integer;
s16 media_rate_fraction;
};
struct EditListEntry32 {
u32 segment_duration;
s32 media_time;
s16 media_rate_integer;
s16 media_rate_fraction;
};
struct EditListBox : FullBox {
u32 entry_count;
if (this.version == 1) {
EditListEntry64 entry_list[this.entry_count];
} else { // version 0
EditListEntry32 entry_list[this.entry_count];
}
};
struct SubEditBox {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("elst"): EditListBox box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("EditBox({})", box.type))]];
struct EditBox : BaseBox {
SubEditBox box[while($ < endOffset)] [[inline]];
};
struct SubTrackBox {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("mdia"): MediaBox box [[inline]];
("edts"): EditBox box [[inline]];
("tkhd"): TrackHeaderBox box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("TrackBox({})", box.type))]];
struct TrackBox : BaseBox {
SubTrackBox box[while($ < endOffset)] [[inline]];
};
struct SubMovieBox {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("mvhd"): MovieHeaderBox box [[inline]];
("trak"): TrackBox box [[inline]];
(_): UnknownBox box [[inline]];
// TODO: Add "iods" box
}
} [[name(std::format("MovieBox({})", box.type))]];
struct MovieBox : BaseBox {
SubMovieBox box[while($ < endOffset)] [[inline]];
};
struct MediaDataBox : BaseBox {
u8 data[while($ < endOffset)] [[sealed]];
};
struct Box {
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
match (str(type)) {
("ftyp"): FileTypeBox box [[inline]];
("moov"): MovieBox box [[inline]];
("mdat"): MediaDataBox box [[inline]];
(_): UnknownBox box [[inline]];
}
} [[name(std::format("Box({})", box.type))]];
Box mp4[while(!std::mem::eof())] @ 0x0;

View File

@@ -1,154 +1,157 @@
#pragma MIME application/x-msgpack
enum Type : u8 {
PositiveFixInt = 0x00 ... 0x7F,
FixMap = 0x80 ... 0x8F,
FixArray = 0x90 ... 0x9F,
FixStr = 0xA0 ... 0xBF,
Nil = 0xC0,
Unused = 0xC1,
False = 0xC2,
True = 0xC3,
Bin8 = 0xC4,
Bin16 = 0xC5,
Bin32 = 0xC6,
Ext8 = 0xC7,
Ext16 = 0xC8,
Ext32 = 0xC9,
Float32 = 0xCA,
Float64 = 0xCB,
Uint8 = 0xCC,
Uint16 = 0xCD,
Uint32 = 0xCE,
Uint64 = 0xCF,
Int8 = 0xD0,
Int16 = 0xD1,
Int32 = 0xD2,
Int64 = 0xD3,
FixExt1 = 0xD4,
FixExt2 = 0xD5,
FixExt4 = 0xD6,
FixExt8 = 0xD7,
FixExt16 = 0xD8,
Str8 = 0xD9,
Str16 = 0xDA,
Str32 = 0xDB,
Array16 = 0xDC,
Array32 = 0xDD,
Map16 = 0xDE,
Map32 = 0xDF,
NegativeFixInt = 0xE0 ... 0xFF
};
fn format_positive_fixint(u8 value) {
return value & 0b0111'1111;
};
fn format_negative_fixint(u8 value) {
return -(value & 0b0001'1111);
};
using MessagePack;
struct MapEntry {
MessagePack key, value;
};
struct MessagePack {
Type type;
if (u8(type) <= 0x7F) {
$ -= 1;
u8 value [[format("format_positive_fixint")]];
} else if (u8(type) >= Type::NegativeFixInt) {
$ -= 1;
u8 value [[format("format_negative_fixint")]];
} else if (type == Type::Uint8)
be u8 value;
else if (type == Type::Uint16)
be u16 value;
else if (type == Type::Uint32)
be u32 value;
else if (type == Type::Uint64)
be u64 value;
else if (type == Type::Int8)
be s8 value;
else if (type == Type::Int16)
be s16 value;
else if (type == Type::Int32)
be s32 value;
else if (type == Type::Int64)
be s64 value;
else if (type == Type::Float32)
be float value;
else if (type == Type::Float64)
be double value;
else if ((u8(type) & 0b1110'0000) == Type::FixStr)
char value[u8(type) & 0b0001'1111];
else if (type == Type::Str8) {
be u8 length;
char value[length];
} else if (type == Type::Str16) {
be u16 length;
char value[length];
} else if (type == Type::Str32) {
be u32 length;
char value[length];
} else if (type == Type::Bin8) {
be u8 length;
u8 value[length];
} else if (type == Type::Bin16) {
be u16 length;
u8 value[length];
} else if (type == Type::Bin32) {
be u32 length;
u8 value[length];
} else if ((u8(type) & 0b1111'0000) == Type::FixArray)
MessagePack value[u8(type) & 0b0000'1111];
else if (type == Type::Array16) {
be u16 length;
MessagePack value[length];
} else if (type == Type::Array32) {
be u32 length;
MessagePack value[length];
} else if ((u8(type) & 0b1111'0000) == Type::FixMap)
MapEntry value[u8(type) & 0b0000'1111];
else if (type == Type::Map16) {
be u16 length;
MapEntry value[length];
} else if (type == Type::Map32) {
be u32 length;
MapEntry value[length];
} else if (type == Type::FixExt1) {
s8 type;
u8 data;
} else if (type == Type::FixExt2) {
s8 type;
u16 data;
} else if (type == Type::FixExt4) {
s8 type;
u32 data;
} else if (type == Type::FixExt8) {
s8 type;
u64 data;
} else if (type == Type::FixExt16) {
s8 type;
u128 data;
} else if (type == Type::Ext8) {
u8 length;
s8 type;
u8 data[length];
} else if (type == Type::Ext16) {
u16 length;
s8 type;
u8 data[length];
} else if (type == Type::Ext32) {
u32 length;
s8 type;
u8 data[length];
}
};
#pragma author WerWolv
#pragma description MessagePack binary serialization format
#pragma MIME application/x-msgpack
enum Type : u8 {
PositiveFixInt = 0x00 ... 0x7F,
FixMap = 0x80 ... 0x8F,
FixArray = 0x90 ... 0x9F,
FixStr = 0xA0 ... 0xBF,
Nil = 0xC0,
Unused = 0xC1,
False = 0xC2,
True = 0xC3,
Bin8 = 0xC4,
Bin16 = 0xC5,
Bin32 = 0xC6,
Ext8 = 0xC7,
Ext16 = 0xC8,
Ext32 = 0xC9,
Float32 = 0xCA,
Float64 = 0xCB,
Uint8 = 0xCC,
Uint16 = 0xCD,
Uint32 = 0xCE,
Uint64 = 0xCF,
Int8 = 0xD0,
Int16 = 0xD1,
Int32 = 0xD2,
Int64 = 0xD3,
FixExt1 = 0xD4,
FixExt2 = 0xD5,
FixExt4 = 0xD6,
FixExt8 = 0xD7,
FixExt16 = 0xD8,
Str8 = 0xD9,
Str16 = 0xDA,
Str32 = 0xDB,
Array16 = 0xDC,
Array32 = 0xDD,
Map16 = 0xDE,
Map32 = 0xDF,
NegativeFixInt = 0xE0 ... 0xFF
};
fn format_positive_fixint(u8 value) {
return value & 0b0111'1111;
};
fn format_negative_fixint(u8 value) {
return -(value & 0b0001'1111);
};
using MessagePack;
struct MapEntry {
MessagePack key, value;
};
struct MessagePack {
Type type;
if (u8(type) <= 0x7F) {
$ -= 1;
u8 value [[format("format_positive_fixint")]];
} else if (u8(type) >= Type::NegativeFixInt) {
$ -= 1;
u8 value [[format("format_negative_fixint")]];
} else if (type == Type::Uint8)
be u8 value;
else if (type == Type::Uint16)
be u16 value;
else if (type == Type::Uint32)
be u32 value;
else if (type == Type::Uint64)
be u64 value;
else if (type == Type::Int8)
be s8 value;
else if (type == Type::Int16)
be s16 value;
else if (type == Type::Int32)
be s32 value;
else if (type == Type::Int64)
be s64 value;
else if (type == Type::Float32)
be float value;
else if (type == Type::Float64)
be double value;
else if ((u8(type) & 0b1110'0000) == Type::FixStr)
char value[u8(type) & 0b0001'1111];
else if (type == Type::Str8) {
be u8 length;
char value[length];
} else if (type == Type::Str16) {
be u16 length;
char value[length];
} else if (type == Type::Str32) {
be u32 length;
char value[length];
} else if (type == Type::Bin8) {
be u8 length;
u8 value[length];
} else if (type == Type::Bin16) {
be u16 length;
u8 value[length];
} else if (type == Type::Bin32) {
be u32 length;
u8 value[length];
} else if ((u8(type) & 0b1111'0000) == Type::FixArray)
MessagePack value[u8(type) & 0b0000'1111];
else if (type == Type::Array16) {
be u16 length;
MessagePack value[length];
} else if (type == Type::Array32) {
be u32 length;
MessagePack value[length];
} else if ((u8(type) & 0b1111'0000) == Type::FixMap)
MapEntry value[u8(type) & 0b0000'1111];
else if (type == Type::Map16) {
be u16 length;
MapEntry value[length];
} else if (type == Type::Map32) {
be u32 length;
MapEntry value[length];
} else if (type == Type::FixExt1) {
s8 type;
u8 data;
} else if (type == Type::FixExt2) {
s8 type;
u16 data;
} else if (type == Type::FixExt4) {
s8 type;
u32 data;
} else if (type == Type::FixExt8) {
s8 type;
u64 data;
} else if (type == Type::FixExt16) {
s8 type;
u128 data;
} else if (type == Type::Ext8) {
u8 length;
s8 type;
u8 data[length];
} else if (type == Type::Ext16) {
u16 length;
s8 type;
u8 data[length];
} else if (type == Type::Ext32) {
u32 length;
s8 type;
u8 data[length];
}
};
MessagePack pack @ 0x00;

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Nintendo Switch NACP files
#pragma endian little
#include <std/sys.pat>

View File

@@ -1,76 +1,79 @@
#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 if (parent.tag == Tag::IntArray){
s32 arrayLength;
s32 value[arrayLength] [[sealed]];
} else if (parent.tag == Tag::LongArray) {
s32 arrayLength;
s64 value[arrayLength] [[sealed]];
} 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;
#pragma author WerWolv
#pragma description Minecraft NBT format
#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 if (parent.tag == Tag::IntArray){
s32 arrayLength;
s32 value[arrayLength] [[sealed]];
} else if (parent.tag == Tag::LongArray) {
s32 arrayLength;
s64 value[arrayLength] [[sealed]];
} 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;

View File

@@ -1,3 +1,5 @@
#pragma description NE header and Standard NE fields
#include <std/mem.pat>
struct DOSHeader {

87
patterns/nes.hexpat Normal file
View File

@@ -0,0 +1,87 @@
#pragma author gmestanley
#pragma description .nes file format
#include <std/mem.pat>
#include <std/string.pat>
bitfield iNES07Flags {
mirroringIsVertical : 1;
batterybackedPRGRAM : 1;
trainerOf512Bytes : 1;
ignoreMirroring : 1;
mapperLowerNybble : 4;
vsUnisystem : 1;
playchoice10 : 1;
nes2Format : 2 [[name("nes2.0Format")]];
mapperHigherNybble : 4;
} [[name("iNES0.7Flags")]];
bitfield Flags9 {
isPAL : 1;
padding : 7;
};
bitfield Flags10 {
tvSystem : 2;
padding : 2;
prgRAM : 1;
busConflicts : 1;
padding : 2;
};
struct iNESFlags {
iNES07Flags ines07Flags [[name("ines0.7Flags")]];
if (!ines07Flags.nes2Format) {
u8 prgRAM8KBMultiplier;
Flags9 flags9;
Flags10 flags10;
restLength = 5;
}
else {
restLength = 9;
}
};
u8 restLength;
struct Header {
char identifier[4];
u8 prgROM16KBMultiplier;
u8 chrROM8KBMultiplier;
iNESFlags inesFlags;
char rest[restLength];
};
Header header @ 0x00;
enum EncodingType : u8 {
ASCII = 1
};
struct OfficialHeader {
char title[16] [[hex::spec_name("Title Registration Area")]];
u16 programChecksum;
u16 characterChecksum;
u8 memorySize [[hex::spec_name("Cartridge Memory Size")]];
u8 cartridgeType;
EncodingType encodingType [[hex::spec_name("Registration Character Type Distinction")]];
u8 titleLength [[hex::spec_name("Registration Characters Count")]];
u8 makerID [[hex::spec_name("Maker Code")]];
u8 complementaryChecksum;
};
union OfficialHeaderUnion {
u8 miscellaneousData[26];
OfficialHeader officialHeader;
};
struct PRGROM {
u8 data[16384*header.prgROM16KBMultiplier-32];
OfficialHeaderUnion officialHeaderUnion;
u16 nmi;
u16 entryPoint;
u16 externalIRQ;
};
PRGROM prgROM @ sizeof(header);
u8 chrROM[8192*header.chrROM8KBMultiplier] @ sizeof(header)+sizeof(prgROM);

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Nintendo Switch NRO files
#include <std/io.pat>
#include <std/sys.pat>

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC
#include <std/core.pat>
using BitfieldOrder = std::core::BitfieldOrder;
@@ -77,7 +80,7 @@ struct Length {
u8 length;
} [[sealed, transform("transform_length"), format("transform_length")]];
fn transform_length(Length length) {
fn transform_length(ref auto length) {
return length.length;
};

View File

@@ -1,29 +1,32 @@
#pragma MIME audio/ogg
#include <std/core.pat>
#include <std/mem.pat>
bitfield HeaderType {
Continuation : 1;
BeginOfStream : 1;
EndOfStream : 1;
};
struct SegmentData {
u8 data[parent.segmentTable[std::core::array_index()]];
};
struct Ogg {
char capturePattern[4];
u8 version;
HeaderType headerType;
u64 granulePosition;
u32 bitstreamSerialNumber;
u32 pageSequenceNumber;
u32 checksum;
u8 pageSegments;
u8 segmentTable[pageSegments];
SegmentData data[pageSegments];
};
#pragma author WerWolv
#pragma description OGG Audio format
#pragma MIME audio/ogg
#include <std/core.pat>
#include <std/mem.pat>
bitfield HeaderType {
Continuation : 1;
BeginOfStream : 1;
EndOfStream : 1;
};
struct SegmentData {
u8 data[parent.segmentTable[std::core::array_index()]];
};
struct Ogg {
char capturePattern[4];
u8 version;
HeaderType headerType;
u64 granulePosition;
u32 bitstreamSerialNumber;
u32 pageSequenceNumber;
u32 checksum;
u8 pageSegments;
u8 segmentTable[pageSegments];
SegmentData data[pageSegments];
};
Ogg ogg[while(!std::mem::eof())] @ 0x00;

View File

@@ -1,3 +1,5 @@
#pragma description pcap header and packets
#include <std/mem.pat>
#pragma MIME application/vnd.tcpdump.pcap

View File

@@ -1,52 +1,55 @@
#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];
};
#pragma author WerWolv
#pragma description PCX Image format
#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;

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,41 @@
#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];
};
#pragma author WerWolv
#pragma description Nintendo Switch PFS0 archive (NSP files)
#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;

View File

@@ -1,3 +1,5 @@
#pragma description PIF Image Format
/* PIF - Portable Image Format
*
* Basic decoder for the PIF file structure

View File

@@ -1,6 +1,10 @@
#pragma description PNG image files
#pragma MIME image/png
#pragma endian big
#include <std/mem.pat>
struct header_t {
u8 highBitByte;
char signature[3];
@@ -168,7 +172,7 @@ struct chunk_t {
}
u32 crc;
} [[format("chunkValueName")]];
} [[name(chunkValueName(this))]];
fn chunkValueName(ref chunk_t chunk) {
return chunk.name;
@@ -178,7 +182,12 @@ struct chunk_set {
chunk_t chunks[while(builtin::std::mem::read_string($ + 4, 4) != "IEND")] [[inline]];
} [[inline]];
struct Chunks {
chunk_t ihdr_chunk [[comment("PNG Header chunk")]];
chunk_set set [[comment("PNG Chunks"), name("Chunks"), inline]];
chunk_t iend_chunk [[comment("Image End Chunk")]];
};
u8 visualizer[std::mem::size()] @ 0x00 [[sealed, hex::visualize("image", this)]];
header_t header @ 0x00 [[comment("PNG file signature"), name("Signature")]];
chunk_t ihdr_chunk @ 0x08 [[comment("PNG Header chunk"), name("IHDR")]];
chunk_set set @ $ [[comment("PNG Chunks"), name("Chunks"), inline]];
chunk_t iend_chunk @ $ [[comment("Image End Chunk"), name("IEND")]];
Chunks chunks @ 0x08 [[name("Chunks")]];

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Nintendo Switch PRODINFO
enum Model : u16 {
NX = 1
};

View File

@@ -1,3 +1,6 @@
#pragma author WerWolv
#pragma description Google Protobuf encoding
#include <std/core.pat>
#include <std/mem.pat>

340
patterns/pyc.hexpat Normal file
View File

@@ -0,0 +1,340 @@
#pragma description Python bytecode files
#include <type/time.pat>
#include <std/mem.pat>
#define FLAG_REF 0x80
#define TYPE_NULL '0'
#define TYPE_NONE 'N'
#define TYPE_FALSE 'F'
#define TYPE_TRUE 'T'
#define TYPE_STOPITER 'S'
#define TYPE_ELLIPSIS '.'
#define TYPE_INT 'i'
#define TYPE_INT64 'I'
#define TYPE_FLOAT 'f'
#define TYPE_BINARY_FLOAT 'g'
#define TYPE_COMPLEX 'x'
#define TYPE_BINARY_COMPLEX 'y'
#define TYPE_LONG 'l'
#define TYPE_STRING 's'
#define TYPE_INTERNED 't'
#define TYPE_REF 'r'
#define TYPE_STRINGREF 'R'
#define TYPE_TUPLE '('
#define TYPE_LIST '['
#define TYPE_DICT '{'
#define TYPE_CODE 'c'
#define TYPE_UNICODE 'u'
#define TYPE_UNKNOWN '?'
#define TYPE_SET '<'
#define TYPE_FROZENSET '>'
#define TYPE_ASCII 'a'
#define TYPE_ASCII_INTERNED 'A'
#define TYPE_SMALL_TUPLE ')'
#define TYPE_SHORT_ASCII 'z'
#define TYPE_SHORT_ASCII_INTERNED 'Z'
#define MAX_REFS 2048
using MarshalObject;
u8 _major;
u8 _minor;
fn above(u8 major, u8 minor) {
return _major >= major && _minor >= minor;
};
fn below(u8 major, u8 minor) {
return _major <=major && _minor < minor;
};
fn is(u8 major, u8 minor) {
return _major == major && _minor == minor;
};
fn between(u8 major, u8 minor, u8 otherMajor, u8 otherMinor) {
return above(major, minor) && below(otherMajor, otherMinor);
};
struct NoneObject {};
struct MarshalString {
if(parent.type == TYPE_SHORT_ASCII || parent.type == TYPE_SHORT_ASCII_INTERNED)
u8 length;
else
u32 length;
char data[length];
};
struct MarshalSequence {
if(parent.type == TYPE_SMALL_TUPLE)
u8 length;
else
u32 length;
MarshalObject values[length];
};
struct MarshalCode {
if(between(1, 3, 2, 3)) u16 numArgs;
else if(above(2, 3)) u32 numArgs;
if(above(3, 8)) u32 numPosOnlyArgs;
if(_major >= 3) u32 numKwOnlyArgs;
if(between(1, 3, 2, 3)) u16 numLocals;
else if(between(2, 3, 3, 11)) u32 numLocals;
if(between(1, 5, 2, 3)) u16 numStack;
else if(above(2, 3)) u32 numStack;
if(between(1, 3, 2, 3)) u16 flags;
else if(above(2, 3)) u32 flags;
MarshalObject code;
MarshalObject constants;
MarshalObject names;
if(above(1, 3)) MarshalObject localNames;
if(above(3, 11)) MarshalObject localKinds;
if(between(2, 1, 3, 11)) {
MarshalObject freeVars;
MarshalObject cellVars;
}
MarshalObject fileName;
MarshalObject name;
if(above(3, 11)) MarshalObject qualifiedName;
if(between(1, 5, 2, 3)) u16 firstLine;
else if(above(2, 3)) u32 firstLine;
if(above(1, 5)) MarshalObject lnTable;
if(above(3, 11)) MarshalObject exceptionTable;
};
struct DictEntry {
MarshalObject key;
if(key.type == TYPE_NULL) break;
MarshalObject value;
};
struct MarshalDict {
DictEntry entries[while(true)];
};
struct LongInt {
u32 len;
u16 buffer[len];
};
struct LongFloat {
u8 len;
u8 buffer[len];
};
struct LongComplex {
LongFloat real;
LongFloat imag;
};
auto section = std::mem::create_section("ref-address");
u128 refs[MAX_REFS] @ 0x0 in section;
u32 refIndex;
fn refMember(u128 address) {
refs[refIndex] = address;
refIndex += 1;
};
fn getRef(u32 index) {
return refs[index];
};
struct MarshalObject {
u8 _type [[hidden]];
u8 flag = _type & FLAG_REF;
u8 type = _type & ~FLAG_REF;
if(flag) {
refMember($-1);
}
match(type) {
(TYPE_NULL | TYPE_NONE | TYPE_STOPITER | TYPE_ELLIPSIS | TYPE_FALSE | TYPE_TRUE): continue;
(TYPE_CODE): {
MarshalCode code [[inline]];
}
(TYPE_STRING |
TYPE_UNICODE |
TYPE_ASCII |
TYPE_ASCII_INTERNED |
TYPE_SHORT_ASCII |
TYPE_SHORT_ASCII_INTERNED): {
MarshalString string [[inline]];
}
(TYPE_SMALL_TUPLE | TYPE_TUPLE | TYPE_LIST | TYPE_SET | TYPE_FROZENSET): {
MarshalSequence sequence [[inline]];
}
(TYPE_DICT): {
MarshalDict dict [[inline]];
}
(TYPE_INT): {
u32 int;
}
(TYPE_INT64): {
u64 long;
}
(TYPE_FLOAT): {
LongFloat number;
}
(TYPE_BINARY_FLOAT): {
double number;
}
(TYPE_COMPLEX): {
LongComplex complex;
}
(TYPE_BINARY_COMPLEX): {
double real;
double imag;
}
(TYPE_LONG): {
LongInt long;
}
(TYPE_REF): {
u32 index;
MarshalObject obj @ getRef(index);
}
(_): {
std::print("Unknown marshal object type: {:c}", type);
}
}
} [[format("format_marshal")]];
fn format_marshal(ref auto obj) {
match(obj.type) {
(TYPE_NONE): return "None";
(TYPE_STOPITER): return "StopIteration";
(TYPE_ELLIPSIS): return "...";
(TYPE_FALSE): return "False";
(TYPE_TRUE): return "True";
(TYPE_INT): return "int";
(TYPE_INT64): return "int64";
(TYPE_FLOAT): return "float";
(TYPE_BINARY_FLOAT): return "float";
(TYPE_COMPLEX): return "complex";
(TYPE_BINARY_COMPLEX): return "complex";
(TYPE_LONG): return "long";
(TYPE_STRING): return "string";
(TYPE_INTERNED): return "interned";
(TYPE_REF): return "ref";
(TYPE_TUPLE): return "tuple";
(TYPE_LIST): return "list";
(TYPE_DICT): return "dict";
(TYPE_CODE): return "code";
(TYPE_UNICODE): return "unicode";
(TYPE_UNKNOWN): return "unknown";
(TYPE_SET): return "set";
(TYPE_FROZENSET): return "frozenset";
(TYPE_ASCII): return "ascii";
(TYPE_ASCII_INTERNED): return "ascii_interned";
(TYPE_SHORT_ASCII): return "short_ascii";
(TYPE_SHORT_ASCII_INTERNED): return "short_ascii_interned";
(TYPE_SMALL_TUPLE): return "small_tuple";
}
};
enum Magic : u32 {
MAGIC_1_0 = 0x00999902,
MAGIC_1_1 = 0x00999903, /* Also covers 1.2 */
MAGIC_1_3 = 0x0A0D2E89,
MAGIC_1_4 = 0x0A0D1704,
MAGIC_1_5 = 0x0A0D4E99,
MAGIC_1_6 = 0x0A0DC4FC,
MAGIC_2_0 = 0x0A0DC687,
MAGIC_2_1 = 0x0A0DEB2A,
MAGIC_2_2 = 0x0A0DED2D,
MAGIC_2_3 = 0x0A0DF23B,
MAGIC_2_4 = 0x0A0DF26D,
MAGIC_2_5 = 0x0A0DF2B3,
MAGIC_2_6 = 0x0A0DF2D1,
MAGIC_2_7 = 0x0A0DF303,
MAGIC_3_0 = 0x0A0D0C3A,
MAGIC_3_1 = 0x0A0D0C4E,
MAGIC_3_2 = 0x0A0D0C6C,
MAGIC_3_3 = 0x0A0D0C9E,
MAGIC_3_4 = 0x0A0D0CEE,
MAGIC_3_5 = 0x0A0D0D16,
MAGIC_3_5_3 = 0x0A0D0D17,
MAGIC_3_6 = 0x0A0D0D33,
MAGIC_3_7 = 0x0A0D0D42,
MAGIC_3_8 = 0x0A0D0D55,
MAGIC_3_9 = 0x0A0D0D61,
MAGIC_3_10 = 0x0A0D0D6F,
MAGIC_3_11 = 0x0A0D0DA7,
INVALID = 0,
};
fn getMajor(Magic magic) {
match(magic) {
(Magic::MAGIC_1_0 | Magic::MAGIC_1_1 | Magic::MAGIC_1_3 | Magic::MAGIC_1_4 | Magic::MAGIC_1_5 | Magic::MAGIC_1_6): return 1;
(Magic::MAGIC_2_0 | Magic::MAGIC_2_1 | Magic::MAGIC_2_2 | Magic::MAGIC_2_3 | Magic::MAGIC_2_4 | Magic::MAGIC_2_5 | Magic::MAGIC_2_6 | Magic::MAGIC_2_7): return 2;
(Magic::MAGIC_3_0 | Magic::MAGIC_3_1 | Magic::MAGIC_3_2 | Magic::MAGIC_3_3 | Magic::MAGIC_3_4 | Magic::MAGIC_3_5 | Magic::MAGIC_3_5_3 | Magic::MAGIC_3_6 | Magic::MAGIC_3_7 | Magic::MAGIC_3_8 | Magic::MAGIC_3_9 | Magic::MAGIC_3_10 | Magic::MAGIC_3_11): return 3;
(Magic::INVALID): return 0;
}
};
fn getMinor(Magic magic) {
match(magic) {
(Magic::MAGIC_1_0 | Magic::MAGIC_2_0 | Magic::MAGIC_3_0): return 0;
(Magic::MAGIC_1_1 | Magic::MAGIC_2_1 | Magic::MAGIC_3_1): return 1;
(Magic::MAGIC_1_3 | Magic::MAGIC_2_2 | Magic::MAGIC_3_2): return 2;
(Magic::MAGIC_1_4 | Magic::MAGIC_2_3 | Magic::MAGIC_3_3): return 3;
(Magic::MAGIC_1_5 | Magic::MAGIC_2_4 | Magic::MAGIC_3_4): return 4;
(Magic::MAGIC_1_6 | Magic::MAGIC_2_5 | Magic::MAGIC_3_5 | Magic::MAGIC_3_5_3): return 5;
(Magic::MAGIC_2_6 | Magic::MAGIC_3_6): return 6;
(Magic::MAGIC_2_7 | Magic::MAGIC_3_7): return 7;
(Magic::MAGIC_3_8): return 8;
(Magic::MAGIC_3_9): return 9;
(Magic::MAGIC_3_10): return 10;
(Magic::MAGIC_3_11): return 11;
(Magic::INVALID): return 0;
}
};
struct PYCHeader {
Magic magic;
_major = getMajor(magic);
_minor = getMinor(magic);
u8 major = _major [[export]];
u8 minor = _minor [[export]];
if(above(3, 7)) {
u32 flags;
} else {
u32 flags;
}
if(flags & 0x1) {
u64 checksum;
} else {
type::time32_t timestamp;
if(above(3, 3)) {
u32 size;
}
}
MarshalObject object;
};
PYCHeader header @ 0x0;

View File

@@ -0,0 +1,80 @@
#pragma description PyInstaller binray files
#pragma endian big
#include <std/mem.pat>
// Reference:
// https://pyinstaller.org/en/stable/advanced-topics.html
// typedef struct _cookie {
// char magic[8]; /* 'MEI\014\013\012\013\016' */
// uint32_t len; /* len of entire package */
// uint32_t TOC; /* pos (rel to start) of TableOfContents */
// int TOClen; /* length of TableOfContents */
// int pyvers; /* new in v4 */
// char pylibname[64]; /* Filename of Python dynamic library. */
// } COOKIE;
u8 cookieStructLength = 88;
struct Cookie {
char signature[8];
u32 len;
u32 TOC[[comment("Table of Content")]];
s32 TOClen;
s32 pyVers;
char pyLibName[64];
};
u32 cookieOffset = std::mem::find_sequence(0, 'M', 'E', 'I', 0x0C, 0x0B, 0x0A, 0x0B, 0x0E);
Cookie cookie @ cookieOffset;
u32 startOffset = cookieOffset + cookieStructLength - cookie.len;
u32 tocOffset = startOffset + cookie.TOC;
struct ZlibArchive {
char pyzMagic[4];
char pyMagic[4];
u32 pyzTOCPos[[comment("Table of Content of the embedded PYZ")]];
};
// typedef struct _toc {
// int structlen; /* len of this one - including full len of name */
// uint32_t pos; /* pos rel to start of concatenation */
// uint32_t len; /* len of the data (compressed) */
// uint32_t ulen; /* len of data (uncompressed) */
// char cflag; /* is it compressed (really a byte) */
// char typcd; /* type code -'b' binary, 'z' zlib, 'm' module,
// * 's' script (v3),'x' data, 'o' runtime option */
// char name[1]; /* the name to save it as */
// /* starting in v5, we stretch this out to a mult of 16 */
// } TOC;
u32 tocStructLength = 18;
enum TypeCode : u8 {
Binary = 98,
Zlib = 122,
Module = 109,
Script = 115,
Data = 120,
RuntimeOption = 111,
};
struct TOC {
s32 structLen;
u32 pos;
u32 len[[comment("len of the data (compressed)")]];;
u32 uLen[[comment("len of data (uncompressed)")]];;
bool cFlag[[comment("is it compressed")]];;
TypeCode typcd;
char name[this.structLen - tocStructLength];
if(typcd == TypeCode::Zlib) {
ZlibArchive zlibArchive @ startOffset + this.pos;
}
};
TOC toc[while( $ < cookie.TOClen + tocOffset)] @ tocOffset;

View File

@@ -1,3 +1,5 @@
#pragma description Qubicle voxel scene project file
// Qubicle QBCL format
struct String {

View File

@@ -1,3 +1,5 @@
#pragma description QOI image files
#pragma MIME image/qoi
#pragma endian big

724
patterns/selinux.hexpat Normal file
View File

@@ -0,0 +1,724 @@
#pragma description SE Linux modules
#pragma author Ange Albertini
#include <std/sys.pat>
#pragma pattern_limit 13107200
#pragma array_limit 13107200
#pragma endian little
u32 version;
u32 symbols_count;
u32 object_contexts_count;
u32 type_primary_names_count = 0;
bool boundary_feature;
using Header;
enum magics: u32 {
kernel = 0xf97cff8c,
module = 0xf97cff8d,
};
bitfield CONFIG {
DENY_UNKNOWN: 1;
MLS: 1;
REJECT_UNKNOWN: 1;
ALLOW_UNKNOWN: 1;
padding: 4 + 3 * 8;
};
enum policy_types: u32 {
kernel = 0,
base = 1,
module = 2,
};
policy_types type_g;
enum targets: u32 {
selinux = 0,
xen = 1,
};
targets target;
struct list<T> {
u32 count;
T item[count];
};
struct symbols_list<T> {
u32 primary_names_count;
list<T> [[inline]];
};
struct permission {
u32 length;
u32 value;
char key[length];
};
struct extensible_bitmap_node {
u32 startbit;
u64 map;
};
struct extensible_bitmap {
u32 mapsize;
std::assert(mapsize == 0x40 , "Incorrect mapsize");
u32 highbit;
std::assert(!(highbit & 0x3F) , "Incorrect highbit");
u32 count;
std::assert(!((highbit > 0) && (count == 0)) , "Incorrect bitmap");
extensible_bitmap_node node[count];
};
struct type_set {
extensible_bitmap types;
extensible_bitmap negset;
u32 flag;
};
enum expression_types: u32 {
not = 1,
and = 2,
or = 3,
attr = 4,
names = 5,
};
struct expression {
expression_types type_;
u32 attribute;
u32 operator;
if (type_ == expression_types::names) {
extensible_bitmap names;
if ((type_g == policy_types::kernel && version >= 29) ||
(type_g != policy_types::kernel))
type_set type_names;
}
};
struct constraint {
u32 permissions;
list<expression> [[inline]];
};
struct mls_range {
u32 items;
u32 sensitivity0;
if (items > 1)
u32 sensitivity1;
extensible_bitmap category0;
if (items > 1)
extensible_bitmap category1;
};
struct role_set {
extensible_bitmap roles;
u32 flags;
};
struct mls_level {
u32 sensitivity;
extensible_bitmap category;
};
struct semantic_category {
u32 low;
u32 high;
};
struct mls_semantic_level {
u32 sensitivity;
list<semantic_category> [[inline]];
};
struct mls_semantic_range {
mls_semantic_level level0;
mls_semantic_level level1;
};
struct context_s {
u32 user;
u32 role;
u32 type_;
if (((type_g == policy_types::kernel) && (version >= 19)) || ((type_g == policy_types::base) && (version >= 5)))
mls_range mls_range;
};
struct common {
u32 length;
u32 value;
u32 primary_names_count;
u32 elements_count;
char key[length];
permission permission[elements_count];
};
using commons = symbols_list<common>;
struct class {
u32 key_length;
u32 common_key_length;
u32 value;
u32 primary_names_count;
u32 elements_count;
u32 constraints_count;
char key[key_length];
char common_key[common_key_length];
permission permissions[elements_count];
constraint constraints[constraints_count];
if (((type_g == policy_types::kernel) && (version >= 19)) || (type_g == policy_types::base && version >= 5))
u32 validatetrans_count;
if ((type_g == policy_types::kernel && version >= 19) || (type_g == policy_types::base && version >= 5))
constraint validatetrans[validatetrans_count];
if ((type_g == policy_types::kernel && version >= 27) || (type_g == policy_types::base && version >= 15)) {
u32 default_user;
u32 default_role;
u32 default_range;
}
if ((type_g == policy_types::kernel && version >= 28) || (type_g == policy_types::base && version >= 16))
u32 default_type;
};
using classes = symbols_list<class>;
struct role_s {
u32 length;
u32 value;
u32 bounds;
char key[length];
extensible_bitmap dominates;
if (type_g == policy_types::kernel)
extensible_bitmap types;
else
type_set types;
if ((type_g != policy_types::kernel && version >= 13)) {
u32 flavor;
extensible_bitmap roles;
}
};
using roles = symbols_list<role_s>;
struct type_s {
u32 length;
u32 value;
if ((boundary_feature && (type_g != policy_types::kernel && version >= 10)) || !boundary_feature)
u32 primary;
if (boundary_feature) {
u32 properties;
u32 bounds;
}
if (!boundary_feature && (type_g != policy_types::kernel))
u32 flavor;
if (!boundary_feature && (type_g != policy_types::kernel && version >= 8))
u32 flags;
if (type_g != policy_types::kernel)
extensible_bitmap types;
char key[length];
};
struct types_s {
u32 primary_names_count;
type_primary_names_count = primary_names_count;
list<type_s> [[inline]];
};
struct user_s {
u32 length;
u32 value;
if (boundary_feature)
u32 bounds;
char key[length];
if (type_g == policy_types::kernel)
extensible_bitmap roles;
else
role_set roles;
if ((type_g == policy_types::kernel && version >= 19) || (type_g == policy_types::module && version >= 5 && version < 6) || (type_g == policy_types::base && version >= 5 && version < 6)) {
mls_range exp_range;
mls_level exp_dftlevel;
}
if ((type_g == policy_types::module || type_g == policy_types::base) && (version >= 6)) {
mls_semantic_range range;
mls_semantic_range dfltlevel;
}
};
using users = symbols_list<user_s>;
struct bool_ { // conditional boolean
u32 value;
u32 state;
u32 length;
char key[length];
if ((type_g != policy_types::kernel && version >= 14))
u32 flags;
};
using bools = symbols_list<bool_>;
struct level {
u32 length;
u32 isalias;
char key[length];
mls_level level;
};
using sensitivity_levels = symbols_list<level>;
struct category {
u32 length;
u32 value;
u32 isalias;
char key[length];
};
using categories = symbols_list<category>;
struct symbols {
commons commons;
classes classes;
roles roles;
types_s types;
users users;
if (symbols_count >= 6)
bools bools;
if (symbols_count >= 7)
sensitivity_levels levels;
if (symbols_count >= 8)
categories cats;
};
struct module_header {
u32 name_length;
std::assert(name_length >= 1, "Invalid 'name_length' in module header.");
char name[name_length];
u32 version_length;
std::assert(version_length >= 1, "Invalid 'version_length' in module header.");
char version[version_length];
};
struct access_vector_old {
u32 total;
u32 source_type;
u32 target_type;
u32 target_class;
u32 value;
u32 data[8];
};
struct access_vector {
u16 source_type;
u16 target_type;
u16 target_class;
u16 specified;
if ((specified & 0x700) != 0) {
u8 xperms_specified;
u8 xperms_drivers;
u32 xperms_perms[8];
}
else
u32 data;
};
struct avrule_item {
u32 tclass;
u32 data;
};
struct avrule {
u32 specified;
u32 flags;
type_set stypes;
type_set ttypes;
u32 length;
avrule_item avrule_item[length];
if ((specified & (0x0100 | 0x0200 | 0x0400 | 0x0800)) != 0) {
u8 xperms_specified;
u8 xperms_driver;
list<u32> perms[[inline]];
}
};
struct avrule_list {
u32 length;
avrule avrule[length];
};
struct conditional_node_item {
u32 expr_type;
u32 boolean;
};
struct access_vector_table_s {
if (version < 20)
list<access_vector_old> access_vector_table;
else
list<access_vector> access_vector_table;
} [[inline]];
using cond_av_list = access_vector_table_s;
struct conditional_node {
u32 current_state;
u32 length;
conditional_node_item item[length];
if (type_g == policy_types::kernel) {
cond_av_list true_list;
cond_av_list false_list;
} else {
avrule_list avtrue_list;
avrule_list avfalse_list;
if (version >= 14)
u32 flags;
}
};
struct conditional_list {
u32 length;
conditional_node conditional_node[length];
};
struct role_trans_item {
u32 role;
u32 type_;
u32 new_role;
if (type_g == policy_types::kernel && version >= 26)
u32 tclass;
};
using role_trans = list<role_trans_item>;
struct role_allow_item {
u32 role;
u32 new_role;
};
using role_allow = list<role_allow_item>;
struct filename_trans_item_old {
u32 length;
char name[length];
u32 stype;
u32 ttype;
u32 tclass;
u32 otype;
};
struct filename_trans_item_item {
extensible_bitmap stypes;
u32 otype;
};
struct filename_trans_item {
u32 length;
char name[length];
u32 ttype;
u32 tclass;
list<filename_trans_item_item> types [[inline]];
};
struct role_trans_rule_item {
role_set roles;
role_set types;
if (version >= 12)
extensible_bitmap classes;
u32 new_role;
};
using role_trans_rule = list<role_trans_rule_item>;
struct role_allow_rule_item {
role_set roles;
role_set new_roles;
};
using role_allow_rule = list<role_allow_rule_item>;
struct scope_s {
u32 length;
char key[length];
u32 scope;
u32 decl_ids_len;
std::assert(decl_ids_len >= 1, "Invalid 'decl_ids_len'");
u32 decl_id[decl_ids_len];
};
struct scope_index {
extensible_bitmap scope[symbols_count];
u32 class_perms_len;
extensible_bitmap class_perms_map[class_perms_len];
};
using scope_list = list<scope_s>;
struct filename_trans_rule_item {
u32 length;
char name[length];
type_set stypes;
type_set ttypes;
u32 tclass;
u32 otype;
if (version >= 21)
u32 flags;
};
using filename_trans_rule = list<filename_trans_rule_item>;
struct range_trans_rule_item {
type_set stypes;
type_set ttypes;
extensible_bitmap tclasses;
mls_semantic_range trange;
};
using range_trans_rule = list<range_trans_rule_item>;
struct avrule_decl {
u32 decl_id;
u32 enabled;
conditional_list cond_list;
avrule_list avrules;
role_trans_rule role_tr_rules;
role_allow_rule role_allow_rules;
if (version >= 11)
filename_trans_rule filename_trans_rules;
if (version >= 6)
range_trans_rule range_tr_rules;
scope_index required;
scope_index declared;
symbols symbols;
};
struct avrule_block_item {
u32 num_decls;
if (num_decls > 0)
avrule_decl avrule_decl[num_decls];
};
using avrule_block = list<avrule_block_item>;
struct initial_sid {
u32 sid0;
context_s context0;
};
struct filesystem {
u32 length;
char key[length];
context_s context0;
context_s context1;
};
struct port {
u32 protocol;
u32 low_port;
u32 high_port;
context_s context;
};
struct node {
u32 addr;
u32 mask;
context_s context;
};
struct fsuse {
u32 behavior;
u32 length;
char name[length];
context_s context;
};
struct node6 {
u32 addr[4];
u32 mask[4];
context_s context;
};
struct ibpkey {
u32 low_pkey;
u32 high_pkey;
context_s context;
};
struct ibpendport {
u32 length;
u32 port;
char dev_name[length];
context_s context;
};
struct ocontext_selinux {
if (object_contexts_count < 1) break;
list<initial_sid> initial_sids;
if (object_contexts_count < 2) break;
list<filesystem> filesystems;
if (object_contexts_count < 3) break;
list<port> ports;
if (object_contexts_count < 4) break;
list<filesystem> network_interfaces; // same type
if (object_contexts_count < 5) break;
list<node> nodes;
if (object_contexts_count < 6) break;
list<fsuse> fsuses;
if (object_contexts_count < 7) break;
list<node6> nodes6;
if (object_contexts_count < 8) break;
list<ibpkey> ibpkeys;
if (object_contexts_count < 9) break;
list<ibpendport> ibpendports;
};
struct xen_isid {
u32 sid0;
context_s context0;
};
struct xen_pirq {
u32 pirq;
context_s context0;
};
struct xen_ioport {
u32 low_port;
u32 high_port;
context_s context0;
};
struct xen_iomem {
if (version >= 30) {
u64 low_iomem;
u64 high_iomem;
} else {
u32 low_iomem;
u32 high_iomem;
}
context_s context;
};
struct xen_pcidevice {
u32 device;
context_s context;
};
struct xen_devicetree {
u32 length;
char name[length];
context_s context;
};
struct ocontext_xen {
if (object_contexts_count < 1) break;
list<xen_isid> xen_isids;
if (object_contexts_count < 2) break;
list<xen_pirq> xen_pirqs;
if (object_contexts_count < 3) break;
list<xen_ioport> xen_ioports;
if (object_contexts_count < 4) break;
list<xen_iomem> xen_iomems;
if (object_contexts_count < 5) break;
list<xen_pcidevice> xen_pcidevices;
if (object_contexts_count < 6) break;
list<xen_devicetree> xen_devicetrees;
if (object_contexts_count < 7) break;
};
struct genfs2_item {
u32 length;
char name[length];
u32 sclass;
context_s context0;
};
struct genfs_item {
u32 length;
char fstype[length];
list<genfs2_item> [[inline]];
};
struct range_item {
u32 source_type;
u32 target_type;
if (type_g == policy_types::kernel && version >= 21)
u32 target_class;
mls_range range_tr;
};
struct Header {
magics magic;
std::assert(magic == magics::kernel || magic == magics::module , "Unexpected magic");
u32 policydb_str_len;
char policydb_str[policydb_str_len];
std::assert(policydb_str == "SE Linux" || policydb_str == "SE Linux Module" || policydb_str == "XenFlask", "Unexpected signature");
if (policydb_str == "XenFlask")
target = targets::xen;
else
target = targets::selinux;
std::assert((magic == magics::kernel && (policydb_str == "SE Linux" || policydb_str == "XenFlask"))
|| (magic == magics::module && policydb_str == "SE Linux Module"), "Non matching magic and signature");
if (magic == magics::module)
u32 policy_subtype;
if (magic == magics::kernel)
type_g = policy_types::kernel;
else
if (policy_subtype == policy_types::module)
type_g = policy_types::module;
else
type_g = policy_types::base;
u32 __policyvers;
version = __policyvers;
boundary_feature = (type_g == policy_types::kernel && version >= 24) || (type_g != policy_types::kernel && version >= 9);
std::assert((magic == magics::kernel && 15 <= version && version <= 33) || (magic != magics::kernel && 4 <= version && version <= 21), "Non matching type_g != and type");
CONFIG config;
u32 symbols_count_;
symbols_count = symbols_count_;
std::assert(0 <= symbols_count && symbols_count <= 9, "Invalid 'symbols_count' value.");
u32 object_contexts_count_;
object_contexts_count = object_contexts_count_;
std::assert(0 <= object_contexts_count && object_contexts_count <= 9, "Invalid 'object_contexts_count' value.");
if (magic == magics::module)
module_header module_header;
if ((type_g == policy_types::kernel && version >= 22) || (version >= 7))
extensible_bitmap policycaps;
if (type_g == policy_types::kernel && version >= 23)
extensible_bitmap permissive_map;
symbols symbols;
if (type_g == policy_types::kernel) {
access_vector_table_s access_vector_table;
}
if (type_g == policy_types::kernel && version >= 16)
conditional_list conditional_list;
if (type_g == policy_types::kernel) {
role_trans role_trans;
role_allow role_allow;
if (version >= 25) {
if (version < 33)
list<filename_trans_item_old> filename_trans;
else
list<filename_trans_item> filename_trans;
}
} else {
list<avrule_block_item> avrule_block;
list<scope_s> scope_list[symbols_count];
}
if (target == targets::selinux)
ocontext_selinux ocontext_selinux;
else
ocontext_xen ocontext_xen;
list<genfs_item> genfs;
if (((type_g == policy_types::kernel) && (version >= 19)) || ((type_g == policy_types::base) && (version == 5)))
list<range_item> range;
if (type_g == policy_types::kernel)
extensible_bitmap type_attr_map[type_primary_names_count];
};
Header header @ 0;

30
patterns/selinuxpp.hexpat Normal file
View File

@@ -0,0 +1,30 @@
#pragma description SE Linux package
// SE Linux Policy Package
// Extension: PP
// https://github.com/SELinuxProject/selinux/blob/master/libsepol/src/module.c
#pragma endian little
#include <std/sys.pat>
enum section_types : u32 {
file_context = 0xf97cff90,
module = 0xf97cff8d,
user = 0x097cff91,
user_extra = 0x097cff92,
netfilter = 0x097cff93,
};
struct section_s {
section_types *type : u32;
};
struct header_s {
u32 magic;
std::assert(magic == 0xf97cff8f, "invalid magic");
u32 version;
u32 sections_count;
section_s sections[sections_count];
};
header_s header @ 0x00;

201
patterns/shp.hexpat Normal file
View File

@@ -0,0 +1,201 @@
#pragma author Calcoph
#pragma description ESRI shapefile
// Spec:
// https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf
enum ShapeType: u32 {
Null = 0,
Point = 1,
PolyLine = 3,
Polygon = 5,
MultiPoint = 8,
PointZ = 11,
PolyLineZ = 13,
PolygonZ = 15,
MultiPointZ = 18,
PointM = 21,
PolyLineM = 23,
PolygonM = 25,
MultiPointM = 28,
MultiPatch = 32,
};
struct NullShape {
};
struct Point {
double x;
double y;
};
struct MultiPoint {
double box[4];
u32 num_points;
Point points[num_point];
};
struct PolyLine {
double box[4];
u32 num_parts;
u32 num_points;
u32 parts[num_parts];
Point points[num_points];
};
struct Polygon {
double box[4];
u32 num_parts;
u32 num_points;
u32 parts[num_parts];
Point points[num_points];
};
struct PointM {
double x;
double y;
double m;
};
struct MultiPointM {
double box[4];
u32 num_points;
Point points[num_point];
double m_range[2];
double m_array[num_points];
};
struct PolyLineM {
double box[4];
u32 num_parts;
u32 num_points;
u32 parts[num_parts];
Point points[num_points];
double m_range[2];
double m_array[num_points];
};
struct PolygonM {
double box[4];
u32 num_parts;
u32 num_points;
u32 parts[num_parts];
Point points[num_points];
double m_range[2];
double m_array[num_points];
};
struct PointZ {
double x;
double y;
double z;
double m;
};
struct MultiPointZ {
double box[4];
u32 num_points;
Point points[num_point];
double z_range[2];
double z_array[num_points];
double m_range[2];
double m_array[num_points];
};
struct PolyLineZ {
double box[4];
u32 num_parts;
u32 num_points;
u32 parts[num_parts];
Point points[num_points];
double z_range[2];
double z_array[num_points];
double m_range[2];
double m_array[num_points];
};
struct PolygonZ {
double box[4];
u32 num_parts;
u32 num_points;
u32 parts[num_parts];
Point points[num_points];
double z_range[2];
double z_array[num_points];
double m_range[2];
double m_array[num_points];
};
enum PartType: u32 {
TriangleStrip = 0,
TriangleFan = 1,
OuterRing = 2,
InnerRing = 3,
FirstRing = 4,
Ring = 5,
};
struct MultiPatch {
double box[4];
u32 num_parts;
u32 num_points;
u32 parts[num_parts];
PartType part_types[num_parts];
Point points[num_points];
double z_range[2];
double z_array[num_points];
double m_range[2];
double m_array[num_points];
};
struct Header {
be u32 magic; // 9994
padding[20]; // unused
be u32 file_length; // in 16-bit words (including header)
u32 version; // 1000
ShapeType shape_type;
// Bounding box
double bb_xmin;
double bb_ymin;
double bb_xmax;
double bb_ymax;
double bb_zmin;
double bb_zmax;
double bb_mmin;
double bb_mmax;
};
struct RecordHeader {
be u32 record_number; // starting at 1
be u32 content_length; // in 16-bit words
};
struct Record {
RecordHeader;
ShapeType shape_type;
match (shape_type) {
(ShapeType::Null): NullShape;
(ShapeType::Point): Point;
(ShapeType::PolyLine): PolyLine;
(ShapeType::Polygon): Polygon;
(ShapeType::MultiPoint): MultiPoint;
(ShapeType::PointZ): PointZ;
(ShapeType::PolyLineZ): PolyLineZ;
(ShapeType::PolygonZ): PolygonZ;
(ShapeType::MultiPointZ): MultiPointZ;
(ShapeType::PointM): PointM;
(ShapeType::PolyLineM): PolyLineM;
(ShapeType::PolygonM): PolygonM;
(ShapeType::MultiPointM): MultiPointM;
(ShapeType::MultiPatch): MultiPatch;
}
};
struct ShapeFile {
Header header;
Record records[while ($ < (header.file_length * 2))];
};
ShapeFile file @ 0x00;

52
patterns/shx.hexpat Normal file
View File

@@ -0,0 +1,52 @@
#pragma author Calcoph
#pragma description ESRI shapefile indices
// Spec:
// https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf
enum ShapeType: u32 {
Null = 0,
Point = 1,
PolyLine = 3,
Polygon = 5,
MultiPoint = 8,
PointZ = 11,
PolyLineZ = 13,
PolygonZ = 15,
MultiPointZ = 18,
PointM = 21,
PolyLineM = 23,
PolygonM = 25,
MultiPointM = 28,
MultiPatch = 32,
};
struct Header {
be u32 magic; // 9994
padding[20]; // unused
be u32 file_length; // in 16-bit words (including header)
u32 version; // 1000
ShapeType shape_type;
// Bounding box
double bb_xmin;
double bb_ymin;
double bb_xmax;
double bb_ymax;
double bb_zmin;
double bb_zmax;
double bb_mmin;
double bb_mmax;
};
struct Record {
u32 offset;
u32 content_length;
};
struct IndexFile {
Header header;
Record records[while($ < header.file_length * 2)];
};
IndexFile file @ 0x00;

View File

@@ -1,115 +1,118 @@
// 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;
};
bitfield Flags2 {
padding : 7;
resource_fork : 1;
padding : 8;
};
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;
};
}
#pragma author WerWolv
#pragma description StuffIt V5 archive
// 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;
};
bitfield Flags2 {
padding : 7;
resource_fork : 1;
padding : 8;
};
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;

View File

@@ -1,3 +1,5 @@
#pragma description SPIR-V header and instructions
#include <std/mem.pat>
enum GeneratorID : u16 {

View File

@@ -1,51 +1,54 @@
#pragma MIME model/stl
#pragma MIME model/x.stl-binary
#pragma MIME model/x.stl-ascii
#pragma MIME application/sla
#include <std/sys.pat>
#include <std/mem.pat>
#include <std/core.pat>
struct Vector3f {
float x, y, z;
} [[static, format("format_vector3f")]];
fn format_vector3f(Vector3f vec) {
return std::format("[ {}, {}, {} ]", vec.x, vec.y, vec.z);
};
struct Triangle {
Vector3f normal;
Vector3f points[3];
u16 flags;
} [[static]];
struct BinarySTLHeader {
char caption[while($[$] != 0x00 && $ - addressof(this) < 80)];
padding[80 - sizeof(caption)];
u32 triangleCount;
};
struct STL {
if (std::mem::read_string(0, 6) == "solid ")
std::warning("ASCII STL file!");
else {
BinarySTLHeader header;
Triangle triangles[header.triangleCount];
}
};
STL stl @ 0x00;
/* Visualize the 3D Model */
struct Vertex {
Vector3f points[3] @ addressof(stl.triangles[std::core::array_index()].points);
};
struct Model {
Vertex vertices[stl.header.triangleCount];
} [[highlight_hidden, sealed, hex::visualize("3d", vertices, null)]];
Model model @ 0x00;
#pragma author WerWolv
#pragma description STL 3D Model format
#pragma MIME model/stl
#pragma MIME model/x.stl-binary
#pragma MIME model/x.stl-ascii
#pragma MIME application/sla
#include <std/sys.pat>
#include <std/mem.pat>
#include <std/core.pat>
struct Vector3f {
float x, y, z;
} [[static, format("format_vector3f")]];
fn format_vector3f(Vector3f vec) {
return std::format("[ {}, {}, {} ]", vec.x, vec.y, vec.z);
};
struct Triangle {
Vector3f normal;
Vector3f points[3];
u16 flags;
} [[static]];
struct BinarySTLHeader {
char caption[while($[$] != 0x00 && $ - addressof(this) < 80)];
padding[80 - sizeof(caption)];
u32 triangleCount;
};
struct STL {
if (std::mem::read_string(0, 6) == "solid ")
std::warning("ASCII STL file!");
else {
BinarySTLHeader header;
Triangle triangles[header.triangleCount];
}
};
STL stl @ 0x00;
/* Visualize the 3D Model */
struct Vertex {
Vector3f points[3] @ addressof(stl.triangles[std::core::array_index()].points);
};
struct Model {
Vertex vertices[stl.header.triangleCount];
} [[highlight_hidden, sealed, hex::visualize("3d", vertices, null)]];
Model model @ 0x00;

View File

@@ -1,3 +1,5 @@
#pragma description Tar file format
#pragma MIME application/tar
#pragma MIME application/x-tar

Some files were not shown because too many files have changed in this diff Show More