<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://codresearch.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Kokole</id>
	<title>COD Engine Research - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://codresearch.dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Kokole"/>
	<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php/Special:Contributions/Kokole"/>
	<updated>2026-06-06T01:01:57Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.3</generator>
	<entry>
		<id>https://codresearch.dev/index.php?title=FastFiles_and_Zone_files_(BO2)&amp;diff=648</id>
		<title>FastFiles and Zone files (BO2)</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=FastFiles_and_Zone_files_(BO2)&amp;diff=648"/>
		<updated>2014-12-20T20:01:53Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Asset List */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:FastFiles]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
== FastFile Structure ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct DB_Header&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  int version;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct DB_AuthSignature&lt;br /&gt;
{&lt;br /&gt;
  char bytes[256];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct DB_AuthHeader&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  int reserved;&lt;br /&gt;
  char fastfileName[32];&lt;br /&gt;
  DB_AuthSignature signedSubheaderHash;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Encryption &amp;amp; Compression ==&lt;br /&gt;
=== PS3 ===&lt;br /&gt;
After the zone file is created, it is split into blocks. The first block is the 0x28 byte XFile header. After that, each block is 0x7FC0 bytes. Each block is first compressed using best compression, then encrypted using salsa20.&lt;br /&gt;
== FastFile Keys ==&lt;br /&gt;
=== XBOX 360 ===&lt;br /&gt;
Thanks to Chocolate.&lt;br /&gt;
 0x0E, 0x50, 0xF4, 0x9F,&lt;br /&gt;
 0x41, 0x23, 0x17, 0x09, &lt;br /&gt;
 0x60, 0x38, 0x66, 0x56, &lt;br /&gt;
 0x22, 0xDD, 0x09, 0x13, &lt;br /&gt;
 0x32, 0xA2, 0x09, 0xBA, &lt;br /&gt;
 0x0A, 0x05, 0xA0, 0x0E, &lt;br /&gt;
 0x13, 0x77, 0xCE, 0xDB, &lt;br /&gt;
 0x0A, 0x3C, 0xB1, 0xD3&lt;br /&gt;
=== PS3 ===&lt;br /&gt;
 0xC8, 0x0B, 0x0E, 0x0C,&lt;br /&gt;
 0x15, 0x4B, 0xFF, 0x91,&lt;br /&gt;
 0x76, 0xA0, 0xC5, 0xC8,&lt;br /&gt;
 0xD2, 0x4F, 0xA5, 0xE3,&lt;br /&gt;
 0xEE, 0x09, 0xEE, 0x90,&lt;br /&gt;
 0x6F, 0x72, 0x90, 0x80,&lt;br /&gt;
 0xA3, 0x92, 0x75, 0xFD,&lt;br /&gt;
 0x3E, 0xA7, 0x13, 0x39 &lt;br /&gt;
=== PC ===&lt;br /&gt;
Thanks to master131.&lt;br /&gt;
 0x64, 0x1D, 0x8A, 0x2F,&lt;br /&gt;
 0xE3, 0x1D, 0x3A, 0xA6,&lt;br /&gt;
 0x36, 0x22, 0xBB, 0xC9,&lt;br /&gt;
 0xCE, 0x85, 0x87, 0x22,&lt;br /&gt;
 0x9D, 0x42, 0xB0, 0xF8, &lt;br /&gt;
 0xED, 0x9B, 0x92, 0x41,&lt;br /&gt;
 0x30, 0xBF, 0x88, 0xB6,&lt;br /&gt;
 0x5E, 0xDC, 0x50, 0xBE&lt;br /&gt;
== Zone File ==&lt;br /&gt;
=== Header ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum&lt;br /&gt;
{&lt;br /&gt;
  XFILE_BLOCK_TEMP = 0,&lt;br /&gt;
  XFILE_BLOCK_RUNTIME_VIRTUAL = 1,&lt;br /&gt;
  XFILE_BLOCK_RUNTIME_PHYSICAL = 2,&lt;br /&gt;
  XFILE_BLOCK_DELAY_VIRTUAL = 3,&lt;br /&gt;
  XFILE_BLOCK_DELAY_PHYSICAL = 4,&lt;br /&gt;
  XFILE_BLOCK_VIRTUAL = 5,&lt;br /&gt;
  XFILE_BLOCK_PHYSICAL = 6,&lt;br /&gt;
  XFILE_BLOCK_STREAMER_RESERVE = 7,&lt;br /&gt;
  MAX_XFILE_COUNT&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct XFile&lt;br /&gt;
{&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int externalSize;&lt;br /&gt;
  unsigned int blockSize[MAX_XFILE_COUNT];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Asset List ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum XAssetType&lt;br /&gt;
{&lt;br /&gt;
  ASSET_TYPE_XMODELPIECES = 0x0,&lt;br /&gt;
  ASSET_TYPE_PHYSPRESET = 0x1,&lt;br /&gt;
  ASSET_TYPE_PHYSCONSTRAINTS = 0x2,&lt;br /&gt;
  ASSET_TYPE_DESTRUCTIBLEDEF = 0x3,&lt;br /&gt;
  ASSET_TYPE_XANIMPARTS = 0x4,&lt;br /&gt;
  ASSET_TYPE_XMODEL = 0x5,&lt;br /&gt;
  ASSET_TYPE_MATERIAL = 0x6,&lt;br /&gt;
  ASSET_TYPE_TECHNIQUE_SET = 0x7,&lt;br /&gt;
  ASSET_TYPE_IMAGE = 0x8,&lt;br /&gt;
  ASSET_TYPE_SOUND = 0x9,&lt;br /&gt;
  ASSET_TYPE_SOUND_PATCH = 0xA,&lt;br /&gt;
  ASSET_TYPE_CLIPMAP = 0xB,&lt;br /&gt;
  ASSET_TYPE_CLIPMAP_PVS = 0xC,&lt;br /&gt;
  ASSET_TYPE_COMWORLD = 0xD,&lt;br /&gt;
  ASSET_TYPE_GAMEWORLD_SP = 0xE,&lt;br /&gt;
  ASSET_TYPE_GAMEWORLD_MP = 0xF,&lt;br /&gt;
  ASSET_TYPE_MAP_ENTS = 0x10,&lt;br /&gt;
  ASSET_TYPE_GFXWORLD = 0x11,&lt;br /&gt;
  ASSET_TYPE_LIGHT_DEF = 0x12,&lt;br /&gt;
  ASSET_TYPE_UI_MAP = 0x13,&lt;br /&gt;
  ASSET_TYPE_FONT = 0x14,&lt;br /&gt;
  ASSET_TYPE_FONTICON = 0x15,&lt;br /&gt;
  ASSET_TYPE_MENULIST = 0x16,&lt;br /&gt;
  ASSET_TYPE_MENU = 0x17,&lt;br /&gt;
  ASSET_TYPE_LOCALIZE_ENTRY = 0x18,&lt;br /&gt;
  ASSET_TYPE_WEAPON = 0x19,&lt;br /&gt;
  ASSET_TYPE_WEAPONDEF = 0x1A,&lt;br /&gt;
  ASSET_TYPE_WEAPON_VARIANT = 0x1B,&lt;br /&gt;
  ASSET_TYPE_WEAPON_FULL = 0x1C,&lt;br /&gt;
  ASSET_TYPE_ATTACHMENT = 0x1D,&lt;br /&gt;
  ASSET_TYPE_ATTACHMENT_UNIQUE = 0x1E,&lt;br /&gt;
  ASSET_TYPE_WEAPON_CAMO = 0x1F,&lt;br /&gt;
  ASSET_TYPE_SNDDRIVER_GLOBALS = 0x20,&lt;br /&gt;
  ASSET_TYPE_FX = 0x21,&lt;br /&gt;
  ASSET_TYPE_IMPACT_FX = 0x22,&lt;br /&gt;
  ASSET_TYPE_AITYPE = 0x23,&lt;br /&gt;
  ASSET_TYPE_MPTYPE = 0x24,&lt;br /&gt;
  ASSET_TYPE_MPBODY = 0x25,&lt;br /&gt;
  ASSET_TYPE_MPHEAD = 0x26,&lt;br /&gt;
  ASSET_TYPE_CHARACTER = 0x27,&lt;br /&gt;
  ASSET_TYPE_XMODELALIAS = 0x28,&lt;br /&gt;
  ASSET_TYPE_RAWFILE = 0x29,&lt;br /&gt;
  ASSET_TYPE_STRINGTABLE = 0x2A,&lt;br /&gt;
  ASSET_TYPE_LEADERBOARD = 0x2B,&lt;br /&gt;
  ASSET_TYPE_XGLOBALS = 0x2C,&lt;br /&gt;
  ASSET_TYPE_DDL = 0x2D,&lt;br /&gt;
  ASSET_TYPE_GLASSES = 0x2E,&lt;br /&gt;
  ASSET_TYPE_EMBLEMSET = 0x2F,&lt;br /&gt;
  ASSET_TYPE_SCRIPTPARSETREE = 0x30,&lt;br /&gt;
  ASSET_TYPE_KEYVALUEPAIRS = 0x31,&lt;br /&gt;
  ASSET_TYPE_VEHICLEDEF = 0x32,&lt;br /&gt;
  ASSET_TYPE_MEMORYBLOCK = 0x33,&lt;br /&gt;
  ASSET_TYPE_ADDON_MAP_ENTS = 0x34,&lt;br /&gt;
  ASSET_TYPE_TRACER = 0x35,&lt;br /&gt;
  ASSET_TYPE_SKINNEDVERTS = 0x36,&lt;br /&gt;
  ASSET_TYPE_QDB = 0x37,&lt;br /&gt;
  ASSET_TYPE_SLUG = 0x38,&lt;br /&gt;
  ASSET_TYPE_FOOTSTEP_TABLE = 0x39,&lt;br /&gt;
  ASSET_TYPE_FOOTSTEPFX_TABLE = 0x3A,&lt;br /&gt;
  ASSET_TYPE_ZBARRIER = 0x3B,&lt;br /&gt;
  ASSET_TYPE_COUNT = 0x3C,&lt;br /&gt;
  ASSET_TYPE_STRING = 0x3C,&lt;br /&gt;
  ASSET_TYPE_ASSETLIST = 0x3D,&lt;br /&gt;
  ASSET_TYPE_REPORT = 0x3E,&lt;br /&gt;
  ASSET_TYPE_DEPEND = 0x3F,&lt;br /&gt;
  ASSET_TYPE_FULL_COUNT = 0x40,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
union XAssetHeader&lt;br /&gt;
{&lt;br /&gt;
  XModelPieces *xmodelPieces;&lt;br /&gt;
  PhysPreset *physPreset;&lt;br /&gt;
  PhysConstraints *physConstraints;&lt;br /&gt;
  DestructibleDef *destructibleDef;&lt;br /&gt;
  XAnimParts *parts;&lt;br /&gt;
  XModel *model;&lt;br /&gt;
  Material *material;&lt;br /&gt;
  MaterialPixelShader *pixelShader;&lt;br /&gt;
  MaterialVertexShader *vertexShader;&lt;br /&gt;
  MaterialTechniqueSet *techniqueSet;&lt;br /&gt;
  GfxImage *image;&lt;br /&gt;
  SndBank *sound;&lt;br /&gt;
  SndPatch *soundPatch;&lt;br /&gt;
  clipMap_t *clipMap;&lt;br /&gt;
  ComWorld *comWorld;&lt;br /&gt;
  GameWorldSp *gameWorldSp;&lt;br /&gt;
  GameWorldMp *gameWorldMp;&lt;br /&gt;
  MapEnts *mapEnts;&lt;br /&gt;
  GfxWorld *gfxWorld;&lt;br /&gt;
  GfxLightDef *lightDef;&lt;br /&gt;
  Font_s *font;&lt;br /&gt;
  FontIcon *fontIcon;&lt;br /&gt;
  MenuList *menuList;&lt;br /&gt;
  menuDef_t *menu;&lt;br /&gt;
  LocalizeEntry *localize;&lt;br /&gt;
  WeaponVariantDef *weapon;&lt;br /&gt;
  WeaponAttachment *attachment;&lt;br /&gt;
  WeaponAttachmentUnique *attachmentUnique;&lt;br /&gt;
  WeaponCamo *weaponCamo;&lt;br /&gt;
  SndDriverGlobals *sndDriverGlobals;&lt;br /&gt;
  FxEffectDef *fx;&lt;br /&gt;
  FxImpactTable *impactFx;&lt;br /&gt;
  RawFile *rawfile;&lt;br /&gt;
  StringTable *stringTable;&lt;br /&gt;
  LeaderboardDef *leaderboardDef;&lt;br /&gt;
  XGlobals *xGlobals;&lt;br /&gt;
  ddlRoot_t *ddlRoot;&lt;br /&gt;
  Glasses *glasses;&lt;br /&gt;
  TextureList *textureList;&lt;br /&gt;
  EmblemSet *emblemSet;&lt;br /&gt;
  ScriptParseTree *scriptParseTree;&lt;br /&gt;
  KeyValuePairs *keyValuePairs;&lt;br /&gt;
  VehicleDef *vehicleDef;&lt;br /&gt;
  MemoryBlock *memoryBlock;&lt;br /&gt;
  AddonMapEnts *addonMapEnts;&lt;br /&gt;
  TracerDef *tracerDef;&lt;br /&gt;
  SkinnedVertsDef *skinnedVertsDef;&lt;br /&gt;
  Qdb *qdb;&lt;br /&gt;
  Slug *slug;&lt;br /&gt;
  FootstepTableDef *footstepTableDef;&lt;br /&gt;
  FootstepFXTableDef *footstepFXTableDef;&lt;br /&gt;
  ZBarrierDef *zbarrierDef;&lt;br /&gt;
  void *data;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ScriptStringList&lt;br /&gt;
{&lt;br /&gt;
  int count;&lt;br /&gt;
  const char **strings;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct XAsset&lt;br /&gt;
{&lt;br /&gt;
  XAssetType type;&lt;br /&gt;
  XAssetHeader header;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct XAssetList&lt;br /&gt;
{&lt;br /&gt;
  ScriptStringList stringList;&lt;br /&gt;
  int dependCount;&lt;br /&gt;
  const char **depends;&lt;br /&gt;
  int assetCount;&lt;br /&gt;
  XAsset *assets;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=FastFiles_and_Zone_files_(BO2)&amp;diff=647</id>
		<title>FastFiles and Zone files (BO2)</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=FastFiles_and_Zone_files_(BO2)&amp;diff=647"/>
		<updated>2014-12-20T19:59:06Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Header */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:FastFiles]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
== FastFile Structure ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct DB_Header&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  int version;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct DB_AuthSignature&lt;br /&gt;
{&lt;br /&gt;
  char bytes[256];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct DB_AuthHeader&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  int reserved;&lt;br /&gt;
  char fastfileName[32];&lt;br /&gt;
  DB_AuthSignature signedSubheaderHash;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Encryption &amp;amp; Compression ==&lt;br /&gt;
=== PS3 ===&lt;br /&gt;
After the zone file is created, it is split into blocks. The first block is the 0x28 byte XFile header. After that, each block is 0x7FC0 bytes. Each block is first compressed using best compression, then encrypted using salsa20.&lt;br /&gt;
== FastFile Keys ==&lt;br /&gt;
=== XBOX 360 ===&lt;br /&gt;
Thanks to Chocolate.&lt;br /&gt;
 0x0E, 0x50, 0xF4, 0x9F,&lt;br /&gt;
 0x41, 0x23, 0x17, 0x09, &lt;br /&gt;
 0x60, 0x38, 0x66, 0x56, &lt;br /&gt;
 0x22, 0xDD, 0x09, 0x13, &lt;br /&gt;
 0x32, 0xA2, 0x09, 0xBA, &lt;br /&gt;
 0x0A, 0x05, 0xA0, 0x0E, &lt;br /&gt;
 0x13, 0x77, 0xCE, 0xDB, &lt;br /&gt;
 0x0A, 0x3C, 0xB1, 0xD3&lt;br /&gt;
=== PS3 ===&lt;br /&gt;
 0xC8, 0x0B, 0x0E, 0x0C,&lt;br /&gt;
 0x15, 0x4B, 0xFF, 0x91,&lt;br /&gt;
 0x76, 0xA0, 0xC5, 0xC8,&lt;br /&gt;
 0xD2, 0x4F, 0xA5, 0xE3,&lt;br /&gt;
 0xEE, 0x09, 0xEE, 0x90,&lt;br /&gt;
 0x6F, 0x72, 0x90, 0x80,&lt;br /&gt;
 0xA3, 0x92, 0x75, 0xFD,&lt;br /&gt;
 0x3E, 0xA7, 0x13, 0x39 &lt;br /&gt;
=== PC ===&lt;br /&gt;
Thanks to master131.&lt;br /&gt;
 0x64, 0x1D, 0x8A, 0x2F,&lt;br /&gt;
 0xE3, 0x1D, 0x3A, 0xA6,&lt;br /&gt;
 0x36, 0x22, 0xBB, 0xC9,&lt;br /&gt;
 0xCE, 0x85, 0x87, 0x22,&lt;br /&gt;
 0x9D, 0x42, 0xB0, 0xF8, &lt;br /&gt;
 0xED, 0x9B, 0x92, 0x41,&lt;br /&gt;
 0x30, 0xBF, 0x88, 0xB6,&lt;br /&gt;
 0x5E, 0xDC, 0x50, 0xBE&lt;br /&gt;
== Zone File ==&lt;br /&gt;
=== Header ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum&lt;br /&gt;
{&lt;br /&gt;
  XFILE_BLOCK_TEMP = 0,&lt;br /&gt;
  XFILE_BLOCK_RUNTIME_VIRTUAL = 1,&lt;br /&gt;
  XFILE_BLOCK_RUNTIME_PHYSICAL = 2,&lt;br /&gt;
  XFILE_BLOCK_DELAY_VIRTUAL = 3,&lt;br /&gt;
  XFILE_BLOCK_DELAY_PHYSICAL = 4,&lt;br /&gt;
  XFILE_BLOCK_VIRTUAL = 5,&lt;br /&gt;
  XFILE_BLOCK_PHYSICAL = 6,&lt;br /&gt;
  XFILE_BLOCK_STREAMER_RESERVE = 7,&lt;br /&gt;
  MAX_XFILE_COUNT&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct XFile&lt;br /&gt;
{&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int externalSize;&lt;br /&gt;
  unsigned int blockSize[MAX_XFILE_COUNT];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Asset List ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct XAsset&lt;br /&gt;
{&lt;br /&gt;
  XAssetType type;&lt;br /&gt;
  XAssetHeader *header;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ScriptStringList&lt;br /&gt;
{&lt;br /&gt;
  int count;&lt;br /&gt;
  const char **strings;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct XAssetList&lt;br /&gt;
{&lt;br /&gt;
  ScriptStringList stringList;&lt;br /&gt;
  int count;&lt;br /&gt;
  const char **strings;&lt;br /&gt;
  int assetCount;&lt;br /&gt;
  XAsset *assets;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=646</id>
		<title>MapEnts Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=646"/>
		<updated>2014-12-20T19:55:05Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Ghosts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:CoD4]]&lt;br /&gt;
[[Category:MW2]]&lt;br /&gt;
[[Category:MW3]]&lt;br /&gt;
[[Category:Ghosts]]&lt;br /&gt;
[[Category:AW]]&lt;br /&gt;
[[Category:WaW]]&lt;br /&gt;
[[Category:BO1]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The map_ents asset is part of the D3DBSP system used that is produced by Radiant. This is used to define any entities in the map particularly spawn points, helicopter path points, physable entities, and destructible entities. Although the entity string itself is quite easy to understand, some unknown structures have been added on later Call of Duty games.&lt;br /&gt;
== Call of Duty 4 &amp;amp; World at War &amp;amp; Black Ops 1 ==&lt;br /&gt;
This is the simplest map_ents.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The entityString is simply a string that defines different entitys, and it&#039;s length is numEntityChars. This is a simple as it gets.&lt;br /&gt;
== Modern Warfare 2 ==&lt;br /&gt;
Modern Warfare 2 adds some extra data to the end, believed to be buffer data and Stage data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Stage&lt;br /&gt;
{&lt;br /&gt;
  char * stageName;&lt;br /&gt;
  float offset[3];&lt;br /&gt;
  int flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  Stage * stages;&lt;br /&gt;
  byte stageCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset, despite one of those never actually having been found.&lt;br /&gt;
== Modern Warfare 3 ==&lt;br /&gt;
Modern Warfare 3 adds even more extra data to the end, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Black Ops 2 ==&lt;br /&gt;
Black Ops 2 adds similar data to Modern Warfare 2 to the end of it&#039;s asset, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  vec3_t dir;&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ghosts ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Bounds&lt;br /&gt;
{&lt;br /&gt;
  float midPoint[3];&lt;br /&gt;
  float halfSize[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  float dir[3];&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerAabbNode&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  unsigned __int16 firstChild;&lt;br /&gt;
  unsigned __int16 childCount;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggers&lt;br /&gt;
{&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  unsigned __int16 numClientTriggerNodes;&lt;br /&gt;
  ClientTriggerAabbNode *clientTriggerAabbTree;&lt;br /&gt;
  unsigned int triggerStringLength;&lt;br /&gt;
  char *triggerString;&lt;br /&gt;
  __int16 *visionSetTriggers;&lt;br /&gt;
  char *triggerType;&lt;br /&gt;
  float (*origins)[3];&lt;br /&gt;
  float *scriptDelay;&lt;br /&gt;
  __int16 *audioTriggers;&lt;br /&gt;
  __int16 *blendLookup;&lt;br /&gt;
  __int16 *npcTriggers;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlendNode&lt;br /&gt;
{&lt;br /&gt;
  float pointA[3];&lt;br /&gt;
  float pointB[3];&lt;br /&gt;
  unsigned __int16 triggerA;&lt;br /&gt;
  unsigned __int16 triggerB;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlend&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 numClientTriggerBlendNodes;&lt;br /&gt;
  ClientTriggerBlendNode *blendNodes;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SpawnPointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 index;&lt;br /&gt;
  scr_string_t name;&lt;br /&gt;
  scr_string_t target;&lt;br /&gt;
  scr_string_t script_noteworthy;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float angles[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SpawnPointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 spawnsCount;&lt;br /&gt;
  SpawnPointEntityRecord *spawns;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  int splineId;&lt;br /&gt;
  int splineNodeId;&lt;br /&gt;
  char *splineNodeLabel;&lt;br /&gt;
  float splineNodeTension;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float corridorDims[2];&lt;br /&gt;
  float tangent[3];&lt;br /&gt;
  float distToNextNode;&lt;br /&gt;
  float (*positionCubic)[3];&lt;br /&gt;
  float (*tangentQuadratic)[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splinePointCount;&lt;br /&gt;
  float splineLength;&lt;br /&gt;
  SplinePointEntityRecord *splinePoints;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplineRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splineCount;&lt;br /&gt;
  SplinePointRecordList *splines;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  ClientTriggers clientTrigger;&lt;br /&gt;
  ClientTriggerBlend clientTriggerBlend;&lt;br /&gt;
  SpawnPointRecordList spawnList;&lt;br /&gt;
  SplineRecordList splineList;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advanced Warfare ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = (unknownCount3 &amp;lt;&amp;lt; 4) + (unknownCount3 &amp;lt;&amp;lt; 2)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData5;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData7;			//size = ((unknownStruct1-&amp;gt;unknownCount1 + unknownStruct1-&amp;gt;unknownCount1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData10;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData11;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData12;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData13;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString3;&lt;br /&gt;
  ScriptString unknownScriptString4;&lt;br /&gt;
  char unknown2[0x12];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format must work in tandem with the other D3DBSP assets. Currently the used the source format is simply a text file with the entityString located at &amp;quot;raw/maps/(MAPNAME).d3dbsp&amp;quot; for SP maps and at &amp;quot;raw/maps/mp/(MAPNAME).d3dbsp&amp;quot; for MP maps.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=645</id>
		<title>MapEnts Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=645"/>
		<updated>2014-12-20T19:54:42Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Black Ops 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:CoD4]]&lt;br /&gt;
[[Category:MW2]]&lt;br /&gt;
[[Category:MW3]]&lt;br /&gt;
[[Category:Ghosts]]&lt;br /&gt;
[[Category:AW]]&lt;br /&gt;
[[Category:WaW]]&lt;br /&gt;
[[Category:BO1]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The map_ents asset is part of the D3DBSP system used that is produced by Radiant. This is used to define any entities in the map particularly spawn points, helicopter path points, physable entities, and destructible entities. Although the entity string itself is quite easy to understand, some unknown structures have been added on later Call of Duty games.&lt;br /&gt;
== Call of Duty 4 &amp;amp; World at War &amp;amp; Black Ops 1 ==&lt;br /&gt;
This is the simplest map_ents.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The entityString is simply a string that defines different entitys, and it&#039;s length is numEntityChars. This is a simple as it gets.&lt;br /&gt;
== Modern Warfare 2 ==&lt;br /&gt;
Modern Warfare 2 adds some extra data to the end, believed to be buffer data and Stage data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Stage&lt;br /&gt;
{&lt;br /&gt;
  char * stageName;&lt;br /&gt;
  float offset[3];&lt;br /&gt;
  int flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  Stage * stages;&lt;br /&gt;
  byte stageCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset, despite one of those never actually having been found.&lt;br /&gt;
== Modern Warfare 3 ==&lt;br /&gt;
Modern Warfare 3 adds even more extra data to the end, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Black Ops 2 ==&lt;br /&gt;
Black Ops 2 adds similar data to Modern Warfare 2 to the end of it&#039;s asset, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  vec3_t dir;&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ghosts ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Bounds&lt;br /&gt;
{&lt;br /&gt;
  float midPoint[3];&lt;br /&gt;
  float halfSize[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  float dir[3];&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerAabbNode&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  unsigned __int16 firstChild;&lt;br /&gt;
  unsigned __int16 childCount;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggers&lt;br /&gt;
{&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  unsigned __int16 numClientTriggerNodes;&lt;br /&gt;
  ClientTriggerAabbNode *clientTriggerAabbTree;&lt;br /&gt;
  unsigned int triggerStringLength;&lt;br /&gt;
  char *triggerString;&lt;br /&gt;
  __int16 *visionSetTriggers;&lt;br /&gt;
  char *triggerType;&lt;br /&gt;
  float (*origins)[3];&lt;br /&gt;
  float *scriptDelay;&lt;br /&gt;
  __int16 *audioTriggers;&lt;br /&gt;
  __int16 *blendLookup;&lt;br /&gt;
  __int16 *npcTriggers;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlendNode&lt;br /&gt;
{&lt;br /&gt;
  float pointA[3];&lt;br /&gt;
  float pointB[3];&lt;br /&gt;
  unsigned __int16 triggerA;&lt;br /&gt;
  unsigned __int16 triggerB;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlend&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 numClientTriggerBlendNodes;&lt;br /&gt;
  ClientTriggerBlendNode *blendNodes;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SpawnPointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 index;&lt;br /&gt;
  scr_string_t name;&lt;br /&gt;
  scr_string_t target;&lt;br /&gt;
  scr_string_t script_noteworthy;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float angles[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SpawnPointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 spawnsCount;&lt;br /&gt;
  SpawnPointEntityRecord *spawns;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  int splineId;&lt;br /&gt;
  int splineNodeId;&lt;br /&gt;
  char *splineNodeLabel;&lt;br /&gt;
  float splineNodeTension;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float corridorDims[2];&lt;br /&gt;
  float tangent[3];&lt;br /&gt;
  float distToNextNode;&lt;br /&gt;
  float (*positionCubic)[3];&lt;br /&gt;
  float (*tangentQuadratic)[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splinePointCount;&lt;br /&gt;
  float splineLength;&lt;br /&gt;
  SplinePointEntityRecord *splinePoints;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplineRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splineCount;&lt;br /&gt;
  SplinePointRecordList *splines;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  ClientTriggers clientTrigger;&lt;br /&gt;
  ClientTriggerBlend clientTriggerBlend;&lt;br /&gt;
  SpawnPointRecordList spawnList;&lt;br /&gt;
  SplineRecordList splineList;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
&lt;br /&gt;
== Advanced Warfare ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = (unknownCount3 &amp;lt;&amp;lt; 4) + (unknownCount3 &amp;lt;&amp;lt; 2)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData5;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData7;			//size = ((unknownStruct1-&amp;gt;unknownCount1 + unknownStruct1-&amp;gt;unknownCount1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData10;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData11;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData12;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData13;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString3;&lt;br /&gt;
  ScriptString unknownScriptString4;&lt;br /&gt;
  char unknown2[0x12];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format must work in tandem with the other D3DBSP assets. Currently the used the source format is simply a text file with the entityString located at &amp;quot;raw/maps/(MAPNAME).d3dbsp&amp;quot; for SP maps and at &amp;quot;raw/maps/mp/(MAPNAME).d3dbsp&amp;quot; for MP maps.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=644</id>
		<title>MapEnts Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=644"/>
		<updated>2014-12-20T19:52:45Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Ghosts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:CoD4]]&lt;br /&gt;
[[Category:MW2]]&lt;br /&gt;
[[Category:MW3]]&lt;br /&gt;
[[Category:Ghosts]]&lt;br /&gt;
[[Category:AW]]&lt;br /&gt;
[[Category:WaW]]&lt;br /&gt;
[[Category:BO1]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The map_ents asset is part of the D3DBSP system used that is produced by Radiant. This is used to define any entities in the map particularly spawn points, helicopter path points, physable entities, and destructible entities. Although the entity string itself is quite easy to understand, some unknown structures have been added on later Call of Duty games.&lt;br /&gt;
== Call of Duty 4 &amp;amp; World at War &amp;amp; Black Ops 1 ==&lt;br /&gt;
This is the simplest map_ents.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The entityString is simply a string that defines different entitys, and it&#039;s length is numEntityChars. This is a simple as it gets.&lt;br /&gt;
== Modern Warfare 2 ==&lt;br /&gt;
Modern Warfare 2 adds some extra data to the end, believed to be buffer data and Stage data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Stage&lt;br /&gt;
{&lt;br /&gt;
  char * stageName;&lt;br /&gt;
  float offset[3];&lt;br /&gt;
  int flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  Stage * stages;&lt;br /&gt;
  byte stageCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset, despite one of those never actually having been found.&lt;br /&gt;
== Modern Warfare 3 ==&lt;br /&gt;
Modern Warfare 3 adds even more extra data to the end, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Black Ops 2 ==&lt;br /&gt;
Black Ops 2 adds similar data to Modern Warfare 2 to the end of it&#039;s asset, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  vec3_t dir;&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset.&lt;br /&gt;
&lt;br /&gt;
== Ghosts ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Bounds&lt;br /&gt;
{&lt;br /&gt;
  float midPoint[3];&lt;br /&gt;
  float halfSize[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  float dir[3];&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerAabbNode&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  unsigned __int16 firstChild;&lt;br /&gt;
  unsigned __int16 childCount;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggers&lt;br /&gt;
{&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  unsigned __int16 numClientTriggerNodes;&lt;br /&gt;
  ClientTriggerAabbNode *clientTriggerAabbTree;&lt;br /&gt;
  unsigned int triggerStringLength;&lt;br /&gt;
  char *triggerString;&lt;br /&gt;
  __int16 *visionSetTriggers;&lt;br /&gt;
  char *triggerType;&lt;br /&gt;
  float (*origins)[3];&lt;br /&gt;
  float *scriptDelay;&lt;br /&gt;
  __int16 *audioTriggers;&lt;br /&gt;
  __int16 *blendLookup;&lt;br /&gt;
  __int16 *npcTriggers;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlendNode&lt;br /&gt;
{&lt;br /&gt;
  float pointA[3];&lt;br /&gt;
  float pointB[3];&lt;br /&gt;
  unsigned __int16 triggerA;&lt;br /&gt;
  unsigned __int16 triggerB;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlend&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 numClientTriggerBlendNodes;&lt;br /&gt;
  ClientTriggerBlendNode *blendNodes;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SpawnPointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 index;&lt;br /&gt;
  scr_string_t name;&lt;br /&gt;
  scr_string_t target;&lt;br /&gt;
  scr_string_t script_noteworthy;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float angles[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SpawnPointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 spawnsCount;&lt;br /&gt;
  SpawnPointEntityRecord *spawns;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  int splineId;&lt;br /&gt;
  int splineNodeId;&lt;br /&gt;
  char *splineNodeLabel;&lt;br /&gt;
  float splineNodeTension;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float corridorDims[2];&lt;br /&gt;
  float tangent[3];&lt;br /&gt;
  float distToNextNode;&lt;br /&gt;
  float (*positionCubic)[3];&lt;br /&gt;
  float (*tangentQuadratic)[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splinePointCount;&lt;br /&gt;
  float splineLength;&lt;br /&gt;
  SplinePointEntityRecord *splinePoints;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplineRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splineCount;&lt;br /&gt;
  SplinePointRecordList *splines;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  ClientTriggers clientTrigger;&lt;br /&gt;
  ClientTriggerBlend clientTriggerBlend;&lt;br /&gt;
  SpawnPointRecordList spawnList;&lt;br /&gt;
  SplineRecordList splineList;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
&lt;br /&gt;
== Advanced Warfare ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = (unknownCount3 &amp;lt;&amp;lt; 4) + (unknownCount3 &amp;lt;&amp;lt; 2)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData5;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData7;			//size = ((unknownStruct1-&amp;gt;unknownCount1 + unknownStruct1-&amp;gt;unknownCount1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData10;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData11;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData12;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData13;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString3;&lt;br /&gt;
  ScriptString unknownScriptString4;&lt;br /&gt;
  char unknown2[0x12];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format must work in tandem with the other D3DBSP assets. Currently the used the source format is simply a text file with the entityString located at &amp;quot;raw/maps/(MAPNAME).d3dbsp&amp;quot; for SP maps and at &amp;quot;raw/maps/mp/(MAPNAME).d3dbsp&amp;quot; for MP maps.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=643</id>
		<title>MapEnts Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=643"/>
		<updated>2014-12-20T19:51:31Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Ghosts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:CoD4]]&lt;br /&gt;
[[Category:MW2]]&lt;br /&gt;
[[Category:MW3]]&lt;br /&gt;
[[Category:Ghosts]]&lt;br /&gt;
[[Category:AW]]&lt;br /&gt;
[[Category:WaW]]&lt;br /&gt;
[[Category:BO1]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The map_ents asset is part of the D3DBSP system used that is produced by Radiant. This is used to define any entities in the map particularly spawn points, helicopter path points, physable entities, and destructible entities. Although the entity string itself is quite easy to understand, some unknown structures have been added on later Call of Duty games.&lt;br /&gt;
== Call of Duty 4 &amp;amp; World at War &amp;amp; Black Ops 1 ==&lt;br /&gt;
This is the simplest map_ents.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The entityString is simply a string that defines different entitys, and it&#039;s length is numEntityChars. This is a simple as it gets.&lt;br /&gt;
== Modern Warfare 2 ==&lt;br /&gt;
Modern Warfare 2 adds some extra data to the end, believed to be buffer data and Stage data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Stage&lt;br /&gt;
{&lt;br /&gt;
  char * stageName;&lt;br /&gt;
  float offset[3];&lt;br /&gt;
  int flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  Stage * stages;&lt;br /&gt;
  byte stageCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset, despite one of those never actually having been found.&lt;br /&gt;
== Modern Warfare 3 ==&lt;br /&gt;
Modern Warfare 3 adds even more extra data to the end, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Black Ops 2 ==&lt;br /&gt;
Black Ops 2 adds similar data to Modern Warfare 2 to the end of it&#039;s asset, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  vec3_t dir;&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset.&lt;br /&gt;
&lt;br /&gt;
== Ghosts ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Bounds&lt;br /&gt;
{&lt;br /&gt;
  float midPoint[3];&lt;br /&gt;
  float halfSize[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  float dir[3];&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerAabbNode&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  unsigned __int16 firstChild;&lt;br /&gt;
  unsigned __int16 childCount;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggers&lt;br /&gt;
{&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  unsigned __int16 numClientTriggerNodes;&lt;br /&gt;
  ClientTriggerAabbNode *clientTriggerAabbTree;&lt;br /&gt;
  unsigned int triggerStringLength;&lt;br /&gt;
  char *triggerString;&lt;br /&gt;
  __int16 *visionSetTriggers;&lt;br /&gt;
  char *triggerType;&lt;br /&gt;
  float (*origins)[3];&lt;br /&gt;
  float *scriptDelay;&lt;br /&gt;
  __int16 *audioTriggers;&lt;br /&gt;
  __int16 *blendLookup;&lt;br /&gt;
  __int16 *npcTriggers;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlendNode&lt;br /&gt;
{&lt;br /&gt;
  float pointA[3];&lt;br /&gt;
  float pointB[3];&lt;br /&gt;
  unsigned __int16 triggerA;&lt;br /&gt;
  unsigned __int16 triggerB;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct ClientTriggerBlend&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 numClientTriggerBlendNodes;&lt;br /&gt;
  ClientTriggerBlendNode *blendNodes;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SpawnPointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 index;&lt;br /&gt;
  scr_string_t name;&lt;br /&gt;
  scr_string_t target;&lt;br /&gt;
  scr_string_t script_noteworthy;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float angles[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 2366 */&lt;br /&gt;
struct SpawnPointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 spawnsCount;&lt;br /&gt;
  SpawnPointEntityRecord *spawns;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointEntityRecord&lt;br /&gt;
{&lt;br /&gt;
  int splineId;&lt;br /&gt;
  int splineNodeId;&lt;br /&gt;
  char *splineNodeLabel;&lt;br /&gt;
  float splineNodeTension;&lt;br /&gt;
  float origin[3];&lt;br /&gt;
  float corridorDims[2];&lt;br /&gt;
  float tangent[3];&lt;br /&gt;
  float distToNextNode;&lt;br /&gt;
  float (*positionCubic)[3];&lt;br /&gt;
  float (*tangentQuadratic)[3];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplinePointRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splinePointCount;&lt;br /&gt;
  float splineLength;&lt;br /&gt;
  SplinePointEntityRecord *splinePoints;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct SplineRecordList&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 splineCount;&lt;br /&gt;
  SplinePointRecordList *splines;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
  ClientTriggers clientTrigger;&lt;br /&gt;
  ClientTriggerBlend clientTriggerBlend;&lt;br /&gt;
  SpawnPointRecordList spawnList;&lt;br /&gt;
  SplineRecordList splineList;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
&lt;br /&gt;
== Advanced Warfare ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = (unknownCount3 &amp;lt;&amp;lt; 4) + (unknownCount3 &amp;lt;&amp;lt; 2)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData5;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData7;			//size = ((unknownStruct1-&amp;gt;unknownCount1 + unknownStruct1-&amp;gt;unknownCount1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData10;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData11;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData12;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData13;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString3;&lt;br /&gt;
  ScriptString unknownScriptString4;&lt;br /&gt;
  char unknown2[0x12];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format must work in tandem with the other D3DBSP assets. Currently the used the source format is simply a text file with the entityString located at &amp;quot;raw/maps/(MAPNAME).d3dbsp&amp;quot; for SP maps and at &amp;quot;raw/maps/mp/(MAPNAME).d3dbsp&amp;quot; for MP maps.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=642</id>
		<title>MapEnts Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=642"/>
		<updated>2014-12-20T19:43:55Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Black Ops 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:CoD4]]&lt;br /&gt;
[[Category:MW2]]&lt;br /&gt;
[[Category:MW3]]&lt;br /&gt;
[[Category:Ghosts]]&lt;br /&gt;
[[Category:AW]]&lt;br /&gt;
[[Category:WaW]]&lt;br /&gt;
[[Category:BO1]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The map_ents asset is part of the D3DBSP system used that is produced by Radiant. This is used to define any entities in the map particularly spawn points, helicopter path points, physable entities, and destructible entities. Although the entity string itself is quite easy to understand, some unknown structures have been added on later Call of Duty games.&lt;br /&gt;
== Call of Duty 4 &amp;amp; World at War &amp;amp; Black Ops 1 ==&lt;br /&gt;
This is the simplest map_ents.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The entityString is simply a string that defines different entitys, and it&#039;s length is numEntityChars. This is a simple as it gets.&lt;br /&gt;
== Modern Warfare 2 ==&lt;br /&gt;
Modern Warfare 2 adds some extra data to the end, believed to be buffer data and Stage data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Stage&lt;br /&gt;
{&lt;br /&gt;
  char * stageName;&lt;br /&gt;
  float offset[3];&lt;br /&gt;
  int flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  Stage * stages;&lt;br /&gt;
  byte stageCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset, despite one of those never actually having been found.&lt;br /&gt;
== Modern Warfare 3 ==&lt;br /&gt;
Modern Warfare 3 adds even more extra data to the end, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Black Ops 2 ==&lt;br /&gt;
Black Ops 2 adds similar data to Modern Warfare 2 to the end of it&#039;s asset, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct TriggerModel&lt;br /&gt;
{&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 hullCount;&lt;br /&gt;
  unsigned __int16 firstHull;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerHull&lt;br /&gt;
{&lt;br /&gt;
  Bounds bounds;&lt;br /&gt;
  int contents;&lt;br /&gt;
  unsigned __int16 slabCount;&lt;br /&gt;
  unsigned __int16 firstSlab;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TriggerSlab&lt;br /&gt;
{&lt;br /&gt;
  vec3_t dir;&lt;br /&gt;
  float midPoint;&lt;br /&gt;
  float halfSize;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset.&lt;br /&gt;
&lt;br /&gt;
== Ghosts ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  char unknown2[0x18];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Advanced Warfare ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = (unknownCount3 &amp;lt;&amp;lt; 4) + (unknownCount3 &amp;lt;&amp;lt; 2)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData5;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData7;			//size = ((unknownStruct1-&amp;gt;unknownCount1 + unknownStruct1-&amp;gt;unknownCount1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData10;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData11;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData12;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData13;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString3;&lt;br /&gt;
  ScriptString unknownScriptString4;&lt;br /&gt;
  char unknown2[0x12];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format must work in tandem with the other D3DBSP assets. Currently the used the source format is simply a text file with the entityString located at &amp;quot;raw/maps/(MAPNAME).d3dbsp&amp;quot; for SP maps and at &amp;quot;raw/maps/mp/(MAPNAME).d3dbsp&amp;quot; for MP maps.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=641</id>
		<title>MapEnts Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=641"/>
		<updated>2014-12-20T19:43:06Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Black Ops 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:CoD4]]&lt;br /&gt;
[[Category:MW2]]&lt;br /&gt;
[[Category:MW3]]&lt;br /&gt;
[[Category:Ghosts]]&lt;br /&gt;
[[Category:AW]]&lt;br /&gt;
[[Category:WaW]]&lt;br /&gt;
[[Category:BO1]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The map_ents asset is part of the D3DBSP system used that is produced by Radiant. This is used to define any entities in the map particularly spawn points, helicopter path points, physable entities, and destructible entities. Although the entity string itself is quite easy to understand, some unknown structures have been added on later Call of Duty games.&lt;br /&gt;
== Call of Duty 4 &amp;amp; World at War &amp;amp; Black Ops 1 ==&lt;br /&gt;
This is the simplest map_ents.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The entityString is simply a string that defines different entitys, and it&#039;s length is numEntityChars. This is a simple as it gets.&lt;br /&gt;
== Modern Warfare 2 ==&lt;br /&gt;
Modern Warfare 2 adds some extra data to the end, believed to be buffer data and Stage data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Stage&lt;br /&gt;
{&lt;br /&gt;
  char * stageName;&lt;br /&gt;
  float offset[3];&lt;br /&gt;
  int flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  Stage * stages;&lt;br /&gt;
  byte stageCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset, despite one of those never actually having been found.&lt;br /&gt;
== Modern Warfare 3 ==&lt;br /&gt;
Modern Warfare 3 adds even more extra data to the end, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Black Ops 2 ==&lt;br /&gt;
Black Ops 2 adds similar data to Modern Warfare 2 to the end of it&#039;s asset, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapTriggers&lt;br /&gt;
{&lt;br /&gt;
  unsigned int count;&lt;br /&gt;
  TriggerModel *models;&lt;br /&gt;
  unsigned int hullCount;&lt;br /&gt;
  TriggerHull *hulls;&lt;br /&gt;
  unsigned int slabCount;&lt;br /&gt;
  TriggerSlab *slabs;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset.&lt;br /&gt;
&lt;br /&gt;
== Ghosts ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  char unknown2[0x18];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Advanced Warfare ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = (unknownCount3 &amp;lt;&amp;lt; 4) + (unknownCount3 &amp;lt;&amp;lt; 2)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData5;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData7;			//size = ((unknownStruct1-&amp;gt;unknownCount1 + unknownStruct1-&amp;gt;unknownCount1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData10;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData11;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData12;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData13;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString3;&lt;br /&gt;
  ScriptString unknownScriptString4;&lt;br /&gt;
  char unknown2[0x12];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format must work in tandem with the other D3DBSP assets. Currently the used the source format is simply a text file with the entityString located at &amp;quot;raw/maps/(MAPNAME).d3dbsp&amp;quot; for SP maps and at &amp;quot;raw/maps/mp/(MAPNAME).d3dbsp&amp;quot; for MP maps.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=640</id>
		<title>MapEnts Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=MapEnts_Asset&amp;diff=640"/>
		<updated>2014-12-20T19:42:08Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Black Ops 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:CoD4]]&lt;br /&gt;
[[Category:MW2]]&lt;br /&gt;
[[Category:MW3]]&lt;br /&gt;
[[Category:Ghosts]]&lt;br /&gt;
[[Category:AW]]&lt;br /&gt;
[[Category:WaW]]&lt;br /&gt;
[[Category:BO1]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The map_ents asset is part of the D3DBSP system used that is produced by Radiant. This is used to define any entities in the map particularly spawn points, helicopter path points, physable entities, and destructible entities. Although the entity string itself is quite easy to understand, some unknown structures have been added on later Call of Duty games.&lt;br /&gt;
== Call of Duty 4 &amp;amp; World at War &amp;amp; Black Ops 1 ==&lt;br /&gt;
This is the simplest map_ents.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The entityString is simply a string that defines different entitys, and it&#039;s length is numEntityChars. This is a simple as it gets.&lt;br /&gt;
== Modern Warfare 2 ==&lt;br /&gt;
Modern Warfare 2 adds some extra data to the end, believed to be buffer data and Stage data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Stage&lt;br /&gt;
{&lt;br /&gt;
  char * stageName;&lt;br /&gt;
  float offset[3];&lt;br /&gt;
  int flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  Stage * stages;&lt;br /&gt;
  byte stageCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset, despite one of those never actually having been found.&lt;br /&gt;
== Modern Warfare 3 ==&lt;br /&gt;
Modern Warfare 3 adds even more extra data to the end, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Black Ops 2 ==&lt;br /&gt;
Black Ops 2 adds similar data to Modern Warfare 2 to the end of it&#039;s asset, believed to be buffer data.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  BYTE * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
  MapTriggers trigger;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents asset.&lt;br /&gt;
&lt;br /&gt;
== Ghosts ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = ((unknownCount3 &amp;lt;&amp;lt; 2) + unknownCount3) &amp;lt;&amp;lt; 2&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1&lt;br /&gt;
  char * unknownData5;			//size = ((unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData7;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  char unknown2[0x18];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind that the unknownInternalMapEnts1 is also used in the addon_map_ents and col_map_mp (clipMap) assets.&lt;br /&gt;
== Advanced Warfare ==&lt;br /&gt;
Ghosts provides a fundamental change to the way the map_ents asset works, because while the entityString still exists it goes unused.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct unknownInternalMapEnts1&lt;br /&gt;
{&lt;br /&gt;
  int unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 &amp;lt;&amp;lt; 3&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2 &amp;lt;&amp;lt; 5&lt;br /&gt;
  int unknownCount3;&lt;br /&gt;
  char * unknownData3;			//size = (unknownCount3 &amp;lt;&amp;lt; 4) + (unknownCount3 &amp;lt;&amp;lt; 2)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts2&lt;br /&gt;
{&lt;br /&gt;
  unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
  short unknownCount1;&lt;br /&gt;
  char * unknownData1;			//size = unknownCount1 * 0x1C&lt;br /&gt;
  int unknownCount2;&lt;br /&gt;
  char * unknownData2;			//size = unknownCount2&lt;br /&gt;
  char * unknownData3;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData4;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData5;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData6;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData7;			//size = ((unknownStruct1-&amp;gt;unknownCount1 + unknownStruct1-&amp;gt;unknownCount1) + unknownStruct1-&amp;gt;unknownCount1) &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData8;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 2&lt;br /&gt;
  char * unknownData9;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData10;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData11;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData12;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
  char * unknownData13;			//size = unknownStruct1-&amp;gt;unknownCount1 &amp;lt;&amp;lt; 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts3&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  char * unknownData;			//size = unknownCount * 0x1C&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknown1;&lt;br /&gt;
  ScriptString unknownScriptString1;&lt;br /&gt;
  ScriptString unknownScriptString2;&lt;br /&gt;
  ScriptString unknownScriptString3;&lt;br /&gt;
  ScriptString unknownScriptString4;&lt;br /&gt;
  char unknown2[0x12];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts4&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts4Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1Internal1&lt;br /&gt;
{&lt;br /&gt;
  char unknown1[8];&lt;br /&gt;
  char (*unknown2)[0x40];&lt;br /&gt;
  char unknown3[0x28];&lt;br /&gt;
  char (*unknown4)[0x30];&lt;br /&gt;
  char (*unknown5)[0x24];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5Internal1&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  int unknown;&lt;br /&gt;
  unknownInternalMapEnts5Internal1Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct unknownInternalMapEnts5&lt;br /&gt;
{&lt;br /&gt;
  short unknownCount;&lt;br /&gt;
  unknownInternalMapEnts5Internal1 * unknownStruct;			//Count = unknownCount&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct MapEnts&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  char *entityString;&lt;br /&gt;
  int numEntityChars;&lt;br /&gt;
       unknownInternalMapEnts1 unknownStruct1;&lt;br /&gt;
       unknownInternalMapEnts2 unknownStruct2;&lt;br /&gt;
       unknownInternalMapEnts3 unknownStruct3;&lt;br /&gt;
       unknownInternalMapEnts4 unknownStruct4;&lt;br /&gt;
       unknownInternalMapEnts5 unknownStruct5;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format must work in tandem with the other D3DBSP assets. Currently the used the source format is simply a text file with the entityString located at &amp;quot;raw/maps/(MAPNAME).d3dbsp&amp;quot; for SP maps and at &amp;quot;raw/maps/mp/(MAPNAME).d3dbsp&amp;quot; for MP maps.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=639</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=639"/>
		<updated>2014-12-20T19:35:05Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
&lt;br /&gt;
struct IPakHeader&lt;br /&gt;
{&lt;br /&gt;
  unsigned int magic;&lt;br /&gt;
  unsigned int version;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int sectionCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakSection&lt;br /&gt;
{&lt;br /&gt;
  unsigned int type; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int itemCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakIndexEntry&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int64 key;&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakDataChunkHeader&lt;br /&gt;
{&lt;br /&gt;
  unsigned int countAndOffset; // 24 bits = offset, 8 bits = count&lt;br /&gt;
  unsigned int commands[31]; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=638</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=638"/>
		<updated>2014-12-20T19:34:47Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
&lt;br /&gt;
struct IPakHeader&lt;br /&gt;
{&lt;br /&gt;
  :unsigned int magic;&lt;br /&gt;
  :  unsigned int version;&lt;br /&gt;
  :  unsigned int size;&lt;br /&gt;
  :  unsigned int sectionCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakSection&lt;br /&gt;
{&lt;br /&gt;
  unsigned int type; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int itemCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakIndexEntry&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int64 key;&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakDataChunkHeader&lt;br /&gt;
{&lt;br /&gt;
  unsigned int countAndOffset; // 24 bits = offset, 8 bits = count&lt;br /&gt;
  unsigned int commands[31]; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=637</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=637"/>
		<updated>2014-12-20T19:32:15Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
&lt;br /&gt;
struct IPakHeader&lt;br /&gt;
{&lt;br /&gt;
  unsigned int magic;&lt;br /&gt;
  unsigned int version;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int sectionCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakSection&lt;br /&gt;
{&lt;br /&gt;
  unsigned int type; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int itemCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakIndexEntry&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int64 key;&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakDataChunkHeader&lt;br /&gt;
{&lt;br /&gt;
  unsigned int countAndOffset; // 24 bits = offset, 8 bits = count&lt;br /&gt;
  unsigned int commands[31]; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=636</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=636"/>
		<updated>2014-12-20T19:30:59Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
struct IPakHeader&lt;br /&gt;
{&lt;br /&gt;
  unsigned int magic;&lt;br /&gt;
  unsigned int version;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int sectionCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakSection&lt;br /&gt;
{&lt;br /&gt;
  unsigned int type; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
  unsigned int itemCount;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakIndexEntry&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int64 key;&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int size;&lt;br /&gt;
};&lt;br /&gt;
 &lt;br /&gt;
struct IPakDataChunkHeader&lt;br /&gt;
{&lt;br /&gt;
  unsigned int countAndOffset; // 24 bits = offset, 8 bits = count&lt;br /&gt;
  unsigned int commands[31]; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=635</id>
		<title>ScriptParseTree Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=635"/>
		<updated>2014-12-20T19:12:44Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Executable Data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The ScriptParseTree asset is a new asset in Black Ops 2 and this is the only Call of Duty game it has appeared in so far. This is Treyarch&#039;s answer to GSCs (Keep in mind that on Black Ops 1 GSCs were still [[:Rawfile Asset|rawfiles]]). Compared to IW&#039;s equivalent scriptfile asset, the ScriptParseTree has proven to give slightly more information and thus are easier to reverse. The basic structure is identical to the rawfiles&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct ScriptParseTree&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  int len;&lt;br /&gt;
  char *buffer;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Simply an uncompressed buffer holding the GSC data. The binary data is then passed to the GSC Virtual Machine (VM) to be ran. Now for the header of the binary data&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#define GSCMagic = 0x804753430D0A0006&lt;br /&gt;
&lt;br /&gt;
struct GSC_IMPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 name_space;&lt;br /&gt;
  unsigned __int16 num_address;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_ANIMNODE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_STRINGTABLE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 string;&lt;br /&gt;
  char num_address;&lt;br /&gt;
  char type;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_ANIMTREE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 num_tree_address;&lt;br /&gt;
  unsigned __int16 num_node_address;&lt;br /&gt;
  char pad[2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_PROFILE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_EXPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int checksum;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_FIXUP_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_OBJ&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  unsigned int source_crc;&lt;br /&gt;
  unsigned int include_offset;&lt;br /&gt;
  unsigned int animtree_offset;&lt;br /&gt;
  unsigned int cseg_offset;&lt;br /&gt;
  unsigned int stringtablefixup_offset;&lt;br /&gt;
  unsigned int exports_offset;&lt;br /&gt;
  unsigned int imports_offset;&lt;br /&gt;
  unsigned int fixup_offset;&lt;br /&gt;
  unsigned int profile_offset;&lt;br /&gt;
  unsigned int cseg_size;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 stringtablefixup_count;&lt;br /&gt;
  unsigned __int16 exports_count;&lt;br /&gt;
  unsigned __int16 imports_count;&lt;br /&gt;
  unsigned __int16 fixup_count;&lt;br /&gt;
  unsigned __int16 profile_count;&lt;br /&gt;
  char include_count;&lt;br /&gt;
  char animtree_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Following the header is a section of null terminated strings (undetermined size/count). This section is also padded at the end to a 4-byte buffer. The following sections will reference back to this section when a string is used. Keep in mind that the offsets are simply just an offset in the buffer.&lt;br /&gt;
=== Include Section ===&lt;br /&gt;
The first known section after the string table is the include section, and this should be the first section dumped as well. This section is used to replace the following in a raw gsc&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include maps\mp\_utility;&lt;br /&gt;
#include common_scripts\utility;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The include section is probably the easiest section to reverse. Each include exists as a single integer which holds the offset of the include&#039;s string in the buffer. &lt;br /&gt;
=== Using Animtree Section ===&lt;br /&gt;
Although this section doesn&#039;t follow the include section, it is what needs to be dumped second. When a GSC wants to directly access and animtree, then the following code is added (for animtree &amp;quot;mp_vehicles&amp;quot;)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#using_animtree( &amp;quot;mp_vehicles&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then animations can be accessed from the tree as follows (Using the %)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
destructible_anims[ &amp;quot;car&amp;quot; ] = %veh_car_destroy;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Knowing this, the binary data section can be reversed fairly easily. The structure for their definitions in this section is&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Reference&lt;br /&gt;
{&lt;br /&gt;
  unsigned short name;&lt;br /&gt;
  unsigned short xrefOffset;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct AnimTree&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned short pathOffset; //Paths do not exist for animtrees (so far)&lt;br /&gt;
	unsigned short referenceCount;&lt;br /&gt;
	Reference references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
XRefs are explained in better detail in the code section. Each animtree thats included will have an AnimTree struct, and every time an animation is used it will be defined in the references.&lt;br /&gt;
=== Argument Section ===&lt;br /&gt;
The argument section not only defines any function arguments that are defined with function declarations, but any local variable a function might create. Although they are defined the same, the difference between the two is highlighted in the code section. Each argument will be defined as follows&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Argument&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned char referenceCount;&lt;br /&gt;
	signed char unknown;&lt;br /&gt;
	unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The references will explained in more detail in the code section.&lt;br /&gt;
&lt;br /&gt;
=== Function Call Section ===&lt;br /&gt;
If a function is called by a function in this GSC, it must be defined here in the function call section, even if that function is located inside this GSC. First the struct&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionCall&lt;br /&gt;
{&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  unsigned short pathOffset;&lt;br /&gt;
  unsigned short referenceCount;&lt;br /&gt;
  byte paramCount;&lt;br /&gt;
  byte flag;&lt;br /&gt;
  unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
NameOffset obviously holds the name of the called function. References are explained in the code section. If the function is not located in this GSC or in a &amp;quot;using&amp;quot; GSC, then the function must have a path with the name of the GSC that it is defined in, and this is where the pathOffset points to. eg&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
thread maps\mp\gametypes\_spawning::init();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Function Declaration Section ===&lt;br /&gt;
This is the section that will be cycled through when dumping the GSC. Every function that is defined in this GSC is here. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionDeclaration&lt;br /&gt;
{&lt;br /&gt;
  int crc32;&lt;br /&gt;
  unsigned int executionDataOffset;&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  byte unknown2;&lt;br /&gt;
  byte argumentCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The executionDataOffset is an offset in the code section defining where this function begins.&lt;br /&gt;
&lt;br /&gt;
=== Executable Data ===&lt;br /&gt;
This section is by far the trickiest section. This is where the actual code the functions are compiled into is stored. The first thing that will be needed is a list of operation codes (OPcodes). These opcodes should be the same for all systems.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum OPCodes : char&lt;br /&gt;
{&lt;br /&gt;
  OP_End = 0x0,&lt;br /&gt;
  OP_Return = 0x1,&lt;br /&gt;
  OP_GetUndefined = 0x2,&lt;br /&gt;
  OP_GetZero = 0x3,&lt;br /&gt;
  OP_GetByte = 0x4,&lt;br /&gt;
  OP_GetNegByte = 0x5,&lt;br /&gt;
  OP_GetUnsignedShort = 0x6,&lt;br /&gt;
  OP_GetNegUnsignedShort = 0x7,&lt;br /&gt;
  OP_GetInteger = 0x8,&lt;br /&gt;
  OP_GetFloat = 0x9,&lt;br /&gt;
  OP_GetString = 0xA,&lt;br /&gt;
  OP_GetIString = 0xB,&lt;br /&gt;
  OP_GetVector = 0xC,&lt;br /&gt;
  OP_GetLevelObject = 0xD,&lt;br /&gt;
  OP_GetAnimObject = 0xE,&lt;br /&gt;
  OP_GetSelf = 0xF,&lt;br /&gt;
  OP_GetLevel = 0x10,&lt;br /&gt;
  OP_GetGame = 0x11,&lt;br /&gt;
  OP_GetAnim = 0x12,&lt;br /&gt;
  OP_GetAnimation = 0x13,&lt;br /&gt;
  OP_GetGameRef = 0x14,&lt;br /&gt;
  OP_GetFunction = 0x15,&lt;br /&gt;
  OP_CreateLocalVariable = 0x16,&lt;br /&gt;
  OP_SafeCreateLocalVariables = 0x17,&lt;br /&gt;
  OP_RemoveLocalVariables = 0x18,&lt;br /&gt;
  OP_EvalLocalVariableCached = 0x19,&lt;br /&gt;
  OP_EvalArray = 0x1A,&lt;br /&gt;
  OP_EvalLocalArrayRefCached = 0x1B,&lt;br /&gt;
  OP_EvalArrayRef = 0x1C,&lt;br /&gt;
  OP_ClearArray = 0x1D,&lt;br /&gt;
  OP_EmptyArray = 0x1E,&lt;br /&gt;
  OP_GetSelfObject = 0x1F,&lt;br /&gt;
  OP_EvalFieldVariable = 0x20,&lt;br /&gt;
  OP_EvalFieldVariableRef = 0x21,&lt;br /&gt;
  OP_ClearFieldVariable = 0x22,&lt;br /&gt;
  OP_SafeSetVariableFieldCached = 0x23,&lt;br /&gt;
  OP_SafeSetWaittillVariableFieldCached = 0x24,&lt;br /&gt;
  OP_ClearParams = 0x25,&lt;br /&gt;
  OP_CheckClearParams = 0x26,&lt;br /&gt;
  OP_EvalLocalVariableRefCached = 0x27,&lt;br /&gt;
  OP_SetVariableField = 0x28,&lt;br /&gt;
  OP_CallBuiltin = 0x29,&lt;br /&gt;
  OP_CallBuiltinMethod = 0x2A,&lt;br /&gt;
  OP_Wait = 0x2B,&lt;br /&gt;
  OP_WaitTillFrameEnd = 0x2C,&lt;br /&gt;
  OP_PreScriptCall = 0x2D,&lt;br /&gt;
  OP_ScriptFunctionCall = 0x2E,&lt;br /&gt;
  OP_ScriptFunctionCallPointer = 0x2F,&lt;br /&gt;
  OP_ScriptMethodCall = 0x30,&lt;br /&gt;
  OP_ScriptMethodCallPointer = 0x31,&lt;br /&gt;
  OP_ScriptThreadCall = 0x32,&lt;br /&gt;
  OP_ScriptThreadCallPointer = 0x33,&lt;br /&gt;
  OP_ScriptMethodThreadCall = 0x34,&lt;br /&gt;
  OP_ScriptMethodThreadCallPointer = 0x35,&lt;br /&gt;
  OP_DecTop = 0x36,&lt;br /&gt;
  OP_CastFieldObject = 0x37,&lt;br /&gt;
  OP_CastBool = 0x38,&lt;br /&gt;
  OP_BoolNot = 0x39,&lt;br /&gt;
  OP_BoolComplement = 0x3A,&lt;br /&gt;
  OP_JumpOnFalse = 0x3B,&lt;br /&gt;
  OP_JumpOnTrue = 0x3C,&lt;br /&gt;
  OP_JumpOnFalseExpr = 0x3D,&lt;br /&gt;
  OP_JumpOnTrueExpr = 0x3E,&lt;br /&gt;
  OP_Jump = 0x3F,&lt;br /&gt;
  OP_JumpBack = 0x40,&lt;br /&gt;
  OP_Inc = 0x41,&lt;br /&gt;
  OP_Dec = 0x42,&lt;br /&gt;
  OP_Bit_Or = 0x43,&lt;br /&gt;
  OP_Bit_Xor = 0x44,&lt;br /&gt;
  OP_Bit_And = 0x45,&lt;br /&gt;
  OP_Equal = 0x46,&lt;br /&gt;
  OP_NotEqual = 0x47,&lt;br /&gt;
  OP_LessThan = 0x48,&lt;br /&gt;
  OP_GreaterThan = 0x49,&lt;br /&gt;
  OP_LessThanOrEqualTo = 0x4A,&lt;br /&gt;
  OP_GreaterThanOrEqualTo = 0x4B,&lt;br /&gt;
  OP_ShiftLeft = 0x4C,&lt;br /&gt;
  OP_ShiftRight = 0x4D,&lt;br /&gt;
  OP_Plus = 0x4E,&lt;br /&gt;
  OP_Minus = 0x4F,&lt;br /&gt;
  OP_Multiply = 0x50,&lt;br /&gt;
  OP_Divide = 0x51,&lt;br /&gt;
  OP_Modulus = 0x52,&lt;br /&gt;
  OP_SizeOf = 0x53,&lt;br /&gt;
  OP_WaitTillMatch = 0x54,&lt;br /&gt;
  OP_WaitTill = 0x55,&lt;br /&gt;
  OP_Notify = 0x56,&lt;br /&gt;
  OP_EndOn = 0x57,&lt;br /&gt;
  OP_VoidCodePos = 0x58,&lt;br /&gt;
  OP_Switch = 0x59,&lt;br /&gt;
  OP_EndSwitch = 0x5A,&lt;br /&gt;
  OP_Vector = 0x5B,&lt;br /&gt;
  OP_GetHash = 0x5C,&lt;br /&gt;
  OP_RealWait = 0x5D,&lt;br /&gt;
  OP_VectorConstant = 0x5E,&lt;br /&gt;
  OP_IsDefined = 0x5F,&lt;br /&gt;
  OP_VectorScale = 0x60,&lt;br /&gt;
  OP_AnglesToUp = 0x61,&lt;br /&gt;
  OP_AnglesToRight = 0x62,&lt;br /&gt;
  OP_AnglesToForward = 0x63,&lt;br /&gt;
  OP_AngleClamp180 = 0x64,&lt;br /&gt;
  OP_VectorToAngles = 0x65,&lt;br /&gt;
  OP_Abs = 0x66,&lt;br /&gt;
  OP_GetTime = 0x67,&lt;br /&gt;
  OP_GetDvar = 0x68,&lt;br /&gt;
  OP_GetDvarInt = 0x69,&lt;br /&gt;
  OP_GetDvarFloat = 0x6A,&lt;br /&gt;
  OP_GetDvarVector = 0x6B,&lt;br /&gt;
  OP_GetDvarColorRed = 0x6C,&lt;br /&gt;
  OP_GetDvarColorGreen = 0x6D,&lt;br /&gt;
  OP_GetDvarColorBlue = 0x6E,&lt;br /&gt;
  OP_GetDvarColorAlpha = 0x6F,&lt;br /&gt;
  OP_FirstArrayKey = 0x70,&lt;br /&gt;
  OP_NextArrayKey = 0x71,&lt;br /&gt;
  OP_ProfileStart = 0x72,&lt;br /&gt;
  OP_ProfileStop = 0x73,&lt;br /&gt;
  OP_SafeDecTop = 0x74,&lt;br /&gt;
  OP_Nop = 0x75,&lt;br /&gt;
  OP_Abort = 0x76,&lt;br /&gt;
  OP_Object = 0x77,&lt;br /&gt;
  OP_ThreadObject = 0x78,&lt;br /&gt;
  OP_EvalLocalVariable = 0x79,&lt;br /&gt;
  OP_EvalLocalVariableRef = 0x7A,&lt;br /&gt;
  OP_DevblockBegin = 0x7B,&lt;br /&gt;
  OP_DevblockEnd = 0x7C,&lt;br /&gt;
  OP_Breakpoint = 0x7D,&lt;br /&gt;
  OP_AutoBreakpoint = 0x7E,&lt;br /&gt;
  OP_ErrorBreakpoint = 0x7F,&lt;br /&gt;
  OP_WatchBreakpoint = 0x80,&lt;br /&gt;
  OP_NotifyBreakpoint = 0x81,&lt;br /&gt;
  OP_Count = 0x82,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Notice that 0x7B is the highest opcode, but 0x7F is still valid. In truth anything over 0x7B will register as NOP. The executable does some odd jumping around for each OP code, so a recap of each OP code will try to be added. In the following functions &amp;quot;currentFunctionDataOffset&amp;quot; is defined as an integer that points to the current OP code being read. Keep in mind that an OP code is read, the data offset is increased by 1, and then the following code is ran. OP codes are parsed in the order they are read, but if a dump is being done then parts are going to be dumped in reverse order. Here is an example of a series of OP codes...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
OP_PreScriptCall&lt;br /&gt;
OP_GetString		&amp;quot;1350&amp;quot;&lt;br /&gt;
OP_GetString		&amp;quot;scr_veh_health_tank&amp;quot;&lt;br /&gt;
OP_CallBuiltin 		2, &amp;quot;setdvar&amp;quot;&lt;br /&gt;
OP_clearparams&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This would be the &amp;quot;asm&amp;quot; of the GSC, and would look like this...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
setdvar( &amp;quot;scr_veh_health_tank&amp;quot;, &amp;quot;1350&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== OP_End ====&lt;br /&gt;
If FunctionDeclaration-&amp;gt;crc32 equals to returned crc then break. This is how you calculate the CRC32 below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
static const unsigned int kCrc32Table[] = {&lt;br /&gt;
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,&lt;br /&gt;
	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,&lt;br /&gt;
	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,&lt;br /&gt;
	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,&lt;br /&gt;
	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,&lt;br /&gt;
	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,&lt;br /&gt;
	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,&lt;br /&gt;
	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,&lt;br /&gt;
	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,&lt;br /&gt;
	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,&lt;br /&gt;
	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,&lt;br /&gt;
	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,&lt;br /&gt;
	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,&lt;br /&gt;
	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,&lt;br /&gt;
	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,&lt;br /&gt;
	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,&lt;br /&gt;
	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,&lt;br /&gt;
	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,&lt;br /&gt;
	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,&lt;br /&gt;
	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,&lt;br /&gt;
	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,&lt;br /&gt;
	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,&lt;br /&gt;
	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,&lt;br /&gt;
	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,&lt;br /&gt;
	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,&lt;br /&gt;
	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,&lt;br /&gt;
	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,&lt;br /&gt;
	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,&lt;br /&gt;
	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,&lt;br /&gt;
	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,&lt;br /&gt;
	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,&lt;br /&gt;
	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,&lt;br /&gt;
	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,&lt;br /&gt;
	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,&lt;br /&gt;
	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,&lt;br /&gt;
	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,&lt;br /&gt;
	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,&lt;br /&gt;
	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,&lt;br /&gt;
	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,&lt;br /&gt;
	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,&lt;br /&gt;
	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,&lt;br /&gt;
	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,&lt;br /&gt;
	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
unsigned int crc(unsigned char* pData, unsigned int length) {&lt;br /&gt;
unsigned char* pCur = (unsigned char*)pData;&lt;br /&gt;
unsigned int remaining = length, _crc = ~0;&lt;br /&gt;
&lt;br /&gt;
for (; remaining--; ++pCur)&lt;br /&gt;
 _crc = (_crc &amp;gt;&amp;gt; 8) ^ kCrc32Table[(_crc ^ *pCur) &amp;amp; 0xff];&lt;br /&gt;
&lt;br /&gt;
return ~_crc;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For the CRC32 checksum parameters it&#039;s unsigned int crc(functionStart, currentFunctionDataOffset - functionStart). If the returned crc does not equal FunctionDeclaration-&amp;gt;crc32 then write &amp;quot;return;&amp;quot; to the stack.&lt;br /&gt;
&lt;br /&gt;
==== OP_Return ====&lt;br /&gt;
The return OP is exactly as expected. Any OP codes in the stack go after a &amp;quot;return&amp;quot;. There is no data skipped, it is simply a 1 byte opcode. Keep in mind that if the game reaches a return, it leaves the function however for a complete dump, data must continue to be read and sometimes this data is unnecessary.&lt;br /&gt;
==== OP_GetUndefined &amp;amp; OP_GetZero ====&lt;br /&gt;
This simply represents the &amp;quot;undefined&amp;quot;/0 element in GSCs. It is a simple 1 byte opcode, and once read it is put right onto the stack. When dumping from the stack, simply print &amp;quot;undefined&amp;quot;/0 and continue.&lt;br /&gt;
==== OP_GetByte &amp;amp; OP_GetNegByte ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 1 byte. These are 2 byte opcode in that the first byte is the opcode and the second byte is an unsigned value. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegByte should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetUnsignedShort &amp;amp; OP_GetNegUnsignedShort ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 2 byte. After reading the opcode, the following is used to determine the offset of the unsigned short value&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the unsigned short value to use. Then skip another 2 bytes for that value to continue reading. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegUnsignedShort should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetInteger &amp;amp; OP_GetFloat ====&lt;br /&gt;
OP_GetInteger is used for any numbers that are large enough to warrant a signed integer, while OP_GetFloat is used for bigger numbers and decimals. After reading the opcode, the following is used to determine the offset of the value to get&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the value to get, then skip another 4 bytes past the value to continue reading. The opcode is then added to the stack. When dumping the value is simply printed and then continued;&lt;br /&gt;
==== OP_GetString &amp;amp; OP_GetIString ====&lt;br /&gt;
These are very clearly used to reference strings in code. Strings are found by their references. To get the offset of the reference use the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the argument section should be an argument with a reference that is equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. The name of the argument is the offset of the string to use in the string pool from the beginning of the GSC. Add another 2 to currentFunctionDataOffset to skip past the reference to continue reading. Keep in mind that OP_GetIString is used to get localized strings, and a &amp;amp; should be a added before the quotes.&lt;br /&gt;
==== OP_GetLevelObject &amp;amp; OP_GetLevel &amp;amp; OP_GetSelf &amp;amp; OP_GetSelfObject &amp;amp; OP_GetGame &amp;amp; OP_GetGameRef &amp;amp; OP_GetAnimObject ====&lt;br /&gt;
All of these are simple 1 byte opcodes that are added to the stack once they are read. They represent (and should be printed as) the &amp;quot;game&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;anim&amp;quot; and &amp;quot;self&amp;quot; objects in GSC code.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetAnimation ====&lt;br /&gt;
These are used to reference animations in an animtree that was included to this GSC. The name of the animation is found by a reference. To get the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should be an animtree in the animtree include section that has an animation with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. Add another 4 bytes to skip past the reference to continue reading opcodes. After this is read it is added to the stack. When dumping the reference animation name should be found and dumped (without quotes) preceeded by a % sign.&lt;br /&gt;
==== OP_GetFunction ====&lt;br /&gt;
This is used to reference a function without calling it. This allows you to set a variable to a function, and then call the variable later. There should be a function call with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;, and this is the function to use. This is then added to the stack. After that the following code is performed&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to continue reading. When dumping the function name should be printed after &amp;quot;::&amp;quot;.&lt;br /&gt;
==== OP_CreateLocalVariable ====&lt;br /&gt;
This opcode is used at the beginning of any function with arguments or local variables to define them. After the opcode is a single byte that is the number to define. Each variable argument is found by getting the reference for it in the argument section. To get the offset of each reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
That gets ran before to find a reference offset. There should be a argument with a reference equal to the &amp;quot;currentFunctionDataOffset&amp;quot;. Then 2 is added to skip past the current reference before the above is started again. The function declaration states the number of arguments, any extra are local variables. Keep in mind the stack should be clear after this is ran.&lt;br /&gt;
==== OP_EvalLocalVariableCached1 &amp;amp; OP_EvalLocalVariableRefCached ====&lt;br /&gt;
This is a simple 2 byte opcode used to reference an argument or local variable. The second byte is the index of the local variable to use, defined by OP_CreateLocalVariable. This is then added to the stack to be dumped. To dump the local variable must be looked up, the argument found and the name referenced.&lt;br /&gt;
==== OP_EvalArray &amp;amp; OP_EvalArrayRef ====&lt;br /&gt;
These are simple 1 byte opcodes used to reference elements in an array. It is simply added to the stack to be dumped. When dumping, the next entity on the stack is the array to use and the next entity is the index in the array (Indexes are not always numbers).&lt;br /&gt;
==== OP_ClearArray ====&lt;br /&gt;
This is a 1 byte opcode used to set an array element to &amp;quot;undefined&amp;quot;. This is not added to the stack, instead the stack is processed. The first entity on the stack is the array to use and the second is the array index. This element is then set to undefined. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_EmptyArray ====&lt;br /&gt;
This is a simple 1 byte opcode used to denote an empty array (&amp;quot;[]&amp;quot;). It is added right to the stack and simply printed when dumping. &lt;br /&gt;
==== OP_EvalFieldVariable &amp;amp; OP_EvalFieldVariableRef ====&lt;br /&gt;
These opcodes are used to reference any field variable. The names of the field variable is found by the offset of a reference. To find the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. The opcode is then added to the stack to be dumped later. The next entity on the stack is the item the field variable is for. &lt;br /&gt;
==== OP_ClearFieldVariable ====&lt;br /&gt;
This opcode is used to set a field variable element to &amp;quot;undefined&amp;quot;. The name of the field variable is found by the offset of a reference. To find the offset of a reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. This opcode is not added to the stack, instead the stack is processed. The only entity on the stack should be the item the field variable is for. Once this is processed the stack should be empty. &lt;br /&gt;
==== OP_checkclearparams &amp;amp; OP_clearparams ====&lt;br /&gt;
Used at the beginning of a function with no arguments. Clears the stack without processing it. &lt;br /&gt;
==== OP_SetVariableField ====&lt;br /&gt;
This is a 1 byte opcode used to set an entity to anything else. This is not added to the stack, instead the stack is processed. The first entity on the stack is the entity to set (left side of the &amp;quot;=&amp;quot; sign) with the second being the entity setting with (right side). At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_CallBuiltin ====&lt;br /&gt;
This opcode is used to call a GSC function that is predefined in the executable. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, there should be an entity on the stack for each expected argument. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_ScriptMethodCall ====&lt;br /&gt;
This opcode is used to call a GSC function on an entity that is defined in another GSC. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, the first entity on the stack will be the entity the function is being called upon, followed by an entity for each argument in the function. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_wait ====&lt;br /&gt;
This is a simple 1 byte opcode used for the &amp;quot;wait()&amp;quot; function. This is not added to the stack, instead the stack is processed. The first (and only) entity on the stack should be the number of milliseconds to wait. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_waittillframeend ====&lt;br /&gt;
This is a simple 1 byte opcode used for &amp;quot;waittillframeend&amp;quot;. This is not added to the stack, and is always ran with an empty stack.&lt;br /&gt;
==== OP_PreScriptCall ====&lt;br /&gt;
This is a simple 1 byte opcode used before all instructions and is equivalent to NOP.&lt;br /&gt;
==== OP_Script Call Functions ====&lt;br /&gt;
These opcodes are used to call a function and are very similar. The names of the function to call are found by a reference, and for all of these opcodes the reference is the offset of the opcode. &amp;quot;Method&amp;quot; opcodes have an extra entity on the stack as the entity the function is called upon. &amp;quot;Thread&amp;quot; opcodes are threading the function they call. The &amp;quot;Pointer&amp;quot; opcodes do not have a reference with the function&#039;s name, instead the function is a variable and an extra entity is on the stack. There will be an entity on the stack for each expected argument. To read past OP_ScriptFunctionCall, OP_ScriptMethodCall, OP_ScriptMethodCall2, and OP_ScriptMethodThreadCall, do&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &amp;quot;Pointer&amp;quot; opcodes are all 2 byte opcdes. All these opcodes are added to the stack to be dumped. &lt;br /&gt;
==== OP_clearparams ====&lt;br /&gt;
This is a 1 byte opcode and is used most often to process the stack. The stack is simply processed and should be clear by the end of this running.&lt;br /&gt;
==== OP_CastFieldObject ====&lt;br /&gt;
Not very well understood, skipping it seems to work fine.&lt;br /&gt;
==== OP_BoolNot ====&lt;br /&gt;
This is a simple 1 byte opcode used for the logical NOT operator (&amp;quot;!&amp;quot;). This is simply added to the stack to be dumped. When dumping, the next entity on the stack is the value to invert. &lt;br /&gt;
==== OP_jump Codes ====&lt;br /&gt;
Rather than have logical AND and OR operators in this language, it is similar to PPC in that there are &amp;quot;branches&amp;quot; or &amp;quot;jumps&amp;quot;. Rather than using an AND operator, a series of conditional jumps are used to produce the same result. OP_jump is a simple absolute jump value. After reading the opcode,&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will point to a &amp;quot;short&amp;quot; data value. This will be an offset in the GSC to jump to (Usually just a few bytes away). Skip another 2 bytes past this offset to continue reading opcodes. This opcode is then added to the stack to be dumped. The next entity in the stack is the condition to jump on.&lt;br /&gt;
==== Logical and Bitwise Operators ====&lt;br /&gt;
OP_inc &amp;amp; OP_dec are skipped by performing this operation&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
currentFunctionDataOffset += 2;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
They are added to the stack to be dumped. When dumping, the next member of the stack is the entity to shift, followed by &amp;quot;++&amp;quot; for increase and &amp;quot;--&amp;quot; for decrease.&lt;br /&gt;
&lt;br /&gt;
The next few operators are all 1 byte operators. They are simply added to the stack to be dumped. When dumping, the next entity on the stack is the right side of the operator with the nxt entity being the left side.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;opcode&#039;&#039;&#039;||&#039;&#039;&#039;Operator&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_or||&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_and||&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|OP_equality||==&lt;br /&gt;
|-&lt;br /&gt;
|OP_inequality||!=&lt;br /&gt;
|-&lt;br /&gt;
|OP_less||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_less_equal||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater_equal||&amp;gt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_plus||+&lt;br /&gt;
|-&lt;br /&gt;
|OP_minus||-&lt;br /&gt;
|-&lt;br /&gt;
|OP_multiply||*&lt;br /&gt;
|-&lt;br /&gt;
|OP_divide||/&lt;br /&gt;
|-&lt;br /&gt;
|OP_mod||%&lt;br /&gt;
|}&lt;br /&gt;
==== OP_size ====&lt;br /&gt;
This opcode is used to get the &amp;quot;.size&amp;quot; of an array entity. Simply added to the stack for dumping, the next stack entity is the array entity. &lt;br /&gt;
==== OP_waittillmatch &amp;amp; OP_waittill &amp;amp; OP_notify ====&lt;br /&gt;
These 1 byte opcodes codes are used in combination with OP_endon for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity the function is being referenced to. The constant strings are next on the stack and should be the only remaining items on the stack. Following these opcodes are a OP_SafeSetWaittillVariableFieldCached for each variable to pass (Used to pass data at the point of the sync). This is a 2 byte opcode, with the second byte being the index of the local variable defined at the beginning of the function. &lt;br /&gt;
==== OP_endon ====&lt;br /&gt;
This 1 byte opcode is used in combination with the above codes for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity this function is being referenced to. The constant strings to end on are then placed on the stack.&lt;br /&gt;
==== OP_voidCodepos ====&lt;br /&gt;
Equivelent to NOP.&lt;br /&gt;
==== OP_switch &amp;amp; OP_endswitch ====&lt;br /&gt;
When a switch is used by the game, only the needed case is ran at a time. However when dumping, all cases must be processed. There are a few points of interest when using the switch, the first is found by doing&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; is a partial pointer to an integer, the case definition location (The switch case code is directly after this integer, with the case definitions directly after that). After setting &amp;quot;currentFunctionDataOffset&amp;quot; to this integer, perform this to get to the actual case definitions&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 7;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Currently &amp;quot;currentFunctionDataOffset&amp;quot; will point to directly after the switch case code. The first integer is the switch case count. Following this is 8 bytes for each case in the switch. The first short in these 8 bytes is the &amp;quot;switch case type&amp;quot;. There are currently 2 known switch types, integer (0x80) and string (0). If the type is integer then the short after the type is the index for this case. If the type is a string, then there will be an argument in the argument section with the offset of the short after the type. The 4 bytes after these 2 shorts is the offset for the section of code for this case. If the type is 0 and the short for the reference is 0, then this is the &amp;quot;default&amp;quot; case. The OP_endswitch is found at the end of the section of code for this switch, just before the case defintions. It is a 1 byte opcode, and after reading this the switch should be ended and the case defintions skipped. &lt;br /&gt;
==== OP_vector ====&lt;br /&gt;
This is a simple 1 byte opcode. Vectors are a standard l-type in GSC and simply defined in raw text by doing (number1, number2, number3). Once this opcode is read it is added to the stack to be dumped. When dumping there must be at least 3 more entities on the stack, one for each item in the vector. &lt;br /&gt;
==== OP_GetHash ====&lt;br /&gt;
This opcode is used to reference dvar entities in GSC. In GSC when referencing a dvar it appears as #&amp;quot;dvarName&amp;quot;. Rather than storing the dvarName directly, the hash is stored and any dvar with a matching hash is used. To get the hash, perform&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will point to an integer that is the dvar&#039;s hash. This is then added to the stack to be dumped. To continue reading opcodes, skip another 4 bytes past the hash.&lt;br /&gt;
&lt;br /&gt;
The hash they used is DJB2 Hash algorithm. This is the implementation:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
unsigned int DvarHash(const char* dvar) {&lt;br /&gt;
    unsigned int hash = 5381;&lt;br /&gt;
&lt;br /&gt;
    while (*str != 0)&lt;br /&gt;
	hash = (33 * hash) + tolower(*str++);&lt;br /&gt;
&lt;br /&gt;
    return hash;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== OP_GetSimpleVector ====&lt;br /&gt;
This 2 byte opcode is used to store very simple vectors. The second byte in the opcode is the flags for the vector elements. Each element in the vector is 0 by default. The first element is &amp;quot;-1&amp;quot; if the bitflag 0x10 is set, and &amp;quot;1&amp;quot; if 0x20 is set. The second element is &amp;quot;-1&amp;quot; if the bitflag 4 is set, and &amp;quot;1&amp;quot; if 8 is set. The third element is &amp;quot;-1&amp;quot; if the bitflag 1 is set, and &amp;quot;1&amp;quot; if 2 is set.&lt;br /&gt;
&lt;br /&gt;
==== OP_isdefined ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;isDefined()&amp;quot; function. The next entity on the stack is the entity to check for existence.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorscale ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vector_scale()&amp;quot; function. The next entity on the stack is the vector entity to scale. The following entity is the scaler entity.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoup ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToUp()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoright ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToRight()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoforward ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToForward()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_angleclamp180 ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;angleClamp180()&amp;quot; function. The next entity on the stack is the angle to clamp.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorstoangle ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vectorsToAngle()&amp;quot; function. The next entity on the stack is the vector to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_abs ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;abs()&amp;quot; or &amp;quot;absolute value&amp;quot; function. The next entity on the stack is the integer to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_gettime ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getTime()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvar ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvar()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarint ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarInt()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarfloat ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarFloat()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarred ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarRed()&amp;quot; function to grab the red component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvargreen ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarGreen()&amp;quot; function to grab the green component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarblue ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarBlue()&amp;quot; function to grab the blue component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetFirstArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getFirstArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetNextArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getNextArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_skipdev ==== &lt;br /&gt;
This opcode is used to denote developer code sections. These sections are outlined by &amp;quot;/#&amp;quot; and &amp;quot;#/&amp;quot; in raw text and are only ran when the dvars &amp;quot;developer&amp;quot; and &amp;quot;developer_script&amp;quot; are set to true. The section starts at this opcode, and the end is defined at&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point there is a short value that holds the length of this code section at which point the end marker will be.&lt;br /&gt;
&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format for GSCs is very well known. Simply a code file (text) with a .gsc extension.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=634</id>
		<title>ScriptParseTree Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=634"/>
		<updated>2014-12-20T19:11:48Z</updated>

		<summary type="html">&lt;p&gt;Kokole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The ScriptParseTree asset is a new asset in Black Ops 2 and this is the only Call of Duty game it has appeared in so far. This is Treyarch&#039;s answer to GSCs (Keep in mind that on Black Ops 1 GSCs were still [[:Rawfile Asset|rawfiles]]). Compared to IW&#039;s equivalent scriptfile asset, the ScriptParseTree has proven to give slightly more information and thus are easier to reverse. The basic structure is identical to the rawfiles&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct ScriptParseTree&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  int len;&lt;br /&gt;
  char *buffer;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Simply an uncompressed buffer holding the GSC data. The binary data is then passed to the GSC Virtual Machine (VM) to be ran. Now for the header of the binary data&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#define GSCMagic = 0x804753430D0A0006&lt;br /&gt;
&lt;br /&gt;
struct GSC_IMPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 name_space;&lt;br /&gt;
  unsigned __int16 num_address;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_ANIMNODE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_STRINGTABLE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 string;&lt;br /&gt;
  char num_address;&lt;br /&gt;
  char type;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_ANIMTREE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 num_tree_address;&lt;br /&gt;
  unsigned __int16 num_node_address;&lt;br /&gt;
  char pad[2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_PROFILE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_EXPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int checksum;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_FIXUP_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_OBJ&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  unsigned int source_crc;&lt;br /&gt;
  unsigned int include_offset;&lt;br /&gt;
  unsigned int animtree_offset;&lt;br /&gt;
  unsigned int cseg_offset;&lt;br /&gt;
  unsigned int stringtablefixup_offset;&lt;br /&gt;
  unsigned int exports_offset;&lt;br /&gt;
  unsigned int imports_offset;&lt;br /&gt;
  unsigned int fixup_offset;&lt;br /&gt;
  unsigned int profile_offset;&lt;br /&gt;
  unsigned int cseg_size;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 stringtablefixup_count;&lt;br /&gt;
  unsigned __int16 exports_count;&lt;br /&gt;
  unsigned __int16 imports_count;&lt;br /&gt;
  unsigned __int16 fixup_count;&lt;br /&gt;
  unsigned __int16 profile_count;&lt;br /&gt;
  char include_count;&lt;br /&gt;
  char animtree_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Following the header is a section of null terminated strings (undetermined size/count). This section is also padded at the end to a 4-byte buffer. The following sections will reference back to this section when a string is used. Keep in mind that the offsets are simply just an offset in the buffer.&lt;br /&gt;
=== Include Section ===&lt;br /&gt;
The first known section after the string table is the include section, and this should be the first section dumped as well. This section is used to replace the following in a raw gsc&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include maps\mp\_utility;&lt;br /&gt;
#include common_scripts\utility;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The include section is probably the easiest section to reverse. Each include exists as a single integer which holds the offset of the include&#039;s string in the buffer. &lt;br /&gt;
=== Using Animtree Section ===&lt;br /&gt;
Although this section doesn&#039;t follow the include section, it is what needs to be dumped second. When a GSC wants to directly access and animtree, then the following code is added (for animtree &amp;quot;mp_vehicles&amp;quot;)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#using_animtree( &amp;quot;mp_vehicles&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then animations can be accessed from the tree as follows (Using the %)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
destructible_anims[ &amp;quot;car&amp;quot; ] = %veh_car_destroy;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Knowing this, the binary data section can be reversed fairly easily. The structure for their definitions in this section is&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Reference&lt;br /&gt;
{&lt;br /&gt;
  unsigned short name;&lt;br /&gt;
  unsigned short xrefOffset;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct AnimTree&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned short pathOffset; //Paths do not exist for animtrees (so far)&lt;br /&gt;
	unsigned short referenceCount;&lt;br /&gt;
	Reference references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
XRefs are explained in better detail in the code section. Each animtree thats included will have an AnimTree struct, and every time an animation is used it will be defined in the references.&lt;br /&gt;
=== Argument Section ===&lt;br /&gt;
The argument section not only defines any function arguments that are defined with function declarations, but any local variable a function might create. Although they are defined the same, the difference between the two is highlighted in the code section. Each argument will be defined as follows&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Argument&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned char referenceCount;&lt;br /&gt;
	signed char unknown;&lt;br /&gt;
	unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The references will explained in more detail in the code section.&lt;br /&gt;
&lt;br /&gt;
=== Function Call Section ===&lt;br /&gt;
If a function is called by a function in this GSC, it must be defined here in the function call section, even if that function is located inside this GSC. First the struct&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionCall&lt;br /&gt;
{&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  unsigned short pathOffset;&lt;br /&gt;
  unsigned short referenceCount;&lt;br /&gt;
  byte paramCount;&lt;br /&gt;
  byte flag;&lt;br /&gt;
  unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
NameOffset obviously holds the name of the called function. References are explained in the code section. If the function is not located in this GSC or in a &amp;quot;using&amp;quot; GSC, then the function must have a path with the name of the GSC that it is defined in, and this is where the pathOffset points to. eg&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
thread maps\mp\gametypes\_spawning::init();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Function Declaration Section ===&lt;br /&gt;
This is the section that will be cycled through when dumping the GSC. Every function that is defined in this GSC is here. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionDeclaration&lt;br /&gt;
{&lt;br /&gt;
  int crc32;&lt;br /&gt;
  unsigned int executionDataOffset;&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  byte unknown2;&lt;br /&gt;
  byte argumentCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The executionDataOffset is an offset in the code section defining where this function begins.&lt;br /&gt;
&lt;br /&gt;
=== Executable Data ===&lt;br /&gt;
This section is by far the trickiest section. This is where the actual code the functions are compiled into is stored. The first thing that will be needed is a list of operation codes (OPcodes). These opcodes should be the same for all systems.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum OPCodes : char&lt;br /&gt;
{&lt;br /&gt;
         OP_End = 0x0,&lt;br /&gt;
         OP_Return = 0x1,&lt;br /&gt;
         OP_GetUndefined = 0x2,&lt;br /&gt;
         OP_GetZero = 0x3,&lt;br /&gt;
         OP_GetByte = 0x4,&lt;br /&gt;
         OP_GetNegByte = 0x5,&lt;br /&gt;
         OP_GetUnsignedShort = 0x6,&lt;br /&gt;
         OP_GetNegUnsignedShort = 0x7,&lt;br /&gt;
         OP_GetInteger = 0x8,&lt;br /&gt;
         OP_GetFloat = 0x9,&lt;br /&gt;
         OP_GetString = 0xA,&lt;br /&gt;
         OP_GetIString = 0xB,&lt;br /&gt;
         OP_GetVector = 0xC,&lt;br /&gt;
         OP_GetLevelObject = 0xD,&lt;br /&gt;
         OP_GetAnimObject = 0xE,&lt;br /&gt;
         OP_GetSelf = 0xF,&lt;br /&gt;
         OP_GetLevel = 0x10,&lt;br /&gt;
         OP_GetGame = 0x11,&lt;br /&gt;
         OP_GetAnim = 0x12,&lt;br /&gt;
         OP_GetAnimation = 0x13,&lt;br /&gt;
         OP_GetGameRef = 0x14,&lt;br /&gt;
         OP_GetFunction = 0x15,&lt;br /&gt;
         OP_CreateLocalVariables = 0x17,&lt;br /&gt;
         OP_EvalLocalVariableCached1 = 0x19,&lt;br /&gt;
         OP_EvalArray = 0x1A,&lt;br /&gt;
         OP_EvalArrayRef = 0x1C,&lt;br /&gt;
         OP_ClearArray = 0x1D,&lt;br /&gt;
         OP_EmptyArray = 0x1E,&lt;br /&gt;
         OP_GetSelfObject = 0x1F,&lt;br /&gt;
         OP_EvalFieldVariable = 0x20,&lt;br /&gt;
         OP_EvalFieldVariableRef = 0x21,&lt;br /&gt;
         OP_ClearFieldVariable = 0x22,&lt;br /&gt;
         OP_SafeSetWaittillVariableFieldCached = 0x24,&lt;br /&gt;
         OP_clearparams = 0x25,&lt;br /&gt;
         OP_checkclearparams = 0x26,&lt;br /&gt;
         OP_EvalLocalVariableRefCached = 0x27,&lt;br /&gt;
         OP_SetVariableField = 0x28,&lt;br /&gt;
         OP_wait = 0x2B,&lt;br /&gt;
         OP_waittillFrameEnd = 0x2C,&lt;br /&gt;
         OP_PreScriptCall = 0x2D,&lt;br /&gt;
         OP_ScriptFunctionCall = 0x2E,&lt;br /&gt;
         OP_ScriptFunctionCallPointer = 0x2F,&lt;br /&gt;
         OP_ScriptMethodCall = 0x30,&lt;br /&gt;
         OP_ScriptMethodCallPointer = 0x31,&lt;br /&gt;
         OP_ScriptThreadCall = 0x32,&lt;br /&gt;
         OP_ScriptThreadCallPointer = 0x33,&lt;br /&gt;
         OP_ScriptMethodThreadCall = 0x34,&lt;br /&gt;
         OP_ScriptMethodThreadCallPointer = 0x35,&lt;br /&gt;
         OP_DecTop = 0x36,&lt;br /&gt;
         OP_CastFieldObject = 0x37,&lt;br /&gt;
         OP_CastBool = 0x38,&lt;br /&gt;
         OP_BoolNot = 0x39,&lt;br /&gt;
         OP_BoolComplement = 0x3A,&lt;br /&gt;
         OP_JumpOnFalse = 0x3B,&lt;br /&gt;
         OP_JumpOnTrue = 0x3C,&lt;br /&gt;
         OP_JumpOnFalseExpr = 0x3D,&lt;br /&gt;
         OP_JumpOnTrueExpr = 0x3E,&lt;br /&gt;
         OP_jump = 0x3F,&lt;br /&gt;
         OP_jumpback = 0x40,&lt;br /&gt;
         OP_inc = 0x41,&lt;br /&gt;
         OP_dec = 0x42,&lt;br /&gt;
         OP_bit_or = 0x43,&lt;br /&gt;
         OP_bit_ex_or = 0x44,&lt;br /&gt;
         OP_bit_and = 0x45,&lt;br /&gt;
         OP_equality = 0x46,&lt;br /&gt;
         OP_inequality = 0x47,&lt;br /&gt;
         OP_less = 0x48,&lt;br /&gt;
         OP_greater = 0x49,&lt;br /&gt;
         OP_less_equal = 0x4A,&lt;br /&gt;
         OP_greater_equal = 0x4B,&lt;br /&gt;
         OP_shift_left = 0x4C,&lt;br /&gt;
         OP_shift_right = 0x4D,&lt;br /&gt;
         OP_plus = 0x4E,&lt;br /&gt;
         OP_minus = 0x4F,&lt;br /&gt;
         OP_multiply = 0x50,&lt;br /&gt;
         OP_divide = 0x51,&lt;br /&gt;
         OP_mod = 0x52,&lt;br /&gt;
         OP_size = 0x53,&lt;br /&gt;
         OP_waittillmatch = 0x54,&lt;br /&gt;
         OP_waittill = 0x55,&lt;br /&gt;
         OP_notify = 0x56,&lt;br /&gt;
         OP_endon = 0x57,&lt;br /&gt;
         OP_voidCodepos = 0x58,&lt;br /&gt;
         OP_switch = 0x59,&lt;br /&gt;
         OP_endswitch = 0x5A,&lt;br /&gt;
         OP_vector = 0x5B,&lt;br /&gt;
         OP_GetHash = 0x5C,&lt;br /&gt;
         OP_GetSimpleVector = 0x5E,&lt;br /&gt;
         OP_isdefined = 0x5F,&lt;br /&gt;
         OP_vectorscale = 0x60,&lt;br /&gt;
         OP_anglestoup = 0x61,&lt;br /&gt;
	 OP_anglestoright = 0x62,&lt;br /&gt;
	 OP_anglestoforward = 0x63,&lt;br /&gt;
	 OP_angleclamp180 = 0x64,&lt;br /&gt;
	 OP_vectorstoangle = 0x65,&lt;br /&gt;
	 OP_abs = 0x66,&lt;br /&gt;
	 OP_gettime = 0x67,&lt;br /&gt;
	 OP_getdvar = 0x68,&lt;br /&gt;
	 OP_getdvarint = 0x69,&lt;br /&gt;
	 OP_getdvarfloat = 0x6A,&lt;br /&gt;
	 OP_getdvarvec3d = 0x6B,&lt;br /&gt;
	 OP_getdvarred = 0x6C,&lt;br /&gt;
	 OP_getdvargreen = 0x6D,&lt;br /&gt;
	 OP_getdvarblue = 0x6E,&lt;br /&gt;
	 OP_GetFirstArrayKey = 0x70,&lt;br /&gt;
	 OP_GetNextArrayKey = 0x71,&lt;br /&gt;
	 OP_GetUndefined2 = 0x73,&lt;br /&gt;
	 OP_skipdev = 0x7B,&lt;br /&gt;
	 OP_count = 0x7C,&lt;br /&gt;
	 OP_NOP = 0x7F,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Notice that 0x7B is the highest opcode, but 0x7F is still valid. In truth anything over 0x7B will register as NOP. The executable does some odd jumping around for each OP code, so a recap of each OP code will try to be added. In the following functions &amp;quot;currentFunctionDataOffset&amp;quot; is defined as an integer that points to the current OP code being read. Keep in mind that an OP code is read, the data offset is increased by 1, and then the following code is ran. OP codes are parsed in the order they are read, but if a dump is being done then parts are going to be dumped in reverse order. Here is an example of a series of OP codes...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
OP_PreScriptCall&lt;br /&gt;
OP_GetString		&amp;quot;1350&amp;quot;&lt;br /&gt;
OP_GetString		&amp;quot;scr_veh_health_tank&amp;quot;&lt;br /&gt;
OP_CallBuiltin 		2, &amp;quot;setdvar&amp;quot;&lt;br /&gt;
OP_clearparams&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This would be the &amp;quot;asm&amp;quot; of the GSC, and would look like this...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
setdvar( &amp;quot;scr_veh_health_tank&amp;quot;, &amp;quot;1350&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== OP_End ====&lt;br /&gt;
If FunctionDeclaration-&amp;gt;crc32 equals to returned crc then break. This is how you calculate the CRC32 below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
static const unsigned int kCrc32Table[] = {&lt;br /&gt;
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,&lt;br /&gt;
	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,&lt;br /&gt;
	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,&lt;br /&gt;
	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,&lt;br /&gt;
	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,&lt;br /&gt;
	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,&lt;br /&gt;
	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,&lt;br /&gt;
	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,&lt;br /&gt;
	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,&lt;br /&gt;
	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,&lt;br /&gt;
	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,&lt;br /&gt;
	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,&lt;br /&gt;
	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,&lt;br /&gt;
	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,&lt;br /&gt;
	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,&lt;br /&gt;
	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,&lt;br /&gt;
	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,&lt;br /&gt;
	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,&lt;br /&gt;
	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,&lt;br /&gt;
	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,&lt;br /&gt;
	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,&lt;br /&gt;
	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,&lt;br /&gt;
	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,&lt;br /&gt;
	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,&lt;br /&gt;
	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,&lt;br /&gt;
	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,&lt;br /&gt;
	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,&lt;br /&gt;
	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,&lt;br /&gt;
	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,&lt;br /&gt;
	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,&lt;br /&gt;
	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,&lt;br /&gt;
	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,&lt;br /&gt;
	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,&lt;br /&gt;
	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,&lt;br /&gt;
	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,&lt;br /&gt;
	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,&lt;br /&gt;
	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,&lt;br /&gt;
	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,&lt;br /&gt;
	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,&lt;br /&gt;
	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,&lt;br /&gt;
	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,&lt;br /&gt;
	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,&lt;br /&gt;
	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
unsigned int crc(unsigned char* pData, unsigned int length) {&lt;br /&gt;
unsigned char* pCur = (unsigned char*)pData;&lt;br /&gt;
unsigned int remaining = length, _crc = ~0;&lt;br /&gt;
&lt;br /&gt;
for (; remaining--; ++pCur)&lt;br /&gt;
 _crc = (_crc &amp;gt;&amp;gt; 8) ^ kCrc32Table[(_crc ^ *pCur) &amp;amp; 0xff];&lt;br /&gt;
&lt;br /&gt;
return ~_crc;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For the CRC32 checksum parameters it&#039;s unsigned int crc(functionStart, currentFunctionDataOffset - functionStart). If the returned crc does not equal FunctionDeclaration-&amp;gt;crc32 then write &amp;quot;return;&amp;quot; to the stack.&lt;br /&gt;
&lt;br /&gt;
==== OP_Return ====&lt;br /&gt;
The return OP is exactly as expected. Any OP codes in the stack go after a &amp;quot;return&amp;quot;. There is no data skipped, it is simply a 1 byte opcode. Keep in mind that if the game reaches a return, it leaves the function however for a complete dump, data must continue to be read and sometimes this data is unnecessary.&lt;br /&gt;
==== OP_GetUndefined &amp;amp; OP_GetZero ====&lt;br /&gt;
This simply represents the &amp;quot;undefined&amp;quot;/0 element in GSCs. It is a simple 1 byte opcode, and once read it is put right onto the stack. When dumping from the stack, simply print &amp;quot;undefined&amp;quot;/0 and continue.&lt;br /&gt;
==== OP_GetByte &amp;amp; OP_GetNegByte ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 1 byte. These are 2 byte opcode in that the first byte is the opcode and the second byte is an unsigned value. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegByte should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetUnsignedShort &amp;amp; OP_GetNegUnsignedShort ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 2 byte. After reading the opcode, the following is used to determine the offset of the unsigned short value&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the unsigned short value to use. Then skip another 2 bytes for that value to continue reading. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegUnsignedShort should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetInteger &amp;amp; OP_GetFloat ====&lt;br /&gt;
OP_GetInteger is used for any numbers that are large enough to warrant a signed integer, while OP_GetFloat is used for bigger numbers and decimals. After reading the opcode, the following is used to determine the offset of the value to get&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the value to get, then skip another 4 bytes past the value to continue reading. The opcode is then added to the stack. When dumping the value is simply printed and then continued;&lt;br /&gt;
==== OP_GetString &amp;amp; OP_GetIString ====&lt;br /&gt;
These are very clearly used to reference strings in code. Strings are found by their references. To get the offset of the reference use the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the argument section should be an argument with a reference that is equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. The name of the argument is the offset of the string to use in the string pool from the beginning of the GSC. Add another 2 to currentFunctionDataOffset to skip past the reference to continue reading. Keep in mind that OP_GetIString is used to get localized strings, and a &amp;amp; should be a added before the quotes.&lt;br /&gt;
==== OP_GetLevelObject &amp;amp; OP_GetLevel &amp;amp; OP_GetSelf &amp;amp; OP_GetSelfObject &amp;amp; OP_GetGame &amp;amp; OP_GetGameRef &amp;amp; OP_GetAnimObject ====&lt;br /&gt;
All of these are simple 1 byte opcodes that are added to the stack once they are read. They represent (and should be printed as) the &amp;quot;game&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;anim&amp;quot; and &amp;quot;self&amp;quot; objects in GSC code.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetAnimation ====&lt;br /&gt;
These are used to reference animations in an animtree that was included to this GSC. The name of the animation is found by a reference. To get the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should be an animtree in the animtree include section that has an animation with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. Add another 4 bytes to skip past the reference to continue reading opcodes. After this is read it is added to the stack. When dumping the reference animation name should be found and dumped (without quotes) preceeded by a % sign.&lt;br /&gt;
==== OP_GetFunction ====&lt;br /&gt;
This is used to reference a function without calling it. This allows you to set a variable to a function, and then call the variable later. There should be a function call with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;, and this is the function to use. This is then added to the stack. After that the following code is performed&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to continue reading. When dumping the function name should be printed after &amp;quot;::&amp;quot;.&lt;br /&gt;
==== OP_CreateLocalVariable ====&lt;br /&gt;
This opcode is used at the beginning of any function with arguments or local variables to define them. After the opcode is a single byte that is the number to define. Each variable argument is found by getting the reference for it in the argument section. To get the offset of each reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
That gets ran before to find a reference offset. There should be a argument with a reference equal to the &amp;quot;currentFunctionDataOffset&amp;quot;. Then 2 is added to skip past the current reference before the above is started again. The function declaration states the number of arguments, any extra are local variables. Keep in mind the stack should be clear after this is ran.&lt;br /&gt;
==== OP_EvalLocalVariableCached1 &amp;amp; OP_EvalLocalVariableRefCached ====&lt;br /&gt;
This is a simple 2 byte opcode used to reference an argument or local variable. The second byte is the index of the local variable to use, defined by OP_CreateLocalVariable. This is then added to the stack to be dumped. To dump the local variable must be looked up, the argument found and the name referenced.&lt;br /&gt;
==== OP_EvalArray &amp;amp; OP_EvalArrayRef ====&lt;br /&gt;
These are simple 1 byte opcodes used to reference elements in an array. It is simply added to the stack to be dumped. When dumping, the next entity on the stack is the array to use and the next entity is the index in the array (Indexes are not always numbers).&lt;br /&gt;
==== OP_ClearArray ====&lt;br /&gt;
This is a 1 byte opcode used to set an array element to &amp;quot;undefined&amp;quot;. This is not added to the stack, instead the stack is processed. The first entity on the stack is the array to use and the second is the array index. This element is then set to undefined. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_EmptyArray ====&lt;br /&gt;
This is a simple 1 byte opcode used to denote an empty array (&amp;quot;[]&amp;quot;). It is added right to the stack and simply printed when dumping. &lt;br /&gt;
==== OP_EvalFieldVariable &amp;amp; OP_EvalFieldVariableRef ====&lt;br /&gt;
These opcodes are used to reference any field variable. The names of the field variable is found by the offset of a reference. To find the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. The opcode is then added to the stack to be dumped later. The next entity on the stack is the item the field variable is for. &lt;br /&gt;
==== OP_ClearFieldVariable ====&lt;br /&gt;
This opcode is used to set a field variable element to &amp;quot;undefined&amp;quot;. The name of the field variable is found by the offset of a reference. To find the offset of a reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. This opcode is not added to the stack, instead the stack is processed. The only entity on the stack should be the item the field variable is for. Once this is processed the stack should be empty. &lt;br /&gt;
==== OP_checkclearparams &amp;amp; OP_clearparams ====&lt;br /&gt;
Used at the beginning of a function with no arguments. Clears the stack without processing it. &lt;br /&gt;
==== OP_SetVariableField ====&lt;br /&gt;
This is a 1 byte opcode used to set an entity to anything else. This is not added to the stack, instead the stack is processed. The first entity on the stack is the entity to set (left side of the &amp;quot;=&amp;quot; sign) with the second being the entity setting with (right side). At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_CallBuiltin ====&lt;br /&gt;
This opcode is used to call a GSC function that is predefined in the executable. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, there should be an entity on the stack for each expected argument. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_ScriptMethodCall ====&lt;br /&gt;
This opcode is used to call a GSC function on an entity that is defined in another GSC. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, the first entity on the stack will be the entity the function is being called upon, followed by an entity for each argument in the function. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_wait ====&lt;br /&gt;
This is a simple 1 byte opcode used for the &amp;quot;wait()&amp;quot; function. This is not added to the stack, instead the stack is processed. The first (and only) entity on the stack should be the number of milliseconds to wait. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_waittillframeend ====&lt;br /&gt;
This is a simple 1 byte opcode used for &amp;quot;waittillframeend&amp;quot;. This is not added to the stack, and is always ran with an empty stack.&lt;br /&gt;
==== OP_PreScriptCall ====&lt;br /&gt;
This is a simple 1 byte opcode used before all instructions and is equivalent to NOP.&lt;br /&gt;
==== OP_Script Call Functions ====&lt;br /&gt;
These opcodes are used to call a function and are very similar. The names of the function to call are found by a reference, and for all of these opcodes the reference is the offset of the opcode. &amp;quot;Method&amp;quot; opcodes have an extra entity on the stack as the entity the function is called upon. &amp;quot;Thread&amp;quot; opcodes are threading the function they call. The &amp;quot;Pointer&amp;quot; opcodes do not have a reference with the function&#039;s name, instead the function is a variable and an extra entity is on the stack. There will be an entity on the stack for each expected argument. To read past OP_ScriptFunctionCall, OP_ScriptMethodCall, OP_ScriptMethodCall2, and OP_ScriptMethodThreadCall, do&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &amp;quot;Pointer&amp;quot; opcodes are all 2 byte opcdes. All these opcodes are added to the stack to be dumped. &lt;br /&gt;
==== OP_clearparams ====&lt;br /&gt;
This is a 1 byte opcode and is used most often to process the stack. The stack is simply processed and should be clear by the end of this running.&lt;br /&gt;
==== OP_CastFieldObject ====&lt;br /&gt;
Not very well understood, skipping it seems to work fine.&lt;br /&gt;
==== OP_BoolNot ====&lt;br /&gt;
This is a simple 1 byte opcode used for the logical NOT operator (&amp;quot;!&amp;quot;). This is simply added to the stack to be dumped. When dumping, the next entity on the stack is the value to invert. &lt;br /&gt;
==== OP_jump Codes ====&lt;br /&gt;
Rather than have logical AND and OR operators in this language, it is similar to PPC in that there are &amp;quot;branches&amp;quot; or &amp;quot;jumps&amp;quot;. Rather than using an AND operator, a series of conditional jumps are used to produce the same result. OP_jump is a simple absolute jump value. After reading the opcode,&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will point to a &amp;quot;short&amp;quot; data value. This will be an offset in the GSC to jump to (Usually just a few bytes away). Skip another 2 bytes past this offset to continue reading opcodes. This opcode is then added to the stack to be dumped. The next entity in the stack is the condition to jump on.&lt;br /&gt;
==== Logical and Bitwise Operators ====&lt;br /&gt;
OP_inc &amp;amp; OP_dec are skipped by performing this operation&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
currentFunctionDataOffset += 2;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
They are added to the stack to be dumped. When dumping, the next member of the stack is the entity to shift, followed by &amp;quot;++&amp;quot; for increase and &amp;quot;--&amp;quot; for decrease.&lt;br /&gt;
&lt;br /&gt;
The next few operators are all 1 byte operators. They are simply added to the stack to be dumped. When dumping, the next entity on the stack is the right side of the operator with the nxt entity being the left side.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;opcode&#039;&#039;&#039;||&#039;&#039;&#039;Operator&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_or||&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_and||&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|OP_equality||==&lt;br /&gt;
|-&lt;br /&gt;
|OP_inequality||!=&lt;br /&gt;
|-&lt;br /&gt;
|OP_less||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_less_equal||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater_equal||&amp;gt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_plus||+&lt;br /&gt;
|-&lt;br /&gt;
|OP_minus||-&lt;br /&gt;
|-&lt;br /&gt;
|OP_multiply||*&lt;br /&gt;
|-&lt;br /&gt;
|OP_divide||/&lt;br /&gt;
|-&lt;br /&gt;
|OP_mod||%&lt;br /&gt;
|}&lt;br /&gt;
==== OP_size ====&lt;br /&gt;
This opcode is used to get the &amp;quot;.size&amp;quot; of an array entity. Simply added to the stack for dumping, the next stack entity is the array entity. &lt;br /&gt;
==== OP_waittillmatch &amp;amp; OP_waittill &amp;amp; OP_notify ====&lt;br /&gt;
These 1 byte opcodes codes are used in combination with OP_endon for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity the function is being referenced to. The constant strings are next on the stack and should be the only remaining items on the stack. Following these opcodes are a OP_SafeSetWaittillVariableFieldCached for each variable to pass (Used to pass data at the point of the sync). This is a 2 byte opcode, with the second byte being the index of the local variable defined at the beginning of the function. &lt;br /&gt;
==== OP_endon ====&lt;br /&gt;
This 1 byte opcode is used in combination with the above codes for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity this function is being referenced to. The constant strings to end on are then placed on the stack.&lt;br /&gt;
==== OP_voidCodepos ====&lt;br /&gt;
Equivelent to NOP.&lt;br /&gt;
==== OP_switch &amp;amp; OP_endswitch ====&lt;br /&gt;
When a switch is used by the game, only the needed case is ran at a time. However when dumping, all cases must be processed. There are a few points of interest when using the switch, the first is found by doing&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; is a partial pointer to an integer, the case definition location (The switch case code is directly after this integer, with the case definitions directly after that). After setting &amp;quot;currentFunctionDataOffset&amp;quot; to this integer, perform this to get to the actual case definitions&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 7;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Currently &amp;quot;currentFunctionDataOffset&amp;quot; will point to directly after the switch case code. The first integer is the switch case count. Following this is 8 bytes for each case in the switch. The first short in these 8 bytes is the &amp;quot;switch case type&amp;quot;. There are currently 2 known switch types, integer (0x80) and string (0). If the type is integer then the short after the type is the index for this case. If the type is a string, then there will be an argument in the argument section with the offset of the short after the type. The 4 bytes after these 2 shorts is the offset for the section of code for this case. If the type is 0 and the short for the reference is 0, then this is the &amp;quot;default&amp;quot; case. The OP_endswitch is found at the end of the section of code for this switch, just before the case defintions. It is a 1 byte opcode, and after reading this the switch should be ended and the case defintions skipped. &lt;br /&gt;
==== OP_vector ====&lt;br /&gt;
This is a simple 1 byte opcode. Vectors are a standard l-type in GSC and simply defined in raw text by doing (number1, number2, number3). Once this opcode is read it is added to the stack to be dumped. When dumping there must be at least 3 more entities on the stack, one for each item in the vector. &lt;br /&gt;
==== OP_GetHash ====&lt;br /&gt;
This opcode is used to reference dvar entities in GSC. In GSC when referencing a dvar it appears as #&amp;quot;dvarName&amp;quot;. Rather than storing the dvarName directly, the hash is stored and any dvar with a matching hash is used. To get the hash, perform&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will point to an integer that is the dvar&#039;s hash. This is then added to the stack to be dumped. To continue reading opcodes, skip another 4 bytes past the hash.&lt;br /&gt;
&lt;br /&gt;
The hash they used is DJB2 Hash algorithm. This is the implementation:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
unsigned int DvarHash(const char* dvar) {&lt;br /&gt;
    unsigned int hash = 5381;&lt;br /&gt;
&lt;br /&gt;
    while (*str != 0)&lt;br /&gt;
	hash = (33 * hash) + tolower(*str++);&lt;br /&gt;
&lt;br /&gt;
    return hash;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== OP_GetSimpleVector ====&lt;br /&gt;
This 2 byte opcode is used to store very simple vectors. The second byte in the opcode is the flags for the vector elements. Each element in the vector is 0 by default. The first element is &amp;quot;-1&amp;quot; if the bitflag 0x10 is set, and &amp;quot;1&amp;quot; if 0x20 is set. The second element is &amp;quot;-1&amp;quot; if the bitflag 4 is set, and &amp;quot;1&amp;quot; if 8 is set. The third element is &amp;quot;-1&amp;quot; if the bitflag 1 is set, and &amp;quot;1&amp;quot; if 2 is set.&lt;br /&gt;
&lt;br /&gt;
==== OP_isdefined ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;isDefined()&amp;quot; function. The next entity on the stack is the entity to check for existence.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorscale ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vector_scale()&amp;quot; function. The next entity on the stack is the vector entity to scale. The following entity is the scaler entity.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoup ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToUp()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoright ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToRight()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoforward ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToForward()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_angleclamp180 ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;angleClamp180()&amp;quot; function. The next entity on the stack is the angle to clamp.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorstoangle ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vectorsToAngle()&amp;quot; function. The next entity on the stack is the vector to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_abs ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;abs()&amp;quot; or &amp;quot;absolute value&amp;quot; function. The next entity on the stack is the integer to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_gettime ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getTime()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvar ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvar()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarint ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarInt()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarfloat ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarFloat()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarred ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarRed()&amp;quot; function to grab the red component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvargreen ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarGreen()&amp;quot; function to grab the green component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarblue ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarBlue()&amp;quot; function to grab the blue component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetFirstArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getFirstArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetNextArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getNextArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_skipdev ==== &lt;br /&gt;
This opcode is used to denote developer code sections. These sections are outlined by &amp;quot;/#&amp;quot; and &amp;quot;#/&amp;quot; in raw text and are only ran when the dvars &amp;quot;developer&amp;quot; and &amp;quot;developer_script&amp;quot; are set to true. The section starts at this opcode, and the end is defined at&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point there is a short value that holds the length of this code section at which point the end marker will be.&lt;br /&gt;
&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format for GSCs is very well known. Simply a code file (text) with a .gsc extension.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=633</id>
		<title>ScriptParseTree Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=633"/>
		<updated>2014-12-20T19:10:29Z</updated>

		<summary type="html">&lt;p&gt;Kokole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The ScriptParseTree asset is a new asset in Black Ops 2 and this is the only Call of Duty game it has appeared in so far. This is Treyarch&#039;s answer to GSCs (Keep in mind that on Black Ops 1 GSCs were still [[:Rawfile Asset|rawfiles]]). Compared to IW&#039;s equivalent scriptfile asset, the ScriptParseTree has proven to give slightly more information and thus are easier to reverse. The basic structure is identical to the rawfiles&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct ScriptParseTree&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  int len;&lt;br /&gt;
  const char *buffer;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Simply an uncompressed buffer holding the GSC data. The binary data is then passed to the GSC Virtual Machine (VM) to be ran. Now for the header of the binary data&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#define GSCMagic = 0x804753430D0A0006&lt;br /&gt;
&lt;br /&gt;
struct GSC_IMPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 name_space;&lt;br /&gt;
  unsigned __int16 num_address;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_ANIMNODE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_STRINGTABLE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 string;&lt;br /&gt;
  char num_address;&lt;br /&gt;
  char type;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_ANIMTREE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 num_tree_address;&lt;br /&gt;
  unsigned __int16 num_node_address;&lt;br /&gt;
  char pad[2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_PROFILE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_EXPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int checksum;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_FIXUP_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_OBJ&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  unsigned int source_crc;&lt;br /&gt;
  unsigned int include_offset;&lt;br /&gt;
  unsigned int animtree_offset;&lt;br /&gt;
  unsigned int cseg_offset;&lt;br /&gt;
  unsigned int stringtablefixup_offset;&lt;br /&gt;
  unsigned int exports_offset;&lt;br /&gt;
  unsigned int imports_offset;&lt;br /&gt;
  unsigned int fixup_offset;&lt;br /&gt;
  unsigned int profile_offset;&lt;br /&gt;
  unsigned int cseg_size;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 stringtablefixup_count;&lt;br /&gt;
  unsigned __int16 exports_count;&lt;br /&gt;
  unsigned __int16 imports_count;&lt;br /&gt;
  unsigned __int16 fixup_count;&lt;br /&gt;
  unsigned __int16 profile_count;&lt;br /&gt;
  char include_count;&lt;br /&gt;
  char animtree_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Following the header is a section of null terminated strings (undetermined size/count). This section is also padded at the end to a 4-byte buffer. The following sections will reference back to this section when a string is used. Keep in mind that the offsets are simply just an offset in the buffer.&lt;br /&gt;
=== Include Section ===&lt;br /&gt;
The first known section after the string table is the include section, and this should be the first section dumped as well. This section is used to replace the following in a raw gsc&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include maps\mp\_utility;&lt;br /&gt;
#include common_scripts\utility;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The include section is probably the easiest section to reverse. Each include exists as a single integer which holds the offset of the include&#039;s string in the buffer. &lt;br /&gt;
=== Using Animtree Section ===&lt;br /&gt;
Although this section doesn&#039;t follow the include section, it is what needs to be dumped second. When a GSC wants to directly access and animtree, then the following code is added (for animtree &amp;quot;mp_vehicles&amp;quot;)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#using_animtree( &amp;quot;mp_vehicles&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then animations can be accessed from the tree as follows (Using the %)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
destructible_anims[ &amp;quot;car&amp;quot; ] = %veh_car_destroy;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Knowing this, the binary data section can be reversed fairly easily. The structure for their definitions in this section is&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Reference&lt;br /&gt;
{&lt;br /&gt;
  unsigned short name;&lt;br /&gt;
  unsigned short xrefOffset;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct AnimTree&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned short pathOffset; //Paths do not exist for animtrees (so far)&lt;br /&gt;
	unsigned short referenceCount;&lt;br /&gt;
	Reference references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
XRefs are explained in better detail in the code section. Each animtree thats included will have an AnimTree struct, and every time an animation is used it will be defined in the references.&lt;br /&gt;
=== Argument Section ===&lt;br /&gt;
The argument section not only defines any function arguments that are defined with function declarations, but any local variable a function might create. Although they are defined the same, the difference between the two is highlighted in the code section. Each argument will be defined as follows&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Argument&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned char referenceCount;&lt;br /&gt;
	signed char unknown;&lt;br /&gt;
	unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The references will explained in more detail in the code section.&lt;br /&gt;
&lt;br /&gt;
=== Function Call Section ===&lt;br /&gt;
If a function is called by a function in this GSC, it must be defined here in the function call section, even if that function is located inside this GSC. First the struct&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionCall&lt;br /&gt;
{&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  unsigned short pathOffset;&lt;br /&gt;
  unsigned short referenceCount;&lt;br /&gt;
  byte paramCount;&lt;br /&gt;
  byte flag;&lt;br /&gt;
  unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
NameOffset obviously holds the name of the called function. References are explained in the code section. If the function is not located in this GSC or in a &amp;quot;using&amp;quot; GSC, then the function must have a path with the name of the GSC that it is defined in, and this is where the pathOffset points to. eg&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
thread maps\mp\gametypes\_spawning::init();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Function Declaration Section ===&lt;br /&gt;
This is the section that will be cycled through when dumping the GSC. Every function that is defined in this GSC is here. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionDeclaration&lt;br /&gt;
{&lt;br /&gt;
  int crc32;&lt;br /&gt;
  unsigned int executionDataOffset;&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  byte unknown2;&lt;br /&gt;
  byte argumentCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The executionDataOffset is an offset in the code section defining where this function begins.&lt;br /&gt;
&lt;br /&gt;
=== Executable Data ===&lt;br /&gt;
This section is by far the trickiest section. This is where the actual code the functions are compiled into is stored. The first thing that will be needed is a list of operation codes (OPcodes). These opcodes should be the same for all systems.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum OPCodes : char&lt;br /&gt;
{&lt;br /&gt;
         OP_End = 0x0,&lt;br /&gt;
         OP_Return = 0x1,&lt;br /&gt;
         OP_GetUndefined = 0x2,&lt;br /&gt;
         OP_GetZero = 0x3,&lt;br /&gt;
         OP_GetByte = 0x4,&lt;br /&gt;
         OP_GetNegByte = 0x5,&lt;br /&gt;
         OP_GetUnsignedShort = 0x6,&lt;br /&gt;
         OP_GetNegUnsignedShort = 0x7,&lt;br /&gt;
         OP_GetInteger = 0x8,&lt;br /&gt;
         OP_GetFloat = 0x9,&lt;br /&gt;
         OP_GetString = 0xA,&lt;br /&gt;
         OP_GetIString = 0xB,&lt;br /&gt;
         OP_GetVector = 0xC,&lt;br /&gt;
         OP_GetLevelObject = 0xD,&lt;br /&gt;
         OP_GetAnimObject = 0xE,&lt;br /&gt;
         OP_GetSelf = 0xF,&lt;br /&gt;
         OP_GetLevel = 0x10,&lt;br /&gt;
         OP_GetGame = 0x11,&lt;br /&gt;
         OP_GetAnim = 0x12,&lt;br /&gt;
         OP_GetAnimation = 0x13,&lt;br /&gt;
         OP_GetGameRef = 0x14,&lt;br /&gt;
         OP_GetFunction = 0x15,&lt;br /&gt;
         OP_CreateLocalVariables = 0x17,&lt;br /&gt;
         OP_EvalLocalVariableCached1 = 0x19,&lt;br /&gt;
         OP_EvalArray = 0x1A,&lt;br /&gt;
         OP_EvalArrayRef = 0x1C,&lt;br /&gt;
         OP_ClearArray = 0x1D,&lt;br /&gt;
         OP_EmptyArray = 0x1E,&lt;br /&gt;
         OP_GetSelfObject = 0x1F,&lt;br /&gt;
         OP_EvalFieldVariable = 0x20,&lt;br /&gt;
         OP_EvalFieldVariableRef = 0x21,&lt;br /&gt;
         OP_ClearFieldVariable = 0x22,&lt;br /&gt;
         OP_SafeSetWaittillVariableFieldCached = 0x24,&lt;br /&gt;
         OP_clearparams = 0x25,&lt;br /&gt;
         OP_checkclearparams = 0x26,&lt;br /&gt;
         OP_EvalLocalVariableRefCached = 0x27,&lt;br /&gt;
         OP_SetVariableField = 0x28,&lt;br /&gt;
         OP_wait = 0x2B,&lt;br /&gt;
         OP_waittillFrameEnd = 0x2C,&lt;br /&gt;
         OP_PreScriptCall = 0x2D,&lt;br /&gt;
         OP_ScriptFunctionCall = 0x2E,&lt;br /&gt;
         OP_ScriptFunctionCallPointer = 0x2F,&lt;br /&gt;
         OP_ScriptMethodCall = 0x30,&lt;br /&gt;
         OP_ScriptMethodCallPointer = 0x31,&lt;br /&gt;
         OP_ScriptThreadCall = 0x32,&lt;br /&gt;
         OP_ScriptThreadCallPointer = 0x33,&lt;br /&gt;
         OP_ScriptMethodThreadCall = 0x34,&lt;br /&gt;
         OP_ScriptMethodThreadCallPointer = 0x35,&lt;br /&gt;
         OP_DecTop = 0x36,&lt;br /&gt;
         OP_CastFieldObject = 0x37,&lt;br /&gt;
         OP_CastBool = 0x38,&lt;br /&gt;
         OP_BoolNot = 0x39,&lt;br /&gt;
         OP_BoolComplement = 0x3A,&lt;br /&gt;
         OP_JumpOnFalse = 0x3B,&lt;br /&gt;
         OP_JumpOnTrue = 0x3C,&lt;br /&gt;
         OP_JumpOnFalseExpr = 0x3D,&lt;br /&gt;
         OP_JumpOnTrueExpr = 0x3E,&lt;br /&gt;
         OP_jump = 0x3F,&lt;br /&gt;
         OP_jumpback = 0x40,&lt;br /&gt;
         OP_inc = 0x41,&lt;br /&gt;
         OP_dec = 0x42,&lt;br /&gt;
         OP_bit_or = 0x43,&lt;br /&gt;
         OP_bit_ex_or = 0x44,&lt;br /&gt;
         OP_bit_and = 0x45,&lt;br /&gt;
         OP_equality = 0x46,&lt;br /&gt;
         OP_inequality = 0x47,&lt;br /&gt;
         OP_less = 0x48,&lt;br /&gt;
         OP_greater = 0x49,&lt;br /&gt;
         OP_less_equal = 0x4A,&lt;br /&gt;
         OP_greater_equal = 0x4B,&lt;br /&gt;
         OP_shift_left = 0x4C,&lt;br /&gt;
         OP_shift_right = 0x4D,&lt;br /&gt;
         OP_plus = 0x4E,&lt;br /&gt;
         OP_minus = 0x4F,&lt;br /&gt;
         OP_multiply = 0x50,&lt;br /&gt;
         OP_divide = 0x51,&lt;br /&gt;
         OP_mod = 0x52,&lt;br /&gt;
         OP_size = 0x53,&lt;br /&gt;
         OP_waittillmatch = 0x54,&lt;br /&gt;
         OP_waittill = 0x55,&lt;br /&gt;
         OP_notify = 0x56,&lt;br /&gt;
         OP_endon = 0x57,&lt;br /&gt;
         OP_voidCodepos = 0x58,&lt;br /&gt;
         OP_switch = 0x59,&lt;br /&gt;
         OP_endswitch = 0x5A,&lt;br /&gt;
         OP_vector = 0x5B,&lt;br /&gt;
         OP_GetHash = 0x5C,&lt;br /&gt;
         OP_GetSimpleVector = 0x5E,&lt;br /&gt;
         OP_isdefined = 0x5F,&lt;br /&gt;
         OP_vectorscale = 0x60,&lt;br /&gt;
         OP_anglestoup = 0x61,&lt;br /&gt;
	 OP_anglestoright = 0x62,&lt;br /&gt;
	 OP_anglestoforward = 0x63,&lt;br /&gt;
	 OP_angleclamp180 = 0x64,&lt;br /&gt;
	 OP_vectorstoangle = 0x65,&lt;br /&gt;
	 OP_abs = 0x66,&lt;br /&gt;
	 OP_gettime = 0x67,&lt;br /&gt;
	 OP_getdvar = 0x68,&lt;br /&gt;
	 OP_getdvarint = 0x69,&lt;br /&gt;
	 OP_getdvarfloat = 0x6A,&lt;br /&gt;
	 OP_getdvarvec3d = 0x6B,&lt;br /&gt;
	 OP_getdvarred = 0x6C,&lt;br /&gt;
	 OP_getdvargreen = 0x6D,&lt;br /&gt;
	 OP_getdvarblue = 0x6E,&lt;br /&gt;
	 OP_GetFirstArrayKey = 0x70,&lt;br /&gt;
	 OP_GetNextArrayKey = 0x71,&lt;br /&gt;
	 OP_GetUndefined2 = 0x73,&lt;br /&gt;
	 OP_skipdev = 0x7B,&lt;br /&gt;
	 OP_count = 0x7C,&lt;br /&gt;
	 OP_NOP = 0x7F,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Notice that 0x7B is the highest opcode, but 0x7F is still valid. In truth anything over 0x7B will register as NOP. The executable does some odd jumping around for each OP code, so a recap of each OP code will try to be added. In the following functions &amp;quot;currentFunctionDataOffset&amp;quot; is defined as an integer that points to the current OP code being read. Keep in mind that an OP code is read, the data offset is increased by 1, and then the following code is ran. OP codes are parsed in the order they are read, but if a dump is being done then parts are going to be dumped in reverse order. Here is an example of a series of OP codes...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
OP_PreScriptCall&lt;br /&gt;
OP_GetString		&amp;quot;1350&amp;quot;&lt;br /&gt;
OP_GetString		&amp;quot;scr_veh_health_tank&amp;quot;&lt;br /&gt;
OP_CallBuiltin 		2, &amp;quot;setdvar&amp;quot;&lt;br /&gt;
OP_clearparams&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This would be the &amp;quot;asm&amp;quot; of the GSC, and would look like this...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
setdvar( &amp;quot;scr_veh_health_tank&amp;quot;, &amp;quot;1350&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== OP_End ====&lt;br /&gt;
If FunctionDeclaration-&amp;gt;crc32 equals to returned crc then break. This is how you calculate the CRC32 below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
static const unsigned int kCrc32Table[] = {&lt;br /&gt;
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,&lt;br /&gt;
	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,&lt;br /&gt;
	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,&lt;br /&gt;
	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,&lt;br /&gt;
	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,&lt;br /&gt;
	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,&lt;br /&gt;
	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,&lt;br /&gt;
	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,&lt;br /&gt;
	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,&lt;br /&gt;
	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,&lt;br /&gt;
	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,&lt;br /&gt;
	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,&lt;br /&gt;
	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,&lt;br /&gt;
	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,&lt;br /&gt;
	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,&lt;br /&gt;
	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,&lt;br /&gt;
	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,&lt;br /&gt;
	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,&lt;br /&gt;
	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,&lt;br /&gt;
	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,&lt;br /&gt;
	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,&lt;br /&gt;
	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,&lt;br /&gt;
	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,&lt;br /&gt;
	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,&lt;br /&gt;
	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,&lt;br /&gt;
	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,&lt;br /&gt;
	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,&lt;br /&gt;
	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,&lt;br /&gt;
	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,&lt;br /&gt;
	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,&lt;br /&gt;
	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,&lt;br /&gt;
	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,&lt;br /&gt;
	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,&lt;br /&gt;
	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,&lt;br /&gt;
	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,&lt;br /&gt;
	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,&lt;br /&gt;
	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,&lt;br /&gt;
	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,&lt;br /&gt;
	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,&lt;br /&gt;
	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,&lt;br /&gt;
	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,&lt;br /&gt;
	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,&lt;br /&gt;
	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
unsigned int crc(unsigned char* pData, unsigned int length) {&lt;br /&gt;
unsigned char* pCur = (unsigned char*)pData;&lt;br /&gt;
unsigned int remaining = length, _crc = ~0;&lt;br /&gt;
&lt;br /&gt;
for (; remaining--; ++pCur)&lt;br /&gt;
 _crc = (_crc &amp;gt;&amp;gt; 8) ^ kCrc32Table[(_crc ^ *pCur) &amp;amp; 0xff];&lt;br /&gt;
&lt;br /&gt;
return ~_crc;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For the CRC32 checksum parameters it&#039;s unsigned int crc(functionStart, currentFunctionDataOffset - functionStart). If the returned crc does not equal FunctionDeclaration-&amp;gt;crc32 then write &amp;quot;return;&amp;quot; to the stack.&lt;br /&gt;
&lt;br /&gt;
==== OP_Return ====&lt;br /&gt;
The return OP is exactly as expected. Any OP codes in the stack go after a &amp;quot;return&amp;quot;. There is no data skipped, it is simply a 1 byte opcode. Keep in mind that if the game reaches a return, it leaves the function however for a complete dump, data must continue to be read and sometimes this data is unnecessary.&lt;br /&gt;
==== OP_GetUndefined &amp;amp; OP_GetZero ====&lt;br /&gt;
This simply represents the &amp;quot;undefined&amp;quot;/0 element in GSCs. It is a simple 1 byte opcode, and once read it is put right onto the stack. When dumping from the stack, simply print &amp;quot;undefined&amp;quot;/0 and continue.&lt;br /&gt;
==== OP_GetByte &amp;amp; OP_GetNegByte ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 1 byte. These are 2 byte opcode in that the first byte is the opcode and the second byte is an unsigned value. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegByte should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetUnsignedShort &amp;amp; OP_GetNegUnsignedShort ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 2 byte. After reading the opcode, the following is used to determine the offset of the unsigned short value&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the unsigned short value to use. Then skip another 2 bytes for that value to continue reading. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegUnsignedShort should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetInteger &amp;amp; OP_GetFloat ====&lt;br /&gt;
OP_GetInteger is used for any numbers that are large enough to warrant a signed integer, while OP_GetFloat is used for bigger numbers and decimals. After reading the opcode, the following is used to determine the offset of the value to get&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the value to get, then skip another 4 bytes past the value to continue reading. The opcode is then added to the stack. When dumping the value is simply printed and then continued;&lt;br /&gt;
==== OP_GetString &amp;amp; OP_GetIString ====&lt;br /&gt;
These are very clearly used to reference strings in code. Strings are found by their references. To get the offset of the reference use the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the argument section should be an argument with a reference that is equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. The name of the argument is the offset of the string to use in the string pool from the beginning of the GSC. Add another 2 to currentFunctionDataOffset to skip past the reference to continue reading. Keep in mind that OP_GetIString is used to get localized strings, and a &amp;amp; should be a added before the quotes.&lt;br /&gt;
==== OP_GetLevelObject &amp;amp; OP_GetLevel &amp;amp; OP_GetSelf &amp;amp; OP_GetSelfObject &amp;amp; OP_GetGame &amp;amp; OP_GetGameRef &amp;amp; OP_GetAnimObject ====&lt;br /&gt;
All of these are simple 1 byte opcodes that are added to the stack once they are read. They represent (and should be printed as) the &amp;quot;game&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;anim&amp;quot; and &amp;quot;self&amp;quot; objects in GSC code.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetAnimation ====&lt;br /&gt;
These are used to reference animations in an animtree that was included to this GSC. The name of the animation is found by a reference. To get the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should be an animtree in the animtree include section that has an animation with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. Add another 4 bytes to skip past the reference to continue reading opcodes. After this is read it is added to the stack. When dumping the reference animation name should be found and dumped (without quotes) preceeded by a % sign.&lt;br /&gt;
==== OP_GetFunction ====&lt;br /&gt;
This is used to reference a function without calling it. This allows you to set a variable to a function, and then call the variable later. There should be a function call with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;, and this is the function to use. This is then added to the stack. After that the following code is performed&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to continue reading. When dumping the function name should be printed after &amp;quot;::&amp;quot;.&lt;br /&gt;
==== OP_CreateLocalVariable ====&lt;br /&gt;
This opcode is used at the beginning of any function with arguments or local variables to define them. After the opcode is a single byte that is the number to define. Each variable argument is found by getting the reference for it in the argument section. To get the offset of each reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
That gets ran before to find a reference offset. There should be a argument with a reference equal to the &amp;quot;currentFunctionDataOffset&amp;quot;. Then 2 is added to skip past the current reference before the above is started again. The function declaration states the number of arguments, any extra are local variables. Keep in mind the stack should be clear after this is ran.&lt;br /&gt;
==== OP_EvalLocalVariableCached1 &amp;amp; OP_EvalLocalVariableRefCached ====&lt;br /&gt;
This is a simple 2 byte opcode used to reference an argument or local variable. The second byte is the index of the local variable to use, defined by OP_CreateLocalVariable. This is then added to the stack to be dumped. To dump the local variable must be looked up, the argument found and the name referenced.&lt;br /&gt;
==== OP_EvalArray &amp;amp; OP_EvalArrayRef ====&lt;br /&gt;
These are simple 1 byte opcodes used to reference elements in an array. It is simply added to the stack to be dumped. When dumping, the next entity on the stack is the array to use and the next entity is the index in the array (Indexes are not always numbers).&lt;br /&gt;
==== OP_ClearArray ====&lt;br /&gt;
This is a 1 byte opcode used to set an array element to &amp;quot;undefined&amp;quot;. This is not added to the stack, instead the stack is processed. The first entity on the stack is the array to use and the second is the array index. This element is then set to undefined. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_EmptyArray ====&lt;br /&gt;
This is a simple 1 byte opcode used to denote an empty array (&amp;quot;[]&amp;quot;). It is added right to the stack and simply printed when dumping. &lt;br /&gt;
==== OP_EvalFieldVariable &amp;amp; OP_EvalFieldVariableRef ====&lt;br /&gt;
These opcodes are used to reference any field variable. The names of the field variable is found by the offset of a reference. To find the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. The opcode is then added to the stack to be dumped later. The next entity on the stack is the item the field variable is for. &lt;br /&gt;
==== OP_ClearFieldVariable ====&lt;br /&gt;
This opcode is used to set a field variable element to &amp;quot;undefined&amp;quot;. The name of the field variable is found by the offset of a reference. To find the offset of a reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. This opcode is not added to the stack, instead the stack is processed. The only entity on the stack should be the item the field variable is for. Once this is processed the stack should be empty. &lt;br /&gt;
==== OP_checkclearparams &amp;amp; OP_clearparams ====&lt;br /&gt;
Used at the beginning of a function with no arguments. Clears the stack without processing it. &lt;br /&gt;
==== OP_SetVariableField ====&lt;br /&gt;
This is a 1 byte opcode used to set an entity to anything else. This is not added to the stack, instead the stack is processed. The first entity on the stack is the entity to set (left side of the &amp;quot;=&amp;quot; sign) with the second being the entity setting with (right side). At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_CallBuiltin ====&lt;br /&gt;
This opcode is used to call a GSC function that is predefined in the executable. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, there should be an entity on the stack for each expected argument. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_ScriptMethodCall ====&lt;br /&gt;
This opcode is used to call a GSC function on an entity that is defined in another GSC. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, the first entity on the stack will be the entity the function is being called upon, followed by an entity for each argument in the function. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_wait ====&lt;br /&gt;
This is a simple 1 byte opcode used for the &amp;quot;wait()&amp;quot; function. This is not added to the stack, instead the stack is processed. The first (and only) entity on the stack should be the number of milliseconds to wait. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_waittillframeend ====&lt;br /&gt;
This is a simple 1 byte opcode used for &amp;quot;waittillframeend&amp;quot;. This is not added to the stack, and is always ran with an empty stack.&lt;br /&gt;
==== OP_PreScriptCall ====&lt;br /&gt;
This is a simple 1 byte opcode used before all instructions and is equivalent to NOP.&lt;br /&gt;
==== OP_Script Call Functions ====&lt;br /&gt;
These opcodes are used to call a function and are very similar. The names of the function to call are found by a reference, and for all of these opcodes the reference is the offset of the opcode. &amp;quot;Method&amp;quot; opcodes have an extra entity on the stack as the entity the function is called upon. &amp;quot;Thread&amp;quot; opcodes are threading the function they call. The &amp;quot;Pointer&amp;quot; opcodes do not have a reference with the function&#039;s name, instead the function is a variable and an extra entity is on the stack. There will be an entity on the stack for each expected argument. To read past OP_ScriptFunctionCall, OP_ScriptMethodCall, OP_ScriptMethodCall2, and OP_ScriptMethodThreadCall, do&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &amp;quot;Pointer&amp;quot; opcodes are all 2 byte opcdes. All these opcodes are added to the stack to be dumped. &lt;br /&gt;
==== OP_clearparams ====&lt;br /&gt;
This is a 1 byte opcode and is used most often to process the stack. The stack is simply processed and should be clear by the end of this running.&lt;br /&gt;
==== OP_CastFieldObject ====&lt;br /&gt;
Not very well understood, skipping it seems to work fine.&lt;br /&gt;
==== OP_BoolNot ====&lt;br /&gt;
This is a simple 1 byte opcode used for the logical NOT operator (&amp;quot;!&amp;quot;). This is simply added to the stack to be dumped. When dumping, the next entity on the stack is the value to invert. &lt;br /&gt;
==== OP_jump Codes ====&lt;br /&gt;
Rather than have logical AND and OR operators in this language, it is similar to PPC in that there are &amp;quot;branches&amp;quot; or &amp;quot;jumps&amp;quot;. Rather than using an AND operator, a series of conditional jumps are used to produce the same result. OP_jump is a simple absolute jump value. After reading the opcode,&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will point to a &amp;quot;short&amp;quot; data value. This will be an offset in the GSC to jump to (Usually just a few bytes away). Skip another 2 bytes past this offset to continue reading opcodes. This opcode is then added to the stack to be dumped. The next entity in the stack is the condition to jump on.&lt;br /&gt;
==== Logical and Bitwise Operators ====&lt;br /&gt;
OP_inc &amp;amp; OP_dec are skipped by performing this operation&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
currentFunctionDataOffset += 2;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
They are added to the stack to be dumped. When dumping, the next member of the stack is the entity to shift, followed by &amp;quot;++&amp;quot; for increase and &amp;quot;--&amp;quot; for decrease.&lt;br /&gt;
&lt;br /&gt;
The next few operators are all 1 byte operators. They are simply added to the stack to be dumped. When dumping, the next entity on the stack is the right side of the operator with the nxt entity being the left side.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;opcode&#039;&#039;&#039;||&#039;&#039;&#039;Operator&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_or||&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_and||&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|OP_equality||==&lt;br /&gt;
|-&lt;br /&gt;
|OP_inequality||!=&lt;br /&gt;
|-&lt;br /&gt;
|OP_less||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_less_equal||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater_equal||&amp;gt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_plus||+&lt;br /&gt;
|-&lt;br /&gt;
|OP_minus||-&lt;br /&gt;
|-&lt;br /&gt;
|OP_multiply||*&lt;br /&gt;
|-&lt;br /&gt;
|OP_divide||/&lt;br /&gt;
|-&lt;br /&gt;
|OP_mod||%&lt;br /&gt;
|}&lt;br /&gt;
==== OP_size ====&lt;br /&gt;
This opcode is used to get the &amp;quot;.size&amp;quot; of an array entity. Simply added to the stack for dumping, the next stack entity is the array entity. &lt;br /&gt;
==== OP_waittillmatch &amp;amp; OP_waittill &amp;amp; OP_notify ====&lt;br /&gt;
These 1 byte opcodes codes are used in combination with OP_endon for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity the function is being referenced to. The constant strings are next on the stack and should be the only remaining items on the stack. Following these opcodes are a OP_SafeSetWaittillVariableFieldCached for each variable to pass (Used to pass data at the point of the sync). This is a 2 byte opcode, with the second byte being the index of the local variable defined at the beginning of the function. &lt;br /&gt;
==== OP_endon ====&lt;br /&gt;
This 1 byte opcode is used in combination with the above codes for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity this function is being referenced to. The constant strings to end on are then placed on the stack.&lt;br /&gt;
==== OP_voidCodepos ====&lt;br /&gt;
Equivelent to NOP.&lt;br /&gt;
==== OP_switch &amp;amp; OP_endswitch ====&lt;br /&gt;
When a switch is used by the game, only the needed case is ran at a time. However when dumping, all cases must be processed. There are a few points of interest when using the switch, the first is found by doing&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; is a partial pointer to an integer, the case definition location (The switch case code is directly after this integer, with the case definitions directly after that). After setting &amp;quot;currentFunctionDataOffset&amp;quot; to this integer, perform this to get to the actual case definitions&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 7;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Currently &amp;quot;currentFunctionDataOffset&amp;quot; will point to directly after the switch case code. The first integer is the switch case count. Following this is 8 bytes for each case in the switch. The first short in these 8 bytes is the &amp;quot;switch case type&amp;quot;. There are currently 2 known switch types, integer (0x80) and string (0). If the type is integer then the short after the type is the index for this case. If the type is a string, then there will be an argument in the argument section with the offset of the short after the type. The 4 bytes after these 2 shorts is the offset for the section of code for this case. If the type is 0 and the short for the reference is 0, then this is the &amp;quot;default&amp;quot; case. The OP_endswitch is found at the end of the section of code for this switch, just before the case defintions. It is a 1 byte opcode, and after reading this the switch should be ended and the case defintions skipped. &lt;br /&gt;
==== OP_vector ====&lt;br /&gt;
This is a simple 1 byte opcode. Vectors are a standard l-type in GSC and simply defined in raw text by doing (number1, number2, number3). Once this opcode is read it is added to the stack to be dumped. When dumping there must be at least 3 more entities on the stack, one for each item in the vector. &lt;br /&gt;
==== OP_GetHash ====&lt;br /&gt;
This opcode is used to reference dvar entities in GSC. In GSC when referencing a dvar it appears as #&amp;quot;dvarName&amp;quot;. Rather than storing the dvarName directly, the hash is stored and any dvar with a matching hash is used. To get the hash, perform&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will point to an integer that is the dvar&#039;s hash. This is then added to the stack to be dumped. To continue reading opcodes, skip another 4 bytes past the hash.&lt;br /&gt;
&lt;br /&gt;
The hash they used is DJB2 Hash algorithm. This is the implementation:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
unsigned int DvarHash(const char* dvar) {&lt;br /&gt;
    unsigned int hash = 5381;&lt;br /&gt;
&lt;br /&gt;
    while (*str != 0)&lt;br /&gt;
	hash = (33 * hash) + tolower(*str++);&lt;br /&gt;
&lt;br /&gt;
    return hash;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== OP_GetSimpleVector ====&lt;br /&gt;
This 2 byte opcode is used to store very simple vectors. The second byte in the opcode is the flags for the vector elements. Each element in the vector is 0 by default. The first element is &amp;quot;-1&amp;quot; if the bitflag 0x10 is set, and &amp;quot;1&amp;quot; if 0x20 is set. The second element is &amp;quot;-1&amp;quot; if the bitflag 4 is set, and &amp;quot;1&amp;quot; if 8 is set. The third element is &amp;quot;-1&amp;quot; if the bitflag 1 is set, and &amp;quot;1&amp;quot; if 2 is set.&lt;br /&gt;
&lt;br /&gt;
==== OP_isdefined ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;isDefined()&amp;quot; function. The next entity on the stack is the entity to check for existence.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorscale ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vector_scale()&amp;quot; function. The next entity on the stack is the vector entity to scale. The following entity is the scaler entity.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoup ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToUp()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoright ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToRight()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoforward ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToForward()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_angleclamp180 ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;angleClamp180()&amp;quot; function. The next entity on the stack is the angle to clamp.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorstoangle ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vectorsToAngle()&amp;quot; function. The next entity on the stack is the vector to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_abs ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;abs()&amp;quot; or &amp;quot;absolute value&amp;quot; function. The next entity on the stack is the integer to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_gettime ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getTime()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvar ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvar()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarint ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarInt()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarfloat ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarFloat()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarred ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarRed()&amp;quot; function to grab the red component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvargreen ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarGreen()&amp;quot; function to grab the green component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarblue ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarBlue()&amp;quot; function to grab the blue component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetFirstArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getFirstArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetNextArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getNextArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_skipdev ==== &lt;br /&gt;
This opcode is used to denote developer code sections. These sections are outlined by &amp;quot;/#&amp;quot; and &amp;quot;#/&amp;quot; in raw text and are only ran when the dvars &amp;quot;developer&amp;quot; and &amp;quot;developer_script&amp;quot; are set to true. The section starts at this opcode, and the end is defined at&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point there is a short value that holds the length of this code section at which point the end marker will be.&lt;br /&gt;
&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format for GSCs is very well known. Simply a code file (text) with a .gsc extension.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=632</id>
		<title>ScriptParseTree Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=632"/>
		<updated>2014-12-20T11:55:46Z</updated>

		<summary type="html">&lt;p&gt;Kokole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The ScriptParseTree asset is a new asset in Black Ops 2 and this is the only Call of Duty game it has appeared in so far. This is Treyarch&#039;s answer to GSCs (Keep in mind that on Black Ops 1 GSCs were still [[:Rawfile Asset|rawfiles]]). Compared to IW&#039;s equivalent scriptfile asset, the ScriptParseTree has proven to give slightly more information and thus are easier to reverse. The basic structure is identical to the rawfiles&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct ScriptParseTree&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  int len;&lt;br /&gt;
  const char *buffer;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Simply an uncompressed buffer holding the GSC data. The binary data is then passed to the GSC Virtual Machine (VM) to be ran. Now for the header of the binary data&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#define GSCMagic = 0x804753430D0A0006&lt;br /&gt;
&lt;br /&gt;
struct GSCHeader&lt;br /&gt;
{&lt;br /&gt;
  __int64 magic;&lt;br /&gt;
  int unknown1;&lt;br /&gt;
  unsigned int includeSectionOffset;&lt;br /&gt;
  unsigned int usingAnimtreeSectionOffset;&lt;br /&gt;
  unsigned int executionDataSectionOffset;&lt;br /&gt;
  unsigned int argumentSectionOffset;&lt;br /&gt;
  unsigned int functionDeclSectionOffset;&lt;br /&gt;
  unsigned int callFunctionSectionOffset;&lt;br /&gt;
    //Sections that do not exist point to the next section.&lt;br /&gt;
    //The next two, for the last time, are most likely NOT the gsc&#039;s total size, repeated twice.&lt;br /&gt;
    //There is most likely a section that I am missing, that has probably never been used.&lt;br /&gt;
    //- CraigChrist8239&lt;br /&gt;
  char unknown2[0xC];&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  unsigned short totalArgumentCount;&lt;br /&gt;
  unsigned short functionDeclCount;&lt;br /&gt;
  unsigned short callFunctionCount;&lt;br /&gt;
  int unknown3;&lt;br /&gt;
  byte includeSectionCount;&lt;br /&gt;
  byte usingAnimtreeCount;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
BO2 PDB VERSION:&lt;br /&gt;
struct GSC_IMPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 name_space;&lt;br /&gt;
  unsigned __int16 num_address;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 4301 */&lt;br /&gt;
struct GSC_ANIMNODE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 4302 */&lt;br /&gt;
struct GSC_STRINGTABLE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 string;&lt;br /&gt;
  char num_address;&lt;br /&gt;
  char type;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 4303 */&lt;br /&gt;
struct GSC_ANIMTREE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 num_tree_address;&lt;br /&gt;
  unsigned __int16 num_node_address;&lt;br /&gt;
  char pad[2];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 4304 */&lt;br /&gt;
struct GSC_PROFILE_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int name;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 4305 */&lt;br /&gt;
struct GSC_EXPORT_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int checksum;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  char param_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* 4306 */&lt;br /&gt;
struct GSC_FIXUP_ITEM&lt;br /&gt;
{&lt;br /&gt;
  unsigned int offset;&lt;br /&gt;
  unsigned int address;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct GSC_OBJ&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  unsigned int source_crc;&lt;br /&gt;
  unsigned int include_offset;&lt;br /&gt;
  unsigned int animtree_offset;&lt;br /&gt;
  unsigned int cseg_offset;&lt;br /&gt;
  unsigned int stringtablefixup_offset;&lt;br /&gt;
  unsigned int exports_offset;&lt;br /&gt;
  unsigned int imports_offset;&lt;br /&gt;
  unsigned int fixup_offset;&lt;br /&gt;
  unsigned int profile_offset;&lt;br /&gt;
  unsigned int cseg_size;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 stringtablefixup_count;&lt;br /&gt;
  unsigned __int16 exports_count;&lt;br /&gt;
  unsigned __int16 imports_count;&lt;br /&gt;
  unsigned __int16 fixup_count;&lt;br /&gt;
  unsigned __int16 profile_count;&lt;br /&gt;
  char include_count;&lt;br /&gt;
  char animtree_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Following the header is a section of null terminated strings (undetermined size/count). This section is also padded at the end to a 4-byte buffer. The following sections will reference back to this section when a string is used. Keep in mind that the offsets are simply just an offset in the buffer.&lt;br /&gt;
=== Include Section ===&lt;br /&gt;
The first known section after the string table is the include section, and this should be the first section dumped as well. This section is used to replace the following in a raw gsc&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include maps\mp\_utility;&lt;br /&gt;
#include common_scripts\utility;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The include section is probably the easiest section to reverse. Each include exists as a single integer which holds the offset of the include&#039;s string in the buffer. &lt;br /&gt;
=== Using Animtree Section ===&lt;br /&gt;
Although this section doesn&#039;t follow the include section, it is what needs to be dumped second. When a GSC wants to directly access and animtree, then the following code is added (for animtree &amp;quot;mp_vehicles&amp;quot;)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#using_animtree( &amp;quot;mp_vehicles&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then animations can be accessed from the tree as follows (Using the %)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
destructible_anims[ &amp;quot;car&amp;quot; ] = %veh_car_destroy;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Knowing this, the binary data section can be reversed fairly easily. The structure for their definitions in this section is&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Reference&lt;br /&gt;
{&lt;br /&gt;
  unsigned short name;&lt;br /&gt;
  unsigned short xrefOffset;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct AnimTree&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned short pathOffset; //Paths do not exist for animtrees (so far)&lt;br /&gt;
	unsigned short referenceCount;&lt;br /&gt;
	Reference references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
XRefs are explained in better detail in the code section. Each animtree thats included will have an AnimTree struct, and every time an animation is used it will be defined in the references.&lt;br /&gt;
=== Argument Section ===&lt;br /&gt;
The argument section not only defines any function arguments that are defined with function declarations, but any local variable a function might create. Although they are defined the same, the difference between the two is highlighted in the code section. Each argument will be defined as follows&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Argument&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned char referenceCount;&lt;br /&gt;
	signed char unknown;&lt;br /&gt;
	unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The references will explained in more detail in the code section.&lt;br /&gt;
&lt;br /&gt;
=== Function Call Section ===&lt;br /&gt;
If a function is called by a function in this GSC, it must be defined here in the function call section, even if that function is located inside this GSC. First the struct&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionCall&lt;br /&gt;
{&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  unsigned short pathOffset;&lt;br /&gt;
  unsigned short referenceCount;&lt;br /&gt;
  byte paramCount;&lt;br /&gt;
  byte flag;&lt;br /&gt;
  unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
NameOffset obviously holds the name of the called function. References are explained in the code section. If the function is not located in this GSC or in a &amp;quot;using&amp;quot; GSC, then the function must have a path with the name of the GSC that it is defined in, and this is where the pathOffset points to. eg&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
thread maps\mp\gametypes\_spawning::init();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Function Declaration Section ===&lt;br /&gt;
This is the section that will be cycled through when dumping the GSC. Every function that is defined in this GSC is here. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionDeclaration&lt;br /&gt;
{&lt;br /&gt;
  int crc32;&lt;br /&gt;
  unsigned int executionDataOffset;&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  byte unknown2;&lt;br /&gt;
  byte argumentCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The executionDataOffset is an offset in the code section defining where this function begins.&lt;br /&gt;
&lt;br /&gt;
=== Executable Data ===&lt;br /&gt;
This section is by far the trickiest section. This is where the actual code the functions are compiled into is stored. The first thing that will be needed is a list of operation codes (OPcodes). These opcodes should be the same for all systems.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum OPCodes : char&lt;br /&gt;
{&lt;br /&gt;
         OP_End = 0x0,&lt;br /&gt;
         OP_Return = 0x1,&lt;br /&gt;
         OP_GetUndefined = 0x2,&lt;br /&gt;
         OP_GetZero = 0x3,&lt;br /&gt;
         OP_GetByte = 0x4,&lt;br /&gt;
         OP_GetNegByte = 0x5,&lt;br /&gt;
         OP_GetUnsignedShort = 0x6,&lt;br /&gt;
         OP_GetNegUnsignedShort = 0x7,&lt;br /&gt;
         OP_GetInteger = 0x8,&lt;br /&gt;
         OP_GetFloat = 0x9,&lt;br /&gt;
         OP_GetString = 0xA,&lt;br /&gt;
         OP_GetIString = 0xB,&lt;br /&gt;
         OP_GetVector = 0xC,&lt;br /&gt;
         OP_GetLevelObject = 0xD,&lt;br /&gt;
         OP_GetAnimObject = 0xE,&lt;br /&gt;
         OP_GetSelf = 0xF,&lt;br /&gt;
         OP_GetLevel = 0x10,&lt;br /&gt;
         OP_GetGame = 0x11,&lt;br /&gt;
         OP_GetAnim = 0x12,&lt;br /&gt;
         OP_GetAnimation = 0x13,&lt;br /&gt;
         OP_GetGameRef = 0x14,&lt;br /&gt;
         OP_GetFunction = 0x15,&lt;br /&gt;
         OP_CreateLocalVariables = 0x17,&lt;br /&gt;
         OP_EvalLocalVariableCached1 = 0x19,&lt;br /&gt;
         OP_EvalArray = 0x1A,&lt;br /&gt;
         OP_EvalArrayRef = 0x1C,&lt;br /&gt;
         OP_ClearArray = 0x1D,&lt;br /&gt;
         OP_EmptyArray = 0x1E,&lt;br /&gt;
         OP_GetSelfObject = 0x1F,&lt;br /&gt;
         OP_EvalFieldVariable = 0x20,&lt;br /&gt;
         OP_EvalFieldVariableRef = 0x21,&lt;br /&gt;
         OP_ClearFieldVariable = 0x22,&lt;br /&gt;
         OP_SafeSetWaittillVariableFieldCached = 0x24,&lt;br /&gt;
         OP_clearparams = 0x25,&lt;br /&gt;
         OP_checkclearparams = 0x26,&lt;br /&gt;
         OP_EvalLocalVariableRefCached = 0x27,&lt;br /&gt;
         OP_SetVariableField = 0x28,&lt;br /&gt;
         OP_wait = 0x2B,&lt;br /&gt;
         OP_waittillFrameEnd = 0x2C,&lt;br /&gt;
         OP_PreScriptCall = 0x2D,&lt;br /&gt;
         OP_ScriptFunctionCall = 0x2E,&lt;br /&gt;
         OP_ScriptFunctionCallPointer = 0x2F,&lt;br /&gt;
         OP_ScriptMethodCall = 0x30,&lt;br /&gt;
         OP_ScriptMethodCallPointer = 0x31,&lt;br /&gt;
         OP_ScriptThreadCall = 0x32,&lt;br /&gt;
         OP_ScriptThreadCallPointer = 0x33,&lt;br /&gt;
         OP_ScriptMethodThreadCall = 0x34,&lt;br /&gt;
         OP_ScriptMethodThreadCallPointer = 0x35,&lt;br /&gt;
         OP_DecTop = 0x36,&lt;br /&gt;
         OP_CastFieldObject = 0x37,&lt;br /&gt;
         OP_CastBool = 0x38,&lt;br /&gt;
         OP_BoolNot = 0x39,&lt;br /&gt;
         OP_BoolComplement = 0x3A,&lt;br /&gt;
         OP_JumpOnFalse = 0x3B,&lt;br /&gt;
         OP_JumpOnTrue = 0x3C,&lt;br /&gt;
         OP_JumpOnFalseExpr = 0x3D,&lt;br /&gt;
         OP_JumpOnTrueExpr = 0x3E,&lt;br /&gt;
         OP_jump = 0x3F,&lt;br /&gt;
         OP_jumpback = 0x40,&lt;br /&gt;
         OP_inc = 0x41,&lt;br /&gt;
         OP_dec = 0x42,&lt;br /&gt;
         OP_bit_or = 0x43,&lt;br /&gt;
         OP_bit_ex_or = 0x44,&lt;br /&gt;
         OP_bit_and = 0x45,&lt;br /&gt;
         OP_equality = 0x46,&lt;br /&gt;
         OP_inequality = 0x47,&lt;br /&gt;
         OP_less = 0x48,&lt;br /&gt;
         OP_greater = 0x49,&lt;br /&gt;
         OP_less_equal = 0x4A,&lt;br /&gt;
         OP_greater_equal = 0x4B,&lt;br /&gt;
         OP_shift_left = 0x4C,&lt;br /&gt;
         OP_shift_right = 0x4D,&lt;br /&gt;
         OP_plus = 0x4E,&lt;br /&gt;
         OP_minus = 0x4F,&lt;br /&gt;
         OP_multiply = 0x50,&lt;br /&gt;
         OP_divide = 0x51,&lt;br /&gt;
         OP_mod = 0x52,&lt;br /&gt;
         OP_size = 0x53,&lt;br /&gt;
         OP_waittillmatch = 0x54,&lt;br /&gt;
         OP_waittill = 0x55,&lt;br /&gt;
         OP_notify = 0x56,&lt;br /&gt;
         OP_endon = 0x57,&lt;br /&gt;
         OP_voidCodepos = 0x58,&lt;br /&gt;
         OP_switch = 0x59,&lt;br /&gt;
         OP_endswitch = 0x5A,&lt;br /&gt;
         OP_vector = 0x5B,&lt;br /&gt;
         OP_GetHash = 0x5C,&lt;br /&gt;
         OP_GetSimpleVector = 0x5E,&lt;br /&gt;
         OP_isdefined = 0x5F,&lt;br /&gt;
         OP_vectorscale = 0x60,&lt;br /&gt;
         OP_anglestoup = 0x61,&lt;br /&gt;
	 OP_anglestoright = 0x62,&lt;br /&gt;
	 OP_anglestoforward = 0x63,&lt;br /&gt;
	 OP_angleclamp180 = 0x64,&lt;br /&gt;
	 OP_vectorstoangle = 0x65,&lt;br /&gt;
	 OP_abs = 0x66,&lt;br /&gt;
	 OP_gettime = 0x67,&lt;br /&gt;
	 OP_getdvar = 0x68,&lt;br /&gt;
	 OP_getdvarint = 0x69,&lt;br /&gt;
	 OP_getdvarfloat = 0x6A,&lt;br /&gt;
	 OP_getdvarvec3d = 0x6B,&lt;br /&gt;
	 OP_getdvarred = 0x6C,&lt;br /&gt;
	 OP_getdvargreen = 0x6D,&lt;br /&gt;
	 OP_getdvarblue = 0x6E,&lt;br /&gt;
	 OP_GetFirstArrayKey = 0x70,&lt;br /&gt;
	 OP_GetNextArrayKey = 0x71,&lt;br /&gt;
	 OP_GetUndefined2 = 0x73,&lt;br /&gt;
	 OP_skipdev = 0x7B,&lt;br /&gt;
	 OP_count = 0x7C,&lt;br /&gt;
	 OP_NOP = 0x7F,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Notice that 0x7B is the highest opcode, but 0x7F is still valid. In truth anything over 0x7B will register as NOP. The executable does some odd jumping around for each OP code, so a recap of each OP code will try to be added. In the following functions &amp;quot;currentFunctionDataOffset&amp;quot; is defined as an integer that points to the current OP code being read. Keep in mind that an OP code is read, the data offset is increased by 1, and then the following code is ran. OP codes are parsed in the order they are read, but if a dump is being done then parts are going to be dumped in reverse order. Here is an example of a series of OP codes...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
OP_PreScriptCall&lt;br /&gt;
OP_GetString		&amp;quot;1350&amp;quot;&lt;br /&gt;
OP_GetString		&amp;quot;scr_veh_health_tank&amp;quot;&lt;br /&gt;
OP_CallBuiltin 		2, &amp;quot;setdvar&amp;quot;&lt;br /&gt;
OP_clearparams&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This would be the &amp;quot;asm&amp;quot; of the GSC, and would look like this...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
setdvar( &amp;quot;scr_veh_health_tank&amp;quot;, &amp;quot;1350&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== OP_End ====&lt;br /&gt;
If FunctionDeclaration-&amp;gt;crc32 equals to returned crc then break. This is how you calculate the CRC32 below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
static const unsigned int kCrc32Table[] = {&lt;br /&gt;
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,&lt;br /&gt;
	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,&lt;br /&gt;
	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,&lt;br /&gt;
	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,&lt;br /&gt;
	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,&lt;br /&gt;
	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,&lt;br /&gt;
	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,&lt;br /&gt;
	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,&lt;br /&gt;
	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,&lt;br /&gt;
	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,&lt;br /&gt;
	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,&lt;br /&gt;
	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,&lt;br /&gt;
	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,&lt;br /&gt;
	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,&lt;br /&gt;
	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,&lt;br /&gt;
	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,&lt;br /&gt;
	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,&lt;br /&gt;
	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,&lt;br /&gt;
	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,&lt;br /&gt;
	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,&lt;br /&gt;
	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,&lt;br /&gt;
	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,&lt;br /&gt;
	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,&lt;br /&gt;
	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,&lt;br /&gt;
	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,&lt;br /&gt;
	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,&lt;br /&gt;
	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,&lt;br /&gt;
	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,&lt;br /&gt;
	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,&lt;br /&gt;
	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,&lt;br /&gt;
	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,&lt;br /&gt;
	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,&lt;br /&gt;
	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,&lt;br /&gt;
	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,&lt;br /&gt;
	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,&lt;br /&gt;
	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,&lt;br /&gt;
	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,&lt;br /&gt;
	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,&lt;br /&gt;
	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,&lt;br /&gt;
	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,&lt;br /&gt;
	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,&lt;br /&gt;
	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,&lt;br /&gt;
	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
unsigned int crc(unsigned char* pData, unsigned int length) {&lt;br /&gt;
unsigned char* pCur = (unsigned char*)pData;&lt;br /&gt;
unsigned int remaining = length, _crc = ~0;&lt;br /&gt;
&lt;br /&gt;
for (; remaining--; ++pCur)&lt;br /&gt;
 _crc = (_crc &amp;gt;&amp;gt; 8) ^ kCrc32Table[(_crc ^ *pCur) &amp;amp; 0xff];&lt;br /&gt;
&lt;br /&gt;
return ~_crc;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For the CRC32 checksum parameters it&#039;s unsigned int crc(functionStart, currentFunctionDataOffset - functionStart). If the returned crc does not equal FunctionDeclaration-&amp;gt;crc32 then write &amp;quot;return;&amp;quot; to the stack.&lt;br /&gt;
&lt;br /&gt;
==== OP_Return ====&lt;br /&gt;
The return OP is exactly as expected. Any OP codes in the stack go after a &amp;quot;return&amp;quot;. There is no data skipped, it is simply a 1 byte opcode. Keep in mind that if the game reaches a return, it leaves the function however for a complete dump, data must continue to be read and sometimes this data is unnecessary.&lt;br /&gt;
==== OP_GetUndefined &amp;amp; OP_GetZero ====&lt;br /&gt;
This simply represents the &amp;quot;undefined&amp;quot;/0 element in GSCs. It is a simple 1 byte opcode, and once read it is put right onto the stack. When dumping from the stack, simply print &amp;quot;undefined&amp;quot;/0 and continue.&lt;br /&gt;
==== OP_GetByte &amp;amp; OP_GetNegByte ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 1 byte. These are 2 byte opcode in that the first byte is the opcode and the second byte is an unsigned value. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegByte should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetUnsignedShort &amp;amp; OP_GetNegUnsignedShort ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 2 byte. After reading the opcode, the following is used to determine the offset of the unsigned short value&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the unsigned short value to use. Then skip another 2 bytes for that value to continue reading. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegUnsignedShort should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetInteger &amp;amp; OP_GetFloat ====&lt;br /&gt;
OP_GetInteger is used for any numbers that are large enough to warrant a signed integer, while OP_GetFloat is used for bigger numbers and decimals. After reading the opcode, the following is used to determine the offset of the value to get&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the value to get, then skip another 4 bytes past the value to continue reading. The opcode is then added to the stack. When dumping the value is simply printed and then continued;&lt;br /&gt;
==== OP_GetString &amp;amp; OP_GetIString ====&lt;br /&gt;
These are very clearly used to reference strings in code. Strings are found by their references. To get the offset of the reference use the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the argument section should be an argument with a reference that is equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. The name of the argument is the offset of the string to use in the string pool from the beginning of the GSC. Add another 2 to currentFunctionDataOffset to skip past the reference to continue reading. Keep in mind that OP_GetIString is used to get localized strings, and a &amp;amp; should be a added before the quotes.&lt;br /&gt;
==== OP_GetLevelObject &amp;amp; OP_GetLevel &amp;amp; OP_GetSelf &amp;amp; OP_GetSelfObject &amp;amp; OP_GetGame &amp;amp; OP_GetGameRef &amp;amp; OP_GetAnimObject ====&lt;br /&gt;
All of these are simple 1 byte opcodes that are added to the stack once they are read. They represent (and should be printed as) the &amp;quot;game&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;anim&amp;quot; and &amp;quot;self&amp;quot; objects in GSC code.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetAnimation ====&lt;br /&gt;
These are used to reference animations in an animtree that was included to this GSC. The name of the animation is found by a reference. To get the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should be an animtree in the animtree include section that has an animation with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. Add another 4 bytes to skip past the reference to continue reading opcodes. After this is read it is added to the stack. When dumping the reference animation name should be found and dumped (without quotes) preceeded by a % sign.&lt;br /&gt;
==== OP_GetFunction ====&lt;br /&gt;
This is used to reference a function without calling it. This allows you to set a variable to a function, and then call the variable later. There should be a function call with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;, and this is the function to use. This is then added to the stack. After that the following code is performed&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to continue reading. When dumping the function name should be printed after &amp;quot;::&amp;quot;.&lt;br /&gt;
==== OP_CreateLocalVariable ====&lt;br /&gt;
This opcode is used at the beginning of any function with arguments or local variables to define them. After the opcode is a single byte that is the number to define. Each variable argument is found by getting the reference for it in the argument section. To get the offset of each reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
That gets ran before to find a reference offset. There should be a argument with a reference equal to the &amp;quot;currentFunctionDataOffset&amp;quot;. Then 2 is added to skip past the current reference before the above is started again. The function declaration states the number of arguments, any extra are local variables. Keep in mind the stack should be clear after this is ran.&lt;br /&gt;
==== OP_EvalLocalVariableCached1 &amp;amp; OP_EvalLocalVariableRefCached ====&lt;br /&gt;
This is a simple 2 byte opcode used to reference an argument or local variable. The second byte is the index of the local variable to use, defined by OP_CreateLocalVariable. This is then added to the stack to be dumped. To dump the local variable must be looked up, the argument found and the name referenced.&lt;br /&gt;
==== OP_EvalArray &amp;amp; OP_EvalArrayRef ====&lt;br /&gt;
These are simple 1 byte opcodes used to reference elements in an array. It is simply added to the stack to be dumped. When dumping, the next entity on the stack is the array to use and the next entity is the index in the array (Indexes are not always numbers).&lt;br /&gt;
==== OP_ClearArray ====&lt;br /&gt;
This is a 1 byte opcode used to set an array element to &amp;quot;undefined&amp;quot;. This is not added to the stack, instead the stack is processed. The first entity on the stack is the array to use and the second is the array index. This element is then set to undefined. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_EmptyArray ====&lt;br /&gt;
This is a simple 1 byte opcode used to denote an empty array (&amp;quot;[]&amp;quot;). It is added right to the stack and simply printed when dumping. &lt;br /&gt;
==== OP_EvalFieldVariable &amp;amp; OP_EvalFieldVariableRef ====&lt;br /&gt;
These opcodes are used to reference any field variable. The names of the field variable is found by the offset of a reference. To find the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. The opcode is then added to the stack to be dumped later. The next entity on the stack is the item the field variable is for. &lt;br /&gt;
==== OP_ClearFieldVariable ====&lt;br /&gt;
This opcode is used to set a field variable element to &amp;quot;undefined&amp;quot;. The name of the field variable is found by the offset of a reference. To find the offset of a reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. This opcode is not added to the stack, instead the stack is processed. The only entity on the stack should be the item the field variable is for. Once this is processed the stack should be empty. &lt;br /&gt;
==== OP_checkclearparams &amp;amp; OP_clearparams ====&lt;br /&gt;
Used at the beginning of a function with no arguments. Clears the stack without processing it. &lt;br /&gt;
==== OP_SetVariableField ====&lt;br /&gt;
This is a 1 byte opcode used to set an entity to anything else. This is not added to the stack, instead the stack is processed. The first entity on the stack is the entity to set (left side of the &amp;quot;=&amp;quot; sign) with the second being the entity setting with (right side). At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_CallBuiltin ====&lt;br /&gt;
This opcode is used to call a GSC function that is predefined in the executable. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, there should be an entity on the stack for each expected argument. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_ScriptMethodCall ====&lt;br /&gt;
This opcode is used to call a GSC function on an entity that is defined in another GSC. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, the first entity on the stack will be the entity the function is being called upon, followed by an entity for each argument in the function. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_wait ====&lt;br /&gt;
This is a simple 1 byte opcode used for the &amp;quot;wait()&amp;quot; function. This is not added to the stack, instead the stack is processed. The first (and only) entity on the stack should be the number of milliseconds to wait. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_waittillframeend ====&lt;br /&gt;
This is a simple 1 byte opcode used for &amp;quot;waittillframeend&amp;quot;. This is not added to the stack, and is always ran with an empty stack.&lt;br /&gt;
==== OP_PreScriptCall ====&lt;br /&gt;
This is a simple 1 byte opcode used before all instructions and is equivalent to NOP.&lt;br /&gt;
==== OP_Script Call Functions ====&lt;br /&gt;
These opcodes are used to call a function and are very similar. The names of the function to call are found by a reference, and for all of these opcodes the reference is the offset of the opcode. &amp;quot;Method&amp;quot; opcodes have an extra entity on the stack as the entity the function is called upon. &amp;quot;Thread&amp;quot; opcodes are threading the function they call. The &amp;quot;Pointer&amp;quot; opcodes do not have a reference with the function&#039;s name, instead the function is a variable and an extra entity is on the stack. There will be an entity on the stack for each expected argument. To read past OP_ScriptFunctionCall, OP_ScriptMethodCall, OP_ScriptMethodCall2, and OP_ScriptMethodThreadCall, do&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &amp;quot;Pointer&amp;quot; opcodes are all 2 byte opcdes. All these opcodes are added to the stack to be dumped. &lt;br /&gt;
==== OP_clearparams ====&lt;br /&gt;
This is a 1 byte opcode and is used most often to process the stack. The stack is simply processed and should be clear by the end of this running.&lt;br /&gt;
==== OP_CastFieldObject ====&lt;br /&gt;
Not very well understood, skipping it seems to work fine.&lt;br /&gt;
==== OP_BoolNot ====&lt;br /&gt;
This is a simple 1 byte opcode used for the logical NOT operator (&amp;quot;!&amp;quot;). This is simply added to the stack to be dumped. When dumping, the next entity on the stack is the value to invert. &lt;br /&gt;
==== OP_jump Codes ====&lt;br /&gt;
Rather than have logical AND and OR operators in this language, it is similar to PPC in that there are &amp;quot;branches&amp;quot; or &amp;quot;jumps&amp;quot;. Rather than using an AND operator, a series of conditional jumps are used to produce the same result. OP_jump is a simple absolute jump value. After reading the opcode,&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will point to a &amp;quot;short&amp;quot; data value. This will be an offset in the GSC to jump to (Usually just a few bytes away). Skip another 2 bytes past this offset to continue reading opcodes. This opcode is then added to the stack to be dumped. The next entity in the stack is the condition to jump on.&lt;br /&gt;
==== Logical and Bitwise Operators ====&lt;br /&gt;
OP_inc &amp;amp; OP_dec are skipped by performing this operation&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
currentFunctionDataOffset += 2;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
They are added to the stack to be dumped. When dumping, the next member of the stack is the entity to shift, followed by &amp;quot;++&amp;quot; for increase and &amp;quot;--&amp;quot; for decrease.&lt;br /&gt;
&lt;br /&gt;
The next few operators are all 1 byte operators. They are simply added to the stack to be dumped. When dumping, the next entity on the stack is the right side of the operator with the nxt entity being the left side.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;opcode&#039;&#039;&#039;||&#039;&#039;&#039;Operator&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_or||&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_and||&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|OP_equality||==&lt;br /&gt;
|-&lt;br /&gt;
|OP_inequality||!=&lt;br /&gt;
|-&lt;br /&gt;
|OP_less||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_less_equal||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater_equal||&amp;gt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_plus||+&lt;br /&gt;
|-&lt;br /&gt;
|OP_minus||-&lt;br /&gt;
|-&lt;br /&gt;
|OP_multiply||*&lt;br /&gt;
|-&lt;br /&gt;
|OP_divide||/&lt;br /&gt;
|-&lt;br /&gt;
|OP_mod||%&lt;br /&gt;
|}&lt;br /&gt;
==== OP_size ====&lt;br /&gt;
This opcode is used to get the &amp;quot;.size&amp;quot; of an array entity. Simply added to the stack for dumping, the next stack entity is the array entity. &lt;br /&gt;
==== OP_waittillmatch &amp;amp; OP_waittill &amp;amp; OP_notify ====&lt;br /&gt;
These 1 byte opcodes codes are used in combination with OP_endon for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity the function is being referenced to. The constant strings are next on the stack and should be the only remaining items on the stack. Following these opcodes are a OP_SafeSetWaittillVariableFieldCached for each variable to pass (Used to pass data at the point of the sync). This is a 2 byte opcode, with the second byte being the index of the local variable defined at the beginning of the function. &lt;br /&gt;
==== OP_endon ====&lt;br /&gt;
This 1 byte opcode is used in combination with the above codes for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity this function is being referenced to. The constant strings to end on are then placed on the stack.&lt;br /&gt;
==== OP_voidCodepos ====&lt;br /&gt;
Equivelent to NOP.&lt;br /&gt;
==== OP_switch &amp;amp; OP_endswitch ====&lt;br /&gt;
When a switch is used by the game, only the needed case is ran at a time. However when dumping, all cases must be processed. There are a few points of interest when using the switch, the first is found by doing&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; is a partial pointer to an integer, the case definition location (The switch case code is directly after this integer, with the case definitions directly after that). After setting &amp;quot;currentFunctionDataOffset&amp;quot; to this integer, perform this to get to the actual case definitions&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 7;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Currently &amp;quot;currentFunctionDataOffset&amp;quot; will point to directly after the switch case code. The first integer is the switch case count. Following this is 8 bytes for each case in the switch. The first short in these 8 bytes is the &amp;quot;switch case type&amp;quot;. There are currently 2 known switch types, integer (0x80) and string (0). If the type is integer then the short after the type is the index for this case. If the type is a string, then there will be an argument in the argument section with the offset of the short after the type. The 4 bytes after these 2 shorts is the offset for the section of code for this case. If the type is 0 and the short for the reference is 0, then this is the &amp;quot;default&amp;quot; case. The OP_endswitch is found at the end of the section of code for this switch, just before the case defintions. It is a 1 byte opcode, and after reading this the switch should be ended and the case defintions skipped. &lt;br /&gt;
==== OP_vector ====&lt;br /&gt;
This is a simple 1 byte opcode. Vectors are a standard l-type in GSC and simply defined in raw text by doing (number1, number2, number3). Once this opcode is read it is added to the stack to be dumped. When dumping there must be at least 3 more entities on the stack, one for each item in the vector. &lt;br /&gt;
==== OP_GetHash ====&lt;br /&gt;
This opcode is used to reference dvar entities in GSC. In GSC when referencing a dvar it appears as #&amp;quot;dvarName&amp;quot;. Rather than storing the dvarName directly, the hash is stored and any dvar with a matching hash is used. To get the hash, perform&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will point to an integer that is the dvar&#039;s hash. This is then added to the stack to be dumped. To continue reading opcodes, skip another 4 bytes past the hash.&lt;br /&gt;
&lt;br /&gt;
The hash they used is DJB2 Hash algorithm. This is the implementation:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
unsigned int DvarHash(const char* dvar) {&lt;br /&gt;
    unsigned int hash = 5381;&lt;br /&gt;
&lt;br /&gt;
    while (*str != 0)&lt;br /&gt;
	hash = (33 * hash) + tolower(*str++);&lt;br /&gt;
&lt;br /&gt;
    return hash;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== OP_GetSimpleVector ====&lt;br /&gt;
This 2 byte opcode is used to store very simple vectors. The second byte in the opcode is the flags for the vector elements. Each element in the vector is 0 by default. The first element is &amp;quot;-1&amp;quot; if the bitflag 0x10 is set, and &amp;quot;1&amp;quot; if 0x20 is set. The second element is &amp;quot;-1&amp;quot; if the bitflag 4 is set, and &amp;quot;1&amp;quot; if 8 is set. The third element is &amp;quot;-1&amp;quot; if the bitflag 1 is set, and &amp;quot;1&amp;quot; if 2 is set.&lt;br /&gt;
&lt;br /&gt;
==== OP_isdefined ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;isDefined()&amp;quot; function. The next entity on the stack is the entity to check for existence.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorscale ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vector_scale()&amp;quot; function. The next entity on the stack is the vector entity to scale. The following entity is the scaler entity.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoup ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToUp()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoright ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToRight()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoforward ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToForward()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_angleclamp180 ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;angleClamp180()&amp;quot; function. The next entity on the stack is the angle to clamp.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorstoangle ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vectorsToAngle()&amp;quot; function. The next entity on the stack is the vector to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_abs ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;abs()&amp;quot; or &amp;quot;absolute value&amp;quot; function. The next entity on the stack is the integer to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_gettime ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getTime()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvar ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvar()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarint ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarInt()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarfloat ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarFloat()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarred ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarRed()&amp;quot; function to grab the red component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvargreen ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarGreen()&amp;quot; function to grab the green component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarblue ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarBlue()&amp;quot; function to grab the blue component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetFirstArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getFirstArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetNextArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getNextArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_skipdev ==== &lt;br /&gt;
This opcode is used to denote developer code sections. These sections are outlined by &amp;quot;/#&amp;quot; and &amp;quot;#/&amp;quot; in raw text and are only ran when the dvars &amp;quot;developer&amp;quot; and &amp;quot;developer_script&amp;quot; are set to true. The section starts at this opcode, and the end is defined at&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point there is a short value that holds the length of this code section at which point the end marker will be.&lt;br /&gt;
&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format for GSCs is very well known. Simply a code file (text) with a .gsc extension.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=631</id>
		<title>ScriptParseTree Asset</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=ScriptParseTree_Asset&amp;diff=631"/>
		<updated>2014-12-20T11:54:16Z</updated>

		<summary type="html">&lt;p&gt;Kokole: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
[[Category:Assets]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
The ScriptParseTree asset is a new asset in Black Ops 2 and this is the only Call of Duty game it has appeared in so far. This is Treyarch&#039;s answer to GSCs (Keep in mind that on Black Ops 1 GSCs were still [[:Rawfile Asset|rawfiles]]). Compared to IW&#039;s equivalent scriptfile asset, the ScriptParseTree has proven to give slightly more information and thus are easier to reverse. The basic structure is identical to the rawfiles&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct ScriptParseTree&lt;br /&gt;
{&lt;br /&gt;
  const char *name;&lt;br /&gt;
  int len;&lt;br /&gt;
  const char *buffer;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Simply an uncompressed buffer holding the GSC data. The binary data is then passed to the GSC Virtual Machine (VM) to be ran. Now for the header of the binary data&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#define GSCMagic = 0x804753430D0A0006&lt;br /&gt;
&lt;br /&gt;
struct GSCHeader&lt;br /&gt;
{&lt;br /&gt;
  __int64 magic;&lt;br /&gt;
  int unknown1;&lt;br /&gt;
  unsigned int includeSectionOffset;&lt;br /&gt;
  unsigned int usingAnimtreeSectionOffset;&lt;br /&gt;
  unsigned int executionDataSectionOffset;&lt;br /&gt;
  unsigned int argumentSectionOffset;&lt;br /&gt;
  unsigned int functionDeclSectionOffset;&lt;br /&gt;
  unsigned int callFunctionSectionOffset;&lt;br /&gt;
    //Sections that do not exist point to the next section.&lt;br /&gt;
    //The next two, for the last time, are most likely NOT the gsc&#039;s total size, repeated twice.&lt;br /&gt;
    //There is most likely a section that I am missing, that has probably never been used.&lt;br /&gt;
    //- CraigChrist8239&lt;br /&gt;
  char unknown2[0xC];&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  unsigned short totalArgumentCount;&lt;br /&gt;
  unsigned short functionDeclCount;&lt;br /&gt;
  unsigned short callFunctionCount;&lt;br /&gt;
  int unknown3;&lt;br /&gt;
  byte includeSectionCount;&lt;br /&gt;
  byte usingAnimtreeCount;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
BO2 PDB VERSION:&lt;br /&gt;
struct GSC_OBJ&lt;br /&gt;
{&lt;br /&gt;
  char magic[8];&lt;br /&gt;
  unsigned int source_crc;&lt;br /&gt;
  unsigned int include_offset;&lt;br /&gt;
  unsigned int animtree_offset;&lt;br /&gt;
  unsigned int cseg_offset;&lt;br /&gt;
  unsigned int stringtablefixup_offset;&lt;br /&gt;
  unsigned int exports_offset;&lt;br /&gt;
  unsigned int imports_offset;&lt;br /&gt;
  unsigned int fixup_offset;&lt;br /&gt;
  unsigned int profile_offset;&lt;br /&gt;
  unsigned int cseg_size;&lt;br /&gt;
  unsigned __int16 name;&lt;br /&gt;
  unsigned __int16 stringtablefixup_count;&lt;br /&gt;
  unsigned __int16 exports_count;&lt;br /&gt;
  unsigned __int16 imports_count;&lt;br /&gt;
  unsigned __int16 fixup_count;&lt;br /&gt;
  unsigned __int16 profile_count;&lt;br /&gt;
  char include_count;&lt;br /&gt;
  char animtree_count;&lt;br /&gt;
  char flags;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Following the header is a section of null terminated strings (undetermined size/count). This section is also padded at the end to a 4-byte buffer. The following sections will reference back to this section when a string is used. Keep in mind that the offsets are simply just an offset in the buffer.&lt;br /&gt;
=== Include Section ===&lt;br /&gt;
The first known section after the string table is the include section, and this should be the first section dumped as well. This section is used to replace the following in a raw gsc&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include maps\mp\_utility;&lt;br /&gt;
#include common_scripts\utility;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The include section is probably the easiest section to reverse. Each include exists as a single integer which holds the offset of the include&#039;s string in the buffer. &lt;br /&gt;
=== Using Animtree Section ===&lt;br /&gt;
Although this section doesn&#039;t follow the include section, it is what needs to be dumped second. When a GSC wants to directly access and animtree, then the following code is added (for animtree &amp;quot;mp_vehicles&amp;quot;)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#using_animtree( &amp;quot;mp_vehicles&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then animations can be accessed from the tree as follows (Using the %)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
destructible_anims[ &amp;quot;car&amp;quot; ] = %veh_car_destroy;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Knowing this, the binary data section can be reversed fairly easily. The structure for their definitions in this section is&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Reference&lt;br /&gt;
{&lt;br /&gt;
  unsigned short name;&lt;br /&gt;
  unsigned short xrefOffset;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct AnimTree&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned short pathOffset; //Paths do not exist for animtrees (so far)&lt;br /&gt;
	unsigned short referenceCount;&lt;br /&gt;
	Reference references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
XRefs are explained in better detail in the code section. Each animtree thats included will have an AnimTree struct, and every time an animation is used it will be defined in the references.&lt;br /&gt;
=== Argument Section ===&lt;br /&gt;
The argument section not only defines any function arguments that are defined with function declarations, but any local variable a function might create. Although they are defined the same, the difference between the two is highlighted in the code section. Each argument will be defined as follows&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct Argument&lt;br /&gt;
{&lt;br /&gt;
	unsigned short nameOffset;&lt;br /&gt;
	unsigned char referenceCount;&lt;br /&gt;
	signed char unknown;&lt;br /&gt;
	unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The references will explained in more detail in the code section.&lt;br /&gt;
&lt;br /&gt;
=== Function Call Section ===&lt;br /&gt;
If a function is called by a function in this GSC, it must be defined here in the function call section, even if that function is located inside this GSC. First the struct&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionCall&lt;br /&gt;
{&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  unsigned short pathOffset;&lt;br /&gt;
  unsigned short referenceCount;&lt;br /&gt;
  byte paramCount;&lt;br /&gt;
  byte flag;&lt;br /&gt;
  unsigned int references[referenceCount];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
NameOffset obviously holds the name of the called function. References are explained in the code section. If the function is not located in this GSC or in a &amp;quot;using&amp;quot; GSC, then the function must have a path with the name of the GSC that it is defined in, and this is where the pathOffset points to. eg&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
thread maps\mp\gametypes\_spawning::init();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Function Declaration Section ===&lt;br /&gt;
This is the section that will be cycled through when dumping the GSC. Every function that is defined in this GSC is here. &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
struct FunctionDeclaration&lt;br /&gt;
{&lt;br /&gt;
  int crc32;&lt;br /&gt;
  unsigned int executionDataOffset;&lt;br /&gt;
  unsigned short nameOffset;&lt;br /&gt;
  byte unknown2;&lt;br /&gt;
  byte argumentCount;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The executionDataOffset is an offset in the code section defining where this function begins.&lt;br /&gt;
&lt;br /&gt;
=== Executable Data ===&lt;br /&gt;
This section is by far the trickiest section. This is where the actual code the functions are compiled into is stored. The first thing that will be needed is a list of operation codes (OPcodes). These opcodes should be the same for all systems.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
enum OPCodes : char&lt;br /&gt;
{&lt;br /&gt;
         OP_End = 0x0,&lt;br /&gt;
         OP_Return = 0x1,&lt;br /&gt;
         OP_GetUndefined = 0x2,&lt;br /&gt;
         OP_GetZero = 0x3,&lt;br /&gt;
         OP_GetByte = 0x4,&lt;br /&gt;
         OP_GetNegByte = 0x5,&lt;br /&gt;
         OP_GetUnsignedShort = 0x6,&lt;br /&gt;
         OP_GetNegUnsignedShort = 0x7,&lt;br /&gt;
         OP_GetInteger = 0x8,&lt;br /&gt;
         OP_GetFloat = 0x9,&lt;br /&gt;
         OP_GetString = 0xA,&lt;br /&gt;
         OP_GetIString = 0xB,&lt;br /&gt;
         OP_GetVector = 0xC,&lt;br /&gt;
         OP_GetLevelObject = 0xD,&lt;br /&gt;
         OP_GetAnimObject = 0xE,&lt;br /&gt;
         OP_GetSelf = 0xF,&lt;br /&gt;
         OP_GetLevel = 0x10,&lt;br /&gt;
         OP_GetGame = 0x11,&lt;br /&gt;
         OP_GetAnim = 0x12,&lt;br /&gt;
         OP_GetAnimation = 0x13,&lt;br /&gt;
         OP_GetGameRef = 0x14,&lt;br /&gt;
         OP_GetFunction = 0x15,&lt;br /&gt;
         OP_CreateLocalVariables = 0x17,&lt;br /&gt;
         OP_EvalLocalVariableCached1 = 0x19,&lt;br /&gt;
         OP_EvalArray = 0x1A,&lt;br /&gt;
         OP_EvalArrayRef = 0x1C,&lt;br /&gt;
         OP_ClearArray = 0x1D,&lt;br /&gt;
         OP_EmptyArray = 0x1E,&lt;br /&gt;
         OP_GetSelfObject = 0x1F,&lt;br /&gt;
         OP_EvalFieldVariable = 0x20,&lt;br /&gt;
         OP_EvalFieldVariableRef = 0x21,&lt;br /&gt;
         OP_ClearFieldVariable = 0x22,&lt;br /&gt;
         OP_SafeSetWaittillVariableFieldCached = 0x24,&lt;br /&gt;
         OP_clearparams = 0x25,&lt;br /&gt;
         OP_checkclearparams = 0x26,&lt;br /&gt;
         OP_EvalLocalVariableRefCached = 0x27,&lt;br /&gt;
         OP_SetVariableField = 0x28,&lt;br /&gt;
         OP_wait = 0x2B,&lt;br /&gt;
         OP_waittillFrameEnd = 0x2C,&lt;br /&gt;
         OP_PreScriptCall = 0x2D,&lt;br /&gt;
         OP_ScriptFunctionCall = 0x2E,&lt;br /&gt;
         OP_ScriptFunctionCallPointer = 0x2F,&lt;br /&gt;
         OP_ScriptMethodCall = 0x30,&lt;br /&gt;
         OP_ScriptMethodCallPointer = 0x31,&lt;br /&gt;
         OP_ScriptThreadCall = 0x32,&lt;br /&gt;
         OP_ScriptThreadCallPointer = 0x33,&lt;br /&gt;
         OP_ScriptMethodThreadCall = 0x34,&lt;br /&gt;
         OP_ScriptMethodThreadCallPointer = 0x35,&lt;br /&gt;
         OP_DecTop = 0x36,&lt;br /&gt;
         OP_CastFieldObject = 0x37,&lt;br /&gt;
         OP_CastBool = 0x38,&lt;br /&gt;
         OP_BoolNot = 0x39,&lt;br /&gt;
         OP_BoolComplement = 0x3A,&lt;br /&gt;
         OP_JumpOnFalse = 0x3B,&lt;br /&gt;
         OP_JumpOnTrue = 0x3C,&lt;br /&gt;
         OP_JumpOnFalseExpr = 0x3D,&lt;br /&gt;
         OP_JumpOnTrueExpr = 0x3E,&lt;br /&gt;
         OP_jump = 0x3F,&lt;br /&gt;
         OP_jumpback = 0x40,&lt;br /&gt;
         OP_inc = 0x41,&lt;br /&gt;
         OP_dec = 0x42,&lt;br /&gt;
         OP_bit_or = 0x43,&lt;br /&gt;
         OP_bit_ex_or = 0x44,&lt;br /&gt;
         OP_bit_and = 0x45,&lt;br /&gt;
         OP_equality = 0x46,&lt;br /&gt;
         OP_inequality = 0x47,&lt;br /&gt;
         OP_less = 0x48,&lt;br /&gt;
         OP_greater = 0x49,&lt;br /&gt;
         OP_less_equal = 0x4A,&lt;br /&gt;
         OP_greater_equal = 0x4B,&lt;br /&gt;
         OP_shift_left = 0x4C,&lt;br /&gt;
         OP_shift_right = 0x4D,&lt;br /&gt;
         OP_plus = 0x4E,&lt;br /&gt;
         OP_minus = 0x4F,&lt;br /&gt;
         OP_multiply = 0x50,&lt;br /&gt;
         OP_divide = 0x51,&lt;br /&gt;
         OP_mod = 0x52,&lt;br /&gt;
         OP_size = 0x53,&lt;br /&gt;
         OP_waittillmatch = 0x54,&lt;br /&gt;
         OP_waittill = 0x55,&lt;br /&gt;
         OP_notify = 0x56,&lt;br /&gt;
         OP_endon = 0x57,&lt;br /&gt;
         OP_voidCodepos = 0x58,&lt;br /&gt;
         OP_switch = 0x59,&lt;br /&gt;
         OP_endswitch = 0x5A,&lt;br /&gt;
         OP_vector = 0x5B,&lt;br /&gt;
         OP_GetHash = 0x5C,&lt;br /&gt;
         OP_GetSimpleVector = 0x5E,&lt;br /&gt;
         OP_isdefined = 0x5F,&lt;br /&gt;
         OP_vectorscale = 0x60,&lt;br /&gt;
         OP_anglestoup = 0x61,&lt;br /&gt;
	 OP_anglestoright = 0x62,&lt;br /&gt;
	 OP_anglestoforward = 0x63,&lt;br /&gt;
	 OP_angleclamp180 = 0x64,&lt;br /&gt;
	 OP_vectorstoangle = 0x65,&lt;br /&gt;
	 OP_abs = 0x66,&lt;br /&gt;
	 OP_gettime = 0x67,&lt;br /&gt;
	 OP_getdvar = 0x68,&lt;br /&gt;
	 OP_getdvarint = 0x69,&lt;br /&gt;
	 OP_getdvarfloat = 0x6A,&lt;br /&gt;
	 OP_getdvarvec3d = 0x6B,&lt;br /&gt;
	 OP_getdvarred = 0x6C,&lt;br /&gt;
	 OP_getdvargreen = 0x6D,&lt;br /&gt;
	 OP_getdvarblue = 0x6E,&lt;br /&gt;
	 OP_GetFirstArrayKey = 0x70,&lt;br /&gt;
	 OP_GetNextArrayKey = 0x71,&lt;br /&gt;
	 OP_GetUndefined2 = 0x73,&lt;br /&gt;
	 OP_skipdev = 0x7B,&lt;br /&gt;
	 OP_count = 0x7C,&lt;br /&gt;
	 OP_NOP = 0x7F,&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Notice that 0x7B is the highest opcode, but 0x7F is still valid. In truth anything over 0x7B will register as NOP. The executable does some odd jumping around for each OP code, so a recap of each OP code will try to be added. In the following functions &amp;quot;currentFunctionDataOffset&amp;quot; is defined as an integer that points to the current OP code being read. Keep in mind that an OP code is read, the data offset is increased by 1, and then the following code is ran. OP codes are parsed in the order they are read, but if a dump is being done then parts are going to be dumped in reverse order. Here is an example of a series of OP codes...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
OP_PreScriptCall&lt;br /&gt;
OP_GetString		&amp;quot;1350&amp;quot;&lt;br /&gt;
OP_GetString		&amp;quot;scr_veh_health_tank&amp;quot;&lt;br /&gt;
OP_CallBuiltin 		2, &amp;quot;setdvar&amp;quot;&lt;br /&gt;
OP_clearparams&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This would be the &amp;quot;asm&amp;quot; of the GSC, and would look like this...&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
setdvar( &amp;quot;scr_veh_health_tank&amp;quot;, &amp;quot;1350&amp;quot; );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== OP_End ====&lt;br /&gt;
If FunctionDeclaration-&amp;gt;crc32 equals to returned crc then break. This is how you calculate the CRC32 below:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
static const unsigned int kCrc32Table[] = {&lt;br /&gt;
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,&lt;br /&gt;
	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,&lt;br /&gt;
	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,&lt;br /&gt;
	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,&lt;br /&gt;
	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,&lt;br /&gt;
	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,&lt;br /&gt;
	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,&lt;br /&gt;
	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,&lt;br /&gt;
	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,&lt;br /&gt;
	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,&lt;br /&gt;
	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,&lt;br /&gt;
	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,&lt;br /&gt;
	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,&lt;br /&gt;
	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,&lt;br /&gt;
	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,&lt;br /&gt;
	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,&lt;br /&gt;
	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,&lt;br /&gt;
	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,&lt;br /&gt;
	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,&lt;br /&gt;
	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,&lt;br /&gt;
	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,&lt;br /&gt;
	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,&lt;br /&gt;
	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,&lt;br /&gt;
	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,&lt;br /&gt;
	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,&lt;br /&gt;
	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,&lt;br /&gt;
	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,&lt;br /&gt;
	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,&lt;br /&gt;
	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,&lt;br /&gt;
	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,&lt;br /&gt;
	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,&lt;br /&gt;
	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,&lt;br /&gt;
	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,&lt;br /&gt;
	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,&lt;br /&gt;
	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,&lt;br /&gt;
	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,&lt;br /&gt;
	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,&lt;br /&gt;
	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,&lt;br /&gt;
	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,&lt;br /&gt;
	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,&lt;br /&gt;
	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,&lt;br /&gt;
	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,&lt;br /&gt;
	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
unsigned int crc(unsigned char* pData, unsigned int length) {&lt;br /&gt;
unsigned char* pCur = (unsigned char*)pData;&lt;br /&gt;
unsigned int remaining = length, _crc = ~0;&lt;br /&gt;
&lt;br /&gt;
for (; remaining--; ++pCur)&lt;br /&gt;
 _crc = (_crc &amp;gt;&amp;gt; 8) ^ kCrc32Table[(_crc ^ *pCur) &amp;amp; 0xff];&lt;br /&gt;
&lt;br /&gt;
return ~_crc;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For the CRC32 checksum parameters it&#039;s unsigned int crc(functionStart, currentFunctionDataOffset - functionStart). If the returned crc does not equal FunctionDeclaration-&amp;gt;crc32 then write &amp;quot;return;&amp;quot; to the stack.&lt;br /&gt;
&lt;br /&gt;
==== OP_Return ====&lt;br /&gt;
The return OP is exactly as expected. Any OP codes in the stack go after a &amp;quot;return&amp;quot;. There is no data skipped, it is simply a 1 byte opcode. Keep in mind that if the game reaches a return, it leaves the function however for a complete dump, data must continue to be read and sometimes this data is unnecessary.&lt;br /&gt;
==== OP_GetUndefined &amp;amp; OP_GetZero ====&lt;br /&gt;
This simply represents the &amp;quot;undefined&amp;quot;/0 element in GSCs. It is a simple 1 byte opcode, and once read it is put right onto the stack. When dumping from the stack, simply print &amp;quot;undefined&amp;quot;/0 and continue.&lt;br /&gt;
==== OP_GetByte &amp;amp; OP_GetNegByte ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 1 byte. These are 2 byte opcode in that the first byte is the opcode and the second byte is an unsigned value. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegByte should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetUnsignedShort &amp;amp; OP_GetNegUnsignedShort ====&lt;br /&gt;
These are used to hold any numbers that are small enough to be held in 2 byte. After reading the opcode, the following is used to determine the offset of the unsigned short value&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the unsigned short value to use. Then skip another 2 bytes for that value to continue reading. The opcode is added to the stack once read. When dumping from the stack the value is simply printed and then continued. Keep in mind that OP_GetNegUnsignedShort should get a negative symbol before the value is printed.&lt;br /&gt;
==== OP_GetInteger &amp;amp; OP_GetFloat ====&lt;br /&gt;
OP_GetInteger is used for any numbers that are large enough to warrant a signed integer, while OP_GetFloat is used for bigger numbers and decimals. After reading the opcode, the following is used to determine the offset of the value to get&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will be the offset of the value to get, then skip another 4 bytes past the value to continue reading. The opcode is then added to the stack. When dumping the value is simply printed and then continued;&lt;br /&gt;
==== OP_GetString &amp;amp; OP_GetIString ====&lt;br /&gt;
These are very clearly used to reference strings in code. Strings are found by their references. To get the offset of the reference use the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the argument section should be an argument with a reference that is equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. The name of the argument is the offset of the string to use in the string pool from the beginning of the GSC. Add another 2 to currentFunctionDataOffset to skip past the reference to continue reading. Keep in mind that OP_GetIString is used to get localized strings, and a &amp;amp; should be a added before the quotes.&lt;br /&gt;
==== OP_GetLevelObject &amp;amp; OP_GetLevel &amp;amp; OP_GetSelf &amp;amp; OP_GetSelfObject &amp;amp; OP_GetGame &amp;amp; OP_GetGameRef &amp;amp; OP_GetAnimObject ====&lt;br /&gt;
All of these are simple 1 byte opcodes that are added to the stack once they are read. They represent (and should be printed as) the &amp;quot;game&amp;quot;, &amp;quot;level&amp;quot;, &amp;quot;anim&amp;quot; and &amp;quot;self&amp;quot; objects in GSC code.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetAnimation ====&lt;br /&gt;
These are used to reference animations in an animtree that was included to this GSC. The name of the animation is found by a reference. To get the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should be an animtree in the animtree include section that has an animation with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot; at this point. Add another 4 bytes to skip past the reference to continue reading opcodes. After this is read it is added to the stack. When dumping the reference animation name should be found and dumped (without quotes) preceeded by a % sign.&lt;br /&gt;
==== OP_GetFunction ====&lt;br /&gt;
This is used to reference a function without calling it. This allows you to set a variable to a function, and then call the variable later. There should be a function call with a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;, and this is the function to use. This is then added to the stack. After that the following code is performed&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
to continue reading. When dumping the function name should be printed after &amp;quot;::&amp;quot;.&lt;br /&gt;
==== OP_CreateLocalVariable ====&lt;br /&gt;
This opcode is used at the beginning of any function with arguments or local variables to define them. After the opcode is a single byte that is the number to define. Each variable argument is found by getting the reference for it in the argument section. To get the offset of each reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
That gets ran before to find a reference offset. There should be a argument with a reference equal to the &amp;quot;currentFunctionDataOffset&amp;quot;. Then 2 is added to skip past the current reference before the above is started again. The function declaration states the number of arguments, any extra are local variables. Keep in mind the stack should be clear after this is ran.&lt;br /&gt;
==== OP_EvalLocalVariableCached1 &amp;amp; OP_EvalLocalVariableRefCached ====&lt;br /&gt;
This is a simple 2 byte opcode used to reference an argument or local variable. The second byte is the index of the local variable to use, defined by OP_CreateLocalVariable. This is then added to the stack to be dumped. To dump the local variable must be looked up, the argument found and the name referenced.&lt;br /&gt;
==== OP_EvalArray &amp;amp; OP_EvalArrayRef ====&lt;br /&gt;
These are simple 1 byte opcodes used to reference elements in an array. It is simply added to the stack to be dumped. When dumping, the next entity on the stack is the array to use and the next entity is the index in the array (Indexes are not always numbers).&lt;br /&gt;
==== OP_ClearArray ====&lt;br /&gt;
This is a 1 byte opcode used to set an array element to &amp;quot;undefined&amp;quot;. This is not added to the stack, instead the stack is processed. The first entity on the stack is the array to use and the second is the array index. This element is then set to undefined. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_EmptyArray ====&lt;br /&gt;
This is a simple 1 byte opcode used to denote an empty array (&amp;quot;[]&amp;quot;). It is added right to the stack and simply printed when dumping. &lt;br /&gt;
==== OP_EvalFieldVariable &amp;amp; OP_EvalFieldVariableRef ====&lt;br /&gt;
These opcodes are used to reference any field variable. The names of the field variable is found by the offset of a reference. To find the offset of the reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. The opcode is then added to the stack to be dumped later. The next entity on the stack is the item the field variable is for. &lt;br /&gt;
==== OP_ClearFieldVariable ====&lt;br /&gt;
This opcode is used to set a field variable element to &amp;quot;undefined&amp;quot;. The name of the field variable is found by the offset of a reference. To find the offset of a reference&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
There should then be an argument in the argument section that has a reference equal to &amp;quot;currentFunctionDataOffset&amp;quot;. Skip another 2 bytes past the reference to continue reading opcodes. This opcode is not added to the stack, instead the stack is processed. The only entity on the stack should be the item the field variable is for. Once this is processed the stack should be empty. &lt;br /&gt;
==== OP_checkclearparams &amp;amp; OP_clearparams ====&lt;br /&gt;
Used at the beginning of a function with no arguments. Clears the stack without processing it. &lt;br /&gt;
==== OP_SetVariableField ====&lt;br /&gt;
This is a 1 byte opcode used to set an entity to anything else. This is not added to the stack, instead the stack is processed. The first entity on the stack is the entity to set (left side of the &amp;quot;=&amp;quot; sign) with the second being the entity setting with (right side). At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_CallBuiltin ====&lt;br /&gt;
This opcode is used to call a GSC function that is predefined in the executable. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, there should be an entity on the stack for each expected argument. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_ScriptMethodCall ====&lt;br /&gt;
This opcode is used to call a GSC function on an entity that is defined in another GSC. The name of the GSC function is found by a reference. The offset of the reference is actually the offset of this opcode. In the function call section should be a definition with a reference to this opcode. This opcode is then added to the stack to be dumped. When dumping, the first entity on the stack will be the entity the function is being called upon, followed by an entity for each argument in the function. To get to the next opcode, perform the following&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Before adding the last 4, &amp;quot;currentFunctionDataOffset&amp;quot; will point to a value that holds the offset of the function to use in memory.&lt;br /&gt;
==== OP_wait ====&lt;br /&gt;
This is a simple 1 byte opcode used for the &amp;quot;wait()&amp;quot; function. This is not added to the stack, instead the stack is processed. The first (and only) entity on the stack should be the number of milliseconds to wait. At the end of this, the stack should be empty.&lt;br /&gt;
==== OP_waittillframeend ====&lt;br /&gt;
This is a simple 1 byte opcode used for &amp;quot;waittillframeend&amp;quot;. This is not added to the stack, and is always ran with an empty stack.&lt;br /&gt;
==== OP_PreScriptCall ====&lt;br /&gt;
This is a simple 1 byte opcode used before all instructions and is equivalent to NOP.&lt;br /&gt;
==== OP_Script Call Functions ====&lt;br /&gt;
These opcodes are used to call a function and are very similar. The names of the function to call are found by a reference, and for all of these opcodes the reference is the offset of the opcode. &amp;quot;Method&amp;quot; opcodes have an extra entity on the stack as the entity the function is called upon. &amp;quot;Thread&amp;quot; opcodes are threading the function they call. The &amp;quot;Pointer&amp;quot; opcodes do not have a reference with the function&#039;s name, instead the function is a variable and an extra entity is on the stack. There will be an entity on the stack for each expected argument. To read past OP_ScriptFunctionCall, OP_ScriptMethodCall, OP_ScriptMethodCall2, and OP_ScriptMethodThreadCall, do&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
currentFunctionDataOffset += 4;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The &amp;quot;Pointer&amp;quot; opcodes are all 2 byte opcdes. All these opcodes are added to the stack to be dumped. &lt;br /&gt;
==== OP_clearparams ====&lt;br /&gt;
This is a 1 byte opcode and is used most often to process the stack. The stack is simply processed and should be clear by the end of this running.&lt;br /&gt;
==== OP_CastFieldObject ====&lt;br /&gt;
Not very well understood, skipping it seems to work fine.&lt;br /&gt;
==== OP_BoolNot ====&lt;br /&gt;
This is a simple 1 byte opcode used for the logical NOT operator (&amp;quot;!&amp;quot;). This is simply added to the stack to be dumped. When dumping, the next entity on the stack is the value to invert. &lt;br /&gt;
==== OP_jump Codes ====&lt;br /&gt;
Rather than have logical AND and OR operators in this language, it is similar to PPC in that there are &amp;quot;branches&amp;quot; or &amp;quot;jumps&amp;quot;. Rather than using an AND operator, a series of conditional jumps are used to produce the same result. OP_jump is a simple absolute jump value. After reading the opcode,&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; will point to a &amp;quot;short&amp;quot; data value. This will be an offset in the GSC to jump to (Usually just a few bytes away). Skip another 2 bytes past this offset to continue reading opcodes. This opcode is then added to the stack to be dumped. The next entity in the stack is the condition to jump on.&lt;br /&gt;
==== Logical and Bitwise Operators ====&lt;br /&gt;
OP_inc &amp;amp; OP_dec are skipped by performing this operation&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
currentFunctionDataOffset += 2;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
They are added to the stack to be dumped. When dumping, the next member of the stack is the entity to shift, followed by &amp;quot;++&amp;quot; for increase and &amp;quot;--&amp;quot; for decrease.&lt;br /&gt;
&lt;br /&gt;
The next few operators are all 1 byte operators. They are simply added to the stack to be dumped. When dumping, the next entity on the stack is the right side of the operator with the nxt entity being the left side.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;opcode&#039;&#039;&#039;||&#039;&#039;&#039;Operator&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_or||&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_bit_and||&amp;amp;&lt;br /&gt;
|-&lt;br /&gt;
|OP_equality||==&lt;br /&gt;
|-&lt;br /&gt;
|OP_inequality||!=&lt;br /&gt;
|-&lt;br /&gt;
|OP_less||&amp;lt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater||&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|OP_less_equal||&amp;lt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_greater_equal||&amp;gt;=&lt;br /&gt;
|-&lt;br /&gt;
|OP_plus||+&lt;br /&gt;
|-&lt;br /&gt;
|OP_minus||-&lt;br /&gt;
|-&lt;br /&gt;
|OP_multiply||*&lt;br /&gt;
|-&lt;br /&gt;
|OP_divide||/&lt;br /&gt;
|-&lt;br /&gt;
|OP_mod||%&lt;br /&gt;
|}&lt;br /&gt;
==== OP_size ====&lt;br /&gt;
This opcode is used to get the &amp;quot;.size&amp;quot; of an array entity. Simply added to the stack for dumping, the next stack entity is the array entity. &lt;br /&gt;
==== OP_waittillmatch &amp;amp; OP_waittill &amp;amp; OP_notify ====&lt;br /&gt;
These 1 byte opcodes codes are used in combination with OP_endon for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity the function is being referenced to. The constant strings are next on the stack and should be the only remaining items on the stack. Following these opcodes are a OP_SafeSetWaittillVariableFieldCached for each variable to pass (Used to pass data at the point of the sync). This is a 2 byte opcode, with the second byte being the index of the local variable defined at the beginning of the function. &lt;br /&gt;
==== OP_endon ====&lt;br /&gt;
This 1 byte opcode is used in combination with the above codes for cross-thread syncing. Rather than being added to the stack, this processes the stack. The first entity on the stack will be the entity this function is being referenced to. The constant strings to end on are then placed on the stack.&lt;br /&gt;
==== OP_voidCodepos ====&lt;br /&gt;
Equivelent to NOP.&lt;br /&gt;
==== OP_switch &amp;amp; OP_endswitch ====&lt;br /&gt;
When a switch is used by the game, only the needed case is ran at a time. However when dumping, all cases must be processed. There are a few points of interest when using the switch, the first is found by doing&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point &amp;quot;currentFunctionDataOffset&amp;quot; is a partial pointer to an integer, the case definition location (The switch case code is directly after this integer, with the case definitions directly after that). After setting &amp;quot;currentFunctionDataOffset&amp;quot; to this integer, perform this to get to the actual case definitions&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 7;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Currently &amp;quot;currentFunctionDataOffset&amp;quot; will point to directly after the switch case code. The first integer is the switch case count. Following this is 8 bytes for each case in the switch. The first short in these 8 bytes is the &amp;quot;switch case type&amp;quot;. There are currently 2 known switch types, integer (0x80) and string (0). If the type is integer then the short after the type is the index for this case. If the type is a string, then there will be an argument in the argument section with the offset of the short after the type. The 4 bytes after these 2 shorts is the offset for the section of code for this case. If the type is 0 and the short for the reference is 0, then this is the &amp;quot;default&amp;quot; case. The OP_endswitch is found at the end of the section of code for this switch, just before the case defintions. It is a 1 byte opcode, and after reading this the switch should be ended and the case defintions skipped. &lt;br /&gt;
==== OP_vector ====&lt;br /&gt;
This is a simple 1 byte opcode. Vectors are a standard l-type in GSC and simply defined in raw text by doing (number1, number2, number3). Once this opcode is read it is added to the stack to be dumped. When dumping there must be at least 3 more entities on the stack, one for each item in the vector. &lt;br /&gt;
==== OP_GetHash ====&lt;br /&gt;
This opcode is used to reference dvar entities in GSC. In GSC when referencing a dvar it appears as #&amp;quot;dvarName&amp;quot;. Rather than storing the dvarName directly, the hash is stored and any dvar with a matching hash is used. To get the hash, perform&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
currentFunctionDataOffset += 3;&lt;br /&gt;
currentFunctionDataOffset &amp;amp;= 0xFFFFFFFC;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Then &amp;quot;currentFunctionDataOffset&amp;quot; will point to an integer that is the dvar&#039;s hash. This is then added to the stack to be dumped. To continue reading opcodes, skip another 4 bytes past the hash.&lt;br /&gt;
&lt;br /&gt;
The hash they used is DJB2 Hash algorithm. This is the implementation:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
unsigned int DvarHash(const char* dvar) {&lt;br /&gt;
    unsigned int hash = 5381;&lt;br /&gt;
&lt;br /&gt;
    while (*str != 0)&lt;br /&gt;
	hash = (33 * hash) + tolower(*str++);&lt;br /&gt;
&lt;br /&gt;
    return hash;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== OP_GetSimpleVector ====&lt;br /&gt;
This 2 byte opcode is used to store very simple vectors. The second byte in the opcode is the flags for the vector elements. Each element in the vector is 0 by default. The first element is &amp;quot;-1&amp;quot; if the bitflag 0x10 is set, and &amp;quot;1&amp;quot; if 0x20 is set. The second element is &amp;quot;-1&amp;quot; if the bitflag 4 is set, and &amp;quot;1&amp;quot; if 8 is set. The third element is &amp;quot;-1&amp;quot; if the bitflag 1 is set, and &amp;quot;1&amp;quot; if 2 is set.&lt;br /&gt;
&lt;br /&gt;
==== OP_isdefined ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;isDefined()&amp;quot; function. The next entity on the stack is the entity to check for existence.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorscale ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vector_scale()&amp;quot; function. The next entity on the stack is the vector entity to scale. The following entity is the scaler entity.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoup ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToUp()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoright ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToRight()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_anglestoforward ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;anglesToForward()&amp;quot; function. The next entity on the stack is the angles to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_angleclamp180 ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;angleClamp180()&amp;quot; function. The next entity on the stack is the angle to clamp.&lt;br /&gt;
&lt;br /&gt;
==== OP_vectorstoangle ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;vectorsToAngle()&amp;quot; function. The next entity on the stack is the vector to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_abs ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;abs()&amp;quot; or &amp;quot;absolute value&amp;quot; function. The next entity on the stack is the integer to convert.&lt;br /&gt;
&lt;br /&gt;
==== OP_gettime ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getTime()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvar ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvar()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarint ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarInt()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarfloat ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarFloat()&amp;quot; function. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarred ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarRed()&amp;quot; function to grab the red component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvargreen ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarGreen()&amp;quot; function to grab the green component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_getdvarblue ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getDvarBlue()&amp;quot; function to grab the blue component of a color dvar. The next entity on the stack is the dvar to get, typically an OP_GetHash for the dvar&#039;s hash.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetFirstArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getFirstArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_GetNextArrayKey ====&lt;br /&gt;
This is a simple 1 byte opcode that is added to the stack once its read. It is used for the &amp;quot;getNextArrayKey()&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
==== OP_skipdev ==== &lt;br /&gt;
This opcode is used to denote developer code sections. These sections are outlined by &amp;quot;/#&amp;quot; and &amp;quot;#/&amp;quot; in raw text and are only ran when the dvars &amp;quot;developer&amp;quot; and &amp;quot;developer_script&amp;quot; are set to true. The section starts at this opcode, and the end is defined at&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
(++currentFunctionDataOffset) &amp;amp;= 0xFFFFFFFE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
At this point there is a short value that holds the length of this code section at which point the end marker will be.&lt;br /&gt;
&lt;br /&gt;
== Source Format ==&lt;br /&gt;
The source format for GSCs is very well known. Simply a code file (text) with a .gsc extension.&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=478</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=478"/>
		<updated>2014-06-08T23:34:26Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
 struct ipak_header_t&lt;br /&gt;
 {&lt;br /&gt;
 	char identifier[4]; // &amp;quot;IPAK&amp;quot;&lt;br /&gt;
 	unsigned int version; //0x50000&lt;br /&gt;
 	unsigned int fileSize;&lt;br /&gt;
 	unsigned int sectionCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct section_t&lt;br /&gt;
 {&lt;br /&gt;
 	unsigned int sectionIndex; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
 	unsigned int sectionStart;&lt;br /&gt;
 	unsigned int sectionLength;&lt;br /&gt;
 	unsigned int numOfEntries; // each entry is a compressed iwi file in section 2 and entry info in section 1&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_info_t&lt;br /&gt;
 {&lt;br /&gt;
 	u32 hash; // checksum, type?&lt;br /&gt;
 	u32 id;&lt;br /&gt;
 	u32 entryStart; // location of compressed iwi file&lt;br /&gt;
 	u32 entryLength;&lt;br /&gt;
 }; // 16 bytes&lt;br /&gt;
 &lt;br /&gt;
 struct entry_t&lt;br /&gt;
 {&lt;br /&gt;
 	entry_header_t header;&lt;br /&gt;
 	block_info_t blocks[31]; //they can be null, actual number of blocks is header-&amp;gt;blockCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_header_t&lt;br /&gt;
 {&lt;br /&gt;
 	int sizeOfPreviousBlocks : 24; // size of previously decompressed blocks, 0 if it&#039;s the first array of blocks for this file&lt;br /&gt;
 	int blockCount : 8;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct block_info_t&lt;br /&gt;
 {			//enum 0x0 = plaintext, 0x1 = encrypted&lt;br /&gt;
 	unsigned int info; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
 }; // 4 bytes&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=477</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=477"/>
		<updated>2014-06-08T23:34:00Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
 struct ipak_header_t&lt;br /&gt;
 {&lt;br /&gt;
 	char identifier[4]; // &amp;quot;IPAK&amp;quot;&lt;br /&gt;
 	unsigned int version; //0x50000&lt;br /&gt;
 	unsigned int fileSize;&lt;br /&gt;
 	unsigned int sectionCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct section_t&lt;br /&gt;
 {&lt;br /&gt;
 	unsigned int sectionIndex; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
 	unsigned int sectionStart;&lt;br /&gt;
 	unsigned int sectionLength;&lt;br /&gt;
 	unsigned int numOfEntries; // each entry is a compressed iwi file in section 2 and entry info in section 1&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_info_t&lt;br /&gt;
 {&lt;br /&gt;
 	u32 hash; // checksum, type?&lt;br /&gt;
 	u32 id;&lt;br /&gt;
 	u32 entryStart; // location of compressed iwi file&lt;br /&gt;
 	u32 entryLength;&lt;br /&gt;
 }; // 16 bytes&lt;br /&gt;
 &lt;br /&gt;
 struct entry_t&lt;br /&gt;
 {&lt;br /&gt;
 	entry_header_t header;&lt;br /&gt;
 	block_info_t blocks[31]; //they can be null, actual number of blocks is header-&amp;gt;blockCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_header_t&lt;br /&gt;
 {&lt;br /&gt;
:Indented line&lt;br /&gt;
int sizeOfPreviousBlocks : 24; // size of previously decompressed blocks, 0 if it&#039;s the first array of blocks for this file&lt;br /&gt;
 	int blockCount : 8;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct block_info_t&lt;br /&gt;
 {			//enum 0x0 = plaintext, 0x1 = encrypted&lt;br /&gt;
 	unsigned int info; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
 }; // 4 bytes&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=476</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=476"/>
		<updated>2014-06-08T23:32:27Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
 struct ipak_header_t&lt;br /&gt;
 {&lt;br /&gt;
 	char identifier[4]; // &amp;quot;IPAK&amp;quot;&lt;br /&gt;
 	unsigned int version; //0x50000&lt;br /&gt;
 	unsigned int fileSize;&lt;br /&gt;
 	unsigned int sectionCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct section_t&lt;br /&gt;
 {&lt;br /&gt;
 	unsigned int sectionIndex; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
 	unsigned int sectionStart;&lt;br /&gt;
 	unsigned int sectionLength;&lt;br /&gt;
 	unsigned int numOfEntries; // each entry is a compressed iwi file in section 2 and entry info in section 1&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_info_t&lt;br /&gt;
 {&lt;br /&gt;
 	u32 hash; // checksum, type?&lt;br /&gt;
 	u32 id;&lt;br /&gt;
 	u32 entryStart; // location of compressed iwi file&lt;br /&gt;
 	u32 entryLength;&lt;br /&gt;
 }; // 16 bytes&lt;br /&gt;
 &lt;br /&gt;
 struct entry_t&lt;br /&gt;
 {&lt;br /&gt;
 	entry_header_t header;&lt;br /&gt;
 	block_info_t blocks[31]; //they can be null, actual number of blocks is header-&amp;gt;blockCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_header_t&lt;br /&gt;
 {&lt;br /&gt;
int sizeOfPreviousBlocks : 24; // size of previously decompressed blocks, 0 if it&#039;s the first array of blocks for this file&lt;br /&gt;
 	int blockCount : 8;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct block_info_t&lt;br /&gt;
 {			//enum 0x0 = plaintext, 0x1 = encrypted&lt;br /&gt;
 	unsigned int info; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
 }; // 4 bytes&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
	<entry>
		<id>https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=475</id>
		<title>IPAK Files</title>
		<link rel="alternate" type="text/html" href="https://codresearch.dev/index.php?title=IPAK_Files&amp;diff=475"/>
		<updated>2014-06-08T23:31:14Z</updated>

		<summary type="html">&lt;p&gt;Kokole: /* Structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:PAK Files]]&lt;br /&gt;
[[Category:BO2]]&lt;br /&gt;
IPAK&#039;s, implemented in [[:Category:BO2|Black Ops 2]], are basically an archive of compressed image data.&lt;br /&gt;
&lt;br /&gt;
== Structure ==&lt;br /&gt;
Thanks to kokole for the structure.&lt;br /&gt;
 struct ipak_header_t&lt;br /&gt;
 {&lt;br /&gt;
 	char identifier[4]; // &amp;quot;IPAK&amp;quot;&lt;br /&gt;
 	unsigned int version; //0x50000&lt;br /&gt;
 	unsigned int fileSize;&lt;br /&gt;
 	unsigned int sectionCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct section_t&lt;br /&gt;
 {&lt;br /&gt;
 	unsigned int sectionIndex; //enum 0x1 = info, 0x2 = data&lt;br /&gt;
 	unsigned int sectionStart;&lt;br /&gt;
 	unsigned int sectionLength;&lt;br /&gt;
 	unsigned int numOfEntries; // each entry is a compressed iwi file in section 2 and entry info in section 1&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_info_t&lt;br /&gt;
 {&lt;br /&gt;
 	u32 hash; // checksum, type?&lt;br /&gt;
 	u32 id;&lt;br /&gt;
 	u32 entryStart; // location of compressed iwi file&lt;br /&gt;
 	u32 entryLength;&lt;br /&gt;
 }; // 16 bytes&lt;br /&gt;
 &lt;br /&gt;
 struct entry_t&lt;br /&gt;
 {&lt;br /&gt;
 	entry_header_t header;&lt;br /&gt;
 	block_info_t blocks[31]; //they can be null, actual number of blocks is header-&amp;gt;blockCount;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct entry_header_t&lt;br /&gt;
 {&lt;br /&gt;
	int sizeOfPreviousBlocks : 24; // size of previously decompressed blocks, 0 if it&#039;s the first array of blocks for this file&lt;br /&gt;
 	int blockCount : 8;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 struct block_info_t&lt;br /&gt;
 {			//enum 0x0 = plaintext, 0x1 = encrypted&lt;br /&gt;
 	unsigned int info; //(depending on endian) blockSize = (info &amp;amp; 0xFFFF); , compressedFlag = info &amp;gt;&amp;gt; 24;&lt;br /&gt;
 }; // 4 bytes&lt;br /&gt;
&lt;br /&gt;
== Decompression Methods ==&lt;br /&gt;
&lt;br /&gt;
The compression method is just the basic LZO1X compression.&lt;br /&gt;
&lt;br /&gt;
PC:&lt;br /&gt;
 http://pastebin.com/vd9t2U2B&lt;br /&gt;
&lt;br /&gt;
PS3:&lt;br /&gt;
 1.00 t6mp_ps3f.self - 0x6AEA78&lt;br /&gt;
&lt;br /&gt;
XBOX:&lt;br /&gt;
 tu9 default_mp.xex - 0x828E5090&lt;br /&gt;
 tu13 default_mp.xex - 0x828E6308&lt;/div&gt;</summary>
		<author><name>Kokole</name></author>
	</entry>
</feed>