//(credit goes to Retriever II, original article is [[http://hocuspocus.taloncrossing.com/rii/tplvtx.txt|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. {{paper_mario_the_thousand_year_door:blockindices.png?500}}\\ --------------------------------------------------------------------------------- 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