Changes

Jump to navigation Jump to search
250 bytes removed ,  20:55, 5 June 2017
update info/formatting, use templates, add cat
Line 1: Line 1: −
==General information==
+
TrackMania '''.gbx files''' ([[GameBox]]) are generic container files that can contain everything from configuration to textures to track definitions. They consist of a header, a reference table and the body.
TrackMania gamebox files (*.gbx) are generic container files that can contain everything from configuration to textures to track definitions. They consist of a header, a reference table and the body.
     −
In old versions of TrackMania they used to be text files - nowadays they are binary files. Integers are stored in little endian order. The file body is often compressed (using LZO).
+
In old versions of TrackMania they used to be text files – nowadays they are binary files. Integers are stored in little-endian order. The file body is often compressed (using {{wp|Lempel–Ziv–Oberhumer|LZO}}).
   −
==Engines, classes, chunks==
+
== Engines, classes, chunks ==
 
A .gbx file more specifically stores the serialization of one or more class instances. There is one main instance, and optionally a number of auxiliary instances.
 
A .gbx file more specifically stores the serialization of one or more class instances. There is one main instance, and optionally a number of auxiliary instances.
    
The serializable classes are organized into 16 ''engines''. Each class is also subdivided into ''chunks''. A class is then not serialized in one go, but rather as a series of chunks. This allows Nadeo to easily extend classes in new TrackMania versions: instead of having to define a new class they can simply add more chunks to an existing one, and have older versions ignore these new chunk types.
 
The serializable classes are organized into 16 ''engines''. Each class is also subdivided into ''chunks''. A class is then not serialized in one go, but rather as a series of chunks. This allows Nadeo to easily extend classes in new TrackMania versions: instead of having to define a new class they can simply add more chunks to an existing one, and have older versions ignore these new chunk types.
   −
The data in a gbx file follows the pattern <chunk ID> <chunk data>. A ''chunk ID'' is a 32-bit number that identifies the engine, the class, and the chunk in that class. If you for example see the bytes <code>07 30 04 03</code> in the file, that would correspond to the integer 0x03043007, and be interpreted as follows:
+
The data in a .gbx file follows the pattern {{c|<chunk ID> <chunk data>}}. A ''chunk ID'' is a 32-bit number that identifies the engine, the class, and the chunk in that class. If you for example see the bytes <code>07 30 04 03</code> in the file, that would correspond to the integer 0x03043007, and be interpreted as follows:
    
  engine class chunk
 
  engine class chunk
Line 16: Line 15:  
All engines and classes are named; in this case, engine 3 is the Game engine, and class 043 in that engine is CGameCtnChallenge. Chunks do not have names.
 
All engines and classes are named; in this case, engine 3 is the Game engine, and class 043 in that engine is CGameCtnChallenge. Chunks do not have names.
   −
Apart from chunk ID's there are also ''class ID's'', which are just like chunk ID's except the chunk index part is ignored (and 0). For a complete overview of engines and classes, see [[Class ID's]].
+
Apart from chunk IDs there are also ''class IDs'', which are just like chunk IDs except the chunk index part is ignored (and 0). For a complete overview of engines and classes, see [[Class IDs]].
   −
==Header==
+
== Header ==
 
The header contains things like compression information and the class ID of the main class instance. The current version of the header also provides a few chunks of the main class that serve as meta information (e.g. the thumbnail of a challenge).
 
The header contains things like compression information and the class ID of the main class instance. The current version of the header also provides a few chunks of the main class that serve as meta information (e.g. the thumbnail of a challenge).
   Line 40: Line 39:  
** uint32 numNodes: the total number of class instances related to this gbx file. This includes the main instance, any local auxiliary instances, and any referenced external nodes/files. An internal list will be allocated with this number of entries; the main instance is at index 0.
 
** uint32 numNodes: the total number of class instances related to this gbx file. This includes the main instance, any local auxiliary instances, and any referenced external nodes/files. An internal list will be allocated with this number of entries; the main instance is at index 0.
   −
==Reference Table==
+
== Reference table ==
 
* uint32 numExternalNodes: the number of external nodes and files that this .gbx references. These come from other files located in the .gbx's [[PAK|.pak]] file. The references to these will be placed in the same list as the local nodes (see above). Both raw files (e.g. textures) and .gbx main instances can be referenced.
 
* uint32 numExternalNodes: the number of external nodes and files that this .gbx references. These come from other files located in the .gbx's [[PAK|.pak]] file. The references to these will be placed in the same list as the local nodes (see above). Both raw files (e.g. textures) and .gbx main instances can be referenced.
 
* if numExternalNodes > 0:
 
* if numExternalNodes > 0:
Line 61: Line 60:  
**** uint32 folderIndex: the depth-first index of the folder which the file is in. 0 means the base folder itself.
 
