Beispiel #1
0
        public static async Task DdtBytes2TgaAsync(byte[] source, string path)
        {
            var data = source;

            if (Alz4Utils.IsAlz4File(data))
            {
                data = await Alz4Utils.ExtractAlz4BytesAsync(data);
            }
            else
            {
                if (L33TZipUtils.IsL33TZipFile(data))
                {
                    data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                }
            }
            DdtFile          ddt     = new DdtFile(data, false);
            PngBitmapEncoder encoder = new PngBitmapEncoder();

            byte[] raw_image = new byte[4 * ddt.BaseWidth * ddt.BaseHeight];
            ddt.Bitmap.CopyPixels(raw_image, 4 * ddt.BaseWidth, 0);
            var tga = new TGAImage(ddt.BaseWidth, ddt.BaseHeight, (byte)ddt.Usage, (byte)ddt.Alpha, (byte)ddt.Format, ddt.MipmapLevels, raw_image);

            var file_name = Path.GetFileNameWithoutExtension(path);

            file_name = file_name + ".(" + tga.image_id[0].ToString() + "," + tga.image_id[1].ToString() + "," + tga.image_id[2].ToString() + "," + tga.image_id[3].ToString() + ").tga";

            await File.WriteAllBytesAsync(Path.Combine(Path.GetDirectoryName(path), file_name), tga.ToByteArray());
        }
        public static async Task <GameFileInfo> GenerateGameFileInfo(string file, string fileName,
                                                                     string outputFolder, string baseHttpLink, CancellationToken ct = default)
        {
            if (!Directory.Exists(outputFolder))
            {
                Directory.CreateDirectory(outputFolder);
            }

            if (!baseHttpLink.EndsWith("/"))
            {
                baseHttpLink += "/";
            }

            var binFileName = $"{fileName.ToLower().GetHashCode():X4}.bin";
            var outFileName = Path.Combine(outputFolder, binFileName);

            await L33TZipUtils.CompressFileAsL33TZipAsync(file, outFileName, ct);

            var fileCrc = await Crc32Utils.DoGetCrc32FromFile(file, ct);

            var fileLength = new FileInfo(file).Length;

            var externalLocation = Path.Combine(baseHttpLink, binFileName).Replace("\\", "/");
            var outFileCrc       = await Crc32Utils.DoGetCrc32FromFile(outFileName, ct);

            var outFileLength = new FileInfo(outFileName).Length;

            return(new GameFileInfo(fileName, fileCrc, fileLength, externalLocation,
                                    outFileCrc, outFileLength));
        }
Beispiel #3
0
        public static async Task Ddt2PngAsync(string ddtFile)
        {
            var outname = ddtFile.ToLower().Replace(".ddt", ".png");

            using (var fileStream = new FileStream(outname, FileMode.Create))
            {
                // DdtFile ddt = new DdtFile(File.ReadAllBytes(ddtFile));
                BitmapEncoder encoder = new PngBitmapEncoder();
                var           data    = await File.ReadAllBytesAsync(ddtFile);

                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }


                //await File.WriteAllBytesAsync("test", data);

                encoder.Frames.Add(BitmapFrame.Create(new DdtFile(data, false).Bitmap));
                encoder.Save(fileStream);
            }
        }
        public async Task saveFiles(List <BarEntry> files, string savePath, bool Decompress, CancellationToken token, ExportDDT settings)
        {
            ResetProgress();
            if (files.Count == 0)
            {
                return;
            }

            using var input = File.OpenRead(barFilePath);

            long filesSize = files.Sum(x => (long)x.FileSize2);

            foreach (var file in files)
            {
                if (token.IsCancellationRequested)
                {
                    while (extractingState == 1)
                    {
                        await Task.Delay(1000);
                    }
                }
                if (token.IsCancellationRequested && extractingState == 2)
                {
                    ResetProgress();
                    return;
                }
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);

                Directory.CreateDirectory(Path.Combine(savePath, Path.GetDirectoryName(file.FileNameWithRoot)));



                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                //
                if (file.Extension != ".XMB" && (L33TZipUtils.IsL33TZipFile(data) || Alz4Utils.IsAlz4File(data)) && Decompress)
                {
                    if (Alz4Utils.IsAlz4File(data))
                    {
                        data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                    }
                    else
                    {
                        if (L33TZipUtils.IsL33TZipFile(data))
                        {
                            data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                        }
                    }
                }

                await File.WriteAllBytesAsync(Path.Combine(savePath, file.FileNameWithRoot), data);

                CurrentProgress += (double)file.FileSize2 / filesSize;
            }
            ResetProgress();
        }
Beispiel #5
0
        private static async Task <FileInfo> EnsureFileIsExtracted(FileInfo file)
        {
            if (file.FullName.EndsWith(".age4scn", StringComparison.OrdinalIgnoreCase) &&
                L33TZipUtils.IsL33TZipFile(file.FullName))
            {
                var data = await L33TZipUtils.ExtractL33TZipFileAsync(file.FullName);

                File.Delete(file.FullName);
                File.WriteAllBytes(file.FullName, data);
                return(new FileInfo(file.FullName));
            }

            return(file);
        }
Beispiel #6
0
        private static async Task <GameFileInfo> GenerateGameFileInfo(string file, string fileName,
                                                                      string outputFolder,
#pragma warning disable IDE0034 // Simplifier l'expression 'default'
                                                                      string baseHttpLink, CancellationToken ct = default(CancellationToken))
