Пример #1
0
        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));
                }
        }
Пример #2
0
        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));
                }
        }
Пример #3
0
        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));
                }
        }