**** uint32 folderIndex: the depth-first index of the folder which the file is in. 0 means the base folder itself.
   −
==Body==
+
== Body ==
 
* if body is compressed:
 
* if body is compressed:
 
** uint32 uncompressedSize
 
** uint32 uncompressedSize
Line 69: Line 68:  
** byte data[]
 
** byte data[]
   −
==Reading the body==
+
== Reading the body ==
 
The file body contains further chunks of the main class instance, and may also contain auxiliary class instances. Reading the body is started by creating an in-memory instance of the class corresponding to the main class ID (instances are called ''nodes'' internally), and calling ReadNode on it:
 
The file body contains further chunks of the main class instance, and may also contain auxiliary class instances. Reading the body is started by creating an in-memory instance of the class corresponding to the main class ID (instances are called ''nodes'' internally), and calling ReadNode on it:
    
  ReadNode()
 
  ReadNode()
 
  {
 
  {
     while(true)
+
     while (true)
 
     {
 
     {
 
         chunkID = ReadUInt32();
 
         chunkID = ReadUInt32();
         if(chunkID == 0xFACADE01)
+
         if (chunkID == 0xFACADE01)
 
             return;
 
             return;
 
   
 
   
 
         chunkFlags = GetChunkFlags(chunkID);
 
         chunkFlags = GetChunkFlags(chunkID);
         if(chunkFlags & 0x10)
+
         if (chunkFlags & 0x10)
 
         {
 
         {
 
             skip = ReadUInt32();
 
             skip = ReadUInt32();
Line 91: Line 90:  
  }
 
  }
   −
GetChunkFlags() doesn't read anything from the file; it provides loading flags for the specified chunk ID. The only important flag is whether or not the chunk is "skippable". If it is, the chunk ID is followed by an uint32 0x50494B53 ("SKIP", shows up as "PIKS" in the file due to little endian ordering) and an uint32 specifying the size of the chunk data. This allows older versions of TrackMania that don't know how to parse this chunk ID to skip over the chunk data and go to the next chunk. If the chunk is not skippable, the chunk data follows immediately after the chunk ID.
+
GetChunkFlags() doesn't read anything from the file; it provides loading flags for the specified chunk ID. The only important flag is whether or not the chunk is "skippable". If it is, the chunk ID is followed by an uint32 0x50494B53 ("SKIP", shows up as "PIKS" in the file due to little-endian ordering) and an uint32 specifying the size of the chunk data. This allows older versions of TrackMania that don't know how to parse this chunk ID to skip over the chunk data and go to the next chunk. If the chunk is not skippable, the chunk data follows immediately after the chunk ID.
    
A dummy chunk ID of 0xFACADE01 signifies the end of the chunk list for the current class.
 
A dummy chunk ID of 0xFACADE01 signifies the end of the chunk list for the current class.
Line 102: Line 101:  
* '''bool''': 32-bit little-endian integer that can be 0 or 1.
 
* '''bool''': 32-bit little-endian integer that can be 0 or 1.
   −
* '''byte''', '''uint16''', '''int32''', '''uint32''', '''uint64''', '''uint128''', '''float''': regular little endian encoding.
+
* '''byte''', '''uint16''', '''int32''', '''uint32''', '''uint64''', '''uint128''', '''float''': regular little-endian encoding.
    
* '''vec2D''':
 
* '''vec2D''':
Line 120: Line 119:  
* '''string''':
 
* '''string''':
 
** uint32 length
 
** uint32 length
** byte chars[length] (UTF8, older files sometimes with BOM, not zero-terminated)
+
** byte chars[length] ({{wp|UTF-8}}, older files sometimes with {{wp|Byte order mark|BOM}}, not zero-terminated)
   −
* '''lookbackstring''': a form of compression which allows to avoid repeating the same string multiple times. Everytime a new string is encountered, it is added to a string list, and from then on this list entry is referenced instead of repeating the string another time.
+
* '''lookbackstring''': a form of compression which allows to avoid repeating the same string multiple times. Every time a new string is encountered, it is added to a string list, and from then on this list entry is referenced instead of repeating the string another time.
 
** if this is the first lookback string encountered:
 
** if this is the first lookback string encountered:
 
*** uint32 version (currently 3)
 
*** uint32 version (currently 3)
Line 129: Line 128:  
*** string newString. Append to the string list.
 
*** string newString. Append to the string list.
   −
''Note'': the lookback string state is reset after each header chunk. The string list is cleared completely, and the next lookback string will again trigger the version number. If index represents a number (bits 30 and 31 not set), it describes the position inside a ''global'' string table. In most cases it concerns the ID of a collection. The correspondences used up to now are: 11 = 'Valley', 12 = 'Canyon', 17 = 'TMCommon', 202 = 'Storm', 299 = 'SMCommon', 10003 = 'Common'.
+
''Note'': the lookback string state is reset after each header chunk. The string list is cleared completely, and the next lookback string will again trigger the version number. If index represents a number (bits 30 and 31 not set), it describes the position inside a ''global'' string table. In most cases it concerns the ID of a collection. The correspondences used up to now are: 11 = 'Valley', 12 = 'Canyon', 13 = 'Lagoon', 17 = 'TMCommon', 202 = 'Storm', 299 = 'SMCommon', 10003 = 'Common'.
    
* '''fileref''': path to an external file, e.g. a skin.
 
* '''fileref''': path to an external file, e.g. a skin.
Line 150: Line 149:  
*** ReadNode()
 
*** ReadNode()
   −
''Note'': In case of a text format gbx file (marked by a 'T' in the header) all numbers and strings are stored as one line of ASCII text in each case. Every line ends with a carriage return-linefeed (<CR><LF>) combination (0x0D and 0x0A). A single <LF> is part of a string.
+
''Note'': In case of a text format .gbx file (marked by a 'T' in the header) all numbers and strings are stored as one line of ASCII text in each case. Every line ends with a carriage return-linefeed ({{c|<CR><LF>}}) combination (0x0D and 0x0A). A single {{c|<LF>}} is part of a string.
 +
 
 +
== Class descriptions ==
   −
==Class descriptions==
   
===CGameCtnChallenge (03 043 000)===
 
===CGameCtnChallenge (03 043 000)===
   Line 169: Line 169:  
         byte
 
         byte
 
     if version >= 4:
 
     if version >= 4:
         uint32 copperPrice
+
         uint32 cost
 
         if version >= 5:
 
         if version >= 5:
 
             bool multilap
 
             bool multilap
Line 255: Line 255:  
'''03043014''' (skippable)
 
'''03043014''' (skippable)
 
  uint32
 
  uint32
  string password (old style password with weak xor encryption. this chunk is no longer used in newer track files, see 03043029)
+
  string password (old style password with weak xor encryption. This chunk is no longer used in newer track files; see 03043029)
 
 
 
'''03043017''' (skippable)
 
'''03043017''' (skippable)
Line 347: Line 347:  
  bool unknown
 
  bool unknown
 
  uint32 version
 
  uint32 version
 +
if version >= 5:
 +
    uint32 flags
 
  if version >= 2:
 
  if version >= 2:
 
     if version >= 4:
 
     if version >= 4:
Line 510: Line 512:  
'''03093002''' (body)
 
'''03093002''' (body)
 
  uint32 size
 
  uint32 size
  byte GBX[size], the track the replay was recorded on
+
  byte GBX[size] (the track the replay was recorded on)
    
'''03093007''' (skippable)
 
'''03093007''' (skippable)
Line 567: Line 569:     
The rotation of the car is calculated as a quaternion.
 
The rotation of the car is calculated as a quaternion.
* The real part of the quaternion is calculated as cos(angle) which corresponds to a rotation of 2*angle around the rotation axis.
+
* The real part of the quaternion is calculated as {{c|cos(angle)}} which corresponds to a rotation of {{c|2*angle}} around the rotation axis.
* The imaginary part of the quaternion (the rotation axis) is calculated as the vector (sin(angle)*cos(axisPitch)*cos(axisHeading), sin(angle)*cos(axisPitch)*sin(axisHeading), sin(angle)*sin(axisPitch)).
+
* The imaginary part of the quaternion (the rotation axis) is calculated as the vector {{c|(sin(angle)*cos(axisPitch)*cos(axisHeading), sin(angle)*cos(axisPitch)*sin(axisHeading), sin(angle)*sin(axisPitch))}}.
 
You can [http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Conversion_to_and_from_the_matrix_representation convert this quaternion to a transform matrix].
 
You can [http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Conversion_to_and_from_the_matrix_representation convert this quaternion to a transform matrix].
   −
The velocity vector (direction and speed of movement) is calculated in a similar way: (speed*cos(velocityPitch)*cos(velocityHeading), speed*cos(velocityPitch)*sin(velocityHeading), speed*sin(velocityPitch)).
+
The velocity vector (direction and speed of movement) is calculated in a similar way: {{c|(speed*cos(velocityPitch)*cos(velocityHeading), speed*cos(velocityPitch)*sin(velocityHeading), speed*sin(velocityPitch))}}.
    
===CGameCtnGhost (03 092 000)===
 
===CGameCtnGhost (03 092 000)===
Line 656: Line 658:  
  lookbackstring version
 
  lookbackstring version
 
  string pagePath (slash-separated folder path where the block appears in the editor)
 
  string pagePath (slash-separated folder path where the block appears in the editor)
  if version = 5
+
  if version == 5:
 
     lookbackstring
 
     lookbackstring
  if version >= 4
+
  if version >= 4:
 
     lookbackstring
 
     lookbackstring
  if version >= 3
+
  if version >= 3:
 
     uint32 flags
 
     uint32 flags
 
     uint16 index
 
     uint16 index
  if version >= 7
+
  if version >= 7:
 
     string name
 
     string name
   Line 872: Line 874:  
  for each number:
 
  for each number:
 
     string dirName
 
     string dirName
  −
== Historical information ==
  −
While the above description of *.Gbx files is far more complete and precise than before, it is also entirely different from &ndash; and more abstract than &ndash; the original description, which formed the basis for several of the tools below.  That historical description can still be viewed at this [http://en.tm-wiki.org/index.php?title=GBX&oldid=5300 revision link].
      
== Applications and Libraries that can inspect/modify the file format ==
 
== Applications and Libraries that can inspect/modify the file format ==
Line 880: Line 879:  
* [http://www.xaseco.org/tools.php GBX Data Fetcher] - a PHP module with classes to extract useful data from .Challenge|Map.Gbx files (including the thumbnail image), .Replay.Gbx files and .Pack.Gbx|.pak files, as well as parse their XML blocks.
 
* [http://www.xaseco.org/tools.php GBX Data Fetcher] - a PHP module with classes to extract useful data from .Challenge|Map.Gbx files (including the thumbnail image), .Replay.Gbx files and .Pack.Gbx|.pak files, as well as parse their XML blocks.
 
* [http://www.xaseco.org/tools.php Extract GBX data] - a PHP script to format and print data from all file types supported by the GBX Data Fetcher module.
 
* [http://www.xaseco.org/tools.php Extract GBX data] - a PHP script to format and print data from all file types supported by the GBX Data Fetcher module.
* [http://www.xaseco.org/tools.php Tally GBX versions] - a PHP script to tally some version data from all .Challenge|Map.Gbx files (including sample challenges in all known versions).
+
* [http://www.xaseco.org/tools.php Tally GBX versions] - a PHP script to tally some version data from all .Challenge|Map.Gbx files (includes sample challenges in all known versions).
* [http://tossha.ru/trackstudio/ TrackStudio] - a Windows TrackMania Forever track editor with 3D interface.
+
* [http://tossha.ru/trackstudio/ TrackStudio] - a Windows TrackMania Forever track editor with 3D interface.{{deadlink}}
* [http://www.mania-creative.com/talk/showthread.php?threadid=644 Blockmix tools] - Challenge editing tools (Recompressor, ChallengeEdit, GBX-Master, CELightRotate, TmfBlockMixEdition).
+
* [http://www.mania-creative.com/talk/showthread.php?threadid=644 Blockmix tools] - Challenge editing tools (Recompressor, ChallengeEdit, GBX-Master, CELightRotate, TmfBlockMixEdition).{{deadlink}}
* [http://www.mania-creative.com/talk/showthread.php?threadid=2379 TMPakTool] - Open and edit .pak files.
+
* [http://www.mania-creative.com/talk/showthread.php?threadid=2379 TMPakTool] - Open and edit .pak files.{{deadlink}}
* [http://www.mania-creative.com/talk/showthread.php?threadid=2421 TMUnlimiter] - Patches the in-game track editor to remove the block placement restrictions.
+
* [http://www.mania-creative.com/talk/showthread.php?threadid=2421 TMUnlimiter] - Patches the in-game track editor to remove the block placement restrictions.{{deadlink}}
* [http://forum.maniaplanet.com/viewtopic.php?t=19432 GBXedit] - Command-line based blockmix editor for TM² Stadium maps.
+
* {{mpforum|19432|GBXedit}} - Command-line based blockmix editor for TM² Stadium maps.
* [http://forum.maniaplanet.com/viewtopic.php?t=19890 MapEdit] - GUI-based blockmix editor for all ManiaPlanet maps.
+
* {{mpforum|19890|MapEdit}} - GUI-based blockmix editor for all ManiaPlanet maps.
 
* [[GbxDump]] - a Windows tool to dump and analyze the header of all kinds of .Gbx files.
 
* [[GbxDump]] - a Windows tool to dump and analyze the header of all kinds of .Gbx files.
 
* [http://www.wolfgang-rolke.de/gbxdump/gbxconv.zip ReplayToChallenge] - a Windows tool to extract a Challenge from a .Replay.Gbx file (includes source code).
 
* [http://www.wolfgang-rolke.de/gbxdump/gbxconv.zip ReplayToChallenge] - a Windows tool to extract a Challenge from a .Replay.Gbx file (includes source code).
* [[Easy TM]]
   
* [http://micolous.id.au/pages/disasm.html Trackmania Disassembler] - includes a library allowing you to write your own applications that can read the format.
 
* [http://micolous.id.au/pages/disasm.html Trackmania Disassembler] - includes a library allowing you to write your own applications that can read the format.
 +
 +
[[Category:File formats]]

Navigation menu