(credit goes to Retriever II, original article is here)
The file format is broken down into 26 distinct data structures, or blocks. A 27th block is identified as an extension to block 26, and contains a set of 9 distinct sub-blocks, making it a format within a format.
In this document, the global structure of the file format is outlined, then each block is examined in detail.
BLOCK INDEX HIERARCHY
Based on references to indices of other blocks. Currently blocks 19
and 26 don't fit into the model. This model is also only a best guess, but
for what I've been able to test, it works.
Global Structure Arrangement
Block Name SIZE Description
Block 1 432 File Header
Block 2 168 Planes
Block 3 8 Polygons
Block 4 12 Vertices
Block 5 4 Polygon Point/Vertex Order
Block 6 12 Normals
Block 7 4 Normal Order
Block 8 4 Colors [RGBA8]
Block 9 4 Color Order
Block 10 4 Texture Point/Vertex Order
.. (Blocks 11-17 never observed)
Block 18 8 Texture Vertex
Block 19 24 Unknown
Block 20 8 Texture Map
Block 21 64 Texture Path Block (what purpose does this serve?)
Block 22 108 Polygon / Texture Map
Block 23 1 Plane Display
Block 24 4 Transformation
Block 25 88 Scene Graph
Block 26 64 Animation Sequence Identifer
Block 27 VAR Animation Sequence - data extension of block 26
Block 1 (Header) (432 bytes)
Mainly serves to list address offsets for block sets 2-27, and the number of
blocks contained within each set. Still, contains some values whose purpose
I don't yet know.
Rel Addr SIZE Description
0x0000 4 Data offset Block 27, size of Blocks 1 - 26
0x0004 64 Filename
0x0044 64 Texture Filename (Minus dash)
0x0084 64 Date String
0x00C4 4 Unknown
0x00C8 4 Unknown
0x00CC 4 Unknown
0x00D0 4f Point1-x 'Main Plane'?
0x00D4 4f Point1-y 'Main Plane'?
0x00D8 4f Point1-z 'Main Plane'?
0x00DC 4f Point4-x 'Main Plane'?
0x00E0 4f Point4-y 'Main Plane'?
0x00E4 4f Point4-z 'Main Plane'?
0x00E8 4 Number blocks in Block 2
0x00EC 4 Number blocks in Block 3
0x00F0 4 Number blocks in Block 4
0x00F4 4 Number blocks in Block 5
0x00F8 4 Number blocks in Block 6
0x00FC 4 Number blocks in Block 7
0x0100 4 Number blocks in Block 8
0x0104 4 Number blocks in Block 9
0x0108 4 Number blocks in Block 10
0x010C 4 Number blocks in Block 11 (*)
0x0110 4 Number blocks in Block 12 (*)
0x0114 4 Number blocks in Block 13 (*)
0x0118 4 Number blocks in Block 14 (*)
0x011C 4 Number blocks in Block 15 (*)
0x0120 4 Number blocks in Block 16 (*)
0x0124 4 Number blocks in Block 17 (*)
0x0128 4 Number blocks in Block 18
0x012C 4 Number blocks in Block 19
0x0130 4 Number blocks in Block 20
0x0134 4 Number blocks in Block 21
0x0138 4 Number blocks in Block 22
0x013C 4 Number blocks in Block 23
0x0140 4 Number blocks in Block 24
0x0144 4 Number blocks in Block 25
0x0148 4 Number blocks in Block 26
0x014C 4 Data offset Block 2 (always 1B0)
0x0150 4 Data offset Block 3
0x0154 4 Data offset Block 4
0x0158 4 Data offset Block 5
0x015C 4 Data offset Block 6
0x0160 4 Data offset Block 7
0x0164 4 Data offset Block 8
0x0168 4 Data offset Block 9
0x016C 4 Data offset Block 10
0x0170 4 Data offset Block 11
0x0174 4 Data offset Block 12
0x0178 4 Data offset Block 13
0x017C 4 Data offset Block 14
0x0180 4 Data offset Block 15
0x0184 4 Data offset Block 16
0x0188 4 Data offset Block 17
0x018C 4 Data offset Block 18
0x0190 4 Data offset Block 19
0x0194 4 Data offset Block 20
0x0198 4 Data offset Block 21
0x019C 4 Data offset Block 22
0x01A0 4 Data offset Block 23
0x01A4 4 Data offset Block 24
0x01A8 4 Data offset Block 25
0x01AC 4 Data offset Block 26
* Always observed as 0. No Blocks.
Block 2 (Plane) (168 bytes)
Defines a “plane”. Named because Paper Mario characters are composed mostly
of single quadrilateral planes, I'm defining a plane to be a collection of
polygons, which are grouped by 1 or more Block 22 blocks. For most planar
characters, a plane will contain only one polygon in one Block 22, but for 3D
characters or 3D objects, a plane will almost always contain many polygons,
which might be split across more than one Block 22.
Rel Addr SIZE Description
0x0000 64? Name String
0x0040 4 Index Block 4 (Starting Vertex)
0x0044 4 Number Block 4 (Vertices in plane)
0x0048 4 Unknown
0x004C 4 Unknown
0x0050 4 Unknown
0x0054 4 Unknown
0x0058 4 Index Block 18 (Starting Texture Vertex)
0x005C 4 Number Block 18 (Texture vertices in plane)
0x0060 4 Index of Ending Vertex + 1? What purpose?
0x0064 4 Unknown
0x0068 4 Unknown (Same as 0x0060?)
0x006C 4 Unknown
0x0070 4 Unknown (Same as 0x0060?)
0x0074 4 Unknown
0x0078 4 Unknown (Same as 0x0060?)
0x007C 4 Unknown
0x0080 4 Unknown (Same as 0x0060?)
0x0084 4 Unknown
0x0088 4 Unknown (Same as 0x0060?)
0x008C 4 Unknown
0x0090 4 Unknown (Same as 0x0060?)
0x0094 4 Unknown
0x0098 4 Index Block 22
0x009C 4 Num Block 22
0x00A0 4 Unknown (Observed values: 0*, 1, 2, 3)
0x00A4 4 Unknown (Cull Options?) (Observed values: 1[=CullBack?], 3*[=No Cull?])
* Most common values
Block 3 (Polygon) (8 bytes)
Defines a single polygon and the number of vertices that compose that polyon.
Also shows the relative index offset for Polygon Vertex Order Points (Block 5)
from the Polygon Vertex Order Point Index provided by the parent Block 22.
Rel Addr SIZE Description
0x0000 4 Relative Polygon Point Index Offset (Also means number points previously defined by polygons in the current Block22)
0x0004 4 Number Points in polygon
Block 4 (Vertex) (12 bytes)
Defines a single polygon within the model. A vertex might be shared by many
polygons. Vertices appear to represent a local assembly of sorts, and many
of the models will display as scattered sub-models until appropriate
transformations are applied (presumably by a combination of Block25 and Block24).
Some models however display perfectly assembled by the positioning of the
vertices alone, even where other transformations are defined.
Rel Addr SIZE Description
0x0000 4f X Coordinate
0x0004 4f Y Coordinate
0x0008 4f Z Coordinate
Block 5 (Polygon Vertex Order) (4 bytes)
Defines the collection of vertices used for each polygon. Because any polygon
within a given Plane can potentially share the same vertices, the vertices
listed are from the same pool starting at the plane's vertixIndex, and ending
at vertixIndex + the highest offset listed in a Block 5 in the given Plane.
Duplicate vertices listed indicates that the vertex is shared by more than
one polygon.
Rel Addr SIZE Description
0x0000 4 Index of vertex from base vertex of plane
Block 6 (Normals) (12 bytes)
Best guess is this defines normals for X, Y, and Z for each vertex in each
polygon. Lately I've had fairly positive results where lighting affected
the model.
Rel Addr SIZE Description
0x0000 4f X Normal
0x0004 4f Y Normal
0x0008 4f Z Normal
Block 7 (Normal Order) (4 bytes)
Most of these values increment by 1 from start to finish, but this is not always
true. They define the order in which normals are applied, which is accessed by
Block 22.
Rel Addr SIZE Description
0x0000 4 Index Block 6 (Normal)
Block 8 (Color Values) (4 bytes)
Best guess is this defines color for each vertex in each polygon. The color
value is represented in RGBA8 format. Most models are white for brightest
possible textures under given lighting conditions, but some of the 3D models
have color defined. I'm still having difficulty properly displaying this data
in a model.
Rel Addr SIZE Description
0x0000 4u Color value in RGBA8 format
Block 9 (Color Order) (4 bytes)
Same as Block 7, but for colors. Why is this level of indirection needed anyway?
Rel Addr SIZE Description
0x0000 4 Index Block 8 (Color)
Block 10 (Texture Point/Vertex Order) (4 bytes)
Similar to Block 5, but this defines the order of vertices used in polygons
for applying textures. In many models, this block will be identical to Block 5.
In cases where no texture is defined for a Block22, vertices for polygons within
that Block22 will not be listed. In a model with no textures, this block will
be empty.
Rel Addr SIZE Description
0x0000 4 Index of vertex from base vertex of plane
Block 18 (Texture Vertex) (8 bytes)
Defines X Y coordinates for mapping a texture.
Rel Addr SIZE Description
0x0000 4 s
0x0004 4 t
Block 19 (Unknown) (24 bytes)
I do not know what this block does. In every model I've checked, the first
3 floats are 0, the next 2 are 1, and the last float is 0. This block may be
texture related as it has the same number of blocks as Block 20 (Texture Map),
and is located among other texture-related blocks. I also have not seen a
reference to indices in this block, but there could be an implied relationship
between these blocks and Texture Map Blocks.
Rel Addr SIZE Description
0x0000 4f Unknown
0x0004 4f Unknown
0x0008 4f Unknown
0x000C 4f Unknown
0x0010 4f Unknown
0x0014 4f Unknown
Block 20 (Texture Map) (8 bytes)
The first value in this block points to one of the textures defined in the
Texture path Block (Block 21). The second value is usually, but not always, 0.
This block is referenced by and used for mapping textures defined in Block 21 to
a given Block 22.
Rel Addr SIZE Description
0x0000 4 Texture index
0x0004 4 Unknown
Block 21 (Texture Path Block) (64 bytes)
This block has a nice text representation of a texture defined in an associated
TPL file. The index at the second value doesn't point to any other block, and
no block lists indices of itself, so it probably points to a texture index within
the TPL file.
Rel Addr SIZE Description
0x0000 4 Unknown
0x0004 4 Index? (index of a texture in the associated TPL)
0x0008 4 Unknown
0x000C ? Name String
…
Block 22 (Polygon / Texture Map) (108 bytes)
This block actually maps more than just textures, but is more like a sub-plane.
This block defines the number of polygons within it and their index offsets, as
well as maps textures. This block also gives a base index for color and normal
blocks. The values between 0x14 and 0x34 are usually set to all FF, so if the
value is signed, they're set to -1. I don't know their purpose, nor the purpose
of the last 7 values which always appear to be 0.
Rel Addr SIZE Description
0x0000 4 Unknown
0x0004 4 Unknown
0x0008 4 Unknown
0x000C 4 Unknown
0x0010 4 Texture Map Index (Index Block 20)
0x0014 4 Unknown
0x0018 4 Unknown
0x001C 4 Unknown
0x0020 4 Unknown
0x0024 4 Unknown
0x0028 4 Unknown
0x002C 4 Unknown
0x0030 4 Unknown
0x0034 4 Unknown
0x0038 4 Polygon Index (Index Block 3)
0x003C 4 Number Polygons
0x0040 4 Index Block 5
0x0044 4 Index Block 7
0x0048 4 Index Block 9
0x004C 4 Index Block 10
0x0050 4 Unknown
0x0054 4 Unknown
0x0058 4 Unknown
0x005C 4 Unknown
0x0060 4 Unknown
0x0064 4 Unknown
0x0068 4 Unknown
Block 23 (Block25 Plane Control) (1 byte)
I've only seen this value set to 0 and 1. It's referenced by Block 25, and
when used to hide the display of Block25 objects that reference a 0 here, objects
which you would expect to be triggered by actions or events, such as lasers,
projectiles, and odd accessories, are hidden from view. Note not all Block 25
objects have an attached Plane. This might also disable transformations
associated with that Block 25.
Rel Addr SIZE Description
0x0000 1 (0=Hide Block22, 1=Display Block22)?
Block 24 (Transformations) (4 bytes)
Referenced by Block 25, these come in sets of 24 and are broken down into 8
sets of three, which are used for translating, scaling, and rotating the objects
from Block 25. Transformations for a parent are applied to children. I think
the implementation of this is mostly correct. I've only found 1 case so far
where objects don't assemble correctly, and the order that causes them to
assemble properly breaks many other more complex models. Assembly could
also be dependent on what is and isn't considered a joint, but I also don't know
that.
If anyone can help me properly identify, order, and implement these transformations, please send me an email.
Rel Addr SIZE Description
0x0000 4f Float value for various XYZ Translation,Scaling,Rotation
Best Guess (Works 99% of the time) of order and application of transformations
Order appled: 1, 7, 2, 8, 4, 5, 3, 6
subset 1: 0-2: Translation
subset 2: 3-5: Scale
subset 3: 6-8: Rotation (half-angle, ZYX)
subset 4: 9-11: Rotation (full-angle, ZYX)
subset 5: 12-14: Rotation Translation
subset 6: 15-17: Rotation Counter-Translation
subset 7: 18-20: Scale Translation
subset 8: 21-23: Scale Counter-Translation
Block 25 (Scene Graph) (88 bytes)
This block is like the superset of all others. After the description, the first
2 values I believe define a hierarchy of Planes. The first value references
a sibling of the current Block25, and the second value references a child.
Because only one child can be pointed at per block, the siblings create a way
to put several children under a single parent. It's assumed that the children
inherit all transformations from their parents before they are drawn. The last
value appears to be associated with joints. The name string references planes,
locators, groups, joints, and a few other things. I don't know what the real
difference is between these (planes are obvious), but those designated as a joint
have their last value set to 1 instead of 0.
Rel Addr SIZE Description
0x0000 64 Name String
0x0040 4 Additional Child Block25 of parent Block25
0x0044 4 Child Block25
0x0048 4 Index Block 2
0x004C 4 Index Block 23
0x0050 4 Index Block 24
0x0054 4 Joint Related?
Block 26 (Animation Sequence Identifier) (64 bytes)
This block acts as a pointer to an animation sequence. It doesn't appear to be
tied to any other block, and is used to track animation sequences which can't
be tracked in the main header because of their variable size.
Rel Addr SIZE Description
0x0000 42? Name String
0x003C 4 Data offset to associated Block 27 (Animation Sequence)
Block 27 (Variable Size, block substructure) ANIMATION SEQUENCE
Each Block 27 contains an animation sequence. So far texture animation (as in
changing of textures) is the only identified form of animation, but it appears
5 different types of animation can be used within a sequence. Each sequence
has a time length (in milliseconds?) defined in Block 27.2, and Block 27.3 is
an index of animation 'frames' that will be triggered at the right time. Each
frame can contain any number of the different animation types to evaluate. It
appears some of the animation sequences are designed to repeat, while others are
designed to play through once. I can't yet tell them apart definitively.
Block 27.1 (Header) (92 bytes)
Rel Addr SIZE Description
0x0000 4 Size of block
0x0004 4 Number Block 27.2
0x0008 4 Number Block 27.3
0x000C 4 Number Block 27.4
0x0010 4 Number Block 27.5
0x0014 4 Number Block 27.6
0x0018 4 Number Block 27.7
0x001C 4 Number Block 27.8
0x0020 4 Number Block 27.9
0x0024 4 Relative Data Offset Block 27.2
0x0028 4 Relative Data Offset Block 27.3
0x002C 4 Relative Data Offset Block 27.4
0x0030 4 Relative Data Offset Block 27.5
0x0034 4 Relative Data Offset Block 27.6
0x0038 4 Relative Data Offset Block 27.7
0x003C 4 Relative Data Offset Block 27.8
0x0040 4 Relative Data Offset Block 27.9
0x0044 4f Unknown
0x0048 4f Unknown
0x004C 4f Unknown
0x0050 4f Unknown
0x0054 4f Unknown
0x0058 4f Unknown
Block 27.2 (12 bytes)
Rel Addr SIZE Description
0x0000 4 Unknown (0=Single Pass? / 1=Loop?)
0x0004 4 Unknown
0x0008 4f Length of time in (milliseconds?) animation sequence lasts
Block 27.3 (Frame List) (44 bytes)
Rel Addr SIZE Description
0x0000 4f Time value in (milliseconds?) associated lines are evaluated
0x0004 4 Index Block 27.4
0x0008 4 Num Associated Block 27.4
0x000C 4 Index Block 27.5
0x0010 4 Num Associated Block 27.5
0x0014 4 Index Block 27.6
0x0018 4 Num Associated Block 27.6
0x001C 4 Index Block 27.7
0x0020 4 Num Associated Block 27.7
0x0024 4 Index Block 27.8
0x0028 4 Num Associated Block 27.8
Block 27.4 (4 bytes)
Rel Addr SIZE Description
0x0000 4* Unknown
Block 27.5 (4 bytes)
Rel Addr SIZE Description
0x0000 4* Unknown (4 signed bytes?)
Block 27.6 (12 bytes)
I don't know why this block has 12 bytes. The first 2 bytes are used in
changing or animating textures. The first byte identifies the texture Map
affected, and the second byte determines how much its texture index is
incremented or decremented. See Block 27.7 for how the indexing works, I
think the indexing is the same for them both (bias), but it might not be
for this block. This doesn't work for a lot of the models, and
it may or may not depend on the other two unknown bytes. I don't know.
Rel Addr SIZE Description
0x0000 1 Index Block 20 (Texture Map) (See Block 27.7 for indexing)
0x0001 1 Number to add to Texture Index of Block 20.
0x0002 1 Unknown (0 or -1?)
0x0003 1 Unknown (0 or -1?)
0x0004 4* Unknown
0x0008 4* Unknown
Block 27.7 (Plane Control) (4 bytes)
This block seems responsible for revealing and hiding the different planes.
It also appears that the format is broken down into 4*n bytes where n is the
number of block 27.7's listed in the associated block 27.3, with the first
n byte pairs actually used for settings the visibility of the planes, the first
byte identifying the index of the block25 or block23, and the second being set
to 1 or -1, which reveal and hide the planes respectively. The index byte is only
the true index for the first pair in the set. Any indices after that are
calculated by adding the index value to all the previous index values. This still
leaves the second n byte pairs, which may not be paired at all. Either way,
I don't know their purpose.
Rel Addr SIZE Description
2x+0x0000 1 Index Block25 or Block23
2x+0x0001 1 Reveal (1) or Hide (-1)
2n+2x+0x0? 1 Unknown
2n+2x+0x1? 1 Unknown
for a set of n blocks with x as the current index
Block 27.8 (4 bytes)
Possible Purpose: Pivot animation, IE general animation
Rel Addr SIZE Description
0x0000 4* Unknown
Block 27.9 (8 bytes)
Rel Addr SIZE Description
0x0000 4 Unknown
0x0004 4 Unknown
* Unknown representation