mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
patterns: Added new WebP and VGM patterns (#294)
* README: fix square bracket * patterns: add WebP pattern * patterns/dds: add x-dds mimetype * patterns: add vgm pattern * patterns/vgm: remove old pointer * patterns/protobuf: fix field number handling * patterns/protobuf: add .pb file extension * patterns/uf2: updating the family IDs again * patterns/png: add cHRM and tIME chunks * patterns/png: whoops, old description snuck back in * new quantized-mesh pattern * add quantized-mesh to README, implement oct16 decoding
This commit is contained in:
@@ -25,7 +25,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
|------|------|------|-------------|
|
||||
| 3DS | | [`patterns/3ds.hexpat`](patterns/3ds.hexpat) | Autodesk 3DS Max Model file |
|
||||
| 7Z | | [`patterns/7z.hexpat`](patterns/7z.hexpat) | 7z File Format |
|
||||
| ADTS | | [`patterns/adts.hexpat`(patterns/adts.hexpat) | ADTS/AAC audio files |
|
||||
| ADTS | | [`patterns/adts.hexpat`](patterns/adts.hexpat) | ADTS/AAC audio files |
|
||||
| AFE2 | | [`patterns/afe2.hexpat`](patterns/afe2.hexpat) | Nintendo Switch Atmosphère CFW Fatal Error log |
|
||||
| ANI | `application/x-navi-animation` | [`patterns/ani.hexpat`](patterns/ani.hexpat) | Windows Animated Cursor file |
|
||||
| AR | `application/x-archive` | [`patterns/ar.hexpat`](patterns/ar.hexpat) | Static library archive files |
|
||||
@@ -115,6 +115,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
| 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 |
|
||||
| quantized-mesh | | [`patterns/quantized-mesh.hexpat`](patterns/quantized-mesh.hexpat) | Cesium quantized-mesh terrain |
|
||||
| RAS | `image/x-sun-raster` | [`patterns/ras.hexpat`](patterns/ras.hexpat) | RAS image files |
|
||||
| ReFS | | [`patterns/refs.hexpat`](patterns/refs.hexpat) | Microsoft Resilient File System |
|
||||
| RGBDS | | [`patterns/rgbds.hexpat`](patterns/rgbds.hexpat) | [RGBDS](https://rgbds.gbdev.io) object file format |
|
||||
@@ -136,10 +137,12 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
|
||||
| UF2 | | [`patterns/uf2.hexpat`](patterns/uf2.hexpat) | [USB Flashing Format](https://github.com/microsoft/uf2) |
|
||||
| VBMeta | | [`patterns/vbmeta.hexpat`](patterns/vbmeta.hexpat) | Android VBMeta image |
|
||||
| VDF | | [`patterns/vdf.hexpat`](patterns/vdf.hexpat) | Binary Value Data Format (.vdf) files |
|
||||
| VGM | | [`patterns/vgm.hexpat`](patterns/vgm.hexpat) | VGM (Video Game Music) sound log |
|
||||
| VHDX | | [`patterns/vhdx.hexpat`](patterns/vhdx.hexpat) | Microsoft Hyper-V Virtual Hard Disk format |
|
||||
| WAV | `audio/x-wav` | [`patterns/wav.hexpat`](patterns/wav.hexpat) | RIFF header, WAVE header, PCM header |
|
||||
| WAS | | [`patterns\was_oskasoftware.hexpat`](patterns\was_oskasoftware.hexpat) | Oska Software DeskMates WAS/WA3 (WAVE/MP3 Set) file
|
||||
| WAD | | [`patterns/wad.hexpat`](patterns/wad.hexpat) | DOOM WAD Archive |
|
||||
| WebP | `image/webp` | [`patterns/webp.hexpat`](patterns/webp.hexpat) | Google WebP image |
|
||||
| XBEH | `audio/x-xbox-executable` | [`patterns/xbeh.hexpat`](patterns/xbeh.hexpat) | Xbox executable |
|
||||
| XCI | | [`patterns/xci.hexpat`](patterns/xci.hexpat) | Nintendo Switch XCI cartridge ROM |
|
||||
| XGT | | [`patterns/xgt.hexpat`](patterns/xgstexture.hexpat) | Exient XGS Engine Texture |
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma description DirectDraw Surface
|
||||
|
||||
#pragma MIME image/vnd-ms.dds
|
||||
#pragma MIME image/x-dds
|
||||
#pragma endian little
|
||||
|
||||
enum DXGI_FORMAT : u32 {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma description PNG image
|
||||
#pragma description PNG image
|
||||
|
||||
#pragma MIME image/png
|
||||
#pragma endian big
|
||||
@@ -121,6 +121,26 @@ struct palette_entry_t {
|
||||
u24 color;
|
||||
} [[inline]];
|
||||
|
||||
struct chrm_t {
|
||||
u32 white_point_x;
|
||||
u32 white_point_y;
|
||||
u32 red_x;
|
||||
u32 red_y;
|
||||
u32 green_x;
|
||||
u32 green_y;
|
||||
u32 blue_x;
|
||||
u32 blue_y;
|
||||
};
|
||||
|
||||
struct time_t {
|
||||
u16 year;
|
||||
u8 month;
|
||||
u8 day;
|
||||
u8 hour;
|
||||
u8 minute;
|
||||
u8 second;
|
||||
};
|
||||
|
||||
struct chunk_t {
|
||||
u32 length [[color("17BECF")]];
|
||||
char name[4];
|
||||
@@ -139,6 +159,8 @@ struct chunk_t {
|
||||
#define acTL_k "acTL"
|
||||
#define fdAT_k "fdAT"
|
||||
#define fcTL_k "fcTL"
|
||||
#define cHRM_k "cHRM"
|
||||
#define tIME_k "tIME"
|
||||
|
||||
if (name == IHDR_k) {
|
||||
ihdr_t ihdr [[comment("Image Header chunk"), name("IHDR")]];
|
||||
@@ -167,6 +189,10 @@ struct chunk_t {
|
||||
} else if (name == fdAT_k) {
|
||||
fdat_t fdat [[comment("Frame data chunk")]];
|
||||
u8 data[length-sizeof(u32)];
|
||||
} else if (name == cHRM_k) {
|
||||
chrm_t chrm;
|
||||
} else if (name == tIME_k) {
|
||||
time_t time;
|
||||
} else {
|
||||
u8 data[length];
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#pragma author WerWolv
|
||||
#pragma description Google Protobuf
|
||||
#pragma description Google Protobuf wire encoding (.pb)
|
||||
|
||||
import std.core;
|
||||
import std.io;
|
||||
import std.mem;
|
||||
|
||||
import type.leb128;
|
||||
@@ -31,10 +32,19 @@ enum WireType : u8 {
|
||||
_32Bit = 5
|
||||
};
|
||||
|
||||
bitfield Key {
|
||||
field_number : 5;
|
||||
wire_type : 3;
|
||||
} [[bitfield_order(std::core::BitfieldOrder::MostToLeastSignificant, 8)]];
|
||||
WireType wire_type;
|
||||
u32 tag;
|
||||
u32 field_number;
|
||||
|
||||
struct Key {
|
||||
type::uLEB128 keyDec;
|
||||
field_number = u32(keyDec) >> 3;
|
||||
wire_type = u32(keyDec) & 7;
|
||||
}[[sealed, format("format_key")]];
|
||||
|
||||
fn format_key(Key keyObject) {
|
||||
return std::format("{} with field number {}", wire_type, field_number);
|
||||
};
|
||||
|
||||
union _64Bit {
|
||||
u64 fixed64;
|
||||
@@ -49,22 +59,22 @@ union _32Bit {
|
||||
};
|
||||
|
||||
struct LengthDelimited {
|
||||
type::LEB128 length;
|
||||
type::uLEB128 length;
|
||||
char data[length];
|
||||
};
|
||||
|
||||
|
||||
struct Entry {
|
||||
Key key;
|
||||
Key key;
|
||||
|
||||
if (key.wire_type == WireType::Varint)
|
||||
type::LEB128 value;
|
||||
else if (key.wire_type == WireType::_64Bit)
|
||||
if (wire_type == WireType::Varint)
|
||||
type::uLEB128 value;
|
||||
else if (wire_type == WireType::_64Bit)
|
||||
_64Bit value;
|
||||
else if (key.wire_type == WireType::LengthDelimited)
|
||||
else if (wire_type == WireType::LengthDelimited)
|
||||
LengthDelimited value;
|
||||
else if (key.wire_type == WireType::_32Bit)
|
||||
else if (wire_type == WireType::_32Bit)
|
||||
_32Bit value;
|
||||
};
|
||||
|
||||
Entry entries[while(!std::mem::eof())] @ 0x00;
|
||||
Entry entries[while(!std::mem::eof())] @ 0x00;
|
||||
169
patterns/quantized-mesh.hexpat
Normal file
169
patterns/quantized-mesh.hexpat
Normal file
@@ -0,0 +1,169 @@
|
||||
#pragma author applecuckoo
|
||||
#pragma description Cesium quantized-mesh terrain
|
||||
#pragma endian little
|
||||
|
||||
// based on https://github.com/CesiumGS/quantized-mesh
|
||||
// potential improvements: figure out high water mark encoding for indices
|
||||
|
||||
import std.math;
|
||||
import std.io;
|
||||
|
||||
u8 extensionCount;
|
||||
extensionCount = 0; // NOTE: set this to the amount of extensions in your terrain.
|
||||
|
||||
// ZigZag decoder based on protobuf.hexpat by WerWolv
|
||||
|
||||
struct ZigZag16 {
|
||||
u16 value;
|
||||
} [[sealed, format("format_zigzag16")]];
|
||||
|
||||
fn format_zigzag16(ZigZag16 zigzag) {
|
||||
return s16((s16(zigzag.value) << 1) ^ (s16(zigzag.value) >> 15));
|
||||
};
|
||||
|
||||
struct QuantizedMeshHeader {
|
||||
double CenterX;
|
||||
double CenterY;
|
||||
double CenterZ;
|
||||
|
||||
float MinimumHeight;
|
||||
float MaximumHeight;
|
||||
|
||||
double BoundingSphereCenterX;
|
||||
double BoundingSphereCenterY;
|
||||
double BoundingSphereCenterZ;
|
||||
double BoundingSphereRadius;
|
||||
|
||||
double HorizonOcclusionPointX;
|
||||
double HorizonOcclusionPointY;
|
||||
double HorizonOcclusionPointZ;
|
||||
};
|
||||
|
||||
struct VertexData {
|
||||
u32 vertexCount;
|
||||
ZigZag16 u[vertexCount];
|
||||
ZigZag16 v[vertexCount];
|
||||
ZigZag16 height[vertexCount];
|
||||
};
|
||||
|
||||
struct IndexData16 {
|
||||
u32 triangleCount;
|
||||
u16 indices[triangleCount * 3];
|
||||
};
|
||||
|
||||
struct IndexData32 {
|
||||
u32 triangleCount;
|
||||
u32 indices[triangleCount * 3];
|
||||
};
|
||||
|
||||
struct EdgeIndices16 {
|
||||
u32 westVertexCount;
|
||||
u16 westIndices[westVertexCount];
|
||||
|
||||
u32 southVertexCount;
|
||||
u16 southIndices[southVertexCount];
|
||||
|
||||
u32 eastVertexCount;
|
||||
u16 eastIndices[eastVertexCount];
|
||||
|
||||
u32 northVertexCount;
|
||||
u16 northIndices[northVertexCount];
|
||||
};
|
||||
|
||||
struct EdgeIndices32 {
|
||||
u32 westVertexCount;
|
||||
u32 westIndices[westVertexCount];
|
||||
|
||||
u32 southVertexCount;
|
||||
u32 southIndices[southVertexCount];
|
||||
|
||||
u32 eastVertexCount;
|
||||
u32 eastIndices[eastVertexCount];
|
||||
|
||||
u32 northVertexCount;
|
||||
u32 northIndices[northVertexCount];
|
||||
};
|
||||
|
||||
enum ExtensionTypes : u8 {
|
||||
OctEncodedVertexNormals = 0x1,
|
||||
WaterMask,
|
||||
Metadata = 0x4,
|
||||
};
|
||||
|
||||
// Oct16 decode based on https://github.com/loicgasser/quantized-mesh-tile/blob/master/quantized_mesh_tile/utils.py
|
||||
|
||||
fn signNotZero(float v) {
|
||||
if (v < 0.0)
|
||||
return -1.0;
|
||||
else
|
||||
return 1.0;
|
||||
};
|
||||
|
||||
fn fromSnorm(u8 value) {
|
||||
return float(std::math::clamp(value, 0.0, 255.0) / 255.0 * 2.0 - 1.0);
|
||||
};
|
||||
|
||||
struct Oct16 {
|
||||
u8 x;
|
||||
u8 y;
|
||||
}[[sealed, format("format_oct16")]];
|
||||
|
||||
fn format_oct16(Oct16 oct) {
|
||||
float xOut;
|
||||
float yOut;
|
||||
float zOut;
|
||||
|
||||
xOut = fromSnorm(oct.x);
|
||||
yOut = fromSnorm(oct.y);
|
||||
zOut = 1.0 - (std::math::abs(xOut) + std::math::abs(yOut));
|
||||
|
||||
if (zOut < 0.0) {
|
||||
float oldX;
|
||||
|
||||
oldX = xOut;
|
||||
xOut = (1.0 - std::math::abs(yOut)) * signNotZero(oldX);
|
||||
yOut = (1.0 - std::math::abs(oldX)) * signNotZero(yOut);
|
||||
}
|
||||
|
||||
return std::format("{}, {}, {}", xOut, yOut, zOut);
|
||||
};
|
||||
|
||||
struct OctEncodedVertexNormals {
|
||||
Oct16 xy[parent.parent.vertdata.vertexCount];
|
||||
};
|
||||
|
||||
struct WaterMask {
|
||||
u8 mask[parent.extensionLength];
|
||||
};
|
||||
|
||||
struct Metadata {
|
||||
u32 jsonLength;
|
||||
char json[jsonLength];
|
||||
};
|
||||
|
||||
struct ExtensionHeader {
|
||||
u8 extensionId;
|
||||
u32 extensionLength;
|
||||
match (extensionId) {
|
||||
(ExtensionTypes::OctEncodedVertexNormals): OctEncodedVertexNormals octVertNormals;
|
||||
(ExtensionTypes::WaterMask): WaterMask maskData;
|
||||
(ExtensionTypes::Metadata): Metadata metadata;
|
||||
}
|
||||
};
|
||||
|
||||
struct QuantizedMesh {
|
||||
QuantizedMeshHeader header;
|
||||
VertexData vertdata;
|
||||
|
||||
if (vertdata.vertexCount > 65536) {
|
||||
IndexData32 indexdata;
|
||||
EdgeIndices32 edgeindices;
|
||||
} else {
|
||||
IndexData16 indexdata;
|
||||
EdgeIndices16 edgeindices;
|
||||
}
|
||||
|
||||
ExtensionHeader extensions[extensionCount];
|
||||
};
|
||||
|
||||
QuantizedMesh mesh @ 0x00;
|
||||
@@ -98,6 +98,16 @@ enum UF2_FamilyID : u32 {
|
||||
NRF52832xxAB = 0x6f752678,
|
||||
AT32F415 = 0xa0c97b8e,
|
||||
CH32V = 0x699b62ec,
|
||||
RA4M1 = 0x7be8976d,
|
||||
RTL8710A = 0x9fffd543,
|
||||
RTL8710B = 0x22e0d6fc,
|
||||
RTL8720C = 0xe08f7564,
|
||||
RTL8720D = 0x3379CFE2,
|
||||
XR809 = 0x51e903a8,
|
||||
BK7231U = 0x675a40b0,
|
||||
BK7251 = 0x6a82cc42,
|
||||
BK7231N = 0x7b3ef230,
|
||||
BL602 = 0xde1270b7,
|
||||
};
|
||||
|
||||
fn formatTagType(UF2_TagType type) {
|
||||
|
||||
248
patterns/vgm.hexpat
Normal file
248
patterns/vgm.hexpat
Normal file
@@ -0,0 +1,248 @@
|
||||
#pragma author applecuckoo
|
||||
#pragma description VGM (Video Game Music) sound log
|
||||
|
||||
#pragma endian little
|
||||
|
||||
import type.magic;
|
||||
import std.string;
|
||||
import std.io;
|
||||
|
||||
u32 versionValue;
|
||||
u32 gd3TagPos;
|
||||
u32 chpClkBase;
|
||||
u32 chpVolBase;
|
||||
|
||||
// note: the versionValue variable exists to help check which fields exist and which don't, otherwise the actual log data would show up as part of the header.
|
||||
|
||||
bitfield VGMVersion {
|
||||
bugfix : 4;
|
||||
minor : 4;
|
||||
major : 24;
|
||||
|
||||
versionValue = major * 100 + minor * 10 + bugfix;
|
||||
|
||||
} [[format("format_VGMVersion")]];
|
||||
|
||||
fn format_VGMVersion(auto version) {
|
||||
return std::format("{}.{}{}", version.major, version.minor, version.bugfix);
|
||||
};
|
||||
|
||||
bitfield SN76489Flags {
|
||||
frequency : 1;
|
||||
negateOutput : 1;
|
||||
GameGearStereo : 1;
|
||||
clockDiv : 1;
|
||||
XNORNoiseMode : 1;
|
||||
padding : 3;
|
||||
};
|
||||
|
||||
bitfield AY8910Flags {
|
||||
legacyOutput : 1;
|
||||
singleOutput : 1;
|
||||
discreteOutput : 1;
|
||||
RAWOutput : 1;
|
||||
YMclockDivLow : 1;
|
||||
padding : 3;
|
||||
};
|
||||
|
||||
bitfield OKIM6258Flags {
|
||||
clockDiv : 2;
|
||||
ADPCMsel : 1;
|
||||
outputBitDepth : 1;
|
||||
padding : 4;
|
||||
};
|
||||
|
||||
bitfield K054539Flags {
|
||||
reverseStereo : 1;
|
||||
disableReverb : 1;
|
||||
KeyOnUpdate : 1;
|
||||
padding : 5;
|
||||
};
|
||||
|
||||
enum AY8190Type : u8 {
|
||||
AY8910,
|
||||
AY8912,
|
||||
AY8913,
|
||||
AY8914,
|
||||
YM2149 = 0x10,
|
||||
YM3439,
|
||||
YMZ284,
|
||||
YMZ294,
|
||||
};
|
||||
|
||||
enum C140Type : u8 {
|
||||
C140_NamcoSystem2,
|
||||
C140_NamcoSystem21,
|
||||
ASIC219_NamcoNA,
|
||||
};
|
||||
|
||||
struct Gd3 {
|
||||
type::Magic<"Gd3 "> ident;
|
||||
VGMVersion version;
|
||||
u32 Gd3Length;
|
||||
std::string::NullString16 trackNameEng;
|
||||
std::string::NullString16 trackNameOriginal;
|
||||
std::string::NullString16 gameNameEng;
|
||||
std::string::NullString16 gameNameOriginal;
|
||||
std::string::NullString16 sysNameEng;
|
||||
std::string::NullString16 sysNameOriginal;
|
||||
std::string::NullString16 trackAuthorEnglish;
|
||||
std::string::NullString16 trackAuthorOriginal;
|
||||
std::string::NullString16 gameReleaseDate;
|
||||
std::string::NullString16 VGMConverter;
|
||||
std::string::NullString16 Notes;
|
||||
};
|
||||
|
||||
struct baseHeader {
|
||||
type::Magic<"Vgm "> ident;
|
||||
u32 eofOffset;
|
||||
VGMVersion version;
|
||||
u32 SN76489_clk;
|
||||
u32 YM2413_clk;
|
||||
gd3TagPos = $;
|
||||
u32 Gd3Offset;
|
||||
u32 sampleCount;
|
||||
u32 loopOffset;
|
||||
u32 loopSamples;
|
||||
};
|
||||
|
||||
struct Header : baseHeader {
|
||||
if (versionValue >= 101) {
|
||||
u32 rate;
|
||||
} if (versionValue >= 110) {
|
||||
u16 SN76489_feedback;
|
||||
u8 SN76489_shift_width;
|
||||
} if (versionValue >= 151) {
|
||||
SN76489Flags snflags;
|
||||
} else {
|
||||
padding[1];
|
||||
} if (versionValue >= 110) {
|
||||
u32 YM2612_clk;
|
||||
u32 YM2151_clk;
|
||||
} if (versionValue >= 150) {
|
||||
u32 VGMOffset;
|
||||
} if (versionValue >= 151) {
|
||||
u32 SegaPCM_clk;
|
||||
u32 SegaPCM_reg;
|
||||
u32 RF5C68_clk;
|
||||
u32 YM2203_clk;
|
||||
u32 YM2608_clk;
|
||||
u32 YM2610_clk;
|
||||
u32 YM3812_clk;
|
||||
u32 YM3526_clk;
|
||||
u32 Y8950_clk;
|
||||
u32 YMF262_clk;
|
||||
u32 YMF278B_clk;
|
||||
u32 YMF271_clk;
|
||||
u32 YMZ280B_clk;
|
||||
u32 RF5C164_clk;
|
||||
u32 PWM_clk;
|
||||
u32 AY8910_clk;
|
||||
AY8190Type AY8910_type;
|
||||
AY8910Flags AY8910_flags;
|
||||
u8 YM2203_flags;
|
||||
u8 YM2608_flags;
|
||||
} if (versionValue >= 160) {
|
||||
u8 volumeMod;
|
||||
padding[1];
|
||||
u8 loopBase;
|
||||
} else {
|
||||
padding[3];
|
||||
} if (versionValue >= 151) {
|
||||
u8 loopMod;
|
||||
} if (versionValue >= 161) {
|
||||
u32 DMG_clk;
|
||||
u32 APU_clk;
|
||||
u32 MultiPCM_clk;
|
||||
u32 uPD7759_clk;
|
||||
u32 OKIM6258_clk;
|
||||
OKIM6258Flags OKIM6258_flags;
|
||||
K054539Flags K054539_flags;
|
||||
C140Type C140_type;
|
||||
padding[1];
|
||||
u32 OKIM6295_clk;
|
||||
u32 K051649_clk;
|
||||
u32 K054539_clk;
|
||||
u32 HuC6280_clk;
|
||||
u32 C140_clk;
|
||||
u32 K053260_clk;
|
||||
u32 Pokey_clk;
|
||||
u32 QSound_clk;
|
||||
} if (versionValue >= 171) {
|
||||
u32 SCSP_clk;
|
||||
} else {
|
||||
padding[4];
|
||||
} if (versionValue >= 170) {
|
||||
u32 extraHeaderOffset;
|
||||
} if (versionValue >= 171) {
|
||||
u32 WonderSwan_clk;
|
||||
u32 VSU_clk;
|
||||
u32 SAA1099_clk;
|
||||
u32 ES5503_clk;
|
||||
u32 ES5005_clk;
|
||||
u8 ES5503_ch;
|
||||
u8 ES5505_ch;
|
||||
u8 C352_clockDiv;
|
||||
padding[1];
|
||||
u32 X1_010_clk;
|
||||
u32 C352_clk;
|
||||
u32 GA20_clk;
|
||||
} if (versionValue > 172) {
|
||||
u32 Mikey_clk;
|
||||
}
|
||||
};
|
||||
|
||||
struct chpClkEntry {
|
||||
u8 chpID;
|
||||
u32 chpClk;
|
||||
};
|
||||
|
||||
struct chpClkHeader {
|
||||
u8 entryCount;
|
||||
chpClkEntry entries[entryCount];
|
||||
};
|
||||
|
||||
bitfield chpVolume {
|
||||
volume : 15;
|
||||
absoluteRelative : 1;
|
||||
};
|
||||
|
||||
struct chpVolEntry {
|
||||
u8 chpID;
|
||||
u8 flags;
|
||||
chpVolume chpVol;
|
||||
};
|
||||
|
||||
struct chpVolHeader {
|
||||
u8 entryCount;
|
||||
chpVolEntry entries[entryCount];
|
||||
};
|
||||
|
||||
struct ExtraHeader {
|
||||
u32 headerSize;
|
||||
chpClkBase = $;
|
||||
u32 chpClkOffset;
|
||||
chpVolBase = $;
|
||||
u32 chpVolOffset;
|
||||
|
||||
if (chpClkOffset > 0) {
|
||||
$ = chpClkBase + chpClkOffset;
|
||||
chpClkHeader chpClk;
|
||||
} if (chpVolOffset > 0) {
|
||||
$ = chpVolBase + chpVolOffset;
|
||||
chpVolHeader chpVol;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct VGM {
|
||||
Header header;
|
||||
if (versionValue >= 170) {
|
||||
if (header.extraHeaderOffset > 0) {
|
||||
ExtraHeader extraHeader;
|
||||
}
|
||||
}
|
||||
Gd3 tag @ (gd3TagPos + header.Gd3Offset);
|
||||
};
|
||||
|
||||
VGM vgm @ 0x00;
|
||||
122
patterns/webp.hexpat
Normal file
122
patterns/webp.hexpat
Normal file
@@ -0,0 +1,122 @@
|
||||
#pragma author applecuckoo
|
||||
#pragma description Google WebP
|
||||
|
||||
#pragma endian little
|
||||
#pragma MIME image/webp
|
||||
|
||||
// based off of ttf.hexpat by Rebuild and wav.hexpat by WerWolv
|
||||
|
||||
import std.mem;
|
||||
import std.core;
|
||||
import type.magic;
|
||||
|
||||
struct RiffHeader {
|
||||
char ckID[4] [[comment("Container Signature"), name("RIFF Header Signature")]];
|
||||
u32 ckSize [[comment("Size of RIFF Header"), name("RIFF Chunk Size")]];
|
||||
char format[4] [[comment("RIFF format"), name("WAVE Header Signature")]];
|
||||
};
|
||||
|
||||
struct WebPChunk {
|
||||
char chunkId[4];
|
||||
u32 chunkSize;
|
||||
};
|
||||
|
||||
bitfield VP8XFlags {
|
||||
padding : 1;
|
||||
A : 1;
|
||||
X : 1;
|
||||
E : 1;
|
||||
L : 1;
|
||||
I : 1;
|
||||
padding : 2;
|
||||
};
|
||||
|
||||
struct OneBase {
|
||||
u24 value;
|
||||
} [[sealed, format("format_onebase")]];
|
||||
|
||||
fn format_onebase(OneBase onebase) {
|
||||
return onebase.value + 1;
|
||||
};
|
||||
|
||||
struct WebPVP8XData {
|
||||
VP8XFlags flags;
|
||||
padding[3];
|
||||
OneBase canvasWidth;
|
||||
OneBase canvasHeight;
|
||||
};
|
||||
|
||||
struct WebPANIMData {
|
||||
u32 backgroundColor;
|
||||
u16 loopCount;
|
||||
};
|
||||
|
||||
bitfield ANMFFlags {
|
||||
D : 1;
|
||||
B : 1;
|
||||
padding : 6;
|
||||
};
|
||||
|
||||
bitfield WebPVP8LHeader {
|
||||
widthMinusOne : 14;
|
||||
heightMinusOne : 14;
|
||||
alphaUsed : 1;
|
||||
version : 3;
|
||||
};
|
||||
|
||||
struct WebPVP8LData {
|
||||
type::Magic<"\x2f"> id;
|
||||
WebPVP8LHeader header;
|
||||
};
|
||||
|
||||
u32 frameSize;
|
||||
|
||||
struct WebPANMFData {
|
||||
u24 frameX;
|
||||
u24 frameY;
|
||||
OneBase frameWidth;
|
||||
OneBase frameHeight;
|
||||
u24 frameDuration;
|
||||
ANMFFlags flags;
|
||||
u8 data[parent.chunkHeader.chunkSize - 16]; // lazy fix - can't be bothered implementing subchunks
|
||||
|
||||
};
|
||||
|
||||
bitfield ALPHFlags {
|
||||
C : 2;
|
||||
F : 2;
|
||||
P : 2;
|
||||
padding : 2;
|
||||
};
|
||||
|
||||
u32 paddedChunkSize;
|
||||
|
||||
struct WebPData {
|
||||
WebPChunk chunkHeader;
|
||||
paddedChunkSize = (chunkHeader.chunkSize + 1) >> 1 << 1;
|
||||
match (chunkHeader.chunkId) {
|
||||
("VP8X"): WebPVP8XData VP8XData;
|
||||
("ANIM"): WebPANIMData ANIMData;
|
||||
("ANMF"): {
|
||||
WebPANMFData ANMFData;
|
||||
padding[paddedChunkSize - sizeof(ANMFData)];
|
||||
}
|
||||
("VP8L"): {
|
||||
WebPVP8LHeader VP8LData;
|
||||
u8 image[chunkHeader.chunkSize-3];
|
||||
padding[paddedChunkSize - sizeof(VP8LData) - sizeof(image)];
|
||||
}
|
||||
("ALPH"): {
|
||||
ALPHFlags flags;
|
||||
u8 ALPHData[chunkHeader.chunkSize-1];
|
||||
padding[paddedChunkSize - sizeof(ALPHData) - sizeof(flags)];
|
||||
}
|
||||
(_): {
|
||||
u8 data[chunkHeader.chunkSize];
|
||||
padding[paddedChunkSize - sizeof(data)];
|
||||
}
|
||||
}
|
||||
} [[name(std::format("Chunk ({})", chunkHeader.chunkId))]];;
|
||||
|
||||
RiffHeader header @0x00;
|
||||
WebPData data[while (!std::mem::eof())] @ $;
|
||||
BIN
tests/patterns/test_data/webp.hexpat.webp
Normal file
BIN
tests/patterns/test_data/webp.hexpat.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 934 B |
Reference in New Issue
Block a user