Пример #1
0
        public void ShowSaveProgress(
            IWin32Window owner,
            Stream stream,
            BigFile archive,
            IEnumerable <BigFile.Entry> saving,
            Dictionary <uint, string> fileNames,
            string basePath,
            SaveAllSettings settings)
        {
            SaveAllInformation info;

            info.BasePath  = basePath;
            info.Stream    = stream;
            info.Archive   = archive;
            info.Saving    = saving;
            info.FileNames = fileNames;
            info.Settings  = settings;

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

            this.SaveThread = new Thread(new ParameterizedThreadStart(SaveAll));
            this.SaveThread.Start(info);
            this.ShowDialog(owner);
        }
Пример #2
0
        private void OnOpen(object sender, EventArgs e)
        {
            if (this.openDialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }

            if (this.openDialog.InitialDirectory != null)
            {
                this.openDialog.InitialDirectory = null;
            }

            BigFile archive;

            using (var input = this.openDialog.OpenFile())
            {
                archive = new BigFile();
                archive.Deserialize(input);
            }
            this.Archive = archive;

            this.BuildFileTree();

            var exists = File.Exists(Path.ChangeExtension(this.openDialog.FileName, ".dat"));

            this.saveAllButton.Enabled         = exists;
            this.saveToolStripMenuItem.Enabled = exists;
        }
