Пример #1
0
        public static void Main(string[] args)
        {
            bool showHelp = false;
            bool verbose  = false;

            OptionSet 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]+ [output_dzip] input_dir+", GetExecutableName());
                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], ".dzip");
            }
            else
            {
                outputPath = extras[0];
                inputPaths.AddRange(extras.Skip(1));
            }

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

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

                    paths[partPath] = fullPath;
                }
            }

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

                output.Seek(PackageFile.HeaderSize, SeekOrigin.Begin);

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

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

                    using (var input = File.OpenRead(kvp.Value))
                    {
                        var entry = new Package.Entry();
                        entry.Name             = kvp.Key;
                        entry.TimeStamp        = File.GetLastWriteTime(kvp.Value);
                        entry.UncompressedSize = input.Length;
                        entry.Offset           = output.Position;

                        int blockCount        = (int)((entry.UncompressedSize + 0xFFFF) >> 16); // .Align(0x10000) / 0x10000;
                        var compressedBlocks  = new byte[blockCount][];
                        var compressedSizes   = new int[blockCount];
                        var uncompressedBlock = new byte[0x10000];

                        long left = input.Length;
                        for (int i = 0; i < blockCount; i++)
                        {
                            int uncompressedSize = input.Read(
                                uncompressedBlock, 0,
                                uncompressedBlock.Length);

                            var lzf = new LZF();
                            compressedBlocks[i] = new byte[0x20000];
                            int compressedSize = lzf.Compress(
                                uncompressedBlock,
                                uncompressedSize,
                                compressedBlocks[i],
                                compressedBlocks[i].Length);
                            if (compressedSize == 0)
                            {
                                throw new InvalidOperationException();
                            }
                            compressedSizes[i] = compressedSize;
                        }

                        int offset = blockCount * 4;
                        for (int i = 0; i < blockCount; i++)
                        {
                            output.WriteValueS32(offset);
                            offset += compressedSizes[i];
                        }

                        for (int i = 0; i < blockCount; i++)
                        {
                            output.Write(compressedBlocks[i], 0, compressedSizes[i]);
                        }

                        entry.CompressedSize = offset;
                        pkg.Entries.Add(entry);
                    }
                }

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

                pkg.Serialize(output, output.Length);
            }
        }
Пример #2
0
        public void Deserialize(Stream input, ulong?decryptKey)
        {
            if (input.ReadValueU32() != 0x50495A44) // DZIP
            {
                throw new FormatException("bad magic");
            }

            this.Version = input.ReadValueU32();
            if (this.Version < 2)
            {
                throw new FormatException("unsupported version");
            }

            var entryCount = input.ReadValueU32();

            /*var unknown =*/ input.ReadValueU32();
            var entryTableOffset = input.ReadValueS64();
            var entryTableHash   = input.ReadValueU64();

            input.Seek(entryTableOffset, SeekOrigin.Begin);
            this.Entries.Clear();
            for (uint i = 0; i < entryCount; i++)
            {
                var entry  = new Package.Entry();
                var length = input.ReadValueU16();

                if (decryptKey.HasValue == false)
                {
                    entry.Name = input.ReadString(
                        length, true, Encoding.ASCII);
                }
                else
                {
                    var nameBytes = new byte[length];
                    input.Read(nameBytes, 0, nameBytes.Length);

                    for (int j = 0; j < nameBytes.Length; j++)
                    {
                        nameBytes[j] ^= (byte)(decryptKey >> j % 8);
                        decryptKey   *= 0x00000100000001B3UL;
                    }

                    using (var nameStream = new MemoryStream(nameBytes))
                    {
                        entry.Name = nameStream.ReadString(
                            length, true, Encoding.ASCII);
                    }
                }

                //entry.TimeStamp = input.ReadValueS64();
                entry.TimeStamp = DateTime.FromFileTime(
                    input.ReadValueS64());
                entry.UncompressedSize = input.ReadValueS64();
                entry.Offset           = input.ReadValueS64();
                entry.CompressedSize   = input.ReadValueS64();
                this.Entries.Add(entry);
            }

            if (this.EntriesHash != entryTableHash)
            {
                throw new FormatException("bad entry table hash (wrong cdkey for DLC archives?)");
            }
        }
Пример #3
0
        public static void Main(string[] args)
        {
            bool showHelp = false;
            bool verbose = false;

            OptionSet 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]+ [output_dzip] input_dir+", GetExecutableName());
                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], ".dzip");
            }
            else
            {
                outputPath = extras[0];
                inputPaths.AddRange(extras.Skip(1));
            }

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

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

                    paths[partPath] = fullPath;
                }
            }

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

                output.Seek(PackageFile.HeaderSize, SeekOrigin.Begin);

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

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

                    using (var input = File.OpenRead(kvp.Value))
                    {
                        var entry = new Package.Entry();
                        entry.Name = kvp.Key;
                        entry.TimeStamp = File.GetLastWriteTime(kvp.Value);
                        entry.UncompressedSize = input.Length;
                        entry.Offset = output.Position;

                        int blockCount = (int)((entry.UncompressedSize + 0xFFFF) >> 16); // .Align(0x10000) / 0x10000;
                        var compressedBlocks = new byte[blockCount][];
                        var compressedSizes = new int[blockCount];
                        var uncompressedBlock = new byte[0x10000];

                        long left = input.Length;
                        for (int i = 0; i < blockCount; i++)
                        {
                            int uncompressedSize = input.Read(
                                uncompressedBlock, 0,
                                uncompressedBlock.Length);
                            
                            var lzf = new LZF();
                            compressedBlocks[i] = new byte[0x20000];
                            int compressedSize = lzf.Compress(
                                uncompressedBlock,
                                uncompressedSize,
                                compressedBlocks[i],
                                compressedBlocks[i].Length);
                            if (compressedSize == 0)
                            {
                                throw new InvalidOperationException();
                            }
                            compressedSizes[i] = compressedSize;
                        }

                        int offset = blockCount * 4;
                        for (int i = 0; i < blockCount; i++)
                        {
                            output.WriteValueS32(offset);
                            offset += compressedSizes[i];
                        }

                        for (int i = 0; i < blockCount; i++)
                        {
                            output.Write(compressedBlocks[i], 0, compressedSizes[i]);
                        }

                        entry.CompressedSize = offset;
                        pkg.Entries.Add(entry);
                    }
                }

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

                pkg.Serialize(output, output.Length);
            }
        }