Skip to content

Commit

Permalink
patterns/fbx: Improved the FBX pattern (#302)
Browse files Browse the repository at this point in the history
* patterns/fbx: Improved the FBX pattern
-Added pragma magic
-Fixed sizing of compressed contents array
-Added references
-Cleaned up whitespace

* Added missing ] bracket in README.md
  • Loading branch information
Hikodroid authored Nov 17, 2024
1 parent 46e41db commit abc78d1
Showing 1 changed file with 34 additions and 25 deletions.
59 changes: 34 additions & 25 deletions patterns/fbx.hexpat
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
#pragma description Kaydara FBX Binary
#pragma magic [4B 61 79 64 61 72 61 20 46 42 58 20 42 69 6E 61 72 79 20 20 00 1A 00] @ 0x00

// Based on Blenders implementation of FBX import/export
/*
* Based on Blenders implementation of FBX import/export, see:
* (incomplete) https://code.blender.org/2013/08/fbx-binary-file-format-specification/
* https://projects.blender.org/blender/blender/src/branch/main/scripts/addons_core/io_scene_fbx/parse_fbx.py
* https://projects.blender.org/blender/blender/src/branch/main/scripts/addons_core/io_scene_fbx/encode_bin.py
*/

#pragma endian little

Expand All @@ -17,9 +23,9 @@ struct Array<E> {
u32 arrayLength;
u32 encoding;
u32 compressedLength;

std::assert(encoding < 2, "Invalid array encoding!");

if (encoding == 0) {
// Uncompressed
E contents[arrayLength];
Expand All @@ -31,7 +37,11 @@ struct Array<E> {
#ifdef __IMHEX__
std::mem::Section contentsSection = std::mem::create_section(std::format("contentsSection @ {:#x}", pos));
hex::dec::zlib_decompress(compressedContents, contentsSection, 15);
E contents[] @ 0x00 in contentsSection;
auto contentsSectionSize = std::mem::get_section_size(contentsSection);
auto contentsElementSize = sizeof(E);
std::assert_warn((contentsSectionSize % contentsElementSize) == 0,
"The size of the contentsSection must be an integer multiple of sizeof(E) !");
E contents[contentsSectionSize / contentsElementSize] @ 0x00 in contentsSection;
#endif
}
};
Expand All @@ -57,7 +67,7 @@ enum PropertyTypeCode : char {

struct PropertyRecord {
PropertyTypeCode typeCode;

match (typeCode) {
(PropertyTypeCode::BYTE): s8 data;
(PropertyTypeCode::SHORT): s16 data;
Expand Down Expand Up @@ -90,15 +100,15 @@ struct NodeRecord32 {
u32 numProperties;
u32 propertyListLen;
u8 nameLen;

// Detect sentinel record which marks the end of a list of node records
if (endOffset == 0
&& numProperties == 0
&& propertyListLen == 0
if (endOffset == 0
&& numProperties == 0
&& propertyListLen == 0
&& nameLen == 0) {
break;
}

char name[nameLen];
auto posBeforePropertyRecords = $;
auto posAfterPropertyRecords = posBeforePropertyRecords + propertyListLen;
Expand All @@ -113,15 +123,15 @@ struct NodeRecord64 {
u64 numProperties;
u64 propertyListLen;
u8 nameLen;

// Detect sentinel record which marks the end of a list of node records
if (endOffset == 0
&& numProperties == 0
&& propertyListLen == 0
if (endOffset == 0
&& numProperties == 0
&& propertyListLen == 0
&& nameLen == 0) {
break;
}

char name[nameLen];
auto posBeforePropertyRecords = $;
auto posAfterPropertyRecords = posBeforePropertyRecords + propertyListLen;
Expand All @@ -133,27 +143,27 @@ struct NodeRecord64 {

fn assertZero (auto array, u128 size, auto message) {
bool nonzeroPadding = false;

for (u8 i = 0, i < size, i = i + 1) {
if (array[i] != 0) {
nonzeroPadding = true;
}
}

std::assert_warn(!nonzeroPadding, message);
};

struct Footer{
struct Footer {
type::Magic<"\xFA\xBC\xAB\x09\xD0\xC8\xD4\x66\xB1\x76\xFB\x83\x1C\xF7\x26\x7E"> footerId;
char zeroes[4];
assertZero(zeroes, 4, "Found non-zero values in footer after footerId!");
u128 ofs = $;
u8 alignmentPaddingSize = ((ofs + 15) & ~15) - ofs;

if (alignmentPaddingSize == 0) {
alignmentPaddingSize = 16;
}

char alignmentPadding[alignmentPaddingSize];
assertZero(alignmentPadding, alignmentPaddingSize, "Found non-zero bytes in alignmentPadding!");
u32 version;
Expand All @@ -162,23 +172,22 @@ struct Footer{
type::Magic<"\xF8\x5A\x8C\x6A\xDE\xF5\xD9\x7E\xEC\xE9\x0C\xE3\x75\x8F\x29\x0B"> footerMagic;
};


struct Header {
type::Magic<"Kaydara FBX Binary \x00\x1A\x00"> magic;
u32 version;
};

struct FBX {
Header header;
if (header.version < 7500) {

if (header.version < 7500) {
NodeRecord32 rootRecords[while(true)];
} else {
NodeRecord64 rootRecords[while(true)];
}

Footer footer;
std::assert_warn(header.version == footer.version, "Version numbers in header and footer do not match!");
};

FBX fbx @ 0x00;
FBX fbx @ 0x00;

0 comments on commit abc78d1

Please sign in to comment.