/// <summary> /// Apply patch data from given <see cref="Stream"/> to the ROM. /// </summary> /// <param name="inStream">Input stream.</param> /// <returns><see cref="SHA256"/> hash of the patch.</returns> public static byte[] ApplyPatch(Stream inStream) { try { var aes = Aes.Create(); var hashAlg = new SHA256Managed(); using (var cryptoStream = new CryptoStream(inStream, aes.CreateDecryptor(key, iv), CryptoStreamMode.Read)) using (var hashStream = new CryptoStream(cryptoStream, hashAlg, CryptoStreamMode.Read)) using (var decompressStream = new GZipStream(hashStream, CompressionMode.Decompress)) using (var memoryStream = new MemoryStream()) { // Fully decompress into MemoryStream so that we can access Position to check for end of Stream. decompressStream.CopyTo(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin); using var reader = new BeBinaryReader(memoryStream); // Validate patch magic. var magic = reader.ReadUInt32(); ValidateMagic(magic); Span <byte> headerBytes = stackalloc byte[PatchHeader.Size]; while (reader.BaseStream.Position != reader.BaseStream.Length) { // Read header bytes into stack buffer to prevent allocation. reader.ReadExact(headerBytes); var header = PatchHeader.Read(headerBytes); var data = reader.ReadBytes(header.Length); ApplyPatchEntry(header, data); } } return(hashAlg.Hash); } catch { throw new IOException("Failed to apply patch. Patch may be invalid."); } }