Пример #1
0
        private void OnOpen(object sender, EventArgs e)
        {
            if (this.openDialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            // ReSharper disable RedundantCheckBeforeAssignment
            if (this.openDialog.InitialDirectory != null) // ReSharper restore RedundantCheckBeforeAssignment
            {
                this.openDialog.InitialDirectory = null;
            }

            using (var input = this.openDialog.OpenFile())
            {
                var table = new ArchiveTableFile();
                table.Deserialize(input);
                this._Table = table;
            }

            /*
             * TextWriter writer = new StreamWriter("all_file_hashes.txt");
             * foreach (var hash in table.Keys.OrderBy(k => k))
             * {
             *  writer.WriteLine(hash.ToString("X8"));
             * }
             * writer.Close();
             */

            this.BuildFileTree();
        }
        public void ShowSaveProgress(
            IWin32Window owner,
            Stream archive,
            ArchiveTableFile table,
            List <uint> saving,
            ProjectData.HashList <uint> fileNames,
            string basePath,
            SaveAllSettings settings)
        {
            SaveAllInformation info;

            info.BasePath  = basePath;
            info.Archive   = archive;
            info.Table     = table;
            info.Saving    = saving;
            info.FileNames = fileNames;
            info.Settings  = settings;

            this.progressBar.Value   = 0;
            this.progressBar.Maximum = 100;

            this._SaveThread = new Thread(this.SaveAll);
            this._SaveThread.Start(info);
            this.ShowDialog(owner);
        }
        // the thread entry point
        private void _DoSearch()
        {
            this._ArchiveIndex = 0;

            this._CurrentFile.Add(null); // the arc file
            this._CurrentFile.Add(null); // the file inside the arc file

            // walk the TAB files
            foreach (var tabFile in this._FileList)
            {
                var tab = new ArchiveTableFile();
                using (var input = File.OpenRead(tabFile))
                {
                    tab.Deserialize(input);
                }

                var arcFile = Path.ChangeExtension(tabFile, ".arc");
                this._CurrentFile[0] = Path.GetFileName(Path.GetDirectoryName(arcFile)) + '/' + Path.GetFileName(arcFile);
                using (var input = File.OpenRead(arcFile))
                {
                    this._ArchiveEntryIndex = 0;
                    this._ArchiveEntryCount = tab.Entries.Count;

                    foreach (var entry in tab.Entries)
                    {
                        ++this._ArchiveEntryIndex;
                        ++this.FileCount;
                        this.PrintProgress();

                        input.Position = entry.Offset;
                        string subtype = this.GetType(input);
                        if (string.IsNullOrEmpty(subtype))
                        {
                            continue;
                        }

                        // set the current file
                        if (this._ProjectFileList.Contains(entry.NameHash))
                        {
                            this._CurrentFile[1] = this._ProjectFileList[entry.NameHash];
                        }
                        else
                        {
                            this._CurrentFile[1] = entry.NameHash.ToString("X8") + '.' + subtype;
                        }
                        this.UpdateCurrentFile();
                        // process that file
                        using (var entryStream = entry.ReadToMemoryStream(input))
                        {
                            this.HandleStream(entryStream, subtype);
                        }
                    }
                }
                ++this._ArchiveIndex;
            }
            this.flush();
            this.PrintEnd();
        }
Пример #4
0
        // the thread entry point
        private void _DoSearch()
        {
            this._ArchiveIndex = 0;

            // walk the TAB files
            foreach (var tabFile in this._FileList)
            {
                var tab = new ArchiveTableFile();
                using (var input = File.OpenRead(tabFile))
                {
                    tab.Deserialize(input);
                }

                var arcFile = Path.ChangeExtension(tabFile, ".arc");
                using (var input = File.OpenRead(arcFile))
                {
                    this._ArchiveEntryIndex = 0;
                    this._ArchiveEntryCount = tab.Entries.Count;

                    foreach (var entry in tab.Entries)
                    {
                        ++this._ArchiveEntryIndex;
                        ++this.FileCount;
                        this.PrintProgress();

                        input.Position = entry.Offset;
                        string subtype = this.GetType(input);
                        if (string.IsNullOrEmpty(subtype))
                        {
                            continue;
                        }
                        using (var entryStream = entry.ReadToMemoryStream(input))
                        {
                            this.HandleStream(entryStream, subtype);
                        }
                    }
                }
                ++this._ArchiveIndex;
            }
            this.PrintEnd();
        }
Пример #5
0
        public static void Main(string[] args)
        {
            bool   showHelp        = false;
            bool   extractUnknowns = true;
            string filterPattern   = null;
            bool   overwriteFiles  = false;
            bool   verbose         = false;
            string currentProject  = null;

            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 },
                { "f|filter=", "only extract files using pattern", v => filterPattern = v },
                { "v|verbose", "be verbose", v => verbose = v != null },
                { "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 < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_tab [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            Regex filter = null;

            if (string.IsNullOrEmpty(filterPattern) == false)
            {
                filter = new Regex(filterPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
            }

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

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

            var hashes = manager.LoadFileLists(null);

            var tab = new ArchiveTableFile();

            using (var input = File.OpenRead(tabPath))
            {
                tab.Deserialize(input);
            }

            var arcPath = Path.ChangeExtension(tabPath, ".arc");

            using (var input = File.OpenRead(arcPath))
            {
                long current = 0;
                long total   = tab.Entries.Count;
                var  padding = total.ToString(CultureInfo.InvariantCulture).Length;

                foreach (var entry in tab.Entries)
                {
                    current++;

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

                        var guess = new byte[32];

                        input.Seek(entry.Offset, SeekOrigin.Begin);
                        var read = input.Read(guess, 0, (int)Math.Min(guess.Length, entry.Size));

                        var extension = FileDetection.Detect(guess, read);
                        name = entry.NameHash.ToString("X8");
                        name = Path.ChangeExtension(name, "." + extension);
                        name = Path.Combine("__UNKNOWN", extension, name);
                    }
                    else
                    {
                        if (name.StartsWith("/") == true)
                        {
                            name = name.Substring(1);
                        }
                        name = name.Replace('/', Path.DirectorySeparatorChar);
                    }

                    if (filter != null && filter.IsMatch(name) == false)
                    {
                        continue;
                    }

                    var entryPath = Path.Combine(outputPath, name);
                    if (overwriteFiles == false && File.Exists(entryPath) == true)
                    {
                        continue;
                    }

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

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

                    using (var output = File.Create(entryPath))
                    {
                        input.Seek(entry.Offset, SeekOrigin.Begin);
                        output.WriteFromStream(input, entry.Size);
                    }
                }
            }
        }
Пример #6
0
        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.LoadFileLists(null);

            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>();

            var locations = new Dictionary <string, string>()
            {
                { "archives_win64", "game*.tab" },
                { "dlc_win64", "*.tab" },
                { "patch_win64", "*.tab" },
            };

            foreach (var kv in locations)
            {
                var locationPath = Path.Combine(installPath, kv.Key);

                if (Directory.Exists(locationPath) == true)
                {
                    inputPaths.AddRange(Directory.GetFiles(locationPath, kv.Value, SearchOption.AllDirectories));
                }
            }

            var outputPaths = new List <string>();

            var breakdown = new Breakdown();
            var allNames  = new List <string>();

            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 tab = new ArchiveTableFile();

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

                var localBreakdown = new Breakdown();

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

                        if (allNames.Contains(name) == false)
                        {
                            allNames.Add(name);
                        }
                    }

                    localBreakdown.Total++;
                }

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

                names.Sort();

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

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

            allNames.Sort();

            using (var output = File.Create(Path.Combine(listsPath, "files", "status.txt")))
                using (var writer = new StreamWriter(output))
                {
                    writer.WriteLine("{0}", breakdown);
                }
        }
