//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"); } }
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); }