Exemplo n.º 1
0
        public static void Main(string[] args)
        {
            bool showHelp       = false;
            bool overwriteFiles = false;
            bool verbose        = false;

            var options = new OptionSet()
            {
                {
                    "o|overwrite",
                    "overwrite existing files",
                    v => overwriteFiles = 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_dir [output_rcf]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            var inputPaths = new List <string>();

            inputPaths.Add(Path.GetFullPath(extras[0]));

            var outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(extras[0], ".rcf");

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

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

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

                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))
                {
                    string fullPath = Path.GetFullPath(path);
                    string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant();

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

                    paths[partPath] = fullPath;
                }
            }

            using (var output = File.Create(outputPath))
            {
                var cement = new CementFile();
                cement.Endian = Endian.Little;

                cement.Entries.Clear();
                cement.Metadatas.Clear();

                foreach (var kv in paths)
                {
                    var entry = new Cement.Entry();
                    entry.NameHash = kv.Key.HashFileName(0);
                    entry.Offset   = 0;
                    entry.Size     = 0;

                    var metadata = new Cement.Metadata();
                    metadata.TypeHash  = 0;
                    metadata.Alignment = 2048;
                    metadata.Name      = kv.Key;

                    cement.Entries.Add(entry);
                    cement.Metadatas.Add(metadata);
                }

                var preestimatedHeaderSize = cement.EstimateHeaderSize();
                output.Seek(preestimatedHeaderSize, SeekOrigin.Begin);

                cement.Entries.Clear();
                cement.Metadatas.Clear();

                const uint fileAlignment = 2048;

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

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

                    using (var input = File.OpenRead(kvp.Value))
                    {
                        var entry = new Cement.Entry();
                        entry.NameHash = kvp.Key.HashFileName(0);
                        entry.Offset   = (uint)output.Position;
                        entry.Size     = (uint)input.Length;

                        /*var extension = Path.GetExtension(kvp.Key);
                         * if (extension != null &&
                         *  extension.StartsWith(".") == true)
                         * {
                         *  extension = extension.Substring(1);
                         * }*/

                        var metadata = new Cement.Metadata();
                        metadata.TypeHash  = 0;//extension == null ? 0 : extension.HashFileName(0);
                        metadata.Alignment = fileAlignment;
                        metadata.Name      = kvp.Key;

                        cement.Entries.Add(entry);
                        cement.Metadatas.Add(metadata);

                        output.WriteFromStream(input, entry.Size);
                        output.Seek(output.Position.Align(fileAlignment), SeekOrigin.Begin);
                    }
                }

                var estimatedHeaderSize = cement.EstimateHeaderSize();
                if (preestimatedHeaderSize != estimatedHeaderSize)
                {
                    throw new InvalidOperationException();
                }

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

                output.Seek(0, SeekOrigin.Begin);
                cement.Serialize(output);

                if (output.Position != estimatedHeaderSize)
                {
                    throw new InvalidOperationException();
                }
            }
        }
Exemplo n.º 2
0
        public static void Main(string[] args)
        {
            bool showHelp       = false;
            bool unpackRz       = false;
            bool overwriteFiles = false;
            bool verbose        = false;

            var options = new OptionSet()
            {
                {
                    "o|overwrite",
                    "overwrite existing files",
                    v => overwriteFiles = v != null
                },
                {
                    "rz",
                    "unpack compressed data (*.rz)",
                    v => unpackRz = 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_rcf [output_dir]", GetExecutableName());
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

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

            using (var input = File.OpenRead(inputPath))
            {
                var cement = new CementFile();
                cement.Deserialize(input);

                long current = 0;
                long total   = cement.Entries.Count;
                var  padding = total.ToString(CultureInfo.InvariantCulture).Length;

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

                    var metadata = cement.GetMetadata(entry.NameHash);

                    bool   unpacking = false;
                    string entryName;

                    if (metadata == null)
                    {
                        entryName = Path.Combine("__UNKNOWN", entry.NameHash.ToString("X8"));
                    }
                    else
                    {
                        entryName = metadata.Name;
                        if (entryName.StartsWith("\\") == true)
                        {
                            entryName = entryName.Substring(1);
                        }

                        if (Path.GetExtension(entryName) == ".rz" && unpackRz == true)
                        {
                            unpacking = true;
                            entryName = Path.ChangeExtension(entryName, null);
                        }
                    }

                    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 entryParentPath = Path.GetDirectoryName(entryPath);
                    if (string.IsNullOrEmpty(entryParentPath) == false)
                    {
                        Directory.CreateDirectory(entryParentPath);
                    }

                    using (var output = File.Create(entryPath))
                    {
                        if (unpacking == false)
                        {
                            output.WriteFromStream(input, entry.Size);
                        }
                        else
                        {
                            var magic = input.ReadValueU32(Endian.Big);
                            if (magic != 0x525A0000) // 'RZ\0\0'
                            {
                                output.WriteFromStream(input, entry.Size);
                            }
                            else
                            {
                                var unknown1         = input.ReadValueU32(Endian.Little);
                                var uncompressedSize = input.ReadValueS32(Endian.Little);
                                var unknown2         = input.ReadValueU32(Endian.Little);

                                if (unknown1 != 0 || unknown2 != 0)
                                {
                                    throw new FormatException();
                                }

                                var zlib = new InflaterInputStream(input);
                                output.WriteFromStream(zlib, uncompressedSize);
                            }
                        }
                    }
                }
            }
        }