#pragma warning restore IDE0034 // Simplifier l'expression 'default'
        {
            if (!baseHttpLink.EndsWith("/"))
            {
                baseHttpLink += "/";
            }

            var binFileName = $"{fileName.ToLower().GetHashCode():X4}.bin";
            var outFileName = Path.Combine(outputFolder, binFileName);

            await L33TZipUtils.DoCreateL33TZipFile(file, outFileName, ct);

            var fileInfo = new GameFileInfo(fileName, await Crc32Utils.DoGetCrc32FromFile(file, ct),
                                            new FileInfo(file).Length, Path.Combine(baseHttpLink, binFileName).Replace("\\", "/"),
                                            await Crc32Utils.DoGetCrc32FromFile(outFileName, ct), new FileInfo(outFileName).Length);

            return(fileInfo);
        }
        public static async Task <bool> ScanAndRepairFile(GameFileInfo fileInfo, string gameFilePath,
                                                          PathTransformer pathTransformer, IProgress <ScanSubProgress> progress = null,
                                                          int concurrentDownload = 0, CancellationToken ct = default)
        {
            var filePath = Path.Combine(gameFilePath, pathTransformer.TransformPath(fileInfo.FileName));

            //#1 Check File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Check, 0));

            Progress <double> subProgressCheck = null;

            if (progress != null)
            {
                subProgressCheck = new Progress <double>();
                subProgressCheck.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.Check, d));
                };
            }

            if (await RunFileCheck(filePath, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheck))
            {
                progress?.Report(new ScanSubProgress(ScanSubProgressStep.End, 100));
                return(true);
            }

            //#2 Download File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Download, 0));

            var tempFileName = Path.Combine(GameScannerTempPath, $"{fileInfo.FileName.GetHashCode():X4}.tmp");

            if (File.Exists(tempFileName))
            {
                File.Delete(tempFileName);
            }

            var fileDownloader = concurrentDownload == 1
                ? (IFileDownloader) new SimpleFileDownloader(fileInfo.HttpLink, tempFileName)
                : new ChunkFileDownloader(fileInfo.HttpLink, tempFileName, GameScannerTempPath,
                                          concurrentDownload);

            if (progress != null)
            {
                fileDownloader.ProgressChanged += (sender, eventArg) =>
                {
                    switch (fileDownloader.State)
                    {
                    case FileDownloaderState.Invalid:
                    case FileDownloaderState.Download:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, fileDownloader.DownloadProgress * 0.99,
                                            new ScanDownloadProgress(fileDownloader.DownloadSize, fileDownloader.BytesDownloaded,
                                                                     fileDownloader.DownloadSpeed)));
                        break;

                    case FileDownloaderState.Finalize:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 99,
                                            new ScanDownloadProgress(fileDownloader.DownloadSize, fileDownloader.BytesDownloaded,
                                                                     0)));
                        break;

                    case FileDownloaderState.Complete:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 100,
                                            new ScanDownloadProgress(fileDownloader.DownloadSize, fileDownloader.BytesDownloaded,
                                                                     0)));
                        break;

                    case FileDownloaderState.Error:
                    case FileDownloaderState.Abort:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(fileDownloader.State),
                                                              fileDownloader.State, null);
                    }
                }
            }
            ;

            await fileDownloader.DownloadAsync(ct);


            //#3 Check Downloaded File
            ct.ThrowIfCancellationRequested();

            Progress <double> subProgressCheckDown = null;

            if (progress != null)
            {
                progress.Report(new ScanSubProgress(ScanSubProgressStep.CheckDownload, 0));

                subProgressCheckDown = new Progress <double>();
                subProgressCheckDown.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckDownload, d));
                };
            }

            try
            {
                await EnsureValidGameFile(tempFileName, fileInfo.BinSize, fileInfo.BinCrc32, ct, subProgressCheckDown);
            }
            catch
            {
                if (File.Exists(tempFileName))
                {
                    File.Delete(tempFileName);
                }

                throw;
            }

            //#4 Extract downloaded file
            ct.ThrowIfCancellationRequested();
            if (L33TZipUtils.IsL33TZipFile(tempFileName))
            {
                var tempFileName2 = $"{tempFileName.Replace(".tmp", string.Empty)}.ext.tmp";
                //
                Progress <double> extractProgress = null;
                if (progress != null)
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.ExtractDownload, 0));

                    extractProgress = new Progress <double>();
                    extractProgress.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.ExtractDownload, d));
                    };
                }

                await L33TZipUtils.ExtractL33TZipFileAsync(tempFileName, tempFileName2, ct, extractProgress);

                //#4.1 Check Extracted File
                ct.ThrowIfCancellationRequested();
                Progress <double> subProgressCheckExt = null;
                if (progress != null)
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckExtractDownload, 0));

                    subProgressCheckExt = new Progress <double>();
                    subProgressCheckExt.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.CheckExtractDownload, d));
                    };
                }

                await EnsureValidGameFile(tempFileName2, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheckExt);

                File.Delete(tempFileName);

                tempFileName = tempFileName2;
            }

            //#5 Move new file to game folder
            ct.ThrowIfCancellationRequested();

            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.Finalize, 0));

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            else
            {
                var pathName = Path.GetDirectoryName(filePath);
                if (!string.IsNullOrEmpty(pathName) && !Directory.Exists(pathName))
                {
                    Directory.CreateDirectory(pathName);
                }
            }

            File.Move(tempFileName, filePath);

            //#6 End
            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.End, 100));

            return(true);
        }
        public async Task readFile(BarEntry file)
        {
            // Firstly, is the file parameter null?

            PreviewDdt   = null;
            Preview      = null;
            PreviewImage = null;
            if (file == null)
            {
                return;
            }

            if (file.Extension == ".WAV" /* || file.Extension == ".MP3"*/)
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                //File.WriteAllBytes(file.fileNameWithoutPath, data);
                audio = new MemoryStream(data);
                if (file.isCompressed)
                {
                    //   AudioFileReader audioFileReader = new AudioFileReader();
                    //  DirectSoundOut directSoundOut = new DirectSoundOut();

                    // audioFileReader.
                    audio = new MemoryStream(data);
                }
                else
                {
                    audio = new MemoryStream(data);
                }

                return;
            }
            if (file.Extension == ".DDT")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);


                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }

                PreviewDdt = new DdtFile(data, true);
                return;
            }
            if (file.Extension == ".BMP" || file.Extension == ".PNG" || file.Extension == ".CUR" || file.Extension == ".JPG")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }
                var bitmap = new BitmapImage();
                using (var stream = new MemoryStream(data))
                {
                    bitmap.BeginInit();
                    bitmap.StreamSource = stream;
                    bitmap.CacheOption  = BitmapCacheOption.OnLoad;
                    bitmap.EndInit();
                    bitmap.Freeze();
                }

                PreviewImage = bitmap;
                return;
            }

            if (file.Extension == ".XMB")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }

                //File.WriteAllBytes(file.fileNameWithoutPath, data);

                Preview = new Document();
                Preview.SyntaxHighlighting = "XML";
                Preview.Text = await XMBFile.XmbToXmlAsync(data);

                NotifyPropertyChanged("Preview");
                return;
            }
            if (file.Extension == ".XAML" || file.Extension == ".XML" || file.Extension == ".SHP" || file.Extension == ".LGT" || file.Extension == ".XS" || file.Extension == ".TXT" || file.Extension == ".CFG" || file.Extension == ".PY")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }
                Preview      = new Document();
                Preview.Text = System.Text.Encoding.UTF8.GetString(data);
                if (file.Extension == ".XS")
                {
                    Preview.SyntaxHighlighting = "C++";
                }
                else
                {
                    Preview.SyntaxHighlighting = "XML";
                }
                NotifyPropertyChanged("Preview");
                return;
            }

            return;
        }
