private static void BuildBsaPatch(string inBsaName, string outBsaName) { string outBSAFile = Path.ChangeExtension(outBsaName, ".bsa"); string outBSAPath = Path.Combine(_dirTTWMain, outBSAFile); string inBSAFile = Path.ChangeExtension(inBsaName, ".bsa"); string inBSAPath = Path.Combine(_dirFO3Data, inBSAFile); var renameDict = BuildRenameDict(outBsaName); Debug.Assert(renameDict != null); var patPath = Path.Combine(OutDir, Path.ChangeExtension(outBsaName, ".pat")); if (File.Exists(patPath)) { return; } var prefix = Path.Combine(InDir, "TTW Patches", outBsaName); using (var inBSA = new BSA(inBSAPath)) using (var outBSA = new BSA(outBSAPath)) { BsaDiff .CreateRenameQuery(inBSA, renameDict) .ToList(); // execute query var oldFiles = inBSA.SelectMany(folder => folder).ToList(); var newFiles = outBSA.SelectMany(folder => folder).ToList(); var newChkDict = FileValidation.FromBSA(outBSA); var joinedPatches = from patKvp in newChkDict join newBsaFile in newFiles on patKvp.Key equals newBsaFile.Filename select new { newBsaFile, file = patKvp.Key, patch = patKvp.Value }; var allJoinedPatches = joinedPatches.ToList(); var patchDict = new PatchDict(allJoinedPatches.Count); foreach (var join in allJoinedPatches) { var oldBsaFile = oldFiles.SingleOrDefault(file => file.Filename == join.file); Debug.Assert(oldBsaFile != null, "File not found: " + join.file); var oldChk = FileValidation.FromBSAFile(oldBsaFile); var newChk = join.patch; var oldFilename = oldBsaFile.Filename; if (oldFilename.StartsWith(TaleOfTwoWastelands.Properties.Resources.VoicePrefix)) { patchDict.Add(join.file, new Patch(newChk, null)); continue; } var patches = new List <PatchInfo>(); var md5OldStr = Util.GetMD5String(oldBsaFile.GetContents(true)); var md5NewStr = Util.GetMD5String(join.newBsaFile.GetContents(true)); var diffPath = Path.Combine(prefix, oldFilename + "." + md5OldStr + "." + md5NewStr + ".diff"); var usedPath = Path.ChangeExtension(diffPath, ".used"); if (File.Exists(usedPath)) { File.Move(usedPath, diffPath); //fixes moronic things } var altDiffs = Util.FindAlternateVersions(diffPath); if (altDiffs != null) { foreach (var altDiff in altDiffs) { var altDiffBytes = GetDiff(altDiff.Item1, Diff.SIG_LZDIFF41); patches.Add(new PatchInfo { Metadata = new FileValidation(altDiff.Item2, 0, FileValidation.ChecksumType.Md5), Data = altDiffBytes }); } } if (newChk != oldChk) { byte[] diffData = GetDiff(diffPath, Diff.SIG_LZDIFF41); var patchInfo = PatchInfo.FromOldDiff(diffData, oldChk); Debug.Assert(patchInfo.Data != null); patches.Add(patchInfo); } patchDict.Add(join.file, new Patch(newChk, patches.ToArray())); } using (var stream = File.OpenWrite(patPath)) patchDict.WriteAll(stream); } }