private void PackPckg(string inputPath, string outputPath)
        {
            var entries = new List <PathEntry>();
            var pckg    = new PckgFile();

            // Searching for archives...
            var inputPaths = new List <string>();

            inputPaths.AddRange(Directory.GetFiles(inputPath, "*", SearchOption.TopDirectoryOnly));

            foreach (var path in inputPaths)
            {
                string name = Path.GetFileNameWithoutExtension(path);
                ulong  hash = 0;
                if (Helpers.IsHexString(name))
                {
                    hash = Helpers.HexLiteral2Unsigned(name);
                }
                else
                {
                    hash = FileFormats.Hashing.FNV64.Hash(name);
                }

                entries.Add(new PathEntry()
                {
                    NameHash = hash,
                    Offset   = 0,
                    Unk1     = 0,
                    Size     = 0,
                    Size2    = 0,
                    Widgth   = 0,
                    Heigth   = 0,
                    Unk2     = 0,
                    Path     = path,
                });
            }


            uint headerSize  = (uint)PckgFile.EstimateHeaderSize(entries.Count);
            long firstOffset = entries.Count * 32 + headerSize;
            long localOffset = firstOffset;

            Stream data = File.Create(outputPath);

            int percents = 0;
            int current  = 0;
            int total    = entries.Count;

            foreach (var entry in entries)
            {
                current++;

                // verbose
                if (InvokeRequired == true)
                {
                    Invoke((MethodInvoker) delegate
                    {
                        progressBar1.Value = percents;
                        resultLabel.Text   = "Pack \"" + entry.Path + "\"";
                    });
                }

                using (var input = File.OpenRead(entry.Path))
                {
                    var length = (uint)input.Length;

                    data.Seek(localOffset, SeekOrigin.Begin);
                    data.WriteFromStream(input, length);

                    ushort height = 0;
                    ushort width  = 0;
                    input.Seek(0L, SeekOrigin.Begin);
                    if (input.Length >= 16 && input.ReadValueU32() == 542327876)
                    {
                        input.Seek(0x0c, SeekOrigin.Begin);
                        height = input.ReadValueU16();
                        input.Seek(0x10, SeekOrigin.Begin);
                        width = input.ReadValueU16();
                    }

                    entry.Size   = length;
                    entry.Size2  = length;
                    entry.Offset = (uint)localOffset;
                    entry.Widgth = width;
                    entry.Heigth = height;
                    pckg.Entries.Add(entry);

                    localOffset += length;
                }

                percents = ((current + 1) * 100) / total;
            }

            if (data != null)
            {
                data.Close();
            }

            using (var output = File.OpenWrite(outputPath))
            {
                pckg.Serialize(output);
            }

            if (InvokeRequired == true)
            {
                Invoke((MethodInvoker) delegate
                {
                    progressBar1.Value   = 0;
                    resultLabel.Text     = "Done \"" + outputPath + "\"";
                    buttonPack.Enabled   = true;
                    buttonUnpack.Enabled = true;
                });
            }
        }
        private void UnpackPckg(string inputPath, string outputPath)
        {
            var pckg = new PckgFile();

            using (var input = File.OpenRead(inputPath))
            {
                pckg.Deserialize(input);
            }

            Directory.CreateDirectory(outputPath);

            Stream data = File.OpenRead(inputPath);

            int percents = 0;
            int current  = 0;
            int total    = pckg.Entries.Count;

            foreach (var entry in pckg.Entries.OrderBy(e => e.Offset))
            {
                current++;

                long entryOffset = entry.Offset;

                // detect type
                string extension;
                {
                    var guess = new byte[64];
                    int read  = 0;

                    if (entry.Size > 0)
                    {
                        data.Seek(entryOffset, SeekOrigin.Begin);
                        read = data.Read(guess, 0, (int)Math.Min(entry.Size, guess.Length));
                    }
                    extension = Helpers.ExtensionsDetect(guess, Math.Min(guess.Length, read));
                }

                // string name = "0x" + entry.NameHash.ToString("X16");
                string name = entry.NameHash.ToString("X16");
                name = Path.ChangeExtension(name, "." + extension);

                var entryPath = Path.Combine(outputPath, name);
                // Directory.CreateDirectory(Path.GetDirectoryName(entryPath));

                using (var output = File.Create(entryPath))
                {
                    if (entry.Size > 0)
                    {
                        data.Seek(entryOffset, SeekOrigin.Begin);
                        output.WriteFromStream(data, entry.Size);
                    }
                }

                // verbose
                if (InvokeRequired == true)
                {
                    Invoke((MethodInvoker) delegate
                    {
                        progressBar1.Value = percents;
                        resultLabel.Text   = entryPath;
                    });
                }

                percents = ((current + 1) * 100) / total;
            }

            if (data != null)
            {
                data.Close();
            }

            if (InvokeRequired == true)
            {
                Invoke((MethodInvoker) delegate
                {
                    progressBar1.Value   = 0;
                    resultLabel.Text     = "Done";
                    buttonUnpack.Enabled = true;
                    buttonPack.Enabled   = true;
                });
            }
        }