Ejemplo n.º 1
0
        private void BuildVoice()
        {
            var outBsaPath = Path.Combine(DirTTWOptional, "Fallout3 Player Voice", "TaleOfTwoWastelands - PlayerVoice.bsa");

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

            var inBsaPath = Path.Combine(DirFO3Data, "Fallout - Voices.bsa");

            using (BSA
                   inBsa = new BSA(inBsaPath),
                   outBsa = new BSA(inBsa.Settings))
            {
                var includedFolders = inBsa
                                      .Where(folder => Game.VoicePaths.ContainsKey(folder.Path))
                                      .Select(folder => new BSAFolder(Game.VoicePaths[folder.Path], folder));

                foreach (var folder in includedFolders)
                {
                    outBsa.Add(folder);
                }

                outBsa.Save(outBsaPath);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Opens and return <see cref="Archive"/> of <paramref name="file"/>.
        /// </summary>
        /// <param name="file">Archive file to open.</param>
        /// <param name="owner">Used with <see cref="MessageBox.Show(IWin32Window, string)"/>.</param>
        public static Archive OpenArchive(string file, IWin32Window owner = null)
        {
            Archive archive;

            try
            {
                string   extension = Path.GetExtension(file);
                Encoding encoding  = Encoding.GetEncoding(Settings.Default.EncodingCodePage);

                // ToDo: Read file header to find archive type, not just extension
                switch (extension.ToLower())
                {
                case ".bsa":
                case ".dat":
                    if (BSA.IsSupportedVersion(file, encoding) == false)
                    {
                        if (Common.ShowMessageBoxInvoke(owner,
                                                        "Archive has an unknown version number.\n" + "Attempt to open anyway?",
                                                        "Warning",
                                                        MessageBoxButtons.YesNo) != DialogResult.Yes)
                        {
                            return(null);
                        }
                    }

                    archive = new BSA(file, encoding, Settings.Default.RetrieveRealSize)
                    {
                        MatchLastWriteTime = Settings.Default.MatchLastWriteTime
                    };
                    break;

                case ".ba2":
                    archive = new BA2(file, encoding, Settings.Default.RetrieveRealSize)
                    {
                        MatchLastWriteTime = Settings.Default.MatchLastWriteTime
                    };

                    if (archive.Type == ArchiveTypes.BA2_GNMF)
                    {
                        // Check if extensions for GNF textures should be replaced
                        Common.ReplaceGNFExtensions(archive.Files.OfType <BA2GNFEntry>(), Settings.Default.ReplaceGNFExt);
                    }
                    break;

                default:
                    throw new Exception($"Unrecognized archive file type ({extension}).");
                }
            }
            catch (Exception ex)
            {
                Common.ShowMessageBoxInvoke(owner,
                                            "An error occured trying to open the archive. Changing the Encoding in Options can help, please try before reporting.\n\n" + ex.ToStringInvariant(),
                                            "Error",
                                            MessageBoxButtons.OK,
                                            MessageBoxIcon.Error);
                return(null);
            }

            return(archive);
        }
Ejemplo n.º 3
0
        public static IEnumerable<Tuple<string, string, string>> CreateRenameQuery(BSA bsa, IDictionary<string, string> renameDict)
        {
            //TODO: use dict union
            var renameGroup = from folder in bsa
                              from file in folder
                              join kvp in renameDict on file.Filename equals kvp.Value
                              let a = new { folder, file, kvp }
                              //group a by kvp.Value into g
                              select a;

            var renameCopies = from g in renameGroup
                               let newFilename = g.kvp.Key
                               let newDirectory = Path.GetDirectoryName(newFilename)
                               let a = new { g.folder, g.file, newFilename }
                               group a by newDirectory into outs
                               select outs;

            var newBsaFolders = renameCopies.ToList();
            newBsaFolders.ForEach(g => bsa.Add(new BSAFolder(g.Key)));

            return from g in newBsaFolders
                   from a in g
                   join folder in bsa on g.Key equals folder.Path
                   let newFile = a.file.DeepCopy(g.Key, Path.GetFileName(a.newFilename))
                   let addedFile = folder.Add(newFile)
                   select Tuple.Create(a.file.Name, newFile.Name, a.newFilename);
        }
Ejemplo n.º 4
0
 public static void Clear()
 {
     foreach (BSAArchive BSA in LoadedArchives)
     {
         BSA.Dispose();
     }
     Meshes.Clear();
     Textures.Clear();
     AvailableMeshes.Clear();
     Loaded = false;
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Estimates the dose based on the pharmacy order and calculation factor passed in.
        /// </summary>
        /// <param name="context"></param>
        protected override void DoWork(CodeActivityContext context)
        {
            int    rxoId = RxoId.Get(context);
            double bsa   = BSA.Get(context);

            ImpacPersistenceManager pm = ImpacPersistenceManagerFactory.CreatePersistenceManager();
            var order = pm.GetEntity <BOM.Entities.PharmOrd>(new PrimaryKey(typeof(BOM.Entities.PharmOrd), rxoId));

            if (!order.IsNullEntity)
            {
                double calculatedDose;
                if (DoseCalcUtils.EstimateOrderingDose(order, bsa, out calculatedDose) == DoseCalcUtils.CalcStatus.CalcSucceed)
                {
                    SuggestedDose.Set(context, calculatedDose);
                }
            }
        }
Ejemplo n.º 6
0
        public void RenameFiles(BSA bsa, IDictionary<string, string> renameDict)
        {
            const string opPrefix = "Renaming BSA files";

            var opRename = new InstallStatus(Progress, Token) { CurrentOperation = opPrefix };

            var renameFixes = CreateRenameQuery(bsa, renameDict);
            opRename.ItemsTotal = renameDict.Count;

#if PARALLEL
            Parallel.ForEach(renameFixes, a =>
#else
            foreach (var a in renameFixes)
#endif
            {
                renameDict.Remove(a.Item3);

                opRename.CurrentOperation = opPrefix + ": " + a.Item1 + " -> " + a.Item2;
                opRename.Step();
            }
        private async void PackBSA(string path, List <Asset> assetList)
        {
            string formText = this.Text;

            this.Text = "Packing...";
            this.IsPackingCurrently = true;
            menuStripMain.Enabled   = false;

            bool compress          = bool.Parse(SettingsIni.Data["Archive"]["CompressAssets"]);
            bool usePS3FileFlags   = bool.Parse(SettingsIni.Data["Archive"]["UsePS3FileFlags"]);
            bool extendDDS         = bool.Parse(SettingsIni.Data["DDS"]["ExtendData"]);
            bool convertNormalMaps = bool.Parse(SettingsIni.Data["DDS"]["ConvertNormalMaps"]);

            await Task.Run(() => BSA.Write(path, assetList, compress, usePS3FileFlags, extendDDS, convertNormalMaps));

            this.IsArchiveSaved     = true;
            this.IsPackingCurrently = false;
            menuStripMain.Enabled   = true;
            this.Text = formText;
            MessageBox.Show("Done!", string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }
Ejemplo n.º 8
0
        private static void ProcessBSAs(Recipe recipe, Settings settings)
        {
            Console.WriteLine("Processing BSAs ...");
            foreach (var filepair in settings.Files.Where(fp => fp.Type == ContentType.BSA))
            {
                Console.Write("{0} => {1} .", filepair.OriginalName, filepair.ResultName);

                var before   = GC.GetTotalMemory(false);
                var original = BSA.Open(string.Format("{0}\\{1}", settings.Fo3DataPath, filepair.OriginalName));
                original.BuildIndex();
                var after = GC.GetTotalMemory(false);

                var referenceFile = string.Format("{0}\\{1}", settings.CurrentDataPath, filepair.ResultName);
                var referenceDir  = new DirectoryInfo(Path.ChangeExtension(referenceFile, null));

                Console.Write(".");
                SortedDictionary <string, Fo3File> reference = new SortedDictionary <string, Fo3File>();
                Parallel.ForEach(referenceDir.EnumerateFiles("*.*", SearchOption.AllDirectories).AsParallel(), new ParallelOptions {
                    MaxDegreeOfParallelism = Environment.ProcessorCount
                }, file =>
                {
                    var assetFile = new Fo3File(file)
                    {
                        Path = file.GetPathRelative(referenceDir.FullName).ToLower()
                    };
                    lock (reference)
                    {
                        reference.Add(file.GetFullNameRelative(referenceDir.FullName).ToLower(), assetFile);
                    }
                });
                Console.Write(". ");

                Parallel.ForEach(reference, new ParallelOptions {
                    MaxDegreeOfParallelism = 1                                               /* Environment.ProcessorCount */
                }, record =>
                {
                    Debug.Write(record.Key);
                    if (original.IndexFullPath.ContainsKey(record.Key))
                    {
                        if (!ByteArrayCompare(record.Value.Checksum, original.IndexFullPath[record.Key].Checksum))
                        {
                            var originalRecord = original.IndexFullPath[record.Key];
                            var resultRecord   = record.Value;

                            var recordAction = new RecordAction {
                                Path = record.Value.Path, Name = record.Value.Name, Type = ActionType.Copy | ActionType.Patch
                            };
                            patchQueue.Enqueue(() => CreateAssetPatch(settings, original, originalRecord, resultRecord, recordAction));
                            filepair.Actions.Add(recordAction);

                            Debug.WriteLine(" patch");
                        }
                        else
                        {
                            filepair.Actions.Add(new RecordAction {
                                Path = record.Value.Path, Name = record.Value.Name, Type = ActionType.Copy
                            });
                            Debug.WriteLine(" copy");
                        }
                        original.IndexFullPath.Remove(record.Key);
                    }
                    else if (original.IndexFileName.ContainsKey(BitConverter.ToString(record.Value.Checksum)))
                    {
                        var originalRecord = original.IndexFileName[BitConverter.ToString(record.Value.Checksum)];
                        if (original.IndexFullPath.ContainsKey(record.Key))
                        {
                            original.IndexFullPath.Remove(record.Key);
                        }

                        filepair.Actions.Add(new RecordAction {
                            Path = originalRecord.Path, Name = originalRecord.Name, Type = ActionType.Rename, NewPath = record.Value.Path, NewName = record.Value.Name
                        });
                        Debug.WriteLine(" rename");
                    }
                    else
                    {
                        filepair.Actions.Add(new RecordAction {
                            Path = record.Value.Path, Name = record.Value.Name, Type = ActionType.New
                        });
                        Debug.WriteLine(" new");
                    }

                    Console.Write("\r{0} => {1} ... {2}/{3}", filepair.OriginalName, filepair.ResultName, filepair.Actions.Count, reference.Count);
                });

                var i = 0;
                foreach (var newRecord in original.IndexFullPath)
                {
                    filepair.Actions.Add(new RecordAction {
                        Path = newRecord.Value.Path, Name = newRecord.Value.Name, Type = ActionType.Delete
                    });
                    Console.Write("\r{0} => {1} ... D{2}/{3}               ", filepair.OriginalName, filepair.ResultName, ++i, original.IndexFullPath.Count);
                    Debug.WriteLine(newRecord.Key);
                }

                recipe.Files.Add(filepair);

                Console.Write("\r{0} => {1} ... ", filepair.OriginalName, filepair.ResultName);
                Console.WriteLine("Done                               ");
#if DEBUG
                FlushRecipe(settings, recipe);
#endif
            }
            Console.WriteLine("BSAs completed");
        }
Ejemplo n.º 9
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);
                }
        }
Ejemplo n.º 10
0
        private void BuildSFX()
        {
            var fo3BsaPath = Path.Combine(DirFO3Data, "Fallout - Sound.bsa");

            var songsPath = Path.Combine("sound", "songs");

            bool skipSongs = false, skipSFX = false;

            if (Directory.Exists(Path.Combine(DirTTWMain, songsPath)))
            {
                skipSongs = ShowSkipDialog("Fallout 3 songs");
            }

            var outBsaPath = Path.Combine(DirTTWOptional, "Fallout3 Sound Effects", "TaleOfTwoWastelands - SFX.bsa");

            if (File.Exists(outBsaPath))
            {
                skipSFX = ShowSkipDialog("Fallout 3 sound effects");
            }

            if (skipSongs && skipSFX)
            {
                return;
            }

            var bsaInstaller = DependencyRegistry.Container.GetInstance <BsaInstaller>();

            using (BSA
                   inBsa = new BSA(fo3BsaPath),
                   outBsa = new BSA(inBsa.Settings))
            {
                if (!skipSongs)
                {
                    Log.Display("Extracting songs");
                    bsaInstaller.Extract(Token, inBsa.Where(folder => folder.Path.StartsWith(songsPath)), "Fallout - Sound", DirTTWMain, false);
                }

                if (skipSFX)
                {
                    return;
                }

                Log.Display("Building optional TaleOfTwoWastelands - SFX.bsa...");

                var fxuiPath = Path.Combine("sound", "fx", "ui");

                var includedFilenames = new HashSet <string>(File.ReadLines(Path.Combine(Paths.AssetsDir, "TTW Data", "TTW_SFXCopy.txt")));

                var includedGroups =
                    from folder in inBsa.Where(folder => folder.Path.StartsWith(fxuiPath))
                    from file in folder
                    where includedFilenames.Contains(file.Filename)
                    group file by folder;

                foreach (var group in includedGroups)
                {
                    //make folder only include files that matched includedFilenames
                    @group.Key.IntersectWith(@group);

                    //add folders back into output BSA
                    outBsa.Add(@group.Key);
                }

                Log.File("Building TaleOfTwoWastelands - SFX.bsa.");
                outBsa.Save(outBsaPath);

                Log.Display("\tDone");
            }
        }
Ejemplo n.º 11
0
        public bool PatchBsa(CompressionOptions bsaOptions, string oldBSA, string newBSA, bool simulate = false)
        {
            var Op = new InstallStatus(Progress, Token) { ItemsTotal = 7 };

            var outBsaFilename = Path.GetFileNameWithoutExtension(newBSA);

            BSA bsa;
            try
            {
                Op.CurrentOperation = "Opening " + Path.GetFileName(oldBSA);

                bsa = new BSA(oldBSA, bsaOptions);
            }
            finally
            {
                Op.Step();
            }

            IDictionary<string, string> renameDict;
            try
            {
                Op.CurrentOperation = "Opening rename database";

#if LEGACY
                var renamePath = Path.Combine(Installer.PatchDir, outBsaFilename, "RenameFiles.dict");
#else
                var renamePath = Path.Combine(Installer.PatchDir, Path.ChangeExtension(outBsaFilename, ".ren"));
#endif
                if (File.Exists(renamePath))
                {
#if LEGACY
                    renameDict = new Dictionary<string, string>(Util.ReadOldDatabase(renamePath));
#else
                    using (var fileStream = File.OpenRead(renamePath))
                    using (var lzmaStream = new LzmaDecodeStream(fileStream))
                    using (var reader = new BinaryReader(lzmaStream))
                    {
                        var numPairs = reader.ReadInt32();
                        renameDict = new Dictionary<string, string>(numPairs);

                        while (numPairs-- > 0)
                            renameDict.Add(reader.ReadString(), reader.ReadString());
                    }
#endif
                }
                else
                    renameDict = new Dictionary<string, string>();
            }
            finally
            {
                Op.Step();
            }

            PatchDict patchDict;
            try
            {
                Op.CurrentOperation = "Opening patch database";

#if LEGACY
                var chkPrefix = Path.Combine(Installer.PatchDir, outBsaFilename);
                var chkPath = Path.Combine(chkPrefix, "CheckSums.dict");
                patchDict = PatchDict.FromOldDatabase(Util.ReadOldDatabase(chkPath), chkPrefix, b => b);
#else
                var patchPath = Path.Combine(Installer.PatchDir, Path.ChangeExtension(outBsaFilename, ".pat"));
                if (File.Exists(patchPath))
                {
                    patchDict = new PatchDict(patchPath);
                }
                else
                {
                    Log.Dual("\tNo patch database is available for: " + oldBSA);
                    return false;
                }
#endif
            }
            finally
            {
                Op.Step();
            }

            using (bsa)
            {
                try
                {
                    RenameFiles(bsa, renameDict);

                    if (renameDict.Count > 0)
                    {
                        foreach (var kvp in renameDict)
                        {
                            Log.Dual("File not found: " + kvp.Value);
                            Log.Dual("\tCannot create: " + kvp.Key);
                        }
                    }
                }
                finally
                {
                    Op.Step();
                }

                var allFiles = bsa.SelectMany(folder => folder).ToList();
                try
                {
                    var opChk = new InstallStatus(Progress, Token) { ItemsTotal = patchDict.Count };

                    var joinedPatches = from patKvp in patchDict
                                        //if the join is not grouped, this will exclude missing files, and we can't find and fail on them
                                        join oldFile in allFiles on patKvp.Key equals oldFile.Filename into foundOld
                                        join bsaFile in allFiles on patKvp.Key equals bsaFile.Filename
                                        select new PatchJoin(bsaFile, foundOld.SingleOrDefault(), patKvp.Value);

#if DEBUG
                    var watch = new Stopwatch();
                    try
                    {
                        watch.Start();
#endif
#if PARALLEL
                        Parallel.ForEach(joinedPatches, join =>
#else
                        foreach (var join in joinedPatches)
#endif
 HandleFile(opChk, join)
#if PARALLEL
)
#endif
;
#if DEBUG
                    }
                    finally
                    {
                        watch.Stop();
                        Debug.WriteLine(outBsaFilename + " HandleFile loop finished in " + watch.Elapsed);
                    }
#endif
                }
                finally
                {
                    Op.Step();
                }

                try
                {
                    Op.CurrentOperation = "Removing unnecessary files";

                    var notIncluded = allFiles.Where(file => !patchDict.ContainsKey(file.Filename));
                    var filesToRemove = new HashSet<BSAFile>(notIncluded);

                    foreach (BSAFolder folder in bsa)
                        folder.RemoveWhere(filesToRemove.Contains);

                    var emptyFolders = bsa.Where(folder => folder.Count == 0).ToList();
                    emptyFolders.ForEach(folder => bsa.Remove(folder));
                }
                finally
                {
                    Op.Step();
                }

                try
                {
                    Op.CurrentOperation = "Saving " + Path.GetFileName(newBSA);

                    if (!simulate)
                        bsa.Save(newBSA.ToLowerInvariant());
                }
                finally
                {
                    Op.Step();
                }
            }

            Op.Finish();

            return true;
        }
        static void Main(string[] args)
        {
            // If there are no arguments passed then it acts as if help command is ran
            if (args.Count() == 0)
            {
                Program.ShowHelpText();
                return;
            }

            switch (args[0].ToLower())
            {
            default:
            {
                if (args.Count() == 1 && Directory.Exists(args[0]))
                {
                    // If a single existing folder is inputted, the tool will autopack that
                    // The following codes sets up that process

                    string inputDir = args[0];
                    args    = new string[6];
                    args[0] = string.Empty;         // Can equal blank string value
                    args[1] = "-useps3settings";

                    args[2] = "-i";
                    args[3] = inputDir;

                    args[4] = "-o";
                    args[5] = Path.GetDirectoryName(inputDir) + "\\output.bsa";

                    goto case "-p";
                }

                Program.ShowHelpText(true);
                break;
            }

            case "-h":
            case "-help":
            {
                Program.ShowHelpText();
                break;
            }

            case "-p":
            case "-pack":
            {
                string inputDir   = string.Empty;
                string outputPath = string.Empty;

                bool compress          = false;
                bool usePS3FileFlags   = false;
                bool extendDDS         = false;
                bool convertNormalMaps = false;

                for (uint i = 1; i < args.Count(); i++)
                {
                    string option = args[i].ToLower();

                    switch (option)
                    {
                    default:
                    {
                        Program.ShowHelpText(true);
                        return;
                    }

                    case "-compress":
                    {
                        compress = true;
                        break;
                    }

                    case "-useps3fileflags":
                    {
                        usePS3FileFlags = true;
                        break;
                    }

                    case "-extenddds":
                    {
                        extendDDS = true;
                        break;
                    }

                    case "-convertnormals":
                    {
                        convertNormalMaps = true;
                        break;
                    }

                    case "-useps3settings":
                    {
                        usePS3FileFlags   = true;
                        extendDDS         = true;
                        convertNormalMaps = true;
                        break;
                    }

                    case "-i":
                    case "-indir":
                    {
                        i++;
                        inputDir = args[i];
                        break;
                    }

                    case "-o":
                    case "-out":
                    {
                        i++;
                        outputPath = args[i];
                        break;
                    }
                    }
                }

                if (string.IsNullOrEmpty(inputDir) || string.IsNullOrEmpty(outputPath))
                {
                    Program.ShowHelpText(true);
                    return;
                }

                Console.WriteLine("Reading and verifying files...");
                var assetList = new List <Asset>();

                foreach (string file in Directory.GetFiles(inputDir, "*", SearchOption.AllDirectories))
                {
                    var assetFile = new Asset(file.Substring(inputDir.Length + 1), file);
                    assetList.Add(assetFile);
                }

                Console.WriteLine("Packing...");
                BSA.Write(outputPath, assetList, compress, usePS3FileFlags, extendDDS, convertNormalMaps);

                Console.WriteLine("\nDone!\n");
                break;
            }
            }
        }
Ejemplo n.º 13
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);
            }
        }
Ejemplo n.º 14
0
 public static Dictionary <string, FileValidation> FromBSA(BSA bsa)
 {
     return(bsa
            .SelectMany(folder => folder)
            .ToDictionary(file => file.Filename, file => FromBSAFile(file)));
 }