/*****************************************************************************
* dat.bt - Structure definitions for Super Smash Brothers Melee - dat file related entities.
*
*****************************************************************************
* Revision History:
* 2009/09/29 - revel8n - Original
* 2010/02/22 - revel8n - Changes based on information from breakpoint
* 2010/02/22 - revel8n - More structure updates
* 2010/02/23 - revel8n - Started adding other structures (FIGHTER and FIGATREE)
*/
#include "common-types.bt"
local uint32 t, cnt, savedFilePointer;
void PushFP(void) { savedFilePointer = FTell(); }
void PopFP(void) { FSeek(savedFilePointer); }
// used only to provide a way of giving "empty" structures a perceived size
void PopOffsetFP(uint32 offset) {FSeek(savedFilePointer + offset);}
void FSeekOfs(uint32 ofs) { FSeek(0x20 + ofs); }
// returns the number of consecutive 32-bit values until zero is reached
// zero itself is not included in the count, and file pointer is not moved
uint32 GetArrayCount(void)
{
local uint32 cnt = 0;
PushFP();
while (ReadUInt(FTell()) != 0)
{
FSeek(FTell() + 4);
cnt++;
}
PopFP();
return cnt;
}
void DumpTransform(uint32 ofs);
void DumpJObj(uint32 ofs);
void DumpDObj(uint32 ofs);
void DumpMObj(uint32 ofs);
void DumpPObj(uint32 ofs);
void DumpTObj(uint32 ofs);
void DumpVtxAttr(uint32 ofs);
void DumpImageHeader(uint32 ofs);
void DumpPaletteHeader(uint32 ofs);
void DumpMaterialColors(uint32 ofs);
void DumpJointWeights(uint32 ofs);
void DumpDisplayList(uint32 ofs);
void DumpFighter(uint32 ofs);
SetReadOnly(true);
// #pragma displayname("dat structures")
// #pragma fileextensions(".dat")
// #pragma byteorder(big_endian)
BigEndian();
// mark used bytes with a light green background
local int64 filePos = FTell();
// pobj, aobj, lobj, gobj, tobj, mobj, cobj, fobj, sobj, robj, dobj, wobj
struct ROOT_NODE
{
uint32 dataOffset <format = hex>;
uint32 stringTableOffset <format = hex>; // relative to the end of root node arrays
};
struct JOBJ_DATA
{
// 0x00
uint32 unknownOffset0x00 <format = hex>;
uint32 flags <format = hex>;
uint32 nextOffset <format = hex>; // next jobj structure?
uint32 childOffset <format = hex>; // child jobj structure?
// 0x10
uint32 dobjOffset <format = hex>; // dobj structure - object information?
float3 rotation; // rotation?
float3 scale; // scale?
float3 translation; // translation?
uint32 transformOffset <format = hex>; // inverse transform
uint32 unknown0x3C;
if (transformOffset != 0)
{
DumpTransform(transformOffset);
}
// dump dobj
if (dobjOffset != 0)
{
struct
{
DumpDObj(dobjOffset);
} dobjs;
}
};
struct DOBJ_DATA
{
uint32 unknown0x00;
uint32 nextOffset <format = hex>; // next dobj structure
uint32 mobjOffset <format = hex>; // mobj structure - material information?
uint32 pobjOffset <format = hex>; // pobj structure - mesh information?
if (mobjOffset != 0)
DumpMObj(mobjOffset);
// dump pobj
if (pobjOffset != 0)
{
struct
{
DumpPObj(pobjOffset);
} pobjs;
}
};
struct MOBJ_DATA
{
// 0x00
uint32 unknown0x00;
uint32 unknownFlags0x04 <format = hex>;
uint32 tobjOffset <format = hex>; // tobj structure
uint32 materialOffset <format = hex>; // material colors?
// 0x10
uint32 unknown0x10;
uint32 unknown0x14;
if (tobjOffset != 0)
DumpTObj(tobjOffset);
if (materialOffset != 0)
DumpMaterialColors(materialOffset);
};
struct MATERIAL_COLORS
{
// 0x00
uint32 unknownColor0x00 <format = hex>; // diffuse?
uint32 unknownColor0x04 <format = hex>; // ambient?
uint32 unknownColor0x08 <format = hex>; // specular?
float unknown0x0C;
// 0x10
float unknown0x10;
};
struct TOBJ_DATA
{
uint32 unknown0x00[19];
uint32 imageOffset <format = hex>; // image header information
uint32 paletteOffset <format = hex>; // palette header information
uint32 unknown0x54;
uint32 unknownOffset0x58 <format = hex>;
if (imageOffset != 0)
DumpImageHeader(imageOffset);
if (paletteOffset != 0)
DumpPaletteHeader(paletteOffset);
};
struct IMAGE_HEADER
{
uint32 imageOffset <format = hex>; // image data
uint16 height;
uint16 width;
uint32 imageFormat;
};
struct PALETTE_HEADER
{
uint32 paletteOffset <format = hex>; // palette data
uint32 paletteFormat;
uint32 unknown0x08;
uint16 colorCount;
uint16 unknown0x0A;
};
struct POBJ_DATA
{
// 0x00
uint32 unknown0x00;
uint32 nextOffset <format = hex>;
uint32 vertexAttrArray <format = hex>; // Unk04 structure - geometry information?
uint16 unknownFlags0x0C <format = hex>;
uint16 displayListSize0x0C; // number of 0x20 (32) byte block occupied by display list data
// 0x10
uint32 displayListOffset <format = hex>; // display list
uint32 weightListOffset <format = hex>; // joint weight info?
if (vertexAttrArray != 0)
DumpVtxAttr(vertexAttrArray);
if (displayListOffset != 0)
DumpDisplayList(displayListOffset);
if (weightListOffset != 0)
DumpJointWeights(weightListOffset);
};
// vertex declaration and attribute information
// attr, type, cnt, data_type, flags?, file_offset
struct ATTR_DATA
{
// 0x00
uint32 vtxAttr; // attr
uint32 vtxAttrType; // index_type
uint32 compCnt; // cnt
uint32 compType; // data_type
// 0x10
uint16 unknown0x10;
uint16 vtxStride;
uint32 dataOffset <format = hex>; // data offset
};
struct WEIGHT_DATA
{
uint32 jobjOffset <format = hex>;
float weight;
};
struct DISPLAY_LIST
{
uint8 primitiveFlags <format = hex>;
uint16 indexCount;
};
struct ACTION_INFO
{
// 0x00
uint32 nameOffset <format = hex>;
uint32 dataOffset <format = hex>;
uint32 dataSize <format = hex>;
uint32 unknownOffset <format = hex>;
// 0x10
uint32 unknown0x10 <format = hex>;
uint32 unknown0x14 <format = hex>;
};
struct FIGHTER_DATA
{
// 0x00
uint32 unknownOffset0x00 <format = hex>; // 0x184
uint32 unknownOffset0x04 <format = hex>;
uint32 unknownOffset0x08 <format = hex>; // 0x18 - {uint32; offset; uint32; offset; uint32[2];}
uint32 unknownOffset0x0C <format = hex>; // 0x18 - {offset; uint32[2]; offset; uint32[2];}[] --
// 0x10
uint32 unknownOffset0x10 <format = hex>; // 0x??
uint32 unknownOffset0x14 <format = hex>; // 0x18 - {offset; uint32[2]; offset; uint32[2];}[] -- win animation info?
uint32 unknownOffset0x18 <format = hex>; // 0x1C?x
uint32 unknownOffset0x1C <format = hex>; // 0x?? - {offset[];}
// 0x20
uint32 unknownOffset0x20 <format = hex>; // 0x04 - {offset;} - JOBJ_DATA
uint32 unknownOffset0x24 <format = hex>; // 0x18?
uint32 unknownOffset0x28 <format = hex>;
uint32 unknownOffset0x2C <format = hex>; // 0x14 - {uint32; offset; uint32; offset; uint32;}
// 0x30
uint32 unknownOffset0x30 <format = hex>; // 0x08 - {uint32; offset;}
uint32 unknownOffset0x34 <format = hex>; // 0x08?
uint32 unknownOffset0x38 <format = hex>; // 0x28
uint32 unknownOffset0x3C <format = hex>; // 0x18
// 0x40
uint32 unknownOffset0x40 <format = hex>; // 0x30
uint32 unknownOffset0x44 <format = hex>; // 0x1C
uint32 unknownOffset0x48 <format = hex>; // 0x0C+ - {offset; offset; offset;}
uint32 unknownOffset0x4C <format = hex>; // 0x38 - {offset; uint32[6]; offset; offset; uint32[5];}
// 0x50
uint32 unknownOffset0x50 <format = hex>; // 0x08 - {uint32; float;}
uint32 unknownOffset0x54 <format = hex>; // 0x14
uint32 unknownOffset0x58 <format = hex>; // 0x34
uint32 unknownOffset0x5C <format = hex>; // 0x40 - JOBJ_DATA
// dump jobj
if (unknownOffset0x20 != 0)
{
if (ReadUInt(unknownOffset0x20 + 0x20) != 0)
{
struct
{
DumpJObj(ReadUInt(unknownOffset0x20 + 0x20));
} jobjs;
}
}
if (unknownOffset0x5C != 0)
{
struct
{
DumpJObj(unknownOffset0x5C);
} jobjs;
}
};
struct FIGATREE_DATA
{
// 0x00
uint32 unknown0x00;
uint32 unknown0x04;
float unknown0x08;
uint32 unknownOffset0x0C <format = hex>;
// 0x10
uint32 unknownOffset0x10 <format = hex>;
};
void DumpJObj(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
SetBackColor(cLtGreen);
struct JOBJ_DATA jobj;
// need to store local copies of variables before recursing into the function again
// otherwise on the next iteration the 'jobj' variable changes, and contains the wrong jobj info
//local uint32 dobjOfs = jobj.dobjOffset;
local uint32 childOfs = jobj.childOffset;
local uint32 nextOfs = jobj.nextOffset;
// iterate into children nodes first
if (childOfs != 0)
DumpJObj(childOfs);
// then iterate sibling nodes
if (nextOfs != 0)
DumpJObj(nextOfs);
FSeek(filePos);
}
void DumpTransform(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
float3x4 transform;
FSeek(filePos);
}
void DumpDObj(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct DOBJ_DATA dobj;
// need to store local copies of variables before recursing into the function again
// otherwise on the next iteration the 'jobj' variable changes, and contains the wrong jobj info
//local uint32 mobjOfs = dobj.mobjOffset;
//local uint32 pobjOfs = dobj.pobjOffset;
local uint32 nextOfs = dobj.nextOffset;
// then iterate sibling nodes
if (nextOfs != 0)
DumpDObj(nextOfs);
FSeek(filePos);
}
void DumpMObj(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct MOBJ_DATA mobj;
FSeek(filePos);
}
void DumpPObj(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct POBJ_DATA pobj;
local uint32 nextOfs = pobj.nextOffset;
// then iterate sibling nodes
if (nextOfs != 0)
DumpPObj(nextOfs);
FSeek(filePos);
}
void DumpTObj(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct TOBJ_DATA tobj;
FSeek(filePos);
}
void DumpImageHeader(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct IMAGE_HEADER imageHeader;
FSeek(filePos);
}
void DumpPaletteHeader(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct PALETTE_HEADER paletteHeader;
FSeek(filePos);
}
void DumpMaterialColors(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct MATERIAL_COLORS materialColors;
FSeek(filePos);
}
void DumpVtxAttr(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct
{
do
{
struct ATTR_DATA vtxAttribute;
} while (vtxAttribute.vtxAttr != 0x000000FF);
} vtxAttributes;
FSeek(filePos);
}
void DumpJointWeights(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
local uint32 dataCount = GetArrayCount();
if (dataCount > 0)
{
struct
{
local uint32 dataCount = GetArrayCount();
uint32 weightOffsets[dataCount] <format = hex>;
struct
{
PushFP();
local uint32 dataNum = 0;
for (dataNum = 0; dataNum < dataCount; ++dataNum)
{
FSeek(weightOffsets[dataNum] + 0x20);
struct
{
do
{
struct WEIGHT_DATA jointWeight;
} while (jointWeight.jobjOffset != 0);
} jointWeights;
}
PopFP();
} weightInfo;
} weightInfo;
}
FSeek(filePos);
}
void DumpDisplayList(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct DISPLAY_LIST displayList;
FSeek(filePos);
}
void DumpFighter(uint32 ofs)
{
local int64 filePos = FTell();
FSeekOfs(ofs);
struct FIGHTER_DATA fighterData;
FSeek(filePos);
}
// DAT_FILE File Structure
struct DAT_FILE
{
// #pragma lockAt(0x00000000)
// DAT_HEADER - DAT file header information structure
SetBackColor(cLtGreen);
struct DAT_HEADER
{
// 0x00
uint32 fileSize0x00 <format = hex>;
uint32 dataBlockSize0x04 <format = hex>; // size of main data block
uint32 relocationTableCount0x08; // unknown data size / 4
uint32 rootCount0x0C; // unknown data size / 8
// if combined "data sizes" + 0x20 is less than file size, then offset to string table?
// overwritten data addresses (as such, assumed they are unimportant?)
// - 0x20 - start + 0x20?
// - 0x24 - start + dataBlockSize0x04 + 0x20 - offsets to offsets?
// - 0x28 - start + [0x24] + (relocationTableCount0x08 * 4)
// - 0x2C - start + [0x28] + (jobjCount0x0C * 8)
// - 0x30 - start + [0x2C] + (unknown0x10 * 8)
// - 0x3C - or'ed with 0x01
// - 0x40 - start
// 0x10
uint32 unknown0x10; // unknown data size / 8
uint32 unknown0x14; // '001B' in main Pl*.dat files
uint32 unknown0x18;
uint32 unknown0x1C;
} fileHeader;
if (0 < fileHeader.rootCount0x0C)
{
FSeek(0x20 + fileHeader.dataBlockSize0x04 + (fileHeader.relocationTableCount0x08 * 4));
SetBackColor(cLtRed);
struct
{
struct
{
uint32 rootOffset0x00 <format = hex>;
uint32 stringTableOffset0x04 <format = hex>; // offset to name string?
filePos = FTell();
FSeek(0x20 + rootOffset0x00);
union
{
SetBackColor(cLtGreen);
//struct
//{
// DumpJObj(rootOffset0x00);
//} jobjData;
struct
{
DumpFighter(rootOffset0x00);
} ftData;
SetBackColor(cLtBlue);
uint16 mappedData <format = hex>;
} mappedData;
FSeek(filePos);
} rootNodes[fileHeader.rootCount0x0C] <optimize = false>;
} rootNodes;
}
if (0 < fileHeader.unknown0x10)
{
FSeek(0x20 + fileHeader.dataBlockSize0x04 + (fileHeader.relocationTableCount0x08 * 4) + (fileHeader.rootCount0x0C * 8));
SetBackColor(cLtBlue);
struct
{
struct
{
uint32 rootOffset0x00 <format = hex>;
uint32 stringTableOffset0x04 <format = hex>;
filePos = FTell();
FSeek(0x20 + rootOffset0x00);
SetBackColor(cLtBlue);
uint16 mappedData <format = hex>;
FSeek(filePos);
} unknownData0x10[fileHeader.unknown0x10] <optimize = false>;
} unknownData0x10;
}
// string table data
if (0 < fileHeader.rootCount0x0C ||
0 < fileHeader.unknown0x10)
{
FSeek(0x20 + fileHeader.dataBlockSize0x04 + (fileHeader.relocationTableCount0x08 * 4) + (fileHeader.rootCount0x0C * 8) + (fileHeader.unknown0x10 * 8));
SetBackColor(cLtYellow);
struct
{
struct
{
string nodeName0x00;
} stringTable[fileHeader.rootCount0x0C + fileHeader.unknown0x10] <optimize = false>;
} stringTable;
}
if (0 != fileHeader.dataBlockSize0x04 &&
0 < fileHeader.relocationTableCount0x08)
{
FSeek(0x20 + fileHeader.dataBlockSize0x04);
SetBackColor(cLtBlue);
uint32 relocationTable[fileHeader.relocationTableCount0x08] <format = hex>;
local uint32 offsetNum = 0;
filePos = FTell();
FSeek(0x20 + fileHeader.dataBlockSize0x04);
SetBackColor(cLtRed);
struct
{
for (offsetNum = 0; offsetNum < fileHeader.relocationTableCount0x08; ++offsetNum)
{
FSeek(0x20 + relocationTable[offsetNum]);
uint32 mappedOffsets <format = hex>;
}
FSeek(filePos);
} relocatedOffsets;
FSeek(0x20 + fileHeader.dataBlockSize0x04);
SetBackColor(cLtBlue);
struct
{
for (offsetNum = 0; offsetNum < fileHeader.relocationTableCount0x08; ++offsetNum)
{
//FSeek(0x20 + ReadUInt(0x20 + relocationTable[offsetNum]));
FSeek(0x20 + relocatedOffsets.mappedOffsets[offsetNum]);
uint16 mappedData <format = hex>;
}
FSeek(filePos);
} relocatedData;
}
};
struct DAT_FILE fileInfo;