reverse engineering substance designer file format

So I spent a bit of time using 010 Editor and breaking down the .sbsar file format used by Substance Designer. It was like trying to solve a jigsaw puzzle. Snapping those first few pieces together was addictive. Unfortunately, I did not document my experiences and a lot of interpretation is now forgotten.  I was able to breakdown simple “hello world” .sbsar files. Identifying a handful of nodes and their properties. Here is the .bt script and a screenshot of applying the script:

//—————–

——————————-
//— 010 Editor v7.0.2 Binary Template
//
// File:
// Authors:
// Version:
// Purpose:
// Category:
// File Mask:
// ID Bytes:
// History:
//————————————————

local int numOutputNodes = 2;

struct SBSAR {

struct HEADER{
char signature[4];
int UNKNOWN_contentFlag;
int cookerBuild;
uint asmUid;
int fileLength;
int UNKNOWN_1cJump;
int UNKNOWN_zeroPadding_1;
int fileLengthFromJump;
ushort versionMajor;
ushort versionMinor;
int UKNOWN_zeroPadding_2;
int UNKNOWN_headerEndFlag;
} header <bgcolor=cLtGray>;

local int numNodes = ReadInt(header.fileLength-16);

struct DELTAJUMPS (int numNodes, int numOutputNodes) {
int zeroDelta;
int UNKNOWN_constant;
int UNKNOWN_zeroPadding_3;
int deltas[numNodes];
int lastIndexes[numOutputNodes*2] <bgcolor=cGray>;

} deltaJumps(numNodes, numOutputNodes) <bgcolor=cPurple, open=true>;

local int nodeByteSizes[numNodes];
local int i;
for(i = 0; i < numNodes – 1; i++) {
nodeByteSizes[i] = deltaJumps.deltas[i+1] – deltaJumps.deltas[i];
}
nodeByteSizes[i] = deltaJumps.zeroDelta – deltaJumps.deltas[numNodes-1];
for(i = 0; i < numNodes; i++) {
Printf(“node[%i] = %i\n”, i, nodeByteSizes[i]);
}
local int j;
for(i = 0; i < numNodes; i++) {
if(i % 2 == 0) {
for(j = 0; j < nodeByteSizes[i]/4; j++) {
int n <bgcolor=cAqua>;
}
}
else {
for(j = 0; j < nodeByteSizes[i]/4; j++) {
int n <bgcolor=cLtBlue>;
}
}
}

// could use jump delta[0] as first 32
// – node[0] size
// 40 = 64
// 32 – node[1] size
// 60 = 96
// 20 – node[2] size
// 74 = 116
// 32 – node[3] size
// 94 = 148
// 20 – node[4] size – not including format 0,8,8
// A8 = 168

struct NODEINFO () {
ushort numOutputNodes <bgcolor=cDkAqua>;
ushort numInputNodes <bgcolor=cDkGreen>;
int outputNodes[numOutputNodes] <bgcolor=cDkAqua>;
if(numInputNodes > 0) {
int inputNodes[numInputNodes*2] <bgcolor=cDkGreen>;
}
int numNodes <bgcolor=cRed>;
int numNodesLowDiff <bgcolor=cLtGray>;
int numNodesHighDiff <bgcolor=cLtGray>;
int offsetToInputType <bgcolor=cSilver>;

} nodeinfo;

} sbsar <open=true>;

 

Leave a Reply