Compare commits

..

415 Commits

Author SHA1 Message Date
Stéphane Bisinger
a534e2a23b Add missing #pragma once to includes (#494) 2026-02-07 12:58:31 -07:00
MrClock
525f3ad4d6 patterns/magic: Add more Arma 3 files (#479)
* patterns/texheaders: Added pattern for Arma 3 texHeaders.bin

* magic/arma3: Added texHeaders.bin magic

* patterns/texheaders: Added test file

* patterns/paa: Small improvements

Added extra data description, and better indication of internally compressed data mipmap data.

* patterns/a3: Moved Arma 3 patterns into common folder

* patterns/a3: Added pattern for MLOD P3D

* patterns/a3: Added pattern for RAP

* magic/arma3: Added P3D and RAP to magic file

* patterns/a3: Added test files for P3D and RAP

* patterns/a3: Small correction to type names in TexHeaders format
2026-02-04 07:35:57 +01:00
gmestanley
27480b1da9 encodings: Removing control characters from TBLs (#481)
* Removing control characters from TBLs

* Delete patterns/gbk.tbl

* Delete patterns/jis_x_0211.tbl

* Delete patterns/euc_jp.tbl

* Add files via upload
2026-01-20 08:05:01 +01:00
MrClock
6a2a963a5a patterns: Add pattern and magic for Arma 3 RTM (#478)
* patterns/rtm: Added pattern for Arma 3 plain RTM

* magic/arma3: Added plain RTM to magic file

* patterns/rtm: Added test file

* patterns/rtm: Changed function parameters to refs

* patterns/rtm: Replaced RTM test file

* patterns/rtm: Added extra description to RTM pattern

* pattern/bmtr: Added BMTR pattern, magic and test file
2026-01-13 07:10:43 +01:00
MrClock
cee3a5de77 patterns: Add pattern and magic for Arma 3 PAA (#475)
* patterns/paa: Added pattern for Arma 3 PAA

* patterns/paa: Small correction

* magic/arma3: Added magic file for Arma 3 formats

Only the PAA format for now
2026-01-11 19:10:23 +01:00
gmestanley
fb84bbb5d1 patterns: More accurate variable declarations on nes.hexpat, add n64, gen, and gbx.hexpat (#477)
* Add n64, gen, and gbx.hexpat

* Add n64, gbx, and gen.hexpat to README.md

* Remove leftover string import from n64.hexpat

* More accurate variable declarations on nes.hexpat

* Add source to gbx.hexpat

* Add accidentally missing curly brace in nes.hexpat
2026-01-11 18:59:37 +01:00
Dexrn ZacAttack
097ab49cae patterns: Add SPC pattern (#476)
* feat: SPC700 hexpat

* chore: add pattern to readme
2026-01-11 09:53:20 +01:00
Illia Trukhanov
5a04a4256b pattern: Add Lua 5.0 pattern (#466)
* patterns: Add Lua 5.0 pattern

Based on Lua 5.1 pattern.

* tests: Add Lua 5.0 test file

function fac(n)
    if n < 2 then
        return 1
    end
    return n * fac(n - 1)
end

./luac - < test.lua
Lua compiled with make ARFLAGS=rv CC="gcc -m32"
at commit 762c7370376dbd13cd8aeb4d8c8da0bb153269c3
luac compiled with make LUA=../lua CC="gcc -m32"
at commit d002063c4605d3ea12d419b34a23c562f9add318

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2026-01-03 20:31:40 +01:00
gmestanley
8a9bd577ad patterns: Fix quirks of nes.hexpat with famiclones and miscellaneous fixes (#467)
* Add credit to ne.hexpat

* Add many changes to nes.hexpat

* Fixing dependance on variables declared in if statement

* Added mappers and inline to NES 2.0 header, removed needless parenthesises

* Add files via upload

* Add files via upload

* Create nsf.hexpat

* Used full name of the SNES on description

* Add SNES, NSF & NSFe, new description for NES

* Removing erroneous condition in ips.hexpat's truncatedSize

* Removing unnecessary std.string import in ips.hexpat

* Added both locations for sections in PE, clearer variable names, reorganized DOS stub

* Delete patterns/nsfe.hexpat

* Delete patterns/nsfmetadata.hexpat

* Added chunks from NSFe to NSF

* Added NSFe

* Fix size of truncatedSize in ips.hexpat

* More mappers, deprecated tag, and constants to nes

* Fixed official header's constants

* Various corrections

* Fix on declaration of sections, reserved words made into padding

* Added hacked algorithm for longer PRG ROM size, fixed iNES check

* For nes.hexpat, fixed mapper 51 still having its submapper's name

* Fix bug that makes size negative on standard roms

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2026-01-03 20:25:48 +01:00
Jarkko Pöyry
190f9d891b patterns: Add ASCII CPIO patterns. (#473) 2026-01-03 20:24:31 +01:00
Jack Manning
2d92bfca13 pattern: Add Chromium pak file (#474)
* Add Chromium pak file pattern

* Show aliases & fix brotli check bug

* Add decompressed size

* Add notes

* Add PakEncoding enum
2026-01-03 20:23:53 +01:00
elyashiv
0e4040fae1 patterns/elf: Added binding and symbol info (#471) 2025-12-30 11:24:19 +01:00
Nik
57c3dd44b8 tests: Fix test failures after library update 2025-12-23 23:26:20 +01:00
Nik
4646e4b965 patterns/xilinx_bootgen: Remove unnecessary parent access after recent pl upgrade 2025-12-06 16:24:17 +01:00
WerWolv
9143996589 patterns/ac_unity: Rename folder to be clonable on Windows 2025-12-06 09:34:44 +01:00
Sean Apeler
7c3dcc1fcc patterns: Add pattern for Vector BLF Frame Logging Format (#409)
* Add Vector Binary Logging Format pattern

* Combine object header extensions into single type

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 22:15:57 +01:00
ellie 🌸
ea8b381ac5 patterns: Add kindle firmware update pattern (#454)
* add kindle update package

* add kindle update pattern to readme

* add header of kindle update as test

* add missing kindle cs2 devices

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 22:15:40 +01:00
Antonio Vazquez
998655f74a patterns/PcapNG: Rewrite hexpat for bugfixing (#462)
PcapNG: Rewrite hexpat.

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 22:15:28 +01:00
haruse23
681b208aab pattern: Add Assassin's Creed: Unity's Forge files and Data files (Compressed and Decompressed) (#448)
* Add Capcom's Devil May Cry 3 HD .mod hexpat

Hex Pattern file for Capcom's Devil May Cry 3 HD Collection's .mod (3D Models) files

* Update DMC3 HD Mod.hexpat

* Update DMC3 HD Mod.hexpat

* Update DMC3 HD Mod.hexpat

* Add files via upload

* Update README.md

* Rename DMC3 HD Mod.hexpat to dmc3_hd_mod.hexpat

* Delete patterns/dmc3_hd_mod.hexpat

* Delete tests/patterns/test_data/dmc3_hd_mod.hexpat.mod

* Add files via upload

* Update dmc3_hd_mod.hexpat

* Add files via upload

* Update README.md

* Update README.md

* Update README.md

* Add files via upload

* Update ACU_FORGE.hexpat

* Update README.md

* Update and rename ACU_DATA_Compressed.hexpat to acu_data_compressed.hexpat

* Update and rename ACU_FORGE.hexpat to acu_forge.hexpat

* Update README.md

* Update acu_data_compressed.hexpat

* Update acu_data_compressed.hexpat

* Add files via upload

* Update and rename ACU_DATA_Decompressed.hexpat to acu_data_decompressed.hexpat

* Update README.md

* Update acu_data_compressed.hexpat

* Update README.md

* Delete patterns/acu_data_compressed.hexpat

* Delete patterns/acu_data_decompressed.hexpat

* Delete patterns/acu_forge.hexpat

* Create acu_forge.hexpat

* Add files via upload

* Update and rename ACU_DATA_Compressed.hexpat to acu_data_compressed.hexpat

* Update and rename ACU_DATA_Decompressed.hexpat to acu_data_decompressed.hexpat

* Update README.md

* Delete patterns/dmc3_hd_mod.hexpat

* Create dmc3_hd_mod.hexpat

* Update README.md

* Update dmc3_hd_mod.hexpat

* Update README.md

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 22:02:07 +01:00
furidosu
64d86cbdd1 pattern: Add parquet.hexpat for Apache Parquet data file (#450)
* Add parquet.hexpat for Apache Parquet data file

> Apache Parquet is an open source, column-oriented data file format designed for efficient data storage and retrieval.
> -- https://parquet.apache.org

* Add parquet.hexpat test file

* Fix parquet.hexpat boolean parsing

* Fix parquet.hexpat ColumnChunkPlacer not placing last chunk

* Fix parquet.hexpat using VarInt = LEB128

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 22:01:54 +01:00
adiee5
285a2fc7d1 pattern: Atari 8-bit binary format (XEX) (#453)
* add atari XEX format

* Update README.md

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 22:01:41 +01:00
tympanicblock61
2a9676238f pattern: Add lua 4.0 pattern (#465)
* add lua 4.0 pattern

* fix offset the top level function is at

* Update README.md

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 21:54:19 +01:00
Hrant
ee340409db patterns: Added APFS pattern (#400)
* updated APFS hexpat

* fix null feature

---------

Co-authored-by: Hrant Tadevosyan <Hrant.Tadevosyan@connectwise.com>
2025-12-05 21:19:37 +01:00
Fabian Neundorf
84dff0c886 patterns: Add json support for glb files (#412)
* patterns: Add json support for glb files

This makes it possible to separate display the different buffer views,
accessors and images (even visualizing them).

Unfortunately the data within the JSON gets sometimes corrupted and this
is the reason, why it parses the JSON multiple times at some places.

* Use original style and only single json variable

* patterns: Reuse json from global variable in gltf

* patterns: Check component type in gltf only once

* patterns: Fix gltf pattern and add formatting

Removes the duplicate definition of `component_type_t` and also removes
the need to pass the `component_type` to `stride_type_t`.
2025-12-05 21:19:19 +01:00
F01TECH
28a297582b patterns: Added DFIR Patterns (#442)
* Added /DFIR/ with patterns

Added /DFIR/ sub-directory.
Contains modified versions of built-in patterns for semi-automated Disk/Volume/Filesystem parsing geared towards Digital Forensics.
Originals in /fs/ should remain in tact for spot placement.

* DFIR_README.md

* DFIR_README.md

* DFIR_README.md

* DISK_PARSER.hexpat

* DISK_PARSER.hexpat

* FAT32.hexpat

* exFAT.hexpat

* README.md

Added DFIR related hexpats to table.

* README.md

---------

Co-authored-by: Xtreme-Liberty <59177844+Xtreme-Liberty@users.noreply.github.com>
2025-12-05 21:18:56 +01:00
Lexi Mayfield
681b1a1ded patterns: Add support for KTX 1.0 textures (#451)
* Commit patterns I've collected

- AppleSingle/AppleDouble pattern, used for macOS resource forks.
- MAME CHD file format, currently only supports v5.
- KEX Engine proprietary TARC format, used by various Nightdive games.

* Add to README

* Add pattern for KTX 1.0 file

* Use import, add reference ktx file

* Add to README
2025-12-05 21:17:01 +01:00
Stephen Hewitt
0a09efdd20 patterns: Pattern for DOS EXE files (#452)
* Initial DOS file

* Update README.md

* Update README.md

* More README

* More README

* Add DOS EXE

From: https://clasqm.github.io/freedos-repo/Games.html

Name: Champ Galagon
2025-12-05 21:16:36 +01:00
gmestanley
0d8bd76c2c patterns: Improvements to NES & IPS, add SNES, NSF, NSFe (#455)
* Add credit to ne.hexpat

* Add many changes to nes.hexpat

* Fixing dependance on variables declared in if statement

* Added mappers and inline to NES 2.0 header, removed needless parenthesises

* Add files via upload

* Add files via upload

* Create nsf.hexpat

* Used full name of the SNES on description

* Add SNES, NSF & NSFe, new description for NES

* Removing erroneous condition in ips.hexpat's truncatedSize

* Removing unnecessary std.string import in ips.hexpat

* Added both locations for sections in PE, clearer variable names, reorganized DOS stub

* Delete patterns/nsfe.hexpat

* Delete patterns/nsfmetadata.hexpat

* Added chunks from NSFe to NSF

* Added NSFe

* Fix size of truncatedSize in ips.hexpat

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-12-05 21:15:50 +01:00
Lucia
a525160243 patterns: Added pattern for PopCap's Lua bytecode (#458)
* patterns: Added PopCap's proprietary Lua bytecode pattern.

* updated README to include new pattern

* fixed README link

* patterns/popcap_luc.hexpat: fixed comments and sources

* patterns/popcap_luc.hexpat: Changed datatype of filename to be more clear about its structure

* patterns/popcap_luc.hexpat: fixed improper handling of Nil type and added test file
2025-12-05 21:14:53 +01:00
Dexrn ZacAttack
c3946d33a7 patterns/java_class: Add class versions up to j26 (#459) 2025-12-05 21:14:31 +01:00
Khoo Hao Yit
cc7eb7d764 patterns: Add support for Unity Asset Bundle (#461) 2025-12-05 21:14:08 +01:00
Gal1leo Gal1lei
53384a4a54 patterns: Added Windows Notepad State File Parser (#463) 2025-12-05 21:12:45 +01:00
Nik
da005f0172 git: Fix json schema checking 2025-12-05 21:10:24 +01:00
Nik
b2f126d22f constants: Update constants to new system 2025-12-02 23:06:30 +01:00
Nik
7ea863269e build: Fix variable name for Git repository reference 2025-12-01 21:44:39 +01:00
Nik
faff9e0364 git: Add option to customize pattern language repo and git hash with workflow call 2025-12-01 21:38:00 +01:00
gmestanley
a35004665f patterns: Credit to NE and improvements on NES (#445)
* Add credit to ne.hexpat

* Add many changes to nes.hexpat

* Fixing dependance on variables declared in if statement

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-09-22 07:15:37 +02:00
Tim Schneeberger
4fc11f1b91 patterns: Add ESP32 image pattern (#449)
Co-authored-by: Nik <werwolv98@gmail.com>
2025-09-21 09:30:38 +00:00
ODeux
7a9a5097a2 patterns: Add Python Pickle Pattern (#446)
* Add pickle pattern file

* Add test file

* Update README.md

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-09-21 11:17:40 +02:00
Nik
0e67ee102b patterns/ico: Disable BMP processing until issues in the pattern language have been resolved 2025-09-21 10:44:20 +02:00
Zackary Newman
69077b919d patterns/ext4: Increase pattern limit to 2 GiB (#440) 2025-09-12 22:42:55 +02:00
Nightowl
297f611fed patterns: Add terminfo pattern (#437)
* patterns/terminfo: Add pattern for compiled term info entry files.

This adds support for the compiled (legacy and extended) term info entry files that are used for determining terminal capabilities.

* Add .bin extension to the terminfo test file.
2025-09-09 22:39:59 +02:00
DmitriLeon2000
b24ae36638 patterns: Add .gmf (Game Maker 3.x Data) pattern file and its test files (#438)
* Add .fas and .was pattern files (Oska DeskMates)

* Update .was pattern file

* Update .was/.wa3 pattern file

* Update README.md

* Update README.md

* Update .fas & .was pattern files

* Update README.md

* Update fas_oskasoftware_old.hexpat

* Added WAS test file

* Update WAS test file

* Update was_oskasoftware.hexpat

* Update was_oskasoftware.hexpat

* Update fas_oskasoftware_old.hexpat

* Update fas_oskasoftware.hexpat

* Update README.md

Replacing backward slashes with forward ones in the `WAS` row.

* Update fas_oskasoftware_old.hexpat

* Update was_oskasoftware.hexpat

* Add files via upload

* Add Game Maker 3.x Data pattern

* Update gmf.hexpat
2025-09-09 18:22:02 +02:00
Zackary Newman
50d776f497 patterns/ext4: Fix group descriptor table location for non-1024 block sizes (#439) 2025-09-09 18:21:12 +02:00
WerWolv
7dfacc4139 revert: includes/std: Added section parameters to a few std::mem functions 2025-09-06 07:38:18 +02:00
WerWolv
5359e385ea git: Added build folders to gitignore 2025-09-06 07:33:32 +02:00
Nik
75bcb487ee patterns/ico: Fixed duplicate variable name 2025-09-01 22:22:43 +02:00
Ivy Fan-Chiang
fb214600ec patterns/ico: Add embedded BMP and PNG parsing to ICO pattern (#426)
Co-authored-by: Nik <werwolv98@gmail.com>
2025-08-31 14:32:21 +02:00
Kris Dekeyser
d95390ea42 patterns/jpeg: added support for extra data in APP0 section (#417)
Apple Multi-Picture Format JPEGs often have 4 extra bytes in the APP0 section. The pattern now skips any extra bytes beyond the fixed APP0 data.

Co-authored-by: Nik <werwolv98@gmail.com>
2025-08-31 11:40:27 +02:00
Marc Jones
284ca8d325 patterns: Add UEFI Firmare Volume Variable Store pattern (#421)
* Add UEFI Firmare Volume Variable Store pattern

Add a pattern for UEFI Firmare Volume Variable store.
This file type is commonly used with virtual machine UEFI variable files,
like OVMF.fd used with QEMU. You could also extract a UEFI firmware binary
from a flash device, search for the FV Variable Store, and set this pattern
to the FV address.

Signed-off-by: Marc Jones <marcj303@gmail.com>

* Fixed description pragma

---------

Signed-off-by: Marc Jones <marcj303@gmail.com>
Co-authored-by: Nik <werwolv98@gmail.com>
2025-08-31 11:38:32 +02:00
ODeux
6630180276 patterns: Add .NET BinaryFormatter pattern (#416)
* Add dotnet BinaryFormatter pattern

* Add dotnet BinaryFormatter test

* Update README.md

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-08-31 11:37:59 +02:00
Henri Asseily
ff68d1e23d patterns: Added Apple IIGS SHR + SHR 3200 + SHR PWA Animation pattern (#432)
* Added SHR pattern

* Added IIGS SHR animation test file

* Added pattern to readme

* Added description and author

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-08-31 11:36:00 +02:00
Tom Arrow
70dd55aa6b patterns/q3demo: Quake 3 demos: Handle corrupted files more gracefully (#414)
Quake 3 demos: Basic safeguard against corrupted files

Co-authored-by: Tom <tomarrowtomarrow@hotmail.com>
2025-08-31 11:31:20 +02:00
DmitriLeon2000
76f850c543 patterns/fas/was: Update FAS, WAS/WA3 pattern files and README.md (#425)
* Add .fas and .was pattern files (Oska DeskMates)

* Update .was pattern file

* Update .was/.wa3 pattern file

* Update README.md

* Update README.md

* Update .fas & .was pattern files

* Update README.md

* Update fas_oskasoftware_old.hexpat

* Added WAS test file

* Update WAS test file

* Update was_oskasoftware.hexpat

* Update was_oskasoftware.hexpat

* Update fas_oskasoftware_old.hexpat

* Update fas_oskasoftware.hexpat

* Update README.md

Replacing backward slashes with forward ones in the `WAS` row.

* Update fas_oskasoftware_old.hexpat

* Update was_oskasoftware.hexpat
2025-08-31 11:28:45 +02:00
MicroBlock
74c06b74f7 patterns/lua53: Fix lua53 long string (#427)
Update lua53.hexpat
2025-08-31 11:27:59 +02:00
Vemmi
f13d9d3894 patterns/upk-ue3: Add magic pragma (#436) 2025-08-31 11:23:09 +02:00
mjarduk
c4c75a9ab2 patterns: Add a pattern for Roblox .pack files (#435)
* Added the .pack format

* Clarified some fields by changing the naming
2025-08-25 22:22:32 +02:00
Nik
7278a22eb2 includes/std: Fix MagicSearch implementation not being found 2025-08-24 13:34:47 +02:00
Nik
91fd36097c includes/std: Fix use of std::mem::size and std::mem::base_address in library 2025-08-24 12:04:33 +02:00
Nik
afffd7eced includes/std: Added section parameters to a few std::mem functions 2025-08-24 12:00:05 +02:00
Lexi Mayfield
7fd79ec9fd patterns: Added AppleSingle, AppleDouble, CHD, TARC patterns (#431)
* Commit patterns I've collected

- AppleSingle/AppleDouble pattern, used for macOS resource forks.
- MAME CHD file format, currently only supports v5.
- KEX Engine proprietary TARC format, used by various Nightdive games.

* Add to README
2025-08-20 19:32:11 +02:00
Mark Jansen
6b9f39cc21 patterns: Add SDB pattern (#424)
Co-authored-by: Nik <werwolv98@gmail.com>
2025-08-15 17:16:50 +02:00
Stephen Hewitt
9207282bcf patterns: Added Commodore BASIC (#428)
* Commodore BASIC

* Update desc

* I made it

* Implemented suggestion

* Implemented suggestion

* Test file

* Rename file

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-08-02 20:13:35 +02:00
WerWolv
5ed64f9f08 tests: Include patterns folder as include path to support import * from X as Y
#426
2025-08-02 19:29:16 +02:00
WerWolv
a75a7a5b98 git: Let the CI still work correctly in PRs 2025-07-29 22:26:27 +02:00
WerWolv
60c8d93449 git: Make sure other repos check out the right repo 2025-07-29 21:57:54 +02:00
WerWolv
d3b05fd753 git: Allow test action to be imported by other projects 2025-07-29 21:38:20 +02:00
paxcut
3b2f098b09 fix: fixed two typos in this theme (#423) 2025-07-18 08:39:37 -07:00
paxcut
f4f004f0eb improv: Added new text editor semantic highlighting themes. (#422)
* improv: Added new text editor semantic highlighting themes.

Current themes use the same colors  for all identifier types. These two new themes are just examples of what the new feature makes possible.
One aims to simulate CLion Darcula theme and the other is an extension of the original dark theme.

* fix: corrected entries to readme file

* fix: corrected base for the theme

Made sure readme looks correctly on fork and links go to files.
2025-07-16 07:01:43 -07:00
paxcut
5c6cb9dccc fix: issues with two remaining themes. (#420)
Both one-dark and nocturne used global-doc-comment instead of the correctly named doc-global-comment. Typos in Nocturned didn't prevent the theme from loading, but left annoying messages in the log. As explained by the author, the base color map must be one of the three that imhex loads by default, dark,light and/or classic. Even if that is not the case, the name given in base must be that of a valid color map that has been loaded prior to the ones that use it as a base.
2025-07-11 03:42:45 -07:00
paxcut
44717e9b19 fix: incorrect names and values for some colormap entries of the text editor. (#419)
fix: incorrect names and values for some colormap entries of the test editor.

Some names were changed from the original that need to be changed back to make the old colormaps compatible with the new system.
Also, the colors of the console text were incorrectly set to be equal to each other.
This Pr brings back the old names and hopefully fixes problems of incorrect color being used
2025-07-11 02:25:02 -07:00
Dominik Tamiołło
bc35349e0f PEF - fix export count calculation (#418)
* Initial version of PEF

* add pef test file

* Fixed export hash slot count calculation

---------

Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com>
2025-07-08 15:21:07 -07:00
Nik
fed5db4109 Add Capcom's Devil May Cry 3 HD .mod hexpat (#415)
* Add Capcom's Devil May Cry 3 HD .mod hexpat

Hex Pattern file for Capcom's Devil May Cry 3 HD Collection's .mod (3D Models) files

* Update DMC3 HD Mod.hexpat

* Update DMC3 HD Mod.hexpat

* Update DMC3 HD Mod.hexpat

* Add files via upload

* Update README.md

* Rename DMC3 HD Mod.hexpat to dmc3_hd_mod.hexpat

* Delete patterns/dmc3_hd_mod.hexpat

* Delete tests/patterns/test_data/dmc3_hd_mod.hexpat.mod

* Add files via upload

* Update dmc3_hd_mod.hexpat

---------

Co-authored-by: haruse23 <mrjokeromar123@outlook.com>
2025-07-08 14:51:54 -07:00
klirktag
1d41392215 Add support for medium and large mp4 files (#413)
add support for medium and large mp4
2025-06-29 07:33:48 -07:00
ruokeqx
0b75336638 feat(pcapng): add support for Decryption Secrets Block (#411)
feat(pcapng): add support for Decryption Secrets Block
2025-06-19 05:13:43 -07:00
C3pa
e3edbd5a6f Small documentation improvements (#408)
doc: add syntax highlighting to std::ptr::NullablePtr example, fix description of type::escape_bytes

Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com>
2025-06-17 23:55:51 -07:00
C3pa
b10a37af67 Docs: describe how to create multidimensional std::Array (#407)
doc: descirbe how to create multidimensional std::Array

Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com>
2025-06-17 23:46:33 -07:00
Dominik Tamiołło
103d434cc5 Add PEF (Preffered Executable Format) support (#406)
* Initial version of PEF

* add pef test file

---------

Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com>
2025-06-17 22:24:54 -07:00
Fabian Neundorf
7716b9d6e7 patterns: Add support for smk (#399)
* patterns: Add support for smk

* patterns: Use builtin function and separate SMK struct

---------

Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com>
2025-06-17 14:57:36 -07:00
Tom Arrow
ad1e300674 Quake 3 Engine demo pattern & test file (#402)
* Quake 3 Engine demo pattern & test file

* Quake 3 Engine demo: Increase limits (demo files can be big) and additional condition

* Quake 3 demo specify little endian

* Quake 3 demo format: Add message type detection

* Quake 3 demo format: Read serverTime for snapshot messages

* Quake 3 demo pattern: fixed bug/typo/sleepy coding

* Quake 3 demo pattern: Ability to read CS_SERVERINFO

* Quake 3 demo pattern: Read CS_SYSTEMINFO as well

* Quake 3 demo pattern: Read first serverCommand per message

* Added Quake 3 engine demo pattern to readme

* Change Quake 3 engine demo entry in readme table

---------

Co-authored-by: Tom <tomarrowtomarrow@hotmail.com>
2025-06-17 02:06:24 -07:00
zn123
e918ce52b9 Add flv.hexpat (#401)
* Add flv.hexpat

https://veovera.org/docs/enhanced/enhanced-rtmp-v2#flv-file-format-overview

* test flv.hexpat

* Update README.md

add flv patterns

* Update flv.hexpat

Optimize spaces

* Update flv.hexpat

fix
2025-06-16 20:25:54 -07:00
Nik
db4d62aa20 patterns/fs: Refactor all partition types into a FS module 2025-05-25 19:51:32 +02:00
WerWolv
d96bfbb942 tests: Execute and test format functions 2025-05-25 12:43:21 +02:00
Nik
2070c95f58 yara: Added crypto identification rules 2025-05-24 23:56:56 +02:00
Nik
877895741d includes/hex: Fixed Json types being twice the size they need to be 2025-05-17 19:45:30 +02:00
Nik
6b279b8375 patterns/exfat: Fixed eval depth error 2025-05-17 16:07:11 +02:00
Khoo Hao Yit
a692b22ecc patterns: Add support for exFAT (#398) 2025-05-17 13:13:35 +02:00
Claudius Coenen
2ae0499293 patterns/wintec_tes: Slightly nicer formatting in a list of entries (#397)
slightly nicer formatting in a list of entries
2025-05-16 20:25:04 +02:00
thrasher
bd06987e8e patterns/zip: Add zip64 support (#395)
Co-authored-by: Nik <werwolv98@gmail.com>
2025-05-15 21:22:20 +02:00
Fabian Neundorf
74e08623f1 patterns: Add support for flc/flic files (#396)
* patterns: Add support for flc/flic files

* patterns: Add #pragma description for flc

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-05-15 20:17:13 +02:00
Nik
a860c396fa patterns: Added Java HPROF pattern 2025-05-15 17:23:06 +02:00
Nik
da934e2045 patterns/optee_ta: Fixed missing author and description pragmas 2025-05-15 08:07:13 +02:00
Nik
394ef80611 patterns: Added OPTEE Trusted Application format 2025-05-13 22:17:05 +02:00
Grant Kim
2ce182b1b3 patterns/tiff: Tags for DNG and TIFF extensions (#376)
Add Tags for DNG and TIFF extensions

References: https://www.loc.gov/preservation/digital/formats/content/tiff_tags.shtml
https://helpx.adobe.com/camera-raw/digital-negative.html

Co-authored-by: Nik <werwolv98@gmail.com>
2025-05-10 13:59:22 +02:00
Glenn Hartmann
6cadad3d1f pattern/protobuf: Allow parsing of nested messages (#378)
Mostly this enables attempted recursive parsing of submessages. Note
that it is inherently impossible to determine the underlying data type
for LengthDelimited for sure, so this is a best-effort attempt. The user
can disable recursive submessage parsing via Settings.

Other minor changes:
* added #pragma MIME and #pragma endian directives
* enabled UTF-8 display for LengthDelimited types
* added signed LEB128 display for Varint types (although this doesn't
  seem to be working on my test case)
* swapped if/else-if structure for match
* fail upon receiving unknown or unsupported WireType

Co-authored-by: Nik <werwolv98@gmail.com>
2025-05-10 13:53:01 +02:00
David Schneider
7ad9cd4f41 patterns: Added support for GNU MO files (#383) 2025-05-10 11:49:02 +00:00
0xZ3R0
bcaeef31d7 pattern: Added DJI Firmware Pattern (#392)
* added IM*H pattern

* improved README
2025-05-10 13:35:14 +02:00
Niketin
ee8d2f50b7 pattern/bencode: Various fixes (#393)
* Fix bencode dictionary

When parsing a bencode dictionary, the end character 'e' was never
consumed. This caused a misinterpretation of the character as struct Value of
an unknown type 'e'.

* Fix bencode list

A list was not included in the Value's parsing logic so it may have
been mistakenly parsed as a string.

* Fix std::ctype::isprint not including space

The space character, 0x20, is considered as a printable character in ASCII
and in >=C89. Adding it to the range of std::ctype::isprint also fixes
other std::ctype functions that use it.

* Fix bencode byte string formatting

Byte strings do not render nicely in pattern data's value column if they
contain non-printable characters. This commit makes the value of byte
strings to be surrounded by quotation marks, and renders a warning text
without quotation marks if the byte string contains non-printable
characters.
2025-05-10 13:34:36 +02:00
DEREFERENC3D
5b8dde19a9 patterns: Added definition for the OpenRGB profile format (#387)
patterns: Add definition for the OpenRGB profile format (up to version 5)
2025-05-10 13:34:16 +02:00
Dhash Shrivathsa
0b0eff0cb6 pattern/macho: Load Commands should include additional specializations (LoadDyLib) (#386)
* add additional command specialization

* address PR feedback
2025-05-10 13:34:01 +02:00
Enaium
3185503be1 patterns: Added valve vpk pattern (#384) 2025-05-10 10:29:50 +00:00
Sabhya
3a64207e58 pattern: Added pcapng capture file pattern (#385)
add: pcapng hexpat
2025-05-10 12:26:39 +02:00
bluisblu
c94d42d5c0 patterns: Added Radcore Cement v1.2 file pattern (#382)
* Add Radcore Cement file pattern

* Update pattern list in README.md
2025-05-10 11:57:51 +02:00
Caleb Denio
45c4c1d35b patterns/uf2: Added magic number (#379) 2025-05-10 11:54:29 +02:00
Jean Pereira
f93be1ea06 themes: Added Nocture theme (#377)
minimal dark theme based on Dracula but more darker
2025-05-10 11:53:28 +02:00
Shadlock0133
5ed9c0fd4d patterns/elf: use Rel{a} structs for parsing REL{A} section data (#375) 2025-05-10 11:52:35 +02:00
C3pa
11d373319f pattern/pe: Check for imageNameRVA in pe.hexpat before reading imageName (#372) 2025-05-10 11:52:00 +02:00
Jonathan Ostrus
e7d366571d pattern/pex: Added formatter for opcode and some other name cleanups (#371) 2025-05-10 11:51:43 +02:00
Caleb Denio
b6df1742b6 patterns: Add ZIM pattern (#367)
* Add ZIM pattern file

* Add test file

* namespace!
2025-05-10 11:51:04 +02:00
Jake Ryan
0b9e83ff8a patterns: Add support for MagicaVoxel .vox files (#390)
* patterns: Added support for MagicaVoxel .vox files

* Fixed incorrect IMAP field size and added basic chunk size mismatch detection and recovery.

* Fixed pattern for "_r" values and added RotationToMat3.

* Added test vox file.

---------

Co-authored-by: paxcut <53811119+paxcut@users.noreply.github.com>
2025-04-30 08:55:53 -07:00
paxcut
c0fc748de6 fix: rgb color attribute is always blue.
The color attribute does not nclude an alpha component but the RGB types were including an alpha of 255 in their color attributes. The 0xFF was being assigned to the blue component hence the error.
2025-04-30 08:40:32 -07:00
Hrant
89307ba8a5 added NTFS pattern (#391)
Thank you!

* added NTFS pattern

* improved the PR

* remove test-data & fixed sd

---------

Co-authored-by: Hrant Tadevosyan <Hrant.Tadevosyan@connectwise.com>
2025-04-30 04:00:52 -07:00
ZHANG Yuntian
a12b5ba406 git: Fix table formatting (#374)
Signed-off-by: ZHANG Yuntian <yt@radxa.com>
2025-03-24 07:33:01 +01:00
ZHANG Yuntian
537ce67895 patterns/partition_table: Added basic MBR and GPT patterns (#358)
Both are conbined into a single pattern due to how GPT always has a pseudo MBR to maintain backward compatibility.
2025-03-24 07:15:25 +01:00
Scrivener07
1771c1f077 patterns: Added support for PEX Papyrus executables (#370)
Added support for PEX, Bethesda's Papyrus executable for compiled script files.
- Skyrim
- Fallout 4
- Fallout 76
- Starfield

Co-authored-by: Jonathan Ostrus <12855515+jbostrus@users.noreply.github.com>
2025-03-23 11:30:43 +01:00
Caleb
cef20e24a7 patterns/zip: Fix 0x5455 extended timestamp fields crash, improve date/time presentation (#363)
Co-authored-by: Nik <werwolv98@gmail.com>
2025-03-22 13:57:42 +01:00
Andreas Wallner
8e7cfd9442 patterns: Add STDFv4 pattern (#326) 2025-03-22 13:54:50 +01:00
5ec1cff
d0ba754dc2 patterns/zip: Handling padded extra fields (#369)
* Handling unresolved extra fields

* Update zip.hexpat

* Update zip.hexpat

* Update zip.hexpat
2025-03-22 13:54:26 +01:00
mheimlich
9f92c38ecf patterns: Add ADTFDAT pattern (#368) 2025-03-22 13:52:59 +01:00
Geky
0844e07056 patterns: Added DS Cartridge Header pattern, updated pyc versions (#366)
* add support for cartridge size type $54

Added support for cartridge size type $54, corresponding to 1.5 MiB (96 banks).

* add missing license

* Add GBA Cartridge Header

* Update README.md

Added GBA information to README.md and corrected a typo.

* Add DS Cartridge Header

* Update ReadMe.md

* Update pyc.hexpat

Included additional versions
2025-03-22 13:51:46 +01:00
C3pa
66fc006b08 includes/std: Update hex::dec::zlib_decompress description (#364)
docs: Update hex::dec::zlib_decompress description
2025-03-22 13:51:00 +01:00
Eddy S.
5bc66df14f patterns/elf: Set endianness globally (#362) 2025-03-22 13:50:17 +01:00
MrMcX
7310a10214 patterns: Add pattern for microsoft prefetch files (uncompressed SCCA format only) (#361)
* Add pattern for microsoft prefetch files (uncompressed SCCA format only)

* Update pf.hexpat

Add longer explanation
2025-03-22 13:49:50 +01:00
MrMcX
34ee3107e2 patterns: Implement Windows thumbcache pattern (#359)
* Implement Windows thumbcache pattern

* Include thumbcache pattern in README.md

* Update thumbcache.hexpat

- Use English warning text
- handle unknown file version
- add thanks to joachimmetz
- create virtual file
- use more elegant magic type

* Update thumbcache.hexpat

- Use padding data type for paddings

* Update thumbcache.hexpat

- make pattern more robust against single erroneous cache record
2025-03-22 13:48:57 +01:00
Shadlock0133
c4378ffb14 patterns/elf: Use e_shstrndx to get section names instead of guessing (#357) 2025-03-22 13:47:43 +01:00
eli_w
5ad7f0c1e7 patterns/ani: Improved compatibility with error size defined in ani files (#354) 2025-03-22 13:46:49 +01:00
Mrmaxmeier
df97fc7257 patterns/includes: More misc cleanups (#353)
* patterns/zip: simplify find_sequence_in_range check

hex(340282366920938463463374607431768211455) =
0xffffffffffffffffffffffffffffffff

* patterns/7z: use Magic<> for signature, add pragma

* patterns/{nro, ogg}: use Magic<> for signature

* patterns/ttf: refactor, check magic

Use the "Field field @ position;" syntax instead of saving and restoring
the cursor position.

* readme: fix copy-paste error in pattern listing
2025-03-22 13:46:06 +01:00
Vemmi
3ad263783d patterns: Added Unreal Engine 3 UPK pattern (#352)
* patterns: Add unreal 3 upk pattern

* readme: Add link to upk-ue3.hexpat
2025-03-22 13:45:25 +01:00
Ilya Sorochan
5ccd431320 patterns: Added RPM pattern (#350) 2025-03-22 13:44:55 +01:00
Nik
fb8e5e3f77 disassemblers/jvm: Fixed mask and mnemonic of areturn and athrow 2025-02-28 11:42:44 +01:00
paxcut
375145e759 include/std: std::ptr::relative_to_base_section not working anymore (#349)
Fixes #348 

In issue #348 it is stated that the pattern fails to find the variable baseAddress in the parent of the parent of the attribute function. One parent is required to access the variables on the pattern that is using the attribute.

That pattern is used in the pattern that contains baseAddress as a pointer to an array of the children pattern and that seems to require an extra parent level to be added in order to access baseAddress without errors. The fix was tested on an xbe file extracted from an xbox cd rom and while it failed without the fix as stated in issue 348 with the fix it ran to completion without issues.
2025-02-16 12:52:01 +01:00
paxcut
71eeed981d patterns/protobuf: Remove global variables
In issue #346 it is noted that the format functions return the same value repeatidly and erroneously. This is due to the use of global variables which result on only their last value being used in format functions due to their delayed evaluation. Fixed by using local variables instead. Also remove tabs from the file and an unused tags variable.
2025-01-30 20:24:11 +01:00
Fabian Neundorf
e779b88a58 patterns/iso: Fix incorrect condition (#344) 2025-01-23 21:44:44 +01:00
Fabian Neundorf
aef3d3451f patterns/iso: Add some improvements to the ISO pattern matching (#343)
* patterns: Load all ISO volume descriptors

* patterns: Parse supplementary volume descriptors

* patterns: Add system use in directory records for iso
2025-01-23 19:23:11 +01:00
Nik
c5fa53dcea includes/type: Make type::Formatted actually work as documented 2025-01-19 18:13:48 +01:00
The Wandering Trader
9a6cbdfe28 patterns: Add CAB pattern (#342)
* Add files via upload

* Add files via upload

* Update README.md
2025-01-19 00:13:04 +01:00
Nik
083042632d includes/hex: Hide implementation data of json types 2025-01-16 19:15:10 +01:00
Nik
4d172cebc3 patterns: Removed invalid zip test file 2025-01-14 20:07:03 +01:00
Nik
53ff0a5d62 patterns/afe2: Fixed misspelled of pragma 2025-01-14 20:06:39 +01:00
WerWolv
b3b730c6e9 patterns: Fixed various test binaries 2025-01-14 20:01:51 +01:00
Nik
8db011b6e5 patterns: Added MIME types and magic numbers to all patterns that have them 2025-01-14 20:01:36 +01:00
Nik
b936c04d21 patterns/gguf: Added #pragma magic to allow auto-loading the pattern 2025-01-14 18:21:16 +01:00
bake
bf56d4ff49 patterns: Add veado pattern (#339)
* Add veado pattern

* Add veado to README

* Add veado example file
2025-01-13 21:21:05 +01:00
Known Rabbit
fdc4a87389 patterns: Add bcss (BeyondCompare SnapShot) file (#338)
* patterns: add bcss (BeyondCompare SnapShot) file

* Add entry to readme

* Change table entries in alphabetical order

* Support both bcss file and uncompressed content

* Remove misleading cases, add warning message

* Add test cases to bcss.hexpat

* ifdef out ImHex-only functionality

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2025-01-13 21:20:36 +01:00
Mia
1f6c701348 patterns: Added sup pattern file (#337)
* Add sup pattern file

* Add files via upload

* Update README.md
2025-01-09 20:01:14 +01:00
JTurtle
4092dad428 includes/type: Fix error in float16 format function (#336) 2025-01-05 09:46:09 +01:00
Nik
559faebec3 patterns: Added simple SQLite3 database pattern 2024-12-28 19:57:48 +01:00
Nik
cde46e1f15 patterns/bgcode: Improve bgcode pattern 2024-12-28 18:51:34 +01:00
Nik
17c200a92e disassemblers/jvm: Added remaining instructions besides lookupswitch and tableswitch 2024-12-27 13:41:46 +01:00
Nik
384d4c7794 disassemblers: Added half of the JVM instructions 2024-12-27 01:07:36 +01:00
Nik
37a7e59c06 disassemblers: Added Intel 8051 architecture 2024-12-26 20:08:42 +01:00
Nik
e8cea09477 include/hex: Added definitions for new built-in types 2024-12-24 12:39:28 +01:00
Andrey Andreyevich Bienkowski
883433b260 includes/type: Fix parsing of signed leb128 (#333) 2024-12-18 21:49:16 +01:00
Nik
2db9993cb1 git: Fixed ninja package name 2024-12-18 21:45:45 +01:00
Nik
01ce565c9e git: Install ninja 2024-12-18 21:35:34 +01:00
Nik
b7b949ea27 git: Updated action runners 2024-12-18 20:53:54 +01:00
BobSmun
e026ff187e build: Improve build system (#327)
* *Add top level CMakeLists.txt, to make it easier to use both independently and from within other projects
* Add a unit_test target, to attach all unit tests to

* * Fix unit tests for windows
* Silence cmake warning regarding missing top project
* update .gitignore for vscode

---------

Co-authored-by: BobSmun <6492115+BobSmun@users.noreply.github.com>
2024-12-16 20:37:38 +01:00
Nik
63504f59a1 tests: Fixed fucked up include 2024-12-14 22:31:12 +01:00
Josef Šimánek
6113df643d git: Fix typo in readme (#332) 2024-12-14 16:35:25 +01:00
WerWolv
3f42dddd19 tests: Improve unit tests for includes and patterns 2024-12-14 16:34:27 +01:00
Luca Corbatto
2cc8868727 patterns: Added rar file pattern as requested in #258 (#324)
* Add rar file pattern as requested in #258

* Fix rar pattern

Removed some experimental (and apperantly broken) code.

* Break on EndOfArchive header instead of EOF

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-12-14 13:48:06 +01:00
Sabhya
7f02510762 patterns: Added dmp64.hexpat and test files (#331)
* [+] Added dmp64.hexpat && test files

* Fix encoding of pattern file

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-12-14 13:40:22 +01:00
Sewer.
13c4168af0 patterns/bzip3: Fixed Incorrect field on branch (#330) 2024-12-13 10:21:47 +01:00
Sewer.
1e69cd7fb2 patterns: Added BZip3 File Header Pattern (#329)
* Added: BZip3 Compression

* Fixed: Bound the SmallBlock data by parent's size

* Improved: Now uses the name 'Chunk' for block wrappers, such that the name 'block' matches with what the BZ3 API does

* Improved: Import rather than Include std::mem

* Added: Missing 'description' field in pragma
2024-12-12 21:56:13 +01:00
Sabhya
16a87df2ac patterns: Added DPAPI Blob, DPAPI MasterKey, CREDHIST patterns (#328)
* [+]Added DPAPI MasterKey & Updated README.md

* [+]Added DPAPI Blob Pattern & Updated README.md

* [+] Added CREDHIST Pattern &  Updated README.md

* [+] Test Files added for dpapimasterkey, dpapiblob & CREDHIST
2024-12-05 21:26:43 +01:00
kbugstar
b7598405b5 encodings: Added Chinese GBK encoding (#308)
Chinese Gbk encoding file
2024-12-01 17:19:14 +01:00
WerWolv
d14f8de459 includes/std: Added new palette control functions 2024-12-01 17:15:24 +01:00
WerWolv
4c96bfbeb3 patterns/fs: Fixed pattern and uploaded test data 2024-11-28 21:35:25 +01:00
Geky
500a3fe26e patterns: Added GBA ROM pattern (#323)
* add support for cartridge size type $54

Added support for cartridge size type $54, corresponding to 1.5 MiB (96 banks).

* add missing license

* Add GBA Cartridge Header

* Update README.md

Added GBA information to README.md and corrected a typo.
2024-11-28 17:59:45 +01:00
WerWolv
5ffc583640 pattern/tiff: Fixed function parameter types 2024-11-27 20:44:56 +01:00
Nik
b9f5f1668b includes/type: Fixed use of Reinterpreter type 2024-11-24 14:53:30 +01:00
Nik
4c22f28a67 pattern/rgbds: Fixed bad include 2024-11-24 14:53:02 +01:00
Bananchiki
6f9b05b853 themes: Added One Dark theme (#322)
* Added One Dark theme

* theme: fixed spacing
2024-11-24 14:51:06 +01:00
Mrmaxmeier
c533017d0b git: Various style fixes everywhere, removing whitespaces (#321)
* repo-wide: trim trailing spaces

Note: This doesn't touch the .tbl files in encodings/ since they include
meaningful trailing spaces (`20= `)

* patterns: clean up duplicate semicolons

* ELF: add header magic check

* glTF: use type::Magic for magic value

* glTF: check that the file size in the header matches

* xgstexture: fix generics syntax for magic value

* JPEG: define hex enum with 0x00 instead of 0X00

* CI: update deprecated actions

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-11-24 11:41:26 +01:00
Dexrn ZacAttack
221fa70a67 patterns: Added Miles Sound System Compressed Archive (MSSCMP) (#320)
* MSSCMP readme

* Add files via upload
2024-11-24 11:39:43 +01:00
Dexrn ZacAttack
661e5b7081 patterns: Added RAD Game Tools BINKA hexpat (#319)
* Binka readme

* Binka hexpat
2024-11-24 11:39:22 +01:00
Geky
7d0bbd1e24 patterns/GameBoy: Add support for cartridge size type $54 and missing licenses (#318)
* add support for cartridge size type $54

Added support for cartridge size type $54, corresponding to 1.5 MiB (96 banks).

* add missing license
2024-11-24 11:38:54 +01:00
Maxim Savenko
55aca93a18 patterns/mp4: Add 'stsz' box definition to MP4 pattern (#317) 2024-11-24 11:38:31 +01:00
otakuxtom
255116a587 patterns/pe: Fix error when ordinalTableRVA is zero (#315)
ordinalTableRVA is not always has value. it might be zero.
Whien this happened, it will failed.

Signed-off-by: Chunhao Hung <chunhao.hung@insyde.com>
Co-authored-by: Chunhao Hung <chunhao.hung@insyde.com>
2024-11-17 14:00:43 +01:00
Luca Corbatto
79e25fdb73 patterns/zip: Added parsing of general purpose bit flag (#314)
* Add parsing of general purpose bit flag

Add "GeneralPurposeBitFlags" bitfield definition. The names are based on
the official ZIP format specification although I chose to name the
fields closer to their purpose rather than their official name. This is
intended to make reading the pattern and its output easier. Example:
official name "Language encoding flag (EFS)" my name
"filenameAndCommentAreUtf8" because this immediately explains what it
does.

I chose not to implement the specifics of the "compressionOptions" as
their meanings are specific to the compression method used and it would
make the pattern much more complicated for (in my opinion) little gain.

I also chose to unify the names of the general purpose bit filed in the
LocalFileHeader and the CentralDirectoryFileHeader. Previously, they had
different names, suggesting they might have different meaning. According
to the official docs though, these fields have the exact same meaning.

Official docs: https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT

* Fix typo and remove redundant type declaration
2024-11-17 14:00:16 +01:00
Dexrn ZacAttack
c8d9a8deb7 patterns: Added Minecraft LCE LOC file pattern (#311)
* create LOC hexpat

* loc to list
2024-11-17 13:59:44 +01:00
Miku-666
1d680fbf5e patterns: Added Minecraft LCE .pck format pattern (#310) 2024-11-17 13:59:20 +01:00
Dexrn ZacAttack
bc5a55affe patterns/lcesave: Use Virtual Filesystem + ZLib support + auto endian detection (#309)
* use Virtual Filesystem + ZLib support + auto endian detection

* fix builtin

* smh how am I only noticing that I just duplicated a function for no reason

* ifdefs to fix actions moment
2024-11-17 13:58:56 +01:00
Dexrn ZacAttack
85f5541350 patterns: Added Minecraft LCE ARC file format (#307)
* Create arc.hexpat

* add test file

* mention arc

* abide by contributing.md

* use virtual filesystem

* brainfart

* ifdefs to fix github actions moment #2
2024-11-17 13:58:02 +01:00
bbbbbr
61d3e110fb patterns/gb: Add 16K and 32K arrays for ROM Banks (#305)
Having arrays for dividing the GB ROM up into ROM Banks makes it much easier to jump to and inspect data at the start and end of banks.

- 16K Banks are the typical standard
- 32K banks aren't very common but are used in a couple unlicensed Games such as those using the Wisdom Tree MBC controller
2024-11-17 13:57:45 +01:00
Hikodroid
af957389c2 patterns: Added pattern for LZNT1 compressed data (#304) 2024-11-17 13:57:23 +01:00
Hikodroid
e85645897e patterns: Added pattern for Blender project files (#303)
* patterns: Added pattern for Blender project files

* patterns/blend: Added pattern file and test data

* patterns/blend: Fix the thumbnail bugs by passing the source data by reference

* patterns/blend: Added ZSTD support and test data
2024-11-17 13:56:59 +01:00
Hikodroid
abc78d1644 patterns/fbx: Improved the FBX pattern (#302)
* patterns/fbx: Improved the FBX pattern
-Added pragma magic
-Fixed sizing of compressed contents array
-Added references
-Cleaned up whitespace

* Added missing ] bracket in README.md
2024-11-17 13:56:40 +01:00
Valentin Lenhart
46e41db0a8 patterns/pe: Use appropriate pointer for first section placement (#300) 2024-11-17 13:56:01 +01:00
Valentin Lenhart
c67dc84911 patterns/pe: Fixed off by one error in coff pattern (#299) 2024-11-17 13:55:30 +01:00
Guest257351
323898d083 patterns/lua5.1: Fixed a bug in the Lua 5.1 bytecode pattern (#298)
* Fixed a bug in the Lua 5.1 bytecode pattern

Lua 5.1 bytecode upvalue fields were incorrectly defined as a `Vector<u32>` instead of `Vector<LuaString>`.

* Fixed another bug in the lua 5.1 bytecode pattern

Lua 5.1 bytecode string sizes were incorrectly parsed as a 64-bit integer, instead of a 32-bit integer.

* Updated the Lua 5.1 bytecode pattern for 32-bit compilers.

Updated the pattern to allow for 32-bit and 64-bit integers for the size of the string length field.
2024-11-17 13:55:00 +01:00
Seth Hall
abbd25e7f6 patterns: Added Windows Notepad cache file pattern (#297)
* Added Windows Notepad Cache file parser.

* Fixed Notepad windowstate link in readme

* Added a test file for notepad-cache.hexpat
2024-11-17 13:54:29 +01:00
Martín Montané
c8ebb3eb8a includes/std: Added checks to ends_with and starts_with to prevent failure (#295)
Fixing cases where part is longer than string, this cases should both return false instead of failing.

Co-authored-by: Nik <werwolv98@gmail.com>
2024-11-17 13:54:03 +01:00
applecuckoo
bf94cb7243 patterns: Added new WebP and VGM patterns (#294)
* README: fix square bracket

* patterns: add WebP pattern

* patterns/dds: add x-dds mimetype

* patterns: add vgm pattern

* patterns/vgm: remove old pointer

* patterns/protobuf: fix field number handling

* patterns/protobuf: add .pb file extension

* patterns/uf2: updating the family IDs again

* patterns/png: add cHRM and tIME chunks

* patterns/png: whoops, old description snuck back in

* new quantized-mesh pattern

* add quantized-mesh to README, implement oct16 decoding
2024-11-17 13:53:18 +01:00
paxcut
6697fc23a4 themes: Updated the custom themes to the new text editor color palettes (#255)
* Updated the custom themes to the new text editor color palettes designed for full syntax highlighting, but the existing themes should look just like they did before.

* impr: renamed pattern-placed-variable to calculated-pointer and added view
fix: pe pattern could read past the end of file if symbol search option was turned on and input file had no symbols. In that case a StringTable array that has 1 element would be created and place at offset 0 where the size variable was set to a large number creating the error. The fix is to set the size of the array using numberOfSymbols>0

* Fix: that was a bad choice for the size of the stringTable array because  even if findSymbols is not on the file can contain symbols. This was causing the pe unit test to fail. To get the right array size use sizeof(symbolTable)>0 which will be 1 only if findSymbols is true and the file actually contains symbols
2024-11-17 13:52:30 +01:00
Nik
8a6bb6612b includes/std: Fixed standard library errors with latest nightly 2024-11-17 13:51:51 +01:00
endes0
1d66949375 patterns: Added ext4 filesystem pattern (#293)
* patterns: add ext4 volume layout pattern

* patterns: improve ext4 pattern

* patterns: remove debug pragma from ext4

* patterns: fix ext4 magic and padding

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-08-20 21:56:05 +02:00
SpaceManiac
7c65d51986 patterns/msgpack: Fixed endianess of lengths and fixint definition (#291)
* Fix endianness of msgpack ext datum lengths

* Fix formatting of negative fixints
2024-08-20 20:41:12 +02:00
BobSmun
d961271c5d includes/std: Fixed std::core::set_pattern_comment (#289) 2024-08-20 20:33:18 +02:00
applecuckoo
26d48df7dd patterns/uf2: Add new RP2xxx-related family IDs (#288)
* patterns/uf2: add family ID enum

* patterns/uf2: Fix enum spacing

* patterns: add missing description pragmas and README entries, etc.

* patterns/uf2: add reference for Family ID enum

* patterns/uf2: add new RP2xxx family IDs

* patterns/uf2: whoops (comma fix)
2024-08-09 12:39:28 +02:00
Nik
8f1f4911a0 includes/std: Fixed value display error with std::string::NullString 2024-08-07 22:12:25 +02:00
Eldred Habert
1d7cc537ed patterns: Added RGBDS object file format (#287) 2024-08-07 22:11:29 +02:00
qux-bbb
62ceaae09b patterns/lua54: Add a Lua 5.4 test file (#286) 2024-08-04 21:54:24 +02:00
Nik
4a8a6cba1b patterns/flipper_settings: Removed #pragma magic as they would give too many false positives 2024-08-03 20:14:27 +02:00
Nik
c3eb9e4126 patterns: Improved pattern descriptions 2024-08-03 17:44:37 +02:00
WerWolv
a263347414 tests: Added StuffIt5 archive 2024-08-03 15:16:48 +02:00
qux-bbb
204599a70b patterns: Added Lua 5.3 bytecode pattern (#285) 2024-08-03 14:47:07 +02:00
Jan Wiesemann
bf6ee6d02f patterns: Added pattern for Flipper Zero settings (#281)
* Added pattern for Flipper Zero settings

* Added readme entry

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-08-03 14:11:02 +02:00
qux-bbb
0125ec2c57 patterns: Added Lua 5.2 bytecode pattern (#284) 2024-08-03 14:07:50 +02:00
applecuckoo
c5aaac25dd patterns/uf2: Added Family ID enum to uf2.hexpat, Added missing description pragmas and other minor fixes (#282)
* patterns/uf2: add family ID enum

* patterns/uf2: Fix enum spacing

* patterns: add missing description pragmas and README entries, etc.

* patterns/uf2: add reference for Family ID enum
2024-08-03 10:47:40 +02:00
qux-bbb
196011ead9 patterns: Added Lua 5.1 bytecode pattern (#283) 2024-08-03 10:46:25 +02:00
xtex
5b15136ea4 patterns: Add HSDT pattern (#280)
Co-authored-by: Nik <werwolv98@gmail.com>
2024-07-27 08:38:44 +02:00
qux-bbb
59c954ae28 patterns/lua54: Removed empty line (#278)
Remove an empty line.
2024-07-26 19:52:24 +02:00
Hikodroid
8a5cb1061b patterns/fbx: Simplified the fbx hexpat (#277) 2024-07-26 19:52:01 +02:00
Hikodroid
120bc84548 patterns/fbx: Fixed the fbx hexpat (#276)
* patterns: FBX - revised hexpat for fbx files but still broken

* patterns: FBX - implemented a workaround for the previously broken hexpat

* Disable ImHex-specific functions outside of ImHex

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-07-25 00:00:11 +02:00
WerWolv
0e17355db0 tests: Added more test files 2024-07-23 21:03:17 +02:00
WerWolv
6aee524d1a patterns: Fix various patterns, added more test files 2024-07-23 20:31:43 +02:00
WerWolv
b42c571d4d patterns: Fixed run problems with some patterns 2024-07-23 18:39:05 +02:00
xndcn
71e1ad8df7 patterns/jpeg: Simplify EOI marker search (#272)
Co-authored-by: Nik <werwolv98@gmail.com>
2024-07-23 18:37:03 +02:00
WerWolv
5c7d77b50f patterns: Added Kaydara FBX Binary format
Credit to @Hikodroid
2024-07-23 18:29:02 +02:00
WerWolv
a746ecb164 tests: Moved/Renamed some test files 2024-07-23 18:24:05 +02:00
Dexrn ZacAttack
569e5c4c1a patterns: Added Minecraft LCE save format (#256)
* Add Minecraft LCE save format

* Add files to the pattern

took forever lol cuz weird syntax

* NBT parsing n stuff

* Minecraft Xbox 360 Edition saves, read description

TU033 is a pre-release version, which has a slightly different file format that I documented myself [here](https://github.com/Team-Lodestone/Documentation/blob/main/LCE/Pre-Release%20Save%20Format.md)

TU5 is a release version which uses the same file format used all the way up to latest TU (aka the last version released)

All of these saves have been decompressed from XMemCompress (iirc modified LZX)
Chunk data however is still compressed, because it's not meant to be uncompressed in the scope of reading the save.

https://github.com/Team-Lodestone/Documentation/blob/main/LCE/LCE%20File%20Versions.md

* Support Pre-Release files, JANKY file type detection, min and cur version.

* fix top comment

* LCE saves to readme
2024-07-23 18:17:02 +02:00
applecuckoo
0316f2b667 patterns: Add PKM pattern + add BCC checksum verification to ntag pattern (#274)
* patterns/ntag: add BCC checksum verification

* patterns: add PKM file pattern

* Add entry to README

* Added missing import

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-07-23 08:30:05 +02:00
WerWolv
196695e37b includes/std: Allow std::print() and std::format() to take any value as format argument again 2024-07-12 21:19:43 +02:00
WerWolv
bced518508 includes/std: Added std::mem::reached() for use with while-sized arrays 2024-07-10 21:32:55 +02:00
WerWolv
2f795fc23c includes/std: Added attrs library 2024-07-10 21:32:35 +02:00
C3pa
5ff783d571 includes: Fix various spelling errors (#270)
docs: fix some spelling errors

Related issue:
https://github.com/WerWolv/ImHex/issues/1139
2024-07-10 21:09:15 +02:00
WerWolv
4299243e95 includes/std: Added hex::dec::lz4_decompress() 2024-07-07 15:51:40 +02:00
Surasia
23b3c2b5d0 git: Fix hinf_tag and hinf_module links in readme (#268) 2024-07-07 13:44:04 +02:00
Surasia
da1c2687e8 patterns/hinf_*: Add Halo Infinite tag and module file patterns (#267)
* patterns/hinf: Add Halo Infinite Tag and Module patterns

* patterns/hinf_bitmap: remove pattern
2024-07-06 17:33:03 +02:00
WerWolv
18f968df5b includes/std: Drastically improved std::mem::MagicSearch, added find_string and find_string_in_range 2024-07-04 20:47:39 +02:00
WerWolv
f797c711ca includes/std: Optimize std::bit::popcount 2024-07-04 17:58:12 +02:00
WerWolv
5380877da4 tests: Added error message when no description is used 2024-07-04 08:28:20 +02:00
Marc Butler
bb46276bde patterns: Added Password Safe Version 3 pattern (#266)
* Add password safe V3

* Added description pragma

---------

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

* ttf: Put cff to preprocessing
2024-06-29 22:52:21 +02:00
Nik
a0bb71be58 includes/std: Added std::core::execute_function() 2024-06-29 11:53:43 +02:00
WerWolv
c7fc39ac19 git: Make sure test data is always treated as binaries 2024-06-26 20:59:41 +02:00
WerWolv
b540ead0ae includes/std: Added std::IIndexed as a nicer wrapper around std::core::array_index() 2024-06-25 22:52:57 +02:00
Nik
26878548f0 includes/std: Fixed NullString not including null terminator and not checking for string end correctly 2024-06-23 18:45:13 +02:00
C3pa
e4c9d86755 includes/std: Add some fixes from the WerWolv/Documentation repo (#262)
* Escape backslash in DOSPath docs

* Spelling correction for std\sys.pat

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-06-22 10:59:36 +02:00
WerWolv
2a3de1b705 includes: Tabs -> Spaces 2024-06-22 10:46:30 +02:00
WerWolv
e02280f9ee includes/type: Added arbitrarily formattable type 2024-06-20 21:21:42 +02:00
WerWolv
bbba68cef7 includes/std: Added null-terminated strings to the strings library 2024-06-20 21:21:30 +02:00
Joachim Schiele
28b281b403 patterns/pe: Added .didata section support (#257) 2024-06-16 15:23:01 +02:00
Kirill Gladkikh
c807959d75 patterns/jpeg: Support EOF in the middle of JPEG (#240)
* Support EOF in the middle of file

* Changed to eoi marker searching
2024-06-16 15:16:01 +02:00
Francisco J. Solis
3416d30f2b pattern/dds: Fix bitfield PixelFormatFlags (#259)
* Fix bitfield PixelFormatFlags

The padding names should not repeat
Comments should be added to each field for clarification
Padding should be corrected for luminance.

* Re-work of PixelFormatFlags

Add more information considering current GIMP repository structure
https://gitlab.gnome.org/GNOME/gimp/-/blame/master/plug-ins/file-dds/dds.h\#L145
2024-06-09 22:15:05 +02:00
iTrooz
10bf1c76cf chore: mention description pragma in PR template 2024-05-20 01:05:48 +02:00
iTrooz
5b7c212029 git: use ccache (#253) 2024-05-20 01:01:59 +02:00
iTrooz
1c2e948940 test: Make description pragma mandatory (#251) 2024-05-20 00:35:24 +02:00
iTrooz
7ea34e410a fix: add missing ; to core.pat 2024-05-20 00:13:52 +02:00
iTrooz
56950e44d8 fix: use renamed PatternRuntime::getEvalError() (#252) 2024-05-20 00:10:34 +02:00
iTrooz
ed42452fc1 chore: remove old coverage code 2024-05-20 00:01:36 +02:00
iTrooz
a68ecb8888 fix: run tests concurrently 2024-05-20 00:01:00 +02:00
WerWolv
8d4cf59497 patterns/ffx: Updated submodule 2024-05-19 17:05:56 +02:00
Benjamin Gilbert
3c2fed22e4 patterns: Add Windows animated cursor (#242)
* patterns: Add Windows animated cursor

* Added readme entry

* Added mime type to readme

---------

Co-authored-by: Nik <werwolv98@gmail.com>
2024-05-19 16:58:03 +02:00
Christoph Koehler
ff550bd105 patterns: Add Digital Terrain Elevation Data (DTED) pattern file (#243)
Tested on DTED0 and DTED2, will likely work with DTED1 as well.
2024-05-19 16:55:30 +02:00
Rebuild
0ad6e3abde patterns/mp4: Use FixedPoint32 instead of u32 for width and height (#248)
Update mp4.hexpat

* Use FixedPoint32 instead of u32 for width and height
* Add formatting for displaying fixed point 16.16 and 8.8 numbers
2024-05-19 16:55:04 +02:00
Marijn Kneppers
891968db53 includes/std: Add create_directories to std (#250) 2024-05-19 16:46:05 +02:00
Marijn Kneppers
5799d1d7ea includes/std: Make std::file::flush not delete files (#246) 2024-05-12 23:39:49 +02:00
Marijn Kneppers
9c6bfeb50f includes/hex: Added hex::core::add_virtual_file (#247) 2024-05-12 23:38:57 +02:00
AdventureT
9f7cdded6a Crashlvl: Added support for version 0.95 (#245)
* Working on new Version

* Needs testing

* Updated CrashLvl script to support version 0.94c

* Update README.md

* Added TestData and author to script

* Delete tests/patterns/test_data/CrashLvl.hexpat.bin

* CrashLvl.hexpat: Added support for version 0.95
2024-05-12 23:38:25 +02:00
Claudius Coenen
03298b0b0c patterns: Added Wintec TES file pattern (#238) 2024-04-21 12:33:19 +02:00
LolHacksRule
5f2738872e patterns: Added XGSPak and XGSTexture patterns (#237)
* Add XGSPak and XGSTexture patterns

* Whoops forgot proper pointers

* Fix typo

* Whoops

* Proper start

* Update xgstexture.hexpat
2024-04-21 12:32:26 +02:00
nazDridoy
63585e6de7 patterns/7z: Added MIME type (#241) 2024-04-21 12:25:00 +02:00
Sabhya Raj Mehta
cb6caafa64 patterns/refs: Added Structure for MinStoreB+ node, missing GlobalRootNode Names & parses all Superblocks (#236)
[+] Added Structure for MinStoreB+ node, Missing GlobalRootNode Names
2024-03-29 11:55:01 +01:00
Leon Jacobs
236fadee47 patterns: Added gguf pattern (#235)
* (feat) add gguf parser

* (chore) cleanup empty struct

* (tests) add sample gguf for tests and update readme

* (feat) update type enum
2024-03-28 21:55:18 +01:00
GlorifiedPig
0549e62a14 patterns/tar: Fixed minor typo (#230)
changes "if" to "id"
2024-03-21 22:16:37 +01:00
Sabhya Raj Mehta
b4bf2b946f patterns/refs: Added filesystem Checking, comments, Renamed REFS_HEADER, and Fixed typo. (#231)
Added FileSystem Checking and comments && renamed struct ReFSHeader to VolumeBootRecord && Fixed Typo
2024-03-21 22:16:15 +01:00
Zwip-Zwap Zapony
5e82bfadac includes/std: Replace get_attribute_value with get_attribute_argument (#233)
Update get_attribute_argument/get_attribute_value

Replace std::core::get_attribute_value with std::core::get_attribute_argument
Mark optional arguments with square brackets in the documentation comments, and list their default values
2024-03-21 21:48:53 +01:00
Sabhya
a5c9f3b18a patterns: Added ReFS filesystem pattern (#229)
Added Pattern File For Parsing ReFS filesystem Header, SuperBlock and CheckPoint && updated README.md
2024-03-17 10:19:18 +01:00
Nik
38262e6bb9 tests/patterns: Moved xilinx bootgen test file to correct folder 2024-03-16 10:24:09 +01:00
Nik
0a37b60d70 git: Mark all test files as binary 2024-03-16 10:22:51 +01:00
Shadlock0133
345e264ff8 patterns: Add .bgcode file (#222)
Support for binary G-code files, used by 3d printers
2024-03-15 21:54:58 +01:00
syuuha
ba2c396534 patterns: Added pattern for ADTS files (#223) 2024-03-15 21:54:41 +01:00
paxcut
439f04e19b includes/std: Fixed "unknown function fm" error was shown in pattern data. (#225) 2024-03-15 21:54:03 +01:00
ogmini
eaeea8d093 patterns: Added pattern for Windows 11 Notepad Window State bin file (#228)
* Add files via upload

* Update README.md

* Update README.md

* Add files via upload

* Update Notepad-WindowState.hexpat

* Update and rename Notepad-WindowState.hexpat to notepadwindowstate.hexpat

* Rename Notepad-WindowState.hexpat.bin to notepad-windowstate.hexpat.bin

* Update README.md
2024-03-15 21:53:40 +01:00
Nik
9af8d7e693 includes/std: Added back #pragma once to mem library 2024-02-27 20:28:02 +01:00
WerWolv
dac2e0f786 patterns: Fixed a few errors 2024-02-25 22:59:32 +01:00
Nik
f70b7066b9 includes: Switch over to import statements (#224)
* Update includes and patterns to new import system

* Update namespaces to new syntax
2024-02-25 22:04:41 +01:00
WerWolv
3f44a743e8 yara: Added advanced analysis rules 2024-02-25 11:29:59 +01:00
WerWolv
834e5261b3 tests: Fixed tests not building 2024-02-18 13:07:04 +01:00
Nik
0e2966f10d includes/std: Added missing std::core::set_pattern_comment function 2024-02-09 13:23:51 +01:00
Nik
b2bc248447 includes/hex: SectionId -> Section 2024-01-31 08:24:03 +01:00
Nik
e6589ecba1 includes/std: Make std::mem::read_string take in a larger size 2024-01-31 08:22:25 +01:00
apewo
f75ba4b6ee patterns/pe: Add extra MIME Type (#220)
add pe mime

Co-authored-by: John Doe <bla@bla.bla>
2024-01-29 18:36:21 +01:00
Nik
cf18580960 includes/hex: Added decompress functions 2024-01-27 17:05:08 +01:00
lucia c
e7d1973957 patterns: Added SWF header pattern (#219)
* patterns: Added pattern for SWF files.

* Added test file for SWF header.

* Update README with SWF file type.
2024-01-27 15:53:16 +01:00
t1hq
35cc68544b encodings: Add custom encoding file for Big5 (#218)
* add big5 encoding table

* add notes for big5 encoding, and how to import custom encoding file
2024-01-27 11:18:47 +01:00
Nik
41d8967deb patterns/pyc: Remove unused function 2024-01-20 22:14:47 +01:00
pew
658ec20b37 patterns: Add .ras pattern (#216)
* Add simple .ras file pattern

* Update ras.hexpat

* Update README.md

* Add .ras test file

* Update ras.hexpat

* Update ras.hexpat

* Update ras.hexpat

* Update ras.hexpat
2024-01-10 00:38:18 +01:00
paxcut
fb5fcbafc1 includes/type: Changes to magic type to include address of failed asserts. (#217) 2024-01-10 00:36:17 +01:00
Brandon Maier
6f7988e96e patterns: Added Xilinx boot images (#210)
* Adds pattern for Xilinx's Zynq UltraScale+ Boot Image format.
* Boot images are generated by Xilinx's `bootgen` tool.
* Spec: Xilinx UG1283 https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/Zynq-UltraScale-MPSoC-Boot-and-Configuration
* Add test file generated as follows
  - Build bootgen tool from https://github.com/Xilinx/bootgen
  - Create dummy data with `dd if=/dev/zero of=image.bin count=1`
  - Create bif with `echo "img: {image.bin}" >image.bif`
  - Create test bin with
    `./bootgen -arch zynqmp -image image.bif -o xilinx_bootgen.hexpat.bin`
2023-12-28 18:32:13 +01:00
g4ngli0s
0a631f0c1f patterns/pe: Fix BaseRelocationBlock count inside BaseRelocationTable (#212) 2023-12-28 18:31:53 +01:00
EvelynTSMG
5942897c29 patterns/ffx: Pull in latest updates (#209)
* Add Final Fantasy X patterns

* Update README

* Fix: github dum

* Add Bastion patterns

* git: update submodules

---------

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

Added glTF binary file pattern.

* Add a test file for the glTF pattern.

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

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

* Update README

* Fix: github dum

* Add Bastion patterns

---------

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

* Update README.md

Added nes.hexpat to list of hex patterns

* Fix indenting of hex patterns list

Moved nes.hexpat below NE.hexpat

* Update README.md

Fixed indenting of PP pattern file's description being wrong

* Added x-msdownload MIME type to PE description

* Made indenting & code of ips.hexpat better

* Improvements to gb.hexpat

* Urgent fix to ips.hexpat

* Urgent fix to gb.hexpat

* Massive pe.hexpat improvement

* Replaced virtualDifference with relativeVirtualDifference

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

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

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

* Update README

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

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

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

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

* renamed some stuff and improved error messages

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

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

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

* patterns/jpeg: add RGB component IDs

* patterns/jpeg: add struct for APP14 marker

* patterns/jpeg: add definition for COM marker

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

* Needs testing

* Updated CrashLvl script to support version 0.94c

* Update README.md

* Added TestData and author to script

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

* Update .was pattern file

* Update .was/.wa3 pattern file

* Update README.md

* Update README.md

* Update .fas & .was pattern files

* Update README.md

* Update fas_oskasoftware_old.hexpat

* Added WAS test file

* Update WAS test file

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

* Update README.md

Added nes.hexpat to list of hex patterns

* Fix indenting of hex patterns list

Moved nes.hexpat below NE.hexpat

* Update README.md

Fixed indenting of PP pattern file's description being wrong

* Added x-msdownload MIME type to PE description

* Made indenting & code of ips.hexpat better

* Improvements to gb.hexpat

* Urgent fix to ips.hexpat

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

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

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

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

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

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

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

* patterns/tiff: show IFD number in IFD list

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

* patterns/tiff: add TIFFRational type

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

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

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

* patterns/tiff: add ValueOffset abstraction

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

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

* patterns/tiff: drop dead code

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

* patterns/tiff: drop set_endian()

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

Fail if we don't recognize the magic number.

* patterns/tiff: minor cleanups

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

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

* patterns/tiff: rewrite strip array generation

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

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

* patterns/tiff: add ImageData array for tiled IFDs

* patterns/tiff: increase variable widths for BigTIFF

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

* patterns/tiff: support BigTIFF

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

* Update README.md

Added nes.hexpat to list of hex patterns

* Fix indenting of hex patterns list

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

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

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

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

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

* Fixed type of ParentLocatorEntry (char -> char16)

* Fixed item address of MetadataTableEntry

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

New improvement

* Add ips.hexpat via upload

* Add ips.hexpat.ips via upload

* Added IPS to README

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

* Added padding and crc32 fields

* Added unit test file

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

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

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

* Fix string parsing

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

module, base, kernel and packages

* Updated README with SELinux patterns

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

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

* Update 7z.hexpat v1.02

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

* themes: add catppuccin flavors

* chore: rename catppuccin files

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

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

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

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

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

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

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

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

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

---

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

Thanks!

* Added test file

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

pattern language created for .cda files

* added test file for cda pattern

* Delete cda.hexpat.cda.cda

* Add test file cda

test file for cda pattern

* Update README.md

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

* Update README.md

Update readme to include tiff hexpat

* added file to test the pattern

---------

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

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

* missing include files

* Small style fixes

---------

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

* Add mime type

* Add test

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

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

---------

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

* Update README.md

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

2
.gitattributes vendored
View File

@@ -1,2 +1,4 @@
*.pat linguist-language=Rust
*.hexpat linguist-language=Rust
tests/patterns/test_data/** binary

View File

@@ -5,7 +5,8 @@
## Checklist
- [ ] 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 new pattern has a description pragma (`#pragma description My pattern Description here`)
- [ ] 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
- Try to keep this file below ~ 1 MB

View File

@@ -8,7 +8,7 @@ on:
repository_dispatch:
types: [run_tests]
workflow_dispatch:
inputs:
inputs:
generate_docs:
description: "Regenerate docs"
required: false
@@ -17,7 +17,7 @@ on:
jobs:
tests:
name: 🎯 Dispatch changes
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
env:
DISPATCH_TOKEN: ${{ secrets.DISPATCH_TOKEN }}
permissions:
@@ -27,13 +27,13 @@ jobs:
steps:
- name: 🧰 Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive
- name: 📄 Check changed include files
id: changed-includes
uses: tj-actions/changed-files@v35
uses: tj-actions/changed-files@v45
with:
files: includes/**/*.pat
@@ -45,3 +45,12 @@ jobs:
repo: Documentation
owner: WerWolv
event_type: update_pl_docs
- name: ✉️ Update PatternLanguage Website
if: ${{ env.DISPATCH_TOKEN != '' }}
uses: mvasigh/dispatch-action@main
with:
token: ${{ secrets.DISPATCH_TOKEN }}
repo: PatternLanguageWeb
owner: WerWolv
event_type: rebuild_wasm

View File

@@ -7,11 +7,17 @@ on:
branches: [ '*' ]
repository_dispatch:
types: [run_tests]
workflow_call:
inputs:
pattern_language_git_repo:
type: string
pattern_language_git_hash:
type: string
jobs:
tests:
name: 🧪 Unit Tests
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
@@ -19,8 +25,9 @@ jobs:
steps:
- name: 🧰 Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: ${{ github.repository_owner }}/ImHex-Patterns
submodules: recursive
- name: ⬇️ Install dependencies
@@ -28,54 +35,56 @@ jobs:
sudo apt update
sudo apt install -y \
build-essential \
gcc-12 \
g++-12 \
ccache \
gcc-14 \
g++-14 \
lld \
${PKGCONF:-} \
cmake \
make \
ninja-build \
python3 \
python3-pip \
libmagic-dev \
lcov
sudo pip install jsonschema
- name: 📜 Setup ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: ${{ runner.os }}-ccache-${{ github.run_id }}
restore-keys: ${{ runner.os }}-ccache
max-size: 1G
- name: 🛠️ Build
run: |
cd tests
mkdir -p build
cd build
CC=gcc-12 CXX=g++-12 cmake \
CC=gcc-14 CXX=g++-14 cmake \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_C_FLAGS="-fuse-ld=lld --coverage" \
-DCMAKE_CXX_FLAGS="-fuse-ld=lld --coverage" \
-DIMHEX_PATTERNS_ENABLE_UNIT_TESTS=ON \
-DLIBPL_ENABLE_TESTS=OFF \
-DLIBPL_ENABLE_CLI=OFF \
-DIMHEX_PATTERNS_LIBPL_GIT_REPO="${{ inputs.pattern_language_git_repo }}" \
-DIMHEX_PATTERNS_LIBPL_GIT_HASH="${{ inputs.pattern_language_git_hash }}" \
-G Ninja \
..
make -j4
ninja unit_tests
- name: 🧪 Perform Unit Tests
run: |
cd tests/build
ctest --output-on-failure
- name: ⚗️ Generate Coverage Report
run: |
cd tests/build
lcov -d ./_deps/pattern_language-build/lib --gcov-tool /usr/bin/gcov-12 -c -o coverage.info
- name: ⬆️ Upload Coverage Report
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: tests/build/coverage.info
cd build
ctest --output-on-failure -j 4
- name: 📎 Validate JSON Files
run: |
cd constants
for file in ./[!_schema.json]*; do jsonschema -i $file _schema.json; done
for file in ./[!_]*; do jsonschema -i $file _schema.json; done
cd ..
cd tips
for file in ./[!_schema.json]*; do jsonschema -i $file _schema.json; done
for file in ./[!_]*; do jsonschema -i $file _schema.json; done
cd ..

12
.gitignore vendored
View File

@@ -1,5 +1,13 @@
tests/cmake-build-debug/
tests/cmake*/
tests/build*/
build/
cmake-build-*/
.vscode/
.devcontainer/
.cache/
.idea/
.DS_Store
.DS_Store
compile_commands.json

8
.gitmodules vendored
View File

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

42
CMakeLists.txt Normal file
View File

@@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 3.16)
project(ImHex-Patterns)
option(IMHEX_PATTERNS_ENABLE_UNIT_TESTS "Enable building unit tests for ImHex-Patterns" OFF)
# if enabled, add a unit_test custom target for all the unit tests to be registered against
if(IMHEX_PATTERNS_ENABLE_UNIT_TESTS)
if(NOT TARGET unit_tests)
enable_testing()
add_custom_target(unit_tests)
endif()
endif()
# If this has been manually cloned into another project, libpl may already have been set up
if(NOT TARGET libpl)
include(FetchContent)
if (NOT DEFINED IMHEX_PATTERNS_LIBPL_GIT_REPO OR IMHEX_PATTERNS_LIBPL_GIT_REPO STREQUAL "")
set(LIBPL_GIT_REPO "https://github.com/WerWolv/PatternLanguage")
else()
set(LIBPL_GIT_REPO ${IMHEX_PATTERNS_LIBPL_GIT_REPO})
endif()
if (NOT DEFINED IMHEX_PATTERNS_LIBPL_GIT_HASH OR IMHEX_PATTERNS_LIBPL_GIT_HASH STREQUAL "")
set(LIBPL_GIT_TAG "master")
else()
set(LIBPL_GIT_TAG ${IMHEX_PATTERNS_LIBPL_GIT_HASH})
endif()
FetchContent_Declare(
pattern_language
GIT_REPOSITORY ${LIBPL_GIT_REPO}
GIT_TAG ${LIBPL_GIT_TAG}
)
FetchContent_MakeAvailable(pattern_language)
endif()
if(IMHEX_PATTERNS_ENABLE_UNIT_TESTS)
add_subdirectory(tests)
endif()

View File

@@ -8,5 +8,5 @@ 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 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.

301
README.md
View File

@@ -1,6 +1,7 @@
# ImHex Database
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
@@ -22,75 +23,229 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| Name | MIME | Path | Description |
|------|------|------|-------------|
| 3DS | | [`patterns/3ds.hexpat`](patterns/3ds.hexpat) | Autodesk 3DS Max Model file |
| 7Z | | [`patterns/7z.hexpat`](patterns/7z.hexpat) | 7z File Format |
| ADTFDAT | | [`patterns/adtfdat.hexpat`](patterns/adtfdat.hexpat) | [ADTFDAT files](https://digitalwerk.gitlab.io/solutions/adtf_content/adtf_base/adtf_file_library) |
| ADTS | `audio/x-hx-aac-adts` | [`patterns/adts.hexpat`](patterns/adts.hexpat) | ADTS/AAC audio files |
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
| ANI | `application/x-navi-animation` | [`patterns/ani.hexpat`](patterns/ani.hexpat) | Windows Animated Cursor file |
| APFS | | [`patterns/fs/apfs.hexpat`](patterns/fs/apfs.hexpat) | Apple File Ssytem (APFS) |
| AppleSingle | `application/applefile` | [`patterns/apple_single_double.hexpat`](patterns/apple_single_double.hexpat) | AppleSingle Dual Fork file |
| AppleDouble | `multipart/appledouble` | [`patterns/apple_single_double.hexpat`](patterns/apple_single_double.hexpat) | AppleDouble Resource Fork/Finder Metadata file |
| AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files |
| ARC | | [`patterns/arc.hexpat`](patterns/arc.hexpat) | Minecraft Legacy Console Edition ARC files |
| ARIA2 | | [`patterns/aria2.hexpat`](patterns/aria2.hexpat) | ARIA2 Download Manager Control files |
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
| Arma 3 config | `application/x.a3-rap` | [`patterns/a3/a3_rap.hexpat`](patterns/a3/a3_rap.hexpat) | Arma 3 binary/rapified config |
| Arma 3 P3D (MLOD) | `model/x.a3-p3d-mlod` | [`patterns/a3/a3_p3d_mlod.hexpat`](patterns/a3/a3_p3d_mlod.hexpat) | Arma 3 P3D model file (MLOD) |
| Arma 3 PAA | `image/x.a3-paa` | [`patterns/a3/a3_paa.hexpat`](patterns/a3/a3_paa.hexpat) | Arma 3 PAA texture file |
| Arma 3 RTM | `application/x.a3-rtm` | [`patterns/a3/a3_rtm.hexpat`](patterns/a3/a3_rtm.hexpat) | Arma 3 RTM animation file (plain) |
| Arma 3 RTM (binarized) | `application/x.a3-bmtr` | [`patterns/a3/a3_bmtr.hexpat`](patterns/a3/a3_bmtr.hexpat) | Arma 3 RTM animation file (binarized) |
| Arma 3 texHeaders.bin | `application/x.a3-texheaders` | [`patterns/a3/a3_texheaders.hexpat`](patterns/a3/a3_texheaders.hexpat) | Arma 3 texture index file |
| Assassin's Creed: Unity | | [`patterns/AC Unity`](patterns/Assassin's Creed: Unity) | Assassin's Creed: Unity archive files -- .forge & .data (compressed and decompressed) -- |
| Bastion | | [`patterns/bastion/*`](https://gitlab.com/EvelynTSMG/imhex-bastion-pats) | Various [Bastion](https://en.wikipedia.org/wiki/Bastion_(video_game)) files |
| BeyondCompare BCSS | | [`patterns/bcss.hexpat`](patterns/bcss.hexpat) | BeyondCompare Snapshot (BCSS) file |
| Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files |
| Prusa BGCODE | | [`patterns/bgcode.hexpat`](patterns/bgcode.hexpat) | PrusaSlicer Binary G-Code files |
| BLEND | | [`patterns/blend.hexpat`](patterns/blend.hexpat) | Blender Project file |
| BLF | | [`patterns/blf.hexpat`](patterns/blf.hexpat) | Vector BLF Frame Logging Files |
| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files |
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
| WAV | `audio/wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers |
| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets |
| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions |
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
| AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files |
| NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files |
| NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files |
| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO |
| Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files |
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
| ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files |
| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files |
| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files |
| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface |
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
| ISO | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system |
| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files |
| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) |
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System |
| Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files |
| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding |
| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format |
| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format |
| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format |
| NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC |
| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format |
| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams |
| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format |
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format |
| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files |
| ID3 | `audio/mpeg` | [`patterns/id3.hexpat`](patterns/id3.hexpat) | ID3 tags in MP3 files |
| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format |
| CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format |
| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob |
| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive |
| NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format |
| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format |
| GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format |
| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) |
| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cardridge ROM |
| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive |
| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files |
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable |
| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable |
| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) |
| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) |
| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable |
| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file |
| BIN | | [`patterns/selinux.hexpat`](patterns/selinux.pat) | SE Linux modules |
| BINKA | | [`patterns/binka.hexpat`](patterns/binka.pat) | RAD Game Tools Bink Audio (BINKA) files |
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
| bplist | `application/x-bplist` | [`patterns/bplist.hexpat`](patterns/bplist.hexpat) | Apple's binary property list format (bplist) |
| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) |
| BZIP3 | | [`patterns/bzip3.hexpat`](patterns/bzip3.hexpat) | Parses BZip3 compression (file format) by Kamila Szewczyk |
| CAB | | [`patterns/cab.hexpat`](patterns/cab.hexpat) | Microsoft Cabinet (CAB) Files |
| CCHVA | | [`patterns/cchva.hexpat`](patterns/cchva.hexpat) | Command and Conquer Voxel Animation |
| CCVXL | | [`patterns/ccvxl.hexpat`](patterns/ccvxl.hexpat) | Command and Conquer Voxel Model |
| CCPAL | | [`patterns/ccpal.hexpat`](patterns/ccpal.hexpat) | Command and Conquer Voxel Palette |
| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format |
| 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 |
| CDA | | [`patterns/cda.hexpat`](patterns/cda.hexpat) | Compact Disc Audio track |
| CHD | | [`patterns/chd.hexpat`](patterns/chd.hexpat) | MAME Compressed Hunks of Data file |
| CHM | `application/vnd.ms-htmlhelp` | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) |
| Chromium Pak | | [`patterns/chromium_pak.hexpat`](patterns/chromium_pak.hexpat) | Chromium pak file |
| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable |
| CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format |
| CPIO | | [`patterns/cpio_portable_ascii.hexpat`](patterns/cpio_portable_ascii.hexpat) | Portable ASCII CPIO Format |
| CPIO | | [`patterns/cpio_new_ascii.hexpat`](patterns/cpio_new_ascii.hexpat) | "New" ASCII CPIO Format |
| CrashLvl | | [`patterns/Crashlvl.hexpat`](patterns/Crashlvl.hexpat) | Crash Bandicoot - Back in Time (fan game) User created level format |
| CREDHIST | | [`patterns/credhist.hexpat`](patterns/credhist.hexpat) | CREDHIST Format |
| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface |
| DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format |
| DS_Store | `application/octet-stream` | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format |
| Devil May Cry HD Collection | | [`patterns/Devil May Cry HD Collection`](patterns/Devil May Cry HD Collection) | 3D Model files used in Devil May Cry 3 HD Collection |
| DICOM | `application/dicom` | [`patterns/dicom.hexpat`](patterns/dicom.hexpat) | DICOM image format |
| DISK_PARSER (DFIR) | `application/x-ima` | [`patterns/DFIR/DISK_PARSER.hexpat`](patterns/DFIR/DISK_PARSER.hexpat) | Recursive Disk/Volume/Filesystem parsing |
| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) |
| DMP | | [`patterns/dmp64.hexpat`](patterns/dmp64.hexpat) | Windows Kernel Dump(DMP64) |
| DOS | `application/x-dosexec` | [`patterns/dos.hexpat`](patterns/dos.hexpat) | 16-bit real mode DOS EXE files |
| DOTNET_BinaryFormatter | | [`patterns/dotnet_binaryformatter.hexpat`](patterns/dotnet_binaryformatter.hexpat) | .NET BinaryFormatter |
| DPAPI_Blob | | [`patterns/dpapblob.hexpat`](patterns/dpapiblob.hexpat) | Data protection API Blob File Format |
| DPAPI_MasterKey | | [`patterns/dpapimasterkey.hexpat`](patterns/dpapimasterkey.hexpat) | Data protection API MasterKey |
| DS_Store | | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format |
| DTA | | [`patterns/max_v104.hexpat`](patterns/max_v104.hexpat) | Mechanized Assault and Exploration v1.04 (strategy game) save file format |
| DTED | | [`patterns/dted.hexpat`](patterns/dted.hexpat) | Digital Terrain Elevation Data (DTED) |
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
| ESP32 Image | | [`patterns/esp32_image.hexpat`](patterns/esp32_image.hexpat) | Firmware image format for the ESP32 chip family |
| EVTX | `application/x-ms-evtx` | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log |
| EXFAT | | [`patterns/fs/exfat.hexpat`](patterns/fs/exfat.hexpat) | Extensible File Allocation Table (exFAT) |
| EXFAT (DFIR) | | [`patterns/DFIR/exFAT.hexpat`](patterns/DFIR/exFAT.hexpat) | Imported by DISK_PARSER.hexpat |
| EXT4 | | [`patterns/fs/ext4.hexpat`](patterns/fs/ext4.hexpat) | Ext4 File System |
| FAS | | [`patterns/fas_oskasoftware.hexpat`](patterns/fas_oskasoftware.hexpat) [`patterns/fas_oskasoftware_old.hexpat`](patterns/fas_oskasoftware_old.hexpat) (Old versions of Oska DeskMate) | Oska Software DeskMates FAS (Frames and Sequences) file |
| FAT32 | | [`patterns/fs/fat32.hexpat`](patterns/fs/fat32.hexpat) | FAT32 File System |
| FAT32 (DFIR) | | [`patterns/DFIR/FAT32.hexpat`](patterns/DFIR/FAT32.hexpat) | Imported by DISK_PARSER.hexpat |
| FBX | | [`patterns/fbx.hexpat`](patterns/fbx.hexpat) | Kaydara FBX Binary |
| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob |
| FFX | | [`patterns/ffx/*`](https://gitlab.com/EvelynTSMG/imhex-ffx-pats) | Various Final Fantasy X files |
| File System | `application/x-ima` | [`patterns/fs/pattern.hexpat`](patterns/fs/pattern.hexpat) | Drive File System |
| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format |
| FLC/FLIC | | [`patterns/flc.hexpat`](patterns/flc.hexpat) | FLC/FLIC animation file |
| FLV | | [`patterns/flv.hexpat`](patterns/flv.hexpat) | FLv animation file |
| Flipper Zero Settings | | [`patterns/flipper_settings.hexpat`](patterns/flipper_settings.hexpat) | Flipper Zero Settings Files |
| GB | `application/x-gameboy-rom` | [`patterns/gb.hexpat`](patterns/gb.hexpat) | Game Boy ROM |
| GBA | `application/x-gameboy-advance-rom` | [`patterns/gba.hexpat`](patterns/gba.hexpat) | Game Boy Advance ROM header |
| GBX | | [`patterns/gbx.hexpat`](patterns/gbx.hexpat) | GameBoy ROM file GBX footer |
| Gen | | [`patterns/gen.hexpat`](patterns/gen.hexpat) | Sega Genesis/MegaDrive ROM |
| GGUF | | [`patterns/gguf.hexpat`](patterns/gguf.hexpat) | GGML Inference Models |
| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files |
| GLTF | `model/gltf-binary` | [`patterns/gltf.hexpat`](patterns/gltf.hexpat) | GL Transmission Format binary 3D model file |
| GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format |
| Halo Tag || [`patterns/hinf_tag.hexpat`](patterns/hinf_tag.hexpat) | Halo Infinite Tag Files |
| Halo Module || [`patterns/hinf_module.hexpat`](patterns/hinf_module.hexpat) | Halo Infinite Module Archive Files |
| Halo HavokScript || [`patterns/hinf_luas.hexpat`](patterns/hinf_luas.hexpat) | Halo Infinite HavokScript 5.1 Bytecode |
| HPROF || [`patterns/hprof.hexpat`](patterns/hprof.hexpat) | Java HPROF Profiler Data Format |
| HSDT || [`patterns/hsdt.hexpat`](patterns/hsdt.hexpat) | HiSilicon device-tree table images |
| 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 |
| IM*H || [`patterns/imah.hexpat`](patterns/imah.hexpat) | DJI Signed Firmware (IM*H) |
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) |
| IPS | | [`patterns/ips.hexpat`](patterns/ips.hexpat) | IPS (International Patching System) files |
| ISO | `application/x-iso9660-image` | [`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 |
| Kindle Update | | [`patterns/kindle_update.hexpat`](patterns/kindle_update.hexpat) | Kindle Update Package |
| KTX | `image/ktx` | [`patterns/ktx.hexpat`](patterns/ktx.hexpat) | Khronos TeXture 1.0 |
| LOC | | [`patterns/loc.hexpat`](patterns/loc.hexpat) | Minecraft Legacy Console Edition Language file |
| Lua 4.0 | | [`patterns/lua40.hexpat`](patterns/lua40.hexpat) | Lua 4.0 bytecode |
| LUC | | [`patterns/popcap_luc.hexpat`](patterns/popcap_luc.hexpat) | PopCap's proprietary Lua bytecode |
| Lua 5.0 | | [`patterns/lua50.hexpat`](patterns/lua50.hexpat) | Lua 5.0 bytecode |
| Lua 5.1 | | [`patterns/lua51.hexpat`](patterns/lua51.hexpat) | Lua 5.1 bytecode |
| Lua 5.2 | | [`patterns/lua52.hexpat`](patterns/lua52.hexpat) | Lua 5.2 bytecode |
| Lua 5.3 | | [`patterns/lua53.hexpat`](patterns/lua53.hexpat) | Lua 5.3 bytecode |
| Lua 5.4 | | [`patterns/lua54.hexpat`](patterns/lua54.hexpat) | Lua 5.4 bytecode |
| LCE Savefile | | [`patterns/lcesave.hexpat`](patterns/lcesave.hexpat) | Minecraft Legacy Console Edition save file |
| LZNT1 | | [`patterns/lznt1.hexpat`](patterns/lznt1.hexpat) | LZNT1 compressed data format |
| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable |
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files |
| MO | | [`patterns/mo.hexpat`](patterns/mo.hexpat) | GNU Machine Object (MO) files containing translations for gettext |
| mp4 | `video/mp4` | [`patterns/mp4.hexpat`](patterns/mp4.hexpat) | MPEG-4 Part 14 digital multimedia container format |
| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format |
| MSSCMP | | [`patterns/msscmp.hexpat`](patterns/msscmp.hexpat) | Miles Sound System Compressed Archive |
| NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files |
| NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format |
| N64 | | [`patterns/n64.hexpat`](patterns/n64.hexpat) | Nintendo 64 ROM header |
| NDS | `application/x-nintendo-ds-rom` | [`patterns/nds.hexpat`](patterns/nds.hexpat) | DS Cartridge Header |
| NE | `application/x-ms-ne-executable` | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
| nes | | [`patterns/nes.hexpat`](patterns/nes.hexpat) | Nintendo Entertainment System ROM |
| NSF | | [`patterns/nsf.hexpat`](patterns/nsf.hexpat) | NES Sound Format |
| NSFe | | [`patterns/nsfe.hexpat`](patterns/nsfe.hexpat) | NES Sound Format extended |
| NotepadCache | | [`patterns/notepad-cache.hexpat`](patterns/notepad-cache.hexpat) | Windows Notepad Cache |
| NotepadStateFile | | [`patterns/notepad-state.hexpat`](patterns/notepad-state.hexpat) | Windows Notepad .bin State files |
| NotepadWindowState | | [`patterns/notepadwindowstate.hexpat`](patterns/notepadwindowstate.hexpat) | Windows 11 Notepad - Window State .bin file |
| 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 |
| NTFS | | [`patterns/fs/ntfs.hexpat`](patterns/fs/ntfs.hexpat) | NTFS (NT File System) |
| NTFS (DFIR) | | [`patterns/DFIR/NTFS.hexpat`](patterns/DFIR/NTFS.hexpat) | Imported by DISK_PARSER.hexpat |
| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format |
| ORP / ORS | | [`patterns/orp.hexpat`](patterns/orp.hexpat) | OpenRGB profile format |
| PACK | | [`patterns/roblox_pack.hexpat`](patterns/roblox_pack.hexpat) | Roblox shader archive format |
| PAK | | [`patterns/xgspak.hexpat`](patterns/xgspak.hexpat) | Exient XGS Engine Pak files |
| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets |
| PcapNG | `application/vnd.tcpdump.pcap` | [`patterns/pcapng.hexpat`](patterns/pcapng.hexpat) | pcapng header and packets |
| PCK | | [`patterns/pck.hexpat`](patterns/pck.hexpat) | Minecraft Legacy Console Edition .pck file |
| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format |
| PE | `application/x-dosexec` `application/x-msdownload` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
| PEF | | [`patterns/pef.hexpat`](patterns/pef.hexpat) | Preffered Executable Format executable (for Mac OS 7.1.2 - Mac OS 10.4 / BeOS) |
| PEX | | [`patterns/pex.hexpat`](patterns/pex.hexpat) | Bethesda Papyrus executable compiled script file |
| PP | | [`patterns/selinuxpp.hexpat`](patterns/selinuxpp.pat) | SE Linux package |
| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) |
| PF | | [`patterns/pf.hexpat`](patterns/pf.hexpat) | Microsoft uncompressed prefetch files (.pf) |
| Pickle | | [`patterns/pickle.hexpat`](patterns/pickle.hexpat) | Python Pickle Protocol |
| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format |
| PKM | | [`patterns/pkm.hexpat`](patterns/pkm.hexpat) | PKM texture 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 |
| psafe3 | | [`patterns/psafe3.hexpat`](patterns/psafe3.hexpat`) | Password Safe V3 |
| PyInstaller | | [`patterns/pyinstaller.hexpat`](patterns/pyinstaller.hexpat) | PyInstaller binray files |
| PYC | `application/x-bytecode.python` | [`patterns/pyc.hexpat`](patterns/pyc.hexpat) | Python bytecode files |
| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file |
| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files |
| Quake 3 engine demo | | [`patterns/q3demo.hexpat`](patterns/q3demo.hexpat) | Demos/replays of most Quake 3 engine games |
| quantized-mesh | | [`patterns/quantized-mesh.hexpat`](patterns/quantized-mesh.hexpat) | Cesium quantized-mesh terrain |
| RAR | `application/x-rar` | [`patterns/rar.hexpat`](patterns/rar.hexpat) | RAR archive file format |
| RAS | `image/x-sun-raster` | [`patterns/ras.hexpat`](patterns/ras.hexpat) | RAS image files |
| RCF 1.2 | | [`patterns/rcf_v1_2.hexpat`](patterns/rcf_v1_2.hexpat) | Radcore Cement Library 1.2 file header |
| ReFS | | [`patterns/refs.hexpat`](patterns/fs/refs.hexpat) | Microsoft Resilient File System |
| RGBDS | | [`patterns/rgbds.hexpat`](patterns/rgbds.hexpat) | [RGBDS](https://rgbds.gbdev.io) object file format |
| RPM | | [`patterns/rpm.hexpat`](patterns/rpm.hexpat) | [RPM](http://ftp.rpm.org/max-rpm/s1-rpm-file-format-rpm-file-format.html) package file format |
| SDB | | [`patterns/sdb.hexpat`](patterns/sdb.hexpat) | [Shim DataBase](https://learn.microsoft.com/en-us/windows/win32/devnotes/application-compatibility-database) file format |
| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format |
| shp | | [`patterns/shp.hexpat`](patterns/shp.hexpat) | ESRI shape file |
| SHR | | [`patterns/SHR.hexpat`](patterns/SHR.hexpat) | Apple IIgs Super Hi-Res (SHR) + PaintWorks Animation (ANI) |
| shx | | [`patterns/shx.hexpat`](patterns/shx.hexpat) | ESRI index file |
| smk | | [`patterns/smk.hexpat`](patterns/smk.hexpat) | Smacker video file |
| SNES | | [`patterns/snes.hexpat`](patterns/snes.hexpat) | Super Nintendo Entertainment System ROM header |
| sup | | [`patterns/sup.hexpat`](patterns/sup.hexpat) | PGS Subtitle |
| SPC | | [`patterns/spc.hexpat`](patterns/spc.hexpat) | Super Nintendo Entertainment System SPC-700 dump file |
| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions |
| STDF | | [`patterns/stdfv4.hexpat`](patterns/stdfv4.hexpat) | Standard test data format for IC testers |
| 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 |
| SQLite3 | `application/vnd.sqlite3` | [`patterns/sqlite3.hexpat`](patterns/sqlite3.hexpat) | SQLite3 Database |
| SWF | `application/x-shockwave-flash` |[`patterns/swf.hexpat`](patterns/swf.hexpat) | Shockwave Flash file format |
| TA | | [`patterns/optee_ta.hexpat`](patterns/optee_ta.hexpat) | OPTEE Trusted Application Executable |
| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format |
| TARC | | [`patterns/tarc.hexpat`](patterns/tarc.hexpat) | KEX Engine TARC file format |
| TES | | [`patterns/wintec_tes.hexpat`](patterns/wintec_tes.hexpat) | Wintec TES GPS log |
| Thumbcache | | [`patterns/thumbcache.hexpat`](patterns/thumbcache.hexpat) | Windows thumbcache_*.db |
| TIFF | `image/tiff` | [`patterns/tiff.hexpat`](patterns/tiff.hexpat) | Tag Image File Format |
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
| TTF | `font/ttf`, `font/otf` | [`patterns/ttf.hexpat`](patterns/ttf.hexpat) | TrueType and OpenType font format |
| Ubiquiti | | [`patterns/ubiquiti.hexpat`](patterns/ubiquiti.hexpat) | Ubiquiti Firmware (update) image |
| UPK | | [`patterns/upk-ue3.hexpat`](patterns/upk-ue3.hexpat) | Unreal Engine 3 UPK file |
| UEFI | | [`patterns/uefi.hexpat`](patterns/uefi.hexpat)` | UEFI structs for parsing efivars |
| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log |
| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) |
| UEFI Boot Entry | | [`patterns/uefi_boot_entry.hexpat`](patterns/uefi_boot_entry.hexpat) | UEFI Boot Entry (Load option) |
| UEFI Variable Store | | [`patterns/uefi_fv_varstore.hexpat`](patterns/uefi_fv_varstore.hexpat) | UEFI Firmware Volume Variable Store |
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
| Unity Asset Bundle | | [`patterns/unity-asset-bundle.hexpat`](patterns/unity-asset-bundle.hexpat) | Unity Asset Bundle |
| Valve VPK | | [`patterns/valve_vpk.hexpat`](valve_vpk.hexpat) | Valve Package File |
| VBMeta | | [`patterns/vbmeta.hexpat`](patterns/vbmeta.hexpat) | Android VBMeta image |
| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files |
| VEADO | | [`patterns/veado.hexpat`](patterns/veado.hexpat) | veadotube mini avatar file |
| VGM | | [`patterns/vgm.hexpat`](patterns/vgm.hexpat) | VGM (Video Game Music) sound log |
| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format |
| VOX | | [`patterns/vox.hexpat`](patterns/vox.hexpat) | MagicaVoxel scene description format |
| WAV | `audio/x-wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
| WAS | | [`patterns/was_oskasoftware.hexpat`](patterns/was_oskasoftware.hexpat) | Oska Software DeskMates WAS/WA3 (WAVE/MP3 Set) file
| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive |
| WebP | `image/webp` | [`patterns/webp.hexpat`](patterns/webp.hexpat) | Google WebP image |
| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable |
| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cartridge ROM |
| XGT | | [`patterns/xgt.hexpat`](patterns/xgstexture.hexpat) | Exient XGS Engine Texture |
| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams |
| Xilinx Bootgen | `application/x-xilinx-boot-zynqmp` | [`patterns/xilinx_bootgen.hexpat`](patterns/xilinx_bootgen.hexpat) | Xilinx ZynqMP Boot Images |
| ZIM | | [`patterns/zim.hexpat`](patterns/zim.hexpat) | [ZIM](https://openzim.org) file format |
| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers |
| ZLIB | `application/zlib` | [`patterns/zlib.hexpat`](patterns/zlib.hexpat) | ZLIB compressed data format |
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
| MOD | `3d-model/mod` | [`patterns/DMC3HD-Mod.hexpat`](patterns/dmc3_hd_mod.hexpat) | 3D Model files used in Devil May Cry 3 HD Collection |
| CBM BASIC | | [`commodore_basic.hexpat`](patterns/commodore_basic.hexpat) | Commodore BASIC |
| Atari XEX | | [`xex.hexpat`](patterns/xex.hexpat) | Atari 8-bit binary format |
| Terminfo | `application/x-terminfo` and `application/x-terminfo2` | [`patterns/terminfo.hexpat`](patterns/terminfo.hexpat) | Compiled *(legacy and extended)* term info entry |
### Scripts
@@ -103,9 +258,9 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| Name | Path | Description |
|------|------|-------------|
| libstd | [`includes/std/*`](includes/std) | Pattern Language Standard Libaray |
| libtype | [`includes/type/*`](includes/type) | Various custom types with special formatters |
| libhex | [`includes/hex/*`](includes/hex) | Functions to interact with ImHex |
| libstd | [`includes/std/*`](includes/std) | Pattern Language Standard Library |
| libtype | [`includes/type/*`](includes/type) | Various custom types with special formatters |
### Yara rules
@@ -117,6 +272,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| Name | Path | Description |
|------|------|-------------|
| Arma 3 | [`magic/arma3_magic`](magic/arma3_magic) | Identifies Arma 3 binary formats |
| Nintendo Switch | [`magic/nintendo_switch_magic`](magic/nintendo_switch_magic) | Identifies common file types used on the Nintendo Switch |
| Portable Executable | [`magic/portable_executable_magic`](magic/portable_executable_magic) | Identifies PE files used on Windows
@@ -140,6 +296,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| ASCII+OEM | [`encodings/ascii_oem.tbl`](encodings/ascii_oem.tbl) | ASCII encoding with Windows OEM characters |
| Baltic ISO | [`encodings/baltic_iso.tbl`](encodings/baltic_iso.tbl) | Baltic ISO encoding |
| Baltic Windows | [`encodings/baltic_windows.tbl`](encodings/baltic_windows.tbl) | Baltic Windows encoding |
| Big5 (Traditional Chinese) | [`encodings/big5.tbl`](encodings/big5.tbl) | Big5 encoding for Traditional Chinese |
| Cyrillic ISO | [`encodings/cyrillic_iso.tbl`](encodings/cyrillic_iso.tbl) | Cyrillic ISO encoding |
| Cyrillic Windows | [`encodings/cyrillic_windows.tbl`](encodings/cyrillic_windows.tbl) | Cyrillic Windows encoding |
| Cyrillic KOI8-R | [`encodings/cyrillic_koi8_r.tbl`](encodings/cyrillic_koi8_r.tbl) | Cyrillic KOI8-R encoding (Russian Characters) |
@@ -169,13 +326,27 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| Vietnamese | [`encodings/vietnamese.tbl`](encodings/vietnamese.tbl) | Vietnamese character encoding |
### 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 |
### 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 |
| Catppuccin Latte | [`themes/catppuccin-latte.json`](themes/catppuccin-latte.json) | Catppuccin Latte Flavor (Light Theme) |
| Catppuccin Frappe | [`themes/catppuccin-frappe.json`](themes/catppuccin-frappe.json) | Catppuccin Frappe Flavor (Dark Theme) |
| Catppuccin Macchiato | [`themes/catppuccin-macchiato.json`](themes/catppuccin-macchiato.json) | Catppuccin Macchiato Flavor (Dark Theme) |
| Catppuccin Mocha | [`themes/catppuccin-mocha.json`](themes/catppuccin-mocha.json) | Catppuccin Mocha Flavor (Dark Theme) |
| Theme Lion | [`themes/theme_lion.json`](themes/theme_lion.json) | Semantic CLion inspired theme (Dark Theme) |
| Retina Dark | [`themes/retina_dark.json`](themes/retina_dark.json) | Semantic theme based on Dark Theme |
### Disassemblers
| Name | Path | Description |
|------|------|-------------|
| 8051 | [`disassemblers/8051.json`](disassemblers/8051.json) | Intel 8051 Architecture |

View File

@@ -29,23 +29,10 @@
"title": "Items",
"type": "object",
"required": [
"type",
"value",
"name"
],
"properties": {
"type": {
"$id": "#root/values/items/type",
"title": "Type",
"type": "string",
"default": "",
"examples": [
"int16be",
"int16le",
"int10"
],
"pattern": "^(int10|int16le|int16be)$"
},
"value": {
"$id": "#root/values/items/value",
"title": "Value",
@@ -54,7 +41,7 @@
"examples": [
"ACDC"
],
"pattern": "^([0-9a-fA-F]+)$"
"pattern": "^.*$"
},
"name": {
"$id": "#root/values/items/name",

View File

@@ -2,118 +2,95 @@
"name": "CRC16 Constants",
"values": [
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/CCITT-FALSE Polynomial"
},
{
"type": "int16be",
"value": "8005",
"value": "80 05",
"name": "CRC-16/ARC Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/AUG-CCITT Polynomial"
},
{
"type": "int16be",
"value": "8005",
"value": "80 05",
"name": "CRC-16/BUYPASS Polynomial"
},
{
"type": "int16be",
"value": "C867",
"value": "C8 67",
"name": "CRC-16/CDMA2000 Polynomial"
},
{
"type": "int16be",
"value": "8005",
"value": "80 05",
"name": "CRC-16/DDS-110 Polynomial"
},
{
"type": "int16be",
"value": "0589",
"value": "05 89",
"name": "CRC-16/DECT-R Polynomial"
},
{
"type": "int16be",
"value": "0589",
"value": "05 89",
"name": "CRC-16/DECT-X Polynomial"
},
{
"type": "int16be",
"value": "3D65",
"value": "3D 65",
"name": "CRC-16/DNP Polynomial"
},
{
"type": "int16be",
"value": "3D65",
"value": "3D 65",
"name": "CRC-16/EN-13757 Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/GENIBUS Polynomial"
},
{
"type": "int16be",
"value": "8005",
"value": "80 05",
"name": "CRC-16/MAXIM Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/MCRF4XX Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/RIELLO Polynomial"
},
{
"type": "int16be",
"value": "8BB7",
"value": "8B B7",
"name": "CRC-16/T10-DIF Polynomial"
},
{
"type": "int16be",
"value": "A097",
"value": "A0 97",
"name": "CRC-16/TELEDISK Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/TMS37157 Polynomial"
},
{
"type": "int16be",
"value": "8005",
"value": "80 05",
"name": "CRC-16/USB Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-A Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/KERMIT Polynomial"
},
{
"type": "int16be",
"value": "8005",
"value": "80 05",
"name": "CRC-16/MODBUS Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/X-25 Polynomial"
},
{
"type": "int16be",
"value": "1021",
"value": "10 21",
"name": "CRC-16/XMODEM Polynomial"
}
]

View File

@@ -2,48 +2,39 @@
"name": "CRC32 Constants",
"values": [
{
"type": "int16be",
"value": "04C11DB7",
"value": "04 C1 1D B7",
"name": "CRC-32 Polynomial"
},
{
"type": "int16be",
"value": "04C11DB7",
"value": "04 C1 1D B7",
"name": "CRC-32/BZIP2 Polynomial"
},
{
"type": "int16be",
"value": "1EDC6F41",
"value": "1E DC 6F 41",
"name": "CRC-32C Polynomial"
},
{
"type": "int16be",
"value": "A833982B",
"value": "A8 33 98 2B",
"name": "CRC-32D Polynomial"
},
{
"type": "int16be",
"value": "04C11DB7",
"value": "04 C1 1D B7",
"name": "CRC-32/MPEG-2 Polynomial"
},
{
"type": "int16be",
"value": "04C11DB7",
"value": "04 C1 1D B7",
"name": "CRC-32/POSIX Polynomial"
},
{
"type": "int16be",
"value": "814141AB",
"value": "81 41 41 AB",
"name": "CRC-32Q Polynomial"
},
{
"type": "int16be",
"value": "04C11DB7",
"value": "04 C1 1D B7",
"name": "CRC-32/JAMCRC Polynomial"
},
{
"type": "int16be",
"value": "000000AF",
"value": "00 00 00 AF",
"name": "CRC-32/XFER Polynomial"
}
]

View File

@@ -1,315 +0,0 @@
{
"name": "HTTP Status Codes",
"values": [
{
"type": "int10",
"value": "100",
"name": "Continue"
},
{
"type": "int10",
"value": "101",
"name": "Switching Protocols"
},
{
"type": "int10",
"value": "102",
"name": "Processing (WebDAV; RFC 2518)"
},
{
"type": "int10",
"value": "103",
"name": "Early Hints (RFC 8297)"
},
{
"type": "int10",
"value": "200",
"name": "OK"
},
{
"type": "int10",
"value": "201",
"name": "Created"
},
{
"type": "int10",
"value": "202",
"name": "Accepted"
},
{
"type": "int10",
"value": "203",
"name": "Non-Authoritative Information (since HTTP/1.1)"
},
{
"type": "int10",
"value": "204",
"name": "No Content"
},
{
"type": "int10",
"value": "205",
"name": "Reset Content"
},
{
"type": "int10",
"value": "206",
"name": "Partial Content (RFC 7233)"
},
{
"type": "int10",
"value": "207",
"name": "Multi-Status (WebDAV; RFC 4918)"
},
{
"type": "int10",
"value": "208",
"name": "Already Reported (WebDAV; RFC 5842)"
},
{
"type": "int10",
"value": "226",
"name": "IM Used (RFC 3229)"
},
{
"type": "int10",
"value": "300",
"name": "Multiple Choices"
},
{
"type": "int10",
"value": "301",
"name": "Moved Permanently"
},
{
"type": "int10",
"value": "302",
"name": "Found (Previously \"Moved temporarily\")"
},
{
"type": "int10",
"value": "303",
"name": "See Other (since HTTP/1.1)"
},
{
"type": "int10",
"value": "304",
"name": "Not Modified (RFC 7232)"
},
{
"type": "int10",
"value": "305",
"name": "Use Proxy (since HTTP/1.1)"
},
{
"type": "int10",
"value": "306",
"name": "Switch Proxy"
},
{
"type": "int10",
"value": "307",
"name": "Temporary Redirect (since HTTP/1.1)"
},
{
"type": "int10",
"value": "308",
"name": "Permanent Redirect (RFC 7538)"
},
{
"type": "int10",
"value": "400",
"name": "Bad Request"
},
{
"type": "int10",
"value": "401",
"name": "Unauthorized (RFC 7235)"
},
{
"type": "int10",
"value": "402",
"name": "Payment Required"
},
{
"type": "int10",
"value": "403",
"name": "Forbidden"
},
{
"type": "int10",
"value": "404",
"name": "Not Found"
},
{
"type": "int10",
"value": "405",
"name": "Method Not Allowed"
},
{
"type": "int10",
"value": "406",
"name": "Not Acceptable"
},
{
"type": "int10",
"value": "407",
"name": "Proxy Authentication Required (RFC 7235)"
},
{
"type": "int10",
"value": "408",
"name": "Request Timeout"
},
{
"type": "int10",
"value": "409",
"name": "Conflict"
},
{
"type": "int10",
"value": "410",
"name": "Gone"
},
{
"type": "int10",
"value": "411",
"name": "Length Required"
},
{
"type": "int10",
"value": "412",
"name": "Precondition Failed (RFC 7232)"
},
{
"type": "int10",
"value": "413",
"name": "Payload Too Large (RFC 7231)"
},
{
"type": "int10",
"value": "414",
"name": "URI Too Long (RFC 7231)"
},
{
"type": "int10",
"value": "415",
"name": "Unsupported Media Type (RFC 7231)"
},
{
"type": "int10",
"value": "416",
"name": "Range Not Satisfiable (RFC 7233)"
},
{
"type": "int10",
"value": "417",
"name": "Expectation Failed"
},
{
"type": "int10",
"value": "418",
"name": "I'm a teapot (RFC 2324, RFC 7168)"
},
{
"type": "int10",
"value": "421",
"name": "Misdirected Request (RFC 7540)"
},
{
"type": "int10",
"value": "422",
"name": "Unprocessable Entity (WebDAV; RFC 4918)"
},
{
"type": "int10",
"value": "424",
"name": "Failed Dependency (WebDAV; RFC 4918)"
},
{
"type": "int10",
"value": "425",
"name": "Too Early (RFC 8470)"
},
{
"type": "int10",
"value": "426",
"name": "Upgrade Required"
},
{
"type": "int10",
"value": "428",
"name": "Precondition Required (RFC 6585)"
},
{
"type": "int10",
"value": "429",
"name": "Too Many Requests (RFC 6585)"
},
{
"type": "int10",
"value": "431",
"name": "Request Header Fields Too Large (RFC 6585)"
},
{
"type": "int10",
"value": "451",
"name": "Unavailable For Legal Reasons (RFC 7725)"
},
{
"type": "int10",
"value": "500",
"name": "Internal Server Error"
},
{
"type": "int10",
"value": "501",
"name": "Not Implemented"
},
{
"type": "int10",
"value": "502",
"name": "Bad Gateway"
},
{
"type": "int10",
"value": "503",
"name": "Service Unavailable"
},
{
"type": "int10",
"value": "504",
"name": "Gateway Timeout"
},
{
"type": "int10",
"value": "505",
"name": "HTTP Version Not Supported"
},
{
"type": "int10",
"value": "506",
"name": "Variant Also Negotiates (RFC 2295)"
},
{
"type": "int10",
"value": "507",
"name": "Insufficient Storage (WebDAV; RFC 4918)"
},
{
"type": "int10",
"value": "508",
"name": "Loop Detected (WebDAV; RFC 5842)"
},
{
"type": "int10",
"value": "510",
"name": "Not Extended (RFC 2774)"
},
{
"type": "int10",
"value": "511",
"name": "Network Authentication Required (RFC 6585)"
}
]
}

View File

@@ -1,780 +0,0 @@
{
"name": "Linux Error Codes",
"values": [
{
"type": "int10",
"value": "1",
"name": "EPERM",
"desc": "Operation not permitted"
},
{
"type": "int10",
"value": "2",
"name": "ENOENT",
"desc": "No such file or directory"
},
{
"type": "int10",
"value": "3",
"name": "ESRCH",
"desc": "No such process"
},
{
"type": "int10",
"value": "4",
"name": "EINTR",
"desc": "Interrupted system call"
},
{
"type": "int10",
"value": "5",
"name": "EIO",
"desc": "I/O error"
},
{
"type": "int10",
"value": "6",
"name": "ENXIO",
"desc": "No such device or address"
},
{
"type": "int10",
"value": "7",
"name": "E2BIG",
"desc": "Argument list too long"
},
{
"type": "int10",
"value": "8",
"name": "ENOEXEC",
"desc": "Exec format error"
},
{
"type": "int10",
"value": "9",
"name": "EBADF",
"desc": "Bad file value"
},
{
"type": "int10",
"value": "10",
"name": "ECHILD",
"desc": "No child processes"
},
{
"type": "int10",
"value": "11",
"name": "EAGAIN",
"desc": "Try again"
},
{
"type": "int10",
"value": "12",
"name": "ENOMEM",
"desc": "Out of memory"
},
{
"type": "int10",
"value": "13",
"name": "EACCES",
"desc": "Permission denied"
},
{
"type": "int10",
"value": "14",
"name": "EFAULT",
"desc": "Bad address"
},
{
"type": "int10",
"value": "15",
"name": "ENOTBLK",
"desc": "Block device required"
},
{
"type": "int10",
"value": "16",
"name": "EBUSY",
"desc": "Device or resource busy"
},
{
"type": "int10",
"value": "17",
"name": "EEXIST",
"desc": "File exists"
},
{
"type": "int10",
"value": "18",
"name": "EXDEV",
"desc": "Cross-device link"
},
{
"type": "int10",
"value": "19",
"name": "ENODEV",
"desc": "No such device"
},
{
"type": "int10",
"value": "20",
"name": "ENOTDIR",
"desc": "Not a directory"
},
{
"type": "int10",
"value": "21",
"name": "EISDIR",
"desc": "Is a directory"
},
{
"type": "int10",
"value": "22",
"name": "EINVAL",
"desc": "Invalid argument"
},
{
"type": "int10",
"value": "23",
"name": "ENFILE",
"desc": "File table overflow"
},
{
"type": "int10",
"value": "24",
"name": "EMFILE",
"desc": "Too many open files"
},
{
"type": "int10",
"value": "25",
"name": "ENOTTY",
"desc": "Not a typewriter"
},
{
"type": "int10",
"value": "26",
"name": "ETXTBSY",
"desc": "Text file busy"
},
{
"type": "int10",
"value": "27",
"name": "EFBIG",
"desc": "File too large"
},
{
"type": "int10",
"value": "28",
"name": "ENOSPC",
"desc": "No space left on device"
},
{
"type": "int10",
"value": "29",
"name": "ESPIPE",
"desc": "Illegal seek"
},
{
"type": "int10",
"value": "30",
"name": "EROFS",
"desc": "Read-only file system"
},
{
"type": "int10",
"value": "31",
"name": "EMLINK",
"desc": "Too many links"
},
{
"type": "int10",
"value": "32",
"name": "EPIPE",
"desc": "Broken pipe"
},
{
"type": "int10",
"value": "33",
"name": "EDOM",
"desc": "Math argument out of domain of func"
},
{
"type": "int10",
"value": "34",
"name": "ERANGE",
"desc": "Math result not representable"
},
{
"type": "int10",
"value": "35",
"name": "EDEADLK",
"desc": "Resource deadlock would occur"
},
{
"type": "int10",
"value": "36",
"name": "ENAMETOOLONG",
"desc": "File name too long"
},
{
"type": "int10",
"value": "37",
"name": "ENOLCK",
"desc": "No record locks available"
},
{
"type": "int10",
"value": "38",
"name": "ENOSYS",
"desc": "Function not implemented"
},
{
"type": "int10",
"value": "39",
"name": "ENOTEMPTY",
"desc": "Directory not empty"
},
{
"type": "int10",
"value": "40",
"name": "ELOOP",
"desc": "Too many symbolic links encountered"
},
{
"type": "int10",
"value": "42",
"name": "ENOMSG",
"desc": "No message of desired type"
},
{
"type": "int10",
"value": "43",
"name": "EIDRM",
"desc": "Identifier removed"
},
{
"type": "int10",
"value": "44",
"name": "ECHRNG",
"desc": "Channel value out of range"
},
{
"type": "int10",
"value": "45",
"name": "EL2NSYNC",
"desc": "Level 2 not synchronized"
},
{
"type": "int10",
"value": "46",
"name": "EL3HLT",
"desc": "Level 3 halted"
},
{
"type": "int10",
"value": "47",
"name": "EL3RST",
"desc": "Level 3 reset"
},
{
"type": "int10",
"value": "48",
"name": "ELNRNG",
"desc": "Link value out of range"
},
{
"type": "int10",
"value": "49",
"name": "EUNATCH",
"desc": "Protocol driver not attached"
},
{
"type": "int10",
"value": "50",
"name": "ENOCSI",
"desc": "No CSI structure available"
},
{
"type": "int10",
"value": "51",
"name": "EL2HLT",
"desc": "Level 2 halted"
},
{
"type": "int10",
"value": "52",
"name": "EBADE",
"desc": "Invalid exchange"
},
{
"type": "int10",
"value": "53",
"name": "EBADR",
"desc": "Invalid request descriptor"
},
{
"type": "int10",
"value": "54",
"name": "EXFULL",
"desc": "Exchange full"
},
{
"type": "int10",
"value": "55",
"name": "ENOANO",
"desc": "No anode"
},
{
"type": "int10",
"value": "56",
"name": "EBADRQC",
"desc": "Invalid request code"
},
{
"type": "int10",
"value": "57",
"name": "EBADSLT",
"desc": "Invalid slot"
},
{
"type": "int10",
"value": "59",
"name": "EBFONT",
"desc": "Bad font file format"
},
{
"type": "int10",
"value": "60",
"name": "ENOSTR",
"desc": "Device not a stream"
},
{
"type": "int10",
"value": "61",
"name": "ENODATA",
"desc": "No data available"
},
{
"type": "int10",
"value": "62",
"name": "ETIME",
"desc": "Timer expired"
},
{
"type": "int10",
"value": "63",
"name": "ENOSR",
"desc": "Out of streams resources"
},
{
"type": "int10",
"value": "64",
"name": "ENONET",
"desc": "Machine is not on the network"
},
{
"type": "int10",
"value": "65",
"name": "ENOPKG",
"desc": "Package not installed"
},
{
"type": "int10",
"value": "66",
"name": "EREMOTE",
"desc": "Object is remote"
},
{
"type": "int10",
"value": "67",
"name": "ENOLINK",
"desc": "Link has been severed"
},
{
"type": "int10",
"value": "68",
"name": "EADV",
"desc": "Advertise error"
},
{
"type": "int10",
"value": "69",
"name": "ESRMNT",
"desc": "Srmount error"
},
{
"type": "int10",
"value": "70",
"name": "ECOMM",
"desc": "Communication error on send"
},
{
"type": "int10",
"value": "71",
"name": "EPROTO",
"desc": "Protocol error"
},
{
"type": "int10",
"value": "72",
"name": "EMULTIHOP",
"desc": "Multihop attempted"
},
{
"type": "int10",
"value": "73",
"name": "EDOTDOT",
"desc": "RFS specific error"
},
{
"type": "int10",
"value": "74",
"name": "EBADMSG",
"desc": "Not a data message"
},
{
"type": "int10",
"value": "75",
"name": "EOVERFLOW",
"desc": "Value too large for defined data type"
},
{
"type": "int10",
"value": "76",
"name": "ENOTUNIQ",
"desc": "Name not unique on network"
},
{
"type": "int10",
"value": "77",
"name": "EBADFD",
"desc": "File descriptor in bad state"
},
{
"type": "int10",
"value": "78",
"name": "EREMCHG",
"desc": "Remote address changed"
},
{
"type": "int10",
"value": "79",
"name": "ELIBACC",
"desc": "Can not access a needed shared library"
},
{
"type": "int10",
"value": "80",
"name": "ELIBBAD",
"desc": "Accessing a corrupted shared library"
},
{
"type": "int10",
"value": "81",
"name": "ELIBSCN",
"desc": ".lib section in a.out corrupted"
},
{
"type": "int10",
"value": "82",
"name": "ELIBMAX",
"desc": "Attempting to link in too many shared libraries"
},
{
"type": "int10",
"value": "83",
"name": "ELIBEXEC",
"desc": "Cannot exec a shared library directly"
},
{
"type": "int10",
"value": "84",
"name": "EILSEQ",
"desc": "Illegal byte sequence"
},
{
"type": "int10",
"value": "85",
"name": "ERESTART",
"desc": "Interrupted system call should be restarted"
},
{
"type": "int10",
"value": "86",
"name": "ESTRPIPE",
"desc": "Streams pipe error"
},
{
"type": "int10",
"value": "87",
"name": "EUSERS",
"desc": "Too many users"
},
{
"type": "int10",
"value": "88",
"name": "ENOTSOCK",
"desc": "Socket operation on non-socket"
},
{
"type": "int10",
"value": "89",
"name": "EDESTADDRREQ",
"desc": "Destination address required"
},
{
"type": "int10",
"value": "90",
"name": "EMSGSIZE",
"desc": "Message too long"
},
{
"type": "int10",
"value": "91",
"name": "EPROTOTYPE",
"desc": "Protocol wrong type for socket"
},
{
"type": "int10",
"value": "92",
"name": "ENOPROTOOPT",
"desc": "Protocol not available"
},
{
"type": "int10",
"value": "93",
"name": "EPROTONOSUPPORT",
"desc": "Protocol not supported"
},
{
"type": "int10",
"value": "94",
"name": "ESOCKTNOSUPPORT",
"desc": "Socket type not supported"
},
{
"type": "int10",
"value": "95",
"name": "EOPNOTSUPP",
"desc": "Operation not supported on transport endpoint"
},
{
"type": "int10",
"value": "96",
"name": "EPFNOSUPPORT",
"desc": "Protocol family not supported"
},
{
"type": "int10",
"value": "97",
"name": "EAFNOSUPPORT",
"desc": "Address family not supported by protocol"
},
{
"type": "int10",
"value": "98",
"name": "EADDRINUSE",
"desc": "Address already in use"
},
{
"type": "int10",
"value": "99",
"name": "EADDRNOTAVAIL",
"desc": "Cannot assign requested address"
},
{
"type": "int10",
"value": "100",
"name": "ENETDOWN",
"desc": "Network is down"
},
{
"type": "int10",
"value": "101",
"name": "ENETUNREACH",
"desc": "Network is unreachable"
},
{
"type": "int10",
"value": "102",
"name": "ENETRESET",
"desc": "Network dropped connection because of reset"
},
{
"type": "int10",
"value": "103",
"name": "ECONNABORTED",
"desc": "Software caused connection abort"
},
{
"type": "int10",
"value": "104",
"name": "ECONNRESET",
"desc": "Connection reset by peer"
},
{
"type": "int10",
"value": "105",
"name": "ENOBUFS",
"desc": "No buffer space available"
},
{
"type": "int10",
"value": "106",
"name": "EISCONN",
"desc": "Transport endpoint is already connected"
},
{
"type": "int10",
"value": "107",
"name": "ENOTCONN",
"desc": "Transport endpoint is not connected"
},
{
"type": "int10",
"value": "108",
"name": "ESHUTDOWN",
"desc": "Cannot send after transport endpoint shutdown"
},
{
"type": "int10",
"value": "109",
"name": "ETOOMANYREFS",
"desc": "Too many references: cannot splice"
},
{
"type": "int10",
"value": "110",
"name": "ETIMEDOUT",
"desc": "Connection timed out"
},
{
"type": "int10",
"value": "111",
"name": "ECONNREFUSED",
"desc": "Connection refused"
},
{
"type": "int10",
"value": "112",
"name": "EHOSTDOWN",
"desc": "Host is down"
},
{
"type": "int10",
"value": "113",
"name": "EHOSTUNREACH",
"desc": "No route to host"
},
{
"type": "int10",
"value": "114",
"name": "EALREADY",
"desc": "Operation already in progress"
},
{
"type": "int10",
"value": "115",
"name": "EINPROGRESS",
"desc": "Operation now in progress"
},
{
"type": "int10",
"value": "116",
"name": "ESTALE",
"desc": "Stale NFS file handle"
},
{
"type": "int10",
"value": "117",
"name": "EUCLEAN",
"desc": "Structure needs cleaning"
},
{
"type": "int10",
"value": "118",
"name": "ENOTNAM",
"desc": "Not a XENIX named type file"
},
{
"type": "int10",
"value": "119",
"name": "ENAVAIL",
"desc": "No XENIX semaphores available"
},
{
"type": "int10",
"value": "120",
"name": "EISNAM",
"desc": "Is a named type file"
},
{
"type": "int10",
"value": "121",
"name": "EREMOTEIO",
"desc": "Remote I/O error"
},
{
"type": "int10",
"value": "122",
"name": "EDQUOT",
"desc": "Quota exceeded"
},
{
"type": "int10",
"value": "123",
"name": "ENOMEDIUM",
"desc": "No medium found"
},
{
"type": "int10",
"value": "124",
"name": "EMEDIUMTYPE",
"desc": "Wrong medium type"
},
{
"type": "int10",
"value": "125",
"name": "ECANCELED",
"desc": "Operation Canceled"
},
{
"type": "int10",
"value": "126",
"name": "ENOKEY",
"desc": "Required key not available"
},
{
"type": "int10",
"value": "127",
"name": "EKEYEXPIRED",
"desc": "Key has expired"
},
{
"type": "int10",
"value": "128",
"name": "EKEYREVOKED",
"desc": "Key has been revoked"
},
{
"type": "int10",
"value": "129",
"name": "EKEYREJECTED",
"desc": "Key was rejected by service"
},
{
"type": "int10",
"value": "130",
"name": "EOWNERDEAD",
"desc": "Owner died"
},
{
"type": "int10",
"value": "131",
"name": "ENOTRECOVERABLE",
"desc": "State not recoverable"
}
]
}

730
disassemblers/8051.json Normal file
View File

@@ -0,0 +1,730 @@
{
"name": "Intel 8051",
"includes": [],
"options": [],
"opcodes": [
{
"mask": "0000'0000",
"mnemonic": "NOP",
"format": ""
},
{
"mask": "0000'0010 AAAA'AAAA AAAA'AAAA",
"mnemonic": "LJMP",
"format": "#0x{A:04X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "A"
}
}
]
},
{
"mask": "1000'0000 AAAA'AAAA",
"mnemonic": "SJMP",
"format": "#0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "A"
}
}
]
},
{
"mask": "0111'0011",
"mnemonic": "JMP",
"format": "@A+DPTR"
},
{
"mask": "0100'0000 AAAA'AAAA",
"mnemonic": "JC",
"format": "PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 2 + A"
}
}
]
},
{
"mask": "0011'0000 BBBB'BBBB AAAA'AAAA",
"mnemonic": "JNB",
"format": "BIT[0x{B:02X}], PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "0001'0000 BBBB'BBBB AAAA'AAAA",
"mnemonic": "JBC",
"format": "BIT[0x{B:02X}], PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "0010'0000 AAAA'AAAA RRRR'RRRR",
"mnemonic": "JB",
"format": "BIT[0x{A:02X}], PC + 0x{R:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "0001'0010 AAAA'AAAA AAAA'AAAA",
"mnemonic": "LCALL",
"format": "#0x{A:04X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "A"
}
}
]
},
{
"mask": "PPP1'0001 AAAA'AAAA",
"mnemonic": "ACALL",
"format": "page{P} #0x{A:04X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "P * 256 + A"
}
}
]
},
{
"mask": "PPP0'0001 AAAA'AAAA",
"mnemonic": "AJMP",
"format": "page{P} #0x{A:04X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "P * 256 + A"
}
}
]
},
{
"mask": "0000'0011",
"mnemonic": "RR",
"format": "A"
},
{
"mask": "0001'0011",
"mnemonic": "RRC",
"format": "A"
},
{
"mask": "0010'0011",
"mnemonic": "RL",
"format": "A"
},
{
"mask": "0011'0011",
"mnemonic": "RLC",
"format": "A"
},
{
"mask": "0000'0100",
"mnemonic": "INC",
"format": "A"
},
{
"mask": "0000'0101 AAAA'AAAA",
"mnemonic": "INC",
"format": "IRAM[0x{A:02X}]"
},
{
"mask": "0000'011R",
"mnemonic": "INC",
"format": "@R{R}"
},
{
"mask": "0000'1RRR",
"mnemonic": "INC",
"format": "R{R}"
},
{
"mask": "1010'0011",
"mnemonic": "INC",
"format": "DPTR"
},
{
"mask": "0001'0100",
"mnemonic": "DEC",
"format": "A"
},
{
"mask": "0001'0101 AAAA'AAAA",
"mnemonic": "DEC",
"format": "IRAM[0x{A:02X}]"
},
{
"mask": "0001'0110",
"mnemonic": "DEC",
"format": "@R0"
},
{
"mask": "0001'0111",
"mnemonic": "DEC",
"format": "@R1"
},
{
"mask": "0001'1RRR",
"mnemonic": "DEC",
"format": "R{R}"
},
{
"mask": "1110'0100",
"mnemonic": "CLR",
"format": "A"
},
{
"mask": "1100'0010 AAAA'AAAA",
"mnemonic": "CLR",
"format": "BIT[0x{A:02X}]"
},
{
"mask": "1100'0011",
"mnemonic": "CLR",
"format": "C"
},
{
"mask": "1111'0000",
"mnemonic": "MOVX",
"format": "@DPTR, A"
},
{
"mask": "1110'0000",
"mnemonic": "MOVX",
"format": "A, @DPTR"
},
{
"mask": "1111'001R",
"mnemonic": "MOVX",
"format": "@R{R}, A"
},
{
"mask": "1110'001R",
"mnemonic": "MOVX",
"format": "A, @R{R}"
},
{
"mask": "0111'011R AAAA'AAAA",
"mnemonic": "MOV",
"format": "@R{R}, #0x{A:02X}"
},
{
"mask": "0111'1RRR AAAA'AAAA",
"mnemonic": "MOV",
"format": "R{R}, #0x{A:02X}"
},
{
"mask": "1111'1RRR",
"mnemonic": "MOV",
"format": "R{R}, A"
},
{
"mask": "1110'011R",
"mnemonic": "MOV",
"format": "A, @R{R}"
},
{
"mask": "1111'011R",
"mnemonic": "MOV",
"format": "@R{R}, A"
},
{
"mask": "1110'1RRR",
"mnemonic": "MOV",
"format": "A, R{R}"
},
{
"mask": "1001'0010 AAAA'AAAA",
"mnemonic": "MOV",
"format": "BIT[0x{A:02X}], C"
},
{
"mask": "1010'0010 AAAA'AAAA",
"mnemonic": "MOV",
"format": "C, BIT[0x{A:02X}]"
},
{
"mask": "1001'0000 DDDD'DDDD DDDD'DDDD",
"mnemonic": "MOV",
"format": "DPTR, #0x{D:04X}"
},
{
"mask": "1110'0101 AAAA'AAAA",
"mnemonic": "MOV",
"format": "A, IRAM[0x{A:02X}]"
},
{
"mask": "1111'0101 AAAA'AAAA",
"mnemonic": "MOV",
"format": "IRAM[#0x{A:02X}], A"
},
{
"mask": "0111'0101 AAAA'AAAA DDDD'DDDD",
"mnemonic": "MOV",
"format": "IRAM[0x{A:02X}], #0x{D:02X}"
},
{
"mask": "1000'0101 AAAA'AAAA BBBB'BBBB",
"mnemonic": "MOV",
"format": "IRAM[0x{A:02X}], IRAM[0x{B:02X}]"
},
{
"mask": "0111'0100 DDDD'DDDD",
"mnemonic": "MOV",
"format": "A, #0x{D:02X}"
},
{
"mask": "1000'011R AAAA'AAAA",
"mnemonic": "MOV",
"format": "IRAM[0x{A:02X}], @R{R}"
},
{
"mask": "1000'1RRR AAAA'AAAA",
"mnemonic": "MOV",
"format": "IRAM[0x{A:02X}], R{R}"
},
{
"mask": "1010'011R AAAA'AAAA",
"mnemonic": "MOV",
"format": "@R{R}, IRAM[0x{A:02X}]"
},
{
"mask": "1010'1RRR AAAA'AAAA",
"mnemonic": "MOV",
"format": "R{R}, IRAM[0x{A:02X}]"
},
{
"mask": "0110'0000 AAAA'AAAA",
"mnemonic": "JZ",
"format": "PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 2 + A"
}
}
]
},
{
"mask": "0111'0000 AAAA'AAAA",
"mnemonic": "JNZ",
"format": "PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 2 + A"
}
}
]
},
{
"mask": "1001'0011",
"mnemonic": "MOVC",
"format": "A, @A+DPTR"
},
{
"mask": "1000'0011",
"mnemonic": "MOVC",
"format": "A, @A+PC"
},
{
"mask": "1101'011R",
"mnemonic": "XCHD",
"format": "A, @R{R}"
},
{
"mask": "1100'011R",
"mnemonic": "XCH",
"format": "A, @R{R}"
},
{
"mask": "1100'1RRR",
"mnemonic": "XCH",
"format": "A, R{R}"
},
{
"mask": "1100'0101 AAAA'AAAA",
"mnemonic": "XCH",
"format": "A, IRAM[0x{A:02X}]"
},
{
"mask": "0010'0010",
"mnemonic": "RET",
"format": ""
},
{
"mask": "0011'0010",
"mnemonic": "RETI",
"format": ""
},
{
"mask": "1101'0010 AAAA'AAAA",
"mnemonic": "SETB",
"format": "BIT[0x{A:02X}]"
},
{
"mask": "1101'0011",
"mnemonic": "SETB",
"format": "C"
},
{
"mask": "0101'0010 AAAA'AAAA",
"mnemonic": "ANL",
"format": "IRAM[0x{A:02X}], A"
},
{
"mask": "0101'0101 AAAA'AAAA",
"mnemonic": "ANL",
"format": "A, IRAM[0x{A:02X}]"
},
{
"mask": "0101'0011 AAAA'AAAA DDDD'DDDD",
"mnemonic": "ANL",
"format": "A, IRAM[0x{A:02X}], #0x{D:02X}"
},
{
"mask": "0101'0100 AAAA'AAAA",
"mnemonic": "ANL",
"format": "A, #0x{A:02X}"
},
{
"mask": "0101'011R",
"mnemonic": "ANL",
"format": "A, @R{R}"
},
{
"mask": "0101'1RRR",
"mnemonic": "ANL",
"format": "A, R{R}"
},
{
"mask": "1000'0010 AAAA'AAAA",
"mnemonic": "ANL",
"format": "C, BIT[0x{A:02X}]"
},
{
"mask": "1011'0000 AAAA'AAAA",
"mnemonic": "ANL",
"format": "C, /BIT[0x{A:02X}]"
},
{
"mask": "0100'0010 AAAA'AAAA",
"mnemonic": "ORL",
"format": "IRAM[0x{A:02X}], A"
},
{
"mask": "0100'0011 AAAA'AAAA DDDD'DDDD",
"mnemonic": "ORL",
"format": "IRAM[0x{A:02X}], #0x{D:02X}"
},
{
"mask": "0100'0100 DDDD'DDDD",
"mnemonic": "ORL",
"format": "A, #0x{D:02X}"
},
{
"mask": "0100'011R",
"mnemonic": "ORL",
"format": "A, @R{R}"
},
{
"mask": "0100'1RRR",
"mnemonic": "ORL",
"format": "A, R{R}"
},
{
"mask": "0100'0101 AAAA'AAAA",
"mnemonic": "ORL",
"format": "A, IRAM[0x{A:02X}]"
},
{
"mask": "0111'0010 AAAA'AAAA",
"mnemonic": "ORL",
"format": "C, BIT[0x{A:02X}]"
},
{
"mask": "1010'0000 AAAA'AAAA",
"mnemonic": "ORL",
"format": "C, /BIT[0x{A:02X}]"
},
{
"mask": "0110'0010 AAAA'AAAA",
"mnemonic": "XRL",
"format": "IRAM[0x{A:02X}], A"
},
{
"mask": "0110'0011 AAAA'AAAA DDDD'DDDD",
"mnemonic": "XRL",
"format": "IRAM[0x{A:02X}], #0x{D:02X}"
},
{
"mask": "0110'0100 DDDD'DDDD",
"mnemonic": "XRL",
"format": "A, #0x{D:02X}"
},
{
"mask": "0110'011R",
"mnemonic": "XRL",
"format": "A, @R{R}"
},
{
"mask": "0110'1RRR",
"mnemonic": "XRL",
"format": "A, R{R}"
},
{
"mask": "0110'0101 AAAA'AAAA",
"mnemonic": "XRL",
"format": "A, IRAM[0x{A:02X}]"
},
{
"mask": "0010'0100 DDDD'DDDD",
"mnemonic": "ADD",
"format": "A, #0x{D:02X}"
},
{
"mask": "0010'011R",
"mnemonic": "ADD",
"format": "A, @R{R}"
},
{
"mask": "0010'0101 AAAA'AAAA",
"mnemonic": "ADD",
"format": "A, IRAM[0x{A:02X}]"
},
{
"mask": "0011'0100 DDDD'DDDD",
"mnemonic": "ADDC",
"format": "A, #0x{D:02X}"
},
{
"mask": "0011'011R",
"mnemonic": "ADDC",
"format": "A, @R{R}"
},
{
"mask": "0011'0101 AAAA'AAAA",
"mnemonic": "ADDC",
"format": "A, IRAM[0x{A:02X}]"
},
{
"mask": "0011'1RRR",
"mnemonic": "ADDC",
"format": "A, R{R}"
},
{
"mask": "1001'0100 DDDD'DDDD",
"mnemonic": "SUBB",
"format": "A, #0x{D:02X}"
},
{
"mask": "1001'0101 IIII'IIII",
"mnemonic": "SUBB",
"format": "A, IRAM[0x{I:02X}]"
},
{
"mask": "1001'011R",
"mnemonic": "SUBB",
"format": "A, @R{R}"
},
{
"mask": "1001'1RRR",
"mnemonic": "SUBB",
"format": "A, R{R}"
},
{
"mask": "1010'0100",
"mnemonic": "MUL",
"format": "AB"
},
{
"mask": "1000'0100",
"mnemonic": "DIV",
"format": "AB"
},
{
"mask": "0010'1RRR",
"mnemonic": "ORL",
"format": "A, R{R}"
},
{
"mask": "1011'0101 IIII'IIII AAAA'AAAA",
"mnemonic": "CJNE",
"format": "A, IRAM[0x{I:02X}], PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "1011'0100 DDDD'DDDD AAAA'AAAA",
"mnemonic": "CJNE",
"format": "A, #0x{D:02X}, PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "1011'011R DDDD'DDDD AAAA'AAAA",
"mnemonic": "CJNE",
"format": "@R{R}, #0x{D:02X}, PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "1011'1RRR DDDD'DDDD AAAA'AAAA",
"mnemonic": "CJNE",
"format": "R{R}, #0x{D:02X}, PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "1101'0101 IIII'IIII AAAA'AAAA",
"mnemonic": "DJNZ",
"format": "IRAM[0x{I:02X}], PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 3 + A"
}
}
]
},
{
"mask": "1101'1RRR AAAA'AAAA",
"mnemonic": "DJNZ",
"format": "R{R}, PC + 0x{R:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 2 + A"
}
}
]
},
{
"mask": "0101'0000 AAAA'AAAA",
"mnemonic": "JNC",
"format": "PC + 0x{A:02X}",
"metadata": [
{
"type": "jump",
"data": {
"destination": "offset + 2 + A"
}
}
]
},
{
"mask": "1101'0000 AAAA'AAAA",
"mnemonic": "POP",
"format": "IRAM[0x{A:02X}]"
},
{
"mask": "1100'0000 AAAA'AAAA",
"mnemonic": "PUSH",
"format": "IRAM[0x{A:02X}]"
},
{
"mask": "1101'0100",
"mnemonic": "DA",
"format": ""
},
{
"mask": "1100'0100",
"mnemonic": "SWAP",
"format": "A"
},
{
"mask": "1111'0100",
"mnemonic": "CPL",
"format": "A"
},
{
"mask": "1011'0011",
"mnemonic": "CPL",
"format": "C"
},
{
"mask": "1011'0010 BBBB'BBBB",
"mnemonic": "CPL",
"format": "BIT[0x{B:02X}]"
},
{
"mask": "1010'0101",
"mnemonic": "INVALID",
"format": ""
},
{
"mask": "XXXX'XXXX",
"mnemonic": "DB",
"format": "#0x{X:02X}",
"metadata": [
{
"type": "data",
"data": {
"value": "X"
}
}
]
}
]
}

1045
disassemblers/jvm.json Normal file

File diff suppressed because it is too large Load Diff

18594
encodings/big5.tbl Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

21887
encodings/gbk.tbl Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -1,12 +1,12 @@
#pragma once
#include <hex/impl/imhex_check.pat>
import hex.impl.imhex_check;
/*!
Core intrinsic functions to interact with the ImHex Hex Editor
*/
namespace hex::core {
namespace auto hex::core {
/**
A type representing a selection in the hex editor
@@ -21,20 +21,30 @@ namespace hex::core {
@return The current selection
*/
fn get_selection() {
u128 result = builtin::hex::core::get_selection();
u128 selection = builtin::hex::core::get_selection();
Selection result;
if (result == u128(-1)) {
if (selection == u128(-1)) {
result.valid = false;
result.address = 0x00;
result.size = 0x00;
} else {
result.valid = true;
result.address = result >> 64;
result.size = result & u64(-1);
result.address = selection >> 64;
result.size = selection & u64(-1);
}
return result;
};
}
/**
Add a file to the Virtual Filesystem
@param path The name of the file
@param pattern The pattern associated with the file
*/
fn add_virtual_file(str path, auto pattern)
{
builtin::hex::core::add_virtual_file(path, pattern);
};
}

View File

@@ -1,12 +1,14 @@
#pragma once
#include <hex/impl/imhex_check.pat>
import hex.impl.imhex_check;
import std.mem;
/*!
Library to allow decoding of more complex values
*/
namespace hex::dec {
namespace auto hex::dec {
/**
Demangles a mangled name into a human readable name
@@ -17,4 +19,57 @@ namespace hex::dec {
return builtin::hex::dec::demangle(mangled_name);
};
/**
Decompresses the bytes of a pattern into a section using the zlib algorithm
@param pattern The pattern whose bytes should be decompressed
@param section The section to decompress the data into
@param window_size The window size passed to zlib
@return A value representing either the number of bytes decompressed or an error code from zlib
*/
fn zlib_decompress(ref auto pattern, std::mem::Section section, u64 window_size = 0) {
return builtin::hex::dec::zlib_decompress(pattern, section, window_size);
};
/**
Decompresses the bytes of a pattern into a section using the bzip algorithm
@param pattern The pattern whose bytes should be decompressed
@param section The section to decompress the data into
@return true if successful, false otherwise
*/
fn bzip_decompress(ref auto pattern, std::mem::Section section) {
return builtin::hex::dec::bzip_decompress(pattern, section);
};
/**
Decompresses the bytes of a pattern into a section using the LZMA algorithm
@param pattern The pattern whose bytes should be decompressed
@param section The section to decompress the data into
@return true if successful, false otherwise
*/
fn lzma_decompress(ref auto pattern, std::mem::Section section) {
return builtin::hex::dec::lzma_decompress(pattern, section);
};
/**
Decompresses the bytes of a pattern into a section using the zstd algorithm
@param pattern The pattern whose bytes should be decompressed
@param section The section to decompress the data into
@return true if successful, false otherwise
*/
fn zstd_decompress(ref auto pattern, std::mem::Section section) {
return builtin::hex::dec::zstd_decompress(pattern, section);
};
/**
Decompresses the bytes of a pattern into a section using the lz4 algorithm
@param pattern The pattern whose bytes should be decompressed
@param section The section to decompress the data into
@param frame Whether the data is framed or not
@return true if successful, false otherwise
*/
fn lz4_decompress(ref auto pattern, std::mem::Section section, bool frame = true) {
return builtin::hex::dec::lz4_decompress(pattern, section, frame);
};
}

View File

@@ -1,12 +1,12 @@
#pragma once
#include <hex/impl/imhex_check.pat>
import hex.impl.imhex_check;
/*!
Library to do HTTP requests
*/
namespace hex::http {
namespace auto hex::http {
/**
Performs a HTTP GET request to the given URL and returns the response body

View File

@@ -1,17 +1,17 @@
#pragma once
#include <hex/impl/imhex_check.pat>
import hex.impl.imhex_check;
/*!
Library to interact with the currently loaded provider.
*/
namespace hex::prv {
namespace auto 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`
@@ -32,12 +32,12 @@ namespace hex::prv {
> - `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

@@ -0,0 +1,28 @@
#pragma once
import hex.impl.imhex_check;
/*!
Types to work with custom encoded strings using Thiny encoding definitions
*/
namespace auto hex::type {
/**
A string that was encoded using a custom encoding
@tparam Data Pattern whose bytes are used in the decoding process
@tparam EncodingDefinition A string containing a Thingy encoding definition as used by ImHex's custom encoding feature
*/
struct EncodedString<auto Data, auto EncodingDefinition> {
builtin::hex::dec::EncodedString<Data, EncodingDefinition> string;
} [[sealed, format("hex::type::impl::format_encoded_string")]];
namespace impl {
fn format_encoded_string(ref auto string) {
return string.string;
};
}
}

View File

@@ -0,0 +1,143 @@
#pragma once
import hex.impl.imhex_check;
/*!
Types to work with machine code
*/
namespace auto hex::type {
/**
A machine code instruction which will get disassembled
@tparam DisassemblerSetting A string containing the config for the disassembler in the form of "architecture; setting1, setting2, no-setting3"
@tparam SyntaxType Syntax used in the disassembly. Possible values are "intel", "at&t", "masm" and "motorola"
@tparam ImageBaseAddress Start address of the instruction region in the data
@tparam ImageLoadAddress Address where the instructions will be loaded into memory
Possible Values for DisassemblerSetting:
- Architecture, all may be suffixed with le or be to specify endianess (e.g armbe or mipsle)
- arm
- thumb
- aarch64
- arm64
- mips
- x86
- x86_64
- x64
- ppc
- powerpc
- sparc
- sysz
- xcore
- m68k
- m680x
- tms320c64x
- evm
- wasm
- riscv
- mos65xx
- bpf
- sh
- tricore
- Settings, not all settings make sense for each architecture. Prefixing settings with no- will remove them instead
- 16bit
- 32bit
- 64bit
- cortex-m
- armv8
- micromips
- mips2
- mips3
- mips32r6
- sparcv9
- qpx
- spe
- ps
- 68000
- 68010
- 68020
- 68030
- 68040
- 68060
- 6301
- 6309
- 6800
- 6801
- 6805
- 6808
- 6809
- 6811
- cpu12
- hcs08
- bpfe
- rv32g
- rv64g
- riscvc
- 6502
- 65c02
- w65c02
- 65816
- long-m
- long-x
- sh2
- sh2a
- sh3
- sh4
- sh4a
- shfpu
- shdsp
- 1.1
- 1.2
- 1.3
- 1.3.1
- 1.6
- 1.6.1
- 1.6.2
*/
struct Instruction<auto DisassemblerSetting, auto SyntaxType, auto ImageBaseAddress, auto ImageLoadAddress> {
builtin::hex::dec::Instruction<DisassemblerSetting, SyntaxType, ImageBaseAddress, ImageLoadAddress> instruction;
} [[sealed, format("hex::type::impl::format_instruction")]];
/**
A machine code instruction which will get disassembled using Intel syntax
@tparam DisassemblerSetting A string containing the config for the disassembler in the form of "architecture; setting1, setting2, no-setting3"
@tparam ImageBaseAddress Start address of the instruction region in the data
@tparam ImageLoadAddress Address where the instructions will be loaded into memory
*/
using InstructionIntel<auto DisassemblerSetting, auto ImageBaseAddress, auto ImageLoadAddress> = Instruction<DisassemblerSetting, "intel", ImageBaseAddress, ImageLoadAddress>;
/**
A machine code instruction which will get disassembled using AT&T syntax
@tparam DisassemblerSetting A string containing the config for the disassembler in the form of "architecture; setting1, setting2, no-setting3"
@tparam ImageBaseAddress Start address of the instruction region in the data
@tparam ImageLoadAddress Address where the instructions will be loaded into memory
*/
using InstructionATNT<auto DisassemblerSetting, auto ImageBaseAddress, auto ImageLoadAddress> = Instruction<DisassemblerSetting, "at&t", ImageBaseAddress, ImageLoadAddress>;
/**
A machine code instruction which will get disassembled using MASM syntax
@tparam DisassemblerSetting A string containing the config for the disassembler in the form of "architecture; setting1, setting2, no-setting3"
@tparam ImageBaseAddress Start address of the instruction region in the data
@tparam ImageLoadAddress Address where the instructions will be loaded into memory
*/
using InstructionMASM<auto DisassemblerSetting, auto ImageBaseAddress, auto ImageLoadAddress> = Instruction<DisassemblerSetting, "masm", ImageBaseAddress, ImageLoadAddress>;
/**
A machine code instruction which will get disassembled using Motorola syntax
@tparam DisassemblerSetting A string containing the config for the disassembler in the form of "architecture; setting1, setting2, no-setting3"
@tparam ImageBaseAddress Start address of the instruction region in the data
@tparam ImageLoadAddress Address where the instructions will be loaded into memory
*/
using InstructionMotorola<auto DisassemblerSetting, auto ImageBaseAddress, auto ImageLoadAddress> = Instruction<DisassemblerSetting, "motorola", ImageBaseAddress, ImageLoadAddress>;
namespace impl {
fn format_instruction(ref auto instruction) {
return instruction.instruction;
};
}
}

View File

@@ -0,0 +1,66 @@
#pragma once
import hex.impl.imhex_check;
/*!
Types to decode JSON and JSON-like file formats into a pattern tree
*/
namespace auto hex::type {
/**
Type representing a JSON string
@tparam Size size of the string
*/
struct Json<auto Size> {
char __data[Size] [[hidden, no_unique_address]];
builtin::hex::dec::Json<__data> json [[merge]];
};
/**
Type representing Bson data
@tparam Size size of the data
*/
struct Bson<auto Size> {
u8 __data[Size] [[hidden, no_unique_address]];
builtin::hex::dec::Bson<__data> bson [[merge]];
};
/**
Type representing Cbor data
@tparam Size size of the data
*/
struct Cbor<auto Size> {
u8 __data[Size] [[hidden, no_unique_address]];
builtin::hex::dec::Cbor<__data> cbor [[merge]];
};
/**
Type representing Bjdata data
@tparam Size size of the data
*/
struct Bjdata<auto Size> {
u8 __data[Size] [[hidden, no_unique_address]];
builtin::hex::dec::Bjdata<__data> bjdata [[merge]];
};
/**
Type representing Msgpack data
@tparam Size size of the data
*/
struct Msgpack<auto Size> {
u8 __data[Size] [[hidden, no_unique_address]];
builtin::hex::dec::Msgpack<__data> msgpack [[merge]];
};
/**
Type representing Ubjson data
@tparam Size size of the data
*/
struct Ubjson<auto Size> {
u8 __data[Size] [[hidden, no_unique_address]];
builtin::hex::dec::Ubjson<__data> ubjson [[merge]];
};
}

View File

@@ -1,30 +1,30 @@
#pragma once
#include <std/io.pat>
#include <std/mem.pat>
import std.io;
import std.mem;
#include <hex/impl/imhex_check.pat>
#include <hex/dec.pat>
import hex.impl.imhex_check;
import hex.dec;
/*!
Types to automatically decode mangled names
*/
namespace hex::type {
namespace auto hex::type {
/**
A mangled name string that gets demangled when displayed
*/
struct MangledName {
char value[];
} [[sealed, format("hex::type::impl::format_mangled_name")]];
namespace impl {
fn format_mangled_name(ref MangledName name) {
return hex::dec::demangle(name.value);
};
}
}

View File

@@ -1,19 +1,68 @@
#pragma once
import std.sys;
import std.core;
/*!
The array library contains various helper functions and types to make
it easier to work with Arrays.
The array library contains a helper type to make it easier to create multi-dimensional arrays
and pass arrays to functions as parameters.
## Multi-dimensional arrays
The following example shows how to use multi-dimensional arrays with structs.
```rust
import std.array;
struct File {
u8 width, height;
std::Array<std::Array<u8, parent.width>, height> cells;
};
File file @ 0x00;
```
*/
namespace std {
namespace auto std {
/**
Simple one dimensional array wrapper
@tparam T The array types
@tparam Size Size of the array
@tparam Size Number of entries in the array
*/
struct Array<T, auto Size> {
T data[Size] [[inline]];
} [[format("std::impl::format_array")]];
/**
Simple array wrapper for an array with a size in bytes
@tparam T The array types
@tparam NumBytes Number of bytes the array contains
*/
struct ByteSizedArray<T, auto NumBytes> {
u64 startAddress = $;
T array[while($ - startAddress < NumBytes)] [[inline]];
std::assert($ - startAddress == NumBytes, "Not enough bytes available to fit a whole number of types");
} [[format("std::impl::format_array")]];
/**
An interface type for getting the index of the currently processed element in an array. This is a nice wrapper around `std::core::array_index()`
To use it, inherit from it and use the `this.index` field to get the index of the current element
*/
struct IIndexed {
const u64 index = std::core::array_index();
};
}
namespace impl {
fn format_array(ref auto array) {
return "[ ... ]";
};
}
}

72
includes/std/attrs.pat Normal file
View File

@@ -0,0 +1,72 @@
#pragma once
import std.io;
import std.core;
/*!
The attributes library contains a set of attributes that can be used to annotate types with certain properties.
To use an attribute, simply make your custom type inherit from the attribute type you want to use.
For example, to make a type hidden, you can use the `Hidden` attribute like this:
```rust
struct MyType : std::attr::Hidden {
// ...
};
```
*/
namespace auto std::attr {
/**
Attribute that marks a type as a literal type.
This means the type behaves like a built-in type in the sense that it doesn't show its internal state and its display value is determined by a format function.
It can also be transformed into a different built-in literal when used in an expression.
@tparam FormatFunction The format function to use. The return value of this function is used to display the value of the literal and also determines the value returned when the literal is used in an expression.
*/
struct Literal<auto FormatFunction> { }
[[sealed, format_read(FormatFunction), transform(FormatFunction)]];
/**
Attribute that changes the name of the variable created from a type.
@tparam Name The name of the variable created
*/
struct Named<auto Name> { }
[[name(Name)]];
/**
Attribute that adds a comment to the variable created from a type.
@tparam Comment The comment to add
*/
struct Commented<auto Comment> {}
[[comment(Comment)]];
/**
Attribute that marks a type as hidden.
This means variables of this type are not displayed in the UI.
*/
struct Hidden {}
[[hidden]];
/**
Attribute that marks a type as hidden and also hides it from the highlighter.
This means variables of this type are don't display any highlighting in the UI but are still visible.
*/
struct HighlightHidden {}
[[highlight_hidden]];
/**
Attribute that marks a type as inline.
Creating a variable of this type will not create a new layer but instead dump the contents of the type directly into the current layer.
*/
struct Inlined {}
[[inline]];
/**
Attribute that marks a type as sealed.
Sealed types don't display their internal state in the UI.
*/
struct Sealed {}
[[sealed]];
}

View File

@@ -1,63 +1,67 @@
#pragma once
#include <std/limits.pat>
import std.limits;
/*!
This library contains various helper functions for common bit operations.
This library contains various helper functions for common bit operations.
*/
namespace std::bit {
namespace auto 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));
x = (x & (std::limits::u128_max() / 17)) + ((x >> 4) & (std::limits::u128_max() / 17));
return x % 0xFF;
};
/**
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) {
const u128 a = 0x55555555555555555555555555555555;
const u128 b = 0x33333333333333333333333333333333;
const u128 c = 0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F;
/**
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;
u8 i;
while ((1 << i) < x)
i = i + 1;
return 1 << i;
};
x = (x & a) + ((x >> 1) & a);
x = (x & b) + ((x >> 2) & b);
x = (x & c) + ((x >> 4) & c);
/**
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;
u8 i;
while ((x >> i) > 0)
i = i + 1;
return 1 << (i - 1);
};
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;
u8 i;
while ((1 << i) < x)
i = i + 1;
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;
u8 i;
while ((x >> i) > 0)
i = i + 1;
return 1 << (i - 1);
};
}

View File

@@ -1,13 +1,13 @@
#pragma once
#include <std/mem.pat>
import std.mem;
/*!
The core library contains intrinsics and "compiler magic" functions that
get extra help from the runtime to fulfill their purpose.
*/
namespace std::core {
namespace auto std::core {
/**
The layout order of each field after byte-endianness has been handled.
@@ -38,27 +38,35 @@ namespace std::core {
};
/**
Returns the first parameter of the attribute of a pattern if it has one
Returns the nth 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
@param [index] The parameter index of the attribute to return. Defaults to 0
*/
fn get_attribute_argument(ref auto pattern, str attribute, u32 index = 0) {
return builtin::std::core::get_attribute_argument(pattern, attribute, index);
};
/**
@warning Removed in 1.27.0
*/
fn get_attribute_value(ref auto pattern, str attribute) {
return builtin::std::core::get_attribute_value(pattern, attribute);
builtin::std::error("`std::core::get_attribute_value(pattern, attribute)` has been removed.\nUse `std::core::get_attribute_argument(pattern, attribute, [index])` instead.");
};
/**
Sets the current default endianess.
Any patterns created following this attribute will be created using the set endianess.
@param endian The new default endianess
Sets the current default endianness.
Any patterns created following this attribute will be created using the set endianness.
@param endian The new default endianness
*/
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
Gets the current default endianness.
@return The currently set default endianness
*/
fn get_endian() {
return builtin::std::core::get_endian();
@@ -146,4 +154,39 @@ namespace std::core {
fn set_display_name(ref auto pattern, str name) {
builtin::std::core::set_display_name(pattern, name);
};
/**
Changes the comment attached to a pattern
@param pattern The pattern to modify
@param comment The new comment of the pattern
*/
fn set_pattern_comment(ref auto pattern, str comment) {
builtin::std::core::set_pattern_comment(pattern, comment);
};
/**
Executes the function with the given name, passing in all given arguments
@param function_name The namespace-prefixed name of the function
@param args Arguments to pass to the function
*/
fn execute_function(str function_name, auto ... args) {
builtin::std::core::execute_function(function_name, args);
};
/**
Sets the pattern color palette for all future created patterns
@param args RGBA8 colors as 32 bit integers (0xAABBGGRR)
*/
fn set_pattern_palette_colors(auto ... colors) {
builtin::std::core::set_pattern_palette_colors(colors);
};
/**
Resets the current pattern palette progress back to zero.
This can be useful to force all instances of a type to have the same coloring for its members
*/
fn reset_pattern_palette() {
builtin::std::core::reset_pattern_palette();
};
}

View File

@@ -5,7 +5,7 @@
of ASCII characters.
*/
namespace std::ctype {
namespace auto std::ctype {
/**
Checks if the given character `c` is a digit between '0' and '9'
@@ -85,7 +85,7 @@ namespace std::ctype {
@return True if `c` is part of this range, false otherwise
*/
fn isprint(char c) {
return c >= '0' && c <= '~';
return c >= ' ' && c <= '~';
};
/**

View File

@@ -1,112 +1,120 @@
#pragma once
/*!
The File library allows reading and writing from/to external files using
a C-like File IO API.
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**
**These functions are considered dangerous and require the user to manually permit them**
*/
namespace std::file {
namespace auto std::file {
/**
/**
A handle representing a file that has been opened
*/
using Handle = s32;
/**
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
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,
Create = 3
};
enum Mode : u8 {
Read = 1,
Write = 2,
Create = 3
};
/**
/**
Opens a file
@param path The path to the file to open
@param mode File open mode
@return Handle to the newly opened 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));
};
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
@param handle The handle to close
*/
fn close(Handle handle) {
builtin::std::file::close(handle);
};
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
@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 read(Handle handle, u64 size) {
return builtin::std::file::read(handle, size);
};
/**
/**
Writes the content of a string into a file
@param handle The file handle to write to
@param data String to write to the file
@param handle The file handle to write to
@param data String or Pattern to write to the file
*/
fn write(Handle handle, str data) {
builtin::std::file::write(handle, data);
};
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
@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);
};
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);
};
/**
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);
};
/**
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);
};
/**
Flushes changes made to a file to disk
@param handle The handle of the file to flush
*/
fn flush(Handle handle) {
builtin::std::file::flush(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);
};
/**
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);
};
/**
Create all directories for the provided path
@param path The path for which all directories should be created
*/
fn create_directories(str path) {
builtin::std::file::create_directories(path);
};
}

View File

@@ -1,89 +1,89 @@
#pragma once
/*!
Library for doing arithmetic with fixed point numbers and converting them from/to floating point numbers.
Library for doing arithmetic with fixed point numbers and converting them from/to floating point numbers.
*/
namespace std::fxpt {
namespace auto std::fxpt {
/**
A fixed point value
*/
using fixed = s128;
/**
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)));
};
/**
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));
};
/**
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;
};
/**
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 s128((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

@@ -4,20 +4,62 @@
The hash library contains various data hash functions
*/
namespace std::hash {
namespace auto std::hash {
/**
Calculates the CRC8 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the CRC8 hash of
@param init The CRC8 init value
@param poly The CRC8 polynomial
@param xorout The CRC8 XOR-Out value
@param reflect_in Whether or not the input bytes should be reflected
@param reflect_out Whether or not the output should be reflected
@return Calculated CRC8 hash
*/
fn crc8(ref auto pattern, u8 init, u8 poly, u8 xorout, bool reflect_in, bool reflect_out) {
return builtin::std::hash::crc8(pattern, init, poly, xorout, reflect_in, reflect_out);
};
/**
Calculates the CRC16 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the CRC16 hash of
@param init The CRC16 init value
@param poly The CRC16 polynomial
@param xorout The CRC16 XOR-Out value
@param reflect_in Whether or not the input bytes should be reflected
@param reflect_out Whether or not the output should be reflected
@return Calculated CRC16 hash
*/
fn crc16(ref auto pattern, u16 init, u16 poly, u16 xorout, bool reflect_in, bool reflect_out) {
return builtin::std::hash::crc16(pattern, init, poly, xorout, reflect_in, reflect_out);
};
/**
Calculates the CRC32 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the crc32 hash of
@param pattern The pattern to calculate the CRC32 hash of
@param init The CRC32 init value
@param poly The CRC32 polynomial
@param xorout The CRC32 XOR-Out value
@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
@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);
};
/**
Calculates the CRC64 hash of the bytes inside of a given pattern
@param pattern The pattern to calculate the CRC64 hash of
@param init The CRC64 init value
@param poly The CRC64 polynomial
@param xorout The CRC64 XOR-Out value
@param reflect_in Whether or not the input bytes should be reflected
@param reflect_out Whether or not the output should be reflected
@return Calculated CRC64 hash
*/
fn crc64(ref auto pattern, u64 init, u64 poly, u64 xorout, bool reflect_in, bool reflect_out) {
return builtin::std::hash::crc64(pattern, init, poly, xorout, reflect_in, reflect_out);
};
}

View File

@@ -4,26 +4,26 @@
The IO library allows formatting strings and outputting text to the console
*/
namespace std {
namespace auto 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 fmt Format string or any other value that can be converted to a string
@param args Values to use in the formatting
*/
fn print(str fmt, auto ... args) {
fn print(auto 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 fmt Format string or any other value that can be converted to a string
@param args Values to use in the formatting
@return The formatted string
*/
fn format(str fmt, auto ... args) {
fn format(auto fmt, auto ... args) {
return builtin::std::format(fmt, args);
};

View File

@@ -1,169 +1,169 @@
#pragma once
/*!
Library to calculate the minimum and maximum values that fit into a given data type
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);
};
namespace auto std::limits {
/**
Returns the minimum value that can be stored in a `s8`.
@return Minimum value
*/
/**
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((std::limits::u8_max() / 2));
};
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((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((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((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((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((std::limits::u128_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((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((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((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((std::limits::u128_max() / 2));
};
}

View File

@@ -1,333 +1,340 @@
#pragma once
#include <std/mem.pat>
import std.mem;
/*!
Library containing more advanced mathematical operations.
Library containing more advanced mathematical operations.
*/
namespace std::math {
namespace auto 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;
else
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;
else
return b;
};
/**
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;
else
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;
else if (x > max)
return max;
else
return x;
};
/**
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;
else
return b;
};
/**
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;
else
return x;
};
/**
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;
else if (x > max)
return max;
else
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;
else if (x < 0)
return -1;
else
return 0;
};
/**
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;
else
return x;
};
/**
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);
else
return -std::math::abs(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;
else if (x < 0)
return -1;
else
return 0;
};
/**
Calculates the factorial of `x`.
@param x Value
@return Factorial of `x`
*/
fn factorial(u128 x) {
u128 result;
result = x;
while (x > 1) {
x = x - 1;
result = result * x;
}
return result;
};
/**
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);
else
return -std::math::abs(x);
};
/**
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;
else
return std::math::factorial(n) / (std::math::factorial(k) * std::math::factorial(n - k));
};
/**
Calculates the factorial of `x`.
@param x Value
@return Factorial of `x`
*/
fn factorial(u128 x) {
u128 result;
/**
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;
else
return std::math::factorial(n) / std::math::factorial(n - k);
};
result = x;
while (x > 1) {
x = x - 1;
result = result * x;
}
/**
Floors the value of `value`.
@param value Value
@return `value` floored
*/
fn floor(auto value) { return builtin::std::math::floor(value); };
return result;
};
/**
Ceils the value of `value`.
@param value Value
@return `value` ceiled
*/
fn ceil(auto value) { return builtin::std::math::ceil(value); };
/**
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;
else
return std::math::factorial(n) / (std::math::factorial(k) * std::math::factorial(n - k));
};
/**
Rounds the value of `value`.
@param value Value
@return `value` rounded
*/
fn round(auto value) { return builtin::std::math::round(value); };
/**
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;
else
return std::math::factorial(n) / std::math::factorial(n - k);
};
/**
Truncates the value of `value`.
@param value Value
@return `value` truncated
*/
fn trunc(auto value) { return builtin::std::math::trunc(value); };
/**
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 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 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
@param base Base
@return Logarithm of `value` with base `e`
*/
fn ln(auto value) { return builtin::std::math::ln(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 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 `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 square root of `value`.
@param value Value
@return Square root of `value`
*/
fn sqrt(auto value) { return builtin::std::math::sqrt(value); };
/**
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 cubic root of `value`.
@param value Value
@return Cubic root of `value`
*/
fn cbrt(auto value) { return builtin::std::math::cbrt(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 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 cubic root of `value`.
@param value Value
@return Cubic root of `value`
*/
fn cbrt(auto value) { return builtin::std::math::cbrt(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 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 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 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 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 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 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 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 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 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` and `pi`
*/
fn atan2(auto value) { return builtin::std::math::atan2(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 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 arc tangent of `value`.
@param y Value representing the proportion of the y-coordinate
@param x Value representing the proportion of the x-coordinate.
@return Arc tangent of `value` in radians between `-pi` and `pi`
*/
fn atan2(auto y, auto x) { return builtin::std::math::atan2(y, x); };
/**
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 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 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 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 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 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); };
/**
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
};
/**
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. Defaults to addition
@param [endian] Endianness to use. Defaults to native
@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));
};
/**
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

@@ -4,15 +4,15 @@
Library for doing raw memory accesses and other low-level operations.
*/
namespace std::mem {
namespace auto std::mem {
/**
A Handle for a custom Section
*/
using Section = u128;
/**
The Endianess of a value
The endianness of a value
*/
enum Endian : u8 {
Native = 0,
@@ -26,7 +26,16 @@ namespace std::mem {
@return True if the cursor is at the end of the memory
*/
fn eof() {
return $ >= std::mem::size();
return $ >= (std::mem::base_address() + std::mem::size());
};
/**
Function that returns true if the cursor position is at or beyond the given address
@param address The address to compare against
@return True if the cursor is at or beyond the given address
*/
fn reached(u128 address) {
return $ >= address;
};
/**
@@ -40,10 +49,10 @@ namespace std::mem {
return remainder != 0 ? value + (alignment - remainder) : value;
};
/**
Gets the base address of the memory
Gets the base address of the data
@return The base address of the memory
*/
fn base_address() {
@@ -51,7 +60,7 @@ namespace std::mem {
};
/**
Gets the size of the memory
Gets the size of the data
@return The size of the memory
*/
fn size() {
@@ -59,17 +68,18 @@ namespace std::mem {
};
/**
Finds a sequence of bytes in the memory
Finds a sequence of bytes in the data
@param occurrence_index The index of the occurrence to find
@param bytes The bytes to find
@return The address of the sequence
*/
fn find_sequence(u128 occurrence_index, auto ... bytes) {
return builtin::std::mem::find_sequence_in_range(occurrence_index, builtin::std::mem::base_address(), builtin::std::mem::size(), bytes);
const u128 address = std::mem::base_address();
return builtin::std::mem::find_sequence_in_range(occurrence_index, address, address + std::mem::size(), bytes);
};
/**
Finds a sequence of bytes in a specific region of the memory
Finds a sequence of bytes in a specific region of the data
@param occurrence_index The index of the occurrence to find
@param offsetFrom The offset from which to start searching
@param offsetTo The offset to which to search
@@ -80,11 +90,35 @@ namespace std::mem {
return builtin::std::mem::find_sequence_in_range(occurrence_index, offsetFrom, offsetTo, bytes);
};
/**
Finds a string in the data
@param occurrence_index The index of the occurrence to find
@param string The string to find
@return The address of the sequence
*/
fn find_string(u128 occurrence_index, str string) {
const u128 address = std::mem::base_address();
return builtin::std::mem::find_string_in_range(occurrence_index, address, address + std::mem::size(), string);
};
/**
Finds a string in a specific region of the data
@param occurrence_index The index of the occurrence to find
@param offsetFrom The offset from which to start searching
@param offsetTo The offset to which to search
@param string The string to find
@return The address of the sequence
*/
fn find_string_in_range(u128 occurrence_index, u128 offsetFrom, u128 offsetTo, str string) {
return builtin::std::mem::find_string_in_range(occurrence_index, offsetFrom, offsetTo, string);
};
/**
Reads a unsigned value from the memory
@param address The address to read from
@param size The size of the value to read
@param endian The endianess of the value to read
@param [endian] The endianness of the value to read. Defaults to native
@return The value read
*/
fn read_unsigned(u128 address, u8 size, Endian endian = Endian::Native) {
@@ -95,7 +129,7 @@ namespace std::mem {
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
@param [endian] The endianness of the value to read. Defaults to native
@return The value read
*/
fn read_signed(u128 address, u8 size, Endian endian = Endian::Native) {
@@ -108,18 +142,10 @@ namespace std::mem {
@param size The size of the value to read
@return The value read
*/
fn read_string(u128 address, u8 size) {
fn read_string(u128 address, u128 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
@@ -160,6 +186,15 @@ namespace std::mem {
return builtin::std::mem::get_section_size(section);
};
/**
Changes the size of a custom section
@param section The handle to the section
@param size The new size of the section
*/
fn set_section_size(Section section, u128 size) {
builtin::std::mem::set_section_size(section, size);
};
/**
Copies a range of bytes from one section into another
@param from_section The section to copy from
@@ -174,35 +209,20 @@ namespace std::mem {
/**
Copies a range of bytes from the main section into a custom section
@param from_section The section to copy from
@param from_address The address to copy from
@param value The pattern whose bytes should be copied
@param to_section The section to copy to
@param to_address The address to copy to
@param size The size of the range to copy
*/
fn copy_value_to_section(ref auto value, Section to_section, u64 to_address) {
builtin::std::mem::copy_value_to_section(value, to_section, to_address);
};
/**
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
Returns the current bit offset when inside of a bitfield.
@return The current bit offset between 0 and 7
*/
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;
}
fn current_bit_offset() {
return builtin::std::mem::current_bit_offset();
};
/**
@@ -211,10 +231,10 @@ namespace std::mem {
@tparam To The type to reinterpret to
*/
union Reinterpreter<From, To> {
From from;
To to;
From from_value;
To to_value;
};
/**
Aligns the cursor to the given alignment
@@ -233,11 +253,33 @@ namespace std::mem {
} [[sealed, format("std::mem::impl::format_bytes")]];
namespace impl {
fn format_bytes(auto bytes) {
return "";
};
struct MagicSearchImpl<auto Magic, T> {
s128 address = builtin::std::mem::find_string_in_range(0, $, std::mem::size(), Magic);
if (address < 0)
break;
$ = address;
try {
T data [[inline]];
} catch {
T data;
}
};
}
/**
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> {
std::mem::impl::MagicSearchImpl<Magic, T> impl[while(!std::mem::eof())] [[inline]];
};
}

View File

@@ -1,11 +1,13 @@
#pragma once
import std.mem;
/*!
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 {
namespace auto std::ptr {
/**
Use the offset of the current pointer as start address
@@ -45,9 +47,9 @@ namespace std::ptr {
Example:
A struct field called `p_myInfo` which is a nullable 64-bit pointer to an
element of type `MyInfoTy` would be written as:
```
```rust
struct MyStruct {
std::ptr::NullablePtr<MyInfoTy, u64> p_myInfo;
std::ptr::NullablePtr<MyInfoTy, u64> p_myInfo;
}
```
*/
@@ -55,7 +57,7 @@ namespace std::ptr {
// `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
// 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) {
@@ -64,4 +66,4 @@ namespace std::ptr {
PointeeTy *data : PointerTy;
}
};
}
}

View File

@@ -1,13 +1,13 @@
#pragma once
#include <std/limits.pat>
import std.limits;
/*!
Library to generate random numbers. Supports various different distribution types.
*/
namespace std::random {
namespace auto std::random {
/**
Represents the type of distribution to use to generate a random number
*/
@@ -61,21 +61,21 @@ namespace std::random {
> - `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.
@param [param1] This parameter depends on the type of distribution used. Defaults to 0
@param [param2] This parameter depends on the type of distribution used. Defaults to 0
*/
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
@param [min] Minimum number. Defaults to 0
@param [max] Maximum number. Defaults to `u64_max`
*/
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

@@ -1,129 +1,153 @@
#pragma once
#include <std/io.pat>
import std.io;
import std.mem;
/*!
Libray to interact with strings.
Library to interact with strings.
*/
namespace std::string {
namespace auto 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")]];
/**
Base type for sized strings. Represents a string with its size preceding 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_string"), transform("std::string::impl::format_string")]];
/**
A ASCII string with a prefixed size.
@tparam SizeType The type of the size field.
*/
using SizedString<SizeType> = SizedStringBase<SizeType, char>;
/**
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>;
/**
A UTF-16 string with a prefixed size.
@tparam SizeType The type of the size field.
*/
using SizedString16<SizeType> = SizedStringBase<SizeType, char16>;
namespace impl {
/**
Base type for null-terminated strings. Represents a string with its size determined by the first 0x00 byte found.
@tparam DataType The type of the characters.
*/
struct NullStringBase<DataType> {
DataType data[while(std::mem::read_unsigned($, sizeof(DataType)) != 0x00)];
DataType null_terminator;
} [[sealed, format("std::string::impl::format_string"), transform("std::string::impl::format_string")]];
fn format_sized_string(ref auto string) {
return string.data;
};
/**
A null-terminated ASCII string.
*/
using NullString = NullStringBase<char>;
}
/**
A null-terminated UTF-16 string.
*/
using NullString16 = NullStringBase<char16>;
/**
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);
};
namespace impl {
/**
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);
};
fn format_string(ref auto string) {
return string.data;
};
/**
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);
};
}
/**
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 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 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.
*/
/**
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.
*/
/**
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) {
if (std::string::length(string) < std::string::length(part))
return false;
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.
*/
/**
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) {
if (std::string::length(string) < std::string::length(part))
return false;
return std::string::substr(string, std::string::length(string) - std::string::length(part), std::string::length(part)) == part;
};
/**
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.
*/
/**
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);
@@ -136,103 +160,100 @@ namespace std::string {
return false;
};
/**
Reverses a string.
@param string The string to reverse.
@return The reversed string.
*/
fn reverse(str string) {
/**
Reverses a string.
@param string The string to reverse.
@return The reversed string.
*/
fn reverse(str string) {
str result;
s32 i;
i = std::string::length(string);
while (i > 0) {
i = i - 1;
result = result + std::string::at(string, i);
}
return result;
};
/**
Converts a string to upper case.
@param string The string to convert.
@return The converted string.
*/
/**
Converts a string to upper case.
@param string The string to convert.
@return The converted string.
*/
fn to_upper(str string) {
str result;
u32 i;
char c;
while (i < std::string::length(string)) {
c = std::string::at(string, i);
if (c >= 'a' && c <= 'z')
result = result + char(c - 0x20);
else
result = result + c;
i = i + 1;
}
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;
u32 i;
char c;
while (i < std::string::length(string)) {
c = std::string::at(string, i);
if (c >= 'A' && c <= 'Z')
result = result + char(c + 0x20);
else
result = result + c;
i = i + 1;
}
return result;
};
str 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.
*/
u32 i;
char c;
while (i < std::string::length(string)) {
c = std::string::at(string, i);
if (c >= 'a' && c <= 'z')
result = result + char(c - 0x20);
else
result = result + c;
i = i + 1;
}
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;
u32 i;
char c;
while (i < std::string::length(string)) {
c = std::string::at(string, i);
if (c >= 'A' && c <= 'Z')
result = result + char(c + 0x20);
else
result = result + c;
i = i + 1;
}
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);
pattern_len = std::string::length(pattern);
replace_len = std::string::length(replace);
if (pattern_len > string_len)
return string;
str result;
u32 i;
while (i <= (string_len - pattern_len)) {
if (std::string::substr(string, i, pattern_len) == pattern) {
result = result + replace;
i = i + pattern_len;
} else {
result = result + std::string::at(string, i);
i = i + 1;
}
}
return result;
};
s32 string_len = std::string::length(string);
s32 pattern_len = std::string::length(pattern);
if (pattern_len > string_len || pattern_len * string_len == 0 )
return string;
str result;
s32 string_index;
s32 remaining_len = string_len;
while (pattern_len <= remaining_len) {
if (std::string::substr(string, string_index, pattern_len) == pattern) {
result += replace;
string_index += pattern_len;
} else {
result += std::string::at(string, string_index);
string_index += 1;
}
remaining_len = string_len - string_index;
}
result += std::string::substr(string, string_index, remaining_len );
return result;
};
}

View File

@@ -1,16 +1,16 @@
#pragma once
#include <std/io.pat>
import std.io;
/*!
Basic helper functions
*/
namespace std {
namespace auto 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 condition 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) {
@@ -21,7 +21,7 @@ namespace std {
/**
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 condition 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) {
@@ -49,4 +49,11 @@ namespace std {
return builtin::std::sizeof_pack(pack);
};
/**
Throws an error notifying the developer that the current code path is not implemented currently.
*/
fn unimplemented() {
std::error("Unimplemented code path reached!");
};
}

View File

@@ -1,191 +1,200 @@
#pragma once
#include <std/io.pat>
import std.io;
/*!
Library to handle time and date related operations.
Library to handle time and date related operations.
*/
namespace std::time {
namespace auto std::time {
/**
A structured representation of a time and date.
*/
struct Time {
u8 sec;
u8 min;
u8 hour;
u8 mday;
u8 mon;
u16 year;
u8 wday;
u16 yday;
bool isdst;
} [[sealed]];
/**
A structured representation of a time and date.
*/
struct Time {
u8 sec;
u8 min;
u8 hour;
u8 mday;
u8 mon;
u16 year;
u8 wday;
u16 yday;
bool isdst;
} [[sealed]];
/**
A helper type to convert between Time and u128.
*/
union TimeConverter {
Time time;
u128 value;
};
/**
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 in seconds since the epoch.
*/
using EpochTime = u32;
/**
A type to represent a time zone.
*/
enum TimeZone : u8 {
Local,
UTC
};
/**
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 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]];
/**
A type to represent a DOS time.
*/
bitfield DOSTime {
seconds: 5;
minutes: 6;
hours: 5;
} [[sealed]];
namespace impl {
namespace impl {
union DOSDateConverter {
DOSDate date;
u16 value;
};
union DOSDateConverter {
DOSDate date;
u16 value;
};
union DOSTimeConverter {
DOSTime time;
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();
};
/**
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;
/**
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) {
le TimeConverter converter;
converter.value = builtin::std::time::to_local(epoch_time);
converter.value = builtin::std::time::to_local(epoch_time);
return converter.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;
/**
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) {
le TimeConverter converter;
converter.value = builtin::std::time::to_utc(epoch_time);
converter.value = builtin::std::time::to_utc(epoch_time);
return converter.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;
/**
Queries the current time in the specified time zone.
@param [time_zone] The time zone to query. Defaults to local.
@return The current time in the specified time zone.
*/
fn now(TimeZone time_zone = TimeZone::Local) {
le 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;
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;
};
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;
/**
Converts a value to a DOS date.
@param value The value to convert.
@return The DOS date.
*/
fn to_dos_date(u16 value) {
le impl::DOSDateConverter converter;
converter.value = value;
converter.value = value;
return converter.date;
};
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;
/**
Converts a value to a DOS time.
@param value The value to convert.
@return The DOS time.
*/
fn to_dos_time(u16 value) {
le impl::DOSTimeConverter converter;
converter.value = value;
converter.value = value;
return converter.time;
};
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;
/**
Converts a FILETIME to unix time.
@param value The value to convert.
@return Timestamp formatted as unix time.
*/
fn filetime_to_unix(u64 value) {
return value / 10000000 - 11644473600;
};
return builtin::std::time::format(format_string, converter.value);
};
/**
Formats a time according to the specified format string.
@param time The time to format.
@param [format_string] The format string to use. Defaults to "%c".
@return The formatted time.
*/
fn format(Time time, str format_string = "%c") {
le TimeConverter converter;
converter.time = time;
/**
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);
};
return builtin::std::time::format(format_string, converter.value);
};
/**
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);
};
/**
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. Defaults to "{}/{}/{}".
@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. Defaults to "{:02}:{:02}:{:02}".
@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);
};
}

View File

@@ -1,14 +1,14 @@
#pragma once
#include <std/io.pat>
#include <std/math.pat>
import std.io;
import std.math;
/*!
Types used to change the base of the displayed integer value.
Used like `type::Hex<u32> hexNumber;`, `type::Oct<u16> octalNumber;`
*/
namespace type {
namespace auto type {
/**
Integer type representing a Hexadecimal value. Displays its value in hexadecimal format.
@@ -34,7 +34,7 @@ namespace type {
*/
using Bin<T> = T [[format("type::impl::format_bin")]];
namespace impl {
namespace impl {
fn format_number(auto value, str fmt) {
bool negative = value < 0;
@@ -50,6 +50,6 @@ namespace type {
fn format_dec(auto value) { return type::impl::format_number(value, "{}"); };
fn format_bin(auto value) { return type::impl::format_number(value, "0b{:08b}"); };
}
}
}

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

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

View File

@@ -1,12 +1,12 @@
#pragma once
#include <std/io.pat>
import std.io;
/*!
Type to decode a BCD (Binary Coded Decimal) number
*/
namespace type {
namespace auto type {
/**
Decodes a BCD value where one byte represents a single digit

View File

@@ -1,13 +1,14 @@
#pragma once
#include <std/io.pat>
import std.io;
import std.core;
/*!
Types to display single bytes using various different representations
*/
namespace type {
namespace auto type {
/**
Type visualizing the value of each individual bit
*/
@@ -20,8 +21,8 @@ namespace type {
bit5 : 1;
bit6 : 1;
bit7 : 1;
} [[format("type::impl::format_bits"), right_to_left]];
} [[format("type::impl::format_bits"), bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 8)]];
/**
Type visualizing the value of the two nibbles
*/
@@ -29,9 +30,9 @@ namespace type {
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
Type representing a single Byte. Decodes the byte as it's hexadecimal value, individual bits and nibbles
*/
union Byte {
u8 value;
@@ -40,7 +41,7 @@ namespace type {
} [[format("type::impl::format_byte"), single_color]];
namespace impl {
namespace impl {
fn format_byte(Byte byte) {
return std::format("0x{0:02X} (0b{1:08b}) LSB:{2}, MSB:{3}",
@@ -49,9 +50,9 @@ namespace type {
byte.bits.bit0,
byte.bits.bit7);
};
fn format_bits(Bits bits) {
return std::format("0b{}{}{}{}{}{}{}{}",
return std::format("0b{}{}{}{}{}{}{}{}",
bits.bit7,
bits.bit6,
bits.bit5,
@@ -61,11 +62,11 @@ namespace type {
bits.bit1,
bits.bit0);
};
fn format_nibbles(Nibbles nibbles) {
return std::format("{{ {0:0X}, {1:0X} }}", nibbles.high, nibbles.low);
};
}
}
}

View File

@@ -1,28 +1,28 @@
#pragma once
#include <std/io.pat>
#include <std/core.pat>
import std.io;
import std.core;
/*!
Types representing RGB or RGBA colors. The decoded color will be displayed in their color field
*/
namespace type {
namespace auto type {
/**
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
@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))]];
} [[sealed, format("type::impl::format_color"), color(std::format("{0:02X}{1:02X}{2:02X}", 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
@@ -30,7 +30,7 @@ namespace type {
@tparam B Number of bits used for the blue component
*/
using RGB<auto R, auto G, auto B> = RGBA<R,G,B,0>;
/**
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
@@ -56,7 +56,7 @@ namespace type {
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 {
@@ -76,5 +76,5 @@ namespace type {
};
}
}
}

View File

@@ -1,45 +1,45 @@
#pragma once
#include <std/io.pat>
#include <std/math.pat>
#include <std/mem.pat>
import std.io;
import std.math;
import std.mem;
/*!
Type representing a 16 bit half precision floating point number
*/
namespace type {
namespace auto type {
/**
Type representing a 16 bit half precision floating point number
*/
using float16 = u16 [[format("type::impl::format_float16")]];
namespace impl {
union U32ToFloatConverter {
u32 intValue;
float floatValue;
};
fn format_float16(float16 value) {
fn format_float16(float16 value) {
u32 sign = value >> 15;
u32 exponent = (value >> 10) & 0x1F;
u32 mantissa = value & 0x3FF;
u32 result = 0x00;
if (exponent == 0) {
if (mantissa == 0) {
result = sign << 31;
} else {
exponent = 0x7F - 14;
while ((mantissa & (1 << 10)) == 0) {
exponent -= 1;
mantissa <<= 1;
}
mantissa &= 0x3FF;
result = (sign << 31) | (exponent << 23) | (mantissa << 13);
}
@@ -48,11 +48,11 @@ namespace type {
} else {
result = (sign << 31) | ((exponent + (0x7F - 15)) << 23) | (mantissa << 13);
}
std::mem::Reinterpreter<u32, float> converter;
converter.from = result;
return std::format("{}", converter.to);
converter.from_value = result;
return std::format("{}", converter.to_value);
};
}

42
includes/type/fmt.pat Normal file
View File

@@ -0,0 +1,42 @@
#pragma once
import std.io;
/*!
Type that allows specifying its format value using a format string.
## Usage
The following code reads a u32 from the data and formats it as an upper case hexadecimal value with
a minimum of 8 digits which is prefixed by 0x.
The format string is the same as passed to `std::format()` and follows the libfmt specification.
```rust
type::Formatted<u32, "0x{:08X}"> hex_formatted_integer @ 0x00;
```
*/
namespace auto type {
/**
Arbitrarily formatted type
@tparam T Type to format
@tparam FormatString libfmt format string to format the value
*/
struct Formatted<T, auto FormatString> {
T value;
} [[sealed, format("type::impl::format_formatted"), transform("type::impl::transform_formatted")]];
namespace impl {
fn format_formatted(ref auto formatted) {
return std::format(formatted.FormatString, formatted.value);
};
fn transform_formatted(ref auto formatted) {
return formatted.value;
};
}
}

View File

@@ -1,17 +1,17 @@
#pragma once
#include <std/io.pat>
import std.io;
/*!
Types to deal with UUIDs (Universally Unique Identifiers) / GUIDs (Globally Unique Identifiers) as described in RFC 4122
Types to deal with UUIDs (Universally Unique Identifiers) / GUIDs (Globally Unique Identifiers) as described in RFC 4122
*/
namespace type {
namespace auto type {
/**
Type representing a GUID value
*/
struct GUID {
/**
Type representing a GUID value
*/
struct GUID {
u32 time_low;
u16 time_mid;
u16 time_high_and_version;
@@ -20,31 +20,31 @@ namespace type {
u8 node[6];
} [[sealed, format("type::impl::format_guid")]];
/**
Alias name for GUID
*/
using UUID = GUID;
/**
Alias name for GUID
*/
using UUID = GUID;
namespace impl {
namespace impl {
fn format_guid(GUID guid) {
bool valid = ((le u16(guid.time_high_and_version) >> 12) <= 5) && (((guid.clock_seq_and_reserved >> 4) >= 8) || ((guid.clock_seq_and_reserved >> 4) == 0));
return std::format("{}{{{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}",
valid ? "" : "Invalid ",
le u32(guid.time_low),
le u16(guid.time_mid),
le u16(guid.time_high_and_version),
guid.clock_seq_and_reserved,
guid.clock_seq_low,
guid.node[0],
guid.node[1],
guid.node[2],
guid.node[3],
guid.node[4],
guid.node[5]);
};
fn format_guid(GUID guid) {
bool valid = ((le u16(guid.time_high_and_version) >> 12) <= 5) && (((guid.clock_seq_and_reserved >> 4) >= 8) || ((guid.clock_seq_and_reserved >> 4) == 0));
}
return std::format("{}{{{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}",
valid ? "" : "Invalid ",
le u32(guid.time_low),
le u16(guid.time_mid),
le u16(guid.time_high_and_version),
guid.clock_seq_and_reserved,
guid.clock_seq_low,
guid.node[0],
guid.node[1],
guid.node[2],
guid.node[3],
guid.node[4],
guid.node[5]);
};
}
}

View File

@@ -1,13 +1,13 @@
#pragma once
#include <std/io.pat>
#include <std/string.pat>
import std.io;
import std.string;
/*!
Types used to decode IP addresses
*/
namespace type {
namespace auto type {
/**
A 4 byte IPv4 Address as described in RFC 791

View File

@@ -1,72 +1,72 @@
#pragma once
#include <std/io.pat>
#include <std/mem.pat>
import std.io;
import std.mem;
/*!
Types used to decode Little Endian Base 128 numbers used to store large numbers as space efficiently as possible
Types used to decode Little Endian Base 128 numbers used to store large numbers as space efficiently as possible
*/
namespace type {
/**
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]];
namespace auto type {
/**
A unsigned variant of a LEB128 number
*/
using uLEB128 = LEB128Base [[format("type::impl::format_uleb128"), transform("type::impl::transform_uleb128")]];
/**
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]];
/**
A signed variant of a LEB128 number
*/
using sLEB128 = LEB128Base [[format("type::impl::format_sleb128"), transform("type::impl::transform_sleb128")]];
/**
A unsigned variant of a LEB128 number
*/
using uLEB128 = LEB128Base [[format("type::impl::format_uleb128"), transform("type::impl::transform_uleb128")]];
/**
Legacy alias for uLEB128
*/
using LEB128 = uLEB128;
namespace impl {
fn transform_uleb128_array(auto array) {
u128 res = array[0] & 0x7f;
for(u8 i = 1, array[i-1] & 0x80 != 0, i+=1) {
res |= u128(array[i] & 0x7f) << 7 * i;
}
return res;
};
/**
A signed variant of a LEB128 number
*/
using sLEB128 = LEB128Base [[format("type::impl::format_sleb128"), transform("type::impl::transform_sleb128")]];
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_uleb128(auto leb128) {
u128 res = type::impl::transform_uleb128_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_uleb128(auto leb128) {
return type::impl::transform_uleb128_array(leb128.array);
};
/**
Legacy alias for uLEB128
*/
using LEB128 = uLEB128;
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);
};
namespace impl {
fn transform_uleb128_array(ref auto array) {
u128 res = array[0] & 0x7f;
for(u8 i = 1, array[i-1] & 0x80 != 0, i+=1) {
res |= u128(array[i] & 0x7f) << 7 * i;
}
return res;
};
fn transform_sleb128_array(ref auto array) {
s128 res = type::impl::transform_uleb128_array(array);
if (res & 1 << ((sizeof(array) / sizeof(u8)) * 7 - 1) != 0) {
res |= ~0 << (sizeof(array) / sizeof(u8)) * 7;
}
return res;
};
fn format_uleb128(ref auto leb128) {
u128 res = type::impl::transform_uleb128_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_uleb128(ref auto leb128) {
return type::impl::transform_uleb128_array(leb128.array);
};
fn format_sleb128(ref auto leb128) {
s128 res = type::impl::transform_sleb128_array(leb128.array);
return std::format("{} ({:#x})", res, res);
};
fn transform_sleb128(ref auto leb128) {
return type::impl::transform_sleb128_array(leb128.array);
};
}
}
}

View File

@@ -1,32 +1,32 @@
#pragma once
#include <std/io.pat>
import std.io;
/*!
Types used to decode MAC Addresses
Types used to decode MAC Addresses
*/
namespace type {
namespace auto type {
/**
A MAC Address as used in the Internet Protocol
*/
struct MACAddress {
u8 bytes[6];
} [[sealed, format("type::impl::format_mac_address")]];
/**
A MAC Address as used in the Internet Protocol
*/
struct MACAddress {
u8 bytes[6];
} [[sealed, format("type::impl::format_mac_address")]];
namespace impl {
namespace impl {
fn format_mac_address(MACAddress address) {
return std::format("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
address.bytes[0],
address.bytes[1],
address.bytes[2],
address.bytes[3],
address.bytes[4],
address.bytes[5]);
};
return std::format("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
address.bytes[0],
address.bytes[1],
address.bytes[2],
address.bytes[3],
address.bytes[4],
address.bytes[5]);
};
}
}
}

View File

@@ -1,13 +1,35 @@
#include <std/string.pat>
#include <std/sys.pat>
#include <std/io.pat>
#include <std/ctype.pat>
#pragma once
import std.string;
import std.sys;
import std.io;
import std.ctype;
/*!
Types used to parse and enforce specific magic numbers
*/
namespace type {
namespace auto type
{
/**
Escapes all bytes in a string to only contain printable characters. All non-printable bytes will be transformed to sequences in the \xFF form
@param value Byte array to escape
@return Escaped string
*/
fn escape_bytes(ref auto value) {
str result;
for (u32 i = 0, i < sizeof(value), i += 1)
{
char c = value[i];
if (std::ctype::isprint(c))
result += c;
else
result += std::format("\\x{:02X}", u8(c));
}
return result;
};
/**
A Magic number. Throws an error if the magic number does not match the expected value
@@ -15,24 +37,11 @@ namespace type {
*/
struct Magic<auto ExpectedValue> {
char value[std::string::length(ExpectedValue)];
std::assert(value == ExpectedValue, std::format("Invalid magic value! Expected \"{}\", got \"{}\".", ExpectedValue, value));
std::assert(value == ExpectedValue, std::format("Invalid magic value! Expected \"{}\", got \"{}\" at position 0x{:X}", type::escape_bytes(ExpectedValue), type::escape_bytes(value), $ - std::string::length(ExpectedValue)));
} [[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);
return std::format("\"{}\"", type::escape_bytes(magic.value));
};
}
}
}

View File

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

View File

@@ -1,10 +1,12 @@
#include <std/io.pat>
#pragma once
import std.io;
/*!
Types used to pretty print size values
*/
namespace type {
namespace auto type {
/**
A generic size type which displays its value in Bytes (or kiB, MiB, GiB, TiB, PiB, EiB if larger)
@@ -69,4 +71,4 @@ namespace type {
}
}
}

View File

@@ -1,21 +1,21 @@
#pragma once
#include <std/io.pat>
#include <std/time.pat>
import std.io;
import std.time;
/*!
Types used to decode various different time formats
*/
namespace type {
namespace auto type {
/**
A 32 bit Unix time value
*/
using time32_t = u32 [[format("type::impl::format_time_t")]];
/**
Alias name for `time32_t`
Alias name for `time32_t`
*/
using time_t = time32_t;
@@ -34,6 +34,11 @@ namespace type {
*/
using DOSTime = u16 [[format("type::impl::format_dostime")]];
/**
A 64bit FILETIME value
*/
using FILETIME = u64 [[format("type::impl::format_filetime_as_unix")]];
namespace impl {
fn format_time_t(u128 value) {
@@ -48,6 +53,10 @@ namespace type {
return std::time::format_dos_time(std::time::to_dos_time(value));
};
fn format_filetime_as_unix(u64 value) {
return std::time::filetime_to_unix(value);
};
}
}

View File

@@ -5,7 +5,7 @@
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {
// namespace auto type {
// using char = s8;
using byte = s8;

View File

@@ -5,7 +5,7 @@
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {
// namespace auto type {
using uint8_t = u8;
using uint16_t = u16;

View File

@@ -5,7 +5,7 @@
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {
// namespace auto type {
using le16 = le u16;
using be16 = be u16;

View File

@@ -5,7 +5,7 @@
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {
// namespace auto type {
// using u8 = u8;
// using u16 = u16;

View File

@@ -5,7 +5,7 @@
*/
// Explicitly don't add these types to the `type` namespace for usability
// namespace type {
// namespace auto type {
using BYTE = u8;
using WORD = u16;

41
magic/arma3_magic Normal file
View File

@@ -0,0 +1,41 @@
# A libmagic database containing definitions for files used by the Arma 3 game by Bohemia Interactive
# Arma 3 PAA image
0x02 string GGAT Arma 3 PAA image file
!:mime image/x.a3-paa
!:ext paa
>0 leshort 0xff01 DXT1 compression
>0 leshort 0xff02 DXT2 compression
>0 leshort 0xff03 DXT3 compression
>0 leshort 0xff04 DXT4 compression
>0 leshort 0xff05 DXT5 compression
>0 leshort 0x4444 RGBA4 format
>0 leshort 0x1555 RGBA5 format
>0 leshort 0x8888 RGBA8 format
>0 leshort 0x8080 Grayscale format
# Arma 3 RTM animation
0 string RTM_ Arma 3 RTM animation file (plain)
!:mime application/x.a3-rtm
!:ext rtm
# Arma 3 binarized RTM animation
0 string BMTR Arma 3 RTM animation file (binarized)
!:mime application/x.a3-bmtr
!:ext rtm
# Arma 3 texture index
0 string 0DHT Arma 3 texture index file
!:mime application/x.a3-texheaders
!:ext bin
# Arma 3 MLOD P3D model
0 string MLOD Arma 3 P3D model file (MLOD)
!:mime model/x.a3-p3d-mlod
!:ext p3d
>0x0c string P3DM P3DM LOD type
# Arma 3 binarized config
0x01 string raP Arma 3 binary configuration file
!:mime application/x.a3-rap
!:ext bin

View File

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

1141
patterns/3ds.hexpat Normal file

File diff suppressed because it is too large Load Diff

93
patterns/7z.hexpat Normal file
View File

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

View File

@@ -0,0 +1,47 @@
#pragma description Assassin's Creed: Unity's Compressed .data file
#pragma author haru233
// many thanks to AxCut
// ImHex Hex Pattern File for Assassin's Creed: Unity's Compressed .data files
import std.core;
import std.mem;
enum CompressionType : u8 {
LZO1X_ = 0x00, // Both 0x00 and 0x01 mean LZO1X
LZO1X = 0x01,
LZO2A = 0x02,
xmemdecompress = 0x03,
LZO1C = 0x05
};
struct CHUNK {
u16 Uncompressed_Size;
u16 Compressed_Size;
};
struct CHUNK_Data {
u32 Hash;
u64 i = std::core::array_index();
u8 data[parent.chunk[i].Compressed_Size];
};
struct PACK {
u64 ID;
padding[2];
CompressionType Compression_Type;
padding[3];
u8 Version;
u16 CHUNK_Count;
CHUNK chunk[CHUNK_Count];
CHUNK_Data data[CHUNK_Count];
};
PACK pack[while(!std::mem::eof())] @0x00;

View File

@@ -0,0 +1,93 @@
#pragma description Assassin's Creed: Unity's Decompressed .data file
#pragma author haru233
// Thanks to yretenai on GitHub for helping with the Block Allocator part
import std.core;
import std.mem;
struct Block_Allocator_Type0 {
padding[4];
u32 Class_ID;
u32 Size;
};
struct Block_Allocator_Type1 {
padding[4];
u32 Type_ID;
u32 Size;
};
struct Block_Allocator {
u16 Version;
if (Version == 0) {
u32 Block_Allocator_Number;
Block_Allocator_Type0 block_allocator_type0[Block_Allocator_Number];
}
else if (Version == 1) {
u32 Block_Allocator_Number;
Block_Allocator_Type1 block_allocator_type1_[Block_Allocator_Number];
}
else if (Version == 2) {
bool Has_Secondary_Block_Allocator;
u32 Main_Block_Allocator_Number;
Block_Allocator_Type1 block_allocator_type1__[Main_Block_Allocator_Number];
if (Has_Secondary_Block_Allocator) {
u32 Secondary_Block_Allocator_Number;
Block_Allocator_Type1 block_allocator_type1___[Secondary_Block_Allocator_Number+1];
}
}
};
struct File {
u32 Object_Hash;
u32 File_Size;
u32 Filename_Length;
if (File_Size > 0) {
if (Filename_Length == 0) {
bool HasBlockAllocator;
if (HasBlockAllocator) {
Block_Allocator block_allocator;
u8 File_Data[File_Size];
}
else
u8 File_Data[File_Size];
}
else {
char Filename[Filename_Length];
bool HasBlockAllocator;
if (HasBlockAllocator) {
Block_Allocator block_allocator;
u8 File_Data[File_Size];
}
else
u8 File_Data[File_Size];
}
}
else
continue;
};
File file[while(!std::mem::eof())] @0x00;

View File

@@ -0,0 +1,64 @@
#pragma description Assassin's Creed: Unity's .forge archive file
#pragma author haru233
// many thanks to AxCut
// ImHex Hex Pattern File for Assassin's Creed: Unity's .forge files
import std.core;
struct Forge_Header {
char MAGIC[8];
padding[1];
u32 Version;
u32 File_Data_Header_Offset;
};
struct File_Data_Header {
u32 File_Count;
padding[32];
u64 File_Data_Header2_Offset;
};
struct File_Data_Header2 {
u32 File_Count2;
padding[4];
u64 File_Table_Offset;
padding[12];
u32 File_Count3;
u64 File_Name_Table_Offset;
padding[8];
};
struct File_Table {
u64 Raw_Data_Offset;
u64 File_ID;
u32 Raw_Data_Size;
};
struct File_Name_Table {
u32 Raw_Data_Size;
padding[40];
char Filename[128];
padding[20];
};
Forge_Header forge_header @0x00;
File_Data_Header file_data_header @(forge_header.File_Data_Header_Offset);
File_Data_Header2 file_data_header2 @(file_data_header.File_Data_Header2_Offset);
File_Table file_table[file_data_header.File_Count] @(file_data_header2.File_Table_Offset);
File_Name_Table file_name_table[file_data_header.File_Count] @(file_data_header2.File_Name_Table_Offset);
struct Raw_Data_Table {
u64 i = std::core::array_index();
u8 Raw_Data[file_table[i].Raw_Data_Size] @ file_table[i].Raw_Data_Offset;
};
Raw_Data_Table raw_data_table[file_data_header.File_Count] @0x00;

371
patterns/Crashlvl.hexpat Normal file
View File

@@ -0,0 +1,371 @@
#pragma author AdventureT
#pragma description Crash Bandicoot - Back in Time (fan game) User created level
#pragma magic [ 43 52 41 53 48 4C 56 4C ] @ 0x00
#pragma history
#pragma 0.3 2024-05-15 Added support for version 0.95
#pragma 0.2 2023-10-29 Added support for version 0.94c
#pragma 0.1 2023-04-25 Initial support
// Supports all versions till 0.95, newer versions might be compatible!
import type.magic;
import std.string;
import std.array;
struct Header {
type::Magic<"CRASHLVL"> magic;
u8 version;
if (version >= 4) {
std::string::SizedString<u8> gameVersion;
}
std::string::SizedString<u8> levelName;
std::string::SizedString<u8> author;
};
// Background Music
enum BGM : u32 {
None,
BonusBGM,
CrashCreatorBGM,
MainMenuBGM,
WarpRoomBGM,
Level01BGM,
Level02BGM,
Level03BGM,
Level04BGM,
Level05BGM,
SewerBGM,
EgyptBGM,
NBrioBGM
};
enum BGMV2 : u32 {
None,
N_TropyBGM,
CrashCreatorBGM,
MainMenuBGM,
WarpRoomBGM,
Jungle01BGM,
SnowBGM,
RiverBGM,
FutureBGM,
LabBGM,
SewerBGM,
EgyptBGM,
NBrioBGM,
AdventureBGM,
SpyBGM,
ChaseBGM,
TrialsBGM,
SpaceBGM,
Jungle02BGM,
RipperBGM,
TheGreatWallBGM,
RoadToSomewhereBGM,
LavaKoalaBGM,
CortexBGM,
CyberCortexBGM,
ArabicBGM,
N_Tropy2BGM,
JazzBGM,
Space2BGM,
TawnaBonusBGM,
CortexPowerBGM,
ArabicBonusBGM,
EgyptBonusBGM,
FutureBonusBGM,
LostCityBGM,
PolarBGM,
RiverBonusBGM,
RuinsBonusBGM,
SewerBonusBGM,
SnowBonusBGM,
RoadToRuinBGM,
NGinBGM,
Arabia01BGM,
Arabia02BGM,
BashBGM,
Cortex02BGM
};
// v0.95
enum BGMV3 : BGMV2 {
None,
N_TropyBGM,
CrashCreatorBGM,
MainMenuBGM,
WarpRoomBGM,
Jungle01BGM,
SnowBGM,
RiverBGM,
FutureBGM,
LabBGM,
SewerBGM,
EgyptBGM,
NBrioBGM,
AdventureBGM,
SpyBGM,
ChaseBGM,
TrialsBGM,
SpaceBGM,
Jungle02BGM,
RipperBGM,
TheGreatWallBGM,
RoadToSomewhereBGM,
LavaKoalaBGM,
CortexBGM,
CyberCortexBGM,
ArabicBGM,
N_Tropy2BGM,
JazzBGM,
Space2BGM,
TawnaBonusBGM,
CortexPowerBGM,
ArabicBonusBGM,
EgyptBonusBGM,
FutureBonusBGM,
LostCityBGM,
PolarBGM,
RiverBonusBGM,
RuinsBonusBGM,
SewerBonusBGM,
SnowBonusBGM,
RoadToRuinBGM,
NGinBGM,
Arabia01BGM,
Arabia02BGM,
BashBGM,
Cortex02BGM,
MedievalBGM,
PreHistoricBGM,
UnderWaterBGM,
BrioRevisitedBGM,
EgyptChaseBGM,
RuinsLoopBGM,
DingoSynthBGM
};
enum Type : u32 {
Unset,
Flashback,
Trial
};
enum TypeV2 : u32 {
Practice,
Flashback,
Trial,
Adventure
};
enum Skybox : u32 {
Night,
Day,
Storm,
Dawn
};
enum SkyboxV2 : u32 {
Default = 1,
Briolab,
Fort,
Moon,
Toxic,
AboutRight,
Crash1Island,
Arabia,
RoadToRuin,
Black
};
// 0.95
enum SkyboxV3 : u32 {
Default = 1,
Briolab,
Fort,
Moon,
Toxic,
AboutRight,
Crash1Island,
Arabia,
RoadToRuin,
MotorcycleDay,
MotorcycleNoon,
MotorcycleMoon,
MotorcycleNight,
Black
};
enum Scenery : u32 {
None,
FutureTense,
Forest,
Waterfall,
Snow,
Fortress
};
enum SceneryV2 : u32 {
None,
FutureTense,
Forest,
Waterfall,
None2,
Fortress,
None3,
Lava,
TheGreatGate,
Mountain,
KoalaKong,
SunsetVista,
HangemHigh,
Sphynxinator,
Tunnel,
Pipes
};
enum SceneryV4 : u32 {
None,
FutureTense,
Forest,
Waterfall,
Snow,
Fortress,
None2,
Lava,
TheGreatGate,
Mountain,
KoalaKong,
SunsetVista,
HangemHigh,
Sphynxinator,
Tunnel,
Pipes
};
// 0.95
enum SceneryV5 : u32 {
None,
FutureTense,
Forest,
Waterfall,
Snow,
Fortress,
None2,
Lava,
TheGreatGate,
Mountain,
KoalaKong,
SunsetVista,
HangemHigh,
Sphynxinator,
Tunnel,
Pipes,
Medieval,
FutureCity,
TinyArena,
HeavyMachinery,
CrystalCave,
MedievalWithHouses,
CortexBonusChamber
};
enum Weather : u32 {
Default,
Snow,
Rain
};
// 0.95
enum WeatherV2 : u32 {
Default,
Snow,
Rain,
Night,
UnderWater
};
struct Options {
// Type
if (header.version > 1) {
TypeV2 type;
}
else {
Type type;
}
// Skybox
if (header.version > 1) {
if (header.gameVersion == "0.95") {
SkyboxV3 skybox;
}
else {
SkyboxV2 skybox;
}
}
else {
Skybox skybox;
}
// Scenery
if (header.version == 1) {
Scenery scenery;
}
else if (header.version > 1 && header.version < 4) {
SceneryV2 scenery;
}
else {
if (header.gameVersion == "0.95") {
SceneryV5 skybox;
}
else {
SceneryV4 skybox;
}
}
// Weather
if (header.version > 2) {
if (header.gameVersion == "0.95") {
WeatherV2 weather;
}
else {
Weather weather;
}
}
// Background music
if (header.version > 1) {
BGMV2 bgm;
}
else {
BGM bgm;
}
// Time Trial
if (type == Type::Trial) {
u32 timeTrialTicksBronze;
u32 timeTrialTicksSilver;
u32 timeTrialTicksGold;
}
};
struct Object {
std::string::SizedString<u8> objName;
if (header.version > 1) {
u16 x;
u16 y;
bool hasMetafields;
if (hasMetafields) {
u16 numOfMetafields;
u8 metafields[numOfMetafields];
}
}
else {
u32 x;
u32 y;
}
};
struct Objects{
u32 objCount;
std::Array<Object, objCount> objArray;
};
Header header @ $;
Options options @ $;
Objects objects @ $;

View File

@@ -0,0 +1,81 @@
ImHex Pattern Files - Digital Forensics:
- [ImHex-DFIR-Patterns](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns)
Enhanced features of the stock Disk/Filesystem pattern files for forensic review of disk content.
- [ImHex](https://github.com/WerWolv/ImHex)
- [ImHex Patterns](https://github.com/WerWolv/ImHex-Patterns)
Use:
- Open a physical disk via Raw Provider (read-only)
- EXAMPLE: /dev/disk6
- Import Pattern File
- EXAMPLE: DISK_PARSER.hexpat
- [Pattern_Selection (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/2-DISK_PARSER-Pattern.png)
- DISK_PARSER.hexpat
- Recognize MBR/GPT Disks and parse MPT/GPT
- Including Logical Volumes in an Extended Partition (container)
- Auto load file system patterns for FAT32, exFAT, NTFS formatted volumes
- Optional Disk Report
- [DISK > MBR/GPT (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/3-DISK-HYBRID.png)
- [DISK > MBR > MPT > 3 Primaries | 2 Logicals in an Extended (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/3a-DISK-MBR.png)
- FAT32.hexpat
- Auto loaded by DISK_PARSER.hexpat
- Parse VBR, FAT1, FAT2, Root Dir, and 1 level of SubDirs
- FAT1/FAT2 Cluster chaining with SFN resolution
- LFN/SFN Alias grouping in Root Dir
- Recognize deleted entries (xE5)
- File Content pointer
- D/T Conversions
- Optional FAT32 Volume Report
- [VOLUME > FAT32 > FAT1 (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/4-FAT32-1_SMALL_TXT.png)
- [VOLUME > FAT32 > Root Dir (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/5-FAT32_ROOT_DIR.png)
- [VOLUME > FAT32 > Data Pointer (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/6-FAT32_SFN_POINTER.png)
- exFAT.hexpat
- Auto loaded by DISK_PARSER.hexpat
- Parse VBR/Boot Sector/Extended Sectors, FAT1, Root Dir
- Recognize active directory entries (x85, xC0, xC1)
- Recognize inactive directory entries (x05, x40, x41)
- xC0/x40 File Content pointer
- D/T Conversions
- Optional exFAT Volume Report
- [VOLUME > exFAT (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/7-exFAT-1.png)
- [VOLUME > exFAT > Root Dir > xC0 (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/8-exFAT_xC0.png)
- [VOLUME > exFAT > Data Pointer (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/9-exFAT-Data_Pointer.png)
- NTFS.hexpat
- Auto loaded by DISK_PARSER.hexpat
- Parse VBR (Boot Sector), $MFT, Root Dir, and Indexes
- Recursively parse the $Metadata files, $Attributes, and user files/dirs
- Added file record | parent [MFT#] [SEQ#] indicators
- Parse x80/xB0 Data Runs
- File Content pointer
- D/T Conversions
- Optional NTFS Volume Report
- [VOLUME > NTFS > $MFT > D/T Conversion (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/10-NTFS-DT.png)
- [VOLUME > NTFS > $MFT > x80 Run List (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/11-NTFS-DATA_RUN.png)
- [VOLUME > NTFS > Data Pointer (screenshot)](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/screenshots/12-NTFS-DATA_POINTER.png)
- Optional Reports
- Simply copy the console output to a file...
- To enable/disable the reports:
- Open each DFIR related .hexpat
- Find the report constant (near the top)
- "true" = enabled
- "false" = disabled
Example Report: GPT > FAT32|exFAT
- [exFAT_Report](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/reports/exFAT_Report.txt)
Example Report: MBR > 5 Logical Volumes (2 in an Extended) > All FAT32 Volumes
- [MBR_5_VOLs](https://github.com/Xtreme-Liberty/ImHex-DFIR-Patterns/blob/main/reports/MBR_5_VOLs.txt)

View File

@@ -0,0 +1,677 @@
#pragma author Formula Zero One Technologies
#pragma description DFIR_DISK_PARSER_v2.0
#pragma MIME application/x-ima
#pragma endian little
// -----------------------------------------------------------------------------
// CREDIT
// -----------------------------------------------------------------------------
// Based on /fs/pattern.hexpat by WerWolv
// -----------------------------------------------------------------------------
// TODO
// -----------------------------------------------------------------------------
// Refine File System Detection/Match
// -----------------------------------------------------------------------------
// IMPORTS
// -----------------------------------------------------------------------------
import std.core;
import std.io;
import std.time;
import type.guid;
import type.magic;
import type.time;
import type.base;
import hex.provider;
// WORKING IMPORTS
import * from DFIR.FAT32 as FAT32Pat;
import * from DFIR.exFAT as EXFATPat;
import * from DFIR.NTFS as NTFSPat;
// ------------------------------------
// DISABLED IMPORTS
// REFS - UNTESTED
// EXT4 - GROUP DESC ERRORS
// APFS - PARTIALLY WORKS
// Comment out "using uuid_t = type::GUID"
// Replace all instances of "uuid_t" with "type::GUID"
// Comment out line 1456-EOF
// JPEG/PNG - OFFSET ERRORS
// ------------------------------------
//import * from fs.apfs as APFSPat;
//import * from fs.ext4 as EXT4Pat;
//import * from fs.refs as REFSPat;
//import * from jpeg as JPEGPat;
//import * from png as PNGPat;
// -----------------------------------------------------------------------------
// FWD DECs - GLOBAL
// -----------------------------------------------------------------------------
bool has_ext = false;
bool has_gpt = false;
u64 partitionOffset = 0;
u64 containerStartOffset = 0;
u32 mptIndex = 0;
u32 extIndex = 0;
str entryName = "";
u32 MPT_Count = 0;
u32 EXT_VolCount = 0;
u32 GPT_Count = 0;
u32 memory_size = std::mem::size();
str disk_path = hex::prv::get_information("file_path","");
u128 sector_size = hex::prv::get_information("sector_size","");
// -----------------------------------------------------------------------------
// REPORT HEADER ** ATTENTION **
// -----------------------------------------------------------------------------
// ---******---*******---vvvv--- |
const bool DISK_REPORT = true;
// ---******---*******---^^^^--- |
if (DISK_REPORT) {
std::print(" # # # # # # ");
std::print(" # # # ");
std::print(" # # # ");
std::print(" # # # # # # # ");
std::print(" I m H e x ");
std::print(" ");
std::print("-----------------------------------------");
std::print(" ");
std::print(" ENTITY: _____________________");
std::print(" ");
std::print("EXAMINER: _____________________");
std::print(" ");
u128 timestamp = std::time::epoch();
std::time::Time local_ts = std::time::to_local(timestamp);
std::time::Time utc_ts = std::time::to_utc(timestamp);
std::print("-----------------------------------------");
std::print(" LOCAL: {}",
std::format("{:02}/{:02}/{:04} @ {:02}:{:02}:{:02}",
local_ts.mon + 1,
local_ts.mday,
local_ts.year + 1900,
local_ts.hour,
local_ts.min,
local_ts.sec
));
std::print(" UTC: {}",
std::format("{:02}/{:02}/{:04} @ {:02}:{:02}:{:02}",
utc_ts.mon + 1,
utc_ts.mday,
utc_ts.year + 1900,
utc_ts.hour,
utc_ts.min,
utc_ts.sec
));
std::print("-----------------------------------------");
std::print(" ");
}
// -----------------------------------------------------------------------------
// SIGNATURE HELPER
// -----------------------------------------------------------------------------
enum MBRSignature : u16 {
MBR_SIG = 0xAA55 // 0x55AA -> Read LE
};
// -----------------------------------------------------------------------------
// CHS HELPER
// -----------------------------------------------------------------------------
bitfield CHS_Decoder {
head : 8;
sector : 6;
cylinder : 10;
} [[format("chs_formatter")]];
fn chs_formatter(CHS_Decoder CHS) {
return std::format("({:X}, {:X}, {:X}) | 0x{:X}", CHS.cylinder, CHS.head, CHS.sector, (CHS.cylinder * 16 + CHS.head) * 63 + (CHS.sector - 1));
};
// -----------------------------------------------------------------------------
// TIMESTAMP HELPER
// -----------------------------------------------------------------------------
struct DiskTimeStamp {
u8 seconds, minutes, hours;
};
// -----------------------------------------------------------------------------
// DISK PROTECTION HELPER
// -----------------------------------------------------------------------------
enum DiskProtection : u16 {
NotProtected = 0x0000,
CopyProtected = 0x5A5A
};
// -----------------------------------------------------------------------------
// PARTITION STATUS HELPER
// -----------------------------------------------------------------------------
enum PartitionStatus : u8 {
Not_Active = 0x00, // not_bootable
Active = 0x80 // bootable
};
enum MPTPartLabel : u8 {
UNUSED_OR_HIDDEN_ENTRY = 0x00,
PRIMARY = 0x07,
PRIMARY_F32_SMALL = 0x0B,
PRIMARY_0C_BIG = 0x0C,
EXTENDED_CONT_SMALL = 0x05,
EXTENDED_CONT_BIG = 0x0F,
LEGACY_MBR = 0xEE
};
// -----------------------------------------------------------------------------
// PARTITION TYPE HELPER
// -----------------------------------------------------------------------------
enum PartitionTypeCode : u8 {
UNUSED_ENTRY = 0x00,
FAT12_HDD = 0x01,
FAT12_HIDDEN = 0x11,
FAT16_SMALL = 0x04,
FAT16_SMALL_HIDDEN = 0x14,
FAT16_BIG = 0x06,
FAT16_BIG_HIDDEN = 0x16,
FAT32_SMALL = 0x0B,
FAT32_SMALL_HIDDEN = 0x1B,
FAT32_BIG = 0x0C,
FAT32_BIG_HIDDEN = 0x1C,
EXT_PART_SMALL = 0x05,
EXT_PART_SMALL_HIDDEN = 0x15,
EXT_PART_BIG = 0x0F,
EXT_PART_BIG_HIDDEN = 0x1F,
NTFS_EXFAT = 0x07,
NTFS_EXFAT_HIDDEN = 0x17,
WINDOWS_RECOVERY = 0x27,
NTFS_VOL_SET_1 = 0x86,
NTFS_VOL_SET_2 = 0x87,
macOSX = 0xA8,
OS2_HIDDEN_CDRIVE = 0x84,
LINUX_EXT = 0x83,
LINUX_EXT2 = 0x85,
LINUX_LVM = 0x8E,
LINUX_PA_RISC = 0xF0,
LINUX_RAID = 0xFD,
FREE_BSD = 0xA5,
OPEN_BSD = 0xA6,
QNX_1 = 0x4D,
QNX_2 = 0x4E,
QNX_3 = 0x4F,
GPT_DISK_STD = 0xEE,
GPT_DISK_SYS = 0xEF,
UNKNOWN = 0xFF,
};
// -----------------------------------------------------------------------------
// GUID PARTITION TABLE (GPT) PARTIONING SCHEME RELATED
// -----------------------------------------------------------------------------
// V V V V V V V V V V
// -----------------------------------------------------------------------------
// GPT PARTITION LABEL HELPER
// -----------------------------------------------------------------------------
enum GUIDPartLabel : u128 {
// ---------------- COMMON ----------------
UNUSED_ENTRY = 0x00000000000000000000000000000000,
EFI_SYSTEM_PART = 0x3BC93EC9A0004BBA11D2F81FC12A7328,
APPLE_APFS_CONT = 0xACEC4365300011AA11AA00007C3457EF,
APPLE_HFS_PLUS_PART = 0xACEC4365300011AA11AA000048465300,
MICROSOFT_RESERVED_PART = 0xAE1502F92DF97D81B84D5C0BE3E3C9E3,
WINDOWS_REC_ENVIRONMENT = 0xACD67901D5BF6AA1404DD106A4BB94DE,
BASIC_DATA_PART = 0xC79926B7B668C0874433B9E5EBD0A0A2,
// ---------------- LINUX ----------------
LINUX_FILE_SYSTEM = 0xE47D47D8693D798E477284830FC63DAF,
RAID_PART = 0x1E91840F3F7406A04D3B05FCA19D880F,
ROOT_PART_X86 = 0x8A45F0D531D1F79A41B2F29744479540,
ROOT_PART_X86_64 = 0x09B784F9CAFBE7964DB1E8CD4F68BCE3,
ROOT_PART_ARM = 0xD3BE9AD4A1216CB14E3C2CE469DAD710,
ROOT_PART_ARM_64 = 0xAE3F0D286F4C44AF41C31DF0B921B045,
BOOT_PART = 0x72716FFD75B252A3426259E6BC13C2FF,
SWAP_PART = 0x4F4F4BC83309E58443C4A4AB0657FD6D,
LOGICAL_VOLUME_MGR_PART = 0x28F93D2A8F233CA244C2F507E6D6D379,
HOME_PART = 0x15F9AEE2140E44B84F132EB4933AC7E1,
SRV_SERVER_DATA_PART = 0xE8986FA7251A7F904F3B20E03B8F8425,
PLAIN_DMCRYPT_PART = 0xB786550AA13E418949B72D007FFEC5C9,
LUKS_PART = 0xCC59605342171C864C5363EDCA7D7CCB,
// ---------------- APPLE ----------------
APPLE_UFS_CONT = 0xACEC4365300011AA11AA000055465300,
APPLE_ZFS = 0x316673200008A69911B21DD26A898CC3,
APPLE_RAID_PART = 0xACEC4365300011AA11AA000052414944,
APPLE_RAID_PART_OFFLINE = 0xACEC4365300011AA11AA5F4F52414944,
APPLE_BOOT_PART_REC_HD = 0xACEC4365300011AA11AA0000426F6F74,
APPLE_LABEL = 0xACEC4365300011AA11AA6C004C616265,
APPLE_TV_RECOVERY_PART = 0xACEC4365300011AA11AA76655265636F,
APPLE_CORE_STORAGE_CONT = 0xACEC4365300011AA11AA616753746F72,
HFS_FILEVAULT_VOLUME_CONT = 0xACEC4365300011AA11AA616753746F72,
APPLE_APFS_PREBOOT_PART = 0xACEC4365300011AA11AA006769646961,
APPLE_APFS_RECOVERY_PART = 0xACEC4365300011AA11AA007972637652,
// ---------------- WINDOWS ----------------
LOGICAL_DISK_MGR_META_PART = 0xB3CF34E104E1D28542E08F7EAAC80858,
LOGICAL_DISK_MGR_DATA_PART = 0xAD694A71113368BC4F621431A0609BAF,
IBM_GENERAL_PARALLEL_FILE_SYS_PART = 0x74B155E07A2DC3914E4EEF7D90FFAA37,
STORAGE_SPACES_PART = 0x2DECF6E501B0A3AFEE4CF6808FAF5CE7,
STORAGE_REPLICA_PART = 0xD123292BD147C8AAC043A1ACC58D4355,
};
// -----------------------------------------------------------------------------
// BASIC DATA PARTITION ATTRIBUTES
// -----------------------------------------------------------------------------
bitfield GPT_BDP_Attributes {
bool platform_required : 1 [[comment("Bit 0: RequiredPartition - Volume must be preserved")]];
bool io_ignore : 1 [[comment("Bit 1: NoBlockIOProtocol - EFI ignores this Volume, no FS Mapping")]];
bool legacy_flag : 1 [[comment("Bit 2: LegacyBIOSBootable - Active/Bootable under BIOS")]];
reserved_UEFI : 45 [[comment("Bits 347: Reserved for UEFI")]];
reserved_MS : 12 [[comment("Bits 4859: Reserved for Microsoft")]];
bool read_only : 1 [[comment("Bit 60: BasicDataPart - Read-Only Volume")]];
bool shadow_copy : 1 [[comment("Bit 61: BasicDataPart - Shadow Copy Volume")]];
bool hidden : 1 [[comment("Bit 62: BasicDataPart - Hidden Volume")]];
bool no_drive_letter : 1 [[comment("Bit 63: BasicDataPart - Do not Auto-Assign Drive Letter")]];
} [[bitfield_order(
std::core::BitfieldOrder::LeastToMostSignificant, 64)]];
// -----------------------------------------------------------------------------
// GPT ENTRIES PARSER
// LBA2-LBA33
// EACH ENTRY IS 128 BYTES (DESCRIBES A VOLUME)
// -----------------------------------------------------------------------------
union PartitionUnion {
le type::GUID PartTypeGUID; // HUMAN READABLE GUID
GUIDPartLabel PartTypeLabel [[name(std::format("PartTypeLabel (DERIVED)"))]]; // OBJECT LABEL
};
struct GPT_PartitionEntry {
PartitionUnion Type [[comment("Known Partition Type GUID: Global Identifier")]];
le type::GUID Unique_GUID [[comment("Unique Partition GUID: Every Volume has its own Unique GUID")]];
u64 Start_LBA [[comment("The first Sector of the Volume (Offset by 1)")]];
u64 End_LBA [[comment("The last Sector of the Volume (Offset by 1)")]];
GPT_BDP_Attributes ATTR [[comment("ATTRs for a Basic Data Partition may not be the same as a Microsoft Reserved Partition")]];
char16 PartName[36] [[comment("Partition Name: Based on Known Partition Type GUID, except for Disk Images")]];
if (Type.PartTypeLabel != GUIDPartLabel::UNUSED_ENTRY) {
GPT_Count += 1;
}
u64 GPTpartitionOffset = Start_LBA * sector_size
[[name(std::format("VOL_OFFSET {} | 0x{:02X} (DERIVED)", Start_LBA * sector_size, Start_LBA * sector_size)),
export]];
match (Type.PartTypeLabel) {
(GUIDPartLabel::UNUSED_ENTRY):
continue;
(GUIDPartLabel::EFI_SYSTEM_PART):
FAT32Pat EFI_SYS_VOL @ GPTpartitionOffset;
(GUIDPartLabel::BASIC_DATA_PART |
GUIDPartLabel::WINDOWS_REC_ENVIRONMENT): {
char gpt_fat32_magic[8] @ GPTpartitionOffset + 82 [[hidden]];
char gpt_ntfs_magic[8] @ GPTpartitionOffset + 3 [[hidden]];
char gpt_exfat_magic[8] @ GPTpartitionOffset + 3 [[hidden]];
if (gpt_fat32_magic == "FAT32 ")
FAT32Pat FAT32_VOL @ GPTpartitionOffset;
if (gpt_ntfs_magic == "NTFS ")
NTFSPat NTFS_VOL @ GPTpartitionOffset;
else if (gpt_exfat_magic == "EXFAT ")
EXFATPat EXFAT_VOL @ GPTpartitionOffset;
}
// --------- DISABLED -----------------
// EXT4 PATTERN WAS INOP WHEN TESTED
//(GUIDPartLabel::LINUX_FILE_SYSTEM):
//EXT4Pat EXT4_VOL @ GPTpartitionOffset;
//(GUIDPartLabel::APPLE_APFS_CONT):
// APFSPat APFS_VOL @ GPTpartitionOffset;
}
} [[name(std::format("GPT_ENTRY [{}]", std::core::array_index()))]];
// -----------------------------------------------------------------------------
// GPT HEADER PARSER
// LBA1 OFFSETS 0-91 (92 bytes of 512 bytes used)
// -----------------------------------------------------------------------------
struct GPT_Header {
type::Magic<"EFI PART"> signature [[comment("Signature (EFI PART)")]];
u32 revision [[comment("Header Revision Value")]];
u32 header_size [[comment("Size of Header - 92 Bytes")]];
type::Hex<u32> header_crc32 [[comment("GPT Header Checksum")]];
u32 reserved [[comment("Zeros")]];
u64 current_lba [[comment("Current LBA - GPT Header Location")]];
u64 backup_lba [[comment("Location of Backup - Header & GPT")]];
u64 first_usable_lba [[comment("1st Sector Available for Logical VOL")]];
u64 last_usable_lba [[comment("Last Sector Available for Logical VOL")]];
type::GUID disk_guid [[comment("Unique Disk GUID")]];
u64 partition_entries_lba [[comment("1st Sector of GPT")]];
u32 num_partition_entries [[comment("Total Number of Partition Entries Available - 128 on Windows")]];
u32 size_of_partition_entry [[comment("Size in Bytes of each GPT Entry")]];
type::Hex<u32> partition_entries_crc32 [[comment("GPT Array Checksum")]];
};
// -----------------------------------------------------------------------------
// MASTER BOOT RECORD (MBR) PARTIONING SCHEME RELATED
// -----------------------------------------------------------------------------
// V V V V V V V V V V
// -----------------------------------------------------------------------------
// MASTER PARTITION TABLE (MPT)
// LBA0 > 0FFSETS 446-509
// Each Entry Describes a Logical Volume (type/start_loc/size)
// -----------------------------------------------------------------------------
union MBRPartitionUnion {
PartitionTypeCode Part_Type;
MPTPartLabel PartTypeLabel; // overlay for 0x00
};
struct PartitionTableEntry {
// partition table fields
PartitionStatus ActiveFlag;
CHS_Decoder Starting_CHS;
MBRPartitionUnion Type;
CHS_Decoder Ending_CHS;
u32 Start_LBA;
u32 Total_Sectors;
if (Type.PartTypeLabel != MPTPartLabel::UNUSED_OR_HIDDEN_ENTRY) {
// Track Count of Logical Volumes in the Extended Container
//MPT_Count += 1;
if (containerStartOffset == 0) {
// top-level MBR entry
MPT_Count = MPT_Count + 1;
} else {
// a logical inside an extended container
EXT_VolCount = EXT_VolCount + 1;
}
}
partitionOffset = containerStartOffset + (Start_LBA * sector_size);
match (Type.PartTypeLabel) {
(PartitionTypeCode::UNUSED_ENTRY): continue;
(PartitionTypeCode::FAT32_SMALL | PartitionTypeCode::FAT32_BIG): {
FAT32Pat FAT32_VOL @ partitionOffset;
}
(PartitionTypeCode::NTFS_EXFAT): {
char magic[8] @ partitionOffset + 3;
if (magic == "NTFS ")
NTFSPat NTFS_VOL @ partitionOffset;
else
EXFATPat EXFAT_VOL @ partitionOffset;
}
(PartitionTypeCode::EXT_PART_SMALL | PartitionTypeCode::EXT_PART_BIG): {
// Save parent state
bool parent_has_ext = has_ext;
has_ext = true;
containerStartOffset = partitionOffset;
// Parse first two entries of the extended partition
PartitionTableEntry EXTENDED_PARTITION[2] @ partitionOffset + 446;
has_ext = parent_has_ext;
}
(PartitionTypeCode::GPT_DISK_STD | PartitionTypeCode::GPT_DISK_SYS):
// Set global flag
has_gpt = true;
}
if (!has_ext) {
entryName = std::format("MPT_ENTRY [{}]", mptIndex);
mptIndex += 1;
} else {
if (std::core::array_index() <= 0) {
entryName = std::format("LOGICAL_VOL (EXT) [{}]", extIndex);
} else if (std::core::array_index() == 1) {
entryName = "NEXT VOL POINTER (EXT)";
} else {
entryName = std::format("LOGICAL_VOL (EXT) [{}]", extIndex);
}
extIndex += 1;
}
} [[name(entryName)]];
// -----------------------------------------------------------------------------
// MBR PARSER
// LBA0 > OFFSETS 0-511 (512 bytes)
// -----------------------------------------------------------------------------
struct MasterBootRecord {
u8 bootstrapCodeArea1[218] [[comment("Boot Strapping Code")]];
padding[2] [[comment("Zeros")]];
u8 originalPhysicalDrive [[comment("???")]];
DiskTimeStamp diskTimeStamp [[comment("Timestamp of Disk OG Partitioning")]];
u8 bootstrapCodeArea2[216] [[comment("Boot Strapping Code")]];
u32 diskSignature [[comment("Disk Signature")]];
DiskProtection diskProtection [[comment("Disk Protection - 0x0000=Not | 0x5A5A=Prot")]];
PartitionTableEntry PT[4] [[comment("Master Partition Table (MPT) Offset 446-509")]];
MBRSignature MBR_SIG [[comment("End of MBR - 0x55AA")]];
};
// -----------------------------------------------------------------------------
// DISK PARSER
// -----------------------------------------------------------------------------
struct DiskRoot {
// Master Boot Record at LBA 0 (1st physical sector)
MasterBootRecord MBR @ 0x00;
if (has_gpt) {
// GPT Header at LBA 1 (2nd physical sector)
GPT_Header GPT_HEADER @ 0x200;
// The GPT (table) at LBA 2 (3rd physical sector) to LBA 33 (34th physical sector)
// 32 sectors total (Windows) that can define up to 128 - (primary) logical volumes
GPT_PartitionEntry GPT_ENTRIES[GPT_HEADER.num_partition_entries] @ (GPT_HEADER.partition_entries_lba * 512);
}
};
// -----------------------------------------------------------------------------
// ROOT OBJECT
// -----------------------------------------------------------------------------
// ---
DiskRoot DISK @ 0x0;
// ---
// ------------------------------
// DISK REPORT
// ------------------------------
if (DISK_REPORT) {
std::print("-----------------------------------------");
std::print("-------------- DISK_REPORT --------------");
std::print("-----------------------------------------");
// Disk Basics
std::print("DISK_PATH = {}", disk_path);
std::print("SECTOR_SIZE = {} BYTES", sector_size);
std::print("DISK_SIZE = {} SECTORS", memory_size / sector_size);
std::print("DISK_SIZE = {:.4f} GB @ 1000", memory_size / 1000.0 / 1000.0 / 1000.0);
std::print("DISK_SIZE = {:.4f} GiB @ 1024", memory_size / 1024.0 / 1024.0 / 1024.0);
// Disk Protection
str diskProtectionStr;
if (DISK.MBR.diskProtection == DiskProtection::NotProtected) {
diskProtectionStr = "NOT_COPY_PROTECTED";
} else if (DISK.MBR.diskProtection == DiskProtection::CopyProtected) {
diskProtectionStr = "COPY_PROTECTED";
} else {
diskProtectionStr = "UNKNOWN";
}
std::print("DISK_PROTECT = {}", diskProtectionStr);
// Partition Scheme
if (MPT_Count >= 1 && GPT_Count == 0) {
std::print("PART_SCHEME = MBR");
} else if (GPT_Count >= 1 && MPT_Count == 0) {
std::print("PART_SCHEME = GPT");
} else if (GPT_Count >= 1 && MPT_Count >= 1) {
std::print("PART_SCHEME = HYBRID (MBR + GPT)");
} else {
std::print("PART_SCHEME = UNKNOWN");
}
// MBR MPT Partitions
for (u32 i = 0, i < MPT_Count, i = i + 1) {
std::print("-----------------------------------------");
std::print("-------------- MBR_MPT [{}] --------------", i);
std::print("-----------------------------------------");
// STATUS
str statusStr;
if (DISK.MBR.PT[i].ActiveFlag == PartitionStatus::Active) {
statusStr = "ACTIVE/BOOTABLE";
} else if (DISK.MBR.PT[i].ActiveFlag == PartitionStatus::Not_Active) {
statusStr = "INACTIVE/NOT_BOOTABLE";
} else {
statusStr = "UNKNOWN";
}
std::print(" STATUS = {}", statusStr);
// TYPE_CODE
str typeStr;
if (DISK.MBR.PT[i].Type.Part_Type == PartitionTypeCode::FAT32_SMALL) {
typeStr = "FAT32 (CHS) (0x0B)";
} else if (DISK.MBR.PT[i].Type.Part_Type == PartitionTypeCode::FAT32_BIG) {
typeStr = "FAT32 (LBA) (0x0C)";
} else if (DISK.MBR.PT[i].Type.Part_Type == PartitionTypeCode::NTFS_EXFAT) {
typeStr = "NTFS/EXFAT (0x07)";
} else if (DISK.MBR.PT[i].Type.Part_Type == PartitionTypeCode::GPT_DISK_STD) {
typeStr = "GPT_PROTECTIVE (0xEE)";
} else if (DISK.MBR.PT[i].Type.Part_Type == PartitionTypeCode::EXT_PART_BIG) {
typeStr = "EXTENDED (0x0F)";
} else {
typeStr = "OTHER/UNKNOWN";
}
std::print(" TYPE_CODE = {}", typeStr);
// LBA and size
std::print(" FIRST_LBA = {:02}", DISK.MBR.PT[i].Start_LBA);
std::print(" LAST_LBA = {:02}", DISK.MBR.PT[i].Start_LBA + DISK.MBR.PT[i].Total_Sectors - 1);
std::print(" VOL_SIZE = {:02} SECTORS", DISK.MBR.PT[i].Total_Sectors);
std::print(" VOL_SIZE = {:.4f} GB", (DISK.MBR.PT[i].Total_Sectors * sector_size) / 1000.0 / 1000.0 / 1000.0);
std::print(" VOL_SIZE = {:.4f} GiB", (DISK.MBR.PT[i].Total_Sectors * sector_size) / 1024.0 / 1024.0 / 1024.0);
if (DISK.MBR.PT[i].Type.PartTypeLabel == MPTPartLabel::EXTENDED_CONT_SMALL ||
DISK.MBR.PT[i].Type.PartTypeLabel == MPTPartLabel::EXTENDED_CONT_BIG) {
u32 logicalCount = std::core::member_count(DISK.MBR.PT[i].EXTENDED_PARTITION);
//u32 logicalCount = std::mem::size(DISK.MBR.PT[i].EXTENDED_PARTITION);
for (u32 e = 0, e < logicalCount, e = e + 1) {
if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].Type.PartTypeLabel == MPTPartLabel::UNUSED_OR_HIDDEN_ENTRY)
continue;
std::print("-----------------------------------------");
std::print("---------- LOGICAL (EXT) [{}] ------------", e);
std::print("-----------------------------------------");
// STATUS
str EXTstatusStr;
if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].ActiveFlag == PartitionStatus::Active) {
EXTstatusStr = "ACTIVE/BOOTABLE";
} else if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].ActiveFlag == PartitionStatus::Not_Active) {
EXTstatusStr = "INACTIVE/NOT_BOOTABLE";
} else {
EXTstatusStr = "UNKNOWN";
}
std::print(" STATUS = {}", EXTstatusStr);
// TYPE_CODE
str EXTtypeStr;
if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].Type.Part_Type == PartitionTypeCode::FAT32_SMALL) {
EXTtypeStr = "FAT32 (CHS) (0x0B)";
} else if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].Type.Part_Type == PartitionTypeCode::FAT32_BIG) {
EXTtypeStr = "FAT32 (LBA) (0x0C)";
} else if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].Type.Part_Type == PartitionTypeCode::NTFS_EXFAT) {
EXTtypeStr = "NTFS/EXFAT (0x07)";
} else if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].Type.Part_Type == PartitionTypeCode::GPT_DISK_STD) {
EXTtypeStr = "GPT_PROTECTIVE (0xEE)";
} else if (DISK.MBR.PT[i].EXTENDED_PARTITION[e].Type.Part_Type == PartitionTypeCode::EXT_PART_BIG) {
EXTtypeStr = "EXTENDED (0x0F)";
} else {
EXTtypeStr = "OTHER/UNKNOWN";
}
std::print(" TYPE_CODE = {}", EXTtypeStr);
std::print(" FIRST_LBA = {}", DISK.MBR.PT[i].EXTENDED_PARTITION[e].Start_LBA);
std::print(" LAST_LBA = {}", DISK.MBR.PT[i].EXTENDED_PARTITION[e].Start_LBA +
DISK.MBR.PT[i].EXTENDED_PARTITION[e].Total_Sectors - 1);
std::print(" VOL_SIZE = {} SECTORS", DISK.MBR.PT[i].EXTENDED_PARTITION[e].Total_Sectors);
std::print(" VOL_SIZE = {:.4f} GB",
(DISK.MBR.PT[i].EXTENDED_PARTITION[e].Total_Sectors * sector_size) / 1000.0 / 1000.0 / 1000.0);
std::print(" VOL_SIZE = {:.4f} GiB",
(DISK.MBR.PT[i].EXTENDED_PARTITION[e].Total_Sectors * sector_size) / 1024.0 / 1024.0 / 1024.0);
}
}
}
// GPT Header
if (GPT_Count >= 1) {
std::print("-----------------------------------------");
std::print("-------------- GPT_HEADER ---------------");
std::print("-----------------------------------------");
std::print("SIGNATURE = {}", DISK.GPT_HEADER.signature);
std::print("REVISION = 0x{:02X}", DISK.GPT_HEADER.revision);
std::print("GPT_HDR_CRC = 0x{:02X}", DISK.GPT_HEADER.header_crc32);
std::print("GPT_HDR_BACKUP_LBA = {}", DISK.GPT_HEADER.backup_lba);
std::print("DISK_GUID = {}", DISK.GPT_HEADER.disk_guid);
std::print("FIRST_USABLE_LBA = {}", DISK.GPT_HEADER.first_usable_lba);
std::print("LAST_USABLE_LBA = {}", DISK.GPT_HEADER.last_usable_lba);
std::print("MAX_GPT_ENTRIES = {:02}", DISK.GPT_HEADER.num_partition_entries);
std::print("GPT_ENTRY_SIZE = {:02} BYTES", DISK.GPT_HEADER.size_of_partition_entry);
std::print("GPT_ARRAY_CRC = 0x{:02X}", DISK.GPT_HEADER.partition_entries_crc32);
// GPT Partitions
for (u32 j = 0, j < GPT_Count, j = j + 1) {
std::print("-----------------------------------------");
std::print("------------- GPT_PART [{}] --------------", j);
std::print("-----------------------------------------");
std::print(" PART_TYPE_LABEL = {}", DISK.GPT_ENTRIES[j].Type.PartTypeLabel);
std::print(" PART_TYPE_GUID = {}", DISK.GPT_ENTRIES[j].Type.PartTypeGUID);
std::print(" UNIQUE_PART_GUID = {}", DISK.GPT_ENTRIES[j].Unique_GUID);
std::print(" FIRST_LBA = {:02}", DISK.GPT_ENTRIES[j].Start_LBA);
std::print(" LAST_LBA = {:02}", DISK.GPT_ENTRIES[j].End_LBA);
bool _any = false;
std::print(" ATTR_FLAGS |");
if(DISK.GPT_ENTRIES[j].ATTR.platform_required) {
std::print(" |- - - - > PlatformRequired");
_any = true;
}
if(DISK.GPT_ENTRIES[j].ATTR.io_ignore) {
std::print(" |- - - - > NO_FS_MAP");
_any = true;
}
if(DISK.GPT_ENTRIES[j].ATTR.legacy_flag) {
std::print(" |- - - - > LEGACY_BOOT");
_any = true;
}
if(DISK.GPT_ENTRIES[j].Type.PartTypeLabel == GUIDPartLabel::BASIC_DATA_PART) {
if(DISK.GPT_ENTRIES[j].ATTR.read_only) {
std::print(" |- - - - > READ_ONLY");
_any = true;
}
if(DISK.GPT_ENTRIES[j].ATTR.shadow_copy) {
std::print(" |- - - - > SHADOW_COPY");
_any = true;
}
if(DISK.GPT_ENTRIES[j].ATTR.hidden) {
std::print(" |- - - - > HIDDEN");
_any = true;
}
if(DISK.GPT_ENTRIES[j].ATTR.no_drive_letter) {
std::print(" |- - - - > NO_AUTO_MOUNT");
_any = true;
}
}
// if nothing was printed, say "NONE"
if (!_any) {
//std::print(" |> NONE");
std::print(" |- - - - > NONE");
}
std::print(" PART_TYPE_NAME = {}", DISK.GPT_ENTRIES[j].PartName);
}
}
std::print("-----------------------------------------");
std::print("------------------ END ------------------");
std::print("-----------------------------------------");
std::print(" ");
}

789
patterns/DFIR/FAT32.hexpat Normal file
View File

@@ -0,0 +1,789 @@
#pragma author Formula Zero One Technologies
#pragma description FAT32 File System (FAT32_v2.0)
#pragma MIME application/x-ima
#pragma endian little
// -----------------------------------------------------------------------------
// CREDIT
// -----------------------------------------------------------------------------
// OG AUTHOR: WerWolv
// OG DESC: fs/fat32.hexpat_v1.0
// -----------------------------------------------------------------------------
// NOTES FOR v2.0 ** GLOBALS NEED YOUR INPUT **
// -----------------------------------------------------------------------------
// Imported by DISK_PARSER.hexpat
// Added section separators for organization
// Added recursive parsing for Root Dir and a next level
// Added D/T conversions
// Show filenames on hover
// Added comments to DFIR fields of interest
// Changed pattern output naming/structure.
// Parse FAT1/FAT2
// Show SFN <-> Starting Cluster Relation Overlay
// -----------------------------------------------------------------------------
// TODO
// -----------------------------------------------------------------------------
// Parse all SFN/LFN entries, not just Root + 1
// -----------------------------------------------------------------------------
// IMPORTS
// -----------------------------------------------------------------------------
import std.core;
import std.io;
import std.mem;
import std.time;
import std.string;
import type.time;
// -----------------------------------------------------------------------------
// FORWARD DECS/GLOBALS
// -----------------------------------------------------------------------------
// *** ATTENTION ***
// SET MAXIMUM NUMBER OF 4 BYTE CHUNKS TO PARSE FROM FAT1
// DEFAULT IS 4096
// Choose a value greater than 1 and less than 65536 OR increase the Array size limit with "#define... "
// -------**************---vvvv--- |
const u64 MAX_FAT_CHUNKS = 4096;
// -------**************---^^^^--- |
// *** ATTENTION ***
// SET MAXIMUM NUMBER OF SFN = STARTING CLUSTER TO PROCESS
// DEFAULT IS 100 (2 LEVELS DEEP | ROOT DIR + 1)
// Choose a value greater than 1 and less than 65536 OR increase the Array size limit with "#define... "
// ---**************---************---vvv--- |
const u64 MAX_SFN_CLUSTER_RELATIONS = 100;
// ---**************---************---^^^--- |
// ---*******---*******----vvvv--- |
const bool VOLUME_REPORT = true;
// ---*******---*******----^^^^--- |
u64 bytesPerCluster = 0;
u64 rootDirSectors = 0;
u64 firstDataSector = 0;
u64 dataRegionStart = 0;
u64 sfn_count = 0;
u64 sfn_del_count = 0;
u64 lfn_count = 0;
u64 lfn_del_count = 0;
u64 start_index = 0;
u64 root_dir_start = 0;
u64 allocated_file_count = 0;
u64 VBR_OFFSET = 0;
u64 FAT1_start_offset = 0;
u64 FAT2_start_offset = 0;
u64 FAT_ClusterHeap_Count = 0;
u64 abs_FAT1_start_offset = 0;
u64 abs_FAT2_start_offset = 0;
u64 abs_rootDirStart_offset = 0;
// -----------------------------------------------------------------------------
// FILE ALLOCATION TABLE RELATED
// -----------------------------------------------------------------------------
// V V V V V V V V V V
// -----------------------------------------------------------------------------
// ------------------------------
// SFN <-> CLUSTER OVERLAY
// ------------------------------
struct INFO_Overlay {
u64 index = std::core::array_index();
u64 start_location = FAT1_start_offset + 8 + (index * 4);
u32 current_cluster = 2 + index;
str filename = overlay_func_name(current_cluster);
if (filename != "") {
char hover_label[4] @ start_location [[
name(std::format(
"SFN: {} | CLUSTER {}",
filename,
current_cluster
))]];
}
} [[inline]];
fn overlay_func_name(u32 cluster_num) {
str fname = "";
str ext = "";
str combo = "";
// Loop through all ROOT_DIR_ENTRIES
for (u32 i = 0, i < std::core::member_count(ROOT_DIR_ENTRIES), i = i + 1) {
// Check SFN_ALIAS and SFN_ENTRY in root entries
if (std::core::has_member(ROOT_DIR_ENTRIES[i], "SFN_ALIAS")) {
if (ROOT_DIR_ENTRIES[i].SFN_ALIAS.first_cluster == cluster_num) {
combo = std::format("{}.{}",
ROOT_DIR_ENTRIES[i].SFN_ALIAS.fileName,
ROOT_DIR_ENTRIES[i].SFN_ALIAS.extension);
return combo;
}
} else if (std::core::has_member(ROOT_DIR_ENTRIES[i], "SFN_ENTRY")) {
if (ROOT_DIR_ENTRIES[i].SFN_ENTRY.first_cluster == cluster_num) {
combo = std::format("{}.{}",
ROOT_DIR_ENTRIES[i].SFN_ENTRY.fileName,
ROOT_DIR_ENTRIES[i].SFN_ENTRY.extension);
return combo;
}
}
// Loop through all SUB_DIR_INDEX arrays for this root entry
if (std::core::has_member(ROOT_DIR_ENTRIES[i], "SUB_DIR_INDEX")) {
for (u32 j = 0, j < std::core::member_count(ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX), j = j + 1) {
if (std::core::has_member(ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j], "SFN_ALIAS")) {
if (ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j].SFN_ALIAS.first_cluster == cluster_num) {
combo = std::format("{}.{}",
ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j].SFN_ALIAS.fileName,
ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j].SFN_ALIAS.extension);
return combo;
}
} else if (std::core::has_member(ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j], "SFN_ENTRY")) {
if (ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j].SFN_ENTRY.first_cluster == cluster_num) {
combo = std::format("{}.{}",
ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j].SFN_ENTRY.fileName,
ROOT_DIR_ENTRIES[i].SUB_DIR_INDEX[j].SFN_ENTRY.extension);
return combo;
}
}
}
}
}
return ""; // no match found
};
// -----------------------------------------------------------------------------
// FAT32 FILE ALLOCATION TABLE (FAT) PARSER
// -----------------------------------------------------------------------------
const u32 CLUSTER_SIZE_BYTES = 4; // Each FAT32 entry = 4 bytes
const u32 FAT32_EOF = 0x0FFFFFFF; // End-of-file marker
const u32 FAT32_BAD = 0x0FFFFFF7; // Bad cluster marker
const u32 FIRST_ALLOC_CLUSTER = 2; // First usable cluster after reserved
enum FAT_Flags : u32 {
UNALLOCATED = 0x00000000,
END_OF_FILE = 0x0FFFFFFF, // L.END
BAD_CLUSTER = 0xFFFFFFF7, // L.END
//POINTER = Num >= 1 // INFO
};
union FAT_Union {
u32 DECIMAL [[hidden]];
FAT_Flags FAT_FLAG;
};
// ------------------------------
// Helper function for pointer label
// ------------------------------
fn cluster_label(u32 val) {
if (val == FAT_Flags::UNALLOCATED)
return "UNALLOCATED";
if (val == FAT_Flags::BAD_CLUSTER)
return "BAD";
if (val >= 0x0FFFFFF8)
return "EOF";
return std::format("{}", val);
};
// ------------------------------
// FAT1/FAT2 HEAPS/CHAINS
// ------------------------------
struct FAT_Entry {
FAT_Union FAT [[inline]];
u32 cluster_num = (FIRST_ALLOC_CLUSTER) + (std::core::array_index());
u32 next_cluster = FAT.DECIMAL & 0x0FFFFFFF;
char hover_label[4] @ $ - 4 [[
name(std::format(
"Cluster: {} → {}",
cluster_num,
cluster_label(next_cluster)
))
]];
bool is_eof = next_cluster >= 0x0FFFFFF8;
bool is_bad = next_cluster == FAT32_BAD;
bool is_free = next_cluster == 0;
if (is_eof) {
allocated_file_count += 1;
}
} [[name(format_fat_entry(FAT.DECIMAL, std::core::array_index(), FIRST_ALLOC_CLUSTER))]];
// ------------------------------
// FAT FORMATTER FUNC
// ------------------------------
fn format_fat_entry(u32 raw_value, u32 cluster_index, u32 first_alloc_cluster) {
u32 next_cluster = raw_value & 0x0FFFFFFF;
str next_label;
if (next_cluster == 0)
next_label = "UNALLOCATED";
else if (next_cluster == FAT32_BAD)
next_label = "BAD";
else if (next_cluster == 0x0FFFFFFF)
next_label = "EOF";
else
next_label = std::format("{}", next_cluster);
u32 logical_cluster = first_alloc_cluster + cluster_index;
if (next_label == "UNALLOCATED" || next_label == "BAD" || next_label == "EOF")
return std::format("Cluster {}: {}", logical_cluster, next_label);
else
return std::format("Cluster {} → {}", logical_cluster, next_label);
};
// ------------------------------
// MEDIA DESCRIPTOR HELPER
// ------------------------------
enum Media_Descriptor : u8 {
SINGLE_SIDE_FLOPPY = 0xF0,
DOUBLE_SIDE_FLOPPY = 0xF9,
HARD_DISK_DRIVE = 0xF8,
};
// ------------------------------
// FAT1/FAT2 HEADER PARSER
// ------------------------------
struct FAT_Header {
Media_Descriptor mediaDescriptor [[comment("0xF8=FIXED DISK | 0xF0=REMOVABLE")]];;
u8 FAT32_FAT_HEADER[7] [[comment("8 BYTES TOTAL: 4 BYTES REPRESENT PSUEDO CLUSTER 0 (SYSTEM) | 4 BYTES REPRESENT PSUEDO CLUSTER 1 (SYSTEM)(EOF)")]];
char root_dir_label[4] @ $ [[
name(std::format(
"ROOT_DIRECTORY"
))
]];
// WHICH IS WHY THE ROOT DIRECTORY (FIRST DATA AREA ITEM) STARTS IN CLUSTER 2
};
// -----------------------------------------------------------------------------
// ROOT DIRECTORY RELATED
// -----------------------------------------------------------------------------
// V V V V V V V V V V
// -----------------------------------------------------------------------------
// ------------------------------
// ACTIVE LFN SEQUENCE NUMBER BITFIELD
// * EXCEPT DELETED ENTRIES - 0xE5 *
// ------------------------------
bitfield LFN_Sequence {
padding : 1;
IS_LAST_ENTRY : 1 [[name("IS_LAST_ENTRY: [0=NO | 1=YES] ==")]];
padding : 1;
LFN_SEQ_NUM : 5;
} [[bitfield_order(
std::core::BitfieldOrder::MostToLeastSignificant, 8)]];
// ------------------------------
// DIRECTORY ENTRY STATUS/SEQUENCE HELPERS
// ------------------------------
enum Entry_Status : u8 {
EMPTY_ENTRY = 0x00,
DOT_ENTRY = 0x2E,
DELETED_ENTRY = 0xE5,
ACTIVE_1ST_ENTRY = 0x01,
ACTIVE_2ND_ENTRY = 0x02,
ACTIVE_3RD_ENTRY = 0x03,
ACTIVE_4TH_ENTRY = 0x04,
ACTIVE_5TH_ENTRY = 0x05,
ACTIVE_6TH_ENTRY = 0x06,
ACTIVE_7TH_ENTRY = 0x07,
ACTIVE_8TH_ENTRY = 0x08,
ACTIVE_9TH_ENTRY = 0x09,
ACTIVE_10TH_ENTRY = 0x0A,
ACTIVE_11TH_ENTRY = 0x0B,
ACTIVE_12TH_ENTRY = 0x0C,
ACTIVE_13TH_ENTRY = 0x0D,
ACTIVE_14TH_ENTRY = 0x0E,
ACTIVE_15TH_ENTRY = 0x0F,
ACTIVE_16TH_ENTRY = 0x10,
ACTIVE_17TH_ENTRY = 0x11,
ACTIVE_18TH_ENTRY = 0x12,
ACTIVE_19TH_ENTRY = 0x13,
ACTIVE_20TH_ENTRY = 0x14,
ACTIVE_1ST_ENTRY_LAST = 0x41,
ACTIVE_2ND_ENTRY_LAST = 0x42,
ACTIVE_3RD_ENTRY_LAST = 0x43,
ACTIVE_4TH_ENTRY_LAST = 0x44,
ACTIVE_5TH_ENTRY_LAST = 0x45,
ACTIVE_6TH_ENTRY_LAST = 0x46,
ACTIVE_7TH_ENTRY_LAST = 0x47,
ACTIVE_8TH_ENTRY_LAST = 0x48,
ACTIVE_9TH_ENTRY_LAST = 0x49,
ACTIVE_10TH_ENTRY_LAST = 0x4A,
ACTIVE_11TH_ENTRY_LAST = 0x4B,
ACTIVE_12TH_ENTRY_LAST = 0x4C,
ACTIVE_13TH_ENTRY_LAST = 0x4D,
ACTIVE_14TH_ENTRY_LAST = 0x4E,
ACTIVE_15TH_ENTRY_LAST = 0x4F,
ACTIVE_16TH_ENTRY_LAST = 0x50,
ACTIVE_17TH_ENTRY_LAST = 0x51,
ACTIVE_18TH_ENTRY_LAST = 0x52,
ACTIVE_19TH_ENTRY_LAST = 0x53,
ACTIVE_20TH_ENTRY_LAST = 0x54,
};
// ------------------------------
// HELPER FOR LFN FIRST BYTE
// ------------------------------
union LFNEntry_FirstByte {
Entry_Status status;
LFN_Sequence seq_num;
};
// ------------------------------
// SFN ATTRIBUTE HELPER
// ------------------------------
bitfield Attributes {
readOnly : 1;
hidden : 1;
systemFile : 1;
volumeLabel : 1;
subDirectory : 1;
archive : 1;
padding : 2;
} [[bitfield_order(
std::core::BitfieldOrder::LeastToMostSignificant, 8)]];
// ------------------------------
// ROOT DIRECTORY ENTRY FUNC
// ------------------------------
fn dir_entry_marker(u64 abs_off) {
u8 first @ abs_off;
return first;
};
// ------------------------------
// ROOT DIRECTORY ENTRY FUNC
// ------------------------------
fn dir_entry_attr(u64 abs_off) {
u8 attr @ abs_off + 0x0B;
return attr;
};
// ------------------------------
// DATES AND TIMES FUNC
// ------------------------------
fn format_dos_time_field(std::time::DOSTime t) {
return std::time::format_dos_time(t, "{:02}:{:02}:{:02}");
};
fn format_dos_date_field(std::time::DOSDate d) {
return std::time::format_dos_date(d, "{1:02}-{0:02}-{2:04}");
};
// ------------------------------
// SHORT FILE NAME ALIAS PARSER
// ------------------------------
struct SFN_Entry_Alias {
char fileName[8] [[name("SFN"), comment("Short File Name (8dot3)")]];
char extension[3] [[name("EXT"), comment("File Extension (8dot3)")]];
Attributes attributes [[name("RASH ATTR"), comment("Read-Only | Archive | System | Hidden | SubDir...")]];
u8 reserved [[comment("Zeros")]];
u8 milliseconds [[comment("Add to Times for Refinement")]];
std::time::DOSTime Created_Time [[format("format_dos_time_field")]];
std::time::DOSDate Created_Date [[format("format_dos_date_field")]];
std::time::DOSDate Accessed_Date [[format("format_dos_date_field")]];
u16 Cluster_Hi [[comment("High Cluster if Needed")]];
std::time::DOSTime Modified_Time [[format("format_dos_time_field")]];
std::time::DOSDate Modified_Date [[format("format_dos_date_field")]];
u16 Cluster_Lo [[comment("Starting Cluster or Combine with Cluster_Hi")]];
u32 fileSize [[name("FILE_SIZE"), comment("File Size in Bytes")]];
u32 first_cluster = (Cluster_Hi << 16) | Cluster_Lo;
u8 FILE_DATA[fileSize] @ dataRegionStart + (first_cluster -2) * bytesPerCluster [[comment("Pointer to the Files Content")]];
sfn_count += 1;
if (fileName[0] == 0xE5) {
sfn_del_count += 1;
}
};
// ------------------------------
// LOOOONG FILE NAME PARSER
// ------------------------------
struct LFN_Entry {
u64 curr_first_byte = $;
u8 curr_attr = dir_entry_attr(curr_first_byte);
LFNEntry_FirstByte SeqByte [[name("SEQUENCE_NUM"), comment("0x01-0x20 | Add 0x40 to Last LFN Entry")]];
char16 NAME_1[5] [[comment("First 5 Characters of LFN")]];
Attributes attributes [[name("LFN_ATTR"), comment("0x0F = LFN")]];
padding[1] [[comment("Zeros")]];
u8 nameChecksum [[name("Checksum"), comment("Checksum Calculated on SFN_ALIAS")]];
char16 NAME_2[6] [[comment("Next 6 Characters of LFN")]];
padding[2] [[comment("Zeros")]];
char16 NAME_3[2] [[comment("Next 2 Characters of LFN")]];
// ATTEMPT TO CLEANUP UNICODE LFN... DOES NOT ACCOUNT FOR MULTI LFN ENTRIES
if (curr_attr == 0x0F) {
char display_name[32] @ $ - 32 [[
name(
(NAME_1[0] >= 0x20 && NAME_1[0] <= 0x7E ? std::string::to_string(NAME_1[0]) : "") +
(NAME_1[1] >= 0x20 && NAME_1[1] <= 0x7E ? std::string::to_string(NAME_1[1]) : "") +
(NAME_1[2] >= 0x20 && NAME_1[2] <= 0x7E ? std::string::to_string(NAME_1[2]) : "") +
(NAME_1[3] >= 0x20 && NAME_1[3] <= 0x7E ? std::string::to_string(NAME_1[3]) : "") +
(NAME_1[4] >= 0x20 && NAME_1[4] <= 0x7E ? std::string::to_string(NAME_1[4]) : "") +
(NAME_2[0] >= 0x20 && NAME_2[0] <= 0x7E ? std::string::to_string(NAME_2[0]) : "") +
(NAME_2[1] >= 0x20 && NAME_2[1] <= 0x7E ? std::string::to_string(NAME_2[1]) : "") +
(NAME_2[2] >= 0x20 && NAME_2[2] <= 0x7E ? std::string::to_string(NAME_2[2]) : "") +
(NAME_2[3] >= 0x20 && NAME_2[3] <= 0x7E ? std::string::to_string(NAME_2[3]) : "") +
(NAME_2[4] >= 0x20 && NAME_2[4] <= 0x7E ? std::string::to_string(NAME_2[4]) : "") +
(NAME_2[5] >= 0x20 && NAME_2[5] <= 0x7E ? std::string::to_string(NAME_2[5]) : "") +
(NAME_3[0] >= 0x20 && NAME_3[0] <= 0x7E ? std::string::to_string(NAME_3[0]) : "") +
(NAME_3[1] >= 0x20 && NAME_3[1] <= 0x7E ? std::string::to_string(NAME_3[1]) : "")
)
]];
}
lfn_count += 1;
if (SeqByte.status == Entry_Status::DELETED_ENTRY) {
lfn_del_count += 1;
}
};
// ------------------------------
// SHORT FILE NAME PARSER
// ------------------------------
struct SFN_Entry {
char fileName[8] [[name("SFN"), comment("Short File Name (8dot3)")]];
char extension[3] [[name("EXT"), comment("File Extension (8dot3)")]];
Attributes attributes [[name("RASH ATTR"), comment("Read-Only | Archive | System | Hidden | SubDir...")]];
u8 reserved [[comment("Zeros")]];
u8 milliseconds [[comment("Add to Times for Refinement")]];
std::time::DOSTime Created_Time [[format("format_dos_time_field")]];
std::time::DOSDate Created_Date [[format("format_dos_date_field")]];
std::time::DOSDate Accessed_Date [[format("format_dos_date_field")]];
u16 Cluster_Hi [[comment("High Cluster if Needed")]];
std::time::DOSTime Modified_Time [[format("format_dos_time_field")]];
std::time::DOSDate Modified_Date [[format("format_dos_date_field")]];
u16 Cluster_Lo [[comment("Starting Cluster or Combine with Cluster_Hi")]];
u32 fileSize [[name("FILE_SIZE"), comment("File Size in Bytes")]];
u32 first_cluster = (Cluster_Hi << 16) | Cluster_Lo;
u8 FILE_DATA[fileSize] @ dataRegionStart + (first_cluster -2) * bytesPerCluster [[comment("Pointer to the File Content")]];
sfn_count += 1;
if (fileName[0] == 0xE5) {
sfn_del_count += 1;
}
};
// ------------------------------
// SUBDIRECTORY PARSER | LEVEL 2
// ------------------------------
struct SubDirParser {
u8 first = dir_entry_marker($);
u8 attr = dir_entry_attr($);
u64 next_first_byte = $ + 32;
u8 next_attr = dir_entry_attr(next_first_byte); // current offset plus 12 bytes (offset 0x0B of entry)
if (first != 0x00 && attr == 0x0F) {
LFN_Entry LFN_ENTRY;
if (next_first_byte != 0x00 && next_first_byte != 0xE5 && next_attr == 0x0F) {
LFN_Entry next_LFN_ENTRY;
SFN_Entry_Alias SFN_ALIAS;
}
} else if (first != 0x00 && attr != 0x0F) {
SFN_Entry SFN_ENTRY;
}
};
// ------------------------------
// ROOT DIRECTORY ENTRY PARSER
// ROUGH METHOD OF PARSING SFN/LFN/SFN_ALIAS/SUBDIR TWO LEVELS DEEP
// IF THE PATTERN CRASHES - THIS IS LIKELY WHY
// ------------------------------
struct RootDirParser {
u64 curr_first_byte = $;
u8 curr_attr = dir_entry_attr(curr_first_byte); // current offset plus 12 bytes (offset 0x0B of entry)
u64 next_first_byte = $ + 32;
u8 next_attr = dir_entry_attr(next_first_byte); // current offset plus 12 bytes (offset 0x0B of entry)
bool is_subdir = false;
if (curr_first_byte != 0x00 && curr_first_byte != 0xE5 && curr_attr == 0x0F) {
LFN_Entry LFN_ENTRY;
if (next_first_byte != 0x00 && next_first_byte != 0xE5 && next_attr == 0x0F) {
LFN_Entry next_LFN_ENTRY;
SFN_Entry_Alias SFN_ALIAS;
is_subdir = SFN_ALIAS.attributes.subDirectory;
if (SFN_ALIAS.attributes.subDirectory && next_first_byte != 0x00 && next_attr != 0xE5) {
is_subdir = SFN_ALIAS.attributes.subDirectory;
u64 dir_start_addr = dataRegionStart + (SFN_ALIAS.first_cluster - 2) * bytesPerCluster;
SubDirParser SUB_DIR_INDEX[while(std::mem::read_unsigned($, 1) != 0x00)] @ dir_start_addr;
}
}
if (next_first_byte != 0x00 && next_first_byte != 0xE5 && next_attr != 0x0F) {
SFN_Entry_Alias SFN_ALIAS;
is_subdir = SFN_ALIAS.attributes.subDirectory;
if (SFN_ALIAS.attributes.subDirectory && next_first_byte != 0x00 && next_attr != 0xE5) {
is_subdir = SFN_ALIAS.attributes.subDirectory;
u64 dir_start_addr = dataRegionStart + (SFN_ALIAS.first_cluster - 2) * bytesPerCluster;
SubDirParser SUB_DIR_INDEX[while(std::mem::read_unsigned($, 1) != 0x00)] @ dir_start_addr;
}
}
} else if (curr_first_byte != 0x00 && curr_first_byte != 0xE5 && curr_attr != 0x0F) {
SFN_Entry SFN_ENTRY;
is_subdir = SFN_ENTRY.attributes.subDirectory;
if (SFN_ENTRY.attributes.subDirectory && next_first_byte != 0x00 && next_attr != 0xE5) {
is_subdir = SFN_ENTRY.attributes.subDirectory;
u64 dir_start_addr = dataRegionStart + (SFN_ENTRY.first_cluster - 2) * bytesPerCluster;
SubDirParser SUB_DIR_INDEX[while(std::mem::read_unsigned($, 1) != 0x00)] @ dir_start_addr;
}
} else if (curr_first_byte != 0x00 && current_first_byte == 0xE5) {
if (next_first_byte != 0x00 && next_attr == 0x0F) {
LFN_Entry LFN_ENTRY;
if (next_first_byte != 0x00 && next_first_byte != 0xE5) {
if (next_attr != 0x0F) {
SFN_Entry_Alias SFN_ALIAS;
is_subdir = SFN_ALIAS.attributes.subDirectory;
if (next_first_byte != 0x00 && next_first_byte != 0xE5 && next_attr != 0x0F) {
SFN_Entry_Alias SFN_ALIAS2; // otherwise switch to SFN
is_subdir = SFN_ALIAS.attributes.subDirectory;
if (SFN_ALIAS.attributes.subDirectory && next_first_byte != 0x00 && next_attr != 0xE5) {
is_subdir = SFN_ALIAS.attributes.subDirectory;
u64 dir_start_addr = dataRegionStart + (SFN_ALIAS.first_cluster - 2) * bytesPerCluster;
SubDirParser SUB_DIR_INDEX[while(std::mem::read_unsigned($, 1) != 0x00)] @ dir_start_addr;
}
}
}
}
} else {
SFN_Entry SFN_ENTRY;
is_subdir = SFN_ENTRY.attributes.subDirectory;
}
}
} [[name(format_element($, start_index, is_subdir)), comment("FILE/DIR [INDX #]")]];
// ------------------------------
// NAME FORMATTER
// ------------------------------
fn format_element(auto v, u64 offset, bool subdir) {
if (subdir) {
return std::format("SUB_DIR [{:02}]", std::core::array_index() + offset);
} else {
return std::format("FILE [{:02}]", std::core::array_index() + offset);
}
};
// ------------------------------
// ROOT DIRECTORY HEADER PARSER
// ------------------------------
struct RootDirHeader {
char VolumeName[11] [[comment("User Defined Name of the VOL")]];
u8 VolumeLabelFlag [[comment("Indicates the Preceding VOL LABEL")]];
padding[10] [[comment("Zeros")]];
std::time::DOSTime Created_Time [[format("format_dos_time_field"), comment("Last Write Time - Typically when Created/Formatted, but NOT ALWAYS...(DISK IMAGE/FAT DRIVERS)")]];
std::time::DOSDate Created_Date [[format("format_dos_date_field"), comment("Last Write Date - Typically when Created/Formatted, but NOT ALWAYS...(DISK IMAGE/FAT DRIVERS)")]];
padding[6] [[comment("Zeros")]];
};
// ------------------------------
// VBR SIGNATURE HELPER
// ------------------------------
enum VBRSignature : u16 {
VBR_SIG = 0xAA55
};
// ------------------------------
// FILE SYSTEM INFO BLOCK
// ------------------------------
struct FSInfo {
u32 leadSignature [[comment("RRaA")]];
padding[480] [[comment("Zeros")]];
u32 structSignature [[comment("FSINFO Signature")]];
u32 freeClusterCount [[comment("Approximate Free Cluster Count")]];
u32 nextFreeCluster [[comment("FAT1: Suggested Starting Point")]];
padding[14] [[comment("Zeros")]];
VBRSignature VBR_SIG [[comment("0x55AA")]];
};
// ------------------------------
// FAT12/16/32 BIOS PARAMETER BLOCK (BPB)
// ------------------------------
struct BPB_Common {
u8 jmp_boot[3] [[comment("Assembly Instructions to Jump to Boot Code")]];
char oem_name[8] [[comment("MSDOS/BSD")]];
u16 bytes_per_sector [[comment("512,1024,2048,4096")]];
u8 sectors_per_cluster [[comment("Under 32K - Must be a power of 2")]];
u16 reserved_sectors [[comment("Size of Reserved Area in Sectors")]];
u8 num_fats [[comment("Typically 2, but can be 1 for Small Volumes")]];
u16 root_entry_count [[comment("Max Num of Entries -- 0 for FAT32| 512 for FAT16")]];
u16 total_sectors16 [[comment("if 0, use total_sectors32")]];
u8 media_type [[comment("0xF8=FIXED DISK | 0xF0=REMOVABLE")]];
u16 fat_size16 [[comment("Size of each FAT in Sectors for FAT12/16; 0 for FAT32")]];
u16 sectors_per_track [[comment("Legacy")]];
u16 num_heads [[comment("Legacy")]];
u32 hidden_sectors [[comment("Num of Sectors before the Volume")]];
u32 total_sectors32 [[comment("32bit Value of Total Num of Sectors in Volume")]];
// ----------------------vvv-----
// FAT32 EXTENDED
// ----------------------vvv-----
u32 FAT_Sector_Count [[comment("Total Sectors per FAT")]];
u16 ext_flags [[comment("16bit Value: BIT_7 = 1 == 1 FAT USED | Otherwise both FATs USED")]];
u16 fs_version [[comment("Major and Minor | None")]];
u32 root_cluster [[comment("Cluster Num of Root Dir")]];
u16 fs_info_sector [[comment("FS_INFO Location")]];
u16 backup_boot_sector [[comment("VBR Backup Location")]];
u8 reserved[12] [[comment("Zeros")]];
u8 drive_number [[comment("BIOS INT13h Drive Num")]];
u8 reserved1 [[comment("Zeros")]];
u8 boot_signature [[comment("Extended Boot Sig = 0x29")]];
u32 volume_id [[comment("Volume Serial Number - Based on Created Date/Time")]];
char volume_label[11] [[comment("No Name | User Defined Name | Check Root Dir")]];
char fs_type[8] [[comment("FAT32 ")]];
u8 bootstrap[420] [[comment("Until Signature")]];
VBRSignature VBR_SIG [[comment("0x55AA")]];
// ----------------------vvv-----
// UPDATE CONSTANTS/GLOBALS
// ----------------------vvv-----
bytesPerCluster = sectors_per_cluster * bytes_per_sector;
rootDirSectors = ((root_entry_count * 32) + (bytes_per_sector - 1)) / bytes_per_sector;
firstDataSector = reserved_sectors + (num_fats * FAT_Sector_Count) + rootDirSectors;
dataRegionStart = firstDataSector * bytes_per_sector;
};
// -----------------------------------------------------------------------------
// FAT32 MAIN RELATED
// -----------------------------------------------------------------------------
// V V V V V V V V V V
// -----------------------------------------------------------------------------
// ------------------------------
// FAT32 VOLUME BOOT RECORD
// ------------------------------
BPB_Common F32_VBR @ $;
VBR_OFFSET = F32_VBR.hidden_sectors * F32_VBR.bytes_per_sector;
/// ------------------------------
// FILE SYSTEM INFO BLOCK
// ------------------------------
FSInfo FS_INFO @ F32_VBR.fs_info_sector * F32_VBR.bytes_per_sector;
root_dir_start = dataRegionStart + ((F32_VBR.root_cluster - 2) * bytesPerCluster) + 32;
// ------------------------------
// FILE ALLOCATION TABLE
// *** HAS GLOBAL AT TOP ***
// ------------------------------
FAT1_start_offset = F32_VBR.reserved_sectors * F32_VBR.bytes_per_sector;
FAT2_start_offset = FAT1_start_offset + (F32_VBR.FAT_Sector_Count * F32_VBR.bytes_per_sector);
FAT_ClusterHeap_Count = F32_VBR.FAT_Sector_Count * F32_VBR.bytes_per_sector / CLUSTER_SIZE_BYTES;
FAT_Header FAT1_HEADER @ FAT1_start_offset;
FAT_Entry FAT1[MAX_FAT_CHUNKS] @ FAT1_start_offset + 8;
FAT_Header FAT2_HEADER @ FAT2_start_offset;
FAT_Entry FAT2[MAX_FAT_CHUNKS] @ FAT2_start_offset + 8;
// ------------------------------
// ROOT DIRECTORY HEADER
// ------------------------------
RootDirHeader ROOT_DIR_HEADER @ dataRegionStart + ((F32_VBR.root_cluster - 2) * bytesPerCluster);
// ----*-----*------*------*-----
// * * ROOT DIRECTORY PARSER * *
// ----*-----*------*------*-----
RootDirParser ROOT_DIR_ENTRIES[while(std::mem::read_unsigned($, 1) != 0x00)] @ root_dir_start;
// ------------------------------
// SFN <-> CLUSTER RELATION OVERLAY
// *** HAS GLOBAL AT TOP ***
// ------------------------------
INFO_Overlay SFN_CLUSTER_LIST[MAX_SFN_CLUSTER_RELATIONS] @ FAT1_start_offset [[name("SFN <-> CLUSTER (DERIVED)")]];
// ------------------------------
// FAT32 VOLUME REPORT
// *** HAS GLOBAL AT TOP ***
// ------------------------------
abs_FAT1_start_offset = VBR_OFFSET + (F32_VBR.reserved_sectors * F32_VBR.bytes_per_sector);
abs_FAT2_start_offset = abs_FAT1_start_offset + (F32_VBR.FAT_Sector_Count * F32_VBR.bytes_per_sector);
abs_rootDirStart_offset = VBR_OFFSET + dataRegionStart;
if (VOLUME_REPORT) {
std::print(" ");
std::print("-----------------------------------------");
std::print("---------- FAT32 VOLUME_REPORT ----------");
std::print("-----------------------------------------");
std::print("VOL_LABEL = {}", F32_VBR.volume_label);
std::print("FILE_SYSTEM = {}", F32_VBR.fs_type);
std::print("SERIAL_NUMBER = 0x{:X}", F32_VBR.volume_id);
std::print("-----------------------------------------");
std::print("BYTES/SECTOR = {:02}", F32_VBR.bytes_per_sector);
std::print("SECTORS/CLUSTER = {:02}", F32_VBR.sectors_per_cluster);
std::print("BYTES/CLUSTER = {:02}", bytesPerCluster);
std::print("ROOT_ENTRIES = {:02}", F32_VBR.root_entry_count);
std::print("CLUSTER_COUNT = {:02}", (F32_VBR.total_sectors32 - firstDataSector) / F32_VBR.sectors_per_cluster);
std::print("-----------------------------------------");
std::print("VOLUME_SIZE = {:02} SECTORS", F32_VBR.total_sectors32);
std::print("VOLUME_SIZE = {:.4f} GB @ 1000", (F32_VBR.total_sectors32 * F32_VBR.bytes_per_sector) / 1000.0 / 1000.0 / 1000.0);
std::print("VOLUME_SIZE = {:.4f} GiB @ 1024", (F32_VBR.total_sectors32 * F32_VBR.bytes_per_sector) / 1024.0 / 1024.0 / 1024.0);
std::print("-----------------------------------------");
std::print("RESERVED_SECTORS = {:02}", F32_VBR.reserved_sectors);
std::print("FAT_COUNT = {:02}", F32_VBR.num_fats);
std::print("FAT_SIZE = {:02} SECTORS", F32_VBR.FAT_Sector_Count);
std::print("FAT1_START_OFF = {} | 0x{:02X}", abs_FAT1_start_offset, abs_FAT1_start_offset);
std::print("FAT2_START_OFF = {} | 0x{:02X}", abs_FAT2_start_offset, abs_FAT2_start_offset);
std::print("ROOT_DIR_CLUSTER = {:02}", F32_VBR.root_cluster);
std::print("ROOT_DIR_OFFSET = {} | 0x{:02X}", abs_rootDirStart_offset, abs_rootDirStart_offset);
std::print("-----------------------------------------");
if (sfn_del_count >= 1) {
std::print("SFN_DEL(xE5) = DETECTED");
}
if (lfn_del_count >= 1) {
std::print("LFN_DEL(xE5) = DETECTED");
}
std::print("FAT1_EOF_COUNT = {:02}", allocated_file_count / 2); // divided by 2 (FAT1/FAT2)
std::print("-----------------------------------------");
std::print("------------------ END ------------------");
std::print("-----------------------------------------");
std::print(" ");
}

1571
patterns/DFIR/NTFS.hexpat Normal file

File diff suppressed because it is too large Load Diff

616
patterns/DFIR/exFAT.hexpat Normal file
View File

@@ -0,0 +1,616 @@
#pragma author Formula Zero One Technologies
#pragma description exFAT Filesystem (exFAT_v2.0)
#pragma MIME application/x-ima
#pragma endian little
// -----------------------------------------------------------------------------
// CREDIT
// -----------------------------------------------------------------------------
// Based on /fs/exfat.hexpat by WerWolv
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// NOTES
// -----------------------------------------------------------------------------
// Imported by DISK_PARSER.hexpat
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// TODO
// -----------------------------------------------------------------------------
// Recursive parsing of Root Directory / SubDirs
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// IMPORTS
// -----------------------------------------------------------------------------
import std.core;
import std.io;
import std.time;
import std.mem;
import type.guid;
import type.magic;
import type.base;
// ------------------------------
// FORWARD DECS/GLOBALS
// ------------------------------
// *** ATTENTION ***
// SET MAXIMUM NUMBER OF 4 BYTE CHUNKS TO PARSE FROM FAT1
// SET MAXIMUM NUMBER OF DIRECTORY ENTRIES TO PARSE FROM ROOT DIRECTORY
// DEFAULTS ARE 4096 | 2500
// Choose a value greater than 1 and less than 65536 OR increase the Array size limit with "#define... "
// -------**************---vvvv--- |
const u64 MAX_FAT_CHUNKS = 4096;
// -------**************---^^^^--- |
// -------**************---vvvv--- |
const u64 MAX_DIR_ENTRIES = 2500;
// -------**************---^^^^--- |
// *** ATTENTION ***
// ---*******---*******----vvvv--- |
const bool VOLUME_REPORT = true;
// ---*******---*******----^^^^--- |
u64 allocated_file_count;
u64 rdc;
// --------------------------
// exFAT DIRECTORY ENTRY HELPER
// --------------------------
enum EntryType : u8 {
UNUSED_ENTRY = 0x00,
ACTIVE_VOLUME_GUID_ENTRY = 0xA0,
INACTIVE_VOLUME_GUID_ENTRY = 0x20,
ACTIVE_TEXFAT_ENTRY = 0xA1,
INACTIVE_TEXFAT_ENTRY = 0x21,
ACTIVE_ACCESS_CONTROL_ENTRY = 0xA2,
INACTIVE_ACCESS_CONTROL_ENTRY = 0x22,
ACTIVE_VOLUME_LABEL_ENTRY = 0x83,
INACTIVE_VOLUME_LABEL_ENTRY = 0x03,
ACTIVE_ALLOCATION_BITMAP_ENTRY = 0x81,
INACTIVE_ALLOCATION_BITMAP_ENTRY = 0x01,
ACTIVE_UPCASE_TABLE_ENTRY = 0x82,
INACTIVE_UPCASE_TABLE_ENTRY = 0x02,
ACTIVE_FILE_INFO_ENTRY = 0x85,
INACTIVE_FILE_INFO_ENTRY = 0x05,
ACTIVE_STREAM_ENTRY = 0xC0,
INACTIVE_STREAM_ENTRY = 0x40,
ACTIVE_FILENAME_ENTRY = 0xC1,
INACTIVE_FILENAME_ENTRY = 0x41,
};
// ------------------------------
// DATES AND TIMES FUNC
// ------------------------------
fn format_dos_time_field(std::time::DOSTime t) {
return std::time::format_dos_time(t, "{:02}:{:02}:{:02}");
};
fn format_dos_date_field(std::time::DOSDate d) {
return std::time::format_dos_date(d, "{1:02}-{0:02}-{2:04}");
};
// ------------------------------
// BITFIELD HELPERS
// ------------------------------
bitfield Entry_Flags {
unsigned TypeCode : 5;
unsigned Importance : 1;
unsigned Category : 1;
unsigned InUse : 1;
} [[bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 8)]];
bitfield Bitmap_Flags {
unsigned Bitmap_1 : 1;
unsigned Bitmap_2 : 1;
} [[bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 8)]];
bitfield General_Primary_Flags {
unsigned Allocation_Possible : 1;
unsigned No_FAT_Chain : 1;
unsigned Reserved : 6;
} [[bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 8)]];
bitfield General_Secondary_Flags {
unsigned Allocation_Possible : 1;
unsigned No_FAT_Chain : 1;
unsigned Reserved : 6;
} [[bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 8)]];
bitfield File_Attr_Flags {
unsigned Read_Only : 1;
unsigned Hidden : 1;
unsigned System : 1;
unsigned Directory : 1;
unsigned Archive : 1;
Reserved : 11;
} [[bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 16)]];
// --------------------------
// exFAT DIRECTORY ENTRY STRUCTURES
// --------------------------
// xA0 / x20 = Volume GUID Entry
struct VolumeGUID_Entry {
Entry_Flags EntryFlags [[comment("ENTRY TYPE IDENTIFIER")]];
u8 SecondaryCount[3] [[comment("COUNT OF SUBSEQUENT ENTRIES")]];
type::Hex<u16> SetChecksum [[comment("16bit CHECKSUM")]];
General_Primary_Flags PrimaryFlags;
type::GUID GUID;
u8 Reserved_1[9];
};
// xA1 / x21 = TexFAT / Padding Entry
struct TexFATPadding_Entry {
Entry_Flags Flags [[comment("ENTRY TYPE IDENTIFIER")]];
u8 Reserved_1[31];
};
// xA2 / x22 = Access Control Entry
struct AccessControl_Entry {
Entry_Flags Flags [[comment("ENTRY TYPE IDENTIFIER")]];
u8 Reserved[31];
};
// x83 / x03 = Volume Label Entry
struct VolumeLabel_Entry {
Entry_Flags Flags [[comment("ENTRY TYPE IDENTIFIER")]];
u8 LabelLength [[comment("NUMBER OF UTF-16 CHARACTERS")]];
char16 Label[LabelLength] [[comment("VOLUME LABEL: UTF-16")]];
u8 Reserved[32-2-(LabelLength * 2)];
};
// x81 / x01 = Allocation Bitmap Entry
struct AllocationBitmap_Entry {
Entry_Flags Flags [[comment("ENTRY TYPE IDENTIFIER")]];
Bitmap_Flags BitmapFlags;
u8 Reserved_1[18];
u32 FirstCluster [[comment("FIRST LOGICAL CLUSTER NUMBER")]];
u64 DataLength [[comment("DATA SIZE")]];
u8 FILE_DATA[DataLength] @ temp_root_location + (FirstCluster - exFAT_VBR.root_dir_cluster) * bytesPerCluster [[comment("POINTER TO THE CLUSTER CONTENT")]];
};
// x82 / x02 = UpCase Table Entry
struct UpCaseTable_Entry {
Entry_Flags Flags [[comment("ENTRY TYPE IDENTIFIER")]];
u8 Reserved_1[3];
type::Hex<u32> TableChecksum [[comment("16bit CHECKSUM")]];
u8 Reserved_2[12];
u32 FirstCluster [[comment("FIRST LOGICAL CLUSTER NUMBER")]];
u64 DataLength [[comment("DATA SIZE")]];
u8 FILE_DATA[DataLength] @ temp_root_location + (FirstCluster - exFAT_VBR.root_dir_cluster) * bytesPerCluster [[comment("POINTER TO THE CLUSTER CONTENT")]];
};
// x85 / x05 = File Info Entry
struct FileInfo_Entry {
Entry_Flags EntryFlags [[comment("ENTRY TYPE IDENTIFIER")]];
u8 SecondaryCount [[comment("COUNT OF SUBSEQUENT ENTRIES")]];
type::Hex<u16> SetChecksum [[comment("16bit CHECKSUM")]];
File_Attr_Flags AttrFlags [[comment("FILE ATTRS: RASH")]];
u16 Reserved_1;
std::time::DOSTime Created_Time [[format("format_dos_time_field")]];
std::time::DOSDate Created_Date [[format("format_dos_date_field")]];
std::time::DOSTime Accessed_Time [[format("format_dos_time_field")]];
std::time::DOSDate Accessed_Date [[format("format_dos_date_field")]];
std::time::DOSTime Modified_Time [[format("format_dos_time_field")]];
std::time::DOSDate Modified_Date [[format("format_dos_date_field")]];
u8 Created_10ms_Increments [[comment("Add to Times for Refinement")]];
u8 Modified_10ms_Increments [[comment("Add to Times for Refinement")]];
s8 Created_UTC_Diff [[comment("Add to Times for Refinement")]];
s8 Modified_UTC_Diff [[comment("Add to Times for Refinement")]];
s8 Accessed_UTC_Diff [[comment("Add to Times for Refinement")]];
u8 Reserved[7];
};
// xC1 / x41 = File Name Entry
struct FileName_Entry {
Entry_Flags EntryFlags [[comment("ENTRY TYPE IDENTIFIER")]];
General_Secondary_Flags SecondaryFlags [[comment("COUNT OF SUBSEQUENT ENTRIES")]];
char16 FileName[15] [[comment("FILE NAME: UTF-16")]];
};
// xC0 / x40 = Stream Extension Entry
struct Stream_Entry {
Entry_Flags EntryFlags [[comment("ENTRY TYPE IDENTIFIER")]];;
General_Secondary_Flags SecondaryFlags [[comment("COUNT OF SUBSEQUENT ENTRIES")]];
u8 Reserved_1;
u8 NameLength [[comment("STREAM LENGTH")]];
type::Hex<u16> NameHash [[comment("16bit QUICK HASH: USED FOR FILE SEARCHING")]];
u16 Reserved_2;
u64 InitSize [[comment("INITIALIZED SIZE")]];
u32 Reserved_3;
u32 FirstCluster [[comment("FIRST LOGICAL CLUSTER NUMBER")]];
u64 ActualSize [[comment("PHYSICAL DATA SIZE")]];;
u8 FILE_DATA[InitSize] @ temp_root_location + (FirstCluster - exFAT_VBR.root_dir_cluster) * bytesPerCluster [[comment("POINTER TO THE CLUSTER CONTENT")]];
};
// --------------------------
// exFAT ROOT DIRECTORY
// --------------------------
struct RootDir {
EntryType Type;
padding[31];
match (Type) {
(EntryType::UNUSED_ENTRY): {
continue;
}
(EntryType::ACTIVE_VOLUME_GUID_ENTRY | EntryType::INACTIVE_VOLUME_GUID_ENTRY):{
VolumeGUID_Entry VOLUME_GUID_ENTRY @ $ - 32;
}
(EntryType::ACTIVE_TEXFAT_ENTRY | EntryType::INACTIVE_TEXFAT_ENTRY):{
TexFATPadding_Entry TEXFAT_PADDING_ENTRY @ $ - 32;
}
(EntryType::ACTIVE_ACCESS_CONTROL_ENTRY | EntryType::INACTIVE_ACCESS_CONTROL_ENTRY):{
AccessControl_Entry ACCESS_CONTROL_ENTRY @ $ - 32;
}
(EntryType::ACTIVE_VOLUME_LABEL_ENTRY | EntryType::INACTIVE_VOLUME_LABEL_ENTRY):{
VolumeLabel_Entry VOLUME_LABEL_ENTRY @ $ - 32;
}
(EntryType::ACTIVE_ALLOCATION_BITMAP_ENTRY | EntryType::INACTIVE_ALLOCATION_BITMAP_ENTRY):{
AllocationBitmap_Entry ALLOCATION_BITMAP_ENTRY @ $ - 32;
u64 bitmap_cluster = ALLOCATION_BITMAP_ENTRY.FirstCluster;
char dolla_BITMAP_label[4] @ FAT1_start_offset + (bitmap_cluster * 4) [[name(std::format("$Bitmap"))]];
}
(EntryType::ACTIVE_UPCASE_TABLE_ENTRY | EntryType::INACTIVE_UPCASE_TABLE_ENTRY):{
UpCaseTable_Entry UPCASE_TABLE_ENTRY @ $ - 32;
u64 upcase_cluster = UPCASE_TABLE_ENTRY.FirstCluster;
char dolla_UPCASE_label[4] @ FAT1_start_offset + (upcase_cluster * 4) [[name(std::format("$UpCase"))]];
}
(EntryType::ACTIVE_FILE_INFO_ENTRY | EntryType::INACTIVE_FILE_INFO_ENTRY):{
FileInfo_Entry FILE_INFO_ENTRY @ $ - 32;
}
(EntryType::ACTIVE_STREAM_ENTRY | EntryType::INACTIVE_STREAM_ENTRY):{
Stream_Entry STREAM_EXT_ENTRY @ $ - 32;
}
(EntryType::ACTIVE_FILENAME_ENTRY | EntryType::INACTIVE_FILENAME_ENTRY):{
FileName_Entry FILE_NAME_ENTRY @ $ - 32;
}
}
} [[name(format_entry_name(std::mem::read_unsigned($-32, 1), std::core::array_index()))]];
fn format_entry_name(auto entry_type, u64 idx) {
return std::format("{}[{}]", type_name(entry_type), idx);
};
// ------------------------------
// TYPE RE-NAMER
// ------------------------------
fn type_name(u32 type) {
if (type == EntryType::UNUSED_ENTRY) return "UNUSED_ENTRY";
if (type == EntryType::ACTIVE_VOLUME_GUID_ENTRY) return "ACTIVE_VOLUME_GUID_ENTRY";
if (type == EntryType::INACTIVE_VOLUME_GUID_ENTRY) return "INACTIVE_VOLUME_GUID_ENTRY";
if (type == EntryType::ACTIVE_TEXFAT_ENTRY) return "ACTIVE_TEXFAT_ENTRY";
if (type == EntryType::INACTIVE_TEXFAT_ENTRY) return "INACTIVE_TEXFAT_ENTRY";
if (type == EntryType::ACTIVE_ACCESS_CONTROL_ENTRY) return "ACTIVE_ACCESS_CONTROL_ENTRY";
if (type == EntryType::INACTIVE_ACCESS_CONTROL_ENTRY) return "INACTIVE_ACCESS_CONTROL_ENTRY";
if (type == EntryType::ACTIVE_VOLUME_LABEL_ENTRY) return "ACTIVE_VOLUME_LABEL_ENTRY";
if (type == EntryType::INACTIVE_VOLUME_LABEL_ENTRY) return "INACTIVE_VOLUME_LABEL_ENTRY";
if (type == EntryType::ACTIVE_ALLOCATION_BITMAP_ENTRY) return "ACTIVE_ALLOCATION_BITMAP_ENTRY";
if (type == EntryType::INACTIVE_ALLOCATION_BITMAP_ENTRY) return "INACTIVE_ALLOCATION_BITMAP_ENTRY";
if (type == EntryType::ACTIVE_UPCASE_TABLE_ENTRY) return "ACTIVE_UPCASE_TABLE_ENTRY";
if (type == EntryType::INACTIVE_UPCASE_TABLE_ENTRY) return "INACTIVE_UPCASE_TABLE_ENTRY";
if (type == EntryType::ACTIVE_FILE_INFO_ENTRY) return "ACTIVE_FILE_INFO_ENTRY";
if (type == EntryType::INACTIVE_FILE_INFO_ENTRY) return "INACTIVE_FILE_INFO_ENTRY";
if (type == EntryType::ACTIVE_STREAM_ENTRY) return "ACTIVE_STREAM_ENTRY";
if (type == EntryType::INACTIVE_STREAM_ENTRY) return "INACTIVE_STREAM_ENTRY";
if (type == EntryType::ACTIVE_FILENAME_ENTRY) return "ACTIVE_FILENAME_ENTRY";
if (type == EntryType::INACTIVE_FILENAME_ENTRY) return "INACTIVE_FILENAME_ENTRY";
return "UNKNOWN";
};
// -----------------------------------------------------------------------------
// exFAT FILE ALLOCATION TABLE (FAT1) PARSER
// -----------------------------------------------------------------------------
const u32 CLUSTER_SIZE_BYTES = 4; // Each FAT32 entry = 4 bytes
const u32 FAT_EOF = 0x0FFFFFFF; // End-of-file marker
const u32 FAT_BAD = 0x0FFFFFF7; // Bad cluster marker
const u32 FIRST_ALLOC_CLUSTER = 2; // First usable cluster after reserved
enum FAT_Flags : u32 {
UNALLOCATED = 0x00000000,
END_OF_FILE = 0xFFFFFFFF, // L.END
BAD_CLUSTER = 0xFFFFFFF7, // L.END
};
union FAT_Union {
u32 DECIMAL [[hidden]];
FAT_Flags FAT_FLAG;
};
// ------------------------------
// Helper function for pointer label
// ------------------------------
fn cluster_label(u32 val) {
if (val == FAT_Flags::UNALLOCATED)
return "UNALLOCATED";
if (val == FAT_Flags::BAD_CLUSTER)
return "BAD";
if (val >= 0x0FFFFFF8)
return "EOF";
return std::format("{}", val);
};
// ------------------------------
// FAT1 HEAPS/CHAINS
// ------------------------------
struct FAT_Entry {
FAT_Union FAT [[inline]];
u32 cluster_num = (FIRST_ALLOC_CLUSTER) + (std::core::array_index());
u32 next_cluster = FAT.DECIMAL & 0x0FFFFFFF;
char hover_label[4] @ $ - 4 [[
name(std::format(
"Cluster: {} → {}",
cluster_num,
cluster_label(next_cluster)
))
]];
bool is_eof = next_cluster >= 0x0FFFFFF8;
bool is_bad = next_cluster == FAT_BAD;
bool is_free = next_cluster == 0;
if (is_eof) {
allocated_file_count += 1;
}
} [[name(format_fat_entry(FAT.DECIMAL, std::core::array_index(), FIRST_ALLOC_CLUSTER))]];
// ------------------------------
// FAT FORMATTER FUNC
// ------------------------------
fn format_fat_entry(u32 raw_value, u32 cluster_index, u32 first_alloc_cluster) {
u32 next_cluster = raw_value & 0x0FFFFFFF;
str next_label;
if (next_cluster == 0)
next_label = "UNALLOCATED";
else if (next_cluster == FAT_BAD)
next_label = "BAD";
else if (next_cluster == 0x0FFFFFFF)
next_label = "EOF";
else
next_label = std::format("{}", next_cluster);
u32 logical_cluster = first_alloc_cluster + cluster_index;
if (next_label == "UNALLOCATED" || next_label == "BAD" || next_label == "EOF")
return std::format("Cluster {}: {}", logical_cluster, next_label);
else
return std::format("Cluster {} → {}", logical_cluster, next_label);
};
// ------------------------------
// MEDIA DESCRIPTOR HELPER
// ------------------------------
enum Media_Descriptor : u8 {
SINGLE_SIDE_FLOPPY = 0xF0,
DOUBLE_SIDE_FLOPPY = 0xF9,
HARD_DISK_DRIVE = 0xF8,
};
// ------------------------------
// FAT HEADER PARSER
// ------------------------------
struct FAT_Header {
Media_Descriptor mediaDescriptor [[comment("0xF8=FIXED DISK | 0xF0=REMOVABLE")]];;
u8 exFAT_FAT_HEADER[7] [[comment("8 BYTES TOTAL: 4 BYTES REPRESENT PSUEDO CLUSTER 0 (SYSTEM) | 4 BYTES REPRESENT PSUEDO CLUSTER 1 (SYSTEM)(EOF)")]];
//Bitmap and UpCase overlays handled in RootDir parser
char root_dir_label[4] @ $ + ((rdc - 2) * 4) [[
name(std::format(
"ROOT_DIRECTORY"
))
]];
};
// ------------------------------
//SIGNATURE HELPER
// ------------------------------
enum VBRSignature : u16 {
VBR_SIG = 0xAA55
};
// ------------------------------
// EXTENDED BOOT REGION
// ------------------------------
struct ExtendedBoot {
u8 Extended_Boot_Sector[1 * bytesPerSector];
VBRSignature VBR_SIG @ $ - 2;
};
// ------------------------------
// BOOT SECTOR BITFIELD FLAGS
// ------------------------------
bitfield VolumeFlags {
unsigned Active : 1;
unsigned VolumeDirty : 1;
unsigned Media_Failure : 1;
unsigned Clear_to_Zero : 1;
Rserved : 12;
} [[bitfield_order(std::core::BitfieldOrder::LeastToMostSignificant, 16)]];
// ------------------------------
// EXFAT VOLUME BOOT RECORD
// ------------------------------
struct exFAT_BootSector {
u8 jmp_boot[3];
char fs_name[8]; // "EXFAT "
u8 must_be_zero[53];
u64 partition_offset; // in sectors
u64 volume_length; // in sectors
u32 fat_offset; // in sectors
u32 fat_length; // in sectors
u32 cluster_heap_offset; // in sectors
u32 cluster_count;
u32 root_dir_cluster;
u32 volume_serial;
u16 fs_revision;
VolumeFlags volume_flags;
u8 bytes_per_sector_shift; // 2^n
u8 sectors_per_cluster_shift; // 2^n
u8 number_of_fats;
u8 drive_select;
u8 percent_in_use;
u8 reserved[7];
u8 bootstrap[390];
VBRSignature VBR_SIG; // 0x55AA
rdc = root_dir_cluster;
};
// -------------------------------------------------------------------------
// MAIN
// -------------------------------------------------------------------------
// V V V V V V V V V
// -------------------------------------------------------------------------
exFAT_BootSector exFAT_VBR @ 0x0;
// -------------------------------------------------------------------------
// DERIVED CONSTANTS
// -------------------------------------------------------------------------
// ============= SIZES ===================================================================
u32 bytesPerSector = 1 << exFAT_VBR.bytes_per_sector_shift;
u32 bytesPerCluster = bytesPerSector << exFAT_VBR.sectors_per_cluster_shift;
// ============= OFFSETS =================================================================
u64 volumeStartSector = exFAT_VBR.partition_offset;
u64 volumeStartOffset = volumeStartSector * bytesPerSector;
u64 volumeSize = exFAT_VBR.volume_length * bytesPerSector;
u64 FAT1_start_offset = exFAT_VBR.fat_offset * bytesPerSector;
//For printing absolute offset
u64 RootDir_Offset = (exFAT_VBR.cluster_heap_offset +
((exFAT_VBR.root_dir_cluster - 2) << exFAT_VBR.sectors_per_cluster_shift))
* bytesPerSector + volumeStartOffset;
// ============= CLUSTERS ================================================================
u32 clusterSize = bytesPerCluster;
u32 clusterCount = exFAT_VBR.cluster_count;
u64 clusterHeapOffset = exFAT_VBR.cluster_heap_offset * bytesPerSector;
// -------------------------------------------------------------------------
// SECONDARY
// -------------------------------------------------------------------------
// V V V V V V V V V
// -------------------------------------------------------------------------
// ============= USAGE ===================================================================
u8 percentInUse = exFAT_VBR.percent_in_use;
// ============= EBS =====================================================================
ExtendedBoot Extended_Boot_Sectors[8] @ $;
// ============= OEM =====================================================================
u8 OEM_Parameters[1 * bytesPerSector] @ $;
// ============= ER ======================================================================
u8 Extended_Reserved[1 * bytesPerSector] @ $;
// ============= BCS =====================================================================
u8 Boot_Checksum[1 * bytesPerSector] @ $;
// ============= BBS =====================================================================
exFAT_BootSector Backup_Boot_Sector @ $;
// ============= BEBS ====================================================================
ExtendedBoot Backup_Extended_Boot_Sectors[8] @ $;
// ============= BOEM ====================================================================
u8 Backup_OEM_Parameters[1 * bytesPerSector] @ $;
// ============= BER =====================================================================
u8 Backup_Extended_Reserved[1 * bytesPerSector] @ $;
// ============= BBCS ====================================================================
u8 Backup_Boot_Checksum[1 * bytesPerSector] @ $;
// ============= FAT =====================================================================
// *** HAS GLOBAL AT TOP ***
FAT_Header FAT1_HEADER @ FAT1_start_offset;
FAT_Entry FAT1[MAX_FAT_CHUNKS] @ FAT1_start_offset + 8;
// ============= ROOT ====================================================================
// ROOT DIRECTORY
// *** HAS GLOBAL AT TOP ***
// for locating root directory within memory
u64 temp_root_location = (exFAT_VBR.root_dir_cluster - 2) * clusterSize + clusterHeapOffset;
RootDir ROOT_DIRECTORY[MAX_DIR_ENTRIES] @ temp_root_location;
// ============= REPORT ==================================================================
// VOLUME REPORT
// *** HAS GLOBAL AT TOP ***
if (VOLUME_REPORT) {
std::print(" ");
std::print("-----------------------------------------");
std::print("---------- EXFAT VOLUME_REPORT ----------");
std::print("-----------------------------------------");
std::print("FILE_SYSTEM = {}", exFAT_VBR.fs_name);
std::print("SERIAL_NUMBER = 0x{:X}", exFAT_VBR.volume_serial);
std::print("FS_REVISION = {}.{}", (exFAT_VBR.fs_revision >> 8) & 0xFF, exFAT_VBR.fs_revision & 0xFF);
bool _any = false;
if(exFAT_VBR.volume_flags.Active) {
std::print("FAT_FLAG = 0b{:X}", exFAT_VBR.volume_flags.Active);
_any = true;
}
if(exFAT_VBR.volume_flags.VolumeDirty) {
std::print("DIRTY_FLAG = 0b{:X}", exFAT_VBR.volume_flags.Volume_Dirty);
_any = true;
}
if(exFAT_VBR.volume_flags.Media_Failure) {
std::print("FAILURE_FLAG = 0b{:X}", exFAT_VBR.volume_flags.Media_Failure);
_any = true;
}
if(exFAT_VBR.volume_flags.Clear_to_Zero) {
std::print("CLEAR_TO_ZERO_FLAG = 0b{:X}", exFAT_VBR.volume_flags.Clear_to_Zero);
_any = true;
}
if (!_any){
std::print("VOL_FLAGS = NONE");
}
std::print("-----------------------------------------");
std::print("BYTES/SECTOR = {}", bytesPerSector);
std::print("SECTORS/CLUSTER = {}", 1 << exFAT_VBR.sectors_per_cluster_shift);
std::print("BYTES/CLUSTER = {}", bytesPerCluster);
std::print("CLUSTER_COUNT = {}", clusterCount);
std::print("-----------------------------------------");
std::print("VOLUME_SIZE = {} SECTORS", exFAT_VBR.volume_length);
std::print("VOLUME_SIZE = {:.4f} GB @ 1000", volumeSize / 1000.0 / 1000.0 / 1000.0);
std::print("VOLUME_SIZE = {:.4f} GiB @ 1024", volumeSize / 1024.0 / 1024.0 / 1024.0);
std::print("-----------------------------------------");
std::print("VOLUME_START_SEC = {}", volumeStartSector);
std::print("VOLUME_START_OFF = 0x{:X}", volumeStartOffset);
std::print("FAT1_START_OFF = 0x{:02X}", FAT1_start_offset);
std::print("CLUSTER_HEAP_OFF = 0x{:02X}", clusterHeapOffset);
std::print("ROOT_DIR_CLUSTER = {:02}", exFAT_VBR.root_dir_cluster);
std::print("ROOT_DIR_OFFSET = 0x{:02X}", RootDir_Offset);
std::print("-----------------------------------------");
std::print("PERCENT_IN_USE = {:02} %", percentInUse);
std::print("NUMBER_OF_FATS = {:02}", exFAT_VBR.number_of_fats);
std::print("DRIVE_SELECT = 0x{:02X}", exFAT_VBR.drive_select);
std::print("-----------------------------------------");
std::print("------------------ END ------------------");
std::print("-----------------------------------------");
std::print(" ");
}

View File

@@ -0,0 +1,165 @@
#pragma description Devil May Cry 3 HD .mod 3D model file
#pragma author haru233
// many thanks to AxCut
// ImHex Hex Pattern File for Capcom's Devil May Cry 3 HD .mod files
import std.core;
struct ModelHeader {
char ID[4];
float Version;
padding[8];
u8 objectCount;
u8 boneCount;
u8 numberTextures;
u8;
u32;
u64;
u64 skeletonOffset;
padding[24];
};
struct ObjectInfo {
u8 meshCount;
u8;
u16 numberVertices;
padding[4];
u64 meshOffset;
u32 flags;
padding[28];
float X, Y, Z;
float radius;
};
struct Positions {
float positions[3];
};
struct Normals {
float normal[3];
};
struct UVs {
s16 uv[2];
};
struct BoneIndices {
u8 boneindex[4];
};
struct Weights {
u16 weight[1];
};
struct MeshSCM {
u16 numberVertices;
u16 textureIndex;
padding[12];
u64 VerticesPositionsOffset;
u64 NormalsPositionsOffset;
u64 UVsPositionsOffset;
padding[16];
u64 unknownOffset;
u64;
padding[8];
Positions positions[numberVertices] @VerticesPositionsOffset;
Normals normals[numberVertices] @NormalsPositionsOffset;
UVs uvs[numberVertices] @UVsPositionsOffset;
};
struct Mesh {
u16 numberVertices;
u16 textureIndex;
padding[12];
u64 VerticesPositionsOffset;
u64 NormalsPositionsOffset;
u64 UVsPositionsOffset;
u64 BoneIndicesOffset;
u64 WeightsOffset;
padding[8];
u64;
padding[8];
Positions positions[numberVertices] @VerticesPositionsOffset;
Normals normals[numberVertices] @NormalsPositionsOffset;
UVs uvs[numberVertices] @UVsPositionsOffset;
BoneIndices b_index[numberVertices] @BoneIndicesOffset;
Weights weights[numberVertices] @WeightsOffset;
};
struct Hierarchy {
u8 hierarchy;
};
struct HierarchyOrder {
u8 hierarchyorder;
};
struct Unknown {
u8;
};
struct Transform {
float x;
float y;
float z;
float length; // sqrt(x*x + y*y + z*z)
padding[16];
};
struct Skeleton{
u32 hierarchyOffset;
u32 hierarchyOrderOffset;
u32 unknownOffset;
u32 transformsOffset;
};
ModelHeader modelheader @ 0x00;
ObjectInfo objects_info[modelheader.objectCount] @ 0x40;
u32 objectOffset;
struct Object {
u64 i = std::core::array_index();
if (modelheader.ID == "SCM ") {
objectOffset = objects_info[0].meshOffset;
MeshSCM meshscm[objects_info[i].meshCount] @ objects_info[i].meshOffset;
} else {
objectOffset = objects_info[0].meshOffset;
Mesh mesh[objects_info[i].meshCount] @ objects_info[i].meshOffset;
}
};
Object objects[modelheader.objectCount] @objectOffset;
Skeleton skeleton @modelheader.skeletonOffset;
Hierarchy hierarchy[modelheader.boneCount] @(modelheader.skeletonOffset + skeleton.hierarchyOffset);
HierarchyOrder hierarchyorder[modelheader.boneCount] @(modelheader.skeletonOffset + skeleton.hierarchyOrderOffset);
Unknown unknown[modelheader.boneCount] @(modelheader.skeletonOffset + skeleton.unknownOffset);
Transform transform[modelheader.boneCount] @(modelheader.skeletonOffset + skeleton.transformsOffset);

189
patterns/SHR.hexpat Normal file
View File

@@ -0,0 +1,189 @@
/*!
Apple IIgs Super Hi-Res (SHR) + PaintWorks Animation (ANI) — ImHex pattern
Supports:
• PIC $C1/$0000 — 32 KB uncompressed SHR screen image
• PIC $C1/$0002 — 3200-color (“Brooks”) per-scanline palettes
• ANI $C2/$0000 — PaintWorks animation:
0x0000..0x7FFF : base SHR $C1/$0000 image
0x8000.. : animation header + chunks
PaintWorks animation structure (per reversed docs):
- Base image: uncompressed SHR ($C1/$0000)
- +0x8000 u32: total animation data length after header (file_len - 0x8008)
- +0x8004 u16: global frame delay in VBLs
- +0x8006 u16: flag/? (commonly 0x00C0 or 0x00C1)
- +0x8008 ...: one or more animation chunks:
chunk:
u32 chunk_len (includes this length field)
repeated { u16 offset; u16 value; } pairs
offset==0x0000 marks End-of-Frame (value is ignored)
- Offsets may target any byte in the 32 KB SHR space (pixels, SCBs, palettes).
This enables palette-cycling and SCB effects.
References:
- CiderPress2 PaintWorks Animation notes (file structure, fields, semantics).
*/
import std.core;
import std.sys;
import std.math;
#pragma endian little
#include <std/mem.pat>
#pragma description Apple IIgs Super Hi-Res (SHR) + PaintWorks Animation (ANI)
#pragma author hasseily
// ------------------------------ Constants ------------------------------
const u32 SHR_ROWS = 200;
const u32 SHR_BYTES_PER_ROW = 160;
const u32 SHR_PIXEL_DATA_SIZE = SHR_ROWS * SHR_BYTES_PER_ROW; // 32000 (0x7D00)
const u32 PIC0000_FILE_SIZE = 0x8000; // 32768
const u32 PIC0002_FILE_SIZE = 0x9600; // 38400 (32000 + 200*32)
const u32 PIC0000_OFF_PIXELS = 0x0000;
const u32 PIC0000_OFF_SCB = 0x7D00;
const u32 PIC0000_OFF_RESERVED = 0x7DC8;
const u32 PIC0000_OFF_PALETTES = 0x7E00;
const u32 PALETTE_COUNT = 16;
const u32 PALETTE_COLORS = 16;
const u32 ANI_BASE_SHR_SIZE = 0x8000; // First 32 KB is a $C1/$0000 image
const u32 ANI_HDR_OFF = 0x8000; // Animation header starts here
const u32 ANI_MIN_TOTAL_SIZE = 0x8008; // base + header (no chunks)
// ------------------------------ Types: SHR core ------------------------------
struct Row160 { u8 data[SHR_BYTES_PER_ROW]; };
// Scanline Control Byte
bitfield ShrSCB {
palette : 4; // 0..15
reserved : 1;
color_fill : 1;
interrupt : 1;
mode_640 : 1; // 0=320, 1=640
};
// helper: expand a 4-bit channel to 8-bit (0x0..0xF -> 0x00..0xFF)
fn expand4(u8 v) { return (v << 4) | v; };
bitfield Colors_gb {
blue : 4; // Blue (B3..B0)
green : 4; // Green (G3..G0)
};
bitfield Colors_r0 {
red : 4; // Red (R3..R0)
unused : 4; // Unused / reserved
};
// RGB444 stored as 0RGB
struct Rgb444_0RGB {
Colors_gb gb;
Colors_r0 r0;
} [[color(std::format("{:02X}{:02X}{:02X}", expand4(r0.red), expand4(gb.green), expand4(gb.blue)))]];
struct Palette16 { Rgb444_0RGB color[PALETTE_COLORS]; };
// $C1/$0000 raw 32 KB screen dump
struct SHR_PIC0000 {
Row160 pixels[SHR_ROWS] @ PIC0000_OFF_PIXELS;
ShrSCB scb[SHR_ROWS] @ PIC0000_OFF_SCB;
u8 reserved[56] @ PIC0000_OFF_RESERVED;
Palette16 palettes[PALETTE_COUNT] @ PIC0000_OFF_PALETTES;
};
// “Brooks” 3200-color: pixels + 200 per-line palettes (no SCBs)
struct BrooksLinePalette { Rgb444_0RGB color[PALETTE_COLORS]; };
struct SHR_PIC0002 {
Row160 pixels[SHR_ROWS] @ 0x0000;
BrooksLinePalette line_palettes[SHR_ROWS] @ SHR_PIXEL_DATA_SIZE; // 0x7D00
};
// ------------------------------ Types: PaintWorks ANI ($C2/$0000) ------------------------------
/* Each operation modifies 1 word at an absolute offset in the 32 KB SHR area.
End-of-frame marker: offset == 0x0000 (value is ignored). */
struct AniOp {
u16 offset [[color("0000AA")]]; // 0x0000..0x7FFE valid; 0x0000 = End-of-Frame
u16 value [[color("00AAAA")]]; // word to store at [offset]
// For convenience in the sidebar:
bool is_eof = (offset == 0x0000);
};
// A contiguous animation chunk: length + packed AniOp pairs.
// Most files have exactly one chunk that spans all frames.
struct AniChunk {
u32 chunk_len; // includes this field
// ops_count = (chunk_len - 4)/4, unless chunk_len == 4
// in which case: (__file_size - 0x8000 - 12)/4
u64 ops_count64 =
(chunk_len == 4)
? ( (__file_size > (0x8000 + 12)) ? ((__file_size - 0x8000 - 12) / 4) : 0 )
: ( (chunk_len >= 4) ? (u64(chunk_len - 4) / 4) : 0 );
u32 ops_count = u32(ops_count64);
// ops start immediately after chunk_len (offset +4)
AniOp ops[ops_count];
};
// Header located at 0x8000 after the base 32 KB image
struct AniHeader {
u32 anim_data_len [[color("660000")]]; // total bytes of animation data after header
u16 frame_delay_vbl [[color("CC0000")]]; // global per-frame delay in VBLs (NTSC/PAL differ)
u16 flag_unknown; // usually 0x00C0 or 0x00C1
};
// Full PaintWorks animation container
struct ANI_PaintWorks {
// Base frame: a normal uncompressed SHR image
SHR_PIC0000 base @ 0x0000;
// Global animation header
AniHeader hdr @ ANI_HDR_OFF;
// One or more chunks, typically exactly one:
AniChunk chunks[ std::math::min(
u32(16), // cap to keep ImHex happy in pathological cases
u32((__file_size - (ANI_HDR_OFF + sizeof(AniHeader))) > 3 ?
1 + u32((__file_size - (ANI_HDR_OFF + sizeof(AniHeader))) / 0x10000000) :
1)
) ] @ (ANI_HDR_OFF + sizeof(AniHeader));
// Helpful computed values for inspection:
u64 file_len = __file_size;
u64 expected_anim_end = ANI_HDR_OFF + sizeof(AniHeader) + u64(hdr.anim_data_len);
};
// ------------------------------ Dispatcher ------------------------------
u64 __file_size = std::mem::size();
if (__file_size == PIC0000_FILE_SIZE) {
// Plain SHR dump
SHR_PIC0000 pic0000 @ 0x0000;
} else if (__file_size == PIC0002_FILE_SIZE) {
// Brooks 3200-color
SHR_PIC0002 pic0002 @ 0x0000;
} else if (__file_size >= ANI_MIN_TOTAL_SIZE) {
// Heuristic: treat as PaintWorks ANI if theres room for base+header.
// (Many PW ANI files use ProDOS type $C2/$0000.)
ANI_PaintWorks ani @ 0x0000;
} else if (__file_size >= SHR_PIXEL_DATA_SIZE) {
// Fallback: show pixels only for odd dumps
Row160 pixels_only[SHR_ROWS] @ 0x0000;
}
ANI_PaintWorks ani_paintworks_at_0 @ 0;

129
patterns/a3/a3_bmtr.hexpat Normal file
View File

@@ -0,0 +1,129 @@
#pragma author MrClock
#pragma description Arma 3 RTM animation format (binarized)
#pragma endian little
#pragma MIME application/x.a3-bmtr
fn get_data_description() {
return "Binarized RTM (BMTR) animation files are the PBO packed versions of plain RTMs.\n Binarized files are optimized for use by the game engine, and they are not editable.\nBone transformations are stored as relative quaternion-vector pairs.\nData blocks are conditionally LZO1X compressed (these are not supported by this pattern).";
};
import std.string;
import std.sys;
import type.float16;
using asciiz = std::string::NullString [[format("formatAsciiz")]];
using half = type::float16 ;
struct s16float {
s16 data;
} [[sealed,static,transform("transforms16float"), format("transforms16float")]];
struct Property {
padding[4];
asciiz name;
float phase;
asciiz value;
} [[format("formatProperty")]];
struct Vector<DataType> {
DataType x [[comment("+Left/-Right")]];
DataType y [[comment("+Up/-Down (UNUSED)")]];
DataType z [[comment("+Forward/-Backward")]];
} [[static]];
struct Quaternion {
s16float x;
s16float y;
s16float z;
s16float w;
} [[static,format("formatQuaternion")]];
struct Transform {
Quaternion orientation;
Vector<half> position [[format("formatVectorHalf")]];
} [[static]];
struct Frame {
u32 count_bones;
bool compressed = count_bones * sizeof(Transform) >= 1024;
if (parent.version > 4) {
u8 lzo_flag;
compressed = lzo_flag > 0;
}
if (compressed) {
std::error("Transformations are LZO compressed and compressed length is unknown");
} else {
Transform transforms[count_bones];
}
};
struct BMTR {
char signature[4];
u32 version;
padding[1];
Vector<float> motion [[format("formatVectorFloat")]];
u32 count_frames;
padding[4];
u32 count_bones;
u32 count_bones_again;
std::assert_warn(count_bones == count_bones_again, "Mismatch between bone counts");
asciiz bones[count_bones];
if (version >= 4) {
padding[4];
u32 count_properties;
Property properties[count_properties];
}
u32 count_phases;
std::assert_warn(count_frames == count_phases, "Frame and phase counts do not match");
bool compressed = count_phases * sizeof(float) >= 1024;
if (version > 4) {
u8 lzo_flag;
compressed = lzo_flag > 0;
}
if (compressed) {
std::error("Phases are LZO compressed and compressed length is unknown");
} else {
float phases[count_phases];
}
Frame frames[count_frames];
};
fn transforms16float(ref s16float value) {
return float(value.data) / 16384;
};
fn formatAsciiz(ref asciiz value) {
return std::format("\"{:s}\"", value);
};
fn formatProperty(ref Property prop) {
return std::format("\"{0:s}\" = \"{1:s}\" @ {2:.4f}", prop.name, prop.value, prop.phase);
};
fn formatVectorHalf(ref Vector<half> vec) {
return std::format(
"[{0}, {1}, {2}]",
type::impl::format_float16(vec.x),
type::impl::format_float16(vec.y),
type::impl::format_float16(vec.z)
);
};
fn formatVectorFloat(ref Vector<float> vec) {
return std::format("[{0:.2f}, {1:.2f}, {2:.2f}]", vec.x, vec.y, vec.z);
};
fn formatQuaternion(ref Quaternion q) {
return std::format("[{0:.2f}, {1:.2f}, {2:.2f}, {3:.2f}]", q.x, q.y, q.z, q.w);
};
BMTR file @ 0x0000;

View File

@@ -0,0 +1,222 @@
#pragma author MrClock
#pragma description Arma 3 P3D model format (MLOD)
#pragma endian little
#pragma MIME model/x.a3-p3d-mlod
fn get_data_description() {
return "MLOD type P3D files are used for authoring 3D models for Arma 3.\nThese files can be carated in and edited in the Object Builder application.\nAll data is stored uncompressed for ease of editing.\nDuring the PBO packing process they are further \"binarized\" into ODOL type P3D files, that are optimized for use by the game engine. (These are no longer editable, the conversion is irreversible.)\n\nP3D model files can by quite large, so by default only the 1st LOD is processed by this pattern. Processing of all LODs can be enabled in the pattern settings.";
};
import std.string;
import std.core;
bool process_all_lods in;
using asciiz = std::string::NullString;
enum FaceType: u32 {
TRIANGLE = 3,
QUAD = 4
};
struct Vector {
float x;
float y;
float z;
} [[static,format("formatVector")]];
struct UV {
float u;
float v;
} [[static,format("formatUV")]];
enum SurfaceFitting: u8 {
NORMAL = 0,
ON_SURFACE = 1,
ABOVE_SURFACE = 2,
UNDER_SURFACE = 4,
KEEP_HEIGHT = 8
};
enum Lighting: u8 {
NORMAL = 0,
SHINING = 1,
SHADOWED = 2,
FULL_LIT = 4,
HALF_LIT = 8
};
enum DecalMode: u8 {
NORMAL = 0,
DECAL = 1,
RADIO12 = 2
};
enum Fog: u8 {
NORMAL = 0,
NONE = 1,
SKY = 2
};
enum NormalCalculation: u8 {
FACE_AREA = 0,
HIDDE_VERTEX = 1,
FIXED = 2,
FACE_ANLGE = 4
};
bitfield VertexFlags {
padding : 5;
NormalCalculation normals : 3;
u8 user;
padding : 2;
Fog fog : 2;
padding : 2;
DecalMode decal : 2;
Lighting lighting : 4;
SurfaceFitting surface : 4;
} [[bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 32)]];
struct Vertex {
Vector position;
VertexFlags flags;
}[[static,format("formatVertex")]];
struct FacePoint {
u32 vertex_index;
u32 normal_index;
UV uv;
} [[static]];
enum ZBiasFlag: u8 {
NONE = 0,
LOW = 1,
MIDDLE = 2,
HIGH = 3
};
bitfield FaceFlags {
user : 7;
disable_texture_merging : 1;
padding : 2;
flat_lighting : 1;
reversed_face : 1;
padding : 10;
ZBiasFlag zbias : 2;
position : 1;
padding : 1;
double_sided_face : 1;
disable_shadow : 1;
padding : 4;
} [[bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 32)]];
struct Face {
FaceType type;
FacePoint points[4];
FaceFlags flags;
asciiz texture;
asciiz material;
} [[format("formatFace")]];
struct Edge {
u32 vertex_1;
u32 vertex_2;
} [[sealed,static,format("formatEdge")]];
struct Property {
char name[64] [[transform("std::string::to_string")]];
char value[64] [[transform("std::string::to_string")]];
} [[static,sealed,format("formatProperty")]];
struct Tagg {
bool active;
asciiz name;
u32 length;
if (name == "#EndOfFile#") {
break;
}
match (name) {
("#SharpEdges#"): Edge edges[length/8];
("#Property#"): Property property;
("#Mass#"): float masses[parent.count_verticies];
("#UVSet#"): {
u32 channel;
UV coordinates[(length - 4) / 8];
}
(_): if (std::string::starts_with(name, "#") && std::string::ends_with(name, "#")) {
u8 unknown_data[length];
} else {
u8 vertex_weights[parent.count_verticies];
u8 face_weights[parent.count_faces];
}
}
} [[format("formatTagg")]];
struct P3dmLod {
char signature[4];
u32 version_major;
u32 version_minor;
u32 count_verticies;
u32 count_normals;
u32 count_faces;
u32; // Unknown data (might be unused model flags)
Vertex verticies[count_verticies];
Vector normals[count_normals];
Face faces[count_faces];
char tagg_signature[4];
Tagg taggs[while(true)];
float resolution;
} [[format("formatP3dmLod")]];
struct P3D {
char signature[4];
u32 version;
u32 count_lods;
if (!process_all_lods) {
P3dmLod lod_0;
} else {
P3dmLod lods[count_lods];
}
};
fn formatVector(ref Vector pos) {
return std::format("[{0:.3f}, {1:.3f}, {1:.3f}]", pos.x, pos.y, pos.z);
};
fn formatUV(ref UV pos) {
return std::format("[{0:.3f}, {1:.3f}]", pos.u, pos.v);
};
fn formatVertex(ref Vertex vert) {
return formatVector(vert.position);
};
fn formatFace(ref Face face) {
return face.type == FaceType::TRIANGLE ? "triangle" : "quad";
};
fn formatEdge(ref Edge edge) {
return std::format("{0:d} <-> {1:d}", edge.vertex_1, edge.vertex_2);
};
fn formatProperty(ref Property prop) {
return std::format("\"{0:s}\" = \"{1:s}\"", prop.name, prop.value);
};
fn formatTagg(ref Tagg tagg) {
if (std::core::has_member(tagg, "vertex_weights")) {
return std::format("\"{0:s}\" selection", tagg.name);
} else {
return std::format("\"{0:s}\"", tagg.name);
}
};
fn formatP3dmLod(ref P3dmLod lod) {
return std::format("Resolution: {0}", lod.resolution);
};
P3D file @ 0x0000;

141
patterns/a3/a3_paa.hexpat Normal file
View File

@@ -0,0 +1,141 @@
#pragma author MrClock
#pragma description Arma 3 PAA image format
#pragma endian little
#pragma MIME image/x.a3-paa
fn get_data_description() {
return "PAA texture files are the proprietary image format used for textures in Arma 3.\nSimilar to most other formats used in game engines, the PAA stores not only a single resolution, but a series of precomputed mipmaps.\nPAA supports multiple pixel encoding formats, such as DXT1, DXT5, RGBA5551, grayscale, and others. Mipmap data in DXT encoded files is optionally compressed with the LZO1X algorithm. All other types are unconditionally LZSS compressed.";
};
import type.color;
import std.mem;
import std.sys;
struct Color<auto alpha> {
u8 b;
u8 g;
u8 r;
if (alpha) u8 a;
} [[sealed, format("type::impl::format_color"), color(std::format("{0:02X}{1:02X}{2:02X}", r, g, b))]];
using BGR8 = Color<false>;
using BGRA8 = Color<true>;
enum PixelFormat: u16 {
DXT1 = 0xFF01,
DXT2 = 0xFF02,
DXT3 = 0xFF03,
DXT4 = 0xFF04,
DXT5 = 0xFF05,
RGBA4 = 0x4444,
RGBA5 = 0x1555,
RGBA8 = 0x8888,
GRAY = 0x8080
};
enum AlphaMode: u32 {
NONE = 0,
INTERPOLATED = 1,
BINARY = 2
};
enum Swizzle: u8 {
ALPHA = 0,
RED = 1,
GREEN = 2,
BLUE = 3,
INVERTED_ALPHA = 4,
INVERTED_RED = 5,
INVERTED_GREEN = 6,
INVERTED_BLUE = 7,
BLANK_WHITE = 8,
BLANK_BLACK = 9
};
enum Compression: u8 {
NONE = 0,
LZO1X = 1,
LZSS = 2
};
struct Tagg {
char signature[8];
u32 length;
match (signature) {
("GGATCGVA"): BGRA8 color;
("GGATCXAM"): BGRA8 color;
("GGATGALF"): AlphaMode alpha;
("GGATSFFO"): u32 offsets[16];
("GGATZIWS"): Swizzle copies[4];
(_): u8 data[length];
}
} [[format("format_tagg_name")]];
struct Palette {
u16 length;
BGR8 colors[length];
};
struct Mipmap {
u16 width_and_lzo [[format("format_width_lzo")]];
u16 height;
u16 width = width_and_lzo;
Compression compression = Compression::NONE;
if ((u32(parent.format) & 0xFF00) == 0xFF00) {
width = width_and_lzo & 0x7FFF;
compression = width_and_lzo & 0x8000 ? Compression::LZO1X : Compression::NONE;
} else {
compression = Compression::LZSS;
}
if (width == 0 && height == 0) {
break;
}
u24 size;
match (compression) {
(Compression::NONE): u8 encoded_data[size];
(Compression::LZO1X): u8 lzo_compressed_data[size];
(Compression::LZSS): u8 lzss_compressed_data[size];
}
} [[format("format_resolution")]];
struct PAA {
PixelFormat format;
Tagg taggs[while(std::mem::read_string($, 4) == "GGAT")];
Palette palette;
Mipmap mipmaps[while(true)];
u16 EOF;
std::assert_warn(EOF == 0, "Invalid EOF sentinel");
};
fn format_resolution(ref auto mip) {
return std::format("{0:d} x {1:d}", mip.width, mip.height);
};
fn format_width_lzo(u16 value) {
u16 width = value & 0x7FFF;
if (value & 0x8000) {
return std::format("{0:d} (+LZO flag)", width);
} else {
return std::format("{0:d}", width);
}
};
fn format_tagg_name(Tagg data) {
match (data.signature) {
("GGATCGVA"): return "Average color";
("GGATCXAM"): return "Max color";
("GGATGALF"): return "Alpha flag";
("GGATZIWS"): return "Swizzle";
("GGATSFFO"): return "Mipmap offsets";
(_): return "Unknown";
}
};
PAA file @ 0x0000;

165
patterns/a3/a3_rap.hexpat Normal file
View File

@@ -0,0 +1,165 @@
#pragma author MrClock
#pragma description Arma 3 binary configuration format
#pragma endian little
#pragma MIME application/x.a3-rap
fn get_data_description() {
return "The RAP format is the binarized/\"rapified\" version of configuration files for Arma 3. Plain text configuration, material definition, scenario description and other files using the configuration syntax are rapified during the PBO packing process. The game can work with the plain text versions (they are actually rapified during boot), but properly converting them into the binary format ahead of time makes the booting easier.";
};
import std.mem;
import std.string;
import std.core;
import std.io;
using asciiz = std::string::NullString [[format("formatAsciiz")]];
/*
Item counts are stored in 7-bit encoded integers. In each byte the top bit signals
if the next byte belongs to the number as well.
*/
struct CompressedUint {
u8 extras[while(std::mem::read_unsigned($, 1) & 0x80)];
u8 last;
} [[sealed,transform("transformCompressedUint"),format("formatCompressedUint")]];
enum MemberType: u8 {
CLASS = 0,
LITERAL = 1,
ARRAY = 2,
EXTERNAL = 3,
DELETE = 4,
ARRAY_EXTENSION = 5
};
enum ValueType: u8 {
STRING = 0,
FLOAT = 1,
INTEGER = 2,
ARRAY = 3,
VARIABLE = 4
};
using Array;
struct ArrayItem {
ValueType type;
match (type) {
(ValueType::STRING): asciiz value;
(ValueType::FLOAT): float value;
(ValueType::INTEGER): s32 value;
(ValueType::ARRAY): Array value;
(ValueType::VARIABLE): asciiz value;
}
} [[format("formatArrayItem")]];
struct Array {
CompressedUint count_items;
ArrayItem items[count_items];
} [[format("formatArray")]];
using ClassBody;
struct Member {
MemberType type;
match(type) {
(MemberType::CLASS): {
asciiz name;
ClassBody *body : u32;
}
(MemberType::LITERAL): {
ValueType subtype;
asciiz name;
match (subtype) {
(ValueType::STRING): asciiz value;
(ValueType::FLOAT): float value;
(ValueType::INTEGER): s32 value;
(_): std::error(std::format("Unexpected subtype for literal: {}", subtype));
}
}
(MemberType::ARRAY | MemberType::ARRAY_EXTENSION): {
asciiz name;
Array value;
}
(MemberType::EXTERNAL): {
asciiz name;
}
(MemberType::DELETE): {
asciiz name;
}
}
} [[format("formatMember")]];
using Enums;
struct ClassBody {
asciiz parent_name;
CompressedUint count_members;
Member members[count_members];
u8 *pointer : u32 [[comment("In the root body this points to the enum list.\nIn all others it points to the next body on the same level.")]];
};
struct EnumItem {
asciiz name;
s32 value;
} [[format("formatEnumItem")]];
struct Enums {
u32 count_items;
EnumItem items[count_items];
};
struct RAP {
char signature[4];
u32;
u32;
Enums *enums : u32;
ClassBody root;
};
fn formatAsciiz(ref asciiz value) {
return std::format("\"{0:s}\"", value);
};
fn transformCompressedUint(ref CompressedUint value) {
u64 result = 0;
for (u8 i = 0, i < sizeof(value.extras), i += 1) {
result += (value.extras[i] & 0x7F) << (7*i);
}
result += value.last << (sizeof(value.extras) * 7);
return result;
};
fn formatCompressedUint(ref CompressedUint value) {
return value;
};
fn formatArrayItem(ref ArrayItem value) {
return value.value;
};
fn formatArray(ref Array value) {
return "{...}";
};
fn formatMember(ref Member item) {
match (item.type) {
(MemberType::CLASS): return std::format("class {0:s} {{...}};", item.name);
(MemberType::LITERAL): return std::format("{0:s} = {1};", item.name, item.value);
(MemberType::ARRAY): return std::format("{0:s}[] = {{...}};", item.name);
(MemberType::EXTERNAL): return std::format("class {0:s};", item.name);
(MemberType::DELETE): return std::format("del {0:s};", item.name);
}
};
fn formatEnumItem(ref EnumItem value) {
return std::format("{0:s} = {1}", item.name, item.value);
};
RAP file @ 0x0000;

93
patterns/a3/a3_rtm.hexpat Normal file
View File

@@ -0,0 +1,93 @@
#pragma author MrClock
#pragma description Arma 3 RTM animation format (plain)
#pragma endian little
#pragma MIME application/x.a3-rtm
fn get_data_description() {
return "Plain RTM animation files are used in animation authoring for Arma 3.\nThey can be created and edited in Object Builder.\nBone transformations are stored as absolute transformation matrices.\nPlain RTMs must be converted to their \"binarized\" versions by an appropriate PBO packing tool for use in game.";
};
import std.mem;
import std.sys;
import std.string;
import std.io;
using lascii = std::string::SizedString<u8> [[format("formatLascii")]];
struct Property {
float phase;
lascii name;
lascii value;
} [[format("formatProperty")]];
struct Bone {
char name[32];
} [[sealed,static,transform("transformBone"),format("formatBone")]];
struct Transform {
Bone bone;
float matrix[12] [[comment("4x4 transformation matrix (with last row omitted)")]];
} [[static,format("formatTransform")]];
struct Frame {
float phase;
Transform transforms[parent.count_bones];
} [[static,format("formatFrame")]];
struct Vector {
float x [[comment("+Left/-Right")]];
float y [[comment("+Up/-Down (UNUSED)")]];
float z [[comment("+Forward/-Backward")]];
} [[static,format("formatVector")]];
struct RTM {
if (std::mem::read_string($, 8) == "RTM_MDAT") {
char properties_signature[8];
padding[4];
u32 count_properties;
Property properties[count_properties];
}
std::assert(std::mem::read_string($, 8) == "RTM_0101", "Missing animation data");
char animation_signature[8];
Vector motion;
u32 count_frames;
u32 count_bones;
Bone bones[count_bones];
Frame frames[count_frames];
std::assert_warn(std::mem::eof(), "Data ended before EOF");
};
fn formatLascii(ref lascii value) {
return std::format("\"{:s}\"", value);
};
fn formatProperty(ref Property prop) {
return std::format("\"{0:s}\" = \"{1:s}\" @ {2:.4f}", prop.name, prop.value, prop.phase);
};
fn transformBone(ref Bone value) {
return std::string::to_string(value.name);
};
fn formatBone(ref Bone value) {
return std::format("\"{0:s}\"", value);
};
fn formatTransform(ref Transform transform) {
return std::format("\"{0:s}\" transform", transform.bone);
};
fn formatFrame(ref Frame frame) {
return std::format("frame @ {0:.4f}", frame.phase);
};
fn formatVector(ref Vector vec) {
return std::format("[{0:.2f}, {1:.2f}, {2:.2f}]", vec.x, vec.y, vec.z);
};
RTM file @ 0x0000;

View File

@@ -0,0 +1,131 @@
#pragma author MrClock
#pragma description Arma 3 texture index file format
#pragma endian little
#pragma MIME application/x.a3-texheaders
fn get_data_description() {
return "TexHeaders.bin files are texture index files used in Arma 3 PBO archives.\nThe files are generated during the PBO packing process, and contain basic information about all the PAA texture files in the PBO.\nThe index for each texture includes the file paths relative to the PBO root, pixel format, suffix, number of mipmaps and their resolutions among other things.";
};
import std.string;
import std.math;
import type.color;
using asciiz = std::string::NullString;
struct BGRA8 {
u8 b;
u8 g;
u8 r;
u8 a;
} [[
static,
sealed,
format("type::impl::format_color"),
color(std::format("{0:02X}{1:02X}{2:02X}", r, g, b))
]];
struct RGBAfloat {
float r [[transform("float2u8")]];
float g [[transform("float2u8")]];
float b [[transform("float2u8")]];
float a [[transform("float2u8")]];
} [[
static,
sealed,
format("type::impl::format_color"),
color(std::format("{0:02X}{1:02X}{2:02X}", r, g, b))
]];
enum PixelFormat: u8 {
INDEXED = 0,
GRAY = 1,
RGB565 = 2,
RGBA5551 = 3,
RGBA4444 = 4,
RGBA8888 = 5,
DXT1 = 6,
DXT2 = 7,
DXT3 = 8,
DXT4 = 9,
DXT5 = 10
};
enum Suffix: u32 {
DIFFUSE = 0,
DIFFUSE_LINEAR = 1,
DETAIL = 2,
NORMAL = 3,
IRRADIANCE = 4,
RANDOM = 5,
TREECROWN = 6,
MACRO = 7,
SHADOW = 8,
SPECULAR = 9,
DITHERING = 10,
DETAIL_SPECULAR = 11,
MASK = 12,
THERMAL = 13
};
struct Mipmap {
u16 width;
u16 height;
padding[2];
PixelFormat format;
padding[1];
u32 offset [[comment("Byte offset in file")]];
} [[static,format("formatMipmap")]];
struct Texture {
u32 count_color_pallets [[comment("Always 1")]];
u32 pallet_pointer [[comment("Always 0")]];
RGBAfloat average_color_float;
BGRA8 average_color;
BGRA8 max_color;
u32 clamp_flags [[comment("Always 0")]];
u32 transparency [[comment("Always 0xffffffff")]];
bool maxcolor_defined [[comment("GGATCXAM was found in PAA")]];
bool alpha_interpolated;
bool alpha_binary;
bool non_opaque [[comment("Interpolated alpha and average alpha < 127")]];
u32 count_mipmaps;
/*
Technically the format is listed as u32 on the community wiki, but
for the sake of reusability in the Mipmap struct, it is broken up into
a u8 + 3 padding bytes here. (The enum values are in the u8 range
anyway.)
*/
PixelFormat format;
padding[3];
bool little_endian [[comment("Always true")]];
bool is_paa [[comment("File is PAA not PAC")]];
asciiz path [[comment("Path relative to texHeaders.bin file")]];
Suffix suffix;
u32 count_mipmaps_again;
Mipmap mipmaps[count_mipmaps];
u32 filesize;
}[[format("formatTexture")]];
struct TexHeaders {
char signature[4];
u32 version [[comment("Always 1")]];
u32 count_textures;
Texture textures[count_textures];
};
fn float2u8(float value) {
return u8(std::math::round(value * 255));
};
fn formatMipmap(ref Mipmap mip) {
return std::format("{0:d} x {1:d}", mip.width, mip.height);
};
fn formatTexture(ref Texture tex) {
return std::format("{0:d} x {1:d} @ {2:s}", tex.mipmaps[0].width, tex.mipmaps[0].height, tex.path);
};
TexHeaders file @ 0x0000;

176
patterns/adtfdat.hexpat Normal file
View File

@@ -0,0 +1,176 @@
#pragma description ADTFDAT File
#pragma magic [ 49 46 48 44 ] @ 0x00
#pragma endian little
import std.io;
import std.mem;
import type.time;
enum FileVersion : u32 {
with_history_end_offset = 0x00000301,
v500 = 0x00000500
};
bitfield ChunkFlags {
key : 1;
info : 1;
marker : 1;
type : 1;
trigger : 1;
reserved: 11;
};
struct Extension
{
char identifier[384];
u16 stream_id;
u8 reserved1[2];
u32 user_id;
u32 type_id;
u32 version_id;
u64 data_pos;
u64 data_size;
u8 reserved[96];
u8 payload[data_size] @ data_pos;
};
struct ChunkHeader {
u64 time_stamp [[format("format_timestamp_with_offset")]];;
u32 ref_master_table_index;
u32 offset_to_last;
u32 size;
u16 stream_id;
ChunkFlags flags;
u64 stream_index;
};
struct SampleInfo {
u8 memory_layout_version;
u32 size;
u8 payload[size];
};
struct Sample {
s64 timestamp [[format("format_timestamp")]];;
s32 flags;
u64 buffer_size;
u8 payload[buffer_size];
if (flags & 0x100) {
SampleInfo sample_info;
}
if (flags & 0x200) {
u32 substream_id;
} else {
u32 substream_id = 0 [[export]];
}
};
struct Chunk {
auto start_address = $;
ChunkHeader header;
if (header.size < 32 || start_address + header.size > std::mem::size()) {
std::warning(std::format("Invalid header size {} in chunk {} at offset 0x{:X}, last valid chunk at 0x{:X}.", header.size, chunk_index, start_address, last_valid_chunk_offset));
break;
}
last_valid_chunk_offset = start_address;
u8 payload[header.size - 32];
if (!skip_valid_chunks) {
if (!header.flags.info && !header.flags.marker && !header.flags.type && !header.flags.trigger) {
try {
Sample sample @ addressof(payload);
} catch {
std::warning(std::format("Invalid sample payload at chunk {} at 0x{:X}", chunk_index, start_address));
}
}
}
chunk_index += 1;
// Padding with 0xEE to the next chunk header
std::mem::AlignTo<16>;
if (skip_valid_chunks) {
continue;
}
};
struct Header {
u32 file_id;
u32 version_id;
u32 flags;
u32 extension_count;
u64 extension_offset;
u64 data_offset;
u64 data_size;
u64 chunk_count;
u64 max_chunk_size;
u64 duration;
type::time64_t filetime;
u8 header_byte_order;
u64 time_offset [[format("format_timestamp")]];
u8 patch_number;
u64 first_chunk_offset;
u64 continuous_offset;
u64 ring_buffer_end_offset;
u8 reserved[30];
char description[1912];
};
struct IndexedFile {
Header header;
Extension extensions[header.extension_count] @ header.extension_offset;
if (header.version_id >= FileVersion::with_history_end_offset &&
header.continuous_offset != header.data_offset) {
try {
Chunk ring_front[while($ < header.continuous_offset)] @ header.first_chunk_offset;
Chunk ring_back[while($ < header.ring_buffer_end_offset)] @ header.data_offset;
Chunk continueous[header.chunk_count - chunk_index] @ header.continuous_offset;
} catch {
std::warning("Too many chunks. Performing check only.");
skip_valid_chunks = true;
chunk_index = 0;
Chunk ring_front[while($ < header.continuous_offset)] @ header.first_chunk_offset;
Chunk ring_back[while($ < header.ring_buffer_end_offset)] @ header.data_offset;
Chunk continueous[while(chunk_index < header.chunk_count)] @ header.continuous_offset;
}
} else {
try {
Chunk chunks[header.chunk_count] @ header.data_offset;
} catch {
std::warning("Too many chunks. Performing check only.");
skip_valid_chunks = true;
chunk_index = 0;
Chunk chunks[while(chunk_index < header.chunk_count)] @ header.data_offset;
}
}
};
fn format_timestamp(u64 data) {
double seconds = 0;
if (file.header.version_id < FileVersion::v500) {
// microseconds
seconds = data / double(1000000);
} else {
// nanoseconds
seconds = data / double(1000000000);
}
std::time::Time time64 = std::time::to_utc(seconds);
return std::time::format(time64);
};
fn format_timestamp_with_offset(u64 data) {
return format_timestamp(data + file.header.time_offset);
};
bool skip_valid_chunks = false;
u64 last_valid_chunk_offset = 0;
u64 chunk_index = 0;
IndexedFile file @ 0x00;

197
patterns/adts.hexpat Normal file
View File

@@ -0,0 +1,197 @@
#pragma author zhoubo
#pragma description AAC ADTSn (Audio Data Transport Stream) Audio
#pragma MIME audio/x-hx-aac-adts
#pragma pattern_limit 0xFFFFFF
// History
// 0.4 2024-02-12 zhoubo: Porting from 010 Editor Templates.
// 0.3 2024-02-09 zhoubo: use BitfieldDisablePadding(Unpadded Bitfields) for odd header bytes(7,9 bytes) color, and remove FSeek.
// 0.2 2024-02-05 zhoubo: fix some comment & color.
// 0.1 2022-06-13 zhoubo: Init release. only ADTS, not support ADIF,LATM.
// More information available at:
// 1. https://wiki.multimedia.cx/index.php?title=ADTS
// 2. https://en.wikipedia.org/wiki/Advanced_Audio_Coding
// 3. https://en.wikipedia.org/wiki/AAC
// 4. https://juejin.cn/post/7032170229732442148
#pragma endian big
#include <std/sys.pat>
#include <std/core.pat>
fn GetMPEGVersionComment(auto MPEG_Version)
{
str comment = "";
match (MPEG_Version)
{
(0): comment = "MPEG-4";
(1): comment = "MPEG-2";
}
return comment;
};
fn GetProtectionAbsentComment(auto Protection_absence)
{
str comment = "";
match (Protection_absence)
{
(0): comment = "ADTS has 9 bytes with CRC";
(1): comment = "ADTS has 7 bytes without CRC";
}
return comment;
};
fn GetProfileComment(auto Profile)
{
str comment = "";
match (Profile)
{
(0x00): comment = "AAC Main";
(0x01): comment = "AAC LC (Low Complexity)";
(0x10): comment = "AAC SSR (Scalable Sample Rate)";
(0x11): comment = "AAC LTP (Long Term Prediction)";
}
return comment;
};
fn GetSamplingFrequencyIndexComment(auto Sampling_frequency_index)
{
str comment = "";
match (Sampling_frequency_index)
{
(0x0): comment = "96000Hz";
(0x1): comment = "88200Hz";
(0x2): comment = "64000Hz";
(0x3): comment = "48000Hz";
(0x4): comment = "44100Hz";
(0x5): comment = "32000Hz";
(0x6): comment = "24000Hz";
(0x7): comment = "22050Hz";
(0x8): comment = "16000Hz";
(0x9): comment = "12000Hz";
(0xa): comment = "11025Hz";
(0xb): comment = "8000Hz";
(0xc): comment = "7350Hz";
(0xd): comment = "Reserved";
(0xe): comment = "Reserved";
(0xf): comment = "FORBIDDEN (malformed)";
}
return comment;
};
fn GetChannelConfigurationComment(auto Channel_configuration)
{
str comment = "";
match (Channel_configuration)
{
(0): comment = "Defined in AOT Specifc Config";
(1): comment = "1 channel: front-center";
(2): comment = "2 channels: front-left, front-right";
(3): comment = "3 channels: front-center, front-left, front-right";
(4): comment = "4 channels: front-center, front-left, front-right, back-center";
(5): comment = "5 channels: front-center, front-left, front-right, back-left, back-right";
(6): comment = "6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel";
(7): comment = "8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel";
}
return comment;
};
fn GetBufferFullnessComment(auto ADTS_buffer_fullness)
{
str comment = "";
match (ADTS_buffer_fullness)
{
(0x7FF): comment = "VBR (most software ignore this field)";
(_): comment = "rate..?? (most software ignore this field)";
}
return comment;
};
fn GetRawDataBlockComment(auto Number_of_AAC_frames_minus_1)
{
str comment = "";
match (Number_of_AAC_frames_minus_1)
{
(0x0): comment = "has 1 AAC data block";
(_): comment = "data block number + 1";
}
return comment;
};
//-----------------------------------
// Define structures used in AAC files
//
// [1.adts_fixed_header information]
// Syncword: 12bits, sync header, always 0xFFF。
// MPEG_Version: 1bit, 0 means MPGE-4, 1 means MPGE-2
// Layer: 2bits, alwayas ”00”
// Protection_absence: 1bit, 0 means ADTS Header 9 bytes; 1 means ADTS Header 7 bytes
// Profile: 2bit, AAC level : Main,LC,SSR,LTP
// Sampling_frequency_index: 4bits, Sampling Frequencies
// Private_bit: 1bit
// Channel_configuration: 3bits, channel number...
// Originality: 1bit
// Home: 1bit
//
// [2.adts_variable_header information]
// Copyright_id_bit: 1bit
// Copyright_id_start: 1bit
// AAC_frame_length: 13bits, AAC frame length : ADTS Header(7 or 9 bytes) + sizeof(AAC Frame)
// ADTS_buffer_fullness: 11bits, 0x7FF means VBR
// Number_of_AAC_frames_minus_1: 2bits, ADTS Frame numbers : Number_of_AAC_frames_minus_1 + 1
//
// [3.CRC information]
// CRC16: 16bits, when Protection_absence=0
bitfield ADTS_HEADER
{
// ADTS_FIXED_HEADER
Syncword : 12 [[color("00FF00"), comment("always 0xFFF")]];
MPEG_Version : 1 [[color("00FF00"), comment(GetMPEGVersionComment(this))]];
Layer : 2 [[color("00FF00"), comment("always 0")]];
Protection_absence : 1 [[color("00FF00"), comment(GetProtectionAbsentComment(this))]];
Profile : 2 [[color("0000FF"), comment(GetProfileComment(this))]];
Sampling_frequency_index : 4 [[color("0000FF"), comment(GetSamplingFrequencyIndexComment(this))]];
Private_bit : 1 [[color("0000FF")]];
Channel_configuration : 3 [[color("0000FF"), comment(GetChannelConfigurationComment(this))]];
Originality : 1 [[color("0000FF")]];
Home : 1 [[color("0000FF")]];
// ADTS_VARIABLE_HEADER
Copyright_id_bit : 1 [[color("0000FF")]];
Copyright_id_start : 1 [[color("0000FF")]];
AAC_frame_length : 13 [[color("0000FF")]];
ADTS_buffer_fullness : 11 [[color("0000FF"), comment(GetBufferFullnessComment(this))]];
Number_of_AAC_frames_minus_1 : 2 [[color("0000FF"), comment(GetRawDataBlockComment(this))]];
// ADTS_CRC_HEADER
if (0 == Protection_absence) // Header with CRC
{
u16 CRC16 [[color("FFFF00")]];
}
else // Header without CRC
{
}
};
struct ADTS_FRAME
{
ADTS_HEADER Header;
if (0 == Header.Protection_absence) // Header with CRC 2 bytes
{
u8 Data[Header.AAC_frame_length - 9] [[color("000000")]];
}
else // Header without CRC
{
u8 Data[Header.AAC_frame_length - 7] [[color("000000")]];
}
};
//---------------------------------------------
ADTS_FRAME adtsFrame[while(!std::mem::eof())] @ 0x00;

View File

@@ -1,7 +1,14 @@
#pragma author WerWolv
#pragma description Nintendo Switch Atmosphère CFW Fatal Error log
#pragma magic [ 41 46 45 30 ] @ 0x00
#pragma magic [ 41 46 45 31 ] @ 0x00
#pragma magic [ 41 46 45 32 ] @ 0x00
#pragma endian little
#include <std/io.pat>
#include <std/sys.pat>
import std.io;
import std.sys;
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC "AFE2"
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_1 "AFE1"
@@ -49,8 +56,8 @@ std::assert(ctx.magic == ATMOSPHERE_REBOOT_TO_FATAL_MAGIC ||
ctx.magic == ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_1 ||
ctx.magic == ATMOSPHERE_REBOOT_TO_FATAL_MAGIC_0,
"File is not a valid Atmosphere fatal error binary!");
std::assert_warn(ctx.magic == ATMOSPHERE_REBOOT_TO_FATAL_MAGIC,
std::assert_warn(ctx.magic == ATMOSPHERE_REBOOT_TO_FATAL_MAGIC,
"Atmosphere fatal error binary is for an older version!");

71
patterns/ani.hexpat Normal file
View File

@@ -0,0 +1,71 @@
#pragma description Windows animated cursor
#pragma MIME application/x-navi-animation
#pragma endian little
import std.io;
import std.mem;
bitfield HeaderFlags {
icon : 1;
sequence : 1;
padding: 30;
};
struct anih {
u32 struct_size;
u32 stored_frames;
u32 animation_steps;
u32 w;
u32 h;
u32 bits;
u32 planes;
u32 default_jiffies;
HeaderFlags flags;
};
struct rate {
u32 jiffies[parent.size / 4];
};
struct seq {
u32 index[parent.size / 4];
};
struct RiffChunk {
char signature[4];
u32 size;
if (signature == "RIFF" || signature == "LIST") {
char type[4];
// Compatible with error size defined in ani files
u32 remain = sizeof($) - addressof(type);
u32 marked = size > remain ? remain : size;
RiffChunk chunks[while($ - addressof(type) < marked)];
} else if (signature[0] == 'I' && parent.type == "INFO") {
char info[size];
} else if (signature == "anih") {
anih anih [[inline]];
} else if (signature == "rate") {
rate rate [[inline]];
} else if (signature == "seq ") {
seq seq [[inline]];
} else {
std::mem::Bytes<size> data;
}
padding[size % 2];
} [[format_read("read_chunk")]];
fn read_chunk(RiffChunk chunk) {
if (chunk.signature == "RIFF" || chunk.signature == "LIST") {
return std::format("{}<{}> ({})", chunk.signature, chunk.type, chunk.size);
} else {
str ret = std::format("{} ({})", chunk.signature, chunk.size);
try {
ret += std::format(" \"{}\"", chunk.info);
} catch {}
return ret;
}
};
RiffChunk riff @ 0;

View File

@@ -0,0 +1,50 @@
#pragma author Lexi Mayfield
#pragma description AppleSingle/AppleDouble file format
#pragma endian big
#pragma magic [00 05 16 0?] @ 0x00
import type.magic;
enum EntryID : u32 {
DataFork = 1,
ResourceFork = 2,
RealName = 3,
Comment = 4,
IconBW = 5,
IconColor = 6,
FileDatesInfo = 8,
FinderInfo = 9,
MacFileInfo = 10,
ProDOSFileInfo = 11,
MSDOSFileInfo = 12,
ShortName = 13,
AFPFileInfo = 14,
DirectoryID = 15,
};
struct Entry {
EntryID entryID;
u32 offset;
u32 length;
u8 data[length] @ offset [[sealed]];
};
enum FileType : u32 {
AppleSingle = 0x00051600,
AppleDouble = 0x00051607,
};
enum Version : u32 {
V1 = 0x00010000,
V2 = 0x00020000,
};
struct AppleSingleDouble {
FileType fileType;
Version version;
char homeFileSystem[16];
u16 numEntries;
Entry entryDescs[numEntries];
};
AppleSingleDouble appleSingleDouble @ 0x00;

View File

@@ -1,8 +1,11 @@
#pragma author WerWolv
#pragma description GNU Static library archive
#pragma MIME application/x-archive
#include <std/string.pat>
#include <std/mem.pat>
#include <std/sys.pat>
import std.string;
import std.mem;
import std.sys;
struct ARFile {
char file_name[16];
@@ -12,7 +15,7 @@ struct ARFile {
char file_mode[8];
char file_size[10];
u16 end_marker;
if (end_marker == 0x0A60) {
u8 data[std::string::parse_int(this.file_size, 10)];
padding[sizeof(data) & 1];
@@ -20,6 +23,9 @@ struct ARFile {
};
char signature[8] @ 0x00;
if (signature == "!<arch>\r") {
std::error("Archive file got corrupted due to CRLF line ending conversion!");
}
std::assert(signature == "!<arch>\n", "File is not a valid archive!");
ARFile files[while($ < std::mem::size())] @ $;

26
patterns/arc.hexpat Normal file
View File

@@ -0,0 +1,26 @@
#pragma author DexrnZacAttack
#pragma description Minecraft LCE ARC File
#pragma endian big
import std.string;
#ifdef __IMHEX__
import hex.core;
#endif
struct Table {
u16 nameSize;
char fileName[nameSize];
u32 offset;
u32 size;
u8 file[size] @ offset;
#ifdef __IMHEX__
hex::core::add_virtual_file(fileName, file);
#endif
} [[name(std::string::to_string(fileName))]];
struct ARC {
u32 count;
Table table[count];
};
ARC arc @ 0x00;

36
patterns/aria2.hexpat Normal file
View File

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

View File

@@ -1,7 +1,10 @@
#pragma author WerWolv
#pragma description ARM Cortex M Vector Table Layout
#pragma endian little
#include <std/io.pat>
#include <std/mem.pat>
import std.io;
import std.mem;
#define VTOR 0x00000000
#define EXTERNAL_INTERRUPT_COUNT 64
@@ -37,21 +40,21 @@ VectorTable vector_table @ VTOR;
fn main() {
u32 table_size = sizeof(vector_table);
u32 default_handler_address = 0x00;
for (u32 i = 4, i < table_size, i = i + 4) {
u32 occurrences = 0;
for (u32 j = 4, j < table_size, j = j + 4) {
if (std::mem::read_unsigned(i, 4) == std::mem::read_unsigned(j, 4)) {
occurrences = occurrences + 1;
if (occurrences > 1)
default_handler_address = std::mem::read_unsigned(i, 4);
}
}
}
if (default_handler_address != 0x00)
std::print("Default Handler implementation at 0x{:08X}", default_handler_address);
};

1
patterns/bastion Submodule

Submodule patterns/bastion added at e6deed433c

168
patterns/bcss.hexpat Normal file
View File

@@ -0,0 +1,168 @@
#pragma author ttimasdf
#pragma description BeyondCompare Snapshot (BCSS) file
#pragma magic [42 43 53 53] @ 0x00
#pragma array_limit 4294967295
#pragma pattern_limit 4294967295
import std.io;
import std.mem;
import std.array;
import std.string;
import type.magic;
#ifdef __IMHEX__
import hex.dec;
import hex.core;
#endif
const u8 max_path_size = 1000;
str current_path[max_path_size];
u8 current_path_level = 0;
enum EntryType : u8 {
DIRECTORY = 0x01,
FILE = 0x02,
SYMLINK = 0x03,
// NULL = 0x00,
DIR_END = 0xFF,
};
struct BCSSEntry {
EntryType type;
match (type) {
(EntryType::DIRECTORY) : {
// FileName name;
std::string::SizedString<u8> name;
if (name.size != 0) {
u8 unknown[12];
on_dir_enter(name.data); // std::string::to_string(name)
} else {
// some buggy edge cases
u8 unknown[6];
std::warning(std::format("invalid empty entry current_lvl={} current_pos=0x{:02x}", current_path_level, $));
}
}
(EntryType::FILE) : {
std::string::SizedString<u8> name;
if (name.size != 0) {
u8 unknown[20];
#ifdef __IMHEX__
hex::core::add_virtual_file(get_vfs_path(name), this); // std::string::to_string(name)
#endif
} else {
// some buggy edge cases
u8 unknown[6];
std::warning(std::format("invalid empty entry current_lvl={} current_pos=0x{:02x}", current_path_level, $));
}
//try {
// u8 unknown[20];
//} catch {
// u8 unknown[0];
//}
}
(EntryType::SYMLINK) : {
std::string::SizedString<u8> name;
u8 unknown[23];
std::string::SizedString<u8> target;
#ifdef __IMHEX__
hex::core::add_virtual_file(get_vfs_path(name + " [s]"), this); // std::string::to_string(name)
#endif
}
(EntryType::DIR_END) : {
on_dir_exit();
}
// (EntryType::NULL) : {
// // some buggy edge cases
// u8 unknown[7];
// std::warning(std::format("invalid empty entry current_lvl={} current_pos=0x{:02x}", current_path_level, $));
// }
(_): {
std::error(std::format("unknown EntryType idx={} current_pos=0x{:02x}", std::core::array_index(), $));
}
}
}[[format_read("fmt_BCSSEntry")]];
fn on_dir_enter(str folder_name) {
// std::print("on_dir_enter folder={} current_lvl={}", folder_name, current_path_level);
if (std::string::length(folder_name) > 0) {
current_path[current_path_level] = folder_name;
current_path_level += 1;
} else {
std::warning(std::format("invalid folder name {} current_lvl={} current_pos=0x{:02x}", folder_name, current_path_level, $));
}
};
fn on_dir_exit() {
if (current_path_level > 0) {
current_path_level -= 1;
} else if (!std::mem::eof()) {
std::warning(std::format("on_dir_exit current_lvl already == 0 current_pos=0x{:02x}", $));
}
// std::print("on_dir_exit current_lvl={}", current_path_level);
};
fn get_vfs_path(str file_name) {
str vfs_path = "";
if (current_path_level > 0) {
vfs_path = current_path[0];
for(u8 i = 1, i < current_path_level, i += 1) {
//hash_hex = hash_hex + std::format("{:02X}",bytes[i]);
vfs_path = vfs_path + "/" + current_path[i];
}
return vfs_path + "/" + file_name;
} else {
return file_name;
}
};
fn fmt_BCSSEntry(BCSSEntry e) {
try {
match (e.type) {
(EntryType::DIRECTORY | EntryType::FILE) : {
return std::format("{}: {}", (e.type == EntryType::DIRECTORY ? "Dir" : "File"), e.name.data);
}
(EntryType::SYMLINK) : {
return std::format("Symlink: {} -> {}", e.name.data, e.target.data);
}
(EntryType::DIR_END) : {
return "Directory End";
}
}
} catch {
return "[FmtErr]";
}
};
struct BCSSFile {
if (std::mem::read_unsigned(0, 4) == 0x53534342) {
type::Magic<"BCSS"> magic;
u8 unknown[14];
std::string::SizedString<u16> root_path;
u8 zlib_content[std::mem::size()-$];
// manually add zlib header which is essential for hex::dec::zlib_decompress
const str zlib_header = "\x78\x9c";
std::mem::Section zlib_compressed = std::mem::create_section("zlib_compressed");
std::mem::copy_value_to_section(zlib_header, zlib_compressed, 0);
std::mem::copy_value_to_section(zlib_content, zlib_compressed, 2);
u8 zlib[std::mem::get_section_size(zlib_compressed)] @ 0x00 in zlib_compressed;
#ifdef __IMHEX__
std::mem::Section zlib_decompressed = std::mem::create_section("zlib_decompressed");
hex::dec::zlib_decompress(zlib, zlib_decompressed, 15);
u8 decompressed_content[std::mem::get_section_size(zlib_decompressed)] @ 0x00 in zlib_decompressed;
hex::core::add_virtual_file("bcss_content", decompressed_content);
std::warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n! BCSS file content is compressed !\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\nopen `bcss_content` file from the Virtual Filesystem tab and run this pattern on it.");
#endif
} else {
BCSSEntry entries[while(!std::mem::eof())];
}
};
BCSSFile bcss_file @ 0x00;

View File

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

101
patterns/bgcode.hexpat Normal file
View File

@@ -0,0 +1,101 @@
#pragma author Shadlock0133 (aka Aurora) / WerWolv
#pragma description Prusa Binary G-Code
#pragma magic [ 47 43 44 45 ] @ 0x00
import type.magic;
import std.mem;
enum ChecksumType : u16 {
None = 0,
CRC32 = 1
};
enum BlockType : u16 {
FileMetadata = 0,
GCode = 1,
SlicerMetadata = 2,
PrinterMetadata = 3,
PrintMetadata = 4,
Thumbnail = 5
};
enum CompressionType : u16 {
NoCompression = 0,
Deflate = 1,
HeatshrinkWindowSize11 = 2,
HeatshrinkWindowSize12 = 3
};
struct BlockHeader {
BlockType type;
CompressionType compressionType;
u32 uncompressedSize;
if (compressionType != CompressionType::NoCompression) {
u32 compressedSize;
}
u32 dataSize = compressionType == CompressionType::NoCompression ? uncompressedSize : compressedSize;
};
enum Encoding : u16 {
INI = 0
};
struct Metadata {
Encoding encoding;
char data[parent.header.dataSize];
};
enum ImageFormat : u16 {
PNG = 0,
JPG = 1,
QOI = 2
};
struct Thumbnail {
ImageFormat format;
u16 width, height;
std::mem::Bytes<parent.header.dataSize> imageData;
} [[hex::visualize("image", imageData)]];
enum GCodeEncoding : u16 {
NoEncoding = 0,
MeatPack = 1,
MeatPackWithComments = 2
};
struct GCode {
GCodeEncoding encoding;
std::mem::Bytes<parent.header.dataSize> gcode;
};
struct Block {
BlockHeader header;
match (header.type) {
(BlockType::FileMetadata): Metadata fileMetadata;
(BlockType::PrinterMetadata): Metadata printerMetadata;
(BlockType::Thumbnail): Thumbnail thumbnail;
(BlockType::PrintMetadata): Metadata printMetadata;
(BlockType::SlicerMetadata): Metadata slicerMetadata;
(BlockType::GCode): GCode gcode;
(_): std::error("Invalid Block type!");
}
if (parent.checksumType != ChecksumType::None)
u32 checksum;
};
struct BGCode {
type::Magic<"GCDE"> magic;
u32 version;
std::assert(version == 1, "Only Version 1 is supported");
ChecksumType checksumType;
Block blocks[while(!std::mem::eof())];
};
BGCode bgcode @ 0x00;

24
patterns/binka.hexpat Normal file
View File

@@ -0,0 +1,24 @@
#pragma author DexrnZacAttack
#pragma description RAD Game Tools BINKA (Bink Audio)
#pragma magic [31 46 43 42] @ 0x00
import std.string;
import std.math;
import type.magic;
fn getDuration(u32 duration_ts, u32 sample_rate) {
return float(duration_ts) / float(sample_rate);
};
struct Binka {
type::Magic<"1FCB"> magic;
u8; // can't get this to change anything when using ffprobe
u8 channel_count [[name(std::format("Channel Count: {}", this))]];
u16 sample_rate [[name(std::format("Sample Rate: {}", this))]];
u32 duration_ts [[name(std::format("Duration: {}s", std::math::floor(getDuration(this, sample_rate))))]];
u32;
u32 size [[name(std::format("File Size: {} bytes", this))]];
u8 data[size - 20];
};
Binka binka @ 0x00;

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