PKG File

A PKG file (.pkg) is a geometry file for Midtown Madness 2. It is used in most objects except for such things like roads in cities.

The structure of a PKG file is as follows

PKG {     char[4]   header = "PKG3";     PKGFile[] files; } PKGFile {     char[4]     header = "FILE";     String      name;   // Name of this section     long        length; // Length of this PKGFile in bytes     PKGFileData data;   // Format depends of name, see below } String {     unsigned byte    length;     // Number of bytes in this string including the string terminator.     char[length - 1] characters; // ASCII characters <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    char             terminator = '\0'; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;">The PKGFileData is different depending on the  <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;font-weight:bold;">name <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;"> of the PKGFile.

<span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;font-weight:bold;">"VL", "L", "M", "H": <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;"> <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">PKGFileData <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long nSections;    // Number of sections making up this LOD <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long nVerticesTot; // Total number of vertices in this LOD <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long nIndiciesTot; // Total number of indicies in this LOD <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long nSections2;   // Repetition of the number of sections? <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">                       // Highly unlikely, but I have no better suggestion at this time <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long flags;        // Flags defining what components are provided with each vertex, see below <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    PKGSection[nSections] sections; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">PKGSection <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long nStrips;         // Number of geometry strips in this section <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long shaderOffset;    // Offset into the shader list of the requested paintjob <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long verticesPerFace; // Determines if the strips are quads or triangles, have only seen 3 in this field though <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long nVertices;       // Number of vertices in this section <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    PKGVertex[nVertices]; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long nIndices;        // Number of indices making up the geometry strip <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    ushort[nIndices] indices; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">PKGVertex <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Vertex3D coordinate;         // If flags indicate coordinates <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Vector3D normal;            // If flags indicate normals <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Vertex2D textureCoordinate;  // If flags indicate texture coordinates <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">Vertex3D <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float x; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float y; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float z; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">Vector3D <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float x; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float y; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float z; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">Vertex2D <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float x; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float y; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">}  <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;"> <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;">Description of the bits for the  <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;font-style:italic;">flags <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;"> field: <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;">All other bits are unknown at this time.
 * Bit 1: Texture coordinates or coordinates
 * Bit 4: Normals
 * Bit 8: Coordinates or texture coordinates

<span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;font-weight:bold;">"shaders": <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;"> <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">PKGFileData <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long shaderType; // Bit 7: Shader type <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">                     // Bit 0-6: Number of paint jobs <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    long shadersPerPaintJob; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    PKGShader[Number of paint jobs * shadersPerPaintJob] shaders; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">PKGShader (Type 0) <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    String textureName; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Color4f ambient; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Color4f diffuse; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Color4f specular; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Color4f emissive; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float shininess; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">PKGShader (Type 1) <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    String textureName; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    Color4f ambient; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">Color4f <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float red; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float green; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float blue; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">    float alpha; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">} <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;font-weight:bold;">"offset": <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;"> <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">PKGFileData <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">   Vector3D offset; // Have not tested, but could be an offset added to all vertices in the object <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;white-space:normal;">}

<span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;font-weight:bold;">"xref": <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;"> <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;">A PKG can reference external objects stored in other PKGs, when rendering a PKG with external references, each object referenced will be rendered too. These objects are possibly  <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;font-style:italic;">breakable <span style="color:rgb(0,0,0);font-family:Verdana,Arial,Helvetica,sans-serif;font-size:12px;line-height:18px;">, meaning that they can be detached from the main object. <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">PKGFileData <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">{ <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   long     nReferences; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   Vector3D xAxis; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   Vector3D yAxis; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   Vector3D zAxis; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   Vector3D origin; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   char[]   name; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   char     terminator = 0x00; // Just to end the string <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   char[]   unknown0 = "max"; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">   ushort[] unknown1 = {0, 0, 0, 0, 0, 0, 0}; <span style="color:rgb(0,0,0);font-family:Courier,'CourierNew',sans-serif;font-size:11px;line-height:normal;">}

A big thanks goes out to fre_ber for the structure information.