public byte[] ReadData(PageType mode, int maxLength) { var resourceGestalt = cache.TagIndex.GetGlobalTag("zone").ReadMetadata <cache_file_resource_gestalt>(); var resourceLayoutTable = cache.TagIndex.GetGlobalTag("play").ReadMetadata <cache_file_resource_layout_table>(); var entry = resourceGestalt.ResourceEntries[ResourceIndex]; if (entry.SegmentIndex < 0) { throw new InvalidOperationException("Data not found"); } var segment = resourceLayoutTable.Segments[entry.SegmentIndex]; var useTertiary = mode == PageType.Tertiary || (mode == PageType.Auto && segment.TertiaryPageIndex >= 0); var useSecondary = mode == PageType.Secondary || (mode == PageType.Auto && segment.SecondaryPageIndex >= 0); var pageIndex = useTertiary ? segment.TertiaryPageIndex : useSecondary ? segment.SecondaryPageIndex : segment.PrimaryPageIndex; var segmentOffset = useTertiary ? segment.TertiaryPageOffset : useSecondary ? segment.SecondaryPageOffset : segment.PrimaryPageOffset; if (pageIndex < 0 || segmentOffset < 0) { throw new InvalidOperationException("Data not found"); } var page = resourceLayoutTable.Pages[pageIndex]; if (mode == PageType.Auto && (page.DataOffset < 0 || page.CompressedSize == 0)) { pageIndex = segment.PrimaryPageIndex; segmentOffset = segment.PrimaryPageOffset; page = resourceLayoutTable.Pages[pageIndex]; } var targetFile = cache.FileName; if (page.CacheIndex >= 0) { var directory = Directory.GetParent(cache.FileName).FullName; var mapName = Utils.GetFileName(resourceLayoutTable.SharedCaches[page.CacheIndex].FileName); targetFile = Path.Combine(directory, mapName); } using (var fs = new FileStream(targetFile, FileMode.Open, FileAccess.Read)) using (var reader = new EndianReader(fs, cache.ByteOrder)) { reader.Seek(cache.CacheType >= CacheType.MccHalo4 ? 1216 : 1152, SeekOrigin.Begin); var dataTableAddress = reader.ReadUInt32(); reader.Seek(dataTableAddress + page.DataOffset, SeekOrigin.Begin); return(ContentFactory.GetResourceData(reader, cache.Metadata.ResourceCodec, maxLength, segmentOffset, page.CompressedSize, page.DecompressedSize)); } }
private byte[] ReadDataHalo3Beta(PageType mode, int maxLength) { var resourceGestalt = cache.TagIndex.GetGlobalTag("zone").ReadMetadata <cache_file_resource_gestalt>(); var directory = Directory.GetParent(cache.FileName).FullName; var entry = resourceGestalt.ResourceEntries[ResourceIndex]; var useSecondary = mode == PageType.Secondary || (mode == PageType.Auto && entry.SecondaryOffset > 0); var address = useSecondary ? entry.SecondaryOffset : entry.PrimaryOffset; var size = useSecondary ? entry.SecondarySize : entry.PrimarySize; var targetFile = entry.CacheIndex == -1 ? cache.FileName : Path.Combine(directory, shared_map); using (var fs = new FileStream(targetFile, FileMode.Open, FileAccess.Read)) using (var reader = new EndianReader(fs)) { reader.Seek(address, SeekOrigin.Begin); return(ContentFactory.GetResourceData(reader, cache.Metadata.ResourceCodec, maxLength, 0, size, size)); } }
public byte[] ReadData(PageType mode, int maxLength) { if (maxLength < 0) { throw new ArgumentOutOfRangeException(nameof(maxLength)); } if (cache.CacheType <= CacheType.Halo3Beta) { return(ReadDataHalo3Beta(mode, maxLength)); } var resourceGestalt = cache.TagIndex.GetGlobalTag("zone").ReadMetadata <cache_file_resource_gestalt>(); var resourceLayoutTable = cache.TagIndex.GetGlobalTag("play").ReadMetadata <cache_file_resource_layout_table>(); var entry = resourceGestalt.ResourceEntries[ResourceIndex]; if (entry.SegmentIndex < 0) { throw new InvalidOperationException("Data not found"); } var segment = resourceLayoutTable.Segments[entry.SegmentIndex]; var useSecondary = mode == PageType.Secondary || (mode == PageType.Auto && segment.SecondaryPageIndex >= 0); var pageIndex = useSecondary ? segment.SecondaryPageIndex : segment.PrimaryPageIndex; var segmentOffset = useSecondary ? segment.SecondaryPageOffset : segment.PrimaryPageOffset; if (pageIndex < 0 || segmentOffset < 0) { throw new InvalidOperationException("Data not found"); } var page = resourceLayoutTable.Pages[pageIndex]; if (mode == PageType.Auto && (page.DataOffset < 0 || page.CompressedSize == 0)) { pageIndex = segment.PrimaryPageIndex; segmentOffset = segment.PrimaryPageOffset; page = resourceLayoutTable.Pages[pageIndex]; } var targetFile = cache.FileName; if (page.CacheIndex >= 0) { var directory = Directory.GetParent(cache.FileName).FullName; var mapName = Utils.GetFileName(resourceLayoutTable.SharedCaches[page.CacheIndex].FileName); targetFile = Path.Combine(directory, mapName); } using (var fs = new FileStream(targetFile, FileMode.Open, FileAccess.Read)) using (var reader = new EndianReader(fs, cache.ByteOrder)) { int dataTableAddress; switch (cache.CacheType) { case CacheType.MccHalo3: case CacheType.MccHalo3U4: case CacheType.MccHalo3ODST: if (page.CacheIndex >= 0) { dataTableAddress = 12288; //header size } else { reader.Seek(1208, SeekOrigin.Begin); dataTableAddress = reader.ReadInt32(); } break; default: reader.Seek(1136, SeekOrigin.Begin); //xbox dataTableAddress = reader.ReadInt32(); break; } reader.Seek(dataTableAddress + page.DataOffset, SeekOrigin.Begin); return(ContentFactory.GetResourceData(reader, cache.Metadata.ResourceCodec, maxLength, segmentOffset, page.CompressedSize, page.DecompressedSize)); } }