public void Repack(string srcFolder, string patchFolder, string importFolder) { Logger.Print("正在读取索引数据"); DDTFileTable table = JsonHelper.Deserialize <DDTFileTable>(File.ReadAllText("./dds3_table.json", Encoding.UTF8)); this.GetEntry(); Logger.Print("正在复制package"); if (File.Exists(Path.Combine(importFolder, Path.GetFileName(this.ImgName)))) { File.Delete(Path.Combine(importFolder, Path.GetFileName(this.ImgName))); } if (File.Exists(Path.Combine(importFolder, Path.GetFileName(this.DDTName)))) { File.Delete(Path.Combine(importFolder, Path.GetFileName(this.DDTName))); } IOHelper.CopyFile(this.ImgName, Path.Combine(importFolder, Path.GetFileName(this.ImgName))); IOHelper.CopyFile(this.DDTName, Path.Combine(importFolder, Path.GetFileName(this.DDTName))); Logger.Print("开始对资源打补丁"); List <string> pFileList = SearchPatchingFiles(table, patchFolder); Logger.Print(string.Format("有 {0} 个资源文件需要打补丁", pFileList.Count)); FileStream imgStream = File.Open(Path.Combine(importFolder, Path.GetFileName(this.ImgName)), FileMode.Open, FileAccess.ReadWrite); FileStream ddtStream = File.Open(Path.Combine(importFolder, Path.GetFileName(this.DDTName)), FileMode.Open, FileAccess.ReadWrite); BinaryWriter imgWriter = new BinaryWriter(imgStream); BinaryWriter ddtWriter = new BinaryWriter(ddtStream); Entry vEntry; SubFile vSubFile; for (int i = 0; i < pFileList.Count; i++) { if (fDictionary.ContainsKey(pFileList[i])) { byte[] data = null; vEntry = fDictionary[pFileList[i]]; vSubFile = tempSubFileDictionary[pFileList[i]]; if (Path.GetExtension(vSubFile.FileName).ToLower().Equals(".lb") && vSubFile.SubItems.Count > 0) { //lb包有子文件,启动压缩 LB lbContainer = new LB(); byte[] packedBytes = lbContainer.Repack(getBaseDir(vSubFile.FileName), vSubFile.FileName, srcFolder, patchFolder, vSubFile.SubItems); //File.WriteAllBytes("temp/" + Path.GetFileName(vSubFile.FileName), packedBytes); data = packedBytes; } else { string tmpPath = ""; if (File.Exists(patchFolder + "/" + vSubFile.FileName)) { tmpPath = patchFolder + "/" + vSubFile.FileName; } else { tmpPath = srcFolder + "/" + vSubFile.FileName; } data = File.ReadAllBytes(tmpPath); } if (data != null) { var t_length = data.Length; var chunk_size = 0; if ((t_length % 0x800) == 0) { chunk_size = t_length; } else { chunk_size = t_length + 0x800 - t_length % 0x800; } var o_chunk_sz = 0; if ((vEntry.Size % 0x800) == 0) { o_chunk_sz = vEntry.Size; } else { o_chunk_sz = vEntry.Size + 0x800 - vEntry.Size % 0x800; } if (chunk_size > o_chunk_sz) { //追加补丁 imgWriter.Seek(0, SeekOrigin.End); var offset = imgWriter.BaseStream.Position / 0x800; Logger.Print(string.Format("Append res file{0} to offfset {1:x8}", vSubFile.FileName, offset * 0x800, t_length)); imgWriter.Write(data); imgWriter.AlignPosition(0x800); ddtWriter.Seek(vEntry.Ptr, SeekOrigin.Begin); ddtWriter.Seek(4, SeekOrigin.Current); ddtWriter.Write((int)offset); ddtWriter.Write((int)t_length); } else { //原位替换 imgWriter.Seek(vEntry.Offset, SeekOrigin.Begin); imgWriter.Write(Enumerable.Repeat((byte)0, vEntry.Size).ToArray()); imgWriter.Seek(vEntry.Offset, SeekOrigin.Begin); var offset = vEntry.Offset / 0x800; Logger.Print(string.Format("overrite res file{0} to offfset {1:x8}", vSubFile.FileName, offset * 0x800, t_length)); imgWriter.Write(data); ddtWriter.Seek(vEntry.Ptr, SeekOrigin.Begin); ddtWriter.Seek(4, SeekOrigin.Current); ddtWriter.Write((int)offset); ddtWriter.Write((int)t_length); } } } } imgWriter.Close(); ddtWriter.Close(); Logger.Print("补丁结束。Have Fun"); }
public void Extract(string pathName) { DDTFileTable table = new DDTFileTable(); this.GetEntry(); using (FileStream fs = File.OpenRead(this.ImgName)) { using (BinaryReader br = new BinaryReader(fs)) { for (int i = 0; i < this.mEntries.Count; i++) { Entry vEntry = mEntries[i]; string dstPath = pathName + "/" + vEntry.FullName; string dirname = Path.GetDirectoryName(dstPath); var vSubItems = new List <SubItem>(); br.BaseStream.Seek(vEntry.Offset, SeekOrigin.Begin); byte[] entryData = br.ReadBytes(vEntry.Size); Logger.Print(string.Format("{0}:at offset:{1:x8}", vEntry.FullName, vEntry.Offset)); if (!Directory.Exists(dirname)) { Directory.CreateDirectory(dirname); } using (FileStream entrFile = File.OpenWrite(dstPath)) { entrFile.Write(entryData, 0, entryData.Length); } //如果是lb,则额外进行解包操作。 if (Path.GetExtension(vEntry.FullName).ToLower().Equals(".lb")) { LB lbPackage = new LB(); lbPackage.Load(dstPath); vSubItems = lbPackage.SubItems; for (int p = 0; p < lbPackage.SubItems.Count; p++) { var vitem = lbPackage.SubItems[p]; var tExt = Path.GetExtension(vitem.FileName).ToLower(); if (tExt.Equals(".bf") || tExt.Equals(".tmx") /*|| Path.GetExtension(vitem.FileName).ToLower().Equals(".pac")*/) { //如果是bf和tmx,则设定为解包并解压。 Logger.Print(string.Format("\t- Extract {0}", vitem.FileName)); byte[] zipdata = lbPackage.Unpack(vitem.FileName); string dstName = Path.Combine(dirname, vitem.FileName); if (vSubItems[p].IsCompressed) { vSubItems[p].NeedReCompress = true; } File.WriteAllBytes(dstName, zipdata); } else { Logger.Print(string.Format("\t- Unpack {0}", vitem.FileName)); byte[] zipdata = lbPackage.GetRaw(vitem.FileName); string dstName = Path.Combine(dirname, vitem.FileName); byte[] dezipdata = lbPackage.Unpack(vitem.FileName); File.WriteAllBytes(dstName + ".decdata", dezipdata); vSubItems[p].NeedReCompress = false; File.WriteAllBytes(dstName, zipdata); } } } else { } table.Files.Add(new SubFile() { FileName = vEntry.FullName, SubItems = vSubItems }); } } } string jsontable = JsonHelper.Serialize(table); File.WriteAllText("dds3_table.json", jsontable, new UTF8Encoding(false)); }