コード例 #1
0
ファイル: Program.cs プロジェクト: gokhan935/Gibbed.Prototype
        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);
                            }
                        }
                    }
                }
            }
        }