/// <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); }
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(); } }
/// <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); // } // } //} }