//the reader must currently be at the start of the encoded block. the first [segmentOffset] bytes of the block will be discarded.
        internal static byte[] GetResourceData(EndianReader reader, CacheResourceCodec codec, int maxLength, int segmentOffset, int compressedSize, int decompressedSize)
        {
            var segmentLength = Math.Min(maxLength, decompressedSize - segmentOffset);

            if (codec == CacheResourceCodec.Uncompressed || compressedSize == decompressedSize)
            {
                reader.Seek(segmentOffset, SeekOrigin.Current);
                return(reader.ReadBytes(segmentLength));
            }
            else if (codec == CacheResourceCodec.Deflate)
            {
                using (var ds = new DeflateStream(reader.BaseStream, CompressionMode.Decompress))
                    using (var reader2 = new BinaryReader(ds))
                    {
                        reader2.ReadBytes(segmentOffset);
                        return(reader2.ReadBytes(segmentLength));
                    }
            }
            else if (codec == CacheResourceCodec.LZX)
            {
                var compressed   = reader.ReadBytes(compressedSize);
                var decompressed = new byte[decompressedSize];

                int startSize            = compressedSize;
                int endSize              = decompressedSize;
                int decompressionContext = 0;
                XCompress.XMemCreateDecompressionContext(XCompress.XMemCodecType.LZX, 0, 0, ref decompressionContext);
                XCompress.XMemResetDecompressionContext(decompressionContext);
                XCompress.XMemDecompressStream(decompressionContext, decompressed, ref endSize, compressed, ref startSize);
                XCompress.XMemDestroyDecompressionContext(decompressionContext);

                if (decompressed.Length == segmentLength)
                {
                    return(decompressed);
                }

                var result = new byte[segmentLength];
                Array.Copy(decompressed, segmentOffset, result, 0, result.Length);
                return(result);
            }
            else if (codec == CacheResourceCodec.UnknownDeflate) //experimental
            {
                using (var ms = new MemoryStream())
                    using (var mw = new BinaryWriter(ms))
                        using (var ds = new DeflateStream(reader.BaseStream, CompressionMode.Decompress))
                            using (var reader2 = new BinaryReader(ds))
                            {
                                for (int i = 0; i < segmentLength;)
                                {
                                    bool flag;
                                    var  blockSize = ReadSpecialInt(reader2, out flag);
                                    if (flag)
                                    {
                                        reader2.ReadBytes(2);
                                    }
                                    mw.Write(reader2.ReadBytes(blockSize));
                                    i += blockSize;
                                }

                                return(ms.ToArray());
                            }
            }
            else
            {
                throw new NotSupportedException("Unknown Resource Codec");
            }
        }
Beispiel #2
0
        public override byte[] GetRawFromID(int ID, int DataLength)
        {
            EndianReader er;
            string       fName = "";

            var Entry = zone.RawEntries[ID & ushort.MaxValue];

            if (Entry.SegmentIndex == -1)
            {
                throw new InvalidDataException("Raw data not found.");
            }

            var Loc = play.Segments[Entry.SegmentIndex];

            //if (Loc.SoundRawIndex != -1)
            //    return GetSoundRaw(ID);

            int index     = (Loc.OptionalPageIndex2 != -1) ? Loc.OptionalPageIndex2 : (Loc.OptionalPageIndex != -1) ? Loc.OptionalPageIndex : Loc.RequiredPageIndex;
            int locOffset = (Loc.OptionalPageOffset2 != -1) ? Loc.OptionalPageOffset2 : (Loc.OptionalPageOffset != -1) ? Loc.OptionalPageOffset : Loc.RequiredPageOffset;

            if (index == -1 || locOffset == -1)
            {
                throw new InvalidDataException("Raw data not found.");
            }

            if (play.Pages[index].RawOffset == -1)
            {
                index     = Loc.RequiredPageIndex;
                locOffset = Loc.RequiredPageOffset;
            }

            var Pool = play.Pages[index];

            if (Pool.CacheIndex != -1)
            {
                fName = play.SharedCaches[Pool.CacheIndex].FileName;
                fName = fName.Substring(fName.LastIndexOf('\\'));
                fName = FilePath + fName;

                if (fName == Filename)
                {
                    er = Reader;
                }
                else
                {
                    FileStream fs = new FileStream(fName, FileMode.Open, FileAccess.Read);
                    er = new EndianReader(fs, EndianFormat.Big);
                }
            }
            else
            {
                er = Reader;
            }

            er.SeekTo(int.Parse(versionNode.ChildNodes[0].Attributes["rawTableOffset"].Value));
            int offset = Pool.RawOffset + er.ReadInt32();

            er.SeekTo(offset);
            byte[] compressed   = er.ReadBytes(Pool.CompressedSize);
            byte[] decompressed = new byte[Pool.DecompressedSize];

            if (Version >= DefinitionSet.Halo4Retail)
            {
                int decompressionContext = 0;
                XCompress.XMemCreateDecompressionContext(XCompress.XMemCodecType.LZX, 0, 0, ref decompressionContext);
                XCompress.XMemResetDecompressionContext(decompressionContext);
                XCompress.XMemDecompressStream(decompressionContext, decompressed, ref Pool.DecompressedSize, compressed, ref Pool.CompressedSize);
                XCompress.XMemDestroyDecompressionContext(decompressionContext);
            }
            else
            {
                BinaryReader BR = new BinaryReader(new DeflateStream(new MemoryStream(compressed), CompressionMode.Decompress));
                decompressed = BR.ReadBytes(Pool.DecompressedSize);
                BR.Close();
                BR.Dispose();
            }

            byte[] data   = new byte[(DataLength != -1) ? DataLength : (Pool.DecompressedSize - locOffset)];
            int    length = data.Length;

            if (length > decompressed.Length)
            {
                length = decompressed.Length;
            }
            Array.Copy(decompressed, locOffset, data, 0, length);

            if (er != Reader)
            {
                er.Close();
                er.Dispose();
            }

            return(data);
        }