Пример #7
0
        public static void Main(string[] args)
        {
            bool overwrite = false;
            bool showHelp  = false;
            var  options   = new OptionSet()
            {
                { "o|overwrite", "overwrite existing files", v => overwrite = 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 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ game[0-9]+_unpack", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            string path      = Path.GetFullPath(extras[0]);
            string base_name = Path.GetFileName(path).Replace("_unpack", "");
            string base_path = Path.GetDirectoryName(path);
            string tabFile   = Path.Combine(base_path, base_name + ".tab");
            string arcFile   = Path.Combine(base_path, base_name + ".arc");

            if (File.Exists(arcFile) && !overwrite)
            {
                Console.Write("Refusing to do this: it will overwrite {0}", Path.GetFileName(arcFile));
                return;
            }

            Console.WriteLine("Will generate {0} and {1}", Path.GetFileName(tabFile), Path.GetFileName(arcFile));

            var fileList             = Directory.GetFiles(path, "*", SearchOption.AllDirectories);
            Uri baseUri              = new Uri(path + Path.DirectorySeparatorChar);
            ArchiveTableFile tabData = new ArchiveTableFile();
            var arcStream            = File.Create(arcFile);

            Console.WriteLine("Found {0} files", fileList.Length);
            Console.WriteLine("Writing the ARC file");
            uint             count     = 0;
            uint             skipCount = 0;
            SortedSet <uint> hashSet   = new SortedSet <uint>();

            foreach (var file in fileList)
            {
                if (count > 0 && count % 300 == 0)
                {
                    Console.WriteLine("[{0:F1} %]", (float)count * 100 / (float)fileList.Length);
                }
                ++count;

                Uri    fileUri      = new Uri(file);
                string relPath      = baseUri.MakeRelativeUri(fileUri).ToString();
                string firstSegment = relPath.Split('/')[0];

                switch (Path.GetExtension(file))
                {
                case ".xml":
                case ".XML":
                case ".dll":
                case ".DLL":
                case ".exe":
                case ".EXE":
                {
                    Console.WriteLine("Skipping {0} [that's a {1} file]", relPath, Path.GetExtension(file));
                    ++skipCount;
                    continue;
                }
                }

                uint hash;
                if (firstSegment == "__UNKNOWN")
                {
                    try
                    {
                        hash = uint.Parse(Path.GetFileNameWithoutExtension(file), System.Globalization.NumberStyles.AllowHexSpecifier);
                    }
                    catch
                    {
                        Console.WriteLine("Skipping {0} [wrong name: not a hash]", relPath);
                        ++skipCount;
                        continue;
                    }
                }
                else
                {
                    hash = relPath.HashJenkins();
                }

                if (hashSet.Contains(hash))
                {
                    Console.WriteLine("Skipping {0} [HASH COLLISION FOUND]", relPath);
                    ++skipCount;
                    continue;
                }
                hashSet.Add(hash);
                uint position = (uint)arcStream.Position;
                uint size;
                // Copy the file contents into the .arc file
                using (var fileStream = File.OpenRead(file))
                {
                    size = (uint)fileStream.Length;
                    arcStream.WriteFromStream(fileStream, fileStream.Length);
                }
                // Create the tab entry
                tabData.Entries.Add(new ArchiveTableFile.EntryInfo(hash, position, size));

                // Align the next entry (pad with '0' (0x30), like avalanche do)
                while ((arcStream.Position % tabData.Alignment) != 0)
                {
                    arcStream.WriteByte(0x30);
                }
            }
            arcStream.Close();
            Console.WriteLine("Skipped {0}/{1} files", skipCount, count);

            // write the tab file
            var tabStream = File.Create(tabFile);

            tabData.Serialize(tabStream);
        }
Пример #8
0
        public static void Main(string[] args)
        {
            bool   showHelp        = false;
            bool   extractUnknowns = true;
            string filterPattern   = null;
            bool   overwriteFiles  = false;
            bool   verbose         = false;
            string currentProject  = null;

            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 },
                { "f|filter=", "only extract files using pattern", v => filterPattern = v },
                { "v|verbose", "be verbose", v => verbose = v != null },
                { "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 < 1 || extras.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_tab [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            Regex filter = null;

            if (string.IsNullOrEmpty(filterPattern) == false)
            {
                filter = new Regex(filterPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
            }

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

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

            var hashes = manager.LoadFileLists();

            var tab = new ArchiveTableFile();

            using (var input = File.OpenRead(tabPath))
            {
                tab.Deserialize(input);
            }

            var arcPath = Path.ChangeExtension(tabPath, ".arc");

            var compressedBlockBytes   = new byte[tab.MaxCompressedBlockSize];
            var uncompressedBlockBytes = new byte[tab.UncompressedBlockSize];

            var singleCompressedBlock = new List <ArchiveTableFile.CompressedBlockInfo>();

            singleCompressedBlock.Add(new ArchiveTableFile.CompressedBlockInfo());

            using (var input = File.OpenRead(arcPath))
            {
                long current = 0;
                long total   = tab.Entries.Count;
                var  padding = total.ToString(CultureInfo.InvariantCulture).Length;

                foreach (var entry in tab.Entries)
                {
                    current++;

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

                        var guess = new byte[32];

                        input.Position = entry.Offset;

                        int read;
                        if (entry.CompressionType == CompressionType.None ||
                            entry.CompressedSize == entry.UncompressedSize)
                        {
                            read = input.Read(guess, 0, (int)Math.Min(guess.Length, entry.CompressedSize));
                        }
                        else
                        {
                            var decompress = GetDecompress(entry.CompressionType);

                            ArchiveTableFile.CompressedBlockInfo compressedBlock;
                            if (entry.CompressedBlockIndex == 0)
                            {
                                compressedBlock = new ArchiveTableFile.CompressedBlockInfo(
                                    entry.CompressedSize,
                                    entry.UncompressedSize);
                            }
                            else
                            {
                                compressedBlock = tab.CompressedBlocks[entry.CompressedBlockIndex];
                            }

                            read = input.Read(compressedBlockBytes, 0, (int)compressedBlock.CompressedSize);
                            if (read != compressedBlock.CompressedSize)
                            {
                                throw new EndOfStreamException();
                            }

                            read = decompress(
                                compressedBlockBytes,
                                0,
                                (int)compressedBlock.CompressedSize,
                                uncompressedBlockBytes,
                                0,
                                (int)compressedBlock.UncompressedSize);
                            if (read != compressedBlock.UncompressedSize)
                            {
                                throw new InvalidOperationException();
                            }

                            var guessSize = Math.Min(32, (int)compressedBlock.UncompressedSize);
                            Array.Copy(uncompressedBlockBytes, 0, guess, 0, guessSize);
                        }

                        var extension = FileDetection.Detect(guess, read);
                        name = entry.NameHash.ToString("X8");
                        name = Path.ChangeExtension(name, "." + extension);
                        name = Path.Combine("__UNKNOWN", extension, name);
                    }
                    else
                    {
                        if (name.StartsWith("/") == true)
                        {
                            name = name.Substring(1);
                        }
                        name = name.Replace('/', Path.DirectorySeparatorChar);
                    }

                    if (filter != null && filter.IsMatch(name) == false)
                    {
                        continue;
                    }

                    var entryPath = Path.Combine(outputPath, name);
                    if (overwriteFiles == false && File.Exists(entryPath) == true)
                    {
                        continue;
                    }

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

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

                    input.Position = entry.Offset;
                    using (var output = File.Create(entryPath))
                    {
                        if (entry.CompressionType == CompressionType.None ||
                            entry.CompressedSize == entry.UncompressedSize)
                        {
                            if (entry.CompressedSize != entry.UncompressedSize)
                            {
                                throw new InvalidOperationException();
                            }

                            output.WriteFromStream(input, entry.CompressedSize);
                        }
                        else
                        {
                            var decompress = GetDecompress(entry.CompressionType);

                            List <ArchiveTableFile.CompressedBlockInfo> compressedBlocks;
                            ushort compressedBlockCount;
                            ushort compressedBlockIndex = entry.CompressedBlockIndex;
                            if (compressedBlockIndex == 0)
                            {
                                compressedBlocks    = singleCompressedBlock;
                                compressedBlocks[0] = new ArchiveTableFile.CompressedBlockInfo(
                                    entry.CompressedSize,
                                    entry.UncompressedSize);
                                compressedBlockCount = 1;
                            }
                            else
                            {
                                compressedBlocks = tab.CompressedBlocks;
                                long uncompressedSize = 0;
                                compressedBlockCount = 0;
                                for (int i = compressedBlockIndex; uncompressedSize < entry.UncompressedSize; i++)
                                {
                                    uncompressedSize += compressedBlocks[i].UncompressedSize;
                                    compressedBlockCount++;
                                }
                            }

                            long remaining = entry.UncompressedSize;
                            for (int i = 0; i < compressedBlockCount; i++)
                            {
                                var compressedBlock = compressedBlocks[compressedBlockIndex];

                                var read = input.Read(compressedBlockBytes, 0, (int)compressedBlock.CompressedSize);
                                if (read != compressedBlock.CompressedSize)
                                {
                                    throw new EndOfStreamException();
                                }

                                var result = decompress(
                                    compressedBlockBytes,
                                    0,
                                    (int)compressedBlock.CompressedSize,
                                    uncompressedBlockBytes,
                                    0,
                                    (int)compressedBlock.UncompressedSize);
                                if (result != compressedBlock.UncompressedSize)
                                {
                                    throw new InvalidOperationException();
                                }
                                output.Write(uncompressedBlockBytes, 0, (int)compressedBlock.UncompressedSize);

                                remaining -= compressedBlock.UncompressedSize;
                                compressedBlockIndex++;
                            }

                            if (remaining != 0)
                            {
                                throw new InvalidOperationException();
                            }
                        }
                    }
                }
            }
        }