-
Notifications
You must be signed in to change notification settings - Fork 43
.WO File Format
Liam Mitchell edited this page Jan 2, 2021
·
4 revisions
We think we can call this format World Objects. It is an archive of multiple compressed parts.
Containing dds texture files for all the various parts of the zones map. Including some ones that seem to be frame by frame animated for fire effects, waterfalls etc.
//--------------------------------------
//--- 010 Editor v5.0 Binary Template
//
// File: Quest Template for Alt1 WO files
// Author: Liam Mitchell
// Revision: 0
// Purpose: To learn about how WO files work in Twelve Sky.
//--------------------------------------
// Defines a file record
/*
typedef struct {
uint UncompressedSize;
uint CompressedSize;
// Compressed data
SetBackColor( cNone );
if( CompressedSize > 0 )
uchar Data[CompressedSize];
}ZIPFILERECORD <size=SizeZIPFILERECORD>;
int SizeZIPFILERECORD( ZIPFILERECORD &r )
{
return 8 + // base size of the struct
ReadUInt(startof(r)+4); // size of the extra field
}
LittleEndian();
uint Count1;
uint Unknown1;
uint Unknown2;
uint Unknown3;
local uint index;
//while( !FEof() )
//{
for (index=0;index<Unknown2;index++) {
SetBackColor( cLtGray );
ZIPFILERECORD record;
uint dataSize;
}
/*
uint poop1;
for (index=0;index<Unknown1;index++) {
SetBackColor( cLtGray );
ZIPFILERECORD record;
}
uint poop2;
uint additionalTextureCount;
uint poop4;
for (index=0;index<additionalTextureCount;index++) {
SetBackColor( cLtGray );
ZIPFILERECORD record;
uint poopn;
}
int Unknown4;
char mobjectName[14];
*/
/*
typedef struct {
uint uncompressedSize;
uint compressedSize;
byte data[compressedSize];
} CompressedData <size=SizeCompressedData>;
int SizeCompressedData( CompressedData &r )
{
return 8 + // base size of the struct
ReadUInt(startof(r)+4); // size of the compressed data
}
string RecordValueRead ( CompressedData &r ) {
return r.data;
}
typedef struct {
uint totalSize; // Textures contain extra data after them such as integers for the mode/transparency type for rending purposes.
CompressedData data <optimize=false>;
} CompressedTexture;
typedef struct _D3DCOLORVALUE {
float r;
float g;
float b;
float a;
} D3DCOLORVALUE;
typedef struct D3DMATERIAL9 {
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;
float Power;
} D3DMATERIAL9;
typedef struct {
float Frame;
float PostTimeForEffect;
D3DMATERIAL9 Material;
// Matrix Scale
// Matrix Rotation
// Matrix Translate
// Mesh Info?
} MOBJECTINFO;
typedef struct {
int textureSizeBytes;
CompressedData texture <optimize=false>;
// These areat end of compressed texture after textureSizeBytes.
// int metalic; // Not Sure, Metalic and Alpha?
// int albedo; // Not Sure Metalic and Emissive?
} Texture;
*/
typedef float VEC3F[3] <read=Vec3FRead, write=Vec3FWrite>;
string Vec3FRead( VEC3F v )
{
string s;
SPrintf( s, "(%f %f %f)", v[0], v[1], v[2] );
return s;
}
void Vec3FWrite( VEC3F &v, string s )
{
SScanf( s, "(%f %f %f)", v[0], v[1], v[2] );
}
struct CompressedData {
uint uncompressedSize;
uint compressedSize;
byte data[compressedSize];
};
struct Block2_B {
DWORD totalSize;
if (totalSize > 0) {
CompressedData textureData;
}
// Internally the texture is a DirectX texture.
// It also has two integers at the end of it.
};
struct ModelPart { // Compresed Texture?
DWORD totalSize;
// Compressed Mesh?
CompressedData meshData <optimize=false>; // WO Internal 1
// Textures?
Block2_B AlbedoTexture;
Block2_B BumpTexture;
DWORD animatedTextureCount;
if (animatedTextureCount) {
Block2_B AnimatedTextures[animatedTextureCount] <optimize=false>;
}
};
struct Model {
DWORD HasBlocks;
DWORD ModelPartCount;
ModelPart Parts[ModelPartCount] <optimize=false>; // 408 size * Block2Count
};
struct ModelPosition {
DWORD ModelIndex;
VEC3F Position;
VEC3F Rotation;
};
DWORD ModelCount;
Model Models[ModelCount] <optimize=false>;
// Big unknown here seems like it contains model names or comments?
struct ModelExtra {
char ModelName[100] <bgcolor=0x0000FF>;
};
//DWORD unknown;
//ModelExtra ModelsInfo[Block1Count];
byte UnknownHasModelNames[ModelCount * 100] <bgcolor=0x0000FF>;
DWORD ModelPositionCount;
ModelPosition ModelPositions[ModelPositionCount] <optimize=false>;
The mesh I'm still working out but I was able to visualize it successfully in a tool for reversing game 3d meshes.
//------------------------------------------------
//--- 010 Editor v8.0.1 Binary Template
//
// File: WOTemplate_Internal1
// Authors: Liam Mitchell
// Version:
// Purpose:
// Category:
// File Mask:
// ID Bytes:
// History:
//------------------------------------------------
// First Decompressed data is
// Matrix?
// byte headerBytes[120];
float HeaderInfos[30];
// SKINVERTEX_FOR_GXD mVertexBufferForBillboard[4] ?
// D3DXVECTOR3 mScaleValue ?
// Matrix ?
//
int FirstValue; // Count
int SecondValue; // Count
int ThirdValue; // Value?
int FaceCount; // Count
byte data[FirstValue << 6]; // Struct Pointer
// SKINSIZE_FOR_GXD ?
// Verts?
byte data2[32 * FirstValue * SecondValue]; // Struct Pointer
// If Second Value == 4, Third Value == 4, Fourth Value == 2
if (SecondValue == 4 && ThirdValue == 4 && FaceCount == 2) {
// Face index shorts fixed size.
short FaceIndexes[6]; // Inline Structure?
} else {
short FaceIndexes[3 * FaceCount]; // Tri 1,2,3
}
SKINVERTEX_FOR_GXD mVertexBufferForBillboard[4];
BOOL mCheckChangeNormalState;
D3DXVECTOR3 mScaleValue;
SKINSIZE_FOR_GXD mSize;
8*4*4+4+12
+16*4
D3DXMATRIX *mScaleKeyMatrix;
BOOL mCheckValidState;
SKINEFFECT_FOR_GXD mEffect;
int mVertexNum;
int mUVNum;
int mWeightNum;
int mTrisNum;
float *mVertex;
float *mNormal;
float *mUV;
float *mWeight;
WORD *mTris;
SKINVERTEX_FOR_GXD *mVertexBuffer;
SKINWEIGHT_FOR_GXD *mWeightBuffer;
WORD *mIndexBuffer;
float *mMotionVertex;
float *mMotionNormal;
TEXTURE_FOR_GXD mTexture[2];
int mTextureAnimationNum;
TEXTURE_FOR_GXD *mTextureAnimation;
DWORD m_dwDyeingColor;
TEXTURE_FOR_GXD mBumpTexture;
TEXTURE_FOR_GXD mSpeculerTexture;
BOOL mbIsUseBumpmap;
BOOL mbIsUseSpeculer;
BUMPEFFECT_FOR_GXD mBumpEffect;
bool m_bIsViewBumpLight;