public GameCacheContextGen3(MapFile mapFile, EndianReader reader) { BaseMapFile = mapFile; Version = BaseMapFile.Version; Deserializer = new TagDeserializer(Version); LocalesKey = SetLocalesKey(); StringsKey = SetStringsKey(); TagsKey = SetTagsKey(); NetworkKey = SetNetworkKey(); StringMods = SetStringMods(); LocaleGlobalsSize = SetLocaleGlobalsSize(); LocaleGlobalsOffset = SetLocaleGlobalsOffset(); var interop = mapFile.Header.GetInterop(); if (interop != null && interop.ResourceBaseAddress == 0) { Magic = (int)(interop.RuntimeBaseAddress - mapFile.Header.GetMemoryBufferSize()); } else { mapFile.Header.ApplyMagic(mapFile.Header.GetStringIDsIndicesOffset() - mapFile.Header.GetHeaderSize(mapFile.Version)); var resourcePartition = mapFile.Header.GetPartitions()[(int)CacheFilePartitionType.Resources]; var resourceSection = interop.Sections[(int)CacheFileSectionType.Resource]; Magic = BitConverter.ToInt32(BitConverter.GetBytes(resourcePartition.BaseAddress), 0) - (interop.DebugSectionSize + resourceSection.Size); } if (mapFile.Header.GetTagIndexAddress() == 0) { return; } mapFile.Header.SetTagIndexAddress(BitConverter.ToUInt32(BitConverter.GetBytes(mapFile.Header.GetTagIndexAddress() - Magic), 0)); IndexHeader = mapFile.GetIndexHeader(reader, Magic); Strings = CreateStringTable(reader); IndexItems = CreateCacheIndexTable(reader); LocaleTables = new List <CacheLocaleTable>(); switch (mapFile.Version) { case CacheVersion.Halo3Retail: Resolver = new StringIdResolverHalo3(); break; case CacheVersion.Halo3ODST: Resolver = new StringIdResolverHalo3ODST(); break; case CacheVersion.HaloReach: Resolver = new StringIdResolverHaloReach(); break; default: throw new NotSupportedException(CacheVersionDetection.GetBuildName(mapFile.Version)); } foreach (var language in Enum.GetValues(typeof(GameLanguage))) { LocaleTables.Add(CreateLocaleTable(reader, (GameLanguage)language)); } }
private CacheStringTable CreateStringTable(EndianReader reader) { CacheStringTable table = new CacheStringTable(); table.StringMods = StringMods; reader.SeekTo(BaseMapFile.Header.GetStringIDsIndicesOffset()); int[] indices = new int[BaseMapFile.Header.GetStringIDsCount()]; for (var i = 0; i < BaseMapFile.Header.GetStringIDsCount(); i++) { indices[i] = reader.ReadInt32(); table.Add(""); } reader.SeekTo(BaseMapFile.Header.GetStringIDsBufferOffset()); EndianReader newReader = null; if (StringsKey == "" || StringsKey == null) { newReader = new EndianReader(new MemoryStream(reader.ReadBytes(BaseMapFile.Header.GetStringIDsBufferSize())), reader.Format); } else { reader.BaseStream.Position = BaseMapFile.Header.GetStringIDsBufferOffset(); newReader = new EndianReader(reader.DecryptAesSegment(BaseMapFile.Header.GetStringIDsBufferSize(), StringsKey), reader.Format); } for (var i = 0; i < indices.Length; i++) { if (indices[i] == -1) { table[i] = "<null>"; continue; } newReader.SeekTo(indices[i]); int length; if (i == indices.Length - 1) { length = BaseMapFile.Header.GetStringIDsBufferSize() - indices[i]; } else { length = (indices[i + 1] != -1) ? indices[i + 1] - indices[i] : indices[i + 2] - indices[i]; } if (length == 1) { table[i] = ""; continue; } table[i] = newReader.ReadString(length); } newReader.Close(); newReader.Dispose(); return(table); }