public CacheSegmenter(IGen3CacheFile cache) { if (cache.CacheType < CacheType.Halo3Retail || cache.Metadata.IsPreRelease) { throw new NotSupportedException(); } this.cache = cache; var debugTranslator = new SectionAddressTranslator(cache, 0); var resourceTranslator = new SectionAddressTranslator(cache, 1); var metadataTranslator = new SectionAddressTranslator(cache, 2); var localeTranslator = new SectionAddressTranslator(cache, 3); //header segments.Add(new Segment(0, cache.GetHeaderSize(), 1)); //eof segments.Add(new Segment((int)cache.Header.FileSize, 0, 1)); //sections var origin = (int)resourceTranslator.GetAddress(resourceTranslator.VirtualAddress); var size = (int)cache.Header.SectionTable[1].Size; segments.Add(resourceSegment = new Segment(origin, size, 0x1000)); origin = (int)metadataTranslator.GetAddress(metadataTranslator.VirtualAddress); size = cache.Header.VirtualSize; segments.Add(metadataSegment = new Segment(origin, size, 0x10000)); //strings origin = (int)debugTranslator.GetAddress(cache.Header.StringTableIndexPointer.Value); size = cache.Header.StringCount * 4; segments.Add(stringsGroup.Add(stringSegments[0] = new Segment(origin, size, 4))); origin = (int)debugTranslator.GetAddress(cache.Header.StringTablePointer.Value); size = cache.Header.StringTableSize; segments.Add(stringsGroup.Add(stringSegments[1] = new Segment(origin, size, cache.UsesStringEncryption ? 16 : 1))); //tag names origin = (int)debugTranslator.GetAddress(cache.Header.FileTableIndexPointer.Value); size = cache.Header.FileCount * 4; segments.Add(stringsGroup.Add(stringSegments[2] = new Segment(origin, size, 4))); origin = (int)debugTranslator.GetAddress(cache.Header.FileTablePointer.Value); size = cache.Header.FileTableSize; segments.Add(stringsGroup.Add(stringSegments[3] = new Segment(origin, size, 1))); //only exists in mcc reach (U3+) var mcc3 = cache.Header as IMccGen3Header; if (mcc3?.StringNamespaceCount > 0) { origin = (int)debugTranslator.GetAddress(mcc3.StringNamespaceTablePointer.Value); size = mcc3.StringNamespaceCount * 4; segments.Add(stringSegments[4] = stringsGroup.Add(new Segment(origin, size, 4))); } var gen4 = cache.Header as IGen4Header; if (gen4?.UnknownTableSize > 0) { origin = (int)debugTranslator.GetAddress(gen4.UnknownTablePointer.Value); size = gen4.UnknownTableSize * 16; segments.Add(stringSegments[5] = stringsGroup.Add(new Segment(origin, size, 16))); } for (int i = 0; i < cache.LocaleIndex.Languages.Count; i++) { var def = cache.LocaleIndex.Languages[i]; if (def.StringCount <= 0) { continue; } var segs = new Segment[2]; origin = (int)localeTranslator.GetAddress(def.IndicesOffset); size = def.StringCount * 8; segments.Add(segs[0] = localesGroup.Add(new Segment(origin, size, 8))); origin = (int)localeTranslator.GetAddress(def.StringsOffset); size = def.StringsSize; segments.Add(segs[1] = localesGroup.Add(new Segment(origin, size, cache.UsesStringEncryption ? 16 : 1))); localeSegments.Add(i, segs); } segments.Sort((a, b) => a.Offset.CompareTo(b.Offset)); for (int i = 0; i < segments.Count - 1; i++) { segments[i].NextSegment = segments[i + 1]; } }