Example #1
0
        /// <summary>
        /// Applies all patches to a file
        /// </summary>
        /// <param name="patchEntry"></param>
        /// <param name="indexContainer"></param>
        /// <param name="input"></param>
        /// <param name="output"></param>
        /// <returns></returns>
        public bool ApplyPatch(PatchEntry patchEntry, Indices.IndexContainer indexContainer, Stream input, Stream output)
        {
            if (indexContainer == null || input == null || output == null || patchEntry == null)
            {
                return(false);
            }

            if (patchEntry.Records.Count == 0)
            {
                return(false);
            }

            // get the correct order - just in case
            patchEntry.Records.Sort((x, y) => x.Ordinal - y.Ordinal);

            // iterate the patches
            for (int i = 0; i < patchEntry.Records.Count; i++)
            {
                // if applying more than one the previous output is required
                // as patches are incremental
                if (i > 0)
                {
                    input = output;
                }

                using (var patch = indexContainer.OpenPatch(patchEntry.Records[i].PatchEKey))
                {
                    if (patch == null)
                    {
                        return(false);
                    }

                    ZBSPatch.Apply(input, patch, output);
                }
            }

            return(true);
        }
Example #2
0
        private void Read(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            if (!stream.CanRead || stream.Length <= 1)
            {
                throw new NotSupportedException($"Unable to read PatchFile stream");
            }

            using (var reader = new BinaryReader(stream))
            {
                PatchHeader.Read(reader);

                // read the patch entries
                int  pageSize = 1 << PatchHeader.PageSize;
                long length   = reader.BaseStream.Length;

                foreach (var offset in GetOffsets(reader))
                {
                    reader.BaseStream.Position = offset;

                    // buffer the page then read the entries to minimise file reads
                    using (var ms = new MemoryStream(reader.ReadBytes(pageSize)))
                        using (var br = new BinaryReader(ms))
                        {
                            var block = new PatchEntry();
                            while (block.Read(br, PatchHeader))
                            {
                                _PatchEntries[block.CKey] = block;
                                block = new PatchEntry();
                            }
                        }
                }

                #region Unknown Data

                // Unknown = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position));

                /*
                 * // the following is unknown entries that comprise of:
                 * // a keysize byte followed by either a CKey or Ekey
                 * // the key type relevant size (decompressed/compressed)
                 * // and optionally an ESpec string
                 * // blocks are always a pair of 112 bytes then 160, Encoding Entry then Content Entry
                 * //
                 * // struct encodin_entry {
                 * //    char _unk0[4]; // always 0
                 * //    char KeySize;
                 * //    char Hash[KeySize];
                 * //    char _unk15[7];
                 * //    uint32_t some_offset;
                 * //
                 * //    // 0x44 CompressedSize;
                 * // }
                 * //
                 * // struct content_entry {
                 * //    char _unk0[4]; // always 0
                 * //    char KeySize;
                 * //    char Hash[KeySize];
                 * //    char _unk15[7];
                 * //    uint32_t some_offset;
                 * //
                 * //    // 0x34 DeompressedSize;
                 * //    // 0x6C partial ESpec   always ends in 0xA0
                 * // }
                 */
                #endregion

                Checksum = stream.MD5Hash();
            }
        }
Example #3
0
 /// <summary>
 /// Returns a PatchEntry by CKey
 /// </summary>
 /// <param name="ckey"></param>
 /// <param name="entry"></param>
 /// <returns></returns>
 public bool TryGet(MD5Hash ckey, out PatchEntry entry) => _PatchEntries.TryGetValue(ckey, out entry);