Skip to content

Commit

Permalink
patterns: Added BZip3 File Header Pattern (WerWolv#329)
Browse files Browse the repository at this point in the history
* Added: BZip3 Compression

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

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

* Improved: Import rather than Include std::mem

* Added: Missing 'description' field in pragma
  • Loading branch information
Sewer56 authored and applecuckoo committed Jan 24, 2025
1 parent cae2969 commit ebb6341
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Everything will immediately show up in ImHex's Content Store and gets bundled wi
| BSON | `application/bson` | [`patterns/bson.hexpat`](patterns/bson.hexpat) | BSON (Binary JSON) format |
| bplist | | [`patterns/bplist.hexpat`](patterns/bplist.hexpat) | Apple's binary property list format (bplist) |
| BSP | | [`patterns/bsp_goldsrc.hexpat`](patterns/bsp_goldsrc.hexpat) | GoldSrc engine maps format (used in Half-Life 1) |
| BZIP3 | | [`patterns/bzip3.hexpat`](patterns/bzip3.hexpat) | 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 |
Expand Down
64 changes: 64 additions & 0 deletions patterns/bzip3.hexpat
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma author Sewer56
#pragma description Parses BZip3 compression (file format) by Kamila Szewczyk
#pragma MIME application/x-bzip3
#pragma endian little
#pragma magic [42 5A 33 76 31] @ 0x00
import std.mem;

// Helper function for bit counting
fn popcount(u8 b) {
u32 count = 0;
while (b != 0) {
count = count + (b & 1);
b = b >> 1;
}
return count;
};

// Frame header structure
struct FrameHeader {
char magic[5]; // "BZ3v1"
u32 blockSize; // Maximum block size
};

// Small block header (for blocks < 64 bytes)
struct SmallBlock {
u32 crc32; // CRC32 checksum
u32 literal; // Always 0xFFFFFFFF for small blocks
u8 data[parent.compressedSize - 8]; // Uncompressed data
};

// Regular block (blocks > 64 bytes)
struct Block {
u32 crc32; // CRC32 checksum of uncompressed data
u32 bwtIndex; // Burrows-Wheeler transform index
u8 model; // Compression model flags

if ((model & 0x02) != 0)
u32 lzpSize; // Size after LZP compression
if ((model & 0x04) != 0)
u32 rleSize; // Size after RLE compression

u8 data[parent.compressedSize - (popcount(model) * 4 + 9)];
};

// Main block structure
struct Chunk {
u32 compressedSize; // Size of compressed block
u32 origSize; // Original uncompressed size

if (compressedSize < 64) {
SmallBlock block;
} else {
Block block;
}
};

// Main parsing structure
struct BZip3File {
FrameHeader header;
// Read blocks until end of file
Chunk chunks[while(!std::mem::eof())];
};

BZip3File file @ 0x0;
Binary file added tests/patterns/test_data/bzip3.hexpat.bz3
Binary file not shown.

0 comments on commit ebb6341

Please sign in to comment.