예제 #1
0
        private void OnOpen(object sender, EventArgs e)
        {
            if (this.openDialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }

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

            ERF archive;

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

            this.modeStatusLabel.Text =
                string.Format("Compression: {0}, Encryption: {1}",
                              archive.Compression, archive.Encryption);

            this.BuildFileTree();
        }
예제 #2
0
        public static void Main(string[] args)
        {
            bool showHelp       = false;
            bool verbose        = false;
            bool stripFileNames = false;

            OptionSet options = new OptionSet()
            {
                {
                    "v|verbose",
                    "be verbose",
                    v => verbose = v != null
                },
                {
                    "s|strip",
                    "strip file names",
                    v => stripFileNames = 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_erf 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 outputPath;

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

            var paths  = new SortedDictionary <ulong, string>();
            var lookup = new Dictionary <ulong, 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))
                {
                    bool   hasName;
                    string fullPath = Path.GetFullPath(path);
                    string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant();

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

                        hash = ulong.Parse(
                            partName,
                            System.Globalization.NumberStyles.AllowHexSpecifier);
                        hasName = false;
                    }
                    else
                    {
                        hash    = partPath.ToLowerInvariant().HashFNV64();
                        hasName = true;
                    }

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

                    paths[hash] = fullPath;

                    if (hasName == false)
                    {
                        partPath = null;
                    }
                    else if (stripFileNames == true &&
                             Path.GetExtension(fullPath) != ".gda")
                    {
                        partPath = null;
                    }

                    lookup[hash] = partPath;
                }
            }

            using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                var erf = new ERF();
                erf.Version     = EncapsulatedResourceFile.FileVersion.V3_0;
                erf.Compression = ERF.CompressionScheme.None;
                erf.Encryption  = ERF.EncryptionScheme.None;
                erf.ContentId   = 0;

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

                long headerSize = ERF.CalculateHeaderSize(
                    erf.Version,
                    lookup.Values.ToArray(),
                    paths.Count);
                long baseOffset = headerSize.Align(16);

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

                erf.Entries.Clear();
                output.Seek(baseOffset, SeekOrigin.Begin);
                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))
                    {
                        var entry = new ERF.Entry()
                        {
                            Name             = lookup[kvp.Key],
                            NameHash         = kvp.Key,
                            TypeHash         = 0,
                            Offset           = output.Position,
                            CompressedSize   = (uint)input.Length,
                            UncompressedSize = (uint)input.Length,
                        };

                        if (entry.Name != null)
                        {
                            entry.CalculateHashes();
                        }
                        else
                        {
                            var extension = Path.GetExtension(kvp.Value);
                            entry.TypeHash = extension == null
                                                 ? 0
                                                 : extension.Trim('.').HashFNV32();
                        }

                        output.WriteFromStream(input, input.Length);
                        output.Seek(output.Position.Align(16), SeekOrigin.Begin);
                        erf.Entries.Add(entry);
                    }
                }

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

                if (output.Position != headerSize)
                {
                    throw new InvalidOperationException();
                }
            }
        }