Exemplo n.º 1
0
        private void BuildBSAs()
        {
            var bsas = ModList.Directives.OfType <CreateBSA>().ToList();

            Info($"Building {bsas.Count} bsa files");

            bsas.Do(bsa =>
            {
                Status($"Building {bsa.To}");
                var source_dir   = Path.Combine(Outputfolder, Consts.BSACreationDir, bsa.TempID);
                var source_files = Directory.EnumerateFiles(source_dir, "*", SearchOption.AllDirectories)
                                   .Select(e => e.Substring(source_dir.Length + 1))
                                   .ToList();

                using (var a = new BSABuilder())
                {
                    //a.Create(Path.Combine(Outputfolder, bsa.To), (bsa_archive_type_t)bsa.Type, entries);
                    a.HeaderType   = (VersionType)bsa.Type;
                    a.FileFlags    = (FileFlags)bsa.FileFlags;
                    a.ArchiveFlags = (ArchiveFlags)bsa.ArchiveFlags;

                    source_files.PMap(f =>
                    {
                        Status($"Adding {f} to BSA");
                        using (var fs = File.OpenRead(Path.Combine(source_dir, f)))
                            a.AddFile(f, fs);
                    });

                    Info($"Writing {bsa.To}");
                    a.Build(Path.Combine(Outputfolder, bsa.To));
                }
            });
        }
Exemplo n.º 2
0
        private static async Task <string[]> CookFiles(VFS vfs, AbsolutePath to, bool trial = false)
        {
            var files = vfs.AllAppliedFiles.Select(f => f.First()).OfType <ModFile>()
                        .Where(f => Definitions.BatchForExtension.ContainsKey(f.Path.Extension))
                        .GroupIntoSizes(f => f.Size, Definitions.MaxBatchSize)
                        .Select((itms, idx) => (itms, idx))
                        .ToArray();

            List <string> newEsps = new();

            Console.WriteLine($"Found {files.Length} archives to build");
            foreach (var(group, idx) in files)
            {
                var name    = $"_Cooked {idx:0000}.bsa";
                var outFile = to.Combine("mods", "Cooked Files", name);
                if (!trial)
                {
                    Console.WriteLine($"Building {name}");
                    var flags = group.Select(f => Definitions.BatchForExtension[f.Path.Extension]).Distinct()
                                .Aggregate((uint)0, (a, b) => a | (uint)b.FileFlags);
                    await using var bsa = await BSABuilder.Create(new BSAStateObject ()
                    {
                        ArchiveFlags = ((int)(ArchiveFlags.HasFileNames | ArchiveFlags.HasFolderNames
                                              /* | ArchiveFlags.HasFileNameBlobs*/)) | 0x10 | 0x80,
                        FileFlags = flags,
                        Magic     = Encoding.ASCII.GetString(new byte[] { 0x42, 0x53, 0x41, 0x00 }),
                        Version   = 0x67
                    }, Definitions.MaxBatchSize);

                    bsa.HeaderType = VersionType.SSE;

                    foreach (var(file, fidx) in group.Select((itm, fidx) => (itm, fidx)))
                    {
                        var state = new BSAFileStateObject
                        {
                            Path            = (RelativePath)((string)file.Path).ToLowerInvariant().Replace('/', '\\'),
                            Index           = fidx,
                            FlipCompression = false
                        };
                        await bsa.AddFile(state, await file.AbsolutePath.OpenRead());
                    }

                    Console.WriteLine($"Writing {name}");

                    await bsa.Build(outFile);

                    Console.WriteLine($"Done building {name}");
                }

                Console.WriteLine($"Writing Stub");
                outFile = outFile.ReplaceExtension(new Extension(".esp"));
                newEsps.Add(outFile.FileName.ToString());
                await "Stub.esp".RelativeTo(AbsolutePath.EntryPoint).CopyToAsync(outFile);
            }

            return(newEsps.ToArray());
        }
Exemplo n.º 3
0
        static void Main(string[] args)
        {
            foreach (var bsa in Directory.EnumerateFiles(TestDir, "*.bsa", SearchOption.AllDirectories).Skip(0))
            {
                Console.WriteLine($"From {bsa}");
                Console.WriteLine("Cleaning Output Dir");
                if (Directory.Exists(TempDir))
                {
                    Directory.Delete(TempDir, true);
                }
                Directory.CreateDirectory(TempDir);

                Console.WriteLine($"Reading {bsa}");
                using (var a = new BSAReader(bsa))
                {
                    Parallel.ForEach(a.Files, file =>
                    {
                        var abs_name = Path.Combine(TempDir, file.Path);

                        if (!Directory.Exists(Path.GetDirectoryName(abs_name)))
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(abs_name));
                        }

                        using (var fs = File.OpenWrite(abs_name))
                            file.CopyDataTo(fs);
                        Equal((long)file.Size, new FileInfo(abs_name).Length);
                    });


                    Console.WriteLine($"Building {bsa}");

                    using (var w = new BSABuilder())
                    {
                        w.ArchiveFlags = a.ArchiveFlags;
                        w.FileFlags    = a.FileFlags;
                        w.HeaderType   = a.HeaderType;

                        Parallel.ForEach(a.Files, file =>
                        {
                            var abs_path = Path.Combine("c:\\tmp\\out", file.Path);
                            using (var str = File.OpenRead(abs_path))
                            {
                                var entry = w.AddFile(file.Path, str, file.FlipCompression);
                            }
                        });

                        w.Build("c:\\tmp\\tmp.bsa");

                        // Sanity Checks
                        Equal(a.Files.Count(), w.Files.Count());
                        Equal(a.Files.Select(f => f.Path).ToHashSet(), w.Files.Select(f => f.Path).ToHashSet());

                        /*foreach (var pair in Enumerable.Zip(a.Files, w.Files, (ai, bi) => (ai, bi)))
                         * {
                         *  Console.WriteLine($"{pair.ai.Path},  {pair.ai.Hash},  {pair.bi.Path}, {pair.bi.Hash}");
                         * }*/

                        foreach (var pair in Enumerable.Zip(a.Files, w.Files, (ai, bi) => (ai, bi)))
                        {
                            Equal(pair.ai.Path, pair.bi.Path);
                            Equal(pair.ai.Hash, pair.bi.Hash);
                        }
                    }

                    Console.WriteLine($"Verifying {bsa}");
                    using (var b = new BSAReader("c:\\tmp\\tmp.bsa"))
                    {
                        Console.WriteLine($"Performing A/B tests on {bsa}");
                        Equal((uint)a.ArchiveFlags, (uint)b.ArchiveFlags);
                        Equal((uint)a.FileFlags, (uint)b.FileFlags);

                        // Check same number of files
                        Equal(a.Files.Count(), b.Files.Count());
                        int idx = 0;
                        foreach (var pair in Enumerable.Zip(a.Files, b.Files, (ai, bi) => (ai, bi)))
                        {
                            idx++;
                            //Console.WriteLine($"   - {pair.ai.Path}");
                            Equal(pair.ai.Path, pair.bi.Path);
                            Equal(pair.ai.Compressed, pair.bi.Compressed);
                            Equal(pair.ai.Size, pair.bi.Size);
                            Equal(pair.ai.GetData(), pair.bi.GetData());
                        }
                    }
                }
            }
        }