Users browsing this thread: 1 Guest(s)
Xenoblade X unknown model format (example files inside)
#3
I don't really have the time to go reverse it entirely but if anyone is interested in doing so, I'll share my notes


Notes:
Code:
// Xenoblade Chronicles X .camdo
// File is in big endian
// Offsets are relative to the start of the struct pointed to in the CamdoHeader

struct CamdoHeader
{
char[4] magic; // MXMD
u32 unk_int_0x04; // 0x2738
u32 unkStruct1Off; // 0x44
u32 unkStruct2Off; // 0x597C
u32 unk_off_0x10; // 0x6A80
u32 bufferDescriptorOff; // 0x6DA4
u32 unk_off_0x18; // 0x78400
u32 unk_off_0x1C; // 0x83400
u32 unk_int_0x20; // 0x00
u32 unk_off_0x24; // 0x6660
}

struct UnkStruct1
{
f32[6] bbox;
u32 unk_off_0x18; // 0x9C
u32 unk_int_0x1C; // 0x01
u32 unk_off_0x20; // 0xE60
u32 unk_int_0x24; // 0x01
u32[10] unk_0x28; // 0x00
u32 unk_off_0x50; // 0x3090
u32 unk_int_0x54; // 0x35
u32 unk_off_0x58; // 0xED4
u32 unk_int_0x5C; // 0x6B
u32 unk_int_0x60; // 0x00
u32 unk_off_0x64; // 0xFA8
u32 unk_int_0x68; // 0x35
u32 unk_int_0x6C; // 0x40
u32 unk_off_0x70; // 0x1288
u32 unk_int_0x74; // 0x31
u32 unk_off_0x78; // 0x1598
u32 unk_int_0x7C; // 0x30
u32[3] unk_0x80; // 0x00
}

struct UnkStruct2
{
u32 unk_off_0x00; // 0x68
u32 unk_int_0x04; // 0x05
u32 unk_int_0x08; // 0x63
u32 unk_int_0x0C; // 0x0B
u32 unk_off_0x10; // 0x310
u32 unk_int_0x14; // 0x3C
u32 unk_off_0x18; // 0x400
u32 unk_int_0x1C; // 0x0E
u32 unk_int_0x20; // 0x00
u32 unk_off_0x24; // 0x5A0
u32 unk_int_0x28; // 0x0B
u32[5] unk_0x2C; // 0x00
// might be bigger, idk
}

struct BufferDescriptor
{
u32 vertBufDescriptorArrayOffset; // 0x30
u32 numVertBuffers; // 0x04
u32 faceBufDescriptorArrayOffset; // 0x90
u32 numFaceBuffers; // 0x6B
u16 unk_int_0x10; // 0x02
u16 unk_int_0x14; // 0x03
}

struct VertBufDescriptor
{
u32 vertBufOffset;
u32 numVertices;
u32 vertStride;
u32 unkIndicesOffset;
u32 numUnkIndices;
u32 unk_int_0x14; // 0x00
}

struct FaceBufDescriptor
{
u32 faceBufOffset;
u32 numFaces;
u32 unk_0x08; // 0x00
}

Preliminary MaxScript (Very WIP)
Code:
gc()

fn GetOpenFile = 
(
clearlistener()
local fname = getOpenFileName \ 
caption:"Open Model" \
types:"Model (*.camdo)|*.camdo" \
historyCategory:"XENBLADECHRX Object Presets"
if (fname == undefined) then
(
return undefined
)
else
(
--globalImportedFilePath = fname
local f = fopen fname "rb"
return f
)
)

-- Reading functions

fn ReadBEShort fstream = 
(
return bit.swapBytes (ReadShort fstream #unsigned) 1 2
)

fn ReadBELong fstream = 
(
return bit.swapBytes (bit.swapBytes (ReadLong fstream #unsigned) 1 4) 2 3
)

fn ReadBEFloat fstream = 
(
return bit.intAsFloat (bit.swapBytes (bit.swapBytes (ReadLong fstream #unsigned) 1 4) 2 3)
)

fn ReadBEVector2 fstream =
(
return [(ReadBEFloat fstream), ((ReadBEFloat fstream) * -1) + 1, 0]
)

fn ReadBEVector3 fstream =
(
return [(ReadBEFloat fstream), (ReadBEFloat fstream), (ReadBEFloat fstream)]
)

struct VertBufDescriptorStruct
(
/* u32 */ vertBufOffset,
/* u32 */ numVertices,
/* u32 */ vertStride,
/* u32 */ unkIndicesArrayOffset,
/* u32 */ numUnkIndices,
/* u32 */ unk0x14
)

struct FaceBufDescriptorStruct
(
/* u32 */ faceBufOffset,
/* u32 */ numFaces,
/* u32 */ unk0x08
)

file = GetOpenFile()

if (file != undefined) then
(
fseek file 0x14 #seek_cur
bufferDescriptorOffset = ReadBELong file

fseek file bufferDescriptorOffset #seek_set

vertBufDescriptorArrayOffset = ReadBELong file
numVertexBuffers = ReadBELong file
faceBufDescriptorArrayOffset = ReadBELong file
numFaceBuffers = ReadBELong file

fseek file (bufferDescriptorOffset + vertBufDescriptorArrayOffset) #seek_set
vertDescriptorArray = #()
for i = 1 to numVertexBuffers do
(
vtxDesc = VertBufDescriptorStruct()
vtxDesc.vertBufOffset = ReadBELong file
vtxDesc.numVertices = ReadBELong file
vtxDesc.vertStride = ReadBELong file
vtxDesc.unkIndicesArrayOffset = ReadBELong file
vtxDesc.numUnkIndices = ReadBELong file
vtxDesc.unk0x14 = ReadBELong file
vertDescriptorArray[i] = vtxDesc
)

fseek file (bufferDescriptorOffset + faceBufDescriptorArrayOffset) #seek_set
faceDescriptorArray = #()
for i = 1 to numFaceBuffers do
(
faceDesc = FaceBufDescriptorStruct()
faceDesc.faceBufOffset = ReadBELong file
faceDesc.numFaces = ReadBELong file
faceDesc.unk0x08 = ReadBELong file
faceDescriptorArray[i] = faceDesc
)

posArray = #()
uvArray = #()
for i = 1 to numVertexBuffers do
(
if (vertDescriptorArray[i].vertStride == 0x10) then continue -- Weight data
for j = 1 to vertDescriptorArray[i].numVertices do
(
fseek file (bufferDescriptorOffset + vertDescriptorArray[i].vertBufOffset + ((j - 1) * vertDescriptorArray[i].vertStride)) #seek_set
append posArray (ReadBEVector3 file)
fseek file 0x04 #seek_cur
append uvArray (ReadBEVector2 file)
)
)

faceArray = #()
for i = 1 to numFaceBuffers do
(
fseek file (bufferDescriptorOffset + faceDescriptorArray[i].faceBufOffset) #seek_set
for j = 1 to faceDescriptorArray[i].numFaces/3 do
(
append faceArray [(ReadBEShort file) + 1, (ReadBEShort file) + 1, (ReadBEShort file) + 1]
)
)

msh = mesh vertices:posArray faces:faceArray tverts:uvArray
buildTVFaces msh
for j = 1 to faceArray.count do setTVFace msh j faceArray[j]
)

gc()
Reply


Messages In This Thread
RE: Xenoblade X unknown model format (example files inside) - by TGE - 01-14-2016, 12:44 PM

Forum Jump: