Example #1
0
        private static void BuildMasterPatch(string esm, ILookup <string, string> knownEsmVersions)
        {
            var fixPath = Path.Combine(OutDir, Path.ChangeExtension(esm, ".pat"));

            if (File.Exists(fixPath))
            {
                return;
            }

            var ttwESM   = Path.Combine(_dirTTWMain, esm);
            var ttwBytes = File.ReadAllBytes(ttwESM);
            var ttwChk   = new FileValidation(ttwBytes);

            var altVersions = knownEsmVersions[esm].ToList();

            var patches =
                altVersions.Select(dataESM =>
            {
                var dataBytes = File.ReadAllBytes(dataESM);
                byte[] patchBytes;

                using (var msPatch = new MemoryStream())
                {
                    MakeDiff.Create(dataBytes, ttwBytes, Diff.SIG_LZDIFF41, msPatch);
                    patchBytes = msPatch.ToArray();
                }

                return(new PatchInfo
                {
                    Metadata = new FileValidation(dataESM),
                    Data = patchBytes
                });
            })
                .AsParallel()
                .ToArray();

            var patchDict = new PatchDict(altVersions.Count);

            patchDict.Add(esm, new Patch(ttwChk, patches));

            using (var fixStream = File.OpenWrite(fixPath))
                patchDict.WriteAll(fixStream);
        }
Example #2
0
        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);
                }
        }
Example #3
0
        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(Game.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);
            }
        }
Example #4
0
        private bool PatchMaster(string esm)
        {
            Log.Dual("Patching " + esm + "...");

            var patchPath = Path.Combine(PatchDir, Path.ChangeExtension(esm, ".pat"));

            if (File.Exists(patchPath))
            {
                var patchDict = new PatchDict(patchPath);

                Debug.Assert(patchDict.ContainsKey(esm));
                var patch   = patchDict[esm];
                var patches = patch.Item2;
                var newChk  = patch.Item1;

                var finalPath = Path.Combine(DirTTWMain, esm);
                if (File.Exists(finalPath))
                {
                    Log.Dual("\t" + esm + " already exists");
                    if (CheckExisting(finalPath, newChk))
                    {
                        Log.Dual("\t" + esm + " is up to date");
                        return(true);
                    }

                    Log.Dual("\t" + esm + " is out of date");
                }

                var dataPath = Path.Combine(DirFO3Data, esm);
                //TODO: change to a user-friendly condition and message
                Trace.Assert(File.Exists(dataPath));

                //make sure we didn't include old patches by mistake
                Debug.Assert(patches.All(p => p.Metadata.Type == FileValidation.ChecksumType.Murmur128));

                using (var dataChk = new FileValidation(dataPath))
                {
                    var matchPatch = patches.SingleOrDefault(p => p.Metadata == dataChk);
                    if (matchPatch == null)
                    {
                        Log.Display("\tA patch for your version of " + esm + " could not be found");
                        Log.File("\tA patch for " + esm + " version " + dataChk + " could not be found");
                    }
                    else
                    {
                        using (FileStream
                               dataStream = File.OpenRead(dataPath),
                               outputStream = File.Open(finalPath, FileMode.Create, FileAccess.ReadWrite))
                        {
                            FileValidation outputChk;
                            if (matchPatch.PatchStream(dataStream, newChk, outputStream, out outputChk))
                            {
                                Log.Dual("\tPatch successful");
                                return(true);
                            }

                            Log.File("\tPatch failed - " + outputChk);
                        }
                    }
                }
            }
            else
            {
                Log.Dual("\t" + esm + " patch is missing from " + PatchDir);
            }

            Fail("Your version of " + esm + " cannot be patched. This is abnormal.");

            return(false);
        }
Example #5
0
        private static void BuildMasterPatch(string esm, ILookup<string, string> knownEsmVersions)
        {
            var fixPath = Path.Combine(OutDir, Path.ChangeExtension(esm, ".pat"));
            if (File.Exists(fixPath))
                return;

            var ttwESM = Path.Combine(_dirTTWMain, esm);
            var ttwBytes = File.ReadAllBytes(ttwESM);
            var ttwChk = new FileValidation(ttwBytes);

            var altVersions = knownEsmVersions[esm].ToList();

            var patches =
                altVersions.Select(dataESM =>
                {
                    var dataBytes = File.ReadAllBytes(dataESM);
                    byte[] patchBytes;

                    using (var msPatch = new MemoryStream())
                    {
                        MakeDiff.Create(dataBytes, ttwBytes, Diff.SIG_LZDIFF41, msPatch);
                        patchBytes = msPatch.ToArray();
                    }

                    return new PatchInfo
                    {
                        Metadata = new FileValidation(dataESM),
                        Data = patchBytes
                    };
                })
                .AsParallel()
                .ToArray();

            var patchDict = new PatchDict(altVersions.Count);
            patchDict.Add(esm, new Patch(ttwChk, patches));

            using (var fixStream = File.OpenWrite(fixPath))
                patchDict.WriteAll(fixStream);
        }