public static string[] ConvertMultiple(Shader shader) { if (shader.compressedBlob != null) //5.5 and up { var strs = new string[shader.platforms.Length]; for (var i = 0; i < shader.platforms.Length; i++) { var compressedBytes = new byte[shader.compressedLengths[i]]; Buffer.BlockCopy(shader.compressedBlob, (int)shader.offsets[i], compressedBytes, 0, (int)shader.compressedLengths[i]); var decompressedBytes = new byte[shader.decompressedLengths[i]]; using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes))) { decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]); } using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) { var program = new ShaderProgram(blobReader, shader.version); var m_Script = ConvertSerializedShader(shader.m_ParsedForm, shader.platforms[i]); strs[i] = header + program.Export(m_Script); } } return(strs); } return(null); }
public Shader(AssetPreloadData preloadData) : base(preloadData) { if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 5 || sourceFile.version[0] > 5) //5.5.0 and up { var str = preloadData.Dump(); m_Script = Encoding.UTF8.GetBytes(str ?? "Serialized Shader can't be read"); } else { m_Script = reader.ReadBytes(reader.ReadInt32()); if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 3) //5.3 - 5.4 { reader.AlignStream(4); var m_PathName = reader.ReadAlignedString(); var decompressedSize = reader.ReadUInt32(); var m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32()); var decompressedBytes = new byte[decompressedSize]; using (var decoder = new Lz4DecoderStream(new MemoryStream(m_SubProgramBlob))) { decoder.Read(decompressedBytes, 0, (int)decompressedSize); } m_Script = m_Script.Concat(decompressedBytes.ToArray()).ToArray(); } } }
public bool Read(AssetsFileReader reader) { header = new ClassDatabaseFileHeader(); header.Read(reader); if (header.header != "cldb" || header.fileVersion > 4 || header.fileVersion < 1) { valid = false; return(valid); } classes = new List <ClassDatabaseType>(); long classTablePos = reader.Position; AssetsFileReader newReader = reader; if (header.compressionType != 0) { classTablePos = 0; MemoryStream ms; if (header.compressionType == 1) //lz4 { byte[] uncompressedBytes = new byte[header.uncompressedSize]; using (MemoryStream tempMs = new MemoryStream(reader.ReadBytes((int)header.compressedSize))) { Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs); decoder.Read(uncompressedBytes, 0, (int)header.uncompressedSize); decoder.Dispose(); } ms = new MemoryStream(uncompressedBytes); } else if (header.compressionType == 2) //lzma { using (MemoryStream tempMs = new MemoryStream(reader.ReadBytes((int)header.compressedSize))) { ms = SevenZipHelper.StreamDecompress(tempMs); } } else { valid = false; return(valid); } newReader = new AssetsFileReader(ms); newReader.bigEndian = false; } newReader.Position = header.stringTablePos; stringTable = newReader.ReadBytes((int)header.stringTableLen); newReader.Position = classTablePos; uint size = newReader.ReadUInt32(); for (int i = 0; i < size; i++) { ClassDatabaseType cdt = new ClassDatabaseType(); cdt.Read(newReader, header.fileVersion, header.flags); classes.Add(cdt); } valid = true; return(valid); }
public BundleFile(string fileName) { if (Path.GetExtension(fileName) == ".lz4") { byte[] filebuffer; using (BinaryReader lz4Stream = new BinaryReader(File.OpenRead(fileName))) { int version = lz4Stream.ReadInt32(); int uncompressedSize = lz4Stream.ReadInt32(); int compressedSize = lz4Stream.ReadInt32(); int something = lz4Stream.ReadInt32(); //1 var lz4buffer = lz4Stream.ReadBytes(compressedSize); using (var inputStream = new MemoryStream(lz4buffer)) { var decoder = new Lz4DecoderStream(inputStream); filebuffer = new byte[uncompressedSize]; decoder.Read(filebuffer, 0, uncompressedSize); decoder.Dispose(); } } using (var b_Stream = new EndianBinaryReader(new MemoryStream(filebuffer))) { readBundle(b_Stream); } } else { using (var b_Stream = new EndianBinaryReader(File.OpenRead(fileName))) { readBundle(b_Stream); } } }
public static byte[] DecompressFromLZ4(Stream stream, int rawLength) { using (stream) { #if NETSTANDARD2_0 var inputLength = rawLength; var inputBuffer = new byte[inputLength]; stream.Read(inputBuffer, 0, rawLength); var guessedOutputLength = inputLength * 10; var outputBuffer = new byte[guessedOutputLength]; var actualOutputLength = LZ4Codec.Decode( inputBuffer, 0, inputLength, outputBuffer, 0, guessedOutputLength); if (actualOutputLength < guessedOutputLength) { return(outputBuffer.Take(actualOutputLength).ToArray()); } else { return(outputBuffer); } #else using (Lz4DecoderStream streamInner = new Lz4DecoderStream(stream)) { byte[] output = new byte[rawLength]; streamInner.Read(output, 0, rawLength); return(output); } #endif } }
public Shader(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; var a_Stream = preloadData.sourceFile.a_Stream; a_Stream.Position = preloadData.Offset; preloadData.extension = ".txt"; if (sourceFile.platform == -2) { uint m_ObjectHideFlags = a_Stream.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); if (readSwitch) { if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 5 || sourceFile.version[0] > 5)//5.5.0 and up { a_Stream.Position = preloadData.Offset; var str = (string)ShaderResource.ResourceManager.GetObject($"Shader{sourceFile.version[0]}{sourceFile.version[1]}"); var members = new JavaScriptSerializer().Deserialize <List <ClassMember> >(str); m_Script = ReadSerializedShader(members, a_Stream); } else { m_Script = a_Stream.ReadBytes(a_Stream.ReadInt32()); if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 3) //5.3 - 5.4 { a_Stream.AlignStream(4); a_Stream.ReadAlignedString(a_Stream.ReadInt32());//m_PathName var decompressedSize = a_Stream.ReadUInt32(); var m_SubProgramBlob = a_Stream.ReadBytes(a_Stream.ReadInt32()); var decompressedBytes = new byte[decompressedSize]; using (var mstream = new MemoryStream(m_SubProgramBlob)) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(decompressedBytes, 0, (int)decompressedSize); decoder.Dispose(); } m_Script = m_Script.Concat(decompressedBytes.ToArray()).ToArray(); } } } else { if (m_Name != "") { preloadData.Text = m_Name; } else { preloadData.Text = preloadData.TypeString + " #" + preloadData.uniqueID; } preloadData.SubItems.AddRange(new[] { preloadData.TypeString, preloadData.Size.ToString() }); } }
public Shader(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; var reader = preloadData.InitReader(); m_Name = reader.ReadAlignedString(); if (readSwitch) { if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 5 || sourceFile.version[0] > 5)//5.5.0 and up { var str = (string)ShaderResource.ResourceManager.GetObject($"Shader{sourceFile.version[0]}{sourceFile.version[1]}"); if (str == null) { str = preloadData.ViewStruct(); if (str == null) { m_Script = Encoding.UTF8.GetBytes("Serialized Shader can't be read"); } else { m_Script = Encoding.UTF8.GetBytes(str); } } else { reader.Position = preloadData.Offset; var sb = new StringBuilder(); var members = new JavaScriptSerializer().Deserialize <List <ClassMember> >(str); ClassStructHelper.ReadClassStruct(sb, members, reader); m_Script = Encoding.UTF8.GetBytes(sb.ToString()); //m_Script = ReadSerializedShader(members, a_Stream); } } else { m_Script = reader.ReadBytes(reader.ReadInt32()); if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 3) //5.3 - 5.4 { reader.AlignStream(4); reader.ReadAlignedString();//m_PathName var decompressedSize = reader.ReadUInt32(); var m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32()); var decompressedBytes = new byte[decompressedSize]; using (var decoder = new Lz4DecoderStream(new MemoryStream(m_SubProgramBlob))) { decoder.Read(decompressedBytes, 0, (int)decompressedSize); } m_Script = m_Script.Concat(decompressedBytes.ToArray()).ToArray(); } } } else { preloadData.extension = ".txt"; preloadData.Text = m_Name; } }
public static bool IsBundleDataCompressed(AssetBundleFile bundle) { AssetsFileReader reader = bundle.reader; reader.Position = bundle.bundleHeader6.GetBundleInfoOffset(); MemoryStream blocksInfoStream; AssetsFileReader memReader; int compressedSize = (int)bundle.bundleHeader6.compressedSize; byte[] uncompressedBytes; switch (bundle.bundleHeader6.GetCompressionType()) { case 1: uncompressedBytes = new byte[bundle.bundleHeader6.decompressedSize]; using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { MemoryStream decoder = SevenZipHelper.StreamDecompress(mstream, compressedSize); decoder.Read(uncompressedBytes, 0, (int)bundle.bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; case 2: case 3: uncompressedBytes = new byte[bundle.bundleHeader6.decompressedSize]; using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, (int)bundle.bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; default: blocksInfoStream = null; break; } var uncompressedInf = bundle.bundleInf6; if (bundle.bundleHeader6.GetCompressionType() != 0) { using (memReader = new AssetsFileReader(blocksInfoStream)) { memReader.Position = 0; uncompressedInf = new AssetBundleBlockAndDirectoryList06(); uncompressedInf.Read(0, memReader); } } return(uncompressedInf.blockInf.Any(inf => (inf.flags & 0x3f) != 0)); }
private byte[] DecompressHeader(byte[] data) { var decompressedSize = ReadScrambledInt1(data, 0x20); var decompressed = new byte[decompressedSize]; var lz4 = new Lz4DecoderStream(new MemoryStream(data, 0x27, data.Length - 0x27)); lz4.Read(decompressed, 0, decompressedSize); return(decompressed); }
public static byte[] DecompressFromLZ4(Stream stream, int rawLength) { using (stream) { using (Lz4DecoderStream streamInner = new Lz4DecoderStream(stream)) { byte[] output = new byte[rawLength]; streamInner.Read(output, 0, rawLength); return(output); } } }
public static void UnpackInfoOnly(this AssetBundleFile bundle) { AssetsFileReader reader = bundle.reader; reader.Position = 0; if (bundle.Read(reader, true)) { reader.Position = bundle.bundleHeader6.GetBundleInfoOffset(); MemoryStream blocksInfoStream; AssetsFileReader memReader; int compressedSize = (int)bundle.bundleHeader6.compressedSize; switch (bundle.bundleHeader6.GetCompressionType()) { case 1: using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { blocksInfoStream = SevenZipHelper.StreamDecompress(mstream); } break; case 2: case 3: byte[] uncompressedBytes = new byte[bundle.bundleHeader6.decompressedSize]; using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, (int)bundle.bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; default: blocksInfoStream = null; break; } if (bundle.bundleHeader6.GetCompressionType() != 0) { using (memReader = new AssetsFileReader(blocksInfoStream)) { memReader.Position = 0; bundle.bundleInf6.Read(0, memReader); } } } }
private static void lz4decompress(byte[] src, byte[] dst) { using (var inputStream = new MemoryStream(src)) { var decoder = new Lz4DecoderStream(inputStream); for (int i = 0; ;) { int nRead = decoder.Read(dst, i, dst.Length - i); if (nRead == 0) { break; } i += nRead; } } }
public BundleFile(string fileName) { if (Path.GetExtension(fileName) == ".lz4") { byte[] filebuffer; using (BinaryReader lz4Stream = new BinaryReader(File.OpenRead(fileName))) { int version = lz4Stream.ReadInt32(); int uncompressedSize = lz4Stream.ReadInt32(); int compressedSize = lz4Stream.ReadInt32(); int something = lz4Stream.ReadInt32(); //1 byte[] lz4buffer = new byte[compressedSize]; lz4Stream.Read(lz4buffer, 0, compressedSize); using (var inputStream = new MemoryStream(lz4buffer)) { var decoder = new Lz4DecoderStream(inputStream); filebuffer = new byte[uncompressedSize]; //is this ok? for (;;) { int nRead = decoder.Read(filebuffer, 0, uncompressedSize); if (nRead == 0) { break; } } } } using (var b_Stream = new EndianStream(new MemoryStream(filebuffer), EndianType.BigEndian)) { readBundle(b_Stream); } } else { using (var b_Stream = new EndianStream(File.OpenRead(fileName), EndianType.BigEndian)) { readBundle(b_Stream); } } }
private static string ConvertSerializedShader(Shader shader) { var shaderPrograms = new ShaderProgram[shader.platforms.Length]; for (var i = 0; i < shader.platforms.Length; i++) { var compressedBytes = new byte[shader.compressedLengths[i]]; Buffer.BlockCopy(shader.compressedBlob, (int)shader.offsets[i], compressedBytes, 0, (int)shader.compressedLengths[i]); var decompressedBytes = new byte[shader.decompressedLengths[i]]; using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes))) { decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]); } using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) { shaderPrograms[i] = new ShaderProgram(blobReader, shader.version); } } return(ConvertSerializedShader(shader.m_ParsedForm, shader.platforms, shaderPrograms)); }
public static string Convert(Shader shader) { if (shader.m_SubProgramBlob != null) //5.3 - 5.4 { var decompressedBytes = new byte[shader.decompressedSize]; using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob))) { decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize); } using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) { var program = new ShaderProgram(blobReader); return(program.Export(Encoding.UTF8.GetString(shader.m_Script))); } } if (shader.compressedBlob != null) //5.5 and up { //TODO /*for (var i = 0; i < shader.platforms.Count; i++) * { * var compressedBytes = new byte[shader.compressedLengths[i]]; * Array.Copy(shader.compressedBlob, shader.offsets[i], compressedBytes, 0, shader.compressedLengths[i]); * var decompressedBytes = new byte[shader.decompressedLengths[i]]; * using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes))) * { * decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]); * } * using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) * { * new ShaderProgram(blobReader); * } * }*/ return(shader.Dump()); } return(Encoding.UTF8.GetString(shader.m_Script)); }
public static string Convert(this Shader shader) { if (shader.m_SubProgramBlob != null) //5.3 - 5.4 { var decompressedBytes = new byte[shader.decompressedSize]; using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob))) { decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize); } using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) { var program = new ShaderProgram(blobReader, shader.version); return(header + program.Export(Encoding.UTF8.GetString(shader.m_Script))); } } if (shader.compressedBlob != null) //5.5 and up { return(header + ConvertSerializedShader(shader)); } return(header + Encoding.UTF8.GetString(shader.m_Script)); }
private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stream stream, BinaryReader xnbReader, Action <IDisposable> recordDisposableObject) { // The first 4 bytes should be the "XNB" header. i use that to detect an invalid file byte x = xnbReader.ReadByte(); byte n = xnbReader.ReadByte(); byte b = xnbReader.ReadByte(); byte platform = xnbReader.ReadByte(); if (x != 'X' || n != 'N' || b != 'B' || !(targetPlatformIdentifiers.Contains((char)platform))) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } byte version = xnbReader.ReadByte(); byte flags = xnbReader.ReadByte(); bool compressedLzx = (flags & ContentCompressedLzx) != 0; bool compressedLz4 = (flags & ContentCompressedLz4) != 0; if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressedLzx || compressedLz4) { // Decompress the xnb int decompressedSize = xnbReader.ReadInt32(); MemoryStream decompressedStream = null; if (compressedLzx) { //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) // default window size for XNB encoded files is 64Kb (need 16 bits to represent it) LzxDecoder dec = new LzxDecoder(16); decompressedStream = new MemoryStream(decompressedSize); int compressedSize = xnbLength - 14; long startPos = stream.Position; long pos = startPos; while (pos - startPos < compressedSize) { // the compressed stream is seperated into blocks that will decompress // into 32Kb or some other size if specified. // normal, 32Kb output blocks will have a short indicating the size // of the block before the block starts // blocks that have a defined output will be preceded by a byte of value // 0xFF (255), then a short indicating the output size and another // for the block size // all shorts for these cases are encoded in big endian order int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; // frame size is 32Kb by default // does this block define a frame size? if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } // either says there is nothing to decode if (block_size == 0 || frame_size == 0) { break; } dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; // reset the position of the input just incase the bit buffer // read in some unused bytes stream.Seek(pos, SeekOrigin.Begin); } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + " failed. "); } decompressedStream.Seek(0, SeekOrigin.Begin); } else if (compressedLz4) { // Decompress to a byte[] because Windows 8 doesn't support MemoryStream.GetBuffer() var buffer = new byte[decompressedSize]; using (var decoderStream = new Lz4DecoderStream(stream)) { if (decoderStream.Read(buffer, 0, buffer.Length) != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + " failed. "); } } // Creating the MemoryStream with a byte[] shares the buffer so it doesn't allocate any more memory decompressedStream = new MemoryStream(buffer); } reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject); } else { reader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject); } return(reader); }
private long ReadBlocksInfoAndDirectory(EndianBinaryReader varReader) { byte[] blocksInfoBytes; if (HeaderInfo.version >= 7) { varReader.AlignStream(16); } if ((HeaderInfo.flags & (int)ArchiveFlags.kArchiveBlocksInfoAtTheEnd) != 0) { var tempPosition = varReader.Position; { varReader.Position = varReader.BaseStream.Length - HeaderInfo.compressedBlocksInfoSize; blocksInfoBytes = varReader.ReadBytes((int)HeaderInfo.compressedBlocksInfoSize); } varReader.Position = tempPosition; } else //0x40 kArchiveBlocksAndDirectoryInfoCombined { blocksInfoBytes = varReader.ReadBytes((int)HeaderInfo.compressedBlocksInfoSize); } var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes); MemoryStream blocksInfoUncompresseddStream; switch (HeaderInfo.GetBlocksInfoCompressionType()) { default: //None { blocksInfoUncompresseddStream = blocksInfoCompressedStream; break; } case Compression.CompressionType.kCompressionLzma: { blocksInfoUncompresseddStream = new MemoryStream((int)(HeaderInfo.uncompressedBlocksInfoSize)); SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, HeaderInfo.compressedBlocksInfoSize, HeaderInfo.uncompressedBlocksInfoSize); blocksInfoUncompresseddStream.Position = 0; blocksInfoCompressedStream.Close(); break; } case Compression.CompressionType.kCompressionLz4: case Compression.CompressionType.kCompressionLz4HC: { var uncompressedBytes = new byte[HeaderInfo.uncompressedBlocksInfoSize]; using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream)) { decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length); } blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes); break; } } using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream)) { var uncompressedDataHash = blocksInfoReader.ReadBytes(16); var blocksInfoCount = blocksInfoReader.ReadInt32(); BlocksInfo = new List <StorageBlock>(blocksInfoCount); for (int i = 0; i < blocksInfoCount; i++) { var tempBlock = new StorageBlock().Parse(blocksInfoReader); BlocksInfo.Add(tempBlock); } var nodesCount = blocksInfoReader.ReadInt32(); DirectoryInfo = new List <Node>(nodesCount); for (int i = 0; i < nodesCount; i++) { var tempDirInfo = new Node().Parse(blocksInfoReader); DirectoryInfo.Add(tempDirInfo); } } return(varReader.Position); }
private void ReadFormat6(EndianBinaryReader bundleReader, bool padding = false) { var bundleSize = bundleReader.ReadInt64(); int compressedSize = bundleReader.ReadInt32(); int uncompressedSize = bundleReader.ReadInt32(); int flag = bundleReader.ReadInt32(); if (padding) { bundleReader.ReadByte(); } byte[] blocksInfoBytes; if ((flag & 0x80) != 0)//at end of file { var position = bundleReader.Position; bundleReader.Position = bundleReader.BaseStream.Length - compressedSize; blocksInfoBytes = bundleReader.ReadBytes(compressedSize); bundleReader.Position = position; } else { blocksInfoBytes = bundleReader.ReadBytes(compressedSize); } var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes); MemoryStream blocksInfoDecompressedStream; switch (flag & 0x3F) { default: //None { blocksInfoDecompressedStream = blocksInfoCompressedStream; break; } case 1: //LZMA { blocksInfoDecompressedStream = SevenZipHelper.StreamDecompress(blocksInfoCompressedStream); blocksInfoCompressedStream.Close(); break; } case 2: //LZ4 case 3: //LZ4HC { byte[] uncompressedBytes = new byte[uncompressedSize]; using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream)) { decoder.Read(uncompressedBytes, 0, uncompressedSize); } blocksInfoDecompressedStream = new MemoryStream(uncompressedBytes); break; } //case 4:LZHAM? } using (var blocksInfoReader = new EndianBinaryReader(blocksInfoDecompressedStream)) { blocksInfoReader.Position = 0x10; int blockcount = blocksInfoReader.ReadInt32(); var blockInfos = new BlockInfo[blockcount]; for (int i = 0; i < blockcount; i++) { blockInfos[i] = new BlockInfo { uncompressedSize = blocksInfoReader.ReadUInt32(), compressedSize = blocksInfoReader.ReadUInt32(), flag = blocksInfoReader.ReadInt16() }; } Stream dataStream; var uncompressedSizeSum = blockInfos.Sum(x => x.uncompressedSize); if (uncompressedSizeSum > int.MaxValue) { /*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum); * assetsDataStream = memoryMappedFile.CreateViewStream();*/ dataStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose); } else { dataStream = new MemoryStream((int)uncompressedSizeSum); } foreach (var blockInfo in blockInfos) { switch (blockInfo.flag & 0x3F) { default: //None { bundleReader.BaseStream.CopyTo(dataStream, blockInfo.compressedSize); break; } case 1: //LZMA { SevenZipHelper.StreamDecompress(bundleReader.BaseStream, dataStream, blockInfo.compressedSize, blockInfo.uncompressedSize); break; } case 2: //LZ4 case 3: //LZ4HC { var lz4Stream = new Lz4DecoderStream(bundleReader.BaseStream, blockInfo.compressedSize); lz4Stream.CopyTo(dataStream, blockInfo.uncompressedSize); break; } //case 4:LZHAM? } } dataStream.Position = 0; using (dataStream) { var entryinfo_count = blocksInfoReader.ReadInt32(); for (int i = 0; i < entryinfo_count; i++) { var file = new StreamFile(); var entryinfo_offset = blocksInfoReader.ReadInt64(); var entryinfo_size = blocksInfoReader.ReadInt64(); flag = blocksInfoReader.ReadInt32(); file.fileName = Path.GetFileName(blocksInfoReader.ReadStringToNull()); if (entryinfo_size > int.MaxValue) { /*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size); * file.stream = memoryMappedFile.CreateViewStream();*/ var extractPath = path + "_unpacked\\"; Directory.CreateDirectory(extractPath); file.stream = File.Create(extractPath + file.fileName); } else { file.stream = new MemoryStream((int)entryinfo_size); } dataStream.Position = entryinfo_offset; dataStream.CopyTo(file.stream, entryinfo_size); file.stream.Position = 0; fileList.Add(file); } } } }
unsafe void ReFillrbr(ReaderBE rbr, int uncompsize, uint flags) { byte[] buf; switch (flags & 0x3F) { default: //None break; case 1: buf = new byte[uncompsize]; break; case 2: //LZ4 case 3: //LZ4HC buf = new byte[uncompsize]; using (var decoder = new Lz4DecoderStream(new MemoryStream(rbr.Bas, rbr.seek, rbr.Bas.Length - rbr.seek))) decoder.Read(buf, 0, uncompsize); rbr.Reload(buf); break; } rbr.seek += 0x10; //uncompressedDataHash int blocksInfoCount = rbr.ri4c(); CompressedBlocks cb0 = *(CompressedBlocks *)rbr.ReadTc(0); if (blocksInfoCount == 1 && cb0.compressedSize == cb0.uncompressedSize) { } else { compressedblocks = new CompressedBlocks[blocksInfoCount]; fixed(byte *srcbb = &rbr.Bas[rbr.seek]) { for (int i = 0; i < blocksInfoCount; i++) { compressedblocks[i] = *(CompressedBlocks *)(srcbb + 0xA * i); } } } rbr.seek += blocksInfoCount * 0xA; blocksInfoCount = rbr.ri4c(); Files = new PackedFiles[blocksInfoCount]; for (int i = 0; i < blocksInfoCount; i++) { Files[i] = new PackedFiles { Offset = rbr.ru8c(), Size = rbr.ru8c(), flags = rbr.ru4c(), Name = rbr.rStr() }; } rbr.Clear(); }
private static byte[] ReadSerializedShader(List <ClassMember> members, EndianStream a_Stream) { var offsets = new List <uint>(); var compressedLengths = new List <uint>(); var decompressedLengths = new List <uint>(); for (int i = 0; i < members.Count; i++) { var member = members[i]; var level = member.Level; var varTypeStr = member.Type; if (member.Name == "offsets") { var offsets_size = a_Stream.ReadInt32(); for (int j = 0; j < offsets_size; j++) { offsets.Add(a_Stream.ReadUInt32()); } var compressedLengths_size = a_Stream.ReadInt32(); for (int j = 0; j < compressedLengths_size; j++) { compressedLengths.Add(a_Stream.ReadUInt32()); } var decompressedLengths_size = a_Stream.ReadInt32(); for (int j = 0; j < decompressedLengths_size; j++) { decompressedLengths.Add(a_Stream.ReadUInt32()); } var compressedBlob = a_Stream.ReadBytes(a_Stream.ReadInt32()); var decompressedStream = new MemoryStream(); for (int j = 0; j < offsets.Count; j++) { var compressedBytes = new byte[compressedLengths[j]]; Array.Copy(compressedBlob, offsets[j], compressedBytes, 0, compressedLengths[j]); var decompressedBytes = new byte[decompressedLengths[j]]; using (var mstream = new MemoryStream(compressedBytes)) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(decompressedBytes, 0, (int)decompressedLengths[j]); decoder.Dispose(); } decompressedStream.Write(decompressedBytes, 0, decompressedBytes.Length); } var decompressedBlob = decompressedStream.ToArray(); return(decompressedBlob); } var align = (member.Flag & 0x4000) != 0; if (varTypeStr == "SInt8")//sbyte { a_Stream.ReadSByte(); } else if (varTypeStr == "UInt8")//byte { a_Stream.ReadByte(); } else if (varTypeStr == "short" || varTypeStr == "SInt16")//Int16 { a_Stream.ReadInt16(); } else if (varTypeStr == "UInt16" || varTypeStr == "unsigned short")//UInt16 { a_Stream.ReadUInt16(); } else if (varTypeStr == "int" || varTypeStr == "SInt32")//Int32 { a_Stream.ReadInt32(); } else if (varTypeStr == "UInt32" || varTypeStr == "unsigned int")//UInt32 { a_Stream.ReadUInt32(); } else if (varTypeStr == "long long" || varTypeStr == "SInt64")//Int64 { a_Stream.ReadInt64(); } else if (varTypeStr == "UInt64" || varTypeStr == "unsigned long long")//UInt64 { a_Stream.ReadUInt64(); } else if (varTypeStr == "float")//float { a_Stream.ReadSingle(); } else if (varTypeStr == "double")//double { a_Stream.ReadDouble(); } else if (varTypeStr == "bool")//bool { a_Stream.ReadBoolean(); } else if (varTypeStr == "string")//string { a_Stream.ReadAlignedString(a_Stream.ReadInt32()); i += 3; //skip } else if (varTypeStr == "Array") //Array { if ((members[i - 1].Flag & 0x4000) != 0) { align = true; } var size = a_Stream.ReadInt32(); var array = AssetPreloadData.ReadArray(members, level, i); for (int j = 0; j < size; j++) { ReadSerializedShader(array, a_Stream); } i += array.Count + 1;//skip } else { align = false; } if (align) { a_Stream.AlignStream(4); } } return(null); }
public Mhy0File(EndianBinaryReader reader) { var originalPos = reader.Position; var magic = reader.ReadUInt32(); if (magic != 0x3079686D) { throw new Exception("not a mhy0"); } var headerSize = reader.ReadInt32(); var headerData = reader.ReadBytes(headerSize); Scramble(headerData, 0, 0x39, 0x1C); //File.WriteAllBytes("decrypted.bin", data); var decompressed = DecompressHeader(headerData); //File.WriteAllBytes("decompressed.bin", decompressed); var cabCount = ReadScrambledInt2(decompressed, 0); // not the best name var entryCount = ReadScrambledInt2(decompressed, cabCount * 0x113 + 6); var name = Encoding.UTF8.GetString(decompressed.Skip(6).TakeWhile(b => !b.Equals(0)).ToArray()); if (name.StartsWith("CAB-")) { //var id1 = Convert.ToUInt64(name.Substring(4, 16), 16); //var id2 = Convert.ToUInt64(name.Substring(20, 16), 16); //_id = id1 ^ id2; //Console.WriteLine(name.Substring(4)); _id = new Guid(name.Substring(4)); //Console.WriteLine(_id); } var compressedEntrySizes = new List <int>(entryCount); var decompressedEntrySizes = new List <int>(entryCount); for (int i = 0; i < entryCount; i++) { var offset = i * 13 + cabCount * 0x113 + 6; compressedEntrySizes.Add(ReadScrambledInt2(decompressed, offset + 6)); decompressedEntrySizes.Add(ReadScrambledInt1(decompressed, offset + 0xC)); } reader.Position = originalPos + headerSize + 8; var finalData = new byte[decompressedEntrySizes.Sum()]; var finalDataPos = 0; for (int i = 0; i < entryCount; i++) { var compressedEntry = reader.ReadBytes(compressedEntrySizes[i]); if (compressedEntry.Length >= 0x21) { Scramble(compressedEntry, 0, 0x21, 8); } var lz4 = new Lz4DecoderStream(new MemoryStream(compressedEntry, 0xC, compressedEntry.Length - 0xC)); lz4.Read(finalData, finalDataPos, decompressedEntrySizes[i]); finalDataPos += decompressedEntrySizes[i]; } _data = finalData; }
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader) { byte[] blocksInfoBytes; if (m_Header.version >= 7) { reader.AlignStream(16); } if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd { var position = reader.Position; reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize; blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); reader.Position = position; } else //0x40 kArchiveBlocksAndDirectoryInfoCombined { blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); } var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes); MemoryStream blocksInfoUncompresseddStream; switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask { default: //None { blocksInfoUncompresseddStream = blocksInfoCompressedStream; break; } case 2: //LZ4 case 3: //LZ4HC { var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize]; using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream)) { decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length); } blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes); break; } } using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream)) { var uncompressedDataHash = blocksInfoReader.ReadBytes(16); var blocksInfoCount = blocksInfoReader.ReadInt32(); m_BlocksInfo = new StorageBlock[blocksInfoCount]; uint offset = 0; for (int i = 0; i < blocksInfoCount; i++) { m_BlocksInfo[i] = new StorageBlock { offset = offset, uncompressedSize = blocksInfoReader.ReadUInt32(), compressedSize = blocksInfoReader.ReadUInt32(), flags = blocksInfoReader.ReadUInt16() }; offset += m_BlocksInfo[i].compressedSize; } var nodesCount = blocksInfoReader.ReadInt32(); m_DirectoryInfo = new Node[nodesCount]; for (int i = 0; i < nodesCount; i++) { m_DirectoryInfo[i] = new Node { offset = blocksInfoReader.ReadInt64(), size = blocksInfoReader.ReadInt64(), flags = blocksInfoReader.ReadUInt32(), path = blocksInfoReader.ReadStringToNull(), }; } } }
private void ReadFormat6(EndianStream b_Stream, bool padding = false) { var bundleSize = b_Stream.ReadInt64(); int compressedSize = b_Stream.ReadInt32(); int uncompressedSize = b_Stream.ReadInt32(); int flag = b_Stream.ReadInt32(); if (padding) { b_Stream.ReadByte(); } byte[] blocksInfoBytes; if ((flag & 0x80) != 0)//at end of file { var position = b_Stream.Position; b_Stream.Position = b_Stream.BaseStream.Length - compressedSize; blocksInfoBytes = b_Stream.ReadBytes(compressedSize); b_Stream.Position = position; } else { blocksInfoBytes = b_Stream.ReadBytes(compressedSize); } EndianStream blocksInfo; switch (flag & 0x3F) { default: //None { blocksInfo = new EndianStream(new MemoryStream(blocksInfoBytes), EndianType.BigEndian); break; } case 1: //LZMA { blocksInfo = new EndianStream(SevenZipHelper.StreamDecompress(new MemoryStream(blocksInfoBytes)), EndianType.BigEndian); break; } case 2: //LZ4 case 3: //LZ4HC { byte[] uncompressedBytes = new byte[uncompressedSize]; using (var mstream = new MemoryStream(blocksInfoBytes)) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } blocksInfo = new EndianStream(new MemoryStream(uncompressedBytes), EndianType.BigEndian); break; } //case 4:LZHAM? } using (blocksInfo) { blocksInfo.Position = 0x10; int blockcount = blocksInfo.ReadInt32(); EndianStream assetsData; var assetsDataStream = new MemoryStream(); for (int i = 0; i < blockcount; i++) { uncompressedSize = blocksInfo.ReadInt32(); compressedSize = blocksInfo.ReadInt32(); flag = blocksInfo.ReadInt16(); var compressedBytes = b_Stream.ReadBytes(compressedSize); switch (flag & 0x3F) { default: //None { assetsDataStream.Write(compressedBytes, 0, compressedSize); break; } case 1: //LZMA { var uncompressedBytes = new byte[uncompressedSize]; using (var mstream = new MemoryStream(compressedBytes)) { var decoder = SevenZipHelper.StreamDecompress(mstream, uncompressedSize); decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } assetsDataStream.Write(uncompressedBytes, 0, uncompressedSize); break; } case 2: //LZ4 case 3: //LZ4HC { var uncompressedBytes = new byte[uncompressedSize]; using (var mstream = new MemoryStream(compressedBytes)) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } assetsDataStream.Write(uncompressedBytes, 0, uncompressedSize); break; } //case 4:LZHAM? } } assetsData = new EndianStream(assetsDataStream, EndianType.BigEndian); using (assetsData) { var entryinfo_count = blocksInfo.ReadInt32(); for (int i = 0; i < entryinfo_count; i++) { var memFile = new MemoryAssetsFile(); var entryinfo_offset = blocksInfo.ReadInt64(); var entryinfo_size = blocksInfo.ReadInt64(); var unknown = blocksInfo.ReadInt32(); memFile.fileName = blocksInfo.ReadStringToNull(); assetsData.Position = entryinfo_offset; var buffer = new byte[entryinfo_size]; assetsData.Read(buffer, 0, (int)entryinfo_size); memFile.memStream = new MemoryStream(buffer); MemoryAssetsFileList.Add(memFile); } } } }
public Shader(AssetPreloadData preloadData, bool readSwitch) { var sourceFile = preloadData.sourceFile; var a_Stream = preloadData.sourceFile.a_Stream; a_Stream.Position = preloadData.Offset; if (sourceFile.platform == -2) { uint m_ObjectHideFlags = a_Stream.ReadUInt32(); PPtr m_PrefabParentObject = sourceFile.ReadPPtr(); PPtr m_PrefabInternal = sourceFile.ReadPPtr(); } m_Name = a_Stream.ReadAlignedString(a_Stream.ReadInt32()); if (readSwitch) { if (true) { //Assume as unity 5.6 or greater. var str1 = preloadData.ViewStruct(); if (str1 == null) { m_Script = Encoding.UTF8.GetBytes("Serialized Shader can't be read"); } else { m_Script = Encoding.UTF8.GetBytes(str1); } return; } /** * SHORTCUT: * System.Resources.MissingManifestResourceException: Could not find * any resources appropriate for the specified culture or the neutral * culture. Make sure "Unity_Studio.ShaderResource.resources" was * correctly embedded or linked into assembly "adebug" at compile * time, or that all the satellite assemblies required are loadable * and fully signed. */ if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 5 || sourceFile.version[0] > 5)//5.5.0 and up { var str = (string)ShaderResource.ResourceManager.GetObject($"Shader{sourceFile.version[0]}{sourceFile.version[1]}"); if (str == null) { str = preloadData.ViewStruct(); if (str == null) { m_Script = Encoding.UTF8.GetBytes("Serialized Shader can't be read"); } else { m_Script = Encoding.UTF8.GetBytes(str); } } else { a_Stream.Position = preloadData.Offset; var sb = new StringBuilder(); var members = new JavaScriptSerializer().Deserialize <List <ClassMember> >(str); ClassStructHelper.ReadClassStruct(sb, members, a_Stream); m_Script = Encoding.UTF8.GetBytes(sb.ToString()); //m_Script = ReadSerializedShader(members, a_Stream); } } else { m_Script = a_Stream.ReadBytes(a_Stream.ReadInt32()); if (sourceFile.version[0] == 5 && sourceFile.version[1] >= 3) //5.3 - 5.4 { a_Stream.AlignStream(4); a_Stream.ReadAlignedString(a_Stream.ReadInt32());//m_PathName var decompressedSize = a_Stream.ReadUInt32(); var m_SubProgramBlob = a_Stream.ReadBytes(a_Stream.ReadInt32()); var decompressedBytes = new byte[decompressedSize]; using (var mstream = new MemoryStream(m_SubProgramBlob)) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(decompressedBytes, 0, (int)decompressedSize); decoder.Dispose(); } m_Script = m_Script.Concat(decompressedBytes.ToArray()).ToArray(); } } } else { preloadData.extension = ".txt"; preloadData.Text = m_Name; } }
public PIGmodel(string PIGfile) { using (BinaryReader binStream = new BinaryReader(File.OpenRead(PIGfile))) { int marker = binStream.ReadInt32(); //0x64 short nodeCount = binStream.ReadInt16(); for (int n = 0; n < nodeCount; n++) { PIGnode newnode = new PIGnode(); marker = binStream.ReadInt32(); newnode.name = ReadStr(binStream); byte nbyte = binStream.ReadByte(); newnode.parentID = binStream.ReadInt16(); newnode.position[0] = binStream.ReadSingle(); newnode.position[1] = binStream.ReadSingle(); newnode.position[2] = binStream.ReadSingle(); newnode.rotation[0] = binStream.ReadSingle(); newnode.rotation[1] = binStream.ReadSingle(); newnode.rotation[2] = binStream.ReadSingle(); newnode.rotation[3] = binStream.ReadSingle(); newnode.scale[0] = binStream.ReadSingle(); newnode.scale[1] = binStream.ReadSingle(); newnode.scale[2] = binStream.ReadSingle(); float afloat = binStream.ReadSingle(); short ashort = binStream.ReadInt16(); nodeList.Add(newnode); } byte abyte = binStream.ReadByte(); short objectCount = binStream.ReadInt16(); for (int o = 0; o < objectCount; o++) { PIGobject newobject = new PIGobject(); marker = binStream.ReadInt32(); //0x64 newobject.nodeID = binStream.ReadInt32(); int LODcount = binStream.ReadInt16(); for (int l = 0; l < LODcount; l++) { byte LODnum = binStream.ReadByte(); marker = binStream.ReadInt32(); //0x64 short edata = binStream.ReadInt16(); binStream.BaseStream.Position += 24; //bounding box short meshCount = binStream.ReadInt16(); geomCount += meshCount; for (int m = 0; m < meshCount; m++) { PIGmesh newmesh = new PIGmesh(); newmesh.LODnum = LODnum; marker = binStream.ReadInt32(); //0x64 BitArray bitflags = new BitArray(new int[1] { binStream.ReadInt32() }); int FVFcode = binStream.ReadInt32(); binStream.BaseStream.Position += 12; //mpivot if (bitflags[0]) { newmesh.position[0] = binStream.ReadSingle(); newmesh.position[1] = binStream.ReadSingle(); newmesh.position[2] = binStream.ReadSingle(); newmesh.scale[0] = binStream.ReadSingle(); newmesh.scale[1] = binStream.ReadSingle(); newmesh.scale[2] = binStream.ReadSingle(); } ushort vertexCount = binStream.ReadUInt16(); newmesh.vertexCount = vertexCount; int indexCount = binStream.ReadInt32(); string materialName = ReadStr(binStream); newmesh.materialName = materialName; newmesh.materialID = matList.Count; PIGmaterial pmat = new PIGmaterial(); pmat.name = materialName; short texureCount = binStream.ReadInt16(); for (int t = 0; t < texureCount; t++) { string textureName = ReadStr(binStream); if (textureName.Length > 0) { PIGtexture ptex = new PIGtexture(); ptex.name = textureName; int ptexID = texList.Count; var existingTexIndex = texList.BinarySearch(ptex, tc); if (existingTexIndex >= 0) { ptexID = existingTexIndex; } else { //get filename string[] texFiles = Directory.GetFiles(Path.GetDirectoryName(PIGfile) + "\\..\\", Path.GetFileNameWithoutExtension(textureName) + ".pvr", SearchOption.AllDirectories); if (texFiles.Length == 0) { texFiles = Directory.GetFiles(Path.GetDirectoryName(PIGfile) + "\\..\\", textureName, SearchOption.AllDirectories); if (texFiles.Length > 0) { var pvrfile = DecompressPVR(texFiles[0]); ptex.filename = pvrfile; } } else { ptex.filename = Path.GetFullPath(texFiles[0]); } texList.Add(ptex); } switch (t) { case 0: //diffuse pmat.diffuseID = ptexID; usedTexCount += 1; break; case 2: //normal pmat.normalID = ptexID; usedTexCount += 1; break; } } } //add material only if it wasn't added before var existingMatIndex = matList.BinarySearch(pmat, mc); if (existingMatIndex >= 0) { newmesh.materialID = existingMatIndex; } else { matList.Add(pmat); } abyte = binStream.ReadByte(); int bufferSize = binStream.ReadInt32(); byte[] geobuffer = new byte[bufferSize]; if (bufferSize == 0) //lz4 compression { int compressedSize = binStream.ReadInt32(); int uncompressedSize = binStream.ReadInt32(); byte[] lz4buffer = new byte[compressedSize]; binStream.Read(lz4buffer, 0, compressedSize); using (var inputStream = new MemoryStream(lz4buffer)) { var decoder = new Lz4DecoderStream(inputStream); geobuffer = new byte[uncompressedSize]; //is this ok? for (; ;) { int nRead = decoder.Read(geobuffer, 0, geobuffer.Length); if (nRead == 0) { break; } } } /*using (BinaryWriter debugStream = new BinaryWriter(File.Open((Path.GetDirectoryName(fileName) + "\\" + Path.GetFileNameWithoutExtension(fileName) + "_" + o + "_" + l + "_" + m), FileMode.Create))) * { * debugStream.Write(geobuffer); * debugStream.Close(); * }*/ } else { binStream.Read(geobuffer, 0, bufferSize); } newmesh.indices = new ushort[indexCount]; using (BinaryReader geostream = new BinaryReader(new MemoryStream(geobuffer))) { geostream.BaseStream.Position = 0; //is this needed? #region positions if ((FVFcode | 1) == FVFcode) //positions { newmesh.vertices = new float[vertexCount * 3]; short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; //test if components are 16bit shorts or 32bit floats int predictedAlign = 16 - ((vertexCount * 8) % 16) - 2; geostream.BaseStream.Position += vertexCount * 8; align = geostream.ReadInt16(); geostream.BaseStream.Position -= vertexCount * 8 + 2; if (align != predictedAlign) { for (int v = 0; v < vertexCount * 3; v++) { newmesh.vertices[v] = geostream.ReadSingle(); } } else { for (int v = 0; v < vertexCount; v++) { newmesh.vertices[v * 3] = (float)geostream.ReadInt16() / 32767; newmesh.vertices[v * 3 + 1] = (float)geostream.ReadInt16() / 32767; newmesh.vertices[v * 3 + 2] = (float)geostream.ReadInt16() / 32767; geostream.BaseStream.Position += 2; //w component } } } #endregion #region normals if ((FVFcode | 2) == FVFcode) //normals { newmesh.normals = new float[vertexCount * 3]; short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; for (int v = 0; v < vertexCount; v++) { newmesh.normals[v * 3] = (float)geostream.ReadSByte() / 127; newmesh.normals[v * 3 + 1] = (float)geostream.ReadSByte() / 127; newmesh.normals[v * 3 + 2] = (float)geostream.ReadSByte() / 127; geostream.BaseStream.Position += 1; } } #endregion #region misc if ((FVFcode | 4) == FVFcode) //tangents { short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; geostream.BaseStream.Position += vertexCount * 4; } if ((FVFcode | 8) == FVFcode) //?? { short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; geostream.BaseStream.Position += vertexCount * 4; } if ((FVFcode | 16) == FVFcode) //?? { short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; geostream.BaseStream.Position += vertexCount * 4; } if ((FVFcode | 32) == FVFcode) //?? { short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; geostream.BaseStream.Position += vertexCount * 4; } if ((FVFcode | 64) == FVFcode) //not colors { //newmesh.colors = new float[vertexCount * 4]; short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; geostream.BaseStream.Position += vertexCount * 4; /*for (int v = 0; v < vertexCount * 4; v++) * { * newmesh.colors[v] = (float)geostream.ReadByte() / 255; * }*/ } #endregion #region texture coords if ((FVFcode | 128) == FVFcode) //texture0 { newmesh.texture0 = new float[vertexCount * 2]; short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; //test if components are 16bit shorts or 32bit floats int predictedAlign = 16 - ((vertexCount * 4) % 16) - 2; geostream.BaseStream.Position += vertexCount * 4; align = geostream.ReadInt16(); geostream.BaseStream.Position -= vertexCount * 4 + 2; if (align != predictedAlign) { for (int v = 0; v < vertexCount; v++) { newmesh.texture0[v * 2] = geostream.ReadSingle(); newmesh.texture0[v * 2 + 1] = 1f - geostream.ReadSingle(); } } else { for (int v = 0; v < vertexCount; v++) { newmesh.texture0[v * 2] = (float)geostream.ReadInt16() / 32767; newmesh.texture0[v * 2 + 1] = 1f - (float)geostream.ReadInt16() / 32767; } } } if ((FVFcode | 256) == FVFcode) //texture1 { newmesh.texture1 = new float[vertexCount * 2]; short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; //test if components are 16bit shorts or 32bit floats int predictedAlign = 16 - ((vertexCount * 4) % 16) - 2; geostream.BaseStream.Position += vertexCount * 4; align = geostream.ReadInt16(); geostream.BaseStream.Position -= vertexCount * 4 + 2; if (align != predictedAlign) { for (int v = 0; v < vertexCount; v++) { newmesh.texture1[v * 2] = geostream.ReadSingle(); newmesh.texture1[v * 2] = 1f - geostream.ReadSingle(); } } else { for (int v = 0; v < vertexCount; v++) { newmesh.texture1[v * 2] = (float)geostream.ReadInt16() / 32767; newmesh.texture1[v * 2] = 1f - (float)geostream.ReadInt16() / 32767; } } } #endregion #region misc2 if ((FVFcode | 512) == FVFcode) //?? { short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; int predictedAlign = 16 - ((vertexCount * 4) % 16) - 2; geostream.BaseStream.Position += vertexCount * 4; align = geostream.ReadInt16(); geostream.BaseStream.Position -= 2; if (align != predictedAlign) { geostream.BaseStream.Position += vertexCount * 4; } //happened in car_ford_mustang_2015_rfx.pig } if ((FVFcode | 1024) == FVFcode) //?? { short align = geostream.ReadInt16(); geostream.BaseStream.Position += align; geostream.BaseStream.Position += vertexCount * 8; } #endregion geostream.BaseStream.Position = geostream.BaseStream.Length - (indexCount * 2); //failsafe in case vertex properties are misread //note that IB alignment is skipped for (int i = 0; i < indexCount; i++) { newmesh.indices[i] = geostream.ReadUInt16(); } } for (int e = 0; e < edata; e++) { short short1 = binStream.ReadInt16(); short short2 = binStream.ReadInt16(); int extraSize = binStream.ReadInt32(); if (extraSize == 0) { int compressedSize = binStream.ReadInt32(); int uncompressedSize = binStream.ReadInt32(); binStream.BaseStream.Position += compressedSize; } else { binStream.BaseStream.Position += extraSize; } } newobject.meshList.Add(newmesh); } } objectList.Add(newobject); } } }
public bool Unpack(AssetsFileReader reader, AssetsFileWriter writer) { reader.Position = 0; if (Read(reader, true)) { reader.Position = bundleHeader6.GetBundleInfoOffset(); MemoryStream blocksInfoStream; AssetsFileReader memReader; int compressedSize = (int)bundleHeader6.compressedSize; switch (bundleHeader6.GetCompressionType()) { case 1: using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { blocksInfoStream = SevenZipHelper.StreamDecompress(mstream); } break; case 2: case 3: byte[] uncompressedBytes = new byte[bundleHeader6.decompressedSize]; using (MemoryStream mstream = new MemoryStream(reader.ReadBytes(compressedSize))) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, (int)bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; default: blocksInfoStream = null; break; } if (bundleHeader6.GetCompressionType() != 0) { using (memReader = new AssetsFileReader(blocksInfoStream)) { memReader.Position = 0; bundleInf6.Read(0, memReader); } } AssetBundleHeader06 newBundleHeader6 = new AssetBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = bundleHeader6.decompressedSize, decompressedSize = bundleHeader6.decompressedSize, flags = bundleHeader6.flags & 0x40 //set compression and block position to 0 }; long fileSize = newBundleHeader6.GetFileDataOffset(); for (int i = 0; i < bundleInf6.blockCount; i++) { fileSize += bundleInf6.blockInf[i].decompressedSize; } newBundleHeader6.totalFileSize = fileSize; AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06() { checksumLow = 0, //-todo, figure out how to make real checksums, uabe sets these to 0 too checksumHigh = 0, blockCount = bundleInf6.blockCount, directoryCount = bundleInf6.directoryCount }; newBundleInf6.blockInf = new AssetBundleBlockInfo06[newBundleInf6.blockCount]; for (int i = 0; i < newBundleInf6.blockCount; i++) { newBundleInf6.blockInf[i] = new AssetBundleBlockInfo06() { compressedSize = bundleInf6.blockInf[i].decompressedSize, decompressedSize = bundleInf6.blockInf[i].decompressedSize, flags = (ushort)(bundleInf6.blockInf[i].flags & 0xC0) //set compression to none }; } newBundleInf6.dirInf = new AssetBundleDirectoryInfo06[newBundleInf6.directoryCount]; for (int i = 0; i < newBundleInf6.directoryCount; i++) { newBundleInf6.dirInf[i] = new AssetBundleDirectoryInfo06() { offset = bundleInf6.dirInf[i].offset, decompressedSize = bundleInf6.dirInf[i].decompressedSize, flags = bundleInf6.dirInf[i].flags, name = bundleInf6.dirInf[i].name }; } newBundleHeader6.Write(writer); if (newBundleHeader6.fileVersion >= 7) { writer.Align16(); } newBundleInf6.Write(writer); reader.Position = bundleHeader6.GetFileDataOffset(); for (int i = 0; i < newBundleInf6.blockCount; i++) { AssetBundleBlockInfo06 info = bundleInf6.blockInf[i]; switch (info.GetCompressionType()) { case 0: reader.BaseStream.CopyToCompat(writer.BaseStream, info.compressedSize); break; case 1: SevenZipHelper.StreamDecompress(reader.BaseStream, writer.BaseStream, info.compressedSize, info.decompressedSize); break; case 2: case 3: using (MemoryStream tempMs = new MemoryStream()) { reader.BaseStream.CopyToCompat(tempMs, info.compressedSize); tempMs.Position = 0; using (Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs)) { decoder.CopyToCompat(writer.BaseStream, info.decompressedSize); } } break; } } return(true); } return(false); }
public bool Read(AssetsFileReader reader) { header = new ClassDatabasePackageHeader(); header.Read(reader); files = new List <ClassDatabaseFile>(); long firstFile = reader.Position; AssetsFileReader newReader = reader; if ((header.compressionType & 0x80) == 0) //multiple compressed blocks { //untested! //the compression is handled by the cldbs themselves for (int i = 0; i < header.fileCount; i++) { newReader.Position = firstFile + header.files[i].offset; byte[] data = newReader.ReadBytes((int)header.files[i].length); using (MemoryStream ms = new MemoryStream(data)) using (AssetsFileReader r = new AssetsFileReader(ms)) { ClassDatabaseFile file = new ClassDatabaseFile(); file.Read(r); files.Add(file); } } } else //one compressed block { if ((header.compressionType & 0x20) == 0) //file block compressed { firstFile = 0; int compressedSize = (int)(header.stringTableOffset - newReader.Position); int uncompressedSize = (int)header.fileBlockSize; MemoryStream ms; if ((header.compressionType & 0x1f) == 1) //lz4 { byte[] uncompressedBytes = new byte[uncompressedSize]; using (MemoryStream tempMs = new MemoryStream(newReader.ReadBytes(compressedSize))) { Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs); decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } ms = new MemoryStream(uncompressedBytes); } else if ((header.compressionType & 0x1f) == 2) //lzma { byte[] dbg = newReader.ReadBytes(compressedSize); using (MemoryStream tempMs = new MemoryStream(dbg)) { ms = SevenZipHelper.StreamDecompress(tempMs, uncompressedSize); } } else { valid = false; return(valid); } newReader = new AssetsFileReader(ms); newReader.bigEndian = false; } for (int i = 0; i < header.fileCount; i++) { newReader.Position = firstFile + header.files[i].offset; byte[] data = newReader.ReadBytes((int)header.files[i].length); using (MemoryStream ms = new MemoryStream(data)) using (AssetsFileReader r = new AssetsFileReader(ms)) { ClassDatabaseFile file = new ClassDatabaseFile(); file.Read(r); files.Add(file); } } } newReader = reader; newReader.Position = header.stringTableOffset; if ((header.compressionType & 0x40) == 0) //string table is compressed { int compressedSize = (int)header.stringTableLenCompressed; int uncompressedSize = (int)header.stringTableLenUncompressed; MemoryStream ms; if ((header.compressionType & 0x1f) == 1) //lz4 { byte[] uncompressedBytes = new byte[uncompressedSize]; using (MemoryStream tempMs = new MemoryStream(newReader.ReadBytes(compressedSize))) { Lz4DecoderStream decoder = new Lz4DecoderStream(tempMs); decoder.Read(uncompressedBytes, 0, uncompressedSize); decoder.Dispose(); } ms = new MemoryStream(uncompressedBytes); } else if ((header.compressionType & 0x1f) == 2) //lzma { using (MemoryStream tempMs = new MemoryStream(newReader.ReadBytes(compressedSize))) { ms = SevenZipHelper.StreamDecompress(tempMs, uncompressedSize); } } else { valid = false; return(valid); } newReader = new AssetsFileReader(ms); newReader.bigEndian = false; } stringTable = newReader.ReadBytes((int)header.stringTableLenUncompressed); for (int i = 0; i < header.fileCount; i++) { files[i].stringTable = stringTable; } valid = true; return(valid); }
///public bool Write(AssetsFileReader reader, LPARAM readerPar, /// AssetsFileWriter writer, LPARAM writerPar, /// /// class BundleReplacer **pReplacers, size_t replacerCount, /// AssetsFileVerifyLogger errorLogger = NULL, ClassDatabaseFile* typeMeta = NULL); //-todo, use a faster custom bundle decompressor. currently a copy paste of unity studio's public bool Unpack(AssetsFileReader reader, AssetsFileWriter writer) { if (Read(reader, true)) { reader.Position = bundleHeader6.GetBundleInfoOffset(); MemoryStream blocksInfoStream; AssetsFileReader memReader; switch (bundleHeader6.flags & 0x3F) { case 1: blocksInfoStream = SevenZipHelper.StreamDecompress(new MemoryStream(reader.ReadBytes((int)bundleHeader6.compressedSize))); break; case 2: case 3: byte[] uncompressedBytes = new byte[bundleHeader6.decompressedSize]; using (var mstream = new MemoryStream(reader.ReadBytes((int)bundleHeader6.compressedSize))) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(uncompressedBytes, 0, (int)bundleHeader6.decompressedSize); decoder.Dispose(); } blocksInfoStream = new MemoryStream(uncompressedBytes); break; default: blocksInfoStream = null; break; } if ((bundleHeader6.flags & 0x3F) != 0) { using (memReader = new AssetsFileReader(blocksInfoStream)) { bundleInf6.Read(0, memReader); } } reader.Position = bundleHeader6.GetFileDataOffset(); byte[][] blocksData = new byte[bundleInf6.blockCount][]; for (int i = 0; i < bundleInf6.blockCount; i++) { AssetsBundleBlockInfo06 info = bundleInf6.blockInf[i]; byte[] data = reader.ReadBytes((int)info.compressedSize); switch (info.flags & 0x3F) { case 0: blocksData[i] = data; break; case 1: blocksData[i] = new byte[info.decompressedSize]; using (MemoryStream mstream = new MemoryStream(data)) { MemoryStream decoder = SevenZipHelper.StreamDecompress(mstream, info.decompressedSize); decoder.Read(blocksData[i], 0, (int)info.decompressedSize); decoder.Dispose(); } break; case 2: case 3: blocksData[i] = new byte[info.decompressedSize]; using (MemoryStream mstream = new MemoryStream(data)) { var decoder = new Lz4DecoderStream(mstream); decoder.Read(blocksData[i], 0, (int)info.decompressedSize); decoder.Dispose(); } break; } } AssetsBundleHeader06 newBundleHeader6 = new AssetsBundleHeader06() { signature = bundleHeader6.signature, fileVersion = bundleHeader6.fileVersion, minPlayerVersion = bundleHeader6.minPlayerVersion, fileEngineVersion = bundleHeader6.fileEngineVersion, totalFileSize = 0, compressedSize = bundleHeader6.decompressedSize, decompressedSize = bundleHeader6.decompressedSize, flags = bundleHeader6.flags & 0x40 //set compression and block position to 0 }; ulong fileSize = newBundleHeader6.GetFileDataOffset(); for (int i = 0; i < bundleInf6.blockCount; i++) { fileSize += bundleInf6.blockInf[i].decompressedSize; } newBundleHeader6.totalFileSize = fileSize; AssetsBundleBlockAndDirectoryList06 newBundleInf6 = new AssetsBundleBlockAndDirectoryList06() { checksumLow = 0, //-todo, figure out how to make real checksums, uabe sets these to 0 too checksumHigh = 0, blockCount = bundleInf6.blockCount, directoryCount = bundleInf6.directoryCount }; newBundleInf6.blockInf = new AssetsBundleBlockInfo06[newBundleInf6.blockCount]; for (int i = 0; i < newBundleInf6.blockCount; i++) { newBundleInf6.blockInf[i] = new AssetsBundleBlockInfo06(); newBundleInf6.blockInf[i].compressedSize = bundleInf6.blockInf[i].decompressedSize; newBundleInf6.blockInf[i].decompressedSize = bundleInf6.blockInf[i].decompressedSize; newBundleInf6.blockInf[i].flags = (ushort)(bundleInf6.blockInf[i].flags & 0xC0); //set compression to none } newBundleInf6.dirInf = new AssetsBundleDirectoryInfo06[newBundleInf6.directoryCount]; for (int i = 0; i < newBundleInf6.directoryCount; i++) { newBundleInf6.dirInf[i].offset = bundleInf6.dirInf[i].offset; newBundleInf6.dirInf[i].decompressedSize = bundleInf6.dirInf[i].decompressedSize; newBundleInf6.dirInf[i].flags = bundleInf6.dirInf[i].flags; newBundleInf6.dirInf[i].name = bundleInf6.dirInf[i].name; } newBundleHeader6.Write(writer, 0); newBundleInf6.Write(writer, writer.Position); for (int i = 0; i < newBundleInf6.blockCount; i++) { writer.Write(blocksData[i]); } return(true); } return(false); }
public string DecompressPVR(string tgaFile) { string outFile = Path.GetDirectoryName(tgaFile) + "\\" + Path.GetFileNameWithoutExtension(tgaFile); bool compressed = false; using (BinaryReader tgaStream = new BinaryReader(File.OpenRead(tgaFile))) { int head = tgaStream.ReadInt32(); switch (head) { case 1481919403: { outFile += ".ktx"; break; } case 55727696: { outFile += ".pvr"; int imageSize = 52; tgaStream.BaseStream.Position = 44; int mipCount = tgaStream.ReadInt32(); int metaSize = tgaStream.ReadInt32(); if (metaSize > 0) { int JETtest = tgaStream.ReadInt32(); int LZ4test = tgaStream.ReadInt32(); if (JETtest == 1413827072 && LZ4test == 878332928) //lz4 { compressed = true; List <lz4mip> lz4mipData = new List <lz4mip>(); int dataSize = tgaStream.ReadInt32(); for (int i = 0; i < mipCount; i++) { //assume no surfaces or faces lz4mip amip = new lz4mip(); amip.offset = tgaStream.ReadInt32(); amip.compressedSize = tgaStream.ReadInt32(); amip.uncompressedSize = tgaStream.ReadInt32(); imageSize += amip.uncompressedSize; lz4mipData.Add(amip); } byte[] imageBuffer = new byte[imageSize]; tgaStream.BaseStream.Position = 0; tgaStream.Read(imageBuffer, 0, 48); //excluding meta data size which will be 0 int imageOffset = 52; foreach (var amip in lz4mipData) { tgaStream.BaseStream.Position = 52 + metaSize + amip.offset; byte[] lz4buffer = new byte[amip.compressedSize]; tgaStream.Read(lz4buffer, 0, amip.compressedSize); using (var inputStream = new MemoryStream(lz4buffer)) { var decoder = new Lz4DecoderStream(inputStream); byte[] mipBuffer = new byte[amip.uncompressedSize]; for (; ;) { int nRead = decoder.Read(mipBuffer, 0, amip.uncompressedSize); if (nRead == 0) { break; } } Buffer.BlockCopy(mipBuffer, 0, imageBuffer, imageOffset, amip.uncompressedSize); imageOffset += amip.uncompressedSize; } } using (BinaryWriter pvrStream = new BinaryWriter(File.Open(outFile, FileMode.Create))) { pvrStream.Write(imageBuffer); pvrStream.Close(); } return(outFile); } } break; } } } if (!compressed) { System.IO.File.Move(tgaFile, outFile); return(outFile); } else { return(tgaFile); } }