public override void Read(BlamLib.IO.EndianReader s) { int pos = 0; Blam.CacheFile.ValidateHeaderAdjustEndian(s, 0x800); s.Seek(4); Halo1.Version ver = (Halo1.Version)(version = s.ReadInt32()); fileLength = s.ReadInt32(); if (fileLength < s.Length) throw new Debug.ExceptionLog("Compressed map editing not available yet!"); s.ReadInt32(); if (ver == Halo1.Version.PC_Demo) { pos = s.Position; s.Position = 0x5EC; offsetToIndex = s.ReadInt32(); s.Position = pos; } else offsetToIndex = s.ReadInt32(); tagBufferSize = s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); if (ver == Halo1.Version.PC_Demo) { pos = s.Position; s.Position = 0x5E8; name = s.ReadTagString(); s.Position = pos; } else name = s.ReadTagString(); build = s.ReadTagString(); cacheType = (CacheType)s.ReadInt16(); s.ReadInt16(); s.ReadInt32(); // CRC s.ReadInt32(); s.Seek((484 * sizeof(int)) + sizeof(uint), System.IO.SeekOrigin.Current); CacheFile cache = s.Owner as CacheFile; if (ver == Halo1.Version.Xbox) cache.EngineVersion = BlamVersion.Halo1_Xbox; else if (ver == Halo1.Version.PC || ver == Halo1.Version.PC_Demo) { if(s.State == IO.EndianState.Big) cache.EngineVersion = BlamVersion.Halo1_XboxX; else { // Interestingly, HaloPC is build 01.00.00.0564, HA10 is build 01.00.01.0563 // Little if(build == "01.00.01.0563") cache.EngineVersion = BlamVersion.Halo1_PCX; else cache.EngineVersion = BlamVersion.Halo1_PC; } } else if (ver == Halo1.Version.CE) cache.EngineVersion = BlamVersion.Halo1_CE; }
public override void Read(BlamLib.IO.EndianReader s) { Blam.CacheFile.ValidateHeader(s, 0x800); s.Seek(4); version = s.ReadInt32(); if (version != 5) throw new InvalidCacheFileException(s.FileName); fileLength = s.ReadInt32(); int xbox = s.ReadInt32(); // Xbox only field offsetToIndex = s.ReadInt32(); s.ReadInt32(); // stream size s.ReadInt32(); s.ReadInt32(); name = s.ReadTagString(); build = s.ReadTagString(); // Xbox only field. Always '400' cacheType = (CacheType)s.ReadInt16(); s.ReadInt16(); s.ReadInt32(); // CRC s.Seek((485 * sizeof(int)) + sizeof(uint), System.IO.SeekOrigin.Current); CacheFile cf = s.Owner as CacheFile; if (xbox != 0) cf.EngineVersion = BlamVersion.Stubbs_Xbox; else // no way to tell when it's mac, which just seems to use PC maps anyway (byte swaps everything when map is loaded) cf.EngineVersion = BlamVersion.Stubbs_PC; }
public override void Read(BlamLib.IO.EndianReader s) { Blam.CacheFile.ValidateHeader(s, 0x800); s.Seek(4); s.ReadInt32(); // version, should be 5 fileLength = s.ReadInt32(); int xbox = s.ReadInt32(); // Xbox only field offsetToIndex = s.ReadInt32(); s.ReadInt32(); // stream size s.ReadInt32(); s.ReadInt32(); name = s.ReadTagString(); build = s.ReadTagString(); // Xbox only field. Always '400' cacheType = (CacheType)s.ReadInt32(); s.ReadInt32(); // CRC s.Seek((485 * sizeof(int)) + sizeof(uint), System.IO.SeekOrigin.Current); CacheFile cf = s.Owner as CacheFile; if (xbox != 0) cf.EngineVersion = BlamVersion.Stubbs_Xbox; else cf.EngineVersion = BlamVersion.Stubbs_PC; // no way to tell when its mac... }
public static string ReadCString(uint offset, BlamLib.IO.EndianReader io) { if (offset == 0) return string.Empty; uint pos = io.PositionUnsigned; io.Seek(offset); byte btchar = 0; var cstring = new System.Text.StringBuilder(); do { btchar = io.ReadByte(); if (btchar != 0) cstring.Append((char)btchar); } while (btchar != 0); io.Seek(pos); return cstring.ToString(); }
public override void Read(BlamLib.IO.EndianReader s) { CacheFile cache = s.Owner as CacheFile; #region read body groupTagsCount = s.ReadInt32(); groupTagsOffset = (groupTagsAddress = s.ReadUInt32()) - cache.AddressMask; tagCount = s.ReadInt32(); tagsOffset = (address = s.ReadUInt32()) - cache.AddressMask; dependentTagsCount = s.ReadInt32(); dependentTagsOffset = (dependentTagsAddress = s.ReadUInt32()) - cache.AddressMask; s.Seek(sizeof(int) + sizeof(uint) + // seems to always be the same address as the dependent tags sizeof(int), // new to Reach. Only seen as zero so far System.IO.SeekOrigin.Current); s.ReadUInt32(); // crc? s.ReadInt32(); // 'tags' #endregion ReadDependents(s); ReadTagInstances(s); ReadGroupTags(s); #region fixup group tag info for (int x = 0; x < tagCount; x++) { var item = items[x]; if (!item.IsEmpty) { item.GroupTag = groupTags[item.Datum.Index].GroupTag1; item.GroupTagInt = item.GroupTag.ID; item.Fixup((ushort)x); // Fix the hacks Bungie did for Halo3 } } #endregion #region Load tag names using (var buffer = cache.DecryptCacheSegment(CacheSectionType.Tag, cache.HeaderHaloReach.TagNamesBufferOffset, cache.HeaderHaloReach.TagNamesBufferSize)) { string tag_name; foreach (var ci in items) { if (!ci.IsEmpty) { // NOTE, we're recording a buffer relative offset here...since the // cache has it encrypted I don't see the point of having the // offset relative to the cache file ci.TagNameOffset = buffer.PositionUnsigned; tag_name = buffer.ReadCString(); if (tag_name == "") tag_name = "NONE"; } else { ci.TagNameOffset = uint.MaxValue; ci.ReferenceName = DatumIndex.Null; continue; } ci.ReferenceName = cache.References.AddOptimized(ci.GroupTag, tag_name); } } #endregion }
public void Read(BlamLib.IO.EndianReader s) { GameMode = s.ReadInt32(); GameSimulation = (GameSimulation)s.ReadByte(); GameNetworkType = s.ReadByte(); GameTickRate = s.ReadInt16(); GameInstance = s.ReadUInt64(); Unknown010 = s.ReadInt32(); Language = s.ReadInt32(); DeterminismVersion = s.ReadInt32(); MapId.Read(s); CachePath = s.ReadAsciiString(260); InitialZoneSetIndex = s.ReadInt16(); Unknown12A = s.ReadBool(); DumpMachineIndex = s.ReadByte(); Unknown12C = s.ReadBool(); Unknown12D = s.ReadBool(); Unknown12E = s.ReadBool(); s.Seek(1, System.IO.SeekOrigin.Current); GamePlayback = (GamePlayback)s.ReadInt16(); Unknown132 = s.ReadBool(); s.Seek(1, System.IO.SeekOrigin.Current); Unknown134 = s.ReadInt32(); Unknown138 = s.ReadInt32(); CampaignDifficulty = s.ReadInt16(); CampaignInsertionPoint = s.ReadInt16(); CampaignMetagameScoring = s.ReadInt16(); Unknown142 = s.ReadBool(); Unknown143 = s.ReadBool(); PrimarySkulls = s.ReadInt32(); SecondarySkulls = s.ReadInt32(); for (int x = 0; x < Unknown14C.Length; x++) Unknown14C[x] = s.ReadBytes(30); Unknown1C4 = s.ReadBool(); s.Seek(3 + 4, System.IO.SeekOrigin.Current); Unknown1CC = s.ReadBytes(92); EngineVariant.Read(s); s.Seek(4, System.IO.SeekOrigin.Current); MapVariant.Read(s); Game.Read(s); }
protected void ReadTagInstances(BlamLib.IO.EndianReader s) { items = new Cache.CacheItemGen3[tagCount]; s.Seek(tagsOffset, System.IO.SeekOrigin.Begin); for (int x = 0; x < tagCount; x++) (items[x] = new Cache.CacheItemGen3()).Read(s); }
public override void Read(BlamLib.IO.EndianReader s) { if (isLoaded) return; // goto the start if we're leaching off another cache's IO if (IsSharedReference) s.Seek(0); cacheHeader.Read(s); DetermineEngineVersion(); // Shared caches can't be loaded from here if (cacheHeader.SharedType == Cache.SharedType.Shared || cacheHeader.SharedType == Cache.SharedType.Campaign) throw new SharedCacheAccessException(); TagIndexInitializeAndRead(s); isLoaded = true; }
public override void Read(BlamLib.IO.EndianReader s) { DataCacheFile cache = s.Owner as DataCacheFile; type = (DataCacheType)s.ReadInt32(); tagNamesTableOffset = s.ReadInt32(); tagInstancesTableOffset = s.ReadInt32(); tagCount = s.ReadInt32(); items = new DataItem[tagCount]; TagInterface.TagGroup tgroup = null; switch(type) { case DataCacheType.Bitmap: tgroup = TagGroups.bitm; break; case DataCacheType.Sound: tgroup = TagGroups.snd_; break; case DataCacheType.Loc: break; } s.Seek(TagNamesTableOffset, System.IO.SeekOrigin.Begin); DataItem item = null; for (int x = 0; x < TagCount; x++) { item = new DataItem(); items[x] = item; item.GroupTag = tgroup; item.ReferenceName = cache.References.AddOptimized(item.GroupTag, s.ReadCString()); } s.Seek(tagInstancesTableOffset, System.IO.SeekOrigin.Begin); for (int x = 0; x < TagCount; x++) items[x].Read(s); }
public override void Read(BlamLib.IO.EndianReader s) { CacheFileBase cache = s.Owner as CacheFileBase; #region read body groupTagsCount = s.ReadInt32(); groupTagsOffset = (groupTagsAddress = s.ReadUInt32()) - cache.AddressMask; tagCount = s.ReadInt32(); tagsOffset = (address = s.ReadUInt32()) - cache.AddressMask; dependentTagsCount = s.ReadInt32(); dependentTagsOffset = (dependentTagsAddress = s.ReadUInt32()) - cache.AddressMask; s.ReadInt32(); s.ReadUInt32(); // seems to be the same address as the dependent tags s.ReadUInt32(); // crc? s.ReadInt32(); // 'tags' #endregion ReadDependents(s); ReadTagInstances(s); ReadGroupTags(s); #region fixup group tag info for (int x = 0; x < tagCount; x++) { var item = items[x]; if (!item.IsEmpty) { item.GroupTag = groupTags[item.Datum.Index].GroupTag1; item.GroupTagInt = item.GroupTag.ID; item.Fixup((ushort)x); // Fix the hacks Bungie did for Halo3 } } #endregion #region Load tag names s.Seek(cache.HeaderHalo3.TagNamesBufferOffset); string file_name; foreach (var ci in items) { if (!ci.IsEmpty) { ci.TagNameOffset = s.PositionUnsigned; file_name = s.ReadCString(); if (file_name == "") file_name = "NONE"; } else { ci.TagNameOffset = uint.MaxValue; ci.ReferenceName = DatumIndex.Null; continue; } ci.ReferenceName = cache.References.AddOptimized(ci.GroupTag, file_name); } #endregion }
void ReadBeta(BlamLib.IO.EndianReader s) { s.ReadUInt32(); //s.ReadBool(); //s.ReadBool(); // false if it belongs to a untracked build //s.ReadBool(); //s.ReadBool(); // Just read the booleans as a f*****g int... s.ReadInt32(); // Filetime.dwHighDateTime = s.ReadInt32(); // Filetime.dwLowDateTime = s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); #region string id // retail doesn't include the 128 byte per string id table, so nix the members /*stringIdsBufferAlignedOffset = */s.ReadInt32(); stringIdsCount = s.ReadInt32(); stringIdsBufferSize = s.ReadInt32(); stringIdIndicesOffset = s.ReadInt32(); stringIdsBufferOffset = s.ReadInt32(); #endregion #region filetimes? // pretty sure this is a flags field // used to tell which of the following 64bit values // are used. Damn sure this are FILETIME structures, but // hex workshop doesn't like them so I can't be for sure... s.ReadInt32(); Filetime.dwHighDateTime = s.ReadInt32(); Filetime.dwLowDateTime = s.ReadInt32(); if (s.ReadInt32() != 0) flags.Add(CacheHeaderFlags.DependsOnMainMenu); s.ReadInt32(); if (s.ReadInt32() != 0) flags.Add(CacheHeaderFlags.DependsOnShared); s.ReadInt32(); if (s.ReadInt32() != 0) flags.Add(CacheHeaderFlags.DependsOnCampaign); s.ReadInt32(); #endregion name = s.ReadTagString(); s.ReadInt32(); scenarioPath = s.ReadAsciiString(256); needsShared = s.ReadInt32() == 1; #region tag names tagNamesCount = s.ReadInt32(); tagNamesBufferOffset = s.ReadInt32(); tagNamesBufferSize = s.ReadInt32(); tagNameIndicesOffset = s.ReadInt32(); #endregion checksum = s.ReadUInt32(); // 0x2CC s.Seek(32, System.IO.SeekOrigin.Current); // these bytes are always the same baseAddress = s.ReadUInt32(); // expected base address xdkVersion = s.ReadInt32(); // xdk version #region memory partitions memoryPartitions = new Partition[3]; memoryPartitions[0].BaseAddress = s.ReadUInt32(); // address memoryPartitions[0].Size = s.ReadInt32(); // size memoryPartitions[1].BaseAddress = s.ReadUInt32(); // address memoryPartitions[1].Size = s.ReadInt32(); // size memoryPartitions[2].BaseAddress = s.ReadUInt32(); // address memoryPartitions[2].Size = s.ReadInt32(); // size #endregion s.Seek(256, System.IO.SeekOrigin.Current); s.Seek(1004 + sizeof(uint), System.IO.SeekOrigin.Current); Managers.BlamDefinition bdef = Program.GetManager(BlamVersion.Halo3_Beta); uint base_address = (s.Owner as Blam.CacheFile).AddressMask = bdef[BlamVersion.Halo3_Beta].CacheTypes.BaseAddress - (uint)MemoryBufferOffset; offsetToIndex = (int)(tagIndexAddress - base_address); CalculatePartitionOffsets(); }
public void Read(BlamLib.IO.EndianReader s) { s.Seek(4 + 4, System.IO.SeekOrigin.Current); Count.Read(s); Size.Read(s); OffsetReferences.Read(s); OffsetStrings.Read(s); s.Seek(1 + 3, System.IO.SeekOrigin.Current); }
public override void Read(BlamLib.IO.EndianReader s) { bool is_alpha; bool is_pc = false; Blam.CacheFile.ValidateHeader(s, 0x800); #region figure out if this is a alpha map s.Seek(0x120); is_alpha = s.ReadTagString() == "02.06.28.07902"; #endregion #region figure out if this is a pc map if (!is_alpha) { s.Seek(0x24); int test = s.ReadInt32(); if (test == -1 || (test != 0 && test < s.Length)) is_pc = true; } #endregion s.Seek(4); version = s.ReadInt32(); fileLength = s.ReadInt32(); s.ReadInt32(); offsetToIndex = s.ReadInt32(); indexStreamSize = s.ReadInt32(); tagBufferSize = s.ReadInt32(); // size of the tag data, excluding the bsp data s.ReadInt32(); // max size: 0x3200000, indexStreamSize+tagBufferSize if(is_pc) { PcFields.VirtualAddress = s.ReadUInt32(); // virtual base address PcFields.TagDependencyGraphOffset = s.ReadInt32(); // buffer offset (starts right before tag index, 512 byte aligned). not shared? should equal -1 PcFields.TagDependencyGraphSize = s.ReadUInt32(); // buffer size. not shared? should be zero. Max: 0x100000 } sourceFile = s.ReadAsciiString(256); build = s.ReadTagString(); cacheType = (Blam.CacheType)s.ReadInt32(); // SP Filesize Max: 0x11800000 // MP Filesize Max: 0x5000000 // Mainmenu Filesize Max: 0x20800000 // Shared Filesize Max: 0xB400000 // Single Player Shared Filesize Max: 0x20800000 s.ReadInt32(); // cache resource (tag) crc s.ReadInt32(); // boolean, set to true in pc when building cache s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); // count of some sort? only on the xbox // offset, then size // (size+0xFFF) & 0xFFFFF000 // test that with 0x1FF, if true, or with 0x1FF then add 1 s.ReadInt32(); // begins with 0x200 bytes of a chunk of the tag filenames table and ends with the same s.ReadInt32(); // has something to do with bitmaps. the bigger the file, the bigger this is #region string id // each string this buffer is aligned to 128 characters (the max length + 1 of a string_id) /*stringIdsBufferAlignedOffset = */s.ReadInt32(); stringIdsCount = s.ReadInt32(); stringIdsBufferSize = s.ReadInt32(); stringIdIndicesOffset = s.ReadInt32(); stringIdsBufferOffset = s.ReadInt32(); #endregion s.ReadInt32(); // 4 bools Filetime.dwHighDateTime = s.ReadInt32(); Filetime.dwLowDateTime = s.ReadInt32(); /*MainmenuFiletime.dwHighDateTime*/ SharedFiletimes[0].dwHighDateTime = s.ReadInt32(); /*MainmenuFiletime.dwLowDateTime = */ SharedFiletimes[0].dwLowDateTime = s.ReadInt32(); /*SharedFiletime.dwHighDateTime*/ SharedFiletimes[1].dwHighDateTime = s.ReadInt32(); /*SharedFiletime.dwLowDateTime*/ SharedFiletimes[1].dwLowDateTime = s.ReadInt32(); /*SharedSingleplayerFiletime.dwHighDateTime*/ SharedFiletimes[2].dwHighDateTime = s.ReadInt32(); /*SharedSingleplayerFiletime.dwLowDateTime*/ SharedFiletimes[2].dwLowDateTime = s.ReadInt32(); name = s.ReadTagString(); s.ReadInt32(); // dword, but unused scenarioPath = s.ReadAsciiString(256); // minor version needsShared = s.ReadInt32() == 1; // doesn't exist on the pc #region tag names tagNamesCount = s.ReadInt32(); // not used in alpha tagNamesBufferOffset = s.ReadInt32(); // not used in alpha tagNamesBufferSize = s.ReadInt32(); // not used in alpha tagNameIndicesOffset = s.ReadInt32(); // not used in alpha #endregion if (is_pc) { // s_cache_language_pack PcFields.LanguagePacksOffset = s.ReadInt32(); // offset, shared database = -1 // sizeof(s_cache_language_pack) * LanguageType.kMax PcFields.LanguagePacksSizeOf = s.ReadUInt32(); // sizeof, shared database = 0 // secondary sound gestalt PcFields.SecondarySoundGestalt.Read(s); // shared database = -1 // fast geometry load region PcFields.FastLoadGeometryBlockOffset = s.ReadInt32(); // offset to a cache block resource PcFields.FastLoadGeometryBlockSize = s.ReadUInt32(); // sizeof entire cache block resources partition. max size: 0x4000000 checksum = s.ReadUInt32(); // another xor checksum // sbsp // - data 0x28C: global_structure_physics_struct->MoppCode // - data 0x2BC: global_structure_physics_struct->BreakableSurfacesMoppCode // - block 0xD4: structure_bsp_cluster_block // * data 0xC4: "Collision mopp Code" // * block 0x54: structure_bsp_cluster_data_block_new // - data 0x3C: global_geometry_section_struct->"Visibility mopp Code" // phmo // - data 0xE8: "mopp codes" // coll // - block 0x28: collision_model_region_block // * block 0x04: collision_model_permutation_block // - block 0x10: collision_bsp_physics_block // * data 0x64: "mopp Code Data" // mode // - block 0x30: render_model_section_block // * block 0x34: render_model_section_data_block // - data 0x3C: global_geometry_section_struct->"Visibility mopp Code" // ltmp // - block 0x80: structure_lightmap_group_block // * block 0x30: lightmap_geometry_section_block // - block 0x54: lightmap_geometry_section_cache_data_block // * data 0x3C: global_geometry_section_struct->"Visibility mopp Code" // * block 0x48: lightmap_geometry_section_block // - block 0x54: lightmap_geometry_section_cache_data_block // * data 0x3C: global_geometry_section_struct->"Visibility mopp Code" PcFields.MoppCodesChecksum = s.ReadUInt32(); // shared databases = 0 s.Seek(1284 + sizeof(uint), System.IO.SeekOrigin.Current); } else { checksum = s.ReadUInt32(); s.Seek(1320 + sizeof(uint), System.IO.SeekOrigin.Current); } CacheFile cf = s.Owner as CacheFile; if (is_pc) cf.EngineVersion = BlamVersion.Halo2_PC; else if (build == "02.08.28.09214") cf.EngineVersion = BlamVersion.Halo2_Epsilon; else if (is_alpha) cf.EngineVersion = BlamVersion.Halo2_Alpha; else cf.EngineVersion = BlamVersion.Halo2_Xbox; }
//PAD16 #region IStreamable Members public virtual void Read(BlamLib.IO.EndianReader s) { MiscOptions.Read(s); RespawnOptions.Read(s); SocialFlags = s.ReadUInt16(); SocialTeamChanging = s.ReadInt16(); MapOverrides.Read(s); Unknown0A8 = s.ReadUInt16(); TeamScoringMethod = s.ReadInt16(); Unknown0AC = s.ReadUInt16(); s.Seek(2, System.IO.SeekOrigin.Current); }
public override void Read(BlamLib.IO.EndianReader s) { base.Read(s); ScoreToWin = s.ReadInt16(); Flags = s.ReadUInt16(); KillPoints = s.ReadByte(); TakedownPoints = s.ReadByte(); KillAsVipPoints = s.ReadByte(); VipDeathPoints = s.ReadByte(); DestinationArrivalPoints = s.ReadByte(); SuicidePoints = s.ReadByte(); BetrayalPoints = s.ReadByte(); VipSuicidePoints = s.ReadByte(); VipSelection = s.ReadByte(); ZoneMovement = s.ReadByte(); ZoneOrder = s.ReadByte(); s.Seek(1, System.IO.SeekOrigin.Current); InfluenceRadius = s.ReadInt16(); VipTraits.Read(s); ProximityTraits.Read(s); VipTeamTraits.Read(s); }
public void Read(BlamLib.IO.EndianReader s) { MovementSpeed = s.ReadByte(); Gravity = s.ReadByte(); VehicleUsage = s.ReadByte(); s.Seek(1, System.IO.SeekOrigin.Current); }
public void Read(BlamLib.IO.EndianReader s) { DamageResistance = s.ReadByte(); ShieldRechargeRate = s.ReadByte(); Vampirism = s.ReadByte(); HeadshotImmunity = s.ReadByte(); ShieldMultiplier = s.ReadByte(); s.Seek(3, System.IO.SeekOrigin.Current); }
public override void Read(BlamLib.IO.EndianReader s) { base.Read(s); MapId = s.ReadInt32(); ScenarioType = s.ReadInt32(); Names.Read(s); Descriptions.Read(s); BlfName = s.ReadAsciiString(256); FileName = s.ReadAsciiString(256); MapIndex = s.ReadInt32(); Unknown1118 = s.ReadInt32(); Unknown111C = s.ReadByte(); Unknown111D = s.ReadByte(); MaxTeams = s.ReadBytes(11); Unknown1129 = s.ReadByte(); s.Seek(2, System.IO.SeekOrigin.Current); Unknown112C = s.ReadUInt32(); foreach (CheckpointData cp in Checkpoints) cp.Read(s); }
void ReadGroupTags(BlamLib.IO.EndianReader s) { groupTags = new CacheItemGroupTag[groupTagsCount]; s.Seek(groupTagsOffset, System.IO.SeekOrigin.Begin); for (int x = 0; x < groupTagsCount; x++) (groupTags[x] = new CacheItemGroupTag()).Read(s); }
public override void Read(BlamLib.IO.EndianReader s) { CacheFile cache = s.Owner as CacheFile; tagsOffset = (uint)(cache.Header.OffsetToIndex + cache.HeaderHalo2.IndexStreamSize); bool is_alpha = cache.EngineVersion == BlamVersion.Halo2_Alpha; bool is_echo = cache.EngineVersion == BlamVersion.Halo2_Epsilon; bool is_pc = cache.EngineVersion == BlamVersion.Halo2_PC; bool is_mp = cache.HeaderHalo2.CacheType == CacheType.Multiplayer; Managers.BlamDefinition bdef = Program.GetManager(cache.EngineVersion); uint tags_addressmask; if(!is_pc) { cache.AddressMask = bdef[cache.EngineVersion].CacheTypes.BaseAddress - (uint)cache.Header.OffsetToIndex; tags_addressmask = (uint)(cache.Header.OffsetToIndex + cache.HeaderHalo2.IndexStreamSize); } else { // pc maps use virtual addresses which are actually offsets relative to // the start of the tag memory buffer. since these are offsets and not actually // addresses which we would normally mask the base off of, we have to do some // number magic so our subtraction operations actually end up working in reverse // to get the correct file offset tags_addressmask = 0 - (uint)cache.Header.OffsetToIndex; cache.AddressMask = tags_addressmask; } #region version dependant loading if (is_alpha) { groupTagsAddress = address = s.ReadUInt32(); groupTagsCount = 0; scenario.Read(s); s.ReadInt32(); // crc tagCount = s.ReadInt32(); items = new CacheItem[tagCount]; s.ReadInt32(); // 'tags' } else if(is_pc) { groupTagsAddress = s.ReadPointer(); // offset (relative to the tag index offset) groupTagsCount = s.ReadInt32(); uint offset = s.ReadPointer(); // offset (relative to the tag index offset) to the tag entries scenario.Read(s); gameGlobals.Read(s); s.ReadInt32(); // crc tagCount = s.ReadInt32(); items = new CacheItem[tagCount]; s.ReadInt32(); // 'tags' s.Seek(offset /*- 32, System.IO.SeekOrigin.Current*/); // go to the first tag entry } else { groupTagsAddress = s.ReadUInt32(); groupTagsCount = s.ReadInt32(); address = s.ReadUInt32(); scenario.Read(s); gameGlobals.Read(s); s.ReadInt32(); // crc tagCount = s.ReadInt32(); items = new CacheItem[tagCount]; s.ReadInt32(); // 'tags' s.Seek(groupTagsCount * 12, System.IO.SeekOrigin.Current); // go to the first tag entry } this.groupTagsOffset = this.groupTagsAddress - s.BaseAddress; #endregion CacheItem item; uint temp_pos = 0; uint sbsp_offset = 0; DatumIndex[] ltmps = null; Tags.scenario_structure_bsp_reference_block bsp_block = new Tags.scenario_structure_bsp_reference_block(); if (is_pc) // MP maps need this adjustment cache.AddressMask = tags_addressmask += cache.HeaderHalo2.PcFields.VirtualAddress; for (int x = 0; x < items.Length; x++) { item = new CacheItem(); items[x] = item; if (is_alpha) item.ReadAlpha(s); else item.Read(s); if (item.Location == ItemLocation.Unknown) items[x] = CacheItem.Null; else if (is_pc && item.HasExternalData) HasExternalTags = true; } if (!is_pc) { // While the tag definitions come right after the tag header in a cache file, when // finally loaded into game memory this isn't the case. The 'stream' size of the tag // header is how much actual memory is used by map's generated the tag header, but the // map's tag header may not utilize the entire memory space dedicated to it in game memory. // So, the game would read the tag header data using the offset and 'stream' size data from // the cache header, then it would seek to offset+stream_size to get to the tag definitions // which it would then read into game memory at the memory location defined by 'address' tags_addressmask = items[0].Address - tags_addressmask; cache.AddressMask = tags_addressmask; for (int x = 0; x < items.Length; x++) { item = items[x]; item.Offset = (int)(item.Address - tags_addressmask); #region on scnr tag if (!is_alpha && !is_echo && TagGroups.scnr.ID == item.GroupTag.ID) { temp_pos = s.PositionUnsigned; //if (is_alpha || is_echo) // s.Seek(item.Offset + 828); //else s.Seek(item.Offset + 528); bspTags = new Item[s.ReadInt32()]; sbsp_offset = s.ReadPointer(); ltmps = new DatumIndex[bspTags.Length]; s.Seek(temp_pos); } #endregion #region on sbsp tag else if (!is_alpha && !is_echo && TagGroups.sbsp.ID == item.GroupTag.ID) { temp_pos = s.PositionUnsigned; s.Seek(sbsp_offset + (uint)(bspCount * Halo2.Tags.scenario_structure_bsp_reference_block.kRuntimeSizeOf)); bspTags[bspCount] = item; bsp_block.Read(cache); if (bsp_block.RuntimeOffset != 0) { item.Offset = bsp_block.RuntimeOffset; item.Size = bsp_block.RuntimeSize; item.Address = (uint)bsp_block.RuntimeAddress.Value; //cache.BspAddressMasks.Add((uint)(item.Address - item.Offset)); } ltmps[bspCount] = bsp_block.Lightmap.Datum; item.BspIndex = bspCount++; s.Seek(temp_pos); } #endregion } } #region alpha tag name code if (is_alpha) { // following the tag datums in alpha builds is the tag names buffer foreach (Halo2.CacheItem ci in items) { ci.TagNameOffset = s.PositionUnsigned; ci.ReferenceName = cache.References.AddOptimized(ci.GroupTag, s.ReadCString()); } } #endregion #region retail tag name & bsp offset fixup code else { // Build the absolute tag name offsets s.Seek(cache.HeaderHalo2.TagNameIndicesOffset); int[] offsets = new int[tagCount]; for (int x = 0; x < offsets.Length; x++) { int offset = s.ReadInt32(); // Offset will be -1 if the tag in question is 'null' if (offset != -1) offset += cache.HeaderHalo2.TagNamesBufferOffset; offsets[x] = offset; } // Fixup all tag instances which are named for (int x = 0; x < tagCount; x++) { if (offsets[x] != -1) FixupTagInstanceHeaderName(cache, items[x], offsets[x], s); } // PC maps store all zones in the tag memory, they don't need to swap out and thus don't // need any fix ups (durrr, PCs have loltons of RAM) if (!is_pc && !is_echo) { var head = new Halo2.Tags.scenario_structure_bsps_header(); foreach (CacheItem tmp_item in bspTags) { s.Seek(tmp_item.Offset); head.Read(cache); // bsp uint bsp_address_mask = head.FixupBspInstanceHeader(tmp_item, s.Position); cache.BspAddressMasks.Add(bsp_address_mask); // ltmp DatumIndex ltmp_datum = ltmps[tmp_item.BspIndex]; if (ltmp_datum != DatumIndex.Null) head.FixupLightmapInstanceHeader(this.items[ltmp_datum.Index], tmp_item); } } } #endregion }
public override void Read(BlamLib.IO.EndianReader s) { bool is_beta = false; bool is_odst = !((s.Owner as Blam.CacheFile).EngineVersion == BlamVersion.Halo3); Blam.CacheFile.ValidateHeader(s, kSizeOf); s.Seek(4); version = s.ReadInt32(); is_beta = version == 9; if (version != 9 && version != 11) throw new InvalidCacheFileException(s.FileName); fileLength = s.ReadInt32(); s.ReadInt32(); tagIndexAddress = s.ReadUInt32(); memoryBufferOffset = s.ReadInt32(); memoryBufferSize = s.ReadInt32(); sourceFile = s.ReadAsciiString(256); build = s.ReadTagString(); cacheType = (Blam.CacheType)s.ReadInt16(); if (is_beta) { s.ReadInt16(); sharedType = Cache.SharedType.Beta; ReadBeta(s); return; } else sharedType = (Cache.SharedType)s.ReadInt16(); s.ReadBool(); s.ReadBool(); // false if it belongs to a untracked build s.ReadBool(); s.ReadByte(); // appears to be an ODST-only field s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); s.ReadInt32(); #region string id table // 0x158 // old 128 byte aligned string table not used after the Delta builds of Halo 3 stringIdsCount = s.ReadInt32(); stringIdsBufferSize = s.ReadInt32(); // cstring buffer total size in bytes stringIdIndicesOffset = s.ReadInt32(); stringIdsBufferOffset = s.ReadInt32(); // cstring buffer #endregion #region filetimes? // pretty sure this is a flags field // used to tell which of the following 64bit values // are used. Damn sure this are FILETIME structures, but // hex workshop doesn't like them so I can't be for sure... needsShared = s.ReadInt32() != 0; // just a little 'hack' if you will. if zero, the map is self reliant, so no worries Filetime.dwHighDateTime = s.ReadInt32(); Filetime.dwLowDateTime = s.ReadInt32(); if (s.ReadInt32() != 0) flags.Add(CacheHeaderFlags.DependsOnMainMenu); s.ReadInt32(); if (s.ReadInt32() != 0) flags.Add(CacheHeaderFlags.DependsOnShared); s.ReadInt32(); if (s.ReadInt32() != 0) flags.Add(CacheHeaderFlags.DependsOnCampaign); s.ReadInt32(); #endregion name = s.ReadTagString(); s.ReadInt32(); scenarioPath = s.ReadAsciiString(256); s.ReadInt32(); // minor version, normally not used #region tag names tagNamesCount = s.ReadInt32(); tagNamesBufferOffset = s.ReadInt32(); // cstring buffer tagNamesBufferSize = s.ReadInt32(); // cstring buffer total size in bytes tagNameIndicesOffset = s.ReadInt32(); #endregion checksum = s.ReadUInt32(); // 0x2C4 s.Seek(32, System.IO.SeekOrigin.Current); // these bytes are always the same baseAddress = s.ReadUInt32(); // expected base address xdkVersion = s.ReadInt32(); // xdk version #region memory partitions // 0x2E8 // memory partitions memoryPartitions = new Partition[6]; memoryPartitions[0].BaseAddress = s.ReadUInt32(); // cache resource buffer memoryPartitions[0].Size = s.ReadInt32(); // readonly memoryPartitions[1].BaseAddress = s.ReadUInt32(); // sound cache resource buffer memoryPartitions[1].Size = s.ReadInt32(); memoryPartitions[2].BaseAddress = s.ReadUInt32(); // global tags buffer memoryPartitions[2].Size = s.ReadInt32(); memoryPartitions[3].BaseAddress = s.ReadUInt32(); // shared tag blocks? memoryPartitions[3].Size = s.ReadInt32(); memoryPartitions[4].BaseAddress = s.ReadUInt32(); // address memoryPartitions[4].Size = s.ReadInt32(); // readonly memoryPartitions[5].BaseAddress = s.ReadUInt32(); // map tags buffer memoryPartitions[5].Size = s.ReadInt32(); #endregion int count = s.ReadInt32(); s.Seek(12, System.IO.SeekOrigin.Current); // these bytes are always the same // if there is a hash in the header, this is the ONLY // place where it can be s.Seek(20 /*SHA1*/ + 40 + 256 /*RSA*/, System.IO.SeekOrigin.Current); // ??? // 0x46C cacheInterop.Read(s); cacheInterop.PostprocessForCacheRead(kSizeOf); s.Seek(16, System.IO.SeekOrigin.Current); // GUID?, these bytes are always the same. ODST is different from Halo 3 #region blah 1 // 0x4AC // campaign has a shit load of these // but shared doesn't nor mainmenu // I compared the sc110 french and english and both have the SAME counts and element data. So // I don't think this is a hash or something. At least, if it is, it's not runtime relative so // nothing we have to worry about s.ReadInt16(); // I've only seen this be two different values (besides zero). count = s.ReadInt16(); s.ReadInt32(); // seems to always be zero CompressionGuid = new Guid(s.ReadBytes(16)); s.Seek(count * 28, System.IO.SeekOrigin.Current); // seek past the elements // dword // long // buffer [0x14] (probably a sha1 hash) s.Seek((320 - count) * 28, System.IO.SeekOrigin.Current); // seek past the unused elements #endregion #region blah 2 { // 0x27C4 // This on the other hand, sc110 french and english had MINOR differences. Those differences were in // DWORDs @ 0x4 and 0x8 // 005 - 1 // 010 - 3 // 020 - 3 // 030 - 2 // 040 - 2 // 050 - 2 // 070 - 3 // 100 - 3 // 110 - 2 // 120 - 2 // 130 - 1 // c100 - 1 // c200 - 1 // h100 - 9 // l200 - 7 // l300 - 8 // sc100 - 5 // sc110 - 5 // sc120 - 6 // sc130 - 6 // sc140 - 6 // sc150 - 6 // going to punt and just assume there is a max count of 10 of these possible // maybe related to bsp\'zones'? int blah2_sizeof = !is_odst ? 172 : 180; count = (int)(s.ReadUInt32() >> 24); // did someone forget to f*****g byte swap something? s.Seek(count * blah2_sizeof, System.IO.SeekOrigin.Current); // seek past the elements s.Seek((10 - count) * blah2_sizeof, System.IO.SeekOrigin.Current); // seek past the unused elements } #endregion s.Seek((!is_odst ? 380 : 300) + sizeof(uint), System.IO.SeekOrigin.Current); // zero ReadPostprocessForInterop(); ReadPostprocessForBaseAddresses(s); }
public override void Read(BlamLib.IO.EndianReader s) { if (isLoaded) return; // goto the start if we're leaching off another cache's IO if (IsSharedReference) s.Seek(0); cacheHeader.Read(s); TagIndexInitializeAndRead(s); isLoaded = true; }
void ReadGroupTags(BlamLib.IO.EndianReader s) { groupTags = CreateEngineItemGroupTags(groupTagsCount); s.Seek(groupTagsOffset, System.IO.SeekOrigin.Begin); for (int x = 0; x < groupTagsCount; x++) (groupTags[x] = CreateEngineItemGroupTag()).Read(s); }
public Base VariantOptions; // 0x160 #region IStreamable Members public void Read(BlamLib.IO.EndianReader s) { GameEngineIndex = (GameEngineType)s.ReadInt32(); _vtable = s.ReadUInt32(); Unknown008 = s.ReadInt32(); Header.Read(s); switch(GameEngineIndex) { case GameEngineType.Ctf: VariantOptions = new Ctf(); break; case GameEngineType.Slayer: VariantOptions = new Slayer(); break; case GameEngineType.Oddball: VariantOptions = new Oddball(); break; case GameEngineType.King: VariantOptions = new King(); break; case GameEngineType.Sandbox: VariantOptions = new Sandbox(); break; case GameEngineType.Vip: VariantOptions = new Vip(); break; case GameEngineType.Juggernaut: VariantOptions = new Juggernaut(); break; case GameEngineType.Territories: VariantOptions = new Teritories(); break; case GameEngineType.Assault: VariantOptions = new Assault(); break; case GameEngineType.Infection: VariantOptions = new Infection(); break; default: throw new Debug.Exceptions.UnreachableException(); } VariantOptions.Read(s); s.Seek(0x160 - VariantOptions.Sizeof, System.IO.SeekOrigin.Current); }
protected void TagIndexInitializeAndRead(BlamLib.IO.EndianReader s) { base.StringIdManagerInitializeAndRead(); base.InitializeReferenceManager(s.FileName); base.InitializeTagIndexManager(); s.Seek(cacheHeader.OffsetToIndex, System.IO.SeekOrigin.Begin); cacheIndex.Read(s); }
public void Read(BlamLib.IO.EndianReader s) { Valid = s.ReadBool(); PrimaryColor = s.ReadByte(); SecondaryColor = s.ReadByte(); TertiaryColor = s.ReadByte(); PlayerModelChoice = s.ReadByte(); ForegroundEmblem = s.ReadByte(); BackgroundEmblem = s.ReadByte(); EmblemFlags = s.ReadByte(); EmblemPrimaryColor = s.ReadByte(); EmblemSecondaryColor = s.ReadByte(); EmblemBackgroundColor = s.ReadByte(); ModelChoices[0] = s.ReadBytes(4); ModelChoices[1] = s.ReadBytes(4); ServiceTag = s.ReadUnicodeString(4); s.Seek(sizeof(ushort), System.IO.SeekOrigin.Current); // alignment }
public override void Read(BlamLib.IO.EndianReader s) { if (!isMemoryMap) Header.Read(s); if (!isMemoryMap) s.Seek(Header.OffsetToIndex, System.IO.SeekOrigin.Begin); else s.Seek(Program.GetManager(engineVersion)[engineVersion].CacheTypes.BaseAddress, System.IO.SeekOrigin.Begin); base.InitializeReferenceManager(s.FileName); base.InitializeTagIndexManager(); cacheIndex.Read(s); }
protected void ReadDependents(BlamLib.IO.EndianReader s) { DependentDatums = new DatumIndex[dependentTagsCount]; s.Seek(dependentTagsOffset, System.IO.SeekOrigin.Begin); for (int x = 0; x < dependentTagsCount; x++) { s.Seek(sizeof(uint), System.IO.SeekOrigin.Current); // group tag DependentDatums[x].Read(s); } }
public override void Read(BlamLib.IO.EndianReader s) { base.Read(s); EndianId = s.ReadUInt16(); TypeString = s.ReadTagString(); s.Seek(2, System.IO.SeekOrigin.Current); }
public void Read(BlamLib.IO.EndianReader s) { Valid = s.ReadBool(); LeftGame = s.ReadBool(); UserIndex = s.ReadInt16(); ControllerIndex = s.ReadInt16(); s.Seek(2, System.IO.SeekOrigin.Current); MachineId = s.ReadBytes(6); Unknown000E = s.ReadUInt64(); s.Seek(2, System.IO.SeekOrigin.Current); Data.Read(s); MatchData.Read(s); }