/// <summary>
        /// 验证并初始化补丁解压流。
        /// </summary>
        public void OpenDecompress()
        {
            this.patchBlock = TrySplit(this.patchFile);

            if (this.patchBlock == null)
            {
                throw new Exception("Decompress Error, cannot find patch block from the stream.");
            }

            BinaryReader r = new BinaryReader(patchBlock);

            patchBlock.Seek(8, SeekOrigin.Begin);
            int  ver       = r.ReadInt32();
            uint checkSum0 = r.ReadUInt32();
            uint checkSum1 = CheckSum.ComputeHash(patchBlock, (int)patchBlock.Length - 0x10);

            VerifyCheckSum(checkSum0, checkSum1, "PatchFile", "0");

            patchBlock.Seek(16, SeekOrigin.Begin);
            byte lb = r.ReadByte(), hb = r.ReadByte();

            if (!(lb == 0x78 && (lb * 0x100 + hb) % 31 == 0)) // zlib头标识 没有就把这两字节都当数据段好了..
            {
                patchBlock.Seek(-2, SeekOrigin.Current);
            }
            this.inflateStream = new InflateStream(patchBlock);
        }
 private void InflateStreamSeek(long offset)
 {
     try
     {
         this.inflateStream.Seek(offset, SeekOrigin.Begin);
     }
     catch
     {
         this.inflateStream = new InflateStream(this.inflateStream);
         this.inflateStream.Seek(offset, SeekOrigin.Begin);
     }
 }
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.patchFile != null)
                {
                    this.patchFile.Close();
                }
            }

            this.patchFile     = null;
            this.patchBlock    = null;
            this.inflateStream = null;
        }
        public long PrePatch()
        {
            if (this.inflateStream == null)
            {
                this.OpenDecompress();
            }
            else if (this.inflateStream.Position > 0) //重置到初始化
            {
                this.inflateStream = new InflateStream(this.inflateStream);
            }

            List <PatchPartContext> patchParts = new List <PatchPartContext>();
            BinaryReader            r          = new BinaryReader(this.inflateStream);

            while (true)
            {
                PatchPartContext part = ReadPatchPart(r);

                if (part == null)
                {
                    break;
                }

                patchParts.Add(part);

                //跳过当前段
                switch (part.Type)
                {
                case 0:
                    if (part.NewFileLength > 0)
                    {
                        this.inflateStream.Seek(part.NewFileLength, SeekOrigin.Current);
                    }
                    break;

                case 1:
                {
                    part.NewFileLength = CalcNewFileLength(part, r);
                }
                break;

                case 2:
                    break;
                }
            }

            this.patchParts = patchParts;
            return(this.inflateStream.Position);
        }
        /// <summary>
        /// 对于已经解压的patch文件,向客户端执行更新过程,可以自己指定临时文件的文件夹。
        /// </summary>
        /// <param Name="mapleStoryFolder">冒险岛客户端所在文件夹。</param>
        /// <param Name="tempFileFolder">生成临时文件的文件夹。</param>
        public void Patch(string mapleStoryFolder, string tempFileFolder)
        {
            string tempDir = CreateRandomDir(tempFileFolder);

            if (this.inflateStream.Position > 0) //重置到初始化
            {
                this.inflateStream = new InflateStream(this.inflateStream);
            }

            if (this.patchParts == null) //边读取边执行
            {
                this.patchParts = new List <PatchPartContext>();
                BinaryReader r = new BinaryReader(this.inflateStream);
                while (true)
                {
                    PatchPartContext part = ReadPatchPart(r);

                    if (part == null)
                    {
                        break;
                    }

                    patchParts.Add(part);

                    //跳过当前段
                    switch (part.Type)
                    {
                    case 0:
                        CreateNewFile(part, tempDir);
                        break;

                    case 1:
                        RebuildFile(part, tempDir, mapleStoryFolder);
                        break;

                    case 2:
                        break;
                    }
                }
            }
            else  //按照调整后顺序执行
            {
                foreach (PatchPartContext part in this.patchParts)
                {
                    switch (part.Type)
                    {
                    case 0:
                        CreateNewFile(part, tempDir);
                        break;

                    case 1:
                        RebuildFile(part, tempDir, mapleStoryFolder);
                        break;

                    case 2:
                        break;
                    }
                }
            }

            foreach (PatchPartContext part in this.patchParts)
            {
                if (part.Type != 2 && !string.IsNullOrEmpty(part.TempFilePath))
                {
                    SafeMove(part.TempFilePath, Path.Combine(mapleStoryFolder, part.FileName));
                }
                else if (part.Type == 2)
                {
                    if (part.FileName.EndsWith("\\"))
                    {
                        SafeDeleteDirectory(Path.Combine(mapleStoryFolder, part.FileName));
                    }
                    else
                    {
                        SafeDeleteFile(Path.Combine(mapleStoryFolder, part.FileName));
                    }
                }
            }

            SafeDeleteDirectory(tempDir);
        }
