コード例 #1
0
        public static void Main(string[] args)
        {
            ushort wadVersion         = 0x202;
            bool   compressFiles      = false;
            bool   uppercaseFileNames = false;
            bool   verbose            = false;
            bool   showHelp           = false;
            string headerFileName     = null;

            var options = new OptionSet()
            {
                {
                    "c|compress",
                    "overwrite files",
                    v => compressFiles = v != null
                },
                {
                    "u|uppercase",
                    "uppsercase file names",
                    v => uppercaseFileNames = v != null
                },
                {
                    "wh|wad-header=",
                    "specify WAD header file name (default is @header.xml)",
                    v => headerFileName = v
                },
                {
                    "wv|wad-version=",
                    "specify WAD version (default is 0x201)",
                    v =>
                    {
                        if (v != null)
                        {
                            if (v.StartsWith("0x") == false)
                            {
                                wadVersion = ushort.Parse(v);
                            }
                            else
                            {
                                wadVersion = ushort.Parse(v.Substring(2), NumberStyles.AllowHexSpecifier);
                            }
                        }
                    }
                },
                {
                    "v|verbose",
                    "show verbose messages",
                    v => verbose = v != null
                },
                {
                    "h|help",
                    "show this message and exit",
                    v => showHelp = v != null
                },
            };

            List <string> extra;

            try
            {
                extra = 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 (extra.Count < 1 || extra.Count > 2 || showHelp == true)
            {
                Console.WriteLine("Usage: {0} [OPTIONS]+ input_dir [output_wad]", GetExecutableName());
                Console.WriteLine("Pack a Duels of the Planewalkers WAD.");
                Console.WriteLine();
                Console.WriteLine("Options:");
                options.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (wadVersion != 0x201 &&
                wadVersion != 0x202)
            {
                Console.WriteLine("Warning: unexpected WAD version specified.");
            }

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

            var inputPath  = Path.GetFullPath(extra[0]);
            var outputPath = extra.Count > 1 ? extra[1] : Path.ChangeExtension(inputPath, ".wad");

            Wad.ArchiveFlags flags = Wad.ArchiveFlags.None;

            flags |= Wad.ArchiveFlags.Unknown6Observed;
            flags |= Wad.ArchiveFlags.HasDataTypes;

            if (compressFiles == true)
            {
                flags |= Wad.ArchiveFlags.HasCompressedFiles;
            }

            var wad = new WadFile()
            {
                Version = wadVersion,
                Flags   = flags,
            };

            bool   usingDefaultHeaderFile;
            string headerPath;

            if (string.IsNullOrWhiteSpace(headerFileName) == true)
            {
                headerPath             = Path.Combine(inputPath, "@header.xml");
                usingDefaultHeaderFile = true;
            }
            else
            {
                headerPath             = headerFileName;
                usingDefaultHeaderFile = false;
                if (Path.IsPathRooted(headerPath) == false)
                {
                    headerPath = Path.Combine(inputPath, headerPath);
                }
            }

            if (wad.Version >= 0x202)
            {
                if (File.Exists(headerPath) == false)
                {
                    Console.WriteLine("Could not find read header file '{0}'!", headerPath);
                    return;
                }

                wad.HeaderXml = File.ReadAllBytes(headerPath);
            }

            Console.WriteLine("Collecting files...");

            foreach (var path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories))
            {
                var fullPath = Path.GetFullPath(path);
                if (usingDefaultHeaderFile == true &&
                    fullPath == headerPath)
                {
                    continue;
                }

                var partPath = fullPath.Substring(inputPath.Length + 1);

                if (uppercaseFileNames == true)
                {
                    partPath = partPath.ToUpperInvariant();
                }

                if (paths.ContainsKey(partPath) == true)
                {
                    // warning?
                    continue;
                }

                paths[partPath] = fullPath;
            }

            var files = new List <MyFileEntry>();

            foreach (var kvp in paths)
            {
                string fileName      = Path.GetFileName(kvp.Key);
                var    directoryName = Path.GetDirectoryName(kvp.Key);
                if (directoryName == null)
                {
                    throw new InvalidOperationException();
                }

                var dir = GetOrCreateDirectory(wad, directoryName);

                var file = new MyFileEntry(dir);

                file.FilePath  = kvp.Value;
                file.Name      = fileName;
                file.Size      = 0;
                file.Unknown0C = 0;

                file.OffsetIndex = wad.DataOffsets.Count;
                file.OffsetCount = 1;
                wad.DataOffsets.Add(0);

                dir.Files.Add(file);
                files.Add(file);
            }

            if (verbose == true)
            {
                Console.WriteLine("Collected {0} files.", files.Count);
            }

            using (var output = File.Create(outputPath))
            {
                Console.WriteLine("Writing stub header...");
                wad.Serialize(output);

                Console.WriteLine("Writing file data...");
                foreach (var entry in files)
                {
                    if (verbose == true)
                    {
                        Console.WriteLine(">> {0}", entry);
                    }

                    wad.DataOffsets[entry.OffsetIndex] = (uint)output.Position;

                    using (var input = File.OpenRead(entry.FilePath))
                    {
                        if (compressFiles == false)
                        {
                            entry.Size = (uint)input.Length;
                            output.WriteFromStream(input, input.Length);
                        }
                        else
                        {
                            using (var temp = new MemoryStream())
                            {
                                var zlib = new DeflaterOutputStream(temp, new Deflater(Deflater.BEST_COMPRESSION));
                                zlib.WriteFromStream(input, input.Length);
                                zlib.Finish();
                                temp.Flush();
                                temp.Position = 0;

                                if (temp.Length < input.Length)
                                {
                                    entry.Size = (uint)(4 + temp.Length);
                                    output.WriteValueU32((uint)input.Length);
                                    output.WriteFromStream(temp, temp.Length);
                                }
                                else
                                {
                                    input.Seek(0, SeekOrigin.Begin);
                                    entry.Size = (uint)(4 + input.Length);
                                    output.WriteValueU32(0xFFFFFFFFu);
                                    output.WriteFromStream(input, input.Length);
                                }
                            }
                        }
                    }
                }

                Console.WriteLine("Writing header...");
                output.Seek(0, SeekOrigin.Begin);
                wad.Serialize(output);

                Console.WriteLine("Done!");
            }
        }