Beispiel #1
0
        public static void Main(string[] args)
        {
            bool showHelp        = false;
            bool extractUnknowns = true;
            bool overwriteFiles  = false;
            bool verbose         = false;
            bool uncompress      = false;

            var options = new OptionSet()
            {
                {
                    "o|overwrite",
                    "overwrite existing files",
                    v => overwriteFiles = v != null
                },
                {
                    "nu|no-unknowns",
                    "don't extract unknown files",
                    v => extractUnknowns = v == null
                },
                {
                    "v|verbose",
                    "be verbose",
                    v => verbose = v != null
                },
                {
                    "u|uncompress",
                    "uncompress DCX compressed files",
                    v => uncompress = v != null
                },
                {
                    "h|help",
                    "show this message and exit",
                    v => showHelp = v != null
                },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_bhd5 [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            string headerPath = extras[0];
            string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(headerPath, null) + "_unpack";
            string dataPath;

            if (Path.GetExtension(headerPath) == ".bdt")
            {
                dataPath   = headerPath;
                headerPath = Path.ChangeExtension(headerPath, ".bhd5");
            }
            else
            {
                dataPath = Path.ChangeExtension(headerPath, ".bdt");
            }

            var manager = ProjectData.Manager.Load();

            if (manager.ActiveProject == null)
            {
                Console.WriteLine("Warning: no active project loaded.");
            }

            var hashes = manager.LoadListsFileNames();

            var bhd = new Binder5File();

            using (var input = File.OpenRead(headerPath))
            {
                bhd.Deserialize(input);
            }

            using (var input = File.OpenRead(dataPath))
            {
                long current = 0;
                long total   = bhd.Entries.Count;

                foreach (var entry in bhd.Entries)
                {
                    bool uncompressing = false;

                    current++;

                    string name = hashes[entry.NameHash];
                    if (name == null)
                    {
                        if (extractUnknowns == false)
                        {
                            continue;
                        }

                        string extension;

                        // detect type
                        {
                            var guess = new byte[64];
                            int read  = 0;

                            extension = "unknown";

                            // TODO: fix me
                        }

                        name = entry.NameHash.ToString("X8");
                        name = Path.ChangeExtension(name, "." + extension);
                        name = Path.Combine(extension, name);
                        name = Path.Combine("__UNKNOWN", name);
                    }
                    else
                    {
                        name = name.Replace("/", "\\");
                        if (name.StartsWith("\\") == true)
                        {
                            name = name.Substring(1);
                        }
                    }

                    if (uncompress == true &&
                        entry.Size >= 76)
                    {
                        input.Seek(entry.Offset, SeekOrigin.Begin);
                        if (input.ReadValueU32(Endian.Big) == 0x44435800)
                        {
                            uncompressing = true;

                            var extension = Path.GetExtension(name);
                            if (extension != null &&
                                extension.EndsWith(".dcx") == true)
                            {
                                name = name.Substring(0, name.Length - 4);
                            }
                        }
                    }

                    var entryPath = Path.Combine(outputPath, name);

                    var parentPath = Path.GetDirectoryName(entryPath);
                    if (parentPath != null)
                    {
                        Directory.CreateDirectory(parentPath);
                    }

                    if (overwriteFiles == false &&
                        File.Exists(entryPath) == true)
                    {
                        continue;
                    }

                    if (verbose == true)
                    {
                        Console.WriteLine("[{0}/{1}] {2}",
                                          current,
                                          total,
                                          name);
                    }

                    using (var output = File.Create(entryPath))
                    {
                        if (entry.Size > 0)
                        {
                            if (uncompress == false ||
                                uncompressing == false)
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);
                                output.WriteFromStream(input, entry.Size);
                            }
                            else
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);
                                using (var temp = CompressedFile.Decompress(input))
                                {
                                    output.WriteFromStream(temp, temp.Length);
                                }
                            }
                        }
                    }
                }
            }
        }
        public static void Main(string[] args)
        {
            bool   showHelp       = false;
            string currentProject = null;

            var options = new OptionSet()
            {
                {
                    "h|help",
                    "show this message and exit",
                    v => showHelp = v != null
                },
                {
                    "p|project=",
                    "override current project",
                    v => currentProject = v
                },
            };

            List <string> extras;

            try
            {
                extras = options.Parse(args);
            }
            catch (OptionException e)
            {
                Console.Write("{0}: ", GetExecutableName());
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName());
                return;
            }

            if (extras.Count != 0 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            Console.WriteLine("Loading project...");

            var manager = Gibbed.ProjectData.Manager.Load(currentProject);

            if (manager.ActiveProject == null)
            {
                Console.WriteLine("Nothing to do: no active project loaded.");
                return;
            }

            var project = manager.ActiveProject;
            var hashes  = manager.LoadListsFileNames();

            var installPath = project.InstallPath;
            var listsPath   = project.ListsPath;

            if (installPath == null)
            {
                Console.WriteLine("Could not detect install path.");
                return;
            }

            if (listsPath == null)
            {
                Console.WriteLine("Could not detect lists path.");
                return;
            }

            Console.WriteLine("Searching for archives...");
            var inputPaths = new List <string>();

            inputPaths.AddRange(Directory.GetFiles(installPath, "*.bhd5", SearchOption.AllDirectories));

            var outputPaths = new List <string>();

            var breakdown = new Breakdown();

            Console.WriteLine("Processing...");
            foreach (var inputPath in inputPaths)
            {
                var outputPath = GetListPath(installPath, inputPath);
                if (outputPath == null)
                {
                    throw new InvalidOperationException();
                }

                Console.WriteLine(outputPath);
                outputPath = Path.Combine(listsPath, outputPath);

                if (outputPaths.Contains(outputPath) == true)
                {
                    throw new InvalidOperationException();
                }

                outputPaths.Add(outputPath);

                var bhd = new Binder5File();

                if (File.Exists(inputPath + ".bak") == true)
                {
                    using (var input = File.OpenRead(inputPath + ".bak"))
                        bhd.Deserialize(input);
                }
                else
                {
                    using (var input = File.OpenRead(inputPath))
                        bhd.Deserialize(input);
                }

                var localBreakdown = new Breakdown();

                var names = new List <string>();
                foreach (var nameHash in bhd.Entries.Select(e => e.NameHash).Distinct())
                {
                    var name = hashes[nameHash];
                    if (name != null)
                    {
                        if (names.Contains(name) == false)
                        {
                            names.Add(name);
                            localBreakdown.Known++;
                        }
                    }

                    localBreakdown.Total++;
                }

                breakdown.Known += localBreakdown.Known;
                breakdown.Total += localBreakdown.Total;

                names.Sort();

                var parentPath = Path.GetDirectoryName(outputPath);
                if (parentPath != null)
                {
                    Directory.CreateDirectory(parentPath);
                }

                using (var output = new StreamWriter(outputPath))
                {
                    output.WriteLine("; {0}", localBreakdown);

                    foreach (string name in names)
                    {
                        output.WriteLine(name);
                    }
                }
            }

            using (var output = new StreamWriter(Path.Combine(Path.Combine(listsPath, "files"), "status.txt")))
                output.WriteLine("{0}", breakdown);
        }