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 CacheIndexTable CreateCacheIndexTable(EndianReader reader) { CacheIndexTable indexTable = new CacheIndexTable(); indexTable.ClassList = new List <TagClass>(); #region Read Class List reader.SeekTo(IndexHeader.TagGroupsOffset); for (int i = 0; i < IndexHeader.TagGroupCount; i++) { var tc = new TagClass() { ClassCode = reader.ReadString(4), Parent = reader.ReadString(4), Parent2 = reader.ReadString(4), StringID = reader.ReadInt32() }; indexTable.ClassList.Add(tc); } #endregion #region Read Tags Info reader.SeekTo(IndexHeader.TagsOffset); for (int i = 0; i < IndexHeader.TagCount; i++) { var classIndex = reader.ReadInt16(); var tagClass = classIndex == -1 ? null : indexTable.ClassList[classIndex]; string groupName = classIndex == -1 ? "" : Strings.GetItemByID(tagClass.StringID); CacheIndexItem item = new CacheIndexItem(classIndex, (reader.ReadInt16() << 16) | i, reader.ReadInt32() - Magic, i, tagClass, groupName); indexTable.Add(item); } #endregion #region Read Indices reader.SeekTo(BaseMapFile.Header.GetTagNamesIndicesOffset()); int[] indices = new int[IndexHeader.TagCount]; for (int i = 0; i < IndexHeader.TagCount; i++) { indices[i] = reader.ReadInt32(); } #endregion #region Read Names reader.SeekTo(BaseMapFile.Header.GetTagNamesBufferOffset()); EndianReader newReader = null; if (TagsKey == "" || TagsKey == null) { newReader = new EndianReader(new MemoryStream(reader.ReadBytes(BaseMapFile.Header.GetTagNamesBufferSize())), EndianFormat.BigEndian); } else { reader.BaseStream.Position = BaseMapFile.Header.GetTagNamesBufferOffset(); newReader = new EndianReader(reader.DecryptAesSegment(BaseMapFile.Header.GetTagNamesBufferSize(), TagsKey), EndianFormat.BigEndian); } for (int i = 0; i < indices.Length; i++) { if (indices[i] == -1) { indexTable[i].Name = "<null>"; continue; } newReader.SeekTo(indices[i]); int length; if (i == indices.Length - 1) { length = BaseMapFile.Header.GetTagNamesBufferSize() - indices[i]; } else { if (indices[i + 1] == -1) { int index = -1; for (int j = i + 1; j < indices.Length; j++) { if (indices[j] != -1) { index = j; break; } } length = (index == -1) ? BaseMapFile.Header.GetTagNamesBufferSize() - indices[i] : indices[index] - indices[i]; } else { length = indices[i + 1] - indices[i]; } } if (length == 1) { indexTable[i].Name = "<blank>"; continue; } if (length < 0) { int i0 = indices[i]; int i1 = indices[i + 1]; int i2 = indices[i + 2]; int i3 = indices[i + 3]; } indexTable[i].Name = newReader.ReadString(length); } newReader.Close(); newReader.Dispose(); #endregion return(indexTable); }