public override void ReadContents(byte[] bytes) { using (var ms = new MemoryStream(bytes)) { var typeByte = (byte) ms.ReadByte(); FrameType = (FrameType) (typeByte >> 4); Codec = (Codec) (typeByte & 0x0f); AVCType = AvcType.NotSet; if (Codec == Codec.AVC) { AVCType = (AvcType) ms.ReadByte(); if (bytes.Length >= 5) { switch (AVCType) { case AvcType.Nalu: CompositionTime = Utils.GetUInt24(ms.ReadBytes(3), 0); break; default: CompositionTime = Utils.GetUInt24(ms.ReadBytes(3), 0); break; } } } Payload = new byte[ms.Length - ms.Position]; ms.Read(Payload, 0, Payload.Length); } }
internal Chunk(MemoryStream ms) { Length = Helper.ConvertEndian(ms.ReadUInt32()); ChunkType = Encoding.ASCII.GetString(ms.ReadBytes(4)); ChunkData = ms.ReadBytes((int)Length); Crc = Helper.ConvertEndian(ms.ReadUInt32()); ParseData(new MemoryStream(ChunkData)); }
public GetWalletPubKeyResponse(byte[] bytes) { MemoryStream ms = new MemoryStream(bytes); var len = ms.ReadByte(); UncompressedPublicKey = new PubKey(ms.ReadBytes(len)); len = ms.ReadByte(); var addr = Encoding.ASCII.GetString(ms.ReadBytes(len)); Address = BitcoinAddress.GetFromBase58Data(addr); ChainCode = ms.ReadBytes(32); }
internal Chunk(byte[] bytes) { var ms = new MemoryStream(bytes); Length = Helper.ConvertEndian(ms.ReadUInt32()); ChunkType = Encoding.ASCII.GetString(ms.ReadBytes(4)); ChunkData = ms.ReadBytes((int)Length); Crc = Helper.ConvertEndian(ms.ReadUInt32()); if (ms.Position != ms.Length) throw new Exception("Chunk length not correct."); if (Length != ChunkData.Length) throw new Exception("Chunk data length not correct."); ParseData(new MemoryStream(ChunkData)); }
public static byte[] Decompress(this byte[] buffer) { if (buffer.Length > 17 && buffer.IsCompressed()) { MemoryStream inputStream = new MemoryStream(buffer); int lzmaID = inputStream.ReadInt(); int acutalSize = inputStream.ReadInt(); int lzmaSize = inputStream.ReadInt(); byte[] props = inputStream.ReadBytes(5); int lzmaBufferSize = buffer.Length - 17; if (lzmaBufferSize != lzmaSize) throw new Exception(string.Format("LZMA data corruption. Expected {0} bytes got {1}", lzmaSize, lzmaBufferSize)); byte[] uncompressedBuffer = new byte[acutalSize]; MemoryStream outputStream = new MemoryStream(uncompressedBuffer); try { LZMADecoder = new Decoder(); LZMADecoder.SetDecoderProperties(props); LZMADecoder.Code(inputStream, outputStream, inputStream.Length, outputStream.Length, null); } catch (Exception e) { throw new Exception(e.Message); } return uncompressedBuffer; } else throw new Exception("Buffer is not compressed!"); }
private static ICollection<Sc2ReplayAttribute> ParseAttributes(IMpqArchive replay) { var file = replay.ReadFile("replay.attributes.events"); using (var stream = new MemoryStream(file)) { stream.Skip(5); // there is a 5-byte header; should we validate this? var attributeCount = stream.ReadInt32(); var attributes = new List<Sc2ReplayAttribute>(); for (var i = 0; i < attributeCount; i++) { var attr = new Sc2ReplayAttribute { Header = stream.ReadInt32(), Type = (Sc2ReplayAttributeType) stream.ReadInt32(), PlayerIndex = stream.ReadByte(), Value = stream.ReadBytes(4).Reverse().ToArray(), }; attributes.Add(attr); } return attributes; } }
public void Decode(byte[] bytes) { using (var ms = new MemoryStream(bytes)) { StreamId = dc.GetInt32(ms.ReadBytes(4), 0); } }
private static bool Fill(StealthMetadata output, Script metadata, byte[] data) { if(data == null || data.Length != 1 + 4 + 33) return false; MemoryStream ms = new MemoryStream(data); output.Version = ms.ReadByte(); if(output.Version != 6) return false; output.Nonce = ms.ReadBytes(4); output.EphemKey = new PubKey(ms.ReadBytes(33)); output.Script = metadata; output.Hash = Hashes.Hash256(data); var msprefix = new MemoryStream(output.Hash.ToBytes(false)); output.BitField = Utils.ToUInt32(msprefix.ReadBytes(4), true); return true; }
public void Decode(byte[] bytes) { using (var ms = new MemoryStream(bytes)) { Value = dc.GetInt32(ms.ReadBytes(4), 0); Type = (LimitType) ms.ReadByte(); } }
public void Decode(byte[] bytes) { using (var ms = new MemoryStream(bytes)) { Type = (ControlType) dc.GetInt16(ms.ReadBytes(2), 0); switch (Type) { case ControlType.STREAM_BEGIN: case ControlType.STREAM_EOF: case ControlType.STREAM_DRY: case ControlType.STREAM_IS_RECORDED: StreamID = dc.GetInt32(ms.ReadBytes(4), 0); break; case ControlType.SET_BUFFER: StreamID = dc.GetInt32(ms.ReadBytes(4), 0); BufferLength = dc.GetInt32(ms.ReadBytes(4), 0); break; case ControlType.PING_REQUEST: case ControlType.PING_RESPONSE: Time = dc.GetInt32(ms.ReadBytes(4), 0); break; case ControlType.SWFV_REQUEST: break; case ControlType.SWFV_RESPONSE: Bytes = ms.ReadBytes(42); break; case ControlType.BUFFER_FULL: case ControlType.BUFFER_EMPTY: StreamID = dc.GetInt32(ms.ReadBytes(4), 0); break; } } }
private static bool Fill(StealthMetadata output, Script metadata) { var ops = metadata.ToOps().ToArray(); if(ops.Length != 2 || ops[0].Code != OpcodeType.OP_RETURN) return false; var data = ops[1].PushData; if(data == null || data.Length != 1 + 4 + 33) return false; MemoryStream ms = new MemoryStream(data); output.Version = ms.ReadByte(); if(output.Version != 6) return false; output.Nonce = ms.ReadBytes(4); output.EphemKey = new PubKey(ms.ReadBytes(33)); output.Script = metadata; output.Hash = Hashes.Hash256(data); var msprefix = new MemoryStream(output.Hash.ToBytes(false)); output.BitField = Utils.ToUInt32(msprefix.ReadBytes(4), true); return true; }
public void SliceStreamTest() { MemoryStream MemoryStream = new MemoryStream(Encoding.ASCII.GetBytes("Hello World")); MemoryStream.ReadBytes(6); var SliceStream = MemoryStream.ReadStream(); Assert.AreEqual("Wo", Encoding.ASCII.GetString(SliceStream.ReadBytes(2))); var SliceStream2 = SliceStream.ReadStream(); Assert.AreEqual(0, SliceStream.Available()); Assert.AreEqual("rld", Encoding.ASCII.GetString(SliceStream2.ReadBytes(3))); Assert.AreEqual(0, SliceStream2.Available()); }
public byte[] DecodeImaAdpcmData() { var s = new MemoryStream(RawOutput); var numBlocks = DataSize / BlockAlign; var blockDataSize = BlockAlign - (Channels * 4); var outputSize = UncompressedSize * Channels * 2; var outOffset = 0; var output = new byte[outputSize]; var predictor = new int[Channels]; var index = new int[Channels]; // Decode each block of IMA ADPCM data in RawOutput for (var block = 0; block < numBlocks; block++) { // Each block starts with a initial state per-channel for (var c = 0; c < Channels; c++) { predictor[c] = s.ReadInt16(); index[c] = s.ReadUInt8(); /* unknown/reserved */ s.ReadUInt8(); // Output first sample from input output[outOffset++] = (byte)predictor[c]; output[outOffset++] = (byte)(predictor[c] >> 8); if (outOffset >= outputSize) return output; } // Decode and output remaining data in this block var blockOffset = 0; while (blockOffset < blockDataSize) { for (var c = 0; c < Channels; c++) { // Decode 4 bytes (to 16 bytes of output) per channel var chunk = s.ReadBytes(4); var decoded = ImaAdpcmReader.LoadImaAdpcmSound(chunk, ref index[c], ref predictor[c]); // Interleave output, one sample per channel var outOffsetChannel = outOffset + (2 * c); for (var i = 0; i < decoded.Length; i += 2) { var outOffsetSample = outOffsetChannel + i; if (outOffsetSample >= outputSize) return output; output[outOffsetSample] = decoded[i]; output[outOffsetSample + 1] = decoded[i + 1]; outOffsetChannel += 2 * (Channels - 1); } blockOffset += 4; } outOffset += 16 * Channels; } } return output; }
public Packet Parse() { var p = new Packet(); byte header = _socket.ReceiveByte(); int chunktype = (header & 0xC0) >> 6; p.ChunkType = chunktype; p.ChunkStreamId = header & 0x3F; switch (p.ChunkStreamId) { case 0: p.ChunkStreamId = 64 + _socket.ReceiveByte(); break; case 1: p.ChunkStreamId = 64 + _socket.ReceiveByte() + (_socket.ReceiveByte()*256); break; } switch (p.ChunkType) { case 3: p.TimeStamp = _previousReadPacket[p.ChunkStreamId].TimeStamp; p.Length = _previousReadPacket[p.ChunkStreamId].Length; p.Type = _previousReadPacket[p.ChunkStreamId].Type; p.MessageStreamId = _previousReadPacket[p.ChunkStreamId].MessageStreamId; break; case 2: p.Length = _previousReadPacket[p.ChunkStreamId].Length; p.Type = _previousReadPacket[p.ChunkStreamId].Type; p.MessageStreamId = _previousReadPacket[p.ChunkStreamId].MessageStreamId; break; case 1: p.MessageStreamId = _previousReadPacket[p.ChunkStreamId].MessageStreamId; break; case 0: break; } _previousReadPacket[p.ChunkStreamId] = p; int headersize = HeaderSizes[p.ChunkType]; if (headersize == MaxHeaderSize) { p.HasAbsTimestamp = true; } if (!Operations.ContainsKey(p.ChunkStreamId)) { Operations[p.ChunkStreamId] = new Operation(); } if (Operations[p.ChunkStreamId].Response != null) { p = Operations[p.ChunkStreamId].Response; headersize = 0; } else { Operations[p.ChunkStreamId].CreateResponse(p); } headersize--; var headerbytes = new byte[0]; if (headersize > 0) { headerbytes = new byte[headersize]; _socket.Receive(headerbytes, 0, headersize); } using (var headerstream = new MemoryStream(headerbytes)) { if (headersize >= 3) { p.TimeStamp = (int) Utils.GetUInt24(headerstream.ReadBytes(3), 0); if (!p.HasAbsTimestamp) { if (!_streamTimestamps.ContainsKey(p.ChunkStreamId)) _streamTimestamps[p.ChunkStreamId] = 0; p.TimeStamp += _streamTimestamps[p.ChunkStreamId]; _streamTimestamps[p.ChunkStreamId] = p.TimeStamp; } } if (headersize >= 6) { p.Length = (int) Utils.GetUInt24(headerstream.ReadBytes(3), 0); p.BytesRead = 0; p.BytePayload = null; } if (headersize > 6) { p.Type = (PayloadType) headerstream.ReadByte(); } if (headersize == 11) { p.MessageStreamId = DataConverter.LittleEndian.GetInt32(headerstream.ReadBytes(4), 0); } } int ntoread = p.Length - p.BytesRead; int nchunk = ChunkSizeR; if (ntoread < nchunk) { nchunk = ntoread; } if (p.BytePayload == null) { p.BytePayload = new byte[0]; } int prevLength = p.BytePayload.Length; Array.Resize(ref p.BytePayload, prevLength + nchunk); _socket.Receive(p.BytePayload, prevLength, nchunk); if (p.BytesRead + nchunk != p.BytePayload.Length) { throw new Exception(String.Format("Read failed, have read {0} of {1}", p.BytePayload.Length, p.BytesRead + nchunk)); } p.BytesRead += nchunk; if (!p.IsReady()) { return null; } p.DecodePayload(); //Special cases that affect the packet parser switch (p.Type) { case PayloadType.CHUNK_SIZE: ChunkSizeR = ((ChunkSize) p.Payload).Size; break; case PayloadType.VIDEO: var v = (Video) p.Payload; v.FlvTag.TimeStamp = (uint) p.TimeStamp; //v.FlvTag.StreamID = (uint)p.MessageStreamID; break; case PayloadType.AUDIO: var a = (Audio) p.Payload; a.FlvTag.TimeStamp = (uint) p.TimeStamp; //v.FlvTag.StreamID = (uint)p.MessageStreamID; break; } return p; }
public async Task<Stream> DecryptDatabase(byte[] source, byte[] aesKey) { var unreadData = source; byte[] decryptedDatabase = null; try { _encryptionEngine.AlgorithmType = CryptoAlgoritmType.AES_CBC_PKCS7; decryptedDatabase = await _encryptionEngine.Decrypt(source, aesKey, file.pbEncryptionIV); } catch (Exception e) { throw new SecurityException("There was a problem opening your database", e); } var startBytes = new byte[32]; var databaseReader = new MemoryStream(decryptedDatabase); databaseReader.ReadBytes(startBytes); var headerStartBytes = file.pbStreamStartBytes; for (int iStart = 0; iStart < 32; ++iStart) { if (startBytes[iStart] != headerStartBytes[iStart]) throw new Exception(); } return databaseReader; }
protected override void ParseData(MemoryStream ms) { SequenceNumber = Helper.ConvertEndian(ms.ReadUInt32()); FrameData = ms.ReadBytes((int) Length - 4); }
public ME2Texture2D(ME2PCCObject pcc, int pccExpID, String pathBioGame) { ME2ExportEntry exp = pcc.Exports[pccExpID]; if (String.Compare(exp.ClassName, className) != 0 && String.Compare(exp.ClassName, class2) != 0 && String.Compare(exp.ClassName, class3) != 0) { throw new FormatException("Export is not a texture"); } Class = exp.ClassName; exportOffset = exp.DataOffset; FullPackage = exp.PackageFullName; texName = exp.ObjectName; pccFileName = pcc.pccFileName; allPccs = new List<string>(); allPccs.Add(pcc.pccFileName); properties = new Dictionary<string, SaltPropertyReader.Property>(); byte[] rawData = (byte[])exp.Data.Clone(); Compression = "No Compression"; int propertiesOffset = SaltPropertyReader.detectStart(pcc, rawData); headerData = new byte[propertiesOffset]; Buffer.BlockCopy(rawData, 0, headerData, 0, propertiesOffset); pccOffset = (uint)exp.DataOffset; UnpackNum = 0; List<SaltPropertyReader.Property> tempProperties = SaltPropertyReader.getPropList(pcc, rawData); for (int i = 0; i < tempProperties.Count; i++) { SaltPropertyReader.Property property = tempProperties[i]; if (property.Name == "UnpackMin") UnpackNum++; if (!properties.ContainsKey(property.Name)) properties.Add(property.Name, property); switch (property.Name) { case "Format": texFormat = property.Value.StringValue; break; case "TextureFileCacheName": arcName = property.Value.StringValue; break; case "LODGroup": LODGroup = property.Value.StringValue; break; case "CompressionSettings": Compression = property.Value.StringValue; break; case "None": dataOffset = (uint)(property.offsetval + property.Size); break; } } // if "None" property isn't found throws an exception if (dataOffset == 0) throw new Exception("\"None\" property not found"); if (!String.IsNullOrEmpty(arcName)) FullArcPath = GetTexArchive(pathBioGame); imageData = new byte[rawData.Length - dataOffset]; Buffer.BlockCopy(rawData, (int)dataOffset, imageData, 0, (int)(rawData.Length - dataOffset)); //DebugOutput.PrintLn("ImageData size = " + imageData.Length); pccExpIdx = pccExpID; MemoryStream dataStream = new MemoryStream(imageData); privateimgList = new List<ImageInfo>(); dataStream.ReadValueU32(); //Current position in pcc numMipMaps = dataStream.ReadValueU32(); uint count = numMipMaps; ArcDataSize = 0; //DebugOutput.PrintLn(numMipMaps + " derp"); while (dataStream.Position < dataStream.Length && count > 0) { ImageInfo imgInfo = new ImageInfo(); imgInfo.storageType = (storage)dataStream.ReadValueS32(); imgInfo.uncSize = dataStream.ReadValueS32(); imgInfo.cprSize = dataStream.ReadValueS32(); imgInfo.offset = dataStream.ReadValueS32(); if (imgInfo.storageType == storage.pccSto) { imgInfo.offset = (int)dataStream.Position; dataStream.Seek(imgInfo.uncSize, SeekOrigin.Current); } else if (imgInfo.storageType == storage.arcCpr || imgInfo.storageType == storage.arcUnc) { ArcDataSize += imgInfo.uncSize; } imgInfo.imgSize = new ImageSize(dataStream.ReadValueU32(), dataStream.ReadValueU32()); if (privateimgList.Exists(img => img.imgSize == imgInfo.imgSize)) { uint width = imgInfo.imgSize.width; uint height = imgInfo.imgSize.height; if (width == 4 && privateimgList.Exists(img => img.imgSize.width == width)) width = privateimgList.Last().imgSize.width / 2; if (width == 0) width = 1; if (height == 4 && privateimgList.Exists(img => img.imgSize.height == height)) height = privateimgList.Last().imgSize.height / 2; if (height == 0) height = 1; imgInfo.imgSize = new ImageSize(width, height); if (privateimgList.Exists(img => img.imgSize == imgInfo.imgSize)) throw new Exception("Duplicate image size found"); } privateimgList.Add(imgInfo); count--; //DebugOutput.PrintLn("ImgInfo no: " + count + ", Storage Type = " + imgInfo.storageType + ", offset = " + imgInfo.offset); } // Grab the rest for the footer footerData = new byte[dataStream.Length - dataStream.Position]; footerData = dataStream.ReadBytes(footerData.Length); }
private ME1Package(string path) { DebugOutput.PrintLn("Load file : " + path); FileName = Path.GetFullPath(path); MemoryStream tempStream = new MemoryStream(); if (!File.Exists(FileName)) throw new FileNotFoundException("PCC file not found"); using (FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read)) { FileInfo tempInfo = new FileInfo(FileName); tempStream.WriteFromStream(fs, tempInfo.Length); if (tempStream.Length != tempInfo.Length) { throw new FileLoadException("File not fully read in. Try again later"); } } tempStream.Seek(12, SeekOrigin.Begin); int tempNameSize = tempStream.ReadValueS32(); tempStream.Seek(64 + tempNameSize, SeekOrigin.Begin); int tempGenerations = tempStream.ReadValueS32(); tempStream.Seek(36 + tempGenerations * 12, SeekOrigin.Current); int tempPos = (int)tempStream.Position + 4; tempStream.Seek(0, SeekOrigin.Begin); header = tempStream.ReadBytes(tempPos); tempStream.Seek(0, SeekOrigin.Begin); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) { DebugOutput.PrintLn("Magic number incorrect: " + magic); throw new FormatException("This is not an ME1 Package file. The magic number is incorrect."); } MemoryStream listsStream; if (IsCompressed) { DebugOutput.PrintLn("File is compressed"); listsStream = CompressionHelper.DecompressME1orME2(tempStream); //Correct the header IsCompressed = false; listsStream.Seek(0, SeekOrigin.Begin); listsStream.WriteBytes(header); // Set numblocks to zero listsStream.WriteValueS32(0); //Write the magic number listsStream.WriteBytes(new byte[] { 0xF2, 0x56, 0x1B, 0x4E }); // Write 4 bytes of 0 listsStream.WriteValueS32(0); } else { DebugOutput.PrintLn("File already decompressed. Reading decompressed data."); //listsStream = tempStream; listsStream = new MemoryStream(); tempStream.WriteTo(listsStream); } tempStream.Dispose(); ReadNames(listsStream); ReadImports(listsStream); ReadExports(listsStream); }
private void ReadExports(MemoryStream fs) { DebugOutput.PrintLn("Reading Exports..."); fs.Seek(ExportOffset, SeekOrigin.Begin); exports = new List<ME1ExportEntry>(); byte[] buffer; for (int i = 0; i < ExportCount; i++) { long start = fs.Position; fs.Seek(40, SeekOrigin.Current); int count = fs.ReadValueS32(); fs.Seek(4 + count * 12, SeekOrigin.Current); count = fs.ReadValueS32(); fs.Seek(4 + count * 4, SeekOrigin.Current); fs.Seek(16, SeekOrigin.Current); long end = fs.Position; fs.Seek(start, SeekOrigin.Begin); ME1ExportEntry exp = new ME1ExportEntry(this, fs.ReadBytes((int)(end - start)), (uint)start); buffer = new byte[exp.DataSize]; fs.Seek(exp.DataOffset, SeekOrigin.Begin); fs.Read(buffer, 0, buffer.Length); exp.Data = buffer; exp.DataChanged = false; exp.Index = i; exp.PropertyChanged += exportChanged; exports.Add(exp); fs.Seek(end, SeekOrigin.Begin); } }
public static SaveFile Deserialize(Stream input, DeserializeSettings settings) { if (input.Position + 20 > input.Length) { throw new SaveCorruptionException("not enough data for save header"); } var check = input.ReadValueU32(Endian.Big); if (check == 0x434F4E20) { throw new SaveFormatException("Xbox 360 save game loading is in the works"); } input.Seek(-4, SeekOrigin.Current); var readSha1Hash = input.ReadBytes(20); using (var data = input.ReadToMemoryStream(input.Length - 20)) { byte[] computedSha1Hash; using (var sha1 = new System.Security.Cryptography.SHA1Managed()) { computedSha1Hash = sha1.ComputeHash(data); } if ((settings & DeserializeSettings.IgnoreSha1Mismatch) == 0 && readSha1Hash.SequenceEqual(computedSha1Hash) == false) { throw new SaveCorruptionException("invalid SHA1 hash"); } data.Position = 0; var uncompressedSize = data.ReadValueU32(Endian.Big); var uncompressedBytes = new byte[uncompressedSize]; if (uncompressedSize <= BlockSize) { var actualUncompressedSize = (int)uncompressedSize; var compressedSize = (uint)(data.Length - 4); var compressedBytes = data.ReadBytes(compressedSize); var result = LZO.Decompress(compressedBytes, 0, (int)compressedSize, uncompressedBytes, 0, ref actualUncompressedSize); if (result != LZO.ErrorCode.Success) { throw new SaveCorruptionException(string.Format("LZO decompression failure ({0})", result)); } if (actualUncompressedSize != (int)uncompressedSize) { throw new SaveCorruptionException("LZO decompression failure (uncompressed size mismatch)"); } } else { var blockCount = data.ReadValueU32(Endian.Big); var blockInfos = new List<Tuple<uint, uint>>(); for (uint i = 0; i < blockCount; i++) { var blockCompressedSize = data.ReadValueU32(Endian.Big); var blockUncompressedSize = data.ReadValueU32(Endian.Big); blockInfos.Add(new Tuple<uint, uint>(blockCompressedSize, blockUncompressedSize)); } int uncompressedOffset = 0; int uncompressedSizeLeft = (int)uncompressedSize; foreach (var blockInfo in blockInfos) { var blockUncompressedSize = Math.Min((int)blockInfo.Item2, uncompressedSizeLeft); var actualUncompressedSize = blockUncompressedSize; var compressedSize = (int)blockInfo.Item1; var compressedBytes = data.ReadBytes(compressedSize); var result = LZO.Decompress(compressedBytes, 0, compressedSize, uncompressedBytes, uncompressedOffset, ref actualUncompressedSize); if (result != LZO.ErrorCode.Success) { throw new SaveCorruptionException(string.Format("LZO decompression failure ({0})", result)); } if (actualUncompressedSize != blockUncompressedSize) { throw new SaveCorruptionException("LZO decompression failure (uncompressed size mismatch)"); } uncompressedOffset += blockUncompressedSize; uncompressedSizeLeft -= blockUncompressedSize; } if (uncompressedSizeLeft != 0) { throw new SaveCorruptionException("LZO decompression failure (uncompressed size left != 0)"); } } using (var outerData = new MemoryStream(uncompressedBytes)) { var innerSize = outerData.ReadValueU32(Endian.Big); var magic = outerData.ReadString(3); if (magic != "WSG") { throw new SaveCorruptionException("invalid magic"); } var version = outerData.ReadValueU32(Endian.Little); if (version != 2 && version.Swap() != 2) { throw new SaveCorruptionException("invalid or unsupported version"); } var endian = version == 2 ? Endian.Little : Endian.Big; var readCRC32Hash = outerData.ReadValueU32(endian); var innerUncompressedSize = outerData.ReadValueS32(endian); var innerCompressedBytes = outerData.ReadBytes(innerSize - 3 - 4 - 4 - 4); var innerUncompressedBytes = Huffman.Decoder.Decode(innerCompressedBytes, innerUncompressedSize); if (innerUncompressedBytes.Length != innerUncompressedSize) { throw new SaveCorruptionException("huffman decompression failure"); } var computedCRC32Hash = CRC32.Hash(innerUncompressedBytes, 0, innerUncompressedBytes.Length); if ((settings & DeserializeSettings.IgnoreCrc32Mismatch) == 0 && computedCRC32Hash != readCRC32Hash) { throw new SaveCorruptionException("invalid CRC32 hash"); } using (var innerUncompressedData = new MemoryStream(innerUncompressedBytes)) { var saveGame = ProtoBuf.Serializer.Deserialize<WillowTwoSave.WillowTwoPlayerSaveGame>(innerUncompressedData); if ((settings & DeserializeSettings.IgnoreReencodeMismatch) == 0) { using (var testData = new MemoryStream()) { ProtoBuf.Serializer.Serialize(testData, saveGame); testData.Position = 0; var testBytes = testData.ReadBytes((uint)testData.Length); if (innerUncompressedBytes.SequenceEqual(testBytes) == false) { throw new SaveCorruptionException("reencode mismatch"); } } } saveGame.Decompose(); return new SaveFile() { Endian = endian, SaveGame = saveGame, }; } } } }
public void Serialize(Stream output) { var saveGame = this.SaveGame; byte[] innerUncompressedBytes; using (var innerUncompressedData = new MemoryStream()) { saveGame.Compose(); try { ProtoBuf.Serializer.Serialize(innerUncompressedData, saveGame); } finally { saveGame.Decompose(); } innerUncompressedData.Position = 0; innerUncompressedBytes = innerUncompressedData.ReadBytes((uint)innerUncompressedData.Length); } byte[] innerCompressedBytes; using (var innerCompressedData = new MemoryStream()) { var endian = this.Endian; innerCompressedData.WriteValueS32(0, Endian.Big); innerCompressedData.WriteString("WSG"); innerCompressedData.WriteValueU32(2, endian); innerCompressedData.WriteValueU32(CRC32.Hash(innerUncompressedBytes, 0, innerUncompressedBytes.Length), endian); // crc32 innerCompressedData.WriteValueS32(innerUncompressedBytes.Length, endian); var encoder = new Huffman.Encoder(); encoder.Build(innerUncompressedBytes); innerCompressedData.WriteBytes(encoder.Encode(innerUncompressedBytes)); innerCompressedData.Position = 0; innerCompressedData.WriteValueU32((uint)(innerCompressedData.Length - 4), Endian.Big); innerCompressedData.Position = 0; innerCompressedBytes = innerCompressedData.ReadBytes((uint)innerCompressedData.Length); } byte[] compressedBytes; if (innerCompressedBytes.Length <= BlockSize) { compressedBytes = new byte[innerCompressedBytes.Length + (innerCompressedBytes.Length / 16) + 64 + 3]; var actualCompressedSize = compressedBytes.Length; var result = LZO.Compress(innerCompressedBytes, 0, innerCompressedBytes.Length, compressedBytes, 0, ref actualCompressedSize); if (result != LZO.ErrorCode.Success) { throw new SaveCorruptionException(string.Format("LZO compression failure ({0})", result)); } Array.Resize(ref compressedBytes, actualCompressedSize); } else { int innerCompressedOffset = 0; int innerCompressedSizeLeft = innerCompressedBytes.Length; using (var blockData = new MemoryStream()) { var blockCount = (innerCompressedSizeLeft + BlockSize) / BlockSize; blockData.WriteValueS32(blockCount, Endian.Big); blockData.Position = 4 + (blockCount * 8); var blockInfos = new List<Tuple<uint, uint>>(); while (innerCompressedSizeLeft > 0) { var blockUncompressedSize = Math.Min(BlockSize, innerCompressedSizeLeft); compressedBytes = new byte[blockUncompressedSize + (blockUncompressedSize / 16) + 64 + 3]; var actualCompressedSize = compressedBytes.Length; var result = LZO.Compress(innerCompressedBytes, innerCompressedOffset, blockUncompressedSize, compressedBytes, 0, ref actualCompressedSize); if (result != LZO.ErrorCode.Success) { throw new SaveCorruptionException(string.Format("LZO compression failure ({0})", result)); } blockData.Write(compressedBytes, 0, actualCompressedSize); blockInfos.Add(new Tuple<uint, uint>((uint)actualCompressedSize, BlockSize)); innerCompressedOffset += blockUncompressedSize; innerCompressedSizeLeft -= blockUncompressedSize; } blockData.Position = 4; foreach (var blockInfo in blockInfos) { blockData.WriteValueU32(blockInfo.Item1, Endian.Big); blockData.WriteValueU32(blockInfo.Item2, Endian.Big); } blockData.Position = 0; compressedBytes = blockData.ReadBytes((uint)blockData.Length); } } byte[] uncompressedBytes; using (var uncompressedData = new MemoryStream()) { uncompressedData.WriteValueS32(innerCompressedBytes.Length, Endian.Big); uncompressedData.WriteBytes(compressedBytes); uncompressedData.Position = 0; uncompressedBytes = uncompressedData.ReadBytes((uint)uncompressedData.Length); } byte[] computedHash; using (var sha1 = new System.Security.Cryptography.SHA1Managed()) { computedHash = sha1.ComputeHash(uncompressedBytes); } output.WriteBytes(computedHash); output.WriteBytes(uncompressedBytes); }
private void ReadExports(MemoryStream fs) { DebugOutput.PrintLn("Reading Exports..."); fs.Seek(ExportOffset, SeekOrigin.Begin); Exports = new List<ME1ExportEntry>(); for (int i = 0; i < ExportCount; i++) { long start = fs.Position; ME1ExportEntry exp = new ME1ExportEntry(); exp.pccRef = this; exp.infoOffset = (int)start; fs.Seek(40, SeekOrigin.Current); int count = fs.ReadValueS32(); fs.Seek(4 + count * 12, SeekOrigin.Current); count = fs.ReadValueS32(); fs.Seek(4 + count * 4, SeekOrigin.Current); fs.Seek(16, SeekOrigin.Current); long end = fs.Position; fs.Seek(start, SeekOrigin.Begin); exp.info = fs.ReadBytes((int)(end - start)); Exports.Add(exp); fs.Seek(end, SeekOrigin.Begin); if (LastExport == null || exp.DataOffset > LastExport.DataOffset) LastExport = exp; } }
private STFSPackage(IFile f) { Stream input = f.GetStream(); FileName = f.Name; disposed = false; stream = input; // Set the type of STFS file. string magic = stream.ReadASCIINullTerminated(4); switch (magic) { case "CON ": Type = STFSType.CON; break; case "LIVE": Type = STFSType.LIVE; break; case "PIRS": Type = STFSType.PIRS; break; default: throw new InvalidDataException("STFS is not CON, LIVE, or PIRS"); } BlockCache = new byte[0x1000]; // Set up STFS info. stream.Position = 0x340; headerSize = stream.ReadInt32BE(); if ((((headerSize + 0xFFF) & 0xF000) >> 0xC) == 0xB) { tableSizeShift = 0; } else { tableSizeShift = 1; } // Volume Descriptor begins at 0x379 stream.Position = 0x37C; fileTableBlockCount = stream.ReadInt16LE(); fileTableBlockNumber = stream.ReadInt24LE(); stream.Position = 0x39D; fileCount = stream.ReadInt32LE(); #if !MINIMAL // Read both package thumbnails into Image instances stream.Position = 0x1712; int thumbnailImgSize = stream.ReadInt32BE(); int titleThumbnailImgSize = stream.ReadInt32BE(); stream.Position = 0x171A; if (thumbnailImgSize > 0) { Thumbnail = System.Drawing.Image.FromStream(new System.IO.MemoryStream(stream.ReadBytes(thumbnailImgSize))); } stream.Position = 0x571A; if (titleThumbnailImgSize > 0) { TitleThumbnail = System.Drawing.Image.FromStream(new System.IO.MemoryStream(stream.ReadBytes(titleThumbnailImgSize))); } #endif root = new STFSDirectory(null, ROOT_DIR); var dirsOrdinal = new Dictionary <int, STFSDirectory>(); dirsOrdinal.Add(-1, root); int items = 0; int[] fileTableBlocks = GetFileBlocks(fileTableBlockNumber, fileTableBlockCount, false); for (var x = 0; x < fileTableBlocks.Length; x++) { var curBlock = fileTableBlocks[x]; long basePosition; CacheBlockAt(BlockToOffset(curBlock)); using (var curBlockStream = new System.IO.MemoryStream(BlockCache)) { for (var i = 0; i < 0x40; i++) { basePosition = 0x40 * i; curBlockStream.Position = basePosition; if (curBlockStream.ReadByte() == 0) { break; } curBlockStream.Position = basePosition + 0x28; byte flags = (byte)curBlockStream.ReadByte(); curBlockStream.Position = basePosition; String name; using (var sr = new System.IO.StreamReader( new System.IO.MemoryStream(curBlockStream.ReadBytes(flags & 0x3f)), Encoding.GetEncoding(1252))) { name = sr.ReadToEnd(); } curBlockStream.Position = basePosition + 0x29; int numBlocks = curBlockStream.ReadInt24LE(); curBlockStream.ReadInt24LE(); int startBlock = curBlockStream.ReadInt24LE(); int parentDir = curBlockStream.ReadInt16BE(); uint size = curBlockStream.ReadUInt32BE(); int update = curBlockStream.ReadInt32BE(); int access = curBlockStream.ReadInt32BE(); STFSDirectory parent; if (!dirsOrdinal.TryGetValue(parentDir, out parent)) // get the parent if it exists { throw new InvalidDataException("File references non-existent directory."); } if ((flags & 0x80) == 0x80) { // item is a directory var tmp = new STFSDirectory(parent, name); dirsOrdinal.Add(items, tmp); parent.AddDir(tmp); } else { // item is a file STFSFile tmp; if ((flags & 0x40) == 0x40) // blocks are sequential { var dataBlocks = GetFileBlocks(startBlock, numBlocks, (flags & 0x40) == 0x40); tmp = new STFSFile(name, size, dataBlocks, parent, this); } else // offload block calculation until we need it { tmp = new STFSFile(name, size, startBlock, numBlocks, parent, this); } parent.AddFile(tmp); } items++; } } } }
private byte[] GetData() { MemoryStream ms = new MemoryStream(pccRef.listsStream.GetBuffer()); { ms.Seek((long)DataOffset, SeekOrigin.Begin); return ms.ReadBytes(DataSize); } }
void PCCObjectHelper(MemoryStream tempStream, string filePath) { tempStream.Seek(0, SeekOrigin.Begin); Names = new List<string>(); Imports = new List<ImportEntry>(); Exports = new List<ExportEntry>(); if (GameVersion != 3) { // Find ME1 and 2 header...Why so difficult ME1 and 2? tempStream.Seek(12, SeekOrigin.Begin); int tempNameSize = tempStream.ReadInt32(); tempStream.Seek(64 + tempNameSize, SeekOrigin.Begin); int tempGenerator = tempStream.ReadInt32(); tempStream.Seek(36 + tempGenerator * 12, SeekOrigin.Current); int tempPos = (int)tempStream.Position + (GameVersion == 2 ? 0 : 4); tempStream.Seek(0, SeekOrigin.Begin); header = tempStream.ReadBytes(tempPos); tempStream.Seek(0, SeekOrigin.Begin); } else header = tempStream.ReadBytes(headerSize); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) throw new FormatException(filePath + " is not a pcc file"); if (GameVersion == 3 && lowVers != 684 && highVers != 194) throw new FormatException("unsupported version"); if (compressed) { if (GameVersion == 3) ReadCompressedME3(tempStream); else ReadCompressedME1And2(tempStream); compressed = false; } else listsStream = tempStream; //Fill name list listsStream.Seek(NameOffset, SeekOrigin.Begin); for (int i = 0; i < NameCount; i++) { int strLength = listsStream.ReadInt32(); string name = null; switch (GameVersion) { case 1: name = ReadME1Name(strLength); break; case 2: name = ReadME2Name(strLength); break; case 3: name = ReadME3Name(strLength); break; } Names.Add(name); } byte[] buffer = null; // fill import list listsStream.Seek(ImportOffset, SeekOrigin.Begin); buffer = new byte[ImportEntry.byteSize]; for (int i = 0; i < ImportCount; i++) Imports.Add(new ImportEntry(this, listsStream)); //fill export list listsStream.Seek(ExportOffset, SeekOrigin.Begin); for (int i = 0; i < ExportCount; i++) { uint expInfoOffset = (uint)listsStream.Position; // Find export data size int count = 0; int expInfoSize = 0; if (GameVersion == 3) { listsStream.Seek(44, SeekOrigin.Current); count = listsStream.ReadInt32(); expInfoSize = 68 + (count * 4); } else { listsStream.Seek(40, SeekOrigin.Current); count = listsStream.ReadInt32(); listsStream.Seek(4 + count * 12, SeekOrigin.Current); count = listsStream.ReadInt32(); listsStream.Seek(4 + count * 4, SeekOrigin.Current); listsStream.Seek(16, SeekOrigin.Current); expInfoSize = (int)(listsStream.Position - expInfoOffset); } // Read export data buffer = new byte[expInfoSize]; listsStream.Seek(expInfoOffset, SeekOrigin.Begin); listsStream.Read(buffer, 0, buffer.Length); Exports.Add(new ExportEntry(this, buffer, expInfoOffset)); } }
private void LoadHelper(MemoryStream tempStream) { tempStream.Seek(12, SeekOrigin.Begin); int tempNameSize = tempStream.ReadValueS32(); tempStream.Seek(64 + tempNameSize, SeekOrigin.Begin); int tempGenerator = tempStream.ReadValueS32(); tempStream.Seek(36 + tempGenerator * 12, SeekOrigin.Current); int tempPos = (int)tempStream.Position + 4; tempStream.Seek(0, SeekOrigin.Begin); header = tempStream.ReadBytes(tempPos); tempStream.Seek(0, SeekOrigin.Begin); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) { DebugOutput.PrintLn("Magic number incorrect: " + magic); throw new FormatException("This is not a pcc file. The magic number is incorrect."); } if (bCompressed) { DebugOutput.PrintLn("File is compressed"); listsStream = lzo.DecompressPCC(tempStream, this); //Correct the header bCompressed = false; listsStream.Seek(0, SeekOrigin.Begin); listsStream.WriteBytes(header); // Set numblocks to zero listsStream.WriteValueS32(0); //Write the magic number listsStream.WriteBytes(new byte[] { 0xF2, 0x56, 0x1B, 0x4E }); // Write 4 bytes of 0 listsStream.WriteValueS32(0); } else { DebugOutput.PrintLn("File already decompressed. Reading decompressed data."); //listsStream = tempStream; listsStream = new MemoryStream(); tempStream.WriteTo(listsStream); } tempStream.Dispose(); ReadNames(listsStream); ReadImports(listsStream); ReadExports(listsStream); LoadExports(); }
public PCCObject(String path, Boolean littleEndian=true) { lzo = new SaltLZOHelper(); fullname = path; BitConverter.IsLittleEndian = littleEndian; StreamHelpers.setIsLittleEndian(littleEndian); DebugOutput.PrintLn("Load file : " + path); pccFileName = Path.GetFullPath(path); MemoryStream tempStream = new MemoryStream(); if (!File.Exists(pccFileName)) throw new FileNotFoundException("PCC file not found"); using (FileStream fs = new FileStream(pccFileName, FileMode.Open, FileAccess.Read)) { FileInfo tempInfo = new FileInfo(pccFileName); tempStream.WriteFromStream(fs, tempInfo.Length); if (tempStream.Length != tempInfo.Length) { throw new FileLoadException("File not fully read in. Try again later"); } } tempStream.Seek(12, SeekOrigin.Begin); int tempNameSize = tempStream.ReadValueS32(); tempStream.Seek(64 + tempNameSize, SeekOrigin.Begin); int tempGenerator = tempStream.ReadValueS32(); tempStream.Seek(36 + tempGenerator * 12, SeekOrigin.Current); int tempPos = (int)tempStream.Position; NumChunks = tempStream.ReadValueS32(); tempStream.Seek(0, SeekOrigin.Begin); header = tempStream.ReadBytes(tempPos); tempStream.Seek(0, SeekOrigin.Begin); if (magic != ZBlock.magic && magic.Swap() != ZBlock.magic) { DebugOutput.PrintLn("Magic number incorrect: " + magic); throw new FormatException("This is not a pcc file. The magic number is incorrect."); } if (bCompressed) { DebugOutput.PrintLn("File is compressed"); { listsStream = lzo.DecompressPCC(tempStream, this); //Correct the header bCompressed = false; listsStream.Seek(0, SeekOrigin.Begin); listsStream.WriteBytes(header); //Set numblocks to zero listsStream.WriteValueS32(0); //Write the magic number listsStream.WriteValueS32(1026281201); //Write 8 bytes of 0 listsStream.WriteValueS32(0); listsStream.WriteValueS32(0); } } else { DebugOutput.PrintLn("File already decompressed. Reading decompressed data."); listsStream = tempStream; } ReadNames(listsStream); ReadImports(listsStream); ReadExports(listsStream); LoadExports(); }
private void ReadImports(MemoryStream fs) { DebugOutput.PrintLn("Reading Imports..."); Imports = new List<ME1ImportEntry>(); fs.Seek(ImportOffset, SeekOrigin.Begin); for (int i = 0; i < ImportCount; i++) { ME1ImportEntry import = new ME1ImportEntry(); import.Package = Names[fs.ReadValueS32()]; fs.Seek(12, SeekOrigin.Current); import.link = fs.ReadValueS32(); import.Name = Names[fs.ReadValueS32()]; fs.Seek(-24, SeekOrigin.Current); import.raw = fs.ReadBytes(28); Imports.Add(import); } }
public APNG(byte[] fileBytes) { ms = new MemoryStream(fileBytes); // check file signature. if (!Helper.IsBytesEqual(ms.ReadBytes(Frame.Signature.Length), Frame.Signature)) throw new Exception("File signature incorrect."); // Read IHDR chunk. IHDRChunk = new IHDRChunk(ms); if (IHDRChunk.ChunkType != "IHDR") throw new Exception("IHDR chunk must located before any other chunks."); // Now let's loop in chunks Chunk chunk; Frame frame = null; List<ITextChunk> text_chunks = new List<ITextChunk>(); bool isIDATAlreadyParsed = false; do { if (ms.Position == ms.Length) throw new Exception("IEND chunk expected."); chunk = new Chunk(ms); switch (chunk.ChunkType) { case "IHDR": throw new Exception("Only single IHDR is allowed."); break; case "acTL": if (IsSimplePNG) throw new Exception("acTL chunk must located before any IDAT and fdAT"); TextChunks = text_chunks.ToArray(); text_chunks.Clear(); acTLChunk = new acTLChunk(chunk); break; case "IDAT": // To be an APNG, acTL must located before any IDAT and fdAT. if (acTLChunk == null) { TextChunks = text_chunks.ToArray(); text_chunks.Clear(); IsSimplePNG = true; } // Only default image has IDAT. defaultImage.IHDRChunk = IHDRChunk; defaultImage.AddIDATChunk(new IDATChunk(chunk)); isIDATAlreadyParsed = true; break; case "fcTL": // Simple PNG should ignore this. if (IsSimplePNG) continue; if (frame != null && frame.IDATChunks.Count == 0) throw new Exception("One frame must have only one fcTL chunk."); // IDAT already parsed means this fcTL is used by FRAME IMAGE. if (isIDATAlreadyParsed) { // register current frame object and build a new frame object // for next use if (frame != null) { frame.TextChunks = text_chunks.ToArray(); frames.Add(frame); text_chunks.Clear(); } frame = new Frame { IHDRChunk = IHDRChunk, fcTLChunk = new fcTLChunk(chunk) }; } // Otherwise this fcTL is used by the DEFAULT IMAGE. else { defaultImage.fcTLChunk = new fcTLChunk(chunk); } break; case "fdAT": // Simple PNG should ignore this. if (IsSimplePNG) continue; // fdAT is only used by frame image. if (frame == null || frame.fcTLChunk == null) throw new Exception("fcTL chunk expected."); frame.AddIDATChunk(new fdATChunk(chunk).ToIDATChunk()); break; case "IEND": // register last frame object if (frame != null) { frame.TextChunks = text_chunks.ToArray(); frames.Add(frame); text_chunks.Clear(); } if (DefaultImage.IDATChunks.Count != 0) DefaultImage.IENDChunk = new IENDChunk(chunk); foreach (Frame f in frames) { f.IENDChunk = new IENDChunk(chunk); } break; case "iTXt": text_chunks.Add(new iTXtChunk(chunk)); break; case "tEXt": text_chunks.Add(new tEXtChunk(chunk)); break; case "zTXt": text_chunks.Add(new zTXtChunk(chunk)); break; default: //TODO: Handle other chunks. break; } } while (chunk.ChunkType != "IEND"); // We have one more thing to do: // If the default image if part of the animation, // we should insert it into frames list. if (defaultImage.fcTLChunk != null) { frames.Insert(0, defaultImage); DefaultImageIsAnimeated = true; } }
/// <summary> /// Takes compressed archived image data and returns the raw image data /// </summary> /// <param name="data"></param> /// <returns></returns> public byte[] DecompressTex(Stream archiveStream, int offset, int uncSize, int cprSize) { int pos = 0; archiveStream.Seek(offset, SeekOrigin.Begin); int magicNumber = archiveStream.ReadValueS32(); pos += 4; if (magicNumber != -1641380927) { throw new FormatException("Magic Number is not correct. Invalid archive data"); } int blockSize = archiveStream.ReadValueS32(); pos += 4; int readCprSize = archiveStream.ReadValueS32(); //Archive cprSize doesn't include header size pos += 4; int uncReadSize = archiveStream.ReadValueS32(); if (uncReadSize != uncSize) { throw new FormatException("Uncompressed data sizes don't match. Read: " + uncReadSize + ", expected: " + uncSize); } pos += 4; int noChunks = (uncSize + blockSize - 1) / blockSize; CompressedChunkBlock[] chunks = new CompressedChunkBlock[noChunks]; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = new CompressedChunkBlock(); chunk.cprSize = archiveStream.ReadValueS32(); chunk.uncSize = archiveStream.ReadValueS32(); chunk.rawData = new byte[chunk.cprSize]; pos += 8; chunks[i] = chunk; } if (readCprSize + pos != cprSize) { throw new FormatException("Compressed data sizes don't match. Invalid archive data"); } byte[] rawData = new byte[readCprSize]; rawData = archiveStream.ReadBytes(readCprSize); archiveStream.Close(); using (MemoryStream data = new MemoryStream(rawData)) { for (int i = 0; i < noChunks; i++) { chunks[i].rawData = data.ReadBytes(chunks[i].cprSize); } } byte[] imgBuffer = new byte[uncSize]; int resultPos = 0; for (int i = 0; i < noChunks; i++) { CompressedChunkBlock chunk = chunks[i]; byte[] tempResult = new byte[chunk.uncSize]; try { LZO1X.Decompress(chunk.rawData, tempResult); } catch { throw new Exception("LZO decompression failed!"); } Buffer.BlockCopy(tempResult, 0, imgBuffer, resultPos, chunk.uncSize); resultPos += chunk.uncSize; } return imgBuffer; }
private static void Main(string[] args) { var paths = Directory.GetFiles("saves", "*.sav"); var successes = 0; var failures = 0; foreach (var path in paths) { var name = Path.GetFileNameWithoutExtension(path); using (var input = File.OpenRead(path)) { var readHash = input.ReadBytes(20); using (var data = input.ReadToMemoryStream(input.Length - 20)) { byte[] computedHash; using (var sha1 = new System.Security.Cryptography.SHA1Managed()) { computedHash = sha1.ComputeHash(data); } if (readHash.SequenceEqual(computedHash) == false) { Console.WriteLine("{0}: failed (SHA1 mismatch)", name); failures++; continue; } data.Position = 0; var uncompressedSize = data.ReadValueU32(Endian.Big); var actualUncompressedSize = (int)uncompressedSize; var uncompressedBytes = new byte[uncompressedSize]; var compressedSize = (int)(data.Length - 4); var compressedBytes = data.ReadBytes(compressedSize); var result = LZO.Decompress(compressedBytes, 0, compressedSize, uncompressedBytes, 0, ref actualUncompressedSize); if (result != LZO.ErrorCode.Success) { Console.WriteLine("{0}: failed (LZO error {1})", name, result); failures++; continue; } using (var outerData = new MemoryStream(uncompressedBytes)) { var innerSize = outerData.ReadValueU32(Endian.Big); var magic = outerData.ReadString(3); if (magic != "WSG") { Console.WriteLine("{0}: failed (bad magic)", name); failures++; continue; } var version = outerData.ReadValueU32(Endian.Little); if (version != 2 && version.Swap() != 2) { Console.WriteLine("{0}: failed (bad version)", name); failures++; continue; } var endian = version == 2 ? Endian.Little : Endian.Big; var hash = outerData.ReadValueU32(endian); var innerUncompressedSize = outerData.ReadValueS32(endian); var innerCompressedBytes = outerData.ReadBytes(innerSize - 3 - 4 - 4 - 4); var innerUncompressedBytes = Huffman.Decoder.Decode(innerCompressedBytes, innerUncompressedSize); using (var innerUncompressedData = new MemoryStream(innerUncompressedBytes)) { using (var output = File.Create("temp.bin")) { output.WriteBytes(innerUncompressedBytes); } var save = Serializer.Deserialize<WillowTwoSave.WillowTwoPlayerSaveGame>(innerUncompressedData); using (var testData = new MemoryStream()) { Serializer.Serialize(testData, save); testData.Position = 0; var testBytes = testData.ReadBytes((uint)testData.Length); if (innerUncompressedBytes.SequenceEqual(testBytes) == false) { Console.WriteLine("{0}: failed (reencode mismatch)", name); using (var output = File.Create(Path.Combine("failures", name + "_before.bin"))) { output.WriteBytes(innerUncompressedBytes); } using (var output = File.Create(Path.Combine("failures", name + "_after.bin"))) { output.WriteBytes(testBytes); } failures++; continue; } successes++; } } } } } } Console.WriteLine("{0} processed ({1} failed, {2} succeeded).", paths.Length, failures, successes); }