Compare commits

..

127 Commits

Author SHA1 Message Date
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
Zaggy1024
1cd7f92a5d patterns/includes: Update standard library and patterns to support the new bitfields (#102)
* Add `current_bit_offset()` and `read_bits(...)` to `std::mem`

* Replace deprecated BitfieldOrder enum values with new clearer names

This adds new options named `MostToLeastSignificant` and `LeastToMostSignificant` to replace the old `LeftToRight` and `RightToLeft` names. These names should be much clearer about what they affect and how.

* Throw errors when `std::core::(get|set)_bitfield_order()` are called

* Update all patterns to work with the new bitfield behaviors
2023-04-01 11:16:54 +02:00
Nik
d42b87d9e6 git: Added CONTRIBUTING.md 2023-03-29 08:10:58 +02:00
Nik
035de359d7 git: Updated readme information 2023-03-29 08:03:40 +02:00
Nik
fe59788783 includes/type: Fixed IP library top level comment 2023-03-28 18:39:46 +02:00
Nik
ef198cf24f includes/type: Fixed Path formatter 2023-03-28 15:53:19 +02:00
Nik
b73b69a8cc includes: Added documentations for all remaining types and functions 2023-03-28 15:28:44 +02:00
Nik
5d72494019 includes/hex: Added ImHex check to provider library 2023-03-28 10:21:03 +02:00
Nik
afbce642fb includes/hex: Added provider functions 2023-03-28 09:49:12 +02:00
Nik
a72058eb65 includes/std: Added std::random functions 2023-03-28 09:28:28 +02:00
Chris Bailey
ab2ed98dab includes/std: Added nullable pointers to std/ptr (#97) 2023-03-27 10:05:12 +02:00
WerWolv
3edc6ea172 includes: Added documentation for a few more files 2023-03-26 16:58:39 +02:00
WerWolv
a9a7f0b186 includes: Added documentation to the rest of the std and hex library 2023-03-26 16:34:06 +02:00
Nik
5f352e26d1 patterns/elf: Make displaying section names optional 2023-03-26 11:34:52 +02:00
Nik
3e2a6aabaa patterns/evtx: Fixed type name typo 2023-03-26 11:22:15 +02:00
Nik
56d6f0187f patterns/zstd: Fixed block_header_t bitfield 2023-03-26 11:09:26 +02:00
Vladimir
adf7256c39 patterns/bsp: Added GoldSrc engine maps file format (#101)
Co-authored-by: Nik <werwolv98@gmail.com>
2023-03-26 10:36:03 +02:00
dora
a25a8a3615 patterns/evtx: Added evtx pattern (#100)
* add evtx pattern

* fix Readme

* fix coding style

* space adjustment

* space adjustment
2023-03-26 10:34:45 +02:00
WerWolv
6ae8b30488 git: Allow documentation to be regenerated when PatternLanguage changes were made 2023-03-26 10:26:40 +02:00
Nik
125ba38d72 plugins/extra-hashes: Fixed ImHex version 2023-03-25 15:33:55 +01:00
Nik
ba55feb200 plugins: Added Extra Hashes plugin to database 2023-03-25 14:47:09 +01:00
Nik
a301a4bfeb themes: Added Solarized Dark theme 2023-03-23 17:20:05 +01:00
Nik
531be04739 themes/vs_dark: Fixed window title alignment 2023-03-23 14:38:39 +01:00
Nik
87e05bec48 git: Fixed uefi pattern link in readme 2023-03-23 11:59:38 +01:00
Morten Linderud
a31d290005 patterns/uefi: Added UEFI pattern (#8)
Added UEFI structs

Signed-off-by: Morten Linderud <morten@linderud.pw>
Co-authored-by: Nik <werwolv98@gmail.com>
2023-03-23 11:52:50 +01:00
Andrei Makeev
f3de35a320 patterns/elf: Make hex view less ambiguous (#92)
* ELF: make section/segment data arrays sealed

* ELF: set display names for section/segment data

* Added new functions to library

* Updated ELF pattern

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2023-03-23 11:51:01 +01:00
Oded Shapira
d9de2f7058 patterns/lua54: Added new Lua 5.4 bytecode pattern (#80)
* Lua 5.4 pattern

* Fixed formatting, added file to readme

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2023-03-23 09:06:24 +01:00
Jozef Izso
790f837e4f patterns/dsstore: Added .DS_Store pattern (#90)
* Initial format for Buddy Allocator structures in `.DS_Store` files

* Add list of entries for files in `.DS_Store`

* Add root block, offsets, toc and free lists structures

* Add parsing of block data

* Document `.DS_Store` pattern and add test file
2023-03-23 08:59:59 +01:00
Josh
d8a291977a encodings: Added Pokemon gen 3 character encoding (#96)
* added Pokemon Emerald character encoding

* update readme.md for generic gen 3 table

* Update and rename pokeEmerald_en.tbl to pokegen3_en.tbl
2023-03-23 08:58:44 +01:00
Nicolás Alvarez
62a83b53aa patterns/pbz: Modernize code, renamed pattern to pbz (#98)
* Update pbz pattern

- Rename pbzx to pbz; turns out the 'x' is the compression type.
- Use type::Magic for the "pbz" magic number.
- Decode compression type as an enum.
- Mention compression_tool in the header comment.

* Rename pbzx.hexpat to pbz.hexpat
2023-03-23 08:57:33 +01:00
Takumi Sueda
53ea45ffa6 patterns/PCAP: Fixed formatting and added endianess support (#99)
* patterns/pcap: reformat

* patterns/pcap: endianness-aware parse / parse packets until EOF
2023-03-23 08:56:20 +01:00
WerWolv
c0a1bbd218 includes/std: Fixed stray " in bit library 2023-03-19 16:30:54 +01:00
WerWolv
27f4e20638 git: Fixed documentation dispatch 2023-03-19 16:26:21 +01:00
WerWolv
bbb2107d5f git: Always execute dispatch 2023-03-19 16:21:46 +01:00
WerWolv
8601a6665e includes/std: Added first set of documentation to the std library 2023-03-19 16:17:04 +01:00
WerWolv
c6f2b57384 git: Fixed workflow name 2023-03-19 11:23:43 +01:00
WerWolv
dd190f7c8a git: Added documentation dispatch workflow 2023-03-19 11:22:55 +01:00
Nik
55e3fec3bc includes/std: Added std::math::accumulate, corrected std::hash::crc32 2023-03-14 14:40:58 +01:00
WerWolv
8e78f371f5 encodings/utf8: Corrected UTF-8 encoding file 2023-03-14 09:36:59 +01:00
Ahmet Bilal Can
2758ec8d36 patterns/dex: Added more information to display (#95)
Added string representations for:
- string ids
- field ids
- method ids
- class ids
- proto ids
2023-03-13 11:43:43 +01:00
WerWolv
82ca79c166 patterns/usb: Fixed duplicate variable declaration 2023-03-13 11:35:09 +01:00
WerWolv
146273b1b3 tests: Fixed compilation with latest libpl 2023-03-13 11:19:20 +01:00
Andrei Makeev
ab4bff9f42 patterns/elf: Treat SHT_SYMTAB as symbol tables (#91)
ELF files: support static symbol tables
2023-03-10 11:03:36 +01:00
cryptax
000f0eb730 patterns/dex: Adding Dalvik Executable pattern (#94)
* adding DEX file format

* adding map list
2023-03-10 11:03:07 +01:00
qux-bbb
2d45d5d086 patterns/pe: Removed unnecessary offset (#87)
Remove unnecessary offsets
2023-02-22 21:05:13 +01:00
Nik
2d4b4add82 includes/std: Added Bytes type 2023-02-22 18:31:52 +01:00
Nik
e635c3a5bf patterns/stl: Added 3D model visualization 2023-02-20 11:35:15 +01:00
Chris
15234a284d includes/type: Add signed LEB128 type support (#86) 2023-02-17 20:35:27 +01:00
Nik
0673673b99 themes/vs_dark: Added new Visual Studio Dark theme 2023-02-16 18:11:05 +01:00
Justus Garbe
3786f7e265 patterns/gif: Improved gif format using more explicit formating styles (#84)
* Improved gif format using more explicit formating styles

* Set mime type

* Move content type formatting to struct value
2023-02-15 09:40:09 +01:00
Kuruyia
ea4dda001a includes/type: Fix the IPv6 type (#83)
includes/type: fix the IPv6 type
2023-02-13 08:49:29 +01:00
Nik
324b0894d3 git: Fixed typos 2023-02-10 11:47:36 +01:00
Nik
e89e85e10c nodes: Added Caecar and XOR cipher nodes 2023-02-10 11:25:56 +01:00
Nik
b93e957e46 patterns/jpeg: Removed hex::visualize attribute until it's supported by ImHex 2023-02-09 11:49:43 +01:00
Camas
e7eba44ae0 git: Fix broken ID3 link in README.md (#81)
Fix broken ID3 link
2023-02-06 07:12:30 +01:00
Lenni0451
41d801a114 patterns/nbt: Added missing int array and long array tag (#79) 2023-02-03 21:55:52 +01:00
Nik
25f73ca721 patterns/afe2: Fixed missing include 2023-01-30 16:37:55 +01:00
Nik
facbe59163 patterns/jpeg: Added JPEG pattern 2023-01-29 00:15:56 +01:00
Nik
55023ce4ea patterns/tga: Make pattern compatible with new version 2023-01-22 12:24:14 +01:00
Hank Donnay
32158edb3a patterns/tar: Support PAX archives (#77)
There are two common magic values for archives: the [GNU one](https://git.savannah.gnu.org/cgit/tar.git/tree/src/tar.h#n160) (8 bytes) and the [ustar one](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_06) (6 bytes).

This change has the pattern support both.
2023-01-17 22:51:11 +01:00
WerWolv
862d4d1c28 includes/std: Added missing std::file::seek function 2023-01-16 14:23:29 +01:00
Pascal
d4045b76c3 patterns/pif: Add PIF image pattern (#76)
* Added PIF pattern

* tests/patterns: Added test file for pif pattern

* Added pif pattern to list

* Delete pif.hexpat.pif

* patterns: Added pif image format pattern
2023-01-16 12:07:11 +01:00
Martin Gerhardy
8ab2ff4ab1 patterns: Added a few voxel model patterns (#74)
* patterns: added a few voxel model patterns

* patterns: updated qbcl

according to https://gist.github.com/tostc/7f049207a2e5a7ccb714499702b5e2fd

* readme: added new voxel format petterns to the readme

* tests: added vxl test file

* ccvxl: updated two fields
2023-01-13 20:19:06 +01:00
Nik
5ea7141cb7 patterns: Added Xbox executable (XBEH) pattern 2023-01-12 11:35:47 +01:00
Berylskid
9b13113682 encodings: Update shiftjis.tbl and create ms932.tbl (#73)
* Duplicate current shiftjis.tbl as ms932.tbl

* Correct some wrong characters in shiftjis.tbl

* Remove bunch of non-shift-jis characters from shiftjis.tbl

* Add a missing character (819F=◆)
2023-01-12 11:33:34 +01:00
Max1Truc
0748fa135e patterns/qoi: Fixed bitfields order being wrong (#72) 2023-01-10 09:15:08 +01:00
Max1Truc
a4a14309be patterns/qoi: Added QOI pattern (#71)
For more information on QOI: https://qoiformat.org/
2023-01-09 07:29:33 +01:00
Nik
7c179b3b41 git: Added note for application/octet-stream MIME type to PR template 2023-01-08 16:19:38 +01:00
Daniel Stinson-Diess
c204696209 patterns/dmg: Added DMG pattern (#70) 2023-01-08 16:11:57 +01:00
Nik
f53be98204 patterns/chm: Added Windows HtmlHelp file pattern 2023-01-03 12:11:56 +01:00
Nik
ee95990225 patterns/macho: Added Mach-O pattern 2023-01-02 13:15:51 +01:00
Nik
ac28d9d029 patterns/coff: Added COFF pattern 2023-01-01 23:51:12 +01:00
123456abcdef
372a0e5bba tests/patterns: Added various pattern test files (#69)
Co-authored-by: Nik <werwolv98@gmail.com>
2022-12-31 22:45:46 +01:00
WerWolv
544cadbcca build: Fixed rest of unit tests 2022-12-31 22:38:40 +01:00
WerWolv
1471b02abd build: Fixed building unit tests 2022-12-31 10:13:29 +01:00
123456abcdef
73cde21254 patterns/zstd: Added ZSTD pattern (#68) 2022-12-30 22:05:21 +01:00
Minei3oat
f730d8b0cc patterns/gif: Added GIF pattern (#67)
patterns/gif: Added GIF pattern
2022-12-28 10:47:11 +01:00
123456abcdef
13183769f8 includes/std: Fix namespacing for std::limits::s*_max() (#66)
fix namespacing for std::limit::s*_max()
2022-12-27 11:04:47 +01:00
Nik
5eda5a15bf patterns: Added XCI and WAD pattern 2022-12-27 10:35:07 +01:00
Nik
8e6248aa2d patterns: Added PCX, GZip and PFS0 pattern 2022-12-27 00:56:24 +01:00
Nik
75fd40442b includes/type: Added BCD type 2022-12-24 15:10:23 +01:00
Nik
5a3036149c patterns/nbt: Added NBT pattern 2022-12-21 19:57:04 +01:00
Nik
b160e99b63 patterns/sit5: Added StuffItV5 archive pattern 2022-12-21 11:27:58 +01:00
Nik
f32db1745f tests/patterns: Added various pattern test files 2022-12-21 07:28:20 +01:00
Nik
7842c974df git: Fixed wrong pattern entry in readme table 2022-12-20 21:41:40 +01:00
Nik
e2c191b7c9 includes/std: Added std::mem::AlignTo type 2022-12-20 21:34:51 +01:00
Nik
71ee41fe2c patterns/fdt: Added flat device tree blob pattern 2022-12-20 17:14:23 +01:00
Nik
69feadfc09 patterns/cpio: Added new CPIO pattern 2022-12-20 16:08:10 +01:00
Nik
e79d512b2b includes/type: Fixed base types 2022-12-20 15:29:00 +01:00
gmestanley
e876270a08 encodings/shiftjis: Make control characters easier to read (#65)
* Update pe.hexpat

Implementing a number of things and fixing others

* Update pe.hexpat

Adding the readonlyData pattern

* Update pe.hexpat

Testing putting the number of tabs on Github to 4 instead of 8 (so that comments on the code for the Sections don't break)

* Update pe.hexpat

Reverting change that turned out to be needless

* Update pe.hexpat

Actually sending the `products[while($ != richHeaderEndPosition)]` to `products[while($ < richHeaderEndPosition)]` change

* Add files via upload

Adding NE test file

* Add files via upload

Adding NE pattern file

* Update ne.hexpat

Fixing the error with the entry table assignment

* Update README.md

Added the NE pattern file to the list of patterns

* Update shiftjis.tbl

Deleted the very first character and changed the other first ones' values
2022-12-19 16:21:06 +01:00
Nicolás Alvarez
8f39ecd879 patterns: Added pattern file for Apple PBZX compressed streams (#63)
This is used by Apple for Xcode .xip files (cpio in pbzx in xar), OTA
updates of iOS, and other files.
2022-12-18 00:36:41 +01:00
João Oliveira
ba36826e2d patterns: Added Tar Pattern (#64)
* patterns: add tar support

* readme: add tar entry

* patterns: update tar file

Co-authored-by: favaioos <120850826+favaioos@users.noreply.github.com>
2022-12-18 00:36:16 +01:00
Nik
ac0b77540d tests: Fixed more tests 2022-12-17 22:35:03 +01:00
Nik
683e78d9c3 tests: Fixed building of unit tests 2022-12-17 22:28:52 +01:00
Nik
110b498d7b includes/type: Added magic number assertion type 2022-11-29 14:43:27 +01:00
gmestanley
9887da7af5 patterns/ne: Adding pattern file for NE executables (#58)
* Update pe.hexpat

Implementing a number of things and fixing others

* Update pe.hexpat

Adding the readonlyData pattern

* Update pe.hexpat

Testing putting the number of tabs on Github to 4 instead of 8 (so that comments on the code for the Sections don't break)

* Update pe.hexpat

Reverting change that turned out to be needless

* Update pe.hexpat

Actually sending the `products[while($ != richHeaderEndPosition)]` to `products[while($ < richHeaderEndPosition)]` change

* Add files via upload

Adding NE test file

* Add files via upload

Adding NE pattern file

* Update ne.hexpat

Fixing the error with the entry table assignment

* Update README.md

Added the NE pattern file to the list of patterns
2022-11-19 19:25:02 +01:00
Nicolás Alvarez
01a1bd0d9f patterns/zip: Change how the end of central directory record is found (#60)
Previously, the zip pattern was searching for the end-of-central-directory
header signature (50 4B 05 06) by searching the entire file for it. This is
*very* slow for large files, and risks false positives since those bytes
could randomly appear in compressed data. I had this happen on the first
large (>2GB) zip file I tried.

I'm now checking for the EOCD signature at exactly 22 bytes from the end of
the file (in the common case there is no zip comment), and if that fails
I search for it in the last 64KB of the file (in case there *is* a comment
at the end of the EOCD, which can't be larger than 64KB). This is much
faster, and fixes loading my zip file where it was spuriously finding the
signature in the wrong place.

This still has a low risk of false positives (what if the comment has the
50 4B 05 06 bytes? what if there is a short comment but the signature
appears in the last 64KB of compressed data?), but I don't know what's the
"right" way to find the EOCD, or how proper zip-reading tools handle the
ambiguity...
2022-11-19 18:05:26 +01:00
finict
fbb6a84323 patterns: Fixed PNG pattern #61 (#62)
Closes #61
2022-11-19 18:04:51 +01:00
Nik
4cdf3c11cf includes/std: Fixed copy_section_to_section copy-paste error 2022-11-19 18:02:04 +01:00
Nicolás Alvarez
a9ada89bd0 patterns: Minor cleanup to zip pattern (#59)
* Use spaces instead of tabs in zip.hexpat

* patterns: minor cleanup to ZIP pattern

- Remove empty and unused CentralDirectoryEntry struct.
- Shorten the comment of CentralDirectoryFileHeader.fileOffset. It was so
  long that the tooltip overflowed my screen, and didn't really add much
  information.
- Small whitespace changes.
2022-11-14 22:46:28 +01:00
Merlyn Morgan-Graham
de0e089165 includes/std+type: Add DOS datetime types (#57)
Add type::dosdate16_t and type::dostime16_t in pattern library
2022-11-14 10:08:00 +01:00
Fredrick Brennan
e7ea6fd77f patterns: Added APNG support to PNG pattern (#53) 2022-11-10 10:36:46 +01:00
Fredrick Brennan
ff3c796de8 patterns: Added sRGB, zTXt, tEXt support to PNG pattern (#55)
* patterns: png.hexpat: APNG support

* patterns: png.hexpat: +sRGB, zTXt, tEXt
2022-11-10 10:23:42 +01:00
lieyanqzu
0c83764f24 patterns: Fix java class pattern and update to javase17 format (#56)
fix java class pattern and update to javase17 format
2022-11-10 10:23:06 +01:00
Fredrick Brennan
d87f95dbfa includes/type: Add RGB8 to color.pat (#54) 2022-11-10 10:22:17 +01:00
Nik
51dad63779 includes/std: Removed invalid returns 2022-11-09 21:56:06 +01:00
Nik
764b86acc9 includes/std: Added section functions 2022-11-09 21:53:31 +01:00
Nik
10fdf94899 includes/std: Fixed syntax error 2022-11-09 21:25:01 +01:00
Nik
9ba998e618 includes/std: Added new functions 2022-11-09 21:21:59 +01:00
WerWolv
aceeb2b7b3 git: Don't build plcli tool in tests 2022-11-06 18:40:39 +01:00
fr0ntlin3
3b1b7cc379 patterns: Fixed ELF pattern for 32-bit files (#51)
Co-authored-by: z <z>
2022-11-06 18:36:37 +01:00
gmestanley
49be43e0e1 patterns: Making pe.hexpat even better (#52)
* Update pe.hexpat

Implementing a number of things and fixing others

* Update pe.hexpat

Adding the readonlyData pattern

* Update pe.hexpat

Testing putting the number of tabs on Github to 4 instead of 8 (so that comments on the code for the Sections don't break)

* Update pe.hexpat

Reverting change that turned out to be needless

* Update pe.hexpat

Actually sending the `products[while($ != richHeaderEndPosition)]` to `products[while($ < richHeaderEndPosition)]` change
2022-10-30 12:07:54 +01:00
Nik
8e70a5524d includes/type: Added templates for number types with specific base 2022-10-10 22:36:46 +02:00
Nik
9c0bf1433c includes/std: Added new Array and SizedString type 2022-10-10 22:36:09 +02:00
Nik
43afbfa120 includes/type: Made size and float16 types more generic 2022-10-09 17:38:05 +02:00
Nik
f75703fd2b includes/std: Added MagicSearch and Reinterpreter helper type 2022-10-09 17:37:37 +02:00
Nik
16eebea2fb patterns: Added USB Descriptor pattern 2022-10-09 12:46:29 +02:00
Florian Limberger
6cb208d975 patterns: Added pattern for ID3 tags (#48)
* Add naive first implementation of ID3 patterns

* Refine string handling a bit

* Optimize structs using the static keyword

* Add MIME type pragma and update README
2022-10-09 12:26:34 +02:00
Nik
665c50b914 patterns: Fixed minidump pattern formatting 2022-10-08 11:20:46 +02:00
150 changed files with 163288 additions and 1116525 deletions

View File

@@ -6,5 +6,6 @@
- [ ] A pattern for this format doesn't exist yet (or this PR improves the existing one)
- [ ] The new pattern has been added to the relevant table in the Readme
- [ ] The pattern was associated with all relevant MIME types (using `#pragma MIME mime-type` in the source code)
- Make sure to never use `application/octet-stream` here as that means "Unidentifiable binary data"
- [ ] A test file for this pattern has been added to [/tests/patterns/test_data](/tests/patterns/test_data)
- Try to keep this file below ~ 1 MB

47
.github/workflows/dispatch.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: "Dispatch"
on:
push:
branches: [ '*' ]
pull_request:
branches: [ '*' ]
repository_dispatch:
types: [run_tests]
workflow_dispatch:
inputs:
generate_docs:
description: "Regenerate docs"
required: false
type: boolean
jobs:
tests:
name: 🎯 Dispatch changes
runs-on: ubuntu-22.04
env:
DISPATCH_TOKEN: ${{ secrets.DISPATCH_TOKEN }}
permissions:
actions: read
contents: read
security-events: write
steps:
- name: 🧰 Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: 📄 Check changed include files
id: changed-includes
uses: tj-actions/changed-files@v35
with:
files: includes/**/*.pat
- name: ✉️ Run Documentation generator
if: ${{ env.DISPATCH_TOKEN != '' && (steps.changed-includes.outputs.any_changed == 'true' || inputs.generate_docs || github.event_name == 'repository_dispatch' ) }}
uses: mvasigh/dispatch-action@main
with:
token: ${{ secrets.DISPATCH_TOKEN }}
repo: Documentation
owner: WerWolv
event_type: update_pl_docs

View File

@@ -50,6 +50,7 @@ jobs:
-DCMAKE_C_FLAGS="-fuse-ld=lld --coverage" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld --coverage" \
-DLIBPL_ENABLE_TESTS=OFF \
-DLIBPL_ENABLE_CLI=OFF \
..
make -j4

1
.gitignore vendored
View File

@@ -2,3 +2,4 @@
tests/cmake-build-debug/
.idea/
.DS_Store

12
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,12 @@
# Contributing
Contributing to the Database is very simple. Fork this repository, add your new files (or changes to existing files) to the right folders and create a PR.
When adding new files, please make sure to also add a link to them to the Table of Contents in the README.md file. That way the files can be discovered by others more easily.
Thanks a lot for any additions or improvements :)
## Adding new Patterns
When adding new patterns, if possible, please also add a test file named `<pattern_name>.hexpat.<extension>` to the `/tests/patterns/test_data` directory. This allows our Unit Tests to be run against your code so we can make sure it stays up-to-date and doesn't break when changes are made to the PatternLanguage.
Please try to keep these files as small as possible (~100kiB at most) so cloning stays fast.
Please also make sure to not submit any test files that are under copyright such as game files, ROMs or files extracted from other programs. We don't want a DMCA takedown on this repo.

131
README.md
View File

@@ -1,6 +1,20 @@
# ImHex-Patterns
# ImHex Database
Hex patterns, include patterns and magic files for the use with the ImHex Hex Editor
This repository serves as a database for files to use with the [ImHex Hex Editor](https://github.com/WerWolv/ImHex). It currently contains
- [Patterns](/patterns) - Binary Format definitions for the Pattern Language
- [Pattern Libraries](/includes) - Libraries that make using the Pattern Language easier
- [Magic Files](/magic) - Custom magic file definitions for the use with libmagic
- [Encodings](/encodings) - Custom encodings in the .tbl format
- [Data Processor Nodes](/nodes) - Custom nodes made for ImHex's Data Processor
- [Themes](/themes) - Custom themes for ImHex
- [Constants](/constants) - Constants definition files
- [Scripts](/scripts) - Various scripts to generate code or automate some tasks
- [Yara](/yara) - Custom Yara rules
## Submissions
Most files in this repository have been submitted by the community. Please feel free to open a PR on your own and add files to it!
Everything will immediately show up in ImHex's Content Store and gets bundled with the next release of ImHex.
## Table of Contents
@@ -8,43 +22,78 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed
| Name | MIME | Path | Description |
|------|------|------|-------------|
| 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 |
| 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 |
| 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 |
| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files |
| 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 |
| 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 |
| 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 flashback tapes 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 | `application/octet-stream` | [`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 |
| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob |
| 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 |
| 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) |
| 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 |
| 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 |
| 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 |
| 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` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
| 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 |
| 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 |
| 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 |
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
| UEFI | | [`patterns/uefi.hexpat`](patterns/uefi.hexpat)` | UEFI structs for parsing efivars |
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
| 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 |
| 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 |
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
### Scripts
@@ -114,6 +163,7 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed
| JIS 0213 | [`encodings/jis_x_0213.tbl`](encodings/jis_x_0213.tbl) | JIS X 0213 encoding in UTF-8 |
| Macintosh | [`encodings/macintosh.tbl`](encodings/macintosh.tbl) | Macintosh character encoding used by the Kermit protocol |
| Pokémon (English, Generation 1) | [`encodings/pokegen1_en.tbl`](encodings/pokegen1_en.tbl) | Character encoding used by the English generation 1 Pokémon games |
| Pokémon (English, Generation 3) | [`encodings/pokegen3_en.tbl`](encodings/pokegen3_en.tbl) | Character encoding used by the English generation 3 Pokémon games |
| Shift-JIS UTF-8 | [`encodings/shiftjis.tbl`](encodings/shiftjis.tbl) | Shift-JIS encoding in UTF-8 |
| Thai | [`encodings/thai.tbl`](encodings/thai.tbl) | Thai character encoding |
| Turkish ISO | [`encodings/turkish_iso.tbl`](encodings/turkish_iso.tbl) | Turkish ISO encoding |
@@ -121,9 +171,14 @@ Hex patterns, include patterns and magic files for the use with the ImHex Hex Ed
| UTF-8 | [`encodings/utf8.tbl`](encodings/utf8.tbl) | UTF-8 encoding |
| Vietnamese | [`encodings/vietnamese.tbl`](encodings/vietnamese.tbl) | Vietnamese character encoding |
## Contributing
### Data Processor Nodes
| Name | Path | Description |
|------|------|-------------|
| Caesar Cipher | [`nodes/caesar.hexnode`](nodes/caesar.hexnode) | Simple adjustable per-byte Caecar Cipher (ROT) |
| XOR Cipher | [`nodes/xor.hexnode`](nodes/xor.hexnode) | XORs a input with a repeating XOR pad |
If you want to contribute a file to the database, please make a PR which adds it to the right folder and adds a new entry to the table in this readme.
To take advantage of the automatic pattern testing, please consider adding a test file named `<pattern_name>.hexpat.<extension>` to the `/tests/patterns/test_data` directory. Try to keep this file as small as possible so the repository doesn't become excessively large
Thanks a lot :)
### Themes
| Name | Path | Description |
|------|------|-------------|
| 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 |

7120
encodings/ms932.tbl Normal file

File diff suppressed because it is too large Load Diff

256
encodings/pokegen3_en.tbl Normal file
View File

@@ -0,0 +1,256 @@
00
01=À
02=Á
03=Â
04=Ç
05=È
06=È
07=Ê
08=Ë
09=Ì
0a
0b=Î
0c=Ï
0d=Ò
0e=Ó
0f=Ô
10=Œ
11=Ù
12=Ú
13=Û
14=Ñ
15=ß
16=à
17=á
18
19=ç
1a=è
1b=é
1c=ê
1d=ë
1e=ì
1f
20=î
21=ï
22=ò
23=ó
24=ô
25=œ
26=ù
27=ú
28=û
29=ñ
2a=º
2b=ª
2c=ᵉʳ
2d=&
2e=+
2f
30
31
32
33
34
35==
36
37
38
39
3a
3b
3c
3d
3e
3f
40
41
42
43
44
45
46
47
48
49
4a
4b
4c
4d
4e
4f
50
51=¿
52=¡
53=Pk
54=Mn
55=Po
56=Ké
57
58
59
5a=Í
5b=%
5c=(
5d=)
5e
5f
60
61
62
63
64
65
66
67
68=â
69
6a
6b
6c
6d
6e
6f=í
70
71
72
73
74
75
76
77
78
79=⬆
7a=⬇
7b=⬅
7c=➡
7d
7e
7f
80
81
82
83
84
85
86
87
88
89
8a
8b
8c
8d
8e
8f
90
91
92
93
94
95
96
97
98
99
9a
9b
9c
9d
9e
9f
a0
a1=0
a2=1
a3=2
a4=3
a5=4
a6=5
a7=6
a8=7
a9=8
aa=9
ab=!
ac=?
ad=.
ae=-
af=・
b0
b1=“
b2=”
b3=
b4=
b5=♂
b6=♀
b7
b8=,
b9=×
ba=/
bb=A
bc=B
bd=C
be=D
bf=E
c0=F
c1=G
c2=H
c3=I
c4=J
c5=K
c6=L
c7=M
c8=N
c9=O
ca=P
cb=Q
cc=R
cd=S
ce=T
cf=U
d0=V
d1=W
d2=X
d3=Y
d4=Z
d5=a
d6=b
d7=c
d8=d
d9=e
da=f
db=g
dc=h
dd=i
de=j
df=k
e0=l
e1=m
e2=n
e3=o
e4=p
e5=q
e6=r
e7=s
e8=t
e9=u
ea=v
eb=w
ec=x
ed=y
ee=z
ef=▶
f0=:
f1=Ä
f2=Ö
f3=Ü
f4=ä
f5=ö
f6=ü
f7
f8
f9
fa
fb
fc
fd
fe
ff

View File

@@ -1,10 +1,3 @@
00=
08=\b
09=\t
0A=\n
0B=\v
0C=\f
0D=\r
20=
21=!
22="
@@ -128,12 +121,12 @@
8159=〆
815A=
815B=ー
815C=
815C=
815D=
815E=
815F=
8160=
8161=
8160=
8161=
8162=
8163=…
8164=‥
@@ -160,7 +153,7 @@
8179=【
817A=】
817B=
817C=
817C=
817D=±
817E=×
8180=÷
@@ -180,8 +173,8 @@
818E=℃
818F=¥
8190=
8191=
8192=
8191=¢
8192=£
8193=
8194=
8195=
@@ -194,6 +187,7 @@
819C=●
819D=◎
819E=◇
819F=◆
81A0=□
81A1=■
81A2=△
@@ -217,7 +211,7 @@
81BF=∩
81C8=∧
81C9=
81CA=
81CA=¬
81CB=⇒
81CC=⇔
81CD=∀
@@ -623,89 +617,6 @@
84BC=┥
84BD=┸
84BE=╂
8740=①
8741=②
8742=③
8743=④
8744=⑤
8745=⑥
8746=⑦
8747=⑧
8748=⑨
8749=⑩
874A=⑪
874B=⑫
874C=⑬
874D=⑭
874E=⑮
874F=⑯
8750=⑰
8751=⑱
8752=⑲
8753=⑳
8754=
8755=Ⅱ
8756=Ⅲ
8757=Ⅳ
8758=
8759=Ⅵ
875A=Ⅶ
875B=Ⅷ
875C=Ⅸ
875D=
875F=㍉
8760=㌔
8761=㌢
8762=㍍
8763=㌘
8764=㌧
8765=㌃
8766=㌶
8767=㍑
8768=㍗
8769=㌍
876A=㌦
876B=㌣
876C=㌫
876D=㍊
876E=㌻
876F=㎜
8770=㎝
8771=㎞
8772=㎎
8773=㎏
8774=㏄
8775=㎡
877E=㍻
8780=〝
8781=〟
8782=№
8783=㏍
8784=℡
8785=㊤
8786=㊥
8787=㊦
8788=㊧
8789=㊨
878A=㈱
878B=㈲
878C=㈹
878D=㍾
878E=㍽
878F=㍼
8790=≒
8791=≡
8792=∫
8793=∮
8794=∑
8795=√
8796=⊥
8797=∠
8798=∟
8799=⊿
879A=∵
879B=∩
879C=
889F=亜
88A0=唖
88A1=娃
@@ -7124,4 +7035,3 @@ EAA1=遙
EAA2=瑤
EAA3=凜
EAA4=熙
FA5B=∵

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,24 @@
#include <hex/impl/imhex_check.pat>
/*!
Core intrinsic functions to interact with the ImHex Hex Editor
*/
namespace hex::core {
/**
A type representing a selection in the hex editor
*/
struct Selection {
bool valid;
u64 address, size;
};
/**
Returns the current selection in the hex editor
@return The current selection
*/
fn get_selection() {
u128 result = builtin::hex::core::get_selection();

View File

@@ -2,8 +2,17 @@
#include <hex/impl/imhex_check.pat>
/*!
Library to allow decoding of more complex values
*/
namespace hex::dec {
/**
Demangles a mangled name into a human readable name
@param mangled_name The mangled name
@return The demangled name
*/
fn demangle(str mangled_name) {
return builtin::hex::dec::demangle(mangled_name);
};

View File

@@ -2,8 +2,17 @@
#include <hex/impl/imhex_check.pat>
/*!
Library to do HTTP requests
*/
namespace hex::http {
/**
Performs a HTTP GET request to the given URL and returns the response body
@param url URL to perform the request to
@return Response body
*/
fn get(str url) {
return builtin::hex::http::get(url);
};

43
includes/hex/provider.pat Normal file
View File

@@ -0,0 +1,43 @@
#pragma once
#include <hex/impl/imhex_check.pat>
/*!
Library to interact with the currently loaded provider.
*/
namespace hex::prv {
/**
Queries information from the currently loaded provider. The kind of information that's available depends on the provider that's loaded
> **Available information**
> - File Provider
> - `file_path() -> str`
> - `file_name() -> str`
> - `file_extension() -> str`
> - `creation_time() -> time_t`
> - `access_time() -> time_t`
> - `modification_time() -> time_t`
> - `permissions() -> u16`
> - Disk Provider
> - `file_path() -> str`
> - `sector_size() -> u128`
> - GDB Provider
> - `ip() -> str`
> - `port() -> u16`
> - Process Memory Provider
> - `region_address(regionName) -> u64`
> - `region_size(regionName) -> u64`
> - `process_id() -> u32`
> - `process_name() -> str`
@param category Information category
@param argument Extra argument to pass along
*/
fn get_information(str category, str argument = "") {
return builtin::hex::prv::get_information(category, argument);
};
}

View File

@@ -6,8 +6,15 @@
#include <hex/impl/imhex_check.pat>
#include <hex/dec.pat>
/*!
Types to automatically decode mangled names
*/
namespace hex::type {
/**
A mangled name string that gets demangled when displayed
*/
struct MangledName {
char value[];
} [[sealed, format("hex::type::impl::format_mangled_name")]];

19
includes/std/array.pat Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
/*!
The array library contains various helper functions and types to make
it easier to work with Arrays.
*/
namespace std {
/**
Simple one dimensional array wrapper
@tparam T The array types
@tparam Size Size of the array
*/
struct Array<T, auto Size> {
T data[Size] [[inline]];
};
}

View File

@@ -2,8 +2,17 @@
#include <std/limits.pat>
/*!
This library contains various helper functions for common bit operations.
*/
namespace std::bit {
/**
Calculates the number of 1 bits in a given number
@param x The number
@return The number of bits set to 1 in `x`
*/
fn popcount(u128 x) {
x = (x & (std::limits::u128_max() / 3)) + ((x >> 1) & (std::limits::u128_max() / 3));
x = (x & (std::limits::u128_max() / 5)) + ((x >> 2) & (std::limits::u128_max() / 5));
@@ -12,10 +21,20 @@ namespace std::bit {
return x % 0xFF;
};
/**
Checks if only a single bit is set to 1 in a given number
@param x The number
@return True if there's a single bit set to 1 in `x`, false otherwise
*/
fn has_single_bit(u128 x) {
return x != 0 && (x & (x - 1)) == 0;
};
/**
Rounds the given number up to the next bigger power of two
@param x The number
@return Next bigger power of two that can fit `x`
*/
fn bit_ceil(u128 x) {
if (x == 0) return 0;
@@ -25,7 +44,12 @@ namespace std::bit {
return 1 << i;
};
/**
Rounds the given number down to the next bigger power of two
@param x The number
@return Next smaller power of two
*/
fn bit_floor(u128 x) {
if (x == 0) return 0;

View File

@@ -2,56 +2,148 @@
#include <std/mem.pat>
/*!
The core library contains intrinsics and "compiler magic" functions that
get extra help from the runtime to fulfill their purpose.
*/
namespace std::core {
/**
The layout order of each field after byte-endianness has been handled.
`LeftToRight` and `RightToLeft` are deprecated in favor of the clearer `MostToLeastSignificant` and `LeastToMostSignificant` names.
*/
enum BitfieldOrder : u8 {
/**
@warning deprecated
*/
LeftToRight = 0,
RightToLeft = 1
/**
@warning deprecated
*/
RightToLeft = 1,
MostToLeastSignificant = 0,
LeastToMostSignificant = 1
};
/**
Checks if a pattern has a specific attribute assigned to it
@param pattern The pattern to check
@param attribute The attribute's name to check for
*/
fn has_attribute(ref auto pattern, str attribute) {
return builtin::std::core::has_attribute(pattern, attribute);
};
/**
Returns the first parameter of the attribute of a pattern if it has one
@param pattern The pattern to check
@param attribute The attribute's name to query
*/
fn get_attribute_value(ref auto pattern, str attribute) {
return builtin::std::core::get_attribute_value(pattern, attribute);
};
/**
Sets the current default endianess.
Any patterns created following this attribute will be created using the set endianess.
@param endian The new default endianess
*/
fn set_endian(std::mem::Endian endian) {
builtin::std::core::set_endian(u32(endian));
};
/**
Gets the current default endianess.
@return The currently set default endianess
*/
fn get_endian() {
return builtin::std::core::get_endian();
};
/**
@warning Removed in 1.28.0
*/
fn set_bitfield_order(BitfieldOrder order) {
builtin::std::core::set_bitfield_order(order);
builtin::std::error("Runtime default bitfield order is no longer supported.\nConsider using `be` or `le` on your bitfield variables,\nor attach attribute `bitfield_order` to the bitfield.");
};
/**
@warning Removed in 1.28.0
*/
fn get_bitfield_order() {
return builtin::std::core::get_bitfield_order();
builtin::std::error("Runtime default bitfield order is no longer supported.\nConsider using `be` or `le` on your bitfield variables,\nor attach attribute `bitfield_order` to the bitfield.");
};
/**
When used inside of a pattern that's being created using a pattern,
returns the current array index that's being processed.
If used outside of an array, always yields 0.
@return The current array index
*/
fn array_index() {
return builtin::std::core::array_index();
};
/**
Queries the number of members of a struct, union or bitfield or the number of entries in an array
@param pattern The pattern to check
@return The number of members in `pattern`
*/
fn member_count(ref auto pattern) {
return builtin::std::core::member_count(pattern);
};
/**
Checks whether or not a given pattern has a member with a given name
@param pattern The pattern to check
@param name The name of the member to look for
@return True if a member called `name` exists, false otherwise
*/
fn has_member(ref auto pattern, str name) {
return builtin::std::core::has_member(pattern, name);
};
/**
Formats a pattern using it's default formatter or its custom formatter function set through
the `[[format]]` or `[[format_read]]` attribute
@param pattern The pattern to format
@return Formatted string representation of `pattern`
*/
fn formatted_value(ref auto pattern) {
return builtin::std::core::formatted_value(pattern);
};
/**
Checks if the given enum value corresponds has a corresponding constant
@param pattern The enum value to check
@return True if pattern has a valid enum representation, false if not
*/
fn is_valid_enum(ref auto pattern) {
return builtin::std::core::is_valid_enum(pattern);
};
/**
Changes the color of the given pattern to a new color
@param pattern The pattern to modify
@param color The RGBA8 color
*/
fn set_pattern_color(ref auto pattern, u32 color) {
builtin::std::core::set_pattern_color(pattern, color);
};
/**
Changes the display name of a given pattern
@param pattern The pattern to modify
@param name The new display name of the pattern
*/
fn set_display_name(ref auto pattern, str name) {
builtin::std::core::set_display_name(pattern, name);
};
}

View File

@@ -1,51 +1,116 @@
#pragma once
/*!
The ctype library has functions to check if a character is part of a specific category
of ASCII characters.
*/
namespace std::ctype {
/**
Checks if the given character `c` is a digit between '0' and '9'
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isdigit(char c) {
return c >= '0' && c <= '9';
};
/**
Checks if the given character `c` is a hexadecimal digit between '0' and '9', `A` and `F` or `a` and `f`
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isxdigit(char c) {
return std::ctype::isdigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
};
/**
Checks if the given character `c` is a upper case letter between 'A' and 'Z'
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isupper(char c) {
return c >= 'A' && c <= 'Z';
};
/**
Checks if the given character `c` is a lower case letter between 'a' and 'z'
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn islower(char c) {
return c >= 'a' && c <= 'z';
};
/**
Checks if the given character `c` is either a upper or lower case letter between 'A' and 'Z' or 'a' and 'z'
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isalpha(char c) {
return std::ctype::isupper(c) || std::ctype::islower(c);
};
/**
Checks if the given character `c` is a upper or lower case letter or a number
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isalnum(char c) {
return std::ctype::isalpha(c) || std::ctype::isdigit(c);
};
/**
Checks if the given character `c` is a space character
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isspace(char c) {
return (c >= 0x09 && c <= 0x0D) || c == 0x20;
};
/**
Checks if the given character `c` is a invisible character
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isblank(char c) {
return c == 0x09 || c == ' ';
};
/**
Checks if the given character `c` has a printable glyph
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isprint(char c) {
return c >= '0' && c <= '~';
};
/**
Checks if the given character `c` is a control code
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn iscntrl(char c) {
return !std::ctype::isprint(c);
};
/**
Checks if the given character `c` has a visible glyph
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn isgraph(char c) {
return std::ctype::isprint(c) && !std::ctype::isspace(c);
};
/**
Checks if the given character `c` is a punctuation character
@param c The character to check
@return True if `c` is part of this range, false otherwise
*/
fn ispunct(char c) {
return std::ctype::isgraph(c) && !std::ctype::isalnum(c);
};

View File

@@ -1,9 +1,25 @@
#pragma once
/*!
The File library allows reading and writing from/to external files using
a C-like File IO API.
**These functions are considered dangerous and require the user to manually permit them**
*/
namespace std::file {
/**
A handle representing a file that has been opened
*/
using Handle = s32;
/**
The mode to open a file in.
Read opens the file in read-only mode
Write opens the file in read and write mode
Create creates a new file if it doesn't exist and overwrites an existing file
*/
enum Mode : u8 {
Read = 1,
Write = 2,
@@ -11,37 +27,84 @@ namespace std::file {
};
/**
Opens a file
@param path The path to the file to open
@param mode File open mode
@return Handle to the newly opened file
*/
fn open(str path, Mode mode) {
return builtin::std::file::open(path, u32(mode));
};
/**
Closes a file handle that has been opened previously
@param handle The handle to close
*/
fn close(Handle handle) {
builtin::std::file::close(handle);
};
/**
Reads the content of a file into a string
@param handle The file handle to read from
@param size Number of bytes to read
@return String containing the read data
*/
fn read(Handle handle, u64 size) {
return builtin::std::file::read(handle, size);
};
fn write(Handle handle, str data) {
return builtin::std::file::write(handle, data);
/**
Writes the content of a string into a file
@param handle The file handle to write to
@param data String or Pattern to write to the file
*/
fn write(Handle handle, auto data) {
builtin::std::file::write(handle, data);
};
/**
Sets the current cursor position in the given file handle
@param handle The file handle to set the cursor position in
@param offset The offset to move the cursor to
*/
fn seek(Handle handle, u64 offset) {
builtin::std::file::seek(handle, offset);
};
/**
Queries the size of a file
@param handle The handle of the file to get the size of
@return The file's size
*/
fn size(Handle handle) {
return builtin::std::file::size(handle);
};
/**
Resizes a file
@param handle The handle of the file to resize
*/
fn resize(Handle handle, u64 size) {
builtin::std::file::resize(handle, size);
};
/**
Flushes changes made to a file to disk
@param handle The handle of the file to flush
*/
fn flush(Handle handle) {
builtin::std::file::remove(handle);
};
/**
Deletes a file from disk. This will also automatically close this file
@param handle The handle of the file to delete
*/
fn remove(Handle handle) {
builtin::std::file::remove(handle);
};

View File

@@ -1,33 +1,87 @@
#pragma once
/*!
Library for doing arithmetic with fixed point numbers and converting them from/to floating point numbers.
*/
namespace std::fxpt {
/**
A fixed point value
*/
using fixed = s128;
/**
Converts a fixed point value into a floating point value
@param fxt The fixed point value to convert
@param precision The bits of precision the new value should have
@return The floating point representation of fxt
*/
fn to_float(fixed fxt, u32 precision) {
return double(fxt) / double((1 << precision));
};
/**
Converts a floating point value into a fixed point value
@param flt The floating point value to convert
@param precision The bits of precision the new value should have
@return The fixed point representation of flt
*/
fn to_fixed(double flt, u32 precision) {
return fixed((flt * (1 << precision)));
};
/**
Changes the number of bits used to represent the decimal part of the given fixed point number
@param value The fixed point value to convert
@param start_precision The current number of bits used
@param end_precision The new number of bits used
@return `value` as a new fixed point number with `end_precision` bits of precision
*/
fn change_precision(fixed value, u32 start_precision, u32 end_precision) {
return std::fxpt::to_fixed(std::fxpt::to_float(value, start_precision), end_precision);
};
/**
Adds two fixed point numbers with a given precision together
@param a First fixed point number
@param b Second fixed point number
@param precision The precision of `a` and `b`
@return Result of the addition of `a` and `b`
*/
fn add(fixed a, fixed b, u32 precision) {
return a + b;
};
/**
Subtracts two fixed point numbers with a given precision together
@param a First fixed point number
@param b Second fixed point number
@param precision The precision of `a` and `b`
@return Result of the subtraction of `a` and `b`
*/
fn subtract(fixed a, fixed b, u32 precision) {
return a - b;
};
/**
Multiplies two fixed point numbers with a given precision together
@param a First fixed point number
@param b Second fixed point number
@param precision The precision of `a` and `b`
@return Result of the multiplication of `a` and `b`
*/
fn multiply(fixed a, fixed b, u32 precision) {
return (a * b) / (1 << precision);
};
/**
Divides two fixed point numbers with a given precision together
@param a First fixed point number
@param b Second fixed point number
@param precision The precision of `a` and `b`
@return Result of the division of `a` and `b`
*/
fn divide(fixed a, fixed b, u32 precision) {
return (a << precision) / b;
};

View File

@@ -1,29 +1,23 @@
#pragma once
/*!
The hash library contains various data hash functions
*/
namespace std::hash {
fn crc32(u128 address, u64 size, u32 init, u32 poly) {
u8 byte;
u32 crc, mask;
crc = init;
u64 i;
while (i < size) {
byte = std::mem::read_unsigned(address + i, 1);
crc = crc ^ byte;
u8 j;
while (j < 8) {
mask = u32(-(crc & 1));
crc = (crc >> 1) ^ (poly & mask);
j = j + 1;
}
i = i + 1;
}
return u32(~crc);
/**
Calculates the CRC32 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the crc32 hash of
@param init The CRC32 init value
@param poly The CRC32 polynomial
@param xorout The CRC32 XOR-Out value
@param reflect_in Whether or not the input bytes should be reflected
@param reflect_out Whether or not the output should be reflected
@return Calculated CRC32 hash
*/
fn crc32(ref auto pattern, u32 init, u32 poly, u32 xorout, bool reflect_in, bool reflect_out) {
return builtin::std::hash::crc32(pattern, init, poly, xorout, reflect_in, reflect_out);
};
}

View File

@@ -1,20 +1,45 @@
#pragma once
/*!
The IO library allows formatting strings and outputting text to the console
*/
namespace std {
/**
Formats the given arguments using the format string and prints the result to the console
This function uses the C++20 `std::format` or libfmt's `fmt::format` syntax.
@param fmt Format string
@param args Values to use in the formatting
*/
fn print(str fmt, auto ... args) {
builtin::std::print(fmt, args);
};
/**
Formats the given arguments using the format string and returns the result as a string
This function uses the C++20 `std::format` or libfmt's `fmt::format` syntax.
@param fmt Format string
@param args Values to use in the formatting
@return The formatted string
*/
fn format(str fmt, auto ... args) {
return builtin::std::format(fmt, args);
};
/**
Aborts evaluation of the code immediately and prints a error message to the console
@param message The message to print
*/
fn error(str message) {
builtin::std::error(message);
};
/**
Prints a warning message to the console
@param message The message to print
*/
fn warning(str message) {
builtin::std::warning(message);
};

View File

@@ -1,85 +1,169 @@
#pragma once
/*!
Library to calculate the minimum and maximum values that fit into a given data type
*/
namespace std::limits {
/**
Returns the minimum value that can be stored in a `u8`.
@return Minimum value
*/
fn u8_min() {
return u8(0);
};
/**
Returns the maximum value that can be stored in a `u8`.
@return Maximum value
*/
fn u8_max() {
return u8(-1);
};
/**
Returns the minimum value that can be stored in a `s8`.
@return Minimum value
*/
fn s8_min() {
return -s8((std::limits::u8_max() / 2)) - 1;
};
/**
Returns the maximum value that can be stored in a `s8`.
@return Maximum value
*/
fn s8_max() {
return s8((u8_max() / 2));
return s8((std::limits::u8_max() / 2));
};
/**
Returns the minimum value that can be stored in a `u16`.
@return Minimum value
*/
fn u16_min() {
return u16(0);
};
/**
Returns the maximum value that can be stored in a `u16`.
@return Maximum value
*/
fn u16_max() {
return u16(-1);
};
/**
Returns the minimum value that can be stored in a `s16`.
@return Minimum value
*/
fn s16_min() {
return -s16((std::limits::u16_max() / 2)) - 1;
};
/**
Returns the maximum value that can be stored in a `s16`.
@return Maximum value
*/
fn s16_max() {
return s16((u16_max() / 2));
return s16((std::limits::u16_max() / 2));
};
/**
Returns the minimum value that can be stored in a `u32`.
@return Minimum value
*/
fn u32_min() {
return u32(0);
};
/**
Returns the maximum value that can be stored in a `u32`.
@return Maximum value
*/
fn u32_max() {
return u32(-1);
};
/**
Returns the minimum value that can be stored in a `s32`.
@return Minimum value
*/
fn s32_min() {
return -s32((std::limits::u32_max() / 2)) - 1;
};
/**
Returns the maximum value that can be stored in a `s32`.
@return Maximum value
*/
fn s32_max() {
return s32((u32_max() / 2));
return s32((std::limits::u32_max() / 2));
};
/**
Returns the minimum value that can be stored in a `u64`.
@return Minimum value
*/
fn u64_min() {
return u64(0);
};
/**
Returns the maximum value that can be stored in a `u64`.
@return Maximum value
*/
fn u64_max() {
return u64(-1);
};
/**
Returns the minimum value that can be stored in a `s64`.
@return Minimum value
*/
fn s64_min() {
return -s64((std::limits::u64_max() / 2)) - 1;
};
/**
Returns the maximum value that can be stored in a `s64`.
@return Maximum value
*/
fn s64_max() {
return s64((u64_max() / 2));
return s64((std::limits::u64_max() / 2));
};
/**
Returns the minimum value that can be stored in a `u128`.
@return Minimum value
*/
fn u128_min() {
return u128(0);
};
/**
Returns the maximum value that can be stored in a `u128`.
@return Maximum value
*/
fn u128_max() {
return u128(-1);
};
/**
Returns the minimum value that can be stored in a `s128`.
@return Minimum value
*/
fn s128_min() {
return -s128((std::limits::u128_max() / 2)) - 1;
};
/**
Returns the maximum value that can be stored in a `s128`.
@return Maximum value
*/
fn s128_max() {
return s128((u128_max() / 2));
return s128((std::limits::u128_max() / 2));
};
}
}

View File

@@ -1,7 +1,19 @@
#pragma once
#include <std/mem.pat>
/*!
Library containing more advanced mathematical operations.
*/
namespace std::math {
/**
Compares the values `a` and `b` with each other and returns the smaller of the two
@param a First value
@param b Second value
@return `a` if `a` is smaller than `b`, otherwise `b`
*/
fn min(auto a, auto b) {
if (a < b)
return a;
@@ -9,6 +21,12 @@ namespace std::math {
return b;
};
/**
Compares the values `a` and `b` with each other and returns the bigger of the two
@param a First value
@param b Second value
@return `a` if `a` is bigger than `b`, otherwise `b`
*/
fn max(auto a, auto b) {
if (a > b)
return a;
@@ -16,6 +34,13 @@ namespace std::math {
return b;
};
/**
Clamps the value of `x` between `min` and `max`.
@param x Value
@param min Minimum value
@param max Maximum value
@return `min` if `x` is smaller than `min`, `max` if `x` is bigger than `max`, `x` otherwise
*/
fn clamp(auto x, auto min, auto max) {
if (x < min)
return min;
@@ -25,6 +50,11 @@ namespace std::math {
return x;
};
/**
Returns the absolute value of `x`.
@param x Value
@return `x` if `x` is positive, `-x` otherwise
*/
fn abs(auto x) {
if (x < 0)
return -x;
@@ -32,6 +62,11 @@ namespace std::math {
return x;
};
/**
Returns the sign of `x`.
@param x Value
@return `1` if `x` is positive, `-1` if `x` is negative, `0` if `x` is zero
*/
fn sign(auto x) {
if (x > 0)
return 1;
@@ -41,6 +76,12 @@ namespace std::math {
return 0;
};
/**
Copies the sign of `y` to `x`.
@param x Value
@param y Value
@return `x` if `y` is positive, `-x` if `y` is negative
*/
fn copy_sign(auto x, auto y) {
if (y >= 0)
return std::math::abs(x);
@@ -48,6 +89,11 @@ namespace std::math {
return -std::math::abs(x);
};
/**
Calculates the factorial of `x`.
@param x Value
@return Factorial of `x`
*/
fn factorial(u128 x) {
u128 result;
@@ -60,6 +106,12 @@ namespace std::math {
return result;
};
/**
Calculates the binomial coefficient of `n` and `k`.
@param n Value
@param k Value
@return Binomial coefficient of `n` and `k`
*/
fn comb(u128 n, u128 k) {
if (k > n)
return 0;
@@ -67,6 +119,12 @@ namespace std::math {
return std::math::factorial(n) / (std::math::factorial(k) * std::math::factorial(n - k));
};
/**
Calculates the permutation of `n` and `k`.
@param n Value
@param k Value
@return Permutation of `n` and `k`
*/
fn perm(u128 n, u128 k) {
if (k > n)
return 0;
@@ -74,36 +132,208 @@ namespace std::math {
return std::math::factorial(n) / std::math::factorial(n - k);
};
/**
Floors the value of `value`.
@param value Value
@return `value` floored
*/
fn floor(auto value) { return builtin::std::math::floor(value); };
/**
Ceils the value of `value`.
@param value Value
@return `value` ceiled
*/
fn ceil(auto value) { return builtin::std::math::ceil(value); };
/**
Rounds the value of `value`.
@param value Value
@return `value` rounded
*/
fn round(auto value) { return builtin::std::math::round(value); };
/**
Truncates the value of `value`.
@param value Value
@return `value` truncated
*/
fn trunc(auto value) { return builtin::std::math::trunc(value); };
/**
Calculates the logarithm of `value` with base 10.
@param value Value
@return Logarithm of `value` with base 10
*/
fn log10(auto value) { return builtin::std::math::log10(value); };
/**
Calculates the logarithm of `value` with base 2.
@param value Value
@return Logarithm of `value` with base 2
*/
fn log2(auto value) { return builtin::std::math::log2(value); };
/**
Calculates the natural logarithm of `value`.
@param value Value
@return Logarithm of `value` with base `e`
*/
fn ln(auto value) { return builtin::std::math::ln(value); };
/**
Calculates the floating point modulus of `value`.
@param value Value
@return Floating point modulus of `value`
*/
fn fmod(auto value) { return builtin::std::math::fmod(value); };
/**
Calculates the value of `base` raised to the power of `exp`.
@param base Base
@param exp Exponent
@return `base` raised to the power of `exp`
*/
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
@return Square root of `value`
*/
fn sqrt(auto value) { return builtin::std::math::sqrt(value); };
/**
Calculates the cubic root of `value`.
@param value Value
@return Cubic root of `value`
*/
fn cbrt(auto value) { return builtin::std::math::cbrt(value); };
/**
Calculates the sine of `value`.
@param value Angle value in radians
@return Sine of `value`
*/
fn sin(auto value) { return builtin::std::math::sin(value); };
/**
Calculates the cosine of `value`.
@param value Angle value in radians
@return Cosine of `value`
*/
fn cos(auto value) { return builtin::std::math::cos(value); };
/**
Calculates the tangent of `value`.
@param value Angle value in radians
@return Tangent of `value`
*/
fn tan(auto value) { return builtin::std::math::tan(value); };
/**
Calculates the arc sine of `value`.
@param value Angle value in radians
@return Arc sine of `value`
*/
fn asin(auto value) { return builtin::std::math::asin(value); };
/**
Calculates the arc cosine of `value`.
@param value Value
@return Arc cosine of `value` in radians
*/
fn acos(auto value) { return builtin::std::math::acos(value); };
/**
Calculates the arc tangent of `value`.
@param value Value
@return Arc tangent of `value` in radians between `-pi/2` and `pi/2`
*/
fn atan(auto value) { return builtin::std::math::atan(value); };
/**
Calculates the arc tangent of `value`.
@param value Value
@return Arc tangent of `value` in radians between `-pi` and `pi`
*/
fn atan2(auto value) { return builtin::std::math::atan2(value); };
/**
Calculates the hyperbolic sine of `value`.
@param value Angle value in radians
@return Hyperbolic sine of `value`
*/
fn sinh(auto value) { return builtin::std::math::sinh(value); };
/**
Calculates the hyperbolic cosine of `value`.
@param value Angle value in radians
@return Hyperbolic cosine of `value`
*/
fn cosh(auto value) { return builtin::std::math::cosh(value); };
/**
Calculates the hyperbolic tangent of `value`.
@param value Angle value in radians
@return Hyperbolic tangent of `value`
*/
fn tanh(auto value) { return builtin::std::math::tanh(value); };
/**
Calculates the arc hyperbolic sine of `value`.
@param value Value
@return Arc hyperbolic sine of `value`
*/
fn asinh(auto value) { return builtin::std::math::asinh(value); };
/**
Calculates the arc hyperbolic cosine of `value`.
@param value Value
@return Arc hyperbolic cosine of `value`
*/
fn acosh(auto value) { return builtin::std::math::acosh(value); };
/**
Calculates the arc hyperbolic tangent of `value`.
@param value Value
@return Arc hyperbolic tangent of `value`
*/
fn atanh(auto value) { return builtin::std::math::atanh(value); };
/**
Options to use with the `std::math::accumulate` function.
*/
enum AccumulateOperation : u8 {
Add = 0,
Multiply = 1,
Modulo = 2,
Min = 3,
Max = 4
};
/**
Calculates the sum of all values in the specified memory range.
@param start Start address
@param end End address
@param valueSize Size of each value in bytes
@param section Section to use
@param operation Operation to use
@param endian Endianness to use
@return Sum of all values in the specified memory range
*/
fn accumulate(u128 start, u128 end, u128 valueSize, std::mem::Section section = 0, AccumulateOperation operation = AccumulateOperation::Add, std::mem::Endian endian = std::mem::Endian::Native) {
return builtin::std::math::accumulate(start, end, valueSize, section, u128(operation), u128(endian));
};
}

View File

@@ -1,17 +1,40 @@
#pragma once
/*!
Library for doing raw memory accesses and other low-level operations.
*/
namespace std::mem {
/**
A Handle for a custom Section
*/
using Section = u128;
/**
The Endianess of a value
*/
enum Endian : u8 {
Native = 0,
Big = 1,
Little = 2
};
/**
Function that returns true if the cursor position is at the end of the memory
This is usually used in while-sized arrays in the form of `u8 array[while(!std::mem::eof())]`
@return True if the cursor is at the end of the memory
*/
fn eof() {
return $ >= std::mem::size();
};
/**
Aligns the given value to the given alignment
@param alignment The alignment to align to
@param value The value to align
@return The aligned value
*/
fn align_to(u128 alignment, u128 value) {
u128 remainder = value % alignment;
@@ -19,32 +42,202 @@ namespace std::mem {
};
/**
Gets the base address of the memory
@return The base address of the memory
*/
fn base_address() {
return builtin::std::mem::base_address();
};
/**
Gets the size of the memory
@return The size of the memory
*/
fn size() {
return builtin::std::mem::size();
};
/**
Finds a sequence of bytes in the memory
@param occurrence_index The index of the occurrence to find
@param bytes The bytes to find
@return The address of the sequence
*/
fn find_sequence(u128 occurrence_index, auto ... bytes) {
return builtin::std::mem::find_sequence_in_range(occurrence_index, builtin::std::mem::base_address(), builtin::std::mem::size(), bytes);
};
/**
Finds a sequence of bytes in a specific region of the memory
@param occurrence_index The index of the occurrence to find
@param offsetFrom The offset from which to start searching
@param offsetTo The offset to which to search
@param bytes The bytes to find
@return The address of the sequence
*/
fn find_sequence_in_range(u128 occurrence_index, u128 offsetFrom, u128 offsetTo, auto ... bytes) {
return builtin::std::mem::find_sequence_in_range(occurrence_index, offsetFrom, offsetTo, bytes);
};
/**
Reads a unsigned value from the memory
@param address The address to read from
@param size The size of the value to read
@param endian The endianess of the value to read
@return The value read
*/
fn read_unsigned(u128 address, u8 size, Endian endian = Endian::Native) {
return builtin::std::mem::read_unsigned(address, size, u32(endian));
};
/**
Reads a signed value from the memory
@param address The address to read from
@param size The size of the value to read
@param endian The endianess of the value to read
@return The value read
*/
fn read_signed(u128 address, u8 size, Endian endian = Endian::Native) {
return builtin::std::mem::read_signed(address, size, u32(endian));
};
/**
Reads a string value from the memory
@param address The address to read from
@param size The size of the value to read
@return The value read
*/
fn read_string(u128 address, u8 size) {
return builtin::std::mem::read_string(address, size);
};
/**
Gets the current bit offset within the current byte that a bitfield will read.
*/
fn current_bit_offset() {
return builtin::std::mem::current_bit_offset();
};
/**
Reads a number of bits from the specified bit offset within the specified byte
@param byteOffset The byte offset within the data
@param bitOffset The bit offset to start the read at within the current byte
@param bitSize The total number of bits to read
@return A u128 containing the value read
*/
fn read_bits(u128 byteOffset, u128 bitOffset, u64 bitSize) {
byteOffset += bitOffset >> 3;
bitOffset = bitOffset & 0x7;
return builtin::std::mem::read_bits(byteOffset, bitOffset, bitSize);
};
/**
Creates a new custom section with the given name
@param name The name of the section
@return The handle to the section
*/
fn create_section(str name) {
return builtin::std::mem::create_section(name);
};
/**
Deletes a custom section
@param section The handle to the section
*/
fn delete_section(Section section) {
builtin::std::mem::delete_section(section);
};
/**
Gets the size of a custom section
@param section The handle to the section
@return The size of the section
*/
fn get_section_size(Section section) {
return builtin::std::mem::get_section_size(section);
};
/**
Copies a range of bytes from one section into another
@param from_section The section to copy from
@param from_address The address to copy from
@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_section_to_section(Section from_section, u64 from_address, Section to_section, u64 to_address, u64 size) {
builtin::std::mem::copy_to_section(from_section, from_address, to_section, to_address, size);
};
/**
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 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);
};
/**
Searches for a sequence of bytes and places the given type at that address
@tparam Magic The magic sequence to search for
@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;
}
};
/**
Reinterprets a value as a different one
@tparam From The type to reinterpret from
@tparam To The type to reinterpret to
*/
union Reinterpreter<From, To> {
From from;
To to;
};
/**
Aligns the cursor to the given alignment
@tparam alignment The alignment to align to
*/
struct AlignTo<auto Alignment> {
padding[Alignment - ((($ - 1) % Alignment) + 1)];
} [[hidden, sealed]];
/**
A type representing a sequence of bytes without any specific meaning
@tparam Size The size of the sequence
*/
struct Bytes<auto Size> {
u8 bytes[Size];
} [[sealed, format("std::mem::impl::format_bytes")]];
namespace impl {
fn format_bytes(auto bytes) {
return "";
};
}
}

View File

@@ -1,17 +1,67 @@
#pragma once
/*!
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
*/
namespace std::ptr {
/**
Use the offset of the current pointer as start address
@param offset The pointer's value
@return The new pointer base
*/
fn relative_to_pointer(u128 offset) {
return $;
};
/**
Use the offset of the pointer's parent as start address
@param offset The pointer's value
@return The new pointer base
*/
fn relative_to_parent(u128 offset) {
return addressof(parent);
};
/**
Use the end of the file as pointer base address and use its value as offset backwards from there
@param offset The pointer's value
@return The new pointer base
*/
fn relative_to_end(u128 offset) {
return std::mem::size() - offset * 2;
};
/**
A nullable pointer, generic over both the pointee type and pointer type.
By nullable, we mean that if the pointer's value is zero (`0x0`), then the
value will appear as padding rather than a pointer to something, but
if the pointer's value is non-zero, that non-zero value will be treated as
a pointer of type `PointerTy` which points to an element of type `PointeeTy`.
Example:
A struct field called `p_myInfo` which is a nullable 64-bit pointer to an
element of type `MyInfoTy` would be written as:
```
struct MyStruct {
std::ptr::NullablePtr<MyInfoTy, u64> p_myInfo;
}
```
*/
struct NullablePtr<PointeeTy, PointerTy> {
// `pointerValue` is `no_unique_address` because we don't want to advance
// the current memory location after reading the value of the pointer itself;
// we want to examine the value at this address to determine what should be
// displayed. It's also `hidden` so the editor only displays either thee
// padding or the populated pointer/pointee field.
PointerTy pointerValue [[no_unique_address, hidden]];
if (pointerValue == 0x0) {
padding[sizeof(PointerTy)];
} else {
PointeeTy *data : PointerTy;
}
};
}

81
includes/std/random.pat Normal file
View File

@@ -0,0 +1,81 @@
#pragma once
#include <std/limits.pat>
/*!
Library to generate random numbers. Supports various different distribution types.
*/
namespace std::random {
/**
Represents the type of distribution to use to generate a random number
*/
enum Distribution : u8 {
Uniform = 0,
Normal = 1,
Exponential = 2,
Gamma = 3,
Weibull = 4,
ExtremeValue = 5,
ChiSquared = 6,
Cauchy = 7,
FisherF = 8,
StudentT = 9,
LogNormal = 10,
Bernoulli = 11,
Binomial = 12,
NegativeBinomial = 13,
Geometric = 14,
Poisson = 15
};
/**
Sets the seed of the random number generator
@param seed Seed to use
*/
fn set_seed(u64 seed) {
builtin::std::random::set_seed(seed);
};
/**
Generates a random number using the given distribution with the given parameters.
The random number generator used internally is C++'s std::mt19937_64 Mersenne Twister implementation.
> **Distributions**
> - `Uniform(min, max) -> i128`
> - `Normal(mean, stddev) -> double`
> - `Exponential(lambda) -> double`
> - `Gamma(alpha, beta) -> double`
> - `Weibull(a, b) -> double`
> - `ExtremeValue(a, b) -> double`
> - `ChiSquared(n) -> double`
> - `Cauchy(a, b) -> double`
> - `FisherF(m, n) -> double`
> - `StudentT(n) -> double`
> - `LogNormal(m, s) -> double`
> - `Bernoulli(p) -> bool`
> - `Binomial(t, p) -> i128`
> - `NegativeBinomial(k, p) -> i128`
> - `Geometric(p) -> i128`
> - `Poisson(mean) -> i128`
@param distribution Distribution to use
@param param1 This parameter depends on the type of distribution used.
@param param2 This parameter depends on the type of distribution used.
*/
fn generate_using(Distribution distribution, auto param1 = 0, auto param2 = 0) {
return builtin::std::random::generate(u32(distribution), param1, param2);
};
/**
Generates a uniformly distributed random number between `min` and `max`
@param min Minimum number
@param max Maximum number
*/
fn generate(u64 min = std::limits::u64_min(), u64 max = std::limits::u64_max()) {
return std::random::generate_using(Distribution::Uniform, min, max);
};
}

View File

@@ -2,54 +2,145 @@
#include <std/io.pat>
/*!
Libray to interact with strings.
*/
namespace std::string {
/**
Base type for sized strings. Represents a string with its size preceeding it.
@tparam SizeType The type of the size field.
@tparam DataType The type of the characters.
*/
struct SizedStringBase<SizeType, DataType> {
SizeType size;
DataType data[size];
} [[sealed, format("std::string::impl::format_sized_string"), transform("std::string::impl::format_sized_string")]];
/**
A ASCII string with a prefixed size.
@tparam SizeType The type of the size field.
*/
using SizedString<SizeType> = SizedStringBase<SizeType, char>;
/**
A UTF-16 string with a prefixed size.
@tparam SizeType The type of the size field.
*/
using SizedString16<SizeType> = SizedStringBase<SizeType, char16>;
namespace impl {
fn format_sized_string(ref auto string) {
return string.data;
};
}
/**
Gets the length of a string.
@param string The string to get the length of.
@return The length of the string.
*/
fn length(str string) {
return builtin::std::string::length(string);
};
/**
Gets the character at a given index.
@param string The string to get the character from.
@param index The index of the character to get.
@return The character at the given index.
*/
fn at(str string, u32 index) {
return builtin::std::string::at(string, index);
};
/**
Gets a substring of a string.
@param string The string to get the substring from.
@param pos The position of the first character of the substring.
@param count The number of characters to get.
@return The substring.
*/
fn substr(str string, u32 pos, u32 count) {
return builtin::std::string::substr(string, pos, count);
};
/**
Converts a string to an integer.
@param string The string to convert.
@param base The base of the number.
@return The integer.
*/
fn parse_int(str string, u8 base) {
return builtin::std::string::parse_int(string, base);
};
/**
Converts a string to a float.
@param string The string to convert.
@return The float.
*/
fn parse_float(str string) {
return builtin::std::string::parse_float(string);
};
/**
Converts any type to a string.
@param x The value to convert.
@return The string.
*/
fn to_string(auto x) {
return std::format("{}", x);
};
/**
Checks if a string starts with a given substring.
@param string The string to check.
@param part The substring to check for.
@return True if the string starts with the substring, false otherwise.
*/
fn starts_with(str string, str part) {
return std::string::substr(string, 0, std::string::length(part)) == part;
};
/**
Checks if a string ends with a given substring.
@param string The string to check.
@param part The substring to check for.
@return True if the string ends with the substring, false otherwise.
*/
fn ends_with(str string, str part) {
return std::string::substr(string, std::string::length(string) - std::string::length(part), std::string::length(part)) == part;
};
fn contains(str a, str b) {
s32 a_len = std::string::length(a);
s32 b_len = std::string::length(b);
/**
Checks if a string contains a given substring.
@param string The string to check.
@param part The substring to check for.
@return True if the string contains the substring, false otherwise.
*/
fn contains(str string, str part) {
s32 string_len = std::string::length(string);
s32 part_len = std::string::length(part);
for (s32 i = 0, i <= (a_len - b_len), i += 1) {
if (std::string::substr(a, i, b_len) == b)
for (s32 i = 0, i <= (string_len - part_len), i += 1) {
if (std::string::substr(string, i, part_len) == part)
return true;
}
return false;
};
/**
Reverses a string.
@param string The string to reverse.
@return The reversed string.
*/
fn reverse(str string) {
str result;
@@ -63,6 +154,11 @@ namespace std::string {
return result;
};
/**
Converts a string to upper case.
@param string The string to convert.
@return The converted string.
*/
fn to_upper(str string) {
str result;
@@ -82,6 +178,11 @@ namespace std::string {
return result;
};
/**
Converts a string to lower case.
@param string The string to convert.
@return The converted string.
*/
fn to_lower(str string) {
str result;
@@ -101,6 +202,13 @@ namespace std::string {
return result;
};
/**
Replaces all occurrences of a substring with another substring.
@param string The string to replace in.
@param pattern The substring to replace.
@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);

View File

@@ -2,14 +2,28 @@
#include <std/io.pat>
/*!
Basic helper functions
*/
namespace std {
/**
Asserts that a given value is true. If it's not, abort evaluation and print the given message to the console
@param conditoon The condition that is required to be true
@param message The message to print in case the assertion doesn't hold
*/
fn assert(bool condition, str message) {
if (!condition) {
std::error(std::format("assertion failed '{0}'", message));
}
};
/**
Asserts that a given value is true. If it's not, print the given message to the console as a warning
@param conditoon The condition that is required to be true
@param message The message to print in case the assertion doesn't hold
*/
fn assert_warn(bool condition, str message) {
if (!condition) {
std::warning(std::format("assertion failed '{0}'", message));
@@ -17,10 +31,20 @@ namespace std {
};
/**
Queries the value of a set environment variable given it's name
@param name The name of the env variable
@return The value of that variable
*/
fn env(str name) {
return builtin::std::env(name);
};
/**
Returns the number of parameters in a parameter pack.
@param pack The pack to check
@return Number of parameters in `pack`
*/
fn sizeof_pack(auto ... pack) {
return builtin::std::sizeof_pack(pack);
};

View File

@@ -2,8 +2,15 @@
#include <std/io.pat>
/*!
Library to handle time and date related operations.
*/
namespace std::time {
/**
A structured representation of a time and date.
*/
struct Time {
u8 sec;
u8 min;
@@ -15,57 +22,170 @@ namespace std::time {
u16 yday;
bool isdst;
} [[sealed]];
/**
A helper type to convert between Time and u128.
*/
union TimeConverter {
Time time;
u128 value;
};
/**
A type to represent a time in seconds since the epoch.
*/
using EpochTime = u128;
/**
A type to represent a time zone.
*/
enum TimeZone : u8 {
Local,
UTC
};
/**
A type to represent a DOS date.
*/
bitfield DOSDate {
day: 5;
month: 4;
year: 7;
} [[sealed]];
/**
A type to represent a DOS time.
*/
bitfield DOSTime {
seconds: 5;
minutes: 6;
hours: 5;
} [[sealed]];
namespace impl {
union DOSDateConverter {
DOSDate date;
u16 value;
};
union DOSTimeConverter {
DOSTime time;
u16 value;
};
}
/**
Returns the current time in seconds since the epoch.
@return The current time in seconds since the epoch.
*/
fn epoch() {
return builtin::std::time::epoch();
};
/**
Converts a time in seconds since the epoch to a local time.
@param epoch_time The time in seconds since the epoch.
@return The local time.
*/
fn to_local(EpochTime epoch_time) {
TimeConverter converter;
converter.value = builtin::std::time::to_local(epoch_time);
return converter.time;
};
/**
Converts a time in seconds since the epoch to a UTC time.
@param epoch_time The time in seconds since the epoch.
@return The UTC time.
*/
fn to_utc(EpochTime epoch_time) {
TimeConverter converter;
converter.value = builtin::std::time::to_utc(epoch_time);
return converter.time;
};
/**
Queries the current time in the specified time zone.
@param time_zone The time zone to query.
@return The current time in the specified time zone.
*/
fn now(TimeZone time_zone = TimeZone::Local) {
TimeConverter converter;
if (time_zone == TimeZone::Local)
converter.value = builtin::std::time::to_local(std::time::epoch());
else if (time_zone == TimeZone::UTC)
converter.value = builtin::std::time::to_utc(std::time::epoch());
else
converter.value = 0x00;
return converter.time;
};
/**
Converts a value to a DOS date.
@param value The value to convert.
@return The DOS date.
*/
fn to_dos_date(u16 value) {
impl::DOSDateConverter converter;
converter.value = value;
return converter.date;
};
/**
Converts a value to a DOS time.
@param value The value to convert.
@return The DOS time.
*/
fn to_dos_time(u16 value) {
impl::DOSTimeConverter converter;
converter.value = value;
return converter.time;
};
/**
Formats a time according to the specified format string.
@param time The time to format.
@param format_string The format string to use.
@return The formatted time.
*/
fn format(Time time, str format_string = "%c") {
TimeConverter converter;
converter.time = time;
return builtin::std::time::format(format_string, converter.value);
};
}
/**
Formats a DOS date according to the specified format string.
@param date The DOS date to format.
@param format_string The format string to use.
@return The formatted DOS date.
*/
fn format_dos_date(DOSDate date, str format_string = "{}/{}/{}") {
return std::format(format_string, date.day, date.month, date.year + 1980);
};
/**
Formats a DOS time according to the specified format string.
@param time The DOS time to format.
@param format_string The format string to use.
@return The formatted DOS time.
*/
fn format_dos_time(DOSTime time, str format_string = "{:02}:{:02}:{:02}") {
return std::format(format_string, time.hours, time.minutes, time.seconds * 2);
};
}

55
includes/type/base.pat Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include <std/io.pat>
#include <std/math.pat>
/*!
Types used to change the base of the displayed integer value.
Used like `type::Hex<u32> hexNumber;`, `type::Oct<u16> octalNumber;`
*/
namespace type {
/**
Integer type representing a Hexadecimal value. Displays its value in hexadecimal format.
@tparam T Integer type to use
*/
using Hex<T> = T [[format("type::impl::format_hex")]];
/**
Integer type representing a Octal value. Displays its value in octal format.
@tparam T Integer type to use
*/
using Oct<T> = T [[format("type::impl::format_oct")]];
/**
Integer type representing a Decimal value. Displays its value in decimal format.
@tparam T Integer type to use
*/
using Dec<T> = T [[format("type::impl::format_dec")]];
/**
Integer type representing a Binary value. Displays its value in binary format.
@tparam T Integer type to use
*/
using Bin<T> = T [[format("type::impl::format_bin")]];
namespace impl {
fn format_number(auto value, str fmt) {
bool negative = value < 0;
if (negative)
return std::format("-" + fmt, std::math::abs(value));
else
return std::format(fmt, value);
};
fn format_hex(auto value) { return type::impl::format_number(value, "0x{:02X}"); };
fn format_oct(auto value) { return type::impl::format_number(value, "0o{:03o}"); };
fn format_dec(auto value) { return type::impl::format_number(value, "{}"); };
fn format_bin(auto value) { return type::impl::format_number(value, "0b{:08b}"); };
}
}

37
includes/type/bcd.pat Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include <std/io.pat>
/*!
Type to decode a BCD (Binary Coded Decimal) number
*/
namespace type {
/**
Decodes a BCD value where one byte represents a single digit
@tparam Digits Number of digits
*/
struct BCD<auto Digits> {
u8 bytes[Digits];
} [[sealed, format_read("type::impl::format_bcd")]];
namespace impl {
fn format_bcd(ref auto bcd) {
str result;
for (u32 i = 0, i < sizeof(bcd.bytes), i += 1) {
u8 byte = bcd.bytes[i];
if (byte >= 10)
return "Invalid";
result += std::format("{}", byte);
}
return result;
};
}
}

View File

@@ -2,8 +2,15 @@
#include <std/io.pat>
/*!
Types to display single bytes using various different representations
*/
namespace type {
/**
Type visualizing the value of each individual bit
*/
bitfield Bits {
bit0 : 1;
bit1 : 1;
@@ -15,11 +22,17 @@ namespace type {
bit7 : 1;
} [[format("type::impl::format_bits"), right_to_left]];
/**
Type visualizing the value of the two nibbles
*/
bitfield Nibbles {
low : 4;
high : 4;
} [[format("type::impl::format_nibbles")]];
/**
Type representing a single Byte. Decodes the byte as it's hexadeicmal value, individual bits and nibbles
*/
union Byte {
u8 value;
Bits bits;

View File

@@ -3,24 +3,60 @@
#include <std/io.pat>
#include <std/core.pat>
/*!
Types representing RGB or RGBA colors. The decoded color will be displayed in their color field
*/
namespace type {
struct RGBA8 {
u8 r, g, b, a;
} [[sealed, format("type::impl::format_color")]];
/**
Type representing a generic RGBA color with a variable number of bits for each color
@tparam R Number of bits used for the red component
@tparam G Number of bits used for the green component
@tparam B Number of bits used for the blue component
@tparam A Number of bits used for the alpha component
*/
bitfield RGBA<auto R, auto G, auto B, auto A> {
r : R;
g : G;
b : B;
if (A > 0) a : A;
} [[sealed, format("type::impl::format_color"), color(std::format("{0:02X}{1:02X}{2:02X}FF", r, g, b))]];
/**
Type representing a generic RGB color with a variable number of bits for each color
@tparam R Number of bits used for the red component
@tparam G Number of bits used for the green component
@tparam B Number of bits used for the blue component
*/
using RGB<auto R, auto G, auto B> = RGBA<R,G,B,0>;
bitfield RGB565 {
r : 5;
g : 6;
b : 5;
} [[sealed, format("type::impl::format_color")]];
/**
Type representing a RGBA color with 8 bits for the red component, 8 bits for green, 8 bits for blue and 8 bits for alpha
*/
using RGBA8 = RGBA<8,8,8,8>;
bitfield RGBA4 {
r : 4;
g : 4;
b : 4;
a : 4;
} [[sealed, format("type::impl::format_color")]];
/**
Type representing a RGB color with 8 bits for the red component, 8 bits for green and 8 bits for blue
*/
using RGB8 = RGB<8,8,8>;
/**
Type representing a RGB color with 5 bits for the red component, 6 bits for green and 5 bits for blue
*/
using RGB565 = RGB<5,6,5>;
/**
Type representing a RGBA color with 4 bits for the red component, 4 bits for green, 4 bits for blue and 4 bits for alpha
*/
using RGB4444 = RGBA<4,4,4,4>;
/**
Type representing a RGBA color with 5 bits for the red component, 5 bits for green, 5 bits for blue and 1 bits for alpha
*/
using RGBA5551 = RGBA<5,5,5,1>;
namespace impl {
@@ -40,5 +76,5 @@ namespace type {
};
}
}
}

View File

@@ -2,9 +2,17 @@
#include <std/io.pat>
#include <std/math.pat>
#include <std/mem.pat>
/*!
Type representing a 16 bit half precision floating point number
*/
namespace type {
/**
Type representing a 16 bit half precision floating point number
*/
using float16 = u16 [[format("type::impl::format_float16")]];
namespace impl {
@@ -41,10 +49,10 @@ namespace type {
result = (sign << 31) | ((exponent + (0x7F - 15)) << 23) | (mantissa << 13);
}
U32ToFloatConverter converter;
converter.intValue = result;
std::mem::Reinterpreter<u32, float> converter;
converter.from = result;
return std::format("{}", converter.floatValue);
return std::format("{}", converter.to);
};
}

View File

@@ -2,8 +2,15 @@
#include <std/io.pat>
/*!
Types to deal with UUIDs (Universally Unique Identifiers) / GUIDs (Globally Unique Identifiers) as described in RFC 4122
*/
namespace type {
/**
Type representing a GUID value
*/
struct GUID {
u32 time_low;
u16 time_mid;
@@ -13,6 +20,11 @@ namespace type {
u8 node[6];
} [[sealed, format("type::impl::format_guid")]];
/**
Alias name for GUID
*/
using UUID = GUID;
namespace impl {
fn format_guid(GUID guid) {

View File

@@ -1,19 +1,30 @@
#pragma once
#include <std/io.pat>
#include <std/string.pat>
/*!
Types used to decode IP addresses
*/
namespace type {
/**
A 4 byte IPv4 Address as described in RFC 791
*/
struct IPv4Address {
u8 bytes[4];
} [[sealed, format("type::impl::format_ipv4_address")]];
/**
A 16 byte IPv6 Address as described in RFC 8200
*/
struct IPv6Address {
u16 words[8];
be u16 words[8];
} [[sealed, format("type::impl::format_ipv6_address")]];
namespace impl {
fn format_ipv4_address(IPv4Address address) {
return std::format("{}.{}.{}.{}",
address.bytes[0],
@@ -24,33 +35,33 @@ namespace type {
fn format_ipv6_address(IPv6Address address) {
str result;
bool hadZeros = false;
s8 startIndex = -1;
for (u8 i = 0, i < 8, i += 1) {
if (address.words[i] == 0x00 && !hadZeros) {
hadZeros = true;
startIndex = i;
while (i < 7) {
if (address.words[i + 1] != 0x00)
break;
i += 1;
}
if (startIndex == 0 || i == 7)
result += ":";
} else {
result += std::format("{:04X}", address.words[i]);
result += std::format("{:X}", address.words[i]);
}
result += ":";
}
return std::string::substr(result, 0, std::string::length(result) - 1);
};
}
}

View File

@@ -3,31 +3,70 @@
#include <std/io.pat>
#include <std/mem.pat>
/*!
Types used to decode Little Endian Base 128 numbers used to store large numbers as space efficiently as possible
*/
namespace type {
struct LEB128 {
/**
Base LEB128 type. Use `uLEB128` and `sLEB128` instead.
*/
struct LEB128Base {
u8 array[while($ == addressof(this) || std::mem::read_unsigned($-1, 1) & 0x80 != 0)] [[hidden]];
} [[sealed, format("type::impl::format_leb128"), transform("type::impl::transform_leb128")]];
} [[sealed]];
/**
A unsigned variant of a LEB128 number
*/
using uLEB128 = LEB128Base [[format("type::impl::format_uleb128"), transform("type::impl::transform_uleb128")]];
/**
A signed variant of a LEB128 number
*/
using sLEB128 = LEB128Base [[format("type::impl::format_sleb128"), transform("type::impl::transform_sleb128")]];
/**
Legacy alias for uLEB128
*/
using LEB128 = uLEB128;
namespace impl {
fn transform_leb128_array(auto array) {
fn transform_uleb128_array(auto array) {
u128 res = array[0] & 0x7f;
for(u8 i = 1, array[i-1] & 0x80 != 0, i+=1) {
res |= u64(array[i] & 0x7f) << 7 * i;
res |= u128(array[i] & 0x7f) << 7 * i;
}
return res;
};
fn transform_sleb128_array(auto array) {
s128 res = type::impl::transform_uleb128_array(array);
if (res & 0x40 != 0) {
res |= ~0 << (sizeof(array) / sizeof(u8)) * 7;
}
return res;
};
fn format_leb128(auto leb128) {
u128 res = type::impl::transform_leb128_array(leb128.array);
fn format_uleb128(auto leb128) {
u128 res = type::impl::transform_uleb128_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_leb128(auto leb128) {
return type::impl::transform_leb128_array(leb128.array);
fn transform_uleb128(auto leb128) {
return type::impl::transform_uleb128_array(leb128.array);
};
fn format_sleb128(auto leb128) {
s128 res = type::impl::transform_sleb128_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_sleb128(auto leb128) {
return type::impl::transform_sleb128_array(leb128.array);
};
}
}

View File

@@ -2,8 +2,15 @@
#include <std/io.pat>
/*!
Types used to decode MAC Addresses
*/
namespace type {
/**
A MAC Address as used in the Internet Protocol
*/
struct MACAddress {
u8 bytes[6];
} [[sealed, format("type::impl::format_mac_address")]];

38
includes/type/magic.pat Normal file
View File

@@ -0,0 +1,38 @@
#include <std/string.pat>
#include <std/sys.pat>
#include <std/io.pat>
#include <std/ctype.pat>
/*!
Types used to parse and enforce specific magic numbers
*/
namespace type {
/**
A Magic number. Throws an error if the magic number does not match the expected value
@tparam ExpectedValue A string representing the expected value
*/
struct Magic<auto ExpectedValue> {
char value[std::string::length(ExpectedValue)];
std::assert(value == ExpectedValue, std::format("Invalid magic value! Expected \"{}\", got \"{}\".", ExpectedValue, value));
} [[sealed, format("type::impl::format_magic")]];
namespace impl {
fn format_magic(ref auto magic) {
str result;
for (u32 i = 0, i < sizeof(magic.value), i += 1) {
char c = magic.value[i];
if (std::ctype::isprint(c))
result += c;
else
result += std::format("\\x{:02X}", u8(c));
}
return std::format("\"{}\"", result);
};
}
}

View File

@@ -1,32 +1,53 @@
#include <std/mem.pat>
/*!
Types dealing with various kinds of resource paths
*/
namespace type {
struct UnixPathSegment {
char string[while(std::mem::read_unsigned($, 1) != '/' && std::mem::read_unsigned($, 1) != 0x00)];
/**
Type representing a single path segment. Use the `Path` type instead of using this on its own
@tparam Delimeter The delimeter sequence used to separate two path segments
*/
struct PathSegment<auto Delimeter> {
char string[while(std::mem::read_string($, std::string::length(Delimeter)) != Delimeter && std::mem::read_unsigned($, 1) != 0x00)];
char separator [[hidden]];
if (separator == 0x00) {
$ -= 1;
break;
}
} [[sealed, format("type::impl::format_unix_path_segment")]];
} [[sealed, format("type::impl::format_path_segment")]];
struct UnixPath {
UnixPathSegment segments[while(true)];
} [[format("type::impl::format_unix_path")]];
/**
A generic type representing a path with an arbitrary delimeter
@tparam Delimeter The delimeter sequence used to separate two path segments
*/
struct Path<auto Delimeter> {
PathSegment<Delimeter> segments[while(true)];
} [[format("type::impl::format_path")]];
/**
A type representing a Unix path using a '/' forwardslash as delimeter
*/
using UnixPath = Path<"/">;
/**
A type representing a DOS path using a '\' backslash as delimeter
*/
using DOSPath = Path<"\\">;
namespace impl {
fn format_unix_path_segment(UnixPathSegment segment) {
fn format_path_segment(ref auto segment) {
return segment.string;
};
fn format_unix_path(UnixPath path) {
fn format_path(ref auto path) {
return std::mem::read_string($, sizeof(path));
};
}
}
}

View File

@@ -1,13 +1,37 @@
#pragma once
#include <std/io.pat>
/*!
Types used to pretty print size values
*/
namespace type {
using Size8 = u8 [[format("type::impl::size_formatter")]];
using Size16 = u16 [[format("type::impl::size_formatter")]];
using Size32 = u32 [[format("type::impl::size_formatter")]];
using Size64 = u64 [[format("type::impl::size_formatter")]];
using Size128 = u128 [[format("type::impl::size_formatter")]];
/**
A generic size type which displays its value in Bytes (or kiB, MiB, GiB, TiB, PiB, EiB if larger)
@tparam T Underlying type
*/
using Size<T> = T [[format("type::impl::size_formatter")]];
/**
A 8 bit size type
*/
using Size8 = Size<u8>;
/**
A 16 bit size type
*/
using Size16 = Size<u16>;
/**
A 32 bit size type
*/
using Size32 = Size<u32>;
/**
A 64 bit size type
*/
using Size64 = Size<u64>;
/**
A 128 bit size type
*/
using Size128 = Size<u128>;
namespace impl {
@@ -45,4 +69,4 @@ namespace type {
}
}
}

View File

@@ -3,17 +3,51 @@
#include <std/io.pat>
#include <std/time.pat>
/*!
Types used to decode various different time formats
*/
namespace type {
/**
A 32 bit Unix time value
*/
using time32_t = u32 [[format("type::impl::format_time_t")]];
/**
Alias name for `time32_t`
*/
using time_t = time32_t;
/**
A 64 bit Unix time value
*/
using time64_t = u64 [[format("type::impl::format_time_t")]];
/**
A DOS Date value
*/
using DOSDate = u16 [[format("type::impl::format_dosdate")]];
/**
A DOS Time value
*/
using DOSTime = u16 [[format("type::impl::format_dostime")]];
namespace impl {
fn format_time_t(u128 value) {
fn format_time_t(u128 value) {
return std::time::format(std::time::to_utc(value));
};
fn format_dosdate(u16 value) {
return std::time::format_dos_date(std::time::to_dos_date(value));
};
fn format_dostime(u16 value) {
return std::time::format_dos_time(std::time::to_dos_time(value));
};
}
}

View File

@@ -1,5 +1,9 @@
#pragma once
/*!
Alias types to make it easier to move template definitions over from 010 Editor to ImHex
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {

View File

@@ -1,5 +1,9 @@
#pragma once
/*!
Alias definitions for all C stdint and regular data types
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {

View File

@@ -1,5 +1,9 @@
#pragma once
/*!
Various data types used in the Linux Kernel
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {

View File

@@ -1,5 +1,9 @@
#pragma once
/*!
Alias definitions for Rust's data types
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {

View File

@@ -1,5 +1,9 @@
#pragma once
/*!
Alias definitions for various type names used in Windows applications
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {

219
nodes/caesar.hexnode Normal file
View File

@@ -0,0 +1,219 @@
{
"attrs": [
76,
77,
78
],
"data": {
"nodes": {
"links": {
"31": {
"from": 54,
"id": 31,
"to": 55
},
"33": {
"from": 59,
"id": 33,
"to": 56
},
"34": {
"from": 60,
"id": 34,
"to": 57
},
"40": {
"from": 68,
"id": 40,
"to": 53
},
"41": {
"from": 66,
"id": 41,
"to": 69
},
"42": {
"from": 66,
"id": 42,
"to": 63
},
"43": {
"from": 58,
"id": 43,
"to": 71
},
"44": {
"from": 70,
"id": 44,
"to": 72
},
"45": {
"from": 73,
"id": 45,
"to": 64
},
"46": {
"from": 65,
"id": 46,
"to": 75
}
},
"nodes": {
"19": {
"attrs": [
66
],
"data": {
"name": "Input",
"type": 2
},
"id": 19,
"name": "Input",
"pos": {
"x": 48.0,
"y": 151.0
},
"type": "hex.builtin.nodes.custom.input"
},
"20": {
"attrs": [
68
],
"data": {
"name": "Count",
"type": 0
},
"id": 20,
"name": "Count",
"pos": {
"x": 50.0,
"y": 264.0
},
"type": "hex.builtin.nodes.custom.input"
},
"21": {
"attrs": [
53,
54
],
"data": null,
"id": 21,
"name": "hex.builtin.nodes.casting.int_to_buffer.header",
"pos": {
"x": 212.0,
"y": 315.0
},
"type": "hex.builtin.nodes.casting.int_to_buffer"
},
"22": {
"attrs": [
55,
56,
57,
58
],
"data": null,
"id": 22,
"name": "hex.builtin.nodes.buffer.slice.header",
"pos": {
"x": 384.0,
"y": 375.0
},
"type": "hex.builtin.nodes.buffer.slice"
},
"23": {
"attrs": [
59
],
"data": {
"data": 0
},
"id": 23,
"name": "hex.builtin.nodes.constants.int.header",
"pos": {
"x": 122.0,
"y": 423.0
},
"type": "hex.builtin.nodes.constants.int"
},
"24": {
"attrs": [
60
],
"data": {
"data": 1
},
"id": 24,
"name": "hex.builtin.nodes.constants.int.header",
"pos": {
"x": 120.0,
"y": 510.0
},
"type": "hex.builtin.nodes.constants.int"
},
"25": {
"attrs": [
63,
64,
65
],
"data": null,
"id": 25,
"name": "hex.builtin.nodes.bitwise.add.header",
"pos": {
"x": 720.0,
"y": 183.0
},
"type": "hex.builtin.nodes.bitwise.add"
},
"26": {
"attrs": [
69,
70
],
"data": null,
"id": 26,
"name": "hex.builtin.nodes.buffer.size.header",
"pos": {
"x": 383.0,
"y": 274.0
},
"type": "hex.builtin.nodes.buffer.size"
},
"27": {
"attrs": [
71,
72,
73
],
"data": null,
"id": 27,
"name": "hex.builtin.nodes.buffer.repeat.header",
"pos": {
"x": 595.0,
"y": 445.0
},
"type": "hex.builtin.nodes.buffer.repeat"
},
"28": {
"attrs": [
75
],
"data": {
"name": "Output",
"type": 2
},
"id": 28,
"name": "Output",
"pos": {
"x": 864.0,
"y": 330.0
},
"type": "hex.builtin.nodes.custom.output"
}
}
}
},
"name": "Caesar Cipher",
"type": "hex.builtin.nodes.custom.custom"
}

223
nodes/xor.hexnode Normal file
View File

@@ -0,0 +1,223 @@
{
"attrs": [
36,
37,
38
],
"data": {
"nodes": {
"links": {
"11": {
"from": 20,
"id": 11,
"to": 22
},
"13": {
"from": 23,
"id": 13,
"to": 32
},
"14": {
"from": 17,
"id": 14,
"to": 19
},
"15": {
"from": 14,
"id": 15,
"to": 15
},
"16": {
"from": 12,
"id": 16,
"to": 16
},
"17": {
"from": 9,
"id": 17,
"to": 11
},
"18": {
"from": 7,
"id": 18,
"to": 10
},
"19": {
"from": 31,
"id": 19,
"to": 8
},
"20": {
"from": 30,
"id": 20,
"to": 6
},
"22": {
"from": 31,
"id": 22,
"to": 18
},
"23": {
"from": 30,
"id": 23,
"to": 21
}
},
"nodes": {
"10": {
"attrs": [
14
],
"data": {
"data": 1
},
"id": 10,
"name": "hex.builtin.nodes.constants.int.header",
"pos": {
"x": 430.0,
"y": 364.0
},
"type": "hex.builtin.nodes.constants.int"
},
"11": {
"attrs": [
15,
16,
17
],
"data": null,
"id": 11,
"name": "hex.builtin.nodes.arithmetic.add.header",
"pos": {
"x": 579.0,
"y": 421.0
},
"type": "hex.builtin.nodes.arithmetic.add"
},
"12": {
"attrs": [
18,
19,
20
],
"data": null,
"id": 12,
"name": "hex.builtin.nodes.buffer.repeat.header",
"pos": {
"x": 661.0,
"y": 241.0
},
"type": "hex.builtin.nodes.buffer.repeat"
},
"13": {
"attrs": [
21,
22,
23
],
"data": null,
"id": 13,
"name": "hex.builtin.nodes.bitwise.xor.header",
"pos": {
"x": 818.0,
"y": 163.0
},
"type": "hex.builtin.nodes.bitwise.xor"
},
"14": {
"attrs": [
32
],
"data": {
"name": "Output",
"type": 2
},
"id": 14,
"name": "Output",
"pos": {
"x": 1000.0,
"y": 432.0
},
"type": "hex.builtin.nodes.custom.output"
},
"4": {
"attrs": [
30
],
"data": {
"name": "Input",
"type": 2
},
"id": 4,
"name": "Input",
"pos": {
"x": 82.0,
"y": 139.0
},
"type": "hex.builtin.nodes.custom.input"
},
"5": {
"attrs": [
31
],
"data": {
"name": "XOR Pad",
"type": 2
},
"id": 5,
"name": "XOR Pad",
"pos": {
"x": 89.0,
"y": 328.0
},
"type": "hex.builtin.nodes.custom.input"
},
"6": {
"attrs": [
6,
7
],
"data": null,
"id": 6,
"name": "hex.builtin.nodes.buffer.size.header",
"pos": {
"x": 269.0,
"y": 403.0
},
"type": "hex.builtin.nodes.buffer.size"
},
"7": {
"attrs": [
8,
9
],
"data": null,
"id": 7,
"name": "hex.builtin.nodes.buffer.size.header",
"pos": {
"x": 267.0,
"y": 486.0
},
"type": "hex.builtin.nodes.buffer.size"
},
"8": {
"attrs": [
10,
11,
12
],
"data": null,
"id": 8,
"name": "hex.builtin.nodes.arithmetic.div.header",
"pos": {
"x": 409.0,
"y": 465.0
},
"type": "hex.builtin.nodes.arithmetic.div"
}
}
}
},
"name": "XOR Pad",
"type": "hex.builtin.nodes.custom.custom"
}

73
patterns/Crashlvl.hexpat Normal file
View File

@@ -0,0 +1,73 @@
#include <type/magic.pat>
#include <std/string.pat>
#include <std/array.pat>
// Crash Bandicoot - Back in Time (fan game) user created tapes
// author AdventureT
struct Header {
type::Magic<"CRASHLVL"> magic;
u8 version;
std::string::SizedString<u8> levelName;
std::string::SizedString<u8> author;
};
enum Music : u32 {
None,
BonusBGM,
CrashCreatorBGM,
MainMenuBGM,
WarpRoomBGM,
Level01BGM,
Level02BGM,
Level03BGM,
Level04BGM,
Level05BGM,
SewerBGM,
EgyptBGM,
NBrioBGM
};
enum Type : u32 {
Unset,
Flashback,
Trial
};
enum Time : u32 {
Night,
Day,
Storm,
Dawn
};
enum Terrain : u32 {
None,
Machines,
Trees,
Waterfall,
Snow,
Fortress,
};
struct Options {
Type type;
Time time;
Terrain terrain;
Music music;
};
struct Object {
std::string::SizedString<u8> objName;
u32 x;
u32 y;
};
struct Objects{
u32 objCount;
std::Array<Object, objCount> objArray;
};
Header header @ 0x0;
Options options @ $;
Objects objects @ $;

View File

@@ -1,6 +1,7 @@
#pragma endian little
#include <std/io.pat>
#include <std/sys.pat>
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC "AFE2"
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_1 "AFE1"
@@ -54,4 +55,4 @@ std::assert_warn(ctx.magic == ATMOSPHERE_REBOOT_TO_FATAL_MAGIC,
std::print("Error Description: 0x{:04X}", ctx.error_desc);
std::print("Program ID: {:016X}", ctx.program_id);
std::print("Program ID: {:016X}", ctx.program_id);

208
patterns/bsp_goldsrc.hexpat Normal file
View File

@@ -0,0 +1,208 @@
#include <std/ptr.pat>
#include <std/mem.pat>
#include <std/sys.pat>
#pragma endian little
#define HEADER_LUMPS 15
#define MAX_MAP_HULLS 4
#define NUM_AMBIENTS 4
#define MAXLIGHTMAPS 4
enum LumpIndex : u32 {
Entities,
Planes,
Textures,
Vertexes,
Visibility,
Nodes,
Texinfo,
Faces,
Lighting,
Clipnodes,
Leafs,
Marksurfaces,
Edges,
Surfedges,
Models,
};
struct vec3f
{
float x, y, z;
};
struct dlump_t
{
s32 fileofs;
s32 filelen;
};
struct dheader_t
{
s32 version;
dlump_t lumps[HEADER_LUMPS];
std::assert(version == 30, "This version of BSP format is unsupported.");
};
struct dmodel_t
{
vec3f mins;
vec3f maxs;
vec3f origin; // for sounds or lights
s32 headnode[MAX_MAP_HULLS];
s32 visleafs; // not including the solid leaf 0
s32 firstface;
s32 numfaces;
};
struct dplane_t
{
vec3f normal;
float dist;
s32 type;
};
struct dtexinfo_t
{
float vecs[8]; // texmatrix [s/t][xyz offset]
s32 miptex;
s16 flags;
s16 faceinfo; // -1 no face info otherwise dfaceinfo_t
};
struct dleaf_t
{
s32 contents;
s32 visofs; // -1 = no visibility info
s16 mins[3];
s16 maxs[3];
u16 firstmarksurface;
u16 nummarksurfaces;
u8 ambient_level[NUM_AMBIENTS];
};
struct dnode_t
{
s32 planenum;
s16 children[2]; // negative numbers are -(leafs + 1), not nodes
s16 mins[3];
s16 maxs[3];
u16 firstface;
u16 numfaces; // counting both sides
};
struct dface_t
{
u16 planenum;
s16 side;
s32 firstedge;
s16 numedges;
s16 texinfo;
u8 styles[MAXLIGHTMAPS];
s32 lightofs; // start of [numstyles*surfsize] samples
};
struct dedge_t
{
u16 v[2]; // indices of vertexes
};
struct dclipnode_t
{
s32 planenum;
s16 children[2];
};
using dmarkface_t = u16;
using dsurfedge_t = s32;
using dvertex_t = vec3f;
fn get_miptex_pixeldata_size(auto width, auto height, auto offset) {
if (offset != 0) {
return std::mem::align_to(4, width * height * 85 / 64 + sizeof(u16) + 768);
}
else {
return 0;
}
};
struct miptex_t
{
char name[16];
u32 width;
u32 height;
u32 offsets[4]; // four mip maps stored
u8 pixeldata[get_miptex_pixeldata_size(width, height, offsets[0])];
};
dheader_t file_header @ 0x00;
fn get_lump_element_count(auto index, auto elem_size) {
return file_header.lumps[index].filelen / elem_size;
};
fn get_lump_address(auto index) {
return file_header.lumps[index].fileofs;
};
fn get_miptex_ptr_base(auto offset) {
return file_header.lumps[LumpIndex::Textures].fileofs;
};
struct MiptexPointer
{
miptex_t *data: u32 [[pointer_base("get_miptex_ptr_base"), inline]];
};
struct dmiptexlump_t
{
s32 nummiptex;
MiptexPointer dataofs[nummiptex];
};
struct VisibilityData
{
u8 data[file_header.lumps[LumpIndex::Visibility].filelen];
u8 pad[std::mem::align_to(4, sizeof(this)) - sizeof(this)];
};
struct LightmapData
{
u8 data[file_header.lumps[LumpIndex::Lighting].filelen];
u8 pad[std::mem::align_to(4, sizeof(this)) - sizeof(this)];
};
struct EntityData
{
char text[];
u8 pad[std::mem::align_to(4, sizeof(this)) - sizeof(this)];
};
s32 models_count = get_lump_element_count(LumpIndex::Models, sizeof(dmodel_t));
s32 vertexes_count = get_lump_element_count(LumpIndex::Vertexes, sizeof(vec3f));
s32 planes_count = get_lump_element_count(LumpIndex::Planes, sizeof(dplane_t));
s32 leafs_count = get_lump_element_count(LumpIndex::Leafs, sizeof(dleaf_t));
s32 nodes_count = get_lump_element_count(LumpIndex::Nodes, sizeof(dnode_t));
s32 faces_count = get_lump_element_count(LumpIndex::Faces, sizeof(dface_t));
s32 markfaces_count = get_lump_element_count(LumpIndex::Marksurfaces, sizeof(dmarkface_t));
s32 surfedges_count = get_lump_element_count(LumpIndex::Surfedges, sizeof(dsurfedge_t));
s32 edges_count = get_lump_element_count(LumpIndex::Edges, sizeof(dedge_t));
s32 clipnodes_count = get_lump_element_count(LumpIndex::Clipnodes, sizeof(dclipnode_t));
s32 texinfo_count = get_lump_element_count(LumpIndex::Texinfo, sizeof(dtexinfo_t));
dmodel_t models_lump[models_count] @ get_lump_address(LumpIndex::Models);
dvertex_t vertexes_lump[vertexes_count] @ get_lump_address(LumpIndex::Vertexes);
dplane_t planes_lump[planes_count] @ get_lump_address(LumpIndex::Planes);
dleaf_t leafs_lump[leafs_count] @ get_lump_address(LumpIndex::Leafs);
dnode_t nodes_lump[nodes_count] @ get_lump_address(LumpIndex::Nodes);
dface_t faces_lump[faces_count] @ get_lump_address(LumpIndex::Faces);
dmarkface_t markfaces_lump[markfaces_count] @ get_lump_address(LumpIndex::Marksurfaces);
dsurfedge_t surfedges_lump[surfedges_count] @ get_lump_address(LumpIndex::Surfedges);
dedge_t edges_lump[edges_count] @ get_lump_address(LumpIndex::Edges);
dclipnode_t clipnodes_lump[clipnodes_count] @ get_lump_address(LumpIndex::Clipnodes);
dtexinfo_t texinfo_lump[texinfo_count] @ get_lump_address(LumpIndex::Texinfo);
dmiptexlump_t textures_lump @ get_lump_address(LumpIndex::Textures);
VisibilityData visdata_lump @ get_lump_address(LumpIndex::Visibility);
LightmapData lightdata_lump @ get_lump_address(LumpIndex::Lighting);
EntityData entdata_lump @ get_lump_address(LumpIndex::Entities);

30
patterns/cchva.hexpat Normal file
View File

@@ -0,0 +1,30 @@
// Command and conquer voxel animation format
struct vec4_s {
float x [[color("FF0000")]];
float y [[color("00FF00")]];
float z [[color("0000FF")]];
float w [[color("FFFF00")]];
};
struct mat3x4_s {
vec4_s row[3];
};
struct name_s {
char buffer[16] [[color("EECCCC")]];
};
struct hva_s {
name_s name;
u32 numFrames;
u32 numNodes;
name_s nodeNames[numNodes];
};
struct frame_s {
mat3x4_s mat[hva.numNodes];
};
hva_s hva @0x00;
frame_s frames[hva.numFrames] @sizeof(hva);

13
patterns/ccpal.hexpat Normal file
View File

@@ -0,0 +1,13 @@
// Command and conquer palette format
struct Color {
u8 r;
u8 g;
u8 b;
};
struct Palette {
Color colors[256];
};
Palette pal @0x00;

69
patterns/ccvxl.hexpat Normal file
View File

@@ -0,0 +1,69 @@
// Command and Conquer voxel model format
struct vec4_s {
float x [[color("FF0000")]];
float y [[color("00FF00")]];
float z [[color("0000FF")]];
float w [[color("FFFF00")]];
};
struct vec3_s {
float x [[color("FF0000")]];
float y [[color("00FF00")]];
float z [[color("0000FF")]];
};
struct mat3x4_s {
vec4_s row[3];
};
struct name_s {
char buffer[16] [[color("EECCCC")]];
};
struct color_s {
u8 r;
u8 g;
u8 b;
};
struct vxl_limb_header_s {
name_s name;
s32 limb_number;
u32 _reserved1;
u32 _reserved2;
};
struct vxl_limb_tailer_s {
u32 span_start_offset;
u32 span_end_offset;
u32 span_data_offset;
float scale;
mat3x4_s matrix;
vec3_s min_bounds;
vec3_s max_bounds;
u8 xsize;
u8 ysize;
u8 zsize;
u8 normal_type;
};
struct vxl_s {
name_s name;
u32 palette_count;
u32 limb_count;
u32 tailer_count;
u32 body_size;
u8 remap_start_index;
u8 remap_end_index;
color_s internal_palette[256];
vxl_limb_header_s _headers[limb_count];
u8 body[body_size];
vxl_limb_tailer_s _tailers[limb_count];
};
struct frame_s {
mat3x4_s mat[hva.numNodes];
};
vxl_s vxl @0x00;

395
patterns/chm.hexpat Normal file
View File

@@ -0,0 +1,395 @@
#include <type/magic.pat>
#include <type/size.pat>
#include <type/guid.pat>
#include <type/leb128.pat>
#include <std/sys.pat>
enum WindowsLanguageId : u32 {
Arabic_SaudiArabia = 0x401,
Arabic_Iraq = 0x801,
Arabic_Egypt = 0xc01,
Arabic_Libya = 0x1001,
Arabic_Algeria = 0x1401,
Arabic_Morocco = 0x1801,
Arabic_Tunisia = 0x1c01,
Arabic_Oman = 0x2001,
Arabic_Yemen = 0x2401,
Arabic_Syria = 0x2801,
Arabic_Jordan = 0x2c01,
Arabic_Lebanon = 0x3001,
Arabic_Kuwait = 0x3401,
Arabic_UAE = 0x3801,
Arabic_Bahrain = 0x3c01,
Arabic_Qatar = 0x4001,
Bulgarian = 0x402,
Catalan = 0x403,
Valencian = 0x803,
Chinese_Taiwan = 0x404,
Chinese_PRC = 0x804,
Chinese_HongKongSAR = 0xc04,
Chinese_Singapore = 0x1004,
Chinese_MacaoSAR = 0x1404,
Czech = 0x405,
Danish = 0x406,
German_Germany = 0x407,
German_Switzerland = 0x807,
German_Austria = 0xc07,
German_Luxembourg = 0x1007,
German_Liechtenstein = 0x1407,
Greek = 0x408,
English_UnitedStates = 0x409,
English_UnitedKingdom = 0x809,
English_Australia = 0xc09,
English_Canada = 0x1009,
English_NewZealand = 0x1409,
English_Ireland = 0x1809,
English_SouthAfrica = 0x1c09,
English_Jamaica = 0x2009,
English_Caribbean = 0x2409,
English_Belize = 0x2809,
English_TrinidadandTobago = 0x2c09,
English_Zimbabwe = 0x3009,
English_Philippines = 0x3409,
English_Indonesia = 0x3809,
English_HongKongSAR = 0x3c09,
English_India = 0x4009,
English_Malaysia = 0x4409,
English_Singapore = 0x4809,
Spanish_SpainTraditionalSort = 0x40a,
Spanish_Mexico = 0x80a,
Spanish_Spain = 0xc0a,
Spanish_Guatemala = 0x100a,
Spanish_CostaRica = 0x140a,
Spanish_Panama = 0x180a,
Spanish_DominicanRepublic = 0x1c0a,
Spanish_Venezuela = 0x200a,
Spanish_Colombia = 0x240a,
Spanish_Peru = 0x280a,
Spanish_Argentina = 0x2c0a,
Spanish_Ecuador = 0x300a,
Spanish_Chile = 0x340a,
Spanish_Uruguay = 0x380a,
Spanish_Paraguay = 0x3c0a,
Spanish_Bolivia = 0x400a,
Spanish_ElSalvador = 0x440a,
Spanish_Honduras = 0x480a,
Spanish_Nicaragua = 0x4c0a,
Spanish_PuertoRico = 0x500a,
Spanish_UnitedStates = 0x540a,
Spanish_LatinAmerica = 0x580a,
Finnish = 0x40b,
French_France = 0x40c,
French_Belgium = 0x80c,
French_Canada = 0xc0c,
French_Switzerland = 0x100c,
French_Luxembourg = 0x140c,
French_Monaco = 0x180c,
French_Caribbean = 0x1c0c,
French_Reunion = 0x200c,
French_CongoDRC = 0x240c,
French_Senegal = 0x280c,
French_Cameroon = 0x2c0c,
French_CoteDIvoire = 0x300c,
French_Mali = 0x340c,
French_Morocco = 0x380c,
French_Haiti = 0x3c0c,
Hebrew = 0x40d,
Hungarian = 0x40e,
Icelandic = 0x40f,
Italian_Italy = 0x410,
Italian_Switzerland = 0x810,
Japanese = 0x411,
Korean = 0x412,
Dutch_Netherlands = 0x413,
Dutch_Belgium = 0x813,
Norwegian_Bokmal = 0x414,
Norwegian_Nynorsk = 0x814,
Polish = 0x415,
Portuguese_Brazil = 0x416,
Portuguese_Portugal = 0x816,
Romansh = 0x417,
Romanian = 0x418,
Romanian_Moldova = 0x818,
Russian = 0x419,
Russian_Moldova = 0x819,
Croatian_Croatia = 0x41a,
Serbian_LatinSerbiaandMontenegroFormer = 0x81a,
Serbian_CyrillicSerbiaAndMontenegroFormer = 0xc1a,
Croatian_BosniaAndHerzegovina = 0x101a,
Bosnian_Latin = 0x141a,
Serbian_LatinBosniaAndHerzegovina = 0x181a,
Serbian_CyrillicBosniaAndHerzegovina = 0x1c1a,
Bosnian_Cyrillic = 0x201a,
Serbian_LatinSerbia = 0x241a,
Serbian_CyrillicSerbia = 0x281a,
Serbian_LatinMontenegro = 0x2c1a,
Serbian_CyrillicMontenegro = 0x301a,
Slovak = 0x41b,
Albanian = 0x41c,
Swedish_Sweden = 0x41d,
Swedish_Finland = 0x81d,
Thai = 0x41e,
Turkish = 0x41f,
Urdu_Pakistan = 0x420,
Urdu_India = 0x820,
Indonesian = 0x421,
Ukrainian = 0x422,
Belarusian = 0x423,
Slovenian = 0x424,
Estonian = 0x425,
Latvian = 0x426,
Lithuanian = 0x427,
Tajik = 0x428,
Persian = 0x429,
Vietnamese = 0x42a,
Armenian = 0x42b,
Azerbaijani_Latin = 0x42c,
Azerbaijani_Cyrillic = 0x82c,
Basque = 0x42d,
UpperSorbian = 0x42e,
LowerSorbian = 0x82e,
Macedonian = 0x42f,
Sesotho_SouthAfrica = 0x430,
Xitsonga = 0x431,
Setswana_SouthAfrica = 0x432,
Setswana_Botswana = 0x832,
Venda = 0x433,
isiXhosa = 0x434,
isiZulu = 0x435,
Afrikaans = 0x436,
Georgian = 0x437,
Faroese = 0x438,
Hindi = 0x439,
Maltese = 0x43a,
NorthernSami_Norway = 0x43b,
NorthernSami_Sweden = 0x83b,
NorthernSami_Finland = 0xc3b,
LuleSami_Norway = 0x103b,
LuleSami_Sweden = 0x143b,
SouthernSami_Norway = 0x183b,
SouthernSami_Sweden = 0x1c3b,
SkoltSami_Finland = 0x203b,
InariSami_Finland = 0x243b,
Irish = 0x83c,
Yiddish = 0x43d,
Malay_Malaysia = 0x43e,
Malay_BruneiDarussalam = 0x83e,
Kazakh = 0x43f,
Kyrgyz = 0x440,
Kiswahili = 0x441,
Turkmen = 0x442,
Uzbek_Latin = 0x443,
Uzbek_Cyrillic = 0x843,
Tatar = 0x444,
Bangla_India = 0x445,
Bangla_Bangladesh = 0x845,
Punjabi_India = 0x446,
Punjabi_Pakistan = 0x846,
Gujarati = 0x447,
Odia = 0x448,
Tamil_India = 0x449,
Tamil_SriLanka = 0x849,
Telugu = 0x44a,
Kannada = 0x44b,
Malayalam = 0x44c,
Assamese = 0x44d,
Marathi = 0x44e,
Sanskrit = 0x44f,
Mongolian_Cyrillic = 0x450,
Mongolian_TraditionalMongolianPRC = 0x850,
Mongolian_TraditionalMongolianMongolia = 0xc50,
Tibetan_PRC = 0x451,
Welsh = 0x452,
Khmer = 0x453,
Lao = 0x454,
Burmese = 0x455,
Galician = 0x456,
Konkani = 0x457,
Manipuri = 0x458,
Sindhi_Devanagari = 0x459,
Sindhi_Arabic = 0x859,
Syriac = 0x45a,
Sinhala = 0x45b,
Cherokee_Cherokee = 0x45c,
Inuktitut_Syllabics = 0x45d,
Inuktitut_Latin = 0x85d,
Amharic = 0x45e,
Tamazight_ArabicMorocco = 0x45f,
Tamazight_LatinAlgeria = 0x85f,
Tamazight_TifinaghMorocco = 0x105f,
Kashmiri_Arabic = 0x460,
Kashmiri = 0x860,
Nepali = 0x461,
Nepali_India = 0x861,
Frisian = 0x462,
Pashto = 0x463,
Filipino = 0x464,
Divehi = 0x465,
Edo = 0x466,
Fulah_Nigeria = 0x467,
Fulah_LatinSenegal = 0x867,
Hausa = 0x468,
Ibibio_Nigeria = 0x469,
Yoruba = 0x46a,
Quechua_Bolivia = 0x46b,
Quechua_Ecuador = 0x86b,
Quechua_Peru = 0xc6b,
SesothoSaLeboa = 0x46c,
Bashkir = 0x46d,
Luxembourgish = 0x46e,
Greenlandic = 0x46f,
Igbo = 0x470,
Kanuri = 0x471,
Oromo = 0x472,
Tigrinya_Ethiopia = 0x473,
Tigrinya_Eritrea = 0x873,
Guarani = 0x474,
Hawaiian = 0x475,
Latin = 0x476,
Somali = 0x477,
Yi_PRC = 0x478,
Papiamentu = 0x479,
Mapudungun = 0x47a,
Mohawk = 0x47c,
Breton = 0x47e,
Uyghur_PRC = 0x480,
Maori = 0x481,
Occitan = 0x482,
Corsican = 0x483,
Alsatian = 0x484,
Sakha = 0x485,
Kiche = 0x486,
Kinyarwanda = 0x487,
Wolof = 0x488,
Dari = 0x48c,
ScottishGaelic_UnitedKingdom = 0x491,
CentralKurdish_Iraq = 0x492
};
struct DirectoryListingEntry {
type::LEB128 nameLength;
char name[nameLength];
type::LEB128 contentSection;
type::LEB128 offset;
type::LEB128 length;
};
struct DirectoryIndexEntry {
type::LEB128 nameLength;
char name[nameLength];
type::LEB128 directoryListingChunk;
};
struct ListingChunk {
char magic[4];
if (magic == "PMGL") {
type::Size<u32> freeSpaceLength;
u32;
u32 prevChunkNumber, nextChunkNumber;
u16 directoryListingEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryListingEntryCount) - (freeSpaceLength - 2);
DirectoryListingEntry directories[directoryListingEntryCount];
$ = addressof(directoryListingEntryCount) + sizeof(directoryListingEntryCount);
} else if (magic == "PMGI") {
type::Size<u32> freeSpaceLength;
u16 directoryIndexEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryIndexEntryCount) - (freeSpaceLength - 2);
DirectoryIndexEntry indexes[directoryIndexEntryCount];
$ = addressof(directoryIndexEntryCount) + sizeof(directoryIndexEntryCount);
} else {
std::error("Invalid chunk magic!");
}
};
struct HeaderSection {
char magic[4];
if (magic == "\xFE\x01\x00\x00") {
u32;
type::Size<u64> fileSize;
u32;
u32;
} else if (magic == "ITSP") {
u32 version;
type::Size<u32> directoryHeaderLength1;
u32;
u32 directoryChunkSize;
u32 quickRefSectionDensity;
u32 indexTreeDepth;
u32 rootIndexChunkNumber;
u32 firstPMGLChunkNumber;
u32 lastPMGLChunkNumber;
u32;
u32 directoryChunkCount;
WindowsLanguageId languageId;
type::GUID guid;
type::Size<u32> directoryHeaderLength2;
u32;
u32;
u32;
ListingChunk chunk[directoryChunkCount];
} else {
std::error("Invalid header section magic!");
}
};
struct HeaderSectionTableEntry {
u64 offset;
type::Size<u64> size;
HeaderSection headerSection @ offset;
};
struct NameListEntry {
type::Size<u16> nameLength;
char16 name[nameLength];
padding[2];
};
struct NameListFile {
u16 fileLengthWords;
u16 entriesInFile;
NameListEntry nameList[entriesInFile];
padding[0x2E];
};
struct SectionData {
u32 fileLengthWords;
type::Magic<"LZXC"> magic;
u32 version;
u32 lzxResetInterval;
type::Size<u32> windowSize;
type::Size<u32> cacheSize;
u32;
};
struct Content {
NameListFile nameListFile;
SectionData sectionData;
};
struct CHM {
type::Magic<"ITSF"> magic;
u32 version;
type::Size<u32> headerSize;
u32;
be u32 timeStamp;
WindowsLanguageId languageId;
type::GUID guids[2];
HeaderSectionTableEntry headerSectionTable[2];
Content *dataOffset : u64;
};
CHM chm @ 0x00;

209
patterns/coff.hexpat Normal file
View File

@@ -0,0 +1,209 @@
#pragma MIME application/x-coff
#include <type/time.pat>
#include <type/size.pat>
enum Machine : u16 {
Unknown = 0x0000,
AM33 = 0x01D3,
AMD64 = 0x8664,
ARM = 0x01C0,
ARM64 = 0xAA64,
ARMNT = 0x01C4,
EBC = 0x0EBC,
I386 = 0x014C,
IA64 = 0x0200,
LOONGARCH32 = 0x6232,
LOONGARCH64 = 0x6264,
M32R = 0x9041,
MIPS16 = 0x0226,
MIPSFPU = 0x0366,
MIPSFPU16 = 0x0466,
POWERPC = 0x01F0,
POWERPCFP = 0x01F0,
R4000 = 0x0166,
RISCV32 = 0x5032,
RISCV64 = 0x5064,
RISCV128 = 0x5128,
SH3 = 0x01A2,
SH3DSP = 0x01A3,
SH4 = 0x01A6,
SH5 = 0x01A8,
THUMB = 0x01C2,
WCEMIPSV2 = 0x0169
};
bitfield Characteristics {
relocsStripped : 1;
executableImage : 1;
lineNumsStripped : 1;
localSymsStripped : 1;
aggressiveWsTrim : 1;
largeAddressAware : 1;
padding : 1;
bytesReversedLo : 1;
_32BitMachine : 1;
debugStripped : 1;
removableRunFromSwap : 1;
netRunFromSwap : 1;
system : 1;
dll : 1;
upSystemOnly : 1;
bytesReversedHi : 1;
};
enum Type : u16 {
Null = 0,
Void = 1,
Char = 2,
Short = 3,
Int = 4,
Long = 5,
Float = 6,
Double = 7,
Struct = 8,
Union = 9,
Enum = 10,
MOE = 11,
Byte = 12,
Word = 13,
UInt = 14,
DWord = 15
};
enum StorageClass : u8 {
EndOfFunction = 0xFF,
Null = 0,
Automatic = 1,
External = 2,
Static = 3,
Register = 4,
ExternalDef = 5,
Label = 6,
UndefinedLabel = 7,
MemberOfStruct = 8,
Argument = 9,
StructTag = 10,
MemberOfUnion = 11,
UnionTag = 12,
TypeDefinition = 13,
UndefinedStatic = 14,
EnumTag = 15,
MemberOfEnum = 16,
RegisterParam = 17,
BitField = 18,
Block = 100,
Function = 101,
EndOfStruct = 102,
File = 103,
Section = 104,
WeakExternal = 105,
CLRToken = 107
};
struct AuxSymbol {
u8 data[18];
};
u32 countedSymbols = 0;
struct SymbolTable {
char name[8];
u32 value;
u16 sectionNumber;
Type type;
StorageClass storageClass;
u8 numberOfAuxSymbols;
countedSymbols += 1 + numberOfAuxSymbols;
AuxSymbol auxSymbols[numberOfAuxSymbols];
if (countedSymbols >= parent.header.numberOfSymbols)
break;
};
struct String {
char value[];
};
struct StringTable {
u32 size;
String strings[while($ < addressof(size) + size)];
};
bitfield SectionFlags {
padding : 3;
typeNoPad : 1;
padding : 1;
cntCode : 1;
initializedData : 1;
uninitializedData : 1;
lnkOther : 1;
lnkInfo : 1;
padding : 1;
lnkRemove : 1;
lnkCOMDAT : 1;
padding : 2;
gprel : 1;
padding : 1;
memPurgeable : 1;
memLocked : 1;
memPreload : 1;
alignment : 4 [[format("format_alignment")]];
lnkNrelocOvfl : 1;
memDiscardable : 1;
memNotCached : 1;
memNotPaged : 1;
memShared : 1;
memExecute : 1;
memRead : 1;
memWrite : 1;
};
fn format_alignment(u8 alignment) {
return 1 << alignment;
};
struct Relocations {
u32 virtualAddress;
u32 symbolTableIndex;
Type type;
};
struct Section {
char name[8];
type::Size<u32> virtualSize;
u32 virtualAddress;
type::Size<u32> sizeOfRawData;
u32 pointerToRawData;
u32 pointerToRelocations;
u32 pointerToLineNumbers;
u16 numberOfRelocations;
u16 numberOfLineNumbers;
SectionFlags characteristics;
u8 rawData[sizeOfRawData] @ pointerToRawData [[sealed]];
Relocations relocations[numberOfRelocations] @ pointerToRelocations;
};
struct Header {
Machine machine;
u16 numberOfSections;
type::time32_t timeDateStamp;
u32 pointerToSymbolTable;
u32 numberOfSymbols;
u16 sizeOfOptionalHeader;
Characteristics characteristics;
};
struct COFF {
Header header;
Section sectionTable[header.numberOfSections];
SymbolTable symbolTable[header.numberOfSymbols] @ header.pointerToSymbolTable;
StringTable stringTable @ addressof(symbolTable) + sizeof(symbolTable);
};
COFF coff @ 0x00;

66
patterns/cpio.pat Normal file
View File

@@ -0,0 +1,66 @@
#include <type/base.pat>
#include <std/time.pat>
#include <std/core.pat>
#include <std/sys.pat>
#include <std/mem.pat>
#pragma MIME application/x-cpio
namespace old_binary {
using Time = u32 [[format("old_binary::format_time")]];
fn swap_32bit(u32 value) {
return ((value >> 16) & 0xFFFF) | ((value & 0xFFFF) << 16);
};
fn format_time(u32 value) {
return std::time::format(std::time::to_utc(swap_32bit(value)));
};
using SwappedU32 = u32 [[transform("old_binary::swap_32bit"), format("old_binary::swap_32bit")]];
bitfield Mode {
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;

174
patterns/dex.hexpat Normal file
View File

@@ -0,0 +1,174 @@
#include <type/leb128.pat>
struct header_item {
u8 magic[8];
u32 checksum;
u8 signature[20];
u32 file_size;
u32 header_size;
u32 endian_tag;
u32 link_size;
u32 link_off;
u32 map_off;
u32 string_ids_size;
u32 string_ids_off;
u32 type_ids_size;
u32 type_ids_off;
u32 proto_ids_size;
u32 proto_ids_off;
u32 field_ids_size;
u32 field_ids_off;
u32 method_ids_size;
u32 method_ids_off;
u32 class_defs_size;
u32 class_defs_off;
u32 data_size;
u32 data_off;
};
struct map_item {
u16 type;
u16 unused;
u32 size;
u32 offset;
};
struct map_list {
u32 size;
map_item list[size];
};
struct string_data_item {
type::uLEB128 utf16_size[[hidden]];
char string[utf16_size];
}[[inline]];
struct string_id_item {
string_data_item* string_data: u32;
}[[name(string_data.string)]];
struct type_id_item {
u32 descriptor_idx;
char type_name[] @ addressof(parent.string_ids[descriptor_idx].string_data.string);
}[[name(type_name)]];
struct proto_id_item {
u32 shorty_idx;
u32 return_type_idx;
u32 parameters_off;
char shorty_dec[] @ addressof(parent.string_ids[shorty_idx].string_data.string);
char return_type[] @ addressof(parent.type_ids[return_type_idx].type_name);
}[[name(shorty_dec)]];
struct field_id_item {
u16 class_idx;
u16 type_idx;
u32 name_idx;
char class_name[] @ addressof(parent.type_ids[class_idx].type_name);
char type_name[] @ addressof(parent.type_ids[type_idx].type_name);
char field_name[] @ addressof(parent.string_ids[name_idx].string_data.string);
}[[name(field_name)]];
struct method_id_item {
u16 class_idx;
u16 proto_idx;
u32 name_idx;
char class_name[] @ addressof(parent.type_ids[class_idx].type_name);
char proto_desc[] @ addressof(parent.proto_ids[proto_idx].shorty_dec);
char method_name[] @ addressof(parent.string_ids[name_idx].string_data.string);
}[[name(class_name+method_name)]];
struct class_site_id_item {
u32 call_site_off;
};
struct method_handle_item {
u16 method_handle_type;
u16 unused;
u16 field_or_method_id;
u16 unused2;
};
enum access_flag : type::uLEB128{
public = 0x1,
private = 0x2,
protected = 0x4,
static = 0x8,
final = 0x10,
synchronized = 0x20,
volatile = 0x40
};
struct encoded_field {
type::uLEB128 field_idx_diff;
access_flag access_flags;
};
struct encoded_method {
type::uLEB128 method_idx_diff;
type::uLEB128 access_flags;
type::uLEB128 code_off;
};
struct class_data_item {
type::uLEB128 static_fields_size;
type::uLEB128 instance_fields_size;
type::uLEB128 direct_methods_size;
type::uLEB128 virtual_methods_size;
encoded_field static_fields[static_fields_size];
encoded_field instance_fields[instance_fields_size];
encoded_method direct_methods[direct_methods_size];
encoded_method virtual_methods[virtual_methods_size];
};
struct class_def_item {
u32 class_idx;
u32 access_flags;
u32 superclass_idx;
u32 interfaces_off;
u32 source_file_idx;
u32 annotations_off;
u32 class_data_off;
//class_data_item *class_data_off:u32;
u32 static_values_off;
char class_name[] @ addressof(parent.type_ids[class_idx].type_name);
}[[name(class_name)]];
struct type_item {
u16 type_idx;
};
struct type_list {
u32 size;
type_item list[size];
};
struct code_item {
u16 registers_size;
u16 ins_size;
u16 outs_size;
u16 tries_size;
u32 debug_info_off;
u32 insns_size;
u16 insns[insns_size];
};
struct try_item {
u32 start_addr;
u16 insn_count;
u16 handler_off;
};
struct Dex {
header_item header;
string_id_item string_ids[header.string_ids_size] @ header.string_ids_off;
type_id_item type_ids[header.type_ids_size] @ header.type_ids_off;
proto_id_item proto_ids[header.proto_ids_size] @ header.proto_ids_off;
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;
};
Dex dex @ 0x00;

49
patterns/dmg.hexpat Normal file
View File

@@ -0,0 +1,49 @@
#pragma endian big
#include <type/magic.pat>
#include <type/size.pat>
#include <type/guid.pat>
#include <std/mem.pat>
// Parse DMG Structure per http://newosxbook.com/DMG.html
//
// UDIFResourceFile starts at size(file) - 512
struct UDIFResourceFile {
type::Magic<"koly"> Signature; // Magic ('koly')
u32 Version; // Current version is 4
type::Size<u32> HeaderSize; // sizeof(this), always 512
u32 Flags;
u64 RunningDataForkOffset; //
u64 DataForkOffset; // Data fork offset (usually 0, beginning of file)
type::Size<u64> DataForkLength; // Size of data fork (usually up to the XMLOffset, below)
u64 RsrcForkOffset; // Resource fork offset, if any
type::Size<u64> RsrcForkLength; // Resource fork length, if any
u32 SegmentNumber; // Usually 1, may be 0
u32 SegmentCount; // Usually 1, may be 0
type::GUID SegmentID; // 128-bit GUID identifier of segment (if SegmentNumber !=0)
u32 DataChecksumType; // Data fork
type::Size<u32> DataChecksumSize; // Checksum Information
u32 DataChecksum[DataChecksumSize]; // Up to 128-bytes (32 x 4) of checksum
u64 XMLOffset; // Offset of property list in DMG, from beginning
type::Size<u64> XMLLength; // Length of property list
u8 Reserved1[120]; // 120 reserved bytes - zeroed
u32 ChecksumType; // Master
type::Size<u32> ChecksumSize; // Checksum information
u32 Checksum[ChecksumSize]; // Up to 128-bytes (32 x 4) of checksum
u32 ImageVariant; // Commonly 1
u64 SectorCount; // Size of DMG when expanded, in sectors
u32 reserved2; // 0
u32 reserved3; // 0
u32 reserved4; // 0
};
UDIFResourceFile trailer @ std::mem::size() - 512;
char metadata_plist[trailer.XMLLength] @ trailer.XMLOffset;

113
patterns/dsstore.hexpat Normal file
View File

@@ -0,0 +1,113 @@
// Apple macOS .DS_Store format
#pragma endian big
#include <std/io.pat>
struct RecordEntry {
u32 length;
char16 filename[length];
char id[4];
// either blob or length
char type[4];
if (type == "blob") {
u32 blobCount;
u8 blobData[blobCount];
}
else if (type == "long") {
u32 value;
}
else if (type == "shor") {
u32 value;
}
else if (type == "bool") {
u8 value;
}
};
struct TreeBlock {
u32 mode;
u32 count;
RecordEntry entries[count];
};
struct BuddyRootBlockOffsets {
u32 count;
u8 reserved[4];
u32 addresses[count];
padding[(1024 - (count * 4))];
};
struct BuddyTableOfContentEntry {
u8 count;
char name[count];
u32 value;
};
struct BuddyTableOfContents {
u32 count;
BuddyTableOfContentEntry toc[count];
};
struct BuddyFreeList {
u32 count;
u32 offsets[count];
};
struct BuddyRootBlock {
BuddyRootBlockOffsets offsets;
BuddyTableOfContents toc;
BuddyFreeList freelists[32];
};
struct BuddyBlock {
u32 blockCount;
u8 reserved[4];
// padding for next multiple of 256 entries (1024 bytes)
u32 addresses[blockCount];
// u8 padding[paddingCount];
u32 directoryCount;
// directory entries
u8 count;
u8 name[count];
u32 blockNumber;
// free lists
// 32 free lists
BuddyRootBlockOffsets off[32];
};
struct BlocksList {
u32 blockId [[color("E57373")]];
u32 internalBlocks [[color("80CBC4")]];
u32 countRecords [[color("ffeb3b")]];
u32 countBlocks [[color("64b5f6")]];
u32 reserved [[color("a1887f")]];
};
struct BuddyAllocator {
char header[4];
u32 offsetBookkeeping;
u32 sizeBookkeeping;
u32 offsetBookkeeping2;
u32 offsetData;
u8 reserved[12];
BuddyRootBlock root @ offsetBookkeeping + 4;
std::print("TOC {} address 0x{:08x}",
root.toc.toc[0].value,
root.offsets.addresses[root.toc.toc[0].value] >> 0x5 << 0x5);
BlocksList blocks @ (root.offsets.addresses[root.toc.toc[0].value] >> 0x5 << 0x5) + 4;
std::print("Blocks start at address 0x{:08x}, size 0x{:04x}",
root.offsets.addresses[blocks.blockId] >> 0x5 << 0x5,
1 << (root.offsets.addresses[blocks.blockId] & 0x1f));
TreeBlock entries @ (root.offsets.addresses[blocks.blockId] >> 0x5 << 0x5) + 4;
};
BuddyAllocator buddy @0x04;

View File

@@ -5,8 +5,11 @@
#pragma MIME application/x-sharedlib
#include <std/core.pat>
#include <std/io.pat>
#include <std/mem.pat>
using BitfieldOrder = std::core::BitfieldOrder;
using EI_ABIVERSION = u8;
using Elf32_Addr = u32;
using Elf32_BaseAddr = u32;
@@ -457,37 +460,37 @@ enum VER_NEED : Elf32_Half {
};
bitfield SYMINFO_FLG {
padding : 10;
NOEXTDIRECT : 1;
DIRECTBIND : 1;
LAZYLOAD : 1;
COPY : 1;
RESERVED : 1;
DIRECT : 1;
} [[left_to_right]];
RESERVED : 1;
COPY : 1;
LAZYLOAD : 1;
DIRECTBIND : 1;
NOEXTDIRECT : 1;
padding : 10;
};
bitfield ST {
ST_BIND : 4;
ST_TYPE : 4;
} [[left_to_right]];
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
bitfield SHF {
MASKPROC : 4;
MASKOS : 8;
UNKNOWN : 8;
COMPRESSED : 1;
TLS : 1;
GROUP : 1;
OS_NONCONFORMING : 1;
LINK_ORDER : 1;
INFO_LINK : 1;
STRINGS : 1;
MERGE : 1;
padding : 1;
EXECINSTR : 1;
ALLOC : 1;
WRITE : 1;
} [[left_to_right]];
ALLOC : 1;
EXECINSTR : 1;
padding : 1;
MERGE : 1;
STRINGS : 1;
INFO_LINK : 1;
LINK_ORDER : 1;
OS_NONCONFORMING : 1;
GROUP : 1;
TLS : 1;
COMPRESSED : 1;
UNKNOWN : 8;
MASKOS : 8;
MASKPROC : 4;
};
bitfield ELF32_R_INFO {
SYM : 8;
@@ -500,13 +503,13 @@ bitfield ELF64_R_INFO {
} [[left_to_right]];
bitfield PF {
MASKPROC : 4;
MASKOS : 4;
padding : 17;
R : 1;
W : 1;
X : 1;
} [[left_to_right]];
W : 1;
R : 1;
padding : 17;
MASKOS : 4;
MASKPROC : 4;
};
struct E_IDENT {
char EI_MAG[4];
@@ -560,8 +563,8 @@ struct Elf32_Phdr {
PF p_flags;
Elf32_Word p_align;
if (p_offset > 0 && p_filesz > 0 && (p_offset + p_filesz) < std::mem::data_size() && p_filesz < std::mem::data_size())
u8 p_data[p_filesz] @ p_offset;
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]];
};
struct Elf64_Phdr {
@@ -575,7 +578,7 @@ struct Elf64_Phdr {
Elf64_Xword p_align;
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;
u8 p_data[p_filesz] @ p_offset [[sealed]];
};
struct Elf32_Chdr {
@@ -637,12 +640,12 @@ struct Elf32_Shdr {
} else if (sh_type == SHT::STRTAB) {
String stringTable[while($ < (sh_offset + sh_size))] @ sh_offset;
stringTableIndex = std::core::array_index();
} else if (sh_type == SHT::DYNSYM) {
} else if (sh_type == SHT::SYMTAB || sh_type == SHT::DYNSYM) {
Elf32_Sym symbolTable[sh_size / sh_entsize] @ sh_offset;
} else if (sh_type == SHT::INIT_ARRAY || sh_type == SHT::FINI_ARRAY) {
u32 pointer[while($ < (sh_offset + sh_size))] @ sh_offset;
} else {
u8 data[sh_size] @ sh_offset;
u8 data[sh_size] @ sh_offset [[sealed]];
}
}
} [[format("format_section_header")]];;
@@ -697,12 +700,12 @@ struct Elf64_Shdr {
} else if (sh_type == SHT::STRTAB) {
String stringTable[while($ < (sh_offset + sh_size))] @ sh_offset;
stringTableIndex = std::core::array_index();
} else if (sh_type == SHT::DYNSYM) {
} else if (sh_type == SHT::SYMTAB || sh_type == SHT::DYNSYM) {
Elf64_Sym symbolTable[sh_size / sh_entsize] @ sh_offset;
} else if (sh_type == SHT::INIT_ARRAY || sh_type == SHT::FINI_ARRAY) {
u32 pointer[while($ < (sh_offset + sh_size))] @ sh_offset;
} else {
u8 data[sh_size] @ sh_offset;
u8 data[sh_size] @ sh_offset [[sealed]];
}
}
} [[format("format_section_header")]];
@@ -731,7 +734,9 @@ struct ELF {
std::core::set_endian(std::mem::Endian::Big);
if (e_ident.EI_CLASS == EI_CLASS::ELFCLASS32) {
Elf32_Ehdr header;
Elf32_Ehdr ehdr;
Elf32_Phdr phdr[ehdr.e_phnum] @ ehdr.e_phoff;
Elf32_Shdr shdr[ehdr.e_shnum] @ ehdr.e_shoff;
} else if (e_ident.EI_CLASS == EI_CLASS::ELFCLASS64) {
Elf64_Ehdr ehdr;
Elf64_Phdr phdr[ehdr.e_phnum] @ ehdr.e_phoff;
@@ -740,3 +745,78 @@ struct ELF {
};
ELF elf @ 0x00;
fn gen_shdr_disp_name(ref auto pattern, str member_name, u8 member_index) {
return std::format(
"{}@shdr[{}]({})",
member_name,
member_index,
format_section_header(pattern)
);
};
fn gen_shdr_sub_disp_name(ref auto pattern, str member_name, u8 member_index, u64 submember_index) {
return std::format(
"{}[{}]@shdr[{}]({})",
member_name,
submember_index,
member_index,
format_section_header(pattern)
);
};
fn gen_phdr_disp_name(ref auto pattern, str member_name, u8 member_index) {
return std::format(
"{}@phdr[{}]({})",
member_name,
member_index,
pattern.p_type
);
};
bool displaySectionNames in;
fn main() {
if (!displaySectionNames)
return;
for (u32 i = 0, i < std::core::member_count(elf.shdr), i += 1) {
if (std::core::has_member(elf.shdr[i], "stringTable")) {
std::core::set_display_name(
elf.shdr[i].stringTable,
gen_shdr_disp_name(elf.shdr[i], "stringTable", i)
);
for (u64 j = 0, j < std::core::member_count(elf.shdr[i].stringTable), j += 1) {
std::core::set_display_name(
elf.shdr[i].stringTable[j],
gen_shdr_sub_disp_name(elf.shdr[i], "String", i, j)
);
}
} else if (std::core::has_member(elf.shdr[i], "symbolTable")) {
std::core::set_display_name(
elf.shdr[i].symbolTable,
gen_shdr_disp_name(elf.shdr[i], "symbolTable", i)
);
} else if (std::core::has_member(elf.shdr[i], "pointer")) {
std::core::set_display_name(
elf.shdr[i].pointer,
gen_shdr_disp_name(elf.shdr[i], "pointer", i)
);
} else if (std::core::has_member(elf.shdr[i], "data")) {
std::core::set_display_name(
elf.shdr[i].data,
gen_shdr_disp_name(elf.shdr[i], "data", i)
);
}
}
for (u32 i = 0, i < std::core::member_count(elf.phdr), i += 1) {
if (std::core::has_member(elf.phdr[i], "p_data")) {
std::core::set_display_name(
elf.phdr[i].p_data,
gen_phdr_disp_name(elf.phdr[i], "p_data", i)
);
}
}
};

57
patterns/evtx.hexpat Normal file
View File

@@ -0,0 +1,57 @@
#pragma endian little
struct Header {
char signature[0x8];
u64 first_chunk_number;
u64 last_chunk_number;
u64 next_record_identifier;
u32 header_size;
u16 minor_format_version;
u16 major_format_version;
u16 header_block_size;
u16 number_of_chunks;
u8 unknown[0x4C];
u32 file_Flag;
u32 checkSum;
u8 unknown2[3968];
};
struct BinaryXML{
u8 fragment_header_token;
u8 major_version;
u8 minor_version;
u8 flags;
};
struct Event_Record{
u32 signature;
u32 size;
u64 event_record_identifier;
u64 written_data_amd_time;
BinaryXML binaryxml;
};
struct Chunk{
char signature[0x8];
u64 first_event_record_number;
u64 last_event_record_number;
u64 first_event_record_identifier;
u64 last_event_record_identifier;
u32 header_size;
u32 last_event_record_data_offset;
u32 free_space_offset;
u32 event_records_checksum;
u8 unknown[64];
u32 unknown2;
u32 checksum;
u8 common_string_offset_array[256];
u8 templatePtr[128];
Event_Record event_record;
};
struct Evtx {
Header header;
Chunk chunk;
};
Evtx evtx @ 0x00;

70
patterns/fdt.pat Normal file
View File

@@ -0,0 +1,70 @@
#pragma endian big
#include <std/sys.pat>
#include <std/io.pat>
#include <type/magic.pat>
#include <type/size.pat>
struct FDTHeader {
type::Magic<"\xD0\x0D\xFE\xED"> magic;
u32 totalsize;
u32 off_dt_struct;
u32 off_dt_strings;
u32 off_mem_rsvmap;
u32 version;
u32 last_comp_version;
u32 boot_cpuid_phys;
u32 size_dt_strings;
u32 size_dt_struct;
};
struct AlignTo<auto Alignment> {
padding[Alignment- ((($ - 1) % Alignment) + 1)];
};
struct FDTReserveEntry {
u64 address;
type::Size<u64> size;
if (address == 0x00 && size == 0x00)
break;
};
enum FDTToken : u32 {
FDT_BEGIN_NODE = 0x00000001,
FDT_END_NODE = 0x00000002,
FDT_PROP = 0x00000003,
FDT_NOP = 0x00000004,
FDT_END = 0x00000009
};
struct FDTStructureBlock {
FDTToken token;
if (token == FDTToken::FDT_BEGIN_NODE) {
char nodeName[];
AlignTo<4>;
} else if (token == FDTToken::FDT_END) {
break;
} else if (token == FDTToken::FDT_PROP) {
u32 len;
u32 nameoff;
char value[len];
AlignTo<4>;
char name[] @ parent.header.off_dt_strings + nameoff;
} else if (token == FDTToken::FDT_NOP || token == FDTToken::FDT_END_NODE) {
// Nothing to do
} else {
std::error(std::format("Invalid token at address 0x{:02X}", addressof(token)));
}
};
struct FDT {
FDTHeader header;
std::assert(header.version == 17, "Unsupported format version");
FDTStructureBlock structureBlocks[while(true)] @ header.off_dt_struct;
FDTReserveEntry reserveEntries[while(true)] @ header.off_mem_rsvmap;
};
FDT fdt @ 0x00;

View File

@@ -1,321 +1,323 @@
#include <std/sys.pat>
#include <std/core.pat>
#include <std/io.pat>
#pragma endian big
u32 sampleSize;
u32 bitsPerSample;
// METADATA
enum BLOCK_TYPE : u8 {
STREAMINFO = 0,
PADDING = 1,
APPLICATION = 2,
SEEKTABLE = 3,
VORBIS_COMMENT = 4,
CUESHEET = 5,
PICTURE = 6,
INVALID = 127
};
bitfield METADATA_BLOCK_HEADER {
lastMetadataBlock : 1;
blockType : 7;
length : 24;
} [[left_to_right]];
bitfield STREAMINFO_FLAGS {
sampleRate : 20;
numChannels : 3 [[format("format_channels")]];
bitsPerSample : 5;
numSamplesInStream : 36;
} [[inline, left_to_right]];
fn format_channels(u8 value) {
return value + 1;
};
struct METADATA_BLOCK_STREAMINFO {
u16 minBlockSize, maxBlockSize;
u24 minFrameSize, maxFrameSize;
STREAMINFO_FLAGS flags;
u128 md5Signature;
bitsPerSample = flags.bitsPerSample;
};
struct METADATA_BLOCK_PADDING {
padding[parent.header.length];
};
struct METADATA_BLOCK_APPLICATION {
char applicationID[4];
u8 applicationData[parent.header.length - sizeof(applicationID)];
};
struct SEEKPOINT {
u64 sampleNumber;
u64 byteOffset;
u16 numSamples;
};
struct METADATA_BLOCK_SEEKTABLE {
SEEKPOINT seekPoints[parent.header.length / 18];
};
struct VORBIS_USER_COMMENT {
le u32 length;
char comment[length];
};
struct METADATA_BLOCK_VORBIS_COMMENT {
le u32 vendorLength;
u8 vendor[vendorLength];
le u32 userCommentListLength;
VORBIS_USER_COMMENT userCommentList[userCommentListLength];
};
bitfield TRACK_FLAGS {
audioTrack : 1;
preEmphasis : 1;
padding : 6;
} [[inline]];
struct CUESHEET_TRACK_INDEX {
u64 sampleOffset;
u8 indexPointNumber;
padding[3];
};
struct CUESHEET_TRACK {
u64 trackOffset;
u8 trackNumber;
char trackISRC[12];
TRACK_FLAGS flags;
padding[13];
u8 numTrackIndexPoints;
CUESHEET_TRACK_INDEX indexes[numTrackIndexPoints];
};
struct METADATA_BLOCK_CUESHEET {
char mediaCatalogNumber[128];
u64 numLeadInSamples;
bool isCD;
padding[258];
u8 numTracks;
CUESHEET_TRACK tracks[numTracks];
};
enum PICTURE_TYPE : u32 {
Other = 0,
FileIcon = 1,
OtherFileIcon = 2,
CoverFront = 3,
CoverBack = 4,
LeafletPage = 5,
Media = 6,
LeadArtist = 7,
Artist = 8,
Conductor = 9,
Band = 10,
Composer = 11,
Lyricist = 12,
RecordingLocation = 13,
DuringRecording = 14,
DuringPerformance = 15,
MovieScreenCapture = 16,
ABrightColoredFish = 17,
Illustration = 18,
BandLogoType = 19,
PublisherLogoType = 20
};
struct METADATA_BLOCK_PICTURE {
PICTURE_TYPE pictureType;
u32 mimeTypeLength;
char mimeType[mineTypeLength];
u32 descriptionLength;
char description[descriptionLength];
u32 width, height;
u32 colorDepth;
u32 colorCount;
u32 pictureDataLength;
u8 pictureData[pictureDataLength];
};
// FRAME DATA
// TODO: THIS IS INCOMPLETE / NOT WORKING CURRENTLY
bitfield FRAME_HEADER_FLAGS {
syncCode : 14;
padding : 1;
blockingStrategy : 1;
blockSize : 4;
sampleRate : 4;
channelAssignment : 4;
sampleSize : 3;
padding : 1;
} [[inline]];
struct FRAME_HEADER {
FRAME_HEADER_FLAGS flags;
sampleSize = flags.sampleSize;
if (flags.blockingStrategy)
char16 sampleNumber[7];
else
char16 frameNumber[6];
if (flags.blockSize == 0b0110)
u8 blockSize;
else if (flags.blockSize == 0b0111)
u16 blockSize;
if (flags.sampleRate == 0b1100)
u8 sampleRate;
else if (flags.sampleRate == 0b1101 || flags.sampleRate == 0b1110)
u16 sampleRate;
u8 crc8;
};
struct FRAME_FOOTER {
u16 crc16;
};
bitfield SUBFRAME_HEADER {
padding : 1;
type : 6;
wastedBits : 1;
};
fn getBitsPerSample() {
if (sampleSize == 0b000)
return bitsPerSample;
else if (sampleSize == 0b001)
return 8;
else if (sampleSize == 0b010)
return 12;
else if (sampleSize == 0b100)
return 16;
else if (sampleSize == 0b101)
return 20;
else if (sampleSize == 0b110)
return 24;
};
bitfield SUBFRAME_CONSTANT {
value : getBitsPerSample();
};
bitfield SUBFRAME_VERBATIM {
value : getBitsPerSample() * parent.parent.header.flags.blockSize;
};
bitfield SUBFRAME_FIXED_VALUE {
value : getBitsPerSample() * (parent.parent.header.type & 0b111);
codingMethod : 2;
} [[inline]];
bitfield RESIDUAL_CODING_METHOD_PARTITIONED_RICE {
partitionOrder : 4;
riceParameter : 4;
if (riceParameter == 0b1111)
bitsPerSample : 5;
} [[right_to_left]];
bitfield RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 {
partitionOrder : 4;
riceParameter : 5;
if (riceParameter == 0b11111)
bitsPerSample : 5;
} [[right_to_left]];
struct RESIDUAL {
if (parent.value.codingMethod == 0b00)
RESIDUAL_CODING_METHOD_PARTITIONED_RICE rice;
else if (parent.value.codingMethod == 0b01)
RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 rice;
if ((parent.parent.header.type & 0b111) == 0b000)
u8 samples[(getBitsPerSample() * (parent.parent.parent.header.flags.blockSize - (parent.parent.header.type & 0b111))) / 8];
else if (std::core::array_index() != 0)
u8 samples[(getBitsPerSample() * (parent.parent.parent.header.flags.blockSize / (1 << rice.partitionOrder))) / 8];
else
u8 samples[(getBitsPerSample() * ((parent.parent.parent.header.flags.blockSize / (1 << rice.partitionOrder)) - (parent.parent.header.type & 0b111))) / 8];
};
struct SUBFRAME_FIXED {
SUBFRAME_FIXED_VALUE value;
RESIDUAL residual;
};
bitfield SUBFRAME_LPC_VALUE {
warmUpSamples : getBitsPerSample() * ((parent.header.type & 0b011111) + 1);
quantizedLinearPredictorCoefficient : 4;
quantizedLinearPredictorCoefficientShift : 5;
predictorCoefficients : quantizedLinearPredictorCoefficient * ((parent.header.type & 0b011111) + 1);
} [[inline]];
struct SUBFRAME_LPC {
SUBFRAME_LPC_VALUE value;
RESIDUAL residual;
};
struct SUBFRAME {
SUBFRAME_HEADER header;
if (header.type == 0b00000)
SUBFRAME_CONSTANT constant;
else if (header.type == 0b000001)
SUBFRAME_VERBATIM verbatim;
else if ((header.type >> 3) == 0b001 && (header.type & 0b111) <= 4)
SUBFRAME_FIXED fixed;
else if (header.type == 0b100000)
SUBFRAME_LPC lpc;
};
struct FRAME {
FRAME_HEADER header;
SUBFRAME subframes[parent.metadata[0].data.flags.numChannels + 1];
FRAME_FOOTER footer;
};
struct METADATA_BLOCK {
METADATA_BLOCK_HEADER header;
if (header.lastMetadataBlock)
break;
if (header.blockType == BLOCK_TYPE::STREAMINFO)
METADATA_BLOCK_STREAMINFO data;
else if (header.blockType == BLOCK_TYPE::PADDING)
METADATA_BLOCK_PADDING data;
else if (header.blockType == BLOCK_TYPE::APPLICATION)
METADATA_BLOCK_APPLICATION data;
else if (header.blockType == BLOCK_TYPE::VORBIS_COMMENT)
METADATA_BLOCK_VORBIS_COMMENT data;
else if (header.blockType == BLOCK_TYPE::CUESHEET)
METADATA_BLOCK_CUESHEET data;
else if (header.blockType == BLOCK_TYPE::PICTURE)
METADATA_BLOCK_PICTURE data;
else
std::error("Invalid metadata block type!");
};
struct STREAM {
char magic[4];
METADATA_BLOCK metadata[while(true)];
//FRAME frames[while(!std::mem::eof())];
};
#include <std/sys.pat>
#include <std/core.pat>
#include <std/io.pat>
#pragma endian big
using BitfieldOrder = std::core::BitfieldOrder;
u32 sampleSize;
u32 bitsPerSample;
// METADATA
enum BLOCK_TYPE : u8 {
STREAMINFO = 0,
PADDING = 1,
APPLICATION = 2,
SEEKTABLE = 3,
VORBIS_COMMENT = 4,
CUESHEET = 5,
PICTURE = 6,
INVALID = 127
};
bitfield METADATA_BLOCK_HEADER {
lastMetadataBlock : 1;
blockType : 7;
length : 24;
};
bitfield STREAMINFO_FLAGS {
sampleRate : 20;
numChannels : 3 [[format("format_channels")]];
bitsPerSample : 5;
numSamplesInStream : 36;
} [[inline]];
fn format_channels(u8 value) {
return value + 1;
};
struct METADATA_BLOCK_STREAMINFO {
u16 minBlockSize, maxBlockSize;
u24 minFrameSize, maxFrameSize;
STREAMINFO_FLAGS flags;
u128 md5Signature;
bitsPerSample = flags.bitsPerSample;
};
struct METADATA_BLOCK_PADDING {
padding[parent.header.length];
};
struct METADATA_BLOCK_APPLICATION {
char applicationID[4];
u8 applicationData[parent.header.length - sizeof(applicationID)];
};
struct SEEKPOINT {
u64 sampleNumber;
u64 byteOffset;
u16 numSamples;
};
struct METADATA_BLOCK_SEEKTABLE {
SEEKPOINT seekPoints[parent.header.length / 18];
};
struct VORBIS_USER_COMMENT {
le u32 length;
char comment[length];
};
struct METADATA_BLOCK_VORBIS_COMMENT {
le u32 vendorLength;
u8 vendor[vendorLength];
le u32 userCommentListLength;
VORBIS_USER_COMMENT userCommentList[userCommentListLength];
};
bitfield TRACK_FLAGS {
audioTrack : 1;
preEmphasis : 1;
} [[inline,bitfield_order(BitfieldOrder::LeastToMostSignificant, 8)]];
struct CUESHEET_TRACK_INDEX {
u64 sampleOffset;
u8 indexPointNumber;
padding[3];
};
struct CUESHEET_TRACK {
u64 trackOffset;
u8 trackNumber;
char trackISRC[12];
TRACK_FLAGS flags;
padding[13];
u8 numTrackIndexPoints;
CUESHEET_TRACK_INDEX indexes[numTrackIndexPoints];
};
struct METADATA_BLOCK_CUESHEET {
char mediaCatalogNumber[128];
u64 numLeadInSamples;
bool isCD;
padding[258];
u8 numTracks;
CUESHEET_TRACK tracks[numTracks];
};
enum PICTURE_TYPE : u32 {
Other = 0,
FileIcon = 1,
OtherFileIcon = 2,
CoverFront = 3,
CoverBack = 4,
LeafletPage = 5,
Media = 6,
LeadArtist = 7,
Artist = 8,
Conductor = 9,
Band = 10,
Composer = 11,
Lyricist = 12,
RecordingLocation = 13,
DuringRecording = 14,
DuringPerformance = 15,
MovieScreenCapture = 16,
ABrightColoredFish = 17,
Illustration = 18,
BandLogoType = 19,
PublisherLogoType = 20
};
struct METADATA_BLOCK_PICTURE {
PICTURE_TYPE pictureType;
u32 mimeTypeLength;
char mimeType[mineTypeLength];
u32 descriptionLength;
char description[descriptionLength];
u32 width, height;
u32 colorDepth;
u32 colorCount;
u32 pictureDataLength;
u8 pictureData[pictureDataLength];
};
// FRAME DATA
// TODO: THIS IS INCOMPLETE / NOT WORKING CURRENTLY
bitfield FRAME_HEADER_FLAGS {
syncCode : 14;
padding : 1;
blockingStrategy : 1;
blockSize : 4;
sampleRate : 4;
channelAssignment : 4;
sampleSize : 3;
} [[inline,bitfield_order(BitfieldOrder::LeastToMostSignificant, 32)]];
struct FRAME_HEADER {
FRAME_HEADER_FLAGS flags;
sampleSize = flags.sampleSize;
if (flags.blockingStrategy)
char16 sampleNumber[7];
else
char16 frameNumber[6];
if (flags.blockSize == 0b0110)
u8 blockSize;
else if (flags.blockSize == 0b0111)
u16 blockSize;
if (flags.sampleRate == 0b1100)
u8 sampleRate;
else if (flags.sampleRate == 0b1101 || flags.sampleRate == 0b1110)
u16 sampleRate;
u8 crc8;
};
struct FRAME_FOOTER {
u16 crc16;
};
bitfield SUBFRAME_HEADER {
padding : 1;
type : 6;
wastedBits : 1;
};
fn getBitsPerSample() {
if (sampleSize == 0b000)
return bitsPerSample;
else if (sampleSize == 0b001)
return 8;
else if (sampleSize == 0b010)
return 12;
else if (sampleSize == 0b100)
return 16;
else if (sampleSize == 0b101)
return 20;
else if (sampleSize == 0b110)
return 24;
else
std::error(std::format("Invalid sample size {}.", sampleSize));
};
bitfield SUBFRAME_CONSTANT {
value : getBitsPerSample();
};
bitfield SUBFRAME_VERBATIM {
value : getBitsPerSample() * parent.parent.header.flags.blockSize;
};
bitfield SUBFRAME_FIXED_VALUE {
value : getBitsPerSample() * (parent.parent.header.type & 0b111);
codingMethod : 2;
} [[inline]];
bitfield RESIDUAL_CODING_METHOD_PARTITIONED_RICE {
partitionOrder : 4;
riceParameter : 4;
if (riceParameter == 0b1111)
bitsPerSample : 5;
};
bitfield RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 {
partitionOrder : 4;
riceParameter : 5;
if (riceParameter == 0b11111)
bitsPerSample : 5;
};
struct RESIDUAL {
if (parent.value.codingMethod == 0b00)
RESIDUAL_CODING_METHOD_PARTITIONED_RICE rice;
else if (parent.value.codingMethod == 0b01)
RESIDUAL_CODING_METHOD_PARTITIONED_RICE2 rice;
if ((parent.parent.header.type & 0b111) == 0b000)
u8 samples[(getBitsPerSample() * (parent.parent.parent.header.flags.blockSize - (parent.parent.header.type & 0b111))) / 8];
else if (std::core::array_index() != 0)
u8 samples[(getBitsPerSample() * (parent.parent.parent.header.flags.blockSize / (1 << rice.partitionOrder))) / 8];
else
u8 samples[(getBitsPerSample() * ((parent.parent.parent.header.flags.blockSize / (1 << rice.partitionOrder)) - (parent.parent.header.type & 0b111))) / 8];
};
struct SUBFRAME_FIXED {
SUBFRAME_FIXED_VALUE value;
RESIDUAL residual;
};
bitfield SUBFRAME_LPC_VALUE {
warmUpSamples : getBitsPerSample() * ((parent.header.type & 0b011111) + 1);
quantizedLinearPredictorCoefficient : 4;
quantizedLinearPredictorCoefficientShift : 5;
predictorCoefficients : quantizedLinearPredictorCoefficient * ((parent.header.type & 0b011111) + 1);
} [[inline]];
struct SUBFRAME_LPC {
SUBFRAME_LPC_VALUE value;
RESIDUAL residual;
};
struct SUBFRAME {
SUBFRAME_HEADER header;
if (header.type == 0b00000)
SUBFRAME_CONSTANT constant;
else if (header.type == 0b000001)
SUBFRAME_VERBATIM verbatim;
else if ((header.type >> 3) == 0b001 && (header.type & 0b111) <= 4)
SUBFRAME_FIXED fixed;
else if (header.type == 0b100000)
SUBFRAME_LPC lpc;
};
struct FRAME {
FRAME_HEADER header;
SUBFRAME subframes[parent.metadata[0].data.flags.numChannels + 1];
FRAME_FOOTER footer;
};
struct METADATA_BLOCK {
METADATA_BLOCK_HEADER header;
if (header.lastMetadataBlock)
break;
if (header.blockType == BLOCK_TYPE::STREAMINFO)
METADATA_BLOCK_STREAMINFO data;
else if (header.blockType == BLOCK_TYPE::PADDING)
METADATA_BLOCK_PADDING data;
else if (header.blockType == BLOCK_TYPE::APPLICATION)
METADATA_BLOCK_APPLICATION data;
else if (header.blockType == BLOCK_TYPE::VORBIS_COMMENT)
METADATA_BLOCK_VORBIS_COMMENT data;
else if (header.blockType == BLOCK_TYPE::CUESHEET)
METADATA_BLOCK_CUESHEET data;
else if (header.blockType == BLOCK_TYPE::PICTURE)
METADATA_BLOCK_PICTURE data;
else
std::error("Invalid metadata block type!");
};
struct STREAM {
char magic[4];
METADATA_BLOCK metadata[while(true)];
//FRAME frames[while(!std::mem::eof())];
};
STREAM stream @ 0x00;

View File

@@ -13,7 +13,7 @@ bitfield CHS {
h : 8;
s : 6;
c : 10;
} [[right_to_left, format("chs_formatter")]];
} [[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));

337
patterns/gb.hexpat Normal file
View File

@@ -0,0 +1,337 @@
#include <type/size.pat>
#include <std/io.pat>
#include <std/string.pat>
#pragma MIME application/x-gameboy-rom
namespace format {
fn rom_type(u8 romType) {
u32 romSize = 32768 * (1 << romType);
u16 romBanks = 2 * (1 << romType);
if(romType == 0x52) {
romSize = 1153434;
romBanks = 72;
}
if(romType == 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 = "( ";
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 ";
}
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";
(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(a[0] == 0 && a[1] == 0) return "See old licensee";
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";
("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";
};
}
bitfield pixel_packed {
p1 : 1;
p2 : 1;
p3 : 1;
p4 : 1;
p5 : 1;
p6 : 1;
p7 : 1;
p8 : 1;
};
enum CGB : u8 {
NO_CGB = 0x00 ... 0x7F,
BACKWARDS_COMPATIBLE = 0x80,
CGB_ONLY = 0xC0
};
struct Logo {
pixel_packed rawData[0x30];
};
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")]];
};
struct Header {
u32 jmpInstruction;
Logo logo;
char title[0xF];
CGB cgb;
char newLicenseeCode[2] [[format("format::new_licensee_code")]];
bool sgbFlag;
u8 type [[format("format::rom_features")]];
u8 romType [[format("format::rom_type")]];
u8 ramType [[format("format::ram_type")]];
bool japanOnly;
u8 licenseeCode [[format("format::licensee_code")]];
u8 version;
u8 checksum [[comment("Checksum for: $134-$14C")]];
u16 gloalChecksum [[comment("Checksum for entire range")]];
};
struct Cartrige {
JumpVectors jumpVectors [[comment("Instructions called on interupts or rst instructions")]];
padding[0x100 - sizeof(JumpVectors)];
Header header;
};
Cartrige cart @ 0x00;

181
patterns/gif.hexpat Normal file
View File

@@ -0,0 +1,181 @@
#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
#include <std/io.pat>
#include <std/core.pat>
#include <std/mem.pat>
#include <std/string.pat>
#pragma MIME image/gif
bitfield GCT_Flags {
size : 3 [[comment("physical size = 2^(flags.size + 1)")]];
sort : 1 [[comment("Indicates if the table is sorted by importance")]];
colorRes : 3 [[comment("Indicates the richness of the original pallet")]];
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 GC_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 subblock {
u8 size;
if(size == 0) break;
u8 data[size];
};
struct block {
subblock blocks[MAX_BLOCKS];
};
fn exp2(auto n) {
return 1 << n;
};
struct Header {
char magic[3];
char version[3];
u16 width;
u16 height;
GCT_Flags gctFlags;
u8 bgColorIndex;
u8 pixelAscpet;
if (gctFlags.enabled) {
color gct[(exp2(gctFlags.size + 1))];
color bgColor = gct[bgColorIndex];
}
};
struct frame {
u16 x;
u16 y;
u16 width;
u16 height;
LCT_Flags lctFlags;
if(lctFlags.enable) {
color lct[(exp2(lctFlags.size + 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")]];
};
struct comment {
block data [[hidden]];
char comment[] @ addressof(data.blocks) + 1; // TODO : need to find a better way of doing this
};
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 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 graphical_control {
u8 blockSize [[hidden]];
GC_Flags flags;
u16 delay [[format("format::delay")]];
u8 transparentColorIndex;
block b [[hidden]];
};
namespace format {
fn dispose_enum(u8 value) {
if(value == 0x00) return "Do nothing";
if(value == 0x01) return "Do not remove pixels";
if(value == 0x02) return "Restore background pixels";
if(value == 0x03) return "Restore previous pixels";
};
fn extension_name(u8 label) {
if(label == LABEL_GC) return "Graphical Control Extension";
if(label == LABEL_COMMENT) return "Comment Extension";
if(label == LABEL_APPLICATION) return "Application Extension";
if(label == LABEL_PLAINTEXT) return "Plaintext Extension";
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 delay(u16 delay) {
if(delay == -1) return "forever";
else if(delay < 2) return "100ms";
else return std::string::to_string(delay * 10) + "ms";
return "notime";
};
}
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 {
Header header;
Data data;
};
Gif gif @ 0x00;

79
patterns/gzip.hexpat Normal file
View File

@@ -0,0 +1,79 @@
#pragma MIME application/gzip
#include <type/time.pat>
#include <type/size.pat>
#include <std/core.pat>
#include <std/mem.pat>
using BitfieldOrder = std::core::BitfieldOrder;
bitfield Flags {
FTEXT : 1;
FHCRC : 1;
FEXTRA : 1;
FNAME : 1;
FCOMMENT : 1;
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 8)]];
bitfield ExtraFlags {
padding : 1;
maximumCompression : 1;
fastestCompression : 1;
padding : 5;
};
enum CompressionMethod : u8 {
Reserved = 0 ... 7,
Deflate = 8
};
enum OperatingSystemID : u8 {
FATFileSystem = 0x00,
Amiga = 0x01,
VMS = 0x02,
Unix = 0x03,
VM_CMS = 0x04,
AtariTOS = 0x05,
HPFSFileSystem = 0x06,
Macintosh = 0x07,
ZSystem = 0x08,
CP_M = 0x09,
TOPS_20 = 0x0A,
NTFSFileSystem = 0x0B,
QDOS = 0x0C,
AcordRISCOS = 0x0D,
Unknown = 0xFF
};
struct GZip {
u16 signature;
CompressionMethod compressionMethod;
Flags flags;
type::time32_t modificationTime;
ExtraFlags extraFlags;
OperatingSystemID operatingSystemId;
if (flags.FEXTRA) {
u16 extraLength;
u8 extraField[extraLength];
}
if (flags.FNAME) {
char originalFileName[];
}
if (flags.FCOMMENT) {
char comment[];
}
if (flags.FHCRC) {
u16 crc16;
}
u8 data[while($ < std::mem::size() - 8)] [[sealed]];
u32 crc32;
type::Size<u32> isize;
};
GZip gzip @ 0x00;

156
patterns/id3.hexpat Normal file
View File

@@ -0,0 +1,156 @@
#pragma MIME audio/mpeg
#include <std/mem.pat>
namespace v1 {
struct Tag {
char header[3];
char title[30];
char artist[30];
char album[30];
char year[4];
char comment[30];
u8 zero;
u8 track;
u8 genre;
} [[static]];
}
namespace v2 {
struct SyncSafeInt {
u8 bytes[4];
} [[sealed, static, format("v2::ssi_value"), transform("v2::ssi_value")]];
fn ssi_value(ref SyncSafeInt n) {
u32 result = 0;
for (u8 i = 0, i < 4, i = i + 1) {
u8 byteval = n.bytes[i] & 0x7F;
u8 shift = 7 * (4 - i - 1);
result = result | (byteval << shift);
}
return result;
};
struct TagVersion {
u8 major;
u8 revision;
};
bitfield TagHeaderFlags {
unsynchronized : 1;
extended : 1;
experimental : 1;
footer : 1;
padding : 4;
};
struct TagHeader {
char identifier[3];
TagVersion version;
TagHeaderFlags flags;
SyncSafeInt size;
} [[static]];
bitfield ExtendedFlag {
padding : 1;
update : 1;
crcpresent : 1;
restrictions : 1;
padding : 4;
};
struct TagExtendedHeader {
SyncSafeInt size;
u8 nflagbytes;
ExtendedFlag flags[nflagbytes];
u8 data[size];
};
struct TagFooter {
char identifier[3];
TagVersion version;
TagHeaderFlags flags;
SyncSafeInt size;
} [[static]];
bitfield FrameFlags {
padding : 1;
tagalterpreservation : 1;
filealterpreservation : 1;
readonly : 1;
padding : 5;
groupid : 1;
padding : 2;
compressed : 1;
encrypted : 1;
unzynchronized : 1;
datalengthindicator : 1;
};
enum TextEncoding : u8 {
ISO88591 = 0x00,
UTF16BOM = 0x01,
UTF16BE = 0x02,
UTF8 = 0x03,
};
struct StringData {
TextEncoding encoding;
if (encoding == TextEncoding::UTF16BOM) {
u16 bom;
char16 data[(parent.size - 3) / 2];
} else if (encoding == TextEncoding::UTF16BE)
be char16 data[(parent.size - 1) / 2];
else
char data[parent.size - 1];
};
// Hack to work around the fact, that chars may not be compared
union FrameId {
char cdata[4];
u8 ndata[4];
} [[sealed, static, format("v2::impl::format_frame_id")]];
namespace impl {
fn format_frame_id(ref FrameId id) {
return id.cdata;
};
}
struct Frame {
FrameId id;
SyncSafeInt size;
FrameFlags flags;
if (id.ndata[0] == 'T')
StringData data;
else
u8 data[size];
};
fn has_next_frame(u32 size) {
bool hasnext = $ < size;
if (hasnext) {
hasnext = std::mem::read_unsigned($, 1) != 0;
$ = $ - 1;
}
return hasnext;
};
struct Tag {
TagHeader header;
if (header.flags.extended)
TagExtendedHeader extendedheader;
Frame frames[while(v2::has_next_frame(header.size))];
if (header.flags.footer)
TagFooter footer;
};
}
v2::Tag tag @ 0;
v1::Tag oldtag @ std::mem::size() - 128;

View File

@@ -1,5 +1,4 @@
#pragma endian big
#pragma bitfield_order left_to_right
#include <std/sys.pat>
#include <std/io.pat>

View File

@@ -1,10 +1,13 @@
#pragma endian big
#pragma MIME application/x-java-applet
#pragma pattern_limit 100000000
#include <std/string.pat>
#include <std/math.pat>
#include <std/core.pat>
#include <std/io.pat>
#include <std/sys.pat>
// The Java documentations use the number of bytes instead of the number of bits for its type names
using BitfieldOrder = std::core::BitfieldOrder;
using u1 = u8;
using u2 = u16;
using u4 = u32;
@@ -12,22 +15,182 @@ using u4 = u32;
using f4 = float;
using f8 = double;
enum cp_tag : u8 {
CONSTANT_Utf8 = 1,
CONSTANT_Integer = 3,
CONSTANT_Float = 4,
CONSTANT_Long = 5,
CONSTANT_Double = 6,
CONSTANT_Class = 7,
CONSTANT_String = 8,
CONSTANT_Fieldref = 9,
CONSTANT_Methodref = 10,
CONSTANT_InterfaceMethodref = 11,
CONSTANT_NameAndType = 12,
CONSTANT_MethodHandle = 15,
CONSTANT_MethodType = 16,
CONSTANT_InvokeDynamic = 18
};
using cp_ref = u16 [[format("fmt::const_ref_top")]];
bool applyPadding = false;
struct cp_info {
bool isTop = false;
if(applyPadding) {
isTop = true;
applyPadding = false;
}
else {
u1 tag;
match(tag) {
(1): { /* cp_utf8 */
u2 length;
char bytes[length];
}
(3): { /* cp_integer */
u4 bytes;
}
(4): { /* cp_float */
float bytes;
}
(5): { /* cp_long */
u64 bytes;
applyPadding = true;
}
(6): { /* cp_double */
double bytes;
applyPadding = true;
}
(7): { /* cp_class */
cp_ref name_index;
}
(8): { /* cp_string */
cp_ref string_index;
}
(9): { /* cp_fieldref */
cp_ref class_index;
cp_ref name_and_type_index;
}
(10): { /* cp_methodref */
cp_ref class_index;
cp_ref name_and_type_index;
}
(11): { /* cp_interface_methodref */
cp_ref class_index;
cp_ref name_and_type_index;
}
(12): { /* cp_name_and_type */
cp_ref name_index;
cp_ref descriptor_index;
}
(15): { /* cp_method_handle */
u1 reference_kind;
cp_ref reference_index;
}
(16): { /* cp_method_type */
cp_ref descriptor_index;
}
(18): { /* cp_invoke_dynamic */
u2 bootstrap_method_attr_index;
cp_ref name_and_type_index;
}
(19): { /* cp_module */
cp_ref name_index;
}
(20): { /* cp_package */
cp_ref name_index;
}
}
}
} [[format("fmt::const_name")]];
namespace fmt {
fn const_name(auto tag) {
if(tag.isTop) return "Top";
match(tag.tag) {
(1): return "Utf8";
(3): return "Integer";
(4): return "Float";
(5): return "Long";
(6): return "Double";
(7): return "Class";
(8): return "String";
(9): return "Fieldref";
(10): return "Methodref";
(11): return "InterfaceMethodref";
(12): return "NameAndType";
(15): return "MethodHandle";
(16): return "MethodType";
(18): return "InvokeDynamic";
(_): return "Unknown";
}
};
fn const_ref(u2 index) {
cp_info info = file.constant_pool[index-1];
match(info.tag) {
(1): return info.bytes;
(3): return std::format("{:d} [{:d}]", index, info.bytes);
(4): return std::format("{:d} [{:f}]", index, info.bytes);
(5): return std::format("{:d} [{:d}", index, info.bytes);
(6): return std::format("{:d} [{:f}", index, info.bytes);
(7): return std::format("{:d} [Class({})]", index, fmt::const_ref(info.name_index));
(8): return std::format("{:d} [String({})]", index, fmt::const_ref(info.string_index));
(9): return std::format("{:d} [Fieldref({}, {})]", index, fmt::const_ref(info.class_index), fmt::const_ref(info.name_and_type_index));
(10): return std::format("{:d} [Methodref({}, {})]", index, fmt::const_ref(info.class_index), fmt::const_ref(info.name_and_type_index));
(11): return std::format("{:d} [InterfaceMethodref({}, {})]", index, fmt::const_ref(info.class_index), fmt::const_ref(info.name_and_type_index));
(12): return std::format("{:d} [NameAndType({}, {})]", index, fmt::const_ref(info.name_index), fmt::const_ref(info.descriptor_index));
(15): return std::format("{:d} [MethodHandle({}, {})]", index, info.reference_kind, fmt::const_ref(info.reference_index));
(16): return std::format("{:d} [MethodType({})]", index, fmt::const_ref(info.descriptor_index));
(18): return std::format("{:d} [InvokeDynamic({}, {})]", index, info.bootstrap_method_attr_index, fmt::const_ref(info.name_and_type_index));
(19): return std::format("{:d} [Module({})]", index, fmt::const_ref(info.name_index));
(20): return std::format("{:d} [Package({})]", index, fmt::const_ref(info.name_index));
(_): return std::format("{:d} [Unknown]", index);
}
};
fn const_ref_top(u2 index) {
cp_info info = file.constant_pool[index-1];
match(info.tag) {
(1): return std::format("{:d} [{:s}]", index, info.bytes);
(_): return fmt::const_ref(index);
}
};
fn attribute(auto info) {
return file.constant_pool[info.attribute_name_index-1].bytes;
};
fn verif_type_info(auto info) {
match(info.tag) {
(0): return "TOP";
(1): return "INTEGER";
(2): return "FLOAT";
(3): return "DOUBLE";
(4): return "LONG";
(5): return "NULL";
(6): return "UNINITIALIZED_THIS";
(7): return std::format("Object({})", fmt::const_ref(info.cpool_index));
(8): return std::format("Uninitialized({})", info.offset);
(_): return "Unknown";
}
};
fn stack_map_frame(auto frame) {
match(frame.frame_type) {
(0 ... 63): return std::format("SAME [{}]", frame.frame_type);
(64 ... 127): return std::format("SAME_LOCALS_1_STACK_ITEM [{}]", frame.frame_type);
(247): return std::format("SAME_LOCALS_1_STACK_ITEM_EXTENDED [{}]", frame.frame_type);
(248 ... 250): return std::format("CHOP [{}]", frame.frame_type);
(251): return std::format("SAME_FRAME_EXTENDED [{}]", frame.frame_type);
(252 ... 254): return std::format("APPEND [{}]", frame.frame_type);
(255): return std::format("FULL_FRAME [{}]", frame.frame_type);
}
};
fn element_value(auto element) {
match(element.tag) {
('B'): return std::format("byte [{:s}]", fmt::const_ref(element.const_value_index));
('C'): return std::format("char [{:s}]", fmt::const_ref(element.const_value_index));
('D'): return std::format("double [{:s}]", fmt::const_ref(element.const_value_index));
('F'): return std::format("float [{:s}]", fmt::const_ref(element.const_value_index));
('I'): return std::format("int [{:s}]", fmt::const_ref(element.const_value_index));
('J'): return std::format("long [{:s}]", fmt::const_ref(element.const_value_index));
('S'): return std::format("short [{:s}]", fmt::const_ref(element.const_value_index));
('Z'): return std::format("boolean [{:s}]", fmt::const_ref(element.const_value_index));
('s'): return std::format("String [{:s}]", fmt::const_ref(element.const_value_index));
('e'): return std::format("Enum [{:s}, {:s}]", fmt::const_ref(element.type_name_index), fmt::const_ref(element.const_name_index));
('c'): return std::format("Class [{:s}]", fmt::const_ref(element.class_info_index));
('@'): return std::format("Annotation [{:s}]", fmt::const_ref(element.annotation_value.type_index));
('['): return std::format("Array [{:s}]", fmt::const_ref(element.num_values));
}
};
}
enum major_version : u2 {
JDK_1_1 = 45,
@@ -36,7 +199,7 @@ enum major_version : u2 {
JDK_1_4 = 48,
Java_SE_5_0 = 49,
Java_SE_6_0 = 50,
Java_SE_6 = 50,
Java_SE_7 = 51,
Java_SE_8 = 52,
Java_SE_9 = 53,
@@ -50,118 +213,6 @@ enum major_version : u2 {
Java_SE_17 = 61,
};
// Tag == CONSTANT_Utf8
struct CONSTANT_Utf8_info {
u2 length;
char bytes[length]; // u1 in documentation. Changed to char to improve readability
};
// Tag == CONSTANT_Integer
struct CONSTANT_Integer_info {
u4 bytes;
};
// Tag == CONSTANT_Float
struct CONSTANT_Float_info {
f4 bytes; // u4 in documentation. Changed to f4 to improve readablilty
};
// Tag == CONSTANT_Long
struct CONSTANT_Long_info {
u4 high_bytes;
u4 low_bytes;
};
// Tag == CONSTANT_Double
struct CONSTANT_Double_info {
u4 high_bytes;
u4 low_bytes;
};
// Tag == CONSTANT_Class
struct CONSTANT_Class_info {
u2 name_index;
};
// Tag == CONSTANT_String
struct CONSTANT_String_info {
u2 string_index;
};
// Tag == CONSTANT_Fieldref
struct CONSTANT_Fieldref_info {
u2 class_index;
u2 name_and_type_index;
};
// Tag == CONSTANT_Methodref
struct CONSTANT_Methodref_info {
u2 class_index;
u2 name_and_type_index;
};
// Tag == CONSTANT_InterfaceMethodref
struct CONSTANT_InterfaceMethodref_info {
u2 class_index;
u2 name_and_type_index;
};
// Tag == CONSTANT_NameAndType
struct CONSTANT_NameAndType_info {
u2 name_index;
u2 descriptor_index;
};
// Tag == CONSTANT_MethodHandle
struct CONSTANT_MethodHandle_info {
u1 reference_kind;
u2 reference_index;
};
// Tag == CONSTANT_MethodType
struct CONSTANT_MethodType_info {
u2 descriptor_index;
};
// Tag == CONSTANT_InvokeDynamic
struct CONSTANT_InvokeDynamic_info {
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
};
struct cp_info {
cp_tag tag;
if (tag == cp_tag::CONSTANT_Utf8)
CONSTANT_Utf8_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Integer)
CONSTANT_Integer_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Float)
CONSTANT_Float_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Long)
CONSTANT_Long_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Double)
CONSTANT_Double_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Class)
CONSTANT_Class_info info [[inline]];
else if (tag == cp_tag::CONSTANT_String)
CONSTANT_String_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Fieldref)
CONSTANT_Fieldref_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Methodref)
CONSTANT_Methodref_info info [[inline]];
else if (tag == cp_tag::CONSTANT_InterfaceMethodref)
CONSTANT_InterfaceMethodref_info info [[inline]];
else if (tag == cp_tag::CONSTANT_NameAndType)
CONSTANT_NameAndType_info info [[inline]];
else if (tag == cp_tag::CONSTANT_MethodHandle)
CONSTANT_MethodHandle_info info [[inline]];
else if (tag == cp_tag::CONSTANT_MethodType)
CONSTANT_MethodType_info info [[inline]];
else if (tag == cp_tag::CONSTANT_InvokeDynamic)
CONSTANT_InvokeDynamic_info info [[inline]];
};
bitfield access_flags_method {
ACC_PUBLIC : 1; // 0x0001
ACC_PRIVATE : 1; // 0x0002
@@ -179,7 +230,7 @@ bitfield access_flags_method {
padding : 1; // 0x2000
padding : 1; // 0x4000
padding : 1; // 0x8000
};
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
bitfield access_flags_field {
ACC_PUBLIC : 1; // 0x0001
@@ -198,7 +249,7 @@ bitfield access_flags_field {
padding : 1; // 0x2000
ACC_ENUM : 1; // 0x4000
padding : 1; // 0x8000
};
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
bitfield access_flags_class {
ACC_PUBLIC : 1; // 0x0001
@@ -216,127 +267,532 @@ bitfield access_flags_class {
ACC_SYNTHETIC : 1; // 0x1000
ACC_ANNOTATION : 1; // 0x2000
ACC_ENUM : 1; // 0x4000
padding : 1; // 0x8000
ACC_MODULE : 1; // 0x8000
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
bitfield access_flags_module {
padding : 1; // 0x0001
padding : 1; // 0x0002
padding : 1; // 0x0004
padding : 1; // 0x0008
padding : 1; // 0x0010
ACC_TRANSITIVE : 1; // 0x0020
ACC_STATIC_PHASE : 1; // 0x0040
padding : 1; // 0x0080
padding : 1; // 0x0100
padding : 1; // 0x0200
padding : 1; // 0x0400
padding : 1; // 0x0800
ACC_SYNTHETIC : 1; // 0x1000
padding : 1; // 0x2000
padding : 1; // 0x4000
ACC_MANDATED : 1; // 0x8000
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
using attribute_code;
struct attribute_constant_value {
cp_ref constantvalue_index;
} [[static]];
struct verification_type_info {
u1 tag;
match(tag) {
(0): { /* Top_variable_info */
}
(1): { /* Integer_variable_info */
}
(2): { /* Float_variable_info */
}
(3): { /* Long_variable_info */
}
(4): { /* Double_variable_info */
}
(5): { /* Null_variable_info */
}
(6): { /* UninitializedThis_variable_info */
}
(7): { /* Object_variable_info */
cp_ref cpool_index;
}
(8): { /* Uninitialized_variable_info */
u2 offset;
}
}
} [[format("fmt::verif_type_info")]];
struct same_locals_1_stack_item_frame {
verification_type_info stack[1];
};
struct attribute_info {
u2 attribute_name_info;
struct same_locals_1_stack_item_frame_extended {
u2 offset_delta;
verification_type_info stack[1];
};
struct chop_frame {
u2 offset_delta;
};
struct same_frame_extended {
u2 offset_delta;
} [[static]];
struct append_frame<auto frame_type> {
u2 offset_delta;
verification_type_info locals[frame_type - 251];
};
struct full_frame {
u2 offset_delta;
u2 number_of_locals;
verification_type_info locals[number_of_locals];
u2 number_of_stack_items;
verification_type_info stack[number_of_stack_items];
};
struct stack_map_frame {
u1 frame_type;
match(frame_type) {
(0 ... 63): {} /* nothing */
(64 ... 127): same_locals_1_stack_item_frame child [[inline]];
(247): same_locals_1_stack_item_frame_extended child [[inline]];
(248 ... 250): chop_frame child [[inline]];
(251): same_frame_extended child [[inline]];
(252 ... 254): append_frame<frame_type> child [[inline]];
(255): full_frame child [[inline]];
}
} [[format("fmt::stack_map_frame")]];
struct same_frame {
u1 frame_type = SAME; /* 0-63 */
};
struct attribute_stack_map_table {
u2 number_of_entries;
stack_map_frame entries[number_of_entries];
};
struct attribute_exception {
u2 number_of_exceptions;
cp_ref exception_index_table[number_of_exceptions];
};
struct inner_class {
cp_ref inner_class_info_index;
u16 __ [[hidden]];
if(__ != 0) {
cp_ref outer_class_info_index @ addressof(__);
}
u16 ___ [[hidden]];
if(___ != 0) {
cp_ref inner_name_index @ addressof(___);
}
u2 inner_class_access_flags;
};
struct attribute_inner_classes {
u2 number_of_classes;
inner_class classes[number_of_classes];
};
struct attribute_enclosing_method {
cp_ref class_index;
cp_ref method_index;
} [[static]];
struct attribute_synthetic {
};
struct attribute_signature {
cp_ref signature_index;
} [[static]];
struct attribute_source_file {
cp_ref sourcefile_index;
} [[static]];
struct attribute_source_debug_extension {
u1 debug_extension[attribute_length];
};
struct line_number_table_entry {
u2 start_pc;
u2 line_number;
} [[static]];
struct attribute_line_number_table {
u2 line_number_table_length;
line_number_table_entry line_number_table[line_number_table_length];
};
struct local_variable_table_entry {
u2 start_pc;
u2 length;
cp_ref name_index;
cp_ref descriptor_index;
u2 index;
} [[static]];
struct attribute_local_variable_table {
u2 local_variable_table_length;
local_variable_table_entry local_variable_table[local_variable_table_length];
};
struct local_variable_type_table_entry {
u2 start_pc;
u2 length;
cp_ref name_index;
cp_ref signature_index;
u2 index;
} [[static]];
struct attribute_local_variable_type_table {
u2 local_variable_type_table_length;
local_variable_type_table_entry local_variable_type_table[local_variable_type_table_length];
};
struct attribute_deprecated {
};
using annotation;
using element_value;
struct element_value {
char tag;
match(tag) {
('B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's'): {
cp_ref const_value_index;
}
('e'): {
cp_ref type_name_index;
cp_ref const_name_index;
}
('c'): {
cp_ref class_info_index;
}
('@'): {
annotation annotation_value;
}
('['): {
u2 num_values;
element_value values[num_values];
}
(_): {
std::error("Unknown element_value tag: %c", tag);
}
}
} [[format("fmt::element_value")]];
struct element_value_pair {
cp_ref element_name_index;
element_value value;
};
struct annotation {
cp_ref type_index;
u2 num_element_value_pairs;
element_value_pair element_value_pairs[num_element_value_pairs];
};
struct annotation_base {
u2 num_annotations;
annotation annotations[num_annotations];
};
struct attribute_runtime_visible_annotations {
annotation_base [[inline]];
};
struct attribute_runtime_invisible_annotations {
annotation_base [[inline]];
};
struct attribute_runtime_visible_parameter_annotations {
u1 num_parameters;
annotation_base parameter_annotations[num_parameters];
};
struct attribute_runtime_invisible_parameter_annotations {
u1 num_parameters;
annotation_base parameter_annotations[num_parameters];
};
struct path_element {
u1 type_path_kind;
u1 type_argument_index;
};
struct type_path {
u1 path_length;
path_element path[path_length];
};
struct localvar_target_entry {
u2 start_pc;
u2 length;
u2 index;
};
struct target_info<auto target_type> {
match(target_type) {
(0x00 | 0x01): { /* type_parameter_target */
u1 type_parameter_index;
}
(0x10): { /* supertype_target */
u2 supertype_index;
}
(0x11 | 0x12): { /* type_parameter_bound_target */
u1 type_parameter_index;
u1 bound_index;
}
(0x13 | 0x14 | 0x15): { /* empty_target */ }
(0x16): { /* formal_parameter_target */
u1 formal_parameter_index;
}
(0x17): { /* throws_target */
u2 throws_type_index;
}
(0x40 | 0x41): { /* localvar_target */
u2 table_length;
localvar_target_entry table[table_length];
}
(0x42): { /* catch_target */
u2 exception_table_index;
}
(0x43 | 0x44 | 0x45 | 0x46): { /* offset_target */
u2 offset;
}
(0x47 | 0x48 | 0x49 | 0x4A): { /* type_argument_target */
u2 offset;
u1 type_argument_index;
}
}
};
struct type_annotation {
u1 target_type;
target_info<target_type> target_info;
type_path type_path;
annotation annotation [[inline]];
};
struct attribute_runtime_visible_type_annotations {
u2 num_annotations;
type_annotation annotations[num_annotations];
};
struct attribute_runtime_invisible_type_annotations {
u2 num_annotations;
type_annotation annotations[num_annotations];
};
struct attribute_annotation_default {
element_value default_value;
};
struct bootstrap_method {
cp_ref bootstrap_method_ref;
u2 num_bootstrap_arguments;
cp_ref bootstrap_arguments[num_bootstrap_arguments];
};
struct attribute_bootstrap_methods {
u2 num_bootstrap_methods;
bootstrap_method bootstrap_methods[num_bootstrap_methods];
};
struct method_parameter {
u2 name_index [[hidden]];
if (name_index != 0) {
cp_ref name_index @ addressof(name_index);
}
u2 access_flags;
};
struct attribute_method_parameters {
u1 parameters_count;
method_parameter parameters[parameters_count];
};
struct require {
cp_ref require_index;
access_flags_module require_flags;
u2 require_version_index [[hidden]];
if (require_version_index != 0) {
cp_ref require_version_index @ addressof(require_version_index);
}
};
struct export {
cp_ref exports_index;
access_flags_module exports_flags;
u2 exports_to_count;
cp_ref exports_to_index[exports_to_count];
};
struct open {
cp_ref opens_index;
access_flags_module opens_flags;
u2 opens_to_count;
cp_ref opens_to_index[opens_to_count];
};
struct provide {
cp_ref provides_index;
u2 provides_with_count;
cp_ref provides_with_index[provides_with_count];
};
struct attribute_module {
cp_ref module_name_index;
u2 module_flags;
u2 module_version_index [[hidden]];
if (module_version_index != 0) {
cp_ref module_version_index @ addressof(module_version_index);
}
u2 requires_count;
require requires[requires_count];
u2 exports_count;
export exports[exports_count];
u2 opens_count;
open opens[opens_count];
u2 uses_count;
cp_ref uses_index[uses_count];
u2 provides_count;
provide provides[provides_count];
};
struct attribute_module_packages {
u2 package_count;
cp_ref package_index[package_count];
};
struct attribute_module_main_class {
cp_ref main_class_index;
};
struct attribute_nest_host {
cp_ref host_class_index;
};
struct attribute_nest_members {
u2 number_of_classes;
cp_ref classes[number_of_classes];
};
using record_component_info;
struct attribute_record {
u2 component_count;
record_component_info components[component_count];
};
struct attribute_permitted_subclasses {
u2 number_of_classes;
cp_ref classes[number_of_classes];
};
struct attribute_info<auto constant_pool> {
cp_ref attribute_name_index;
u4 attribute_length;
match(constant_pool[attribute_name_index-1].bytes) {
("Code"): attribute_code child [[inline]];
("ConstantValue"): attribute_constant_value [[inline]];
("StackMapTable"): attribute_stack_map_table [[inline]];
("Exceptions"): attribute_exception [[inline]];
("InnerClasses"): attribute_inner_classes [[inline]];
("EnclosingMethod"): attribute_enclosing_method [[inline]];
("Synthetic"): attribute_synthetic [[inline]];
("Signature"): attribute_signature [[inline]];
("SourceFile"): attribute_source_file [[inline]];
("SourceDebugExtension"): attribute_source_debug_extension [[inline]];
("LineNumberTable"): attribute_line_number_table [[inline]];
("LocalVariableTable"): attribute_local_variable_table [[inline]];
("LocalVariableTypeTable"): attribute_local_variable_type_table [[inline]];
("Deprecated"): attribute_deprecated [[inline]];
("RuntimeVisibleAnnotations"): attribute_runtime_visible_annotations [[inline]];
("RuntimeInvisibleAnnotations"): attribute_runtime_invisible_annotations [[inline]];
("RuntimeVisibleParameterAnnotations"): attribute_runtime_visible_parameter_annotations [[inline]];
("RuntimeInvisibleParameterAnnotations"): attribute_runtime_invisible_parameter_annotations [[inline]];
("RuntimeVisibleTypeAnnotations"): attribute_runtime_visible_type_annotations [[inline]];
("RuntimeInvisibleTypeAnnotations"): attribute_runtime_invisible_type_annotations [[inline]];
("AnnotationDefault"): attribute_annotation_default [[inline]];
("BootstrapMethods"): attribute_bootstrap_methods [[inline]];
("MethodParameters"): attribute_method_parameters [[inline]];
("Module"): attribute_module [[inline]];
("ModulePackages"): attribute_module_packages [[inline]];
("ModuleMainClass"): attribute_module_main_class [[inline]];
("NestHost"): attribute_nest_host [[inline]];
("NestMembers"): attribute_nest_members [[inline]];
("Record"): attribute_record [[inline]];
(_): u1 info[attribute_length];
}
if(($-(addressof(this)+6)) != attribute_length) std::warning("Invalid attribute length at "
+ std::format("{:x}", addressof(this))
+ " " + std::string::to_string($-(addressof(this)+6)) + "!=" + std::string::to_string(attribute_length));
} [[format("fmt::attribute")]];
u1 info[attribute_length];
struct record_component_info {
cp_ref name_index;
cp_ref descriptor_index;
u2 attributes_count;
attribute_info<parent.parent.parent.constant_pool> attributes[attributes_count];
};
struct exception {
u2 start_pc;
u2 end_pc;
u2 handler_pc;
u2 catch_type;
} [[static]];
struct attribute_code {
u2 max_stack;
u2 max_locals;
u4 code_length;
u1 code[code_length];
u2 exception_table_length;
exception exception_table[exception_table_length];
u2 attributes_count;
attribute_info<parent.parent.parent.constant_pool> attributes[attributes_count];
};
struct field_info {
access_flags_field access_flags;
u2 name_index;
u2 descriptor_index;
u2 attribute_count;
attribute_info attributes[attribute_count];
access_flags_field access_flags;
cp_ref name_index;
cp_ref descriptor_index;
u2 attribute_count;
attribute_info<parent.constant_pool> attributes[attribute_count];
};
struct method_info {
access_flags_method access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
access_flags_method access_flags;
cp_ref name_index;
cp_ref descriptor_index;
u2 attribute_count;
attribute_info<parent.constant_pool> attributes[attribute_count];
};
struct ClassFile {
u4 magic;
u2 minor_version;
major_version major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count - 1];
access_flags_class access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attribute_count;
attribute_info attributes[attribute_count];
u1 magic[4];
u2 minor_version;
major_version major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
access_flags_class access_flags;
cp_ref this_class;
cp_ref super_class;
u2 interfaces_count;
cp_ref interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info<constant_pool> attributes[attributes_count];
};
ClassFile class_file @ 0x00;
fn main() {
std::assert(class_file.magic == 0xCAFEBABE, "File is not a valid Java Class file! Invalid header magic");
std::print("Fields:");
for (le u16 i = 0, i < class_file.fields_count, i = i + 1) {
str method_string = " ";
if (class_file.fields[i].access_flags.ACC_PUBLIC)
method_string = method_string + "public ";
if (class_file.fields[i].access_flags.ACC_PRIVATE)
method_string = method_string + "private ";
if (class_file.fields[i].access_flags.ACC_PROTECTED)
method_string = method_string + "protected ";
if (class_file.fields[i].access_flags.ACC_STATIC)
method_string = method_string + "static ";
if (class_file.fields[i].access_flags.ACC_FINAL)
method_string = method_string + "final ";
if (class_file.fields[i].access_flags.ACC_VOLATILE)
method_string = method_string + "volatile ";
if (class_file.fields[i].access_flags.ACC_NATIVE)
method_string = method_string + "native ";
if (class_file.fields[i].access_flags.ACC_TRANSIENT)
method_string = method_string + "transient ";
if (class_file.fields[i].access_flags.ACC_ENUM)
method_string = method_string + "enum ";
method_string = method_string + class_file.constant_pool[class_file.fields[i].name_index - 1].info.bytes;
method_string = method_string + " [ " + class_file.constant_pool[class_file.fields[i].descriptor_index - 1].info.bytes + " ]";
std::print("{}", method_string);
}
std::print("Methods:");
for (le u16 i = 0, i < class_file.methods_count, i = i + 1) {
str method_string = " ";
if (class_file.methods[i].access_flags.ACC_PUBLIC)
method_string = method_string + "public ";
if (class_file.methods[i].access_flags.ACC_PRIVATE)
method_string = method_string + "private ";
if (class_file.methods[i].access_flags.ACC_PROTECTED)
method_string = method_string + "protected ";
if (class_file.methods[i].access_flags.ACC_STATIC)
method_string = method_string + "static ";
if (class_file.methods[i].access_flags.ACC_FINAL)
method_string = method_string + "final ";
if (class_file.methods[i].access_flags.ACC_SYNCHRONIZED)
method_string = method_string + "synchronized ";
if (class_file.methods[i].access_flags.ACC_NATIVE)
method_string = method_string + "native ";
if (class_file.methods[i].access_flags.ACC_ABSTRACT)
method_string = method_string + "abstract ";
if (class_file.methods[i].access_flags.ACC_STRICT)
method_string = method_string + "strictfp ";
method_string = method_string + class_file.constant_pool[class_file.methods[i].name_index - 1].info.bytes;
method_string = method_string + " [ " + class_file.constant_pool[class_file.methods[i].descriptor_index - 1].info.bytes + " ]";
std::print("{}", method_string);
}
std::print("Class Attributes:");
for (le u16 i = 0, i < class_file.attribute_count, i = i + 1) {
std::print(" {}", class_file.constant_pool[class_file.attributes[i].attribute_name_info - 1].info.bytes);
}
};
ClassFile file @ 0x0;

122
patterns/jpeg.hexpat Normal file
View File

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

View File

@@ -1,459 +1,462 @@
#pragma MIME application/x-ms-shortcut
#include <type/guid.pat>
#include <type/size.pat>
bitfield LinkFlags {
HasLinkTargetIDList : 1;
HasLinkInfo : 1;
HasName : 1;
HasRelativePath : 1;
HasWorkingDir : 1;
HasArguments : 1;
HasIconLocation : 1;
IsUnicode : 1;
ForceNoLinkInfo : 1;
HasExpString : 1;
RunInSeparateProcess : 1;
padding : 1;
HasDarwinID : 1;
RunAsUser : 1;
HasExpIcon : 1;
NoPidlAlias : 1;
padding : 1;
RunWithShimLayer : 1;
ForceNoLinkTrack : 1;
EnableTargetMetadata : 1;
DisableLinkPathTracking : 1;
DisableKnownFolderTracking : 1;
DisableKnownFolderAlias : 1;
AllowLinkToLink : 1;
UnaliasOnSave : 1;
PreferEnvironmentPath : 1;
KeepLocalIDListForUNCTarget : 1;
padding : 5;
} [[right_to_left]];
bitfield FileAttributesFlags {
FILE_ATTRIBUTE_READONLY : 1;
FILE_ATTRIBUTE_HIDDEN : 1;
FILE_ATTRIBUTE_SYSTEM : 1;
padding : 1;
FILE_ATTRIBUTE_DIRECTORY : 1;
FILE_ATTRIBUTE_ARCHIVE : 1;
padding : 1;
FILE_ATTRIBUTE_NORMAL : 1;
FILE_ATTRIBUTE_TEMPORARY : 1;
FILE_ATTRIBUTE_SPARSE_FILE : 1;
FILE_ATTRIBUTE_REPARSE_POINT : 1;
FILE_ATTRIBUTE_COMPRESSED : 1;
FILE_ATTRIBUTE_OFFLINE : 1;
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED : 1;
FILE_ATTRIBUTE_ENCRYPTED : 1;
padding : 17;
} [[right_to_left]];
bitfield ModifierKeys {
HOTKEYF_SHIFT : 1;
HOTKEYF_CONTROL : 1;
HOTKEYF_ALT : 1;
padding : 5;
} [[right_to_left]];
enum Keys : u8 {
KEY_NONE = 0x00,
KEY_0 = 0x30,
KEY_1 = 0x31,
KEY_2 = 0x32,
KEY_3 = 0x33,
KEY_4 = 0x34,
KEY_5 = 0x35,
KEY_6 = 0x36,
KEY_7 = 0x37,
KEY_8 = 0x38,
KEY_9 = 0x39,
KEY_A = 0x41,
KEY_B = 0x42,
KEY_C = 0x43,
KEY_D = 0x44,
KEY_E = 0x45,
KEY_F = 0x46,
KEY_G = 0x47,
KEY_H = 0x48,
KEY_I = 0x49,
KEY_J = 0x4A,
KEY_K = 0x4B,
KEY_L = 0x4C,
KEY_M = 0x4D,
KEY_N = 0x4E,
KEY_O = 0x4F,
KEY_P = 0x50,
KEY_Q = 0x51,
KEY_R = 0x52,
KEY_S = 0x53,
KEY_T = 0x54,
KEY_U = 0x55,
KEY_V = 0x56,
KEY_W = 0x57,
KEY_X = 0x58,
KEY_Y = 0x59,
KEY_Z = 0x5A,
VK_F1 = 0x70,
VK_F2 = 0x71,
VK_F3 = 0x72,
VK_F4 = 0x73,
VK_F5 = 0x74,
VK_F6 = 0x75,
VK_F7 = 0x76,
VK_F8 = 0x77,
VK_F9 = 0x78,
VK_F10 = 0x79,
VK_F11 = 0x7A,
VK_F12 = 0x7B,
VK_F13 = 0x7C,
VK_F14 = 0x7D,
VK_F15 = 0x7E,
VK_F16 = 0x7F,
VK_F17 = 0x80,
VK_F18 = 0x81,
VK_F19 = 0x82,
VK_F20 = 0x83,
VK_F21 = 0x84,
VK_F22 = 0x85,
VK_F23 = 0x86,
VK_F24 = 0x87,
VK_NUMLOCK = 0x90,
VK_SCROLL = 0x91,
};
struct HotKeyFlags {
Keys Key;
ModifierKeys ModifierKeys;
};
struct FILETIME {
u32 dwLowDateTime;
u32 dwHighDateTime;
};
enum SHOWWINDOW_FLAGS : u32 {
SW_SHOWNORMAL = 0x00000001,
SW_SHOWMAXIMIZED = 0x00000003,
SW_SHOWMINNOACTIVE = 0x00000007
};
struct ShellLinkHeader {
type::Size32 HeaderSize;
type::GUID LinkCLSID;
LinkFlags LinkFlags;
FileAttributesFlags FileAttributes;
FILETIME CreationTime, AccessTime, WriteTime;
type::Size32 FileSize;
u32 IconIndex;
SHOWWINDOW_FLAGS ShowCommand;
HotKeyFlags HotKey;
padding[2];
padding[4];
padding[4];
};
struct ItemID {
type::Size16 ItemIDSize;
if (ItemIDSize == 0x00)
break;
else
u8 Data[ItemIDSize - sizeof(ItemIDSize)];
};
struct IDList {
ItemID ItemIDList[while(true)];
};
struct LinkTargetIDList {
type::Size16 IDListSize;
IDList IDList[while($ < (addressof(IDListSize) + IDListSize))];
};
bitfield LinkInfoFlags {
VolumeIDAndLocalBasePath : 1;
CommonNetworkRelativeLinkAndPathSuffix : 1;
padding : 30;
};
enum DriveType : u32 {
DRIVE_UNKNOWN = 0x00000000,
DRIVE_NO_ROOT_DIR = 0x00000001,
DRIVE_REMOVABLE = 0x00000002,
DRIVE_FIXED = 0x00000003,
DRIVE_REMOTE = 0x00000004,
DRIVE_CDROM = 0x00000005,
DRIVE_RAMDISK = 0x00000006
};
struct VolumeID {
type::Size32 VolumeIDSize;
DriveType DriveType;
u32 DriveSerialNumber;
u32 VolumeLabelOffset;
if (VolumeLabelOffset == 0x14)
u32 VolumeLabelOffsetUnicode;
char Data[VolumeIDSize - ($ - addressof(this))];
};
bitfield CommonNetworkRelativeLinkFlags {
ValidDevice : 1;
ValidNetType : 1;
padding : 30;
} [[right_to_left]];
enum NetworkProviderType : u32 {
WNNC_NET_AVID = 0x001A0000,
WNNC_NET_DOCUSPACE = 0x001B0000,
WNNC_NET_MANGOSOFT = 0x001C0000,
WNNC_NET_SERNET = 0x001D0000,
WNNC_NET_RIVERFRONT1 = 0x001E0000,
WNNC_NET_RIVERFRONT2 = 0x001F0000,
WNNC_NET_DECORB = 0x00200000,
WNNC_NET_PROTSTOR = 0x00210000,
WNNC_NET_FJ_REDIR = 0x00220000,
WNNC_NET_DISTINCT = 0x00230000,
WNNC_NET_TWINS = 0x00240000,
WNNC_NET_RDR2SAMPLE = 0x00250000,
WNNC_NET_CSC = 0x00260000,
WNNC_NET_3IN1 = 0x00270000,
WNNC_NET_EXTENDNET = 0x00290000,
WNNC_NET_STAC = 0x002A0000,
WNNC_NET_FOXBAT = 0x002B0000,
WNNC_NET_YAHOO = 0x002C0000,
WNNC_NET_EXIFS = 0x002D0000,
WNNC_NET_DAV = 0x002E0000,
WNNC_NET_KNOWARE = 0x002F0000,
WNNC_NET_OBJECT_DIRE = 0x00300000,
WNNC_NET_MASFAX = 0x00310000,
WNNC_NET_HOB_NFS = 0x00320000,
WNNC_NET_SHIVA = 0x00330000,
WNNC_NET_IBMAL = 0x00340000,
WNNC_NET_LOCK = 0x00350000,
WNNC_NET_TERMSRV = 0x00360000,
WNNC_NET_SRT = 0x00370000,
WNNC_NET_QUINCY = 0x00380000,
WNNC_NET_OPENAFS = 0x00390000,
WNNC_NET_AVID1 = 0x003A0000,
WNNC_NET_DFS = 0x003B0000,
WNNC_NET_KWNP = 0x003C0000,
WNNC_NET_ZENWORKS = 0x003D0000,
WNNC_NET_DRIVEONWEB = 0x003E0000,
WNNC_NET_VMWARE = 0x003F0000,
WNNC_NET_RSFX = 0x00400000,
WNNC_NET_MFILES = 0x00410000,
WNNC_NET_MS_NFS = 0x00420000,
WNNC_NET_GOOGLE = 0x00430000
};
struct CommonNetworkRelativeLink {
type::Size32 CommonNetworkRelativeLinkSize;
CommonNetworkRelativeLinkFlags CommonNetworkRelativeLinkFlags;
u32 NetNameOffset;
u32 DeviceNameOffset;
NetworkProviderType NetworkProviderType;
if (NetNameOffset > 0x14) {
u32 NetNameOffsetUnicode;
u32 DeviceNameOffsetUnicode;
}
char NetName[];
char DeviceName[];
if (NetNameOffset > 0x14) {
char16 NetNameUnicode[];
char16 DeviceNameUnicode[];
}
};
struct LinkInfo {
type::Size32 LinkInfoSize;
type::Size32 LinkInfoHeaderSize;
LinkInfoFlags LinkInfoFlags;
u32 VolumeIDOffset;
u32 LocalBasePathOffset;
u32 CommonNetworkRelativeLinkOffset;
u32 CommonPathSuffixOffset;
if (LinkInfoHeaderSize >= 0x24) {
u32 LocalBasePathOffsetUnicode;
u32 CommonPathSuffixOffsetUnicode;
}
if (LinkInfoFlags.VolumeIDAndLocalBasePath) {
VolumeID VolumeID;
char LocalBasePath[];
}
if (LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix)
CommonNetworkRelativeLink CommonNetworkRelativeLink;
char CommonPathSuffix[];
if (LinkInfoHeaderSize >= 0x24) {
if (LinkInfoFlags.VolumeIDAndLocalBasePath)
char16 LocalBasePathUnicode[];
char16 CommonPathSuffixUnicode[];
}
};
struct String {
u16 CountCharacters;
char16 String[CountCharacters];
};
struct StringData {
if (parent.ShellLinkHeader.LinkFlags.HasName)
String NAME_STRING;
if (parent.ShellLinkHeader.LinkFlags.HasRelativePath)
String RELATIVE_PATH;
if (parent.ShellLinkHeader.LinkFlags.HasWorkingDir)
String WORKING_DIR;
if (parent.ShellLinkHeader.LinkFlags.HasArguments)
String COMMAND_LINE_ARGUMENTS;
if (parent.ShellLinkHeader.LinkFlags.HasIconLocation)
String ICON_LOCATION;
};
bitfield FillAttributes {
FOREGROUND_BLUE : 1;
FOREGROUND_GREEN : 1;
FOREGROUND_RED : 1;
FOREGROUND_INTENSITY : 1;
BACKGROUND_BLUE : 1;
BACKGROUND_GREEN : 1;
BACKGROUND_RED : 1;
BACKGROUND_INTENSITY : 1;
padding : 8;
} [[right_to_left]];
struct ConsoleDataBlock {
FillAttributes FillAttributes;
FillAttributes PopupFillAttributes;
u16 ScreenBufferSizeX, ScreenBufferSizeY;
u16 WindowSizeX, WindowSizeY;
u16 WindowOriginX, WindowOriginY;
padding[4];
padding[4];
u32 FontSize;
u32 FontFamily;
u32 FontWeight;
char16 FaceName[32];
u32 CursorSize;
u32 FullScreen;
u32 QuickEdit;
u32 InsertMode;
u32 AutoPosition;
u32 HistoryBufferSize;
u32 NumberOfHistoryBuffers;
u32 HistoryNoDup;
u32 ColorTable[16];
};
struct ConsoleFEDataBlock {
u32 CodePage;
};
struct DarwinDataBlock {
char DarwinDataAnsi[260];
char16 DarwinDataUnicode[260];
};
struct EnvironmentVariableDataBlock {
char TargetAnsi[260];
char16 TargetUnicode[260];
};
struct IconEnvironmentDataBlock {
char TargetAnsi[260];
char16 TargetUnicode[260];
};
struct KnownFolderDataBlock {
type::GUID KnownFolderID;
u32 Offset;
};
struct PropertyStoreDataBlock {
u8 Bytes[parent.BlockSize - sizeof(parent.BlockSize) - sizeof(parent.BlockSignature)];
std::warning("PropertyStoreDataBlock is not yet implemented!");
};
struct ShimDataBlock {
char16 LayerName[(parent.BlockSize - sizeof(parent.BlockSize) - sizeof(parent.BlockSignature)) / sizeof(char16)];
};
struct SpecialFolderDataBlock {
u32 SpecialFolderID;
u32 Offset;
};
struct TrackerDataBlock {
type::Size32 Length;
u32 Version;
char MachineID[16];
type::GUID Droid[2];
type::GUID DroidBirth[2];
};
struct VistaAndAboveIDListDataBlock {
IDList IDList;
};
struct ExtraDataBlock {
type::Size32 BlockSize;
if (BlockSize < 0x04)
break;
else {
u32 BlockSignature;
if (BlockSignature == 0xA000'0002)
ConsoleDataBlock CONSOLE_PROPS;
else if (BlockSignature == 0xA000'0004)
ConsoleFEDataBlock CONSOLE_FE_PROPS;
else if (BlockSignature == 0xA000'0006)
DarwinDataBlock DARWIN_PROPS;
else if (BlockSignature == 0xA000'0001)
EnvironmentVariableDataBlock ENVIRONMENT_PROPS;
else if (BlockSignature == 0xA000'0007)
IconEnvironmentDataBlock ICON_ENVIRONMENT_PROPS;
else if (BlockSignature == 0xA000'000B)
KnownFolderDataBlock KNOWN_FOLDER_PROPS;
else if (BlockSignature == 0xA000'0009)
PropertyStoreDataBlock PROPERTY_STORE_PROPS;
else if (BlockSignature == 0xA000'0008)
ShimDataBlock SHIM_PROPS;
else if (BlockSignature == 0xA000'0005)
SpecialFolderDataBlock SPECIAL_FOLDER_PROPS;
else if (BlockSignature == 0xA000'0003)
TrackerDataBlock TRACKER_PROPS;
else if (BlockSignature == 0xA000'000C)
VistaAndAboveIDListDataBlock VISTA_AND_ABOVE_IDLIST_PROPS;
}
};
struct ExtraData {
ExtraDataBlock ExtraDataBlock[while(true)];
};
struct LNK {
ShellLinkHeader ShellLinkHeader;
if (ShellLinkHeader.LinkFlags.HasLinkTargetIDList)
LinkTargetIDList LinkTargetIDList;
if (ShellLinkHeader.LinkFlags.HasLinkInfo)
LinkInfo LinkInfo;
StringData StringData;
ExtraData ExtraData;
};
LNK lnk @ 0x00;
#pragma MIME application/x-ms-shortcut
#include <std/core.pat>
#include <type/guid.pat>
#include <type/size.pat>
using BitfieldOrder = std::core::BitfieldOrder;
bitfield LinkFlags {
HasLinkTargetIDList : 1;
HasLinkInfo : 1;
HasName : 1;
HasRelativePath : 1;
HasWorkingDir : 1;
HasArguments : 1;
HasIconLocation : 1;
IsUnicode : 1;
ForceNoLinkInfo : 1;
HasExpString : 1;
RunInSeparateProcess : 1;
padding : 1;
HasDarwinID : 1;
RunAsUser : 1;
HasExpIcon : 1;
NoPidlAlias : 1;
padding : 1;
RunWithShimLayer : 1;
ForceNoLinkTrack : 1;
EnableTargetMetadata : 1;
DisableLinkPathTracking : 1;
DisableKnownFolderTracking : 1;
DisableKnownFolderAlias : 1;
AllowLinkToLink : 1;
UnaliasOnSave : 1;
PreferEnvironmentPath : 1;
KeepLocalIDListForUNCTarget : 1;
padding : 5;
};
bitfield FileAttributesFlags {
FILE_ATTRIBUTE_READONLY : 1;
FILE_ATTRIBUTE_HIDDEN : 1;
FILE_ATTRIBUTE_SYSTEM : 1;
padding : 1;
FILE_ATTRIBUTE_DIRECTORY : 1;
FILE_ATTRIBUTE_ARCHIVE : 1;
padding : 1;
FILE_ATTRIBUTE_NORMAL : 1;
FILE_ATTRIBUTE_TEMPORARY : 1;
FILE_ATTRIBUTE_SPARSE_FILE : 1;
FILE_ATTRIBUTE_REPARSE_POINT : 1;
FILE_ATTRIBUTE_COMPRESSED : 1;
FILE_ATTRIBUTE_OFFLINE : 1;
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED : 1;
FILE_ATTRIBUTE_ENCRYPTED : 1;
padding : 17;
};
bitfield ModifierKeys {
HOTKEYF_SHIFT : 1;
HOTKEYF_CONTROL : 1;
HOTKEYF_ALT : 1;
padding : 5;
};
enum Keys : u8 {
KEY_NONE = 0x00,
KEY_0 = 0x30,
KEY_1 = 0x31,
KEY_2 = 0x32,
KEY_3 = 0x33,
KEY_4 = 0x34,
KEY_5 = 0x35,
KEY_6 = 0x36,
KEY_7 = 0x37,
KEY_8 = 0x38,
KEY_9 = 0x39,
KEY_A = 0x41,
KEY_B = 0x42,
KEY_C = 0x43,
KEY_D = 0x44,
KEY_E = 0x45,
KEY_F = 0x46,
KEY_G = 0x47,
KEY_H = 0x48,
KEY_I = 0x49,
KEY_J = 0x4A,
KEY_K = 0x4B,
KEY_L = 0x4C,
KEY_M = 0x4D,
KEY_N = 0x4E,
KEY_O = 0x4F,
KEY_P = 0x50,
KEY_Q = 0x51,
KEY_R = 0x52,
KEY_S = 0x53,
KEY_T = 0x54,
KEY_U = 0x55,
KEY_V = 0x56,
KEY_W = 0x57,
KEY_X = 0x58,
KEY_Y = 0x59,
KEY_Z = 0x5A,
VK_F1 = 0x70,
VK_F2 = 0x71,
VK_F3 = 0x72,
VK_F4 = 0x73,
VK_F5 = 0x74,
VK_F6 = 0x75,
VK_F7 = 0x76,
VK_F8 = 0x77,
VK_F9 = 0x78,
VK_F10 = 0x79,
VK_F11 = 0x7A,
VK_F12 = 0x7B,
VK_F13 = 0x7C,
VK_F14 = 0x7D,
VK_F15 = 0x7E,
VK_F16 = 0x7F,
VK_F17 = 0x80,
VK_F18 = 0x81,
VK_F19 = 0x82,
VK_F20 = 0x83,
VK_F21 = 0x84,
VK_F22 = 0x85,
VK_F23 = 0x86,
VK_F24 = 0x87,
VK_NUMLOCK = 0x90,
VK_SCROLL = 0x91,
};
struct HotKeyFlags {
Keys Key;
ModifierKeys ModifierKeys;
};
struct FILETIME {
u32 dwLowDateTime;
u32 dwHighDateTime;
};
enum SHOWWINDOW_FLAGS : u32 {
SW_SHOWNORMAL = 0x00000001,
SW_SHOWMAXIMIZED = 0x00000003,
SW_SHOWMINNOACTIVE = 0x00000007
};
struct ShellLinkHeader {
type::Size32 HeaderSize;
type::GUID LinkCLSID;
LinkFlags LinkFlags;
FileAttributesFlags FileAttributes;
FILETIME CreationTime, AccessTime, WriteTime;
type::Size32 FileSize;
u32 IconIndex;
SHOWWINDOW_FLAGS ShowCommand;
HotKeyFlags HotKey;
padding[2];
padding[4];
padding[4];
};
struct ItemID {
type::Size16 ItemIDSize;
if (ItemIDSize == 0x00)
break;
else
u8 Data[ItemIDSize - sizeof(ItemIDSize)];
};
struct IDList {
ItemID ItemIDList[while(true)];
};
struct LinkTargetIDList {
type::Size16 IDListSize;
IDList IDList[while($ < (addressof(IDListSize) + IDListSize))];
};
bitfield LinkInfoFlags {
VolumeIDAndLocalBasePath : 1;
CommonNetworkRelativeLinkAndPathSuffix : 1;
padding : 30;
};
enum DriveType : u32 {
DRIVE_UNKNOWN = 0x00000000,
DRIVE_NO_ROOT_DIR = 0x00000001,
DRIVE_REMOVABLE = 0x00000002,
DRIVE_FIXED = 0x00000003,
DRIVE_REMOTE = 0x00000004,
DRIVE_CDROM = 0x00000005,
DRIVE_RAMDISK = 0x00000006
};
struct VolumeID {
type::Size32 VolumeIDSize;
DriveType DriveType;
u32 DriveSerialNumber;
u32 VolumeLabelOffset;
if (VolumeLabelOffset == 0x14)
u32 VolumeLabelOffsetUnicode;
char Data[VolumeIDSize - ($ - addressof(this))];
};
bitfield CommonNetworkRelativeLinkFlags {
ValidDevice : 1;
ValidNetType : 1;
padding : 30;
};
enum NetworkProviderType : u32 {
WNNC_NET_AVID = 0x001A0000,
WNNC_NET_DOCUSPACE = 0x001B0000,
WNNC_NET_MANGOSOFT = 0x001C0000,
WNNC_NET_SERNET = 0x001D0000,
WNNC_NET_RIVERFRONT1 = 0x001E0000,
WNNC_NET_RIVERFRONT2 = 0x001F0000,
WNNC_NET_DECORB = 0x00200000,
WNNC_NET_PROTSTOR = 0x00210000,
WNNC_NET_FJ_REDIR = 0x00220000,
WNNC_NET_DISTINCT = 0x00230000,
WNNC_NET_TWINS = 0x00240000,
WNNC_NET_RDR2SAMPLE = 0x00250000,
WNNC_NET_CSC = 0x00260000,
WNNC_NET_3IN1 = 0x00270000,
WNNC_NET_EXTENDNET = 0x00290000,
WNNC_NET_STAC = 0x002A0000,
WNNC_NET_FOXBAT = 0x002B0000,
WNNC_NET_YAHOO = 0x002C0000,
WNNC_NET_EXIFS = 0x002D0000,
WNNC_NET_DAV = 0x002E0000,
WNNC_NET_KNOWARE = 0x002F0000,
WNNC_NET_OBJECT_DIRE = 0x00300000,
WNNC_NET_MASFAX = 0x00310000,
WNNC_NET_HOB_NFS = 0x00320000,
WNNC_NET_SHIVA = 0x00330000,
WNNC_NET_IBMAL = 0x00340000,
WNNC_NET_LOCK = 0x00350000,
WNNC_NET_TERMSRV = 0x00360000,
WNNC_NET_SRT = 0x00370000,
WNNC_NET_QUINCY = 0x00380000,
WNNC_NET_OPENAFS = 0x00390000,
WNNC_NET_AVID1 = 0x003A0000,
WNNC_NET_DFS = 0x003B0000,
WNNC_NET_KWNP = 0x003C0000,
WNNC_NET_ZENWORKS = 0x003D0000,
WNNC_NET_DRIVEONWEB = 0x003E0000,
WNNC_NET_VMWARE = 0x003F0000,
WNNC_NET_RSFX = 0x00400000,
WNNC_NET_MFILES = 0x00410000,
WNNC_NET_MS_NFS = 0x00420000,
WNNC_NET_GOOGLE = 0x00430000
};
struct CommonNetworkRelativeLink {
type::Size32 CommonNetworkRelativeLinkSize;
CommonNetworkRelativeLinkFlags CommonNetworkRelativeLinkFlags;
u32 NetNameOffset;
u32 DeviceNameOffset;
NetworkProviderType NetworkProviderType;
if (NetNameOffset > 0x14) {
u32 NetNameOffsetUnicode;
u32 DeviceNameOffsetUnicode;
}
char NetName[];
char DeviceName[];
if (NetNameOffset > 0x14) {
char16 NetNameUnicode[];
char16 DeviceNameUnicode[];
}
};
struct LinkInfo {
type::Size32 LinkInfoSize;
type::Size32 LinkInfoHeaderSize;
LinkInfoFlags LinkInfoFlags;
u32 VolumeIDOffset;
u32 LocalBasePathOffset;
u32 CommonNetworkRelativeLinkOffset;
u32 CommonPathSuffixOffset;
if (LinkInfoHeaderSize >= 0x24) {
u32 LocalBasePathOffsetUnicode;
u32 CommonPathSuffixOffsetUnicode;
}
if (LinkInfoFlags.VolumeIDAndLocalBasePath) {
VolumeID VolumeID;
char LocalBasePath[];
}
if (LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix)
CommonNetworkRelativeLink CommonNetworkRelativeLink;
char CommonPathSuffix[];
if (LinkInfoHeaderSize >= 0x24) {
if (LinkInfoFlags.VolumeIDAndLocalBasePath)
char16 LocalBasePathUnicode[];
char16 CommonPathSuffixUnicode[];
}
};
struct String {
u16 CountCharacters;
char16 String[CountCharacters];
};
struct StringData {
if (parent.ShellLinkHeader.LinkFlags.HasName)
String NAME_STRING;
if (parent.ShellLinkHeader.LinkFlags.HasRelativePath)
String RELATIVE_PATH;
if (parent.ShellLinkHeader.LinkFlags.HasWorkingDir)
String WORKING_DIR;
if (parent.ShellLinkHeader.LinkFlags.HasArguments)
String COMMAND_LINE_ARGUMENTS;
if (parent.ShellLinkHeader.LinkFlags.HasIconLocation)
String ICON_LOCATION;
};
bitfield FillAttributes {
FOREGROUND_BLUE : 1;
FOREGROUND_GREEN : 1;
FOREGROUND_RED : 1;
FOREGROUND_INTENSITY : 1;
BACKGROUND_BLUE : 1;
BACKGROUND_GREEN : 1;
BACKGROUND_RED : 1;
BACKGROUND_INTENSITY : 1;
padding : 8;
};
struct ConsoleDataBlock {
FillAttributes FillAttributes;
FillAttributes PopupFillAttributes;
u16 ScreenBufferSizeX, ScreenBufferSizeY;
u16 WindowSizeX, WindowSizeY;
u16 WindowOriginX, WindowOriginY;
padding[4];
padding[4];
u32 FontSize;
u32 FontFamily;
u32 FontWeight;
char16 FaceName[32];
u32 CursorSize;
u32 FullScreen;
u32 QuickEdit;
u32 InsertMode;
u32 AutoPosition;
u32 HistoryBufferSize;
u32 NumberOfHistoryBuffers;
u32 HistoryNoDup;
u32 ColorTable[16];
};
struct ConsoleFEDataBlock {
u32 CodePage;
};
struct DarwinDataBlock {
char DarwinDataAnsi[260];
char16 DarwinDataUnicode[260];
};
struct EnvironmentVariableDataBlock {
char TargetAnsi[260];
char16 TargetUnicode[260];
};
struct IconEnvironmentDataBlock {
char TargetAnsi[260];
char16 TargetUnicode[260];
};
struct KnownFolderDataBlock {
type::GUID KnownFolderID;
u32 Offset;
};
struct PropertyStoreDataBlock {
u8 Bytes[parent.BlockSize - sizeof(parent.BlockSize) - sizeof(parent.BlockSignature)];
std::warning("PropertyStoreDataBlock is not yet implemented!");
};
struct ShimDataBlock {
char16 LayerName[(parent.BlockSize - sizeof(parent.BlockSize) - sizeof(parent.BlockSignature)) / sizeof(char16)];
};
struct SpecialFolderDataBlock {
u32 SpecialFolderID;
u32 Offset;
};
struct TrackerDataBlock {
type::Size32 Length;
u32 Version;
char MachineID[16];
type::GUID Droid[2];
type::GUID DroidBirth[2];
};
struct VistaAndAboveIDListDataBlock {
IDList IDList;
};
struct ExtraDataBlock {
type::Size32 BlockSize;
if (BlockSize < 0x04)
break;
else {
u32 BlockSignature;
if (BlockSignature == 0xA000'0002)
ConsoleDataBlock CONSOLE_PROPS;
else if (BlockSignature == 0xA000'0004)
ConsoleFEDataBlock CONSOLE_FE_PROPS;
else if (BlockSignature == 0xA000'0006)
DarwinDataBlock DARWIN_PROPS;
else if (BlockSignature == 0xA000'0001)
EnvironmentVariableDataBlock ENVIRONMENT_PROPS;
else if (BlockSignature == 0xA000'0007)
IconEnvironmentDataBlock ICON_ENVIRONMENT_PROPS;
else if (BlockSignature == 0xA000'000B)
KnownFolderDataBlock KNOWN_FOLDER_PROPS;
else if (BlockSignature == 0xA000'0009)
PropertyStoreDataBlock PROPERTY_STORE_PROPS;
else if (BlockSignature == 0xA000'0008)
ShimDataBlock SHIM_PROPS;
else if (BlockSignature == 0xA000'0005)
SpecialFolderDataBlock SPECIAL_FOLDER_PROPS;
else if (BlockSignature == 0xA000'0003)
TrackerDataBlock TRACKER_PROPS;
else if (BlockSignature == 0xA000'000C)
VistaAndAboveIDListDataBlock VISTA_AND_ABOVE_IDLIST_PROPS;
}
};
struct ExtraData {
ExtraDataBlock ExtraDataBlock[while(true)];
};
struct LNK {
ShellLinkHeader ShellLinkHeader;
if (ShellLinkHeader.LinkFlags.HasLinkTargetIDList)
LinkTargetIDList LinkTargetIDList;
if (ShellLinkHeader.LinkFlags.HasLinkInfo)
LinkInfo LinkInfo;
StringData StringData;
ExtraData ExtraData;
};
LNK lnk @ 0x00;

135
patterns/lua54.hexpat Normal file
View File

@@ -0,0 +1,135 @@
#include <std/io.pat>
#include <std/mem.pat>
namespace impl {
fn transform_Size_array(auto array) {
u128 res = 0;
for(u8 i = 0, (array[i] & 0x80 == 0) && (i < 9), i+=1) {
res <<= 7;
res |= array[i] & 0x7f;
}
res <<= 7;
res |= array[sizeof(array)-1] & 0x7f;
return res;
};
fn format_Size(auto leb128) {
u128 res = impl::transform_Size_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_Size(auto leb128) {
return impl::transform_Size_array(leb128.array);
};
fn format_LuaString(auto string) {
if (string.size == 0) {
return "None";
}
return std::format("\"{}\"", string.data);
};
fn format_Constant(auto const) {
return const.data;
};
fn format_Version(auto ver) {
return std::format("Ver. {}.{}", ver.major, ver.minor);
};
}
using LuaFunction;
struct Size {
u8 array[while(addressof(this) == $ || ((addressof(this)-$ < 9) && (std::mem::read_unsigned($-1, 1) & 0x80 == 0)))] [[hidden]];
} [[sealed, format("impl::format_Size"), transform("impl::transform_Size")]];
bitfield Version {
minor : 4;
major : 4;
} [[format("impl::format_Version")]];
struct LuaBinaryHeader {
u32 magic;
Version version_number;
u8 format_version;
u8 error_detection_data[6];
u8 size_of_int;
u8 size_of_size_t;
u8 size_of_number;
u64 luac_int;
double luac_num;
};
struct LuaString {
Size size;
if (size > 0) {
char data[size-1];
}
}[[format("impl::format_LuaString")]];
struct LuaConstant {
u8 type;
if (type == 3) {
u64 data;
} else if (type == 0x13) {
double data;
} else if (type == 0x4 || type == 0x14) {
LuaString data;
}
}[[format("impl::format_Constant")]];
struct LuaUpvalue {
u8 instack;
u8 idx;
u8 kind;
};
struct Vector<T> {
Size size;
T values[size];
};
struct AbsLineInfo {
Size pc;
Size line;
};
struct LocalVar {
LuaString varname;
Size startpc;
Size endpc;
};
struct LuaDebugInfo {
Vector<s8> lineInfo;
Vector<AbsLineInfo> abslineinfo;
Vector<LocalVar> local_vars;
Vector<LuaString> upvalues;
};
struct LuaFunction {
LuaString source;
Size line_defined;
Size last_line_defined;
u8 number_of_parameters;
u8 is_vararg;
u8 maxstacksize;
Vector<u32> code;
Vector<LuaConstant> constants;
Vector<LuaUpvalue> upvalues;
Vector<LuaFunction> protos;
LuaDebugInfo debugInfo;
};
struct LuaFile {
LuaBinaryHeader header;
u8 size_of_upvalues;
LuaFunction func;
};
LuaFile file @ 0;

383
patterns/macho.hexpat Normal file
View File

@@ -0,0 +1,383 @@
#pragma MIME application/x-mach-binary
#include <type/size.pat>
enum Magic : u32 {
_32BitMagic = 0xFEEDFACE,
_64BitMagic = 0xFEEDFACF
};
enum CpuType : u32 {
VAX = 1,
ROMP = 2,
BS32032 = 4,
BS32332 = 5,
MC680x0 = 6,
I386 = 7,
X86_64 = CpuType::I386 | 0x100'0000,
MIPS = 8,
NS32532 = 9,
HPPA = 11,
ARM = 12,
MC88000 = 13,
SPARC = 14,
I860 = be u32(15),
I860_LITTLE = 16,
RS6000 = 17,
MC980000 = 18,
POWERPC = 18,
POWERPC64 = CpuType::POWERPC | 0x100'0000,
VEO = 255
};
enum SubCpuTypeVAX : u24 {
ALL = 0,
VAX780 = 1,
VAX785 = 2,
VAX750 = 3,
VAX730 = 4,
UVAXI = 5,
UVAXII = 6,
VAX8200 = 7,
VAX8500 = 8,
VAX8600 = 9,
VAX8650 = 10,
VAX8800 = 11,
UVAXIII = 12
};
enum SubCpuTypeROMP : u24 {
ALL = 0,
PC = 1,
APC = 2,
_135 = 3
};
enum SubCpuType32XXX : u24 {
ALL = 0,
MMAX_DPC = 1,
SQT = 2,
MMAX_APC_FPU = 3,
MMAX_APC_FPA = 4,
MMAX_XPC = 5
};
enum SubCpuTypeI386 : u24 {
_386 = 3,
_486 = 4,
_486SX = SubCpuTypeI386::_486 + 128,
_586 = 5,
IntelPentium = 5 + (0 << 4),
IntelPentiumPro = 6 + (1 << 4),
IntelPentiumIIM3 = 6 + (3 << 4),
IntelPentiumIIM5 = 6 + (5 << 4),
IntelPentium4 = 10 + (0 << 4),
};
enum SubCpuTypeMips : u24 {
ALL = 0,
R2300 = 1,
R2600 = 2,
R2800 = 3,
R2000a = 4
};
enum SubCpuType680x0 : u24 {
ALL = 1,
MC68030 = 1,
MC68040 = 2,
MC68030_Only = 3
};
enum SubCpuTypeHPPA : u24 {
ALL = 0,
_7100 = 0,
_7100LC = 1
};
enum SubCpuTypeARM : u24 {
ALL = 0,
A500_ARCH = 1,
A500 = 2,
A440 = 3,
M4 = 4,
V4T = 5,
V6 = 6,
V5TEJ = 7,
XSCALE = 8,
V7 = 9,
V7F = 10, /* Cortex A9 */
V7S = 11, /* Swift */
V7K = 12 /* Kirkwood40 */
};
enum SubCpuTypeMC88000 : u24 {
ALL = 0,
MMAX_JPC = 1,
MC88100 = 1,
MC88110 = 2
};
enum SubCpuTypeMC98000 : u24 {
ALL = 0,
MC98601 = 1
};
enum SubCpuTypeI860 : u24 {
ALL = 0,
_860 = 1
};
enum SubCpuTypeI860Little : u24 {
ALL = 0 ... 1
};
enum SubCpuTypeRS6000 : u24 {
ALL = 0 ... 1
};
enum SubCpuTypeSparc : u24 {
ALL = 0,
_260 = 1,
_110 = 2
};
enum SubCpuTypePowerPC : u24 {
ALL = 0,
_601 = 1,
_602 = 2,
_603 = 3,
_603e = 4,
_603ev = 5,
_604 = 6,
_604e = 7,
_620 = 8,
_750 = 9,
_7400 = 10,
_7450 = 11,
_970 = 100
};
enum SubCpuTypeVEO : u24 {
_1 = 1,
_2 = 2,
_3 = 3,
_4 = 4,
ALL = SubCpuTypeVEO::_2
};
bitfield Capabilities {
padding : 7;
lib64 : 1;
};
enum FileType : u32 {
Object = 1,
Execute = 2,
FVMLib = 3,
Core = 4,
Preload = 5,
DyLib = 6,
DyLinker = 7,
Bundle = 8,
DyLibStub = 9,
DSym = 10,
KExtBundle = 11,
};
bitfield Flags {
noUndefs : 1;
incrLink : 1;
dyldLink : 1;
binDatLoad : 1;
prebound : 1;
splitSegs : 1;
lazyInit : 1;
twoLevel : 1;
forceFlat : 1;
noMultiDefs : 1;
noFixPrebinding : 1;
prebindable : 1;
allModsBound : 1;
subSectionsViaSymbols : 1;
canonical : 1;
weakDefines : 1;
bindsToWeak : 1;
allowStackExecution : 1;
rootSafe : 1;
setuidSafe : 1;
noReexportedDylibs : 1;
pie : 1;
deadStrippableDylib : 1;
hasTlvDescriptors : 1;
noHeapExecution : 1;
appExtensionSafe : 1;
nlistOutOfSyncWithDyldinof : 1;
simSupport : 1;
};
struct Header {
Magic magic;
CpuType cpuType;
if (cpuType == CpuType::VAX) SubCpuTypeVAX subCpuType;
else if (cpuType == CpuType::ROMP) SubCpuTypeROMP subCpuType;
else if (cpuType == CpuType::BS32032 || cpuType == CpuType::BS32332 || cpuType == CpuType::NS32532) SubCpuType32XXX subCpuType;
else if (cpuType == CpuType::I386 || cpuType == CpuType::X86_64) SubCpuTypeI386 subCpuType;
else if (cpuType == CpuType::MIPS) SubCpuTypeMips subCpuType;
else if (cpuType == CpuType::HPPA) SubCpuTypeHPPA subCpuType;
else if (cpuType == CpuType::ARM) SubCpuTypeARM subCpuType;
else if (cpuType == CpuType::MC88000) SubCpuTypeMC88000 subCpuType;
else if (cpuType == CpuType::MC98000) SubCpuTypeMC98000 subCpuType;
else if (cpuType == CpuType::I860 || cpuType == CpuType::I860_LITTLE) SubCpuTypeI860 subCpuType;
else if (cpuType == CpuType::SPARC) SubCpuTypeSparc subCpuType;
else if (cpuType == CpuType::POWERPC || cpuType == CpuType::POWERPC64) SubCpuTypePowerPC subCpuType;
else if (cpuType == CpuType::VEO) SubCpuTypeVEO subCpuType;
else u24 subCpuType;
Capabilities capabilities;
FileType fileType;
u32 numCommands;
type::Size<u32> sizeOfCommands;
Flags flags;
if (magic == Magic::_64BitMagic) padding[sizeof(u32)];
};
enum Command : u32 {
ReqDyLd = 0x8000'0000,
Segment = 0x01,
SymTab = 0x02,
SymSeg = 0x03,
Thread = 0x04,
UnixThread = 0x05,
LoadFVMLib = 0x06,
IdFVMLib = 0x07,
Ident = 0x08,
FVMFile = 0x09,
PrePage = 0x0A,
DySymTab = 0x0B,
LoadDyLib = 0x0C,
IdDyLib = 0x0D,
LoadDyLinker = 0x0E,
IdDyLinker = 0x0F,
PreboundDyLib = 0x10,
Routines = 0x11,
SubFramework = 0x12,
SubUmbrella = 0x13,
SubClient = 0x14,
SubLibrary = 0x15,
TwoLevelHints = 0x16,
PrebindCksum = 0x17,
LoadWeakDyLib = 0x18 | Command::ReqDyLd,
Segment64 = 0x19,
Routines64 = 0x1A,
UUID = 0x1B,
RPath = 0x1C | 0x8000'0000,
CodeSignature = 0x1D,
SegmentSplitInfo = 0x1E,
ReExportDyLib = 0x1F | Command::ReqDyLd,
LazyLoadDyLib = 0x20,
EncryptionInfo = 0x21,
DyLdInfo = 0x22,
DyLdInfoOnly = 0x22 | Command::ReqDyLd,
LoadUpwardDyLib = 0x23 | Command::ReqDyLd,
VersionMinMacOSX = 0x24,
VersionMinIPhoneOS = 0x25,
FunctionStarts = 0x26,
DyLdEnvironment = 0x27,
Main = 0x28 | Command::ReqDyLd,
DataInCode = 0x29,
SourceVersion = 0x2A,
DyLibCodeSignDRS = 0x2B
};
struct CommandUUID {
u128 uuid;
};
struct Section {
char sectionName[16];
char segmentName[16];
u32 address;
type::Size<u32> size;
u32 offset;
u32 align;
u32 reloff;
u32 numRelocs;
u32 flags;
padding[8];
if (offset > 0)
u8 data[size] @ offset [[sealed]];
};
struct CommandSegment {
char segmentName[16];
u32 vmAddress;
type::Size<u32> vmSize;
u32 fileOffset;
type::Size<u32> fileSize;
u32 maxProtection;
u32 initProtection;
u32 numSections;
u32 flags;
Section sections[numSections];
if (fileOffset > 0)
u8 data[fileSize] @ fileOffset [[sealed]];
};
struct Section64 {
char sectionName[16];
char segmentName[16];
u64 address;
type::Size<u64> size;
u32 offset;
u32 align;
u32 reloff;
u32 numRelocs;
u32 flags;
padding[12];
if (offset > 0)
u8 data[size] @ offset [[sealed]];
};
struct CommandSegment64 {
char segmentName[16];
u64 vmAddress;
type::Size<u64> vmSize;
u64 fileOffset;
type::Size<u64> fileSize;
u32 maxProtection;
u32 initProtection;
u32 numSections;
u32 flags;
Section64 sections[numSections];
if (fileOffset > 0)
u8 data[fileSize] @ fileOffset [[sealed]];
};
struct LoadCommand {
Command command;
type::Size<u32> commandSize;
if (command == Command::UUID)
CommandUUID data;
else if (command == Command::Segment)
CommandSegment data;
else if (command == Command::Segment64)
CommandSegment64 data;
else
u8 data[commandSize - 8] [[sealed]];
};
struct MachO {
Header header;
LoadCommand loadCommands[header.numCommands];
};
MachO macho @ 0x00;

831
patterns/max_v104.hexpat Normal file
View File

@@ -0,0 +1,831 @@
#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,423 +1,423 @@
#pragma MIME application/x-dmp
#include <type/time.pat>
#include <type/types/win32.pat>
#include <type/size.pat>
using RVA = ULONG32;
using RVA64 = ULONG64;
enum MINIDUMP_STREAM_TYPE : ULONG32 {
UnusedStream = 0,
ReservedStream0 = 1,
ReservedStream1 = 2,
ThreadListStream = 3,
ModuleListStream = 4,
MemoryListStream = 5,
ExceptionStream = 6,
SystemInfoStream = 7,
ThreadExListStream = 8,
Memory64ListStream = 9,
CommentStreamA = 10,
CommentStreamW = 11,
HandleDataStream = 12,
FunctionTableStream = 13,
UnloadedModuleListStream = 14,
MiscInfoStream = 15,
MemoryInfoListStream = 16,
ThreadInfoListStream = 17,
HandleOperationListStream = 18,
TokenStream = 19,
JavaScriptDataStream = 20,
SystemMemoryInfoStream = 21,
ProcessVmCountersStream = 22,
IptTraceStream = 23,
ThreadNamesStream = 24,
ceStreamNull = 0x8000,
ceStreamSystemInfo = 0x8001,
ceStreamException = 0x8002,
ceStreamModuleList = 0x8003,
ceStreamProcessList = 0x8004,
ceStreamThreadList = 0x8005,
ceStreamThreadContextList = 0x8006,
ceStreamThreadCallStackList = 0x8007,
ceStreamMemoryVirtualList = 0x8008,
ceStreamMemoryPhysicalList = 0x8009,
ceStreamBucketParameters = 0x800A,
ceStreamProcessModuleMap = 0x800B,
ceStreamDiagnosisList = 0x800C,
LastReservedStream = 0xFFFF
};
struct MINIDUMP_LOCATION_DESCRIPTOR {
type::Size32 DataSize;
RVA Rva;
};
struct MINIDUMP_MEMORY_DESCRIPTOR {
ULONG64 StartOfMemoryRange;
MINIDUMP_LOCATION_DESCRIPTOR Memory;
};
struct MINIDUMP_THREAD {
ULONG32 ThreadId;
ULONG32 SuspendCount;
ULONG32 PriorityClass;
ULONG32 Priority;
ULONG64 Teb;
MINIDUMP_MEMORY_DESCRIPTOR Stack;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
};
struct MINIDUMP_THREAD_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD Threads[NumberOfThreads];
};
struct VS_FIXEDFILEINFO {
DWORD dwSignature;
DWORD dwStrucVersion;
DWORD dwFileVersionMS;
DWORD dwFileVersionLS;
DWORD dwProductVersionMS;
DWORD dwProductVersionLS;
DWORD dwFileFlagsMask;
DWORD dwFileFlags;
DWORD dwFileOS;
DWORD dwFileType;
DWORD dwFileSubtype;
DWORD dwFileDateMS;
DWORD dwFileDateLS;
};
struct MINIDUMP_MODULE {
ULONG64 BaseOfImage;
type::Size32 SizeOfImage;
ULONG32 CheckSum;
type::time32_t TimeDateStamp;
RVA ModuleNameRva;
VS_FIXEDFILEINFO VersionInfo;
MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
ULONG64 Reserved0;
ULONG64 Reserved1;
char16 ModuleName[] @ ModuleNameRva + 4 [[hidden]];
} [[format("format_module")]];
fn format_module(ref MINIDUMP_MODULE module) {
return module.ModuleName;
};
struct MINIDUMP_MODULE_LIST {
ULONG32 NumberOfModules;
MINIDUMP_MODULE Modules[NumberOfModules];
};
struct MINIDUMP_MEMORY_LIST {
ULONG32 NumberOfMemoryRanges;
MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges[NumberOfMemoryRanges];
};
struct MINIDUMP_EXCEPTION {
ULONG32 ExceptionCode;
ULONG32 ExceptionFlags;
ULONG64 ExceptionRecord;
ULONG64 ExceptionAddress;
ULONG32 NumberParameters;
padding[4];
ULONG64 ExceptionInformation[15];
};
struct MINIDUMP_EXCEPTION_STREAM {
ULONG32 ThreadId;
padding[4];
MINIDUMP_EXCEPTION ExceptionRecord;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
};
struct CPU_INFORMATION {
ULONG32 VendorId[3];
ULONG32 VersionInformation;
ULONG32 FeatureInformation;
ULONG32 AMDExtendedCpuFeatures;
};
struct MINIDUMP_SYSTEM_INFO {
USHORT ProcessorArchitecture;
USHORT ProcessorLevel;
USHORT ProcessorRevision;
UCHAR NumberOfProcessors;
UCHAR ProductType;
ULONG32 MajorVersion;
ULONG32 MinorVersion;
ULONG32 BuildNumber;
ULONG32 PlatformId;
RVA CSDVersionRva;
USHORT SuiteMask;
USHORT Reserved;
CPU_INFORMATION Cpu;
};
struct MINIDUMP_THREAD_EX {
ULONG32 ThreadId;
ULONG32 SuspendCount;
ULONG32 PriorityClass;
ULONG32 Priority;
ULONG64 Teb;
MINIDUMP_MEMORY_DESCRIPTOR Stack;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
MINIDUMP_MEMORY_DESCRIPTOR BackingStore;
};
struct MINIDUMP_THREAD_EX_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD_EX Threads[NumberOfThreads];
};
struct MINIDUMP_MEMORY_DESCRIPTOR64 {
ULONG64 StartOfMemoryRange;
type::Size64 DataSize;
};
struct MINIDUMP_MEMORY64_LIST {
ULONG64 NumberOfMemoryRanges;
RVA64 BaseRva;
MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges[NumberOfMemoryRanges];
};
struct MINIDUMP_HANDLE_DESCRIPTOR {
ULONG64 Handle;
RVA TypeNameRva;
RVA ObjectNameRva;
ULONG32 Attributes;
ULONG32 GrantedAccess;
ULONG32 HandleCount;
ULONG32 PointerCount;
};
struct MINIDUMP_HANDLE_DESCRIPTOR_2 {
ULONG64 Handle;
RVA TypeNameRva;
RVA ObjectNameRva;
ULONG32 Attributes;
ULONG32 GrantedAccess;
ULONG32 HandleCount;
ULONG32 PointerCount;
RVA ObjectInfoRva;
ULONG32 Reserved0;
};
struct MINIDUMP_HANDLE_DATA_STREAM {
ULONG32 SizeOfHeader;
ULONG32 SizeOfDescriptor;
ULONG32 NumberOfDescriptors;
ULONG32 Reserved;
if (SizeOfDescriptor == 32)
MINIDUMP_HANDLE_DESCRIPTOR HandleDescriptors[NumberOfDescriptors];
else if (SizeOfDescriptor == 40)
MINIDUMP_HANDLE_DESCRIPTOR_2 HandleDescriptors[NumberOfDescriptors];
};
struct MINIDUMP_FUNCTION_TABLE_DESCRIPTOR {
ULONG64 MinimumAddress;
ULONG64 MaximumAddress;
ULONG64 BaseAddress;
ULONG32 EntryCount;
type::Size32 SizeOfAlignPad;
};
struct MINIDUMP_FUNCTION_TABLE_STREAM {
type::Size32 SizeOfHeader;
type::Size32 SizeOfDescriptor;
type::Size32 SizeOfNativeDescriptor;
type::Size32 SizeOfFunctionEntry;
ULONG32 NumberOfDescriptors;
ULONG32 SizeOfAlignPad;
MINIDUMP_FUNCTION_TABLE_DESCRIPTOR FunctionDescriptors[NumberOfDescriptors];
};
struct MINIDUMP_UNLOADED_MODULE {
ULONG64 BaseOfImage;
type::Size32 SizeOfImage;
ULONG32 CheckSum;
ULONG32 TimeDateStamp;
RVA ModuleNameRva;
char16 ModuleName[] @ ModuleNameRva + 4 [[hidden]];
} [[format("format_unloaded_module")]];
fn format_unloaded_module(ref MINIDUMP_UNLOADED_MODULE module) {
return module.ModuleName;
};
struct MINIDUMP_UNLOADED_MODULE_LIST {
ULONG32 SizeOfHeader;
ULONG32 SizeOfEntry;
ULONG32 NumberOfEntries;
if (SizeOfHeader > 12)
padding[header.SizeOfHeader - 12];
MINIDUMP_UNLOADED_MODULE Modules[NumberOfEntries];
};
struct MINIDUMP_MISC_INFO {
ULONG32 SizeOfInfo;
ULONG32 Flags1;
ULONG32 ProcessId;
ULONG32 ProcessCreateTime;
ULONG32 ProcessUserTime;
ULONG32 ProcessKernelTime;
if (SizeOfInfo > 24) {
ULONG32 ProcessorMaxMhz;
ULONG32 ProcessorCurrentMhz;
ULONG32 ProcessorMhzLimit;
ULONG32 ProcessorMaxIdleState;
ULONG32 ProcessorCurrentIdleState;
}
};
struct MINIDUMP_MEMORY_INFO {
ULONG64 BaseAddress;
ULONG64 AllocationBase;
ULONG32 AllocationProtect;
padding[4];
type::Size64 RegionSize;
ULONG32 State;
ULONG32 Protect;
ULONG32 Type;
padding[4];
};
struct MINIDUMP_MEMORY_INFO_LIST {
ULONG SizeOfHeader;
ULONG SizeOfEntry;
ULONG64 NumberOfEntries;
if (SizeOfHeader > 16)
padding[SizeOfHeader - 16];
MINIDUMP_MEMORY_INFO Info[NumberOfEntries];
};
struct MINIDUMP_THREAD_INFO {
ULONG32 ThreadId;
ULONG32 DumpFlags;
ULONG32 DumpError;
ULONG32 ExitStatus;
ULONG64 CreateTime;
ULONG64 ExitTime;
ULONG64 KernelTime;
ULONG64 UserTime;
ULONG64 StartAddress;
ULONG64 Affinity;
};
struct MINIDUMP_THREAD_INFO_LIST {
ULONG SizeOfHeader;
ULONG SizeOfEntry;
ULONG NumberOfEntries;
if (SizeOfHeader > 12)
padding[SizeOfHeader - 12];
MINIDUMP_THREAD_INFO Info[NumberOfEntries];
};
struct MINIDUMP_HANDLE_OPERATION_LIST {
ULONG32 SizeOfHeader;
ULONG32 SizeOfEntry;
ULONG32 NumberOfEntries;
ULONG32 Reserved;
};
struct MINIDUMP_DIRECTORY {
MINIDUMP_STREAM_TYPE StreamType;
MINIDUMP_LOCATION_DESCRIPTOR Location;
if (StreamType == MINIDUMP_STREAM_TYPE::ThreadListStream)
MINIDUMP_THREAD_LIST ThreadList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ModuleListStream)
MINIDUMP_MODULE_LIST ModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryListStream)
MINIDUMP_MEMORY_LIST MemoryList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ExceptionStream)
MINIDUMP_EXCEPTION_STREAM ExceptionInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::SystemInfoStream)
MINIDUMP_SYSTEM_INFO SystemInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadExListStream)
MINIDUMP_THREAD_EX_LIST ThreadExList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::Memory64ListStream)
MINIDUMP_MEMORY64_LIST Mem64List @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamA)
char Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamW)
char16 Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleDataStream)
MINIDUMP_HANDLE_DATA_STREAM HandleData @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::FunctionTableStream)
MINIDUMP_FUNCTION_TABLE_STREAM FunctionTable @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::UnloadedModuleListStream)
MINIDUMP_UNLOADED_MODULE_LIST UnloadModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MiscInfoStream)
MINIDUMP_MISC_INFO MiscInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryInfoListStream)
MINIDUMP_MEMORY_INFO_LIST MemInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadInfoListStream)
MINIDUMP_THREAD_INFO_LIST ThreadInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleOperationListStream)
MINIDUMP_HANDLE_OPERATION_LIST HandleOperList @ Location.Rva;
};
bitfield MINIDUMP_TYPE {
MiniDumpWithDataSegs : 1;
MiniDumpWithFullMemory : 1;
MiniDumpWithHandleData : 1;
MiniDumpFilterMemory : 1;
MiniDumpScanMemory : 1;
MiniDumpWithUnloadedModules : 1;
MiniDumpWithIndirectlyReferencedMemory : 1;
MiniDumpFilterModulePaths : 1;
MiniDumpWithProcessThreadData : 1;
MiniDumpWithPrivateReadWriteMemory : 1;
MiniDumpWithoutOptionalData : 1;
MiniDumpWithFullMemoryInfo : 1;
MiniDumpWithThreadInfo : 1;
MiniDumpWithCodeSegs : 1;
MiniDumpWithoutAuxiliaryState : 1;
MiniDumpWithFullAuxiliaryState : 1;
MiniDumpWithPrivateWriteCopyMemory : 1;
MiniDumpIgnoreInaccessibleMemory : 1;
MiniDumpWithTokenInformation : 1;
MiniDumpWithModuleHeaders : 1;
MiniDumpFilterTriage : 1;
MiniDumpWithAvxXStateContext : 1;
MiniDumpWithIptTrace : 1;
MiniDumpScanInaccessiblePartialPages : 1;
padding : 40;
} [[right_to_left]];
struct MINIDUMP_HEADER {
char Signature[4];
ULONG32 Version;
ULONG32 NumberOfStreams;
RVA StreamDirectoryRva;
ULONG32 Checksum;
type::time32_t TimeDateStamp;
MINIDUMP_TYPE Flags;
};
struct MINIDUMP {
MINIDUMP_HEADER Header;
MINIDUMP_DIRECTORY Streams[Header.NumberOfStreams] [[format_entries("format_stream")]];
};
fn format_stream(ref MINIDUMP_DIRECTORY stream) {
return stream.StreamType;
};
MINIDUMP MiniDump @ 0x00;
#pragma MIME application/x-dmp
#include <type/time.pat>
#include <type/types/win32.pat>
#include <type/size.pat>
using RVA = ULONG32;
using RVA64 = ULONG64;
enum MINIDUMP_STREAM_TYPE : ULONG32 {
UnusedStream = 0,
ReservedStream0 = 1,
ReservedStream1 = 2,
ThreadListStream = 3,
ModuleListStream = 4,
MemoryListStream = 5,
ExceptionStream = 6,
SystemInfoStream = 7,
ThreadExListStream = 8,
Memory64ListStream = 9,
CommentStreamA = 10,
CommentStreamW = 11,
HandleDataStream = 12,
FunctionTableStream = 13,
UnloadedModuleListStream = 14,
MiscInfoStream = 15,
MemoryInfoListStream = 16,
ThreadInfoListStream = 17,
HandleOperationListStream = 18,
TokenStream = 19,
JavaScriptDataStream = 20,
SystemMemoryInfoStream = 21,
ProcessVmCountersStream = 22,
IptTraceStream = 23,
ThreadNamesStream = 24,
ceStreamNull = 0x8000,
ceStreamSystemInfo = 0x8001,
ceStreamException = 0x8002,
ceStreamModuleList = 0x8003,
ceStreamProcessList = 0x8004,
ceStreamThreadList = 0x8005,
ceStreamThreadContextList = 0x8006,
ceStreamThreadCallStackList = 0x8007,
ceStreamMemoryVirtualList = 0x8008,
ceStreamMemoryPhysicalList = 0x8009,
ceStreamBucketParameters = 0x800A,
ceStreamProcessModuleMap = 0x800B,
ceStreamDiagnosisList = 0x800C,
LastReservedStream = 0xFFFF
};
struct MINIDUMP_LOCATION_DESCRIPTOR {
type::Size32 DataSize;
RVA Rva;
};
struct MINIDUMP_MEMORY_DESCRIPTOR {
ULONG64 StartOfMemoryRange;
MINIDUMP_LOCATION_DESCRIPTOR Memory;
};
struct MINIDUMP_THREAD {
ULONG32 ThreadId;
ULONG32 SuspendCount;
ULONG32 PriorityClass;
ULONG32 Priority;
ULONG64 Teb;
MINIDUMP_MEMORY_DESCRIPTOR Stack;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
};
struct MINIDUMP_THREAD_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD Threads[NumberOfThreads];
};
struct VS_FIXEDFILEINFO {
DWORD dwSignature;
DWORD dwStrucVersion;
DWORD dwFileVersionMS;
DWORD dwFileVersionLS;
DWORD dwProductVersionMS;
DWORD dwProductVersionLS;
DWORD dwFileFlagsMask;
DWORD dwFileFlags;
DWORD dwFileOS;
DWORD dwFileType;
DWORD dwFileSubtype;
DWORD dwFileDateMS;
DWORD dwFileDateLS;
};
struct MINIDUMP_MODULE {
ULONG64 BaseOfImage;
type::Size32 SizeOfImage;
ULONG32 CheckSum;
type::time32_t TimeDateStamp;
RVA ModuleNameRva;
VS_FIXEDFILEINFO VersionInfo;
MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
ULONG64 Reserved0;
ULONG64 Reserved1;
char16 ModuleName[] @ ModuleNameRva + 4 [[hidden]];
} [[format("format_module")]];
fn format_module(ref MINIDUMP_MODULE module) {
return module.ModuleName;
};
struct MINIDUMP_MODULE_LIST {
ULONG32 NumberOfModules;
MINIDUMP_MODULE Modules[NumberOfModules];
};
struct MINIDUMP_MEMORY_LIST {
ULONG32 NumberOfMemoryRanges;
MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges[NumberOfMemoryRanges];
};
struct MINIDUMP_EXCEPTION {
ULONG32 ExceptionCode;
ULONG32 ExceptionFlags;
ULONG64 ExceptionRecord;
ULONG64 ExceptionAddress;
ULONG32 NumberParameters;
padding[4];
ULONG64 ExceptionInformation[15];
};
struct MINIDUMP_EXCEPTION_STREAM {
ULONG32 ThreadId;
padding[4];
MINIDUMP_EXCEPTION ExceptionRecord;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
};
struct CPU_INFORMATION {
ULONG32 VendorId[3];
ULONG32 VersionInformation;
ULONG32 FeatureInformation;
ULONG32 AMDExtendedCpuFeatures;
};
struct MINIDUMP_SYSTEM_INFO {
USHORT ProcessorArchitecture;
USHORT ProcessorLevel;
USHORT ProcessorRevision;
UCHAR NumberOfProcessors;
UCHAR ProductType;
ULONG32 MajorVersion;
ULONG32 MinorVersion;
ULONG32 BuildNumber;
ULONG32 PlatformId;
RVA CSDVersionRva;
USHORT SuiteMask;
USHORT Reserved;
CPU_INFORMATION Cpu;
};
struct MINIDUMP_THREAD_EX {
ULONG32 ThreadId;
ULONG32 SuspendCount;
ULONG32 PriorityClass;
ULONG32 Priority;
ULONG64 Teb;
MINIDUMP_MEMORY_DESCRIPTOR Stack;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
MINIDUMP_MEMORY_DESCRIPTOR BackingStore;
};
struct MINIDUMP_THREAD_EX_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD_EX Threads[NumberOfThreads];
};
struct MINIDUMP_MEMORY_DESCRIPTOR64 {
ULONG64 StartOfMemoryRange;
type::Size64 DataSize;
};
struct MINIDUMP_MEMORY64_LIST {
ULONG64 NumberOfMemoryRanges;
RVA64 BaseRva;
MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges[NumberOfMemoryRanges];
};
struct MINIDUMP_HANDLE_DESCRIPTOR {
ULONG64 Handle;
RVA TypeNameRva;
RVA ObjectNameRva;
ULONG32 Attributes;
ULONG32 GrantedAccess;
ULONG32 HandleCount;
ULONG32 PointerCount;
};
struct MINIDUMP_HANDLE_DESCRIPTOR_2 {
ULONG64 Handle;
RVA TypeNameRva;
RVA ObjectNameRva;
ULONG32 Attributes;
ULONG32 GrantedAccess;
ULONG32 HandleCount;
ULONG32 PointerCount;
RVA ObjectInfoRva;
ULONG32 Reserved0;
};
struct MINIDUMP_HANDLE_DATA_STREAM {
ULONG32 SizeOfHeader;
ULONG32 SizeOfDescriptor;
ULONG32 NumberOfDescriptors;
ULONG32 Reserved;
if (SizeOfDescriptor == 32)
MINIDUMP_HANDLE_DESCRIPTOR HandleDescriptors[NumberOfDescriptors];
else if (SizeOfDescriptor == 40)
MINIDUMP_HANDLE_DESCRIPTOR_2 HandleDescriptors[NumberOfDescriptors];
};
struct MINIDUMP_FUNCTION_TABLE_DESCRIPTOR {
ULONG64 MinimumAddress;
ULONG64 MaximumAddress;
ULONG64 BaseAddress;
ULONG32 EntryCount;
type::Size32 SizeOfAlignPad;
};
struct MINIDUMP_FUNCTION_TABLE_STREAM {
type::Size32 SizeOfHeader;
type::Size32 SizeOfDescriptor;
type::Size32 SizeOfNativeDescriptor;
type::Size32 SizeOfFunctionEntry;
ULONG32 NumberOfDescriptors;
ULONG32 SizeOfAlignPad;
MINIDUMP_FUNCTION_TABLE_DESCRIPTOR FunctionDescriptors[NumberOfDescriptors];
};
struct MINIDUMP_UNLOADED_MODULE {
ULONG64 BaseOfImage;
type::Size32 SizeOfImage;
ULONG32 CheckSum;
ULONG32 TimeDateStamp;
RVA ModuleNameRva;
char16 ModuleName[] @ ModuleNameRva + 4 [[hidden]];
} [[format("format_unloaded_module")]];
fn format_unloaded_module(ref MINIDUMP_UNLOADED_MODULE module) {
return module.ModuleName;
};
struct MINIDUMP_UNLOADED_MODULE_LIST {
ULONG32 SizeOfHeader;
ULONG32 SizeOfEntry;
ULONG32 NumberOfEntries;
if (SizeOfHeader > 12)
padding[header.SizeOfHeader - 12];
MINIDUMP_UNLOADED_MODULE Modules[NumberOfEntries];
};
struct MINIDUMP_MISC_INFO {
ULONG32 SizeOfInfo;
ULONG32 Flags1;
ULONG32 ProcessId;
ULONG32 ProcessCreateTime;
ULONG32 ProcessUserTime;
ULONG32 ProcessKernelTime;
if (SizeOfInfo > 24) {
ULONG32 ProcessorMaxMhz;
ULONG32 ProcessorCurrentMhz;
ULONG32 ProcessorMhzLimit;
ULONG32 ProcessorMaxIdleState;
ULONG32 ProcessorCurrentIdleState;
}
};
struct MINIDUMP_MEMORY_INFO {
ULONG64 BaseAddress;
ULONG64 AllocationBase;
ULONG32 AllocationProtect;
padding[4];
type::Size64 RegionSize;
ULONG32 State;
ULONG32 Protect;
ULONG32 Type;
padding[4];
};
struct MINIDUMP_MEMORY_INFO_LIST {
ULONG SizeOfHeader;
ULONG SizeOfEntry;
ULONG64 NumberOfEntries;
if (SizeOfHeader > 16)
padding[SizeOfHeader - 16];
MINIDUMP_MEMORY_INFO Info[NumberOfEntries];
};
struct MINIDUMP_THREAD_INFO {
ULONG32 ThreadId;
ULONG32 DumpFlags;
ULONG32 DumpError;
ULONG32 ExitStatus;
ULONG64 CreateTime;
ULONG64 ExitTime;
ULONG64 KernelTime;
ULONG64 UserTime;
ULONG64 StartAddress;
ULONG64 Affinity;
};
struct MINIDUMP_THREAD_INFO_LIST {
ULONG SizeOfHeader;
ULONG SizeOfEntry;
ULONG NumberOfEntries;
if (SizeOfHeader > 12)
padding[SizeOfHeader - 12];
MINIDUMP_THREAD_INFO Info[NumberOfEntries];
};
struct MINIDUMP_HANDLE_OPERATION_LIST {
ULONG32 SizeOfHeader;
ULONG32 SizeOfEntry;
ULONG32 NumberOfEntries;
ULONG32 Reserved;
};
struct MINIDUMP_DIRECTORY {
MINIDUMP_STREAM_TYPE StreamType;
MINIDUMP_LOCATION_DESCRIPTOR Location;
if (StreamType == MINIDUMP_STREAM_TYPE::ThreadListStream)
MINIDUMP_THREAD_LIST ThreadList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ModuleListStream)
MINIDUMP_MODULE_LIST ModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryListStream)
MINIDUMP_MEMORY_LIST MemoryList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ExceptionStream)
MINIDUMP_EXCEPTION_STREAM ExceptionInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::SystemInfoStream)
MINIDUMP_SYSTEM_INFO SystemInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadExListStream)
MINIDUMP_THREAD_EX_LIST ThreadExList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::Memory64ListStream)
MINIDUMP_MEMORY64_LIST Mem64List @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamA)
char Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::CommentStreamW)
char16 Comment[] @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleDataStream)
MINIDUMP_HANDLE_DATA_STREAM HandleData @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::FunctionTableStream)
MINIDUMP_FUNCTION_TABLE_STREAM FunctionTable @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::UnloadedModuleListStream)
MINIDUMP_UNLOADED_MODULE_LIST UnloadModuleList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MiscInfoStream)
MINIDUMP_MISC_INFO MiscInfo @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::MemoryInfoListStream)
MINIDUMP_MEMORY_INFO_LIST MemInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::ThreadInfoListStream)
MINIDUMP_THREAD_INFO_LIST ThreadInfoList @ Location.Rva;
else if (StreamType == MINIDUMP_STREAM_TYPE::HandleOperationListStream)
MINIDUMP_HANDLE_OPERATION_LIST HandleOperList @ Location.Rva;
};
bitfield MINIDUMP_TYPE {
MiniDumpWithDataSegs : 1;
MiniDumpWithFullMemory : 1;
MiniDumpWithHandleData : 1;
MiniDumpFilterMemory : 1;
MiniDumpScanMemory : 1;
MiniDumpWithUnloadedModules : 1;
MiniDumpWithIndirectlyReferencedMemory : 1;
MiniDumpFilterModulePaths : 1;
MiniDumpWithProcessThreadData : 1;
MiniDumpWithPrivateReadWriteMemory : 1;
MiniDumpWithoutOptionalData : 1;
MiniDumpWithFullMemoryInfo : 1;
MiniDumpWithThreadInfo : 1;
MiniDumpWithCodeSegs : 1;
MiniDumpWithoutAuxiliaryState : 1;
MiniDumpWithFullAuxiliaryState : 1;
MiniDumpWithPrivateWriteCopyMemory : 1;
MiniDumpIgnoreInaccessibleMemory : 1;
MiniDumpWithTokenInformation : 1;
MiniDumpWithModuleHeaders : 1;
MiniDumpFilterTriage : 1;
MiniDumpWithAvxXStateContext : 1;
MiniDumpWithIptTrace : 1;
MiniDumpScanInaccessiblePartialPages : 1;
padding : 40;
};
struct MINIDUMP_HEADER {
char Signature[4];
ULONG32 Version;
ULONG32 NumberOfStreams;
RVA StreamDirectoryRva;
ULONG32 Checksum;
type::time32_t TimeDateStamp;
MINIDUMP_TYPE Flags;
};
struct MINIDUMP {
MINIDUMP_HEADER Header;
MINIDUMP_DIRECTORY Streams[Header.NumberOfStreams] [[format_entries("format_stream")]];
};
fn format_stream(ref MINIDUMP_DIRECTORY stream) {
return stream.StreamType;
};
MINIDUMP MiniDump @ 0x00;

76
patterns/nbt.hexpat Normal file
View File

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

262
patterns/ne.hexpat Normal file
View File

@@ -0,0 +1,262 @@
#include <std/mem.pat>
struct DOSHeader {
char signature[2];
u16 lastPageSize;
u16 numberOfPages;
u16 relocations;
u16 headerSizeInParagraphs;
u16 minimumAllocatedParagraphs;
u16 maximumAllocatedParagraphs;
u16 initialSSValue;
u16 initialRelativeSPValue;
u16 checksum;
u16 initialRelativeIPValue;
u16 initialCSValue;
u16 relocationsTablePointer;
u16 overlayNumber;
u8 overlayInformation[0x20];
u32 neHeaderPointer;
};
u16 dosMessageOffset;
u16 pointedCodeOffset;
fn finddosmessage() {
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
if (std::mem::read_unsigned($+i, 1) == 0xBA) { // MOV instruction
dosMessageOffset = std::mem::read_unsigned($+i+1, 2);
break;
}
}
};
fn findpointingcode() {
for (u8 i = 0, $+i < std::mem::read_unsigned(0x3C, 4), i = i + 1) {
if (std::mem::read_unsigned($+i, 1) == 0xE8) { // CALL instruction
pointedCodeOffset = std::mem::read_unsigned($+i+1, 2);
return true;
}
}
return false;
};
fn isdosdata(char c) {
return c == 0x0D || c == '$';
};
struct DOSStub {
if (findpointingcode()) {
u8 pointingCode[3];
u8 code[while(std::mem::read_unsigned($, 1) != 0x00)] @ addressof(this) + pointedCodeOffset + 3;
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
char data[while(std::mem::read_string($-1, 1) != "$")];
}
else {
finddosmessage();
if (dosMessageOffset > 0) {
u8 code[while($ != addressof(this) + dosMessageOffset)];
char message[while(!isdosdata(std::mem::read_unsigned($, 1)))];
char data[while(std::mem::read_string($-1, 1) != "$")];
}
else {
char code[while(std::mem::read_unsigned($, 1) != 0x00)];
}
}
};
struct FileHeader {
DOSHeader dosHeader;
DOSStub dosStub @ dosHeader.headerSizeInParagraphs * 16;
};
FileHeader fileHeader @ 0x00;
enum DGroupType : u8 {
NoAutoData,
SingleData,
MultipleData,
Null
};
fn formatDGroupType(u8 value) {
DGroupType dgroup = value;
return dgroup;
};
enum AppType : u8 {
None,
Fullscreen,
WinPMCompatible,
UsesWinPM
};
fn formatAppType(u8 value) {
AppType app = value;
return app;
};
bitfield ProgramFlags {
dGroupType : 2 [[format("formatDGroupType")]];
globalInitialization : 1;
protectedModeOnly : 1;
instructions86 : 1;
instructions286 : 1;
instructions386 : 1;
instructionsX87 : 1;
};
bitfield ApplicationFlags {
applicationType : 2 [[format("formatAppType")]];
padding : 1;
os2Application : 1;
reserved : 1;
imageError : 1;
nonConforming : 1;
dll : 1;
};
enum OSType : u8 {
Unknown = 0x00,
OS2 = 0x01,
Win16 = 0x02,
DOS4 = 0x03,
Win32 = 0x04,
BorlandOSServices = 0x05,
PharlapDOSExtenderOS2 = 0x81,
PharlapDOSExtenderWindows = 0x82
};
bitfield OS2EXEFlags {
longFilename : 1;
protectedMode : 1;
proportionalFonts : 1;
gangloadArea : 1;
};
struct NEHeader {
char signature[2];
u8 majorLinkerVersion;
u8 minorLinkerVersion;
u16 entryTableOffset;
u16 entryTableLength;
u32 fileCRC;
ProgramFlags programFlags;
ApplicationFlags appFlags;
u16 autoDataSegmentIndex;
u16 initHeapSize;
u16 initStackSize;
u32 entryPoint;
u32 initialStackPointer;
u16 segmentCount;
u16 moduleReferenceCount;
u16 nonResidentNamesTableSize;
u16 segmentTableOffset;
u16 resourceTableOffset;
u16 residentNamesTableOffset;
u16 moduleReferenceTableOffset;
u16 importedNamesTableOffset;
u8 *nonResidentNamesTablePointer[nonResidentNamesTableSize] : u32;
u16 moveableEntryCount;
u16 fileAlignmentSizeShiftCount;
u16 resourceCount;
OSType targetOS;
OS2EXEFlags os2ExeFlags;
u16 thunksReturnOffset;
u16 segmentReferenceThunksOffset;
u16 minimumCodeSwapAreaSize;
u8 expectedMinorWindowsVersion;
u8 expectedMajorWindowsVersion;
};
NEHeader neHeader @ fileHeader.dosHeader.neHeaderPointer;
bitfield SegmentTableFlags {
dataSegment : 1;
typeMask : 2;
padding : 1;
moveable : 1;
padding : 1;
preloaded : 1;
padding : 1;
containsRelocationInfo : 1;
padding : 1;
discardPriority : 4;
};
struct SegmentTable {
u16 segmentDataPointer;
u16 segmentLength;
SegmentTableFlags segmentTableFlags;
u16 minimumAllocationSize;
};
SegmentTable segmentTable[neHeader.segmentCount] @ addressof(neHeader) + neHeader.segmentTableOffset;
bitfield BlockFlags {
padding : 4;
moveable : 1;
shared : 1;
preload : 1;
padding : 9;
};
struct ResourceTypeInformationBlock {
u8 *resourcePointer : u16;
u16 resourceLength;
BlockFlags flags;
u16 resourceID;
u32 reserved;
};
struct ResourceRecord {
u16 typeID;
u16 numberOfResources;
u32 reserved;
ResourceTypeInformationBlock blocks[numberOfResources];
};
struct ResourceTable {
u16 alignmentShiftCount;
ResourceRecord records[neHeader.resourceTableEntryCount];
u8 stringLength;
char string[stringLength];
};
ResourceTable resourceTable[neHeader.resourceCount] @ addressof(neHeader) + neHeader.resourceTableOffset;
struct ResidentName {
u8 stringLength;
char string[stringLength];
u16 ordinalNumber;
};
ResidentName residentNameTable[while($+1 < addressof(neHeader) + neHeader.moduleReferenceTableOffset)] @ addressof(neHeader) + neHeader.residentNamesTableOffset;
struct ModuleReference {
u16 moduleNameOffset;
};
ModuleReference moduleReferenceTable[neHeader.moduleReferenceCount] @ addressof(neHeader) + neHeader.moduleReferenceTableOffset;
struct ImportedNameTable {
u8 stringLength;
char string[stringLength];
};
ImportedNameTable importedNameTable[while($ < addressof(neHeader) + neHeader.entryTableOffset)] @ addressof(neHeader) + neHeader.importedNamesTableOffset;
enum EntryDataType : u8 {
Unused,
Fixed = 0x01 ... 0xFE,
Moveable
};
struct EntryTable {
u8 entryCount;
EntryDataType segmentIndicator;
};
EntryTable entryTable[neHeader.entryTableLength/2] @ addressof(neHeader) + neHeader.entryTableOffset;

View File

@@ -1,161 +1,165 @@
bitfield AccessCapability {
Read : 4;
Write : 4;
} [[left_to_right]];
struct CapabilityContainer {
u8 magic;
u8 version;
u8 memorySize;
AccessCapability accessCapability;
};
bitfield NDEFFlags {
MB : 1;
ME : 1;
CF : 1;
SR : 1;
IL : 1;
TNF : 3;
} [[left_to_right]];
enum TNFType : u8 {
Empty = 0x00,
NFCForumWellKnownType = 0x01,
MediaType = 0x02,
AbsoluteURI = 0x03,
NFCForumExternalType = 0x04,
Unknown = 0x05,
Unchanged = 0x06,
Reserved = 0x07
};
struct NDEF {
NDEFFlags flags;
u8 typeLength;
if (flags.SR)
u8 payloadLength;
else
u32 payloadLength;
if (flags.IL)
u8 idLength;
char type[typeLength];
if (flags.IL)
u8 id[idLength];
u8 payload[payloadLength];
if (flags.ME)
break;
};
struct LockControl {
u8 dynamicLockByteOffset;
u8 numBits;
u8 pageControlInfo;
};
struct MemoryControl {
u8 reservedBytesOffset;
u8 numBytes;
u8 pageSize;
};
struct Length {
u8 byte [[hidden, no_unique_address]];
if (byte == 0xFF)
u24 length;
else
u8 length;
} [[sealed, transform("transform_length"), format("transform_length")]];
fn transform_length(Length length) {
return length.length;
};
enum Tag : u8 {
NULL = 0x00,
LockControl = 0x01,
MemoryControl = 0x02,
NDEFMessage = 0x03,
Proprietary = 0xFD,
TerminatorTLV = 0xFE
};
struct TLV {
Tag tag;
if (tag == Tag::TerminatorTLV) {
break;
} else if (tag == Tag::NULL) {
// Empty
} else {
Length length;
if (length > 0) {
if (tag == Tag::LockControl) {
LockControl lockControl;
} else if (tag == Tag::MemoryControl) {
LockControl lockControl;
} else if (tag == Tag::NDEFMessage) {
NDEF ndef[while(true)];
} else {
u8 value[length];
}
}
}
};
struct ManufacturerData {
u8 serial1[3];
u8 checkByte0;
u8 serial2[4];
u8 checkByte1;
u8 internal;
u16 lockBytes;
};
struct DynamicLockBytes {
u8 bytes[3];
padding[1];
};
bitfield MIRROR {
MIRROR_CONF : 2;
MIRROR_BYTE : 2;
padding : 1;
STRG_MOD_EN : 1;
padding : 2;
} [[left_to_right]];
bitfield ACCESS {
PROT : 1;
CFGLCK : 1;
padding : 1;
NFC_CNT_EN : 1;
NFC_CNT_PWD_PROT : 1;
AUTHLIM : 3;
};
struct Config {
MIRROR MIRROR;
u8 MIRROR_PAGE;
u8 AUTH0;
ACCESS ACCESS;
u32 PWD;
u16 PACK;
};
struct NTAG {
ManufacturerData manufacturerData;
CapabilityContainer cc;
TLV tlv[while(true)];
padding[addressof(tlv) + cc.memorySize * 8 - sizeof(tlv)];
DynamicLockBytes dynamicLockBytes;
Config config;
};
NTAG ntag @ 0x00;
#include <std/core.pat>
using BitfieldOrder = std::core::BitfieldOrder;
bitfield AccessCapability {
Read : 4;
Write : 4;
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
struct CapabilityContainer {
u8 magic;
u8 version;
u8 memorySize;
be AccessCapability accessCapability;
};
bitfield NDEFFlags {
MB : 1;
ME : 1;
CF : 1;
SR : 1;
IL : 1;
TNF : 3;
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
enum TNFType : u8 {
Empty = 0x00,
NFCForumWellKnownType = 0x01,
MediaType = 0x02,
AbsoluteURI = 0x03,
NFCForumExternalType = 0x04,
Unknown = 0x05,
Unchanged = 0x06,
Reserved = 0x07
};
struct NDEF {
NDEFFlags flags;
u8 typeLength;
if (flags.SR)
u8 payloadLength;
else
u32 payloadLength;
if (flags.IL)
u8 idLength;
char type[typeLength];
if (flags.IL)
u8 id[idLength];
u8 payload[payloadLength];
if (flags.ME)
break;
};
struct LockControl {
u8 dynamicLockByteOffset;
u8 numBits;
u8 pageControlInfo;
};
struct MemoryControl {
u8 reservedBytesOffset;
u8 numBytes;
u8 pageSize;
};
struct Length {
u8 byte [[hidden, no_unique_address]];
if (byte == 0xFF)
u24 length;
else
u8 length;
} [[sealed, transform("transform_length"), format("transform_length")]];
fn transform_length(Length length) {
return length.length;
};
enum Tag : u8 {
NULL = 0x00,
LockControl = 0x01,
MemoryControl = 0x02,
NDEFMessage = 0x03,
Proprietary = 0xFD,
TerminatorTLV = 0xFE
};
struct TLV {
Tag tag;
if (tag == Tag::TerminatorTLV) {
break;
} else if (tag == Tag::NULL) {
// Empty
} else {
Length length;
if (length > 0) {
if (tag == Tag::LockControl) {
LockControl lockControl;
} else if (tag == Tag::MemoryControl) {
LockControl lockControl;
} else if (tag == Tag::NDEFMessage) {
NDEF ndef[while(true)];
} else {
u8 value[length];
}
}
}
};
struct ManufacturerData {
u8 serial1[3];
u8 checkByte0;
u8 serial2[4];
u8 checkByte1;
u8 internal;
u16 lockBytes;
};
struct DynamicLockBytes {
u8 bytes[3];
padding[1];
};
bitfield MIRROR {
MIRROR_CONF : 2;
MIRROR_BYTE : 2;
padding : 1;
STRG_MOD_EN : 1;
padding : 2;
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
bitfield ACCESS {
PROT : 1;
CFGLCK : 1;
padding : 1;
NFC_CNT_EN : 1;
NFC_CNT_PWD_PROT : 1;
AUTHLIM : 3;
};
struct Config {
MIRROR MIRROR;
u8 MIRROR_PAGE;
u8 AUTH0;
ACCESS ACCESS;
u32 PWD;
u16 PACK;
};
struct NTAG {
ManufacturerData manufacturerData;
CapabilityContainer cc;
TLV tlv[while(true)];
padding[addressof(tlv) + cc.memorySize * 8 - sizeof(tlv)];
DynamicLockBytes dynamicLockBytes;
Config config;
};
NTAG ntag @ 0x00;

40
patterns/pbz.hexpat Normal file
View File

@@ -0,0 +1,40 @@
// Apple pbz compressed file
// Used by Apple on .xip files and OTA updates,
// and can be created with macOS compression_tool.
//
// Copyright (c) 2023 Nicolás Alvarez <nicolas.alvarez@gmail.com>
//
// SPDX-License-Identifier: GPL-2.0-or-later
#include <std/mem.pat>
#include <type/magic.pat>
#pragma endian big
#define SHOW_DATA 0
enum CompressionType: char {
ZLIB = 'z',
LZMA = 'x',
LZ4 = '4',
LZFSE = 'e'
};
struct Chunk {
u64 uncompressed_size;
u64 compressed_size;
if (SHOW_DATA) {
u8 data[compressed_size] [[sealed]];
} else {
padding[compressed_size];
}
};
struct PBZ {
type::Magic<"pbz"> magic;
CompressionType compression;
u64 chunk_size;
Chunk chunks[while(!std::mem::eof())];
};
PBZ pbz @ 0;

View File

@@ -1,140 +1,155 @@
#include <std/mem.pat>
#pragma MIME application/vnd.tcpdump.pcap
#pragma endian little
enum network_type : u32 {
LINKTYPE_NULL = 0,
LINKTYPE_ETHERNET = 1,
LINKTYPE_AX25 = 3,
LINKTYPE_IEEE802_5 = 6,
LINKTYPE_ARCNET_BSD = 7,
LINKTYPE_SLIP = 8,
LINKTYPE_PPP = 9,
LINKTYPE_FDDI = 10,
LINKTYPE_PPP_HDLC = 50,
LINKTYPE_PPP_ETHER = 51,
LINKTYPE_ATM_RFC1483 = 100,
LINKTYPE_RAW = 101,
LINKTYPE_C_HDLC = 104,
LINKTYPE_IEEE802_11 = 105,
LINKTYPE_FRELAY = 107,
LINKTYPE_LOOP = 108,
LINKTYPE_LINUX_SLL = 113,
LINKTYPE_LTALK = 114,
LINKTYPE_PFLOG = 117,
LINKTYPE_IEEE802_11_PRISM = 119,
LINKTYPE_IP_OVER_FC = 122,
LINKTYPE_SUNATM = 123,
LINKTYPE_IEEE802_11_RADIOTAP = 127,
LINKTYPE_ARCNET_LINUX = 129,
LINKTYPE_APPLE_IP_OVER_IEEE1394 = 138,
LINKTYPE_MTP2_WITH_PHDR = 139,
LINKTYPE_MTP2 = 140,
LINKTYPE_MTP3 = 141,
LINKTYPE_SCCP = 142,
LINKTYPE_DOCSIS = 143,
LINKTYPE_LINUX_IRDA = 144,
LINKTYPE_IEEE802_11_AVS = 163,
LINKTYPE_BACNET_MS_TP = 165,
LINKTYPE_PPP_PPPD = 166,
LINKTYPE_GPRS_LLC = 169,
LINKTYPE_GPF_T = 170,
LINKTYPE_GPF_F = 171,
LINKTYPE_LINUX_LAPD = 177,
LINKTYPE_MFR = 182,
LINKTYPE_BLUETOOTH_HCI_H4 = 187,
LINKTYPE_USB_LINUX = 189,
LINKTYPE_PPI = 192,
LINKTYPE_IEEE802_15_4_WITHFCS = 195,
LINKTYPE_SITA = 196,
LINKTYPE_ERF = 197,
LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR = 201,
LINKTYPE_AX25_KISS = 202,
LINKTYPE_LAPD = 203,
LINKTYPE_PPP_WITH_DIR = 204,
LINKTYPE_C_HDLC_WITH_DIR = 205,
LINKTYPE_FRELAY_WITH_DIR = 206,
LINKTYPE_LAPB_WITH_DIR = 207,
LINKTYPE_IPMB_LINUX = 209,
LINKTYPE_FLEXRAY = 210,
LINKTYPE_IEEE802_15_4_NONASK_PHY = 215,
LINKTYPE_USB_LINUX_MMAPPED = 220,
LINKTYPE_FC_2 = 224,
LINKTYPE_FC_2_WITH_FRAME_DELIMS = 225,
LINKTYPE_IPNET = 226,
LINKTYPE_CAN_SOCKETCAN = 227,
LINKTYPE_IPV4 = 228,
LINKTYPE_IPV6 = 229,
LINKTYPE_IEEE802_15_4_NOFCS = 230,
LINKTYPE_DBUS = 231,
LINKTYPE_DVB_CI = 235,
LINKTYPE_MUX27010 = 236,
LINKTYPE_STANAG_5066_D_PDU = 237,
LINKTYPE_NFLOG = 239,
LINKTYPE_NETANALYZER = 240,
LINKTYPE_NETANALYZER_TRANSPARENT = 241,
LINKTYPE_IPOIB = 242,
LINKTYPE_MPEG_2_TS = 243,
LINKTYPE_NG40 = 244,
LINKTYPE_NFC_LLCP = 245,
LINKTYPE_INFINIBAND = 247,
LINKTYPE_SCTP = 248,
LINKTYPE_USBPCAP = 249,
LINKTYPE_RTAC_SERIAL = 250,
LINKTYPE_BLUETOOTH_LE_LL = 251,
LINKTYPE_NETLINK = 253,
LINKTYPE_BLUETOOTH_LINUX_MONITOR = 254,
LINKTYPE_BLUETOOTH_BREDR_BB = 255,
LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR = 256,
LINKTYPE_PROFIBUS_DL = 257,
LINKTYPE_PKTAP = 258,
LINKTYPE_EPON = 259,
LINKTYPE_IPMI_HPM_2 = 260,
LINKTYPE_ZWAVE_R1_R2 = 261,
LINKTYPE_ZWAVE_R3 = 262,
LINKTYPE_WATTSTOPPER_DLM = 263,
LINKTYPE_ISO_14443 = 264,
LINKTYPE_RDS = 265,
LINKTYPE_USB_DARWIN = 266,
LINKTYPE_SDLC = 268,
LINKTYPE_LORATAP = 270,
LINKTYPE_VSOCK = 271,
LINKTYPE_NORDIC_BLE = 272,
LINKTYPE_DOCSIS31_XRA31 = 273,
LINKTYPE_ETHERNET_MPACKET = 274,
LINKTYPE_DISPLAYPORT_AUX = 275,
LINKTYPE_LINUX_SLL2 = 276,
LINKTYPE_OPENVIZSLA = 278,
LINKTYPE_EBHSCR = 279,
LINKTYPE_VPP_DISPATCH = 280,
LINKTYPE_DSA_TAG_BRCM = 281,
LINKTYPE_DSA_TAG_BRCM_PREPEND = 282,
LINKTYPE_IEEE802_15_4_TAP = 283,
LINKTYPE_DSA_TAG_DSA = 284,
LINKTYPE_DSA_TAG_EDSA = 285,
LINKTYPE_ELEE = 286,
LINKTYPE_Z_WAVE_SERIAL = 287,
LINKTYPE_USB_2_0 = 288,
LINKTYPE_ATSC_ALP = 289,
LINKTYPE_ETW = 290
LINKTYPE_NULL = 0,
LINKTYPE_ETHERNET = 1,
LINKTYPE_AX25 = 3,
LINKTYPE_IEEE802_5 = 6,
LINKTYPE_ARCNET_BSD = 7,
LINKTYPE_SLIP = 8,
LINKTYPE_PPP = 9,
LINKTYPE_FDDI = 10,
LINKTYPE_PPP_HDLC = 50,
LINKTYPE_PPP_ETHER = 51,
LINKTYPE_ATM_RFC1483 = 100,
LINKTYPE_RAW = 101,
LINKTYPE_C_HDLC = 104,
LINKTYPE_IEEE802_11 = 105,
LINKTYPE_FRELAY = 107,
LINKTYPE_LOOP = 108,
LINKTYPE_LINUX_SLL = 113,
LINKTYPE_LTALK = 114,
LINKTYPE_PFLOG = 117,
LINKTYPE_IEEE802_11_PRISM = 119,
LINKTYPE_IP_OVER_FC = 122,
LINKTYPE_SUNATM = 123,
LINKTYPE_IEEE802_11_RADIOTAP = 127,
LINKTYPE_ARCNET_LINUX = 129,
LINKTYPE_APPLE_IP_OVER_IEEE1394 = 138,
LINKTYPE_MTP2_WITH_PHDR = 139,
LINKTYPE_MTP2 = 140,
LINKTYPE_MTP3 = 141,
LINKTYPE_SCCP = 142,
LINKTYPE_DOCSIS = 143,
LINKTYPE_LINUX_IRDA = 144,
LINKTYPE_IEEE802_11_AVS = 163,
LINKTYPE_BACNET_MS_TP = 165,
LINKTYPE_PPP_PPPD = 166,
LINKTYPE_GPRS_LLC = 169,
LINKTYPE_GPF_T = 170,
LINKTYPE_GPF_F = 171,
LINKTYPE_LINUX_LAPD = 177,
LINKTYPE_MFR = 182,
LINKTYPE_BLUETOOTH_HCI_H4 = 187,
LINKTYPE_USB_LINUX = 189,
LINKTYPE_PPI = 192,
LINKTYPE_IEEE802_15_4_WITHFCS = 195,
LINKTYPE_SITA = 196,
LINKTYPE_ERF = 197,
LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR = 201,
LINKTYPE_AX25_KISS = 202,
LINKTYPE_LAPD = 203,
LINKTYPE_PPP_WITH_DIR = 204,
LINKTYPE_C_HDLC_WITH_DIR = 205,
LINKTYPE_FRELAY_WITH_DIR = 206,
LINKTYPE_LAPB_WITH_DIR = 207,
LINKTYPE_IPMB_LINUX = 209,
LINKTYPE_FLEXRAY = 210,
LINKTYPE_IEEE802_15_4_NONASK_PHY = 215,
LINKTYPE_USB_LINUX_MMAPPED = 220,
LINKTYPE_FC_2 = 224,
LINKTYPE_FC_2_WITH_FRAME_DELIMS = 225,
LINKTYPE_IPNET = 226,
LINKTYPE_CAN_SOCKETCAN = 227,
LINKTYPE_IPV4 = 228,
LINKTYPE_IPV6 = 229,
LINKTYPE_IEEE802_15_4_NOFCS = 230,
LINKTYPE_DBUS = 231,
LINKTYPE_DVB_CI = 235,
LINKTYPE_MUX27010 = 236,
LINKTYPE_STANAG_5066_D_PDU = 237,
LINKTYPE_NFLOG = 239,
LINKTYPE_NETANALYZER = 240,
LINKTYPE_NETANALYZER_TRANSPARENT = 241,
LINKTYPE_IPOIB = 242,
LINKTYPE_MPEG_2_TS = 243,
LINKTYPE_NG40 = 244,
LINKTYPE_NFC_LLCP = 245,
LINKTYPE_INFINIBAND = 247,
LINKTYPE_SCTP = 248,
LINKTYPE_USBPCAP = 249,
LINKTYPE_RTAC_SERIAL = 250,
LINKTYPE_BLUETOOTH_LE_LL = 251,
LINKTYPE_NETLINK = 253,
LINKTYPE_BLUETOOTH_LINUX_MONITOR = 254,
LINKTYPE_BLUETOOTH_BREDR_BB = 255,
LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR = 256,
LINKTYPE_PROFIBUS_DL = 257,
LINKTYPE_PKTAP = 258,
LINKTYPE_EPON = 259,
LINKTYPE_IPMI_HPM_2 = 260,
LINKTYPE_ZWAVE_R1_R2 = 261,
LINKTYPE_ZWAVE_R3 = 262,
LINKTYPE_WATTSTOPPER_DLM = 263,
LINKTYPE_ISO_14443 = 264,
LINKTYPE_RDS = 265,
LINKTYPE_USB_DARWIN = 266,
LINKTYPE_SDLC = 268,
LINKTYPE_LORATAP = 270,
LINKTYPE_VSOCK = 271,
LINKTYPE_NORDIC_BLE = 272,
LINKTYPE_DOCSIS31_XRA31 = 273,
LINKTYPE_ETHERNET_MPACKET = 274,
LINKTYPE_DISPLAYPORT_AUX = 275,
LINKTYPE_LINUX_SLL2 = 276,
LINKTYPE_OPENVIZSLA = 278,
LINKTYPE_EBHSCR = 279,
LINKTYPE_VPP_DISPATCH = 280,
LINKTYPE_DSA_TAG_BRCM = 281,
LINKTYPE_DSA_TAG_BRCM_PREPEND = 282,
LINKTYPE_IEEE802_15_4_TAP = 283,
LINKTYPE_DSA_TAG_DSA = 284,
LINKTYPE_DSA_TAG_EDSA = 285,
LINKTYPE_ELEE = 286,
LINKTYPE_Z_WAVE_SERIAL = 287,
LINKTYPE_USB_2_0 = 288,
LINKTYPE_ATSC_ALP = 289,
LINKTYPE_ETW = 290
};
struct pcaprec_hdr_t {
u32 ts_sec; /* timestamp seconds */
u32 ts_usec; /* timestamp microseconds */
u32 incl_len; /* number of octets of packet saved in file */
u32 orig_len; /* actual length of packet */
u8 data[incl_len];
enum magic : u32 {
BE = 0xA1B2C3D4,
LE = 0xD4C3B2A1
};
struct pcap_hdr_t {
u32 magic_number; /* magic number */
u16 version_major; /* major version number */
u16 version_minor; /* minor version number */
s32 thiszone; /* GMT to local correction */
u32 sigfigs; /* accuracy of timestamps */
u32 snaplen; /* max length of captured packets, in octets */
network_type network; /* data link type */
pcaprec_hdr_t packet[1000];
struct pcap_record_t {
u32 ts_sec; /* timestamp seconds */
u32 ts_usec; /* timestamp microseconds */
u32 incl_len; /* number of octets of packet saved in file */
u32 orig_len; /* actual length of packet */
u8 data[incl_len];
};
pcap_hdr_t pcap @ 0x00;
struct pcap_header_t {
u16 version_major; /* major version number */
u16 version_minor; /* minor version number */
s32 thiszone; /* GMT to local correction */
u32 sigfigs; /* accuracy of timestamps */
u32 snaplen; /* max length of captured packets, in octets */
network_type network; /* data link type */
};
struct pcap {
be magic magic_number;
if (magic_number == magic::BE) {
be pcap_header_t header;
be pcap_record_t packet[while(!std::mem::eof())];
} else {
le pcap_header_t header;
le pcap_record_t packet[while(!std::mem::eof())];
}
};
pcap pcap @ 0x00;

52
patterns/pcx.hexpat Normal file
View File

@@ -0,0 +1,52 @@
#pragma MIME application/x-pcx
#include <std/io.pat>
enum Encoding : u8 {
NoEncoding = 0x00,
RunLengthEncoding = 0x01
};
enum PaletteType : u16 {
MonochromeOrColorInformation = 0x01,
GrayscaleInformation = 0x02
};
enum Version : u8 {
V2_5 = 0x00,
V2_8WithPalette = 0x02,
V2_8_WithoutPalette = 0x03,
PaintbrushForWindows = 0x04,
V3_0 = 0x05
};
struct Header {
u8 magic;
Version version;
Encoding encoding;
u8 bitsPerPixel;
u16 xMin, yMin;
u16 xMax, yMax;
u16 hdpi, vdpi;
};
struct RGB8 {
u8 r, g, b;
} [[sealed, color(std::format("{:02X}{:02X}{:02X}", this.r, this.g, this.b))]];
struct Palette {
RGB8 color[16];
};
struct PCX {
Header header;
Palette palette;
padding[1];
u8 numPlanes;
u16 bytesPerLine;
PaletteType paletteType;
u16 hres, vres;
padding[54];
};
PCX pcx @ 0x00;

File diff suppressed because it is too large Load Diff

38
patterns/pfs0.hexpat Normal file
View File

@@ -0,0 +1,38 @@
#include <type/magic.pat>
#include <type/size.pat>
#include <std/core.pat>
struct FileEntry {
u64 dataOffset;
type::Size<u64> dataSize;
u32 nameOffset;
padding[4];
};
struct String {
char value[];
};
struct Header {
type::Magic<"PFS0"> magic;
u32 numFiles;
type::Size<u32> stringTableSize;
padding[4];
FileEntry fileEntryTable[numFiles];
String strings[numFiles];
};
struct File {
char name[] @ addressof(parent.header.strings) + parent.header.fileEntryTable[std::core::array_index()].nameOffset;
u8 data[parent.header.fileEntryTable[std::core::array_index()].dataSize] @ parent.header.fileEntryTable[std::core::array_index()].dataOffset [[sealed]];
};
struct PFS0 {
Header header;
File files[header.numFiles];
};
PFS0 pfs0 @ 0x00;

76
patterns/pif.hexpat Normal file
View File

@@ -0,0 +1,76 @@
/* PIF - Portable Image Format
*
* Basic decoder for the PIF file structure
* https://github.com/gfcwfzkm/PIF-Image-Format
*/
#pragma MIME image/pif
#pragma endian little
enum imageType_t : u16 {
RGB888 = 0x433C,
RGB565 = 0xE5C5,
RGB332 = 0x1E53,
RGB16C = 0xB895,
BLWH = 0x7DAA,
IND24 = 0x4952,
IND16 = 0x4947,
IND8 = 0x4942
};
enum compression_t : u16 {
NO_COMPRESSION = 0,
RLE_COMPRESSION = 0x7DDE
};
struct PIFFileHeader {
char Signature[4];
u32 FileSize;
u32 ImageOffset;
};
struct PIFInfoHeader {
imageType_t ImageType;
u16 BitsPerPixel;
u16 ImageWidth;
u16 ImageHeight;
u32 ImageSize;
u16 ColorTableSize;
compression_t Compression;
};
struct PIF {
PIFFileHeader PIF_FileHeader;
PIFInfoHeader PIF_ImageHeader;
if (PIF_ImageHeader.ImageType == imageType_t::IND24)
{
u24 ColorTable[PIF_ImageHeader.ColorTableSize/3];
}
else if (PIF_ImageHeader.ImageType == imageType_t::IND16)
{
u16 ColorTable[PIF_ImageHeader.ColorTableSize/2];
}
else if (PIF_ImageHeader.ImageType == imageType_t::IND8)
{
u8 ColorTable[PIF_ImageHeader.ColorTableSize];
}
if ((PIF_ImageHeader.ImageType == imageType_t::RGB888) ||
(PIF_ImageHeader.ImageType == imageType_t::IND24))
{
u24 ImageData[(PIF_FileHeader.FileSize - PIF_FileHeader.ImageOffset)/3];
}
else if ((PIF_ImageHeader.ImageType == imageType_t::RGB565) ||
(PIF_ImageHeader.ImageType == imageType_t::IND16))
{
u16 ImageData[(PIF_FileHeader.FileSize - PIF_FileHeader.ImageOffset)/2];
}
else if ((PIF_ImageHeader.ImageType == imageType_t::RGB332) ||
(PIF_ImageHeader.ImageType == imageType_t::IND8))
{
u8 ImageData[(PIF_FileHeader.FileSize - PIF_FileHeader.ImageOffset)/1];
}
};
PIF pif @ 0x00;

View File

@@ -1,36 +1,90 @@
#pragma MIME image/png
#pragma endian big
struct header_t
{
struct header_t {
u8 highBitByte;
char signature[3];
char dosLineEnding[2];
char dosEOF;
char unixLineEnding;
char signature[3];
char dosLineEnding[2];
char dosEOF;
char unixLineEnding;
};
struct ihdr_t
{
struct actl_t {
u32 frames [[comment("Total № of frames in animation")]];
u32 plays [[comment("№ of times animation will loop")]];
} [[comment("Animation control chunk"), name("acTL")]];
enum ColorType: u8 {
Grayscale = 0x0,
RGBTriple = 0x2,
Palette,
GrayscaleAlpha,
RGBA = 0x6
};
enum Interlacing: u8 {
None,
Adam7
};
struct ihdr_t {
u32 width [[comment("Image width")]];
u32 height [[comment("Image height")]];
u8 bit_depth;
u8 color_type [[comment("PNG Image Type\n0: greyscale\n2: truecolour\n3: indexed-color\n4: greyscale with alpha\n6: truecolour with alpha")]];
u8 compression_method;
u8 filter_method;
u8 interlace_method [[comment("values 0 \"no interlace\" or 1 \"Adam7 interlace\"")]];
ColorType color_type [[comment("PNG Image Type")]];
u8 compression_method [[comment("Only 0x0 = zlib supported by most")]];
u8 filter_method [[comment("Only 0x0 = adaptive supported by most")]];
Interlacing interlacing;
};
struct palette_entry_t {
u8 r;
u8 g;
u8 b;
enum sRGB: u8 {
Perceptual = 0x0,
RelativeColorimetric,
Saturation,
AbsoluteColorimetric
};
enum Unit: u8 {
Unknown,
Meter
};
struct phys_t {
u32 ppu_x [[comment("Pixels per unit, X axis")]];
u32 ppu_y [[comment("Pixels per unit, Y axis")]];
u8 unit [[comment("Unit Specifier\n0: unit is unknown\n1: unit is the metre")]];
Unit unit;
};
enum BlendOp: u8 {
Source = 0x0,
Over
};
enum DisposeOp: u8 {
None = 0x0,
Background,
Previous
};
struct fctl_t {
u32 sequence_no [[comment("Sequence №")]];
u32 width [[comment("Frame width")]];
u32 height;
u32 xoff;
u32 yoff;
u16 delay_num;
u16 delay_den;
DisposeOp dispose_op;
BlendOp blend_op;
};
struct fdat_t {
u32 sequence_no;
};
fn text_len() {
u64 len = parent.parent.length - ($ - addressof(parent.keyword));
return len;
};
struct itxt_t {
@@ -39,48 +93,92 @@ struct itxt_t {
u8 compression_method;
char language_tag[];
char translated_keyword[];
char text[parent.length - ($ - addressof(keyword))];
char text[text_len()];
};
struct ztxt_t {
char keyword[];
u8 compression_method;
char text[text_len()];
};
struct text_t {
char keyword[];
char text[text_len()];
};
struct iccp_t {
char profile [];
u8 compression_method;
u8 compressed_profile[parent.length - ($ - addressof(profile))];
char keyword[];
u8 compression_method;
u8 compressed_profile[text_len()];
};
struct palette_entry_t {
u24 color;
} [[inline]];
struct chunk_t {
u32 length [[color("17BECF")]];
char type[4];
char name[4];
#define IHDR_k "IHDR"
#define PLTE_k "PLTE"
#define sRGB_k "sRGB"
#define pHYs_k "pHYs"
#define iTXt_k "iTXt"
#define tEXt_k "tEXt"
#define zTXt_k "zTXt"
#define IDAT_k "IDAT"
#define IEND_k "IEND"
#define gAMA_k "gAMA"
#define iCCP_k "iCCP"
#define acTL_k "acTL"
#define fdAT_k "fdAT"
#define fcTL_k "fcTL"
if (type == IHDR_k) {
if (name == IHDR_k) {
ihdr_t ihdr [[comment("Image Header chunk"), name("IHDR")]];
} else if (type == PLTE_k) {
} else if (name == PLTE_k) {
palette_entry_t entries[length / 3];
} else if (type == pHYs_k) {
} else if (name == sRGB_k) {
sRGB srgb;
} else if (name == pHYs_k) {
phys_t phys;
} else if (type == iTXt_k) {
} else if (name == acTL_k) {
actl_t actl [[comment("Animation control chunk")]];
} else if (name == fcTL_k) {
fctl_t fctl [[comment("Frame control chunk")]];
} else if (name == iTXt_k) {
itxt_t text;
} else if (type == gAMA_k) {
} else if (name == gAMA_k) {
u32 gamma [[name("image gamma"), comment("4 byte unsigned integer representing gamma times 100000")]];
} else if (type == iCCP_k) {
} else if (name == iCCP_k) {
iccp_t iccp;
} else if (name == tEXt_k) {
text_t text;
} else if (name == zTXt_k) {
ztxt_t text;
} else if (name == iCCP_k) {
iccp_t iccp;
} else if (name == fdAT_k) {
fdat_t fdat [[comment("Frame data chunk")]];
u8 data[length-sizeof(u32)];
} else {
u8 data[length];
}
u32 crc;
} [[format("chunkValueName")]];
fn chunkValueName(ref chunk_t chunk) {
return chunk.name;
};
struct chunk_set {
chunk_t chunks[while(builtin::std::mem::read_string($ + 4, 4) != "IEND")] [[inline]];
} [[inline]];
header_t header @ 0x00 [[comment("PNG file signature"), name("Signature")]];
chunk_t ihdr_chunk @ 0x08 [[comment("PNG Header chunk"), name("IHDR")]];
chunk_t chunk_set[while(builtin::std::mem::read_string($ + 4, 4) != "IEND")] @ $ [[comment("PNG file chunks"), name("Chunks"), inline]];
chunk_t iend_chunk @ $ [[name("IEND"), comment("Image End Chunk")]];
chunk_set set @ $ [[comment("PNG Chunks"), name("Chunks"), inline]];
chunk_t iend_chunk @ $ [[comment("Image End Chunk"), name("IEND")]];

View File

@@ -1,66 +1,67 @@
#include <std/mem.pat>
#include <type/leb128.pat>
struct ZigZag32 {
u32 value;
} [[sealed, format("format_zigzag32")]];
fn format_zigzag32(ZigZag32 zigzag) {
return s32((s32(zigzag.value) << 1) ^ (s32(zigzag.value) >> 31));
};
struct ZigZag64 {
u64 value;
} [[sealed, format("format_zigzag64")]];
fn format_zigzag64(ZigZag64 zigzag) {
return s64((s64(zigzag.value) << 1) ^ (s64(zigzag.value) >> 63));
};
enum WireType : u8 {
Varint = 0,
_64Bit = 1,
LengthDelimited = 2,
StartGroup = 3,
EndGroup = 4,
_32Bit = 5
};
bitfield Key {
field_number : 5;
wire_type : 3;
} [[left_to_right]];
union _64Bit {
u64 fixed64;
ZigZag64 sfixed64;
double dbl;
};
union _32Bit {
u32 fixed32;
ZigZag32 sfixed32;
float flt;
};
struct LengthDelimited {
type::LEB128 length;
char data[length];
};
struct Entry {
Key key;
if (key.wire_type == WireType::Varint)
type::LEB128 value;
else if (key.wire_type == WireType::_64Bit)
_64Bit value;
else if (key.wire_type == WireType::LengthDelimited)
LengthDelimited value;
else if (key.wire_type == WireType::_32Bit)
_32Bit value;
};
Entry entries[while(!std::mem::eof())] @ 0x00;
#include <std/core.pat>
#include <std/mem.pat>
#include <type/leb128.pat>
struct ZigZag32 {
u32 value;
} [[sealed, format("format_zigzag32")]];
fn format_zigzag32(ZigZag32 zigzag) {
return s32((s32(zigzag.value) << 1) ^ (s32(zigzag.value) >> 31));
};
struct ZigZag64 {
u64 value;
} [[sealed, format("format_zigzag64")]];
fn format_zigzag64(ZigZag64 zigzag) {
return s64((s64(zigzag.value) << 1) ^ (s64(zigzag.value) >> 63));
};
enum WireType : u8 {
Varint = 0,
_64Bit = 1,
LengthDelimited = 2,
StartGroup = 3,
EndGroup = 4,
_32Bit = 5
};
bitfield Key {
field_number : 5;
wire_type : 3;
} [[bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 8)]];
union _64Bit {
u64 fixed64;
ZigZag64 sfixed64;
double dbl;
};
union _32Bit {
u32 fixed32;
ZigZag32 sfixed32;
float flt;
};
struct LengthDelimited {
type::LEB128 length;
char data[length];
};
struct Entry {
Key key;
if (key.wire_type == WireType::Varint)
type::LEB128 value;
else if (key.wire_type == WireType::_64Bit)
_64Bit value;
else if (key.wire_type == WireType::LengthDelimited)
LengthDelimited value;
else if (key.wire_type == WireType::_32Bit)
_32Bit value;
};
Entry entries[while(!std::mem::eof())] @ 0x00;

80
patterns/qbcl.hexpat Normal file
View File

@@ -0,0 +1,80 @@
// Qubicle QBCL format
struct String {
u32 len;
char string[len];
};
struct Matrix {
u32 sizex;
u32 sizey;
u32 sizez;
s32 tx;
s32 ty;
s32 tz;
float pivotx;
float pivoty;
float pivotz;
u32 compressedDataSize;
u8 zip[compressedDataSize];
};
// Rotation matrix according to wikipedia
// https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
struct Matrices {
float row1[3];
float row2[3];
float row3[3];
};
using Node;
struct Model {
Matrices rotation;
u32 childCount;
Node nodes[childCount];
};
struct Compound {
Matrix matrix;
u32 childCount;
Node nodes[childCount];
};
struct Node {
u32 type;
u32 unknown;
String name;
u8 visible;
u8 unknown2;
u8 locked;
if (type == 0) {
Matrix matrix;
} else if (type == 1) {
Model model;
} else if (type == 2) {
Compound compound;
}
};
struct Header {
u32 magic;
u32 version;
u32 fileversion;
u32 thumbwidth;
u32 thumbheight;
char bgra[thumbwidth * thumbheight * 4];
String title;
String desc;
String metadata;
String author;
String company;
String website;
String copyright;
// Maybe change and creation time?
double time1;
double time2;
Node node;
};
Header hdr @0x00;

98
patterns/qoi.hexpat Normal file
View File

@@ -0,0 +1,98 @@
#pragma MIME image/qoi
#pragma endian big
#include <std/mem.pat>
namespace qoi {
enum channels_t : u8 {
RGB = 3,
RGBA = 4
};
enum color_space_t : u8 {
sRGB = 0,
linear = 1
};
struct header_t {
char magic[4];
u32 width;
u32 height;
channels_t channels;
color_space_t color_space;
};
enum tags_t : u8 {
index = 0b00000000 ... 0b00111111,
diff = 0b01000000 ... 0b01111111,
luma = 0b10000000 ... 0b10111111,
run = 0b11000000 ... 0b11111101,
rgb = 0b11111110,
rgba = 0b11111111,
};
bitfield op_index {
tag: 2;
index: 6;
} [[color("0000FF")]];
bitfield op_diff {
tag: 2;
dr: 2;
dg: 2;
db: 2;
} [[color("FFFFFF")]];
bitfield op_luma {
tag: 2;
diff_green: 6;
dr_dg: 4;
db_dg: 4;
} [[color("FFFF00")]];
bitfield op_run {
tag: 2;
run_length: 6;
} [[color("00FF00")]];
struct op_rgb {
u8 tag;
u8 red;
u8 green;
u8 blue;
} [[color("FF7700")]];
struct op_rgba {
u8 tag;
u8 red;
u8 green;
u8 blue;
u8 alpha;
} [[color("FF0000")]];
u8 op_type;
fn get_op_type() {
op_type = std::mem::read_unsigned($, 1);
if (op_type < tags_t::rgb)
op_type &= 0b11000000;
};
struct op_t {
qoi::get_op_type();
if (op_type == tags_t::index) op_index;
else if (op_type == tags_t::diff) op_diff;
else if (op_type == tags_t::luma) op_luma;
else if (op_type == tags_t::run) op_run;
else if (op_type == tags_t::rgb) op_rgb;
else if (op_type == tags_t::rgba) op_rgba;
};
struct file_t {
header_t header;
op_t data[while(!std::mem::eof())];
};
} // namespace qoi
qoi::file_t qoi_picture @ 0x0;

115
patterns/sit5.hexpat Normal file
View File

@@ -0,0 +1,115 @@
// Based on https://github.com/mietek/theunarchiver/wiki/StuffIt5Format and https://github.com/ParksProjets/Maconv/blob/master/docs/stuffit/Stuffit_v5.md
#pragma endian big
#pragma MIME application/x-stuffit
#include <std/io.pat>
#include <std/time.pat>
namespace v5 {
bitfield Flags1 {
padding : 1;
folder : 1;
encrypted : 1;
padding : 5;
};
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 @@
#include <std/mem.pat>
enum GeneratorID : u16 {
Khronos = 0,
LunarG = 1,
@@ -642,4 +644,4 @@ struct Instruction {
Header header @ 0x00;
// SPIR-V does not have any footer, increase number of instructions manually if you encounter a bigger shader
Instruction instructions[1024] @ 0x14;
Instruction instructions[while (!std::mem::eof())] @ 0x14;

View File

@@ -5,34 +5,47 @@
#include <std/sys.pat>
#include <std/mem.pat>
#include <std/core.pat>
struct Vector3f {
float x, y, z;
float x, y, z;
} [[static, format("format_vector3f")]];
fn format_vector3f(Vector3f vec) {
return std::format("[ {}, {}, {} ]", vec.x, vec.y, vec.z);
return std::format("[ {}, {}, {} ]", vec.x, vec.y, vec.z);
};
struct Triangle {
Vector3f normal;
Vector3f points[3];
u16 flags;
Vector3f normal;
Vector3f points[3];
u16 flags;
} [[static]];
struct BinarySTLHeader {
char caption[];
padding[80 - sizeof(caption)];
u32 triangleCount;
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];
}
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;
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;

89
patterns/tar.hexpat Normal file
View File

@@ -0,0 +1,89 @@
#pragma MIME application/tar
#pragma MIME application/x-tar
#pragma endian little
#include <std/string.pat>
#include <std/time.pat>
#include <std/mem.pat>
#include <std/sys.pat>
#define GNU_HEADER "ustar "
#define PAX_HEADER "ustar\x00"
#define NULL "\x00"
fn octal_to_decimal(str value) {
return std::string::parse_int(value, 8);
};
fn get_time(str time) {
std::time::EpochTime epochtime = octal_to_decimal(time);
std::time::Time localtime = std::time::to_local(epochtime);
return std::time::format(localtime, "%c");
};
enum typeflagenum : char {
regular = '0',
also_regular = '\x00',
link_to_another_file_already_archived = '1',
symbolic_link = '2',
character_special_device = '3',
block_special_device = '4',
directory = '5',
fifo_special_file = '6',
reserved = '7'
};
struct posix_header {
char name[100] [[name("file name")]];
char mode[8] [[name("file mode")]];
char uid[8] [[name("user id of the file")]];
char gid[8] [[name("group if of the file")]];
char size[12] [[name("size of the file in octal")]];
char mtime[12] [[name("modified time of file in epoch time")]];
char chksum[8] [[name("checksum")]];
typeflagenum typeflag [[name("type of file")]];
char linkname[100] [[name("name of link")]];
char magic[6] [[name("magic bytes that identifies the 'file version'")]];
char version[2] [[name("version (also used with magic bytes)")]];
char uname[32] [[name("username of the owner of the file")]];
char gname[32] [[name("group name of the owner of the file")]];
char devmajor[8] [[name("major device numbers")]];
char devminor[8] [[name("minor device numbers")]];
char prefix[155] [[name("filename prefix")]];
char reserved[12] [[name("reserved")]];
};
struct tar {
posix_header header_raw;
char file[octal_to_decimal(header_raw.size)];
std::print("-" * 50);
std::print("File Name: {}", header_raw.name);
std::print("File Permissions: {}" , header_raw.mode);
std::print("UID: {}", header_raw.uid);
std::print("GUID: {}", header_raw.gid);
std::print("Size: {} bytes", octal_to_decimal(header_raw.size));
std::print("Modified Time: {}", get_time(header_raw.mtime));
std::print("Checksum: {}", header_raw.chksum);
std::print("Type of File: {}", header_raw.typeflag);
std::print("Magic Bytes: {}", header_raw.magic);
std::print("Version: {}", header_raw.version);
std::print("uname: {}", header_raw.uname);
std::print("gname: {}", header_raw.gname);
std::print("devmajor: {}", header_raw.devmajor);
std::print("devminor: {}", header_raw.devminor);
std::print("prefix: {}", header_raw.prefix);
char empty[while (std::mem::read_string($, 1) == NULL && !std::mem::eof())];
if (std::mem::eof()) {
break;
}
};
char magic[6] @ 0x00000101 [[hidden]];
std::assert(magic == PAX_HEADER || magic == GNU_HEADER, "Magic bytes are not correct! Perhaps wrong file?");
tar tar[while(!std::mem::eof())] @ 0x000;

View File

@@ -72,7 +72,7 @@ struct Footer {
u32 developerDirectoryOffset;
char signature[0x10];
char dot;
char null;
char zero;
};
Header header @ 0x0;

67
patterns/uefi.hexpat Normal file
View File

@@ -0,0 +1,67 @@
#pragma MIME data
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0
#define WIN_CERT_TYPE_EFI_GUID 0x0EF1
struct EFI_TIME {
u16 Year; // 1900 9999
u8 Month; // 1 12
u8 Day; // 1 31
u8 Hour; // 0 23
u8 Minute; // 0 59
u8 Second; // 0 59
u8 Pad1;
u32 Nanosecond; // 0 999,999,999
s16 TimeZone; // -1440 to 1440 or 2047
u8 Daylight;
u8 Pad2;
};
struct EFI_GUID {
u32 Data1;
u16 Data2;
u16 Data3;
u8 Data4[8];
};
struct WIN_CERTIFICATE {
u32 Length;
u16 Revision;
u16 CertificateType;
//u8 Certificate[];
};
struct WIN_CERTIFICATE_UEFI_GUID {
WIN_CERTIFICATE Hdr;
EFI_GUID CertType;
u8 CertData[Hdr.Length-SizeofWIN_CERTIFICATE_UEFI_GUID];
};
#define SizeofWIN_CERTIFICATE_UEFI_GUID 24
struct EFI_VARIABLE_AUTHENTICATION_2 {
EFI_TIME TimeStamp;
WIN_CERTIFICATE_UEFI_GUID AuthInfo;
};
struct EFI_SIGNATURE_DATA {
EFI_GUID SignatureOwner;
u8 SignatureData[1076];
};
struct EFI_SIGNATURE_LIST {
EFI_GUID SignatureType;
u32 SignatureListSize;
u32 SignatureHeaderSize;
u32 SignatureSize;
u8 SignatureHeader[SignatureHeaderSize];
EFI_SIGNATURE_DATA Signatures;
};
struct dbx_esl {
EFI_VARIABLE_AUTHENTICATION_2 Auth;
EFI_SIGNATURE_LIST x509_1;
};
dbx_esl header @ 0x00;

272
patterns/usb.hexpat Normal file
View File

@@ -0,0 +1,272 @@
#include <std/core.pat>
#include <std/io.pat>
#include <std/mem.pat>
#include <std/string.pat>
using BitfieldOrder = std::core::BitfieldOrder;
enum DescriptorType : u8 {
DeviceDescriptor = 0x01,
ConfigDescriptor = 0x02,
StringDescriptor = 0x03,
InterfaceDescriptor = 0x04,
EndpointDescriptor = 0x05,
DeviceQualifierDescriptor = 0x06,
OtherSpeedConfigurationDescriptor = 0x07,
InterfacePowerDescriptor = 0x08,
OTGDescriptor = 0x09,
DebugDescriptor = 0x0A,
InterfaceAssociationDescriptor = 0x0B,
HIDDescriptor = 0x21,
ReportDescriptor = 0x22,
PhysicalDescriptor = 0x23
};
enum InterfaceClass : u8 {
UseClassInformationInInterfaceDescriptors = 0x00,
Audio = 0x01,
CommunicationAndCDCControl = 0x02,
HID = 0x03,
Physical = 0x05,
Image = 0x06,
Printer = 0x07,
MassStorage = 0x08,
Hub = 0x09,
CDCData = 0x0A,
SmartCard = 0x0B,
ContentSecurity = 0x0C,
Video = 0x0E,
PersonalHealthcare = 0x0F,
AudioVideoDevice = 0x10,
BillboardDevice = 0x11,
USBTypeCBridge = 0x12,
I3CDevice = 0x3C,
DiagnosticDevice = 0xDC,
WirelessController = 0xE0,
Miscellaneous = 0xEF,
ApplicationSpecific = 0xFE,
VendorSpecific = 0xFF
};
enum CountryCode : u8 {
NotSupported = 0,
Arabic = 1,
Belgian = 2,
CanadianBilingual = 3,
CanadianFrench = 4,
CzechRepublic = 5,
Danish = 6,
Finnish = 7,
French = 8,
German = 9,
Greek = 10,
Hebrew = 11,
Hungary = 12,
International = 13,
Italian = 14,
JapanKatakana = 15,
Korean = 16,
LatinAmerican = 17,
Dutch = 18,
Norwegian = 19,
PersianFarsi = 20,
Polish = 21,
Portuguese = 22,
Russian = 23,
Slovakian = 24,
Spanish = 25,
Swedish = 26,
SwissFrench = 27,
SwissGerman = 28,
Switzerland = 29,
Taiwan = 30,
TurkishQ = 31,
EnglishUK = 32,
EnglishUS = 33,
Yugoslavian = 34,
TurkishF = 35,
Reserved = 36 ... 255
};
enum HubInterfaceSubClass : u8 {
Hub = 0x00
};
enum AudioVideoDeviceSubClass : u8 {
AVControlInterface = 0x01,
AVDataVideoStreamingInterface = 0x02,
AVDataAudioStreamingInterface = 0x03
};
enum HubInterfaceProtocol : u8 {
FullSpeedHub = 0x00,
HiSpeedHubWithSingleTT = 0x01,
HiSpeedHubWithMultipleTTs = 0x02
};
struct Ampere {
u8 amps;
} [[sealed, format("format_ampere")]];
fn format_ampere(Ampere ampere) {
return std::format("{} mA", ampere.amps * 2);
};
bitfield ConfigAttributes {
padding : 1;
SelfPowered : 1;
RemoteWakeup : 1;
padding : 5;
} [[bitfield_order(BitfieldOrder::MostToLeastSignificant, 8)]];
struct BCD<auto Size> {
u8 bytes[Size];
} [[sealed, format("format_bcd")]];
fn format_bcd(ref auto bcd) {
str result;
for (s8 i = sizeof(bcd.bytes) - 1, i >= 0, i -= 1)
result += std::format("{:X}.", bcd.bytes[i]);
return std::string::substr(result, 0, std::string::length(result) - 1);
};
struct DeviceDescriptor {
BCD<2> bcdUSB;
InterfaceClass bDeviceClass;
if (bDeviceClass == InterfaceClass::Hub) {
HubInterfaceSubClass bDeviceSubClass;
if (bDeviceSubClass == HubInterfaceSubClass::Hub)
HubInterfaceProtocol bDeviceSubClass;
else
u8 bDeviceSubClass;
} else if (bDeviceClass == InterfaceClass::AudioVideoDevice) {
AudioVideoDeviceSubClass bDeviceSubClass;
u8 bDeviceSubClass;
} else {
u8 bDeviceSubClass;
}
};
struct ConfigDescriptor {
u16 wTotalLength;
u8 bNumInterfaces;
u8 bConfigurationValue;
u8 iConfiguration;
ConfigAttributes bmAttributes;
Ampere bMaxPower;
};
struct StringDescriptor {
char bString[parent.bLength - 2];
};
struct InterfaceDescriptor {
u8 bInterfaceNumber;
u8 bAlternateSetting;
u8 bNumEndpoints;
InterfaceClass bInterfaceClass;
if (bInterfaceClass == InterfaceClass::Hub) {
HubInterfaceSubClass bInterfaceSubClass;
if (bInterfaceSubClass == HubInterfaceSubClass::Hub)
HubInterfaceProtocol bInterfaceProtocol;
else
u8 bInterfaceProtocol;
} else if (bInterfaceClass == InterfaceClass::AudioVideoDevice) {
AudioVideoDeviceSubClass bInterfaceSubClass;
u8 bInterfaceProtocol;
} else {
u8 bInterfaceSubClass;
u8 bInterfaceProtocol;
}
u8 iInterface;
};
enum EndpointDirection : u8 {
OUT = 0,
IN = 1
};
fn format_direction(u8 value) {
EndpointDirection direction;
direction = value;
return direction;
};
bitfield EndpointAddress {
EndpointNumber : 4;
padding : 3;
Direction : 1 [[format("format_direction")]];
};
bitfield EndpointAttributes {
TransferType : 2;
SynchronizationType : 2;
UsageType : 2;
};
struct EndpointDescriptor {
EndpointAddress bEndPointAddress;
EndpointAttributes bmAttributes;
u16 wMaxPacketSize;
u8 bInterval;
};
struct OtherSpeedConfigurationDescriptor {
ConfigDescriptor content [[inline]];
};
struct DeviceQualifierDescriptor {
DeviceDescriptor deviceDescriptor [[inline]];
u8 bMaxPacketSize0;
u8 bNumConfigurations;
padding[1];
};
bitfield OTGAttributes {
SRPSupport : 1;
HNPSupport : 1;
} [[right_to_left]];
struct OTGDescriptor {
OTGAttributes bmAttributes;
};
struct HIDDescriptor {
BCD<2> bcdVersion;
CountryCode bCountryCode;
u8 bNumDescriptors;
DescriptorType bDescriptorType;
u16 wDescriptorLength;
};
struct USBDescriptor {
u8 bLength;
DescriptorType bDescriptorType;
if (bDescriptorType == DescriptorType::DeviceDescriptor)
DeviceDescriptor deviceDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::ConfigDescriptor)
ConfigDescriptor configDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::StringDescriptor)
StringDescriptor stringDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::InterfaceDescriptor)
InterfaceDescriptor interfaceDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::EndpointDescriptor)
EndpointDescriptor endpointDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::OtherSpeedConfigurationDescriptor)
OtherSpeedConfigurationDescriptor otherSpeedConfigurationDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::DeviceQualifierDescriptor)
DeviceQualifierDescriptor deviceQualifierDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::OTGDescriptor)
OTGDescriptor otgDescriptor [[inline]];
else if (bDescriptorType == DescriptorType::HIDDescriptor)
HIDDescriptor hidDescriptor [[inline]];
padding[bLength - ($ - addressof(this))];
};
USBDescriptor descriptors[while(!std::mem::eof())] @ 0x00;

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