Beispiel #9
0
        public static async Task CreateXMBFileL33T(string filename)
        {
            using var output = new MemoryStream();

            var writer = new BinaryWriter(output, Encoding.Default, true);

            writer.Write((byte)88);
            writer.Write((byte)49);

            writer.Write(0);

            writer.Write((byte)88);
            writer.Write((byte)82);
            writer.Write(4);
            writer.Write(8);


            XmlDocument file = new XmlDocument();

            file.Load(filename);
            XmlNode rootElement = file.FirstChild;


            // Get the list of element/attribute names, sorted by first appearance
            List <XmlString> ElementNames   = new List <XmlString>();
            List <XmlString> AttributeNames = new List <XmlString>();
            await Task.Run(() =>
            {
                ExtractStrings(file.DocumentElement, ref ElementNames, ref AttributeNames);
            });

            // Output element names
            int NumElements = ElementNames.Count;

            writer.Write(NumElements);
            for (int i = 0; i < NumElements; ++i)
            {
                writer.Write(ElementNames[i].Content.Length);
                writer.Write(Encoding.Unicode.GetBytes(ElementNames[i].Content));
            }

            int NumAttributes = AttributeNames.Count;

            writer.Write(NumAttributes);
            for (int i = 0; i < NumAttributes; ++i)
            {
                writer.Write(AttributeNames[i].Content.Length);
                writer.Write(Encoding.Unicode.GetBytes(AttributeNames[i].Content));
            }

            // Output root node, plus all descendants
            await Task.Run(() =>
            {
                WriteNode(ref writer, rootElement, ElementNames, AttributeNames);
            });


            // Fill in data-length field near the beginning
            long DataEnd = writer.BaseStream.Position;

            writer.BaseStream.Seek(2, SeekOrigin.Begin);
            int Length = (int)(DataEnd - (2 + 4));

            writer.Write(Length);
            writer.BaseStream.Seek(DataEnd, SeekOrigin.Begin);

            await L33TZipUtils.CompressBytesAsL33TZipAsync(output.ToArray(), filename + ".xmb");
        }
        private async void convertFiles(object sender, RoutedEventArgs e)
        {
            mainMenu.IsEnabled        = false;
            SpinnerConvert.Visibility = Visibility.Visible;
            tbConvert.Text            = "Converting";
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.Multiselect = true;

            string operationType = (sender as MenuItem).Tag.ToString();

            //await DdtFileUtils.Ddt2PngAsync(@"D:\Development\Resource Manager\Resource Manager\bin\Release\netcoreapp3.1\Art\ui\alerts\alert_treatyend_bump.ddt");

            if (operationType == "topng")
            {
                openFileDialog.Filter = "Age of Empires 3 ddt files (*.ddt)|*.ddt";
                if (openFileDialog.ShowDialog() == true)
                {
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            await DdtFileUtils.Ddt2PngAsync(file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "toxml")
            {
                openFileDialog.Filter = "Age of Empires 3 xmb files (*.xmb)|*.xmb";

                if (openFileDialog.ShowDialog() == true)
                {
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            var data = await File.ReadAllBytesAsync(file);


                            if (Alz4Utils.IsAlz4File(data))
                            {
                                data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                            }
                            else
                            {
                                if (L33TZipUtils.IsL33TZipFile(data))
                                {
                                    data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                                }
                            }


                            using MemoryStream stream = new MemoryStream(data);
                            XMBFile xmb = await XMBFile.LoadXMBFile(stream);

                            var newName = Path.ChangeExtension(file, "");

                            xmb.file.Save(newName);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "toxmbde")
            {
                openFileDialog.Filter = "Age of Empires 3 xml files (*.xml)|*.xml";

                if (openFileDialog.ShowDialog() == true)
                {
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            await XMBFile.CreateXMBFileALZ4(file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "toxmbcc")
            {
                openFileDialog.Filter = "Age of Empires 3 xml files (*.xml)|*.xml";
                if (openFileDialog.ShowDialog() == true)
                {
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            await XMBFile.CreateXMBFileL33T(file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }



            tbConvert.Text            = "Convert";
            SpinnerConvert.Visibility = Visibility.Collapsed;
            mainMenu.IsEnabled        = true;
        }
        public async Task saveFiles(List <BarEntry> files, string savePath, bool Decompress, CancellationToken token, bool convertDDT, bool convertXMB)
        {
            ResetProgress();
            if (files.Count == 0)
            {
                return;
            }

            using var input = File.OpenRead(barFilePath);

            long filesSize = files.Sum(x => (long)x.FileSize2);

            foreach (var file in files)
            {
                if (token.IsCancellationRequested)
                {
                    while (extractingState == 1)
                    {
                        await Task.Delay(1000);
                    }
                }
                if (token.IsCancellationRequested && extractingState == 2)
                {
                    ResetProgress();
                    return;
                }
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);

                Directory.CreateDirectory(Path.Combine(savePath, Path.GetDirectoryName(file.FileNameWithRoot)));



                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);


                if (file.Extension != ".XMB" && (L33TZipUtils.IsL33TZipFile(data) || Alz4Utils.IsAlz4File(data)) && Decompress)
                {
                    if (Alz4Utils.IsAlz4File(data))
                    {
                        data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                    }
                    else
                    {
                        if (L33TZipUtils.IsL33TZipFile(data))
                        {
                            data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                        }
                    }
                }

                if (file.Extension == ".WAV" || file.Extension == ".MP3")
                {
                    if (file.isCompressed == 2)
                    {
                        data = await soundUtils.DecryptSound(data);
                    }
                }

                await File.WriteAllBytesAsync(Path.Combine(savePath, file.FileNameWithRoot), data);



                if (file.Extension == ".XMB" && convertXMB)
                {
                    if (Alz4Utils.IsAlz4File(data))
                    {
                        data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                    }
                    else
                    {
                        if (L33TZipUtils.IsL33TZipFile(data))
                        {
                            data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                        }
                    }

                    using MemoryStream stream = new MemoryStream(data);
                    XMBFile xmb = await XMBFile.LoadXMBFile(stream);

                    var newName = Path.ChangeExtension(Path.Combine(savePath, file.FileNameWithRoot), "");

                    xmb.file.Save(newName);
                }

                if (file.Extension == ".DDT" && convertDDT)
                {
                    await DdtFileUtils.DdtBytes2PngAsync(data, Path.Combine(savePath, file.FileNameWithRoot));
                }


                CurrentProgress += (double)file.FileSize2 / filesSize;
            }
            ResetProgress();
        }
Beispiel #12
0
        private static async Task ConvertFile(bool convertFile, string tempFileName, BarEntry barFileInfo, string filePath)
        {
            //Convert file
            if (convertFile)
            {
                if (L33TZipUtils.IsL33TZipFile(tempFileName) &&
                    !barFileInfo.FileName.EndsWith(".age4scn", StringComparison.OrdinalIgnoreCase))
                {
                    var rnd           = new Random(Guid.NewGuid().GetHashCode());
                    var tempFileName2 =
                        Path.Combine(Path.GetTempPath(),
                                     $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                    await L33TZipUtils.ExtractL33TZipFileAsync(tempFileName, tempFileName2);

                    if (File.Exists(tempFileName))
                    {
                        File.Delete(tempFileName);
                    }

                    tempFileName = tempFileName2;
                }

                if (barFileInfo.FileName.EndsWith(".xmb", StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        var rnd           = new Random(Guid.NewGuid().GetHashCode());
                        var tempFileName2 =
                            Path.Combine(Path.GetTempPath(),
                                         $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                        XmbFileUtils.XmbToXml(tempFileName, tempFileName2);

                        if (File.Exists(tempFileName))
                        {
                            File.Delete(tempFileName);
                        }

                        tempFileName = tempFileName2;

                        filePath = filePath.Substring(0, filePath.Length - 4);
                    }
                    catch (Exception)
                    {
                        //
                    }
                }
                else if (barFileInfo.FileName.EndsWith(".age4scn",
                                                       StringComparison.OrdinalIgnoreCase) &&
                         !L33TZipUtils.IsL33TZipFile(tempFileName))
                {
                    var rnd           = new Random(Guid.NewGuid().GetHashCode());
                    var tempFileName2 =
                        Path.Combine(Path.GetTempPath(),
                                     $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                    await L33TZipUtils.CompressFileAsL33TZipAsync(tempFileName, tempFileName2);

                    if (File.Exists(tempFileName))
                    {
                        File.Delete(tempFileName);
                    }

                    tempFileName = tempFileName2;
                }
            }

            //Move new file
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }

            File.Move(tempFileName, filePath);

            File.SetCreationTimeUtc(filePath,
                                    new DateTime(barFileInfo.LastWriteTime.Year, barFileInfo.LastWriteTime.Month,
                                                 barFileInfo.LastWriteTime.Day, barFileInfo.LastWriteTime.Hour,
                                                 barFileInfo.LastWriteTime.Minute, barFileInfo.LastWriteTime.Second));

            File.SetLastWriteTimeUtc(filePath,
                                     new DateTime(barFileInfo.LastWriteTime.Year, barFileInfo.LastWriteTime.Month,
                                                  barFileInfo.LastWriteTime.Day, barFileInfo.LastWriteTime.Hour,
                                                  barFileInfo.LastWriteTime.Minute, barFileInfo.LastWriteTime.Second));
        }
        public static void CreateBarFile(IReadOnlyCollection <FileInfo> fileInfos, string inputPath,
                                         string outputFileName, string rootDir, bool ignoreLastWriteTime = true, bool xmlToXmb = true)
        {
            if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                inputPath = inputPath.Substring(0, inputPath.Length - 1);
            }

            var folder = Path.GetDirectoryName(outputFileName);

            if (folder != null && !Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }

            var newFilesInfos = new List <FileInfo>();

            foreach (var file in fileInfos.ToArray())
            {
                if (file.FullName.EndsWith(".age4scn", StringComparison.OrdinalIgnoreCase))
                {
                    if (L33TZipUtils.IsL33TZip(file.FullName))
                    {
                        var data = L33TZipUtils.DecompressL33TZip(file.FullName);
                        File.Delete(file.FullName);
                        File.WriteAllBytes(file.FullName, data);
                        newFilesInfos.Add(new FileInfo(file.FullName));
                    }
                    else
                    {
                        newFilesInfos.Add(file);
                    }
                }
                else if (xmlToXmb && file.FullName.EndsWith(".quest", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".region", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".tactics", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".character", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".dataset", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".empire", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".spawneritem", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".groupingset", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".set", StringComparison.OrdinalIgnoreCase) ||
                         file.FullName.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
                {
                    if (XmbFile.IsXmlFile(file.FullName))
                    {
                        XmbFileUtils.XmlFileToXmbFile(file.FullName, file.FullName + ".xmb");
                        File.Delete(file.FullName);
                        newFilesInfos.Add(new FileInfo(file.FullName + ".xmb"));
                    }
                    else
                    {
                        newFilesInfos.Add(file);
                    }
                }
                else
                {
                    newFilesInfos.Add(file);
                }
            }

            using var fileStream = File.Open(outputFileName, FileMode.Create, FileAccess.Write, FileShare.None);
            using var writer     = new BinaryWriter(fileStream);
            //Write Bar Header
            var header = new BarFileHeader(Path.GetFileName(outputFileName), newFilesInfos);

            writer.Write(header.ToByteArray());

            //Write Files
            var barEntrys = new List <BarEntry>();

            foreach (var file in newFilesInfos)
            {
                var filePath = file.FullName;
                barEntrys.Add(new BarEntry(inputPath, file, (int)writer.BaseStream.Position,
                                           ignoreLastWriteTime));
                using var fileStream2 = File.Open(filePath, FileMode.Open, FileAccess.Read,
                                                  FileShare.Read);
                using var binReader = new BinaryReader(fileStream2);
                var buffer = new byte[4096];
                int read;
                while ((read = binReader.Read(buffer, 0, buffer.Length)) > 0)
                {
                    writer.Write(buffer, 0, read);
                }
            }

            //Write Bar Entrys
            var end = new BarFileBody(rootDir, barEntrys);

            writer.Write(end.ToByteArray());
        }
        public static void ExtractBarFiles(string inputFile, string outputPath, bool convertFile = true)
        {
            if (!File.Exists(inputFile))
            {
                throw new FileNotFoundException($"File '{inputFile}' not found!", inputFile);
            }

            if (!outputPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                outputPath = outputPath + Path.DirectorySeparatorChar;
            }

            BarFileBody barFilesInfo;

            using (var fileStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using var binReader = new BinaryReader(fileStream);
                //Read Header
                binReader.BaseStream.Seek(0, SeekOrigin.Begin); //Seek to header
                var barFileHeader = new BarFileHeader(binReader);

                //Read Files Info
                binReader.BaseStream.Seek(barFileHeader.FilesTableOffset, SeekOrigin.Begin); //Seek to file table

                barFilesInfo = new BarFileBody(binReader);
            }

            var exceptions = new BlockingCollection <Exception>();

            Parallel.ForEach(barFilesInfo.Entries.ToArray(), barFileInfo =>
            {
                try
                {
                    using var fileStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read);
                    using var binReader  = new BinaryReader(fileStream);
                    binReader.BaseStream.Seek(barFileInfo.Offset, SeekOrigin.Begin); //Seek to file

                    var path = Path.Combine(outputPath, barFilesInfo.RootPath,
                                            Path.GetDirectoryName(barFileInfo.FileName) ?? string.Empty);

                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }

                    var filePath = Path.Combine(outputPath, barFilesInfo.RootPath, barFileInfo.FileName);

                    //Extract to tmp file
                    var tempFileName = Path.GetTempFileName();
                    using (var fileStreamFinal =
                               File.Open(tempFileName, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        using var final = new BinaryWriter(fileStreamFinal);
                        var buffer      = new byte[4096];
                        int read;
                        var totalread = 0L;
                        while ((read = binReader.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            if (read > barFileInfo.FileSize)
                            {
                                totalread = barFileInfo.FileSize;
                                final.Write(buffer, 0, barFileInfo.FileSize);
                            }
                            else if (totalread + read <= barFileInfo.FileSize)
                            {
                                totalread += read;
                                final.Write(buffer, 0, read);
                            }
                            else if (totalread + read > barFileInfo.FileSize)
                            {
                                var leftToRead = barFileInfo.FileSize - totalread;
                                totalread      = barFileInfo.FileSize;
                                final.Write(buffer, 0, Convert.ToInt32(leftToRead));
                            }

                            if (totalread >= barFileInfo.FileSize)
                            {
                                break;
                            }
                        }
                    }

                    //Convert file
                    if (convertFile)
                    {
                        if (L33TZipUtils.IsL33TZip(tempFileName) &&
                            !barFileInfo.FileName.EndsWith(".age4scn", StringComparison.OrdinalIgnoreCase))
                        {
                            var rnd           = new Random(Guid.NewGuid().GetHashCode());
                            var tempFileName2 =
                                Path.Combine(Path.GetTempPath(),
                                             $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                            L33TZipUtils.DecompressL33TZip(tempFileName, tempFileName2);

                            if (File.Exists(tempFileName))
                            {
                                File.Delete(tempFileName);
                            }

                            tempFileName = tempFileName2;
                        }

                        if (barFileInfo.FileName.EndsWith(".xmb", StringComparison.OrdinalIgnoreCase))
                        {
                            try
                            {
                                var rnd           = new Random(Guid.NewGuid().GetHashCode());
                                var tempFileName2 =
                                    Path.Combine(Path.GetTempPath(),
                                                 $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                                XmbFileUtils.XmbFileToXmlFile(tempFileName, tempFileName2);

                                if (File.Exists(tempFileName))
                                {
                                    File.Delete(tempFileName);
                                }

                                tempFileName = tempFileName2;

                                filePath = filePath.Substring(0, filePath.Length - 4);
                            }
                            catch (Exception)
                            {
                                //
                            }
                        }
                        else if (barFileInfo.FileName.EndsWith(".age4scn",
                                                               StringComparison.OrdinalIgnoreCase) &&
                                 !L33TZipUtils.IsL33TZip(tempFileName))
                        {
                            var rnd           = new Random(Guid.NewGuid().GetHashCode());
                            var tempFileName2 =
                                Path.Combine(Path.GetTempPath(),
                                             $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                            L33TZipUtils.CompressFileAsL33TZipAsync(tempFileName, tempFileName2).GetAwaiter()
                            .GetResult();

                            if (File.Exists(tempFileName))
                            {
                                File.Delete(tempFileName);
                            }

                            tempFileName = tempFileName2;
                        }
                    }

                    //Move new file
                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                    }

                    //
                    File.Move(tempFileName, filePath);

                    //
                    File.SetCreationTimeUtc(filePath,
                                            new DateTime(barFileInfo.LastWriteTime.Year, barFileInfo.LastWriteTime.Month,
                                                         barFileInfo.LastWriteTime.Day, barFileInfo.LastWriteTime.Hour,
                                                         barFileInfo.LastWriteTime.Minute, barFileInfo.LastWriteTime.Second));

                    File.SetLastWriteTimeUtc(filePath,
                                             new DateTime(barFileInfo.LastWriteTime.Year, barFileInfo.LastWriteTime.Month,
                                                          barFileInfo.LastWriteTime.Day, barFileInfo.LastWriteTime.Hour,
                                                          barFileInfo.LastWriteTime.Minute, barFileInfo.LastWriteTime.Second));
                }
                catch (Exception e)
                {
                    exceptions.Add(e);
                }
            });
            exceptions.CompleteAdding();
            if (exceptions.Count > 0)
            {
                throw new AggregateException(exceptions.ToArray());
            }
        }
Beispiel #15
0
        public static void ExtractBarFile(string inputFile, string file, string outputPath, bool convertFile = true)
        {
            if (string.IsNullOrWhiteSpace(file))
            {
                throw new ArgumentNullException(nameof(file), "Value cannot be null or empty.");
            }

            if (!File.Exists(inputFile))
            {
                throw new FileNotFoundException($"File '{inputFile}' not found!", inputFile);
            }

            if (!outputPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                outputPath = outputPath + Path.DirectorySeparatorChar;
            }

            BarFile barFilesInfo;

            using (var fileStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (var binReader = new BinaryReader(fileStream))
                {
                    //Read Header
                    binReader.BaseStream.Seek(0, SeekOrigin.Begin); //Seek to header
                    var barFileHeader = new BarFileHeader(binReader);

                    //Read Files Info
                    binReader.BaseStream.Seek(barFileHeader.FilesTableOffset, SeekOrigin.Begin); //Seek to file table

                    barFilesInfo = new BarFile(binReader);
                }
            }

            var barFileInfo = barFilesInfo.BarFileEntrys.First(
                key => string.Equals(key.FileName, file, StringComparison.OrdinalIgnoreCase));

            using (var fileStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                using (var binReader = new BinaryReader(fileStream))
                {
                    binReader.BaseStream.Seek(barFileInfo.Offset, SeekOrigin.Begin); //Seek to file

                    var path = Path.Combine(outputPath, barFilesInfo.RootPath,
                                            Path.GetDirectoryName(barFileInfo.FileName) ?? string.Empty);

                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }

                    var filePath = Path.Combine(outputPath, barFilesInfo.RootPath, barFileInfo.FileName);

                    //Extract to tmp file
                    var tempFileName = Path.GetTempFileName();
                    using (var fileStreamFinal =
                               File.Open(tempFileName, FileMode.Create, FileAccess.Write, FileShare.None))
                    {
                        using (var final = new BinaryWriter(fileStreamFinal))
                        {
                            var buffer = new byte[4096];
                            int read;
                            var totalread = 0L;
                            while ((read = binReader.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                if (read > barFileInfo.FileSize)
                                {
                                    totalread = barFileInfo.FileSize;
                                    final.Write(buffer, 0, barFileInfo.FileSize);
                                }
                                else if (totalread + read <= barFileInfo.FileSize)
                                {
                                    totalread += read;
                                    final.Write(buffer, 0, read);
                                }
                                else if (totalread + read > barFileInfo.FileSize)
                                {
                                    var leftToRead = barFileInfo.FileSize - totalread;
                                    totalread = barFileInfo.FileSize;
                                    final.Write(buffer, 0, Convert.ToInt32(leftToRead));
                                }

                                if (totalread >= barFileInfo.FileSize)
                                {
                                    break;
                                }
                            }
                        }
                    }

                    //Convert file
                    if (convertFile)
                    {
                        if (L33TZipUtils.IsL33TZipFile(tempFileName) &&
                            !barFileInfo.FileName.EndsWith(".age4scn", StringComparison.OrdinalIgnoreCase))
                        {
                            var rnd           = new Random(Guid.NewGuid().GetHashCode());
                            var tempFileName2 =
                                Path.Combine(Path.GetTempPath(),
                                             $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                            L33TZipUtils.ExtractL33TZipFile(tempFileName, tempFileName2);

                            if (File.Exists(tempFileName))
                            {
                                File.Delete(tempFileName);
                            }

                            tempFileName = tempFileName2;
                        }

                        if (barFileInfo.FileName.EndsWith(".xmb", StringComparison.OrdinalIgnoreCase))
                        {
                            try
                            {
                                var rnd           = new Random(Guid.NewGuid().GetHashCode());
                                var tempFileName2 =
                                    Path.Combine(Path.GetTempPath(),
                                                 $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                                XmbFileUtils.XmbToXml(tempFileName, tempFileName2);

                                if (File.Exists(tempFileName))
                                {
                                    File.Delete(tempFileName);
                                }

                                tempFileName = tempFileName2;

                                filePath = filePath.Substring(0, filePath.Length - 4);
                            }
                            catch (Exception)
                            {
                                //
                            }
                        }
                        else if (barFileInfo.FileName.EndsWith(".age4scn",
                                                               StringComparison.OrdinalIgnoreCase) &&
                                 !L33TZipUtils.IsL33TZipFile(tempFileName))
                        {
                            var rnd           = new Random(Guid.NewGuid().GetHashCode());
                            var tempFileName2 =
                                Path.Combine(Path.GetTempPath(),
                                             $"{Path.GetFileName(barFileInfo.FileName)}-{rnd.Next()}.tmp");
                            L33TZipUtils.CreateL33TZipFile(tempFileName, tempFileName2);

                            if (File.Exists(tempFileName))
                            {
                                File.Delete(tempFileName);
                            }

                            tempFileName = tempFileName2;
                        }
                    }

                    //Move new file
                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                    }

                    //
                    File.Move(tempFileName, filePath);

                    //
                    File.SetCreationTimeUtc(filePath,
                                            new DateTime(barFileInfo.LastWriteTime.Year, barFileInfo.LastWriteTime.Month,
                                                         barFileInfo.LastWriteTime.Day, barFileInfo.LastWriteTime.Hour,
                                                         barFileInfo.LastWriteTime.Minute, barFileInfo.LastWriteTime.Second));

                    File.SetLastWriteTimeUtc(filePath,
                                             new DateTime(barFileInfo.LastWriteTime.Year, barFileInfo.LastWriteTime.Month,
                                                          barFileInfo.LastWriteTime.Day, barFileInfo.LastWriteTime.Hour,
                                                          barFileInfo.LastWriteTime.Minute, barFileInfo.LastWriteTime.Second));
                }
            }
        }
Beispiel #16
0
        public static void CreateBarFile(IReadOnlyCollection <FileInfo> fileInfos, string inputPath,
                                         string outputFileName, string rootdir, bool ignoreLastWriteTime = true)
        {
            if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                inputPath = inputPath.Substring(0, inputPath.Length - 1);
            }

            var folder = Path.GetDirectoryName(outputFileName);

            if (folder != null && !Directory.Exists(folder))
            {
                Directory.CreateDirectory(folder);
            }

            var newFilesInfos = new List <FileInfo>();

            foreach (var file in fileInfos.ToArray())
            {
                if (file.FullName.EndsWith(".age4scn", StringComparison.OrdinalIgnoreCase) &&
                    L33TZipUtils.IsL33TZipFile(file.FullName))
                {
                    var data = L33TZipUtils.ExtractL33TZipFile(file.FullName);
                    File.Delete(file.FullName);
                    File.WriteAllBytes(file.FullName, data);
                    newFilesInfos.Add(new FileInfo(file.FullName));
                }
                else
                {
                    newFilesInfos.Add(file);
                }
            }

            using (var fileStream = File.Open(outputFileName, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (var writer = new BinaryWriter(fileStream))
                {
                    //Write Bar Header
                    var header = new BarFileHeader(Path.GetFileName(outputFileName), newFilesInfos);
                    writer.Write(header.ToByteArray());

                    //Write Files
                    var barEntrys = new List <BarEntry>();
                    foreach (var file in newFilesInfos)
                    {
                        var filePath = file.FullName;
                        barEntrys.Add(new BarEntry(inputPath, file, (int)writer.BaseStream.Position,
                                                   ignoreLastWriteTime));
                        using (var fileStream2 = File.Open(filePath, FileMode.Open, FileAccess.Read,
                                                           FileShare.Read))
                        {
                            using (var binReader = new BinaryReader(fileStream2))
                            {
                                var buffer = new byte[4096];
                                int read;
                                while ((read = binReader.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    writer.Write(buffer, 0, read);
                                }
                            }
                        }
                    }

                    //Write Bar Entrys
                    var end = new BarFile(rootdir, barEntrys);
                    writer.Write(end.ToByteArray());
                }
            }
        }
        public async void GetCustomValues(string filename)
        {
            if (!File.Exists(filename))
            {
                throw new Exception("BAR file does not exist!");
            }
            using var file = File.OpenRead(filename);
            var reader = new BinaryReader(file);

            reader.BaseStream.Seek(entry.Offset, SeekOrigin.Begin);
            byte[] data = reader.ReadBytes(entry.FileSize2);
            await Task.Run(() =>
            {
                entry.CRC32 = Crc32Algorithm.Compute(data);
            });

            reader.BaseStream.Seek(entry.Offset, SeekOrigin.Begin);
            HeaderText = new string(reader.ReadChars(4));
            reader.BaseStream.Seek(entry.Offset, SeekOrigin.Begin);
            Header = reader.ReadInt32();
            if (entry.Extension == ".DDT")
            {
                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }



                PreviewDdt = new DdtFile(data, true);
                var flagList = new List <string>();
                if (PreviewDdt.Usage.HasFlag(DdtFileTypeUsage.AlphaTest))
                {
                    flagList.Add(DdtFileTypeUsage.AlphaTest.ToString());
                }
                if (PreviewDdt.Usage.HasFlag(DdtFileTypeUsage.LowDetail))
                {
                    flagList.Add(DdtFileTypeUsage.LowDetail.ToString());
                }
                if (PreviewDdt.Usage.HasFlag(DdtFileTypeUsage.Bump))
                {
                    flagList.Add(DdtFileTypeUsage.Bump.ToString());
                }
                if (PreviewDdt.Usage.HasFlag(DdtFileTypeUsage.Cube))
                {
                    flagList.Add(DdtFileTypeUsage.Cube.ToString());
                }
                if (flagList.Count > 0)
                {
                    DdtUsage = ((byte)PreviewDdt.Usage).ToString() + " (" + string.Join('+', flagList) + ")";
                }
                else
                {
                    DdtUsage = ((byte)PreviewDdt.Usage).ToString();
                }
                DdtAlpha         = ((byte)PreviewDdt.Alpha).ToString() + " (" + PreviewDdt.Alpha.ToString() + ")";
                DdtFormat        = ((byte)PreviewDdt.Format).ToString() + " (" + PreviewDdt.Format.ToString() + ")";
                gpDDT.Visibility = Visibility.Visible;
            }
        }
        private async void convertFiles(object sender, RoutedEventArgs e)
        {
            mainMenu.IsEnabled        = false;
            SpinnerConvert.Visibility = Visibility.Visible;
            tbConvert.Text            = "Converting";
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.InitialDirectory = Settings.Default.lastConvertedPath;
            openFileDialog.Multiselect      = true;

            string operationType = (sender as MenuItem).Tag.ToString();

            //await DdtFileUtils.Ddt2PngAsync(@"D:\Development\Resource Manager\Resource Manager\bin\Release\netcoreapp3.1\Art\ui\alerts\alert_treatyend_bump.ddt");



            if (operationType == "totga")
            {
                openFileDialog.Filter = "Age of Empires 3 ddt files (*.ddt)|*.ddt";
                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            await DdtFileUtils.Ddt2TgaAsync(file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "topng")
            {
                openFileDialog.Filter = "Age of Empires 3 ddt files (*.ddt)|*.ddt";
                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            await DdtFileUtils.Ddt2PngAsync(file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "toxml")
            {
                openFileDialog.Filter = "Age of Empires 3 xmb files (*.xmb)|*.xmb";

                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            var data = await File.ReadAllBytesAsync(file);


                            if (Alz4Utils.IsAlz4File(data))
                            {
                                data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                            }
                            else
                            {
                                if (L33TZipUtils.IsL33TZipFile(data))
                                {
                                    data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                                }
                            }


                            using MemoryStream stream = new MemoryStream(data);
                            XMBFile xmb = await XMBFile.LoadXMBFile(stream);

                            var newName = Path.ChangeExtension(file, "");

                            xmb.file.Save(newName);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "jsontoxml")
            {
                openFileDialog.Filter = "JSON files (*.json)|*.json";

                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            var data = await File.ReadAllBytesAsync(file);


                            if (Alz4Utils.IsAlz4File(data))
                            {
                                data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                            }
                            else
                            {
                                if (L33TZipUtils.IsL33TZipFile(data))
                                {
                                    data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                                }
                            }
                            string json = await File.ReadAllTextAsync(file);

                            var xml = JsonConvert.DeserializeXmlNode(json);

                            var newName = Path.ChangeExtension(file, "");



                            xml.Save(newName);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "xmbtojson")
            {
                openFileDialog.Filter = "Age of Empires 3 xmb files (*.xmb)|*.xmb";

                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            var data = await File.ReadAllBytesAsync(file);


                            if (Alz4Utils.IsAlz4File(data))
                            {
                                data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                            }
                            else
                            {
                                if (L33TZipUtils.IsL33TZipFile(data))
                                {
                                    data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                                }
                            }


                            using MemoryStream stream = new MemoryStream(data);

                            XMBFile xmb = await XMBFile.LoadXMBFile(stream);

                            string json = JsonConvert.SerializeXmlNode(xmb.file);
                            await File.WriteAllTextAsync(Path.ChangeExtension(file, "json"), json);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "xmltojson")
            {
                openFileDialog.Filter = "Age of Empires 3 xml files (*.*)|*.*";

                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            XmlDocument xml = new XmlDocument();
                            xml.Load(file);
                            string json = JsonConvert.SerializeXmlNode(xml);
                            await File.WriteAllTextAsync(Path.ChangeExtension(file, "json"), json);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "jsontoxmblegacy")
            {
                openFileDialog.Filter = "JSON files (*.json)|*.json";

                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            string json = await File.ReadAllTextAsync(file);

                            var xml = JsonConvert.DeserializeXmlNode(json);
                            await XMBFile.CreateXMBFileL33T(xml, file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "jsontoxmbde")
            {
                openFileDialog.Filter = "JSON files (*.json)|*.json";

                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            string json = await File.ReadAllTextAsync(file);

                            var xml = JsonConvert.DeserializeXmlNode(json);
                            await XMBFile.CreateXMBFileALZ4(xml, file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "toxmbde")
            {
                openFileDialog.Filter = "Age of Empires 3 xml files (*.*)|*.*";

                if (openFileDialog.ShowDialog() == true)
                {
                    Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                    Settings.Default.Save();
                    foreach (var file in openFileDialog.FileNames)
                    {
                        try
                        {
                            await XMBFile.CreateXMBFileALZ4(file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
            if (operationType == "toxmbcc")
            {
                openFileDialog.Filter = "Age of Empires 3 xml files (*.*)|*.*";
                if (openFileDialog.ShowDialog() == true)
                {
                    foreach (var file in openFileDialog.FileNames)
                    {
                        Settings.Default.lastConvertedPath = Path.GetDirectoryName(openFileDialog.FileName);
                        Settings.Default.Save();
                        try
                        {
                            await XMBFile.CreateXMBFileL33T(file);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Conversion error - " + Path.GetFileName(file), MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }



            tbConvert.Text            = "Convert";
            SpinnerConvert.Visibility = Visibility.Collapsed;
            mainMenu.IsEnabled        = true;
        }
        public async Task saveFiles(List <BarEntry> files, string savePath, bool Decompress, CancellationToken token, bool convertDDTToPNG, bool convertDDTToTGA, bool convertXMB, bool OneFolder, bool SavePNGasBMP, bool AutoJSONConversion, Color OverlayColor)
        {
            ResetProgress();
            if (files.Count == 0)
            {
                return;
            }

            using var input = File.OpenRead(barFilePath);

            long filesSize = files.Sum(x => (long)x.FileSize2);

            foreach (var file in files)
            {
                if (token.IsCancellationRequested)
                {
                    while (extractingState == 1)
                    {
                        await Task.Delay(1000);
                    }
                }
                if (token.IsCancellationRequested && extractingState == 2)
                {
                    ResetProgress();
                    return;
                }
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);


                string ExtractPath = Path.Combine(savePath, file.FileNameWithRoot);
                if (OneFolder)
                {
                    ExtractPath = Path.Combine(savePath, file.fileNameWithoutPath);
                }

                Directory.CreateDirectory(Path.GetDirectoryName(ExtractPath));


                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                // XMB and decompress
                if (file.Extension != ".XMB" && (L33TZipUtils.IsL33TZipFile(data) || Alz4Utils.IsAlz4File(data)) && Decompress)
                {
                    if (Alz4Utils.IsAlz4File(data))
                    {
                        data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                    }
                    else
                    {
                        if (L33TZipUtils.IsL33TZipFile(data))
                        {
                            data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                        }
                    }
                }

                // WAV or MP3
                if (file.Extension == ".WAV" || file.Extension == ".MP3")
                {
                    if (file.isCompressed == 2)
                    {
                        data = await soundUtils.DecryptSound(data);
                    }
                }

                // Save PNG as BMP, skip saving as PNG
                if (file.Extension == ".PNG" && SavePNGasBMP)
                {
                    using var memory = new MemoryStream(data);
                    Bitmap img = new Bitmap(memory);


                    PixelFormat fmt1 = img.PixelFormat;
                    byte        bpp1 = 4;

                    Rectangle  rect    = new Rectangle(Point.Empty, new Size(img.Width, img.Height));
                    BitmapData bmpData = img.LockBits(rect, ImageLockMode.ReadWrite, fmt1);

                    int    size1  = bmpData.Stride * bmpData.Height;
                    byte[] pixels = new byte[size1];
                    Marshal.Copy(bmpData.Scan0, pixels, 0, size1);

                    for (int y = 0; y < img.Height; y++)
                    {
                        for (int x = 0; x < img.Width; x++)
                        {
                            int index = y * bmpData.Stride + x * bpp1;
                            var alpha = pixels[index + 3];
                            if (alpha < 255)
                            {
                                pixels[index]     = (byte)(pixels[index] * OverlayColor.B / 255);     //b
                                pixels[index + 1] = (byte)(pixels[index + 1] * OverlayColor.G / 255); //g
                                pixels[index + 2] = (byte)(pixels[index + 2] * OverlayColor.R / 255); //r
                                pixels[index + 3] = 255;
                            }
                        }
                    }

                    Marshal.Copy(pixels, 0, bmpData.Scan0, pixels.Length);
                    img.UnlockBits(bmpData);
                    using (Graphics g = Graphics.FromImage(img))
                    {
                        g.DrawImage(new Bitmap(memory), Point.Empty);
                    }
                    img.Save(ExtractPath, System.Drawing.Imaging.ImageFormat.Png);
                    CurrentProgress += (double)file.FileSize2 / filesSize;
                    continue;
                }


                // Save data
                await File.WriteAllBytesAsync(ExtractPath, data);


                // Additionaly convert xmb
                if (file.Extension == ".XMB" && convertXMB)
                {
                    if (Alz4Utils.IsAlz4File(data))
                    {
                        data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                    }
                    else
                    {
                        if (L33TZipUtils.IsL33TZipFile(data))
                        {
                            data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                        }
                    }

                    using MemoryStream stream = new MemoryStream(data);
                    XMBFile xmb = await XMBFile.LoadXMBFile(stream);

                    xmb.file.Save(Path.ChangeExtension(ExtractPath, ""));
                }

                // Additionaly convert xmb -> json
                if (file.Extension == ".XMB" && AutoJSONConversion)
                {
                    if (Alz4Utils.IsAlz4File(data))
                    {
                        data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                    }
                    else
                    {
                        if (L33TZipUtils.IsL33TZipFile(data))
                        {
                            data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                        }
                    }

                    using MemoryStream stream = new MemoryStream(data);
                    XMBFile xmb = await XMBFile.LoadXMBFile(stream);

                    string json = JsonConvert.SerializeXmlNode(xmb.file);
                    await File.WriteAllTextAsync(Path.ChangeExtension(ExtractPath, "json"), json);
                }

                // Additionaly convert xml -> json
                if (file.Extension == ".XML" && AutoJSONConversion)
                {
                    if (Alz4Utils.IsAlz4File(data))
                    {
                        data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                    }
                    else
                    {
                        if (L33TZipUtils.IsL33TZipFile(data))
                        {
                            data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                        }
                    }

                    using MemoryStream stream = new MemoryStream(data);
                    XmlDocument xml = new XmlDocument();
                    xml.Load(stream);
                    string json = JsonConvert.SerializeXmlNode(xml);
                    await File.WriteAllTextAsync(Path.ChangeExtension(ExtractPath, "json"), json);
                }



                // Additionaly convert ddt to png
                if (file.Extension == ".DDT" && convertDDTToPNG)
                {
                    await DdtFileUtils.DdtBytes2PngAsync(data, ExtractPath);
                }
                // Additionaly convert ddt to tga
                if (file.Extension == ".DDT" && convertDDTToTGA)
                {
                    await DdtFileUtils.DdtBytes2TgaAsync(data, ExtractPath);
                }



                CurrentProgress += (double)file.FileSize2 / filesSize;
            }
            ResetProgress();
        }
        public async Task readFile(BarEntry file)
        {
            // Firstly, is the file parameter null?

            PreviewDdt   = null;
            Preview      = null;
            PreviewImage = null;
            if (file == null)
            {
                return;
            }

            if (file.Extension == ".WAV" || file.Extension == ".MP3")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                if (file.isCompressed == 2)
                {
                    audio = new MemoryStream(await soundUtils.DecryptSound(data));
                }
                else
                {
                    audio = new MemoryStream(data);
                }
                return;
            }
            if (file.Extension == ".DDT")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);


                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }



                PreviewDdt = new DdtFile(data, true);
                return;
            }
            if (file.Extension == ".BMP" || file.Extension == ".TGA" || file.Extension == ".PNG" || file.Extension == ".CUR" || file.Extension == ".JPG")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }
                var bitmap = new BitmapImage();

                using (var stream = new MemoryStream(data))
                {
                    if (file.Extension == ".TGA")
                    {
                        IImage image = await Task.Run(() => Pfim.Pfim.FromStream(stream));

                        var pinnedArray = GCHandle.Alloc(image.Data, GCHandleType.Pinned);
                        var addr        = pinnedArray.AddrOfPinnedObject();
                        var bsource     = BitmapSource.Create(image.Width, image.Height, 96.0, 96.0,
                                                              PixelFormat(image), null, addr, image.DataLen, image.Stride);
                        PngBitmapEncoder encoder      = new PngBitmapEncoder();
                        MemoryStream     memoryStream = new MemoryStream();

                        encoder.Frames.Add(BitmapFrame.Create(bsource));
                        encoder.Save(memoryStream);
                        memoryStream.Position = 0;
                        bitmap.BeginInit();
                        bitmap.StreamSource = memoryStream;
                        bitmap.CacheOption  = BitmapCacheOption.OnLoad;
                        bitmap.EndInit();
                        bitmap.Freeze();
                        memoryStream.Close();
                    }

                    /*else if (file.Extension == ".PNG")
                     * {
                     *  System.Drawing.Image image = System.Drawing.Image.FromStream(stream);
                     *  using var memory = new MemoryStream();
                     *  image.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
                     *  memory.Seek(0, SeekOrigin.Begin);
                     *  bitmap.BeginInit();
                     *  bitmap.CacheOption = BitmapCacheOption.OnLoad;
                     *  bitmap.StreamSource = memory;
                     *  bitmap.EndInit();
                     * }*/
                    else
                    {
                        bitmap.BeginInit();
                        bitmap.StreamSource = stream;
                        bitmap.CacheOption  = BitmapCacheOption.OnLoad;
                        bitmap.EndInit();
                        bitmap.Freeze();
                    }
                }


                PreviewImage = bitmap;
                return;
            }

            if (file.Extension == ".XMB")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }

                //File.WriteAllBytes(file.fileNameWithoutPath, data);

                Preview = new Document();
                Preview.SyntaxHighlighting = "XML";
                Preview.Text = await XMBFile.XmbToXmlAsync(data);

                NotifyPropertyChanged("Preview");
                return;
            }
            if (file.Extension == ".XAML" || file.Extension == ".XML" || file.Extension == ".SHP" || file.Extension == ".LGT" || file.Extension == ".XS" || file.Extension == ".TXT" || file.Extension == ".CFG" || file.Extension == ".PY" || file.Extension == ".TACTICS")
            {
                using FileStream input = File.OpenRead(barFilePath);
                // Locate the file within the BAR file.
                input.Seek(file.Offset, SeekOrigin.Begin);
                var data = new byte[file.FileSize2];
                await input.ReadAsync(data, 0, data.Length);

                if (Alz4Utils.IsAlz4File(data))
                {
                    data = await Alz4Utils.ExtractAlz4BytesAsync(data);
                }
                else
                {
                    if (L33TZipUtils.IsL33TZipFile(data))
                    {
                        data = await L33TZipUtils.ExtractL33TZippedBytesAsync(data);
                    }
                }
                Preview      = new Document();
                Preview.Text = System.Text.Encoding.UTF8.GetString(data);
                if (file.Extension == ".XS")
                {
                    Preview.SyntaxHighlighting = "C++";
                }
                else
                {
                    Preview.SyntaxHighlighting = "XML";
                }
                NotifyPropertyChanged("Preview");
                return;
            }

            return;
        }
Beispiel #21
0
        public static async Task <bool> ScanAndRepairFile(GameFileInfo fileInfo, string gameFilePath,
                                                          bool useChunkDownloader = false, IProgress <ScanSubProgress> progress = null,
#pragma warning disable IDE0034 // Simplifier l'expression 'default'
                                                          CancellationToken ct = default(CancellationToken))
#pragma warning restore IDE0034 // Simplifier l'expression 'default'
        {
            var filePath = Path.Combine(gameFilePath, fileInfo.FileName);

            //#1 Check File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Check, 0));

            Progress <double> subProgressCheck = null;

            if (progress != null)
            {
                subProgressCheck = new Progress <double>();
                subProgressCheck.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.Check, d));
                };
            }

            if (await RunFileCheck(filePath, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheck))
            {
                progress?.Report(new ScanSubProgress(ScanSubProgressStep.End, 100));
                return(true);
            }

            //#2 Download File
            ct.ThrowIfCancellationRequested();
            progress?.Report(new ScanSubProgress(ScanSubProgressStep.Download, 0));

            var tempFileName = Path.Combine(GameScannerTempPath, $"{fileInfo.FileName.GetHashCode():X4}.tmp");

            if (File.Exists(tempFileName))
            {
                File.Delete(tempFileName);
            }

            var fileDownloader = useChunkDownloader && fileInfo.BinSize > ChunkFileDownloader.ChunkSizeLimit
                ? new ChunkFileDownloader(fileInfo.HttpLink, tempFileName, GameScannerTempPath)
                : (IFileDownloader) new SimpleFileDownloader(fileInfo.HttpLink, tempFileName);

            if (progress != null)
            {
                fileDownloader.ProgressChanged += (sender, eventArg) =>
                {
                    switch (fileDownloader.State)
                    {
                    case FileDownloaderState.Invalid:
                    case FileDownloaderState.Download:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, fileDownloader.DwnlProgress * 0.99,
                                            new ScanDownloadProgress(fileDownloader.DwnlSize, fileDownloader.DwnlSizeCompleted,
                                                                     fileDownloader.DwnlSpeed)));
                        break;

                    case FileDownloaderState.Finalize:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 99,
                                            new ScanDownloadProgress(fileDownloader.DwnlSize, fileDownloader.DwnlSizeCompleted,
                                                                     0)));
                        break;

                    case FileDownloaderState.Complete:
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.Download, 100,
                                            new ScanDownloadProgress(fileDownloader.DwnlSize, fileDownloader.DwnlSizeCompleted,
                                                                     0)));
                        break;

                    case FileDownloaderState.Error:
                    case FileDownloaderState.Abort:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(fileDownloader.State),
                                                              fileDownloader.State, null);
                    }
                }
            }
            ;

            try
            {
                await fileDownloader.Download(ct);
            }
            catch (Exception e)
            {
                throw new Exception($"Downloaded file '{fileInfo.FileName}' failed!\r\n" +
                                    $"{e.Message}");
            }

            //#3 Check Downloaded File
            ct.ThrowIfCancellationRequested();

            Progress <double> subProgressCheckDown = null;

            if (progress != null)
            {
                progress.Report(new ScanSubProgress(ScanSubProgressStep.CheckDownload, 0));

                subProgressCheckDown = new Progress <double>();
                subProgressCheckDown.ProgressChanged += (o, d) =>
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckDownload, d));
                };
            }

            if (!await RunFileCheck(tempFileName, fileInfo.BinSize, fileInfo.BinCrc32, ct, subProgressCheckDown))
            {
                if (File.Exists(tempFileName))
                {
                    File.Delete(tempFileName);
                }

                throw new Exception($"Downloaded file '{fileInfo.FileName}' is invalid!");
            }

            //#4 Extract downloaded file
            ct.ThrowIfCancellationRequested();
            if (L33TZipUtils.IsL33TZipFile(tempFileName))
            {
                var tempFileName2 = $"{tempFileName.Replace(".tmp", string.Empty)}.ext.tmp";
                //
                Progress <double> extractProgress = null;
                if (progress != null)
                {
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.ExtractDownload, 0));

                    extractProgress = new Progress <double>();
                    extractProgress.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.ExtractDownload, d));
                    };
                }
                await L33TZipUtils.DoExtractL33TZipFile(tempFileName, tempFileName2, ct, extractProgress);

                //#4.1 Check Extracted File
                ct.ThrowIfCancellationRequested();
                Progress <double> subProgressCheckExt = null;
                if (progress != null)
                {
                    //
                    progress.Report(new ScanSubProgress(
                                        ScanSubProgressStep.CheckExtractDownload, 0));

                    subProgressCheckExt = new Progress <double>();
                    subProgressCheckExt.ProgressChanged += (o, d) =>
                    {
                        progress.Report(new ScanSubProgress(
                                            ScanSubProgressStep.CheckExtractDownload, d));
                    };
                }

                if (!await RunFileCheck(tempFileName2, fileInfo.Size, fileInfo.Crc32, ct, subProgressCheckExt))
                {
                    throw new Exception($"Extracted file '{fileInfo.FileName}' is invalid!");
                }

                tempFileName = tempFileName2;
            }

            //#5 Move new file to game folder
            ct.ThrowIfCancellationRequested();

            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.Finalize, 0));

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            else
            {
                var pathName = Path.GetDirectoryName(filePath);
                if (!string.IsNullOrEmpty(pathName) && !Directory.Exists(pathName))
                {
                    Directory.CreateDirectory(pathName);
                }
            }

            File.Move(tempFileName, filePath);

            //#6 End
            progress?.Report(new ScanSubProgress(
                                 ScanSubProgressStep.End, 100));

            return(true);
        }