mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-31 05:15:54 -05:00
Compare commits
274 Commits
ImHex-v1.3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a534e2a23b | ||
|
|
525f3ad4d6 | ||
|
|
27480b1da9 | ||
|
|
6a2a963a5a | ||
|
|
cee3a5de77 | ||
|
|
fb84bbb5d1 | ||
|
|
097ab49cae | ||
|
|
5a04a4256b | ||
|
|
8a9bd577ad | ||
|
|
190f9d891b | ||
|
|
2d92bfca13 | ||
|
|
0e4040fae1 | ||
|
|
57c3dd44b8 | ||
|
|
4646e4b965 | ||
|
|
9143996589 | ||
|
|
7c3dcc1fcc | ||
|
|
ea8b381ac5 | ||
|
|
998655f74a | ||
|
|
681b208aab | ||
|
|
64d86cbdd1 | ||
|
|
285a2fc7d1 | ||
|
|
2a9676238f | ||
|
|
ee340409db | ||
|
|
84dff0c886 | ||
|
|
28a297582b | ||
|
|
681b1a1ded | ||
|
|
0a09efdd20 | ||
|
|
0d8bd76c2c | ||
|
|
a525160243 | ||
|
|
c3946d33a7 | ||
|
|
cc7eb7d764 | ||
|
|
53384a4a54 | ||
|
|
da005f0172 | ||
|
|
b2f126d22f | ||
|
|
7ea863269e | ||
|
|
faff9e0364 | ||
|
|
a35004665f | ||
|
|
4fc11f1b91 | ||
|
|
7a9a5097a2 | ||
|
|
0e67ee102b | ||
|
|
69077b919d | ||
|
|
297f611fed | ||
|
|
b24ae36638 | ||
|
|
50d776f497 | ||
|
|
7dfacc4139 | ||
|
|
5359e385ea | ||
|
|
75bcb487ee | ||
|
|
fb214600ec | ||
|
|
d95390ea42 | ||
|
|
284ca8d325 | ||
|
|
6630180276 | ||
|
|
ff68d1e23d | ||
|
|
70dd55aa6b | ||
|
|
76f850c543 | ||
|
|
74c06b74f7 | ||
|
|
f13d9d3894 | ||
|
|
c4c75a9ab2 | ||
|
|
7278a22eb2 | ||
|
|
91fd36097c | ||
|
|
afffd7eced | ||
|
|
7fd79ec9fd | ||
|
|
6b9f39cc21 | ||
|
|
9207282bcf | ||
|
|
5ed64f9f08 | ||
|
|
a75a7a5b98 | ||
|
|
60c8d93449 | ||
|
|
d3b05fd753 | ||
|
|
3b2f098b09 | ||
|
|
f4f004f0eb | ||
|
|
5c6cb9dccc | ||
|
|
44717e9b19 | ||
|
|
bc35349e0f | ||
|
|
fed5db4109 | ||
|
|
1d41392215 | ||
|
|
0b75336638 | ||
|
|
e3edbd5a6f | ||
|
|
b10a37af67 | ||
|
|
103d434cc5 | ||
|
|
7716b9d6e7 | ||
|
|
ad1e300674 | ||
|
|
e918ce52b9 | ||
|
|
db4d62aa20 | ||
|
|
d96bfbb942 | ||
|
|
2070c95f58 | ||
|
|
877895741d | ||
|
|
6b279b8375 | ||
|
|
a692b22ecc | ||
|
|
2ae0499293 | ||
|
|
bd06987e8e | ||
|
|
74e08623f1 | ||
|
|
a860c396fa | ||
|
|
da934e2045 | ||
|
|
394ef80611 | ||
|
|
2ce182b1b3 | ||
|
|
6cadad3d1f | ||
|
|
7ad9cd4f41 | ||
|
|
bcaeef31d7 | ||
|
|
ee8d2f50b7 | ||
|
|
5b8dde19a9 | ||
|
|
0b0eff0cb6 | ||
|
|
3185503be1 | ||
|
|
3a64207e58 | ||
|
|
c94d42d5c0 | ||
|
|
45c4c1d35b | ||
|
|
f93be1ea06 | ||
|
|
5ed9c0fd4d | ||
|
|
11d373319f | ||
|
|
e7d366571d | ||
|
|
b6df1742b6 | ||
|
|
0b9e83ff8a | ||
|
|
c0fc748de6 | ||
|
|
89307ba8a5 | ||
|
|
a12b5ba406 | ||
|
|
537ce67895 | ||
|
|
1771c1f077 | ||
|
|
cef20e24a7 | ||
|
|
8e7cfd9442 | ||
|
|
d0ba754dc2 | ||
|
|
9f92c38ecf | ||
|
|
0844e07056 | ||
|
|
66fc006b08 | ||
|
|
5bc66df14f | ||
|
|
7310a10214 | ||
|
|
34ee3107e2 | ||
|
|
c4378ffb14 | ||
|
|
5ad7f0c1e7 | ||
|
|
df97fc7257 | ||
|
|
3ad263783d | ||
|
|
5ccd431320 | ||
|
|
fb8e5e3f77 | ||
|
|
375145e759 | ||
|
|
71eeed981d | ||
|
|
e779b88a58 | ||
|
|
aef3d3451f | ||
|
|
c5fa53dcea | ||
|
|
9a6cbdfe28 | ||
|
|
083042632d | ||
|
|
4d172cebc3 | ||
|
|
53ff0a5d62 | ||
|
|
b3b730c6e9 | ||
|
|
8db011b6e5 | ||
|
|
b936c04d21 | ||
|
|
bf56d4ff49 | ||
|
|
fdc4a87389 | ||
|
|
1f6c701348 | ||
|
|
4092dad428 | ||
|
|
559faebec3 | ||
|
|
cde46e1f15 | ||
|
|
17c200a92e | ||
|
|
384d4c7794 | ||
|
|
37a7e59c06 | ||
|
|
e8cea09477 | ||
|
|
883433b260 | ||
|
|
2db9993cb1 | ||
|
|
01ce565c9e | ||
|
|
b7b949ea27 | ||
|
|
e026ff187e | ||
|
|
63504f59a1 | ||
|
|
6113df643d | ||
|
|
3f42dddd19 | ||
|
|
2cc8868727 | ||
|
|
7f02510762 | ||
|
|
13c4168af0 | ||
|
|
1e69cd7fb2 | ||
|
|
16a87df2ac | ||
|
|
b7598405b5 | ||
|
|
d14f8de459 | ||
|
|
4c96bfbeb3 | ||
|
|
500a3fe26e | ||
|
|
5ffc583640 | ||
|
|
b9f5f1668b | ||
|
|
4c22f28a67 | ||
|
|
6f9b05b853 | ||
|
|
c533017d0b | ||
|
|
221fa70a67 | ||
|
|
661e5b7081 | ||
|
|
7d0bbd1e24 | ||
|
|
55aca93a18 | ||
|
|
255116a587 | ||
|
|
79e25fdb73 | ||
|
|
c8d9a8deb7 | ||
|
|
1d680fbf5e | ||
|
|
bc5a55affe | ||
|
|
85f5541350 | ||
|
|
61d3e110fb | ||
|
|
af957389c2 | ||
|
|
e85645897e | ||
|
|
abc78d1644 | ||
|
|
46e41db0a8 | ||
|
|
c67dc84911 | ||
|
|
323898d083 | ||
|
|
abbd25e7f6 | ||
|
|
c8ebb3eb8a | ||
|
|
bf94cb7243 | ||
|
|
6697fc23a4 | ||
|
|
8a6bb6612b | ||
|
|
1d66949375 | ||
|
|
7c65d51986 | ||
|
|
d961271c5d | ||
|
|
26d48df7dd | ||
|
|
8f1f4911a0 | ||
|
|
1d7cc537ed | ||
|
|
62ceaae09b | ||
|
|
4a8a6cba1b | ||
|
|
c3eb9e4126 | ||
|
|
a263347414 | ||
|
|
204599a70b | ||
|
|
bf6ee6d02f | ||
|
|
0125ec2c57 | ||
|
|
c5aaac25dd | ||
|
|
196011ead9 | ||
|
|
5b15136ea4 | ||
|
|
59c954ae28 | ||
|
|
8a5cb1061b | ||
|
|
120bc84548 | ||
|
|
0e17355db0 | ||
|
|
6aee524d1a | ||
|
|
b42c571d4d | ||
|
|
71e1ad8df7 | ||
|
|
5c7d77b50f | ||
|
|
a746ecb164 | ||
|
|
569e5c4c1a | ||
|
|
0316f2b667 | ||
|
|
196695e37b | ||
|
|
bced518508 | ||
|
|
2f795fc23c | ||
|
|
5ff783d571 | ||
|
|
4299243e95 | ||
|
|
23b3c2b5d0 | ||
|
|
da1c2687e8 | ||
|
|
18f968df5b | ||
|
|
f797c711ca | ||
|
|
5380877da4 | ||
|
|
bb46276bde | ||
|
|
4242869ac1 | ||
|
|
8bdcd814a9 | ||
|
|
d7811ff5e9 | ||
|
|
4d0b3e21bc | ||
|
|
acd6903b21 | ||
|
|
8d2a39f7d4 | ||
|
|
65ef3a7783 | ||
|
|
21a0b99eac | ||
|
|
a33b68921d | ||
|
|
a0bb71be58 | ||
|
|
c7fc39ac19 | ||
|
|
b540ead0ae | ||
|
|
26878548f0 | ||
|
|
e4c9d86755 | ||
|
|
2a3de1b705 | ||
|
|
e02280f9ee | ||
|
|
bbba68cef7 | ||
|
|
28b281b403 | ||
|
|
c807959d75 | ||
|
|
3416d30f2b | ||
|
|
10bf1c76cf | ||
|
|
5b7c212029 | ||
|
|
1c2e948940 | ||
|
|
7ea34e410a | ||
|
|
56950e44d8 | ||
|
|
ed42452fc1 | ||
|
|
a68ecb8888 | ||
|
|
8d4cf59497 | ||
|
|
3c2fed22e4 | ||
|
|
ff550bd105 | ||
|
|
0ad6e3abde | ||
|
|
891968db53 | ||
|
|
5799d1d7ea | ||
|
|
9c6bfeb50f | ||
|
|
9f7cdded6a | ||
|
|
03298b0b0c | ||
|
|
5f2738872e | ||
|
|
63585e6de7 | ||
|
|
cb6caafa64 | ||
|
|
236fadee47 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,4 +1,4 @@
|
||||
*.pat linguist-language=Rust
|
||||
*.hexpat linguist-language=Rust
|
||||
|
||||
tests/patterns/test_data/* binary
|
||||
tests/patterns/test_data/** binary
|
||||
|
||||
@@ -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
|
||||
|
||||
10
.github/workflows/dispatch.yml
vendored
10
.github/workflows/dispatch.yml
vendored
@@ -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,7 +45,7 @@ jobs:
|
||||
repo: Documentation
|
||||
owner: WerWolv
|
||||
event_type: update_pl_docs
|
||||
|
||||
|
||||
- name: ✉️ Update PatternLanguage Website
|
||||
if: ${{ env.DISPATCH_TOKEN != '' }}
|
||||
uses: mvasigh/dispatch-action@main
|
||||
|
||||
61
.github/workflows/tests.yml
vendored
61
.github/workflows/tests.yml
vendored
@@ -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,56 +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
|
||||
# env:
|
||||
# NODE_OPTIONS: --max-old-space-size=8000
|
||||
# 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
12
.gitignore
vendored
@@ -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
|
||||
42
CMakeLists.txt
Normal file
42
CMakeLists.txt
Normal 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()
|
||||
@@ -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.
|
||||
|
||||
183
README.md
183
README.md
@@ -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
|
||||
@@ -24,105 +25,227 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
|------|------|------|-------------|
|
||||
| 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 |
|
||||
| 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 | | [`patterns/bplist.hexpat`](patterns/bplist.hexpat) | Apple's binary property list format (bplist) |
|
||||
| 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 |
|
||||
| CDA | | [`patterns/cda.hexpat`](patterns/cda.hexpat) | Compact Disc Audio track |
|
||||
| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log |
|
||||
| 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 | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System |
|
||||
| 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 |
|
||||
| GB | `application/x-gameboy-rom` | [`patterns/gb.hexpat`](patterns/gb.hexpat) | Gameboy ROM |
|
||||
| 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 Bitmap || [`patterns/hinf_bitmap.hexpat`](patterns/hinf_bitmap.hexpat) | Halo Infinite Bitmap tag files |
|
||||
| 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 | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system |
|
||||
| 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 |
|
||||
| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
|
||||
| nes | | [`patterns/nes.hexpat`](patterns/nes.hexpat) | .nes file format |
|
||||
| NotepadWindowState | | [`patterns/notepad-windowstate.hexpat`](patterns/notepad-windowstate.hexpat) | Windows 11 Notepad - Window State .bin file |
|
||||
| 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 |
|
||||
| PP | | [`patterns/selinuxpp.hexpat`](patterns/selinuxpp.pat) | SE Linux package |
|
||||
| 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 |
|
||||
| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files |
|
||||
| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO |
|
||||
| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding |
|
||||
| PyInstaller | | [`patterns/pyinstaller.hexpat`](patterns/pyinstaller.hexpat) | PyInstaller binray files |
|
||||
| PYC | | [`patterns/pyc.hexpat`](patterns/pyc.hexpat) | Python bytecode files |
|
||||
| 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 |
|
||||
| RAS | `image/x-sun-raster` | [`patterns/ras.hexpat`](patterns/ras.hexpat) | RAS image files |
|
||||
| ReFS | | [`patterns/refs.hexpat`](patterns/refs.hexpat) | Microsoft Resilient File System |
|
||||
| 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 |
|
||||
| SWF | |[`patterns/swf.hexpat`](patterns/swf.hexpat) | Shockwave Flash file format |
|
||||
| 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 |
|
||||
| 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
|
||||
| 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 cardridge ROM |
|
||||
| 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 | | [`patterns/xilinx_bootgen.hexpat`](patterns/xilinx_bootgen.hexpat) | Xilinx ZynqMP Boot Images |
|
||||
| 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
|
||||
|
||||
@@ -149,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
|
||||
|
||||
@@ -200,15 +324,16 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
| Turkish Windows | [`encodings/turkish_windows.tbl`](encodings/turkish_windows.tbl) | Turkish Windows encoding |
|
||||
| UTF-8 | [`encodings/utf8.tbl`](encodings/utf8.tbl) | UTF-8 encoding |
|
||||
| Vietnamese | [`encodings/vietnamese.tbl`](encodings/vietnamese.tbl) | Vietnamese character encoding |
|
||||
> import custom encoding from File -> Import... -> Custome Encoding File
|
||||
|
||||
### 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 |
|
||||
@@ -217,3 +342,11 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
| 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 |
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -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)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
730
disassemblers/8051.json
Normal 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
1045
disassemblers/jvm.json
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
21887
encodings/gbk.tbl
Normal file
21887
encodings/gbk.tbl
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -37,4 +37,14 @@ namespace auto hex::core {
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace auto hex::dec {
|
||||
@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 true if successful, false otherwise
|
||||
@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);
|
||||
@@ -60,5 +60,16 @@ namespace auto hex::dec {
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -7,11 +7,11 @@ import hex.impl.imhex_check;
|
||||
*/
|
||||
|
||||
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 auto 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);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
28
includes/hex/type/encstr.pat
Normal file
28
includes/hex/type/encstr.pat
Normal 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;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
143
includes/hex/type/instruction.pat
Normal file
143
includes/hex/type/instruction.pat
Normal 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;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
66
includes/hex/type/json.pat
Normal file
66
includes/hex/type/json.pat
Normal 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]];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,20 +11,20 @@ import hex.dec;
|
||||
*/
|
||||
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
import std.sys;
|
||||
import std.core;
|
||||
|
||||
/*!
|
||||
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 auto std {
|
||||
@@ -26,10 +43,20 @@ namespace auto std {
|
||||
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) {
|
||||
|
||||
72
includes/std/attrs.pat
Normal file
72
includes/std/attrs.pat
Normal 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]];
|
||||
|
||||
}
|
||||
@@ -3,61 +3,65 @@
|
||||
import std.limits;
|
||||
|
||||
/*!
|
||||
This library contains various helper functions for common bit operations.
|
||||
This library contains various helper functions for common bit operations.
|
||||
*/
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -56,17 +56,17 @@ namespace auto std::core {
|
||||
|
||||
|
||||
/**
|
||||
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();
|
||||
@@ -159,9 +159,34 @@ namespace auto std::core {
|
||||
/**
|
||||
Changes the comment attached to a pattern
|
||||
@param pattern The pattern to modify
|
||||
@param name The new comment of the pattern
|
||||
@param comment The new comment of the pattern
|
||||
*/
|
||||
fn set_pattern_comment(ref auto pattern, str comment) {
|
||||
builtin::std::core::set_pattern_comment(pattern, name);
|
||||
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();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace auto std::ctype {
|
||||
@return True if `c` is part of this range, false otherwise
|
||||
*/
|
||||
fn isprint(char c) {
|
||||
return c >= '0' && c <= '~';
|
||||
return c >= ' ' && c <= '~';
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 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 or Pattern 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, auto 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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 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 s128((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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,18 +6,60 @@
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -9,21 +9,21 @@ 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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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 auto std::limits {
|
||||
|
||||
/**
|
||||
Returns the minimum value that can be stored in a `u8`.
|
||||
@return Minimum value
|
||||
*/
|
||||
fn u8_min() {
|
||||
return u8(0);
|
||||
};
|
||||
|
||||
/**
|
||||
Returns the maximum value that can be stored in a `u8`.
|
||||
@return Maximum value
|
||||
*/
|
||||
fn u8_max() {
|
||||
return u8(-1);
|
||||
};
|
||||
|
||||
/**
|
||||
Returns the minimum value that can be stored in a `s8`.
|
||||
@return Minimum value
|
||||
*/
|
||||
/**
|
||||
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));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -3,338 +3,338 @@
|
||||
import std.mem;
|
||||
|
||||
/*!
|
||||
Library containing more advanced mathematical operations.
|
||||
Library containing more advanced mathematical operations.
|
||||
*/
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
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 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;
|
||||
};
|
||||
|
||||
/**
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
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 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;
|
||||
};
|
||||
|
||||
/**
|
||||
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 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);
|
||||
};
|
||||
|
||||
/**
|
||||
Floors the value of `value`.
|
||||
@param value Value
|
||||
@return `value` floored
|
||||
*/
|
||||
fn floor(auto value) { return builtin::std::math::floor(value); };
|
||||
|
||||
/**
|
||||
Ceils the value of `value`.
|
||||
@param value Value
|
||||
@return `value` ceiled
|
||||
*/
|
||||
fn ceil(auto value) { return builtin::std::math::ceil(value); };
|
||||
|
||||
/**
|
||||
Rounds the value of `value`.
|
||||
@param value Value
|
||||
@return `value` rounded
|
||||
*/
|
||||
fn round(auto value) { return builtin::std::math::round(value); };
|
||||
|
||||
/**
|
||||
Truncates the value of `value`.
|
||||
@param value Value
|
||||
@return `value` truncated
|
||||
*/
|
||||
fn trunc(auto value) { return builtin::std::math::trunc(value); };
|
||||
|
||||
|
||||
/**
|
||||
Calculates the logarithm of `value` with base 10.
|
||||
@param value Value
|
||||
@return Logarithm of `value` with base 10
|
||||
*/
|
||||
fn log10(auto value) { return builtin::std::math::log10(value); };
|
||||
|
||||
/**
|
||||
Calculates the logarithm of `value` with base 2.
|
||||
@param value Value
|
||||
@return Logarithm of `value` with base 2
|
||||
*/
|
||||
fn log2(auto value) { return builtin::std::math::log2(value); };
|
||||
|
||||
/**
|
||||
Calculates the natural logarithm of `value`.
|
||||
@param value Value
|
||||
@return Logarithm of `value` with base `e`
|
||||
*/
|
||||
fn ln(auto value) { return builtin::std::math::ln(value); };
|
||||
|
||||
/**
|
||||
Calculates the floating point modulus of `value`.
|
||||
@param value Value
|
||||
@return Floating point modulus of `value`
|
||||
*/
|
||||
fn fmod(auto value) { return builtin::std::math::fmod(value); };
|
||||
|
||||
/**
|
||||
Calculates the value of `base` raised to the power of `exp`.
|
||||
@param base Base
|
||||
@param exp Exponent
|
||||
@return `base` raised to the power of `exp`
|
||||
*/
|
||||
fn pow(auto base, auto exp) { return builtin::std::math::pow(base, exp); };
|
||||
/**
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
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`
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
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 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;
|
||||
};
|
||||
|
||||
/**
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
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 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;
|
||||
};
|
||||
|
||||
/**
|
||||
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 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);
|
||||
};
|
||||
|
||||
/**
|
||||
Floors the value of `value`.
|
||||
@param value Value
|
||||
@return `value` floored
|
||||
*/
|
||||
fn floor(auto value) { return builtin::std::math::floor(value); };
|
||||
|
||||
/**
|
||||
Ceils the value of `value`.
|
||||
@param value Value
|
||||
@return `value` ceiled
|
||||
*/
|
||||
fn ceil(auto value) { return builtin::std::math::ceil(value); };
|
||||
|
||||
/**
|
||||
Rounds the value of `value`.
|
||||
@param value Value
|
||||
@return `value` rounded
|
||||
*/
|
||||
fn round(auto value) { return builtin::std::math::round(value); };
|
||||
|
||||
/**
|
||||
Truncates the value of `value`.
|
||||
@param value Value
|
||||
@return `value` truncated
|
||||
*/
|
||||
fn trunc(auto value) { return builtin::std::math::trunc(value); };
|
||||
|
||||
|
||||
/**
|
||||
Calculates the logarithm of `value` with base 10.
|
||||
@param value Value
|
||||
@return Logarithm of `value` with base 10
|
||||
*/
|
||||
fn log10(auto value) { return builtin::std::math::log10(value); };
|
||||
|
||||
/**
|
||||
Calculates the logarithm of `value` with base 2.
|
||||
@param value Value
|
||||
@return Logarithm of `value` with base 2
|
||||
*/
|
||||
fn log2(auto value) { return builtin::std::math::log2(value); };
|
||||
|
||||
/**
|
||||
Calculates the natural logarithm of `value`.
|
||||
@param value Value
|
||||
@return Logarithm of `value` with base `e`
|
||||
*/
|
||||
fn ln(auto value) { return builtin::std::math::ln(value); };
|
||||
|
||||
/**
|
||||
Calculates the floating point modulus of `value`.
|
||||
@param value Value
|
||||
@return Floating point modulus of `value`
|
||||
*/
|
||||
fn fmod(auto value) { return builtin::std::math::fmod(value); };
|
||||
|
||||
/**
|
||||
Calculates the value of `base` raised to the power of `exp`.
|
||||
@param base Base
|
||||
@param exp Exponent
|
||||
@return `base` raised to the power of `exp`
|
||||
*/
|
||||
fn pow(auto base, auto exp) { return builtin::std::math::pow(base, exp); };
|
||||
|
||||
/**
|
||||
Calculates the value of the natural number `e` raised to the power of `value`.
|
||||
@param value Exponent
|
||||
@return `e` raised to the power of `value`
|
||||
*/
|
||||
fn exp(auto value) { return builtin::std::math::exp(value); };
|
||||
|
||||
/**
|
||||
Calculates the square root of `value`.
|
||||
@param value Value
|
||||
@return Square root of `value`
|
||||
*/
|
||||
fn sqrt(auto value) { return builtin::std::math::sqrt(value); };
|
||||
/**
|
||||
Calculates the square root of `value`.
|
||||
@param value Value
|
||||
@return Square root of `value`
|
||||
*/
|
||||
fn sqrt(auto value) { return builtin::std::math::sqrt(value); };
|
||||
|
||||
/**
|
||||
Calculates the cubic root of `value`.
|
||||
@param value Value
|
||||
@return Cubic root of `value`
|
||||
*/
|
||||
fn cbrt(auto value) { return builtin::std::math::cbrt(value); };
|
||||
/**
|
||||
Calculates the cubic root of `value`.
|
||||
@param value Value
|
||||
@return Cubic root of `value`
|
||||
*/
|
||||
fn cbrt(auto value) { return builtin::std::math::cbrt(value); };
|
||||
|
||||
/**
|
||||
Calculates the sine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Sine of `value`
|
||||
*/
|
||||
fn sin(auto value) { return builtin::std::math::sin(value); };
|
||||
/**
|
||||
Calculates the sine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Sine of `value`
|
||||
*/
|
||||
fn sin(auto value) { return builtin::std::math::sin(value); };
|
||||
|
||||
/**
|
||||
Calculates the cosine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Cosine of `value`
|
||||
*/
|
||||
fn cos(auto value) { return builtin::std::math::cos(value); };
|
||||
/**
|
||||
Calculates the cosine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Cosine of `value`
|
||||
*/
|
||||
fn cos(auto value) { return builtin::std::math::cos(value); };
|
||||
|
||||
/**
|
||||
Calculates the tangent of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Tangent of `value`
|
||||
*/
|
||||
fn tan(auto value) { return builtin::std::math::tan(value); };
|
||||
/**
|
||||
Calculates the tangent of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Tangent of `value`
|
||||
*/
|
||||
fn tan(auto value) { return builtin::std::math::tan(value); };
|
||||
|
||||
/**
|
||||
Calculates the arc sine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Arc sine of `value`
|
||||
*/
|
||||
fn asin(auto value) { return builtin::std::math::asin(value); };
|
||||
/**
|
||||
Calculates the arc sine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Arc sine of `value`
|
||||
*/
|
||||
fn asin(auto value) { return builtin::std::math::asin(value); };
|
||||
|
||||
/**
|
||||
Calculates the arc cosine of `value`.
|
||||
@param value Value
|
||||
@return Arc cosine of `value` in radians
|
||||
*/
|
||||
fn acos(auto value) { return builtin::std::math::acos(value); };
|
||||
/**
|
||||
Calculates the arc cosine of `value`.
|
||||
@param value Value
|
||||
@return Arc cosine of `value` in radians
|
||||
*/
|
||||
fn acos(auto value) { return builtin::std::math::acos(value); };
|
||||
|
||||
/**
|
||||
Calculates the arc tangent of `value`.
|
||||
@param value Value
|
||||
@return Arc tangent of `value` in radians between `-pi/2` and `pi/2`
|
||||
*/
|
||||
fn atan(auto value) { return builtin::std::math::atan(value); };
|
||||
/**
|
||||
Calculates the arc tangent of `value`.
|
||||
@param value Value
|
||||
@return Arc tangent of `value` in radians between `-pi/2` and `pi/2`
|
||||
*/
|
||||
fn atan(auto value) { return builtin::std::math::atan(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 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 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 sine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Hyperbolic sine of `value`
|
||||
*/
|
||||
fn sinh(auto value) { return builtin::std::math::sinh(value); };
|
||||
|
||||
/**
|
||||
Calculates the hyperbolic cosine of `value`.
|
||||
@param value Angle value in radians
|
||||
@return Hyperbolic cosine of `value`
|
||||
*/
|
||||
fn cosh(auto value) { return builtin::std::math::cosh(value); };
|
||||
/**
|
||||
Calculates the hyperbolic 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 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. 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));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -6,33 +6,13 @@
|
||||
|
||||
namespace auto std::mem {
|
||||
|
||||
namespace impl {
|
||||
|
||||
struct MagicSearchImpl<auto Magic, T> {
|
||||
if ($ < (std::mem::base_address() + std::mem::size() - std::string::length(Magic) - 1)) {
|
||||
char __potentialMagic__[std::string::length(Magic)] [[hidden, no_unique_address]];
|
||||
|
||||
if (__potentialMagic__ == Magic) {
|
||||
T data [[inline]];
|
||||
} else {
|
||||
padding[1];
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
padding[1];
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
A Handle for a custom Section
|
||||
*/
|
||||
using Section = u128;
|
||||
|
||||
/**
|
||||
The Endianess of a value
|
||||
The endianness of a value
|
||||
*/
|
||||
enum Endian : u8 {
|
||||
Native = 0,
|
||||
@@ -49,6 +29,15 @@ namespace auto std::mem {
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
Aligns the given value to the given alignment
|
||||
@param alignment The alignment to align to
|
||||
@@ -60,10 +49,10 @@ namespace auto 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() {
|
||||
@@ -71,7 +60,7 @@ namespace auto std::mem {
|
||||
};
|
||||
|
||||
/**
|
||||
Gets the size of the memory
|
||||
Gets the size of the data
|
||||
@return The size of the memory
|
||||
*/
|
||||
fn size() {
|
||||
@@ -79,17 +68,18 @@ namespace auto 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
|
||||
@@ -100,11 +90,35 @@ namespace auto 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. Defaults to native
|
||||
@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) {
|
||||
@@ -115,7 +129,7 @@ namespace auto 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. Defaults to native
|
||||
@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) {
|
||||
@@ -132,14 +146,6 @@ namespace auto std::mem {
|
||||
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
|
||||
@@ -211,14 +217,12 @@ namespace auto std::mem {
|
||||
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> {
|
||||
std::mem::impl::MagicSearchImpl<Magic, T> impl[while(!std::mem::eof())] [[inline]];
|
||||
fn current_bit_offset() {
|
||||
return builtin::std::mem::current_bit_offset();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -227,10 +231,10 @@ namespace auto 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
|
||||
@@ -249,11 +253,33 @@ namespace auto 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]];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -47,9 +47,9 @@ namespace auto 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;
|
||||
}
|
||||
```
|
||||
*/
|
||||
@@ -57,7 +57,7 @@ namespace auto 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) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import std.limits;
|
||||
*/
|
||||
|
||||
namespace auto std::random {
|
||||
|
||||
|
||||
/**
|
||||
Represents the type of distribution to use to generate a random number
|
||||
*/
|
||||
@@ -68,7 +68,7 @@ namespace auto std::random {
|
||||
return builtin::std::random::generate(u32(distribution), param1, param2);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Generates a uniformly distributed random number between `min` and `max`
|
||||
@param [min] Minimum number. Defaults to 0
|
||||
@@ -77,5 +77,5 @@ namespace auto std::random {
|
||||
fn generate(u64 min = std::limits::u64_min(), u64 max = std::limits::u64_max()) {
|
||||
return std::random::generate_using(Distribution::Uniform, min, max);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,129 +1,153 @@
|
||||
#pragma once
|
||||
|
||||
import std.io;
|
||||
import std.mem;
|
||||
|
||||
/*!
|
||||
Libray to interact with strings.
|
||||
Library to interact with strings.
|
||||
*/
|
||||
|
||||
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,100 +160,100 @@ namespace auto 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.
|
||||
*/
|
||||
fn replace(str string, str pattern, str replace) {
|
||||
s32 string_len = std::string::length(string);
|
||||
s32 pattern_len = std::string::length(pattern);
|
||||
u32 i;
|
||||
char c;
|
||||
while (i < std::string::length(string)) {
|
||||
c = std::string::at(string, i);
|
||||
|
||||
if (pattern_len > string_len || pattern_len * string_len == 0 )
|
||||
return string;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
result = result + char(c - 0x20);
|
||||
else
|
||||
result = result + c;
|
||||
|
||||
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;
|
||||
};
|
||||
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) {
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ 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 auto 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 auto 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!");
|
||||
};
|
||||
|
||||
}
|
||||
@@ -3,198 +3,198 @@
|
||||
import std.io;
|
||||
|
||||
/*!
|
||||
Library to handle time and date related operations.
|
||||
Library to handle time and date related operations.
|
||||
*/
|
||||
|
||||
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 = u32;
|
||||
/**
|
||||
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) {
|
||||
le 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) {
|
||||
le 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. Defaults to local.
|
||||
@return The current time in the specified time zone.
|
||||
*/
|
||||
fn now(TimeZone time_zone = TimeZone::Local) {
|
||||
le 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) {
|
||||
le 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) {
|
||||
le 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;
|
||||
};
|
||||
|
||||
/**
|
||||
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;
|
||||
};
|
||||
/**
|
||||
Converts a FILETIME to unix time.
|
||||
@param value The value to convert.
|
||||
@return Timestamp formatted as unix time.
|
||||
*/
|
||||
fn filetime_to_unix(u64 value) {
|
||||
return value / 10000000 - 11644473600;
|
||||
};
|
||||
|
||||
/**
|
||||
Formats a time according to the specified format string.
|
||||
@param time The time to format.
|
||||
@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 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;
|
||||
|
||||
return builtin::std::time::format(format_string, converter.value);
|
||||
};
|
||||
return builtin::std::time::format(format_string, converter.value);
|
||||
};
|
||||
|
||||
/**
|
||||
Formats a DOS date according to the specified format string.
|
||||
@param date The DOS date to format.
|
||||
@param [format_string] The format string to use. 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 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);
|
||||
};
|
||||
/**
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace auto 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 auto 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}"); };
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
import std.io;
|
||||
import std.string;
|
||||
import std.mem;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
import std.io;
|
||||
import std.core;
|
||||
|
||||
/*!
|
||||
Types to display single bytes using various different representations
|
||||
*/
|
||||
|
||||
namespace auto type {
|
||||
|
||||
|
||||
/**
|
||||
Type visualizing the value of each individual bit
|
||||
*/
|
||||
@@ -20,8 +21,8 @@ namespace auto 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 auto 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 auto 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 auto 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 auto type {
|
||||
bits.bit1,
|
||||
bits.bit0);
|
||||
};
|
||||
|
||||
|
||||
fn format_nibbles(Nibbles nibbles) {
|
||||
return std::format("{{ {0:0X}, {1:0X} }}", nibbles.high, nibbles.low);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,15 +14,15 @@ namespace auto type {
|
||||
@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 auto 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 auto 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 auto type {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,37 +9,37 @@ import std.mem;
|
||||
*/
|
||||
|
||||
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 auto 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
42
includes/type/fmt.pat
Normal 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,15 +3,15 @@
|
||||
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 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 auto 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]);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,69 +4,69 @@ 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 auto 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]];
|
||||
|
||||
/**
|
||||
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(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;
|
||||
};
|
||||
/**
|
||||
A signed variant of a LEB128 number
|
||||
*/
|
||||
using sLEB128 = LEB128Base [[format("type::impl::format_sleb128"), transform("type::impl::transform_sleb128")]];
|
||||
|
||||
fn transform_sleb128_array(ref auto array) {
|
||||
s128 res = type::impl::transform_uleb128_array(array);
|
||||
if (res & 0x40 != 0) {
|
||||
res |= ~0 << (sizeof(array) / sizeof(u8)) * 7;
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
Legacy alias for uLEB128
|
||||
*/
|
||||
using LEB128 = uLEB128;
|
||||
|
||||
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);
|
||||
};
|
||||
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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,30 +3,30 @@
|
||||
import std.io;
|
||||
|
||||
/*!
|
||||
Types used to decode MAC Addresses
|
||||
Types used to decode MAC Addresses
|
||||
*/
|
||||
|
||||
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]);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
import std.string;
|
||||
import std.sys;
|
||||
import std.io;
|
||||
@@ -9,8 +11,13 @@ import std.ctype;
|
||||
|
||||
namespace auto type
|
||||
{
|
||||
fn fm(ref auto value)
|
||||
{
|
||||
|
||||
/**
|
||||
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)
|
||||
{
|
||||
@@ -21,23 +28,20 @@ namespace auto type
|
||||
else
|
||||
result += std::format("\\x{:02X}", u8(c));
|
||||
}
|
||||
return std::format("\"{}\"", result);
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
A Magic number. Throws an error if the magic number does not match the expected value
|
||||
@tparam ExpectedValue A string representing the expected value
|
||||
*/
|
||||
struct Magic<auto ExpectedValue>
|
||||
{
|
||||
struct Magic<auto ExpectedValue> {
|
||||
char value[std::string::length(ExpectedValue)];
|
||||
std::assert_warn(value == ExpectedValue, std::format("Invalid magic value! Expected {}, got {} at position 0x{:X}", type::fm(ExpectedValue), type::fm(value), $ - std::string::length(ExpectedValue)));
|
||||
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)
|
||||
{
|
||||
return type::fm(magic.value);
|
||||
namespace impl {
|
||||
fn format_magic(ref auto magic) {
|
||||
return std::format("\"{}\"", type::escape_bytes(magic.value));
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
import std.mem;
|
||||
|
||||
/*!
|
||||
Types dealing with various kinds of resource paths
|
||||
Types dealing with various kinds of resource paths
|
||||
*/
|
||||
|
||||
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));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
import std.io;
|
||||
|
||||
/*!
|
||||
@@ -69,4 +71,4 @@ namespace auto type {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ 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;
|
||||
|
||||
|
||||
41
magic/arma3_magic
Normal file
41
magic/arma3_magic
Normal 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
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Autodesk 3DS Max Model file
|
||||
#pragma description Autodesk 3DS Max Model
|
||||
|
||||
import std.io;
|
||||
import type.base;
|
||||
@@ -7,7 +7,7 @@ import type.base;
|
||||
#pragma MIME image/x-3ds
|
||||
|
||||
// Heavily based off of ZiZi's 010 Editor 3DS Template
|
||||
enum ChunkIdentifier : u16 {
|
||||
enum ChunkIdentifier : u16 {
|
||||
NULL_CHUNK = 0x0000,
|
||||
ChunkType = 0x0995,
|
||||
ChunkUnique = 0x0996,
|
||||
@@ -40,10 +40,10 @@ enum ChunkIdentifier : u16 {
|
||||
COLOR_24 = 0x0011, // r,g,b: Byte
|
||||
LIN_COLOR_24 = 0x0012, // r,g,b: Byte (gamma corrected)
|
||||
LIN_COLOR_F = 0x0013, // r,g,b: Single precision float (gamma corrected)
|
||||
|
||||
|
||||
INT_PERCENTAGE = 0x0030, // u16 integer
|
||||
FLOAT_PERCENTAGE = 0x0031, // Single precision float
|
||||
|
||||
|
||||
M3DMAGIC = 0x4D4D,
|
||||
SMAGIC = 0x2D2D,
|
||||
LMAGIC = 0x2D3D,
|
||||
@@ -72,7 +72,7 @@ enum ChunkIdentifier : u16 {
|
||||
RAY_BIAS = 0x1460,
|
||||
USE_RAYTRACE = 0x1470,
|
||||
O_CONSTS = 0x1500,
|
||||
|
||||
|
||||
AMBIENT_LIGHT = 0x2100,
|
||||
|
||||
FOG = 0x2200,
|
||||
@@ -82,7 +82,7 @@ enum ChunkIdentifier : u16 {
|
||||
USE_DISTANCE_CUE = 0x2301,
|
||||
WORLD_LAYERED_FOG = 0x2302,
|
||||
WORLD_USE_LAYERED_FOG = 0x2303,
|
||||
|
||||
|
||||
DEFAULT_VIEW = 0x3000,
|
||||
VIEW_TOP = 0x3010,
|
||||
VIEW_BOTTOM = 0x3020,
|
||||
@@ -93,7 +93,7 @@ enum ChunkIdentifier : u16 {
|
||||
VIEW_USER = 0x3070,
|
||||
VIEW_CAMERA = 0x3080,
|
||||
VIEW_WINDOW = 0x3090,
|
||||
|
||||
|
||||
NAMED_OBJECT = 0x4000,
|
||||
OBJ_HIDDEN = 0x4010,
|
||||
OBJ_VIS_LOFTER = 0x4011,
|
||||
@@ -103,7 +103,7 @@ enum ChunkIdentifier : u16 {
|
||||
OBJ_PROCEDURAL = 0x4015,
|
||||
OBJ_FROZEN = 0x4016,
|
||||
OBJ_DONT_RCVSHADOW = 0x4017,
|
||||
|
||||
|
||||
N_TRI_OBJECT = 0x4100,
|
||||
POINT_ARRAY = 0x4110,
|
||||
POINT_FLAG_ARRAY = 0x4111,
|
||||
@@ -134,7 +134,7 @@ enum ChunkIdentifier : u16 {
|
||||
DL_SPOT_OVERSHOOT = 0x4652,
|
||||
DL_SPOT_PROJECTOR = 0x4653,
|
||||
DL_EXCLUDE = 0x4654,
|
||||
DL_RANGE = 0x4655, /* Not used in R3 */
|
||||
DL_RANGE = 0x4655, /* Not used in R3 */
|
||||
DL_SPOT_ROLL = 0x4656,
|
||||
DL_SPOT_ASPECT = 0x4657,
|
||||
DL_RAY_BIAS = 0x4658,
|
||||
@@ -143,22 +143,22 @@ enum ChunkIdentifier : u16 {
|
||||
DL_INNER_RANGE = 0x4659,
|
||||
DL_OUTER_RANGE = 0x465A,
|
||||
DL_MULTIPLIER = 0x465B,
|
||||
|
||||
|
||||
N_AMBIENT_LIGHT = 0x4680,
|
||||
|
||||
|
||||
N_CAMERA = 0x4700,
|
||||
CAM_SEE_CONE = 0x4710,
|
||||
CAM_RANGES = 0x4720,
|
||||
|
||||
|
||||
HIERARCHY = 0x4F00,
|
||||
PARENT_OBJECT = 0x4F10,
|
||||
PIVOT_OBJECT = 0x4F20,
|
||||
PIVOT_LIMITS = 0x4F30,
|
||||
PIVOT_ORDER = 0x4F40,
|
||||
XLATE_RANGE = 0x4F50,
|
||||
|
||||
|
||||
POLY_2D = 0x5000,
|
||||
|
||||
|
||||
/* Flags in shaper file that tell whether polys make up an ok shape */
|
||||
SHAPE_OK = 0x5010,
|
||||
SHAPE_NOT_OK = 0x5011,
|
||||
@@ -177,8 +177,8 @@ enum ChunkIdentifier : u16 {
|
||||
YZ_CURVE = 0x6080,
|
||||
INTERPCT = 0x6090,
|
||||
DEFORM_LIMIT = 0x60A0,
|
||||
|
||||
/* Flags for Modeler options */
|
||||
|
||||
/* Flags for Modeler options */
|
||||
USE_CONTOUR = 0x6100,
|
||||
USE_TWEEN = 0x6110,
|
||||
USE_SCALE = 0x6120,
|
||||
@@ -187,7 +187,7 @@ enum ChunkIdentifier : u16 {
|
||||
USE_FIT = 0x6150,
|
||||
USE_BEVEL = 0x6160,
|
||||
|
||||
/* Viewport description chunks */
|
||||
/* Viewport description chunks */
|
||||
VIEWPORT_LAYOUT_OLD = 0x7000,
|
||||
VIEWPORT_DATA_OLD = 0x7010,
|
||||
VIEWPORT_LAYOUT = 0x7001,
|
||||
@@ -196,7 +196,7 @@ enum ChunkIdentifier : u16 {
|
||||
VIEWPORT_SIZE = 0x7020,
|
||||
NETWORK_VIEW = 0x7030,
|
||||
|
||||
/* External Application Data */
|
||||
/* External Application Data */
|
||||
XDATA_SECTION = 0x8000,
|
||||
XDATA_ENTRY = 0x8001,
|
||||
XDATA_APPNAME = 0x8002,
|
||||
@@ -215,8 +215,8 @@ enum ChunkIdentifier : u16 {
|
||||
XDATA_RFU1 = 0x800F,
|
||||
|
||||
PARENT_NAME = 0x80F0,
|
||||
|
||||
/* Material Chunk IDs */
|
||||
|
||||
/* Material Chunk IDs */
|
||||
MAT_ENTRY = 0xAFFF,
|
||||
MAT_NAME = 0xA000,
|
||||
MAT_AMBIENT = 0xA010,
|
||||
@@ -228,7 +228,7 @@ enum ChunkIdentifier : u16 {
|
||||
MAT_TRANSPARENCY = 0xA050,
|
||||
MAT_XPFALL = 0xA052,
|
||||
MAT_REFBLUR = 0xA053,
|
||||
|
||||
|
||||
MAT_SELF_ILLUM = 0xA080,
|
||||
MAT_TWO_SIDE = 0xA081,
|
||||
MAT_DECAL = 0xA082,
|
||||
@@ -241,13 +241,13 @@ enum ChunkIdentifier : u16 {
|
||||
MAT_XPFALLIN = 0xA08A,
|
||||
MAT_PHONGSOFT = 0xA08C,
|
||||
MAT_WIREABS = 0xA08E,
|
||||
|
||||
|
||||
MAT_SHADING = 0xA100,
|
||||
|
||||
|
||||
MAT_TEXMAP = 0xA200,
|
||||
MAT_MAPNAME = 0xA300,
|
||||
MAT_ACUBIC = 0xA310,
|
||||
|
||||
|
||||
MAT_MAP_TILINGOLD = 0xA350,
|
||||
MAT_MAP_TILING = 0xA351,
|
||||
MAT_MAP_TEXBLUR_OLD = 0xA352,
|
||||
@@ -262,14 +262,14 @@ enum ChunkIdentifier : u16 {
|
||||
MAT_MAP_RCOL = 0xA364,
|
||||
MAT_MAP_GCOL = 0xA366,
|
||||
MAT_MAP_BCOL = 0xA368,
|
||||
|
||||
|
||||
MAT_SPECMAP = 0xA204,
|
||||
MAT_OPACMAP = 0xA210,
|
||||
MAT_REFLMAP = 0xA220,
|
||||
MAT_BUMPMAP = 0xA230,
|
||||
MAT_USE_REFBLUR = 0xA250,
|
||||
MAT_BUMP_PERCENT = 0xA252,
|
||||
|
||||
|
||||
MAT_SXP_TEXT_DATA = 0xA320,
|
||||
MAT_SXP_TEXT2_DATA = 0xA321,
|
||||
MAT_SXP_OPAC_DATA = 0xA322,
|
||||
@@ -285,7 +285,7 @@ enum ChunkIdentifier : u16 {
|
||||
MAT_SXP_SHIN_MASKDATA = 0xA334,
|
||||
MAT_SXP_SELFI_MASKDATA = 0xA336,
|
||||
MAT_SXP_REFL_MASKDATA = 0xA338,
|
||||
|
||||
|
||||
MAT_TEX2MAP = 0xA33A,
|
||||
MAT_SHINMAP = 0xA33C,
|
||||
MAT_SELFIMAP = 0xA33D,
|
||||
@@ -297,8 +297,8 @@ enum ChunkIdentifier : u16 {
|
||||
MAT_SPECMASK = 0xA348,
|
||||
MAT_SELFIMASK = 0xA34A,
|
||||
MAT_REFLMASK = 0xA34C,
|
||||
|
||||
/* Keyframe Chunk IDs */
|
||||
|
||||
/* Keyframe Chunk IDs */
|
||||
KFDATA = 0xB000,
|
||||
KFHDR = 0xB00A,
|
||||
AMBIENT_NODE_TAG = 0xB001,
|
||||
@@ -308,13 +308,13 @@ enum ChunkIdentifier : u16 {
|
||||
LIGHT_NODE_TAG = 0xB005,
|
||||
L_TARGET_NODE_TAG = 0xB006,
|
||||
SPOTLIGHT_NODE_TAG = 0xB007,
|
||||
|
||||
|
||||
KFSEG = 0xB008,
|
||||
KFCURTIME = 0xB009,
|
||||
|
||||
|
||||
NODE_HDR = 0xB010,
|
||||
INSTANCE_NAME = 0xB011,
|
||||
PRESCALE = 0xB012,
|
||||
PRESCALE = 0xB012,
|
||||
PIVOT = 0xB013,
|
||||
BOUNDBOX = 0xB014,
|
||||
MORPH_SMOOTH = 0xB015,
|
||||
@@ -329,10 +329,10 @@ enum ChunkIdentifier : u16 {
|
||||
FALL_TRACK_TAG = 0xB028,
|
||||
HIDE_TRACK_TAG = 0xB029,
|
||||
NODE_ID = 0xB030,
|
||||
|
||||
|
||||
|
||||
|
||||
CMAGIC = 0xC23D,
|
||||
|
||||
|
||||
C_MDRAWER = 0xC010,
|
||||
C_TDRAWER = 0xC020,
|
||||
C_SHPDRAWER = 0xC030,
|
||||
@@ -395,7 +395,7 @@ enum ChunkIdentifier : u16 {
|
||||
C_BITMAP_DRAWER = 0xC25B,
|
||||
C_RGB_FILE = 0xC260,
|
||||
C_RGB_OVASPECT = 0xC270,
|
||||
|
||||
|
||||
C_RGB_ANIMTYPE = 0xC271,
|
||||
C_RENDER_ALL = 0xC272,
|
||||
C_REND_FROM = 0xC273,
|
||||
@@ -513,16 +513,16 @@ enum ChunkIdentifier : u16 {
|
||||
C_VTR_IN = 0xC775,
|
||||
C_VTR_PK = 0xC780,
|
||||
C_VTR_SH = 0xC785,
|
||||
|
||||
/* Material chunks */
|
||||
C_WORK_MTLS = 0xC790, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_2 = 0xC792, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_3 = 0xC793, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_4 = 0xC794, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_5 = 0xCB00, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_6 = 0xCB01, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_7 = 0xCB02, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_8 = 0xCB03, /* Old-style -- now ignored */
|
||||
|
||||
/* Material chunks */
|
||||
C_WORK_MTLS = 0xC790, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_2 = 0xC792, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_3 = 0xC793, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_4 = 0xC794, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_5 = 0xCB00, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_6 = 0xCB01, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_7 = 0xCB02, /* Old-style -- now ignored */
|
||||
C_WORK_MTLS_8 = 0xCB03, /* Old-style -- now ignored */
|
||||
C_WORKMTL = 0xCB04,
|
||||
C_SXP_TEXT_DATA = 0xCB10,
|
||||
C_SXP_TEXT2_DATA = 0xCB20,
|
||||
@@ -542,15 +542,15 @@ enum ChunkIdentifier : u16 {
|
||||
|
||||
C_BGTYPE = 0xC7A1,
|
||||
C_MEDTILE = 0xC7B0,
|
||||
|
||||
|
||||
/* Contrast */
|
||||
C_LO_CONTRAST = 0xC7D0,
|
||||
C_HI_CONTRAST = 0xC7D1,
|
||||
|
||||
/* 3d frozen display */
|
||||
|
||||
/* 3d frozen display */
|
||||
C_FROZ_DISPLAY = 0xC7E0,
|
||||
|
||||
/* Booleans */
|
||||
|
||||
/* Booleans */
|
||||
C_BOOLWELD = 0xc7f0,
|
||||
C_BOOLTYPE = 0xc7f1,
|
||||
|
||||
@@ -569,8 +569,8 @@ enum ChunkIdentifier : u16 {
|
||||
C_MAPDRAWER8 = 0xCA08,
|
||||
C_MAPDRAWER9 = 0xCA09,
|
||||
C_MAPDRAWER_ENTRY = 0xCA10,
|
||||
|
||||
/* System Options */
|
||||
|
||||
/* System Options */
|
||||
C_BACKUP_FILE = 0xCA20,
|
||||
C_DITHER_256 = 0xCA21,
|
||||
C_SAVE_LAST = 0xCA22,
|
||||
@@ -596,8 +596,8 @@ enum ChunkIdentifier : u16 {
|
||||
C_AUTO_SMOOTH = 0xCA80,
|
||||
C_DXF_SMOOTH_ANG = 0xCA90,
|
||||
C_SMOOTH_ANG = 0xCAA0,
|
||||
|
||||
/* Special network-use chunks */
|
||||
|
||||
/* Special network-use chunks */
|
||||
C_NET_USE_VPOST = 0xCC00,
|
||||
C_NET_USE_GAMMA = 0xCC10,
|
||||
C_NET_FIELD_ORDER = 0xCC20,
|
||||
@@ -628,8 +628,8 @@ enum ChunkIdentifier : u16 {
|
||||
C_VIEW_PRES_RATIO = 0xCE50,
|
||||
C_BGND_PRES_RATIO = 0xCE60,
|
||||
C_NTH_SERIAL_NUM = 0xCE70,
|
||||
|
||||
/* Video Post */
|
||||
|
||||
/* Video Post */
|
||||
VPDATA = 0xd000,
|
||||
|
||||
P_QUEUE_ENTRY = 0xd100,
|
||||
@@ -648,7 +648,7 @@ enum ChunkIdentifier : u16 {
|
||||
P_QUEUE_ALIGN = 0xd190,
|
||||
|
||||
P_CUSTOM_SIZE = 0xd1a0,
|
||||
|
||||
|
||||
P_ALPH_NONE = 0xd210,
|
||||
P_ALPH_PSEUDO = 0xd220, /* Old chunk */
|
||||
P_ALPH_OP_PSEUDO = 0xd221, /* Old chunk */
|
||||
@@ -732,7 +732,7 @@ bitfield Spline {
|
||||
Use_Bias : 1;
|
||||
Use_Ease_To : 1;
|
||||
Use_Ease_From : 1;
|
||||
|
||||
|
||||
padding : 3;
|
||||
|
||||
if (Use_Tension == 1)
|
||||
@@ -745,7 +745,7 @@ bitfield Spline {
|
||||
float Ease_To;
|
||||
if (Use_Ease_From == 1)
|
||||
float Ease_From;
|
||||
|
||||
|
||||
padding : 8;
|
||||
};
|
||||
|
||||
@@ -795,7 +795,7 @@ struct Keys<auto identifier> {
|
||||
) : {
|
||||
RotationKey data[count];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::FOV_TRACK_TAG |
|
||||
ChunkIdentifier::ROLL_TRACK_TAG |
|
||||
@@ -804,13 +804,13 @@ struct Keys<auto identifier> {
|
||||
) : {
|
||||
AngleKey data[count];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::MORPH_TRACK_TAG
|
||||
) : {
|
||||
MorphKey data[count];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::HIDE_TRACK_TAG
|
||||
) : {
|
||||
@@ -842,7 +842,7 @@ struct Chunk {
|
||||
u32 chunkSize;
|
||||
u32 dataLength = chunkSize - 6 [[export]];
|
||||
u32 chunkEnd = $ + dataLength;
|
||||
|
||||
|
||||
if (chunkSize > 0) {
|
||||
std::print("{}", identifier);
|
||||
match (identifier) {
|
||||
@@ -894,14 +894,14 @@ struct Chunk {
|
||||
): {
|
||||
Chunk chunks[while($ < chunkEnd)];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::M3D_VERSION |
|
||||
ChunkIdentifier::MESH_VERSION
|
||||
): {
|
||||
u32 version;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::LO_SHADOW_BIAS |
|
||||
ChunkIdentifier::HI_SHADOW_BIAS |
|
||||
@@ -921,41 +921,41 @@ struct Chunk {
|
||||
): {
|
||||
float value;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::V_GRADIENT
|
||||
) : {
|
||||
float position;
|
||||
Chunk chunks[while($ < chunkEnd)];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::NAMED_OBJECT
|
||||
) : {
|
||||
char name[];
|
||||
Chunk chunks[while($ < chunkEnd)];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::POINT_ARRAY
|
||||
) : {
|
||||
u16 count;
|
||||
Vector3f vectices[count] [[hex::visualize("3d", this, null)]];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::TEX_VERTS
|
||||
) : {
|
||||
u16 count;
|
||||
Vector2f coords[count];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::MESH_MATRIX
|
||||
) : {
|
||||
Vector3f x, y, z, w;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::FACE_ARRAY
|
||||
) : {
|
||||
@@ -963,26 +963,26 @@ struct Chunk {
|
||||
Face faces[count];
|
||||
Chunk chunks[while($ < chunkEnd)];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::POINT_FLAG_ARRAY
|
||||
) : {
|
||||
u16 count;
|
||||
VertexFlags flags[count];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::SMOOTH_GROUP
|
||||
) : {
|
||||
u32 groups[dataLength / sizeof(u32)];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::MESH_COLOR
|
||||
) : {
|
||||
u8 value;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::MSH_MAT_GROUP
|
||||
) : {
|
||||
@@ -990,7 +990,7 @@ struct Chunk {
|
||||
u16 count;
|
||||
u16 groups[count];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::KFHDR
|
||||
) : {
|
||||
@@ -998,25 +998,25 @@ struct Chunk {
|
||||
char name[];
|
||||
u32 animationLength;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::KFSEG
|
||||
) : {
|
||||
u32 start, end;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::KFCURTIME
|
||||
) : {
|
||||
u32 frameIndex;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::NODE_ID
|
||||
) : {
|
||||
type::Hex<u16> id;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::NODE_HDR
|
||||
) : {
|
||||
@@ -1026,47 +1026,47 @@ struct Chunk {
|
||||
KeyFlags2 flags2;
|
||||
type::Hex<u16> parentId;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::PIVOT
|
||||
) : {
|
||||
Vector3f value;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::BOUNDBOX
|
||||
) : {
|
||||
Vector3f min, max;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::COLOR_24 |
|
||||
ChunkIdentifier::LIN_COLOR_24
|
||||
) : {
|
||||
RGB<u8> color;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::COLOR_F |
|
||||
ChunkIdentifier::LIN_COLOR_F
|
||||
) : {
|
||||
RGB<float> color;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::INT_PERCENTAGE |
|
||||
ChunkIdentifier::MAT_BUMP_PERCENT
|
||||
) : {
|
||||
u16 value;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::SHADOW_MAP_SIZE |
|
||||
ChunkIdentifier::MAT_SHADING
|
||||
) : {
|
||||
u16 value;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::POS_TRACK_TAG |
|
||||
ChunkIdentifier::ROT_TRACK_TAG |
|
||||
@@ -1077,13 +1077,13 @@ struct Chunk {
|
||||
ChunkIdentifier::MORPH_TRACK_TAG |
|
||||
ChunkIdentifier::HOT_TRACK_TAG |
|
||||
ChunkIdentifier::FALL_TRACK_TAG |
|
||||
ChunkIdentifier::HIDE_TRACK_TAG
|
||||
ChunkIdentifier::HIDE_TRACK_TAG
|
||||
) : {
|
||||
TrackFlags flags;
|
||||
u8 unknown[8];
|
||||
Keys<identifier> keys;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::INSTANCE_NAME |
|
||||
ChunkIdentifier::BIT_MAP |
|
||||
@@ -1093,26 +1093,26 @@ struct Chunk {
|
||||
) : {
|
||||
char name[];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::MAT_MAP_TILING
|
||||
) : {
|
||||
u16 tiling;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::WORLD_VIEWPORT_SIZE
|
||||
) : {
|
||||
u16 x, y, w, h;
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::N_DIRECT_LIGHT
|
||||
) : {
|
||||
Vector3f position;
|
||||
Chunk chunks[while($ < chunkEnd)];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::DL_SPOTLIGHT
|
||||
) : {
|
||||
@@ -1120,16 +1120,16 @@ struct Chunk {
|
||||
float hotspot, falloff;
|
||||
Chunk chunks[while($ < chunkEnd)];
|
||||
}
|
||||
|
||||
|
||||
(
|
||||
ChunkIdentifier::N_CAMERA
|
||||
) : {
|
||||
Vector3f position, target;
|
||||
float roll, fov;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(_) : {
|
||||
std::warning(std::format("Unhandled Chunk ID: {}, Skipping 0x{:04X} bytes", identifier, dataLength));
|
||||
$ += dataLength;
|
||||
|
||||
@@ -1,101 +1,93 @@
|
||||
#pragma description 7z File Format
|
||||
#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 std.io;
|
||||
import std.mem;
|
||||
import std.math;
|
||||
import type.magic;
|
||||
|
||||
|
||||
enum Type:u8{
|
||||
startPosition = 0x00, // Start position
|
||||
sizeStartHeader = 0x20, // Size of start Header
|
||||
};
|
||||
enum Type:u8{
|
||||
startPosition = 0x00, // Start position
|
||||
sizeStartHeader = 0x20, // Size of start Header
|
||||
};
|
||||
|
||||
enum TypeB:u48{
|
||||
sevenZipSignature = 0x1C27AFBC7A37, // Defining 7z signature
|
||||
};
|
||||
struct StartHeader {
|
||||
// File signature
|
||||
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;
|
||||
};
|
||||
|
||||
struct StartHeader {
|
||||
// File signature
|
||||
u48 signature [[color("FF0000")] ];
|
||||
// Version format
|
||||
u16 formatVersion [[color("00FF00")]];
|
||||
// CRC start header
|
||||
u32 crcOfTheFollowing20Bytes [[color("0000FF")]];
|
||||
// Relative offset of End Header
|
||||
u64 relativeOffsetEndHeader [[color("FFFF00")]];
|
||||
// Length of End Header
|
||||
u64 theLengthOfEndHeader [[color("00FFFF")]];
|
||||
// CRC of End Ender
|
||||
u32 crcOftheEndHeader [[color("FF00FF")]];
|
||||
// File size calculation
|
||||
u64 fileSize = relativeOffsetEndHeader + theLengthOfEndHeader + Type::sizeStartHeader;
|
||||
// Absolute offset calculation End Header
|
||||
u64 startEndHeader = relativeOffsetEndHeader + Type::sizeStartHeader;
|
||||
};
|
||||
StartHeader startheader @ Type::startPosition;
|
||||
|
||||
StartHeader startheader @ Type::startPosition;
|
||||
|
||||
struct CompressedData {
|
||||
// Start of compressed data
|
||||
u8 startOfCompressedData[4] [[color("C0C0C0")]];
|
||||
};
|
||||
struct CompressedData {
|
||||
// Start of compressed data
|
||||
u8 startOfCompressedData[4] [[color("C0C0C0")]];
|
||||
};
|
||||
|
||||
CompressedData compresseddata @ Type::sizeStartHeader;
|
||||
CompressedData compresseddata @ Type::sizeStartHeader;
|
||||
|
||||
|
||||
struct EndHeader {
|
||||
// Set padding to place End Header in right position
|
||||
padding[startheader.relativeOffsetEndHeader];
|
||||
// Mark link to meta block
|
||||
u8 linkToMetaBlock [[color("FF0000")]];
|
||||
// Mark all End Header
|
||||
char fullEndHeader[startheader.theLengthOfEndHeader] [[color("63954A")]];
|
||||
// Detect LZMA signature
|
||||
u64 lzmaSignaturePosition = std::mem::find_sequence_in_range(0, addressof(fullEndHeader), addressof(fullEndHeader) + sizeof(fullEndHeader), 0x23, 0x03, 0x01, 0x01, 0x05, 0x5D);
|
||||
|
||||
// Mark positions if LZMA signature was detected
|
||||
if(lzmaSignaturePosition != 0xFFFFFFFFFFFFFFFF){
|
||||
u48 lzmaSignature @ lzmaSignaturePosition [[color("0000FF")]];
|
||||
}
|
||||
};
|
||||
|
||||
EndHeader endheader @ Type::sizeStartHeader;
|
||||
|
||||
// Check 7z type
|
||||
if(startheader.signature == TypeB::sevenZipSignature){
|
||||
std::print("It is a 7z File Type");
|
||||
}else{
|
||||
std::print("The file is not 7z type");
|
||||
}
|
||||
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);
|
||||
|
||||
std::print("Format Version {} ",startheader.formatVersion);
|
||||
// Mark positions if LZMA signature was detected
|
||||
if(lzmaSignaturePosition != 0xFFFFFFFFFFFFFFFF){
|
||||
u48 lzmaSignature @ lzmaSignaturePosition [[color("0000FF")]];
|
||||
}
|
||||
};
|
||||
|
||||
// Version verification
|
||||
if(startheader.formatVersion == 0x0400){
|
||||
std::print("Major Version 0x00 || 0 - Minor Version 0x04 || 4");
|
||||
}
|
||||
EndHeader endheader @ Type::sizeStartHeader;
|
||||
|
||||
// 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("Format Version {} ",startheader.formatVersion);
|
||||
|
||||
|
||||
// Version verification
|
||||
if(startheader.formatVersion == 0x0400){
|
||||
std::print("Major Version 0x00 || 0 - Minor Version 0x04 || 4");
|
||||
}
|
||||
|
||||
std::print("CRC Start Header 0x{:X}",startheader.crcOfTheFollowing20Bytes);
|
||||
// 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 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("CRC Start Header 0x{:X}",startheader.crcOfTheFollowing20Bytes);
|
||||
|
||||
std::print("Offset to start End Header 0x{:X} || {} bytes",startheader.startEndHeader,startheader.startEndHeader);
|
||||
std::print("CRC End Header 0x{:X} ", startheader.crcOftheEndHeader);
|
||||
|
||||
std::print("End Header length 0x{:X} || {} bytes",startheader.theLengthOfEndHeader,startheader.theLengthOfEndHeader);
|
||||
std::print("CompressedData length 0x{:X} || {} bytes ",startheader.relativeOffsetEndHeader, startheader.relativeOffsetEndHeader);
|
||||
|
||||
std::print("File size 0x{:X} || {} bytes",startheader.fileSize, startheader.fileSize);
|
||||
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);
|
||||
|
||||
47
patterns/AC Unity/acu_data_compressed.hexpat
Normal file
47
patterns/AC Unity/acu_data_compressed.hexpat
Normal 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;
|
||||
93
patterns/AC Unity/acu_data_decompressed.hexpat
Normal file
93
patterns/AC Unity/acu_data_decompressed.hexpat
Normal 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;
|
||||
64
patterns/AC Unity/acu_forge.hexpat
Normal file
64
patterns/AC Unity/acu_forge.hexpat
Normal 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;
|
||||
@@ -1,12 +1,16 @@
|
||||
#pragma author AdventureT
|
||||
#pragma description Crash Bandicoot - Back in Time (fan game) User created level format
|
||||
// Supports all versions till 0.94c, newer versions might be compatible!
|
||||
#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;
|
||||
@@ -17,8 +21,6 @@ struct Header {
|
||||
std::string::SizedString<u8> author;
|
||||
};
|
||||
|
||||
Header header @ 0x0;
|
||||
|
||||
// Background Music
|
||||
enum BGM : u32 {
|
||||
None,
|
||||
@@ -37,6 +39,56 @@ enum BGM : u32 {
|
||||
};
|
||||
|
||||
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,
|
||||
@@ -83,12 +135,19 @@ enum BGMV2 : u32 {
|
||||
Arabia02BGM,
|
||||
BashBGM,
|
||||
Cortex02BGM,
|
||||
MedievalBGM,
|
||||
PreHistoricBGM,
|
||||
UnderWaterBGM,
|
||||
BrioRevisitedBGM,
|
||||
EgyptChaseBGM,
|
||||
RuinsLoopBGM,
|
||||
DingoSynthBGM
|
||||
};
|
||||
|
||||
enum Type : u32 {
|
||||
Unset,
|
||||
Flashback,
|
||||
Trial,
|
||||
Trial
|
||||
};
|
||||
|
||||
enum TypeV2 : u32 {
|
||||
@@ -118,13 +177,31 @@ enum SkyboxV2 : u32 {
|
||||
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,
|
||||
Fortress
|
||||
};
|
||||
|
||||
enum SceneryV2 : u32 {
|
||||
@@ -165,44 +242,102 @@ enum SceneryV4 : u32 {
|
||||
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 {
|
||||
|
||||
if (header.version > 1)
|
||||
// Type
|
||||
if (header.version > 1) {
|
||||
TypeV2 type;
|
||||
else
|
||||
Type type;
|
||||
|
||||
if (header.version > 1)
|
||||
SkyboxV2 skybox;
|
||||
else
|
||||
Skybox skybox;
|
||||
|
||||
if (header.version == 1)
|
||||
Scenery scenery;
|
||||
else if (header.version > 1 && header.version < 4)
|
||||
SceneryV2 scenery;
|
||||
else
|
||||
SceneryV4 scenery;
|
||||
|
||||
if (header.version > 2)
|
||||
{
|
||||
Weather weather;
|
||||
}
|
||||
|
||||
if (header.version > 1)
|
||||
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
|
||||
}
|
||||
else {
|
||||
BGM bgm;
|
||||
|
||||
|
||||
if (type == Type::Trial)
|
||||
{
|
||||
}
|
||||
// Time Trial
|
||||
if (type == Type::Trial) {
|
||||
u32 timeTrialTicksBronze;
|
||||
u32 timeTrialTicksSilver;
|
||||
u32 timeTrialTicksGold;
|
||||
@@ -210,22 +345,17 @@ struct Options {
|
||||
};
|
||||
|
||||
struct Object {
|
||||
|
||||
std::string::SizedString<u8> objName;
|
||||
|
||||
if (header.version > 1)
|
||||
{
|
||||
if (header.version > 1) {
|
||||
u16 x;
|
||||
u16 y;
|
||||
bool hasMetafields;
|
||||
if (hasMetafields)
|
||||
{
|
||||
if (hasMetafields) {
|
||||
u16 numOfMetafields;
|
||||
u8 metafields[numOfMetafields];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
u32 x;
|
||||
u32 y;
|
||||
}
|
||||
@@ -236,9 +366,6 @@ struct Objects{
|
||||
std::Array<Object, objCount> objArray;
|
||||
};
|
||||
|
||||
|
||||
Header header @ $;
|
||||
Options options @ $;
|
||||
Objects objects @ $;
|
||||
|
||||
|
||||
|
||||
Objects objects @ $;
|
||||
81
patterns/DFIR/DFIR_README.md
Normal file
81
patterns/DFIR/DFIR_README.md
Normal 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)
|
||||
|
||||
|
||||
677
patterns/DFIR/DISK_PARSER.hexpat
Normal file
677
patterns/DFIR/DISK_PARSER.hexpat
Normal 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 3–47: Reserved for UEFI")]];
|
||||
reserved_MS : 12 [[comment("Bits 48–59: 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
789
patterns/DFIR/FAT32.hexpat
Normal 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
1571
patterns/DFIR/NTFS.hexpat
Normal file
File diff suppressed because it is too large
Load Diff
616
patterns/DFIR/exFAT.hexpat
Normal file
616
patterns/DFIR/exFAT.hexpat
Normal 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(" ");
|
||||
}
|
||||
165
patterns/Devil May Cry HD Collection/dmc3_hd_mod.hexpat
Normal file
165
patterns/Devil May Cry HD Collection/dmc3_hd_mod.hexpat
Normal 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
189
patterns/SHR.hexpat
Normal 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 there’s 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
129
patterns/a3/a3_bmtr.hexpat
Normal 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;
|
||||
222
patterns/a3/a3_p3d_mlod.hexpat
Normal file
222
patterns/a3/a3_p3d_mlod.hexpat
Normal 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
141
patterns/a3/a3_paa.hexpat
Normal 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
165
patterns/a3/a3_rap.hexpat
Normal 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
93
patterns/a3/a3_rtm.hexpat
Normal 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;
|
||||
131
patterns/a3/a3_texheaders.hexpat
Normal file
131
patterns/a3/a3_texheaders.hexpat
Normal 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
176
patterns/adtfdat.hexpat
Normal 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;
|
||||
@@ -1,14 +1,13 @@
|
||||
#pragma authors: zhoubo
|
||||
#pragma version: 0.4
|
||||
#pragma description: Parse AAC's ADTS(Audio Data Transport Stream) audio files.
|
||||
#pragma category: Audio
|
||||
#pragma filemask: *.aac
|
||||
#pragma IDBytes: FF F //ADTS Syncword
|
||||
#pragma history:
|
||||
#pragma 0.4 2024-02-12 zhoubo: Porting from 010 Editor Templates.
|
||||
#pragma 0.3 2024-02-09 zhoubo: use BitfieldDisablePadding(Unpadded Bitfields) for odd header bytes(7,9 bytes) color, and remove FSeek.
|
||||
#pragma 0.2 2024-02-05 zhoubo: fix some comment & color.
|
||||
#pragma 0.1 2022-06-13 zhoubo: Init release. only ADTS, not support ADIF,LATM.
|
||||
#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
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#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
|
||||
|
||||
import std.io;
|
||||
@@ -52,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
71
patterns/ani.hexpat
Normal 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;
|
||||
50
patterns/apple_single_double.hexpat
Normal file
50
patterns/apple_single_double.hexpat
Normal 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;
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Static library archive files
|
||||
#pragma description GNU Static library archive
|
||||
|
||||
#pragma MIME application/x-archive
|
||||
|
||||
@@ -15,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];
|
||||
@@ -23,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
26
patterns/arc.hexpat
Normal 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;
|
||||
@@ -40,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);
|
||||
};
|
||||
168
patterns/bcss.hexpat
Normal file
168
patterns/bcss.hexpat
Normal 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;
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Bencode encoding, used by Torrent files
|
||||
#pragma description Torrent data (Bencode)
|
||||
|
||||
#pragma MIME application/x-bittorrent
|
||||
|
||||
@@ -8,20 +8,20 @@ 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',
|
||||
@@ -33,30 +33,39 @@ namespace bencode {
|
||||
String8 = '8',
|
||||
String9 = '9'
|
||||
};
|
||||
|
||||
|
||||
struct String {
|
||||
ASCIIDecimal length;
|
||||
char separator [[hidden]];
|
||||
char value[length];
|
||||
} [[sealed, format("bencode::format_string"), transform("bencode::format_string")]];
|
||||
|
||||
} [[sealed, format("bencode::format_string")]];
|
||||
|
||||
fn format_string(String string) {
|
||||
return string.value;
|
||||
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')];
|
||||
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;
|
||||
@@ -65,12 +74,12 @@ namespace bencode {
|
||||
String value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Bencode {
|
||||
Value value[while(!std::mem::eof())] [[inline]];
|
||||
Value value[while(!std::mem::eof())] [[inline]];
|
||||
char end;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
bencode::Bencode bencode @ 0x00;
|
||||
|
||||
@@ -1,80 +1,101 @@
|
||||
#pragma author Shadlock0133 (aka Aurora)
|
||||
#pragma description Binary G-Code from Prusa
|
||||
#pragma author Shadlock0133 (aka Aurora) / WerWolv
|
||||
#pragma description Prusa Binary G-Code
|
||||
#pragma magic [ 47 43 44 45 ] @ 0x00
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <std/mem.pat>
|
||||
import type.magic;
|
||||
import std.mem;
|
||||
|
||||
enum ChecksumType : u16 {
|
||||
None,
|
||||
CRC32,
|
||||
None = 0,
|
||||
CRC32 = 1
|
||||
};
|
||||
|
||||
enum BlockType : u16 {
|
||||
FileMetadata,
|
||||
GCode,
|
||||
SlicerMetadata,
|
||||
PrinterMetadata,
|
||||
PrintMetadata,
|
||||
Thumbnail,
|
||||
FileMetadata = 0,
|
||||
GCode = 1,
|
||||
SlicerMetadata = 2,
|
||||
PrinterMetadata = 3,
|
||||
PrintMetadata = 4,
|
||||
Thumbnail = 5
|
||||
};
|
||||
|
||||
enum Compression : u16 {
|
||||
None,
|
||||
Deflate,
|
||||
Heatshrink11_4,
|
||||
Heatshrink12_4,
|
||||
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,
|
||||
INI = 0
|
||||
};
|
||||
|
||||
struct Metadata {
|
||||
Encoding encoding;
|
||||
char data[parent.header.dataSize];
|
||||
};
|
||||
|
||||
enum ImageFormat : u16 {
|
||||
Png,
|
||||
Jpg,
|
||||
Qoi,
|
||||
PNG = 0,
|
||||
JPG = 1,
|
||||
QOI = 2
|
||||
};
|
||||
|
||||
struct Header {
|
||||
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;
|
||||
ChecksumType checksum_type;
|
||||
};
|
||||
|
||||
Header header @ 0;
|
||||
std::assert(header.version == 1, "only version 1 supported");
|
||||
std::assert(version == 1, "Only Version 1 is supported");
|
||||
|
||||
struct Block {
|
||||
BlockType type;
|
||||
Compression compression;
|
||||
u32 uncompressed_size;
|
||||
auto size = uncompressed_size;
|
||||
if (compression != Compression::None) {
|
||||
u32 compressed_size;
|
||||
size = compressed_size;
|
||||
}
|
||||
match (type) {
|
||||
(BlockType::FileMetadata
|
||||
| BlockType::PrinterMetadata
|
||||
| BlockType::PrintMetadata
|
||||
| BlockType::SlicerMetadata): {
|
||||
Encoding encoding;
|
||||
}
|
||||
(BlockType::Thumbnail): {
|
||||
ImageFormat image_format;
|
||||
u16 width;
|
||||
u16 height;
|
||||
}
|
||||
(BlockType::GCode): {
|
||||
u16;
|
||||
}
|
||||
(_): { std::assert(false, "unknown type"); }
|
||||
}
|
||||
u8 data[size];
|
||||
match (header.checksum_type) {
|
||||
(ChecksumType::None): {}
|
||||
(ChecksumType::CRC32): { u32 checksum; }
|
||||
}
|
||||
ChecksumType checksumType;
|
||||
|
||||
Block blocks[while(!std::mem::eof())];
|
||||
};
|
||||
|
||||
Block blocks[while(!std::mem::eof())] @ $;
|
||||
BGCode bgcode @ 0x00;
|
||||
24
patterns/binka.hexpat
Normal file
24
patterns/binka.hexpat
Normal 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;
|
||||
196
patterns/blend.hexpat
Normal file
196
patterns/blend.hexpat
Normal file
@@ -0,0 +1,196 @@
|
||||
#pragma description Blender file
|
||||
#pragma magic [42 4C 45 4E 44 45 52] @ 0x00
|
||||
|
||||
/*
|
||||
* References:
|
||||
* https://projects.blender.org/blender/blender
|
||||
* https://github.com/facebook/zstd/blob/master/contrib/seekable_format/zstd_seekable_compression_format.md
|
||||
*
|
||||
* Refer to the following files/structs:
|
||||
* source/blender/blenloader/intern/writefile.cc
|
||||
* source/blender/blenkernel/BKE_main.hh BlendThumbnail
|
||||
* source/blender/makesdna/DNA_sdna_types.h BHead
|
||||
*/
|
||||
|
||||
// Increased the pattern limit to be able to evaluate all pixels of the embedded thumbnail.
|
||||
#pragma pattern_limit 1000000
|
||||
|
||||
#ifdef __IMHEX__
|
||||
import hex.dec;
|
||||
#endif
|
||||
|
||||
import std.core;
|
||||
import std.io;
|
||||
import std.mem;
|
||||
import std.string;
|
||||
import std.sys;
|
||||
import type.color;
|
||||
import type.magic;
|
||||
|
||||
// Useful for extracting the thumbnail if the rest of the blend file is corrupted or truncated.
|
||||
bool quitAfterThumbnailIsParsed in;
|
||||
// Allow the pattern evaluator to skip the thumbnail e.g. if evaluation takes too long.
|
||||
bool skipThumbnail in;
|
||||
|
||||
struct BHead<Ptr> {
|
||||
char code[4];
|
||||
s32 len;
|
||||
Ptr old;
|
||||
s32 SDNAnr;
|
||||
s32 nr;
|
||||
|
||||
// ENDB marks the last data block in the file.
|
||||
if (code == "ENDB") {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
struct ThumbnailLine<auto width> {
|
||||
type::RGBA8 pixels[width];
|
||||
};
|
||||
|
||||
fn copyThumbnail(u32 height, ref auto lines, std::mem::Section target) {
|
||||
for (s64 l = (height - 1), l >= 0, l = l - 1) {
|
||||
u64 currentSectionSize = std::mem::get_section_size(target);
|
||||
// Append the current line to section.
|
||||
std::mem::copy_value_to_section(lines[l], target, currentSectionSize);
|
||||
}
|
||||
};
|
||||
|
||||
struct Thumbnail {
|
||||
u32 width;
|
||||
u32 height;
|
||||
u128 size = width * height;
|
||||
ThumbnailLine<width> lines[height];
|
||||
|
||||
// Generate the thumbnail section.
|
||||
std::mem::Section thumbnailFlipped = std::mem::create_section("thumbnail");
|
||||
copyThumbnail(height, lines, thumbnailFlipped);
|
||||
type::RGBA8 image[size] @ 0x00 in thumbnailFlipped;
|
||||
}
|
||||
#ifdef __IMHEX__
|
||||
[[hex::visualize("bitmap", image, width, height)]]
|
||||
#endif
|
||||
;
|
||||
|
||||
struct DataBlock<Ptr> {
|
||||
BHead<Ptr> bHead;
|
||||
|
||||
if (bHead.SDNAnr == 0 && bHead.code == "TEST") {
|
||||
if (skipThumbnail) {
|
||||
u8 thumbnail[bHead.len]; // Interpret as raw binary data.
|
||||
} else {
|
||||
Thumbnail thumbnail;
|
||||
auto thumbnailSize = sizeof(thumbnail);
|
||||
std::assert(thumbnailSize == bHead.len,
|
||||
std::format("The thumbnail (size={:#x}) does not fit exactly into its DataBlock (len={:#x})!",
|
||||
thumbnailSize, bHead.len));
|
||||
}
|
||||
|
||||
if (quitAfterThumbnailIsParsed) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
u8 data[bHead.len]; // Unknown. Interpret as raw binary data.
|
||||
}
|
||||
};
|
||||
|
||||
enum PointerSize : char {
|
||||
POINTER_4BYTE = '_',
|
||||
POINTER_8BYTE = '-'
|
||||
};
|
||||
|
||||
enum Endianness : char {
|
||||
BIG_ENDIAN = 'V',
|
||||
LITTLE_ENDIAN = 'v'
|
||||
};
|
||||
|
||||
struct Blend<auto inputSize> {
|
||||
type::Magic<"BLENDER"> magic;
|
||||
PointerSize pointerSize;
|
||||
Endianness endianness;
|
||||
char version[3];
|
||||
|
||||
match (endianness) {
|
||||
(Endianness::LITTLE_ENDIAN): std::core::set_endian(std::mem::Endian::Little);
|
||||
(Endianness::BIG_ENDIAN): std::core::set_endian(std::mem::Endian::Big);
|
||||
(_): std::error("Invalid value for endianness!");
|
||||
}
|
||||
|
||||
match (pointerSize) {
|
||||
(PointerSize::POINTER_4BYTE): DataBlock<u32> dataBlock[while($ < inputSize)];
|
||||
(PointerSize::POINTER_8BYTE): DataBlock<u64> dataBlock[while($ < inputSize)];
|
||||
(_): std::error("Invalid pointer size!");
|
||||
}
|
||||
};
|
||||
|
||||
struct BlendWrapper {
|
||||
u128 currentPos = $;
|
||||
char magic[4] @ currentPos [[hidden]];
|
||||
|
||||
if (magic != "\x28\xB5\x2F\xFD") { // ZSTD magic
|
||||
// Assume the blend file is uncompressed.
|
||||
Blend<sizeof($)> blend @ currentPos;
|
||||
return;
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
BlendWrapper blendWrapper @ 0x00;
|
||||
|
||||
// Assume the blend file is ZSTD compressed.
|
||||
|
||||
struct SeekTableFooter {
|
||||
u32 numFrames;
|
||||
char flag;
|
||||
type::Magic<"\xB1\xEA\x92\x8F"> footerMagic;
|
||||
};
|
||||
|
||||
u128 seekTableFooterSize = 9;
|
||||
SeekTableFooter seekTableFooter @ (sizeof($) - seekTableFooterSize);
|
||||
|
||||
struct SeekTableEntry {
|
||||
u32 compressedSize;
|
||||
u32 uncompressedSize;
|
||||
};
|
||||
|
||||
u128 seekTableEntrySize = 8;
|
||||
SeekTableEntry seekTableEntries[seekTableFooter.numFrames]
|
||||
@ (addressof(seekTableFooter) - seekTableFooter.numFrames * seekTableEntrySize);
|
||||
|
||||
struct SeekTableHeader {
|
||||
type::Magic<"\x5E\x2A\x4D\x18"> magic;
|
||||
u32 frameSize;
|
||||
};
|
||||
|
||||
u128 seekTableHeaderSize = 8;
|
||||
std::assert(seekTableFooter.numFrames > 0, "The seek table must contain entries!");
|
||||
SeekTableHeader seekTableHeader @ (addressof(seekTableEntries[0]) - seekTableHeaderSize);
|
||||
|
||||
u32 frameIndex = 0;
|
||||
|
||||
struct ZSTDFrame {
|
||||
u8 data[seekTableEntries[frameIndex].compressedSize];
|
||||
frameIndex = frameIndex + 1;
|
||||
};
|
||||
|
||||
ZSTDFrame zstdFrames[seekTableFooter.numFrames] @ 0x00;
|
||||
|
||||
#ifdef __IMHEX__
|
||||
std::mem::Section decompressedSection = std::mem::create_section("decompressedBlend");
|
||||
u128 previousSectionSize = 0;
|
||||
|
||||
for (u32 i = 0, i < seekTableFooter.numFrames, i = i + 1) {
|
||||
std::assert(hex::dec::zstd_decompress(zstdFrames[i].data, decompressedSection),
|
||||
"Decompression failed!");
|
||||
u32 uncompressedSize = seekTableEntries[i].uncompressedSize;
|
||||
u128 currentSectionSize = std::mem::get_section_size(decompressedSection)
|
||||
- previousSectionSize;
|
||||
std::assert_warn(uncompressedSize == currentSectionSize,
|
||||
std::format("The uncompressedSize {} for ZSTDFrame #{} "
|
||||
+ "must be equal to its actual decompressed size{}!",
|
||||
uncompressedSize, i, currentSectionSize));
|
||||
previousSectionSize += currentSectionSize;
|
||||
};
|
||||
|
||||
Blend<previousSectionSize> blend @ 0x00 in decompressedSection;
|
||||
#endif
|
||||
533
patterns/blf.hexpat
Normal file
533
patterns/blf.hexpat
Normal file
@@ -0,0 +1,533 @@
|
||||
|
||||
|
||||
// Pattern for binary logging files (Vector BLF)
|
||||
// References used for writing this:
|
||||
// https://python-can.readthedocs.io/en/stable/_modules/can/io/blf.html
|
||||
// https://bitbucket.org/tobylorenz/vector_blf
|
||||
|
||||
#pragma magic [ 4C 4F 47 47 ] @ 0x00
|
||||
#pragma description Vector BLF Frame Logging Files
|
||||
#pragma array_limit 4194304
|
||||
#pragma pattern_limit 4294967296
|
||||
#pragma endian little
|
||||
|
||||
import hex.dec;
|
||||
import std.io;
|
||||
import type.magic;
|
||||
|
||||
enum object_type : u32 {
|
||||
unknown = 0, //< unknown object
|
||||
can_message = 1, //< CAN message object
|
||||
can_error = 2, //< CAN error frame object
|
||||
can_overload = 3, //< CAN overload frame object
|
||||
can_statistic = 4, //< CAN driver statistics object
|
||||
app_trigger = 5, //< application trigger object
|
||||
env_integer = 6, //< environment integer object
|
||||
env_double = 7, //< environment double object
|
||||
env_string = 8, //< environment string object
|
||||
env_data = 9, //< environment data object
|
||||
log_container = 10, //< container object
|
||||
lin_message = 11, //< LIN message object
|
||||
lin_crc_error = 12, //< LIN CRC error object
|
||||
lin_dlc_info = 13, //< LIN DLC info object
|
||||
lin_rcv_error = 14, //< LIN receive error object
|
||||
lin_snd_error = 15, //< LIN send error object
|
||||
lin_slv_timeout = 16, //< LIN slave timeout object
|
||||
lin_sched_modch = 17, //< LIN scheduler mode change object
|
||||
lin_syn_error = 18, //< LIN sync error object
|
||||
lin_baudrate = 19, //< LIN baudrate event object
|
||||
lin_sleep = 20, //< LIN sleep mode event object
|
||||
lin_wakeup = 21, //< LIN wakeup event object
|
||||
most_spy = 22, //< MOST spy message object
|
||||
most_ctrl = 23, //< MOST control message object
|
||||
most_lightlock = 24, //< MOST light lock object
|
||||
most_statistic = 25, //< MOST statistic object
|
||||
|
||||
flexray_data = 29, //< FLEXRAY data object
|
||||
flexray_sync = 30, //< FLEXRAY sync object
|
||||
can_driver_error = 31, //< CAN driver error object
|
||||
most_pkt = 32, //< MOST Packet
|
||||
most_pkt2 = 33, //< MOST Packet including original timestamp
|
||||
most_hwmode = 34, //< MOST hardware mode event
|
||||
most_reg = 35, //< MOST register data (various chips)
|
||||
most_genreg = 36, //< MOST register data (MOST register)
|
||||
most_netstate = 37, //< MOST NetState event
|
||||
most_datalost = 38, //< MOST data lost
|
||||
most_trigger = 39, //< MOST trigger
|
||||
flexray_cycle = 40, //< FLEXRAY V6 start cycle object
|
||||
flexray_message = 41, //< FLEXRAY V6 message object
|
||||
lin_checksum_info = 42, //< LIN checksum info event object
|
||||
lin_spike_event = 43, //< LIN spike event object
|
||||
can_driver_sync = 44, //< CAN driver hardware sync
|
||||
flexray_status = 45, //< FLEXRAY status event object
|
||||
gps_event = 46, //< GPS event object
|
||||
flexray_error = 47, //< FLEXRAY error event object
|
||||
flexray_status = 48, //< FLEXRAY status event object
|
||||
flexray_startcycle = 49, //< FLEXRAY start cycle event object
|
||||
flexray_rcv_message = 50, //< FLEXRAY receive message event object
|
||||
realtime_clock = 51, //< Realtime clock object
|
||||
|
||||
lin_statistic = 54, //< LIN statistic event object
|
||||
j1708_message = 55, //< J1708 message object
|
||||
j1708_virtual_message = 56, //< J1708 message object with more than 21 data bytes
|
||||
lin_message2 = 57, //< LIN frame object - extended
|
||||
lin_snd_error2 = 58, //< LIN transmission error object - extended
|
||||
lin_syn_error2 = 59, //< LIN sync error object - extended
|
||||
lin_crc_error2 = 60, //< LIN checksum error object - extended
|
||||
lin_crv_error2 = 61, //< LIN receive error object
|
||||
lin_wakeup2 = 62, //< LIN wakeup event object - extended
|
||||
lin_spike_event2 = 63, //< LIN spike event object - extended
|
||||
lin_long_dom_sig = 64, //< LIN long dominant signal object
|
||||
app_text = 65, //< text object
|
||||
flexray_rcvmessage_ex = 66, //< FLEXRAY receive message ex event object
|
||||
most_statistic_ex = 67, //< MOST extended statistic event
|
||||
most_txlight = 68, //< MOST TxLight event
|
||||
most_alloctab = 69, //< MOST Allocation table event
|
||||
most_stress = 70, //< MOST Stress event
|
||||
ethernet_frame = 71, //< Ethernet frame object
|
||||
sys_variable = 72, //< system variable object
|
||||
can_error_ext = 73, //< CAN error frame object (extended)
|
||||
can_driver_error_ext = 74, //< CAN driver error object (extended)
|
||||
lin_long_dom_sig2 = 75, //< LIN long dominant signal object - extended
|
||||
most_150_message = 76, //< MOST150 Control channel message
|
||||
most_150_pkt = 77, //< MOST150 Asynchronous channel message
|
||||
most_ethernet_pkt = 78, //< MOST Ethernet channel message
|
||||
most_150_message_fragment = 79, //< Partial transmitted MOST50/150 Control channel message
|
||||
most_150_pkt_fragment = 80, //< Partial transmitted MOST50/150 data packet on asynchronous channel
|
||||
most_ethernet_pkt_fragment = 81, //< Partial transmitted MOST Ethernet packet on asynchronous channel
|
||||
most_system_event = 82, //< Event for various system states on MOST
|
||||
most_150_alloctab = 83, //< MOST50/150 Allocation table event
|
||||
most_50_message = 84, //< MOST50 Control channel message
|
||||
most_50_pkg = 85, //< MOST50 Asynchronous channel message
|
||||
can_message2 = 86, //< CAN message object - extended
|
||||
lin_unexpected_wakeup = 87,
|
||||
lin_short_or_slow_response = 88,
|
||||
lin_disturbance_event = 89,
|
||||
serial_event = 90,
|
||||
overrun_error = 91, //< driver overrun event
|
||||
event_comment = 92,
|
||||
wlan_frame = 93,
|
||||
wlan_statistic = 94,
|
||||
most_ecl = 95, //< MOST Electrical Control Line event
|
||||
global_marker = 96,
|
||||
afdx_frame = 97,
|
||||
afdx_statistic = 98,
|
||||
kline_statusevent = 99, //< E.g. wake-up pattern
|
||||
can_fd_message = 100, //< CAN FD message object
|
||||
can_fd_message_64 = 101, //< CAN FD message object
|
||||
ethernet_rx_error = 102, //< Ethernet RX error object
|
||||
ethernet_status = 103, //< Ethernet status object
|
||||
can_fd_error_64 = 104, //< CAN FD Error Frame object
|
||||
lin_short_or_slow_response2 = 105,
|
||||
afdx_status = 106, //< AFDX status object
|
||||
afdx_bus_statistic = 107, //< AFDX line-dependent busstatistic object
|
||||
|
||||
afdx_error_event = 109, //< AFDX asynchronous error event
|
||||
a429_error = 110, //< A429 error object
|
||||
a429_status = 111, //< A429 status object
|
||||
a429_bus_statistic = 112, //< A429 busstatistic object
|
||||
a429_message = 113, //< A429 Message
|
||||
ethernet_statistic = 114, //< Ethernet statistic object
|
||||
restore_point_container = 115, //< Restore point container, use unknown
|
||||
|
||||
test_structure = 118, //< Event for test execution flow
|
||||
diag_request_information = 119, //< Event for correct interpretation of diagnostic requests
|
||||
ethernet_frame_ex = 120, //< Ethernet packet extended object
|
||||
ethernet_frame_forwarded = 121, //< Ethernet packet forwarded object
|
||||
ethernet_error_ex = 122, //< Ethernet error extended object
|
||||
ethernet_error_forwarded = 123, //< Ethernet error forwarded object
|
||||
function_bus = 124, //< FunctionBus object
|
||||
data_lost_begin = 125, //< Data lost begin
|
||||
data_lost_end = 126, //< Data lost end
|
||||
water_mark_event = 127, //< Watermark event
|
||||
trigger_condition = 128, //< Trigger Condition event
|
||||
can_setting_changed = 129, //< CAN Settings Changed object
|
||||
distributed_object_member = 130, //< Distributed object member (communication setup)
|
||||
attribute_event = 131, //< ATTRIBUTE event (communication setup)
|
||||
};
|
||||
|
||||
bitfield can_msg_flags {
|
||||
is_tx : 1;
|
||||
padding : 4;
|
||||
nerr : 1;
|
||||
wu : 1;
|
||||
rtr : 1;
|
||||
};
|
||||
|
||||
struct can_msg {
|
||||
u16 channel;
|
||||
can_msg_flags flags;
|
||||
u8 dlc;
|
||||
u32 id;
|
||||
u8 data[8];
|
||||
};
|
||||
struct can_msg2 {
|
||||
u16 channel;
|
||||
can_msg_flags flags;
|
||||
u8 dlc;
|
||||
u32 id;
|
||||
|
||||
auto struct_len = 2 + 1 + 1 + 4 + 4 + 1 + 1 + 2; // TODO: Alternative way of doing this?
|
||||
u8 data[parent.header.object_size - parent.header.header_size - struct_len];
|
||||
|
||||
// The frame length in nanoseconds
|
||||
u32 frame_length;
|
||||
// Total number of bits of the CAN frame
|
||||
u8 bit_count;
|
||||
padding[1];
|
||||
padding[2];
|
||||
};
|
||||
|
||||
bitfield can_fd_msg_flags {
|
||||
edl : 1; //< Extended data length
|
||||
brs : 1; //< Bit rate switch
|
||||
esi : 1; //< Error state indicator
|
||||
padding : 5;
|
||||
};
|
||||
|
||||
fn format_can_fd_dlc(u8 dlc) {
|
||||
if (dlc > 8)
|
||||
return 8 + (dlc - 8) * 4;
|
||||
return dlc;
|
||||
};
|
||||
|
||||
struct can_fd_msg {
|
||||
u16 channel;
|
||||
u8 flags;
|
||||
u8 dlc [[format("format_can_fd_dlc")]];
|
||||
u32 id;
|
||||
|
||||
// The frame length in nanoseconds
|
||||
u32 frame_length;
|
||||
u8 arbitration_bit_count;
|
||||
can_fd_msg_flags fd_flags;
|
||||
u8 valid_data_bytes;
|
||||
padding[1];
|
||||
padding[4];
|
||||
|
||||
u8 data[64];
|
||||
|
||||
padding[4];
|
||||
};
|
||||
|
||||
bitfield can_fd_msg_64_flags {
|
||||
padding : 2;
|
||||
nerr : 1;
|
||||
hv_wake_up : 1;
|
||||
remote_frame : 1;
|
||||
padding : 1;
|
||||
tx_ack : 1;
|
||||
tx_req : 1;
|
||||
padding : 1;
|
||||
srr : 1;
|
||||
r0 : 1;
|
||||
r1 : 1;
|
||||
edl : 1; //< Extended data length
|
||||
brs : 1; //< Bit rate switch
|
||||
esi : 1; //< Error state indicator
|
||||
padding : 2;
|
||||
burst : 1;
|
||||
padding : 13;
|
||||
};
|
||||
struct can_bitrate_cfg {
|
||||
u8 quartz_frequency;
|
||||
u8 prescaler;
|
||||
u8 btl_cycles;
|
||||
u8 sampling_point;
|
||||
};
|
||||
struct can_fd_msg_64 {
|
||||
u8 channel;
|
||||
u8 dlc [[format("format_can_fd_dlc")]];
|
||||
u8 valid_data_bytes;
|
||||
u8 tx_count;
|
||||
u32 id;
|
||||
u32 frame_length;
|
||||
can_fd_msg_64_flags flags;
|
||||
can_bitrate_cfg arbitration_bitrate;
|
||||
can_bitrate_cfg data_bitrate;
|
||||
u32 brs_time_offset;
|
||||
u32 crc_time_offset;
|
||||
u16 bit_length;
|
||||
u8 direction;
|
||||
u8 data_offset;
|
||||
u32 crc;
|
||||
|
||||
u8 data[valid_data_bytes];
|
||||
};
|
||||
|
||||
fn format_bus_load(u16 bus_load) {
|
||||
return std::format("{}%", float(bus_load) / 100.f);
|
||||
};
|
||||
struct can_statistic {
|
||||
u16 channel;
|
||||
// Bus load in 1/100 percent
|
||||
u16 bus_load [[format("format_bus_load")]];
|
||||
|
||||
u32 standard_data_frames;
|
||||
u32 extended_data_frames;
|
||||
|
||||
u32 standard_remote_frames;
|
||||
u32 extended_remote_frames;
|
||||
|
||||
u32 error_frames;
|
||||
u32 overload_frames;
|
||||
|
||||
u32 reserved;
|
||||
};
|
||||
|
||||
struct can_driver_error {
|
||||
u16 channel;
|
||||
u8 tx_errors;
|
||||
u8 rx_errors;
|
||||
u32 error_code;
|
||||
};
|
||||
|
||||
enum app_text_source : u32 {
|
||||
comment = 0,
|
||||
database_info = 1,
|
||||
metadata = 2,
|
||||
};
|
||||
enum database_bus_type : u8 {
|
||||
can = 1,
|
||||
lin = 5,
|
||||
most = 6,
|
||||
flexray = 7,
|
||||
j1708 = 9,
|
||||
ethernet = 10,
|
||||
wlan = 13,
|
||||
afdx = 14,
|
||||
};
|
||||
bitfield app_text_database_info {
|
||||
version : 8;
|
||||
channel_num : 8;
|
||||
database_bus_type bus_type : 8;
|
||||
is_can_fd : 1;
|
||||
padding : 7;
|
||||
};
|
||||
struct app_text {
|
||||
app_text_source source;
|
||||
if (source == 1)
|
||||
app_text_database_info database_info;
|
||||
else
|
||||
padding[4]; // TODO: This is not necessarily padding, there's data here
|
||||
u32 text_length;
|
||||
padding[4];
|
||||
char text[text_length];
|
||||
};
|
||||
|
||||
// No idea what this is or does
|
||||
struct restore_point_container {
|
||||
u8 rpc[14];
|
||||
u16 data_len;
|
||||
u8 data[data_len];
|
||||
};
|
||||
|
||||
enum compression_method : u16 {
|
||||
no_compression = 0,
|
||||
zlib = 2,
|
||||
};
|
||||
|
||||
// The following section contains all of the decompressed data at once
|
||||
std::mem::Section decompressed_data = std::mem::create_section("Decompressed data");
|
||||
// This section is used only for decompressing data
|
||||
std::mem::Section zlib_decompress_result = std::mem::create_section("zlib decompress result");
|
||||
|
||||
struct log_container {
|
||||
u64 container_begin = $;
|
||||
|
||||
compression_method compression_method;
|
||||
padding[2];
|
||||
padding[4];
|
||||
u32 uncompressed_size;
|
||||
padding[4];
|
||||
|
||||
if (compression_method == compression_method::zlib) {
|
||||
std::mem::set_section_size(zlib_decompress_result, uncompressed_size);
|
||||
|
||||
// Create a pattern that defines the compressed array data
|
||||
auto compressed_byte_len = parent.header.object_size - parent.header.header_size - ($ - container_begin);
|
||||
u8 compressed[compressed_byte_len];
|
||||
if (uncompressed_size != 0)
|
||||
padding[parent.header.object_size % 4]; // Idk, the format wants this... for some reason
|
||||
|
||||
std::assert(hex::dec::zlib_decompress(compressed, zlib_decompress_result) == compressed_byte_len,
|
||||
"zlib decompress needs to succeed");
|
||||
|
||||
// Copy the decompressed data to the end of the section
|
||||
std::mem::copy_section_to_section(zlib_decompress_result, 0,
|
||||
decompressed_data, std::mem::get_section_size(decompressed_data),
|
||||
std::mem::get_section_size(zlib_decompress_result));
|
||||
} else if (compression_method == compression_method::no_compression) {
|
||||
u8 data[uncompressed_size];
|
||||
std::mem::copy_value_to_section(data, decompressed_data, std::mem::get_section_size(decompressed_data));
|
||||
} else {
|
||||
std::assert(false, "Invalid/unknown compression method");
|
||||
}
|
||||
};
|
||||
|
||||
enum object_flags : u32 {
|
||||
// Timestamps are stored with a unit of 10us (10 microseconds)
|
||||
time_10_us = 1,
|
||||
// Timestamps are stored with a unit of 1ns (1 nanosecond)
|
||||
time_1_ns = 2,
|
||||
};
|
||||
|
||||
enum timestamp_status : u8 {
|
||||
// Means original timestamps are valid
|
||||
orig = 0x01,
|
||||
// Timestamp is generated by software (1) or by hardware (0)
|
||||
swhw = 0x02,
|
||||
user = 0x10,
|
||||
};
|
||||
|
||||
struct obj_header_ext {
|
||||
object_flags flags;
|
||||
if (parent.header.header_version == 1)
|
||||
u16 client_index;
|
||||
else if (parent.header.header_version == 2) {
|
||||
timestamp_status timestamp_status;
|
||||
padding[1];
|
||||
}
|
||||
u16 object_version;
|
||||
u64 object_timestamp;
|
||||
if (parent.header.header_version == 2)
|
||||
u64 original_timestamp;
|
||||
};
|
||||
|
||||
struct obj_header {
|
||||
type::Magic<"LOBJ"> magic; // 4C 4F 42 4A
|
||||
u16 header_size;
|
||||
u16 header_version;
|
||||
u32 object_size;
|
||||
object_type object_type;
|
||||
|
||||
std::assert(header_version == 1 || header_version == 2, "Invalid/unknown header version");
|
||||
};
|
||||
|
||||
struct obj_struct {
|
||||
auto object_begin = $;
|
||||
obj_header header [[inline]];
|
||||
|
||||
if (header.object_type == object_type::log_container) {
|
||||
// Log containers seem to never include additional V1 or V2 headers
|
||||
log_container log [[inline]];
|
||||
} else {
|
||||
obj_header_ext ext_header [[inline]];
|
||||
|
||||
match(header.object_type) {
|
||||
(object_type::can_message): {
|
||||
can_msg message [[inline]];
|
||||
}
|
||||
(object_type::can_statistic): {
|
||||
can_statistic statistics [[inline]];
|
||||
}
|
||||
(object_type::can_driver_error): {
|
||||
can_driver_error errors [[inline]];
|
||||
}
|
||||
(object_type::can_message2): {
|
||||
can_msg2 message [[inline]];
|
||||
}
|
||||
(object_type::can_fd_message): {
|
||||
can_fd_msg message [[inline]];
|
||||
}
|
||||
(object_type::can_fd_message_64): {
|
||||
can_fd_msg_64 message [[inline]];
|
||||
padding[header.object_size - ($ - object_begin)]; // TODO: This pattern doesn't support the extra data for this object
|
||||
}
|
||||
(object_type::app_text): {
|
||||
app_text text [[inline]];
|
||||
padding[header.object_size % 4];
|
||||
}
|
||||
(object_type::restore_point_container): {
|
||||
restore_point_container rpc [[inline]];
|
||||
}
|
||||
(_): u8 bytes[header.object_size - header.header_size];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum application_id : u8 {
|
||||
unknown = 0,
|
||||
canalyzer = 1,
|
||||
canoe = 2,
|
||||
canstress = 3,
|
||||
canlog = 4,
|
||||
canape = 5,
|
||||
cancasexl = 6,
|
||||
vlconfig = 7,
|
||||
porsche_logger = 200,
|
||||
caetec_logger = 201,
|
||||
vector_net_sim = 202,
|
||||
ipetronik_logger = 203,
|
||||
rtpk = 204,
|
||||
piketec = 205,
|
||||
sparks = 206,
|
||||
};
|
||||
|
||||
fn format_api_version(u32 api_version) {
|
||||
return std::format("{}.{}.{}",
|
||||
api_version / 1000000,
|
||||
(api_version % 1000000) / 1000,
|
||||
(api_version % 1000) / 100);
|
||||
};
|
||||
|
||||
// Mostly just the zlib compression levels, but with some extras
|
||||
enum compression_level : u8 {
|
||||
no_compression = 0,
|
||||
best_speed = 1,
|
||||
default_compression = 6,
|
||||
best_compression = 9,
|
||||
// This means that the file contains only log containers, usually compressed at level 6
|
||||
default_container_compression = 10,
|
||||
};
|
||||
|
||||
struct timestamp {
|
||||
u16 year;
|
||||
u16 month;
|
||||
u16 day_of_week;
|
||||
u16 day;
|
||||
u16 hour;
|
||||
u16 minute;
|
||||
u16 second;
|
||||
u16 millisecond;
|
||||
} [[format("format_timestamp")]];
|
||||
fn format_timestamp(timestamp ts) {
|
||||
return std::format("{}-{}-{}_{}-{}-{}",
|
||||
ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second);
|
||||
};
|
||||
|
||||
struct file_header {
|
||||
type::Magic<"LOGG"> magic; // 4C 4F 47 47
|
||||
u32 header_length;
|
||||
|
||||
u32 api_version [[format("format_api_version")]];
|
||||
application_id app_id;
|
||||
compression_level compression_level;
|
||||
u8 app_major;
|
||||
u8 app_minor;
|
||||
|
||||
u64 file_length;
|
||||
u64 uncompressed_length;
|
||||
u32 object_count;
|
||||
u32 application_build;
|
||||
|
||||
timestamp start_timestamp;
|
||||
timestamp stop_timestamp;
|
||||
|
||||
u64 restore_point_offset; // ?
|
||||
} [[inline]];
|
||||
|
||||
struct file_layout {
|
||||
file_header header;
|
||||
padding[header.header_length - sizeof(header)];
|
||||
obj_struct objects[while($ < std::mem::size())];
|
||||
|
||||
// Decode all objects from the zlib compressed data
|
||||
if (std::mem::get_section_size(decompressed_data) != 0)
|
||||
obj_struct decompressed_objects[header.object_count] @ 0x00 in decompressed_data;
|
||||
} [[inline]];
|
||||
|
||||
file_layout file @ 0x00;
|
||||
|
||||
std::assert_warn(std::mem::size() == file.header.file_length, "file size mismatch");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma description OS2/Windows Bitmap files
|
||||
#pragma description OS2/Windows Bitmap
|
||||
|
||||
#pragma MIME image/bmp
|
||||
#pragma endian little
|
||||
@@ -97,7 +97,7 @@ struct Bitmap {
|
||||
(_): BitmapInfoHeaderV1 bmih;
|
||||
}
|
||||
padding[bmih.biSize - sizeof(bmih)];
|
||||
|
||||
|
||||
if (bmih.biBitCount <= 8)
|
||||
{
|
||||
if (bmih.biClrUsed > 0 )
|
||||
@@ -105,7 +105,7 @@ struct Bitmap {
|
||||
else
|
||||
Colors rgbq[1 << bmih.biBitCount];
|
||||
}
|
||||
|
||||
|
||||
if (bmih.biSizeImage > 0 )
|
||||
u8 lineData[bmih.biSizeImage];
|
||||
else
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma description Apple binary property list
|
||||
#pragma MIME application/x-bplist
|
||||
|
||||
import std.math;
|
||||
import std.core;
|
||||
import type.magic;
|
||||
@@ -27,14 +30,14 @@ enum Marker : u8 {
|
||||
UNK_0xF0 = 0xF0
|
||||
};
|
||||
|
||||
fn get_marker_name(u8 marker) {
|
||||
fn get_marker_name(u8 marker) {
|
||||
if (marker == Marker::Null){// null 0000 0000
|
||||
return "Null ";
|
||||
}else if (marker == Marker::False){ //bool 0000 1000 // false
|
||||
return "False";
|
||||
}else if (marker == Marker::True){//bool 0000 1001 // true
|
||||
return "True";
|
||||
}else if (marker == Marker::Fill){ //fill 0000 1111 // fill byte
|
||||
}else if (marker == Marker::Fill){ //fill 0000 1111 // fill byte
|
||||
return "Fill";
|
||||
}else if (marker & 0xF0 == Marker::Int){ //int 0001 nnnn ... // # of bytes is 2^nnnn, big-endian bytes
|
||||
return "Int";
|
||||
@@ -43,10 +46,10 @@ fn get_marker_name(u8 marker) {
|
||||
}else if (marker == Marker::Date){ //date 0011 0011 ... // 8 byte float follows, big-endian bytes
|
||||
return "Date";
|
||||
}else if (marker & 0xF0 == Marker::Data){ //data 0100 nnnn [int] ... // nnnn is number of bytes unless 1111 then int count follows, followed by bytes
|
||||
return "Data";
|
||||
return "Data";
|
||||
}else if (marker & 0xF0 == Marker::ASCIIString){ //string 0101 nnnn [int] ... // ASCII string, nnnn is # of chars, else 1111 then int count, then bytes
|
||||
return "ASCIIString";
|
||||
}else if (marker & 0xF0 == Marker::Unicode16String){ //string 0110 nnnn [int] ... // Unicode string, nnnn is # of chars, else 1111 then int count, then big-endian 2-byte
|
||||
}else if (marker & 0xF0 == Marker::Unicode16String){ //string 0110 nnnn [int] ... // Unicode string, nnnn is # of chars, else 1111 then int count, then big-endian 2-byte
|
||||
return "Unicode16String";
|
||||
}else if (marker & 0xF0 == Marker::UNK_0x70){ //0111 xxxx // unused
|
||||
return "UNK_0x70";
|
||||
@@ -54,19 +57,19 @@ fn get_marker_name(u8 marker) {
|
||||
return "UID";
|
||||
}else if (marker & 0xF0 == Marker::UNK_0x90){ // 1001 xxxx // unused
|
||||
return "UNK_0x90";
|
||||
}else if (marker & 0xF0 == Marker::Array){ //array 1010 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows
|
||||
}else if (marker & 0xF0 == Marker::Array){ //array 1010 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows
|
||||
return "Array";
|
||||
}else if (marker & 0xF0 == Marker::UNK_0xB0){ //1011 xxxx // unused
|
||||
return "UNK_0xB0";
|
||||
}else if (marker & 0xF0 == Marker::Set){ //set 1100 nnnn [int] objref* // nnnn is count, unless '1111', then int count follows
|
||||
return "Set";
|
||||
}else if (marker & 0xF0 == Marker::Dict){ //dict 1101 nnnn [int] keyref* objref* // nnnn is count, unless '1111', then int count follows
|
||||
}else if (marker & 0xF0 == Marker::Dict){ //dict 1101 nnnn [int] keyref* objref* // nnnn is count, unless '1111', then int count follows
|
||||
return "Dict";
|
||||
}else if (marker & 0xF0 == Marker::UNK_0xE0){ // 1110 xxxx // unused
|
||||
return "UNK_0xE0";
|
||||
}else if (marker & 0xF0 == Marker::UNK_0xF0){ //1111 xxxx // unused
|
||||
return "UNK_0xF0";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn format_tag(u8 marker) {
|
||||
@@ -77,12 +80,12 @@ fn coredata_to_date (double val){
|
||||
return type::impl::format_time_t(978307200 + val);
|
||||
};
|
||||
|
||||
struct DictElement {
|
||||
struct DictElement {
|
||||
CFBinaryPlistObject key @ offsetTable[parent.objReference.key_refs[std::core::array_index()]].offset;
|
||||
CFBinaryPlistObject value @ offsetTable[parent.objReference.value_refs[std::core::array_index()]].offset;
|
||||
};
|
||||
|
||||
struct ArrayElement {
|
||||
struct ArrayElement {
|
||||
CFBinaryPlistObject value @ offsetTable[parent.objReference.value_refs[std::core::array_index()]].offset;
|
||||
};
|
||||
|
||||
@@ -140,23 +143,23 @@ struct CFBinaryPlistOffset{
|
||||
|
||||
struct CFBinaryPlistObject{
|
||||
u8 marker [[format("get_marker_name")]];
|
||||
|
||||
|
||||
u8 marker_msb = marker & 0xF0;
|
||||
u8 marker_lsb = marker & 0x0F;
|
||||
|
||||
match (marker_msb){
|
||||
match (marker_msb){
|
||||
(0x0): {
|
||||
match (marker_lsb){
|
||||
(Marker::Null): {
|
||||
u8 value = 0x00 [[export]];
|
||||
}
|
||||
(Marker::False): {
|
||||
(Marker::False): {
|
||||
bool value = false [[export]];
|
||||
}
|
||||
(Marker::True): {
|
||||
bool value = true [[export]];
|
||||
}
|
||||
(Marker::Fill): {
|
||||
(Marker::Fill): {
|
||||
//I think the correct implementation is to do nothing here. The marker will be used as padding (Fill) ???
|
||||
}
|
||||
(_): {
|
||||
@@ -165,7 +168,7 @@ struct CFBinaryPlistObject{
|
||||
}
|
||||
}
|
||||
(Marker::Int): {
|
||||
be u8 size = std::math::pow(2, marker_lsb);
|
||||
be u8 size = std::math::pow(2, marker_lsb);
|
||||
// in format version '00', 1, 2, and 4-byte integers have to be interpreted as unsigned,
|
||||
// whereas 8-byte integers are signed (and 16-byte when available)
|
||||
// negative 1, 2, 4-byte integers are always emitted as 8 bytes in format '00'
|
||||
@@ -179,10 +182,10 @@ struct CFBinaryPlistObject{
|
||||
(8): be s64 value;
|
||||
(16): be s128 value;
|
||||
(_): std::error(std::format("Invalid size detected for 'Int' marker. Got size: {}.", size));
|
||||
}
|
||||
}
|
||||
}
|
||||
(Marker::Real): {
|
||||
be u8 size = std::math::pow(2, marker_lsb);
|
||||
be u8 size = std::math::pow(2, marker_lsb);
|
||||
match (size){
|
||||
(4): be float value;
|
||||
(8): be double value;
|
||||
@@ -194,7 +197,7 @@ struct CFBinaryPlistObject{
|
||||
}
|
||||
(Marker::Data): {
|
||||
ObjectLen ObjectLen;
|
||||
u8 value[ObjectLen.size];
|
||||
u8 value[ObjectLen.size];
|
||||
}
|
||||
(Marker::ASCIIString): {
|
||||
ObjectLen ObjectLen;
|
||||
@@ -214,7 +217,7 @@ struct CFBinaryPlistObject{
|
||||
(8): be u64 value;
|
||||
(16): be u128 value;
|
||||
(_): std::error(std::format("Invalid size detected for 'UID' marker. Got size: {}.", size));
|
||||
}
|
||||
}
|
||||
}
|
||||
(Marker::Set | Marker::Array): {
|
||||
ObjectLen ObjectLen;
|
||||
@@ -224,7 +227,7 @@ struct CFBinaryPlistObject{
|
||||
}
|
||||
(Marker::Dict): {
|
||||
ObjectLen ObjectLen;
|
||||
|
||||
|
||||
ObjectReference objReference;
|
||||
DictElement value[ObjectLen.size];
|
||||
}
|
||||
@@ -233,7 +236,7 @@ struct CFBinaryPlistObject{
|
||||
}
|
||||
(_): {
|
||||
std::error(std::format("Got unknown marker 0x{:x}", marker));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -247,13 +250,13 @@ struct CFBinaryPlistHeader{
|
||||
|
||||
struct CFBinaryPlistTrailer {
|
||||
u8 unused[5];
|
||||
u8 sortVersion;
|
||||
u8 sortVersion;
|
||||
be u8 offsetIntSize;
|
||||
match (offsetIntSize){
|
||||
(1|2|4|8): {}
|
||||
(_): {std::error("Invalid offsetIntSize.");}
|
||||
}
|
||||
be u8 objectRefSize;
|
||||
be u8 objectRefSize;
|
||||
match (objectRefSize){
|
||||
(1|2|4|8): {}
|
||||
(_): {std::error("Invalid objectRefSize.");}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description BSON (Binary JSON) format
|
||||
#pragma description BSON (Binary JSON)
|
||||
|
||||
#pragma MIME application/bson
|
||||
|
||||
@@ -26,8 +26,8 @@ enum Type : u8 {
|
||||
Timestamp = 0x11,
|
||||
Int64 = 0x12,
|
||||
Decimal128 = 0x13,
|
||||
|
||||
MinKey = 0xFF,
|
||||
|
||||
MinKey = 0xFF,
|
||||
MaxKey = 0x7F
|
||||
};
|
||||
|
||||
@@ -78,9 +78,9 @@ using Document;
|
||||
|
||||
struct Element {
|
||||
Type type;
|
||||
|
||||
|
||||
CString name;
|
||||
|
||||
|
||||
if (type == Type::Double) {
|
||||
double value;
|
||||
} else if (type == Type::String) {
|
||||
@@ -93,9 +93,9 @@ struct Element {
|
||||
Binary value;
|
||||
} else if (type == Type::Undefined) {
|
||||
/* undefined */
|
||||
} else if (type == Type::ObjectId) {
|
||||
} else if (type == Type::ObjectId) {
|
||||
ObjectId value;
|
||||
} else if (type == Type::Boolean) {
|
||||
} else if (type == Type::Boolean) {
|
||||
bool value;
|
||||
} else if (type == Type::UTCDatetime) {
|
||||
type::time64_t value;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma description GoldSrc engine maps format (used in Half-Life 1)
|
||||
#pragma description GoldSrc engine map (Half-Life 1)
|
||||
|
||||
import std.ptr;
|
||||
import std.mem;
|
||||
@@ -163,7 +163,7 @@ struct dmiptexlump_t
|
||||
MiptexPointer dataofs[nummiptex];
|
||||
};
|
||||
|
||||
struct VisibilityData
|
||||
struct VisibilityData
|
||||
{
|
||||
u8 data[file_header.lumps[LumpIndex::Visibility].filelen];
|
||||
u8 pad[std::mem::align_to(4, sizeof(this)) - sizeof(this)];
|
||||
|
||||
64
patterns/bzip3.hexpat
Normal file
64
patterns/bzip3.hexpat
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma author Sewer56
|
||||
#pragma description Parses BZip3 compression (file format) by Kamila Szewczyk
|
||||
#pragma MIME application/x-bzip3
|
||||
#pragma endian little
|
||||
#pragma magic [42 5A 33 76 31] @ 0x00
|
||||
import std.mem;
|
||||
|
||||
// Helper function for bit counting
|
||||
fn popcount(u8 b) {
|
||||
u32 count = 0;
|
||||
while (b != 0) {
|
||||
count = count + (b & 1);
|
||||
b = b >> 1;
|
||||
}
|
||||
return count;
|
||||
};
|
||||
|
||||
// Frame header structure
|
||||
struct FrameHeader {
|
||||
char magic[5]; // "BZ3v1"
|
||||
u32 blockSize; // Maximum block size
|
||||
};
|
||||
|
||||
// Small block header (for blocks < 64 bytes)
|
||||
struct SmallBlock {
|
||||
u32 crc32; // CRC32 checksum
|
||||
u32 literal; // Always 0xFFFFFFFF for small blocks
|
||||
u8 data[parent.compressedSize - 8]; // Uncompressed data
|
||||
};
|
||||
|
||||
// Regular block (blocks > 64 bytes)
|
||||
struct Block {
|
||||
u32 crc32; // CRC32 checksum of uncompressed data
|
||||
u32 bwtIndex; // Burrows-Wheeler transform index
|
||||
u8 model; // Compression model flags
|
||||
|
||||
if ((model & 0x02) != 0)
|
||||
u32 lzpSize; // Size after LZP compression
|
||||
if ((model & 0x04) != 0)
|
||||
u32 rleSize; // Size after RLE compression
|
||||
|
||||
u8 data[parent.compressedSize - (popcount(model) * 4 + 9)];
|
||||
};
|
||||
|
||||
// Main block structure
|
||||
struct Chunk {
|
||||
u32 compressedSize; // Size of compressed block
|
||||
u32 origSize; // Original uncompressed size
|
||||
|
||||
if (origSize < 64) {
|
||||
SmallBlock block;
|
||||
} else {
|
||||
Block block;
|
||||
}
|
||||
};
|
||||
|
||||
// Main parsing structure
|
||||
struct BZip3File {
|
||||
FrameHeader header;
|
||||
// Read blocks until end of file
|
||||
Chunk chunks[while(!std::mem::eof())];
|
||||
};
|
||||
|
||||
BZip3File file @ 0x0;
|
||||
110
patterns/cab.hexpat
Normal file
110
patterns/cab.hexpat
Normal file
@@ -0,0 +1,110 @@
|
||||
#pragma author The Wandering Trader
|
||||
#pragma description Microsoft Cabinet (CAB) Files
|
||||
#pragma magic [4D 53 43 46] @ 0x00
|
||||
|
||||
import type.time;
|
||||
import type.magic;
|
||||
import type.size;
|
||||
|
||||
fn format_string(auto string) {
|
||||
return std::format("{}",string);
|
||||
};
|
||||
|
||||
bitfield flags {
|
||||
bool cfhdrPREV_CABINET : 1;
|
||||
bool cfhdrNEXT_CABINET : 1;
|
||||
bool cfhdrRESERVE_PRESENT : 1;
|
||||
padding : 13;
|
||||
};
|
||||
|
||||
struct CFHEADER {
|
||||
type::Magic<"MSCF"> signature;
|
||||
u32 reserved1;
|
||||
type::Size32 cbCabinet;
|
||||
u32 reserved2;
|
||||
u32 coffFiles;
|
||||
u32 reserved3;
|
||||
u8 versionMajor;
|
||||
u8 versionMinor;
|
||||
u16 cFolders;
|
||||
u16 cFiles;
|
||||
flags flags;
|
||||
u16 setID;
|
||||
u16 iCabinet;
|
||||
if (flags.cfhdrRESERVE_PRESENT) {
|
||||
type::Size16 cbCFHeader;
|
||||
type::Size8 cbCFFolder;
|
||||
type::Size8 cbCFData;
|
||||
u8 abReserve[cbCFHeader];
|
||||
}
|
||||
if (flags.cfhdrPREV_CABINET) {
|
||||
char szCabinetPrev[] [[format("format_string")]];
|
||||
char szDiskPrev[] [[format("format_string")]];
|
||||
}
|
||||
if (flags.cfhdrNEXT_CABINET) {
|
||||
char szCabinetNext[] [[format("format_string")]];
|
||||
char szDiskNext[] [[format("format_string")]];
|
||||
}
|
||||
};
|
||||
|
||||
enum typeCompress : u8{
|
||||
tcompMASK_TYPE = 0x000F,
|
||||
tcompTYPE_NONE = 0x0000,
|
||||
tcompTYPE_MSZIP = 0x0001,
|
||||
tcompTYPE_QUANTUM = 0x0002,
|
||||
tcompTYPE_LZX = 0x0003,
|
||||
};
|
||||
|
||||
using CFDATA;
|
||||
|
||||
struct CFFOLDER {
|
||||
u32 coffCabStart;
|
||||
u16 cCfData;
|
||||
typeCompress typeCompress;
|
||||
u8 compressionLevel;
|
||||
if (CFHEADER.flags.cfhdrRESERVE_PRESENT) {
|
||||
u8 abReserve[CFHEADER.cbCFFolder];
|
||||
}
|
||||
CFDATA CFDATA[cCfData] @ coffCabStart;
|
||||
};
|
||||
|
||||
bitfield attribs {
|
||||
bool _A_RDONLY : 1;
|
||||
bool _A_HIDDEN : 1;
|
||||
bool _A_SYSTEM : 1;
|
||||
padding : 2;
|
||||
bool _A_ARCH : 1;
|
||||
bool _A_EXEC : 1;
|
||||
bool _A_NAME_IS_UTF : 1;
|
||||
padding : 8;
|
||||
};
|
||||
|
||||
struct CFFILE {
|
||||
type::Size32 cbFile;
|
||||
u32 uoffFolderStart;
|
||||
u16 iFolder;
|
||||
type::DOSDate date;
|
||||
type::DOSTime time;
|
||||
attribs attribs;
|
||||
if (attribs._A_NAME_IS_UTF) {
|
||||
char16 szName[];
|
||||
} else {
|
||||
char szName[] [[format("format_string")]];
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct CFDATA {
|
||||
u32 csum;
|
||||
type::Size16 cbData;
|
||||
type::Size16 cbUncomp;
|
||||
if (CFHEADER.flags.cfhdrRESERVE_PRESENT) {
|
||||
u8 abReserve[CFHEADER.cbCFData];
|
||||
}
|
||||
u8 ab[cbData];
|
||||
};
|
||||
|
||||
CFHEADER CFHEADER @ 0;
|
||||
CFFOLDER CFFOLDER[CFHEADER.cFolders] @ $;
|
||||
CFFILE CFFILE[CFHEADER.cFiles] @ $;
|
||||
@@ -1,29 +1,29 @@
|
||||
#pragma description Compact Disc Audio track
|
||||
#pragma magic [ 52 49 46 46 ] @ 0x00
|
||||
|
||||
struct Header {
|
||||
u32 RIFF;
|
||||
s32 size;
|
||||
u32 CDDA;
|
||||
u32 fmt;
|
||||
u32 lenghtofthechunck;
|
||||
u16 versionofcdformat;
|
||||
u16 numberofrange;
|
||||
u32 identifier;
|
||||
u32 RIFF;
|
||||
s32 size;
|
||||
u32 CDDA;
|
||||
u32 fmt;
|
||||
u32 lenghtofthechunck;
|
||||
u16 versionofcdformat;
|
||||
u16 numberofrange;
|
||||
u32 identifier;
|
||||
};
|
||||
|
||||
|
||||
struct DataInfo {
|
||||
|
||||
u32 range;
|
||||
u32 duration;
|
||||
u8 rangepositionframes;
|
||||
u8 rangepositionseconds;
|
||||
u8 rangepositionminutes;
|
||||
u8 nullbyte;
|
||||
u8 durationtrackframes;
|
||||
u8 durationtrackseconds;
|
||||
u8 durationtrackminutes;
|
||||
u8 nullbytee;
|
||||
u32 range;
|
||||
u32 duration;
|
||||
u8 rangepositionframes;
|
||||
u8 rangepositionseconds;
|
||||
u8 rangepositionminutes;
|
||||
u8 nullbyte;
|
||||
u8 durationtrackframes;
|
||||
u8 durationtrackseconds;
|
||||
u8 durationtrackminutes;
|
||||
u8 nullbytee;
|
||||
};
|
||||
|
||||
|
||||
|
||||
105
patterns/chd.hexpat
Normal file
105
patterns/chd.hexpat
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma author Lexi Mayfield
|
||||
#pragma description MAME Compressed Hunks of Data
|
||||
#pragma endian big
|
||||
|
||||
fn CHD_MAKE_TAG(char a, char b, char c, char d) {
|
||||
return (u32(u8(a)) << 24) |
|
||||
u32(u8((b)) << 16) |
|
||||
u32(u8((c)) << 8) |
|
||||
u32(u8(d));
|
||||
};
|
||||
|
||||
enum CHDv5_CODEC : u32 {
|
||||
NONE = 0,
|
||||
ZLIB = CHD_MAKE_TAG('z','l','i','b'),
|
||||
ZSTD = CHD_MAKE_TAG('z','s','t','d'),
|
||||
LZMA = CHD_MAKE_TAG('l','z','m','a'),
|
||||
HUFFMAN = CHD_MAKE_TAG('h','u','f','f'),
|
||||
FLAC = CHD_MAKE_TAG('f','l','a','c'),
|
||||
CD_ZLIB = CHD_MAKE_TAG('c','d','z','l'),
|
||||
CD_ZSTD = CHD_MAKE_TAG('c','d','z','s'),
|
||||
CD_LZMA = CHD_MAKE_TAG('c','d','l','z'),
|
||||
CD_FLAC = CHD_MAKE_TAG('c','d','f','l'),
|
||||
AVHUFF = CHD_MAKE_TAG('a','v','h','u'),
|
||||
};
|
||||
|
||||
enum CHDv5_METADATA_TAG : u32 {
|
||||
CHDMETATAG_WILDCARD = 0,
|
||||
HARD_DISK_METADATA_TAG = CHD_MAKE_TAG('G','D','D','D'),
|
||||
HARD_DISK_IDENT_METADATA_TAG = CHD_MAKE_TAG('I','D','N','T'),
|
||||
HARD_DISK_KEY_METADATA_TAG = CHD_MAKE_TAG('K','E','Y',' '),
|
||||
PCMCIA_CIS_METADATA_TAG = CHD_MAKE_TAG('C','I','S',' '),
|
||||
CDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','C','D'),
|
||||
CDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','T','R'),
|
||||
CDROM_TRACK_METADATA2_TAG = CHD_MAKE_TAG('C','H','T','2'),
|
||||
GDROM_OLD_METADATA_TAG = CHD_MAKE_TAG('C','H','G','T'),
|
||||
GDROM_TRACK_METADATA_TAG = CHD_MAKE_TAG('C','H','G','D'),
|
||||
DVD_METADATA_TAG = CHD_MAKE_TAG('D','V','D',' '),
|
||||
AV_METADATA_TAG = CHD_MAKE_TAG('A','V','A','V'),
|
||||
AV_LD_METADATA_TAG = CHD_MAKE_TAG('A','V','L','D'),
|
||||
};
|
||||
|
||||
struct CHDv5UncompressedMap {
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
struct CHDv5CompressedMapEntry {
|
||||
u8 compression;
|
||||
u24 complength;
|
||||
u48 offset;
|
||||
u16 crc;
|
||||
};
|
||||
|
||||
struct CHDv5CompressedMap {
|
||||
u32 length;
|
||||
u48 datastart;
|
||||
u16 crc;
|
||||
u8 lengthbits;
|
||||
u8 hunkbits;
|
||||
u8 parentunitbits;
|
||||
u8 reserved;
|
||||
};
|
||||
|
||||
struct CHDv5MetadataEntry {
|
||||
CHDv5_METADATA_TAG metatag;
|
||||
u8 flags;
|
||||
u24 length;
|
||||
u64 next;
|
||||
char entry[length];
|
||||
|
||||
if (next != 0) {
|
||||
CHDv5MetadataEntry nextMeta @ next;
|
||||
}
|
||||
};
|
||||
|
||||
struct CHDv5 {
|
||||
CHDv5_CODEC compressors[4];
|
||||
u64 logicalbytes;
|
||||
u64 mapoffset;
|
||||
u64 metaoffset;
|
||||
u32 hunkbytes;
|
||||
u32 unitbytes;
|
||||
u8 rawsha1[20];
|
||||
u8 sha1[20];
|
||||
u8 parentsha1[20];
|
||||
|
||||
if (compressors[0] == CHDv5_CODEC::NONE) {
|
||||
CHDv5UncompressedMap map @ mapoffset;
|
||||
} else {
|
||||
CHDv5CompressedMap map @ mapoffset;
|
||||
}
|
||||
|
||||
CHDv5MetadataEntry meta @ metaoffset;
|
||||
};
|
||||
|
||||
struct CHD {
|
||||
char tag[8];
|
||||
u32 length;
|
||||
u32 version;
|
||||
|
||||
if (version == 5) {
|
||||
CHDv5 chd;
|
||||
}
|
||||
};
|
||||
|
||||
CHD chd @ 0x00;
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Windows HtmlHelp Data (ITSF / CHM)
|
||||
#pragma MIME application/vnd.ms-htmlhelp
|
||||
|
||||
import type.magic;
|
||||
import type.size;
|
||||
@@ -285,26 +286,26 @@ struct DirectoryIndexEntry {
|
||||
|
||||
struct ListingChunk {
|
||||
char magic[4];
|
||||
|
||||
|
||||
if (magic == "PMGL") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
u32;
|
||||
u32 prevChunkNumber, nextChunkNumber;
|
||||
|
||||
|
||||
u16 directoryListingEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryListingEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
|
||||
DirectoryListingEntry directories[directoryListingEntryCount];
|
||||
|
||||
|
||||
$ = addressof(directoryListingEntryCount) + sizeof(directoryListingEntryCount);
|
||||
} else if (magic == "PMGI") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
|
||||
|
||||
u16 directoryIndexEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryIndexEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
|
||||
DirectoryIndexEntry indexes[directoryIndexEntryCount];
|
||||
|
||||
|
||||
$ = addressof(directoryIndexEntryCount) + sizeof(directoryIndexEntryCount);
|
||||
} else {
|
||||
std::error("Invalid chunk magic!");
|
||||
@@ -313,7 +314,7 @@ struct ListingChunk {
|
||||
|
||||
struct HeaderSection {
|
||||
char magic[4];
|
||||
|
||||
|
||||
if (magic == "\xFE\x01\x00\x00") {
|
||||
u32;
|
||||
type::Size<u64> fileSize;
|
||||
@@ -337,7 +338,7 @@ struct HeaderSection {
|
||||
u32;
|
||||
u32;
|
||||
u32;
|
||||
|
||||
|
||||
ListingChunk chunk[directoryChunkCount];
|
||||
} else {
|
||||
std::error("Invalid header section magic!");
|
||||
@@ -347,22 +348,22 @@ struct HeaderSection {
|
||||
struct HeaderSectionTableEntry {
|
||||
u64 offset;
|
||||
type::Size<u64> size;
|
||||
|
||||
|
||||
HeaderSection headerSection @ offset;
|
||||
};
|
||||
|
||||
struct NameListEntry {
|
||||
type::Size<u16> nameLength;
|
||||
char16 name[nameLength];
|
||||
char16 name[nameLength];
|
||||
padding[2];
|
||||
};
|
||||
|
||||
struct NameListFile {
|
||||
u16 fileLengthWords;
|
||||
u16 entriesInFile;
|
||||
|
||||
|
||||
NameListEntry nameList[entriesInFile];
|
||||
|
||||
|
||||
padding[0x2E];
|
||||
};
|
||||
|
||||
@@ -376,7 +377,7 @@ struct SectionData {
|
||||
u32;
|
||||
};
|
||||
|
||||
struct Content {
|
||||
struct Content {
|
||||
NameListFile nameListFile;
|
||||
SectionData sectionData;
|
||||
};
|
||||
@@ -389,9 +390,9 @@ struct CHM {
|
||||
be u32 timeStamp;
|
||||
WindowsLanguageId languageId;
|
||||
type::GUID guids[2];
|
||||
|
||||
|
||||
HeaderSectionTableEntry headerSectionTable[2];
|
||||
|
||||
|
||||
Content *dataOffset : u64;
|
||||
};
|
||||
|
||||
|
||||
81
patterns/chromium_pak.hexpat
Normal file
81
patterns/chromium_pak.hexpat
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma author East_Arctica
|
||||
#pragma description Chromium Pak File
|
||||
|
||||
import std.core;
|
||||
import std.io;
|
||||
|
||||
struct IndexEntry {
|
||||
u16 id;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
struct AliasEntry {
|
||||
u16 id;
|
||||
u16 index;
|
||||
};
|
||||
|
||||
struct ResourceView {
|
||||
u32 i = std::core::array_index();
|
||||
|
||||
u16 id = parent.entries[i].id;
|
||||
u32 start = parent.entries[i].offset;
|
||||
u32 end = parent.entries[i + 1].offset;
|
||||
u32 length = (end >= start) ? (end - start) : 0;
|
||||
|
||||
u8 data[length] @ start;
|
||||
|
||||
// pak_util.py implies that this may also be gzip with a header of 0x1f 0x8b
|
||||
bool is_brotli = (length > 8 && data[0] == 0x1e && data[1] == 0x9b);
|
||||
if (is_brotli) {
|
||||
u8 magic[2] @ start;
|
||||
u48 decompressed_size @ start + 2;
|
||||
// TODO: If brotli decompression is added to ImHex, add it here.
|
||||
}
|
||||
};
|
||||
|
||||
struct AliasResourceView {
|
||||
u32 i = std::core::array_index();
|
||||
|
||||
u16 id = parent.aliases[i].id;
|
||||
u16 idx = parent.aliases[i].index;
|
||||
|
||||
bool valid = (idx < parent.resource_count);
|
||||
u32 start = valid ? parent.entries[idx].offset : 0;
|
||||
u32 end = valid ? parent.entries[idx + 1].offset : 0;
|
||||
u32 length = (valid && end >= start) ? (end - start) : 0;
|
||||
|
||||
u8 data[length] @ start;
|
||||
|
||||
};
|
||||
|
||||
enum PakEncoding : u8 {
|
||||
binary = 0,
|
||||
utf8 = 1,
|
||||
utf16 = 2
|
||||
};
|
||||
|
||||
struct Pak {
|
||||
u32 version;
|
||||
if (version == 4) {
|
||||
u32 resource_count;
|
||||
PakEncoding encoding;
|
||||
|
||||
IndexEntry entries[resource_count + 1];
|
||||
ResourceView resources[resource_count];
|
||||
} else if (version == 5) {
|
||||
PakEncoding encoding;
|
||||
padding[3];
|
||||
u16 resource_count;
|
||||
u16 alias_count;
|
||||
|
||||
IndexEntry entries[resource_count + 1];
|
||||
AliasEntry aliases[alias_count];
|
||||
ResourceView resources[resource_count];
|
||||
AliasResourceView alias_resources[alias_count];
|
||||
} else {
|
||||
std::error("Unsupported pak version");
|
||||
}
|
||||
};
|
||||
|
||||
// Some pack files are stored gzipped and need to be gunzipped first
|
||||
Pak pak @ 0x00;
|
||||
@@ -116,11 +116,11 @@ struct SymbolTable {
|
||||
Type type;
|
||||
StorageClass storageClass;
|
||||
u8 numberOfAuxSymbols;
|
||||
|
||||
|
||||
countedSymbols += 1 + numberOfAuxSymbols;
|
||||
|
||||
|
||||
AuxSymbol auxSymbols[numberOfAuxSymbols];
|
||||
|
||||
|
||||
if (countedSymbols >= parent.header.numberOfSymbols)
|
||||
break;
|
||||
};
|
||||
@@ -164,7 +164,10 @@ bitfield SectionFlags {
|
||||
};
|
||||
|
||||
fn format_alignment(u8 alignment) {
|
||||
return 1 << alignment;
|
||||
if(alignment > 0) {
|
||||
return 1 << (alignment - 1);
|
||||
}
|
||||
return alignment;
|
||||
};
|
||||
|
||||
struct Relocations {
|
||||
@@ -184,7 +187,7 @@ struct Section {
|
||||
u16 numberOfRelocations;
|
||||
u16 numberOfLineNumbers;
|
||||
SectionFlags characteristics;
|
||||
|
||||
|
||||
u8 rawData[sizeOfRawData] @ pointerToRawData [[sealed]];
|
||||
Relocations relocations[numberOfRelocations] @ pointerToRelocations;
|
||||
};
|
||||
@@ -202,9 +205,9 @@ struct Header {
|
||||
|
||||
struct COFF {
|
||||
Header header;
|
||||
|
||||
|
||||
Section sectionTable[header.numberOfSections];
|
||||
|
||||
|
||||
SymbolTable symbolTable[header.numberOfSymbols] @ header.pointerToSymbolTable;
|
||||
StringTable stringTable @ addressof(symbolTable) + sizeof(symbolTable);
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user