Exemple #6
0
        public long PrePatch()
        {
            if (this.inflateStream == null)
            {
                this.OpenDecompress();
            }
            else if (this.inflateStream.Position > 0) //重置到初始化
            {
                this.inflateStream = new InflateStream(this.inflateStream);
            }

            var patchParts = new List <PatchPartContext>();
            var r          = new BinaryReader(this.inflateStream);

            if (this.TryReadKMST1125FileHashList(r, out var fileHash))
            {
                this.oldFileHash      = fileHash;
                this.IsKMST1125Format = true;
            }
            else
            {
                this.IsKMST1125Format = false;
                // reset file cursor
                this.inflateStream = new InflateStream(this.inflateStream);
                r = new BinaryReader(this.inflateStream);
            }

            while (true)
            {
                PatchPartContext part = ReadPatchPart(r);

                if (part == null)
                {
                    break;
                }

                patchParts.Add(part);

                //跳过当前段
                switch (part.Type)
                {
                case 0:
                    if (part.NewFileLength > 0)
                    {
                        this.inflateStream.Seek(part.NewFileLength, SeekOrigin.Current);
                    }
                    break;

                case 1:
                {
                    part.NewFileLength = CalcNewFileLength(part, r);
                }
                break;

                case 2:
                    break;
                }
            }

            this.patchParts = patchParts;
            return(this.inflateStream.Position);
        }
        public void Build()
        {
            List <FileReversePart> preReverse = new List <FileReversePart>();

            using (FileStream fs = new FileStream(patchFileName, FileMode.Open, FileAccess.Read))
            {
                fs.Position = 18;
                InflateStream   stream = new InflateStream(fs, true);
                WzPatcherReader reader = new WzPatcherReader(stream);
                PatchPart       filePart;

                PatchPart reversePart;

                while ((filePart = reader.ReadPart()) != null)
                {
                    switch (filePart.Type)
                    {
                    case PatchType.Create:
                        if (filePart.FileLength > 0)
                        {
                            stream.Seek(filePart.FileLength, SeekOrigin.Current);
                            //在原文件夹寻找同名文件
                            string oldFile = Path.Combine(msDir, filePart.FileName);
                            if (File.Exists(oldFile))
                            {
                                reversePart = new PatchPart()
                                {
                                    Type = PatchType.Create
                                };
                                reversePart.FileName   = filePart.FileName;
                                reversePart.FileLength = (int)new FileInfo(oldFile).Length;
                                preReverse.Add(new FileReversePart(reversePart));
                            }
                            else
                            {
                                reversePart = new PatchPart()
                                {
                                    Type = PatchType.Delete
                                };
                                reversePart.FileName = filePart.FileName;
                                preReverse.Add(new FileReversePart(reversePart));
                            }
                        }
                        break;

                    case PatchType.Rebuild:
                        reversePart = new PatchPart()
                        {
                            Type        = PatchType.Rebuild,
                            OldChecksum = filePart.Checksum,
                            Checksum    = filePart.OldChecksum,
                            FileName    = filePart.FileName
                        };
                        List <FileReverseInst> instList = new List <FileReverseInst>();

                        BuildInstruction inst;
                        int filePos = 0;
                        while ((inst = reader.ReadInst()).Type != null)
                        {
                            if (inst.Type == BuildType.Ending)
                            {
                                break;
                            }

                            switch (inst.Type)
                            {
                            case BuildType.FromPatcher:
                                stream.Seek(inst.Length, SeekOrigin.Current);

                                break;

                            case BuildType.FillBytes:

                                break;

                            case BuildType.FromOldFile:
                                instList.Add(new FileReverseInst()
                                {
                                    Inst = inst, NewFilePosition = filePos
                                });
                                break;
                            }
                            filePos += inst.Length;
                        }

                        preReverse.Add(new FileReversePart(reversePart)
                        {
                            InstList = instList
                        });
                        break;

                    case PatchType.Delete:
                    {
                        string oldFile = Path.Combine(msDir, filePart.FileName);
                        if (File.Exists(oldFile))
                        {
                            reversePart = new PatchPart()
                            {
                                Type = PatchType.Create
                            };
                            reversePart.FileName   = filePart.FileName;
                            reversePart.FileLength = (int)new FileInfo(oldFile).Length;
                            preReverse.Add(new FileReversePart(reversePart));
                        }
                    }

                    break;
                    }
                } //end while
            }     //end using

            preReverse.Sort();

            using (FileStream dest = new FileStream(outputFileName, FileMode.Create))
            {
                WzPatcherWriter writer = new WzPatcherWriter(dest);

                writer.Begin();
                foreach (var part in preReverse)
                {
                    string oldFileName = Path.Combine(msDir, part.Part.FileName);
                    switch (part.Part.Type)
                    {
                    case PatchType.Create:
                        //计算hash copy文件
                        using (FileStream oldFs = new FileStream(oldFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            part.Part.FileLength = (int)oldFs.Length;
                            part.Part.Checksum   = CheckSum.ComputeHash(oldFs, part.Part.FileLength);
                            oldFs.Position       = 0;
                            writer.WritePart(part.Part);
                            writer.WriteContent(oldFs, part.Part.FileLength);
                        }
                        break;

                    case PatchType.Rebuild:
                        writer.WritePart(part.Part);

                        using (FileStream oldFs = new FileStream(oldFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            //计算指令
                            var instList = Work(part.InstList, (int)oldFs.Length);
                            //开始执行
                            foreach (var inst in instList)
                            {
                                switch (inst.Inst.Type)
                                {
                                case BuildType.FromOldFile:         //参数反转
                                    inst.Inst.OldFilePosition = inst.NewFilePosition;
                                    writer.WriteInst(inst.Inst);
                                    break;

                                case BuildType.FromPatcher:         //go 待优化
                                    writer.WriteInst(inst.Inst);
                                    oldFs.Position = inst.NewFilePosition;
                                    writer.WriteContent(oldFs, inst.Inst.Length);
                                    break;
                                }
                            }
                            //结束执行
                            writer.WriteInst(new BuildInstruction(BuildType.Ending));
                        }
                        break;

                    case PatchType.Delete:
                        writer.WritePart(part.Part);
                        break;
                    }
                }
                writer.End();
            }
        }
Exemple #8
0
        /// <summary>
        /// Reads the scanlines.
        /// </summary>
        /// <param name="dataStream">The data stream.</param>
        /// <param name="pixels">The pixels.</param>
        /// <param name="colorReader">The color reader.</param>
        /// <param name="colorTypeInformation">The color type information.</param>
        /// <param name="header">The header.</param>
        private void ReadScanlines(MemoryStream dataStream, Color[] pixels, IColorReader colorReader, ColorTypeInformation colorTypeInformation, Header header)
        {
            dataStream.Seek(0, SeekOrigin.Begin);

            var ScanlineLength = CalculateScanlineLength(colorTypeInformation, header);
            var ScanlineStep   = CalculateScanlineStep(colorTypeInformation, header);

            byte[] LastScanline = new byte[ScanlineLength];
            byte[] CurrentScanline = new byte[ScanlineLength];
            int    Filter = 0, Column = -1, Row = 0;

            using (InflateStream CompressedStream = new InflateStream(dataStream))
            {
                int ReadByte;
                while ((ReadByte = CompressedStream.ReadByte()) >= 0)
                {
                    if (Column == -1)
                    {
                        Filter = ReadByte;
                        ++Column;
                    }
                    else
                    {
                        CurrentScanline[Column] = (byte)ReadByte;
                        byte a;
                        byte b;
                        byte c;
                        if (Column >= ScanlineStep)
                        {
                            a = CurrentScanline[Column - ScanlineStep];
                            c = LastScanline[Column - ScanlineStep];
                        }
                        else
                        {
                            a = 0;
                            c = 0;
                        }

                        b = LastScanline[Column];
                        switch (Filter)
                        {
                        case 1:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + a);
                            break;

                        case 2:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + b);
                            break;

                        case 3:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + (byte)((a + b) / 2));
                            break;

                        case 4:
                            CurrentScanline[Column] = (byte)(CurrentScanline[Column] + PaethPredicator(a, b, c));
                            break;
                        }

                        ++Column;

                        if (Column == ScanlineLength)
                        {
                            colorReader.ReadScanline(CurrentScanline, pixels, header, Row);
                            ++Row;
                            Column = -1;
                            var Holder = CurrentScanline;
                            CurrentScanline = LastScanline;
                            LastScanline    = Holder;
                        }
                    }
                }
            }
            //dataStream.Seek(0, SeekOrigin.Begin);

            //var ScanlineLength = CalculateScanlineLength(colorTypeInformation, header);
            //var ScanlineStep = CalculateScanlineStep(colorTypeInformation, header);

            //byte[] LastScanline = new byte[ScanlineLength];
            //byte[] CurrentScanline = new byte[ScanlineLength];

            //using (InflateStream CompressedStream = new InflateStream(dataStream))
            //{
            //    using (MemoryStream DecompressedStream = new MemoryStream())
            //    {
            //        CompressedStream.CopyTo(DecompressedStream);
            //        DecompressedStream.Flush();
            //        byte[] DecompressedArray = DecompressedStream.ToArray();
            //        for (int y = 0, Column = 0; y < header.Height; ++y, Column += (ScanlineLength + 1))
            //        {
            //            Array.Copy(DecompressedArray, Column + 1, CurrentScanline, 0, ScanlineLength);
            //            if (DecompressedArray[Column] < 0)
            //                break;
            //            byte[] Result = Filters[(FilterType)DecompressedArray[Column]].Decode(CurrentScanline, LastScanline, ScanlineStep);
            //            colorReader.ReadScanline(Result, pixels, header, y);
            //            Array.Copy(CurrentScanline, LastScanline, ScanlineLength);
            //        }
            //    }
            //}
        }