Пример #3
0
        static void CheckFiles()
        {
            Console.Write("File path: ");
            string path = Console.ReadLine();

            if (!File.Exists(path) && !Directory.Exists(path))
            {
                Environment.Exit(69);
            }

            LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info;

            BigFile bigFile = BigFile.OpenBigFile(path);

            bigFile.LoadFromDisk();

            for (int i = 0; i < bigFile.FileMap.FilesList.Length; i++)
            {
                BigFileFile file = bigFile.FileMap.FilesList[i];

                if (file.FileInfo.Offset == -1)
                {
                    LogManager.GlobalLogFlags = LogFlags.All;
                    file.FileInfo.DebugLog(log);
                    LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info;
                }
            }

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

            if (this.openDialog.InitialDirectory != null)
            {
                this.openDialog.InitialDirectory = null;
            }

            BigFile archive;

            using (var input = this.openDialog.OpenFile())
            {
                archive = new BigFile();
                archive.Deserialize(input);
            }
            this.Archive = archive;

            /*
             * 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();
        }
Пример #5
0
        private async void button24_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Filter = "Crash Team Racing BIG file|*.big";

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                Task load = new Task(() => big = BigFile.FromFile(ofd.FileName));
                load.Start();
                await load;
                LoadBig(ofd.FileName);
            }
        }
Пример #6
0
        bool IPackageLoader.TryParsePackage(Stream s, string filename, FS context, out IReadOnlyPackage package)
        {
            // Take a peek at the file signature
            var signature = s.ReadASCII(4);

            s.Position -= 4;

            if (signature != "BIGF")
            {
                package = null;
                return(false);
            }

            package = new BigFile(s, filename);
            return(true);
        }
Пример #7
0
        /// <summary>
        /// Creates a thread and loads a bigfile on it, then calls the method provided.
        /// </summary>
        /// <param name="file"></param>
        /// <param name="next"></param>
        public static void LoadBigFileInBackground(string file, Action <BigFile> next)
        {
            BigFile bigFile = BigFile.OpenBigFile(file);

            ThreadStart ts = new ThreadStart
                                 (() =>
            {
                bigFile.LoadFromDisk();

                next?.Invoke(bigFile);
            });

            Thread t = new Thread(ts);

            t.Start();
        }
Пример #8
0
        public void LoadBigFile()
        {
            if (isLoaded)
            {
                return;
            }

            isLoaded = true;
            IntegrationUtil.LoadBigFileInBackground
                (currentFilePath,
                (bigFile) =>
            {
                textureMetadataFiles = bigFile.RootFolder.GetAllFilesOfArchetype <TextureMetadataFileArchetype>();
                bigFile.FileLoader.LoadFiles(textureMetadataFiles);
                m_bigFile = bigFile;
            });
        }
Пример #9
0
        private async void LoadBigFull(string path)
        {
            if (!File.Exists(path))
            {
                MessageBox.Show($"File doesn't exist!\r\n{path}");
                return;
            }

            Task load = new Task(() => big = BigFile.FromFile(path));

            load.Start();
            await load;

            LoadBig(path);

            MessageBox.Show("Done.");
        }
Пример #10
0
        static void Main(string[] args)
        {
            Console.WriteLine(
                "{0}\r\n{1}\r\n\r\n{2}\r\n",
                "CTR-tools: BigTool",
                "Builds and extracts Crash Team Racing BIG files",
                Meta.GetVersion());

            if (args.Length > 0)
            {
                Console.WriteLine("Current path: " + Environment.CurrentDirectory);

                string ext = Path.GetExtension(args[0]).ToLower();

                try
                {
                    BigFile big = BigFile.FromFile(args[0]);

                    if (big.Entries.Count > 0)
                    {
                        switch (ext)
                        {
                        case ".big": big.Export(".\\bigfile"); break;

                        case ".txt": big.Build(".\\bigfile.big"); break;

                        default: Console.WriteLine("{0}: {1}", "Unsupported file", ext); break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: " + ex.Message);
                }

                return;
            }

            Console.WriteLine(
                "{0}:\r\n\t{1}: {2}\r\n\t{3}: {4}",
                "Usage",
                "Extract example", "bigtool C:\\BIGFILE.BIG",
                "Build example", "bigtool C:\\BIGFILE.TXT"
                );
        }
Пример #11
0
        private static bool FileExistsInBig(string fatPath, string fileName)
        {
            if (File.Exists(fatPath) == false)
            {
                return(false);
            }

            var big = new BigFile();

            using (var input = File.OpenRead(fatPath))
            {
                big.Deserialize(input);
            }

            var entries = big.Entries.Where(e => e.NameHash == fileName.HashFileNameCRC32());

            if (entries.Count() == 0)
            {
                return(false);
            }

            return(true);
        }
Пример #12
0
        private void HandleNodeClick(object sender, EventArgs ea)
        {
            itemsList.Items.Clear();

            if (filesTree.SelectedNodes.Count > 0)
            {
                var node = filesTree.SelectedNodes[0];

                if (node.Tag != null)
                {
                    var tag = (NodeTag)node.Tag;
                    if (tag.FullPath.EndsWith(".big"))
                    {
                        BigFile bf = new BigFile();
                        if (bf.Read(tag.FullPath))
                        {
                            //label2.Text = $"archive {Path.GetFileName(tag.FullPath)} has {bf.Entries.Count} files.";

                            foreach (var e in bf.Entries)
                            {
                                DarkListItem item = new DarkListItem(e.Name);
                                item.Tag = new ListTag()
                                {
                                    NodeTag = tag, BigFile = bf, Entry = e
                                };

                                itemsList.Items.Add(item);
                            }
                        }
                        else
                        {
                            MessageBox.Show($"Failed reading {Path.GetFileName(tag.FullPath)} :(");
                        }
                    }
                }
            }
        }
Пример #13
0
        static void Main(string[] args)
        {
            Console.WriteLine(
                "{0}\r\n{1}\r\n\r\n{2}\r\n",
                "CTR-tools: bigtool by DCxDemo*",
                "Builds and extracts Crash Team Racing BIG files",
                Meta.GetVersionInfo());

            if (args.Length > 0)
            {
                Console.WriteLine("Current path: " + Environment.CurrentDirectory);

                string name    = Path.GetFileNameWithoutExtension(args[0]).ToLower();
                string ext     = Path.GetExtension(args[0]).ToLower();
                string bigpath = Path.GetDirectoryName(args[0]);

                if (!Path.IsPathRooted(args[0]))
                {
                    bigpath = Environment.CurrentDirectory;

                    if (!File.Exists(Path.Combine(bigpath, args[0])))
                    {
                        bigpath = bigpath = Meta.BasePath;

                        if (!File.Exists(Path.Combine(bigpath, args[0])))
                        {
                            Console.WriteLine("Check filename.");
                            return;
                        }
                    }
                }

                string path = Path.Combine(bigpath, name);

                try
                {
                    BigFile big = BigFile.FromFile(Path.Combine(bigpath, $"{name}{ext}"));

                    if (big.Entries.Count == 0)
                    {
                        Console.WriteLine("No files to process.");
                        return;
                    }

                    switch (ext)
                    {
                    case ".big": big.Extract(path); break;

                    case ".txt": big.Save(Path.Combine(bigpath, $"{name}.big")); break;

                    default: Console.WriteLine($"Unsupported file type: {ext}"); break;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: " + ex.Message);
                }

                return;
            }

            Console.WriteLine(
                "{0}:\r\n\t{1}: {2}\r\n\t{3}: {4}",
                "Usage",
                "Extract example", "bigtool C:\\BIGFILE.BIG",
                "Build example", "bigtool C:\\BIGFILE.TXT"
                );
        }
Пример #14
0
        static void CompareAllFiles()
        {
            LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info;

            Console.Write("Bigfile 1: ");
            string path1 = Console.ReadLine();

            Console.Write("Bigfile 2: ");
            string path2 = Console.ReadLine();

            IOBuffers buffer1 = new IOBuffers();
            IOBuffers buffer2 = new IOBuffers();

            BigFile file1 = BigFile.OpenBigFile(path1);
            BigFile file2 = BigFile.OpenBigFile(path2);

            if (file1 == null)
            {
                Console.WriteLine("file 1 null");
                Console.ReadLine();
                Environment.Exit(911);
            }
            if (file2 == null)
            {
                Console.WriteLine("file 2 null");
                Console.ReadLine();
                Environment.Exit(911);
            }

            file1.LoadFromDisk();
            Console.Write("Press enter...");
            Console.ReadLine();
            file2.LoadFromDisk();
            Console.Write("Press enter...");
            Console.ReadLine();
            Console.Clear();

            int missingFiles = 0;

            if (file1.FileMap.FilesList.Length != file2.FileMap.FilesList.Length)
            {
                Console.WriteLine("Files count don't match!");
                foreach (BigFileFile file1file in file1.FileMap.FilesList)
                {
                    if (file2.FileMap[file1file.FileInfo.Key] == null)
                    {
                        missingFiles++;
                        Console.WriteLine("Found file {0} (key: {1:X8}) that appears in the first bigfile but not the second!", file1file.Name, file1file.FileInfo.Key);
                    }
                }
                Console.ReadLine();
                foreach (BigFileFile file2file in file2.FileMap.FilesList)
                {
                    if (file1.FileMap[file2file.FileInfo.Key] == null)
                    {
                        missingFiles++;
                        Console.WriteLine("Found file {0} (key: {1:X8}) that appears in the second bigfile but not the first!", file2file.Name, file2file.FileInfo.Key);
                    }
                }
                Console.ReadLine();
            }

            Console.WriteLine("");
            Console.WriteLine("Found {0} file discrepancies between the two bigfiles", missingFiles);
            Console.Write("Would you like to continue? ");
            Console.ReadLine();

            Console.Clear();

            IEnumerator <int[]> headers1 = file1.FileReader.ReadAllHeaders(file1.FileMap.FilesList, buffer1, file1.FileReader.DefaultFlags).GetEnumerator();
            IEnumerator <int[]> headers2 = file2.FileReader.ReadAllHeaders(file2.FileMap.FilesList, buffer1, file2.FileReader.DefaultFlags).GetEnumerator();

            void CompareHeaders(BigFileFile file1file, BigFileFile file2file, int[] a, int[] b)
            {
                bool foundError = a.Length != b.Length;

                if (!foundError)
                {
                    for (int i = 0; i < a.Length; i++)
                    {
                        if (a[i] != b[i])
                        {
                            foundError = true;
                            break;
                        }
                    }
                }
                if (foundError)
                {
                    Console.WriteLine("File {0} has a header discrepancy!");
                    Console.WriteLine("File 1 header length: {0}", a.Length);
                    Console.WriteLine("File 2 header length: {1}", b.Length);
                    for (int i = 0; i < a.Length; i++)
                    {
                        Console.Write("{0:X8} ", a[i]);
                    }
                    for (int i = 0; i < b.Length; i++)
                    {
                        Console.Write("{0:X8} ", b[i]);
                    }
                }
            }
        }
Пример #15
0
 internal BigFileFileReader(BigFile _bigFile)
 {
     bigFile = _bigFile;
 }
Пример #16
0
        static void CompareFiles()
        {
            LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info;

            Console.Write("Bigfile 1: ");
            string path1 = Console.ReadLine();

            Console.Write("Bigfile 2: ");
            string path2 = Console.ReadLine();

            IOBuffers buffer1 = new IOBuffers();
            IOBuffers buffer2 = new IOBuffers();

            Console.Write("File key: ");
            int key = 0;

            key = Convert.ToInt32(Console.ReadLine(), 16);
            if (key == 0)
            {
                Environment.Exit(420);
            }

            BigFile file1 = BigFile.OpenBigFile(path1);
            BigFile file2 = BigFile.OpenBigFile(path2);

            if (file1 == null)
            {
                Console.WriteLine("file 1 null");
                Console.ReadLine();
                Environment.Exit(911);
            }
            if (file2 == null)
            {
                Console.WriteLine("file 2 null");
                Console.ReadLine();
                Environment.Exit(911);
            }

            file1.LoadFromDisk();
            Console.Write("Press enter...");
            Console.ReadLine();
            file2.LoadFromDisk();
            Console.Write("Press enter...");
            Console.ReadLine();

            BigFileFile bigFileFile1 = file1.FileMap[key];
            BigFileFile bigFileFile2 = file2.FileMap[key];

            int[] header1 = file1.FileReader.ReadFileHeader(bigFileFile1, buffer1, file1.FileReader.DefaultFlags);
            int[] header2 = file2.FileReader.ReadFileHeader(bigFileFile2, buffer2, file2.FileReader.DefaultFlags);

            int size1 = file1.FileReader.ReadFileRaw(bigFileFile1, buffer1, file1.FileReader.DefaultFlags);
            int size2 = file2.FileReader.ReadFileRaw(bigFileFile2, buffer2, file2.FileReader.DefaultFlags);

            int chksum1 = 0;
            int chksum2 = 0;

            for (int i = 0; i < size1; i++)
            {
                chksum1 += buffer1[size1][i];
            }
            for (int i = 0; i < size2; i++)
            {
                chksum2 += buffer2[size2][i];
            }

            Console.Clear();

            Console.WriteLine("Size 1: " + size1);
            Console.WriteLine("Checksum 1: " + chksum1);
            Console.WriteLine("Size 2: " + size2);
            Console.WriteLine("Checksum 2: " + chksum2);

            Console.Write("Header 1, length: {0} : ", header1.Length);
            for (int i = 0; i < header1.Length; i++)
            {
                Console.Write("{0:X8} ", header1[i]);
            }
            Console.Write("\nHeader 2, length: {0} : ", header2.Length);
            for (int i = 0; i < header2.Length; i++)
            {
                Console.Write("{0:X8} ", header2[i]);
            }

            Console.WriteLine("");

            LogManager.GlobalLogFlags = LogFlags.All;

            bigFileFile1.FileInfo.DebugLog(log);
            bigFileFile2.FileInfo.DebugLog(log);


            Console.ReadLine();
        }
Пример #17
0
        public static void Main(string[] args)
        {
            bool showHelp = false;
            bool verbose  = false;
            bool compress = false;

            var options = new OptionSet()
            {
                {
                    "v|verbose",
                    "be verbose",
                    v => verbose = v != null
                },
                {
                    "c|compress",
                    "compress data with LZO1x",
                    v => compress = 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]+ output_fat input_directory+", GetExecutableName());
                Console.WriteLine("Pack files from input directories into a Encapsulated Resource File.");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            var    inputPaths = new List <string>();
            string fatPath, datPath;

            if (extras.Count == 1)
            {
                inputPaths.Add(extras[0]);
                fatPath = Path.ChangeExtension(extras[0], ".fat");
                datPath = Path.ChangeExtension(extras[0], ".dat");
            }
            else
            {
                fatPath = extras[0];

                if (Path.GetExtension(fatPath) != ".fat")
                {
                    datPath = fatPath;
                    fatPath = Path.ChangeExtension(datPath, ".fat");
                }
                else
                {
                    datPath = Path.ChangeExtension(fatPath, ".dat");
                }

                inputPaths.AddRange(extras.Skip(1));
            }

            var paths = new SortedDictionary <uint, string>();

            if (verbose == true)
            {
                Console.WriteLine("Finding files...");
            }

            foreach (var relPath in inputPaths)
            {
                string inputPath = Path.GetFullPath(relPath);

                if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true)
                {
                    inputPath = inputPath.Substring(0, inputPath.Length - 1);
                }

                foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories))
                {
                    string fullPath = Path.GetFullPath(path);
                    string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant();

                    uint hash = 0xFFFFFFFFu;
                    if (partPath.ToUpper().StartsWith("__UNKNOWN") == true)
                    {
                        string partName;
                        partName = Path.GetFileNameWithoutExtension(partPath);
                        if (partName.Length > 8)
                        {
                            partName = partName.Substring(0, 8);
                        }

                        hash = uint.Parse(
                            partName,
                            System.Globalization.NumberStyles.AllowHexSpecifier);
                    }
                    else
                    {
                        hash = partPath.HashFileNameCRC32();
                    }

                    if (paths.ContainsKey(hash) == true)
                    {
                        //if (verbose == true)
                        {
                            Console.WriteLine("Ignoring {0} duplicate.", partPath);
                        }

                        continue;
                    }

                    paths[hash] = fullPath;
                    //Console.WriteLine(fullPath);
                }
            }

            var big = new BigFile();

            using (var output = File.Create(datPath))
            {
                foreach (var value in paths)
                {
                    var hash = value.Key;
                    var path = value.Value;

                    if (verbose == true)
                    {
                        Console.WriteLine(path);
                    }

                    var entry = new Big.Entry();
                    entry.NameHash = hash;
                    entry.Offset   = output.Position;

                    using (var input = File.OpenRead(path))
                    {
                        if (compress == false)
                        {
                            entry.CompressionScheme = Big.CompressionScheme.None;
                            entry.UncompressedSize  = 0;
                            entry.CompressedSize    = (uint)input.Length;
                            output.WriteFromStream(input, input.Length);
                        }
                        else
                        {
                            var uncompressedData = new byte[input.Length];
                            var uncompressedSize = (uint)uncompressedData.Length;
                            input.Read(uncompressedData, 0, uncompressedData.Length);

                            var compressedData = new byte[
                                uncompressedData.Length +
                                (uncompressedData.Length / 16) + 64 + 3];
                            var compressedSize = (uint)compressedData.Length;

                            var result = LZO1x.Compress(
                                uncompressedData, uncompressedSize,
                                compressedData, ref compressedSize);

                            if (result != 0)
                            {
                                throw new InvalidOperationException("compression error " + result.ToString());
                            }

                            if (compressedSize < uncompressedSize)
                            {
                                entry.CompressionScheme = Big.CompressionScheme.LZO1x;
                                entry.UncompressedSize  = uncompressedSize;
                                entry.CompressedSize    = compressedSize;
                                output.Write(compressedData, 0, (int)compressedSize);
                            }
                            else
                            {
                                input.Seek(0, SeekOrigin.Begin);
                                entry.CompressionScheme = Big.CompressionScheme.None;
                                entry.UncompressedSize  = 0;
                                entry.CompressedSize    = (uint)input.Length;
                                output.WriteFromStream(input, input.Length);
                            }
                        }

                        output.Seek(output.Position.Align(16), SeekOrigin.Begin);
                    }

                    big.Entries.Add(entry);
                }
            }

            using (var output = File.Create(fatPath))
            {
                big.Serialize(output);
            }
        }
Пример #18
0
        public static void Main(string[] args)
        {
            Logger = new LogConsole(null, new LogOptions()
            {
                LogTimestamp = false
            });

            Logger.ClearPrependers();

            var origVisible = Console.CursorVisible;
            var origWidth   = Console.WindowWidth;
            var origHeight  = Console.WindowHeight;

            Console.CursorVisible   = false;
            Console.CancelKeyPress += (s, e) =>
            {
                ms_isTerminating = true;
                e.Cancel         = true;
                FinishWithError("User terminated execution.", true);
            };

            if (origWidth < 160)
            {
                Console.WindowWidth = 160;
            }

            if (origHeight < 8 + 16)
            {
                Console.WindowHeight = 8 + 16;
            }

            Console.Clear();

            void DrawCentered(string text, Color col)
            {
                Logger.Info(new string(' ', (Console.WindowWidth - text.Length) / 2), col);
                Console.WriteLine(text);
            }

            string filePath = "";

            if (args.Length == 0)
            {
                TitleDraw.Welcome(Logger);
                DrawCentered("DR2 Format Tools - by avail (alpha)", Color.OrangeRed);

                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine();

                DrawCentered("Drop a .big or .tex onto me to dump contents.", Color.Cyan);
                DrawCentered("(or drop to exe itself next time instead of launching it first)", Color.Green);

                Logger.Info("\t\t Input -> ", Color.Cyan);

                bool CheckExtension(char[] data, int len)
                {
                    int readOffset = 0;

                    if (data[0] == '"')
                    {
                        readOffset += 1;
                    }

                    if (data[len - (readOffset + 2)] == 't' &&
                        data[len - (readOffset + 1)] == 'e' &&
                        data[len - (readOffset + 0)] == 'x')
                    {
                        return(true);
                    }

                    if (data[len - (readOffset + 2)] == 'b' &&
                        data[len - (readOffset + 1)] == 'i' &&
                        data[len - (readOffset + 0)] == 'g')
                    {
                        return(true);
                    }

                    return(false);
                }

                var input = new char[256];
                for (var i = 0; i < input.Length; i++)
                {
                    input[i] = Console.ReadKey().KeyChar;

                    if (i > 6 && CheckExtension(input, i))
                    {
                        Console.WriteLine();
                        break;
                    }
                }

                filePath = new string(input).Split('\0')[0].Replace("\"", "");

                if (!File.Exists(filePath))
                {
                    FinishWithError("The file you specified isn't valid.");
                }
            }
            else
            {
                filePath = args[0];
                var ext = Path.GetExtension(filePath);

                if (!File.Exists(filePath) || (ext != ".tex" && ext != ".big"))
                {
                    FinishWithError("The file you specified isn't valid.");
                }
            }

            var bf = new BigFile();

            var  dumpDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dump", Path.GetFileNameWithoutExtension(filePath));
            bool success = bf.Read(filePath, true, dumpDir);

            Console.CursorVisible = origVisible;
            //Console.WindowWidth = origWidth;
            //Console.WindowHeight = origHeight;

            Console.Clear();
            Console.SetCursorPosition(0, 0);

            if (success)
            {
                FinishWithSuccess(ProcessElapsed, MetadataElapsed, ExportElapsed, EntryCount);
            }
        }
Пример #19
0
        public static void Main(string[] args)
        {
            bool showHelp       = false;
            bool overwriteFiles = false;
            bool verbose        = false;

            var options = new OptionSet()
            {
                {
                    "v|verbose",
                    "be verbose",
                    v => verbose = 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_fat [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            var map = new MapFile();

            map.Info          = new Map.Info();
            map.Snapshot      = new Map.Snapshot();
            map.Data          = new Map.Data();
            map.Data.Unknown2 = new Map.Snapshot();
            map.Archive       = new Map.Archive();

            using (var input = File.OpenRead(Path.Combine(inputPath, "map.xml")))
            {
                var doc = new XPathDocument(input);
                var nav = doc.CreateNavigator();

                var info = nav.SelectSingleNode("/map/info");
                map.Info.Name      = info.SelectSingleNode("name").Value;
                map.Info.Creator   = info.SelectSingleNode("creator").Value;
                map.Info.Author    = info.SelectSingleNode("author").Value;
                map.Info.Size      = (Map.Size)Enum.Parse(typeof(Map.Size), info.SelectSingleNode("size").Value);
                map.Info.Players   = (Map.Players)Enum.Parse(typeof(Map.Players), info.SelectSingleNode("players").Value);
                map.Info.Unknown2  = uint.Parse(info.SelectSingleNode("unknown2").Value, CultureInfo.InvariantCulture);
                map.Info.Unknown3  = uint.Parse(info.SelectSingleNode("unknown3").Value, CultureInfo.InvariantCulture);
                map.Info.Unknown4  = uint.Parse(info.SelectSingleNode("unknown4").Value, CultureInfo.InvariantCulture);
                map.Info.Unknown5  = ulong.Parse(info.SelectSingleNode("unknown5").Value, CultureInfo.InvariantCulture);
                map.Info.Unknown7  = ulong.Parse(info.SelectSingleNode("unknown7").Value, CultureInfo.InvariantCulture);
                map.Info.Unknown10 = ulong.Parse(info.SelectSingleNode("unknown10").Value, CultureInfo.InvariantCulture);

                using (var reader = new XmlTextReader(new StringReader(info.SelectSingleNode("unknown11").OuterXml)))
                {
                    reader.MoveToContent();
                    map.Info.Unknown11 = new byte[0];
                    int read = 0;
                    do
                    {
                        Array.Resize(ref map.Info.Unknown11, map.Info.Unknown11.Length + 4096);
                        read += reader.ReadBinHex(map.Info.Unknown11, read, 4096);
                    }while (reader.EOF == false);
                    Array.Resize(ref map.Info.Unknown11, read);
                }

                using (var reader = new XmlTextReader(new StringReader(info.SelectSingleNode("unknown12").OuterXml)))
                {
                    reader.MoveToContent();
                    map.Info.Unknown12 = new byte[0];
                    int read = 0;
                    do
                    {
                        Array.Resize(ref map.Info.Unknown12, map.Info.Unknown12.Length + 4096);
                        read += reader.ReadBinHex(map.Info.Unknown12, read, 4096);
                    }while (reader.EOF == false);
                    Array.Resize(ref map.Info.Unknown12, read);
                }

                map.Info.Unknown15 = uint.Parse(info.SelectSingleNode("unknown15").Value, CultureInfo.InvariantCulture);

                var snapshot = nav.SelectSingleNode("/map/snapshot");
                map.Snapshot.Width         = uint.Parse(snapshot.SelectSingleNode("width").Value, CultureInfo.InvariantCulture);
                map.Snapshot.Height        = uint.Parse(snapshot.SelectSingleNode("height").Value, CultureInfo.InvariantCulture);
                map.Snapshot.BytesPerPixel = uint.Parse(snapshot.SelectSingleNode("bpp").Value, CultureInfo.InvariantCulture);
                map.Snapshot.Unknown4      = uint.Parse(snapshot.SelectSingleNode("unknown4").Value, CultureInfo.InvariantCulture);

                var data = nav.SelectSingleNode("/map/data");
                map.Data.Unknown1 = data.SelectSingleNode("unknown1").Value;
            }

            using (var input = File.OpenRead(Path.Combine(inputPath, "snapshot.bin")))
            {
                map.Snapshot.Data = new byte[input.Length];
                input.Read(map.Snapshot.Data, 0, map.Snapshot.Data.Length);
            }

            var paths = new SortedDictionary <uint, string>();

            if (verbose == true)
            {
                Console.WriteLine("Finding files...");
            }

            var dataPath = Path.Combine(inputPath, "archive");

            dataPath = Path.GetFullPath(dataPath);

            if (dataPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true)
            {
                dataPath = dataPath.Substring(0, dataPath.Length - 1);
            }

            foreach (string path in Directory.GetFiles(dataPath, "*", SearchOption.AllDirectories))
            {
                string fullPath = Path.GetFullPath(path);
                string partPath = fullPath.Substring(dataPath.Length + 1).ToLowerInvariant();

                uint hash = 0xFFFFFFFFu;
                if (partPath.ToUpper().StartsWith("__UNKNOWN") == true)
                {
                    string partName;
                    partName = Path.GetFileNameWithoutExtension(partPath);
                    if (partName.Length > 8)
                    {
                        partName = partName.Substring(0, 8);
                    }

                    hash = uint.Parse(
                        partName,
                        System.Globalization.NumberStyles.AllowHexSpecifier);
                }
                else
                {
                    hash = partPath.HashFileNameCRC32();
                }

                if (paths.ContainsKey(hash) == true)
                {
                    continue;
                }

                paths[hash] = fullPath;
            }

            var big = new BigFile();

            using (var output = new MemoryStream())
            {
                foreach (var value in paths)
                {
                    var hash = value.Key;
                    var path = value.Value;

                    if (verbose == true)
                    {
                        Console.WriteLine(path);
                    }

                    var entry = new Big.Entry();
                    entry.NameHash = hash;
                    entry.Offset   = output.Position;

                    using (var input = File.OpenRead(path))
                    {
                        entry.CompressionScheme = Big.CompressionScheme.None;
                        entry.UncompressedSize  = 0;
                        entry.CompressedSize    = (uint)input.Length;
                        output.WriteFromStream(input, input.Length);
                    }

                    big.Entries.Add(entry);
                }

                map.Archive.DAT = MakeCompressedData(output);
            }

            using (var output = new MemoryStream())
            {
                big.Serialize(output);
                map.Archive.FAT = MakeCompressedData(output);
            }

            using (var output = new MemoryStream())
            {
                var settings = new XmlWriterSettings();
                settings.Indent             = true;
                settings.OmitXmlDeclaration = true;
                settings.IndentChars        = "\t";
                settings.Encoding           = Encoding.ASCII;

                using (var writer = XmlWriter.Create(output, settings))
                {
                    writer.WriteStartDocument();
                    writer.WriteStartElement("FatInfo");

                    foreach (var entry in big.Entries.OrderBy(e => e.NameHash))
                    {
                        writer.WriteStartElement("File");
                        writer.WriteAttributeString("Path", entry.NameHash.ToString(CultureInfo.InvariantCulture));
                        writer.WriteAttributeString("Crc", entry.NameHash.ToString(CultureInfo.InvariantCulture));
                        writer.WriteAttributeString("FileTime", "0");
                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                }

                output.Position = 0;
                map.Archive.XML = MakeCompressedData(output);
            }

            using (var output = File.Create(outputPath))
            {
                map.Serialize(output);
            }
        }
Пример #20
0
        private static bool GetEntryName(Stream input,
                                         BigFile fat,
                                         Big.Entry entry,
                                         ProjectData.HashList <uint> hashes,
                                         bool extractUnknowns,
                                         bool onlyUnknowns,
                                         out string entryName)
        {
            entryName = hashes[entry.NameHash];

            if (entryName == null)
            {
                if (extractUnknowns == false)
                {
                    return(false);
                }

                string type;
                string extension;
                {
                    var guess = new byte[64];
                    int read  = 0;

                    if (entry.CompressionScheme == Big.CompressionScheme.None)
                    {
                        if (entry.CompressedSize > 0)
                        {
                            input.Seek(entry.Offset, SeekOrigin.Begin);
                            read = input.Read(guess, 0, (int)Math.Min(entry.CompressedSize, guess.Length));
                        }
                    }
                    else
                    {
                        using (var temp = new MemoryStream())
                        {
                            EntryDecompression.Decompress(entry, input, temp);
                            temp.Position = 0;
                            read          = temp.Read(guess, 0, (int)Math.Min(temp.Length, guess.Length));
                        }
                    }

                    var tuple = FileDetection.Detect(guess, Math.Min(guess.Length, read));
                    type      = tuple != null ? tuple.Item1 : "unknown";
                    extension = tuple != null ? tuple.Item2 : null;
                }

                entryName = entry.NameHash.ToString("X8");

                if (string.IsNullOrEmpty(extension) == false)
                {
                    entryName = Path.ChangeExtension(entryName, "." + extension);
                }

                if (string.IsNullOrEmpty(type) == false)
                {
                    entryName = Path.Combine(type, entryName);
                }

                entryName = Path.Combine("__UNKNOWN", entryName);
            }
            else
            {
                if (onlyUnknowns == true)
                {
                    return(false);
                }

                entryName = FilterEntryName(entryName);
            }

            return(true);
        }
Пример #21
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)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            var manager = Manager.Load(currentProject);

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

            var             project     = manager.ActiveProject;
            var             version     = -1;
            HashList <uint> knownHashes = 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 .fat archives in game directory...");
            var fatPaths = new List <string>();

            fatPaths.AddRange(Directory.GetFiles(installPath, "*.fat", SearchOption.AllDirectories));

            var outputPaths = new List <string>();

            var breakdown = new Breakdown();
            var tracking  = new Tracking();

            Console.WriteLine("Processing...");
            for (int i = 0; i < fatPaths.Count; i++)
            {
                var fatPath = fatPaths[i];

                var outputPath = GetListPath(installPath, fatPath);
                if (outputPath == null)
                {
                    throw new InvalidOperationException();
                }

                Console.WriteLine("Found file: " + outputPath);
                outputPath = Path.Combine(listsPath, outputPath);

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

                outputPaths.Add(outputPath);

                if (File.Exists(fatPath + ".bak"))
                {
                    fatPath += ".bak";
                }

                var fat = new BigFile();
                using (var input = File.OpenRead(fatPath))
                {
                    fat.Deserialize(input);
                }

                if (version == -1)
                {
                    version     = fat.Version;
                    knownHashes = manager.LoadListsFileNames(fat.Version);
                }
                else if (version != fat.Version)
                {
                    throw new InvalidOperationException();
                }

                if (knownHashes == null)
                {
                    throw new InvalidOperationException();
                }

                HandleEntries(fat.Entries.Select(e => e.NameHash).Distinct(),
                              knownHashes,
                              tracking,
                              breakdown,
                              outputPath);
            }

            using (var output = new StreamWriter(Path.Combine(Path.Combine(listsPath, "files"), "status.txt")))
            {
                output.WriteLine("{0}",
                                 new Breakdown()
                {
                    Known = tracking.Names.Distinct().Count(),
                    Total = tracking.Hashes.Distinct().Count(),
                });
            }
        }
Пример #22
0
        private static void Main(string[] args)
        {
            bool showHelp = false;
            bool verbose  = false;
            bool compress = false;

            int packageVersion = 9;

            Big.Platform packagePlatform = Big.Platform.PC;

            var options = new OptionSet()
            {
                { "v|verbose", "be verbose", v => verbose = v != null },
                { "c|compress", "compress data with LZO1x", v => compress = v != null },
                { "pv|package-version", "package version (default 9)", v => packageVersion = ParsePackageVersion(v) },
                { "pp|package-platform", "package platform (default PC)", v => packagePlatform = ParsePackagePlatform(v) },
                { "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]+ output_fat input_directory+", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Pack files from input directories into a Big File (FAT/DAT pair).");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            var    inputPaths = new List <string>();
            string fatPath, datPath;

            if (extras.Count == 1)
            {
                inputPaths.Add(extras[0]);
                fatPath = Path.ChangeExtension(extras[0], ".fat");
                datPath = Path.ChangeExtension(extras[0], ".dat");
            }
            else
            {
                fatPath = extras[0];

                if (Path.GetExtension(fatPath) != ".fat")
                {
                    datPath = fatPath;
                    fatPath = Path.ChangeExtension(datPath, ".fat");
                }
                else
                {
                    datPath = Path.ChangeExtension(fatPath, ".dat");
                }

                inputPaths.AddRange(extras.Skip(1));
            }

            var pendingEntries = new SortedDictionary <ulong, PendingEntry>();

            if (verbose == true)
            {
                Console.WriteLine("Finding files...");
            }

            foreach (var relativePath in inputPaths)
            {
                string inputPath = Path.GetFullPath(relativePath);

                if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture)) == true)
                {
                    inputPath = inputPath.Substring(0, inputPath.Length - 1);
                }

                foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories))
                {
                    PendingEntry pendingEntry;

                    string fullPath = Path.GetFullPath(path);
                    string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant();

                    pendingEntry.FullPath = fullPath;
                    pendingEntry.PartPath = partPath;

                    var pieces = partPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
                    int index  = 0;

                    if (index >= pieces.Length)
                    {
                        continue;
                    }

                    if (pieces[index].ToUpperInvariant() == "__SUBFAT")
                    {
                        Console.WriteLine("Sorry, packing of subfats is not currently implemented.");
                        return;
                    }

                    if (index >= pieces.Length)
                    {
                        continue;
                    }

                    if (pieces[index].ToUpperInvariant() == "__UNKNOWN")
                    {
                        var partName = Path.GetFileNameWithoutExtension(partPath);

                        if (string.IsNullOrEmpty(partName) == true)
                        {
                            continue;
                        }

                        if (partName.Length > 16)
                        {
                            partName = partName.Substring(0, 16);
                        }

                        pendingEntry.Name     = null;
                        pendingEntry.NameHash = ulong.Parse(partName, NumberStyles.AllowHexSpecifier);
                    }
                    else
                    {
                        pendingEntry.Name     = string.Join("\\", pieces.Skip(index).ToArray()).ToLowerInvariant();
                        pendingEntry.NameHash = CRC64.Hash(pendingEntry.Name);
                    }

                    if (pendingEntries.ContainsKey(pendingEntry.NameHash) == true)
                    {
                        Console.WriteLine("Ignoring duplicate of {0:X}: {1}", pendingEntry.NameHash, partPath);

                        if (verbose == true)
                        {
                            Console.WriteLine("  Previously added from: {0}",
                                              pendingEntries[pendingEntry.NameHash].PartPath);
                        }

                        continue;
                    }

                    pendingEntries[pendingEntry.NameHash] = pendingEntry;
                }
            }

            var fat = new BigFile
            {
                Version  = packageVersion,
                Platform = packagePlatform
            };

            // reasonable default?
            // need to figure out what this value actually does
            if (packagePlatform == Big.Platform.PC)
            {
                fat.Unknown74 = 3;
            }
            else if (packagePlatform == Big.Platform.PS3 ||
                     packagePlatform == Big.Platform.X360)
            {
                fat.Unknown74 = 4;
            }
            else
            {
                throw new InvalidOperationException();
            }

            using (var output = File.Create(datPath))
            {
                long current = 0;
                long total   = pendingEntries.Count;
                var  padding = total.ToString(CultureInfo.InvariantCulture).Length;

                foreach (var pendingEntry in pendingEntries.Select(kv => kv.Value))
                {
                    current++;

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

                    var entry = new Big.Entry();
                    entry.NameHash = pendingEntry.NameHash;
                    entry.Offset   = output.Position;

                    using (var input = File.OpenRead(pendingEntry.FullPath))
                    {
                        EntryCompression.Compress(fat.Platform, ref entry, input, compress, output);
                        output.Seek(output.Position.Align(16), SeekOrigin.Begin);
                    }

                    fat.Entries.Add(entry);
                }
            }

            using (var output = File.Create(fatPath))
            {
                fat.Serialize(output);
            }
        }
Пример #23
0
        private static bool UnpackFileFromBig(string fatPath, string fileName, string outputPath)
        {
            var datPath = Path.ChangeExtension(fatPath, ".dat");

            if (File.Exists(fatPath) == false ||
                File.Exists(datPath) == false)
            {
                return(false);
            }

            var big = new BigFile();

            using (var input = File.OpenRead(fatPath))
            {
                big.Deserialize(input);
            }

            var entries = big.Entries.Where(e => e.NameHash == fileName.HashFileNameCRC32());

            if (entries.Count() == 0)
            {
                return(false);
            }

            var entry = entries.First();

            using (var input = File.OpenRead(datPath))
            {
                using (var output = File.Create(outputPath))
                {
                    if (entry.CompressionScheme == Big.CompressionScheme.None)
                    {
                        if (entry.CompressedSize > 0)
                        {
                            input.Seek(entry.Offset, SeekOrigin.Begin);
                            output.WriteFromStream(input, entry.CompressedSize);
                        }
                    }
                    else if (entry.CompressionScheme == Big.CompressionScheme.LZO1x)
                    {
                        if (entry.UncompressedSize > 0)
                        {
                            input.Seek(entry.Offset, SeekOrigin.Begin);

                            var compressedData = new byte[entry.CompressedSize];
                            if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length)
                            {
                                throw new EndOfStreamException();
                            }

                            var uncompressedData = new byte[entry.UncompressedSize];
                            int uncompressedSize = (int)entry.UncompressedSize;

                            var result = MiniLZO.LZO.DecompressSafe(
                                compressedData,
                                0,
                                (int)entry.CompressedSize,
                                uncompressedData,
                                0,
                                ref uncompressedSize);
                            if (result != MiniLZO.ErrorCode.Success)
                            {
                                throw new InvalidOperationException("decompression error: " + result.ToString());
                            }
                            else if (uncompressedSize != entry.UncompressedSize)
                            {
                                throw new InvalidOperationException("did not decompress correct amount of data");
                            }

                            output.Write(uncompressedData, 0, uncompressedData.Length);
                        }
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                }
            }

            return(true);
        }
Пример #24
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 = Manager.Load(currentProject);

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

            var project = manager.ActiveProject;
            var version = -1;
            HashList <ulong> knownHashes  = null;
            HashList <ulong> subFatHashes = 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 fatPaths = new List <string>();

            fatPaths.AddRange(Directory.GetFiles(installPath, "*.fat", SearchOption.AllDirectories));

            var outputPaths = new List <string>();

            var breakdown = new Breakdown();
            var tracking  = new Tracking();

            Console.WriteLine("Processing...");
            for (int i = 0; i < fatPaths.Count; i++)
            {
                var fatPath = fatPaths[i];
                var datPath = Path.ChangeExtension(fatPath, ".dat");

                var outputPath = GetListPath(installPath, fatPath);
                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);

                if (File.Exists(fatPath + ".bak") == true)
                {
                    fatPath += ".bak";
                    datPath += ".bak";
                }

                var fat = new BigFile();
                using (var input = File.OpenRead(fatPath))
                {
                    fat.Deserialize(input);
                }

                if (version == -1)
                {
                    version      = fat.Version;
                    knownHashes  = manager.LoadListsFileNames(fat.Version);
                    subFatHashes = manager.LoadListsSubFatNames(fat.Version);
                }
                else if (version != fat.Version)
                {
                    throw new InvalidOperationException();
                }

                if (knownHashes == null ||
                    subFatHashes == null)
                {
                    throw new InvalidOperationException();
                }

                HandleEntries(fat.Entries.Select(e => e.NameHash).Distinct(),
                              knownHashes,
                              tracking,
                              breakdown,
                              outputPath);

                using (var input = File.OpenRead(datPath))
                {
                    foreach (var headerEntry in fat.Entries.Where(e => subFatHashes.Contains(e.NameHash) == true))
                    {
                        var subFat = new SubFatFile();
                        using (var temp = new MemoryStream())
                        {
                            Big.EntryDecompression.Decompress(headerEntry, input, temp);
                            temp.Position = 0;
                            subFat.Deserialize(temp, fat);
                        }

                        var matchingSubFats = fat.SubFats
                                              .Where(sf => subFat.Entries.SequenceEqual(sf.Entries))
                                              .ToArray();

                        if (matchingSubFats.Length == 0)
                        {
                            continue;
                        }

                        if (matchingSubFats.Length > 1)
                        {
                            throw new InvalidOperationException();
                        }

                        var subfatPath = GetListPath(installPath,
                                                     fatPath,
                                                     FilterEntryName(subFatHashes[headerEntry.NameHash]));
                        if (subfatPath == null)
                        {
                            throw new InvalidOperationException();
                        }

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

                        HandleEntries(subFat.Entries.Select(e => e.NameHash),
                                      knownHashes,
                                      tracking,
                                      breakdown,
                                      subfatPath);
                    }
                }
            }

            using (var output = new StreamWriter(Path.Combine(Path.Combine(listsPath, "files"), "status.txt")))
            {
                output.WriteLine("{0}",
                                 new Breakdown()
                {
                    Known = tracking.Names.Distinct().Count(),
                    Total = tracking.Hashes.Distinct().Count(),
                });
            }
        }
Пример #25
0
        public static void Main(string[] args)
        {
            bool showHelp        = false;
            bool extractUnknowns = true;
            bool noArt           = true;
            bool overwriteFiles  = false;
            bool verbose         = false;

            var options = new OptionSet()
            {
                {
                    "o|overwrite",
                    "overwrite existing files",
                    v => overwriteFiles = v != null
                },
                {
                    "na|no-art",
                    "don't extract art files (textures, models, etc)",
                    v => noArt = v != null
                },
                {
                    "nu|no-unknowns",
                    "don't extract unknown files",
                    v => extractUnknowns = v == null
                },
                {
                    "v|verbose",
                    "be verbose",
                    v => verbose = 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_fat [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            if (Path.GetExtension(fatPath) == ".dat")
            {
                datPath = fatPath;
                fatPath = Path.ChangeExtension(fatPath, ".fat");
            }
            else
            {
                datPath = Path.ChangeExtension(fatPath, ".dat");
            }

            var manager = ProjectData.Manager.Load();

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

            var hashes = manager.LoadLists(
                "*.filelist",
                s => s.HashFileNameCRC32(),
                s => s.ToLowerInvariant());

            var big = new BigFile();

            using (var input = File.OpenRead(fatPath))
            {
                big.Deserialize(input);
            }

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

                foreach (var entry in big.Entries)
                {
                    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;

                            if (entry.CompressionScheme == CompressionScheme.None)
                            {
                                if (entry.CompressedSize > 0)
                                {
                                    input.Seek(entry.Offset, SeekOrigin.Begin);
                                    read = input.Read(guess, 0, (int)Math.Min(
                                                          entry.CompressedSize, guess.Length));
                                }
                            }
                            else if (entry.CompressionScheme == CompressionScheme.LZO1x)
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);

                                var compressedData = new byte[entry.CompressedSize];
                                if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length)
                                {
                                    throw new EndOfStreamException();
                                }

                                var  uncompressedData = new byte[entry.UncompressedSize];
                                uint uncompressedSize = entry.UncompressedSize;

                                var result = LZO1x.Decompress(
                                    compressedData,
                                    entry.CompressedSize,
                                    uncompressedData,
                                    ref uncompressedSize);
                                if (result != 0)
                                {
                                    throw new InvalidOperationException("decompression error: " + result.ToString());
                                }
                                else if (uncompressedSize != entry.UncompressedSize)
                                {
                                    throw new InvalidOperationException("did not decompress correct amount of data");
                                }

                                Array.Copy(uncompressedData, 0, guess, 0, Math.Min(guess.Length, uncompressedData.Length));
                                read = uncompressedData.Length;
                            }
                            else
                            {
                                throw new NotSupportedException();
                            }

                            extension = FileExtensions.Detect(guess, Math.Min(guess.Length, read));
                        }

                        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 (noArt == true)
                    {
                        var ext = Path.GetExtension(name);
                        if (ext == ".xbt" ||
                            ext == ".xbg" ||
                            ext == ".xbm" ||
                            ext == ".spk" ||
                            ext == ".mab" ||
                            ext == ".lfe" ||
                            ext == ".lfa" ||
                            ext == ".rtx" ||
                            ext == ".apm")
                        {
                            continue;
                        }
                    }

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

                    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.CompressionScheme == CompressionScheme.None)
                        {
                            if (entry.CompressedSize > 0)
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);
                                output.WriteFromStream(input, entry.CompressedSize);
                            }
                        }
                        else if (entry.CompressionScheme == CompressionScheme.LZO1x)
                        {
                            if (entry.UncompressedSize > 0)
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);

                                var compressedData = new byte[entry.CompressedSize];
                                if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length)
                                {
                                    throw new EndOfStreamException();
                                }

                                var  uncompressedData = new byte[entry.UncompressedSize];
                                uint uncompressedSize = entry.UncompressedSize;

                                var result = LZO1x.Decompress(
                                    compressedData,
                                    entry.CompressedSize,
                                    uncompressedData,
                                    ref uncompressedSize);
                                if (result != 0)
                                {
                                    throw new InvalidOperationException("decompression error: " + result.ToString());
                                }
                                else if (uncompressedSize != entry.UncompressedSize)
                                {
                                    throw new InvalidOperationException("did not decompress correct amount of data");
                                }

                                output.Write(uncompressedData, 0, uncompressedData.Length);
                            }
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                    }
                }
            }
        }
Пример #26
0
        public static void Main(string[] args)
        {
            bool   showHelp        = false;
            bool   extractUnknowns = true;
            bool   onlyUnknowns    = false;
            bool   extractFiles    = true;
            string filterPattern   = null;
            bool   overwriteFiles  = false;
            bool   verbose         = false;

            var options = new OptionSet()
            {
                { "o|overwrite", "overwrite existing files", v => overwriteFiles = v != null },
                { "nf|no-files", "don't extract files", v => extractFiles = v == null },
                { "nu|no-unknowns", "don't extract unknown files", v => extractUnknowns = v == null },
                { "ou|only-unknowns", "only extract unknown files", v => onlyUnknowns = 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 },
            };

            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_fat [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Unpack files from a Big File (FAT/DAT pair).");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            Regex filter = null;

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

            if (Path.GetExtension(fatPath) == ".dat")
            {
                datPath = fatPath;
                fatPath = Path.ChangeExtension(fatPath, ".fat");
            }
            else
            {
                datPath = Path.ChangeExtension(fatPath, ".dat");
            }

            if (verbose == true)
            {
                Console.WriteLine("Loading project...");
            }

            var manager = ProjectData.Manager.Load();

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

            if (verbose == true)
            {
                Console.WriteLine("Reading FAT...");
            }

            BigFile fat;

            using (var input = File.OpenRead(fatPath))
            {
                fat = new BigFile();
                fat.Deserialize(input);
            }

            var hashes = manager.LoadListsFileNames(fat.Version);

            using (var input = File.OpenRead(datPath))
            {
                if (extractFiles == true)
                {
                    Big.Entry[] entries = fat.Entries.OrderBy(e => e.Offset).ToArray();

                    if (entries.Length > 0)
                    {
                        if (verbose == true)
                        {
                            Console.WriteLine("Unpacking files...");
                        }

                        long current = 0;
                        long total   = entries.Length;
                        var  padding = total.ToString(CultureInfo.InvariantCulture).Length;

                        var duplicates = new Dictionary <ulong, int>();

                        foreach (var entry in entries)
                        {
                            current++;

                            string entryName;
                            if (GetEntryName(input,
                                             fat,
                                             entry,
                                             hashes,
                                             extractUnknowns,
                                             onlyUnknowns,
                                             out entryName) == false)
                            {
                                continue;
                            }

                            if (duplicates.ContainsKey(entry.NameHash) == true)
                            {
                                var number = duplicates[entry.NameHash]++;
                                var e      = Path.GetExtension(entryName);
                                var nn     =
                                    Path.ChangeExtension(
                                        Path.ChangeExtension(entryName, null) + "__DUPLICATE_" +
                                        number.ToString(CultureInfo.InvariantCulture),
                                        e);
                                entryName = Path.Combine("__DUPLICATE", nn);
                            }
                            else
                            {
                                duplicates[entry.NameHash] = 0;
                            }

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

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

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

                            input.Seek(entry.Offset, SeekOrigin.Begin);

                            var entryParent = Path.GetDirectoryName(entryPath);
                            if (string.IsNullOrEmpty(entryParent) == false)
                            {
                                Directory.CreateDirectory(entryParent);
                            }

                            using (var output = File.Create(entryPath))
                            {
                                EntryDecompression.Decompress(entry, input, output);
                            }
                        }
                    }
                }
            }
        }
Пример #27
0
 public BigFileFileLoader(BigFile _bigFile)
 {
     bigFile = _bigFile;
 }
Пример #28
0
        public static void Main(string[] args)
        {
            bool showHelp = false;

            var options = new OptionSet()
            {
                {
                    "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 != 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 = ProjectData.Manager.Load();

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

            var project = manager.ActiveProject;
            var hashes  = project.LoadLists(
                "*.filelist",
                s => s.HashFileNameCRC32(),
                s => s.ToLowerInvariant());

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

            if (installPath == null)
            {
                Console.WriteLine("Could not detect install path.");
                return;
            }
            else 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, "*.fat", SearchOption.AllDirectories));

            var outputPaths = new List <string>();

            Console.WriteLine("Processing...");
            foreach (var inputPath in inputPaths)
            {
                // f**k you, colliding fat *g*
                if (Path.GetFileNameWithoutExtension(inputPath).ToLowerInvariant()
                    == "shadersobj")
                {
                    continue;
                }

                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 big = new BigFile();

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

                var localBreakdown = new Breakdown();

                var names = new List <string>();
                foreach (var entry in big.Entries)
                {
                    if (entry.UncompressedSize == 4680308)
                    {
                    }

                    var name = hashes[entry.NameHash];
                    if (name != null)
                    {
                        if (names.Contains(name) == false)
                        {
                            names.Add(name);
                            localBreakdown.Known++;
                        }
                    }

                    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);
                    }
                }
            }
        }
Пример #29
0
        public static void Main(string[] args)
        {
            bool showHelp       = false;
            bool overwriteFiles = false;
            bool verbose        = false;

            var options = new OptionSet()
            {
                {
                    "v|verbose",
                    "be verbose",
                    v => verbose = 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_fat [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            var manager = ProjectData.Manager.Load();

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

            var hashes = manager.LoadLists(
                "*.filelist",
                s => s.HashFileNameCRC32(),
                s => s.ToLowerInvariant());

            var map = new MapFile();

            using (var input = File.OpenRead(inputPath))
            {
                map.Deserialize(input);
            }

            Directory.CreateDirectory(outputPath);
            using (var output = File.Create(Path.Combine(outputPath, "map.xml")))
            {
                var settings = new XmlWriterSettings();
                settings.Indent = true;

                using (var writer = XmlWriter.Create(output, settings))
                {
                    writer.WriteStartDocument();
                    writer.WriteStartElement("map");

                    writer.WriteStartElement("info");
                    writer.WriteElementString("name", map.Info.Name);
                    writer.WriteElementString("creator", map.Info.Creator);
                    writer.WriteElementString("author", map.Info.Author);
                    writer.WriteElementString("size", map.Info.Size.ToString());
                    writer.WriteElementString("players", map.Info.Players.ToString());
                    writer.WriteElementString("unknown2", map.Info.Unknown2.ToString());
                    writer.WriteElementString("unknown3", map.Info.Unknown3.ToString());
                    writer.WriteElementString("unknown4", map.Info.Unknown4.ToString());
                    writer.WriteElementString("unknown5", map.Info.Unknown5.ToString());
                    writer.WriteElementString("unknown7", map.Info.Unknown7.ToString());
                    writer.WriteElementString("unknown10", map.Info.Unknown10.ToString());
                    writer.WriteStartElement("unknown11");
                    writer.WriteBinHex(map.Info.Unknown11, 0, map.Info.Unknown11.Length);
                    writer.WriteEndElement();
                    writer.WriteStartElement("unknown12");
                    writer.WriteBinHex(map.Info.Unknown12, 0, map.Info.Unknown12.Length);
                    writer.WriteEndElement();
                    writer.WriteElementString("unknown15", map.Info.Unknown15.ToString());
                    writer.WriteEndElement();

                    writer.WriteStartElement("snapshot");
                    writer.WriteElementString("width", map.Snapshot.Width.ToString());
                    writer.WriteElementString("height", map.Snapshot.Height.ToString());
                    writer.WriteElementString("bpp", map.Snapshot.BytesPerPixel.ToString());
                    writer.WriteElementString("unknown4", map.Snapshot.Unknown4.ToString());
                    writer.WriteEndElement();

                    writer.WriteStartElement("data");
                    writer.WriteElementString("unknown1", map.Data.Unknown1);
                    writer.WriteEndElement();

                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                }
            }

            using (var input = map.Archive.XML.Unpack())
            {
                using (var output = File.Create(Path.Combine(outputPath, "archive.xml")))
                {
                    output.WriteFromStream(input, input.Length);
                }
            }

            using (var output = File.Create(Path.Combine(outputPath, "snapshot.bin")))
            {
                output.Write(map.Snapshot.Data, 0, map.Snapshot.Data.Length);
            }

            var big = new BigFile();

            using (var input = map.Archive.FAT.Unpack())
            {
                big.Deserialize(input);
            }

            var dataPath = Path.Combine(outputPath, "archive");

            Directory.CreateDirectory(dataPath);

            using (var input = map.Archive.DAT.Unpack())
            {
                long current = 0;
                long total   = big.Entries.Count;

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

                    string name = hashes[entry.NameHash];
                    if (name == null)
                    {
                        string extension;

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

                            if (entry.CompressionScheme == CompressionScheme.None)
                            {
                                if (entry.CompressedSize > 0)
                                {
                                    input.Seek(entry.Offset, SeekOrigin.Begin);
                                    read = input.Read(guess, 0, (int)Math.Min(
                                                          entry.CompressedSize, guess.Length));
                                }
                            }
                            else if (entry.CompressionScheme == CompressionScheme.LZO1x)
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);

                                var compressedData = new byte[entry.CompressedSize];
                                if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length)
                                {
                                    throw new EndOfStreamException();
                                }

                                var  uncompressedData = new byte[entry.UncompressedSize];
                                uint uncompressedSize = entry.UncompressedSize;

                                var result = LZO1x.Decompress(
                                    compressedData,
                                    entry.CompressedSize,
                                    uncompressedData,
                                    ref uncompressedSize);
                                if (result != 0)
                                {
                                    throw new InvalidOperationException("decompression error: " + result.ToString());
                                }
                                else if (uncompressedSize != entry.UncompressedSize)
                                {
                                    throw new InvalidOperationException("did not decompress correct amount of data");
                                }

                                Array.Copy(uncompressedData, 0, guess, 0, Math.Min(guess.Length, uncompressedData.Length));
                                read = uncompressedData.Length;
                            }
                            else
                            {
                                throw new NotSupportedException();
                            }

                            extension = FileExtensions.Detect(guess, Math.Min(guess.Length, read));
                        }

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

                    var entryPath = Path.Combine(dataPath, name);
                    Directory.CreateDirectory(Path.GetDirectoryName(entryPath));

                    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.CompressionScheme == CompressionScheme.None)
                        {
                            if (entry.CompressedSize > 0)
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);
                                output.WriteFromStream(input, entry.CompressedSize);
                            }
                        }
                        else if (entry.CompressionScheme == CompressionScheme.LZO1x)
                        {
                            if (entry.UncompressedSize > 0)
                            {
                                input.Seek(entry.Offset, SeekOrigin.Begin);

                                var compressedData = new byte[entry.CompressedSize];
                                if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length)
                                {
                                    throw new EndOfStreamException();
                                }

                                var  uncompressedData = new byte[entry.UncompressedSize];
                                uint uncompressedSize = entry.UncompressedSize;

                                var result = LZO1x.Decompress(
                                    compressedData,
                                    entry.CompressedSize,
                                    uncompressedData,
                                    ref uncompressedSize);
                                if (result != 0)
                                {
                                    throw new InvalidOperationException("decompression error: " + result.ToString());
                                }
                                else if (uncompressedSize != entry.UncompressedSize)
                                {
                                    throw new InvalidOperationException("did not decompress correct amount of data");
                                }

                                output.Write(uncompressedData, 0, uncompressedData.Length);
                            }
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                    }
                }
            }
        }
Пример #30
0
        public static void Main(string[] args)
        {
            bool showHelp = false;
            bool verbose  = false;

            OptionSet options = new OptionSet()
            {
                {
                    "v|verbose",
                    "be verbose (list files)",
                    v => verbose = 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]+ output_big input_directory+", GetExecutableName());
                Console.WriteLine("Pack files from input directories into a Big File.");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            var    inputPaths = new List <string>();
            string outputPath;

            if (extras.Count == 1)
            {
                inputPaths.Add(extras[0]);
                outputPath = Path.ChangeExtension(extras[0], ".viv");
            }
            else
            {
                outputPath = extras[0];
                inputPaths.AddRange(extras.Skip(1));
            }

            var paths = new SortedDictionary <uint, string>();

            if (verbose == true)
            {
                Console.WriteLine("Finding files...");
            }

            foreach (var relPath in inputPaths)
            {
                string inputPath = Path.GetFullPath(relPath);

                if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true)
                {
                    inputPath = inputPath.Substring(0, inputPath.Length - 1);
                }

                foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories))
                {
                    string fullPath = Path.GetFullPath(path);
                    string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant();

                    uint hash = 0xFFFFFFFF;
                    if (partPath.ToUpper().StartsWith("__UNKNOWN") == true)
                    {
                        string partName;

                        partName = Path.GetFileNameWithoutExtension(partPath);
                        if (partName.Length > 8)
                        {
                            partName = partName.Substring(0, 8);
                        }

                        hash = uint.Parse(
                            partName,
                            System.Globalization.NumberStyles.AllowHexSpecifier);
                    }
                    else
                    {
                        hash = partPath.ToLowerInvariant().HashFileName();
                    }

                    if (paths.ContainsKey(hash) == true)
                    {
                        Console.WriteLine("Ignoring {0} duplicate.", partPath);
                        continue;
                    }

                    paths[hash] = fullPath;
                }
            }

            using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                var big = new BigFile();

                if (verbose == true)
                {
                    Console.WriteLine("Adding files...");
                }

                // write a dummy header
                output.Seek(0, SeekOrigin.Begin);
                big.Entries.Clear();
                foreach (var kvp in paths)
                {
                    big.Entries.Add(new BigFile.Entry()
                    {
                        Name   = 0,
                        Offset = 0,
                        Size   = 0,
                    });
                }
                big.Serialize(output);

                output.Seek(output.Position.Align(2048), SeekOrigin.Begin);
                long baseOffset = output.Position;

                // write file data
                big.Entries.Clear();

                if (verbose == true)
                {
                    Console.WriteLine("Writing to disk...");
                }

                foreach (var kvp in paths)
                {
                    if (verbose == true)
                    {
                        Console.WriteLine(kvp.Value);
                    }

                    using (var input = File.Open(kvp.Value, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        output.Seek(baseOffset, SeekOrigin.Begin);

                        uint size = (uint)input.Length.Align(2048);

                        big.Entries.Add(new BigFile.Entry()
                        {
                            Name   = kvp.Key,
                            Offset = (uint)output.Position,
                            Size   = size,
                        });

                        output.WriteFromStream(input, input.Length);
                        baseOffset += size;
                    }
                }

                // write filled header
                output.Seek(0, SeekOrigin.Begin);
                big.TotalFileSize = (uint)output.Length;
                big.Serialize(output);
            }
        }