mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-31 05:15:54 -05:00
Compare commits
76 Commits
ImHex-v1.2
...
ImHex-v1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ecd6d87dd | ||
|
|
bf0d96db5f | ||
|
|
705900d38b | ||
|
|
734afdf500 | ||
|
|
c0c117ac19 | ||
|
|
7fba66a444 | ||
|
|
8eed75d783 | ||
|
|
81f4978656 | ||
|
|
b6e0557a1d | ||
|
|
ba14dd0cb2 | ||
|
|
86f93dfdaf | ||
|
|
001900e3c2 | ||
|
|
6baae92553 | ||
|
|
520f9bcb22 | ||
|
|
44b0392b78 | ||
|
|
df2bd4e3f9 | ||
|
|
7723cf55c6 | ||
|
|
caa2b6aaa6 | ||
|
|
7344df7ff6 | ||
|
|
df649d2e62 | ||
|
|
8710b9e66f | ||
|
|
665c942329 | ||
|
|
50f93d14ff | ||
|
|
ab43516517 | ||
|
|
4587b465d4 | ||
|
|
75b2c7be7e | ||
|
|
19dd39e7c0 | ||
|
|
ecd34d35b2 | ||
|
|
06366839aa | ||
|
|
e3c387d0cf | ||
|
|
5a7077412c | ||
|
|
d8a37b0579 | ||
|
|
1f1b2b9c5b | ||
|
|
d1645d2dc2 | ||
|
|
61ef68b12a | ||
|
|
c52e5b959b | ||
|
|
4a62892411 | ||
|
|
fc9b4cdbc2 | ||
|
|
daa556db31 | ||
|
|
e01a832fab | ||
|
|
759708d446 | ||
|
|
82560e6d9d | ||
|
|
1a2d785093 | ||
|
|
addec74d91 | ||
|
|
ce83eedf02 | ||
|
|
463ddcc62e | ||
|
|
13b97fc976 | ||
|
|
55e4283432 | ||
|
|
ea225edf12 | ||
|
|
bb19cb43ee | ||
|
|
8f8ad0e2d5 | ||
|
|
3ad1f3969f | ||
|
|
5451d45158 | ||
|
|
e6a731fa1d | ||
|
|
8a62001705 | ||
|
|
1f8710b586 | ||
|
|
acd2d4abb8 | ||
|
|
032f3c7c01 | ||
|
|
3841ff51ef | ||
|
|
622721403f | ||
|
|
11291d1ebb | ||
|
|
92e61ccf5d | ||
|
|
062edfe527 | ||
|
|
5b32941801 | ||
|
|
e99ab5b59b | ||
|
|
775c836766 | ||
|
|
43058b4c45 | ||
|
|
0128ea87db | ||
|
|
fe231436d9 | ||
|
|
7a9ac44577 | ||
|
|
74e9d8f2e7 | ||
|
|
2f39a62d85 | ||
|
|
e21063d58b | ||
|
|
8f1a6bdd75 | ||
|
|
b9af43e08b | ||
|
|
2ffa4e0161 |
9
.github/workflows/dispatch.yml
vendored
9
.github/workflows/dispatch.yml
vendored
@@ -45,3 +45,12 @@ jobs:
|
||||
repo: Documentation
|
||||
owner: WerWolv
|
||||
event_type: update_pl_docs
|
||||
|
||||
- name: ✉️ Update PatternLanguage Website
|
||||
if: ${{ env.DISPATCH_TOKEN != '' }}
|
||||
uses: mvasigh/dispatch-action@main
|
||||
with:
|
||||
token: ${{ secrets.DISPATCH_TOKEN }}
|
||||
repo: PatternLanguageWeb
|
||||
owner: WerWolv
|
||||
event_type: rebuild_wasm
|
||||
|
||||
20
.github/workflows/tests.yml
vendored
20
.github/workflows/tests.yml
vendored
@@ -59,16 +59,18 @@ jobs:
|
||||
cd tests/build
|
||||
ctest --output-on-failure
|
||||
|
||||
- name: ⚗️ Generate Coverage Report
|
||||
run: |
|
||||
cd tests/build
|
||||
lcov -d ./_deps/pattern_language-build/lib --gcov-tool /usr/bin/gcov-12 -c -o coverage.info
|
||||
#- name: ⚗️ Generate Coverage Report
|
||||
# run: |
|
||||
# cd tests/build
|
||||
# lcov -d ./_deps/pattern_language-build/lib --gcov-tool /usr/bin/gcov-12 -c -o coverage.info
|
||||
|
||||
- name: ⬆️ Upload Coverage Report
|
||||
uses: coverallsapp/github-action@master
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
path-to-lcov: tests/build/coverage.info
|
||||
#- name: ⬆️ Upload Coverage Report
|
||||
# uses: coverallsapp/github-action@master
|
||||
# env:
|
||||
# NODE_OPTIONS: --max-old-space-size=8000
|
||||
# with:
|
||||
# github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# path-to-lcov: tests/build/coverage.info
|
||||
|
||||
- name: 📎 Validate JSON Files
|
||||
run: |
|
||||
|
||||
144
README.md
144
README.md
@@ -22,75 +22,91 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
|
||||
| Name | MIME | Path | Description |
|
||||
|------|------|------|-------------|
|
||||
| 3DS | | [`patterns/3ds.hexpat`](patterns/3ds.hexpat) | Autodesk 3DS Max Model file |
|
||||
| 7Z | | [`patterns/7z.hexpat`](patterns/7z.hexpat) | 7z File Format |
|
||||
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
|
||||
| AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files |
|
||||
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
|
||||
| Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files |
|
||||
| BMP | `image/bmp` | [`patterns/bmp.hexpat`](patterns/bmp.hexpat) | OS2/Windows Bitmap files |
|
||||
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
|
||||
| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
|
||||
| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
|
||||
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
|
||||
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
|
||||
| WAV | `audio/wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
|
||||
| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers |
|
||||
| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets |
|
||||
| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions |
|
||||
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
|
||||
| AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files |
|
||||
| NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files |
|
||||
| NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files |
|
||||
| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO |
|
||||
| Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files |
|
||||
| ARM VTOR | | [`patterns/arm_cm_vtor.hexpat`](patterns/arm_cm_vtor.hexpat) | ARM Cortex M Vector Table Layout |
|
||||
| ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files |
|
||||
| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files |
|
||||
| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files |
|
||||
| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface |
|
||||
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
|
||||
| ISO | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system |
|
||||
| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files |
|
||||
| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) |
|
||||
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
|
||||
| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System |
|
||||
| Bencode | `application/x-bittorrent` | [`patterns/bencode.hexpat`](patterns/bencode.hexpat) | Bencode encoding, used by Torrent files |
|
||||
| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding |
|
||||
| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format |
|
||||
| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format |
|
||||
| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format |
|
||||
| NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC |
|
||||
| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format |
|
||||
| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams |
|
||||
| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format |
|
||||
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
|
||||
| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format |
|
||||
| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files |
|
||||
| ID3 | `audio/mpeg` | [`patterns/id3.hexpat`](patterns/id3.hexpat) | ID3 tags in MP3 files |
|
||||
| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format |
|
||||
| CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format |
|
||||
| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob |
|
||||
| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive |
|
||||
| NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format |
|
||||
| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format |
|
||||
| GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format |
|
||||
| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) |
|
||||
| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cardridge ROM |
|
||||
| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive |
|
||||
| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files |
|
||||
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
|
||||
| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable |
|
||||
| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable |
|
||||
| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) |
|
||||
| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) |
|
||||
| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable |
|
||||
| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file |
|
||||
| BIN | | [`patterns/selinux.hexpat`](patterns/selinux.pat) | SE Linux modules |
|
||||
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
|
||||
| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) |
|
||||
| CCHVA | | [`patterns/cchva.hexpat`](patterns/cchva.hexpat) | Command and Conquer Voxel Animation |
|
||||
| CCVXL | | [`patterns/ccvxl.hexpat`](patterns/ccvxl.hexpat) | Command and Conquer Voxel Model |
|
||||
| CCPAL | | [`patterns/ccpal.hexpat`](patterns/ccpal.hexpat) | Command and Conquer Voxel Palette |
|
||||
| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format |
|
||||
| CDA | | [`patterns/cda.hexpat`](patterns/cda.hexpat) | Compact Disc Audio track |
|
||||
| CHM | | [`patterns/chm.hexpat`](patterns/chm.hexpat) | Windows HtmlHelp Data (ITSF / CHM) |
|
||||
| COFF | `application/x-coff` | [`patterns/coff.hexpat`](patterns/coff.hexpat) | Common Object File Format (COFF) executable |
|
||||
| CPIO | `application/x-cpio` | [`patterns/cpio.hexpat`](patterns/cpio.hexpat) | Old Binary CPIO Format |
|
||||
| CrashLvl | | [`patterns/Crashlvl.hexpat`](patterns/Crashlvl.hexpat) | Crash Bandicoot - Back in Time (fan game) User created flashback tapes level format |
|
||||
| DDS | `image/vnd-ms.dds` | [`patterns/dds.hexpat`](patterns/dds.hexpat) | DirectDraw Surface |
|
||||
| DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format |
|
||||
| DMG | | [`patterns/dmg.hexpat`](patterns/dmg.hexpat) | Apple Disk Image Trailer (DMG) |
|
||||
| DS_Store | `application/octet-stream` | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format |
|
||||
| DTA | | [`patterns/max_v104.hexpat`](patterns/max_v104.hexpat) | Mechanized Assault and Exploration v1.04 (strategy game) save file format |
|
||||
| ELF | `application/x-executable` | [`patterns/elf.hexpat`](patterns/elf.hexpat) | ELF header in elf binaries |
|
||||
| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log |
|
||||
| FDT | | [`patterns/fdt.hexpat`](patterns/fdt.hexpat) | Flat Linux Device Tree blob |
|
||||
| File System | | [`patterns/fs.hexpat`](patterns/fs.hexpat) | Drive File System |
|
||||
| FLAC | `audio/flac` | [`patterns/flac.hexpat`](patterns/flac.hexpat) | Free Lossless Audio Codec, FLAC Audio Format |
|
||||
| GB | `application/x-gameboy-rom` | [`patterns/gb.hexpat`](patterns/gb.hexpat) | Gameboy ROM |
|
||||
| GIF | `image/gif` | [`patterns/gif.hexpat`](patterns/gif.hexpat) | GIF image files |
|
||||
| GZIP | `application/gzip` | [`patterns/gzip.hexpat`](patterns/gzip.hexpat) | GZip compressed data format |
|
||||
| ICO | | [`patterns/ico.hexpat`](patterns/ico.hexpat) | Icon (.ico) or Cursor (.cur) files |
|
||||
| ID3 | `audio/mpeg` | [`patterns/id3.hexpat`](patterns/id3.hexpat) | ID3 tags in MP3 files |
|
||||
| Intel HEX | | [`patterns/intel_hex.hexpat`](patterns/intel_hex.hexpat) | [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX") |
|
||||
| IP | | [`patterns/ip.hexpat`](patterns/ip.hexpat) | Ethernet II Frames (IP Packets) |
|
||||
| IPS | | [`patterns/ips.hexpat`](patterns/ips.hexpat) | IPS (International Patching System) files |
|
||||
| ISO | | [`patterns/iso.hexpat`](patterns/iso.hexpat) | ISO 9660 file system |
|
||||
| Java Class | `application/x-java-applet` | [`patterns/java_class.hexpat`](patterns/java_class.hexpat) | Java Class files |
|
||||
| JPEG | `image/jpeg` | [`patterns/jpeg.hexpat`](patterns/jpeg.hexpat) | JPEG Image Format |
|
||||
| Lua 5.4 | | [`patterns/lua54.hexpat`](patterns/lua54.hexpat) | Lua 5.4 bytecode |
|
||||
| DEX | | [`patterns/dex.hexpat`](patterns/dex.hexpat) | Dalvik EXecutable Format |
|
||||
| DS_Store | `application/octet-stream` | [`patterns/dsstore.hexpat`](patterns/dsstore.hexpat) | .DS_Store file format |
|
||||
| Mach-O | `application/x-mach-binary` | [`patterns/macho.hexpat`](patterns/macho.hexpat) | Mach-O executable |
|
||||
| MIDI | `audio/midi` | [`patterns/midi.hexpat`](patterns/midi.hexpat) | MIDI header, event fields provided |
|
||||
| MiniDump | `application/x-dmp` | [`patterns/minidump.hexpat`](patterns/minidump.hexpat) | Windows MiniDump files |
|
||||
| mp4 | `video/mp4` | [`patterns/mp4.hexpat`](patterns/mp4.hexpat) | MPEG-4 Part 14 digital multimedia container format |
|
||||
| msgpack | `application/x-msgpack` | [`patterns/msgpack.hexpat`](patterns/msgpack.hexpat) | MessagePack binary serialization format |
|
||||
| NACP | | [`patterns/nacp.hexpat`](patterns/nacp.hexpat) | Nintendo Switch NACP files |
|
||||
| NBT | | [`patterns/nbt.hexpat`](patterns/nbt.hexpat) | Minecraft NBT format |
|
||||
| NE | | [`patterns/ne.hexpat`](patterns/ne.hexpat) | NE header and Standard NE fields |
|
||||
| nes | | [`patterns/nes.hexpat`](patterns/nes.hexpat) | .nes file format |
|
||||
| NRO | | [`patterns/nro.hexpat`](patterns/nro.hexpat) | Nintendo Switch NRO files |
|
||||
| NTAG | | [`patterns/ntag.hexpat`](patterns/ntag.hexpat) | NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC |
|
||||
| OGG | `audio/ogg` | [`patterns/ogg.hexpat`](patterns/ogg.hexpat) | OGG Audio format |
|
||||
| PCAP | `application/vnd.tcpdump.pcap` | [`patterns/pcap.hexpat`](patterns/pcap.hexpat) | pcap header and packets |
|
||||
| PCX | `application/x-pcx` | [`patterns/pcx.hexpat`](patterns/pcx.hexpat) | PCX Image format |
|
||||
| PE | `application/x-dosexec` | [`patterns/pe.hexpat`](patterns/pe.hexpat) | PE header, COFF header, Standard COFF fields and Windows Specific fields |
|
||||
| PP | [`patterns/selinuxpp.hexpat`](patterns/selinuxpp.pat) | SE Linux package |
|
||||
| PFS0 | | [`patterns/pfs0.hexpat`](patterns/pfs0.hexpat) | Nintendo Switch PFS0 archive (NSP files) |
|
||||
| PIF | `image/pif` | [`patterns/pif.hexpat`](patterns/pif.hexpat) | PIF Image Format |
|
||||
| PNG | `image/png` | [`patterns/png.hexpat`](patterns/png.hexpat) | PNG image files |
|
||||
| PRODINFO | | [`patterns/prodinfo.hexpat`](patterns/prodinfo.hexpat) | Nintendo Switch PRODINFO |
|
||||
| Protobuf | | [`patterns/protobuf.hexpat`](patterns/protobuf.hexpat) | Google Protobuf encoding |
|
||||
| PyInstaller | | [`patterns/pyinstaller.hexpat`](patterns/pyinstaller.hexpat) | PyInstaller binray files |
|
||||
| PYC | | [`patterns/pyc.hexpat`](patterns/pyc.hexpat) | Python bytecode files |
|
||||
| QBCL | | [`patterns/qbcl.hexpat`](patterns/qbcl.hexpat) | Qubicle voxel scene project file |
|
||||
| QOI | `image/qoi` | [`patterns/qoi.hexpat`](patterns/qoi.hexpat) | QOI image files |
|
||||
| Shell Link | `application/x-ms-shortcut` | [`patterns/lnk.hexpat`](patterns/lnk.hexpat) | Windows Shell Link file format |
|
||||
| SPIRV | | [`patterns/spirv.hexpat`](patterns/spirv.hexpat) | SPIR-V header and instructions |
|
||||
| STL | `model/stl` | [`patterns/stl.hexpat`](patterns/stl.hexpat) | STL 3D Model format |
|
||||
| StuffItV5 | `application/x-stuffit` | [`patterns/sit5.hexpat`](patterns/sit5.hexpat) | StuffIt V5 archive |
|
||||
| TAR | `application/x-tar` | [`patterns/tar.hexpat`](patterns/tar.hexpat) | Tar file format |
|
||||
| TIFF | `image/tiff` | [`patterns/tiff.hexpat`](patterns/tiff.hexpat) | Tag Image File Format |
|
||||
| TGA | `image/tga` | [`patterns/tga.hexpat`](patterns/tga.hexpat) | Truevision TGA/TARGA image |
|
||||
| Ubiquiti | | [`patterns/ubiquiti.hexpat`](patterns/ubiquiti.hexpat) | Ubiquiti Firmware (update) image |
|
||||
| UEFI | | [`patterns/uefi.hexpat`](patterns/uefi.hexpat)` | UEFI structs for parsing efivars |
|
||||
| EVTX | | [`patterns/evtx.hexpat`](patterns/evtx.hexpat) | MS Windows Vista Event Log |
|
||||
| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) |
|
||||
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
|
||||
| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files |
|
||||
| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format |
|
||||
| WAV | `audio/x-wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
|
||||
| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive |
|
||||
| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable |
|
||||
| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cardridge ROM |
|
||||
| Xilinx BIT | | [`patterns/xilinx_bit.hexpat`](patterns/xilinx_bit.hexpat) | Xilinx FPGA Bitstreams |
|
||||
| ZIP | `application/zip` | [`patterns/zip.hexpat`](patterns/zip.hexpat) | End of Central Directory Header, Central Directory File Headers |
|
||||
| ZLIB | `application/zlib` | [`patterns/zlib.hexpat`](patterns/zlib.hexpat) | ZLIB compressed data format |
|
||||
| ZSTD | `application/zstd` | [`patterns/zstd.hexpat`](patterns/zstd.hexpat) | Zstandard compressed data format |
|
||||
|
||||
### Scripts
|
||||
|
||||
@@ -179,3 +195,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
|------|------|-------------|
|
||||
| Visual Studio Dark | [`themes/vs_dark.json`](themes/vs_dark.json) | Theme similar to Visual Studio's Dark theme |
|
||||
| Solarized Dark | [`themes/solarized_dark.json`](themes/solarized_dark.json) | Solarized Dark Theme |
|
||||
| Catppuccin Latte | [`themes/catppuccin-latte.json`](themes/catppuccin-latte.json) | Catppuccin Latte Flavor (Light Theme) |
|
||||
| Catppuccin Frappe | [`themes/catppuccin-frappe.json`](themes/catppuccin-frappe.json) | Catppuccin Frappe Flavor (Dark Theme) |
|
||||
| Catppuccin Macchiato | [`themes/catppuccin-macchiato.json`](themes/catppuccin-macchiato.json) | Catppuccin Macchiato Flavor (Dark Theme) |
|
||||
| Catppuccin Mocha | [`themes/catppuccin-mocha.json`](themes/catppuccin-mocha.json) | Catppuccin Mocha Flavor (Dark Theme) |
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <std/sys.pat>
|
||||
|
||||
/*!
|
||||
The array library contains various helper functions and types to make
|
||||
it easier to work with Arrays.
|
||||
The array library contains a helper type to make it easier to create multi-dimensional arrays
|
||||
and pass arrays to functions as parameters.
|
||||
*/
|
||||
|
||||
namespace std {
|
||||
@@ -10,10 +12,30 @@ namespace std {
|
||||
/**
|
||||
Simple one dimensional array wrapper
|
||||
@tparam T The array types
|
||||
@tparam Size Size of the array
|
||||
@tparam Size Number of entries in the array
|
||||
*/
|
||||
struct Array<T, auto Size> {
|
||||
T data[Size] [[inline]];
|
||||
};
|
||||
} [[format("std::impl::format_array")]];
|
||||
|
||||
}
|
||||
/**
|
||||
Simple array wrapper for an array with a size in bytes
|
||||
@tparam T The array types
|
||||
@tparam NumBytes Number of bytes the array contains
|
||||
*/
|
||||
struct ByteSizedArray<T, auto NumBytes> {
|
||||
u64 startAddress = $;
|
||||
T array[while($ - startAddress < NumBytes)] [[inline]];
|
||||
|
||||
std::assert($ - startAddress == NumBytes, "Not enough bytes available to fit a whole number of types");
|
||||
} [[format("std::impl::format_array")]];
|
||||
|
||||
namespace impl {
|
||||
|
||||
fn format_array(ref auto array) {
|
||||
return "[ ... ]";
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,9 +59,9 @@ namespace std::file {
|
||||
/**
|
||||
Writes the content of a string into a file
|
||||
@param handle The file handle to write to
|
||||
@param data String to write to the file
|
||||
@param data String or Pattern to write to the file
|
||||
*/
|
||||
fn write(Handle handle, str data) {
|
||||
fn write(Handle handle, auto data) {
|
||||
builtin::std::file::write(handle, data);
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace std::fxpt {
|
||||
@return The fixed point representation of flt
|
||||
*/
|
||||
fn to_fixed(double flt, u32 precision) {
|
||||
return fixed((flt * (1 << precision)));
|
||||
return s128((flt * (1 << precision)));
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -178,7 +178,6 @@ namespace std::math {
|
||||
/**
|
||||
Calculates the natural logarithm of `value`.
|
||||
@param value Value
|
||||
@param base Base
|
||||
@return Logarithm of `value` with base `e`
|
||||
*/
|
||||
fn ln(auto value) { return builtin::std::math::ln(value); };
|
||||
@@ -198,6 +197,13 @@ namespace std::math {
|
||||
*/
|
||||
fn pow(auto base, auto exp) { return builtin::std::math::pow(base, exp); };
|
||||
|
||||
/**
|
||||
Calculates the value of the natural number `e` raised to the power of `value`.
|
||||
@param value Exponent
|
||||
@return `e` raised to the power of `value`
|
||||
*/
|
||||
fn exp(auto value) { return builtin::std::math::exp(value); };
|
||||
|
||||
/**
|
||||
Calculates the square root of `value`.
|
||||
@param value Value
|
||||
|
||||
@@ -5,7 +5,27 @@
|
||||
*/
|
||||
|
||||
namespace std::mem {
|
||||
|
||||
|
||||
namespace impl {
|
||||
|
||||
struct MagicSearchImpl<auto Magic, T> {
|
||||
if ($ < (std::mem::base_address() + std::mem::size() - std::string::length(Magic) - 1)) {
|
||||
char __potentialMagic__[std::string::length(Magic)] [[hidden, no_unique_address]];
|
||||
|
||||
if (__potentialMagic__ == Magic) {
|
||||
T data [[inline]];
|
||||
} else {
|
||||
padding[1];
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
padding[1];
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
A Handle for a custom Section
|
||||
*/
|
||||
@@ -26,7 +46,7 @@ namespace std::mem {
|
||||
@return True if the cursor is at the end of the memory
|
||||
*/
|
||||
fn eof() {
|
||||
return $ >= std::mem::size();
|
||||
return $ >= (std::mem::base_address() + std::mem::size());
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -174,10 +194,9 @@ namespace std::mem {
|
||||
|
||||
/**
|
||||
Copies a range of bytes from the main section into a custom section
|
||||
@param from_section The section to copy from
|
||||
@param from_address The address to copy from
|
||||
@param value The pattern whose bytes should be copied
|
||||
@param to_section The section to copy to
|
||||
@param to_address The address to copy to
|
||||
@param size The size of the range to copy
|
||||
*/
|
||||
fn copy_value_to_section(ref auto value, Section to_section, u64 to_address) {
|
||||
builtin::std::mem::copy_value_to_section(value, to_section, to_address);
|
||||
@@ -190,19 +209,7 @@ namespace std::mem {
|
||||
@tparam T The type to place at the address
|
||||
*/
|
||||
struct MagicSearch<auto Magic, T> {
|
||||
if ($ < (std::mem::size() - std::string::length(Magic) - 1)) {
|
||||
char __potentialMagic__[std::string::length(Magic)] [[hidden, no_unique_address]];
|
||||
|
||||
if (__potentialMagic__ == Magic) {
|
||||
T data [[inline]];
|
||||
} else {
|
||||
padding[1];
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
padding[1];
|
||||
continue;
|
||||
}
|
||||
std::mem::impl::MagicSearchImpl<Magic, T> impl[while(!std::mem::eof())] [[inline]];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
/*!
|
||||
The Pointer library contains helper functions to deal with pointer types.
|
||||
The `relative_to` functions are meant to be used with the `[[pointer_base]]` attribute
|
||||
@@ -64,4 +66,4 @@ namespace std::ptr {
|
||||
PointeeTy *data : PointerTy;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +230,7 @@ namespace std::string {
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
result = result + std::string::substr(string,string_len-pattern_len+1,pattern_len);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
63
includes/type/base64.pat
Normal file
63
includes/type/base64.pat
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <std/io.pat>
|
||||
#include <std/string.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
/*!
|
||||
Type representing a Base64 encoded string
|
||||
*/
|
||||
|
||||
namespace type {
|
||||
|
||||
/**
|
||||
Type representing a Base64 encoded string
|
||||
@tparam T String type
|
||||
*/
|
||||
struct Base64<T> {
|
||||
T string;
|
||||
} [[sealed, format("type::impl::transform_base64")]];
|
||||
|
||||
namespace impl {
|
||||
|
||||
fn get_decoded_value(char c) {
|
||||
if (c >= 'A' && c <= 'Z') return c - 'A';
|
||||
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
|
||||
if (c >= '0' && c <= '9') return c - '0' + 52;
|
||||
if (c == '+') return 62;
|
||||
if (c == '/') return 63;
|
||||
return -1; // Invalid character
|
||||
};
|
||||
|
||||
fn decode_base64(str input) {
|
||||
u64 inputLength = std::string::length(input);
|
||||
str result;
|
||||
|
||||
s32 val = 0;
|
||||
s32 bits = -8;
|
||||
for (u32 i = 0, i < inputLength, i += 1) {
|
||||
char c = input[i];
|
||||
if (c == '=')
|
||||
break;
|
||||
|
||||
s32 index = type::impl::get_decoded_value(c);
|
||||
if (index == -1)
|
||||
continue;
|
||||
|
||||
val = (val << 6) + index;
|
||||
bits += 6;
|
||||
|
||||
if (bits >= 0) {
|
||||
result += char((val >> bits) & 0xFF);
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
fn transform_base64(ref auto base64) {
|
||||
return type::impl::decode_base64(base64.string);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,7 +33,7 @@ namespace type {
|
||||
|
||||
namespace impl {
|
||||
|
||||
fn transform_uleb128_array(auto array) {
|
||||
fn transform_uleb128_array(ref auto array) {
|
||||
u128 res = array[0] & 0x7f;
|
||||
for(u8 i = 1, array[i-1] & 0x80 != 0, i+=1) {
|
||||
res |= u128(array[i] & 0x7f) << 7 * i;
|
||||
@@ -41,7 +41,7 @@ namespace type {
|
||||
return res;
|
||||
};
|
||||
|
||||
fn transform_sleb128_array(auto array) {
|
||||
fn transform_sleb128_array(ref auto array) {
|
||||
s128 res = type::impl::transform_uleb128_array(array);
|
||||
if (res & 0x40 != 0) {
|
||||
res |= ~0 << (sizeof(array) / sizeof(u8)) * 7;
|
||||
@@ -49,21 +49,21 @@ namespace type {
|
||||
return res;
|
||||
};
|
||||
|
||||
fn format_uleb128(auto leb128) {
|
||||
fn format_uleb128(ref auto leb128) {
|
||||
u128 res = type::impl::transform_uleb128_array(leb128.array);
|
||||
return std::format("{} ({:#x})", res, res);
|
||||
};
|
||||
|
||||
fn transform_uleb128(auto leb128) {
|
||||
fn transform_uleb128(ref auto leb128) {
|
||||
return type::impl::transform_uleb128_array(leb128.array);
|
||||
};
|
||||
|
||||
fn format_sleb128(auto leb128) {
|
||||
fn format_sleb128(ref auto leb128) {
|
||||
s128 res = type::impl::transform_sleb128_array(leb128.array);
|
||||
return std::format("{} ({:#x})", res, res);
|
||||
};
|
||||
|
||||
fn transform_sleb128(auto leb128) {
|
||||
fn transform_sleb128(ref auto leb128) {
|
||||
return type::impl::transform_sleb128_array(leb128.array);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# A libmagic database containing definition for PE files used by MS-DOS based systems
|
||||
# A libmagic database containing definition for PE files used by MS-DOS/Windows based systems
|
||||
|
||||
# MS-DOS Portable Executable
|
||||
0x0 string/b MZ MS-DOS Binary
|
||||
|
||||
1141
patterns/3ds.hexpat
Normal file
1141
patterns/3ds.hexpat
Normal file
File diff suppressed because it is too large
Load Diff
101
patterns/7z.hexpat
Normal file
101
patterns/7z.hexpat
Normal file
@@ -0,0 +1,101 @@
|
||||
#pragma description 7z File Format
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/math.pat>
|
||||
|
||||
|
||||
enum Type:u8{
|
||||
startPosition = 0x00, // Start position
|
||||
sizeStartHeader = 0x20, // Size of start Header
|
||||
};
|
||||
|
||||
enum TypeB:u48{
|
||||
sevenZipSignature = 0x1C27AFBC7A37, // Defining 7z signature
|
||||
};
|
||||
|
||||
struct StartHeader {
|
||||
// File signature
|
||||
u48 signature [[color("FF0000")] ];
|
||||
// Version format
|
||||
u16 formatVersion [[color("00FF00")]];
|
||||
// CRC start header
|
||||
u32 crcOfTheFollowing20Bytes [[color("0000FF")]];
|
||||
// Relative offset of End Header
|
||||
u64 relativeOffsetEndHeader [[color("FFFF00")]];
|
||||
// Length of End Header
|
||||
u64 theLengthOfEndHeader [[color("00FFFF")]];
|
||||
// CRC of End Ender
|
||||
u32 crcOftheEndHeader [[color("FF00FF")]];
|
||||
// File size calculation
|
||||
u64 fileSize = relativeOffsetEndHeader + theLengthOfEndHeader + Type::sizeStartHeader;
|
||||
// Absolute offset calculation End Header
|
||||
u64 startEndHeader = relativeOffsetEndHeader + Type::sizeStartHeader;
|
||||
};
|
||||
|
||||
StartHeader startheader @ Type::startPosition;
|
||||
|
||||
struct CompressedData {
|
||||
// Start of compressed data
|
||||
u8 startOfCompressedData[4] [[color("C0C0C0")]];
|
||||
};
|
||||
|
||||
CompressedData compresseddata @ Type::sizeStartHeader;
|
||||
|
||||
|
||||
struct EndHeader {
|
||||
// Set padding to place End Header in right position
|
||||
padding[startheader.relativeOffsetEndHeader];
|
||||
// Mark link to meta block
|
||||
u8 linkToMetaBlock [[color("FF0000")]];
|
||||
// Mark all End Header
|
||||
char fullEndHeader[startheader.theLengthOfEndHeader] [[color("63954A")]];
|
||||
// Detect LZMA signature
|
||||
u64 lzmaSignaturePosition = std::mem::find_sequence_in_range(0, addressof(fullEndHeader), addressof(fullEndHeader) + sizeof(fullEndHeader), 0x23, 0x03, 0x01, 0x01, 0x05, 0x5D);
|
||||
|
||||
// Mark positions if LZMA signature was detected
|
||||
if(lzmaSignaturePosition != 0xFFFFFFFFFFFFFFFF){
|
||||
u48 lzmaSignature @ lzmaSignaturePosition [[color("0000FF")]];
|
||||
}
|
||||
};
|
||||
|
||||
EndHeader endheader @ Type::sizeStartHeader;
|
||||
|
||||
// Check 7z type
|
||||
if(startheader.signature == TypeB::sevenZipSignature){
|
||||
std::print("It is a 7z File Type");
|
||||
}else{
|
||||
std::print("The file is not 7z type");
|
||||
}
|
||||
|
||||
std::print("Format Version {} ",startheader.formatVersion);
|
||||
|
||||
// Version verification
|
||||
if(startheader.formatVersion == 0x0400){
|
||||
std::print("Major Version 0x00 || 0 - Minor Version 0x04 || 4");
|
||||
}
|
||||
|
||||
// Verification of the compressed method is LZMA, Bzip2 or LZMA2
|
||||
if(compresseddata.startOfCompressedData[0] == Type::startPosition){
|
||||
std::print("Compressed Method LZMA");
|
||||
}else if(compresseddata.startOfCompressedData[0] == 0x42){
|
||||
std::print("Compressed Method Bzip2");
|
||||
}else{
|
||||
std::print("Compressed Method LZMA2");
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::print("CRC Start Header 0x{:X}",startheader.crcOfTheFollowing20Bytes);
|
||||
|
||||
std::print("CRC End Header 0x{:X} ", startheader.crcOftheEndHeader);
|
||||
|
||||
std::print("CompressedData length 0x{:X} || {} bytes ",startheader.relativeOffsetEndHeader, startheader.relativeOffsetEndHeader);
|
||||
|
||||
std::print("Relative Offset of End Header 0x{:X} || {} bytes",startheader.relativeOffsetEndHeader, startheader.relativeOffsetEndHeader);
|
||||
|
||||
std::print("Offset to start End Header 0x{:X} || {} bytes",startheader.startEndHeader,startheader.startEndHeader);
|
||||
|
||||
std::print("End Header length 0x{:X} || {} bytes",startheader.theLengthOfEndHeader,startheader.theLengthOfEndHeader);
|
||||
|
||||
std::print("File size 0x{:X} || {} bytes",startheader.fileSize, startheader.fileSize);
|
||||
75
patterns/Crashlvl.hexpat
Normal file
75
patterns/Crashlvl.hexpat
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma description Crash Bandicoot - Back in Time (fan game) User created flashback tapes level format
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <std/string.pat>
|
||||
#include <std/array.pat>
|
||||
|
||||
// Crash Bandicoot - Back in Time (fan game) user created tapes
|
||||
// author AdventureT
|
||||
|
||||
struct Header {
|
||||
type::Magic<"CRASHLVL"> magic;
|
||||
u8 version;
|
||||
std::string::SizedString<u8> levelName;
|
||||
std::string::SizedString<u8> author;
|
||||
};
|
||||
|
||||
enum Music : u32 {
|
||||
None,
|
||||
BonusBGM,
|
||||
CrashCreatorBGM,
|
||||
MainMenuBGM,
|
||||
WarpRoomBGM,
|
||||
Level01BGM,
|
||||
Level02BGM,
|
||||
Level03BGM,
|
||||
Level04BGM,
|
||||
Level05BGM,
|
||||
SewerBGM,
|
||||
EgyptBGM,
|
||||
NBrioBGM
|
||||
};
|
||||
|
||||
enum Type : u32 {
|
||||
Unset,
|
||||
Flashback,
|
||||
Trial
|
||||
};
|
||||
|
||||
enum Time : u32 {
|
||||
Night,
|
||||
Day,
|
||||
Storm,
|
||||
Dawn
|
||||
};
|
||||
|
||||
enum Terrain : u32 {
|
||||
None,
|
||||
Machines,
|
||||
Trees,
|
||||
Waterfall,
|
||||
Snow,
|
||||
Fortress,
|
||||
};
|
||||
|
||||
struct Options {
|
||||
Type type;
|
||||
Time time;
|
||||
Terrain terrain;
|
||||
Music music;
|
||||
};
|
||||
|
||||
struct Object {
|
||||
std::string::SizedString<u8> objName;
|
||||
u32 x;
|
||||
u32 y;
|
||||
};
|
||||
|
||||
struct Objects{
|
||||
u32 objCount;
|
||||
std::Array<Object, objCount> objArray;
|
||||
};
|
||||
|
||||
Header header @ 0x0;
|
||||
Options options @ $;
|
||||
Objects objects @ $;
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Nintendo Switch Atmosphère CFW Fatal Error log
|
||||
|
||||
#pragma endian little
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Static library archive files
|
||||
|
||||
#pragma MIME application/x-archive
|
||||
|
||||
#include <std/string.pat>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description ARM Cortex M Vector Table Layout
|
||||
|
||||
#pragma endian little
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
@@ -1,73 +1,76 @@
|
||||
#pragma MIME application/x-bittorrent
|
||||
|
||||
#include <std/ctype.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
|
||||
namespace bencode {
|
||||
|
||||
struct ASCIIDecimal {
|
||||
char value[while(std::ctype::isdigit(std::mem::read_unsigned($, 1)))];
|
||||
} [[sealed, format("bencode::format_ascii_decimal"), transform("bencode::format_ascii_decimal")]];
|
||||
|
||||
fn format_ascii_decimal(ASCIIDecimal adsasd) {
|
||||
return std::string::parse_int(adsasd.value, 10);
|
||||
};
|
||||
|
||||
enum Type : u8 {
|
||||
Integer = 'i',
|
||||
Dictionary = 'd',
|
||||
List = 'l',
|
||||
|
||||
String0 = '0',
|
||||
String1 = '1',
|
||||
String2 = '2',
|
||||
String3 = '3',
|
||||
String4 = '4',
|
||||
String5 = '5',
|
||||
String6 = '6',
|
||||
String7 = '7',
|
||||
String8 = '8',
|
||||
String9 = '9'
|
||||
};
|
||||
|
||||
struct String {
|
||||
ASCIIDecimal length;
|
||||
char separator [[hidden]];
|
||||
char value[length];
|
||||
} [[sealed, format("bencode::format_string"), transform("bencode::format_string")]];
|
||||
|
||||
fn format_string(String string) {
|
||||
return string.value;
|
||||
};
|
||||
|
||||
using Bencode;
|
||||
using Value;
|
||||
|
||||
struct DictionaryEntry {
|
||||
String key;
|
||||
Value value;
|
||||
};
|
||||
|
||||
struct Value {
|
||||
Type type;
|
||||
|
||||
if (type == Type::Dictionary) {
|
||||
DictionaryEntry entry[while(std::mem::read_unsigned($, 1) != 'e')];
|
||||
} else if (type == Type::Integer) {
|
||||
ASCIIDecimal value;
|
||||
char end;
|
||||
} else {
|
||||
$ -= 1;
|
||||
String value;
|
||||
}
|
||||
};
|
||||
|
||||
struct Bencode {
|
||||
Value value[while(!std::mem::eof())] [[inline]];
|
||||
char end;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bencode::Bencode bencode @ 0x00;
|
||||
#pragma author WerWolv
|
||||
#pragma description Bencode encoding, used by Torrent files
|
||||
|
||||
#pragma MIME application/x-bittorrent
|
||||
|
||||
#include <std/ctype.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
|
||||
namespace bencode {
|
||||
|
||||
struct ASCIIDecimal {
|
||||
char value[while(std::ctype::isdigit(std::mem::read_unsigned($, 1)))];
|
||||
} [[sealed, format("bencode::format_ascii_decimal"), transform("bencode::format_ascii_decimal")]];
|
||||
|
||||
fn format_ascii_decimal(ASCIIDecimal adsasd) {
|
||||
return std::string::parse_int(adsasd.value, 10);
|
||||
};
|
||||
|
||||
enum Type : u8 {
|
||||
Integer = 'i',
|
||||
Dictionary = 'd',
|
||||
List = 'l',
|
||||
|
||||
String0 = '0',
|
||||
String1 = '1',
|
||||
String2 = '2',
|
||||
String3 = '3',
|
||||
String4 = '4',
|
||||
String5 = '5',
|
||||
String6 = '6',
|
||||
String7 = '7',
|
||||
String8 = '8',
|
||||
String9 = '9'
|
||||
};
|
||||
|
||||
struct String {
|
||||
ASCIIDecimal length;
|
||||
char separator [[hidden]];
|
||||
char value[length];
|
||||
} [[sealed, format("bencode::format_string"), transform("bencode::format_string")]];
|
||||
|
||||
fn format_string(String string) {
|
||||
return string.value;
|
||||
};
|
||||
|
||||
using Bencode;
|
||||
using Value;
|
||||
|
||||
struct DictionaryEntry {
|
||||
String key;
|
||||
Value value;
|
||||
};
|
||||
|
||||
struct Value {
|
||||
Type type;
|
||||
|
||||
if (type == Type::Dictionary) {
|
||||
DictionaryEntry entry[while(std::mem::read_unsigned($, 1) != 'e')];
|
||||
} else if (type == Type::Integer) {
|
||||
ASCIIDecimal value;
|
||||
char end;
|
||||
} else {
|
||||
$ -= 1;
|
||||
String value;
|
||||
}
|
||||
};
|
||||
|
||||
struct Bencode {
|
||||
Value value[while(!std::mem::eof())] [[inline]];
|
||||
char end;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bencode::Bencode bencode @ 0x00;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma description OS2/Windows Bitmap files
|
||||
|
||||
#pragma MIME image/bmp
|
||||
#pragma endian little
|
||||
#include <std/mem.pat>
|
||||
|
||||
struct BitmapFileHeader {
|
||||
u8 bfType[2];
|
||||
@@ -9,13 +12,38 @@ struct BitmapFileHeader {
|
||||
u32 bfOffBits;
|
||||
};
|
||||
|
||||
struct BitmapInfoHeader {
|
||||
enum Compression : u32 {
|
||||
BI_RGB,
|
||||
BI_RLE8,
|
||||
BI_RLE4,
|
||||
BI_BITFIELDS,
|
||||
BI_JPEG,
|
||||
BI_PNG,
|
||||
BI_ALPHABITFIELDS,
|
||||
BI_CMYK,
|
||||
BI_CMYKRLE8,
|
||||
BI_CMYKRLE4,
|
||||
};
|
||||
|
||||
struct CIEXYZ {
|
||||
u32 ciexyzX;
|
||||
u32 ciexyzY;
|
||||
u32 ciexyzZ;
|
||||
};
|
||||
|
||||
struct CIEXYZTRIPLE {
|
||||
CIEXYZ ciexyzRed;
|
||||
CIEXYZ ciexyzGreen;
|
||||
CIEXYZ ciexyzBlue;
|
||||
};
|
||||
|
||||
struct BitmapInfoHeaderV1 {
|
||||
u32 biSize;
|
||||
s32 biWidth;
|
||||
s32 biHeight;
|
||||
u16 biPlanes;
|
||||
u16 biBitCount;
|
||||
u32 biCompression;
|
||||
Compression biCompression;
|
||||
u32 biSizeImage;
|
||||
s32 biXPelsPerMeter;
|
||||
s32 biYPelsPerMeter;
|
||||
@@ -23,6 +51,31 @@ struct BitmapInfoHeader {
|
||||
u32 biClrImportant;
|
||||
};
|
||||
|
||||
struct BitmapInfoHeaderV2 : BitmapInfoHeaderV1 {
|
||||
u32 biRedMask;
|
||||
u32 biGreenMask;
|
||||
u32 biBlueMask;
|
||||
};
|
||||
|
||||
struct BitmapInfoHeaderV3 : BitmapInfoHeaderV2 {
|
||||
u32 biAlphaMask;
|
||||
};
|
||||
|
||||
struct BitmapInfoHeaderV4 : BitmapInfoHeaderV3 {
|
||||
u32 biCSType;
|
||||
CIEXYZTRIPLE biEndpoints;
|
||||
u32 biGammaRed;
|
||||
u32 biGammaGreen;
|
||||
u32 biGammaBlue;
|
||||
};
|
||||
|
||||
struct BitmapInfoHeaderV5 : BitmapInfoHeaderV4 {
|
||||
u32 biIntent;
|
||||
u32 biProfileData;
|
||||
u32 biProfileSize;
|
||||
u32 biReserved;
|
||||
};
|
||||
|
||||
struct Colors {
|
||||
u8 blue;
|
||||
u8 green;
|
||||
@@ -31,10 +84,21 @@ struct Colors {
|
||||
};
|
||||
|
||||
struct Bitmap {
|
||||
u8 data[std::mem::size()] [[no_unique_address, hidden]];
|
||||
BitmapFileHeader bmfh;
|
||||
BitmapInfoHeader bmih;
|
||||
// Deduce the header version from its size
|
||||
u32 bmInfoHeaderSize [[hidden, no_unique_address]];
|
||||
match (bmInfoHeaderSize) {
|
||||
(40): BitmapInfoHeaderV1 bmih;
|
||||
(52): BitmapInfoHeaderV2 bmih;
|
||||
(56): BitmapInfoHeaderV3 bmih;
|
||||
(108): BitmapInfoHeaderV4 bmih;
|
||||
(124): BitmapInfoHeaderV5 bmih;
|
||||
(_): BitmapInfoHeaderV1 bmih;
|
||||
}
|
||||
padding[bmih.biSize - sizeof(bmih)];
|
||||
|
||||
if ((bmih.biBitCount != 24) && (bmih.biBitCount != 32))
|
||||
if (bmih.biBitCount <= 8)
|
||||
{
|
||||
if (bmih.biClrUsed > 0 )
|
||||
Colors rgbq[bmih.biClrUsed];
|
||||
@@ -46,6 +110,6 @@ struct Bitmap {
|
||||
u8 lineData[bmih.biSizeImage];
|
||||
else
|
||||
u8 lineData[bmfh.bfSize - $];
|
||||
};
|
||||
} [[hex::visualize("image", this.data)]];
|
||||
|
||||
Bitmap bitmap @ 0x00;
|
||||
|
||||
@@ -1,128 +1,132 @@
|
||||
#pragma MIME application/bson
|
||||
|
||||
#include <type/time.pat>
|
||||
|
||||
enum Type : u8 {
|
||||
Double = 0x01,
|
||||
String = 0x02,
|
||||
EmbeddedDocument = 0x03,
|
||||
Array = 0x04,
|
||||
Binary = 0x05,
|
||||
Undefined = 0x06,
|
||||
ObjectId = 0x07,
|
||||
Boolean = 0x08,
|
||||
UTCDatetime = 0x09,
|
||||
Null = 0x0A,
|
||||
Regex = 0x0B,
|
||||
DBPointer = 0x0C,
|
||||
JavaScript = 0x0D,
|
||||
Symbol = 0x0E,
|
||||
JavaScriptWithScope = 0x0F,
|
||||
Int32 = 0x10,
|
||||
Timestamp = 0x11,
|
||||
Int64 = 0x12,
|
||||
Decimal128 = 0x13,
|
||||
|
||||
MinKey = 0xFF,
|
||||
MaxKey = 0x7F
|
||||
};
|
||||
|
||||
enum Subtype : u8 {
|
||||
GenericBinarySubtype = 0x00,
|
||||
Function = 0x01,
|
||||
BinaryOld = 0x02,
|
||||
UUIDOld = 0x03,
|
||||
UUID = 0x04,
|
||||
MD5 = 0x05,
|
||||
EncryptedBSONValue = 0x06,
|
||||
CompressedBSONColumn = 0x07,
|
||||
UserDefined = 0x80
|
||||
};
|
||||
|
||||
struct Binary {
|
||||
s32 length;
|
||||
Subtype subtype;
|
||||
u8 data[length];
|
||||
};
|
||||
|
||||
struct String {
|
||||
u32 length [[hidden]];
|
||||
char value[length];
|
||||
} [[sealed, format("format_string")]];
|
||||
|
||||
struct CString {
|
||||
char value[];
|
||||
} [[sealed, format("format_string")]];
|
||||
|
||||
fn format_string(auto string) {
|
||||
return string.value;
|
||||
};
|
||||
|
||||
struct ObjectId {
|
||||
type::time32_t timestamp;
|
||||
u8 randomValue[5];
|
||||
u24 counter;
|
||||
};
|
||||
|
||||
struct DBPointer {
|
||||
String name;
|
||||
ObjectId value;
|
||||
};
|
||||
|
||||
|
||||
using Document;
|
||||
|
||||
struct Element {
|
||||
Type type;
|
||||
|
||||
CString name;
|
||||
|
||||
if (type == Type::Double) {
|
||||
double value;
|
||||
} else if (type == Type::String) {
|
||||
String value;
|
||||
} else if (type == Type::EmbeddedDocument) {
|
||||
Document value;
|
||||
} else if (type == Type::Array) {
|
||||
Document value;
|
||||
} else if (type == Type::Binary) {
|
||||
Binary value;
|
||||
} else if (type == Type::Undefined) {
|
||||
/* undefined */
|
||||
} else if (type == Type::ObjectId) {
|
||||
ObjectId value;
|
||||
} else if (type == Type::Boolean) {
|
||||
bool value;
|
||||
} else if (type == Type::UTCDatetime) {
|
||||
type::time64_t value;
|
||||
} else if (type == Type::Null) {
|
||||
/* null */
|
||||
} else if (type == Type::Regex) {
|
||||
CString regexPattern;
|
||||
CString regexOptions;
|
||||
} else if (type == Type::DBPointer) {
|
||||
DBPointer value;
|
||||
} else if (type == Type::JavaScript) {
|
||||
String value;
|
||||
} else if (type == Type::Symbol) {
|
||||
String value;
|
||||
} else if (type == Type::JavaScriptWithScope) {
|
||||
String value;
|
||||
} else if (type == Type::Int32) {
|
||||
s32 value;
|
||||
} else if (type == Type::Timestamp) {
|
||||
u64 value;
|
||||
} else if (type == Type::Int64) {
|
||||
s64 value;
|
||||
} else if (type == Type::Decimal128) {
|
||||
u128 value;
|
||||
}
|
||||
};
|
||||
|
||||
struct Document {
|
||||
s32 listLength;
|
||||
Element elements[while($ < ((addressof(this) + listLength) - 1))];
|
||||
padding[1];
|
||||
};
|
||||
|
||||
Document document @ 0x00;
|
||||
#pragma author WerWolv
|
||||
#pragma description BSON (Binary JSON) format
|
||||
|
||||
#pragma MIME application/bson
|
||||
|
||||
#include <std/mem.pat>
|
||||
#include <type/time.pat>
|
||||
|
||||
enum Type : u8 {
|
||||
Double = 0x01,
|
||||
String = 0x02,
|
||||
EmbeddedDocument = 0x03,
|
||||
Array = 0x04,
|
||||
Binary = 0x05,
|
||||
Undefined = 0x06,
|
||||
ObjectId = 0x07,
|
||||
Boolean = 0x08,
|
||||
UTCDatetime = 0x09,
|
||||
Null = 0x0A,
|
||||
Regex = 0x0B,
|
||||
DBPointer = 0x0C,
|
||||
JavaScript = 0x0D,
|
||||
Symbol = 0x0E,
|
||||
JavaScriptWithScope = 0x0F,
|
||||
Int32 = 0x10,
|
||||
Timestamp = 0x11,
|
||||
Int64 = 0x12,
|
||||
Decimal128 = 0x13,
|
||||
|
||||
MinKey = 0xFF,
|
||||
MaxKey = 0x7F
|
||||
};
|
||||
|
||||
enum Subtype : u8 {
|
||||
GenericBinarySubtype = 0x00,
|
||||
Function = 0x01,
|
||||
BinaryOld = 0x02,
|
||||
UUIDOld = 0x03,
|
||||
UUID = 0x04,
|
||||
MD5 = 0x05,
|
||||
EncryptedBSONValue = 0x06,
|
||||
CompressedBSONColumn = 0x07,
|
||||
UserDefined = 0x80
|
||||
};
|
||||
|
||||
struct Binary {
|
||||
s32 length;
|
||||
Subtype subtype;
|
||||
u8 data[length];
|
||||
};
|
||||
|
||||
struct String {
|
||||
u32 length [[hidden]];
|
||||
char value[length];
|
||||
} [[sealed, format("format_string")]];
|
||||
|
||||
struct CString {
|
||||
char value[];
|
||||
} [[sealed, format("format_string")]];
|
||||
|
||||
fn format_string(auto string) {
|
||||
return string.value;
|
||||
};
|
||||
|
||||
struct ObjectId {
|
||||
type::time32_t timestamp;
|
||||
u8 randomValue[5];
|
||||
u24 counter;
|
||||
};
|
||||
|
||||
struct DBPointer {
|
||||
String name;
|
||||
ObjectId value;
|
||||
};
|
||||
|
||||
|
||||
using Document;
|
||||
|
||||
struct Element {
|
||||
Type type;
|
||||
|
||||
CString name;
|
||||
|
||||
if (type == Type::Double) {
|
||||
double value;
|
||||
} else if (type == Type::String) {
|
||||
String value;
|
||||
} else if (type == Type::EmbeddedDocument) {
|
||||
Document value;
|
||||
} else if (type == Type::Array) {
|
||||
Document value;
|
||||
} else if (type == Type::Binary) {
|
||||
Binary value;
|
||||
} else if (type == Type::Undefined) {
|
||||
/* undefined */
|
||||
} else if (type == Type::ObjectId) {
|
||||
ObjectId value;
|
||||
} else if (type == Type::Boolean) {
|
||||
bool value;
|
||||
} else if (type == Type::UTCDatetime) {
|
||||
type::time64_t value;
|
||||
} else if (type == Type::Null) {
|
||||
/* null */
|
||||
} else if (type == Type::Regex) {
|
||||
CString regexPattern;
|
||||
CString regexOptions;
|
||||
} else if (type == Type::DBPointer) {
|
||||
DBPointer value;
|
||||
} else if (type == Type::JavaScript) {
|
||||
String value;
|
||||
} else if (type == Type::Symbol) {
|
||||
String value;
|
||||
} else if (type == Type::JavaScriptWithScope) {
|
||||
String value;
|
||||
} else if (type == Type::Int32) {
|
||||
s32 value;
|
||||
} else if (type == Type::Timestamp) {
|
||||
u64 value;
|
||||
} else if (type == Type::Int64) {
|
||||
s64 value;
|
||||
} else if (type == Type::Decimal128) {
|
||||
u128 value;
|
||||
}
|
||||
};
|
||||
|
||||
struct Document {
|
||||
s32 listLength;
|
||||
Element elements[while($ < ((addressof(this) + listLength) - 1))];
|
||||
padding[1];
|
||||
};
|
||||
|
||||
Document documents[while(!std::mem::eof())] @ 0x00 [[inline]];
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description GoldSrc engine maps format (used in Half-Life 1)
|
||||
|
||||
#include <std/ptr.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Command and Conquer Voxel Animation
|
||||
|
||||
// Command and conquer voxel animation format
|
||||
|
||||
struct vec4_s {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Command and Conquer Voxel Palette
|
||||
|
||||
// Command and conquer palette format
|
||||
|
||||
struct Color {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Command and Conquer Voxel Model
|
||||
|
||||
// Command and Conquer voxel model format
|
||||
|
||||
struct vec4_s {
|
||||
|
||||
31
patterns/cda.hexpat
Normal file
31
patterns/cda.hexpat
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma description Compact Disc Audio track
|
||||
|
||||
struct Header {
|
||||
u32 RIFF;
|
||||
s32 size;
|
||||
u32 CDDA;
|
||||
u32 fmt;
|
||||
u32 lenghtofthechunck;
|
||||
u16 versionofcdformat;
|
||||
u16 numberofrange;
|
||||
u32 identifier;
|
||||
};
|
||||
|
||||
|
||||
struct DataInfo {
|
||||
|
||||
u32 range;
|
||||
u32 duration;
|
||||
u8 rangepositionframes;
|
||||
u8 rangepositionseconds;
|
||||
u8 rangepositionminutes;
|
||||
u8 nullbyte;
|
||||
u8 durationtrackframes;
|
||||
u8 durationtrackseconds;
|
||||
u8 durationtrackminutes;
|
||||
u8 nullbytee;
|
||||
};
|
||||
|
||||
|
||||
Header header @ 0;
|
||||
DataInfo data @ 0x1C;
|
||||
@@ -1,395 +1,398 @@
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
#include <type/guid.pat>
|
||||
#include <type/leb128.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
enum WindowsLanguageId : u32 {
|
||||
Arabic_SaudiArabia = 0x401,
|
||||
Arabic_Iraq = 0x801,
|
||||
Arabic_Egypt = 0xc01,
|
||||
Arabic_Libya = 0x1001,
|
||||
Arabic_Algeria = 0x1401,
|
||||
Arabic_Morocco = 0x1801,
|
||||
Arabic_Tunisia = 0x1c01,
|
||||
Arabic_Oman = 0x2001,
|
||||
Arabic_Yemen = 0x2401,
|
||||
Arabic_Syria = 0x2801,
|
||||
Arabic_Jordan = 0x2c01,
|
||||
Arabic_Lebanon = 0x3001,
|
||||
Arabic_Kuwait = 0x3401,
|
||||
Arabic_UAE = 0x3801,
|
||||
Arabic_Bahrain = 0x3c01,
|
||||
Arabic_Qatar = 0x4001,
|
||||
Bulgarian = 0x402,
|
||||
Catalan = 0x403,
|
||||
Valencian = 0x803,
|
||||
Chinese_Taiwan = 0x404,
|
||||
Chinese_PRC = 0x804,
|
||||
Chinese_HongKongSAR = 0xc04,
|
||||
Chinese_Singapore = 0x1004,
|
||||
Chinese_MacaoSAR = 0x1404,
|
||||
Czech = 0x405,
|
||||
Danish = 0x406,
|
||||
German_Germany = 0x407,
|
||||
German_Switzerland = 0x807,
|
||||
German_Austria = 0xc07,
|
||||
German_Luxembourg = 0x1007,
|
||||
German_Liechtenstein = 0x1407,
|
||||
Greek = 0x408,
|
||||
English_UnitedStates = 0x409,
|
||||
English_UnitedKingdom = 0x809,
|
||||
English_Australia = 0xc09,
|
||||
English_Canada = 0x1009,
|
||||
English_NewZealand = 0x1409,
|
||||
English_Ireland = 0x1809,
|
||||
English_SouthAfrica = 0x1c09,
|
||||
English_Jamaica = 0x2009,
|
||||
English_Caribbean = 0x2409,
|
||||
English_Belize = 0x2809,
|
||||
English_TrinidadandTobago = 0x2c09,
|
||||
English_Zimbabwe = 0x3009,
|
||||
English_Philippines = 0x3409,
|
||||
English_Indonesia = 0x3809,
|
||||
English_HongKongSAR = 0x3c09,
|
||||
English_India = 0x4009,
|
||||
English_Malaysia = 0x4409,
|
||||
English_Singapore = 0x4809,
|
||||
Spanish_SpainTraditionalSort = 0x40a,
|
||||
Spanish_Mexico = 0x80a,
|
||||
Spanish_Spain = 0xc0a,
|
||||
Spanish_Guatemala = 0x100a,
|
||||
Spanish_CostaRica = 0x140a,
|
||||
Spanish_Panama = 0x180a,
|
||||
Spanish_DominicanRepublic = 0x1c0a,
|
||||
Spanish_Venezuela = 0x200a,
|
||||
Spanish_Colombia = 0x240a,
|
||||
Spanish_Peru = 0x280a,
|
||||
Spanish_Argentina = 0x2c0a,
|
||||
Spanish_Ecuador = 0x300a,
|
||||
Spanish_Chile = 0x340a,
|
||||
Spanish_Uruguay = 0x380a,
|
||||
Spanish_Paraguay = 0x3c0a,
|
||||
Spanish_Bolivia = 0x400a,
|
||||
Spanish_ElSalvador = 0x440a,
|
||||
Spanish_Honduras = 0x480a,
|
||||
Spanish_Nicaragua = 0x4c0a,
|
||||
Spanish_PuertoRico = 0x500a,
|
||||
Spanish_UnitedStates = 0x540a,
|
||||
Spanish_LatinAmerica = 0x580a,
|
||||
Finnish = 0x40b,
|
||||
French_France = 0x40c,
|
||||
French_Belgium = 0x80c,
|
||||
French_Canada = 0xc0c,
|
||||
French_Switzerland = 0x100c,
|
||||
French_Luxembourg = 0x140c,
|
||||
French_Monaco = 0x180c,
|
||||
French_Caribbean = 0x1c0c,
|
||||
French_Reunion = 0x200c,
|
||||
French_CongoDRC = 0x240c,
|
||||
French_Senegal = 0x280c,
|
||||
French_Cameroon = 0x2c0c,
|
||||
French_CoteDIvoire = 0x300c,
|
||||
French_Mali = 0x340c,
|
||||
French_Morocco = 0x380c,
|
||||
French_Haiti = 0x3c0c,
|
||||
Hebrew = 0x40d,
|
||||
Hungarian = 0x40e,
|
||||
Icelandic = 0x40f,
|
||||
Italian_Italy = 0x410,
|
||||
Italian_Switzerland = 0x810,
|
||||
Japanese = 0x411,
|
||||
Korean = 0x412,
|
||||
Dutch_Netherlands = 0x413,
|
||||
Dutch_Belgium = 0x813,
|
||||
Norwegian_Bokmal = 0x414,
|
||||
Norwegian_Nynorsk = 0x814,
|
||||
Polish = 0x415,
|
||||
Portuguese_Brazil = 0x416,
|
||||
Portuguese_Portugal = 0x816,
|
||||
Romansh = 0x417,
|
||||
Romanian = 0x418,
|
||||
Romanian_Moldova = 0x818,
|
||||
Russian = 0x419,
|
||||
Russian_Moldova = 0x819,
|
||||
Croatian_Croatia = 0x41a,
|
||||
Serbian_LatinSerbiaandMontenegroFormer = 0x81a,
|
||||
Serbian_CyrillicSerbiaAndMontenegroFormer = 0xc1a,
|
||||
Croatian_BosniaAndHerzegovina = 0x101a,
|
||||
Bosnian_Latin = 0x141a,
|
||||
Serbian_LatinBosniaAndHerzegovina = 0x181a,
|
||||
Serbian_CyrillicBosniaAndHerzegovina = 0x1c1a,
|
||||
Bosnian_Cyrillic = 0x201a,
|
||||
Serbian_LatinSerbia = 0x241a,
|
||||
Serbian_CyrillicSerbia = 0x281a,
|
||||
Serbian_LatinMontenegro = 0x2c1a,
|
||||
Serbian_CyrillicMontenegro = 0x301a,
|
||||
Slovak = 0x41b,
|
||||
Albanian = 0x41c,
|
||||
Swedish_Sweden = 0x41d,
|
||||
Swedish_Finland = 0x81d,
|
||||
Thai = 0x41e,
|
||||
Turkish = 0x41f,
|
||||
Urdu_Pakistan = 0x420,
|
||||
Urdu_India = 0x820,
|
||||
Indonesian = 0x421,
|
||||
Ukrainian = 0x422,
|
||||
Belarusian = 0x423,
|
||||
Slovenian = 0x424,
|
||||
Estonian = 0x425,
|
||||
Latvian = 0x426,
|
||||
Lithuanian = 0x427,
|
||||
Tajik = 0x428,
|
||||
Persian = 0x429,
|
||||
Vietnamese = 0x42a,
|
||||
Armenian = 0x42b,
|
||||
Azerbaijani_Latin = 0x42c,
|
||||
Azerbaijani_Cyrillic = 0x82c,
|
||||
Basque = 0x42d,
|
||||
UpperSorbian = 0x42e,
|
||||
LowerSorbian = 0x82e,
|
||||
Macedonian = 0x42f,
|
||||
Sesotho_SouthAfrica = 0x430,
|
||||
Xitsonga = 0x431,
|
||||
Setswana_SouthAfrica = 0x432,
|
||||
Setswana_Botswana = 0x832,
|
||||
Venda = 0x433,
|
||||
isiXhosa = 0x434,
|
||||
isiZulu = 0x435,
|
||||
Afrikaans = 0x436,
|
||||
Georgian = 0x437,
|
||||
Faroese = 0x438,
|
||||
Hindi = 0x439,
|
||||
Maltese = 0x43a,
|
||||
NorthernSami_Norway = 0x43b,
|
||||
NorthernSami_Sweden = 0x83b,
|
||||
NorthernSami_Finland = 0xc3b,
|
||||
LuleSami_Norway = 0x103b,
|
||||
LuleSami_Sweden = 0x143b,
|
||||
SouthernSami_Norway = 0x183b,
|
||||
SouthernSami_Sweden = 0x1c3b,
|
||||
SkoltSami_Finland = 0x203b,
|
||||
InariSami_Finland = 0x243b,
|
||||
Irish = 0x83c,
|
||||
Yiddish = 0x43d,
|
||||
Malay_Malaysia = 0x43e,
|
||||
Malay_BruneiDarussalam = 0x83e,
|
||||
Kazakh = 0x43f,
|
||||
Kyrgyz = 0x440,
|
||||
Kiswahili = 0x441,
|
||||
Turkmen = 0x442,
|
||||
Uzbek_Latin = 0x443,
|
||||
Uzbek_Cyrillic = 0x843,
|
||||
Tatar = 0x444,
|
||||
Bangla_India = 0x445,
|
||||
Bangla_Bangladesh = 0x845,
|
||||
Punjabi_India = 0x446,
|
||||
Punjabi_Pakistan = 0x846,
|
||||
Gujarati = 0x447,
|
||||
Odia = 0x448,
|
||||
Tamil_India = 0x449,
|
||||
Tamil_SriLanka = 0x849,
|
||||
Telugu = 0x44a,
|
||||
Kannada = 0x44b,
|
||||
Malayalam = 0x44c,
|
||||
Assamese = 0x44d,
|
||||
Marathi = 0x44e,
|
||||
Sanskrit = 0x44f,
|
||||
Mongolian_Cyrillic = 0x450,
|
||||
Mongolian_TraditionalMongolianPRC = 0x850,
|
||||
Mongolian_TraditionalMongolianMongolia = 0xc50,
|
||||
Tibetan_PRC = 0x451,
|
||||
Welsh = 0x452,
|
||||
Khmer = 0x453,
|
||||
Lao = 0x454,
|
||||
Burmese = 0x455,
|
||||
Galician = 0x456,
|
||||
Konkani = 0x457,
|
||||
Manipuri = 0x458,
|
||||
Sindhi_Devanagari = 0x459,
|
||||
Sindhi_Arabic = 0x859,
|
||||
Syriac = 0x45a,
|
||||
Sinhala = 0x45b,
|
||||
Cherokee_Cherokee = 0x45c,
|
||||
Inuktitut_Syllabics = 0x45d,
|
||||
Inuktitut_Latin = 0x85d,
|
||||
Amharic = 0x45e,
|
||||
Tamazight_ArabicMorocco = 0x45f,
|
||||
Tamazight_LatinAlgeria = 0x85f,
|
||||
Tamazight_TifinaghMorocco = 0x105f,
|
||||
Kashmiri_Arabic = 0x460,
|
||||
Kashmiri = 0x860,
|
||||
Nepali = 0x461,
|
||||
Nepali_India = 0x861,
|
||||
Frisian = 0x462,
|
||||
Pashto = 0x463,
|
||||
Filipino = 0x464,
|
||||
Divehi = 0x465,
|
||||
Edo = 0x466,
|
||||
Fulah_Nigeria = 0x467,
|
||||
Fulah_LatinSenegal = 0x867,
|
||||
Hausa = 0x468,
|
||||
Ibibio_Nigeria = 0x469,
|
||||
Yoruba = 0x46a,
|
||||
Quechua_Bolivia = 0x46b,
|
||||
Quechua_Ecuador = 0x86b,
|
||||
Quechua_Peru = 0xc6b,
|
||||
SesothoSaLeboa = 0x46c,
|
||||
Bashkir = 0x46d,
|
||||
Luxembourgish = 0x46e,
|
||||
Greenlandic = 0x46f,
|
||||
Igbo = 0x470,
|
||||
Kanuri = 0x471,
|
||||
Oromo = 0x472,
|
||||
Tigrinya_Ethiopia = 0x473,
|
||||
Tigrinya_Eritrea = 0x873,
|
||||
Guarani = 0x474,
|
||||
Hawaiian = 0x475,
|
||||
Latin = 0x476,
|
||||
Somali = 0x477,
|
||||
Yi_PRC = 0x478,
|
||||
Papiamentu = 0x479,
|
||||
Mapudungun = 0x47a,
|
||||
Mohawk = 0x47c,
|
||||
Breton = 0x47e,
|
||||
Uyghur_PRC = 0x480,
|
||||
Maori = 0x481,
|
||||
Occitan = 0x482,
|
||||
Corsican = 0x483,
|
||||
Alsatian = 0x484,
|
||||
Sakha = 0x485,
|
||||
Kiche = 0x486,
|
||||
Kinyarwanda = 0x487,
|
||||
Wolof = 0x488,
|
||||
Dari = 0x48c,
|
||||
ScottishGaelic_UnitedKingdom = 0x491,
|
||||
CentralKurdish_Iraq = 0x492
|
||||
};
|
||||
|
||||
struct DirectoryListingEntry {
|
||||
type::LEB128 nameLength;
|
||||
char name[nameLength];
|
||||
type::LEB128 contentSection;
|
||||
type::LEB128 offset;
|
||||
type::LEB128 length;
|
||||
};
|
||||
|
||||
struct DirectoryIndexEntry {
|
||||
type::LEB128 nameLength;
|
||||
char name[nameLength];
|
||||
type::LEB128 directoryListingChunk;
|
||||
};
|
||||
|
||||
struct ListingChunk {
|
||||
char magic[4];
|
||||
|
||||
if (magic == "PMGL") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
u32;
|
||||
u32 prevChunkNumber, nextChunkNumber;
|
||||
|
||||
u16 directoryListingEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryListingEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
DirectoryListingEntry directories[directoryListingEntryCount];
|
||||
|
||||
$ = addressof(directoryListingEntryCount) + sizeof(directoryListingEntryCount);
|
||||
} else if (magic == "PMGI") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
|
||||
u16 directoryIndexEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryIndexEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
DirectoryIndexEntry indexes[directoryIndexEntryCount];
|
||||
|
||||
$ = addressof(directoryIndexEntryCount) + sizeof(directoryIndexEntryCount);
|
||||
} else {
|
||||
std::error("Invalid chunk magic!");
|
||||
}
|
||||
};
|
||||
|
||||
struct HeaderSection {
|
||||
char magic[4];
|
||||
|
||||
if (magic == "\xFE\x01\x00\x00") {
|
||||
u32;
|
||||
type::Size<u64> fileSize;
|
||||
u32;
|
||||
u32;
|
||||
} else if (magic == "ITSP") {
|
||||
u32 version;
|
||||
type::Size<u32> directoryHeaderLength1;
|
||||
u32;
|
||||
u32 directoryChunkSize;
|
||||
u32 quickRefSectionDensity;
|
||||
u32 indexTreeDepth;
|
||||
u32 rootIndexChunkNumber;
|
||||
u32 firstPMGLChunkNumber;
|
||||
u32 lastPMGLChunkNumber;
|
||||
u32;
|
||||
u32 directoryChunkCount;
|
||||
WindowsLanguageId languageId;
|
||||
type::GUID guid;
|
||||
type::Size<u32> directoryHeaderLength2;
|
||||
u32;
|
||||
u32;
|
||||
u32;
|
||||
|
||||
ListingChunk chunk[directoryChunkCount];
|
||||
} else {
|
||||
std::error("Invalid header section magic!");
|
||||
}
|
||||
};
|
||||
|
||||
struct HeaderSectionTableEntry {
|
||||
u64 offset;
|
||||
type::Size<u64> size;
|
||||
|
||||
HeaderSection headerSection @ offset;
|
||||
};
|
||||
|
||||
struct NameListEntry {
|
||||
type::Size<u16> nameLength;
|
||||
char16 name[nameLength];
|
||||
padding[2];
|
||||
};
|
||||
|
||||
struct NameListFile {
|
||||
u16 fileLengthWords;
|
||||
u16 entriesInFile;
|
||||
|
||||
NameListEntry nameList[entriesInFile];
|
||||
|
||||
padding[0x2E];
|
||||
};
|
||||
|
||||
struct SectionData {
|
||||
u32 fileLengthWords;
|
||||
type::Magic<"LZXC"> magic;
|
||||
u32 version;
|
||||
u32 lzxResetInterval;
|
||||
type::Size<u32> windowSize;
|
||||
type::Size<u32> cacheSize;
|
||||
u32;
|
||||
};
|
||||
|
||||
struct Content {
|
||||
NameListFile nameListFile;
|
||||
SectionData sectionData;
|
||||
};
|
||||
|
||||
struct CHM {
|
||||
type::Magic<"ITSF"> magic;
|
||||
u32 version;
|
||||
type::Size<u32> headerSize;
|
||||
u32;
|
||||
be u32 timeStamp;
|
||||
WindowsLanguageId languageId;
|
||||
type::GUID guids[2];
|
||||
|
||||
HeaderSectionTableEntry headerSectionTable[2];
|
||||
|
||||
Content *dataOffset : u64;
|
||||
};
|
||||
|
||||
CHM chm @ 0x00;
|
||||
#pragma author WerWolv
|
||||
#pragma description Windows HtmlHelp Data (ITSF / CHM)
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
#include <type/guid.pat>
|
||||
#include <type/leb128.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
enum WindowsLanguageId : u32 {
|
||||
Arabic_SaudiArabia = 0x401,
|
||||
Arabic_Iraq = 0x801,
|
||||
Arabic_Egypt = 0xc01,
|
||||
Arabic_Libya = 0x1001,
|
||||
Arabic_Algeria = 0x1401,
|
||||
Arabic_Morocco = 0x1801,
|
||||
Arabic_Tunisia = 0x1c01,
|
||||
Arabic_Oman = 0x2001,
|
||||
Arabic_Yemen = 0x2401,
|
||||
Arabic_Syria = 0x2801,
|
||||
Arabic_Jordan = 0x2c01,
|
||||
Arabic_Lebanon = 0x3001,
|
||||
Arabic_Kuwait = 0x3401,
|
||||
Arabic_UAE = 0x3801,
|
||||
Arabic_Bahrain = 0x3c01,
|
||||
Arabic_Qatar = 0x4001,
|
||||
Bulgarian = 0x402,
|
||||
Catalan = 0x403,
|
||||
Valencian = 0x803,
|
||||
Chinese_Taiwan = 0x404,
|
||||
Chinese_PRC = 0x804,
|
||||
Chinese_HongKongSAR = 0xc04,
|
||||
Chinese_Singapore = 0x1004,
|
||||
Chinese_MacaoSAR = 0x1404,
|
||||
Czech = 0x405,
|
||||
Danish = 0x406,
|
||||
German_Germany = 0x407,
|
||||
German_Switzerland = 0x807,
|
||||
German_Austria = 0xc07,
|
||||
German_Luxembourg = 0x1007,
|
||||
German_Liechtenstein = 0x1407,
|
||||
Greek = 0x408,
|
||||
English_UnitedStates = 0x409,
|
||||
English_UnitedKingdom = 0x809,
|
||||
English_Australia = 0xc09,
|
||||
English_Canada = 0x1009,
|
||||
English_NewZealand = 0x1409,
|
||||
English_Ireland = 0x1809,
|
||||
English_SouthAfrica = 0x1c09,
|
||||
English_Jamaica = 0x2009,
|
||||
English_Caribbean = 0x2409,
|
||||
English_Belize = 0x2809,
|
||||
English_TrinidadandTobago = 0x2c09,
|
||||
English_Zimbabwe = 0x3009,
|
||||
English_Philippines = 0x3409,
|
||||
English_Indonesia = 0x3809,
|
||||
English_HongKongSAR = 0x3c09,
|
||||
English_India = 0x4009,
|
||||
English_Malaysia = 0x4409,
|
||||
English_Singapore = 0x4809,
|
||||
Spanish_SpainTraditionalSort = 0x40a,
|
||||
Spanish_Mexico = 0x80a,
|
||||
Spanish_Spain = 0xc0a,
|
||||
Spanish_Guatemala = 0x100a,
|
||||
Spanish_CostaRica = 0x140a,
|
||||
Spanish_Panama = 0x180a,
|
||||
Spanish_DominicanRepublic = 0x1c0a,
|
||||
Spanish_Venezuela = 0x200a,
|
||||
Spanish_Colombia = 0x240a,
|
||||
Spanish_Peru = 0x280a,
|
||||
Spanish_Argentina = 0x2c0a,
|
||||
Spanish_Ecuador = 0x300a,
|
||||
Spanish_Chile = 0x340a,
|
||||
Spanish_Uruguay = 0x380a,
|
||||
Spanish_Paraguay = 0x3c0a,
|
||||
Spanish_Bolivia = 0x400a,
|
||||
Spanish_ElSalvador = 0x440a,
|
||||
Spanish_Honduras = 0x480a,
|
||||
Spanish_Nicaragua = 0x4c0a,
|
||||
Spanish_PuertoRico = 0x500a,
|
||||
Spanish_UnitedStates = 0x540a,
|
||||
Spanish_LatinAmerica = 0x580a,
|
||||
Finnish = 0x40b,
|
||||
French_France = 0x40c,
|
||||
French_Belgium = 0x80c,
|
||||
French_Canada = 0xc0c,
|
||||
French_Switzerland = 0x100c,
|
||||
French_Luxembourg = 0x140c,
|
||||
French_Monaco = 0x180c,
|
||||
French_Caribbean = 0x1c0c,
|
||||
French_Reunion = 0x200c,
|
||||
French_CongoDRC = 0x240c,
|
||||
French_Senegal = 0x280c,
|
||||
French_Cameroon = 0x2c0c,
|
||||
French_CoteDIvoire = 0x300c,
|
||||
French_Mali = 0x340c,
|
||||
French_Morocco = 0x380c,
|
||||
French_Haiti = 0x3c0c,
|
||||
Hebrew = 0x40d,
|
||||
Hungarian = 0x40e,
|
||||
Icelandic = 0x40f,
|
||||
Italian_Italy = 0x410,
|
||||
Italian_Switzerland = 0x810,
|
||||
Japanese = 0x411,
|
||||
Korean = 0x412,
|
||||
Dutch_Netherlands = 0x413,
|
||||
Dutch_Belgium = 0x813,
|
||||
Norwegian_Bokmal = 0x414,
|
||||
Norwegian_Nynorsk = 0x814,
|
||||
Polish = 0x415,
|
||||
Portuguese_Brazil = 0x416,
|
||||
Portuguese_Portugal = 0x816,
|
||||
Romansh = 0x417,
|
||||
Romanian = 0x418,
|
||||
Romanian_Moldova = 0x818,
|
||||
Russian = 0x419,
|
||||
Russian_Moldova = 0x819,
|
||||
Croatian_Croatia = 0x41a,
|
||||
Serbian_LatinSerbiaandMontenegroFormer = 0x81a,
|
||||
Serbian_CyrillicSerbiaAndMontenegroFormer = 0xc1a,
|
||||
Croatian_BosniaAndHerzegovina = 0x101a,
|
||||
Bosnian_Latin = 0x141a,
|
||||
Serbian_LatinBosniaAndHerzegovina = 0x181a,
|
||||
Serbian_CyrillicBosniaAndHerzegovina = 0x1c1a,
|
||||
Bosnian_Cyrillic = 0x201a,
|
||||
Serbian_LatinSerbia = 0x241a,
|
||||
Serbian_CyrillicSerbia = 0x281a,
|
||||
Serbian_LatinMontenegro = 0x2c1a,
|
||||
Serbian_CyrillicMontenegro = 0x301a,
|
||||
Slovak = 0x41b,
|
||||
Albanian = 0x41c,
|
||||
Swedish_Sweden = 0x41d,
|
||||
Swedish_Finland = 0x81d,
|
||||
Thai = 0x41e,
|
||||
Turkish = 0x41f,
|
||||
Urdu_Pakistan = 0x420,
|
||||
Urdu_India = 0x820,
|
||||
Indonesian = 0x421,
|
||||
Ukrainian = 0x422,
|
||||
Belarusian = 0x423,
|
||||
Slovenian = 0x424,
|
||||
Estonian = 0x425,
|
||||
Latvian = 0x426,
|
||||
Lithuanian = 0x427,
|
||||
Tajik = 0x428,
|
||||
Persian = 0x429,
|
||||
Vietnamese = 0x42a,
|
||||
Armenian = 0x42b,
|
||||
Azerbaijani_Latin = 0x42c,
|
||||
Azerbaijani_Cyrillic = 0x82c,
|
||||
Basque = 0x42d,
|
||||
UpperSorbian = 0x42e,
|
||||
LowerSorbian = 0x82e,
|
||||
Macedonian = 0x42f,
|
||||
Sesotho_SouthAfrica = 0x430,
|
||||
Xitsonga = 0x431,
|
||||
Setswana_SouthAfrica = 0x432,
|
||||
Setswana_Botswana = 0x832,
|
||||
Venda = 0x433,
|
||||
isiXhosa = 0x434,
|
||||
isiZulu = 0x435,
|
||||
Afrikaans = 0x436,
|
||||
Georgian = 0x437,
|
||||
Faroese = 0x438,
|
||||
Hindi = 0x439,
|
||||
Maltese = 0x43a,
|
||||
NorthernSami_Norway = 0x43b,
|
||||
NorthernSami_Sweden = 0x83b,
|
||||
NorthernSami_Finland = 0xc3b,
|
||||
LuleSami_Norway = 0x103b,
|
||||
LuleSami_Sweden = 0x143b,
|
||||
SouthernSami_Norway = 0x183b,
|
||||
SouthernSami_Sweden = 0x1c3b,
|
||||
SkoltSami_Finland = 0x203b,
|
||||
InariSami_Finland = 0x243b,
|
||||
Irish = 0x83c,
|
||||
Yiddish = 0x43d,
|
||||
Malay_Malaysia = 0x43e,
|
||||
Malay_BruneiDarussalam = 0x83e,
|
||||
Kazakh = 0x43f,
|
||||
Kyrgyz = 0x440,
|
||||
Kiswahili = 0x441,
|
||||
Turkmen = 0x442,
|
||||
Uzbek_Latin = 0x443,
|
||||
Uzbek_Cyrillic = 0x843,
|
||||
Tatar = 0x444,
|
||||
Bangla_India = 0x445,
|
||||
Bangla_Bangladesh = 0x845,
|
||||
Punjabi_India = 0x446,
|
||||
Punjabi_Pakistan = 0x846,
|
||||
Gujarati = 0x447,
|
||||
Odia = 0x448,
|
||||
Tamil_India = 0x449,
|
||||
Tamil_SriLanka = 0x849,
|
||||
Telugu = 0x44a,
|
||||
Kannada = 0x44b,
|
||||
Malayalam = 0x44c,
|
||||
Assamese = 0x44d,
|
||||
Marathi = 0x44e,
|
||||
Sanskrit = 0x44f,
|
||||
Mongolian_Cyrillic = 0x450,
|
||||
Mongolian_TraditionalMongolianPRC = 0x850,
|
||||
Mongolian_TraditionalMongolianMongolia = 0xc50,
|
||||
Tibetan_PRC = 0x451,
|
||||
Welsh = 0x452,
|
||||
Khmer = 0x453,
|
||||
Lao = 0x454,
|
||||
Burmese = 0x455,
|
||||
Galician = 0x456,
|
||||
Konkani = 0x457,
|
||||
Manipuri = 0x458,
|
||||
Sindhi_Devanagari = 0x459,
|
||||
Sindhi_Arabic = 0x859,
|
||||
Syriac = 0x45a,
|
||||
Sinhala = 0x45b,
|
||||
Cherokee_Cherokee = 0x45c,
|
||||
Inuktitut_Syllabics = 0x45d,
|
||||
Inuktitut_Latin = 0x85d,
|
||||
Amharic = 0x45e,
|
||||
Tamazight_ArabicMorocco = 0x45f,
|
||||
Tamazight_LatinAlgeria = 0x85f,
|
||||
Tamazight_TifinaghMorocco = 0x105f,
|
||||
Kashmiri_Arabic = 0x460,
|
||||
Kashmiri = 0x860,
|
||||
Nepali = 0x461,
|
||||
Nepali_India = 0x861,
|
||||
Frisian = 0x462,
|
||||
Pashto = 0x463,
|
||||
Filipino = 0x464,
|
||||
Divehi = 0x465,
|
||||
Edo = 0x466,
|
||||
Fulah_Nigeria = 0x467,
|
||||
Fulah_LatinSenegal = 0x867,
|
||||
Hausa = 0x468,
|
||||
Ibibio_Nigeria = 0x469,
|
||||
Yoruba = 0x46a,
|
||||
Quechua_Bolivia = 0x46b,
|
||||
Quechua_Ecuador = 0x86b,
|
||||
Quechua_Peru = 0xc6b,
|
||||
SesothoSaLeboa = 0x46c,
|
||||
Bashkir = 0x46d,
|
||||
Luxembourgish = 0x46e,
|
||||
Greenlandic = 0x46f,
|
||||
Igbo = 0x470,
|
||||
Kanuri = 0x471,
|
||||
Oromo = 0x472,
|
||||
Tigrinya_Ethiopia = 0x473,
|
||||
Tigrinya_Eritrea = 0x873,
|
||||
Guarani = 0x474,
|
||||
Hawaiian = 0x475,
|
||||
Latin = 0x476,
|
||||
Somali = 0x477,
|
||||
Yi_PRC = 0x478,
|
||||
Papiamentu = 0x479,
|
||||
Mapudungun = 0x47a,
|
||||
Mohawk = 0x47c,
|
||||
Breton = 0x47e,
|
||||
Uyghur_PRC = 0x480,
|
||||
Maori = 0x481,
|
||||
Occitan = 0x482,
|
||||
Corsican = 0x483,
|
||||
Alsatian = 0x484,
|
||||
Sakha = 0x485,
|
||||
Kiche = 0x486,
|
||||
Kinyarwanda = 0x487,
|
||||
Wolof = 0x488,
|
||||
Dari = 0x48c,
|
||||
ScottishGaelic_UnitedKingdom = 0x491,
|
||||
CentralKurdish_Iraq = 0x492
|
||||
};
|
||||
|
||||
struct DirectoryListingEntry {
|
||||
type::LEB128 nameLength;
|
||||
char name[nameLength];
|
||||
type::LEB128 contentSection;
|
||||
type::LEB128 offset;
|
||||
type::LEB128 length;
|
||||
};
|
||||
|
||||
struct DirectoryIndexEntry {
|
||||
type::LEB128 nameLength;
|
||||
char name[nameLength];
|
||||
type::LEB128 directoryListingChunk;
|
||||
};
|
||||
|
||||
struct ListingChunk {
|
||||
char magic[4];
|
||||
|
||||
if (magic == "PMGL") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
u32;
|
||||
u32 prevChunkNumber, nextChunkNumber;
|
||||
|
||||
u16 directoryListingEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryListingEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
DirectoryListingEntry directories[directoryListingEntryCount];
|
||||
|
||||
$ = addressof(directoryListingEntryCount) + sizeof(directoryListingEntryCount);
|
||||
} else if (magic == "PMGI") {
|
||||
type::Size<u32> freeSpaceLength;
|
||||
|
||||
u16 directoryIndexEntryCount @ addressof(this) + parent.directoryChunkSize - 2;
|
||||
u16 offsets[(freeSpaceLength - 2) / 2] @ addressof(directoryIndexEntryCount) - (freeSpaceLength - 2);
|
||||
|
||||
DirectoryIndexEntry indexes[directoryIndexEntryCount];
|
||||
|
||||
$ = addressof(directoryIndexEntryCount) + sizeof(directoryIndexEntryCount);
|
||||
} else {
|
||||
std::error("Invalid chunk magic!");
|
||||
}
|
||||
};
|
||||
|
||||
struct HeaderSection {
|
||||
char magic[4];
|
||||
|
||||
if (magic == "\xFE\x01\x00\x00") {
|
||||
u32;
|
||||
type::Size<u64> fileSize;
|
||||
u32;
|
||||
u32;
|
||||
} else if (magic == "ITSP") {
|
||||
u32 version;
|
||||
type::Size<u32> directoryHeaderLength1;
|
||||
u32;
|
||||
u32 directoryChunkSize;
|
||||
u32 quickRefSectionDensity;
|
||||
u32 indexTreeDepth;
|
||||
u32 rootIndexChunkNumber;
|
||||
u32 firstPMGLChunkNumber;
|
||||
u32 lastPMGLChunkNumber;
|
||||
u32;
|
||||
u32 directoryChunkCount;
|
||||
WindowsLanguageId languageId;
|
||||
type::GUID guid;
|
||||
type::Size<u32> directoryHeaderLength2;
|
||||
u32;
|
||||
u32;
|
||||
u32;
|
||||
|
||||
ListingChunk chunk[directoryChunkCount];
|
||||
} else {
|
||||
std::error("Invalid header section magic!");
|
||||
}
|
||||
};
|
||||
|
||||
struct HeaderSectionTableEntry {
|
||||
u64 offset;
|
||||
type::Size<u64> size;
|
||||
|
||||
HeaderSection headerSection @ offset;
|
||||
};
|
||||
|
||||
struct NameListEntry {
|
||||
type::Size<u16> nameLength;
|
||||
char16 name[nameLength];
|
||||
padding[2];
|
||||
};
|
||||
|
||||
struct NameListFile {
|
||||
u16 fileLengthWords;
|
||||
u16 entriesInFile;
|
||||
|
||||
NameListEntry nameList[entriesInFile];
|
||||
|
||||
padding[0x2E];
|
||||
};
|
||||
|
||||
struct SectionData {
|
||||
u32 fileLengthWords;
|
||||
type::Magic<"LZXC"> magic;
|
||||
u32 version;
|
||||
u32 lzxResetInterval;
|
||||
type::Size<u32> windowSize;
|
||||
type::Size<u32> cacheSize;
|
||||
u32;
|
||||
};
|
||||
|
||||
struct Content {
|
||||
NameListFile nameListFile;
|
||||
SectionData sectionData;
|
||||
};
|
||||
|
||||
struct CHM {
|
||||
type::Magic<"ITSF"> magic;
|
||||
u32 version;
|
||||
type::Size<u32> headerSize;
|
||||
u32;
|
||||
be u32 timeStamp;
|
||||
WindowsLanguageId languageId;
|
||||
type::GUID guids[2];
|
||||
|
||||
HeaderSectionTableEntry headerSectionTable[2];
|
||||
|
||||
Content *dataOffset : u64;
|
||||
};
|
||||
|
||||
CHM chm @ 0x00;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Common Object File Format (COFF) executable
|
||||
|
||||
#pragma MIME application/x-coff
|
||||
|
||||
#include <type/time.pat>
|
||||
|
||||
@@ -1,66 +1,69 @@
|
||||
#include <type/base.pat>
|
||||
|
||||
#include <std/time.pat>
|
||||
#include <std/core.pat>
|
||||
#include <std/sys.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
#pragma MIME application/x-cpio
|
||||
|
||||
namespace old_binary {
|
||||
|
||||
using Time = u32 [[format("old_binary::format_time")]];
|
||||
|
||||
fn swap_32bit(u32 value) {
|
||||
return ((value >> 16) & 0xFFFF) | ((value & 0xFFFF) << 16);
|
||||
};
|
||||
|
||||
fn format_time(u32 value) {
|
||||
return std::time::format(std::time::to_utc(swap_32bit(value)));
|
||||
};
|
||||
|
||||
using SwappedU32 = u32 [[transform("old_binary::swap_32bit"), format("old_binary::swap_32bit")]];
|
||||
|
||||
bitfield Mode {
|
||||
x : 3;
|
||||
w : 3;
|
||||
r : 3;
|
||||
sticky : 1;
|
||||
sgid : 1;
|
||||
suid : 1;
|
||||
file_type : 4;
|
||||
};
|
||||
|
||||
struct CpioHeader {
|
||||
type::Oct<u16> magic;
|
||||
if (magic == be u16(0o070707))
|
||||
std::core::set_endian(std::mem::Endian::Big);
|
||||
else if (magic == le u16(0o070707))
|
||||
std::core::set_endian(std::mem::Endian::Little);
|
||||
else
|
||||
std::error("Invalid CPIO Magic!");
|
||||
|
||||
u16 dev;
|
||||
u16 ino;
|
||||
Mode mode;
|
||||
u16 uid;
|
||||
u16 gid;
|
||||
u16 nlink;
|
||||
u16 rdev;
|
||||
Time mtime;
|
||||
u16 namesize;
|
||||
SwappedU32 filesize;
|
||||
};
|
||||
|
||||
struct Cpio {
|
||||
CpioHeader header;
|
||||
char pathname[header.namesize % 2 == 0 ? header.namesize : header.namesize + 1];
|
||||
u8 data[header.filesize % 2 == 0 ? header.filesize : header.filesize + 1];
|
||||
|
||||
if (pathname == "TRAILER!!!\x00\x00")
|
||||
break;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
old_binary::Cpio cpio[while(true)] @ 0x00;
|
||||
#pragma author WerWolv
|
||||
#pragma description Old Binary CPIO Format
|
||||
|
||||
#include <type/base.pat>
|
||||
|
||||
#include <std/time.pat>
|
||||
#include <std/core.pat>
|
||||
#include <std/sys.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
#pragma MIME application/x-cpio
|
||||
|
||||
namespace old_binary {
|
||||
|
||||
using Time = u32 [[format("old_binary::format_time")]];
|
||||
|
||||
fn swap_32bit(u32 value) {
|
||||
return ((value >> 16) & 0xFFFF) | ((value & 0xFFFF) << 16);
|
||||
};
|
||||
|
||||
fn format_time(u32 value) {
|
||||
return std::time::format(std::time::to_utc(swap_32bit(value)));
|
||||
};
|
||||
|
||||
using SwappedU32 = u32 [[transform("old_binary::swap_32bit"), format("old_binary::swap_32bit")]];
|
||||
|
||||
bitfield Mode {
|
||||
x : 3;
|
||||
w : 3;
|
||||
r : 3;
|
||||
sticky : 1;
|
||||
sgid : 1;
|
||||
suid : 1;
|
||||
file_type : 4;
|
||||
};
|
||||
|
||||
struct CpioHeader {
|
||||
type::Oct<u16> magic;
|
||||
if (magic == be u16(0o070707))
|
||||
std::core::set_endian(std::mem::Endian::Big);
|
||||
else if (magic == le u16(0o070707))
|
||||
std::core::set_endian(std::mem::Endian::Little);
|
||||
else
|
||||
std::error("Invalid CPIO Magic!");
|
||||
|
||||
u16 dev;
|
||||
u16 ino;
|
||||
Mode mode;
|
||||
u16 uid;
|
||||
u16 gid;
|
||||
u16 nlink;
|
||||
u16 rdev;
|
||||
Time mtime;
|
||||
u16 namesize;
|
||||
SwappedU32 filesize;
|
||||
};
|
||||
|
||||
struct Cpio {
|
||||
CpioHeader header;
|
||||
char pathname[header.namesize % 2 == 0 ? header.namesize : header.namesize + 1];
|
||||
u8 data[header.filesize % 2 == 0 ? header.filesize : header.filesize + 1];
|
||||
|
||||
if (pathname == "TRAILER!!!\x00\x00")
|
||||
break;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
old_binary::Cpio cpio[while(true)] @ 0x00;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description DirectDraw Surface
|
||||
|
||||
#pragma MIME image/vnd-ms.dds
|
||||
#pragma endian little
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Dalvik EXecutable Format
|
||||
|
||||
#include <type/leb128.pat>
|
||||
|
||||
struct header_item {
|
||||
@@ -170,5 +172,8 @@ struct Dex {
|
||||
field_id_item field_ids[header.field_ids_size] @ header.field_ids_off;
|
||||
method_id_item method_ids[header.method_ids_size] @ header.method_ids_off;
|
||||
class_def_item class_defs[header.class_defs_size] @ header.class_defs_off;
|
||||
u8 data[header.data_size] @header.data_off;
|
||||
map_list map_list @ header.map_off;
|
||||
u8 link_data[header.link_size] @ header.link_off;
|
||||
};
|
||||
Dex dex @ 0x00;
|
||||
Dex dex @ 0x00;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Apple Disk Image Trailer (DMG)
|
||||
|
||||
#pragma endian big
|
||||
|
||||
#include <type/magic.pat>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description .DS_Store file format
|
||||
|
||||
// Apple macOS .DS_Store format
|
||||
#pragma endian big
|
||||
#include <std/io.pat>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description ELF header in elf binaries
|
||||
|
||||
#pragma MIME application/x-executable
|
||||
#pragma MIME application/x-elf
|
||||
#pragma MIME application/x-coredump
|
||||
@@ -563,7 +566,7 @@ struct Elf32_Phdr {
|
||||
PF p_flags;
|
||||
Elf32_Word p_align;
|
||||
|
||||
if (p_offset > 0 && p_filesz > 0 && (p_offset + p_filesz) < std::mem::size() && p_filesz < std::mem::size())
|
||||
if (p_offset >= 0 && p_filesz > 0 && (p_offset + p_filesz) <= std::mem::size() && p_filesz <= std::mem::size())
|
||||
u8 p_data[p_filesz] @ p_offset [[sealed]];
|
||||
};
|
||||
|
||||
@@ -577,7 +580,7 @@ struct Elf64_Phdr {
|
||||
Elf64_Xword p_memsz;
|
||||
Elf64_Xword p_align;
|
||||
|
||||
if (p_offset > 0 && p_filesz > 0 && (p_offset + p_filesz) < std::mem::size() && p_filesz < std::mem::size())
|
||||
if (p_offset >= 0 && p_filesz > 0 && (p_offset + p_filesz) <= std::mem::size() && p_filesz <= std::mem::size())
|
||||
u8 p_data[p_filesz] @ p_offset [[sealed]];
|
||||
};
|
||||
|
||||
@@ -714,14 +717,9 @@ fn format_section_header(auto shdr) {
|
||||
u32 i = 0;
|
||||
|
||||
u32 nameAddress = addressof(elf.shdr[stringTableIndex].stringTable) + shdr.sh_name;
|
||||
while (i < std::core::member_count(elf.shdr[stringTableIndex].stringTable)) {
|
||||
if (nameAddress >= addressof(elf.shdr[stringTableIndex].stringTable[i]) && nameAddress < (addressof(elf.shdr[stringTableIndex].stringTable[i]) + sizeof(elf.shdr[stringTableIndex].stringTable[i])))
|
||||
break;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
String string @ nameAddress;
|
||||
|
||||
return elf.shdr[stringTableIndex].stringTable[i].value;
|
||||
return string;
|
||||
};
|
||||
|
||||
|
||||
@@ -819,4 +817,4 @@ fn main() {
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description MS Windows Vista Event Log
|
||||
|
||||
#pragma endian little
|
||||
|
||||
struct Header {
|
||||
|
||||
125
patterns/fdt.hexpat
Normal file
125
patterns/fdt.hexpat
Normal file
@@ -0,0 +1,125 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Flat Linux Device Tree blob
|
||||
|
||||
#pragma endian big
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/io.pat>
|
||||
#include <std/core.pat>
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
// These are used in order for the children to be able to find strings
|
||||
u64 fdt_addr;
|
||||
u64 str_offset;
|
||||
|
||||
|
||||
struct FDTHeader {
|
||||
type::Magic<"\xD0\x0D\xFE\xED"> magic;
|
||||
u32 totalsize;
|
||||
u32 off_dt_struct;
|
||||
u32 off_dt_strings;
|
||||
u32 off_mem_rsvmap;
|
||||
u32 version;
|
||||
u32 last_comp_version;
|
||||
u32 boot_cpuid_phys;
|
||||
u32 size_dt_strings;
|
||||
u32 size_dt_struct;
|
||||
};
|
||||
|
||||
struct AlignTo<auto Alignment> {
|
||||
padding[Alignment- ((($ - 1) % Alignment) + 1)];
|
||||
} [[hidden]];
|
||||
|
||||
struct FDTReserveEntry {
|
||||
u64 address;
|
||||
type::Size<u64> size;
|
||||
|
||||
if (address == 0x00 && size == 0x00)
|
||||
break;
|
||||
};
|
||||
|
||||
enum FDTToken : u32 {
|
||||
FDT_BEGIN_NODE = 0x00000001,
|
||||
FDT_END_NODE = 0x00000002,
|
||||
FDT_PROP = 0x00000003,
|
||||
FDT_NOP = 0x00000004,
|
||||
FDT_END = 0x00000009
|
||||
};
|
||||
|
||||
union FDTPropValue<auto len> {
|
||||
u32 prop_array[len / sizeof(u32)];
|
||||
char string[len];
|
||||
};
|
||||
|
||||
struct FDTProp {
|
||||
FDTToken tok[[hidden]];
|
||||
u32 len [[hidden]];
|
||||
u32 nameoff [[hidden]];
|
||||
if (len > 0) {
|
||||
// if len is zero, value is absent and no need to include it
|
||||
FDTPropValue<len> value;
|
||||
}
|
||||
AlignTo<4>;
|
||||
char name[] @ fdt_addr + str_offset + nameoff;
|
||||
|
||||
std::core::set_display_name(this, name);
|
||||
std::print(std::format("{:x} token {} len {} {}",
|
||||
$, tok, len,nameoff));
|
||||
FDTToken token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
||||
if (token != FDTToken::FDT_PROP) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
struct FDTNode {
|
||||
FDTToken token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
||||
|
||||
if (token == FDTToken::FDT_BEGIN_NODE) {
|
||||
FDTToken tok[[hidden]];
|
||||
char name[];
|
||||
AlignTo<4>;
|
||||
std::core::set_display_name(this, name[0] ? name : "/");
|
||||
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
||||
|
||||
if(token == FDTToken::FDT_PROP) {
|
||||
FDTProp props[while(true)];
|
||||
}
|
||||
|
||||
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
||||
if(token == FDTToken::FDT_END_NODE) {
|
||||
FDTToken[[hidden]];
|
||||
break;
|
||||
}
|
||||
|
||||
FDTNode children[while(true)][[inline]];
|
||||
} else if(token == FDTToken::FDT_NOP) {
|
||||
// TODO this may break the pattern, I've so far not encountered it
|
||||
}
|
||||
|
||||
// ew duplication
|
||||
token = std::mem::read_unsigned($, 4, std::mem::Endian::Big);
|
||||
if(token == FDTToken::FDT_END_NODE) {
|
||||
FDTToken[[hidden]];
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
struct FDTStructureBlock {
|
||||
FDTNode;
|
||||
};
|
||||
|
||||
|
||||
struct FDT {
|
||||
FDTHeader header;
|
||||
std::assert(header.version == 17, "Unsupported format version");
|
||||
fdt_addr = addressof(this);
|
||||
str_offset = header.off_dt_strings;
|
||||
|
||||
FDTStructureBlock structureBlocks @ fdt_addr + header.off_dt_struct;
|
||||
FDTReserveEntry reserveEntries[while(true)] @ fdt_addr + header.off_mem_rsvmap;
|
||||
};
|
||||
|
||||
std::mem::MagicSearch<"\xD0\x0D\xFE\xED", FDT> fdt @ std::mem::base_address();
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
#pragma endian big
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/io.pat>
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
struct FDTHeader {
|
||||
type::Magic<"\xD0\x0D\xFE\xED"> magic;
|
||||
u32 totalsize;
|
||||
u32 off_dt_struct;
|
||||
u32 off_dt_strings;
|
||||
u32 off_mem_rsvmap;
|
||||
u32 version;
|
||||
u32 last_comp_version;
|
||||
u32 boot_cpuid_phys;
|
||||
u32 size_dt_strings;
|
||||
u32 size_dt_struct;
|
||||
};
|
||||
|
||||
struct AlignTo<auto Alignment> {
|
||||
padding[Alignment- ((($ - 1) % Alignment) + 1)];
|
||||
};
|
||||
|
||||
struct FDTReserveEntry {
|
||||
u64 address;
|
||||
type::Size<u64> size;
|
||||
|
||||
if (address == 0x00 && size == 0x00)
|
||||
break;
|
||||
};
|
||||
|
||||
enum FDTToken : u32 {
|
||||
FDT_BEGIN_NODE = 0x00000001,
|
||||
FDT_END_NODE = 0x00000002,
|
||||
FDT_PROP = 0x00000003,
|
||||
FDT_NOP = 0x00000004,
|
||||
FDT_END = 0x00000009
|
||||
};
|
||||
|
||||
struct FDTStructureBlock {
|
||||
FDTToken token;
|
||||
if (token == FDTToken::FDT_BEGIN_NODE) {
|
||||
char nodeName[];
|
||||
AlignTo<4>;
|
||||
} else if (token == FDTToken::FDT_END) {
|
||||
break;
|
||||
} else if (token == FDTToken::FDT_PROP) {
|
||||
u32 len;
|
||||
u32 nameoff;
|
||||
char value[len];
|
||||
AlignTo<4>;
|
||||
char name[] @ parent.header.off_dt_strings + nameoff;
|
||||
} else if (token == FDTToken::FDT_NOP || token == FDTToken::FDT_END_NODE) {
|
||||
// Nothing to do
|
||||
} else {
|
||||
std::error(std::format("Invalid token at address 0x{:02X}", addressof(token)));
|
||||
}
|
||||
};
|
||||
|
||||
struct FDT {
|
||||
FDTHeader header;
|
||||
std::assert(header.version == 17, "Unsupported format version");
|
||||
|
||||
FDTStructureBlock structureBlocks[while(true)] @ header.off_dt_struct;
|
||||
FDTReserveEntry reserveEntries[while(true)] @ header.off_mem_rsvmap;
|
||||
};
|
||||
|
||||
FDT fdt @ 0x00;
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Free Lossless Audio Codec, FLAC Audio Format
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/core.pat>
|
||||
#include <std/io.pat>
|
||||
@@ -138,7 +141,7 @@ enum PICTURE_TYPE : u32 {
|
||||
struct METADATA_BLOCK_PICTURE {
|
||||
PICTURE_TYPE pictureType;
|
||||
u32 mimeTypeLength;
|
||||
char mimeType[mineTypeLength];
|
||||
char mimeType[mimeTypeLength];
|
||||
u32 descriptionLength;
|
||||
char description[descriptionLength];
|
||||
u32 width, height;
|
||||
|
||||
@@ -1,168 +1,171 @@
|
||||
#include <std/io.pat>
|
||||
|
||||
struct DiskTimeStamp {
|
||||
u8 seconds, minutes, hours;
|
||||
};
|
||||
|
||||
enum DiskProtection : u16 {
|
||||
None = 0x0000,
|
||||
CopyProtected = 0x5A5A
|
||||
};
|
||||
|
||||
bitfield CHS {
|
||||
h : 8;
|
||||
s : 6;
|
||||
c : 10;
|
||||
} [[format("chs_formatter")]];
|
||||
|
||||
fn chs_formatter(CHS chs) {
|
||||
return std::format("({:X}, {:X}, {:X}) | 0x{:X}", chs.c, chs.h, chs.s, (chs.c * 16 + chs.h) * 63 + (chs.s - 1));
|
||||
};
|
||||
|
||||
enum PartitionStatus : u8 {
|
||||
None = 0x00,
|
||||
Active = 0x80
|
||||
};
|
||||
|
||||
enum PartitionType : u8 {
|
||||
EmptyPartitionEntry = 0x00,
|
||||
FAT32_CHS = 0x0B,
|
||||
FAT32_LBA = 0x0C
|
||||
};
|
||||
|
||||
namespace fat32 {
|
||||
|
||||
u64 bytesPerCluster;
|
||||
|
||||
struct FSInfo {
|
||||
u32 leadSignature;
|
||||
padding[480];
|
||||
u32 structSignature;
|
||||
u32 freeClusterCount;
|
||||
u32 nextFreeCluster;
|
||||
padding[12];
|
||||
u32 trailSignature;
|
||||
};
|
||||
|
||||
bitfield SequenceNumber {
|
||||
padding : 1;
|
||||
lastLogical : 1;
|
||||
padding : 1;
|
||||
number : 5;
|
||||
} [[left_to_right]];
|
||||
|
||||
enum EntryStatus : u8 {
|
||||
Regular = 0x00,
|
||||
DotEntry = 0x2E,
|
||||
DeletedEntry = 0xE5
|
||||
};
|
||||
|
||||
union EntryStatusOrSequenceNumber {
|
||||
EntryStatus entryStatus;
|
||||
SequenceNumber sequenceNumber;
|
||||
};
|
||||
|
||||
bitfield Attributes {
|
||||
readOnly : 1;
|
||||
hidden : 1;
|
||||
systemFile : 1;
|
||||
volumeLabel : 1;
|
||||
subdirectory : 1;
|
||||
archive : 1;
|
||||
padding : 2;
|
||||
} [[right_to_left]];
|
||||
|
||||
struct DirEntry {
|
||||
char fileName[8];
|
||||
char extension[3];
|
||||
Attributes attributes;
|
||||
u8 reserved[10];
|
||||
u16 time, date;
|
||||
u16 startingCluster;
|
||||
u32 fileSize;
|
||||
|
||||
u8 data[fileSize] @ startingCluster * bytesPerCluster;
|
||||
};
|
||||
|
||||
struct VFATDirEntry {
|
||||
EntryStatusOrSequenceNumber entryStatusOrSequenceNumber;
|
||||
char16 name1[5];
|
||||
Attributes attributes;
|
||||
u8 type;
|
||||
u8 nameChecksum;
|
||||
char16 name2[6];
|
||||
u16 startingCluster;
|
||||
char16 name3[2];
|
||||
|
||||
if (entryStatusOrSequenceNumber.sequenceNumber.number > 1)
|
||||
VFATDirEntry nextLogicalEntry;
|
||||
else
|
||||
DirEntry physicalEntry;
|
||||
};
|
||||
|
||||
struct Partition {
|
||||
u8 jmpCode[3];
|
||||
char oemName[8];
|
||||
u16 bytesPerSector;
|
||||
u8 sectorsPerCluster;
|
||||
u16 reservedAreaSize;
|
||||
u8 numFats;
|
||||
u16 rootEntryCount;
|
||||
u16 numSectors;
|
||||
u8 mediaType;
|
||||
u16 fatSize;
|
||||
u16 sectorsPerTrack;
|
||||
u16 numHeads;
|
||||
u32 numHiddenSectors;
|
||||
u32 numFsSectors;
|
||||
u32 numFatSectors;
|
||||
u16 extFlags;
|
||||
u16 fsVersion;
|
||||
u32 rootCluster;
|
||||
u16 fsInfoSector;
|
||||
u16 backupBootSector;
|
||||
padding[12];
|
||||
u8 driveNumber;
|
||||
padding[1];
|
||||
u8 bootSignature;
|
||||
u32 volumeID;
|
||||
char volumeLabel[11];
|
||||
char fsType[8];
|
||||
u8 bootstrapCode[420];
|
||||
u16 signature;
|
||||
|
||||
bytesPerCluster = (sectorsPerCluster * 1024) * bytesPerSector;
|
||||
|
||||
FSInfo fsInfo @ addressof(this) + fsInfoSector * bytesPerSector;
|
||||
VFATDirEntry rootDirEntry @ addressof(this) + rootCluster * bytesPerCluster;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct PartitionEntry {
|
||||
PartitionStatus status;
|
||||
CHS chsFirstSectorAddress;
|
||||
PartitionType type;
|
||||
CHS chsLastSectorAddress;
|
||||
u32 lbaFirstSectorAddress;
|
||||
u32 numSectors;
|
||||
|
||||
if (type == PartitionType::EmptyPartitionEntry)
|
||||
continue;
|
||||
else if (type == PartitionType::FAT32_CHS || type == PartitionType::FAT32_LBA)
|
||||
fat32::Partition partition @ lbaFirstSectorAddress * 512;
|
||||
};
|
||||
|
||||
struct MasterBootRecord {
|
||||
u8 bootstrapCodeArea1[218];
|
||||
padding[2];
|
||||
u8 originalPhysicalDrive;
|
||||
DiskTimeStamp diskTimeStamp;
|
||||
u8 bootstrapCodeArea2[216];
|
||||
u32 diskSignature;
|
||||
DiskProtection diskProtection;
|
||||
PartitionEntry partitionEntries[4];
|
||||
u16 bootSignature;
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description Drive File System
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
struct DiskTimeStamp {
|
||||
u8 seconds, minutes, hours;
|
||||
};
|
||||
|
||||
enum DiskProtection : u16 {
|
||||
None = 0x0000,
|
||||
CopyProtected = 0x5A5A
|
||||
};
|
||||
|
||||
bitfield CHS {
|
||||
h : 8;
|
||||
s : 6;
|
||||
c : 10;
|
||||
} [[format("chs_formatter")]];
|
||||
|
||||
fn chs_formatter(CHS chs) {
|
||||
return std::format("({:X}, {:X}, {:X}) | 0x{:X}", chs.c, chs.h, chs.s, (chs.c * 16 + chs.h) * 63 + (chs.s - 1));
|
||||
};
|
||||
|
||||
enum PartitionStatus : u8 {
|
||||
None = 0x00,
|
||||
Active = 0x80
|
||||
};
|
||||
|
||||
enum PartitionType : u8 {
|
||||
EmptyPartitionEntry = 0x00,
|
||||
FAT32_CHS = 0x0B,
|
||||
FAT32_LBA = 0x0C
|
||||
};
|
||||
|
||||
namespace fat32 {
|
||||
|
||||
u64 bytesPerCluster;
|
||||
|
||||
struct FSInfo {
|
||||
u32 leadSignature;
|
||||
padding[480];
|
||||
u32 structSignature;
|
||||
u32 freeClusterCount;
|
||||
u32 nextFreeCluster;
|
||||
padding[12];
|
||||
u32 trailSignature;
|
||||
};
|
||||
|
||||
bitfield SequenceNumber {
|
||||
padding : 1;
|
||||
lastLogical : 1;
|
||||
padding : 1;
|
||||
number : 5;
|
||||
} [[left_to_right]];
|
||||
|
||||
enum EntryStatus : u8 {
|
||||
Regular = 0x00,
|
||||
DotEntry = 0x2E,
|
||||
DeletedEntry = 0xE5
|
||||
};
|
||||
|
||||
union EntryStatusOrSequenceNumber {
|
||||
EntryStatus entryStatus;
|
||||
SequenceNumber sequenceNumber;
|
||||
};
|
||||
|
||||
bitfield Attributes {
|
||||
readOnly : 1;
|
||||
hidden : 1;
|
||||
systemFile : 1;
|
||||
volumeLabel : 1;
|
||||
subdirectory : 1;
|
||||
archive : 1;
|
||||
padding : 2;
|
||||
} [[right_to_left]];
|
||||
|
||||
struct DirEntry {
|
||||
char fileName[8];
|
||||
char extension[3];
|
||||
Attributes attributes;
|
||||
u8 reserved[10];
|
||||
u16 time, date;
|
||||
u16 startingCluster;
|
||||
u32 fileSize;
|
||||
|
||||
u8 data[fileSize] @ startingCluster * bytesPerCluster;
|
||||
};
|
||||
|
||||
struct VFATDirEntry {
|
||||
EntryStatusOrSequenceNumber entryStatusOrSequenceNumber;
|
||||
char16 name1[5];
|
||||
Attributes attributes;
|
||||
u8 type;
|
||||
u8 nameChecksum;
|
||||
char16 name2[6];
|
||||
u16 startingCluster;
|
||||
char16 name3[2];
|
||||
|
||||
if (entryStatusOrSequenceNumber.sequenceNumber.number > 1)
|
||||
VFATDirEntry nextLogicalEntry;
|
||||
else
|
||||
DirEntry physicalEntry;
|
||||
};
|
||||
|
||||
struct Partition {
|
||||
u8 jmpCode[3];
|
||||
char oemName[8];
|
||||
u16 bytesPerSector;
|
||||
u8 sectorsPerCluster;
|
||||
u16 reservedAreaSize;
|
||||
u8 numFats;
|
||||
u16 rootEntryCount;
|
||||
u16 numSectors;
|
||||
u8 mediaType;
|
||||
u16 fatSize;
|
||||
u16 sectorsPerTrack;
|
||||
u16 numHeads;
|
||||
u32 numHiddenSectors;
|
||||
u32 numFsSectors;
|
||||
u32 numFatSectors;
|
||||
u16 extFlags;
|
||||
u16 fsVersion;
|
||||
u32 rootCluster;
|
||||
u16 fsInfoSector;
|
||||
u16 backupBootSector;
|
||||
padding[12];
|
||||
u8 driveNumber;
|
||||
padding[1];
|
||||
u8 bootSignature;
|
||||
u32 volumeID;
|
||||
char volumeLabel[11];
|
||||
char fsType[8];
|
||||
u8 bootstrapCode[420];
|
||||
u16 signature;
|
||||
|
||||
bytesPerCluster = (sectorsPerCluster * 1024) * bytesPerSector;
|
||||
|
||||
FSInfo fsInfo @ addressof(this) + fsInfoSector * bytesPerSector;
|
||||
VFATDirEntry rootDirEntry @ addressof(this) + rootCluster * bytesPerCluster;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct PartitionEntry {
|
||||
PartitionStatus status;
|
||||
CHS chsFirstSectorAddress;
|
||||
PartitionType type;
|
||||
CHS chsLastSectorAddress;
|
||||
u32 lbaFirstSectorAddress;
|
||||
u32 numSectors;
|
||||
|
||||
if (type == PartitionType::EmptyPartitionEntry)
|
||||
continue;
|
||||
else if (type == PartitionType::FAT32_CHS || type == PartitionType::FAT32_LBA)
|
||||
fat32::Partition partition @ lbaFirstSectorAddress * 512;
|
||||
};
|
||||
|
||||
struct MasterBootRecord {
|
||||
u8 bootstrapCodeArea1[218];
|
||||
padding[2];
|
||||
u8 originalPhysicalDrive;
|
||||
DiskTimeStamp diskTimeStamp;
|
||||
u8 bootstrapCodeArea2[216];
|
||||
u32 diskSignature;
|
||||
DiskProtection diskProtection;
|
||||
PartitionEntry partitionEntries[4];
|
||||
u16 bootSignature;
|
||||
};
|
||||
|
||||
MasterBootRecord mbr @ 0x00;
|
||||
340
patterns/gb.hexpat
Normal file
340
patterns/gb.hexpat
Normal file
@@ -0,0 +1,340 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Gameboy ROM
|
||||
|
||||
#include <type/size.pat>
|
||||
#include <std/io.pat>
|
||||
#include <std/string.pat>
|
||||
|
||||
#pragma MIME application/x-gameboy-rom
|
||||
|
||||
namespace format {
|
||||
|
||||
fn rom_type(u8 romType) {
|
||||
u32 romSize = 32768 * (1 << romType);
|
||||
u16 romBanks = 2 * (1 << romType);
|
||||
if(romType == 0x52) {
|
||||
romSize = 1153434;
|
||||
romBanks = 72;
|
||||
}
|
||||
if(romType == 0x53) {
|
||||
romSize = 1258291;
|
||||
romBanks = 80;
|
||||
}
|
||||
return std::format("size: {}, banks: {}", type::impl::size_formatter(romSize), romBanks);
|
||||
};
|
||||
|
||||
fn ram_type(u8 ramType) {
|
||||
u16 ramSize;
|
||||
u16 ramBanks;
|
||||
if(ramType == 2) {
|
||||
ramSize = 8192;
|
||||
ramBanks = 1;
|
||||
}
|
||||
if(ramType == 3) {
|
||||
ramSize = 32768;
|
||||
ramBanks = 4;
|
||||
}
|
||||
if(ramType == 4) {
|
||||
ramSize = 131072;
|
||||
ramBanks = 16;
|
||||
}
|
||||
if(ramType == 5) {
|
||||
ramSize = 65536;
|
||||
ramBanks = 8;
|
||||
}
|
||||
return std::format("size: {}, banks: {}", type::impl::size_formatter(ramSize), ramBanks);
|
||||
};
|
||||
|
||||
fn rom_features(u8 type) {
|
||||
str result = "( ";
|
||||
match(type) {
|
||||
(0x00): result += "no_mbc ";
|
||||
(0x01): result += "mbc1 ";
|
||||
(0x02): result += "mbc1 | ram ";
|
||||
(0x03): result += "mbc1 | ram | battery ";
|
||||
(0x05): result += "mbc2 ";
|
||||
(0x06): result += "mbc2 | battery ";
|
||||
(0x08): result += "no_mbc | ram ";
|
||||
(0x09): result += "no_mbc | ram | battery ";
|
||||
(0x0B): result += "mmm01 ";
|
||||
(0x0C): result += "mmm01 | ram ";
|
||||
(0x0D): result += "mmm01 | ram | battery ";
|
||||
(0x0F): result += "mbc3 | timer | battery ";
|
||||
(0x10): result += "mbc3 | timer | ram | battery ";
|
||||
(0x11): result += "mbc3 ";
|
||||
(0x12): result += "mbc3 | ram ";
|
||||
(0x13): result += "mbc3 | ram | battery ";
|
||||
(0x19): result += "mbc5 ";
|
||||
(0x1A): result += "mbc5 | ram ";
|
||||
(0x1B): result += "mbc5 | ram | battery ";
|
||||
(0x1C): result += "mbc5 | rumble ";
|
||||
(0x1D): result += "mbc5 | rumble | ram ";
|
||||
(0x1E): result += "mbc5 | rumble | ram | battery ";
|
||||
(0x20): result += "mbc6 ";
|
||||
(0x22): result += "mbc7 | sensor | rumble ";
|
||||
(0xFC): result += "camera ";
|
||||
(0xFD): result += "tama5 ";
|
||||
(0xFE): result += "huc3 ";
|
||||
(0xFF): result += "huc1 | ram | battery ";
|
||||
}
|
||||
return result + ")";
|
||||
};
|
||||
|
||||
fn licensee_code(u8 code) {
|
||||
match(code) {
|
||||
(0x00): return "None";
|
||||
(0x01 | 0x31): return "Nintendo";
|
||||
(0x08 | 0x38): return "Capcom";
|
||||
(0x09): return "Hot-B";
|
||||
(0x0A | 0xE0): return "Jaleco";
|
||||
(0x0B): return "Coconuts Japan";
|
||||
(0x0C | 0x6E): return "Elite Systems";
|
||||
(0x13 | 0x69): return "EA (Electronic Arts)";
|
||||
(0x18): return "Hudsonsoft";
|
||||
(0x19): return "ITC Entertainment";
|
||||
(0x1A): return "Yanoman";
|
||||
(0x1D): return "Japan Clary";
|
||||
(0x1F | 0x4A | 0x61): return "Virgin Interactive";
|
||||
(0x24): return "PCM Complete";
|
||||
(0x25): return "San-X";
|
||||
(0x28): return "Kotobuki Systems";
|
||||
(0x29): return "Seta";
|
||||
(0x30 | 0x70): return "Infogrames";
|
||||
(0x32 | 0xA2 | 0xB2 | 0xC4): return "Bandai";
|
||||
(0x33): return "See new licensee";
|
||||
(0x34 | 0xA4): return "Konami";
|
||||
(0x35): return "HectorSoft";
|
||||
(0x39 | 0x9D): return "Banpresto";
|
||||
(0x3C): return ".Entertainment i";
|
||||
(0x3E): return "Gremlin";
|
||||
(0x41): return "Ubisoft";
|
||||
(0x42 | 0xEB): return "Atlus";
|
||||
(0x44 | 0x4D): return "Malibu";
|
||||
(0x46 | 0xCF): return "Angel";
|
||||
(0x47): return "Spectrum Holoby";
|
||||
(0x49): return "Irem";
|
||||
(0x50): return "Absolute";
|
||||
(0x51 | 0xB0): return "Acclaim";
|
||||
(0x52): return "Activision";
|
||||
(0x53): return "American Sammy";
|
||||
(0x54): return "GameTek";
|
||||
(0x55): return "Park Place";
|
||||
(0x56 | 0xDB | 0xFF): return "LJN";
|
||||
(0x57): return "Matchbox";
|
||||
(0x59): return "Milton Bradley";
|
||||
(0x5A): return "Mindscape";
|
||||
(0x5B): return "Romstar";
|
||||
(0x5C | 0xD6): return "Naxat Soft";
|
||||
(0x5D): return "Tradewest";
|
||||
(0x60): return "Titus";
|
||||
(0x67): return "Ocean Interactive";
|
||||
(0x6F): return "Electro Brain";
|
||||
(0x71): return "Interplay";
|
||||
(0x72 | 0xAA): return "Broderbund";
|
||||
(0x73): return "Sculptered Soft";
|
||||
(0x75): return "The Sales Curve";
|
||||
(0x78): return "t.hq";
|
||||
(0x79): return "Accolade";
|
||||
(0x7A): return "Triffix Entertainment";
|
||||
(0x7C): return "Microprose";
|
||||
(0x7F | 0xC2): return "Kemco";
|
||||
(0x80): return "Misawa Entertainment";
|
||||
(0x83): return "Lozc";
|
||||
(0x86 | 0xC4): return "Tokuma Shoten Intermedia";
|
||||
(0x8B): return "Bullet-Proof Software";
|
||||
(0x8C): return "Vic Tokai";
|
||||
(0x8E): return "Ape";
|
||||
(0x8F): return "I'Max";
|
||||
(0x91): return "Chunksoft Co.";
|
||||
(0x92): return "Video System";
|
||||
(0x93): return "Tsubaraya Productions Co.";
|
||||
(0x95): return "Varie Corporation";
|
||||
(0x96): return "Yonezawa/S’Pal";
|
||||
(0x97): return "Kaneko";
|
||||
(0x99): return "Arc";
|
||||
(0x9A): return "Nihon Bussan";
|
||||
(0x9B): return "Tecmo";
|
||||
(0x9C): return "Imagineer";
|
||||
(0x9F): return "Nova";
|
||||
(0xA1): return "Hori Electric";
|
||||
(0xA6): return "Kawada";
|
||||
(0xA7): return "Takara";
|
||||
(0xA9): return "Technos Japan";
|
||||
(0xAC): return "Toei Animation";
|
||||
(0xAD): return "Toho";
|
||||
(0xAF): return "Namco";
|
||||
(0xB1): return "ASCII or Nexsoft";
|
||||
(0xB4): return "Square Enix";
|
||||
(0xB6): return "HAL Laboratory";
|
||||
(0xB7): return "SNK";
|
||||
(0xB9 | 0xCE): return "Pony Canyon";
|
||||
(0xBA): return "Culture Brain";
|
||||
(0xBB): return "Sunsoft";
|
||||
(0xBD): return "Sony Imagesoft";
|
||||
(0xBF): return "Sammy";
|
||||
(0xC0 | 0xD0): return "Taito";
|
||||
(0xC3): return "Squaresoft";
|
||||
(0xC5): return "Data East";
|
||||
(0xC6): return "Tonkinhouse";
|
||||
(0xC8): return "Koei";
|
||||
(0xC9): return "UFL";
|
||||
(0xCA): return "Ultra";
|
||||
(0xCB): return "Vap";
|
||||
(0xCC): return "Use Corporation";
|
||||
(0xCD): return "Meldac";
|
||||
(0xD1): return "Sofel";
|
||||
(0xD2): return "Quest";
|
||||
(0xD3): return "Sigma Enterprises";
|
||||
(0xD4): return "ASK Kodansha Co.";
|
||||
(0xD7): return "Copya System";
|
||||
(0xDA): return "Tomy";
|
||||
(0xDD): return "NCS";
|
||||
(0xDE): return "Human";
|
||||
(0xDF): return "Altron";
|
||||
(0xE1): return "Towa Chiki";
|
||||
(0xE2): return "Yutaka";
|
||||
(0xE3): return "Varie";
|
||||
(0xE5): return "Epoch";
|
||||
(0xE7): return "Athena";
|
||||
(0xE8): return "Asmik";
|
||||
(0xE9): return "Natsume";
|
||||
(0xEA): return "King Records";
|
||||
(0xEE): return "IGS";
|
||||
(0xF0): return "A Wave";
|
||||
(0xF3): return "Extreme Entertainment";
|
||||
}
|
||||
return "Unknown Licensee";
|
||||
};
|
||||
|
||||
fn new_licensee_code(str a) {
|
||||
if(a[0] == 0 && a[1] == 0) return "See old licensee";
|
||||
match(a) {
|
||||
("00"): return "None";
|
||||
("01"): return "Nintendo R&D1";
|
||||
("08"): return "Capcom";
|
||||
("13"): return "Electronic Arts";
|
||||
("18"): return "Hudson Soft";
|
||||
("19"): return "b-ai";
|
||||
("20"): return "kss";
|
||||
("22"): return "pow";
|
||||
("24"): return "PCM Complete";
|
||||
("25"): return "san-x";
|
||||
("28"): return "Kemco Japan";
|
||||
("29"): return "seta";
|
||||
("30"): return "Viacom";
|
||||
("31"): return "Nintendo";
|
||||
("32"): return "Bandai";
|
||||
("33"): return "Ocean/Acclaim";
|
||||
("34"): return "Konami";
|
||||
("35"): return "Hector";
|
||||
("37"): return "Taito";
|
||||
("38"): return "Hudson";
|
||||
("39"): return "Banpresto";
|
||||
("41"): return "Ubi Soft";
|
||||
("42"): return "Atlus";
|
||||
("44"): return "Malibu";
|
||||
("46"): return "angel";
|
||||
("47"): return "Bullet-Proof";
|
||||
("49"): return "irem";
|
||||
("50"): return "Absolute";
|
||||
("51"): return "Acclaim";
|
||||
("52"): return "Activision";
|
||||
("53"): return "American sammy";
|
||||
("54"): return "Konami";
|
||||
("55"): return "Hi tech entertainment";
|
||||
("56"): return "LJN";
|
||||
("57"): return "Matchbox";
|
||||
("58"): return "Mattel";
|
||||
("59"): return "Milton Bradley";
|
||||
("60"): return "Titus";
|
||||
("61"): return "Virgin";
|
||||
("64"): return "LucasArts";
|
||||
("67"): return "Ocean";
|
||||
("69"): return "Electronic Arts";
|
||||
("70"): return "Infogrames";
|
||||
("71"): return "Interplay";
|
||||
("72"): return "Broderbund";
|
||||
("73"): return "sculptured";
|
||||
("75"): return "sci";
|
||||
("78"): return "THQ";
|
||||
("79"): return "Accolade";
|
||||
("80"): return "misawa";
|
||||
("83"): return "lozc";
|
||||
("86"): return "Tokuma Shoten Intermedia";
|
||||
("87"): return "Tsukuda Original";
|
||||
("91"): return "Chunksoft";
|
||||
("92"): return "Video system";
|
||||
("93"): return "Ocean/Acclaim";
|
||||
("95"): return "Varie";
|
||||
("96"): return "Yonezawa/s’pal";
|
||||
("97"): return "Kaneko";
|
||||
("99"): return "Pack in soft";
|
||||
("A4"): return "Konami (Yu-Gi-Oh!)";
|
||||
}
|
||||
return "Unknown";
|
||||
};
|
||||
}
|
||||
|
||||
bitfield pixel_packed {
|
||||
p1 : 1;
|
||||
p2 : 1;
|
||||
p3 : 1;
|
||||
p4 : 1;
|
||||
p5 : 1;
|
||||
p6 : 1;
|
||||
p7 : 1;
|
||||
p8 : 1;
|
||||
};
|
||||
|
||||
enum CGB : u8 {
|
||||
NO_CGB = 0x00 ... 0x7F,
|
||||
BACKWARDS_COMPATIBLE = 0x80,
|
||||
CGB_ONLY = 0xC0
|
||||
};
|
||||
|
||||
|
||||
struct Logo {
|
||||
pixel_packed rawData[0x30];
|
||||
};
|
||||
|
||||
struct JumpVectors {
|
||||
u8 rst1[8] [[comment("rst $1")]];
|
||||
u8 rst2[8] [[comment("rst $2")]];
|
||||
u8 rst3[8] [[comment("rst $3")]];
|
||||
u8 rst4[8] [[comment("rst $4")]];
|
||||
u8 rst5[8] [[comment("rst $5")]];;
|
||||
u8 rst6[8] [[comment("rst $6")]];
|
||||
u8 rst7[8] [[comment("rst $7")]];
|
||||
u8 rst8[8] [[comment("rst $8")]];
|
||||
u8 int1[8] [[comment("vblank")]];
|
||||
u8 int2[8] [[comment("lcd stat")]];
|
||||
u8 int3[8] [[comment("timer")]];
|
||||
u8 int4[8] [[comment("serial")]];
|
||||
u8 int5[8] [[comment("joypad")]];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
u32 jmpInstruction;
|
||||
Logo logo;
|
||||
char title[0xF];
|
||||
CGB cgb;
|
||||
char newLicenseeCode[2] [[format("format::new_licensee_code")]];
|
||||
bool sgbFlag;
|
||||
u8 type [[format("format::rom_features")]];
|
||||
u8 romType [[format("format::rom_type")]];
|
||||
u8 ramType [[format("format::ram_type")]];
|
||||
bool japanOnly;
|
||||
u8 licenseeCode [[format("format::licensee_code")]];
|
||||
u8 version;
|
||||
u8 checksum [[comment("Checksum for: $134-$14C")]];
|
||||
u16 gloalChecksum [[comment("Checksum for entire range")]];
|
||||
};
|
||||
|
||||
struct Cartrige {
|
||||
JumpVectors jumpVectors [[comment("Instructions called on interupts or rst instructions")]];
|
||||
padding[0x100 - sizeof(JumpVectors)];
|
||||
Header header;
|
||||
};
|
||||
|
||||
|
||||
Cartrige cart @ 0x00;
|
||||
@@ -1,20 +1,25 @@
|
||||
#pragma description GIF image files
|
||||
|
||||
#pragma MIME image/gif
|
||||
|
||||
// Extension Labels
|
||||
#define LABEL_GC 0xF9
|
||||
#define LABEL_COMMENT 0xFE
|
||||
#define LABEL_APPLICATION 0xFF
|
||||
#define LABEL_PLAINTEXT 0x01
|
||||
#define LABEL_APPLICATION_NETSCAPE "NETSCAPE"
|
||||
#define CODE_FRAME 0x2C
|
||||
#define CODE_EXTENSION 0x21
|
||||
#define CODE_TRAILER 0x3B
|
||||
#define MAX_BLOCKS 4096
|
||||
#define GCT_ACCESS parent.parent.parent.parent.header.gct
|
||||
|
||||
// Indentifier Magics
|
||||
#define IMAGE_SEPERATOR_MAGIC 0x2C
|
||||
#define EXTENSION_INTRODUCER_MAGIC 0x21
|
||||
#define GIF_TRAILER_MAGIC 0x3B
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/core.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
#include <std/math.pat>
|
||||
|
||||
#pragma MIME image/gif
|
||||
#include <type/magic.pat>
|
||||
|
||||
bitfield GCT_Flags {
|
||||
size : 3 [[comment("physical size = 2^(flags.size + 1)")]];
|
||||
@@ -23,106 +28,114 @@ bitfield GCT_Flags {
|
||||
enabled : 1;
|
||||
};
|
||||
|
||||
bitfield LCT_Flags {
|
||||
size : 3 [[comment("physical size = 2^(flags.size + 1)")]];
|
||||
padding : 2;
|
||||
sort : 1 [[comment("Indicates if the table is sorted by importance")]];
|
||||
interlace : 1;
|
||||
enable : 1;
|
||||
bitfield ImageDescriptorFlags {
|
||||
lctSize: 3;
|
||||
reserved: 2;
|
||||
lctSort: 1;
|
||||
interlaceFlag: 1;
|
||||
lctEnable: 1;
|
||||
};
|
||||
|
||||
bitfield GC_Flags {
|
||||
bitfield GCE_Flags {
|
||||
transparent : 1;
|
||||
userInput : 1;
|
||||
disposalMode : 3 [[format("format::dispose_enum")]];
|
||||
reserved : 3;
|
||||
};
|
||||
|
||||
struct color {
|
||||
u8 r, g, b;
|
||||
} [[color(std::format("{:02X}{:02X}{:02X}", r, g, b))]];
|
||||
struct Color {
|
||||
u8 red;
|
||||
u8 green;
|
||||
u8 blue;
|
||||
} [[color(std::format("{:02X}{:02X}{:02X}", red, green, blue))]];
|
||||
|
||||
struct subblock {
|
||||
u8 size;
|
||||
if(size == 0) break;
|
||||
u8 data[size];
|
||||
struct _SubBlocks {
|
||||
u8 data_size;
|
||||
u8 data[data_size];
|
||||
};
|
||||
|
||||
struct block {
|
||||
subblock blocks[MAX_BLOCKS];
|
||||
};
|
||||
|
||||
fn exp2(auto n) {
|
||||
return 1 << n;
|
||||
struct DataSubBlocks {
|
||||
_SubBlocks subBlocks[while(std::mem::read_unsigned($, 1) != 0)];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char magic[3];
|
||||
type::Magic<"GIF"> magic;
|
||||
char version[3];
|
||||
};
|
||||
|
||||
struct LogicalScreenDescriptor {
|
||||
u16 width;
|
||||
u16 height;
|
||||
GCT_Flags gctFlags;
|
||||
u8 bgColorIndex;
|
||||
u8 pixelAscpet;
|
||||
if (gctFlags.enabled) {
|
||||
color gct[(exp2(gctFlags.size + 1))];
|
||||
color bgColor = gct[bgColorIndex];
|
||||
Color gct[std::math::pow(2, gctFlags.size + 1)];
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct frame {
|
||||
u16 x;
|
||||
u16 y;
|
||||
u16 width;
|
||||
u16 height;
|
||||
LCT_Flags lctFlags;
|
||||
if(lctFlags.enable) {
|
||||
color lct[(exp2(lctFlags.size + 1))];
|
||||
struct ImageDescriptor {
|
||||
u16 imageLeftPosition;
|
||||
u16 imageTopPosition;
|
||||
u16 imageWidth;
|
||||
u16 imageHeight;
|
||||
ImageDescriptorFlags flags;
|
||||
if(flags.lctEnable) {
|
||||
Color lct[std::math::pow(2, flags.lctSize + 1)];
|
||||
}
|
||||
u8 lzwMinCode [[comment("This byte determines the initial number of bits used for LZW codes in the image data")]];
|
||||
block lzwCompressedData [[comment("Data is pallet indecies either into current LDC or GCT and is compressed using LZW")]];
|
||||
DataSubBlocks lzwCompressedData [[comment("Data is pallet indecies either into current LDC or GCT and is compressed using LZW")]];
|
||||
};
|
||||
|
||||
struct comment {
|
||||
block data [[hidden]];
|
||||
char comment[] @ addressof(data.blocks) + 1; // TODO : need to find a better way of doing this
|
||||
struct CommentExtension {
|
||||
DataSubBlocks commentData;
|
||||
};
|
||||
|
||||
struct application {
|
||||
u8 blockSize [[hidden]];
|
||||
char identifier[8] [[comment("Only known are: NETSCAPE")]];
|
||||
char version[3] [[comment("Only known for NETSCAPE: '2.0'")]];
|
||||
block b [[hidden]];
|
||||
if(identifier == LABEL_APPLICATION_NETSCAPE) {
|
||||
u16 loopcount @ addressof(b.blocks[0].data) + 1 [[comment("0, = Forever")]];
|
||||
}
|
||||
struct ApplicationExtension {
|
||||
u8 blockSize;
|
||||
char identifier[8];
|
||||
char authenticationCode[3];
|
||||
DataSubBlocks applicationData;
|
||||
};
|
||||
|
||||
struct plaintext {
|
||||
u8 blockSize [[hidden]];
|
||||
u16 gridLeftPos;
|
||||
u16 gridTopPos;
|
||||
u16 gridWidth;
|
||||
u16 gridHeight;
|
||||
u8 cellWidth;
|
||||
u8 cellHeight;
|
||||
u8 textForegroundColorIndex [[hidden]];
|
||||
u8 textBackgroundColorIndex [[hidden]];
|
||||
color textForegroundColor @ addressof(GCT_ACCESS[textForegroundColorIndex]);
|
||||
color textBackgroundColor @ addressof(GCT_ACCESS[textBackgroundColorIndex]);
|
||||
block data [[hidden]];
|
||||
char text[] @ addressof(data.blocks) + 1;
|
||||
//char text[data.blocks[std::core::array_index()].size] @ addressof(data.blocks[std::core::array_index()].data);
|
||||
struct PlainTextExtension {
|
||||
u8 blockSize;
|
||||
u16 textGridLeftPos;
|
||||
u16 textGridTopPos;
|
||||
u16 textGridWidth;
|
||||
u16 textGridHeight;
|
||||
u8 charCellWidth;
|
||||
u8 charCellHeight;
|
||||
u8 textForegroundColorIndex;
|
||||
u8 textBackgroundColorIndex;
|
||||
DataSubBlocks plainTextData;
|
||||
|
||||
};
|
||||
|
||||
struct graphical_control {
|
||||
u8 blockSize [[hidden]];
|
||||
GC_Flags flags;
|
||||
struct GraphicControlExtension {
|
||||
u8 blockSize;
|
||||
std::assert_warn(blockSize == 4, "Unexpected GCE block size");
|
||||
GCE_Flags flags;
|
||||
u16 delay [[format("format::delay")]];
|
||||
u8 transparentColorIndex;
|
||||
block b [[hidden]];
|
||||
};
|
||||
|
||||
struct Extension {
|
||||
u8 label [[format("format::extension_name")]];
|
||||
if(label == LABEL_GC) GraphicControlExtension gce [[inline]];
|
||||
if(label == LABEL_COMMENT) CommentExtension c [[inline]];
|
||||
if(label == LABEL_APPLICATION) ApplicationExtension a [[inline]];
|
||||
if(label == LABEL_PLAINTEXT) PlainTextExtension p [[inline]];
|
||||
};
|
||||
|
||||
struct Block {
|
||||
u8 identifier [[format("format::identifier_name")]];
|
||||
if(identifier == IMAGE_SEPERATOR_MAGIC) ImageDescriptor i [[inline]];
|
||||
if(identifier == EXTENSION_INTRODUCER_MAGIC) Extension e [[inline]];
|
||||
if(identifier == GIF_TRAILER_MAGIC) break;
|
||||
u8 blockTerminator;
|
||||
} [[format("format::block_name")]];
|
||||
|
||||
namespace format {
|
||||
fn dispose_enum(u8 value) {
|
||||
if(value == 0x00) return "Do nothing";
|
||||
@@ -139,11 +152,18 @@ namespace format {
|
||||
return "Unknown Extension";
|
||||
};
|
||||
|
||||
fn content_name(ref frame f) {
|
||||
if(f.code == CODE_FRAME) return "Frame";
|
||||
if(f.code == CODE_EXTENSION) return "Extension";
|
||||
if(f.code == CODE_TRAILER) return "End";
|
||||
return "Unknown Content";
|
||||
fn block_name(ref Block b) {
|
||||
if(b.identifier == IMAGE_SEPERATOR_MAGIC) return "Image Descriptor";
|
||||
if(b.identifier == EXTENSION_INTRODUCER_MAGIC) return "Extension";
|
||||
if(b.identifier == GIF_TRAILER_MAGIC) return "Trailer";
|
||||
return "Unknown Block Type";
|
||||
};
|
||||
|
||||
fn identifier_name(u8 identifier) {
|
||||
if(identifier == IMAGE_SEPERATOR_MAGIC) return "Image Separator";
|
||||
if(identifier == EXTENSION_INTRODUCER_MAGIC) return "Extension Introducer";
|
||||
if(identifier == GIF_TRAILER_MAGIC) return "GIF Trailer";
|
||||
return "Unknown Identifier";
|
||||
};
|
||||
|
||||
fn delay(u16 delay) {
|
||||
@@ -154,28 +174,12 @@ namespace format {
|
||||
};
|
||||
}
|
||||
|
||||
struct extension {
|
||||
u8 label [[format("format::extension_name")]];
|
||||
if(label == LABEL_GC) graphical_control gc [[inline]];
|
||||
if(label == LABEL_COMMENT) comment c [[inline]];
|
||||
if(label == LABEL_APPLICATION) application a [[inline]];
|
||||
if(label == LABEL_PLAINTEXT) plaintext [[inline]];
|
||||
};
|
||||
|
||||
struct content {
|
||||
u8 code [[hidden]];
|
||||
if(code == CODE_FRAME) frame f [[inline]];
|
||||
if(code == CODE_EXTENSION) extension e [[inline]];
|
||||
if(code == CODE_TRAILER) break;
|
||||
} [[format("format::content_name")]];
|
||||
|
||||
struct Data {
|
||||
content contents[while(!std::mem::eof())] [[inline]];
|
||||
};
|
||||
|
||||
struct Gif {
|
||||
u8 data[std::mem::size()] [[no_unique_address, hidden]];
|
||||
Header header;
|
||||
Data data;
|
||||
};
|
||||
std::assert_warn(header.version == "89a" || header.version == "87a", "Unsupported format version");
|
||||
LogicalScreenDescriptor logicalScreenDescriptor;
|
||||
Block blocks[while(!std::mem::eof())];
|
||||
} [[hex::visualize("image", this.data)]];
|
||||
|
||||
Gif gif @ 0x00;
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description GZip compressed data format
|
||||
|
||||
#pragma MIME application/gzip
|
||||
|
||||
#include <type/time.pat>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Icon (.ico) or Cursor (.cur) files
|
||||
|
||||
#pragma endian little
|
||||
|
||||
#include <std/sys.pat>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description ID3 tags in MP3 files
|
||||
|
||||
#pragma MIME audio/mpeg
|
||||
|
||||
#include <std/mem.pat>
|
||||
@@ -24,10 +26,10 @@ namespace v2 {
|
||||
u8 bytes[4];
|
||||
} [[sealed, static, format("v2::ssi_value"), transform("v2::ssi_value")]];
|
||||
|
||||
fn ssi_value(ref SyncSafeInt n) {
|
||||
fn ssi_value(ref SyncSafeInt size) {
|
||||
u32 result = 0;
|
||||
for (u8 i = 0, i < 4, i = i + 1) {
|
||||
u8 byteval = n.bytes[i] & 0x7F;
|
||||
u8 byteval = size.bytes[i] & 0x7F;
|
||||
u8 shift = 7 * (4 - i - 1);
|
||||
result = result | (byteval << shift);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description [Intel hexadecimal object file format definition]("https://en.wikipedia.org/wiki/Intel_HEX")
|
||||
|
||||
/* If you have no delimiters between data records then remove
|
||||
* the null_bytes field in the data_packet struct.
|
||||
* Set the array at the bottom to the highest index + 1 in the Pattern Data view
|
||||
@@ -6,6 +8,8 @@
|
||||
*/
|
||||
#pragma endian big
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
enum FileType: u16 {
|
||||
Data = 0x3030,
|
||||
EOF = 0x3031,
|
||||
@@ -45,7 +49,9 @@ struct data_packet {
|
||||
}
|
||||
|
||||
u16 checksum [[color("0045F0DF")]];
|
||||
u16 null_bytes [[color("005E565A")]];
|
||||
u8 line_ending_1 [[color("005E565A")]];
|
||||
if (line_ending_1 == '\r')
|
||||
u8 line_ending_2 [[color("005E565A")]];
|
||||
};
|
||||
|
||||
data_packet data[1418] @ 0x00;
|
||||
data_packet data[while(!std::mem::eof())] @ 0x00;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Ethernet II Frames (IP Packets)
|
||||
|
||||
#pragma endian big
|
||||
|
||||
#include <std/sys.pat>
|
||||
|
||||
32
patterns/ips.hexpat
Normal file
32
patterns/ips.hexpat
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma description IPS (International Patching System) files
|
||||
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
|
||||
#pragma endian big
|
||||
|
||||
u8 eofOffset = 3;
|
||||
|
||||
struct Hunk {
|
||||
u24 offset;
|
||||
u16 length;
|
||||
if (length == 0) {
|
||||
u16 runCount;
|
||||
u8 payload;
|
||||
}
|
||||
else {
|
||||
u8 payload[length];
|
||||
}
|
||||
};
|
||||
|
||||
struct IPS {
|
||||
char signature[5];
|
||||
if (std::mem::read_string(std::mem::size()-3, 3) != "EOF") {
|
||||
eofOffset += 3;
|
||||
}
|
||||
Hunk hunks[while($ < std::mem::size()-eofOffset)];
|
||||
char eof[3];
|
||||
u24 truncatedSize[eofOffset>3];
|
||||
};
|
||||
|
||||
IPS ips @ 0x00;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description ISO 9660 file system
|
||||
|
||||
#pragma endian little
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,122 +1,125 @@
|
||||
#include <std/mem.pat>
|
||||
#pragma endian big
|
||||
|
||||
#pragma MIME image/jpeg
|
||||
|
||||
enum Marker : u8 {
|
||||
TEM = 0x01,
|
||||
SOF0 = 0xC0,
|
||||
SOF1 = 0xC1,
|
||||
SOF2 = 0xC2,
|
||||
SOF3 = 0xC3,
|
||||
DHT = 0xC4,
|
||||
SOF5 = 0xC5,
|
||||
SOF6 = 0xC6,
|
||||
SOF7 = 0xC7,
|
||||
SOI = 0xD8,
|
||||
EOI = 0xD9,
|
||||
SOS = 0xDA,
|
||||
DQT = 0xDB,
|
||||
DNL = 0xDC,
|
||||
DRI = 0xDD,
|
||||
DHP = 0xDE,
|
||||
APP0 = 0xE0,
|
||||
APP1 = 0xE1,
|
||||
APP2 = 0xE2,
|
||||
APP3 = 0xE3,
|
||||
APP4 = 0xE4,
|
||||
APP5 = 0xE5,
|
||||
APP6 = 0xE6,
|
||||
APP7 = 0xE7,
|
||||
APP8 = 0xE8,
|
||||
APP9 = 0xE9,
|
||||
APP10 = 0xEA,
|
||||
APP11 = 0xEB,
|
||||
APP12 = 0xEC,
|
||||
APP13 = 0xED,
|
||||
APP14 = 0xEE,
|
||||
APP15 = 0xEF,
|
||||
COM = 0xFE
|
||||
};
|
||||
|
||||
enum DensityUnit : u8 {
|
||||
NoUnit = 0x00,
|
||||
PixelsPerInch = 0x01,
|
||||
PixelsPerCm = 0x02
|
||||
};
|
||||
|
||||
struct Pixel {
|
||||
u8 r, g, b;
|
||||
} [[sealed, transform("transform_pixel")]];
|
||||
|
||||
fn transform_pixel(Pixel pixel) {
|
||||
return (0xFF << 24) | (pixel.b << 16) | (pixel.g << 8) | (pixel.r << 0);
|
||||
};
|
||||
|
||||
|
||||
struct APP0 {
|
||||
char magic[5];
|
||||
u8 versionMajor, versionMinor;
|
||||
DensityUnit densityUnit;
|
||||
u16 densityX, densityY;
|
||||
u8 thumbnailX, thumbnailY;
|
||||
Pixel thumbnail[thumbnailX * thumbnailY] [[sealed]];
|
||||
};
|
||||
|
||||
enum ComponentId : u8 {
|
||||
Y = 1,
|
||||
CB = 2,
|
||||
CR = 3,
|
||||
I = 4,
|
||||
Q = 5
|
||||
};
|
||||
|
||||
struct SOF0Component {
|
||||
ComponentId componentId;
|
||||
u8 samplingFactors;
|
||||
u8 quantizationTableId;
|
||||
};
|
||||
|
||||
struct SOF0 {
|
||||
u8 bitsPerSample;
|
||||
u16 imageHeight, imageWidth;
|
||||
u8 numComponents;
|
||||
SOF0Component components[numComponents];
|
||||
};
|
||||
|
||||
struct SOSComponent {
|
||||
ComponentId componentId;
|
||||
u8 huffmanTable;
|
||||
};
|
||||
|
||||
struct SOS {
|
||||
u8 numComponents;
|
||||
SOSComponent components[numComponents];
|
||||
u8 startSpectralSelection;
|
||||
u8 endSpectral;
|
||||
u8 apprBitPos;
|
||||
|
||||
u8 image_data[while(!std::mem::eof())] [[sealed]];
|
||||
};
|
||||
|
||||
struct Segment {
|
||||
u8 magic;
|
||||
Marker marker;
|
||||
|
||||
if (marker == Marker::SOI || marker == Marker::EOI) {
|
||||
|
||||
} else {
|
||||
u16 length;
|
||||
if (marker == Marker::APP0) {
|
||||
APP0 data;
|
||||
} else if (marker == Marker::SOF0) {
|
||||
SOF0 data;
|
||||
} else if (marker == Marker::SOS) {
|
||||
SOS data;
|
||||
} else {
|
||||
u8 data[length - sizeof(length)] [[sealed]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Segment segments[while(!std::mem::eof())] @ 0x00;
|
||||
#pragma author WerWolv
|
||||
#pragma description JPEG Image Format
|
||||
|
||||
#include <std/mem.pat>
|
||||
#pragma endian big
|
||||
|
||||
#pragma MIME image/jpeg
|
||||
|
||||
enum Marker : u8 {
|
||||
TEM = 0x01,
|
||||
SOF0 = 0xC0,
|
||||
SOF1 = 0xC1,
|
||||
SOF2 = 0xC2,
|
||||
SOF3 = 0xC3,
|
||||
DHT = 0xC4,
|
||||
SOF5 = 0xC5,
|
||||
SOF6 = 0xC6,
|
||||
SOF7 = 0xC7,
|
||||
SOI = 0xD8,
|
||||
EOI = 0xD9,
|
||||
SOS = 0xDA,
|
||||
DQT = 0xDB,
|
||||
DNL = 0xDC,
|
||||
DRI = 0xDD,
|
||||
DHP = 0xDE,
|
||||
APP0 = 0xE0,
|
||||
APP1 = 0xE1,
|
||||
APP2 = 0xE2,
|
||||
APP3 = 0xE3,
|
||||
APP4 = 0xE4,
|
||||
APP5 = 0xE5,
|
||||
APP6 = 0xE6,
|
||||
APP7 = 0xE7,
|
||||
APP8 = 0xE8,
|
||||
APP9 = 0xE9,
|
||||
APP10 = 0xEA,
|
||||
APP11 = 0xEB,
|
||||
APP12 = 0xEC,
|
||||
APP13 = 0xED,
|
||||
APP14 = 0xEE,
|
||||
APP15 = 0xEF,
|
||||
COM = 0xFE
|
||||
};
|
||||
|
||||
enum DensityUnit : u8 {
|
||||
NoUnit = 0x00,
|
||||
PixelsPerInch = 0x01,
|
||||
PixelsPerCm = 0x02
|
||||
};
|
||||
|
||||
struct Pixel {
|
||||
u8 r, g, b;
|
||||
} [[sealed, transform("transform_pixel")]];
|
||||
|
||||
fn transform_pixel(Pixel pixel) {
|
||||
return (0xFF << 24) | (pixel.b << 16) | (pixel.g << 8) | (pixel.r << 0);
|
||||
};
|
||||
|
||||
|
||||
struct APP0 {
|
||||
char magic[5];
|
||||
u8 versionMajor, versionMinor;
|
||||
DensityUnit densityUnit;
|
||||
u16 densityX, densityY;
|
||||
u8 thumbnailX, thumbnailY;
|
||||
Pixel thumbnail[thumbnailX * thumbnailY] [[sealed]];
|
||||
};
|
||||
|
||||
enum ComponentId : u8 {
|
||||
Y = 1,
|
||||
CB = 2,
|
||||
CR = 3,
|
||||
I = 4,
|
||||
Q = 5
|
||||
};
|
||||
|
||||
struct SOF0Component {
|
||||
ComponentId componentId;
|
||||
u8 samplingFactors;
|
||||
u8 quantizationTableId;
|
||||
};
|
||||
|
||||
struct SOF0 {
|
||||
u8 bitsPerSample;
|
||||
u16 imageHeight, imageWidth;
|
||||
u8 numComponents;
|
||||
SOF0Component components[numComponents];
|
||||
};
|
||||
|
||||
struct SOSComponent {
|
||||
ComponentId componentId;
|
||||
u8 huffmanTable;
|
||||
};
|
||||
|
||||
struct SOS {
|
||||
u8 numComponents;
|
||||
SOSComponent components[numComponents];
|
||||
u8 startSpectralSelection;
|
||||
u8 endSpectral;
|
||||
u8 apprBitPos;
|
||||
|
||||
u8 image_data[while(!std::mem::eof())] [[sealed]];
|
||||
};
|
||||
|
||||
struct Segment {
|
||||
u8 magic;
|
||||
Marker marker;
|
||||
|
||||
if (marker == Marker::SOI || marker == Marker::EOI) {
|
||||
|
||||
} else {
|
||||
u16 length;
|
||||
if (marker == Marker::APP0) {
|
||||
APP0 data;
|
||||
} else if (marker == Marker::SOF0) {
|
||||
SOF0 data;
|
||||
} else if (marker == Marker::SOS) {
|
||||
SOS data;
|
||||
} else {
|
||||
u8 data[length - sizeof(length)] [[sealed]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Segment segments[while(!std::mem::eof())] @ 0x00 [[hex::visualize("image", this)]];
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Windows Shell Link file format
|
||||
|
||||
#pragma MIME application/x-ms-shortcut
|
||||
|
||||
#include <std/core.pat>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Lua 5.4 bytecode
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
@@ -30,8 +32,8 @@ namespace impl {
|
||||
return std::format("\"{}\"", string.data);
|
||||
};
|
||||
|
||||
fn format_Constant(auto const) {
|
||||
return const.data;
|
||||
fn format_Constant(auto constant) {
|
||||
return constant.data;
|
||||
};
|
||||
|
||||
fn format_Version(auto ver) {
|
||||
@@ -132,4 +134,4 @@ struct LuaFile {
|
||||
LuaFunction func;
|
||||
};
|
||||
|
||||
LuaFile file @ 0;
|
||||
LuaFile file @ 0;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Mach-O executable
|
||||
|
||||
#pragma MIME application/x-mach-binary
|
||||
|
||||
#include <type/size.pat>
|
||||
@@ -8,6 +11,7 @@ enum Magic : u32 {
|
||||
};
|
||||
|
||||
enum CpuType : u32 {
|
||||
ANY = -1,
|
||||
VAX = 1,
|
||||
ROMP = 2,
|
||||
BS32032 = 4,
|
||||
@@ -17,14 +21,16 @@ enum CpuType : u32 {
|
||||
X86_64 = CpuType::I386 | 0x100'0000,
|
||||
MIPS = 8,
|
||||
NS32532 = 9,
|
||||
MC98000 = 10,
|
||||
HPPA = 11,
|
||||
ARM = 12,
|
||||
ARM64 = CpuType::ARM | 0x100'0000,
|
||||
ARM64_32 = CpuType::ARM | 0x200'0000,
|
||||
MC88000 = 13,
|
||||
SPARC = 14,
|
||||
I860 = be u32(15),
|
||||
I860_LITTLE = 16,
|
||||
RS6000 = 17,
|
||||
MC980000 = 18,
|
||||
POWERPC = 18,
|
||||
POWERPC64 = CpuType::POWERPC | 0x100'0000,
|
||||
VEO = 255
|
||||
|
||||
833
patterns/max_v104.hexpat
Normal file
833
patterns/max_v104.hexpat
Normal file
@@ -0,0 +1,833 @@
|
||||
#pragma description Mechanized Assault and Exploration v1.04 (strategy game) save file format
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
#pragma array_limit 12544
|
||||
#pragma pattern_limit 2000000
|
||||
#pragma eval_depth 32
|
||||
|
||||
enum FileType : u8
|
||||
{
|
||||
Custom,
|
||||
Tutorial,
|
||||
Campaign,
|
||||
Hot_seat,
|
||||
Multiplayer,
|
||||
Demo,
|
||||
Debug,
|
||||
Text,
|
||||
Scenario,
|
||||
Multi_scenario
|
||||
};
|
||||
|
||||
enum PlanetType : u8
|
||||
{
|
||||
Snowcrab,
|
||||
Frigia,
|
||||
Ice_Berg,
|
||||
The_Cooler,
|
||||
Ultima_Thule,
|
||||
Long_Floes,
|
||||
Iron_Cross,
|
||||
Splatterscape,
|
||||
Peak_a_boo,
|
||||
Valentines_Planet,
|
||||
Three_Rings,
|
||||
Great_divide,
|
||||
New_Luzon,
|
||||
Middle_Sea,
|
||||
High_Impact,
|
||||
Sanctuary,
|
||||
Islandia,
|
||||
Hammerhead,
|
||||
Freckles,
|
||||
Sandspit,
|
||||
Great_Circle,
|
||||
Long_Passage,
|
||||
Flash_Point,
|
||||
Bottleneck
|
||||
};
|
||||
|
||||
enum TeamType : u8
|
||||
{
|
||||
None = 0,
|
||||
Human = 1,
|
||||
Computer = 2,
|
||||
Remote = 3,
|
||||
Eliminated = 4
|
||||
};
|
||||
|
||||
enum TeamIndex : u8
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
Gray = 3
|
||||
};
|
||||
|
||||
enum TeamIndex16 : u16
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
Gray = 3
|
||||
};
|
||||
|
||||
enum PlayMode : u8
|
||||
{
|
||||
Turn_Based = 0,
|
||||
Simultaneous_Moves = 1
|
||||
};
|
||||
|
||||
enum TeamClan : u8
|
||||
{
|
||||
None = 0,
|
||||
The_Chosen = 1,
|
||||
Crimson_Path = 2,
|
||||
Von_Griffin = 3,
|
||||
Ayers_Hand = 4,
|
||||
Musashi = 5,
|
||||
Sacred_Eights = 6,
|
||||
Seven_Knights = 7,
|
||||
Axis_Inc = 8
|
||||
};
|
||||
|
||||
enum OpponentType : u8
|
||||
{
|
||||
Clueless = 0,
|
||||
Apprentice = 1,
|
||||
Average = 2,
|
||||
Expert = 3,
|
||||
Master = 4,
|
||||
God = 5
|
||||
};
|
||||
|
||||
enum VictoryType : u8
|
||||
{
|
||||
Duration = 0,
|
||||
Score = 1
|
||||
};
|
||||
|
||||
struct IniOptions
|
||||
{
|
||||
s32 world;
|
||||
s32 turn_timer;
|
||||
s32 endturn;
|
||||
s32 start_gold;
|
||||
s32 play_mode;
|
||||
s32 victory_type;
|
||||
s32 victory_limit;
|
||||
s32 opponent;
|
||||
s32 raw_resource;
|
||||
s32 fuel_resource;
|
||||
s32 gold_resource;
|
||||
s32 alien_derelicts;
|
||||
};
|
||||
|
||||
struct IniPreferences
|
||||
{
|
||||
s32 effects;
|
||||
s32 click_scroll;
|
||||
s32 quick_scroll;
|
||||
s32 fast_movement;
|
||||
s32 follow_unit;
|
||||
s32 auto_select;
|
||||
s32 enemy_halt;
|
||||
};
|
||||
|
||||
enum SurfaceType : u8
|
||||
{
|
||||
Land = 1,
|
||||
Water = 2,
|
||||
Coast = 4,
|
||||
Air = 8
|
||||
};
|
||||
|
||||
enum AiStrategy : u8
|
||||
{
|
||||
Random,
|
||||
Defensive,
|
||||
Missiles,
|
||||
Air,
|
||||
Sea,
|
||||
Scout_horde,
|
||||
Tank_horde,
|
||||
Fast_attack,
|
||||
Combined_arms,
|
||||
Espionage
|
||||
};
|
||||
|
||||
bitfield GridResourceMapEntry
|
||||
{
|
||||
padding : 2;
|
||||
team_visibility_gray : 1;
|
||||
team_visibility_blue : 1;
|
||||
team_visibility_green : 1;
|
||||
team_visibility_red : 1;
|
||||
padding : 2;
|
||||
cargo_amount : 5;
|
||||
cargo_type_fuel : 1;
|
||||
cargo_type_gold : 1;
|
||||
cargo_type_material : 1;
|
||||
};
|
||||
|
||||
bitfield UnitFlags
|
||||
{
|
||||
// MSB
|
||||
requires_slab: 1;
|
||||
turret_sprite: 1;
|
||||
sentry_unit: 1;
|
||||
spinning_turret: 1;
|
||||
padding: 4;
|
||||
|
||||
hovering: 1;
|
||||
has_firing_sprite: 1;
|
||||
fires_missiles: 1;
|
||||
constructor_unit: 1;
|
||||
padding: 1;
|
||||
electronic_unit: 1;
|
||||
selectable: 1;
|
||||
standalone: 1;
|
||||
|
||||
mobile_land_unit: 1;
|
||||
stationary: 1;
|
||||
padding: 4;
|
||||
upgradeable: 1;
|
||||
padding: 1;
|
||||
|
||||
// LSB
|
||||
ground_cover : 1;
|
||||
exploding: 1;
|
||||
animated: 1;
|
||||
connector_unit: 1;
|
||||
building: 1;
|
||||
missile_unit: 1;
|
||||
mobile_air_unit: 1;
|
||||
mobile_sea_unit: 1;
|
||||
};
|
||||
|
||||
struct Point
|
||||
{
|
||||
s16 x;
|
||||
s16 y;
|
||||
};
|
||||
|
||||
struct ResearchTopicInfo
|
||||
{
|
||||
u32 research_level;
|
||||
u32 turns_to_complete;
|
||||
s32 allocation;
|
||||
};
|
||||
|
||||
struct ScreenLocation
|
||||
{
|
||||
s8 x;
|
||||
s8 y;
|
||||
};
|
||||
|
||||
struct TeamInfo
|
||||
{
|
||||
Point markers[10];
|
||||
TeamType team_type;
|
||||
s8 field_41;
|
||||
TeamClan team_clan;
|
||||
ResearchTopicInfo research_topics[8];
|
||||
u32 victory_points;
|
||||
u16 next_unit_id;
|
||||
u8 unit_counters[93];
|
||||
ScreenLocation screen_location[6];
|
||||
u16 score_graph[50];
|
||||
u16 selected_unit;
|
||||
u16 zoom_level;
|
||||
Point screen_position;
|
||||
bool gui_button_state_range;
|
||||
bool gui_button_state_scan;
|
||||
bool gui_button_state_status;
|
||||
bool gui_button_state_colors;
|
||||
bool gui_button_state_hits;
|
||||
bool gui_button_state_ammo;
|
||||
bool gui_button_state_names;
|
||||
bool gui_button_state_minimap_2x;
|
||||
bool gui_button_state_minimap_tnt;
|
||||
bool gui_button_state_grid;
|
||||
bool gui_button_state_survey;
|
||||
u16 stats_factories_built;
|
||||
u16 stats_mines_built;
|
||||
u16 stats_buildings_built;
|
||||
u16 stats_units_built;
|
||||
u16 casualties[93];
|
||||
u16 stats_gold_spent_on_upgrades;
|
||||
};
|
||||
|
||||
struct UnitValues
|
||||
{
|
||||
u16 object_index;
|
||||
|
||||
if(CheckObjectId(object_index, true) == true)
|
||||
{
|
||||
u16 class_type;
|
||||
u16 turns;
|
||||
u16 hits;
|
||||
u16 armor;
|
||||
u16 attack;
|
||||
u16 speed;
|
||||
u16 range;
|
||||
u16 rounds;
|
||||
bool move_and_fire;
|
||||
u16 scan;
|
||||
u16 storage;
|
||||
u16 ammo;
|
||||
u16 attack_radius;
|
||||
u16 agent_adjust;
|
||||
u16 version;
|
||||
u8 units_built;
|
||||
}
|
||||
};
|
||||
|
||||
struct Complex
|
||||
{
|
||||
u16 object_index;
|
||||
|
||||
if(CheckObjectId(object_index, true) == true)
|
||||
{
|
||||
u16 class_type;
|
||||
s16 material;
|
||||
s16 fuel;
|
||||
s16 gold;
|
||||
s16 power;
|
||||
s16 workers;
|
||||
s16 buildings;
|
||||
s16 id;
|
||||
}
|
||||
};
|
||||
|
||||
struct TeamUnits
|
||||
{
|
||||
s16 gold;
|
||||
UnitValues base_unit_values[93];
|
||||
UnitValues current_unit_values[93];
|
||||
u16 complex_count;
|
||||
Complex complexes[complex_count];
|
||||
};
|
||||
|
||||
enum UnitType : u16
|
||||
{
|
||||
UNIT_TYPE_GOLD_REFINERY = 0,
|
||||
UNIT_TYPE_POWER_STATION = 1,
|
||||
UNIT_TYPE_POWER_GENERATOR = 2,
|
||||
UNIT_TYPE_BARRACKS = 3,
|
||||
UNIT_TYPE_ALIEN_BUILDING_1 = 4,
|
||||
UNIT_TYPE_RADAR = 5,
|
||||
UNIT_TYPE_STORAGE_UNIT = 6,
|
||||
UNIT_TYPE_FUEL_TANK = 7,
|
||||
UNIT_TYPE_GOLD_VAULT = 8,
|
||||
UNIT_TYPE_DEPOT = 9,
|
||||
UNIT_TYPE_HANGAR = 10,
|
||||
UNIT_TYPE_DOCK = 11,
|
||||
UNIT_TYPE_CONNECTOR = 12,
|
||||
UNIT_TYPE_LARGE_RUBBLE_1 = 13,
|
||||
UNIT_TYPE_SMALL_RUBBLE_1 = 14,
|
||||
UNIT_TYPE_LARGE_TAPE = 15,
|
||||
UNIT_TYPE_SMALL_TAPE = 16,
|
||||
UNIT_TYPE_LARGE_SLAB = 17,
|
||||
UNIT_TYPE_SMALL_SLAB = 18,
|
||||
UNIT_TYPE_LARGE_CONES = 19,
|
||||
UNIT_TYPE_SMALL_CONES = 20,
|
||||
UNIT_TYPE_ROAD = 21,
|
||||
UNIT_TYPE_LANDING_PAD = 22,
|
||||
UNIT_TYPE_SHIPYARD = 23,
|
||||
UNIT_TYPE_LIGHT_VEHICLE_PLANT = 24,
|
||||
UNIT_TYPE_HEAVY_VEHICLE_PLANT = 25,
|
||||
UNIT_TYPE_ALIEN_BUILDING_2 = 26,
|
||||
UNIT_TYPE_AIR_UNITS_PLANT = 27,
|
||||
UNIT_TYPE_HABITAT = 28,
|
||||
UNIT_TYPE_RESEARCH_CENTER = 29,
|
||||
UNIT_TYPE_ECOSPHERE = 30,
|
||||
UNIT_TYPE_ALIEN_BUILDING_3 = 31,
|
||||
UNIT_TYPE_TRAINING_HALL = 32,
|
||||
UNIT_TYPE_WATER_PLATFORM = 33,
|
||||
UNIT_TYPE_GUN_TURRET = 34,
|
||||
UNIT_TYPE_ANTI_AIRCRAFT = 35,
|
||||
UNIT_TYPE_ARTILLERY = 36,
|
||||
UNIT_TYPE_MISSILE_LAUNCHER = 37,
|
||||
UNIT_TYPE_CONCRETE_BLOCK = 38,
|
||||
UNIT_TYPE_BRIDGE = 39,
|
||||
UNIT_TYPE_MINING_STATION = 40,
|
||||
UNIT_TYPE_LAND_MINE = 41,
|
||||
UNIT_TYPE_SEA_MINE = 42,
|
||||
UNIT_TYPE_LAND_EXPLOSION = 43,
|
||||
UNIT_TYPE_AIR_EXPLOSION = 44,
|
||||
UNIT_TYPE_SEA_EXPLOSION = 45,
|
||||
UNIT_TYPE_BUILDING_EXPLOSION = 46,
|
||||
UNIT_TYPE_HIT_EXPLOSION = 47,
|
||||
UNIT_TYPE_MASTER_BUILDER = 48,
|
||||
UNIT_TYPE_CONSTRUCTOR = 49,
|
||||
UNIT_TYPE_SCOUT = 50,
|
||||
UNIT_TYPE_TANK = 51,
|
||||
UNIT_TYPE_ASSAULT_GUN = 52,
|
||||
UNIT_TYPE_ROCKET_LAUNCHER = 53,
|
||||
UNIT_TYPE_MISSILE_CRAWLER = 54,
|
||||
UNIT_TYPE_MOBILE_ANTI_AIRCRAFT = 55,
|
||||
UNIT_TYPE_MINE_LAYER = 56,
|
||||
UNIT_TYPE_SURVEYOR = 57,
|
||||
UNIT_TYPE_SCANNER = 58,
|
||||
UNIT_TYPE_SUPPLY_TRUCK = 59,
|
||||
UNIT_TYPE_GOLD_TRUCK = 60,
|
||||
UNIT_TYPE_ENGINEER = 61,
|
||||
UNIT_TYPE_BULLDOZER = 62,
|
||||
UNIT_TYPE_REPAIR_UNIT = 63,
|
||||
UNIT_TYPE_FUEL_TRUCK = 64,
|
||||
UNIT_TYPE_PERSONNEL_CARRIER = 65,
|
||||
UNIT_TYPE_INFILTRATOR = 66,
|
||||
UNIT_TYPE_INFANTRY = 67,
|
||||
UNIT_TYPE_ESCORT = 68,
|
||||
UNIT_TYPE_CORVETTE = 69,
|
||||
UNIT_TYPE_GUNBOAT = 70,
|
||||
UNIT_TYPE_SUBMARINE = 71,
|
||||
UNIT_TYPE_SEA_TRANSPORT = 72,
|
||||
UNIT_TYPE_MISSILE_CRUISER = 73,
|
||||
UNIT_TYPE_SEA_MINE_LAYER = 74,
|
||||
UNIT_TYPE_CARGO_SHIP = 75,
|
||||
UNIT_TYPE_FIGHTER = 76,
|
||||
UNIT_TYPE_GROUND_ATTACK_PLANE = 77,
|
||||
UNIT_TYPE_AIR_TRANSPORT = 78,
|
||||
UNIT_TYPE_AWAC = 79,
|
||||
UNIT_TYPE_ALIEN_GUNBOAT = 80,
|
||||
UNIT_TYPE_ALIEN_TANK = 81,
|
||||
UNIT_TYPE_ALIEN_ASSAULT_GUN = 82,
|
||||
UNIT_TYPE_ALIEN_ATTACK_PLANE = 83,
|
||||
UNIT_TYPE_MISSILE = 84,
|
||||
UNIT_TYPE_TORPEDO = 85,
|
||||
UNIT_TYPE_ALIEN_MISSILE = 86,
|
||||
UNIT_TYPE_TANK_PLASMA_BALL = 87,
|
||||
UNIT_TYPE_ARTILLERY_PLASMA_BALL = 88,
|
||||
UNIT_TYPE_SMOKE_TRAIL = 89,
|
||||
UNIT_TYPE_BUBBLE_TRAIL = 90,
|
||||
UNIT_TYPE_HARVESTER = 91,
|
||||
UNIT_TYPE_DEAD_WALDO = 92
|
||||
};
|
||||
|
||||
enum OrderType : u8
|
||||
{
|
||||
ORDER_TYPE_AWAITING = 0x0,
|
||||
ORDER_TYPE_TRANSFORMING = 0x1,
|
||||
ORDER_TYPE_MOVING = 0x2,
|
||||
ORDER_TYPE_FIRING = 0x3,
|
||||
ORDER_TYPE_ORDER_BUILDING = 0x4,
|
||||
ORDER_TYPE_ACTIVATE_ORDER = 0x5,
|
||||
ORDER_TYPE_NEW_ALLOCATE_ORDER = 0x6,
|
||||
ORDER_TYPE_POWER_ON = 0x7,
|
||||
ORDER_TYPE_POWER_OFF = 0x8,
|
||||
ORDER_TYPE_EXPLODING = 0x9,
|
||||
ORDER_TYPE_UNLOADING = 0xA,
|
||||
ORDER_TYPE_CLEARING = 0xB,
|
||||
ORDER_TYPE_SENTRY = 0xC,
|
||||
ORDER_TYPE_LANDING = 0xD,
|
||||
ORDER_TYPE_TAKING_OFF = 0xE,
|
||||
ORDER_TYPE_LOADING = 0xF,
|
||||
ORDER_TYPE_IDLE = 0x10,
|
||||
ORDER_TYPE_REPAIRING = 0x11,
|
||||
ORDER_TYPE_REFUELING = 0x12,
|
||||
ORDER_TYPE_RELOADING = 0x13,
|
||||
ORDER_TYPE_TRANSFERRING = 0x14,
|
||||
ORDER_TYPE_AWAITING_21 = 0x15,
|
||||
ORDER_TYPE_AWAITING_22 = 0x16,
|
||||
ORDER_TYPE_AWAITING_23 = 0x17,
|
||||
ORDER_TYPE_AWAITING_24 = 0x18,
|
||||
ORDER_TYPE_AWAITING_25 = 0x19,
|
||||
ORDER_TYPE_DISABLED = 0x1A,
|
||||
ORDER_TYPE_MOVING_27 = 0x1B,
|
||||
ORDER_TYPE_REPAIRING_28 = 0x1C,
|
||||
ORDER_TYPE_TRANSFERRING_29 = 0x1D,
|
||||
ORDER_TYPE_ATTACKING = 0x1E,
|
||||
ORDER_TYPE_BUILDING_HALTED = 0x1F
|
||||
};
|
||||
|
||||
struct Rect
|
||||
{
|
||||
s32 ulx;
|
||||
s32 uly;
|
||||
s32 lrx;
|
||||
s32 lry;
|
||||
};
|
||||
|
||||
struct PathStep
|
||||
{
|
||||
s8 x;
|
||||
s8 y;
|
||||
};
|
||||
|
||||
struct Path
|
||||
{
|
||||
u16 object_index;
|
||||
|
||||
if(CheckObjectId(object_index, true) == true)
|
||||
{
|
||||
u16 class_type;
|
||||
|
||||
// Air path
|
||||
if (class_type == 1)
|
||||
{
|
||||
s16 length;
|
||||
u8 angle;
|
||||
Point pixel_start;
|
||||
Point pixel_end;
|
||||
s32 x_step;
|
||||
s32 y_step;
|
||||
s32 delta_x;
|
||||
s32 delta_y;
|
||||
}
|
||||
// Ground path
|
||||
else if (class_type == 4)
|
||||
{
|
||||
Point pixel_end;
|
||||
s16 index;
|
||||
s16 steps_count;
|
||||
PathStep steps[steps_count];
|
||||
}
|
||||
// Builder path
|
||||
else if (class_type == 2)
|
||||
{
|
||||
Point coordinate;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::assert(0, "Unknown path class");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct UnitTypeArray
|
||||
{
|
||||
u16 object_count;
|
||||
|
||||
UnitType array[object_count];
|
||||
};
|
||||
|
||||
struct UnitInfo
|
||||
{
|
||||
u16 object_index;
|
||||
|
||||
if(CheckObjectId(object_index, true) == true)
|
||||
{
|
||||
u16 class_type;
|
||||
UnitType unit_type;
|
||||
|
||||
if (unit_type == UnitType::UNIT_TYPE_DEAD_WALDO)
|
||||
{
|
||||
std::print("Found Waldo!");
|
||||
}
|
||||
|
||||
u16 hash_id;
|
||||
UnitFlags flags;
|
||||
Point pixel_position;
|
||||
Point grid_position;
|
||||
u16 name_length;
|
||||
s8 name[name_length];
|
||||
Point shadow_offset;
|
||||
TeamIndex team;
|
||||
u8 name_index;
|
||||
u8 brightness;
|
||||
u8 angle;
|
||||
u8 visible_to_team[5];
|
||||
u8 spotted_by_team[5];
|
||||
u8 max_velocity;
|
||||
u8 velocity;
|
||||
u8 sound;
|
||||
u8 scaler_adjust;
|
||||
Rect sprite_bounds;
|
||||
Rect shadow_bounds;
|
||||
u8 turret_angle;
|
||||
s8 turret_offset_x;
|
||||
s8 turret_offset_y;
|
||||
u16 total_images;
|
||||
u16 image_base;
|
||||
u16 turret_image_base;
|
||||
u16 firing_image_base;
|
||||
u16 connector_image_base;
|
||||
u16 image_index;
|
||||
u16 turret_image_index;
|
||||
u16 image_index_max;
|
||||
OrderType orders;
|
||||
u8 state;
|
||||
OrderType prior_orders;
|
||||
u8 prior_state;
|
||||
u8 laying_state;
|
||||
Point target_grid;
|
||||
u8 build_time;
|
||||
u8 total_mining;
|
||||
u8 raw_mining;
|
||||
u8 fuel_mining;
|
||||
u8 gold_mining;
|
||||
u8 raw_mining_max;
|
||||
u8 gold_mining_max;
|
||||
u8 fuel_mining_max;
|
||||
u8 hits;
|
||||
u8 speed;
|
||||
u8 shots;
|
||||
u8 move_and_fire;
|
||||
u16 storage;
|
||||
u8 ammo;
|
||||
u8 targeting_mode;
|
||||
u8 enter_mode;
|
||||
u8 cursor;
|
||||
u8 recoil_delay;
|
||||
u8 delayed_reaction;
|
||||
u8 damaged_this_turn;
|
||||
u8 research_topic;
|
||||
u8 moved;
|
||||
u8 bobbed;
|
||||
u8 shake_effect_state;
|
||||
u8 engine;
|
||||
u8 weapon;
|
||||
u8 comm;
|
||||
u8 fuel_distance;
|
||||
u8 move_fraction;
|
||||
u8 energized;
|
||||
u8 repeat_build;
|
||||
u16 build_rate;
|
||||
u8 disabled_reaction_fire;
|
||||
u8 auto_survey;
|
||||
u32 field_221;
|
||||
Path path;
|
||||
u16 connectors;
|
||||
UnitValues base_values;
|
||||
Complex complex;
|
||||
UnitInfo parent_unit;
|
||||
UnitInfo enemy_unit;
|
||||
UnitTypeArray build_list;
|
||||
}
|
||||
};
|
||||
|
||||
struct UnitInfoList
|
||||
{
|
||||
u16 unitinfo_count;
|
||||
UnitInfo units[unitinfo_count];
|
||||
};
|
||||
|
||||
struct HashMapUnitInfo
|
||||
{
|
||||
u16 hash_size;
|
||||
UnitInfoList map[hash_size];
|
||||
};
|
||||
|
||||
struct MapHash
|
||||
{
|
||||
Point coordinates;
|
||||
UnitInfoList units;
|
||||
};
|
||||
|
||||
struct MapHashList
|
||||
{
|
||||
u16 maphash_count;
|
||||
MapHash objects[maphash_count];
|
||||
};
|
||||
|
||||
struct HashMapMapHash
|
||||
{
|
||||
u16 hash_size;
|
||||
s16 x_shift;
|
||||
MapHashList map[hash_size];
|
||||
};
|
||||
|
||||
struct TeamHeatMaps
|
||||
{
|
||||
u8 heatmap_complete[12544];
|
||||
u8 heatmap_stealth_sea[12544];
|
||||
u8 heatmap_stealth_land[12544];
|
||||
};
|
||||
|
||||
struct MessageLog
|
||||
{
|
||||
s16 length;
|
||||
char text[length];
|
||||
UnitInfo unit;
|
||||
Point coordinates;
|
||||
bool is_alert_message;
|
||||
u16 resource_id;
|
||||
};
|
||||
|
||||
struct MessageLogList
|
||||
{
|
||||
u16 message_log_count;
|
||||
MessageLog entires[message_log_count];
|
||||
};
|
||||
|
||||
struct AiMap
|
||||
{
|
||||
UnitInfo unit;
|
||||
TeamIndex16 team;
|
||||
bool visible_to_team;
|
||||
Point point;
|
||||
};
|
||||
|
||||
struct AiMapList
|
||||
{
|
||||
u16 ai_map_count;
|
||||
AiMap objects[ai_map_count];
|
||||
};
|
||||
|
||||
struct AiPlayer
|
||||
{
|
||||
TeamIndex16 team;
|
||||
AiStrategy strategy;
|
||||
s16 field_3;
|
||||
s16 field_5;
|
||||
s16 field_7;
|
||||
TeamIndex16 target_team;
|
||||
AiMapList map_list;
|
||||
u16 has_info_map;
|
||||
|
||||
if (has_info_map)
|
||||
{
|
||||
u8 info_map[12544];
|
||||
}
|
||||
|
||||
u16 has_mine_map;
|
||||
|
||||
if (has_mine_map)
|
||||
{
|
||||
u8 mine_map[12544];
|
||||
}
|
||||
|
||||
Point target_location;
|
||||
};
|
||||
|
||||
u16 last_object_index;
|
||||
bool context;
|
||||
|
||||
fn Init()
|
||||
{
|
||||
context = false;
|
||||
last_object_index = 0;
|
||||
};
|
||||
|
||||
fn CheckObjectId(u16 index, bool caller)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// ImHex bug workaround
|
||||
if (context) { context = false; return result; }
|
||||
|
||||
// null object?
|
||||
if (index == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// already serialized object?
|
||||
if (last_object_index < index)
|
||||
{
|
||||
last_object_index = index;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
struct SaveFile
|
||||
{
|
||||
Init();
|
||||
|
||||
s16 version;
|
||||
FileType save_file_type;
|
||||
char save_game_name[30];
|
||||
PlanetType planet;
|
||||
s16 mission_index;
|
||||
char team_name_red[30];
|
||||
char team_name_green[30];
|
||||
char team_name_blue[30];
|
||||
char team_name_gray[30];
|
||||
TeamType team_type_red;
|
||||
TeamType team_type_green;
|
||||
TeamType team_type_blue;
|
||||
TeamType team_type_gray;
|
||||
TeamType team_type_alien;
|
||||
TeamClan team_clan_red;
|
||||
TeamClan team_clan_green;
|
||||
TeamClan team_clan_blue;
|
||||
TeamClan team_clan_gray;
|
||||
TeamClan team_clan_alien;
|
||||
u32 rng_seed;
|
||||
OpponentType opponent;
|
||||
s16 turn_timer;
|
||||
s16 endturn;
|
||||
PlayMode play_mode;
|
||||
IniOptions options;
|
||||
SurfaceType surface_map[12544];
|
||||
GridResourceMapEntry GridResourceMap[12544];
|
||||
TeamInfo team_info_red;
|
||||
TeamInfo team_info_green;
|
||||
TeamInfo team_info_blue;
|
||||
TeamInfo team_info_gray;
|
||||
TeamIndex active_turn_team;
|
||||
TeamIndex player_team;
|
||||
s32 turn_counter;
|
||||
s16 game_state;
|
||||
u16 turn_timer_;
|
||||
IniPreferences preferences;
|
||||
TeamUnits team_units_red;
|
||||
TeamUnits team_units_green;
|
||||
TeamUnits team_units_blue;
|
||||
TeamUnits team_units_gray;
|
||||
UnitInfoList unit_info_list_ground_cover_units;
|
||||
UnitInfoList unit_info_list_mobile_land_sea_units;
|
||||
UnitInfoList unit_info_list_stationary_units;
|
||||
UnitInfoList unit_info_list_mobile_air_units;
|
||||
UnitInfoList unit_info_list_particles;
|
||||
HashMapUnitInfo hash_map_unit_info;
|
||||
HashMapMapHash hash_map_map_hash;
|
||||
|
||||
if (team_type_red != TeamType::None)
|
||||
{
|
||||
TeamHeatMaps heat_maps_red;
|
||||
}
|
||||
|
||||
if (team_type_green != TeamType::None)
|
||||
{
|
||||
TeamHeatMaps heat_maps_green;
|
||||
}
|
||||
|
||||
if (team_type_blue != TeamType::None)
|
||||
{
|
||||
TeamHeatMaps heat_maps_blue;
|
||||
}
|
||||
|
||||
if (team_type_gray != TeamType::None)
|
||||
{
|
||||
TeamHeatMaps heat_maps_gray;
|
||||
}
|
||||
|
||||
MessageLogList message_log_red;
|
||||
MessageLogList message_log_green;
|
||||
MessageLogList message_log_blue;
|
||||
MessageLogList message_log_gray;
|
||||
|
||||
if (team_type_red == TeamType::Computer)
|
||||
{
|
||||
AiPlayer ai_player_red;
|
||||
}
|
||||
|
||||
if (team_type_green == TeamType::Computer)
|
||||
{
|
||||
AiPlayer ai_player_green;
|
||||
}
|
||||
|
||||
if (team_type_blue == TeamType::Computer)
|
||||
{
|
||||
AiPlayer ai_player_blue;
|
||||
}
|
||||
|
||||
if (team_type_gray == TeamType::Computer)
|
||||
{
|
||||
AiPlayer ai_player_gray;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
SaveFile save @ 0x0;
|
||||
|
||||
std::assert($ == std::mem::size(), "Extra data found after parsed data");
|
||||
|
||||
|
||||
@@ -1,72 +1,280 @@
|
||||
#pragma description MIDI header, event fields provided
|
||||
|
||||
#include <std/core.pat>
|
||||
|
||||
#pragma MIME audio/midi
|
||||
#pragma endian big
|
||||
|
||||
using Delta = u8;
|
||||
using NoteValue = u8;
|
||||
using Velocity = u8;
|
||||
using EOF = u8;
|
||||
|
||||
// this is just for debugging midi file generation
|
||||
// I'm testing a known good file against a bad one
|
||||
// the file is hard coded in file format 0, and if
|
||||
// you're expecting meta events anywhere add a specific
|
||||
// call for those
|
||||
// Only supports format 0
|
||||
// https://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html
|
||||
|
||||
enum NoteEvent : u8 {
|
||||
NoteOn = 0x90,
|
||||
NoteOff = 0x80
|
||||
bool g_has_more_messages = true;
|
||||
bool g_has_more_tracks = true;
|
||||
|
||||
fn signed14(s16 n) {
|
||||
// Converts to 14-bit in range 0..16383. Note that MIDI data bytes
|
||||
// have their first (most significant) bit clear (0), thus each byte
|
||||
// is in range 0..127
|
||||
n = ((n & 0x7f) << 7) | ((n >> 8) & 0x7f);
|
||||
if (n >= 0) {
|
||||
n -= 0x2000;
|
||||
}
|
||||
return n;
|
||||
};
|
||||
|
||||
enum MetaFlag : u16 {
|
||||
Footer = 0xFF2F,
|
||||
KeySigEvent = 0xFF59,
|
||||
TimeSigEvent = 0xFF58,
|
||||
TempoEvent = 0xFF51,
|
||||
TrackNameEvent = 0xFF03
|
||||
fn u32ify(u32 vlq) {
|
||||
// Converts from variable-length quantity to u32. These numbers are
|
||||
// represented 7 bits per byte, most significant bits first. All bytes
|
||||
// except the last have bit 7 set, and the last byte has bit 7 clear.
|
||||
// If the number is in range 0..127, it is thus represented exactly
|
||||
// as one byte.
|
||||
u32 n = vlq & 0x7f;
|
||||
if (vlq & 0x8000 == 0x8000) {
|
||||
n += ((vlq & 0x7f00) >> 8) * 0x80;
|
||||
}
|
||||
if (vlq & 0x800000 == 0x800000) {
|
||||
n += ((vlq & 0x7f0000) >> 8 * 2) * 0x80 * 0x80;
|
||||
}
|
||||
if (vlq & 0x80000000 == 0x80000000) {
|
||||
n += ((vlq & 0x7f000000) >> 8 * 3) * 0x80 * 0x80 * 0x80;
|
||||
}
|
||||
return n;
|
||||
};
|
||||
|
||||
enum Status : u8 {
|
||||
NoteOff = 0x80 ... 0x8F,
|
||||
NoteOn = 0x90 ... 0x9F,
|
||||
PolyphonicAfterTouch = 0xA0 ... 0xAF,
|
||||
ControlChange = 0xB0 ... 0xBF,
|
||||
ProgramChange = 0xC0 ... 0xCF,
|
||||
ChannelAfterTouch = 0xD0 ... 0xDF,
|
||||
PitchWheel = 0xE0 ... 0xEF,
|
||||
SysEx = 0xF0,
|
||||
TimeCodeQtrFrame = 0xF1,
|
||||
SongPositionPointer = 0xF2,
|
||||
SongSelect = 0xF3,
|
||||
Undefined = 0xF4 ... 0xF5,
|
||||
TuneRequest = 0xF6,
|
||||
EndOfSysEx = 0xF7,
|
||||
TimingClock = 0xF8,
|
||||
Undefined = 0xF9,
|
||||
Start = 0xFA,
|
||||
Continue = 0xFB,
|
||||
Stop = 0xFC,
|
||||
Undefined = 0xFD,
|
||||
ActiveSensing = 0xFE,
|
||||
MetaEvent = 0xFF,
|
||||
};
|
||||
|
||||
Status g_next_status;
|
||||
|
||||
enum MetaType : u8 {
|
||||
SequenceNumber = 0x00,
|
||||
Text = 0x01,
|
||||
CopyrightNotice = 0x02,
|
||||
TrackName = 0x03,
|
||||
InstrumentName = 0x04,
|
||||
Lyric = 0x05,
|
||||
Marker = 0x06,
|
||||
CuePoint = 0x07,
|
||||
ChannelPrefix = 0x20,
|
||||
EndOfTrack = 0x2F,
|
||||
SetTempo = 0x51,
|
||||
SMPTEOffset = 0x54,
|
||||
TimeSignature = 0x58,
|
||||
KeySignature = 0x59,
|
||||
SequencerSpecific = 0x7F
|
||||
};
|
||||
|
||||
enum ControlChangeType : u8 {
|
||||
Bank_Select_MSB = 0,
|
||||
Modulation_Wheel_MSB = 1,
|
||||
Breath_Controller_MSB = 2,
|
||||
Undefined_MSB = 3,
|
||||
Foot_Pedal_MSB = 4,
|
||||
Portamento_Time_MSB = 5,
|
||||
Data_Entry_MSB = 6,
|
||||
Volume_MSB = 7,
|
||||
Balance_MSB = 8,
|
||||
Undefined_MSB = 9,
|
||||
Pan_MSB = 10,
|
||||
Expression_MSB = 11,
|
||||
Effect_Controller_1_MSB = 12,
|
||||
Effect_Controller_2_MSB = 13,
|
||||
Undefined_MSB = 14,
|
||||
Undefined_MSB = 15,
|
||||
General_Purpose_MSB = 16 ... 19,
|
||||
Undefined_MSB = 20 ... 31,
|
||||
Bank_Select_LSB = 32,
|
||||
Modulation_Wheel_LSB = 33,
|
||||
Breath_Controller_LSB = 34,
|
||||
Undefined_LSB = 35,
|
||||
Foot_Pedal_LSB = 36,
|
||||
Portamento_Time_LSB = 37,
|
||||
Data_Entry_LSB = 38,
|
||||
Volume_LSB = 39,
|
||||
Balance_LSB = 40,
|
||||
Undefined_LSB = 41,
|
||||
Pan_LSB = 42,
|
||||
Expression_LSB = 43,
|
||||
Effect_Controller_1_LSB = 44,
|
||||
Effect_Controller_2_LSB = 45,
|
||||
Undefined_LSB = 46,
|
||||
Undefined_LSB = 47,
|
||||
General_Purpose_LSB = 48 ... 51,
|
||||
Undefined_LSB = 52 ... 63,
|
||||
Damper_Pedal = 64,
|
||||
Portamento = 65,
|
||||
Sostenuto_Pedal = 66,
|
||||
Soft_Pedal = 67,
|
||||
Legato_FootSwitch = 68,
|
||||
Hold_2 = 69,
|
||||
Sound_Controller_1 = 70,
|
||||
Sound_Controller_2 = 71,
|
||||
Sound_Controller_3 = 72,
|
||||
Sound_Controller_4 = 73,
|
||||
Sound_Controller_6 = 75,
|
||||
Sound_Controller_7 = 76,
|
||||
Sound_Controller_8 = 77,
|
||||
Sound_Controller_9 = 78,
|
||||
Sound_Controller_10 = 79,
|
||||
General_Purpose_CC_Control = 80 ... 83,
|
||||
Portamento_CC_Control = 84,
|
||||
Undefined = 85 ... 87,
|
||||
High_Resolution_Velocity_Prefix = 88,
|
||||
Effect_2_Depth = 92,
|
||||
Effect_3_Depth = 93,
|
||||
Effect_4_Depth = 94,
|
||||
Effect_5_Depth = 95,
|
||||
Data_Increment = 96,
|
||||
Data_Decrement = 97,
|
||||
Non_Registered_Parameter_Number_LSB = 98,
|
||||
Non_Registered_Parameter_Number_MSB = 99,
|
||||
Registered_Parameter_Number_LSB = 100,
|
||||
Registered_Parameter_Number_MSB = 101,
|
||||
Undefined = 102 ... 119,
|
||||
All_Sound_Off = 120,
|
||||
Reset_All_Controllers = 121,
|
||||
Local_Switch = 122,
|
||||
All_Notes_Off = 123,
|
||||
Omni_Mode_Off = 124,
|
||||
Omni_Mode_On = 125,
|
||||
Mono_Mode = 126,
|
||||
Poly_Mode = 127,
|
||||
};
|
||||
|
||||
enum HeaderFlag : u32 {
|
||||
MThd = 0x4D546864
|
||||
};
|
||||
|
||||
enum TrackChunk : u32 {
|
||||
enum TrackFlag : u32 {
|
||||
MTrk = 0x4D54726B
|
||||
};
|
||||
|
||||
struct TimeSigEvent {
|
||||
Delta delta;
|
||||
MetaFlag flag;
|
||||
u16 numerator;
|
||||
u8 denominator;
|
||||
u8 ticks_per_click; // not used
|
||||
u8 thirty_second_notes_per_crotchet;
|
||||
struct VariableLengthQuantity<auto name> {
|
||||
if (std::mem::read_unsigned($, 1) & 0x80 == 0x80) {
|
||||
if (std::mem::read_unsigned($ + 1, 1) & 0x80 == 0x80) {
|
||||
if (std::mem::read_unsigned($ + 2, 1) & 0x80 == 0x80) {
|
||||
u32 value [[format("u32ify"), name(name)]];
|
||||
} else {
|
||||
u24 value [[format("u32ify"), name(name)]];
|
||||
}
|
||||
} else {
|
||||
u16 value [[format("u32ify"), name(name)]];
|
||||
}
|
||||
} else {
|
||||
u8 value [[format("u32ify"), name(name)]];
|
||||
}
|
||||
};
|
||||
|
||||
struct KeySigEvent {
|
||||
Delta delta;
|
||||
MetaFlag flag;
|
||||
u16 key;
|
||||
u8 mode;
|
||||
struct MessageData {
|
||||
match (u8(g_next_status) & 0xf0) {
|
||||
(Status::NoteOff | Status::NoteOn): {
|
||||
u8 note_number;
|
||||
u8 velocity;
|
||||
}
|
||||
(Status::PolyphonicAfterTouch): {
|
||||
u8 note_number;
|
||||
u8 amount;
|
||||
}
|
||||
(Status::ControlChange): {
|
||||
ControlChangeType cc_number;
|
||||
u8 value;
|
||||
}
|
||||
(Status::ProgramChange): {
|
||||
u8 program_number;
|
||||
}
|
||||
(Status::ChannelAfterTouch): {
|
||||
u8 amount;
|
||||
}
|
||||
(Status::PitchWheel): {
|
||||
s16 value [[format("signed14")]];
|
||||
}
|
||||
}
|
||||
match (g_next_status) {
|
||||
(Status::SysEx | Status::EndOfSysEx): {
|
||||
// "EndOfSysEx" can appear as the last data byte in a
|
||||
// system exclusive message, or as the starting byte in
|
||||
// multi-packet messages
|
||||
VariableLengthQuantity<"sysex_length"> sysex_length [[inline]];
|
||||
u8 sysex_data[sysex_length.value];
|
||||
}
|
||||
(Status::SongPositionPointer): {
|
||||
u8 lsb;
|
||||
u8 msb;
|
||||
}
|
||||
(Status::SongSelect): {
|
||||
u8 song_number;
|
||||
}
|
||||
(Status::MetaEvent): {
|
||||
MetaType meta_type;
|
||||
VariableLengthQuantity<"meta_length"> meta_length [[inline]];
|
||||
match (meta_type) {
|
||||
(MetaType::EndOfTrack): {
|
||||
g_has_more_messages = false;
|
||||
g_has_more_tracks = std::mem::read_unsigned($, 4) == le u32(TrackFlag::MTrk);
|
||||
}
|
||||
(MetaType::Text
|
||||
| MetaType::CopyrightNotice
|
||||
| MetaType::TrackName
|
||||
| MetaType::InstrumentName
|
||||
| MetaType::Lyric
|
||||
| MetaType::Marker
|
||||
| MetaType::CuePoint): {
|
||||
char text[meta_length.value];
|
||||
}
|
||||
(MetaType::TimeSignature): {
|
||||
u8 numerator;
|
||||
u8 denominator;
|
||||
u8 ticks_per_click;
|
||||
u8 thirty_second_notes_per_crotchet;
|
||||
}
|
||||
(MetaType::KeySignature): {
|
||||
u8 key;
|
||||
u8 mode;
|
||||
}
|
||||
(MetaType::SetTempo): {
|
||||
u24 micro_seconds_per_click; // default 1 million
|
||||
}
|
||||
(_): {
|
||||
u8 meta_data[meta_length.value];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct TempoEvent {
|
||||
Delta delta;
|
||||
MetaFlag flag;
|
||||
u32 micro_seconds_per_click; // default 1 million
|
||||
};
|
||||
struct Message {
|
||||
VariableLengthQuantity<"delta"> delta [[inline]];
|
||||
|
||||
struct TrackNameEvent {
|
||||
Delta delta;
|
||||
MetaFlag flag;
|
||||
u8 length;
|
||||
u8 text;
|
||||
};
|
||||
// Status bytes of MIDI channel messages may be omitted if the
|
||||
// preceding event is a MIDI channel message with the same status
|
||||
if (std::mem::read_unsigned($, 1) > 0x7f) {
|
||||
Status status;
|
||||
g_next_status = status;
|
||||
}
|
||||
|
||||
struct Note {
|
||||
Delta delta;
|
||||
NoteEvent ne;
|
||||
NoteValue note;
|
||||
Velocity vel;
|
||||
MessageData data [[inline]];
|
||||
};
|
||||
|
||||
struct HeaderChunk {
|
||||
@@ -75,21 +283,18 @@ struct HeaderChunk {
|
||||
u16 mode;
|
||||
u16 num_tracks;
|
||||
u16 ticks_per_quarter;
|
||||
TrackChunk chunk;
|
||||
u32 track_length;
|
||||
};
|
||||
|
||||
struct Footer {
|
||||
Delta d;
|
||||
MetaFlag m;
|
||||
EOF eof;
|
||||
struct TrackChunk {
|
||||
TrackFlag flag;
|
||||
u32 length;
|
||||
g_has_more_messages = true;
|
||||
Message messages[while(g_has_more_messages)];
|
||||
};
|
||||
|
||||
struct MidiFile {
|
||||
HeaderChunk header;
|
||||
// whatever meta flags can be in here
|
||||
Note notes[12]; //however many notes you're looking at
|
||||
Footer f;
|
||||
TrackChunk tracks[while(g_has_more_tracks)];
|
||||
};
|
||||
|
||||
MidiFile midi_file @ 0x00;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Windows MiniDump files
|
||||
|
||||
#pragma MIME application/x-dmp
|
||||
|
||||
#include <type/time.pat>
|
||||
|
||||
288
patterns/mp4.hexpat
Normal file
288
patterns/mp4.hexpat
Normal file
@@ -0,0 +1,288 @@
|
||||
#pragma description MPEG-4 Part 14 digital multimedia container format
|
||||
|
||||
#pragma endian big
|
||||
|
||||
#pragma MIME audio/mp4
|
||||
#pragma MIME video/mp4
|
||||
#pragma MIME application/mp4
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
|
||||
fn to_string(auto var) {
|
||||
return str(var);
|
||||
};
|
||||
|
||||
fn format_string(auto string) {
|
||||
return string.value;
|
||||
};
|
||||
|
||||
struct string {
|
||||
char value[std::mem::find_sequence_in_range(0, $, std::mem::size(), 0x00) - $];
|
||||
} [[sealed, format("format_string")]];
|
||||
|
||||
struct BaseBox {
|
||||
u64 boxSize = 0;
|
||||
u64 startOffset = $;
|
||||
u64 endOffset = 0;
|
||||
|
||||
u32 size;
|
||||
char type[4];
|
||||
|
||||
// Calculate the size of the current box
|
||||
// 1. If the size is equal to 1 -> the box size is equal to 'largeSize' attribute.
|
||||
// 2. If the size is equal to 0 -> The box extends to the end of the file.
|
||||
// 3. Otherwise, size is equaly to the 'size' attribute.
|
||||
if (this.size == 1) {
|
||||
u64 largeSize;
|
||||
boxSize = largeSize;
|
||||
endOffset = startOffset + boxSize;
|
||||
} else if (this.size == 0) {
|
||||
boxSize = std::mem::size() - startOffset;
|
||||
endOffset = std::mem::size();
|
||||
} else {
|
||||
boxSize = size;
|
||||
endOffset = startOffset + boxSize;
|
||||
}
|
||||
|
||||
if (this.type == "uuid") {
|
||||
char usertype[16];
|
||||
}
|
||||
};
|
||||
|
||||
struct FullBox : BaseBox {
|
||||
u8 version;
|
||||
u24 flags;
|
||||
};
|
||||
|
||||
struct UnknownBox : BaseBox {
|
||||
u8 unk[while($ != endOffset)];
|
||||
};
|
||||
|
||||
using brand = u32 [[format("to_string")]];
|
||||
struct FileTypeBox : BaseBox {
|
||||
brand major_brand;
|
||||
u32 minor_version;
|
||||
brand compatible_brands[(endOffset - $) / sizeof(brand)];
|
||||
};
|
||||
|
||||
struct MovieHeaderBox : FullBox {
|
||||
if (this.version == 1) {
|
||||
u64 creation_time;
|
||||
u64 modification_time;
|
||||
u32 timescale;
|
||||
u64 duration;
|
||||
} else { // version == 0
|
||||
u32 creation_time;
|
||||
u32 modification_time;
|
||||
u32 timescale;
|
||||
u32 duration;
|
||||
}
|
||||
u32 rate [[comment("Fixed point number 16.16")]];
|
||||
u16 volume [[comment("Fixed point number 8.8")]];
|
||||
u8 reserved[10] [[sealed]];
|
||||
u32 matrix[9];
|
||||
u32 preview_time;
|
||||
u32 preview_duration;
|
||||
u32 poster_time;
|
||||
u32 selection_time;
|
||||
u32 selection_duration;
|
||||
u32 current_time;
|
||||
u32 next_track_id;
|
||||
};
|
||||
|
||||
struct TrackHeaderBox : FullBox {
|
||||
if (this.version == 1) {
|
||||
u64 creation_time;
|
||||
u64 modification_time;
|
||||
u32 track_id;
|
||||
u32 reserved;
|
||||
u64 duration;
|
||||
} else { // version == 0
|
||||
u32 creation_time;
|
||||
u32 modification_time;
|
||||
u32 track_id;
|
||||
u32 reserved;
|
||||
u32 duration;
|
||||
}
|
||||
u32 reserved_2[2] [[sealed]];
|
||||
s16 layer;
|
||||
s16 alternate_group;
|
||||
s16 volume;
|
||||
u16 reserved_3;
|
||||
s32 matrix[9];
|
||||
u32 width;
|
||||
u32 height;
|
||||
};
|
||||
|
||||
struct DataEntryBox : FullBox {
|
||||
if (std::string::contains(this.type, "url")) {
|
||||
string location;
|
||||
} else if (std::string::contains(this.type, "urn")) {
|
||||
string name;
|
||||
string location;
|
||||
} else {
|
||||
std::error("Invalid DataEntryBox");
|
||||
}
|
||||
};
|
||||
|
||||
struct DataReferenceBox : FullBox {
|
||||
u32 entry_count;
|
||||
DataEntryBox data_entries[this.entry_count];
|
||||
};
|
||||
|
||||
struct SubDataInformationBox {
|
||||
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
|
||||
|
||||
match (str(type)) {
|
||||
("dref"): DataReferenceBox box [[inline]];
|
||||
(_): UnknownBox box [[inline]];
|
||||
}
|
||||
} [[name(std::format("DataInformationBox({})", box.type))]];
|
||||
|
||||
struct DataInformationBox : BaseBox {
|
||||
SubDataInformationBox box[while($ < endOffset)] [[inline]];
|
||||
};
|
||||
|
||||
struct HandlerBox : FullBox {
|
||||
u32 component_type;
|
||||
u32 handler_type;
|
||||
u32 reserved[3];
|
||||
char name[endOffset - $];
|
||||
};
|
||||
|
||||
struct VideoMediaHeaderBox : FullBox {
|
||||
u16 graphicsmode;
|
||||
u16 opcolor[3];
|
||||
};
|
||||
|
||||
struct SubMediaInformationBox {
|
||||
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
|
||||
|
||||
match (str(type)) {
|
||||
("vmhd"): VideoMediaHeaderBox box [[inline]];
|
||||
("hdlr"): HandlerBox box [[inline]];
|
||||
("dinf"): DataInformationBox box [[inline]];
|
||||
(_): UnknownBox box [[inline]];
|
||||
// TODO: Add stbl
|
||||
}
|
||||
} [[name(std::format("MediaInformationBox({})", box.type))]];
|
||||
|
||||
struct MediaInformationBox : BaseBox {
|
||||
SubMediaInformationBox box[while($ < endOffset)] [[inline]];
|
||||
};
|
||||
|
||||
struct MediaHeaderBox : FullBox {
|
||||
if (this.version == 1) {
|
||||
u64 creation_time;
|
||||
u64 modification_time;
|
||||
u32 timescale;
|
||||
u64 duration;
|
||||
} else { // version==0
|
||||
u32 creation_time;
|
||||
u32 modification_time;
|
||||
u32 timescale;
|
||||
u32 duration;
|
||||
}
|
||||
u16 language [[comment("ISO-639-2/T language code")]];
|
||||
u16 quality;
|
||||
};
|
||||
|
||||
struct SubMediaBox {
|
||||
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
|
||||
|
||||
match (str(type)) {
|
||||
("mdhd"): MediaHeaderBox box [[inline]];
|
||||
("hdlr"): HandlerBox box [[inline]];
|
||||
("minf"): MediaInformationBox box [[inline]];
|
||||
(_): UnknownBox box [[inline]];
|
||||
}
|
||||
} [[name(std::format("MediaBox({})", box.type))]];
|
||||
|
||||
struct MediaBox : BaseBox {
|
||||
SubMediaBox box[while($ < endOffset)] [[inline]];
|
||||
};
|
||||
|
||||
struct EditListEntry64 {
|
||||
u64 segment_duration;
|
||||
s64 media_time;
|
||||
s16 media_rate_integer;
|
||||
s16 media_rate_fraction;
|
||||
};
|
||||
|
||||
struct EditListEntry32 {
|
||||
u32 segment_duration;
|
||||
s32 media_time;
|
||||
s16 media_rate_integer;
|
||||
s16 media_rate_fraction;
|
||||
};
|
||||
|
||||
struct EditListBox : FullBox {
|
||||
u32 entry_count;
|
||||
if (this.version == 1) {
|
||||
EditListEntry64 entry_list[this.entry_count];
|
||||
} else { // version 0
|
||||
EditListEntry32 entry_list[this.entry_count];
|
||||
}
|
||||
};
|
||||
|
||||
struct SubEditBox {
|
||||
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
|
||||
|
||||
match (str(type)) {
|
||||
("elst"): EditListBox box [[inline]];
|
||||
(_): UnknownBox box [[inline]];
|
||||
}
|
||||
} [[name(std::format("EditBox({})", box.type))]];
|
||||
|
||||
struct EditBox : BaseBox {
|
||||
SubEditBox box[while($ < endOffset)] [[inline]];
|
||||
};
|
||||
|
||||
struct SubTrackBox {
|
||||
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
|
||||
|
||||
match (str(type)) {
|
||||
("mdia"): MediaBox box [[inline]];
|
||||
("edts"): EditBox box [[inline]];
|
||||
("tkhd"): TrackHeaderBox box [[inline]];
|
||||
(_): UnknownBox box [[inline]];
|
||||
}
|
||||
} [[name(std::format("TrackBox({})", box.type))]];
|
||||
|
||||
struct TrackBox : BaseBox {
|
||||
SubTrackBox box[while($ < endOffset)] [[inline]];
|
||||
};
|
||||
|
||||
struct SubMovieBox {
|
||||
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
|
||||
|
||||
match (str(type)) {
|
||||
("mvhd"): MovieHeaderBox box [[inline]];
|
||||
("trak"): TrackBox box [[inline]];
|
||||
(_): UnknownBox box [[inline]];
|
||||
// TODO: Add "iods" box
|
||||
}
|
||||
} [[name(std::format("MovieBox({})", box.type))]];
|
||||
|
||||
struct MovieBox : BaseBox {
|
||||
SubMovieBox box[while($ < endOffset)] [[inline]];
|
||||
};
|
||||
|
||||
struct MediaDataBox : BaseBox {
|
||||
u8 data[while($ < endOffset)] [[sealed]];
|
||||
};
|
||||
|
||||
struct Box {
|
||||
u32 type = std::mem::read_unsigned($ + 4, 4, std::mem::Endian::Big);
|
||||
|
||||
match (str(type)) {
|
||||
("ftyp"): FileTypeBox box [[inline]];
|
||||
("moov"): MovieBox box [[inline]];
|
||||
("mdat"): MediaDataBox box [[inline]];
|
||||
(_): UnknownBox box [[inline]];
|
||||
}
|
||||
} [[name(std::format("Box({})", box.type))]];
|
||||
|
||||
Box mp4[while(!std::mem::eof())] @ 0x0;
|
||||
@@ -1,154 +1,157 @@
|
||||
#pragma MIME application/x-msgpack
|
||||
|
||||
enum Type : u8 {
|
||||
PositiveFixInt = 0x00 ... 0x7F,
|
||||
FixMap = 0x80 ... 0x8F,
|
||||
FixArray = 0x90 ... 0x9F,
|
||||
FixStr = 0xA0 ... 0xBF,
|
||||
Nil = 0xC0,
|
||||
Unused = 0xC1,
|
||||
False = 0xC2,
|
||||
True = 0xC3,
|
||||
Bin8 = 0xC4,
|
||||
Bin16 = 0xC5,
|
||||
Bin32 = 0xC6,
|
||||
Ext8 = 0xC7,
|
||||
Ext16 = 0xC8,
|
||||
Ext32 = 0xC9,
|
||||
Float32 = 0xCA,
|
||||
Float64 = 0xCB,
|
||||
Uint8 = 0xCC,
|
||||
Uint16 = 0xCD,
|
||||
Uint32 = 0xCE,
|
||||
Uint64 = 0xCF,
|
||||
Int8 = 0xD0,
|
||||
Int16 = 0xD1,
|
||||
Int32 = 0xD2,
|
||||
Int64 = 0xD3,
|
||||
FixExt1 = 0xD4,
|
||||
FixExt2 = 0xD5,
|
||||
FixExt4 = 0xD6,
|
||||
FixExt8 = 0xD7,
|
||||
FixExt16 = 0xD8,
|
||||
Str8 = 0xD9,
|
||||
Str16 = 0xDA,
|
||||
Str32 = 0xDB,
|
||||
Array16 = 0xDC,
|
||||
Array32 = 0xDD,
|
||||
Map16 = 0xDE,
|
||||
Map32 = 0xDF,
|
||||
NegativeFixInt = 0xE0 ... 0xFF
|
||||
};
|
||||
|
||||
fn format_positive_fixint(u8 value) {
|
||||
return value & 0b0111'1111;
|
||||
};
|
||||
|
||||
fn format_negative_fixint(u8 value) {
|
||||
return -(value & 0b0001'1111);
|
||||
};
|
||||
|
||||
using MessagePack;
|
||||
|
||||
struct MapEntry {
|
||||
MessagePack key, value;
|
||||
};
|
||||
|
||||
struct MessagePack {
|
||||
Type type;
|
||||
|
||||
if (u8(type) <= 0x7F) {
|
||||
$ -= 1;
|
||||
u8 value [[format("format_positive_fixint")]];
|
||||
} else if (u8(type) >= Type::NegativeFixInt) {
|
||||
$ -= 1;
|
||||
u8 value [[format("format_negative_fixint")]];
|
||||
} else if (type == Type::Uint8)
|
||||
be u8 value;
|
||||
else if (type == Type::Uint16)
|
||||
be u16 value;
|
||||
else if (type == Type::Uint32)
|
||||
be u32 value;
|
||||
else if (type == Type::Uint64)
|
||||
be u64 value;
|
||||
else if (type == Type::Int8)
|
||||
be s8 value;
|
||||
else if (type == Type::Int16)
|
||||
be s16 value;
|
||||
else if (type == Type::Int32)
|
||||
be s32 value;
|
||||
else if (type == Type::Int64)
|
||||
be s64 value;
|
||||
else if (type == Type::Float32)
|
||||
be float value;
|
||||
else if (type == Type::Float64)
|
||||
be double value;
|
||||
else if ((u8(type) & 0b1110'0000) == Type::FixStr)
|
||||
char value[u8(type) & 0b0001'1111];
|
||||
else if (type == Type::Str8) {
|
||||
be u8 length;
|
||||
char value[length];
|
||||
} else if (type == Type::Str16) {
|
||||
be u16 length;
|
||||
char value[length];
|
||||
} else if (type == Type::Str32) {
|
||||
be u32 length;
|
||||
char value[length];
|
||||
} else if (type == Type::Bin8) {
|
||||
be u8 length;
|
||||
u8 value[length];
|
||||
} else if (type == Type::Bin16) {
|
||||
be u16 length;
|
||||
u8 value[length];
|
||||
} else if (type == Type::Bin32) {
|
||||
be u32 length;
|
||||
u8 value[length];
|
||||
} else if ((u8(type) & 0b1111'0000) == Type::FixArray)
|
||||
MessagePack value[u8(type) & 0b0000'1111];
|
||||
else if (type == Type::Array16) {
|
||||
be u16 length;
|
||||
MessagePack value[length];
|
||||
} else if (type == Type::Array32) {
|
||||
be u32 length;
|
||||
MessagePack value[length];
|
||||
} else if ((u8(type) & 0b1111'0000) == Type::FixMap)
|
||||
MapEntry value[u8(type) & 0b0000'1111];
|
||||
else if (type == Type::Map16) {
|
||||
be u16 length;
|
||||
MapEntry value[length];
|
||||
} else if (type == Type::Map32) {
|
||||
be u32 length;
|
||||
MapEntry value[length];
|
||||
} else if (type == Type::FixExt1) {
|
||||
s8 type;
|
||||
u8 data;
|
||||
} else if (type == Type::FixExt2) {
|
||||
s8 type;
|
||||
u16 data;
|
||||
} else if (type == Type::FixExt4) {
|
||||
s8 type;
|
||||
u32 data;
|
||||
} else if (type == Type::FixExt8) {
|
||||
s8 type;
|
||||
u64 data;
|
||||
} else if (type == Type::FixExt16) {
|
||||
s8 type;
|
||||
u128 data;
|
||||
} else if (type == Type::Ext8) {
|
||||
u8 length;
|
||||
s8 type;
|
||||
u8 data[length];
|
||||
} else if (type == Type::Ext16) {
|
||||
u16 length;
|
||||
s8 type;
|
||||
u8 data[length];
|
||||
} else if (type == Type::Ext32) {
|
||||
u32 length;
|
||||
s8 type;
|
||||
u8 data[length];
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description MessagePack binary serialization format
|
||||
|
||||
#pragma MIME application/x-msgpack
|
||||
|
||||
enum Type : u8 {
|
||||
PositiveFixInt = 0x00 ... 0x7F,
|
||||
FixMap = 0x80 ... 0x8F,
|
||||
FixArray = 0x90 ... 0x9F,
|
||||
FixStr = 0xA0 ... 0xBF,
|
||||
Nil = 0xC0,
|
||||
Unused = 0xC1,
|
||||
False = 0xC2,
|
||||
True = 0xC3,
|
||||
Bin8 = 0xC4,
|
||||
Bin16 = 0xC5,
|
||||
Bin32 = 0xC6,
|
||||
Ext8 = 0xC7,
|
||||
Ext16 = 0xC8,
|
||||
Ext32 = 0xC9,
|
||||
Float32 = 0xCA,
|
||||
Float64 = 0xCB,
|
||||
Uint8 = 0xCC,
|
||||
Uint16 = 0xCD,
|
||||
Uint32 = 0xCE,
|
||||
Uint64 = 0xCF,
|
||||
Int8 = 0xD0,
|
||||
Int16 = 0xD1,
|
||||
Int32 = 0xD2,
|
||||
Int64 = 0xD3,
|
||||
FixExt1 = 0xD4,
|
||||
FixExt2 = 0xD5,
|
||||
FixExt4 = 0xD6,
|
||||
FixExt8 = 0xD7,
|
||||
FixExt16 = 0xD8,
|
||||
Str8 = 0xD9,
|
||||
Str16 = 0xDA,
|
||||
Str32 = 0xDB,
|
||||
Array16 = 0xDC,
|
||||
Array32 = 0xDD,
|
||||
Map16 = 0xDE,
|
||||
Map32 = 0xDF,
|
||||
NegativeFixInt = 0xE0 ... 0xFF
|
||||
};
|
||||
|
||||
fn format_positive_fixint(u8 value) {
|
||||
return value & 0b0111'1111;
|
||||
};
|
||||
|
||||
fn format_negative_fixint(u8 value) {
|
||||
return -(value & 0b0001'1111);
|
||||
};
|
||||
|
||||
using MessagePack;
|
||||
|
||||
struct MapEntry {
|
||||
MessagePack key, value;
|
||||
};
|
||||
|
||||
struct MessagePack {
|
||||
Type type;
|
||||
|
||||
if (u8(type) <= 0x7F) {
|
||||
$ -= 1;
|
||||
u8 value [[format("format_positive_fixint")]];
|
||||
} else if (u8(type) >= Type::NegativeFixInt) {
|
||||
$ -= 1;
|
||||
u8 value [[format("format_negative_fixint")]];
|
||||
} else if (type == Type::Uint8)
|
||||
be u8 value;
|
||||
else if (type == Type::Uint16)
|
||||
be u16 value;
|
||||
else if (type == Type::Uint32)
|
||||
be u32 value;
|
||||
else if (type == Type::Uint64)
|
||||
be u64 value;
|
||||
else if (type == Type::Int8)
|
||||
be s8 value;
|
||||
else if (type == Type::Int16)
|
||||
be s16 value;
|
||||
else if (type == Type::Int32)
|
||||
be s32 value;
|
||||
else if (type == Type::Int64)
|
||||
be s64 value;
|
||||
else if (type == Type::Float32)
|
||||
be float value;
|
||||
else if (type == Type::Float64)
|
||||
be double value;
|
||||
else if ((u8(type) & 0b1110'0000) == Type::FixStr)
|
||||
char value[u8(type) & 0b0001'1111];
|
||||
else if (type == Type::Str8) {
|
||||
be u8 length;
|
||||
char value[length];
|
||||
} else if (type == Type::Str16) {
|
||||
be u16 length;
|
||||
char value[length];
|
||||
} else if (type == Type::Str32) {
|
||||
be u32 length;
|
||||
char value[length];
|
||||
} else if (type == Type::Bin8) {
|
||||
be u8 length;
|
||||
u8 value[length];
|
||||
} else if (type == Type::Bin16) {
|
||||
be u16 length;
|
||||
u8 value[length];
|
||||
} else if (type == Type::Bin32) {
|
||||
be u32 length;
|
||||
u8 value[length];
|
||||
} else if ((u8(type) & 0b1111'0000) == Type::FixArray)
|
||||
MessagePack value[u8(type) & 0b0000'1111];
|
||||
else if (type == Type::Array16) {
|
||||
be u16 length;
|
||||
MessagePack value[length];
|
||||
} else if (type == Type::Array32) {
|
||||
be u32 length;
|
||||
MessagePack value[length];
|
||||
} else if ((u8(type) & 0b1111'0000) == Type::FixMap)
|
||||
MapEntry value[u8(type) & 0b0000'1111];
|
||||
else if (type == Type::Map16) {
|
||||
be u16 length;
|
||||
MapEntry value[length];
|
||||
} else if (type == Type::Map32) {
|
||||
be u32 length;
|
||||
MapEntry value[length];
|
||||
} else if (type == Type::FixExt1) {
|
||||
s8 type;
|
||||
u8 data;
|
||||
} else if (type == Type::FixExt2) {
|
||||
s8 type;
|
||||
u16 data;
|
||||
} else if (type == Type::FixExt4) {
|
||||
s8 type;
|
||||
u32 data;
|
||||
} else if (type == Type::FixExt8) {
|
||||
s8 type;
|
||||
u64 data;
|
||||
} else if (type == Type::FixExt16) {
|
||||
s8 type;
|
||||
u128 data;
|
||||
} else if (type == Type::Ext8) {
|
||||
u8 length;
|
||||
s8 type;
|
||||
u8 data[length];
|
||||
} else if (type == Type::Ext16) {
|
||||
u16 length;
|
||||
s8 type;
|
||||
u8 data[length];
|
||||
} else if (type == Type::Ext32) {
|
||||
u32 length;
|
||||
s8 type;
|
||||
u8 data[length];
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
MessagePack pack @ 0x00;
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Nintendo Switch NACP files
|
||||
|
||||
#pragma endian little
|
||||
|
||||
#include <std/sys.pat>
|
||||
|
||||
@@ -1,76 +1,79 @@
|
||||
#include <std/sys.pat>
|
||||
|
||||
#pragma endian big
|
||||
|
||||
enum Tag : u8 {
|
||||
End = 0,
|
||||
Byte = 1,
|
||||
Short = 2,
|
||||
Int = 3,
|
||||
Long = 4,
|
||||
Float = 5,
|
||||
Double = 6,
|
||||
ByteArray = 7,
|
||||
String = 8,
|
||||
List = 9,
|
||||
Compound = 10,
|
||||
IntArray = 11,
|
||||
LongArray = 12
|
||||
};
|
||||
|
||||
using Element;
|
||||
|
||||
struct Value {
|
||||
if (parent.tag == Tag::Byte)
|
||||
s8 value;
|
||||
else if (parent.tag == Tag::Short)
|
||||
s16 value;
|
||||
else if (parent.tag == Tag::Int)
|
||||
s32 value;
|
||||
else if (parent.tag == Tag::Long)
|
||||
s64 value;
|
||||
else if (parent.tag == Tag::Float)
|
||||
float value;
|
||||
else if (parent.tag == Tag::Double)
|
||||
double value;
|
||||
else if (parent.tag == Tag::ByteArray) {
|
||||
s32 arrayLength;
|
||||
s8 value[arrayLength] [[sealed]];
|
||||
} else if (parent.tag == Tag::String) {
|
||||
u16 stringLength;
|
||||
char value[stringLength];
|
||||
} else if (parent.tag == Tag::List) {
|
||||
Tag tag;
|
||||
s32 listLength;
|
||||
Value values[listLength] [[static]];
|
||||
} else if (parent.tag == Tag::Compound) {
|
||||
Element values[while(true)];
|
||||
} else if (parent.tag == Tag::IntArray){
|
||||
s32 arrayLength;
|
||||
s32 value[arrayLength] [[sealed]];
|
||||
} else if (parent.tag == Tag::LongArray) {
|
||||
s32 arrayLength;
|
||||
s64 value[arrayLength] [[sealed]];
|
||||
} else {
|
||||
std::error(std::format("Invalid tag {:02X}", TypeTag));
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
struct Element {
|
||||
Tag tag;
|
||||
if (tag == Tag::End)
|
||||
break;
|
||||
else {
|
||||
|
||||
u16 nameLength;
|
||||
char name[nameLength];
|
||||
|
||||
Value value;
|
||||
}
|
||||
};
|
||||
|
||||
struct NBT {
|
||||
Element element[while(true)] [[inline]];
|
||||
};
|
||||
|
||||
NBT nbt @ 0x00;
|
||||
#pragma author WerWolv
|
||||
#pragma description Minecraft NBT format
|
||||
|
||||
#include <std/sys.pat>
|
||||
|
||||
#pragma endian big
|
||||
|
||||
enum Tag : u8 {
|
||||
End = 0,
|
||||
Byte = 1,
|
||||
Short = 2,
|
||||
Int = 3,
|
||||
Long = 4,
|
||||
Float = 5,
|
||||
Double = 6,
|
||||
ByteArray = 7,
|
||||
String = 8,
|
||||
List = 9,
|
||||
Compound = 10,
|
||||
IntArray = 11,
|
||||
LongArray = 12
|
||||
};
|
||||
|
||||
using Element;
|
||||
|
||||
struct Value {
|
||||
if (parent.tag == Tag::Byte)
|
||||
s8 value;
|
||||
else if (parent.tag == Tag::Short)
|
||||
s16 value;
|
||||
else if (parent.tag == Tag::Int)
|
||||
s32 value;
|
||||
else if (parent.tag == Tag::Long)
|
||||
s64 value;
|
||||
else if (parent.tag == Tag::Float)
|
||||
float value;
|
||||
else if (parent.tag == Tag::Double)
|
||||
double value;
|
||||
else if (parent.tag == Tag::ByteArray) {
|
||||
s32 arrayLength;
|
||||
s8 value[arrayLength] [[sealed]];
|
||||
} else if (parent.tag == Tag::String) {
|
||||
u16 stringLength;
|
||||
char value[stringLength];
|
||||
} else if (parent.tag == Tag::List) {
|
||||
Tag tag;
|
||||
s32 listLength;
|
||||
Value values[listLength] [[static]];
|
||||
} else if (parent.tag == Tag::Compound) {
|
||||
Element values[while(true)];
|
||||
} else if (parent.tag == Tag::IntArray){
|
||||
s32 arrayLength;
|
||||
s32 value[arrayLength] [[sealed]];
|
||||
} else if (parent.tag == Tag::LongArray) {
|
||||
s32 arrayLength;
|
||||
s64 value[arrayLength] [[sealed]];
|
||||
} else {
|
||||
std::error(std::format("Invalid tag {:02X}", TypeTag));
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
struct Element {
|
||||
Tag tag;
|
||||
if (tag == Tag::End)
|
||||
break;
|
||||
else {
|
||||
|
||||
u16 nameLength;
|
||||
char name[nameLength];
|
||||
|
||||
Value value;
|
||||
}
|
||||
};
|
||||
|
||||
struct NBT {
|
||||
Element element[while(true)] [[inline]];
|
||||
};
|
||||
|
||||
NBT nbt @ 0x00;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description NE header and Standard NE fields
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
struct DOSHeader {
|
||||
|
||||
87
patterns/nes.hexpat
Normal file
87
patterns/nes.hexpat
Normal file
@@ -0,0 +1,87 @@
|
||||
#pragma author gmestanley
|
||||
#pragma description .nes file format
|
||||
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
|
||||
bitfield iNES07Flags {
|
||||
mirroringIsVertical : 1;
|
||||
batterybackedPRGRAM : 1;
|
||||
trainerOf512Bytes : 1;
|
||||
ignoreMirroring : 1;
|
||||
mapperLowerNybble : 4;
|
||||
vsUnisystem : 1;
|
||||
playchoice10 : 1;
|
||||
nes2Format : 2 [[name("nes2.0Format")]];
|
||||
mapperHigherNybble : 4;
|
||||
} [[name("iNES0.7Flags")]];
|
||||
|
||||
bitfield Flags9 {
|
||||
isPAL : 1;
|
||||
padding : 7;
|
||||
};
|
||||
|
||||
bitfield Flags10 {
|
||||
tvSystem : 2;
|
||||
padding : 2;
|
||||
prgRAM : 1;
|
||||
busConflicts : 1;
|
||||
padding : 2;
|
||||
};
|
||||
|
||||
struct iNESFlags {
|
||||
iNES07Flags ines07Flags [[name("ines0.7Flags")]];
|
||||
if (!ines07Flags.nes2Format) {
|
||||
u8 prgRAM8KBMultiplier;
|
||||
Flags9 flags9;
|
||||
Flags10 flags10;
|
||||
restLength = 5;
|
||||
}
|
||||
else {
|
||||
restLength = 9;
|
||||
}
|
||||
};
|
||||
|
||||
u8 restLength;
|
||||
|
||||
struct Header {
|
||||
char identifier[4];
|
||||
u8 prgROM16KBMultiplier;
|
||||
u8 chrROM8KBMultiplier;
|
||||
iNESFlags inesFlags;
|
||||
char rest[restLength];
|
||||
};
|
||||
|
||||
Header header @ 0x00;
|
||||
|
||||
enum EncodingType : u8 {
|
||||
ASCII = 1
|
||||
};
|
||||
|
||||
struct OfficialHeader {
|
||||
char title[16] [[hex::spec_name("Title Registration Area")]];
|
||||
u16 programChecksum;
|
||||
u16 characterChecksum;
|
||||
u8 memorySize [[hex::spec_name("Cartridge Memory Size")]];
|
||||
u8 cartridgeType;
|
||||
EncodingType encodingType [[hex::spec_name("Registration Character Type Distinction")]];
|
||||
u8 titleLength [[hex::spec_name("Registration Characters Count")]];
|
||||
u8 makerID [[hex::spec_name("Maker Code")]];
|
||||
u8 complementaryChecksum;
|
||||
};
|
||||
|
||||
union OfficialHeaderUnion {
|
||||
u8 miscellaneousData[26];
|
||||
OfficialHeader officialHeader;
|
||||
};
|
||||
|
||||
struct PRGROM {
|
||||
u8 data[16384*header.prgROM16KBMultiplier-32];
|
||||
OfficialHeaderUnion officialHeaderUnion;
|
||||
u16 nmi;
|
||||
u16 entryPoint;
|
||||
u16 externalIRQ;
|
||||
};
|
||||
|
||||
PRGROM prgROM @ sizeof(header);
|
||||
u8 chrROM[8192*header.chrROM8KBMultiplier] @ sizeof(header)+sizeof(prgROM);
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Nintendo Switch NRO files
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description NTAG213/NTAG215/NTAG216, NFC Forum Type 2 Tag compliant IC
|
||||
|
||||
#include <std/core.pat>
|
||||
|
||||
using BitfieldOrder = std::core::BitfieldOrder;
|
||||
@@ -77,7 +80,7 @@ struct Length {
|
||||
u8 length;
|
||||
} [[sealed, transform("transform_length"), format("transform_length")]];
|
||||
|
||||
fn transform_length(Length length) {
|
||||
fn transform_length(ref auto length) {
|
||||
return length.length;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,29 +1,32 @@
|
||||
#pragma MIME audio/ogg
|
||||
|
||||
#include <std/core.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
bitfield HeaderType {
|
||||
Continuation : 1;
|
||||
BeginOfStream : 1;
|
||||
EndOfStream : 1;
|
||||
};
|
||||
|
||||
struct SegmentData {
|
||||
u8 data[parent.segmentTable[std::core::array_index()]];
|
||||
};
|
||||
|
||||
struct Ogg {
|
||||
char capturePattern[4];
|
||||
u8 version;
|
||||
HeaderType headerType;
|
||||
u64 granulePosition;
|
||||
u32 bitstreamSerialNumber;
|
||||
u32 pageSequenceNumber;
|
||||
u32 checksum;
|
||||
u8 pageSegments;
|
||||
u8 segmentTable[pageSegments];
|
||||
SegmentData data[pageSegments];
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description OGG Audio format
|
||||
|
||||
#pragma MIME audio/ogg
|
||||
|
||||
#include <std/core.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
bitfield HeaderType {
|
||||
Continuation : 1;
|
||||
BeginOfStream : 1;
|
||||
EndOfStream : 1;
|
||||
};
|
||||
|
||||
struct SegmentData {
|
||||
u8 data[parent.segmentTable[std::core::array_index()]];
|
||||
};
|
||||
|
||||
struct Ogg {
|
||||
char capturePattern[4];
|
||||
u8 version;
|
||||
HeaderType headerType;
|
||||
u64 granulePosition;
|
||||
u32 bitstreamSerialNumber;
|
||||
u32 pageSequenceNumber;
|
||||
u32 checksum;
|
||||
u8 pageSegments;
|
||||
u8 segmentTable[pageSegments];
|
||||
SegmentData data[pageSegments];
|
||||
};
|
||||
|
||||
Ogg ogg[while(!std::mem::eof())] @ 0x00;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description pcap header and packets
|
||||
|
||||
#include <std/mem.pat>
|
||||
#pragma MIME application/vnd.tcpdump.pcap
|
||||
|
||||
|
||||
@@ -1,52 +1,55 @@
|
||||
#pragma MIME application/x-pcx
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
enum Encoding : u8 {
|
||||
NoEncoding = 0x00,
|
||||
RunLengthEncoding = 0x01
|
||||
};
|
||||
|
||||
enum PaletteType : u16 {
|
||||
MonochromeOrColorInformation = 0x01,
|
||||
GrayscaleInformation = 0x02
|
||||
};
|
||||
|
||||
enum Version : u8 {
|
||||
V2_5 = 0x00,
|
||||
V2_8WithPalette = 0x02,
|
||||
V2_8_WithoutPalette = 0x03,
|
||||
PaintbrushForWindows = 0x04,
|
||||
V3_0 = 0x05
|
||||
};
|
||||
|
||||
struct Header {
|
||||
u8 magic;
|
||||
Version version;
|
||||
Encoding encoding;
|
||||
u8 bitsPerPixel;
|
||||
u16 xMin, yMin;
|
||||
u16 xMax, yMax;
|
||||
u16 hdpi, vdpi;
|
||||
};
|
||||
|
||||
struct RGB8 {
|
||||
u8 r, g, b;
|
||||
} [[sealed, color(std::format("{:02X}{:02X}{:02X}", this.r, this.g, this.b))]];
|
||||
|
||||
struct Palette {
|
||||
RGB8 color[16];
|
||||
};
|
||||
|
||||
struct PCX {
|
||||
Header header;
|
||||
Palette palette;
|
||||
padding[1];
|
||||
u8 numPlanes;
|
||||
u16 bytesPerLine;
|
||||
PaletteType paletteType;
|
||||
u16 hres, vres;
|
||||
padding[54];
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description PCX Image format
|
||||
|
||||
#pragma MIME application/x-pcx
|
||||
|
||||
#include <std/io.pat>
|
||||
|
||||
enum Encoding : u8 {
|
||||
NoEncoding = 0x00,
|
||||
RunLengthEncoding = 0x01
|
||||
};
|
||||
|
||||
enum PaletteType : u16 {
|
||||
MonochromeOrColorInformation = 0x01,
|
||||
GrayscaleInformation = 0x02
|
||||
};
|
||||
|
||||
enum Version : u8 {
|
||||
V2_5 = 0x00,
|
||||
V2_8WithPalette = 0x02,
|
||||
V2_8_WithoutPalette = 0x03,
|
||||
PaintbrushForWindows = 0x04,
|
||||
V3_0 = 0x05
|
||||
};
|
||||
|
||||
struct Header {
|
||||
u8 magic;
|
||||
Version version;
|
||||
Encoding encoding;
|
||||
u8 bitsPerPixel;
|
||||
u16 xMin, yMin;
|
||||
u16 xMax, yMax;
|
||||
u16 hdpi, vdpi;
|
||||
};
|
||||
|
||||
struct RGB8 {
|
||||
u8 r, g, b;
|
||||
} [[sealed, color(std::format("{:02X}{:02X}{:02X}", this.r, this.g, this.b))]];
|
||||
|
||||
struct Palette {
|
||||
RGB8 color[16];
|
||||
};
|
||||
|
||||
struct PCX {
|
||||
Header header;
|
||||
Palette palette;
|
||||
padding[1];
|
||||
u8 numPlanes;
|
||||
u16 bytesPerLine;
|
||||
PaletteType paletteType;
|
||||
u16 hres, vres;
|
||||
padding[54];
|
||||
};
|
||||
|
||||
PCX pcx @ 0x00;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,38 +1,41 @@
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
#include <std/core.pat>
|
||||
|
||||
struct FileEntry {
|
||||
u64 dataOffset;
|
||||
type::Size<u64> dataSize;
|
||||
u32 nameOffset;
|
||||
padding[4];
|
||||
};
|
||||
|
||||
struct String {
|
||||
char value[];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
type::Magic<"PFS0"> magic;
|
||||
u32 numFiles;
|
||||
type::Size<u32> stringTableSize;
|
||||
padding[4];
|
||||
|
||||
FileEntry fileEntryTable[numFiles];
|
||||
String strings[numFiles];
|
||||
};
|
||||
|
||||
struct File {
|
||||
char name[] @ addressof(parent.header.strings) + parent.header.fileEntryTable[std::core::array_index()].nameOffset;
|
||||
u8 data[parent.header.fileEntryTable[std::core::array_index()].dataSize] @ parent.header.fileEntryTable[std::core::array_index()].dataOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct PFS0 {
|
||||
Header header;
|
||||
|
||||
File files[header.numFiles];
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description Nintendo Switch PFS0 archive (NSP files)
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
#include <std/core.pat>
|
||||
|
||||
struct FileEntry {
|
||||
u64 dataOffset;
|
||||
type::Size<u64> dataSize;
|
||||
u32 nameOffset;
|
||||
padding[4];
|
||||
};
|
||||
|
||||
struct String {
|
||||
char value[];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
type::Magic<"PFS0"> magic;
|
||||
u32 numFiles;
|
||||
type::Size<u32> stringTableSize;
|
||||
padding[4];
|
||||
|
||||
FileEntry fileEntryTable[numFiles];
|
||||
String strings[numFiles];
|
||||
};
|
||||
|
||||
struct File {
|
||||
char name[] @ addressof(parent.header.strings) + parent.header.fileEntryTable[std::core::array_index()].nameOffset;
|
||||
u8 data[parent.header.fileEntryTable[std::core::array_index()].dataSize] @ parent.header.fileEntryTable[std::core::array_index()].dataOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct PFS0 {
|
||||
Header header;
|
||||
|
||||
File files[header.numFiles];
|
||||
};
|
||||
|
||||
PFS0 pfs0 @ 0x00;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description PIF Image Format
|
||||
|
||||
/* PIF - Portable Image Format
|
||||
*
|
||||
* Basic decoder for the PIF file structure
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#pragma description PNG image files
|
||||
|
||||
#pragma MIME image/png
|
||||
#pragma endian big
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
struct header_t {
|
||||
u8 highBitByte;
|
||||
char signature[3];
|
||||
@@ -168,7 +172,7 @@ struct chunk_t {
|
||||
}
|
||||
|
||||
u32 crc;
|
||||
} [[format("chunkValueName")]];
|
||||
} [[name(chunkValueName(this))]];
|
||||
|
||||
fn chunkValueName(ref chunk_t chunk) {
|
||||
return chunk.name;
|
||||
@@ -178,7 +182,12 @@ struct chunk_set {
|
||||
chunk_t chunks[while(builtin::std::mem::read_string($ + 4, 4) != "IEND")] [[inline]];
|
||||
} [[inline]];
|
||||
|
||||
struct Chunks {
|
||||
chunk_t ihdr_chunk [[comment("PNG Header chunk")]];
|
||||
chunk_set set [[comment("PNG Chunks"), name("Chunks"), inline]];
|
||||
chunk_t iend_chunk [[comment("Image End Chunk")]];
|
||||
};
|
||||
|
||||
u8 visualizer[std::mem::size()] @ 0x00 [[sealed, hex::visualize("image", this)]];
|
||||
header_t header @ 0x00 [[comment("PNG file signature"), name("Signature")]];
|
||||
chunk_t ihdr_chunk @ 0x08 [[comment("PNG Header chunk"), name("IHDR")]];
|
||||
chunk_set set @ $ [[comment("PNG Chunks"), name("Chunks"), inline]];
|
||||
chunk_t iend_chunk @ $ [[comment("Image End Chunk"), name("IEND")]];
|
||||
Chunks chunks @ 0x08 [[name("Chunks")]];
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Nintendo Switch PRODINFO
|
||||
|
||||
enum Model : u16 {
|
||||
NX = 1
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Google Protobuf encoding
|
||||
|
||||
#include <std/core.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
|
||||
340
patterns/pyc.hexpat
Normal file
340
patterns/pyc.hexpat
Normal file
@@ -0,0 +1,340 @@
|
||||
#pragma description Python bytecode files
|
||||
|
||||
#include <type/time.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
#define FLAG_REF 0x80
|
||||
#define TYPE_NULL '0'
|
||||
#define TYPE_NONE 'N'
|
||||
#define TYPE_FALSE 'F'
|
||||
#define TYPE_TRUE 'T'
|
||||
#define TYPE_STOPITER 'S'
|
||||
#define TYPE_ELLIPSIS '.'
|
||||
#define TYPE_INT 'i'
|
||||
#define TYPE_INT64 'I'
|
||||
#define TYPE_FLOAT 'f'
|
||||
#define TYPE_BINARY_FLOAT 'g'
|
||||
#define TYPE_COMPLEX 'x'
|
||||
#define TYPE_BINARY_COMPLEX 'y'
|
||||
#define TYPE_LONG 'l'
|
||||
#define TYPE_STRING 's'
|
||||
#define TYPE_INTERNED 't'
|
||||
#define TYPE_REF 'r'
|
||||
#define TYPE_STRINGREF 'R'
|
||||
#define TYPE_TUPLE '('
|
||||
#define TYPE_LIST '['
|
||||
#define TYPE_DICT '{'
|
||||
#define TYPE_CODE 'c'
|
||||
#define TYPE_UNICODE 'u'
|
||||
#define TYPE_UNKNOWN '?'
|
||||
#define TYPE_SET '<'
|
||||
#define TYPE_FROZENSET '>'
|
||||
#define TYPE_ASCII 'a'
|
||||
#define TYPE_ASCII_INTERNED 'A'
|
||||
#define TYPE_SMALL_TUPLE ')'
|
||||
#define TYPE_SHORT_ASCII 'z'
|
||||
#define TYPE_SHORT_ASCII_INTERNED 'Z'
|
||||
#define MAX_REFS 2048
|
||||
|
||||
using MarshalObject;
|
||||
u8 _major;
|
||||
u8 _minor;
|
||||
|
||||
fn above(u8 major, u8 minor) {
|
||||
return _major >= major && _minor >= minor;
|
||||
};
|
||||
|
||||
fn below(u8 major, u8 minor) {
|
||||
return _major <=major && _minor < minor;
|
||||
};
|
||||
|
||||
fn is(u8 major, u8 minor) {
|
||||
return _major == major && _minor == minor;
|
||||
};
|
||||
|
||||
fn between(u8 major, u8 minor, u8 otherMajor, u8 otherMinor) {
|
||||
return above(major, minor) && below(otherMajor, otherMinor);
|
||||
};
|
||||
|
||||
struct NoneObject {};
|
||||
|
||||
struct MarshalString {
|
||||
if(parent.type == TYPE_SHORT_ASCII || parent.type == TYPE_SHORT_ASCII_INTERNED)
|
||||
u8 length;
|
||||
else
|
||||
u32 length;
|
||||
|
||||
char data[length];
|
||||
};
|
||||
|
||||
struct MarshalSequence {
|
||||
if(parent.type == TYPE_SMALL_TUPLE)
|
||||
u8 length;
|
||||
else
|
||||
u32 length;
|
||||
MarshalObject values[length];
|
||||
};
|
||||
|
||||
struct MarshalCode {
|
||||
if(between(1, 3, 2, 3)) u16 numArgs;
|
||||
else if(above(2, 3)) u32 numArgs;
|
||||
|
||||
if(above(3, 8)) u32 numPosOnlyArgs;
|
||||
|
||||
if(_major >= 3) u32 numKwOnlyArgs;
|
||||
|
||||
if(between(1, 3, 2, 3)) u16 numLocals;
|
||||
else if(between(2, 3, 3, 11)) u32 numLocals;
|
||||
|
||||
if(between(1, 5, 2, 3)) u16 numStack;
|
||||
else if(above(2, 3)) u32 numStack;
|
||||
|
||||
if(between(1, 3, 2, 3)) u16 flags;
|
||||
else if(above(2, 3)) u32 flags;
|
||||
|
||||
MarshalObject code;
|
||||
MarshalObject constants;
|
||||
MarshalObject names;
|
||||
|
||||
if(above(1, 3)) MarshalObject localNames;
|
||||
|
||||
if(above(3, 11)) MarshalObject localKinds;
|
||||
|
||||
if(between(2, 1, 3, 11)) {
|
||||
MarshalObject freeVars;
|
||||
MarshalObject cellVars;
|
||||
}
|
||||
|
||||
MarshalObject fileName;
|
||||
MarshalObject name;
|
||||
|
||||
if(above(3, 11)) MarshalObject qualifiedName;
|
||||
|
||||
if(between(1, 5, 2, 3)) u16 firstLine;
|
||||
else if(above(2, 3)) u32 firstLine;
|
||||
|
||||
if(above(1, 5)) MarshalObject lnTable;
|
||||
|
||||
if(above(3, 11)) MarshalObject exceptionTable;
|
||||
};
|
||||
|
||||
struct DictEntry {
|
||||
MarshalObject key;
|
||||
if(key.type == TYPE_NULL) break;
|
||||
MarshalObject value;
|
||||
};
|
||||
|
||||
struct MarshalDict {
|
||||
DictEntry entries[while(true)];
|
||||
};
|
||||
|
||||
struct LongInt {
|
||||
u32 len;
|
||||
u16 buffer[len];
|
||||
};
|
||||
|
||||
struct LongFloat {
|
||||
u8 len;
|
||||
u8 buffer[len];
|
||||
};
|
||||
|
||||
struct LongComplex {
|
||||
LongFloat real;
|
||||
LongFloat imag;
|
||||
};
|
||||
|
||||
auto section = std::mem::create_section("ref-address");
|
||||
u128 refs[MAX_REFS] @ 0x0 in section;
|
||||
u32 refIndex;
|
||||
|
||||
fn refMember(u128 address) {
|
||||
refs[refIndex] = address;
|
||||
refIndex += 1;
|
||||
};
|
||||
|
||||
fn getRef(u32 index) {
|
||||
return refs[index];
|
||||
};
|
||||
|
||||
struct MarshalObject {
|
||||
u8 _type [[hidden]];
|
||||
u8 flag = _type & FLAG_REF;
|
||||
u8 type = _type & ~FLAG_REF;
|
||||
|
||||
if(flag) {
|
||||
refMember($-1);
|
||||
}
|
||||
|
||||
match(type) {
|
||||
(TYPE_NULL | TYPE_NONE | TYPE_STOPITER | TYPE_ELLIPSIS | TYPE_FALSE | TYPE_TRUE): continue;
|
||||
(TYPE_CODE): {
|
||||
MarshalCode code [[inline]];
|
||||
}
|
||||
(TYPE_STRING |
|
||||
TYPE_UNICODE |
|
||||
TYPE_ASCII |
|
||||
TYPE_ASCII_INTERNED |
|
||||
TYPE_SHORT_ASCII |
|
||||
TYPE_SHORT_ASCII_INTERNED): {
|
||||
MarshalString string [[inline]];
|
||||
}
|
||||
(TYPE_SMALL_TUPLE | TYPE_TUPLE | TYPE_LIST | TYPE_SET | TYPE_FROZENSET): {
|
||||
MarshalSequence sequence [[inline]];
|
||||
}
|
||||
(TYPE_DICT): {
|
||||
MarshalDict dict [[inline]];
|
||||
}
|
||||
(TYPE_INT): {
|
||||
u32 int;
|
||||
}
|
||||
(TYPE_INT64): {
|
||||
u64 long;
|
||||
}
|
||||
(TYPE_FLOAT): {
|
||||
LongFloat number;
|
||||
}
|
||||
(TYPE_BINARY_FLOAT): {
|
||||
double number;
|
||||
}
|
||||
(TYPE_COMPLEX): {
|
||||
LongComplex complex;
|
||||
}
|
||||
(TYPE_BINARY_COMPLEX): {
|
||||
double real;
|
||||
double imag;
|
||||
}
|
||||
(TYPE_LONG): {
|
||||
LongInt long;
|
||||
}
|
||||
(TYPE_REF): {
|
||||
u32 index;
|
||||
MarshalObject obj @ getRef(index);
|
||||
}
|
||||
(_): {
|
||||
std::print("Unknown marshal object type: {:c}", type);
|
||||
}
|
||||
}
|
||||
|
||||
} [[format("format_marshal")]];
|
||||
|
||||
fn format_marshal(ref auto obj) {
|
||||
match(obj.type) {
|
||||
(TYPE_NONE): return "None";
|
||||
(TYPE_STOPITER): return "StopIteration";
|
||||
(TYPE_ELLIPSIS): return "...";
|
||||
(TYPE_FALSE): return "False";
|
||||
(TYPE_TRUE): return "True";
|
||||
(TYPE_INT): return "int";
|
||||
(TYPE_INT64): return "int64";
|
||||
(TYPE_FLOAT): return "float";
|
||||
(TYPE_BINARY_FLOAT): return "float";
|
||||
(TYPE_COMPLEX): return "complex";
|
||||
(TYPE_BINARY_COMPLEX): return "complex";
|
||||
(TYPE_LONG): return "long";
|
||||
(TYPE_STRING): return "string";
|
||||
(TYPE_INTERNED): return "interned";
|
||||
(TYPE_REF): return "ref";
|
||||
(TYPE_TUPLE): return "tuple";
|
||||
(TYPE_LIST): return "list";
|
||||
(TYPE_DICT): return "dict";
|
||||
(TYPE_CODE): return "code";
|
||||
(TYPE_UNICODE): return "unicode";
|
||||
(TYPE_UNKNOWN): return "unknown";
|
||||
(TYPE_SET): return "set";
|
||||
(TYPE_FROZENSET): return "frozenset";
|
||||
(TYPE_ASCII): return "ascii";
|
||||
(TYPE_ASCII_INTERNED): return "ascii_interned";
|
||||
(TYPE_SHORT_ASCII): return "short_ascii";
|
||||
(TYPE_SHORT_ASCII_INTERNED): return "short_ascii_interned";
|
||||
(TYPE_SMALL_TUPLE): return "small_tuple";
|
||||
}
|
||||
};
|
||||
|
||||
enum Magic : u32 {
|
||||
MAGIC_1_0 = 0x00999902,
|
||||
MAGIC_1_1 = 0x00999903, /* Also covers 1.2 */
|
||||
MAGIC_1_3 = 0x0A0D2E89,
|
||||
MAGIC_1_4 = 0x0A0D1704,
|
||||
MAGIC_1_5 = 0x0A0D4E99,
|
||||
MAGIC_1_6 = 0x0A0DC4FC,
|
||||
|
||||
MAGIC_2_0 = 0x0A0DC687,
|
||||
MAGIC_2_1 = 0x0A0DEB2A,
|
||||
MAGIC_2_2 = 0x0A0DED2D,
|
||||
MAGIC_2_3 = 0x0A0DF23B,
|
||||
MAGIC_2_4 = 0x0A0DF26D,
|
||||
MAGIC_2_5 = 0x0A0DF2B3,
|
||||
MAGIC_2_6 = 0x0A0DF2D1,
|
||||
MAGIC_2_7 = 0x0A0DF303,
|
||||
|
||||
MAGIC_3_0 = 0x0A0D0C3A,
|
||||
MAGIC_3_1 = 0x0A0D0C4E,
|
||||
MAGIC_3_2 = 0x0A0D0C6C,
|
||||
MAGIC_3_3 = 0x0A0D0C9E,
|
||||
MAGIC_3_4 = 0x0A0D0CEE,
|
||||
MAGIC_3_5 = 0x0A0D0D16,
|
||||
MAGIC_3_5_3 = 0x0A0D0D17,
|
||||
MAGIC_3_6 = 0x0A0D0D33,
|
||||
MAGIC_3_7 = 0x0A0D0D42,
|
||||
MAGIC_3_8 = 0x0A0D0D55,
|
||||
MAGIC_3_9 = 0x0A0D0D61,
|
||||
MAGIC_3_10 = 0x0A0D0D6F,
|
||||
MAGIC_3_11 = 0x0A0D0DA7,
|
||||
|
||||
INVALID = 0,
|
||||
};
|
||||
|
||||
fn getMajor(Magic magic) {
|
||||
match(magic) {
|
||||
(Magic::MAGIC_1_0 | Magic::MAGIC_1_1 | Magic::MAGIC_1_3 | Magic::MAGIC_1_4 | Magic::MAGIC_1_5 | Magic::MAGIC_1_6): return 1;
|
||||
(Magic::MAGIC_2_0 | Magic::MAGIC_2_1 | Magic::MAGIC_2_2 | Magic::MAGIC_2_3 | Magic::MAGIC_2_4 | Magic::MAGIC_2_5 | Magic::MAGIC_2_6 | Magic::MAGIC_2_7): return 2;
|
||||
(Magic::MAGIC_3_0 | Magic::MAGIC_3_1 | Magic::MAGIC_3_2 | Magic::MAGIC_3_3 | Magic::MAGIC_3_4 | Magic::MAGIC_3_5 | Magic::MAGIC_3_5_3 | Magic::MAGIC_3_6 | Magic::MAGIC_3_7 | Magic::MAGIC_3_8 | Magic::MAGIC_3_9 | Magic::MAGIC_3_10 | Magic::MAGIC_3_11): return 3;
|
||||
(Magic::INVALID): return 0;
|
||||
}
|
||||
};
|
||||
|
||||
fn getMinor(Magic magic) {
|
||||
match(magic) {
|
||||
(Magic::MAGIC_1_0 | Magic::MAGIC_2_0 | Magic::MAGIC_3_0): return 0;
|
||||
(Magic::MAGIC_1_1 | Magic::MAGIC_2_1 | Magic::MAGIC_3_1): return 1;
|
||||
(Magic::MAGIC_1_3 | Magic::MAGIC_2_2 | Magic::MAGIC_3_2): return 2;
|
||||
(Magic::MAGIC_1_4 | Magic::MAGIC_2_3 | Magic::MAGIC_3_3): return 3;
|
||||
(Magic::MAGIC_1_5 | Magic::MAGIC_2_4 | Magic::MAGIC_3_4): return 4;
|
||||
(Magic::MAGIC_1_6 | Magic::MAGIC_2_5 | Magic::MAGIC_3_5 | Magic::MAGIC_3_5_3): return 5;
|
||||
(Magic::MAGIC_2_6 | Magic::MAGIC_3_6): return 6;
|
||||
(Magic::MAGIC_2_7 | Magic::MAGIC_3_7): return 7;
|
||||
(Magic::MAGIC_3_8): return 8;
|
||||
(Magic::MAGIC_3_9): return 9;
|
||||
(Magic::MAGIC_3_10): return 10;
|
||||
(Magic::MAGIC_3_11): return 11;
|
||||
(Magic::INVALID): return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct PYCHeader {
|
||||
Magic magic;
|
||||
_major = getMajor(magic);
|
||||
_minor = getMinor(magic);
|
||||
u8 major = _major [[export]];
|
||||
u8 minor = _minor [[export]];
|
||||
|
||||
if(above(3, 7)) {
|
||||
u32 flags;
|
||||
} else {
|
||||
u32 flags;
|
||||
}
|
||||
|
||||
if(flags & 0x1) {
|
||||
u64 checksum;
|
||||
} else {
|
||||
type::time32_t timestamp;
|
||||
|
||||
if(above(3, 3)) {
|
||||
u32 size;
|
||||
}
|
||||
}
|
||||
|
||||
MarshalObject object;
|
||||
};
|
||||
|
||||
PYCHeader header @ 0x0;
|
||||
80
patterns/pyinstaller.hexpat
Normal file
80
patterns/pyinstaller.hexpat
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma description PyInstaller binray files
|
||||
|
||||
#pragma endian big
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
// Reference:
|
||||
// https://pyinstaller.org/en/stable/advanced-topics.html
|
||||
|
||||
// typedef struct _cookie {
|
||||
// char magic[8]; /* 'MEI\014\013\012\013\016' */
|
||||
// uint32_t len; /* len of entire package */
|
||||
// uint32_t TOC; /* pos (rel to start) of TableOfContents */
|
||||
// int TOClen; /* length of TableOfContents */
|
||||
// int pyvers; /* new in v4 */
|
||||
// char pylibname[64]; /* Filename of Python dynamic library. */
|
||||
// } COOKIE;
|
||||
|
||||
u8 cookieStructLength = 88;
|
||||
|
||||
struct Cookie {
|
||||
char signature[8];
|
||||
u32 len;
|
||||
u32 TOC[[comment("Table of Content")]];
|
||||
s32 TOClen;
|
||||
s32 pyVers;
|
||||
char pyLibName[64];
|
||||
};
|
||||
|
||||
u32 cookieOffset = std::mem::find_sequence(0, 'M', 'E', 'I', 0x0C, 0x0B, 0x0A, 0x0B, 0x0E);
|
||||
Cookie cookie @ cookieOffset;
|
||||
|
||||
u32 startOffset = cookieOffset + cookieStructLength - cookie.len;
|
||||
u32 tocOffset = startOffset + cookie.TOC;
|
||||
|
||||
struct ZlibArchive {
|
||||
char pyzMagic[4];
|
||||
char pyMagic[4];
|
||||
u32 pyzTOCPos[[comment("Table of Content of the embedded PYZ")]];
|
||||
};
|
||||
|
||||
// typedef struct _toc {
|
||||
// int structlen; /* len of this one - including full len of name */
|
||||
// uint32_t pos; /* pos rel to start of concatenation */
|
||||
// uint32_t len; /* len of the data (compressed) */
|
||||
// uint32_t ulen; /* len of data (uncompressed) */
|
||||
// char cflag; /* is it compressed (really a byte) */
|
||||
// char typcd; /* type code -'b' binary, 'z' zlib, 'm' module,
|
||||
// * 's' script (v3),'x' data, 'o' runtime option */
|
||||
// char name[1]; /* the name to save it as */
|
||||
// /* starting in v5, we stretch this out to a mult of 16 */
|
||||
// } TOC;
|
||||
|
||||
u32 tocStructLength = 18;
|
||||
|
||||
enum TypeCode : u8 {
|
||||
Binary = 98,
|
||||
Zlib = 122,
|
||||
Module = 109,
|
||||
Script = 115,
|
||||
Data = 120,
|
||||
RuntimeOption = 111,
|
||||
};
|
||||
|
||||
struct TOC {
|
||||
s32 structLen;
|
||||
u32 pos;
|
||||
u32 len[[comment("len of the data (compressed)")]];;
|
||||
u32 uLen[[comment("len of data (uncompressed)")]];;
|
||||
bool cFlag[[comment("is it compressed")]];;
|
||||
TypeCode typcd;
|
||||
char name[this.structLen - tocStructLength];
|
||||
|
||||
if(typcd == TypeCode::Zlib) {
|
||||
ZlibArchive zlibArchive @ startOffset + this.pos;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TOC toc[while( $ < cookie.TOClen + tocOffset)] @ tocOffset;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Qubicle voxel scene project file
|
||||
|
||||
// Qubicle QBCL format
|
||||
|
||||
struct String {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description QOI image files
|
||||
|
||||
#pragma MIME image/qoi
|
||||
#pragma endian big
|
||||
|
||||
|
||||
715
patterns/selinux.hexpat
Normal file
715
patterns/selinux.hexpat
Normal file
@@ -0,0 +1,715 @@
|
||||
#pragma description SE Linux modules
|
||||
|
||||
#include <std/sys.pat>
|
||||
#pragma pattern_limit 13107200
|
||||
#pragma endian little
|
||||
|
||||
u32 version;
|
||||
u32 symbols_count;
|
||||
u32 object_contexts_count;
|
||||
u32 type_primary_names_count = 0;
|
||||
bool boundary_feature;
|
||||
|
||||
using Header;
|
||||
|
||||
enum magics: u32 {
|
||||
kernel = 0xf97cff8c,
|
||||
module = 0xf97cff8d,
|
||||
};
|
||||
|
||||
|
||||
enum policy_types: u32 {
|
||||
kernel = 0,
|
||||
base = 1,
|
||||
module = 2,
|
||||
};
|
||||
|
||||
policy_types type_g;
|
||||
|
||||
enum targets: u32 {
|
||||
selinux = 0,
|
||||
xen = 1,
|
||||
};
|
||||
|
||||
targets target;
|
||||
|
||||
struct list<T> {
|
||||
u32 count;
|
||||
T item[count];
|
||||
};
|
||||
|
||||
struct symbols_list<T> {
|
||||
u32 primary_names_count;
|
||||
list<T> [[inline]];
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct permission {
|
||||
u32 length;
|
||||
u32 value;
|
||||
char key[length];
|
||||
};
|
||||
|
||||
|
||||
struct extensible_bitmap_node {
|
||||
u32 startbit;
|
||||
u64 map;
|
||||
};
|
||||
struct extensible_bitmap {
|
||||
u32 mapsize;
|
||||
std::assert(mapsize == 0x40 , "Incorrect mapsize");
|
||||
u32 highbit;
|
||||
std::assert(!(highbit & 0x3F) , "Incorrect highbit");
|
||||
u32 count;
|
||||
std::assert(!((highbit > 0) && (count == 0)) , "Incorrect bitmap");
|
||||
extensible_bitmap_node node[count];
|
||||
};
|
||||
|
||||
|
||||
struct type_set {
|
||||
extensible_bitmap types;
|
||||
extensible_bitmap negset;
|
||||
u32 flag;
|
||||
};
|
||||
|
||||
enum expression_types: u32 {
|
||||
not = 1,
|
||||
and = 2,
|
||||
or = 3,
|
||||
attr = 4,
|
||||
names = 5,
|
||||
};
|
||||
|
||||
struct expression {
|
||||
expression_types type_;
|
||||
u32 attribute;
|
||||
u32 operator;
|
||||
if (type_ == expression_types::names) {
|
||||
extensible_bitmap names;
|
||||
if ((type_g == policy_types::kernel && version >= 29) ||
|
||||
(type_g != policy_types::kernel))
|
||||
type_set type_names;
|
||||
}
|
||||
};
|
||||
|
||||
struct constraint {
|
||||
u32 permissions;
|
||||
list<expression> [[inline]];
|
||||
};
|
||||
|
||||
struct mls_range {
|
||||
u32 items;
|
||||
u32 sensitivity0;
|
||||
if (items > 1)
|
||||
u32 sensitivity1;
|
||||
extensible_bitmap category0;
|
||||
if (items > 1)
|
||||
extensible_bitmap category1;
|
||||
};
|
||||
|
||||
struct role_set {
|
||||
extensible_bitmap roles;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct mls_level {
|
||||
u32 sensitivity;
|
||||
extensible_bitmap category;
|
||||
};
|
||||
|
||||
struct semantic_category {
|
||||
u32 low;
|
||||
u32 high;
|
||||
};
|
||||
|
||||
struct mls_semantic_level {
|
||||
u32 sensitivity;
|
||||
list<semantic_category> [[inline]];
|
||||
};
|
||||
|
||||
struct mls_semantic_range {
|
||||
mls_semantic_level level0;
|
||||
mls_semantic_level level1;
|
||||
};
|
||||
|
||||
|
||||
struct context_s {
|
||||
u32 user;
|
||||
u32 role;
|
||||
u32 type_;
|
||||
if (((type_g == policy_types::kernel) && (version >= 19)) || ((type_g == policy_types::base) && (version >= 5)))
|
||||
mls_range mls_range;
|
||||
};
|
||||
|
||||
|
||||
struct common {
|
||||
u32 length;
|
||||
u32 value;
|
||||
u32 primary_names_count;
|
||||
u32 elements_count;
|
||||
char key[length];
|
||||
permission permission[elements_count];
|
||||
};
|
||||
using commons = symbols_list<common>;
|
||||
|
||||
struct class {
|
||||
u32 key_length;
|
||||
u32 common_key_length;
|
||||
u32 value;
|
||||
u32 primary_names_count;
|
||||
u32 elements_count;
|
||||
u32 constraints_count;
|
||||
char key[key_length];
|
||||
char common_key[common_key_length];
|
||||
permission permissions[elements_count];
|
||||
constraint constraints[constraints_count];
|
||||
if (((type_g == policy_types::kernel) && (version >= 19)) || (type_g == policy_types::base && version >= 5))
|
||||
u32 validatetrans_count;
|
||||
if ((type_g == policy_types::kernel && version >= 19) || (type_g == policy_types::base && version >= 5))
|
||||
constraint validatetrans[validatetrans_count];
|
||||
if ((type_g == policy_types::kernel && version >= 27) || (type_g == policy_types::base && version >= 15)) {
|
||||
u32 default_user;
|
||||
u32 default_role;
|
||||
u32 default_range;
|
||||
}
|
||||
if ((type_g == policy_types::kernel && version >= 28) || (type_g == policy_types::base && version >= 16))
|
||||
u32 default_type;
|
||||
};
|
||||
using classes = symbols_list<class>;
|
||||
|
||||
|
||||
struct role_s {
|
||||
u32 length;
|
||||
u32 value;
|
||||
u32 bounds;
|
||||
char key[length];
|
||||
extensible_bitmap dominates;
|
||||
if (type_g == policy_types::kernel)
|
||||
extensible_bitmap types;
|
||||
else
|
||||
type_set types;
|
||||
if ((type_g != policy_types::kernel && version >= 13)) {
|
||||
u32 flavor;
|
||||
extensible_bitmap roles;
|
||||
}
|
||||
};
|
||||
using roles = symbols_list<role_s>;
|
||||
|
||||
|
||||
struct type_s {
|
||||
u32 length;
|
||||
u32 value;
|
||||
if ((boundary_feature && (type_g != policy_types::kernel && version >= 10)) || !boundary_feature)
|
||||
u32 primary;
|
||||
if (boundary_feature) {
|
||||
u32 properties;
|
||||
u32 bounds;
|
||||
}
|
||||
if (!boundary_feature && (type_g != policy_types::kernel))
|
||||
u32 flavor;
|
||||
if (!boundary_feature && (type_g != policy_types::kernel && version >= 8))
|
||||
u32 flags;
|
||||
if (type_g != policy_types::kernel)
|
||||
extensible_bitmap types;
|
||||
char key[length];
|
||||
};
|
||||
struct types_s {
|
||||
u32 primary_names_count;
|
||||
type_primary_names_count = primary_names_count;
|
||||
list<type_s> [[inline]];
|
||||
};
|
||||
|
||||
struct user_s {
|
||||
u32 length;
|
||||
u32 value;
|
||||
if (boundary_feature)
|
||||
u32 bounds;
|
||||
char key[length];
|
||||
|
||||
if (type_g == policy_types::kernel)
|
||||
extensible_bitmap roles;
|
||||
else
|
||||
role_set roles;
|
||||
|
||||
if ((type_g == policy_types::kernel && version >= 19) || (type_g == policy_types::module && version >= 5 && version < 6) || (type_g == policy_types::base && version >= 5 && version < 6)) {
|
||||
mls_range exp_range;
|
||||
mls_level exp_dftlevel;
|
||||
}
|
||||
|
||||
if ((type_g == policy_types::module || type_g == policy_types::base) && (version >= 6)) {
|
||||
mls_semantic_range range;
|
||||
mls_semantic_range dfltlevel;
|
||||
}
|
||||
};
|
||||
using users = symbols_list<user_s>;
|
||||
|
||||
struct bool_ { // conditional boolean
|
||||
u32 value;
|
||||
u32 state;
|
||||
u32 length;
|
||||
char key[length];
|
||||
if ((type_g != policy_types::kernel && version >= 14))
|
||||
u32 flags;
|
||||
};
|
||||
using bools = symbols_list<bool_>;
|
||||
|
||||
struct level {
|
||||
u32 length;
|
||||
u32 isalias;
|
||||
char key[length];
|
||||
mls_level level;
|
||||
};
|
||||
using sensitivity_levels = symbols_list<level>;
|
||||
|
||||
struct category {
|
||||
u32 length;
|
||||
u32 value;
|
||||
u32 isalias;
|
||||
char key[length];
|
||||
};
|
||||
using categories = symbols_list<category>;
|
||||
|
||||
|
||||
struct symbols {
|
||||
commons commons;
|
||||
classes classes;
|
||||
roles roles;
|
||||
types_s types;
|
||||
users users;
|
||||
if (symbols_count >= 6)
|
||||
bools bools;
|
||||
if (symbols_count >= 7)
|
||||
sensitivity_levels levels;
|
||||
if (symbols_count >= 8)
|
||||
categories cats;
|
||||
};
|
||||
|
||||
struct module_header {
|
||||
u32 name_length;
|
||||
std::assert(name_length >= 1, "Invalid 'name_length' in module header.");
|
||||
char name[name_length];
|
||||
u32 version_length;
|
||||
std::assert(version_length >= 1, "Invalid 'version_length' in module header.");
|
||||
char version[version_length];
|
||||
};
|
||||
|
||||
|
||||
struct access_vector_old {
|
||||
u32 total;
|
||||
u32 source_type;
|
||||
u32 target_type;
|
||||
u32 target_class;
|
||||
u32 value;
|
||||
u32 data[8];
|
||||
};
|
||||
struct access_vector {
|
||||
u16 source_type;
|
||||
u16 target_type;
|
||||
u16 target_class;
|
||||
u16 specified;
|
||||
|
||||
if ((specified & 0x700) != 0) {
|
||||
u8 xperms_specified;
|
||||
u8 xperms_drivers;
|
||||
u32 xperms_perms[8];
|
||||
}
|
||||
else
|
||||
u32 data;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct avrule_item {
|
||||
u32 tclass;
|
||||
u32 data;
|
||||
};
|
||||
struct avrule {
|
||||
u32 specified;
|
||||
u32 flags;
|
||||
type_set stypes;
|
||||
type_set ttypes;
|
||||
|
||||
u32 length;
|
||||
avrule_item avrule_item[length];
|
||||
|
||||
if ((specified & (0x0100 | 0x0200 | 0x0400 | 0x0800)) != 0) {
|
||||
u8 xperms_specified;
|
||||
u8 xperms_driver;
|
||||
|
||||
list<u32> perms[[inline]];
|
||||
}
|
||||
};
|
||||
struct avrule_list {
|
||||
u32 length;
|
||||
avrule avrule[length];
|
||||
};
|
||||
|
||||
|
||||
struct conditional_node_item {
|
||||
u32 expr_type;
|
||||
u32 boolean;
|
||||
};
|
||||
|
||||
struct access_vector_table_s {
|
||||
if (version < 20)
|
||||
list<access_vector_old> access_vector_table;
|
||||
else
|
||||
list<access_vector> access_vector_table;
|
||||
} [[inline]];
|
||||
|
||||
using cond_av_list = access_vector_table_s;
|
||||
|
||||
struct conditional_node {
|
||||
u32 current_state;
|
||||
u32 length;
|
||||
conditional_node_item item[length];
|
||||
|
||||
if (type_g == policy_types::kernel) {
|
||||
cond_av_list true_list;
|
||||
cond_av_list false_list;
|
||||
} else {
|
||||
avrule_list avtrue_list;
|
||||
avrule_list avfalse_list;
|
||||
if (version >= 14)
|
||||
u32 flags;
|
||||
}
|
||||
};
|
||||
struct conditional_list {
|
||||
u32 length;
|
||||
conditional_node conditional_node[length];
|
||||
};
|
||||
|
||||
|
||||
struct role_trans_item {
|
||||
u32 role;
|
||||
u32 type_;
|
||||
u32 new_role;
|
||||
if (type_g == policy_types::kernel && version >= 26)
|
||||
u32 tclass;
|
||||
};
|
||||
using role_trans = list<role_trans_item>;
|
||||
|
||||
struct role_allow_item {
|
||||
u32 role;
|
||||
u32 new_role;
|
||||
};
|
||||
using role_allow = list<role_allow_item>;
|
||||
|
||||
struct filename_trans_item_old {
|
||||
u32 length;
|
||||
char name[length];
|
||||
u32 stype;
|
||||
u32 ttype;
|
||||
u32 tclass;
|
||||
u32 otype;
|
||||
};
|
||||
struct filename_trans_item_item {
|
||||
extensible_bitmap stypes;
|
||||
u32 otype;
|
||||
};
|
||||
struct filename_trans_item {
|
||||
u32 length;
|
||||
char name[length];
|
||||
u32 ttype;
|
||||
u32 tclass;
|
||||
list<filename_trans_item_item> types [[inline]];
|
||||
};
|
||||
|
||||
|
||||
struct role_trans_rule_item {
|
||||
role_set roles;
|
||||
role_set types;
|
||||
if (version >= 12)
|
||||
extensible_bitmap classes;
|
||||
u32 new_role;
|
||||
};
|
||||
using role_trans_rule = list<role_trans_rule_item>;
|
||||
|
||||
struct role_allow_rule_item {
|
||||
role_set roles;
|
||||
role_set new_roles;
|
||||
};
|
||||
using role_allow_rule = list<role_allow_rule_item>;
|
||||
|
||||
|
||||
struct scope_s {
|
||||
u32 length;
|
||||
char key[length];
|
||||
|
||||
u32 scope;
|
||||
|
||||
u32 decl_ids_len;
|
||||
std::assert(decl_ids_len >= 1, "Invalid 'decl_ids_len'");
|
||||
u32 decl_id[decl_ids_len];
|
||||
};
|
||||
struct scope_index {
|
||||
extensible_bitmap scope[symbols_count];
|
||||
u32 class_perms_len;
|
||||
extensible_bitmap class_perms_map[class_perms_len];
|
||||
};
|
||||
using scope_list = list<scope_s>;
|
||||
|
||||
|
||||
struct filename_trans_rule_item {
|
||||
u32 length;
|
||||
char name[length];
|
||||
type_set stypes;
|
||||
type_set ttypes;
|
||||
u32 tclass;
|
||||
u32 otype;
|
||||
|
||||
if (version >= 21)
|
||||
u32 flags;
|
||||
};
|
||||
using filename_trans_rule = list<filename_trans_rule_item>;
|
||||
|
||||
|
||||
struct range_trans_rule_item {
|
||||
type_set stypes;
|
||||
type_set ttypes;
|
||||
extensible_bitmap tclasses;
|
||||
mls_semantic_range trange;
|
||||
};
|
||||
using range_trans_rule = list<range_trans_rule_item>;
|
||||
|
||||
struct avrule_decl {
|
||||
u32 decl_id;
|
||||
u32 enabled;
|
||||
conditional_list cond_list;
|
||||
avrule_list avrules;
|
||||
role_trans_rule role_tr_rules;
|
||||
role_allow_rule role_allow_rules;
|
||||
|
||||
if (version >= 11)
|
||||
filename_trans_rule filename_trans_rules;
|
||||
|
||||
if (version >= 6)
|
||||
range_trans_rule range_tr_rules;
|
||||
scope_index required;
|
||||
scope_index declared;
|
||||
symbols symbols;
|
||||
};
|
||||
|
||||
struct avrule_block_item {
|
||||
u32 num_decls;
|
||||
if (num_decls > 0)
|
||||
avrule_decl avrule_decl[num_decls];
|
||||
};
|
||||
using avrule_block = list<avrule_block_item>;
|
||||
|
||||
|
||||
struct initial_sid {
|
||||
u32 sid0;
|
||||
context_s context0;
|
||||
};
|
||||
struct filesystem {
|
||||
u32 length;
|
||||
char key[length];
|
||||
context_s context0;
|
||||
context_s context1;
|
||||
};
|
||||
struct port {
|
||||
u32 protocol;
|
||||
u32 low_port;
|
||||
u32 high_port;
|
||||
context_s context;
|
||||
};
|
||||
struct node {
|
||||
u32 addr;
|
||||
u32 mask;
|
||||
context_s context;
|
||||
};
|
||||
struct fsuse {
|
||||
u32 behavior;
|
||||
u32 length;
|
||||
char name[length];
|
||||
context_s context;
|
||||
};
|
||||
struct node6 {
|
||||
u32 addr[4];
|
||||
u32 mask[4];
|
||||
context_s context;
|
||||
};
|
||||
struct ibpkey {
|
||||
u32 low_pkey;
|
||||
u32 high_pkey;
|
||||
context_s context;
|
||||
};
|
||||
struct ibpendport {
|
||||
u32 length;
|
||||
u32 port;
|
||||
char dev_name[length];
|
||||
context_s context;
|
||||
};
|
||||
|
||||
|
||||
struct ocontext_selinux {
|
||||
if (object_contexts_count < 1) break;
|
||||
list<initial_sid> initial_sids;
|
||||
if (object_contexts_count < 2) break;
|
||||
list<filesystem> filesystems;
|
||||
if (object_contexts_count < 3) break;
|
||||
list<port> ports;
|
||||
if (object_contexts_count < 4) break;
|
||||
list<filesystem> network_interfaces; // same type
|
||||
if (object_contexts_count < 5) break;
|
||||
list<node> nodes;
|
||||
if (object_contexts_count < 6) break;
|
||||
list<fsuse> fsuses;
|
||||
if (object_contexts_count < 7) break;
|
||||
list<node6> nodes6;
|
||||
if (object_contexts_count < 8) break;
|
||||
list<ibpkey> ibpkeys;
|
||||
if (object_contexts_count < 9) break;
|
||||
list<ibpendport> ibpendports;
|
||||
};
|
||||
|
||||
|
||||
struct xen_isid {
|
||||
u32 sid0;
|
||||
context_s context0;
|
||||
};
|
||||
|
||||
struct xen_pirq {
|
||||
u32 pirq;
|
||||
context_s context0;
|
||||
};
|
||||
|
||||
struct xen_ioport {
|
||||
u32 low_port;
|
||||
u32 high_port;
|
||||
context_s context0;
|
||||
};
|
||||
|
||||
struct xen_iomem {
|
||||
if (version >= 30) {
|
||||
u64 low_iomem;
|
||||
u64 high_iomem;
|
||||
} else {
|
||||
u32 low_iomem;
|
||||
u32 high_iomem;
|
||||
}
|
||||
context_s context;
|
||||
};
|
||||
|
||||
struct xen_pcidevice {
|
||||
u32 device;
|
||||
context_s context;
|
||||
};
|
||||
|
||||
struct xen_devicetree {
|
||||
u32 length;
|
||||
char name[length];
|
||||
context_s context;
|
||||
};
|
||||
|
||||
|
||||
struct ocontext_xen {
|
||||
if (object_contexts_count < 1) break;
|
||||
list<xen_isid> xen_isids;
|
||||
if (object_contexts_count < 2) break;
|
||||
list<xen_pirq> xen_pirqs;
|
||||
if (object_contexts_count < 3) break;
|
||||
list<xen_ioport> xen_ioports;
|
||||
if (object_contexts_count < 4) break;
|
||||
list<xen_iomem> xen_iomems;
|
||||
if (object_contexts_count < 5) break;
|
||||
list<xen_pcidevice> xen_pcidevices;
|
||||
if (object_contexts_count < 6) break;
|
||||
list<xen_devicetree> xen_devicetrees;
|
||||
if (object_contexts_count < 7) break;
|
||||
};
|
||||
|
||||
|
||||
struct genfs2_item {
|
||||
u32 length;
|
||||
char name[length];
|
||||
u32 sclass;
|
||||
context_s context0;
|
||||
};
|
||||
struct genfs_item {
|
||||
u32 length;
|
||||
char fstype[length];
|
||||
list<genfs2_item> [[inline]];
|
||||
};
|
||||
|
||||
struct range_item {
|
||||
u32 source_type;
|
||||
u32 target_type;
|
||||
if (type_g == policy_types::kernel && version >= 21)
|
||||
u32 target_class;
|
||||
mls_range range_tr;
|
||||
};
|
||||
|
||||
struct Header {
|
||||
magics magic;
|
||||
std::assert(magic == magics::kernel || magic == magics::module , "Unexpected magic");
|
||||
u32 policydb_str_len;
|
||||
char policydb_str[policydb_str_len];
|
||||
std::assert(policydb_str == "SE Linux" || policydb_str == "SE Linux Module" || policydb_str == "XenFlask", "Unexpected signature");
|
||||
if (policydb_str == "XenFlask")
|
||||
target = targets::xen;
|
||||
else
|
||||
target = targets::selinux;
|
||||
std::assert((magic == magics::kernel && (policydb_str == "SE Linux" || policydb_str == "XenFlask"))
|
||||
|| (magic == magics::module && policydb_str == "SE Linux Module"), "Non matching magic and signature");
|
||||
if (magic == magics::module)
|
||||
u32 policy_subtype;
|
||||
if (magic == magics::kernel)
|
||||
type_g = policy_types::kernel;
|
||||
else
|
||||
if (policy_subtype == policy_types::module)
|
||||
type_g = policy_types::module;
|
||||
else
|
||||
type_g = policy_types::base;
|
||||
u32 __policyvers;
|
||||
version = __policyvers;
|
||||
boundary_feature = (type_g == policy_types::kernel && version >= 24) || (type_g != policy_types::kernel && version >= 9);
|
||||
std::assert((magic == magics::kernel && 15 <= version && version <= 33) || (magic != magics::kernel && 4 <= version && version <= 21), "Non matching type_g != and type");
|
||||
u32 config;
|
||||
u32 symbols_count_;
|
||||
symbols_count = symbols_count_;
|
||||
std::assert(0 <= symbols_count && symbols_count <= 9, "Invalid 'symbols_count' value.");
|
||||
u32 object_contexts_count_;
|
||||
object_contexts_count = object_contexts_count_;
|
||||
std::assert(0 <= object_contexts_count && object_contexts_count <= 9, "Invalid 'object_contexts_count' value.");
|
||||
if (magic == magics::module)
|
||||
module_header module_header;
|
||||
|
||||
if ((type_g == policy_types::kernel && version >= 22) || (version >= 7))
|
||||
extensible_bitmap policycaps;
|
||||
if (type_g == policy_types::kernel && version >= 23)
|
||||
extensible_bitmap permissive_map;
|
||||
symbols symbols;
|
||||
if (type_g == policy_types::kernel) {
|
||||
access_vector_table_s access_vector_table;
|
||||
}
|
||||
if (type_g == policy_types::kernel && version >= 16)
|
||||
conditional_list conditional_list;
|
||||
if (type_g == policy_types::kernel) {
|
||||
role_trans role_trans;
|
||||
role_allow role_allow;
|
||||
if (version >= 25) {
|
||||
if (version < 33)
|
||||
list<filename_trans_item_old> filename_trans;
|
||||
else
|
||||
list<filename_trans_item> filename_trans;
|
||||
}
|
||||
} else {
|
||||
list<avrule_block_item> avrule_block;
|
||||
list<scope_s> scope_list[symbols_count];
|
||||
}
|
||||
if (target == targets::selinux)
|
||||
ocontext_selinux ocontext_selinux;
|
||||
else
|
||||
ocontext_xen ocontext_xen;
|
||||
list<genfs_item> genfs;
|
||||
if (((type_g == policy_types::kernel) && (version >= 19)) || ((type_g == policy_types::base) && (version == 5)))
|
||||
list<range_item> range;
|
||||
if (type_g == policy_types::kernel)
|
||||
extensible_bitmap type_attr_map[type_primary_names_count];
|
||||
};
|
||||
|
||||
|
||||
Header header @ 0;
|
||||
30
patterns/selinuxpp.hexpat
Normal file
30
patterns/selinuxpp.hexpat
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma description SE Linux package
|
||||
|
||||
// SE Linux Policy Package
|
||||
// Extension: PP
|
||||
// https://github.com/SELinuxProject/selinux/blob/master/libsepol/src/module.c
|
||||
|
||||
#pragma endian little
|
||||
#include <std/sys.pat>
|
||||
|
||||
enum section_types : u32 {
|
||||
file_context = 0xf97cff90,
|
||||
module = 0xf97cff8d,
|
||||
user = 0x097cff91,
|
||||
user_extra = 0x097cff92,
|
||||
netfilter = 0x097cff93,
|
||||
};
|
||||
|
||||
struct section_s {
|
||||
section_types *type : u32;
|
||||
};
|
||||
|
||||
struct header_s {
|
||||
u32 magic;
|
||||
std::assert(magic == 0xf97cff8f, "invalid magic");
|
||||
u32 version;
|
||||
u32 sections_count;
|
||||
section_s sections[sections_count];
|
||||
};
|
||||
|
||||
header_s header @ 0x00;
|
||||
@@ -1,115 +1,118 @@
|
||||
// Based on https://github.com/mietek/theunarchiver/wiki/StuffIt5Format and https://github.com/ParksProjets/Maconv/blob/master/docs/stuffit/Stuffit_v5.md
|
||||
|
||||
#pragma endian big
|
||||
#pragma MIME application/x-stuffit
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/time.pat>
|
||||
|
||||
namespace v5 {
|
||||
|
||||
bitfield Flags1 {
|
||||
padding : 1;
|
||||
folder : 1;
|
||||
encrypted : 1;
|
||||
padding : 5;
|
||||
};
|
||||
|
||||
bitfield Flags2 {
|
||||
padding : 7;
|
||||
resource_fork : 1;
|
||||
padding : 8;
|
||||
};
|
||||
|
||||
using MacOSHFSPlusDate = u32 [[format("v5::format_macos_date")]];
|
||||
|
||||
fn format_macos_date(MacOSHFSPlusDate date) {
|
||||
return std::time::format(std::time::to_utc(date - 2082844800));
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char magic[0x50];
|
||||
u32 unknown1;
|
||||
u32 archiveSize;
|
||||
u32 entriesOffset;
|
||||
u32 unknown2;
|
||||
};
|
||||
|
||||
struct EntryHeader {
|
||||
u32 magic;
|
||||
u8 version;
|
||||
u8 unknown1;
|
||||
u16 headerSize;
|
||||
u8 unknown2;
|
||||
Flags1 flags;
|
||||
MacOSHFSPlusDate creationDate, modificationDate;
|
||||
u32 prevEntryOffset, nextEntryOffset, parentEntryOffset;
|
||||
u16 nameSize;
|
||||
u16 headerChecksum;
|
||||
|
||||
u32 dataForkUncompressedLength, dataForkCompressedLength;
|
||||
u16 dataForkChecksum;
|
||||
u16 unknown3;
|
||||
};
|
||||
|
||||
enum CompressionMethod : u8 {
|
||||
None = 0x00, // No compression
|
||||
Rle90 = 0x01, // Run length encoding
|
||||
Compress = 0x02, // Compress LZW algorithm, 14 bit max code length, block mode
|
||||
StuffIt3 = 0x03, // Simple Huffman encoding for individual bytes
|
||||
StuffIt5 = 0x05, // LZAH
|
||||
StuffIt8 = 0x08, // Miller-Wegman
|
||||
StuffIt13 = 0x0D, // LZSS and Huffman
|
||||
Stuffit14 = 0x0E, // Unknown
|
||||
StuffItArsenic = 0x0F // BWT and arithmetic coding
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
EntryHeader header;
|
||||
if (header.flags.folder) {
|
||||
u16 numFiles;
|
||||
|
||||
if (header.dataForkUncompressedLength)
|
||||
std::print("Folder entry {} is special!", std::core::array_index());
|
||||
} else {
|
||||
CompressionMethod compressionMethod;
|
||||
}
|
||||
|
||||
u8 passwordDataLength;
|
||||
u8 passwordInformation[passwordDataLength];
|
||||
char fileName[header.nameSize];
|
||||
u16 commentSize;
|
||||
u16 unknown2;
|
||||
char comment[commentSize];
|
||||
|
||||
if (!header.flags.folder) {
|
||||
Flags2 flags;
|
||||
u16 unknown3;
|
||||
char fileType[4];
|
||||
u32 fileCreator;
|
||||
u16 macOSFinderFlags;
|
||||
u32 unknown4;
|
||||
u32 unknown5;
|
||||
u8 unknown6[6];
|
||||
|
||||
if (header.version == 1)
|
||||
u32 unknown7;
|
||||
|
||||
u8 compressedData[header.dataForkCompressedLength] [[sealed]];
|
||||
|
||||
if (header.nextEntryOffset == 0x00)
|
||||
break;
|
||||
else
|
||||
$ = header.nextEntryOffset;
|
||||
}
|
||||
};
|
||||
|
||||
struct StuffIt {
|
||||
Header header;
|
||||
|
||||
Entry entries[while(true)] @ header.entriesOffset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description StuffIt V5 archive
|
||||
|
||||
// Based on https://github.com/mietek/theunarchiver/wiki/StuffIt5Format and https://github.com/ParksProjets/Maconv/blob/master/docs/stuffit/Stuffit_v5.md
|
||||
|
||||
#pragma endian big
|
||||
#pragma MIME application/x-stuffit
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/time.pat>
|
||||
|
||||
namespace v5 {
|
||||
|
||||
bitfield Flags1 {
|
||||
padding : 1;
|
||||
folder : 1;
|
||||
encrypted : 1;
|
||||
padding : 5;
|
||||
};
|
||||
|
||||
bitfield Flags2 {
|
||||
padding : 7;
|
||||
resource_fork : 1;
|
||||
padding : 8;
|
||||
};
|
||||
|
||||
using MacOSHFSPlusDate = u32 [[format("v5::format_macos_date")]];
|
||||
|
||||
fn format_macos_date(MacOSHFSPlusDate date) {
|
||||
return std::time::format(std::time::to_utc(date - 2082844800));
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char magic[0x50];
|
||||
u32 unknown1;
|
||||
u32 archiveSize;
|
||||
u32 entriesOffset;
|
||||
u32 unknown2;
|
||||
};
|
||||
|
||||
struct EntryHeader {
|
||||
u32 magic;
|
||||
u8 version;
|
||||
u8 unknown1;
|
||||
u16 headerSize;
|
||||
u8 unknown2;
|
||||
Flags1 flags;
|
||||
MacOSHFSPlusDate creationDate, modificationDate;
|
||||
u32 prevEntryOffset, nextEntryOffset, parentEntryOffset;
|
||||
u16 nameSize;
|
||||
u16 headerChecksum;
|
||||
|
||||
u32 dataForkUncompressedLength, dataForkCompressedLength;
|
||||
u16 dataForkChecksum;
|
||||
u16 unknown3;
|
||||
};
|
||||
|
||||
enum CompressionMethod : u8 {
|
||||
None = 0x00, // No compression
|
||||
Rle90 = 0x01, // Run length encoding
|
||||
Compress = 0x02, // Compress LZW algorithm, 14 bit max code length, block mode
|
||||
StuffIt3 = 0x03, // Simple Huffman encoding for individual bytes
|
||||
StuffIt5 = 0x05, // LZAH
|
||||
StuffIt8 = 0x08, // Miller-Wegman
|
||||
StuffIt13 = 0x0D, // LZSS and Huffman
|
||||
Stuffit14 = 0x0E, // Unknown
|
||||
StuffItArsenic = 0x0F // BWT and arithmetic coding
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
EntryHeader header;
|
||||
if (header.flags.folder) {
|
||||
u16 numFiles;
|
||||
|
||||
if (header.dataForkUncompressedLength)
|
||||
std::print("Folder entry {} is special!", std::core::array_index());
|
||||
} else {
|
||||
CompressionMethod compressionMethod;
|
||||
}
|
||||
|
||||
u8 passwordDataLength;
|
||||
u8 passwordInformation[passwordDataLength];
|
||||
char fileName[header.nameSize];
|
||||
u16 commentSize;
|
||||
u16 unknown2;
|
||||
char comment[commentSize];
|
||||
|
||||
if (!header.flags.folder) {
|
||||
Flags2 flags;
|
||||
u16 unknown3;
|
||||
char fileType[4];
|
||||
u32 fileCreator;
|
||||
u16 macOSFinderFlags;
|
||||
u32 unknown4;
|
||||
u32 unknown5;
|
||||
u8 unknown6[6];
|
||||
|
||||
if (header.version == 1)
|
||||
u32 unknown7;
|
||||
|
||||
u8 compressedData[header.dataForkCompressedLength] [[sealed]];
|
||||
|
||||
if (header.nextEntryOffset == 0x00)
|
||||
break;
|
||||
else
|
||||
$ = header.nextEntryOffset;
|
||||
}
|
||||
};
|
||||
|
||||
struct StuffIt {
|
||||
Header header;
|
||||
|
||||
Entry entries[while(true)] @ header.entriesOffset;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
v5::StuffIt stuffIt @ 0x00;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description SPIR-V header and instructions
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
enum GeneratorID : u16 {
|
||||
|
||||
@@ -1,51 +1,54 @@
|
||||
#pragma MIME model/stl
|
||||
#pragma MIME model/x.stl-binary
|
||||
#pragma MIME model/x.stl-ascii
|
||||
#pragma MIME application/sla
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/core.pat>
|
||||
|
||||
struct Vector3f {
|
||||
float x, y, z;
|
||||
} [[static, format("format_vector3f")]];
|
||||
|
||||
fn format_vector3f(Vector3f vec) {
|
||||
return std::format("[ {}, {}, {} ]", vec.x, vec.y, vec.z);
|
||||
};
|
||||
|
||||
struct Triangle {
|
||||
Vector3f normal;
|
||||
Vector3f points[3];
|
||||
u16 flags;
|
||||
} [[static]];
|
||||
|
||||
struct BinarySTLHeader {
|
||||
char caption[while($[$] != 0x00 && $ - addressof(this) < 80)];
|
||||
padding[80 - sizeof(caption)];
|
||||
u32 triangleCount;
|
||||
};
|
||||
|
||||
struct STL {
|
||||
if (std::mem::read_string(0, 6) == "solid ")
|
||||
std::warning("ASCII STL file!");
|
||||
else {
|
||||
BinarySTLHeader header;
|
||||
Triangle triangles[header.triangleCount];
|
||||
}
|
||||
};
|
||||
|
||||
STL stl @ 0x00;
|
||||
|
||||
/* Visualize the 3D Model */
|
||||
|
||||
struct Vertex {
|
||||
Vector3f points[3] @ addressof(stl.triangles[std::core::array_index()].points);
|
||||
};
|
||||
|
||||
struct Model {
|
||||
Vertex vertices[stl.header.triangleCount];
|
||||
} [[highlight_hidden, sealed, hex::visualize("3d", vertices, null)]];
|
||||
|
||||
Model model @ 0x00;
|
||||
#pragma author WerWolv
|
||||
#pragma description STL 3D Model format
|
||||
|
||||
#pragma MIME model/stl
|
||||
#pragma MIME model/x.stl-binary
|
||||
#pragma MIME model/x.stl-ascii
|
||||
#pragma MIME application/sla
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/core.pat>
|
||||
|
||||
struct Vector3f {
|
||||
float x, y, z;
|
||||
} [[static, format("format_vector3f")]];
|
||||
|
||||
fn format_vector3f(Vector3f vec) {
|
||||
return std::format("[ {}, {}, {} ]", vec.x, vec.y, vec.z);
|
||||
};
|
||||
|
||||
struct Triangle {
|
||||
Vector3f normal;
|
||||
Vector3f points[3];
|
||||
u16 flags;
|
||||
} [[static]];
|
||||
|
||||
struct BinarySTLHeader {
|
||||
char caption[while($[$] != 0x00 && $ - addressof(this) < 80)];
|
||||
padding[80 - sizeof(caption)];
|
||||
u32 triangleCount;
|
||||
};
|
||||
|
||||
struct STL {
|
||||
if (std::mem::read_string(0, 6) == "solid ")
|
||||
std::warning("ASCII STL file!");
|
||||
else {
|
||||
BinarySTLHeader header;
|
||||
Triangle triangles[header.triangleCount];
|
||||
}
|
||||
};
|
||||
|
||||
STL stl @ 0x00;
|
||||
|
||||
/* Visualize the 3D Model */
|
||||
|
||||
struct Vertex {
|
||||
Vector3f points[3] @ addressof(stl.triangles[std::core::array_index()].points);
|
||||
};
|
||||
|
||||
struct Model {
|
||||
Vertex vertices[stl.header.triangleCount];
|
||||
} [[highlight_hidden, sealed, hex::visualize("3d", vertices, null)]];
|
||||
|
||||
Model model @ 0x00;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Tar file format
|
||||
|
||||
#pragma MIME application/tar
|
||||
#pragma MIME application/x-tar
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Truevision TGA/TARGA image
|
||||
|
||||
#pragma MIME image/tga
|
||||
#pragma endian little
|
||||
|
||||
@@ -75,5 +77,6 @@ struct Footer {
|
||||
char zero;
|
||||
};
|
||||
|
||||
u8 visualizer[std::mem::size()] @ 0x00 [[sealed, hex::visualize("image", this)]];
|
||||
Header header @ 0x0;
|
||||
Footer footer @ std::mem::size() - 0x1A;
|
||||
|
||||
256
patterns/tiff.hexpat
Normal file
256
patterns/tiff.hexpat
Normal file
@@ -0,0 +1,256 @@
|
||||
#pragma description Tag Image File Format
|
||||
|
||||
#pragma MIME image/tiff
|
||||
|
||||
#pragma eval_depth 100
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
#include <std/string.pat>
|
||||
#include <std/core.pat>
|
||||
|
||||
char Magic[2] @ 0 [[hidden]];
|
||||
match (Magic) {
|
||||
("II"): std::core::set_endian(std::mem::Endian::Little);
|
||||
("MM"): std::core::set_endian(std::mem::Endian::Big);
|
||||
(_): std::error(std::format("Unrecognized magic number: {}", Magic));
|
||||
}
|
||||
|
||||
u16 Version @ 2 [[hidden]];
|
||||
u32 ValueOffsetSize;
|
||||
match (Version) {
|
||||
(42): ValueOffsetSize = 4;
|
||||
(43): ValueOffsetSize = 8;
|
||||
(_): std::error(std::format("Unrecognized version: {}", Version));
|
||||
}
|
||||
struct Big<T> {
|
||||
match (Version) {
|
||||
(42): T V;
|
||||
(43): u64 V;
|
||||
(_): std::error(std::format("Unrecognized version: {}", Version));
|
||||
}
|
||||
} [[sealed, format_read("format_read_big"), format_write("format_write_big"), transform("transform_big")]];
|
||||
fn format_read_big(Big<u32> v) {
|
||||
return std::format("{} (0x{:X})", v, v);
|
||||
};
|
||||
fn format_write_big(str v) {
|
||||
return std::string::parse_int(v, 0);
|
||||
};
|
||||
fn transform_big(Big<u32> v) {
|
||||
return v.V;
|
||||
};
|
||||
|
||||
struct TIFFHeader {
|
||||
char Magic[2];
|
||||
u16 Version;
|
||||
if (Version > 42) {
|
||||
u16 OffsetSize;
|
||||
padding[2];
|
||||
}
|
||||
Big<u32> Offset;
|
||||
};
|
||||
|
||||
enum TIFFFieldType : u16 {
|
||||
BYTE = 1,
|
||||
ASCII = 2,
|
||||
SHORT = 3,
|
||||
LONG = 4,
|
||||
RATIONAL = 5,
|
||||
SBYTE = 6,
|
||||
UNDEFINED = 7,
|
||||
SSHORT = 8,
|
||||
SLONG = 9,
|
||||
SRATIONAL = 10,
|
||||
FLOAT = 11,
|
||||
DOUBLE = 12,
|
||||
LONG8 = 16,
|
||||
SLONG8 = 17,
|
||||
};
|
||||
|
||||
struct TIFFRational<T> {
|
||||
T Numerator;
|
||||
T Denominator;
|
||||
} [[format_read("format_read_rational")]];
|
||||
|
||||
fn format_read_rational(auto r) {
|
||||
return std::format("{}/{}", r.Numerator, r.Denominator);
|
||||
};
|
||||
|
||||
enum TIFFTag : u16 {
|
||||
NewSubfileType = 0x00FE,
|
||||
SubfileType = 0x00FF,
|
||||
ImageWidth = 0x0100,
|
||||
ImageLength = 0x0101,
|
||||
BitsPerSample = 0x0102,
|
||||
Compression = 0x0103,
|
||||
PhotometricInterpretation = 0x0106,
|
||||
Threshholding = 0x0107,
|
||||
CellWidth = 0x0108,
|
||||
CellLength = 0x0109,
|
||||
FillOrder = 0x010A,
|
||||
DocumentName = 0x010D,
|
||||
ImageDescription = 0x010E,
|
||||
Make = 0x010F,
|
||||
Model = 0x0110,
|
||||
StripOffsets = 0x0111,
|
||||
Orientation = 0x0112,
|
||||
SamplesPerPixel = 0x0115,
|
||||
RowsPerStrip = 0x0116,
|
||||
StripByteCounts = 0x0117,
|
||||
MinSampleValue = 0x0118,
|
||||
MaxSampleValue = 0x0119,
|
||||
XResolution = 0x011A,
|
||||
YResolution = 0x011B,
|
||||
PlanarConfiguration = 0x011C,
|
||||
PageName = 0x011D,
|
||||
XPosition = 0x011E,
|
||||
YPosition = 0x011F,
|
||||
FreeOffsets = 0x0120,
|
||||
FreeByteCounts = 0x0121,
|
||||
GrayResponseUnit = 0x0122,
|
||||
GrayResponseCurve = 0x0123,
|
||||
T4Options = 0x0124,
|
||||
T6Options = 0x0125,
|
||||
ResolutionUnit = 0x0128,
|
||||
PageNumber = 0x0129,
|
||||
TransferFunction = 0x012D,
|
||||
Software = 0x0131,
|
||||
DateTime = 0x0132,
|
||||
Artist = 0x013B,
|
||||
HostComputer = 0x013C,
|
||||
Predictor = 0x013D,
|
||||
WhitePoint = 0x013E,
|
||||
PrimaryChromaticities = 0x013F,
|
||||
ColorMap = 0x0140,
|
||||
HalftoneHints = 0x0141,
|
||||
TileWidth = 0x0142,
|
||||
TileLength = 0x0143,
|
||||
TileOffsets = 0x0144,
|
||||
TileByteCounts = 0x0145,
|
||||
InkSet = 0x014C,
|
||||
InkNames = 0x014D,
|
||||
NumberOfInks = 0x014E,
|
||||
DotRange = 0x0150,
|
||||
TargetPrinter = 0x0151,
|
||||
ExtraSamples = 0x0152,
|
||||
SampleFormat = 0x0153,
|
||||
SMinSampleValue = 0x0154,
|
||||
SMaxSampleValue = 0x0155,
|
||||
TransferRange = 0x0156,
|
||||
JPEGTables = 0x015B,
|
||||
JPEGProc = 0x0200,
|
||||
JPEGInterchangeFormat = 0x0201,
|
||||
JPEGInterchangeFormatLngth = 0x0202,
|
||||
JPEGRestartInterval = 0x0203,
|
||||
JPEGLosslessPredictors = 0x0205,
|
||||
JPEGPointTransforms = 0x0206,
|
||||
JPEGQTables = 0x0207,
|
||||
JPEGDCTables = 0x0208,
|
||||
JPEGACTables = 0x0209,
|
||||
YCbCrCoefficients = 0x0211,
|
||||
YCbCrSubSampling = 0x0212,
|
||||
YCbCrPositioning = 0x0213,
|
||||
ReferenceBlackWhite = 0x0214,
|
||||
Copyright = 0x8298,
|
||||
ICCProfile = 0x8773
|
||||
};
|
||||
|
||||
struct ValueArray<T, auto Count> {
|
||||
if (Count > 1) {
|
||||
T Values[Count];
|
||||
} else {
|
||||
T Values[Count] [[hidden, no_unique_address]];
|
||||
T Value;
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
struct ValueOffset<T, auto Count> {
|
||||
u64 Size = sizeof(T) * Count;
|
||||
if (Size <= ValueOffsetSize) {
|
||||
ValueArray<T, Count> ValueArray;
|
||||
padding[ValueOffsetSize - Size];
|
||||
} else {
|
||||
Big<u32> Offset;
|
||||
ValueArray<T, Count> ValueArray @ Offset;
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
struct IFDEntry {
|
||||
TIFFTag Tag;
|
||||
TIFFFieldType Type;
|
||||
Big<u32> Count;
|
||||
|
||||
match (Type) {
|
||||
(TIFFFieldType::BYTE): ValueOffset<u8, Count> ValueOffset;
|
||||
(TIFFFieldType::ASCII): ValueOffset<char, Count> ValueOffset;
|
||||
(TIFFFieldType::SHORT): ValueOffset<u16, Count> ValueOffset;
|
||||
(TIFFFieldType::LONG): ValueOffset<u32, Count> ValueOffset;
|
||||
(TIFFFieldType::RATIONAL): ValueOffset<TIFFRational<u32>, Count> ValueOffset;
|
||||
(TIFFFieldType::SBYTE): ValueOffset<s8, Count> ValueOffset;
|
||||
(TIFFFieldType::UNDEFINED): ValueOffset<u8, Count> ValueOffset;
|
||||
(TIFFFieldType::SSHORT): ValueOffset<s16, Count> ValueOffset;
|
||||
(TIFFFieldType::SLONG): ValueOffset<s32, Count> ValueOffset;
|
||||
(TIFFFieldType::SRATIONAL): ValueOffset<TIFFRational<s32>, Count> ValueOffset;
|
||||
(TIFFFieldType::FLOAT): ValueOffset<float, Count> ValueOffset;
|
||||
(TIFFFieldType::DOUBLE): ValueOffset<double, Count> ValueOffset;
|
||||
(TIFFFieldType::LONG8): ValueOffset<u64, Count> ValueOffset;
|
||||
(TIFFFieldType::SLONG8): ValueOffset<s64, Count> ValueOffset;
|
||||
(_): {
|
||||
padding[ValueOffsetSize];
|
||||
std::print(std::format("TIFFFieldType {} not supported", u16(Type)));
|
||||
}
|
||||
}
|
||||
} [[name(std::string::replace(std::core::formatted_value(Tag), "TIFFTag::", ""))]];
|
||||
|
||||
fn get_field(ref auto entries, TIFFTag tag) {
|
||||
for (u64 i = 0, i < std::core::member_count(entries), i = i + 1) {
|
||||
if (entries[i].Tag == tag) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
std::error(std::format("Tag {} not found in directory", tag));
|
||||
};
|
||||
|
||||
struct ImageData<auto Desc> {
|
||||
u64 Index = std::core::array_index();
|
||||
u64 Offset = parent.DirectoryEntry[parent.OffsetField].ValueOffset.ValueArray.Values[Index];
|
||||
u64 ByteCount = parent.DirectoryEntry[parent.ByteCountField].ValueOffset.ValueArray.Values[Index];
|
||||
std::mem::Bytes<ByteCount> ImageData @ Offset [[name(std::format("{} {}", Desc, Index))]];
|
||||
} [[inline]];
|
||||
|
||||
u64 currentIFD = 0;
|
||||
struct IFD {
|
||||
u64 Number = currentIFD;
|
||||
Big<u16> NumberDirectoryEntries;
|
||||
IFDEntry DirectoryEntry[NumberDirectoryEntries];
|
||||
Big<u32> NextIFD;
|
||||
|
||||
try {
|
||||
u64 OffsetField = get_field(DirectoryEntry, TIFFTag::StripOffsets);
|
||||
u64 ByteCountField = get_field(DirectoryEntry, TIFFTag::StripByteCounts);
|
||||
u64 Count = std::core::member_count(DirectoryEntry[OffsetField].ValueOffset.ValueArray.Values);
|
||||
ImageData<"Strip"> Strips[Count];
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
u64 OffsetField = get_field(DirectoryEntry, TIFFTag::TileOffsets);
|
||||
u64 ByteCountField = get_field(DirectoryEntry, TIFFTag::TileByteCounts);
|
||||
u64 Count = std::core::member_count(DirectoryEntry[OffsetField].ValueOffset.ValueArray.Values);
|
||||
ImageData<"Tile"> Tiles[Count];
|
||||
} catch {}
|
||||
} [[name(std::format("IFD {}", Number))]];
|
||||
|
||||
struct IFDS {
|
||||
IFD IFD;
|
||||
if (IFD.NextIFD > 0) {
|
||||
currentIFD += 1;
|
||||
IFDS IFD_tmp @ IFD.NextIFD;
|
||||
}
|
||||
} [[inline]];
|
||||
|
||||
struct TIFFFile {
|
||||
TIFFHeader Header;
|
||||
IFDS @ Header.Offset;
|
||||
};
|
||||
|
||||
TIFFFile File @ 0x00;
|
||||
92
patterns/ubiquiti.hexpat
Normal file
92
patterns/ubiquiti.hexpat
Normal file
@@ -0,0 +1,92 @@
|
||||
#pragma description Ubiquiti Firmware (update) image
|
||||
|
||||
#pragma endian big
|
||||
|
||||
#include <std/mem.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
// Ubiquiti Firmware related structs
|
||||
// More information here: https://dl.ubnt.com/firmwares/XN-fw/v5.6.3/GPL.UBNT.v5.6.3.tar.bz2
|
||||
|
||||
/*
|
||||
* Block types of a default firmware file file:
|
||||
* - UBNT := header
|
||||
* - PART := partition
|
||||
* - EXEC := additional data block
|
||||
* - END. := default end block
|
||||
* - ENDS := signed end block using RSA 2048 bit
|
||||
*/
|
||||
#define TYPE_UBNT "UBNT"
|
||||
#define TYPE_PART "PART"
|
||||
#define TYPE_EXEC "EXEC"
|
||||
#define TYPE_END "END."
|
||||
#define TYPE_SIGNED_END "ENDS"
|
||||
|
||||
namespace ubnt {
|
||||
struct UBNT {
|
||||
char version[256];
|
||||
u32 crc32;
|
||||
};
|
||||
|
||||
struct PART {
|
||||
char name[16];
|
||||
padding[12];
|
||||
u32 memaddr;
|
||||
u32 index;
|
||||
u32 baseaddr;
|
||||
u32 entryaddr;
|
||||
u32 data_size;
|
||||
u32 part_size;
|
||||
u8 data[this.data_size];
|
||||
u32 crc32;
|
||||
};
|
||||
|
||||
struct EXEC {
|
||||
char name[16];
|
||||
u8 reserved[28];
|
||||
u32 size;
|
||||
u32 size2;
|
||||
u32 crc32;
|
||||
u8 data[this.size];
|
||||
};
|
||||
|
||||
struct END {
|
||||
u32 crc32;
|
||||
};
|
||||
|
||||
struct ENDS {
|
||||
u8 data[256];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
struct Block {
|
||||
char type[4];
|
||||
|
||||
if (type == TYPE_UBNT) {
|
||||
ubnt::UBNT header;
|
||||
}
|
||||
else if (type == TYPE_PART) {
|
||||
ubnt::PART partition;
|
||||
}
|
||||
else if (type == TYPE_EXEC) {
|
||||
ubnt::EXEC data;
|
||||
}
|
||||
else if (type == TYPE_END) {
|
||||
ubnt::END end;
|
||||
}
|
||||
else if (type == TYPE_SIGNED_END) {
|
||||
ubnt::ENDS end;
|
||||
}
|
||||
|
||||
// REVISIT: change the type to u32
|
||||
padding[4];
|
||||
};
|
||||
|
||||
// Greedy parsing of Block structs
|
||||
Block blocks[while(!std::mem::eof())] @ 0x00;
|
||||
|
||||
std::assert(blocks[0].type == TYPE_UBNT,
|
||||
"File is not a valid Ubiquiti firmare file!");
|
||||
|
||||
std::print("Version: {}", blocks[0].header.version);
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description UEFI structs for parsing efivars
|
||||
|
||||
#pragma MIME data
|
||||
|
||||
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description [USB Flashing Format](https://github.com/microsoft/uf2)
|
||||
|
||||
#include <std/sys.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Binary Value Data Format (.vdf) files
|
||||
|
||||
#pragma eval_depth 0x10000
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
@@ -1,193 +1,190 @@
|
||||
#include <std/io.pat>
|
||||
#include <std/ptr.pat>
|
||||
#include <std/core.pat>
|
||||
|
||||
#include <type/guid.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
struct FileTypeIdentifier {
|
||||
char signature[8];
|
||||
char16 creator[256];
|
||||
padding[0x1'0000 - sizeof(signature) - sizeof(creator)];
|
||||
};
|
||||
|
||||
struct DataSector {
|
||||
u32 sequenceHigh;
|
||||
u8 data[4084];
|
||||
u32 sequenceLow;
|
||||
} [[static]];
|
||||
|
||||
struct ZeroDescriptor {
|
||||
padding[4];
|
||||
u64 zeroLength;
|
||||
DataSector *dataSector : u64;
|
||||
u64 sequenceNumber;
|
||||
} [[static]];
|
||||
|
||||
struct DataDescriptor {
|
||||
u32 trailingBytes;
|
||||
u64 leadingBytes;
|
||||
DataSector *dataSector : u64;
|
||||
u64 sequenceNumber;
|
||||
} [[static]];
|
||||
|
||||
struct LogDescriptor {
|
||||
char signature[4];
|
||||
|
||||
if (signature == "zero")
|
||||
ZeroDescriptor descriptor [[inline]];
|
||||
else if (signature == "desc")
|
||||
DataDescriptor descriptor [[inline]];
|
||||
};
|
||||
|
||||
struct LogEntry {
|
||||
char signature[4];
|
||||
u32 checksum;
|
||||
type::Size32 entryLength;
|
||||
u32 tail;
|
||||
u64 sequenceNumber;
|
||||
u32 descriptorCount;
|
||||
padding[4];
|
||||
type::GUID logGuid;
|
||||
u64 flushedFileOffset;
|
||||
u64 lastFileOffset;
|
||||
} [[static]];
|
||||
|
||||
bitfield BAT {
|
||||
State : 3;
|
||||
padding : 17;
|
||||
FileOffsetMB : 44;
|
||||
} [[right_to_left]];
|
||||
|
||||
bitfield MetadataEntryFlags {
|
||||
IsUser : 1;
|
||||
IsVirtualDisk : 1;
|
||||
IsRequired : 1;
|
||||
padding : 29;
|
||||
};
|
||||
|
||||
bitfield FileParameterFlags {
|
||||
LeaveBlockAllocated : 1;
|
||||
HasParent : 1;
|
||||
padding : 30;
|
||||
};
|
||||
|
||||
struct MetadataFileParameters {
|
||||
type::Size32 blockSize;
|
||||
FileParameterFlags flags;
|
||||
};
|
||||
|
||||
struct MetadataVirtualDiskSize {
|
||||
type::Size64 virtualDiskSize;
|
||||
};
|
||||
|
||||
struct MetadataVirtualDiskID {
|
||||
type::GUID virtualDiskID;
|
||||
};
|
||||
|
||||
struct MetadataLogicalSectorSize {
|
||||
type::Size32 logicalSectorSize;
|
||||
};
|
||||
|
||||
struct MetadataPhysicalSectorSize {
|
||||
type::Size32 physicalSectorSize;
|
||||
};
|
||||
|
||||
struct ParentLocatorEntry {
|
||||
u32 keyOffset;
|
||||
u32 valueOffset;
|
||||
u16 keyLength;
|
||||
u16 valueLength;
|
||||
|
||||
char key[keyLength] @ addressof(parent) + keyOffset;
|
||||
char value[valueLength] @ addressof(parent) + valueOffset;
|
||||
};
|
||||
|
||||
struct MetadataParentLocator {
|
||||
type::GUID locatorType;
|
||||
padding[2];
|
||||
u16 keyValueCount;
|
||||
ParentLocatorEntry entries[keyValueCount];
|
||||
};
|
||||
|
||||
fn metadata_relative(u128 offset) {
|
||||
return addressof(parent.parent);
|
||||
};
|
||||
|
||||
struct MetadataTableEntry {
|
||||
type::GUID itemID;
|
||||
|
||||
if (std::core::formatted_value(itemID) == "{CAA16737-FA36-4D43-B3B6-33F0AA44E76B}")
|
||||
MetadataFileParameters *data : u32 [[pointer_base("metadata_relative")]];
|
||||
else if (std::core::formatted_value(itemID) == "{2FA54224-CD1B-4876-B211-5DBED83BF4B8}")
|
||||
MetadataVirtualDiskSize *data : u32 [[pointer_base("metadata_relative")]];
|
||||
else if (std::core::formatted_value(itemID) == "{BECA12AB-B2E6-4523-93EF-C309E000C746}")
|
||||
MetadataVirtualDiskID *data : u32 [[pointer_base("metadata_relative")]];
|
||||
else if (std::core::formatted_value(itemID) == "{8141BF1D-A96F-4709-BA47-F233A8FAAB5F}")
|
||||
MetadataLogicalSectorSize *data : u32 [[pointer_base("metadata_relative")]];
|
||||
else if (std::core::formatted_value(itemID) == "{CDA348C7-445D-4471-9CC9-E9885251C556}")
|
||||
MetadataPhysicalSectorSize *data : u32 [[pointer_base("metadata_relative")]];
|
||||
else if (std::core::formatted_value(itemID) == "{A8D35F2D-B30B-454D-ABF7-D3D84834AB0C}")
|
||||
MetadataParentLocator *data : u32 [[pointer_base("metadata_relative")]];
|
||||
else
|
||||
u32 dataOffset;
|
||||
|
||||
type::Size32 length;
|
||||
MetadataEntryFlags flags;
|
||||
padding[4];
|
||||
};
|
||||
|
||||
struct MetadataRegion {
|
||||
char signature[8];
|
||||
padding[2];
|
||||
u16 entryCount;
|
||||
padding[20];
|
||||
MetadataTableEntry entries[entryCount];
|
||||
};
|
||||
|
||||
struct RegionTableEntry {
|
||||
type::GUID guid;
|
||||
|
||||
if (std::core::formatted_value(guid) == "{2DC27766-F623-4200-9D64-115E9BFD4A08}")
|
||||
BAT *bat : u64;
|
||||
else if (std::core::formatted_value(guid) == "{8B7CA206-4790-4B9A-B8FE-575F050F886E}")
|
||||
MetadataRegion *metadata : u64;
|
||||
else
|
||||
u64 fileOffset;
|
||||
|
||||
type::Size32 length;
|
||||
u32 required;
|
||||
};
|
||||
|
||||
struct RegionTable {
|
||||
char signature[4];
|
||||
u32 checksum;
|
||||
u32 entryCount;
|
||||
padding[4];
|
||||
|
||||
RegionTableEntry entries[entryCount];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char signature[4];
|
||||
u32 checksum;
|
||||
u64 sequenceNumber;
|
||||
type::GUID fileWriteGuid, dataWriteGuid, logGuid;
|
||||
u16 logVersion;
|
||||
u16 version;
|
||||
type::Size32 logLength;
|
||||
LogEntry *log : u64;
|
||||
padding[4016];
|
||||
};
|
||||
|
||||
struct VHDX {
|
||||
FileTypeIdentifier fileTypeIdentifier;
|
||||
|
||||
Header header @ 0x1'0000;
|
||||
Header headerBackup @ 0x2'0000;
|
||||
|
||||
RegionTable regionTable @ 0x3'0000;
|
||||
RegionTable regionTableBackup @ 0x4'0000;
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description Microsoft Hyper-V Virtual Hard Disk format
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/ptr.pat>
|
||||
#include <std/core.pat>
|
||||
|
||||
#include <type/guid.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
using BitfieldOrder = std::core::BitfieldOrder;
|
||||
|
||||
struct FileTypeIdentifier {
|
||||
char signature[8];
|
||||
char16 creator[256];
|
||||
padding[0x1'0000 - sizeof(signature) - sizeof(creator)];
|
||||
};
|
||||
|
||||
struct DataSector {
|
||||
u32 sequenceHigh;
|
||||
u8 data[4084];
|
||||
u32 sequenceLow;
|
||||
} [[static]];
|
||||
|
||||
struct ZeroDescriptor {
|
||||
padding[4];
|
||||
u64 zeroLength;
|
||||
DataSector *dataSector : u64;
|
||||
u64 sequenceNumber;
|
||||
} [[static]];
|
||||
|
||||
struct DataDescriptor {
|
||||
u32 trailingBytes;
|
||||
u64 leadingBytes;
|
||||
DataSector *dataSector : u64;
|
||||
u64 sequenceNumber;
|
||||
} [[static]];
|
||||
|
||||
struct LogDescriptor {
|
||||
char signature[4];
|
||||
|
||||
if (signature == "zero")
|
||||
ZeroDescriptor descriptor [[inline]];
|
||||
else if (signature == "desc")
|
||||
DataDescriptor descriptor [[inline]];
|
||||
};
|
||||
|
||||
struct LogEntry {
|
||||
char signature[4];
|
||||
u32 checksum;
|
||||
type::Size32 entryLength;
|
||||
u32 tail;
|
||||
u64 sequenceNumber;
|
||||
u32 descriptorCount;
|
||||
padding[4];
|
||||
type::GUID logGuid;
|
||||
u64 flushedFileOffset;
|
||||
u64 lastFileOffset;
|
||||
} [[static]];
|
||||
|
||||
bitfield BAT {
|
||||
State : 3;
|
||||
padding : 17;
|
||||
FileOffsetMB : 44;
|
||||
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 64)]];
|
||||
|
||||
bitfield MetadataEntryFlags {
|
||||
IsUser : 1;
|
||||
IsVirtualDisk : 1;
|
||||
IsRequired : 1;
|
||||
padding : 29;
|
||||
};
|
||||
|
||||
bitfield FileParameterFlags {
|
||||
LeaveBlockAllocated : 1;
|
||||
HasParent : 1;
|
||||
padding : 30;
|
||||
};
|
||||
|
||||
struct MetadataFileParameters {
|
||||
type::Size32 blockSize;
|
||||
FileParameterFlags flags;
|
||||
};
|
||||
|
||||
struct MetadataVirtualDiskSize {
|
||||
type::Size64 virtualDiskSize;
|
||||
};
|
||||
|
||||
struct MetadataVirtualDiskID {
|
||||
type::GUID virtualDiskID;
|
||||
};
|
||||
|
||||
struct MetadataLogicalSectorSize {
|
||||
type::Size32 logicalSectorSize;
|
||||
};
|
||||
|
||||
struct MetadataPhysicalSectorSize {
|
||||
type::Size32 physicalSectorSize;
|
||||
};
|
||||
|
||||
struct ParentLocatorEntry {
|
||||
u32 keyOffset;
|
||||
u32 valueOffset;
|
||||
u16 keyLength;
|
||||
u16 valueLength;
|
||||
|
||||
char16 key[keyLength / 2] @ addressof(parent) + keyOffset;
|
||||
char16 value[valueLength / 2] @ addressof(parent) + valueOffset;
|
||||
};
|
||||
|
||||
struct MetadataParentLocator {
|
||||
type::GUID locatorType;
|
||||
padding[2];
|
||||
u16 keyValueCount;
|
||||
ParentLocatorEntry entries[keyValueCount];
|
||||
};
|
||||
|
||||
struct MetadataTableEntry {
|
||||
type::GUID itemID;
|
||||
u32 dataOffset;
|
||||
type::Size32 length;
|
||||
MetadataEntryFlags flags;
|
||||
padding[4];
|
||||
|
||||
if (std::core::formatted_value(itemID) == "{CAA16737-FA36-4D43-B3B6-33F0AA44E76B}")
|
||||
MetadataFileParameters fileParameters @ addressof(parent) + dataOffset;
|
||||
else if (std::core::formatted_value(itemID) == "{2FA54224-CD1B-4876-B211-5DBED83BF4B8}")
|
||||
MetadataVirtualDiskSize virtualDiskSize @ addressof(parent) + dataOffset;
|
||||
else if (std::core::formatted_value(itemID) == "{BECA12AB-B2E6-4523-93EF-C309E000C746}")
|
||||
MetadataVirtualDiskID virtualDiskId @ addressof(parent) + dataOffset;
|
||||
else if (std::core::formatted_value(itemID) == "{8141BF1D-A96F-4709-BA47-F233A8FAAB5F}")
|
||||
MetadataLogicalSectorSize logicalSectorSize @ addressof(parent) + dataOffset;
|
||||
else if (std::core::formatted_value(itemID) == "{CDA348C7-445D-4471-9CC9-E9885251C556}")
|
||||
MetadataPhysicalSectorSize physicalSectorSize @ addressof(parent) + dataOffset;
|
||||
else if (std::core::formatted_value(itemID) == "{A8D35F2D-B30B-454D-ABF7-D3D84834AB0C}")
|
||||
MetadataParentLocator parentLocator @ addressof(parent) + dataOffset;
|
||||
};
|
||||
|
||||
struct MetadataRegion {
|
||||
char signature[8];
|
||||
padding[2];
|
||||
u16 entryCount;
|
||||
padding[20];
|
||||
MetadataTableEntry entries[entryCount];
|
||||
};
|
||||
|
||||
struct RegionTableEntry {
|
||||
type::GUID guid;
|
||||
u64 fileOffset;
|
||||
type::Size32 length;
|
||||
u32 required;
|
||||
|
||||
if (std::core::formatted_value(guid) == "{2DC27766-F623-4200-9D64-115E9BFD4A08}")
|
||||
BAT bat @ fileOffset;
|
||||
else if (std::core::formatted_value(guid) == "{8B7CA206-4790-4B9A-B8FE-575F050F886E}")
|
||||
MetadataRegion metadata @ fileOffset;
|
||||
};
|
||||
|
||||
struct RegionTable {
|
||||
char signature[4];
|
||||
u32 checksum;
|
||||
u32 entryCount;
|
||||
padding[4];
|
||||
|
||||
RegionTableEntry entries[entryCount];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
char signature[4];
|
||||
u32 checksum;
|
||||
u64 sequenceNumber;
|
||||
type::GUID fileWriteGuid, dataWriteGuid, logGuid;
|
||||
u16 logVersion;
|
||||
u16 version;
|
||||
type::Size32 logLength;
|
||||
LogEntry *log : u64;
|
||||
padding[4016];
|
||||
};
|
||||
|
||||
struct VHDX {
|
||||
FileTypeIdentifier fileTypeIdentifier;
|
||||
|
||||
Header header @ 0x1'0000;
|
||||
Header headerBackup @ 0x2'0000;
|
||||
|
||||
RegionTable regionTable @ 0x3'0000;
|
||||
RegionTable regionTableBackup @ 0x4'0000;
|
||||
};
|
||||
|
||||
VHDX vhdx @ 0x00;
|
||||
@@ -1,24 +1,27 @@
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
enum WADType : char {
|
||||
Internal = 'I',
|
||||
Patch = 'P'
|
||||
};
|
||||
|
||||
struct FileLump {
|
||||
u32 filePos;
|
||||
type::Size<u32> size;
|
||||
char name[8];
|
||||
|
||||
u8 data[size] @ filePos [[sealed]];
|
||||
};
|
||||
|
||||
struct WAD {
|
||||
WADType type;
|
||||
type::Magic<"WAD"> identification;
|
||||
u32 numLumps;
|
||||
FileLump *infoTable[numLumps] : u32;
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description DOOM WAD Archive
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
enum WADType : char {
|
||||
Internal = 'I',
|
||||
Patch = 'P'
|
||||
};
|
||||
|
||||
struct FileLump {
|
||||
u32 filePos;
|
||||
type::Size<u32> size;
|
||||
char name[8];
|
||||
|
||||
u8 data[size] @ filePos [[sealed]];
|
||||
};
|
||||
|
||||
struct WAD {
|
||||
WADType type;
|
||||
type::Magic<"WAD"> identification;
|
||||
u32 numLumps;
|
||||
FileLump *infoTable[numLumps] : u32;
|
||||
};
|
||||
|
||||
WAD wad @ 0x00;
|
||||
@@ -1,3 +1,6 @@
|
||||
#pragma description RIFF header, WAVE header, PCM header
|
||||
|
||||
#pragma MIME audio/x-wav
|
||||
#pragma MIME audio/wav
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
@@ -1,403 +1,406 @@
|
||||
#pragma MIME audio/x-xbox-executable
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
#include <type/time.pat>
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
|
||||
bitfield AllowedMedia {
|
||||
HardDisk : 1;
|
||||
DVD_X2 : 1;
|
||||
DVD_CD : 1;
|
||||
CD : 1;
|
||||
DVD_5_RO : 1;
|
||||
DVD_9_RO : 1;
|
||||
DVD_5_RW : 1;
|
||||
DVD_9_RW : 1;
|
||||
Dongle : 1;
|
||||
MediaBoard : 1;
|
||||
padding : 20;
|
||||
NonSecureHardDisk : 1;
|
||||
NonSecureMode : 1;
|
||||
};
|
||||
|
||||
bitfield GameRegion {
|
||||
NorthAmerica : 1;
|
||||
Japan : 1;
|
||||
RestOfTheWorld : 1;
|
||||
padding : 28;
|
||||
Manufacturing : 1;
|
||||
};
|
||||
|
||||
struct Certificate {
|
||||
type::Size<u32> certificateSize;
|
||||
type::time32_t timeDate;
|
||||
u32 titleId;
|
||||
char16 titleName[0x50 / 2];
|
||||
u32 alternateTitleIds[16];
|
||||
AllowedMedia allowedMedia;
|
||||
GameRegion gameRegion;
|
||||
u32 gameRatings;
|
||||
u128 lanKey;
|
||||
u128 signatureKey;
|
||||
u128 alternateSignatureKeys[16];
|
||||
};
|
||||
|
||||
bitfield InitializationFlags {
|
||||
MountUtilityDrive : 1;
|
||||
FormatUtilityDrive : 1;
|
||||
Limit64Megabytes : 1;
|
||||
DontSetuptHarddisk : 1;
|
||||
padding : 28;
|
||||
};
|
||||
|
||||
union EntryPoint {
|
||||
u32 betaAddress [[format("format_beta_entrypoint")]];
|
||||
u32 debugAddress [[format("format_debug_entrypoint")]];
|
||||
u32 retailAddress [[format("format_retail_entrypoint")]];
|
||||
|
||||
if ((betaAddress ^ 0xE682F45B) - parent.baseAddress < std::mem::size())
|
||||
u8 beta @ (betaAddress ^ 0xE682F45B) - parent.baseAddress;;
|
||||
if ((debugAddress ^ 0x94859D4B) - parent.baseAddress < std::mem::size())
|
||||
u8 debug @ (debugAddress ^ 0x94859D4B) - parent.baseAddress;;
|
||||
if ((retailAddress ^ 0xA8FC57AB) - parent.baseAddress < std::mem::size())
|
||||
u8 retail @ (retailAddress ^ 0xA8FC57AB) - parent.baseAddress;
|
||||
};
|
||||
|
||||
fn format_beta_entrypoint(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0xE682F45B);
|
||||
};
|
||||
|
||||
fn format_debug_entrypoint(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0x94859D4B);
|
||||
};
|
||||
|
||||
fn format_retail_entrypoint(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0xA8FC57AB);
|
||||
};
|
||||
|
||||
#define KERNEL_BASE 0x8000'0000
|
||||
enum KernelImageFunction : u32 {
|
||||
AvGetSavedDataAddress = 1 + KERNEL_BASE,
|
||||
AvSendTVEncoderOption = 2 + KERNEL_BASE,
|
||||
AvSetDisplayMode = 3 + KERNEL_BASE,
|
||||
AvSetSavedDataAddress = 4 + KERNEL_BASE,
|
||||
DbgBreakPoint = 5 + KERNEL_BASE,
|
||||
DbgBreakPointWithStatus = 6 + KERNEL_BASE,
|
||||
DbgLoadImageSymbols = 7 + KERNEL_BASE,
|
||||
DbgPrint = 8 + KERNEL_BASE,
|
||||
HalReadSMCTrayState = 9 + KERNEL_BASE,
|
||||
DbgPrompt = 10 + KERNEL_BASE,
|
||||
DbgUnLoadImageSymbols = 11 + KERNEL_BASE,
|
||||
ExAcquireReadWriteLockExclusive = 12 + KERNEL_BASE,
|
||||
ExAcquireReadWriteLockShared = 13 + KERNEL_BASE,
|
||||
ExAllocatePool = 14 + KERNEL_BASE,
|
||||
ExAllocatePoolWithTag = 15 + KERNEL_BASE,
|
||||
ExEventObjectType = 16 + KERNEL_BASE,
|
||||
ExFreePool = 17 + KERNEL_BASE,
|
||||
ExInitializeReadWriteLock = 18 + KERNEL_BASE,
|
||||
ExInterlockedAddLargeInteger = 19 + KERNEL_BASE,
|
||||
ExInterlockedAddLargeStatistic = 20 + KERNEL_BASE,
|
||||
ExInterlockedCompareExchange64 = 21 + KERNEL_BASE,
|
||||
ExMutantObjectType = 22 + KERNEL_BASE,
|
||||
ExQueryPoolBlockSize = 23 + KERNEL_BASE,
|
||||
ExQueryNonVolatileSetting = 24 + KERNEL_BASE,
|
||||
ExReadWriteRefurbInfo = 25 + KERNEL_BASE,
|
||||
ExRaiseException = 26 + KERNEL_BASE,
|
||||
ExRaiseStatus = 27 + KERNEL_BASE,
|
||||
ExReleaseReadWriteLock = 28 + KERNEL_BASE,
|
||||
ExSaveNonVolatileSetting = 29 + KERNEL_BASE,
|
||||
ExSemaphoreObjectType = 30 + KERNEL_BASE,
|
||||
ExTimerObjectType = 31 + KERNEL_BASE,
|
||||
ExfInterlockedInsertHeadList = 32 + KERNEL_BASE,
|
||||
ExfInterlockedInsertTailList = 33 + KERNEL_BASE,
|
||||
ExfInterlockedRemoveHeadList = 34 + KERNEL_BASE,
|
||||
FscGetCacheSize = 35 + KERNEL_BASE,
|
||||
FscInvalidateIdleBlocks = 36 + KERNEL_BASE,
|
||||
FscSetCacheSize = 37 + KERNEL_BASE,
|
||||
HalClearSoftwareInterrupt = 38 + KERNEL_BASE,
|
||||
HalDisableSystemInterrupt = 39 + KERNEL_BASE,
|
||||
HalDiskCachePartitionCount = 40 + KERNEL_BASE,
|
||||
HalDiskModelNumber = 41 + KERNEL_BASE,
|
||||
HalDiskSerialNumber = 42 + KERNEL_BASE,
|
||||
HalEnableSystemInterrupt = 43 + KERNEL_BASE,
|
||||
HalGetInterruptVector = 44 + KERNEL_BASE,
|
||||
HalReadSMBusValue = 45 + KERNEL_BASE,
|
||||
HalReadWritePCISpace = 46 + KERNEL_BASE,
|
||||
HalRegisterShutdownNotification = 47 + KERNEL_BASE,
|
||||
HalRequestSoftwareInterrupt = 48 + KERNEL_BASE,
|
||||
HalReturnToFirmware = 49 + KERNEL_BASE,
|
||||
HalWriteSMBusValue = 50 + KERNEL_BASE,
|
||||
InterlockedCompareExchange = 51 + KERNEL_BASE,
|
||||
InterlockedDecrement = 52 + KERNEL_BASE,
|
||||
InterlockedIncrement = 53 + KERNEL_BASE,
|
||||
InterlockedExchange = 54 + KERNEL_BASE,
|
||||
InterlockedExchangeAdd = 55 + KERNEL_BASE,
|
||||
InterlockedFlushSList = 56 + KERNEL_BASE,
|
||||
InterlockedPopEntrySList = 57 + KERNEL_BASE,
|
||||
InterlockedPushEntrySList = 58 + KERNEL_BASE,
|
||||
IoAllocateIrp = 59 + KERNEL_BASE,
|
||||
IoBuildAsynchronousFsdRequest = 60 + KERNEL_BASE,
|
||||
IoBuildDeviceIoControlRequest = 61 + KERNEL_BASE,
|
||||
IoBuildSynchronousFsdRequest = 62 + KERNEL_BASE,
|
||||
IoCheckShareAccess = 63 + KERNEL_BASE,
|
||||
IoCompletionObjectType = 64 + KERNEL_BASE,
|
||||
IoCreateDevice = 65 + KERNEL_BASE,
|
||||
IoCreateFile = 66 + KERNEL_BASE,
|
||||
IoCreateSymbolicLink = 67 + KERNEL_BASE,
|
||||
IoDeleteDevice = 68 + KERNEL_BASE,
|
||||
IoDeleteSymbolicLink = 69 + KERNEL_BASE,
|
||||
IoDeviceObjectType = 70 + KERNEL_BASE,
|
||||
IoFileObjectType = 71 + KERNEL_BASE,
|
||||
IoFreeIrp = 72 + KERNEL_BASE,
|
||||
IoInitializeIrp = 73 + KERNEL_BASE,
|
||||
IoInvalidDeviceRequest = 74 + KERNEL_BASE,
|
||||
IoQueryFileInformation = 75 + KERNEL_BASE,
|
||||
IoQueryVolumeInformation = 76 + KERNEL_BASE,
|
||||
IoQueueThreadIrp = 77 + KERNEL_BASE,
|
||||
IoRemoveShareAccess = 78 + KERNEL_BASE,
|
||||
IoSetIoCompletion = 79 + KERNEL_BASE,
|
||||
IoSetShareAccess = 80 + KERNEL_BASE,
|
||||
IoStartNextPacket = 81 + KERNEL_BASE,
|
||||
IoStartNextPacketByKey = 82 + KERNEL_BASE,
|
||||
IoStartPacket = 83 + KERNEL_BASE,
|
||||
IoSynchronousDeviceIoControlRequest = 84 + KERNEL_BASE,
|
||||
IoSynchronousFsdRequest = 85 + KERNEL_BASE,
|
||||
IofCallDriver = 86 + KERNEL_BASE,
|
||||
IofCompleteRequest = 87 + KERNEL_BASE,
|
||||
KdDebuggerEnabled = 88 + KERNEL_BASE,
|
||||
KdDebuggerNotPresent = 89 + KERNEL_BASE,
|
||||
IoDismountVolume = 90 + KERNEL_BASE,
|
||||
IoDismountVolumeByName = 91 + KERNEL_BASE,
|
||||
KeAlertResumeThread = 92 + KERNEL_BASE,
|
||||
KeAlertThread = 93 + KERNEL_BASE,
|
||||
KeBoostPriorityThread = 94 + KERNEL_BASE,
|
||||
KeBugCheck = 95 + KERNEL_BASE,
|
||||
KeBugCheckEx = 96 + KERNEL_BASE,
|
||||
KeCancelTimer = 97 + KERNEL_BASE,
|
||||
KeConnectInterrupt = 98 + KERNEL_BASE,
|
||||
KeDelayExecutionThread = 99 + KERNEL_BASE,
|
||||
KeDisconnectInterrupt = 100 + KERNEL_BASE,
|
||||
KeEnterCriticalRegion = 101 + KERNEL_BASE,
|
||||
MmGlobalData = 102 + KERNEL_BASE,
|
||||
KeGetCurrentIrql = 103 + KERNEL_BASE,
|
||||
KeGetCurrentThread = 104 + KERNEL_BASE,
|
||||
KeInitializeApc = 105 + KERNEL_BASE,
|
||||
KeInitializeDeviceQueue = 106 + KERNEL_BASE,
|
||||
KeInitializeDpc = 107 + KERNEL_BASE,
|
||||
KeInitializeEvent = 108 + KERNEL_BASE,
|
||||
KeInitializeInterrupt = 109 + KERNEL_BASE,
|
||||
KeInitializeMutant = 110 + KERNEL_BASE,
|
||||
KeInitializeQueue = 111 + KERNEL_BASE,
|
||||
KeInitializeSemaphore = 112 + KERNEL_BASE,
|
||||
KeInitializeTimerEx = 113 + KERNEL_BASE,
|
||||
KeInsertByKeyDeviceQueue = 114 + KERNEL_BASE,
|
||||
KeInsertDeviceQueue = 115 + KERNEL_BASE,
|
||||
KeInsertHeadQueue = 116 + KERNEL_BASE,
|
||||
KeInsertQueue = 117 + KERNEL_BASE,
|
||||
KeInsertQueueApc = 118 + KERNEL_BASE,
|
||||
KeInsertQueueDpc = 119 + KERNEL_BASE,
|
||||
KeInterruptTime = 120 + KERNEL_BASE,
|
||||
KeIsExecutingDpc = 121 + KERNEL_BASE,
|
||||
KeLeaveCriticalRegion = 122 + KERNEL_BASE,
|
||||
KePulseEvent = 123 + KERNEL_BASE,
|
||||
KeQueryBasePriorityThread = 124 + KERNEL_BASE,
|
||||
KeQueryInterruptTime = 125 + KERNEL_BASE,
|
||||
KeQueryPerformanceCounter = 126 + KERNEL_BASE,
|
||||
KeQueryPerformanceFrequency = 127 + KERNEL_BASE,
|
||||
KeQuerySystemTime = 128 + KERNEL_BASE,
|
||||
KeRaiseIrqlToDpcLevel = 129 + KERNEL_BASE,
|
||||
KeRaiseIrqlToSynchLevel = 130 + KERNEL_BASE,
|
||||
KeReleaseMutant = 131 + KERNEL_BASE,
|
||||
KeReleaseSemaphore = 132 + KERNEL_BASE,
|
||||
KeRemoveByKeyDeviceQueue = 133 + KERNEL_BASE,
|
||||
KeRemoveDeviceQueue = 134 + KERNEL_BASE,
|
||||
KeRemoveEntryDeviceQueue = 135 + KERNEL_BASE,
|
||||
KeRemoveQueue = 136 + KERNEL_BASE,
|
||||
KeRemoveQueueDpc = 137 + KERNEL_BASE,
|
||||
KeResetEvent = 138 + KERNEL_BASE,
|
||||
KeRestoreFloatingPointState = 139 + KERNEL_BASE,
|
||||
KeResumeThread = 140 + KERNEL_BASE,
|
||||
KeRundownQueue = 141 + KERNEL_BASE,
|
||||
KeSaveFloatingPointState = 142 + KERNEL_BASE,
|
||||
KeSetBasePriorityThread = 143 + KERNEL_BASE,
|
||||
KeSetDisableBoostThread = 144 + KERNEL_BASE,
|
||||
KeSetEvent = 145 + KERNEL_BASE,
|
||||
KeSetEventBoostPriority = 146 + KERNEL_BASE,
|
||||
KeSetPriorityProcess = 147 + KERNEL_BASE,
|
||||
KeSetPriorityThread = 148 + KERNEL_BASE,
|
||||
KeSetTimer = 149 + KERNEL_BASE,
|
||||
KeSetTimerEx = 150 + KERNEL_BASE,
|
||||
KeStallExecutionProcessor = 151 + KERNEL_BASE,
|
||||
KeSuspendThread = 152 + KERNEL_BASE,
|
||||
KeSynchronizeExecution = 153 + KERNEL_BASE,
|
||||
KeSystemTime = 154 + KERNEL_BASE,
|
||||
KeTestAlertThread = 155 + KERNEL_BASE,
|
||||
KeTickCount = 156 + KERNEL_BASE,
|
||||
KeTimeIncrement = 157 + KERNEL_BASE,
|
||||
KeWaitForMultipleObjects = 158 + KERNEL_BASE,
|
||||
KeWaitForSingleObject = 159 + KERNEL_BASE,
|
||||
KfRaiseIrql = 160 + KERNEL_BASE,
|
||||
KfLowerIrql = 161 + KERNEL_BASE,
|
||||
KiBugCheckData = 162 + KERNEL_BASE,
|
||||
KiUnlockDispatcherDatabase = 163 + KERNEL_BASE,
|
||||
LaunchDataPage = 164 + KERNEL_BASE,
|
||||
MmAllocateContiguousMemory = 165 + KERNEL_BASE,
|
||||
MmAllocateContiguousMemoryEx = 166 + KERNEL_BASE,
|
||||
MmAllocateSystemMemory = 167 + KERNEL_BASE,
|
||||
MmClaimGpuInstanceMemory = 168 + KERNEL_BASE,
|
||||
MmCreateKernelStack = 169 + KERNEL_BASE,
|
||||
MmDeleteKernelStack = 170 + KERNEL_BASE,
|
||||
MmFreeContiguousMemory = 171 + KERNEL_BASE,
|
||||
MmFreeSystemMemory = 172 + KERNEL_BASE,
|
||||
MmGetPhysicalAddress = 173 + KERNEL_BASE,
|
||||
MmIsAddressValid = 174 + KERNEL_BASE,
|
||||
MmLockUnlockBufferPages = 175 + KERNEL_BASE,
|
||||
MmLockUnlockPhysicalPage = 176 + KERNEL_BASE,
|
||||
MmMapIoSpace = 177 + KERNEL_BASE,
|
||||
MmPersistContiguousMemory = 178 + KERNEL_BASE,
|
||||
MmQueryAddressProtect = 179 + KERNEL_BASE,
|
||||
MmQueryAllocationSize = 180 + KERNEL_BASE,
|
||||
MmQueryStatistics = 181 + KERNEL_BASE,
|
||||
MmSetAddressProtect = 182 + KERNEL_BASE,
|
||||
MmUnmapIoSpace = 183 + KERNEL_BASE,
|
||||
NtAllocateVirtualMemory = 184 + KERNEL_BASE,
|
||||
NtCancelTimer = 185 + KERNEL_BASE,
|
||||
NtClearEvent = 186 + KERNEL_BASE,
|
||||
NtClose = 187 + KERNEL_BASE,
|
||||
NtCreateDirectoryObject = 188 + KERNEL_BASE,
|
||||
NtCreateEvent = 189 + KERNEL_BASE,
|
||||
NtCreateFile = 190 + KERNEL_BASE,
|
||||
NtCreateIoCompletion = 191 + KERNEL_BASE,
|
||||
NtCreateMutant = 192 + KERNEL_BASE,
|
||||
NtCreateSemaphore = 193 + KERNEL_BASE,
|
||||
NtCreateTimer = 194 + KERNEL_BASE,
|
||||
NtDeleteFile = 195 + KERNEL_BASE,
|
||||
NtDeviceIoControlFile = 196 + KERNEL_BASE,
|
||||
NtDuplicateObject = 197 + KERNEL_BASE,
|
||||
NtFlushBuffersFile = 198 + KERNEL_BASE,
|
||||
NtFreeVirtualMemory = 199 + KERNEL_BASE,
|
||||
NtFsControlFile = 200 + KERNEL_BASE,
|
||||
NtOpenDirectoryObject = 201 + KERNEL_BASE,
|
||||
NtOpenFile = 202 + KERNEL_BASE,
|
||||
NtOpenSymbolicLinkObject = 203 + KERNEL_BASE,
|
||||
NtProtectVirtualMemory = 204 + KERNEL_BASE,
|
||||
NtPulseEvent = 205 + KERNEL_BASE,
|
||||
NtQueueApcThread = 206 + KERNEL_BASE,
|
||||
NtQueryDirectoryFile = 207 + KERNEL_BASE
|
||||
};
|
||||
|
||||
struct KernelImageThunk {
|
||||
KernelImageFunction addresses[while(std::mem::read_unsigned($, 4) != 0x00)];
|
||||
padding[4];
|
||||
};
|
||||
|
||||
union KernelImageThunkAddress {
|
||||
u32 debugAddress [[format("format_debug_kernel_image_thunk_address")]];
|
||||
u32 retailAddress [[format("format_retail_kernel_image_thunk_address")]];
|
||||
|
||||
if ((debugAddress ^ 0xEFB1F152) - parent.baseAddress < std::mem::size())
|
||||
KernelImageThunk debug @ (debugAddress ^ 0xEFB1F152) - parent.baseAddress;;
|
||||
if ((retailAddress ^ 0x5B6D40B6) - parent.baseAddress < std::mem::size())
|
||||
KernelImageThunk retail @ (retailAddress ^ 0x5B6D40B6) - parent.baseAddress;
|
||||
};
|
||||
|
||||
fn format_debug_kernel_image_thunk_address(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0xEFB1F152);
|
||||
};
|
||||
|
||||
fn format_retail_kernel_image_thunk_address(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0x5B6D40B6);
|
||||
};
|
||||
|
||||
struct TLS {
|
||||
u32 rawDataStart, rawDataEnd;
|
||||
u32 indexAddress;
|
||||
u32 callbacksAddress;
|
||||
type::Size<u32> zeroFillSize;
|
||||
u32 characteristics;
|
||||
};
|
||||
|
||||
fn relative_to_base(auto pointer) {
|
||||
return -parent.baseAddress;
|
||||
};
|
||||
|
||||
fn relative_to_base_section(auto pointer) {
|
||||
return -parent.parent.baseAddress;
|
||||
};
|
||||
|
||||
bitfield LibraryFlags {
|
||||
QFEVersion : 13;
|
||||
Approved : 2;
|
||||
DebugBuild : 1;
|
||||
};
|
||||
|
||||
struct LibraryVersion {
|
||||
char libraryName[8];
|
||||
u16 major, minor, build;
|
||||
LibraryFlags flags;
|
||||
};
|
||||
|
||||
bitfield SectionFlags {
|
||||
Writable : 1;
|
||||
Preload : 1;
|
||||
Executable : 1;
|
||||
InsertedFile : 1;
|
||||
HeadPageReadOnly : 1;
|
||||
TailPageReadOnly : 1;
|
||||
padding : 26;
|
||||
};
|
||||
|
||||
struct SectionHeader {
|
||||
SectionFlags sectionFlags;
|
||||
u32 virtualAddress;
|
||||
type::Size<u32> virtualSize;
|
||||
u32 rawAddress;
|
||||
type::Size<u32> rawSize;
|
||||
char *sectionName[] : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u32 *sectionNameRefrenceCount : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u16 *headSharedPageReferenceCount : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u16 *tailSharedPageReferenceCount : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u8 sectionDigest[20];
|
||||
|
||||
u8 data[rawSize] @ rawAddress [[sealed]];
|
||||
};
|
||||
|
||||
struct XBEH {
|
||||
type::Magic<"XBEH"> magic;
|
||||
u8 signature[0x100] [[sealed]];
|
||||
u32 baseAddress;
|
||||
type::Size<u32> headerSize, imageSize, imageHeaderSize;
|
||||
type::time32_t timeDate;
|
||||
Certificate *certificate : u32 [[pointer_base("relative_to_base")]];
|
||||
u32 numSections;
|
||||
SectionHeader *sectionHeader[numSections] : u32 [[pointer_base("relative_to_base")]];
|
||||
InitializationFlags initializationFlags;
|
||||
EntryPoint entrypoint;
|
||||
TLS *tls : u32 [[pointer_base("relative_to_base")]];
|
||||
|
||||
type::Size<u32> stackSize;
|
||||
u32 peHeapReserve, peHeapCommit, peBaseAddress;
|
||||
type::Size<u32> peImageSize;
|
||||
u32 peChecksum;
|
||||
type::time32_t peTimeDate;
|
||||
char *debugPathNameAddress[] : u32 [[pointer_base("relative_to_base")]];
|
||||
char *debugFileNameAddress[] : u32 [[pointer_base("relative_to_base")]];
|
||||
char16 *utf16DebugFileNameAddress[] : u32 [[pointer_base("relative_to_base")]];
|
||||
KernelImageThunkAddress kernelImageThunkAddress;
|
||||
u32 nonKernelImportDirectoryAddress;
|
||||
u32 numLibraryVersions;
|
||||
LibraryVersion *libraryVersonTable[numLibraryVersions] : u32 [[pointer_base("relative_to_base")]];
|
||||
LibraryVersion *kernelLibraryVersion : u32 [[pointer_base("relative_to_base")]];
|
||||
LibraryVersion *xapiLibraryVersion : u32 [[pointer_base("relative_to_base")]];
|
||||
u32 logoBitMapAddress, logoBitmapSize;
|
||||
u64 unknown1;
|
||||
u32 unknown2;
|
||||
|
||||
u8 logoBitmap[logoBitmapSize] @ logoBitMapAddress - baseAddress;
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description Xbox executable
|
||||
|
||||
#pragma MIME audio/x-xbox-executable
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
#include <type/time.pat>
|
||||
|
||||
#include <std/io.pat>
|
||||
#include <std/mem.pat>
|
||||
|
||||
|
||||
bitfield AllowedMedia {
|
||||
HardDisk : 1;
|
||||
DVD_X2 : 1;
|
||||
DVD_CD : 1;
|
||||
CD : 1;
|
||||
DVD_5_RO : 1;
|
||||
DVD_9_RO : 1;
|
||||
DVD_5_RW : 1;
|
||||
DVD_9_RW : 1;
|
||||
Dongle : 1;
|
||||
MediaBoard : 1;
|
||||
padding : 20;
|
||||
NonSecureHardDisk : 1;
|
||||
NonSecureMode : 1;
|
||||
};
|
||||
|
||||
bitfield GameRegion {
|
||||
NorthAmerica : 1;
|
||||
Japan : 1;
|
||||
RestOfTheWorld : 1;
|
||||
padding : 28;
|
||||
Manufacturing : 1;
|
||||
};
|
||||
|
||||
struct Certificate {
|
||||
type::Size<u32> certificateSize;
|
||||
type::time32_t timeDate;
|
||||
u32 titleId;
|
||||
char16 titleName[0x50 / 2];
|
||||
u32 alternateTitleIds[16];
|
||||
AllowedMedia allowedMedia;
|
||||
GameRegion gameRegion;
|
||||
u32 gameRatings;
|
||||
u128 lanKey;
|
||||
u128 signatureKey;
|
||||
u128 alternateSignatureKeys[16];
|
||||
};
|
||||
|
||||
bitfield InitializationFlags {
|
||||
MountUtilityDrive : 1;
|
||||
FormatUtilityDrive : 1;
|
||||
Limit64Megabytes : 1;
|
||||
DontSetuptHarddisk : 1;
|
||||
padding : 28;
|
||||
};
|
||||
|
||||
union EntryPoint {
|
||||
u32 betaAddress [[format("format_beta_entrypoint")]];
|
||||
u32 debugAddress [[format("format_debug_entrypoint")]];
|
||||
u32 retailAddress [[format("format_retail_entrypoint")]];
|
||||
|
||||
if ((betaAddress ^ 0xE682F45B) - parent.baseAddress < std::mem::size())
|
||||
u8 beta @ (betaAddress ^ 0xE682F45B) - parent.baseAddress;;
|
||||
if ((debugAddress ^ 0x94859D4B) - parent.baseAddress < std::mem::size())
|
||||
u8 debug @ (debugAddress ^ 0x94859D4B) - parent.baseAddress;;
|
||||
if ((retailAddress ^ 0xA8FC57AB) - parent.baseAddress < std::mem::size())
|
||||
u8 retail @ (retailAddress ^ 0xA8FC57AB) - parent.baseAddress;
|
||||
};
|
||||
|
||||
fn format_beta_entrypoint(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0xE682F45B);
|
||||
};
|
||||
|
||||
fn format_debug_entrypoint(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0x94859D4B);
|
||||
};
|
||||
|
||||
fn format_retail_entrypoint(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0xA8FC57AB);
|
||||
};
|
||||
|
||||
#define KERNEL_BASE 0x8000'0000
|
||||
enum KernelImageFunction : u32 {
|
||||
AvGetSavedDataAddress = 1 + KERNEL_BASE,
|
||||
AvSendTVEncoderOption = 2 + KERNEL_BASE,
|
||||
AvSetDisplayMode = 3 + KERNEL_BASE,
|
||||
AvSetSavedDataAddress = 4 + KERNEL_BASE,
|
||||
DbgBreakPoint = 5 + KERNEL_BASE,
|
||||
DbgBreakPointWithStatus = 6 + KERNEL_BASE,
|
||||
DbgLoadImageSymbols = 7 + KERNEL_BASE,
|
||||
DbgPrint = 8 + KERNEL_BASE,
|
||||
HalReadSMCTrayState = 9 + KERNEL_BASE,
|
||||
DbgPrompt = 10 + KERNEL_BASE,
|
||||
DbgUnLoadImageSymbols = 11 + KERNEL_BASE,
|
||||
ExAcquireReadWriteLockExclusive = 12 + KERNEL_BASE,
|
||||
ExAcquireReadWriteLockShared = 13 + KERNEL_BASE,
|
||||
ExAllocatePool = 14 + KERNEL_BASE,
|
||||
ExAllocatePoolWithTag = 15 + KERNEL_BASE,
|
||||
ExEventObjectType = 16 + KERNEL_BASE,
|
||||
ExFreePool = 17 + KERNEL_BASE,
|
||||
ExInitializeReadWriteLock = 18 + KERNEL_BASE,
|
||||
ExInterlockedAddLargeInteger = 19 + KERNEL_BASE,
|
||||
ExInterlockedAddLargeStatistic = 20 + KERNEL_BASE,
|
||||
ExInterlockedCompareExchange64 = 21 + KERNEL_BASE,
|
||||
ExMutantObjectType = 22 + KERNEL_BASE,
|
||||
ExQueryPoolBlockSize = 23 + KERNEL_BASE,
|
||||
ExQueryNonVolatileSetting = 24 + KERNEL_BASE,
|
||||
ExReadWriteRefurbInfo = 25 + KERNEL_BASE,
|
||||
ExRaiseException = 26 + KERNEL_BASE,
|
||||
ExRaiseStatus = 27 + KERNEL_BASE,
|
||||
ExReleaseReadWriteLock = 28 + KERNEL_BASE,
|
||||
ExSaveNonVolatileSetting = 29 + KERNEL_BASE,
|
||||
ExSemaphoreObjectType = 30 + KERNEL_BASE,
|
||||
ExTimerObjectType = 31 + KERNEL_BASE,
|
||||
ExfInterlockedInsertHeadList = 32 + KERNEL_BASE,
|
||||
ExfInterlockedInsertTailList = 33 + KERNEL_BASE,
|
||||
ExfInterlockedRemoveHeadList = 34 + KERNEL_BASE,
|
||||
FscGetCacheSize = 35 + KERNEL_BASE,
|
||||
FscInvalidateIdleBlocks = 36 + KERNEL_BASE,
|
||||
FscSetCacheSize = 37 + KERNEL_BASE,
|
||||
HalClearSoftwareInterrupt = 38 + KERNEL_BASE,
|
||||
HalDisableSystemInterrupt = 39 + KERNEL_BASE,
|
||||
HalDiskCachePartitionCount = 40 + KERNEL_BASE,
|
||||
HalDiskModelNumber = 41 + KERNEL_BASE,
|
||||
HalDiskSerialNumber = 42 + KERNEL_BASE,
|
||||
HalEnableSystemInterrupt = 43 + KERNEL_BASE,
|
||||
HalGetInterruptVector = 44 + KERNEL_BASE,
|
||||
HalReadSMBusValue = 45 + KERNEL_BASE,
|
||||
HalReadWritePCISpace = 46 + KERNEL_BASE,
|
||||
HalRegisterShutdownNotification = 47 + KERNEL_BASE,
|
||||
HalRequestSoftwareInterrupt = 48 + KERNEL_BASE,
|
||||
HalReturnToFirmware = 49 + KERNEL_BASE,
|
||||
HalWriteSMBusValue = 50 + KERNEL_BASE,
|
||||
InterlockedCompareExchange = 51 + KERNEL_BASE,
|
||||
InterlockedDecrement = 52 + KERNEL_BASE,
|
||||
InterlockedIncrement = 53 + KERNEL_BASE,
|
||||
InterlockedExchange = 54 + KERNEL_BASE,
|
||||
InterlockedExchangeAdd = 55 + KERNEL_BASE,
|
||||
InterlockedFlushSList = 56 + KERNEL_BASE,
|
||||
InterlockedPopEntrySList = 57 + KERNEL_BASE,
|
||||
InterlockedPushEntrySList = 58 + KERNEL_BASE,
|
||||
IoAllocateIrp = 59 + KERNEL_BASE,
|
||||
IoBuildAsynchronousFsdRequest = 60 + KERNEL_BASE,
|
||||
IoBuildDeviceIoControlRequest = 61 + KERNEL_BASE,
|
||||
IoBuildSynchronousFsdRequest = 62 + KERNEL_BASE,
|
||||
IoCheckShareAccess = 63 + KERNEL_BASE,
|
||||
IoCompletionObjectType = 64 + KERNEL_BASE,
|
||||
IoCreateDevice = 65 + KERNEL_BASE,
|
||||
IoCreateFile = 66 + KERNEL_BASE,
|
||||
IoCreateSymbolicLink = 67 + KERNEL_BASE,
|
||||
IoDeleteDevice = 68 + KERNEL_BASE,
|
||||
IoDeleteSymbolicLink = 69 + KERNEL_BASE,
|
||||
IoDeviceObjectType = 70 + KERNEL_BASE,
|
||||
IoFileObjectType = 71 + KERNEL_BASE,
|
||||
IoFreeIrp = 72 + KERNEL_BASE,
|
||||
IoInitializeIrp = 73 + KERNEL_BASE,
|
||||
IoInvalidDeviceRequest = 74 + KERNEL_BASE,
|
||||
IoQueryFileInformation = 75 + KERNEL_BASE,
|
||||
IoQueryVolumeInformation = 76 + KERNEL_BASE,
|
||||
IoQueueThreadIrp = 77 + KERNEL_BASE,
|
||||
IoRemoveShareAccess = 78 + KERNEL_BASE,
|
||||
IoSetIoCompletion = 79 + KERNEL_BASE,
|
||||
IoSetShareAccess = 80 + KERNEL_BASE,
|
||||
IoStartNextPacket = 81 + KERNEL_BASE,
|
||||
IoStartNextPacketByKey = 82 + KERNEL_BASE,
|
||||
IoStartPacket = 83 + KERNEL_BASE,
|
||||
IoSynchronousDeviceIoControlRequest = 84 + KERNEL_BASE,
|
||||
IoSynchronousFsdRequest = 85 + KERNEL_BASE,
|
||||
IofCallDriver = 86 + KERNEL_BASE,
|
||||
IofCompleteRequest = 87 + KERNEL_BASE,
|
||||
KdDebuggerEnabled = 88 + KERNEL_BASE,
|
||||
KdDebuggerNotPresent = 89 + KERNEL_BASE,
|
||||
IoDismountVolume = 90 + KERNEL_BASE,
|
||||
IoDismountVolumeByName = 91 + KERNEL_BASE,
|
||||
KeAlertResumeThread = 92 + KERNEL_BASE,
|
||||
KeAlertThread = 93 + KERNEL_BASE,
|
||||
KeBoostPriorityThread = 94 + KERNEL_BASE,
|
||||
KeBugCheck = 95 + KERNEL_BASE,
|
||||
KeBugCheckEx = 96 + KERNEL_BASE,
|
||||
KeCancelTimer = 97 + KERNEL_BASE,
|
||||
KeConnectInterrupt = 98 + KERNEL_BASE,
|
||||
KeDelayExecutionThread = 99 + KERNEL_BASE,
|
||||
KeDisconnectInterrupt = 100 + KERNEL_BASE,
|
||||
KeEnterCriticalRegion = 101 + KERNEL_BASE,
|
||||
MmGlobalData = 102 + KERNEL_BASE,
|
||||
KeGetCurrentIrql = 103 + KERNEL_BASE,
|
||||
KeGetCurrentThread = 104 + KERNEL_BASE,
|
||||
KeInitializeApc = 105 + KERNEL_BASE,
|
||||
KeInitializeDeviceQueue = 106 + KERNEL_BASE,
|
||||
KeInitializeDpc = 107 + KERNEL_BASE,
|
||||
KeInitializeEvent = 108 + KERNEL_BASE,
|
||||
KeInitializeInterrupt = 109 + KERNEL_BASE,
|
||||
KeInitializeMutant = 110 + KERNEL_BASE,
|
||||
KeInitializeQueue = 111 + KERNEL_BASE,
|
||||
KeInitializeSemaphore = 112 + KERNEL_BASE,
|
||||
KeInitializeTimerEx = 113 + KERNEL_BASE,
|
||||
KeInsertByKeyDeviceQueue = 114 + KERNEL_BASE,
|
||||
KeInsertDeviceQueue = 115 + KERNEL_BASE,
|
||||
KeInsertHeadQueue = 116 + KERNEL_BASE,
|
||||
KeInsertQueue = 117 + KERNEL_BASE,
|
||||
KeInsertQueueApc = 118 + KERNEL_BASE,
|
||||
KeInsertQueueDpc = 119 + KERNEL_BASE,
|
||||
KeInterruptTime = 120 + KERNEL_BASE,
|
||||
KeIsExecutingDpc = 121 + KERNEL_BASE,
|
||||
KeLeaveCriticalRegion = 122 + KERNEL_BASE,
|
||||
KePulseEvent = 123 + KERNEL_BASE,
|
||||
KeQueryBasePriorityThread = 124 + KERNEL_BASE,
|
||||
KeQueryInterruptTime = 125 + KERNEL_BASE,
|
||||
KeQueryPerformanceCounter = 126 + KERNEL_BASE,
|
||||
KeQueryPerformanceFrequency = 127 + KERNEL_BASE,
|
||||
KeQuerySystemTime = 128 + KERNEL_BASE,
|
||||
KeRaiseIrqlToDpcLevel = 129 + KERNEL_BASE,
|
||||
KeRaiseIrqlToSynchLevel = 130 + KERNEL_BASE,
|
||||
KeReleaseMutant = 131 + KERNEL_BASE,
|
||||
KeReleaseSemaphore = 132 + KERNEL_BASE,
|
||||
KeRemoveByKeyDeviceQueue = 133 + KERNEL_BASE,
|
||||
KeRemoveDeviceQueue = 134 + KERNEL_BASE,
|
||||
KeRemoveEntryDeviceQueue = 135 + KERNEL_BASE,
|
||||
KeRemoveQueue = 136 + KERNEL_BASE,
|
||||
KeRemoveQueueDpc = 137 + KERNEL_BASE,
|
||||
KeResetEvent = 138 + KERNEL_BASE,
|
||||
KeRestoreFloatingPointState = 139 + KERNEL_BASE,
|
||||
KeResumeThread = 140 + KERNEL_BASE,
|
||||
KeRundownQueue = 141 + KERNEL_BASE,
|
||||
KeSaveFloatingPointState = 142 + KERNEL_BASE,
|
||||
KeSetBasePriorityThread = 143 + KERNEL_BASE,
|
||||
KeSetDisableBoostThread = 144 + KERNEL_BASE,
|
||||
KeSetEvent = 145 + KERNEL_BASE,
|
||||
KeSetEventBoostPriority = 146 + KERNEL_BASE,
|
||||
KeSetPriorityProcess = 147 + KERNEL_BASE,
|
||||
KeSetPriorityThread = 148 + KERNEL_BASE,
|
||||
KeSetTimer = 149 + KERNEL_BASE,
|
||||
KeSetTimerEx = 150 + KERNEL_BASE,
|
||||
KeStallExecutionProcessor = 151 + KERNEL_BASE,
|
||||
KeSuspendThread = 152 + KERNEL_BASE,
|
||||
KeSynchronizeExecution = 153 + KERNEL_BASE,
|
||||
KeSystemTime = 154 + KERNEL_BASE,
|
||||
KeTestAlertThread = 155 + KERNEL_BASE,
|
||||
KeTickCount = 156 + KERNEL_BASE,
|
||||
KeTimeIncrement = 157 + KERNEL_BASE,
|
||||
KeWaitForMultipleObjects = 158 + KERNEL_BASE,
|
||||
KeWaitForSingleObject = 159 + KERNEL_BASE,
|
||||
KfRaiseIrql = 160 + KERNEL_BASE,
|
||||
KfLowerIrql = 161 + KERNEL_BASE,
|
||||
KiBugCheckData = 162 + KERNEL_BASE,
|
||||
KiUnlockDispatcherDatabase = 163 + KERNEL_BASE,
|
||||
LaunchDataPage = 164 + KERNEL_BASE,
|
||||
MmAllocateContiguousMemory = 165 + KERNEL_BASE,
|
||||
MmAllocateContiguousMemoryEx = 166 + KERNEL_BASE,
|
||||
MmAllocateSystemMemory = 167 + KERNEL_BASE,
|
||||
MmClaimGpuInstanceMemory = 168 + KERNEL_BASE,
|
||||
MmCreateKernelStack = 169 + KERNEL_BASE,
|
||||
MmDeleteKernelStack = 170 + KERNEL_BASE,
|
||||
MmFreeContiguousMemory = 171 + KERNEL_BASE,
|
||||
MmFreeSystemMemory = 172 + KERNEL_BASE,
|
||||
MmGetPhysicalAddress = 173 + KERNEL_BASE,
|
||||
MmIsAddressValid = 174 + KERNEL_BASE,
|
||||
MmLockUnlockBufferPages = 175 + KERNEL_BASE,
|
||||
MmLockUnlockPhysicalPage = 176 + KERNEL_BASE,
|
||||
MmMapIoSpace = 177 + KERNEL_BASE,
|
||||
MmPersistContiguousMemory = 178 + KERNEL_BASE,
|
||||
MmQueryAddressProtect = 179 + KERNEL_BASE,
|
||||
MmQueryAllocationSize = 180 + KERNEL_BASE,
|
||||
MmQueryStatistics = 181 + KERNEL_BASE,
|
||||
MmSetAddressProtect = 182 + KERNEL_BASE,
|
||||
MmUnmapIoSpace = 183 + KERNEL_BASE,
|
||||
NtAllocateVirtualMemory = 184 + KERNEL_BASE,
|
||||
NtCancelTimer = 185 + KERNEL_BASE,
|
||||
NtClearEvent = 186 + KERNEL_BASE,
|
||||
NtClose = 187 + KERNEL_BASE,
|
||||
NtCreateDirectoryObject = 188 + KERNEL_BASE,
|
||||
NtCreateEvent = 189 + KERNEL_BASE,
|
||||
NtCreateFile = 190 + KERNEL_BASE,
|
||||
NtCreateIoCompletion = 191 + KERNEL_BASE,
|
||||
NtCreateMutant = 192 + KERNEL_BASE,
|
||||
NtCreateSemaphore = 193 + KERNEL_BASE,
|
||||
NtCreateTimer = 194 + KERNEL_BASE,
|
||||
NtDeleteFile = 195 + KERNEL_BASE,
|
||||
NtDeviceIoControlFile = 196 + KERNEL_BASE,
|
||||
NtDuplicateObject = 197 + KERNEL_BASE,
|
||||
NtFlushBuffersFile = 198 + KERNEL_BASE,
|
||||
NtFreeVirtualMemory = 199 + KERNEL_BASE,
|
||||
NtFsControlFile = 200 + KERNEL_BASE,
|
||||
NtOpenDirectoryObject = 201 + KERNEL_BASE,
|
||||
NtOpenFile = 202 + KERNEL_BASE,
|
||||
NtOpenSymbolicLinkObject = 203 + KERNEL_BASE,
|
||||
NtProtectVirtualMemory = 204 + KERNEL_BASE,
|
||||
NtPulseEvent = 205 + KERNEL_BASE,
|
||||
NtQueueApcThread = 206 + KERNEL_BASE,
|
||||
NtQueryDirectoryFile = 207 + KERNEL_BASE
|
||||
};
|
||||
|
||||
struct KernelImageThunk {
|
||||
KernelImageFunction addresses[while(std::mem::read_unsigned($, 4) != 0x00)];
|
||||
padding[4];
|
||||
};
|
||||
|
||||
union KernelImageThunkAddress {
|
||||
u32 debugAddress [[format("format_debug_kernel_image_thunk_address")]];
|
||||
u32 retailAddress [[format("format_retail_kernel_image_thunk_address")]];
|
||||
|
||||
if ((debugAddress ^ 0xEFB1F152) - parent.baseAddress < std::mem::size())
|
||||
KernelImageThunk debug @ (debugAddress ^ 0xEFB1F152) - parent.baseAddress;;
|
||||
if ((retailAddress ^ 0x5B6D40B6) - parent.baseAddress < std::mem::size())
|
||||
KernelImageThunk retail @ (retailAddress ^ 0x5B6D40B6) - parent.baseAddress;
|
||||
};
|
||||
|
||||
fn format_debug_kernel_image_thunk_address(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0xEFB1F152);
|
||||
};
|
||||
|
||||
fn format_retail_kernel_image_thunk_address(u32 value) {
|
||||
return std::format("0x{:08X}", value ^ 0x5B6D40B6);
|
||||
};
|
||||
|
||||
struct TLS {
|
||||
u32 rawDataStart, rawDataEnd;
|
||||
u32 indexAddress;
|
||||
u32 callbacksAddress;
|
||||
type::Size<u32> zeroFillSize;
|
||||
u32 characteristics;
|
||||
};
|
||||
|
||||
fn relative_to_base(auto pointer) {
|
||||
return -parent.baseAddress;
|
||||
};
|
||||
|
||||
fn relative_to_base_section(auto pointer) {
|
||||
return -parent.parent.baseAddress;
|
||||
};
|
||||
|
||||
bitfield LibraryFlags {
|
||||
QFEVersion : 13;
|
||||
Approved : 2;
|
||||
DebugBuild : 1;
|
||||
};
|
||||
|
||||
struct LibraryVersion {
|
||||
char libraryName[8];
|
||||
u16 major, minor, build;
|
||||
LibraryFlags flags;
|
||||
};
|
||||
|
||||
bitfield SectionFlags {
|
||||
Writable : 1;
|
||||
Preload : 1;
|
||||
Executable : 1;
|
||||
InsertedFile : 1;
|
||||
HeadPageReadOnly : 1;
|
||||
TailPageReadOnly : 1;
|
||||
padding : 26;
|
||||
};
|
||||
|
||||
struct SectionHeader {
|
||||
SectionFlags sectionFlags;
|
||||
u32 virtualAddress;
|
||||
type::Size<u32> virtualSize;
|
||||
u32 rawAddress;
|
||||
type::Size<u32> rawSize;
|
||||
char *sectionName[] : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u32 *sectionNameRefrenceCount : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u16 *headSharedPageReferenceCount : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u16 *tailSharedPageReferenceCount : u32 [[pointer_base("relative_to_base_section")]];
|
||||
u8 sectionDigest[20];
|
||||
|
||||
u8 data[rawSize] @ rawAddress [[sealed]];
|
||||
};
|
||||
|
||||
struct XBEH {
|
||||
type::Magic<"XBEH"> magic;
|
||||
u8 signature[0x100] [[sealed]];
|
||||
u32 baseAddress;
|
||||
type::Size<u32> headerSize, imageSize, imageHeaderSize;
|
||||
type::time32_t timeDate;
|
||||
Certificate *certificate : u32 [[pointer_base("relative_to_base")]];
|
||||
u32 numSections;
|
||||
SectionHeader *sectionHeader[numSections] : u32 [[pointer_base("relative_to_base")]];
|
||||
InitializationFlags initializationFlags;
|
||||
EntryPoint entrypoint;
|
||||
TLS *tls : u32 [[pointer_base("relative_to_base")]];
|
||||
|
||||
type::Size<u32> stackSize;
|
||||
u32 peHeapReserve, peHeapCommit, peBaseAddress;
|
||||
type::Size<u32> peImageSize;
|
||||
u32 peChecksum;
|
||||
type::time32_t peTimeDate;
|
||||
char *debugPathNameAddress[] : u32 [[pointer_base("relative_to_base")]];
|
||||
char *debugFileNameAddress[] : u32 [[pointer_base("relative_to_base")]];
|
||||
char16 *utf16DebugFileNameAddress[] : u32 [[pointer_base("relative_to_base")]];
|
||||
KernelImageThunkAddress kernelImageThunkAddress;
|
||||
u32 nonKernelImportDirectoryAddress;
|
||||
u32 numLibraryVersions;
|
||||
LibraryVersion *libraryVersonTable[numLibraryVersions] : u32 [[pointer_base("relative_to_base")]];
|
||||
LibraryVersion *kernelLibraryVersion : u32 [[pointer_base("relative_to_base")]];
|
||||
LibraryVersion *xapiLibraryVersion : u32 [[pointer_base("relative_to_base")]];
|
||||
u32 logoBitMapAddress, logoBitmapSize;
|
||||
u64 unknown1;
|
||||
u32 unknown2;
|
||||
|
||||
u8 logoBitmap[logoBitmapSize] @ logoBitMapAddress - baseAddress;
|
||||
};
|
||||
|
||||
XBEH xbeh @ 0x00;
|
||||
@@ -1,97 +1,100 @@
|
||||
#include <std/core.pat>
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
#define PAGE_SIZE 0x200
|
||||
|
||||
enum RomSize : u8 {
|
||||
_1GB = 0xFA,
|
||||
_2GB = 0xF8,
|
||||
_4GB = 0xF0,
|
||||
_8GB = 0xE0,
|
||||
_16GB = 0xE1,
|
||||
_32GB = 0xE2
|
||||
};
|
||||
|
||||
bitfield Index {
|
||||
titleKeyDecIndex : 4;
|
||||
kekIndex : 4;
|
||||
};
|
||||
|
||||
bitfield Flags {
|
||||
autoBoot : 1;
|
||||
historyErase : 1;
|
||||
repairTool : 1;
|
||||
differentRegionCupToTerraDevice : 1;
|
||||
differentRegionCupToGlobalDevice : 1;
|
||||
padding : 2;
|
||||
hasNewCardHeader : 1;
|
||||
};
|
||||
|
||||
struct SelSec {
|
||||
u16 t1, t2;
|
||||
};
|
||||
|
||||
struct CardHeader {
|
||||
u8 headerSignature[0x100];
|
||||
type::Magic<"HEAD"> magic;
|
||||
u32 romAreaStartPageAddress;
|
||||
u32 backupAreaStartPageAddress;
|
||||
Index index [[inline]];
|
||||
RomSize romSize;
|
||||
u8 cardHeaderVersion;
|
||||
Flags flags;
|
||||
u64 packageId;
|
||||
u32 validDataEndAddress;
|
||||
padding[4];
|
||||
u8 iv[0x10];
|
||||
u64 partitionFsHeaderAddress;
|
||||
type::Size<u64> partitionFsHeaderSize;
|
||||
u8 partitionFsHeaderHash[0x20];
|
||||
u8 initialDataHash[0x20];
|
||||
SelSec selSec;
|
||||
u32 selT1Key;
|
||||
u32 selKey;
|
||||
u32 limArea;
|
||||
|
||||
u8 cardHeaderEncryptedData[0x70];
|
||||
};
|
||||
|
||||
struct FileEntry {
|
||||
u64 dataOffset;
|
||||
type::Size<u64> dataSize;
|
||||
u32 fileNameOffset;
|
||||
type::Size<u32> hashedRegionSize;
|
||||
padding[8];
|
||||
u8 hash[0x20];
|
||||
};
|
||||
|
||||
struct String {
|
||||
char string[];
|
||||
};
|
||||
|
||||
struct File {
|
||||
String fileName @ addressof(parent.stringTable) + parent.fileEntryTable[std::core::array_index()].fileNameOffset;
|
||||
u8 data[parent.fileEntryTable[std::core::array_index()].dataSize] @ addressof(parent.stringTable) + sizeof(parent.stringTable) + parent.fileEntryTable[std::core::array_index()].dataOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct PartitionFs {
|
||||
type::Magic<"HFS0"> magic;
|
||||
u32 fileCount;
|
||||
type::Size<u32> stringTableSize;
|
||||
padding[4];
|
||||
FileEntry fileEntryTable[fileCount];
|
||||
String stringTable[while($ < (addressof(fileEntryTable) + sizeof(fileEntryTable) + stringTableSize))];
|
||||
|
||||
File files[fileCount];
|
||||
};
|
||||
|
||||
struct XCI {
|
||||
CardHeader header;
|
||||
|
||||
PartitionFs x @ header.romAreaStartPageAddress * PAGE_SIZE;
|
||||
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description Nintendo Switch XCI cardridge ROM
|
||||
|
||||
#include <std/core.pat>
|
||||
|
||||
#include <type/magic.pat>
|
||||
#include <type/size.pat>
|
||||
|
||||
#define PAGE_SIZE 0x200
|
||||
|
||||
enum RomSize : u8 {
|
||||
_1GB = 0xFA,
|
||||
_2GB = 0xF8,
|
||||
_4GB = 0xF0,
|
||||
_8GB = 0xE0,
|
||||
_16GB = 0xE1,
|
||||
_32GB = 0xE2
|
||||
};
|
||||
|
||||
bitfield Index {
|
||||
titleKeyDecIndex : 4;
|
||||
kekIndex : 4;
|
||||
};
|
||||
|
||||
bitfield Flags {
|
||||
autoBoot : 1;
|
||||
historyErase : 1;
|
||||
repairTool : 1;
|
||||
differentRegionCupToTerraDevice : 1;
|
||||
differentRegionCupToGlobalDevice : 1;
|
||||
padding : 2;
|
||||
hasNewCardHeader : 1;
|
||||
};
|
||||
|
||||
struct SelSec {
|
||||
u16 t1, t2;
|
||||
};
|
||||
|
||||
struct CardHeader {
|
||||
u8 headerSignature[0x100];
|
||||
type::Magic<"HEAD"> magic;
|
||||
u32 romAreaStartPageAddress;
|
||||
u32 backupAreaStartPageAddress;
|
||||
Index index [[inline]];
|
||||
RomSize romSize;
|
||||
u8 cardHeaderVersion;
|
||||
Flags flags;
|
||||
u64 packageId;
|
||||
u32 validDataEndAddress;
|
||||
padding[4];
|
||||
u8 iv[0x10];
|
||||
u64 partitionFsHeaderAddress;
|
||||
type::Size<u64> partitionFsHeaderSize;
|
||||
u8 partitionFsHeaderHash[0x20];
|
||||
u8 initialDataHash[0x20];
|
||||
SelSec selSec;
|
||||
u32 selT1Key;
|
||||
u32 selKey;
|
||||
u32 limArea;
|
||||
|
||||
u8 cardHeaderEncryptedData[0x70];
|
||||
};
|
||||
|
||||
struct FileEntry {
|
||||
u64 dataOffset;
|
||||
type::Size<u64> dataSize;
|
||||
u32 fileNameOffset;
|
||||
type::Size<u32> hashedRegionSize;
|
||||
padding[8];
|
||||
u8 hash[0x20];
|
||||
};
|
||||
|
||||
struct String {
|
||||
char string[];
|
||||
};
|
||||
|
||||
struct File {
|
||||
String fileName @ addressof(parent.stringTable) + parent.fileEntryTable[std::core::array_index()].fileNameOffset;
|
||||
u8 data[parent.fileEntryTable[std::core::array_index()].dataSize] @ addressof(parent.stringTable) + sizeof(parent.stringTable) + parent.fileEntryTable[std::core::array_index()].dataOffset [[sealed]];
|
||||
};
|
||||
|
||||
struct PartitionFs {
|
||||
type::Magic<"HFS0"> magic;
|
||||
u32 fileCount;
|
||||
type::Size<u32> stringTableSize;
|
||||
padding[4];
|
||||
FileEntry fileEntryTable[fileCount];
|
||||
String stringTable[while($ < (addressof(fileEntryTable) + sizeof(fileEntryTable) + stringTableSize))];
|
||||
|
||||
File files[fileCount];
|
||||
};
|
||||
|
||||
struct XCI {
|
||||
CardHeader header;
|
||||
|
||||
PartitionFs x @ header.romAreaStartPageAddress * PAGE_SIZE;
|
||||
|
||||
};
|
||||
|
||||
XCI xci @ 0x00;
|
||||
@@ -1,52 +1,55 @@
|
||||
#include <std/mem.pat>
|
||||
#include <std/io.pat>
|
||||
|
||||
struct Flags {
|
||||
be u16 length;
|
||||
u8 value[length];
|
||||
};
|
||||
|
||||
struct TLV {
|
||||
char tag[parent.keySize];
|
||||
be u16 length;
|
||||
char value[length];
|
||||
};
|
||||
|
||||
struct Command {
|
||||
be u32 value;
|
||||
} [[static, sealed, format("format_command")]];
|
||||
|
||||
fn format_command(Command command) {
|
||||
u32 x = command.value;
|
||||
|
||||
if (x == 0x20000000) return "NOP";
|
||||
if (x == 0xAA995566) return "SYNC";
|
||||
if (x == 0x000000BB) return "Bus Width Sync";
|
||||
if (x == 0x11220044) return "Bus Width Detect";
|
||||
if (x == 0x30002001) return "Write to FAR";
|
||||
if (x == 0x28006000) return "Write to FDRO";
|
||||
if (x == 0x30000001) return "Write to CRC";
|
||||
if (x == 0x30018001) return "Write to IDCODE";
|
||||
if (x == 0x30004000) return "Write to FDRI";
|
||||
if (x == 0x30008001) return "Write to CMD";
|
||||
|
||||
if ((x & 0xF0000000) == 0x30000000)
|
||||
return std::format("Write to Register {}", (x & 0x0003E000) >> 13);
|
||||
|
||||
return std::format("0x{:08X}", x);
|
||||
};
|
||||
|
||||
struct Commands {
|
||||
char tag[parent.keySize];
|
||||
be u32 length;
|
||||
Command commands[length / 4];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
Flags flags;
|
||||
be u16 keySize;
|
||||
TLV tlv[4];
|
||||
Commands data;
|
||||
};
|
||||
|
||||
#pragma author WerWolv
|
||||
#pragma description Xilinx FPGA Bitstreams
|
||||
|
||||
#include <std/mem.pat>
|
||||
#include <std/io.pat>
|
||||
|
||||
struct Flags {
|
||||
be u16 length;
|
||||
u8 value[length];
|
||||
};
|
||||
|
||||
struct TLV {
|
||||
char tag[parent.keySize];
|
||||
be u16 length;
|
||||
char value[length];
|
||||
};
|
||||
|
||||
struct Command {
|
||||
be u32 value;
|
||||
} [[static, sealed, format("format_command")]];
|
||||
|
||||
fn format_command(Command command) {
|
||||
u32 x = command.value;
|
||||
|
||||
if (x == 0x20000000) return "NOP";
|
||||
if (x == 0xAA995566) return "SYNC";
|
||||
if (x == 0x000000BB) return "Bus Width Sync";
|
||||
if (x == 0x11220044) return "Bus Width Detect";
|
||||
if (x == 0x30002001) return "Write to FAR";
|
||||
if (x == 0x28006000) return "Write to FDRO";
|
||||
if (x == 0x30000001) return "Write to CRC";
|
||||
if (x == 0x30018001) return "Write to IDCODE";
|
||||
if (x == 0x30004000) return "Write to FDRI";
|
||||
if (x == 0x30008001) return "Write to CMD";
|
||||
|
||||
if ((x & 0xF0000000) == 0x30000000)
|
||||
return std::format("Write to Register {}", (x & 0x0003E000) >> 13);
|
||||
|
||||
return std::format("0x{:08X}", x);
|
||||
};
|
||||
|
||||
struct Commands {
|
||||
char tag[parent.keySize];
|
||||
be u32 length;
|
||||
Command commands[length / 4];
|
||||
};
|
||||
|
||||
struct Header {
|
||||
Flags flags;
|
||||
be u16 keySize;
|
||||
TLV tlv[4];
|
||||
Commands data;
|
||||
};
|
||||
|
||||
Header header @ 0x00;
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description End of Central Directory Header, Central Directory File Headers
|
||||
|
||||
#pragma MIME application/zip
|
||||
|
||||
#include <std/mem.pat>
|
||||
|
||||
90
patterns/zlib.hexpat
Normal file
90
patterns/zlib.hexpat
Normal file
@@ -0,0 +1,90 @@
|
||||
#pragma description ZLIB compressed data format
|
||||
|
||||
#pragma MIME application/zlib
|
||||
|
||||
#include <std/core.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
#define HEADER_SIZE 2
|
||||
#define CSUM_SIZE 4
|
||||
|
||||
using BitfieldOrder = std::core::BitfieldOrder;
|
||||
|
||||
/// Entire stream minus header (2) and checksum (4)
|
||||
u64 data_len = std::mem::size();
|
||||
|
||||
if (data_len > (HEADER_SIZE + CSUM_SIZE)) {
|
||||
data_len -= (HEADER_SIZE + CSUM_SIZE);
|
||||
} else {
|
||||
data_len = 0;
|
||||
}
|
||||
|
||||
/// Compression method; only Deflate is used
|
||||
enum CM: u8 {
|
||||
Deflate = 8,
|
||||
Reserved = 15,
|
||||
};
|
||||
|
||||
/// Compression level
|
||||
enum Level: u8 {
|
||||
Fastest = 0,
|
||||
Fast = 1,
|
||||
Default = 2,
|
||||
Smallest = 3, // slowest
|
||||
};
|
||||
|
||||
// Compression method & flags
|
||||
bitfield Header {
|
||||
CM method : 4;
|
||||
info: 4;
|
||||
fcheck: 5;
|
||||
bool fdict: 1;
|
||||
Level flevel: 2;
|
||||
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
|
||||
|
||||
|
||||
/// Validate the header's checksum
|
||||
fn validate_hdr_checksum(Header hdr) {
|
||||
// Reassemble as a 2-byte big endian value
|
||||
u16 value = (
|
||||
(hdr.method << 8) +
|
||||
(hdr.info << 12) +
|
||||
(hdr.fcheck << 0) +
|
||||
(hdr.fdict << 5) +
|
||||
(hdr.flevel << 6)
|
||||
);
|
||||
|
||||
if (value % 31 == 0) {
|
||||
std::print("Zlib header checksum OK. Value: {}", value);
|
||||
} else {
|
||||
std::warning(std::format("Zlib header checksum failed! Value: {}", value));
|
||||
}
|
||||
};
|
||||
|
||||
/// Representation of a Zlib stream
|
||||
struct Zlib {
|
||||
/// Configuration
|
||||
Header header;
|
||||
|
||||
if (header.fdict) {
|
||||
/// Adler checksum of the optional dictionary
|
||||
u32 dict;
|
||||
}
|
||||
|
||||
/// Compressed data
|
||||
u8 data[data_len];
|
||||
/// Adler-32 checksum of uncompressed data
|
||||
u32 checksum;
|
||||
};
|
||||
|
||||
|
||||
// start parsing at the beginning of stream
|
||||
Zlib zlib @ 0x00;
|
||||
|
||||
// Only mode 8 (deflate) is recognized
|
||||
std::assert_warn(
|
||||
zlib.header.method == CM::Deflate,
|
||||
"Unrecognized compression method"
|
||||
);
|
||||
|
||||
validate_hdr_checksum(zlib.header);
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma description Zstandard compressed data format
|
||||
|
||||
// https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
|
||||
|
||||
#pragma MIME application/zstd
|
||||
|
||||
205
scripts/ksy2pat.py
Normal file
205
scripts/ksy2pat.py
Normal file
@@ -0,0 +1,205 @@
|
||||
import yaml
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
|
||||
output = ""
|
||||
|
||||
top_level_struct_name = ""
|
||||
top_level_struct = ""
|
||||
|
||||
def fixTypeName(name):
|
||||
name = name.replace("_", " ")
|
||||
name = string.capwords(name)
|
||||
name = name.replace(" ", "")
|
||||
|
||||
return name
|
||||
|
||||
def add_line(line, indent = 0):
|
||||
global output
|
||||
output += (" " * indent) + line + "\n"
|
||||
|
||||
def handle_meta_xref(xref):
|
||||
if "mime" in xref:
|
||||
add_line(f"#pragma MIME {xref['mime']}")
|
||||
|
||||
def handle_meta_endian(meta_endian):
|
||||
if meta_endian == "be":
|
||||
add_line("#pragma endian big")
|
||||
elif meta_endian == "le":
|
||||
add_line("#pragma endian little")
|
||||
else:
|
||||
print(f"Unknown endian: {meta_endian}")
|
||||
exit(1)
|
||||
|
||||
def handle_meta(meta):
|
||||
if "xref" in meta:
|
||||
handle_meta_xref(meta["xref"])
|
||||
if "endian" in meta:
|
||||
handle_meta_endian(meta["endian"])
|
||||
if "id" in meta:
|
||||
global top_level_struct_name
|
||||
top_level_struct_name = str(meta["id"]).capitalize()
|
||||
|
||||
def handle_types(types):
|
||||
result = ""
|
||||
for type in types:
|
||||
entry = types[type]
|
||||
|
||||
is_bitfield = False
|
||||
lines = ""
|
||||
|
||||
if "seq" in entry:
|
||||
is_bitfield, lines = handle_seq(entry["seq"])
|
||||
if "instances" in entry:
|
||||
lines += handle_instances(entry["instances"])
|
||||
|
||||
if is_bitfield:
|
||||
result += f"bitfield {fixTypeName(type)} {{\n"
|
||||
else:
|
||||
result += f"struct {fixTypeName(type)} {{\n"
|
||||
|
||||
result += lines + "\n"
|
||||
|
||||
result += "};\n\n"
|
||||
|
||||
return result
|
||||
|
||||
def handle_instances(instances):
|
||||
result = ""
|
||||
for name in instances:
|
||||
instance = instances[name]
|
||||
result += f" auto {name} = {instance['value']} [[export]];"
|
||||
|
||||
if "doc" in instance:
|
||||
result += " // " + instance["doc"].replace('\n', ' ')
|
||||
|
||||
result += "\n"
|
||||
|
||||
return result.rstrip()
|
||||
|
||||
|
||||
def handle_seq(seq):
|
||||
result = ""
|
||||
|
||||
is_bitfield = False
|
||||
lines = []
|
||||
|
||||
for entry in seq:
|
||||
name = entry["id"]
|
||||
entry_type = ""
|
||||
array_size = ""
|
||||
bitfield_field_size = ""
|
||||
content_check = ""
|
||||
docs = ""
|
||||
|
||||
if "doc" in entry:
|
||||
docs = entry["doc"]
|
||||
|
||||
if "type" in entry:
|
||||
entry_type = entry["type"]
|
||||
|
||||
if entry_type == "str":
|
||||
if entry["encoding"] == "UTF-16LE":
|
||||
entry_type = "le char16"
|
||||
elif entry["encoding"] == "UTF-16BE":
|
||||
entry_type = "be char16"
|
||||
else:
|
||||
entry_type = "char"
|
||||
elif entry_type == "u1":
|
||||
entry_type = "u8"
|
||||
elif entry_type == "u2":
|
||||
entry_type = "u16"
|
||||
elif entry_type == "u4":
|
||||
entry_type = "u32"
|
||||
elif entry_type == "u8":
|
||||
entry_type = "u64"
|
||||
elif entry_type == "s1":
|
||||
entry_type = "s8"
|
||||
elif entry_type == "s2":
|
||||
entry_type = "s16"
|
||||
elif entry_type == "s4":
|
||||
entry_type = "s32"
|
||||
elif entry_type == "s8":
|
||||
entry_type = "s64"
|
||||
elif entry_type == "f4":
|
||||
entry_type = "float"
|
||||
elif entry_type == "f8":
|
||||
entry_type = "double"
|
||||
else:
|
||||
entry_type = fixTypeName(entry_type)
|
||||
|
||||
if "contents" in entry:
|
||||
if isinstance(entry["contents"], str):
|
||||
entry_type = f"type::Magic<\"{entry['contents']}\">"
|
||||
else:
|
||||
array_size = len(entry["contents"])
|
||||
encoded_string = ""
|
||||
for char in entry["contents"]:
|
||||
encoded_string += f"\\x{char:02X}"
|
||||
|
||||
entry_type = f"type::Magic<\"{encoded_string}\">"
|
||||
elif "size" in entry:
|
||||
array_size = entry["size"]
|
||||
if isinstance(array_size, str):
|
||||
array_size = array_size.replace("_root", "parent")
|
||||
entry_type = "u8"
|
||||
|
||||
if re.compile("^b[0-9]+$").match(entry_type):
|
||||
is_bitfield = True
|
||||
bitfield_field_size = int(entry_type[1:])
|
||||
|
||||
new_line = ""
|
||||
|
||||
if "if" in entry:
|
||||
new_line += f" if ({entry['if']})\n "
|
||||
|
||||
if array_size != "":
|
||||
new_line += f" {entry_type} {name}[{array_size}];"
|
||||
elif bitfield_field_size != "":
|
||||
new_line += f" {name} : {bitfield_field_size};"
|
||||
else:
|
||||
new_line += f" {entry_type} {name};"
|
||||
|
||||
if docs != "":
|
||||
new_line += " // " + docs.replace('\n', ' ')
|
||||
|
||||
lines.append(new_line)
|
||||
|
||||
for line in lines:
|
||||
result += line + "\n"
|
||||
|
||||
return (is_bitfield, result)
|
||||
|
||||
def generate_imhex_pattern(data):
|
||||
global top_level_struct
|
||||
|
||||
add_line("#include <type/magic.pat>\n")
|
||||
|
||||
if "meta" in data:
|
||||
handle_meta(data["meta"])
|
||||
|
||||
add_line("")
|
||||
|
||||
if "types" in data:
|
||||
add_line(handle_types(data["types"]))
|
||||
|
||||
if "seq" in data:
|
||||
add_line(handle_types({ top_level_struct_name: { "seq": data["seq"] } }))
|
||||
|
||||
add_line(f"{fixTypeName(top_level_struct_name)} {fixTypeName(top_level_struct_name).lower()} @ 0x00;\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: ksy2pat.py <ksy file>")
|
||||
exit(1)
|
||||
|
||||
file_content = ""
|
||||
with open(sys.argv[1]) as f:
|
||||
file_content = f.read()
|
||||
|
||||
data = yaml.load(file_content, Loader=yaml.CLoader)
|
||||
generate_imhex_pattern(data)
|
||||
|
||||
with open(f"{sys.argv[1]}.hexpat", "w") as f:
|
||||
f.write(output)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user