O

    From FIFA Manager Modding Wiki

    O is a file extension in EA Sports games which is used for model and animation files. The file itself has an ELF structure. EA used their own code for ELF reading.

    The file may contain model (geometry) data, skeleton information, animations, rendering information, effects (shaders) and embedded textures.

    Games[edit | edit source]

    O files were used mostly in games developed by EA Vancouver, between 1999 and 2009.

    Elf File Structure[edit | edit source]

    The overall file structure is following (the order of sections might be different, but for most files it is same):

    1. Elf Header (52 bytes)
    2. .data section data (Data section)
    3. .shstrtab section data (Section names table)
    4. .strtab section data (Symbol names table)
    5. .symtab section data (Symbol table)
    6. .rel.data section data (Relocation table)
    7. Section descriptions (section header table)

    Each block is aligned by 16 bytes.

    Header[edit | edit source]

    The file starts with ELF header:

    Data type Name Value
    UINT8[16] e_ident 7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00
    UINT16 e_type ET_REL (1)
    UINT16 e_machine EM_MIPS (8)
    UINT32 e_version EV_CURRENT (1)
    UINT32 e_entry 0
    UINT32 e_phoff 0
    UINT32 e_shoff sections offset - different for each file
    UINT32 e_flags 546455552
    UINT16 e_ehsize 52 (size of this header)
    UINT16 e_phentsize 0
    UINT16 e_phnum 0
    UINT16 e_shentsize 40 (size of section header entry)
    UINT16 e_shnum 6 (number of sections)
    UINT16 e_shstrndx index of .shstrtab section (section with section names)

    Sections[edit | edit source]

    There are 6 sections in the Elf File. Information about each section is stored in section table header.

    Null section[edit | edit source]

    Attribute Value
    s_name SHN_UNDEF
    s_type SHT_NULL (0)
    s_flags SF32_None (0)
    s_addr 0
    s_offset 0
    s_size 0
    s_link 0
    s_info 0
    s_addralign 0
    s_entsize 0

    Inactive section.

    Data section[edit | edit source]

    Attribute Value
    s_name .data
    s_type SHT_PROGBITS (1)
    s_flags SF32_Alloc_Exec (3)
    s_addr 0
    s_offset 64
    s_size different for each file
    s_link 0
    s_info 0
    s_addralign 16
    s_entsize 0

    Objects data is stored in this section.

    Section names table[edit | edit source]

    Attribute Value
    s_name .shstrtab
    s_type SHT_STRTAB (3)
    s_flags SF32_None (0)
    s_addr 0
    s_offset different for each file
    s_size 48
    s_link 0
    s_info 0
    s_addralign 1
    s_entsize 0

    6 null-terminated strings, names for each section. The local offset of the name (relative to table start) is stored in each section header (s_name value). The table consists of following strings (the order may differ):

    (empty)
    .data
    .shstrtab
    .strtab
    .symtab
    .rel.data
    

    Symbol names table[edit | edit source]

    Attribute Value
    s_name .strtab
    s_type SHT_STRTAB (3)
    s_flags SF32_None (0)
    s_addr 0
    s_offset different for each file
    s_size different for each file
    s_link 0
    s_info 0
    s_addralign 1
    s_entsize 0

    A table of null-terminated strings for symbol names.

    Symbol table[edit | edit source]

    Attribute Value
    s_name .symtab
    s_type SHT_SYMTAB (2)
    s_flags SF32_None (0)
    s_addr 0
    s_offset different for each file
    s_size different for each file
    s_link .strtab section index (section index with symbol names)
    s_info unknown flag (2 for regular files, 6 for eaglrm)
    s_addralign 4
    s_entsize 16

    Table of symbols. Each symbol is represented with 16-byte structure:

    Data type Name Value
    UINT32 st_name Local offset to name in string table
    UINT32 st_value Symbol value (data offset or 0 if there's no data)
    UINT32 st_size Value (data) size (4 for pointer)
    UINT4 st_info_type
    STT_NOTYPE 0 Symbol is not specified
    STT_OBJECT 1 Symbol for object (data, variable or array)
    STT_FUNC 2 Symbol for function
    STT_SECTION 3 Symbol for section. Present only in eaglrm file
    UINT4 st_info_bind
    STB_LOCAL 0 Local symbol
    STB_GLOBAL 1 Global symbol
    STB_WEAK 2 Weak symbol
    UINT8 st_other Value (data) type
    UINT16 st_shndx Index of section where the value (data) is located (if not a global symbol)

    Symbol names which start with __ prefix and also contain ::: substring, are translated to ObjectType-VariableName pair:

    __ObjectType:::VariableName
    

    Relocation table[edit | edit source]

    Attribute Value
    s_name .rel.data
    s_type SHT_REL (9)
    s_flags SF32_None (0)
    s_addr 0
    s_offset different for each file
    s_size different for each file
    s_link .symtab section index (section with symbols)
    s_info .data section index (section with data)
    s_addralign 4
    s_entsize 8

    Table with relocation information. Each relocation is represented with 8-byte structure:

    Data type Name Value
    UINT32 r_offset offset in s_info section
    UINT8 r_info_type relocation type:
    R_MIPS_32 2 *(UINT32 *)dst = base + offset
    R_MIPS_26 4 jmp instruction patch
    R_MIPS_HI16 5 *(UINT16 *)dst += base >>= 16
    R_MIPS_LO16 6 *(UINT16 *)dst += base

    In FIFA Manager files, only type "2" is used.

    The "base" argument depends on symbol type.

    UINT24 r_info_sym symbol index in symbols table

    Objects[edit | edit source]

    Objects can be obtained by symbols in the ELF symbol table or by pointers in other objects.

    Objects structure may differ on different platforms (PC, PS2, XBOX). This part of article shows file structure for PC files.

    Model[edit | edit source]

    Object name Size Visible
    Model 0xE0 Yes

    Model is a set of layers which determine which geometry data must be rendered. An .o file may contain several model instances.

    OFFSET    Variables (points to an array of Variable)
    UINT32    Number of variables
    UINT32    Total instances (variations) count (usually 1; 25 for player model; 4 for corner flags)
    MATRIX4X4 Transformation matrix (always an identity matrix)
    VECTOR4   Rough bounding corner 1 (2x next one,  W component is 1) - probably unused
    VECTOR4   Rough bounding corner 2 (W component is 0) - probably unused
    VECTOR4   Bounding min (W component is 1)
    VECTOR4   Bounding max (W component is 1)
    VECTOR3   Cull sphere center
    FLOAT     Cull sphere radius
    UINT32    Groups count
    OFFSET    Groups names (points to an array of pointers to null-terminated strings)
    UINT32    unknown1 (always 0)
    OFFSET    unknown2 (always 0)
    OFFSET    unknown3 (always 0)
    OFFSET    Next model (always 0)
    OFFSET    Model name (points to null-terminated string)
    OFFSET    Interleaved vertices information (points to InterleavedVertices)
    OFFSET    Textures (points to ModelTextures)
    UINT32    Instance index (variation ID)
    OFFSET    Group states (points to GroupStates)
    BOOL32    Is model renderable (always 1)
    OFFSET    Groups (points to Groups)
    OFFSET    Model "patch" (points to EAGL::Variation object, used to change values/offsets in mode struct? Always 0)
    OFFSET    Morph pointer (runtime, always 0)
    UINT32    Animation version (for files with skeleton; might be 0, 49370 (0xC0DA), 60007 (0xEA67) or other value)
    UINT32    Current frame number (always 0)
    

    BBOX[edit | edit source]

    Simply a bounding box.

    Object name Size Visible
    BBOX 0x18 Yes
    VECTOR3 Min
    VECTOR3 Max
    

    RenderMethod[edit | edit source]

    Object name Size Visible
    RenderMethod 0x34 Yes

    Stores an information about data rendering.

    OFFSET    Code block (points to where the code starts - usually geoprimdatabuffer+4)
    OFFSET    Used code block - array of pointers to code blocks for each selected technique (runtime, always 0)
    OFFSET    EAGL MicroCode (points to EAGLMicroCode object)
    OFFSET    Effect (runtime, always 0)
    OFFSET    Parent render method (points to RenderMethod objects)
    OFFSET    Parameter names (always 0)
    UINT32    unknown2 (always 0)
    INT32     unknown3 (always -1)
    OFFSET    unknown4 (always 0)
    OFFSET    Geometry data buffer (points to geoprimdatabuffer object)
    INT32     Index of command with computation index as global argument (-1 if command is not present)
    OFFSET    Effect name (points to null-terminated string)
    OFFSET    EAGL Model object (runtime, always 0)
    

    EAGLMicroCode[edit | edit source]

    Object name Size Visible
    EAGLMicroCode Dynamic Yes

    Represents an effect (shader).

    UINT32    number of techniques
    UINT32    section type (always 0 - Effect)
    UINT32    number of vertex shader declarations
    #FOR number of vertex shader declarations
    UINT32    vertex shader declaration
    #END FOR
    UINT32    number of techniques implementations
    #FOR number of techniques implementations
    UINT32    section type (always 1 - Technique)
    UINT32    tecnique type (0-4)
    UINT32    number of Sampler assignments
    UINT32    number of GeoPrimState assignments
    #FOR total number of state assignments
    UINT32    state assignment type
    CHAR[]    state assignment data (see Stage Assignments)
    #END FOR
    UINT32    number of passes
    #FOR number of passes
    UINT32    section type (always 2 - Pass)
    UINT32    number of Sampler assignments
    UINT32    number of GeoPrimState parameter assignments
    UINT32    unknown (always 548, 548 is a size of TextureStageState struct)
    #FOR total number of state assignments + 3
    UINT32    state assignment type
    CHAR[]    state assignment data (see Stage Assignments)
    #END FOR
    #END FOR
    #END FOR
    

    Each technique may contain a different number of implementation. For each technique type the game will select the first technique implementation which is compatible with user hardware. For example, if we have 3 techniques (number of techniques = 3), the layout of effect might be the following (number of techniques = 7):

    Technique #1 - tecnique type 0 implementation 1
    Technique #2 - tecnique type 0 implementation 2
    Technique #3 - tecnique type 0 implementation 3
    Technique #4 - tecnique type 1 implementation 1
    Technique #5 - tecnique type 1 implementation 2
    Technique #6 - tecnique type 2 implementation 1
    Technique #7 - tecnique type 2 implementation 2
    

    Usually the first implementation of technique is the most advanced one, and following implementations are simplified.

    The meaning of technique types is different in different games.

    Effect pass always contain at least 3 state assignments - VertexShaderState (or Vertex Shader Reference), PixelShaderState and TextureStageState.

    Vertex Shader Declaration[edit | edit source]

    UINT8 index
    UINT8 unknown (0)
    UINT8 data type (see Data types)
    UINT8 type (0x20 - vertex stream, 0x40 - vertex element, 0xFF - end of declaration)
    

    Data types[edit | edit source]

    0 - UBYTE4 COLOR1
    1 - FLOAT2 TEXCOORDX (X - occurance index)
    2 - FLOAT3 (first occurance - POSITION, second - NORMAL)
    3 - FLOAT4 POSITION
    4 - D3DCOLOR COLOR0
    

    Stage Assignments[edit | edit source]

    Type Name Size Data
    3 Sampler 8
    UINT32 texture stage index
    UINT32 sampler index (SET_SAMPLER command)
    4 TextureStageState 548
    UINT32[8] D3DTSS_COLOROP value for each texture stage
    UINT32[8] D3DTSS_COLORARG0 value for each texture stage
    UINT32[8] D3DTSS_COLORARG1 value for each texture stage
    UINT32[8] D3DTSS_COLORARG2 value for each texture stage
    UINT32[8] D3DTSS_RESULTARG value for each texture stage
    UINT32[8] D3DTSS_BUMPENVMAT00 value for each texture stage
    UINT32[8] D3DTSS_BUMPENVMAT01 value for each texture stage
    UINT32[8] D3DTSS_BUMPENVMAT10 value for each texture stage
    UINT32[8] D3DTSS_BUMPENVMAT11 value for each texture stage
    UINT32[8] D3DTSS_TEXCOORDINDEX value for each texture stage
    UINT32[8] D3DTSS_BUMPENVLSCALE value for each texture stage
    UINT32[8] D3DTSS_BUMPENVLOFFSET value for each texture stage
    UINT32[8] D3DTSS_TEXTURETRANSFORMFLAGS value for each texture stage
    UINT32 max texture stage (0-7) - increase this by 1 to get number of textures stages
    5 GeoPrimStateAssignment 8
    UINT32 offset in bytes in GeoPrimState struct
    UINT32 value to store at offset
    6 VertexShaderState Dynamic Vertex shader code.
    UINT32 size
    UINT32[size] compiled shader code
    7 PixelShaderState Dynamic Pixel shader code.
    UINT32 size (can be 0)
    UINT32[size] compiled shader code
    8 VertexShaderStateReference Dynamic Uses previously created vertex shader. "size" is always 1. "data" is unknown value (example: 66, 86, 322, 326, 338, 342, 598)
    UINT32 size
    UINT32[size] data

    Groups[edit | edit source]

    Object name Size Visible
    Unknown Dynamic No

    Stores a list of model groups.

    Version 3 and later

    OFFSET    Unknown (0)
    #FOR number of groups in model
    UINT32    number of meshes
    #FOR number of meshes
    OFFSET    mesh (points to Mesh)
    #END FOR
    #END FOR
    

    Version 2 and earlier

    In version 2 and earlier, model groups is a list of descriptors:

    UINT32    id (0xA0000000 - start descriptor, 0xA0000001 - group descriptor, 0xA000FFFF - mesh descriptor
    #IF id is 0xA000FFFF
    OFFSET    mesh (points to Mesh)
    #ELSE
    UINT32    unknown1 (0)
    #IF id is 0xA0000000
    UINT32    group and mesh descriptors size (number of groups * 2 + total number of meshes  * 2)
    #ELSE IF id is 0xA0000001
    UINT32    mesh descriptors size (number of meshes  * 2)
    #END IF
    

    The list ends with a null descriptor (id = 0).

    GroupStates[edit | edit source]

    Object name Size Visible
    Unknown Dynamic No

    Stores a list of model layers states.

    INT32     unknown1
    #FOR number of model layers
    UINT16    default state (always 1 - enabled)
    UINT16    unknown2
    #END FOR
    

    Mesh[edit | edit source]

    Object name Size Visible
    Unknown Dynamic No

    Contains a pointer to RenderMethod and a list of global parameters for each command in the code block.

    OFFSET    render method (points to RenderMethod)
    #FOR (number of commands in code block - 1)
    UINT32    global command parameter - objects count
    UINT32    global command parameter - object (might be an integer or offset to object/objects)
    #END FOR
    

    First parameter in the list in most cases is a pointer to GeometryInfo.

    GeometryInfo[edit | edit source]

    Object name Size Visible
    Unknown 0x10 No
    UINT32    Indices count
    UINT32    Vertices count
    UINT32    Primitives count
    BOOL32    unknown1
    

    geoprimdatabuffer[edit | edit source]

    Object name Size Visible
    Unknown Dynamic Yes

    Stores a code (list of instructions) for rendering. Eeach instruction, except the first and the last one, may additionally use a global parameter, which is stored in RenderDescriptor.

    #FOR number of techniques in RenderMethod's effect
    UINT32    unknown1 (usually 0)
    #WHILE Instruction id != 0 AND Instruction size != 0
    UINT16    Instrution size (real size in bytes = Instruction size * 4)
    UINT16    Instruction id
    #IF Instruction size > 1
    UINT32[Instruction size - 1] Instruction parameters
    #END WHILE
    #END FOR
    

    Commands[edit | edit source]

    ID Name Parameters Global parameter Description
    0 - - - Code-end marker
    1 SET_GEOMETRY_INFO (NOP) - GeometryInfo (local) No-operation. Takes GeometryInfo as parameter
    2 SET_VERTEX_SHADER_CONSTANT INT32 register, INT32 numContants constantData (global) Sends constants (each constant - 4 bytes) to vertex shader
    3 NOP
    4 SET_STREAM_SOURCE INT32 streamNumber, INT32 vertexSize, INT32 vertexFVF,

    INT32 unknown (-1), INT32 unknown (-1), OFFSET vertexBuffer,

    INT32 vertexCount, INT32 variationsCount (can be -1), INT32 vertexBufferIndex,

    INT32 unknown (-1), INT32 unknown (-1)

    vertexBuffer (local) Setup vertex buffer. FVF flags:
    0x1
    0x2 POSITION
    0x4 COLOR1
    0x8
    0x10 NORMAL
    0x20 BLENDINDICES
    0x40 COLOR0
    0x80
    0x100 TEXCOORD0
    0x200 TEXCOORD1
    6 NOP
    7 SET_INDEX_BUFFER INT32 unknown (2), INT32 unknown (-1), INT32 unknown (-1),

    OFFSET indexBuffer, INT32 indexCount

    indexBuffer (local)
    9 SET_SAMPLER
    12 SET_VERTEX_SHADER_CONSTANT_MATRIX
    16 DRAW_PRIM
    17 DRAW_INDEXED_PRIM_NO_Z_WRITE INT32 unknown (4) -
    18 DRAW_INDEXED_PRIM
    28 SET_VERTEX_BONE_WEIGHTS INT32 num3Bones, INT32 num2Bones, INT32 num1Bone vertexSkinDataBuffer Setup vertex bone weights
    29
    30 SET_VERTEX_SHADER_CONSTANT
    31 SET_VERTEX_SHADER_CONSTANT
    32 SET_SAMPLER INT32 samplerIndex, INT32 textureObjectSize (48) Texture array Sets sampler at index
    33 SET_GEO_PRIM_STATE - GeoPrimState
    35 SET_VERTEX_SHADER_TRANSPOSED_MATRIX INT32 register Matrix4x4 Transposes passed matrix and sends it to vertex shader
    40 SET_ANIMATION_BUFFER INT32 unknown, INT32 unknown EAGLAnimationBuffer Setup animation buffer
    46 SET_VERTEX_SHADER_CONSTANT INT32 register, INT32 numContants constantData (local) Sends constants (each constant - 4 bytes) to vertex shader
    57 DRAW_INDEXED_PRIM
    65 DRAW_INDEXED_PRIM_AND_END
    69 SETUP_RENDER BOOL32 SoftwareVertexProcessing, INT32 unknown (-1) - Enable/disable software vertex processing; setup fog
    72 SET_PIXEL_SHADER_CONSTANT INT32 register, INT32 numContants constantData (global) Sends constants (each constant - 4 bytes) to pixel shader
    73 SET_PIXEL_SHADER_CONTANT
    74
    75 SET_STREAM_SOURCE_SKINNED INT32 streamNumber, INT32 vertexSize, INT32 vertexFVF,

    INT32 unknown (-1), INT32 unknown (-1), OFFSET vertexBuffer,

    INT32 vertexCount, INT32 variationsCount (can be -1), INT32 vertexBufferIndex,

    INT32 unknown (-1), INT32 unknown (-1)

    vertexBuffer (local) Setup vertex buffer for skinned mesh

    Vertex structure[edit | edit source]

    Vertex structure depends on vertex shader declarations in EAGLMicroCode.

    For skinned models, while BLENDWEIGHTS and BLENDINDICES attributes are present in declaration, they aren't present in Vertex buffer. Instead, there's always COLOR1 attribute, where an index (32-bit integer) to Vertex skin data buffer is stored.

    A Vertex skin data buffer is an array of entries:

    #union
    UINT8 bone index 1
    FLOAT weight value 1 (clear lower 8 bits when unpacking)
    #end
    #union
    UINT8 bone index 2
    FLOAT weight value 2 (clear lower 8 bits when unpacking)
    #end
    #union
    UINT8 bone index 3
    FLOAT weight value 3 (clear lower 8 bits when unpacking)
    #end
    UINT32 padding
    

    The pointer to these entries is passed through SET_VERTEX_BONE_WEIGHTS command. It's not possible to have more than 128 such entries for one mesh. To bypass this limit, the mesh must be splitted.

    GeoPrimState[edit | edit source]

    Object name Size Visible
    EAGL::GeoPrimState 0x44 No

    Rendering states for geometry.

    UINT32 Primitive type
    UINT32 Shading
    BOOL32 Culling enabled
    UINT32 Cull direction
    UINT32 Depth test method
    UINT32 Alpha blend mode
    BOOL32 Alpha test enable
    UINT32 Alpha compare value
    UINT32 Alpha test method
    BOOL32 Texture enabled
    UINT32 Transparency method
    UINT32 Fill mode
    UINT32 Blend operation
    UINT32 Source blend
    UINT32 Destination blend
    UINT32 Number of patch segments
    INT32  Z-Writing state (-1 - undefined?)
    

    Variable[edit | edit source]

    Object name Size Visible
    Unknown 0x10 No

    Container with model data which can be edited in runtime, from the program. Primarly used for lights attributes and geometry states.

    OFFSET    Name  (points to null-terminated string)
    UINT16    Entry size
    UINT16    unknown1 (same as entries count?)
    UINT32    Entries count (always 1)
    OFFSET    Entries (points to an array of entries)
    

    ModelTextures[edit | edit source]

    Object name Size Visible
    Unknown Dynamic No

    Model textures descriptors.

    #REPEAT
    OFFSET    Name  (points to null-terminated string)
    #IF Name != 0
    UINT32    number of TAR (texture) objects
    #FOR (number of TAR objects)
    OFFSET    TAR (texture) object (single or array)
    #END FOR
    #IF version is 4
    UINT16    unknown2
    UINT16    unknown3
    #END IF
    #END IF
    #UNTIL Name = 0
    

    TAR[edit | edit source]

    Object name Size Visible
    TAR 0x30 No

    Texture (sampler) descriptor.

    UINT32    unknown1 (usually 0)
    CHAR[4]   texture tag (4-character name)
    UINT32    unknown2 (usually 0)
    FLOAT     unknown3 (usually 0.0)
    UINT32    unknown4 (usually 0)
    FLOAT     unknown5 (usually 0.0)
    UINT32    unknown6 (usually 0)
    UINT32    U wrap mode
    UINT32    V wrap mode
    UINT32    W wrap mode
    UINT32    unknown7 (usually 0)
    UINT32    unknown8 (usually 0)
    

    ComputationIndex[edit | edit source]

    Object name Size Visible
    ComputationIndex 0x4 No
    UINT16    Active technique index (always 0)
    UINT16    unknown2 (1 or 2)
    

    EAGL_TOOLLIB_VERSION-X[edit | edit source]

    Object name Size Visible
    EAGL_TOOLLIB_VERSION-* 0x0 Yes

    Dummy object. EAGL library version (most recent is 4). Used since version 3.

    LASTCHANGELIST[edit | edit source]

    Object name Size Visible
    LASTCHANGELIST 0x0 Yes

    Dummy object. Used before version 3.

    Skeleton[edit | edit source]

    Object name Size Visible
    Skeleton Dynamic Yes

    Skeleton information.

    UINT16    Signature (usually 0xC0DA)
    UINT16    unknown1 (usually 510)
    UINT16    Signature (usually 0xC0DA)
    UINT16    unknown2 (usually 0)
    UINT32    Number of bones
    OFFSET    unknown3 (always 0)
    #FOR Number of bones
    VECTOR3   Bone scale (usually 1.0 1.0 1.0)
    INT32     ParentBoneID (-1 - no parent)
    VECTOR4   Bone rotation (quaternion)
    VECTOR4   Bone translation (W component is 0.0)
    MATRIX4X4 Inversed bone matrix
    #END FOR
    

    Bone[edit | edit source]

    Object name Size Visible
    Bone 0x10 Yes

    Bone information.

    UINT32    Index
    UINT32    unknown1 (always 0)
    UINT32    unknown2 (always 0)
    UINT32    unknown3 (always 0)
    

    Morph[edit | edit source]

    Object name Size Visible
    Morph Dynamic Yes

    Vertices morphing information.

    UINT32    Blend weights count
    OFFSET    Blend weights names (points to array of pointers to null-terminated strings, array count is BW count)
    OFFSET    Blend weights (points to array of zero floats, array count is BW count)
    UINT32    unknown1 (0)
    UINT32    Number of blend targets (each "target" is connected to InterleavedVertices instance)
    #FOR Number of blend targets
    OFFSET    Interleaved vertices name (null-terminated string)
    UINT32    Blendshapes count (same as Blend weights count)
    #FOR Blendshapes count
    UINT32    Blend weight index
    UINT32    Number of vertex attributes for blending
    #FOR Number of vertex attributes for blending
    UINT28    Blend data size (number of vertices * entry size)
    UINT2     Blend data component type (1 - BYTE, 2 - USHORT, 4 - FLOAT, 0 - default (FLOAT))
    UINT2     Number of components in one blend data entry (0 - 4, 0 - default (4 components))
    UINT32    Number of vertices
    UINT32    Offset in Interleaved vertex buffer
    UINT32    Interleaved vertex buffer index
    CHAR[Blend data size] Blend data
    #END FOR
    #END FOR
    #END FOR
    
    The morphing process can be desribed with this pseudocode:
    for (auto &blendTarget : blendTargets) {
        for (auto &blendShape : blendTarget.blendShapes) {
            float weight = morph->blendWeights[blendShape.weightIndex];
            for (auto &bva : blendShape.blendVertexAttributes) {
                for (unsigned int v = 0; v < bva.numVertices; v++) {
                    auto &iv = FindInterleavedVerticesBuffer(blendTarget.interleavedVerticesName, bva.interleavedVBIndex);
                    unsigned char *dst = iv->vb + iv->vbSize * model->instanceId + iv->vertexSize * v + bva.offsetInVertex;
                    unsigned char *src = bva.blendData + (bva.blendDataSize / bva.numVertices) * v;
                    for (unsigned int c = 0; c < bva.numComponents; c++) {
                        if (bva.componentType == 1)
                            *(unsigned char *)dst += (unsigned char)((double)(*(unsigned char *)src) * weight);
                        else if (bva.componentType == 2)
                            *(unsigned short *)dst += (unsigned short)((double)(*(unsigned short *)src) * weight);
                        else if (bva.componentType == 0 || bva.componentType == 4)
                            *(float *)dst += *(float *)src * weight;
                        dst += (bva.componentType == 0) ? 4 : bva.componentType;
                        src += (bva.componentType == 0) ? 4 : bva.componentType;
                    }
                }
            }
        }
    }
    

    InterleavedVertices[edit | edit source]

    Object name Size Visible
    Unknown Dynamic No

    Represent a set of vertex buffers.

    UINT32    unknown1 (0)
    #REPEAT
    OFFSET    name (null-terminated string, usually "InterleavedVertices")
    #IF name is not null
    UINT32    number of vertex datas
    #FOR number of vertex datas
    UINT32    vertex data index (starting from 0, increated by 1)
    UINT16    vertex count
    UINT1     multiple vertex buffers used (morph vertex data exists for each model instance)
    UINT15    morph vertex data size (same as vertex size)
    UINT32    vertex buffer size
    OFFSET    vertex buffer offset
    #END FOR
    #END IF
    #UNTIIL   name is not null
    

    When this information is present for vertex buffer, the vertex buffer acts as a morph vertex data (this data is modified in-game during morphing), and original vertex bufer is placed right before the vertex buffer itself (normally, same vertex data is duplicated twice):

    vertex buffer copy offset | CHAR[vertex count * vertex size]            vertex buffer copy
    #IF morph vertex data exists for each model instance
    vertex buffer offset      | CHAR[vertex count * morph vertex data size * number of model instances] vertex buffer
    #ELSE
    vertex buffer offset      | CHAR[vertex count * morph vertex data size] vertex buffer
    #END IF
    

    During the morphing, vertex buffer is modified. Vertex buffer copy can be used to access unmodified vertex data. The offset to vertex buffer copy is calculated as following:

    vertex buffer copy offset = vertex buffer offset - vertex buffer size
    

    AnimationBank[edit | edit source]

    Object name Size Visible
    AnimationBank 0x20 Yes

    Animations container.

    UINT32    unknown1
    UINT32    Animations count
    UINT32    unknown2
    UINT32    unknown3
    OFFSET    Animations
    OFFSET    Animation names
    UINT32    unknown4
    UINT32    unknown5
    

    Animation[edit | edit source]

    Object name Size Visible
    Animation Dynamic No

    Animation description.

    UINT16    Type
    UINT16    Animation version (usually 0xC0DA)
    CHAR[]    Data (depends on animation type)
    

    Animation types

    ID Name Description Data
    0 ANIM_RAWPOSE
    10 ANIM_DELTALERP
    OFFSET    Data offset
    UINT16    unknown1
    UINT16    unknown2
    UINT16    unknown3
    UINT16    unknown4
    
    11 ANIM_DELTAQUAT
    OFFSET    Data offset
    UINT16    unknown1
    UINT16    unknown2
    
    15 ANIM_COMPOUND Animation container, contains other animations
    OFFSET    unknown1
    UINT16    Number of child animations
    UINT16    unknown3
    #FOR Number of child animations
    OFFSET    Child animation
    #END FOR
    
    20 ANIM_DELTAF3
    22 ANIM_STATELESSQ
    23 ANIM_STATELESSF3
    25 ANIM_POSEANIM

    ORD and ORL[edit | edit source]

    In some games, .ORD and .ORL are used as an alternative to .O

    In order to get .O from .ORD and .ORL, these 2 files must be simply concatanated.

    ORD and ORP[edit | edit source]

    In some games, .ORD and .ORP are used as an alternative to .O

    In order to get .O from .ORD and .ORL, these 2 files must be concatanated: the data from .ORL file, from (offset 4) to (end of the file) must be placed at (value at offset 0) in ORD file.

    ORD file[edit | edit source]

    CHAR[] ORD data
    CHAR[] buffer for ORP data (ORP data must be placed there)
    

    ORP file[edit | edit source]

    UINT32 offset in ORD file where ORP data must be placed
    CHAR[] ORP data
    

    Tools[edit | edit source]

    OTools - open-source tool for .O files import/export, by Dmitri

    OEdit - .O files editor, by Arushan