예제 #1
0
        /// <summary>
        /// Processes work on two file
        /// </summary>
        /// <param name="main">The path to the main file.</param>
        /// <param name="secondary">The path to the secondary file.</param>
        /// <param name="target">The path to the target file.</param>
        /// <param name="messageHandler">The message handler.</param>
        /// <param name="init">The initialization label.</param>
        /// <param name="action">The action to process.</param>
        /// <returns></returns>
        private async Task WorkOnTwoFiles(string main, string secondary, string target, IMessageHandler messageHandler, string init, Func <CsvGamesList, CsvGamesList, CsvGamesList> action)
        {
            messageHandler.Init(init);

            try {
                var steps   = 5;
                var current = 0;

                var fiMain      = new FileInfo(main);
                var fiSecondary = new FileInfo(secondary);
                var fiTarget    = new FileInfo(target);

                messageHandler.Progress($"reading file {fiMain.Name}", steps, ++current);
                var mainEntries = await ReadFile(main, true);

                messageHandler.Progress($"reading file {fiSecondary.Name}", steps, ++current);
                var secondaryEntries = await ReadFile(secondary, true);

                messageHandler.Progress($"action", steps, ++current);
                var result = action(mainEntries, secondaryEntries);

                messageHandler.Progress($"save to file {fiTarget.Name}", steps, ++current);
                await WriteFile(result, target);

                messageHandler.Done($"Done! Result has {result.Games.Count} entries", target);
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }
예제 #2
0
        /// <summary>
        /// Converts a DAT file.
        /// </summary>
        /// <param name="main">The main file.</param>
        /// <param name="target">The target file.</param>
        /// <param name="messageHandler">The message handler.</param>
        public async Task ConvertDat(string main, string target, IMessageHandler messageHandler)
        {
            messageHandler.Init("DAT conversion");

            try {
                // read input file
                using (var reader = File.OpenRead(main)) {
                    // deserialize file
                    var datFile = Serializer.DeserializeXml <Models.DatFile.Datafile>(reader);

                    // output stream
                    using (var outStream = new FileStream(target, FileMode.Create, FileAccess.Write)) {
                        using (var outStreamWriter = new StreamWriter(outStream)) {
                            await outStreamWriter.WriteLineAsync(headerDatRow);

                            // list entries depending on if it's a list of machines or games
                            IEnumerable <Models.DatFile.BaseEntry> entries = datFile.Game != null && datFile.Game.Any()
                                                                ? datFile.Game
                                                                : datFile.Machine;

                            int total = entries.Count();
                            int i     = 0;
                            foreach (var e in entries)
                            {
                                i++;
                                messageHandler.Progress($"Converting {e.Name}", total, i);

                                var sb = new StringBuilder();
                                sb.Append($"{e.Name}{defaultDelimiter}");
                                sb.Append($"{e.Description ?? "-"}{defaultDelimiter}");
                                sb.Append($"{e.Year ?? "-"}{defaultDelimiter}");
                                sb.Append($"{e.Manufacturer ?? "-"}{defaultDelimiter}");

                                if (e is Models.DatFile.Game)
                                {
                                    var eg = e as Models.DatFile.Game;

                                    sb.Append(string.IsNullOrEmpty(eg.Cloneof) ? "NO" : "YES").Append(defaultDelimiter);     // is_parent
                                    sb.Append(eg.Romof ?? "-").Append(defaultDelimiter);                                     // romof
                                    sb.Append(string.IsNullOrEmpty(eg.Cloneof) ? "YES" : "NO").Append(defaultDelimiter);     // is_clone
                                    sb.Append(eg.Cloneof ?? "-").Append(defaultDelimiter);                                   // cloneof
                                    sb.Append(eg.Sampleof ?? "-").Append(defaultDelimiter);                                  // sampleof
                                }
                                else
                                {
                                    sb.Append("-;-;-;-;-;");
                                }

                                await outStreamWriter.WriteLineAsync(sb.ToString());
                            }
                        }
                    }

                    messageHandler.Done("DAT file converted", target);
                }
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }
예제 #3
0
        /// <summary>
        /// Deletes roms from a folder
        /// </summary>
        /// <param name="args">The arguments</param>
        /// <param name="messageHandler">The message handler.</param>
        /// <exception cref="FileNotFoundException">Unable to find main CSV file</exception>
        /// <exception cref="DirectoryNotFoundException">Unable to find selection folder {args.selection}</exception>
        public async Task Delete(Actions.RomsAction args, IMessageHandler messageHandler)
        {
            messageHandler.Init("Deleting roms");

            try {
                // check files and folders
                if (!File.Exists(args.main))
                {
                    throw new FileNotFoundException("Unable to find main CSV file", args.main);
                }
                if (!Directory.Exists(args.selection))
                {
                    throw new DirectoryNotFoundException($"Unable to find selection folder {args.selection}");
                }

                // read CSV file
                var content = await csvService.ReadFile(args.main, false);

                var total   = content.Games.Count();
                var i       = 0;
                var deleted = 0;

                foreach (var f in content.Games)
                {
                    if (messageHandler.MustCancel)
                    {
                        break;
                    }
                    i++;

                    // build vars
                    var game     = f.Name;
                    var zip      = $"{game}.zip";
                    var filePath = Path.Join(args.selection, zip);

                    messageHandler.Progress(game, total, i);

                    if (File.Exists(filePath))
                    {
                        File.Delete(filePath);
                        deleted++;
                    }
                }

                messageHandler.Done($"Deleted {deleted} file(s)", args.selection);
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }
예제 #4
0
        /// <summary>
        /// Keeps only listed roms in a folder
        /// </summary>
        /// <param name="args">The arguments</param>
        /// <param name="messageHandler">The message handler.</param>
        /// <exception cref="FileNotFoundException">Unable to find main CSV file</exception>
        /// <exception cref="DirectoryNotFoundException">Unable to find selection folder {args.selection}</exception>
        public async Task Keep(Actions.RomsAction args, IMessageHandler messageHandler)
        {
            messageHandler.Init("Filtering roms");

            try {
                // check files and folders
                if (!File.Exists(args.main))
                {
                    throw new FileNotFoundException("Unable to find main CSV file", args.main);
                }
                if (!Directory.Exists(args.selection))
                {
                    throw new DirectoryNotFoundException($"Unable to find selection folder {args.selection}");
                }

                // read CSV file
                var content = await csvService.ReadFile(args.main, false);

                // get list of files
                var files = (new DirectoryInfo(args.selection)).GetFiles("*.zip");

                var total   = content.Games.Count();
                var i       = 0;
                var deleted = 0;

                // check if files exist in games list
                foreach (var f in files)
                {
                    if (messageHandler.MustCancel)
                    {
                        break;
                    }
                    i++;

                    messageHandler.Progress(f.Name, total, i);

                    if (!content.Games.Any(c => $"{c.Name}.zip" == f.Name))
                    {
                        File.Delete(f.FullName);
                        deleted++;
                    }
                }

                messageHandler.Done($"Deleted {deleted} files", args.selection);
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }
예제 #5
0
        /// <summary>
        /// Lists the files in a folder to a CSV file.
        /// </summary>
        /// <param name="main">The main folder.</param>
        /// <param name="target">The target CSV file.</param>
        /// <param name="messageHandler">The message handler.</param>
        /// <exception cref="DirectoryNotFoundException">Unable to find the folder {main}</exception>
        public async Task ListFiles(string main, string target, IMessageHandler messageHandler)
        {
            messageHandler.Init("List files to a CSV");

            try {
                if (!Directory.Exists(main))
                {
                    throw new DirectoryNotFoundException($"Unable to find the folder {main}");
                }

                var di = new DirectoryInfo(main);

                using (var output = new StreamWriter(target, false)) {
                    await output.WriteLineAsync($"{nameColumn}{defaultDelimiter}");

                    var files = di.GetFiles("*.zip", new EnumerationOptions {
                        MatchCasing = MatchCasing.CaseInsensitive
                    });
                    var total = files.Length;
                    var i     = 0;

                    foreach (var f in files)
                    {
                        i++;
                        messageHandler.Progress($"Listing file {f.Name}", total, i);

                        await output.WriteLineAsync(f.Name.Replace(".zip", "", StringComparison.InvariantCultureIgnoreCase) + defaultDelimiter);
                    }
                }

                messageHandler.Done("Files listed", target);
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }
예제 #6
0
        /// <summary>
        /// Copies roms
        /// </summary>
        /// <param name="args">The arguments</param>
        /// <param name="messageHandler">The message handler.</param>
        /// <exception cref="FileNotFoundException">Unable to find main CSV file</exception>
        /// <exception cref="DirectoryNotFoundException">Unable to find romset folder {args.romset}</exception>
        public async Task Add(Actions.RomsAction args, IMessageHandler messageHandler)
        {
            messageHandler.Init("Copying roms");

            try {
                // check files and folders
                if (!File.Exists(args.main))
                {
                    throw new FileNotFoundException("Unable to find main CSV file", args.main);
                }
                if (!Directory.Exists(args.romset))
                {
                    throw new DirectoryNotFoundException($"Unable to find romset folder {args.romset}");
                }
                if (!Directory.Exists(args.selection))
                {
                    Directory.CreateDirectory(args.selection);
                }

                // read CSV file
                var content = await csvService.ReadFile(args.main, false);

                var total  = content.Games.Count();
                var i      = 0;
                var copied = 0;

                // copy each file found in CSV
                foreach (var f in content.Games)
                {
                    if (messageHandler.MustCancel)
                    {
                        break;
                    }

                    i++;

                    // build vars
                    var game      = f.Name;
                    var zip       = $"{game}.zip";
                    var sourceRom = Path.Join(args.romset, zip);
                    var destRom   = Path.Join(args.selection, zip);

                    if (File.Exists(sourceRom))
                    {
                        var fi = new FileInfo(sourceRom);

                        messageHandler.Progress($"{game} ({FileSystem.HumanSize(fi.Length)})", total, i);

                        // copy rom
                        if (!File.Exists(destRom) || args.overwrite)
                        {
                            File.Copy(sourceRom, destRom, true);
                            copied++;
                        }

                        // try to copy chd if it can be found
                        var sourceChd = Path.Join(args.romset, game);
                        var targetChd = Path.Join(args.selection, game);
                        if (Directory.Exists(sourceChd))
                        {
                            if (messageHandler.MustCancel)
                            {
                                break;
                            }

                            messageHandler.Progress($"Copying {game} CHD ({FileSystem.HumanSize(FileSystem.DirectorySize(sourceChd))})", total, i);

                            FileSystem.DirectoryCopy(sourceChd, targetChd, args.overwrite, false);
                        }
                    }
                }

                messageHandler.Done($"Copied {copied} file(s)", args.selection);
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }
예제 #7
0
        /// <summary>
        /// Downloads an overlay pack
        /// </summary>
        /// <param name="data">The parameters</param>
        /// <param name="messageHandler">The message handler.</param>
        /// <exception cref="FileNotFoundException">Unable to parse rom config {game} to find overlay (input_overlay)
        /// or
        /// Unable to parse overlay config {game} to find image (overlay0_overlay)</exception>
        public async Task Download(Actions.OverlaysAction data, IMessageHandler messageHandler)
        {
            messageHandler.Init("Download overlay pack");

            try {
                var os   = ArcadeManagerEnvironment.SettingsOs;
                var pack = ArcadeManagerEnvironment.AppData.Overlays.Where(o => o.Name == data.pack).First();

                // check if the destination of rom cfg is the rom folder
                var romCfgFolder = pack.Roms.Dest[os] == "roms"
                                        ? null                                              // save rom cfg directly into rom folder(s)
                                        : Path.Join(data.configFolder, pack.Roms.Dest[os]); // save rom cfg in config folder

                // list the available rom configs
                messageHandler.Progress("list of files to download", 1, 100);
                var romConfigs = await downloaderService.ListFiles(pack.Repository, pack.Roms.Src);

                // download common files
                messageHandler.Progress("common files", 1, 100);
                if (pack.Common != null && !string.IsNullOrWhiteSpace(pack.Common.Src))
                {
                    await DownloadCommon(pack, Path.Join(data.configFolder, pack.Common.Dest[os]), data.overwrite, data.ratio, messageHandler, 100, 1);
                }

                if (messageHandler.MustCancel)
                {
                    throw new Exception("Operation cancelled");
                }

                // check that thvere is a matching game in any of the roms folders
                messageHandler.Progress("games list to process", 1, 100);
                var processedOverlays = new List <string>();
                var romsToProcess     = GetRomsToProcess(data.romFolders, romConfigs.Tree);

                var total     = romConfigs.Tree.Count;
                var current   = 0;
                var installed = 0;

                foreach (var r in romsToProcess.OrderBy(r => r.Game))
                {
                    if (messageHandler.MustCancel)
                    {
                        throw new Exception("Operation cancelled");
                    }

                    current++;

                    var game = r.Game;

                    messageHandler.Progress($"{game}: download overlay (rom config)", total, current);

                    // download the rom config and extract the overlay file name
                    var romConfigContent = string.Empty;
                    foreach (var romFolder in r.TargetFolder)
                    {
                        if (messageHandler.MustCancel)
                        {
                            throw new Exception("Operation cancelled");
                        }

                        var romConfigFile = Path.Join(romFolder, $"{game}.zip.cfg");

                        // get rom config content
                        if (string.IsNullOrEmpty(romConfigContent))
                        {
                            if (data.overwrite || !File.Exists(romConfigFile))
                            {
                                // file doesn't exist or we'll overwrite it
                                romConfigContent = await downloaderService.DownloadFileText(pack.Repository, $"{pack.Roms.Src}/{game}.zip.cfg");

                                // fix resolution and paths
                                romConfigContent = ChangeResolution(romConfigContent, data.ratio);
                                romConfigContent = FixPaths(romConfigContent, pack);
                            }
                            else
                            {
                                // file exist, we don"t overwrite: read it
                                romConfigContent = await File.ReadAllTextAsync(romConfigFile);
                            }
                        }

                        // write rom config
                        if (data.overwrite || !File.Exists(romConfigFile))
                        {
                            if (messageHandler.MustCancel)
                            {
                                throw new Exception("Operation cancelled");
                            }

                            await File.WriteAllTextAsync(romConfigFile, romConfigContent);

                            installed++;
                        }
                    }

                    if (messageHandler.MustCancel)
                    {
                        throw new Exception("Operation cancelled");
                    }

                    messageHandler.Progress($"{game}: download overlay (config)", total, current);

                    // extract the overlay file name
                    var overlayPath = GetCfgData(romConfigContent, "input_overlay");
                    if (string.IsNullOrWhiteSpace(overlayPath))
                    {
                        throw new FileNotFoundException($"Unable to parse rom config {game} to find overlay (input_overlay)");
                    }
                    var overlayFi         = new FileInfo(overlayPath);
                    var overlayConfigDest = Path.Join(data.configFolder, overlayFi.Name);

                    // download the overlay file name and extract the image file name
                    var overlayConfigContent = string.Empty;
                    if (data.overwrite || !File.Exists(overlayConfigDest))
                    {
                        if (messageHandler.MustCancel)
                        {
                            throw new Exception("Operation cancelled");
                        }

                        overlayConfigContent = await downloaderService.DownloadFileText(pack.Repository, $"{pack.Overlays.Src}/{overlayFi.Name}");

                        // fix path
                        overlayConfigContent = FixPaths(overlayConfigContent, pack);

                        await File.WriteAllTextAsync(overlayConfigDest, overlayConfigContent);
                    }
                    else
                    {
                        overlayConfigContent = File.ReadAllText(overlayConfigDest);
                    }

                    if (messageHandler.MustCancel)
                    {
                        throw new Exception("Operation cancelled");
                    }

                    messageHandler.Progress($"{game}: download overlay (image)", total, current);

                    // extract the image file name
                    var imagePath = GetCfgData(overlayConfigContent, "overlay0_overlay");
                    if (string.IsNullOrWhiteSpace(imagePath))
                    {
                        throw new FileNotFoundException($"Unable to parse overlay config {game} to find image (overlay0_overlay)");
                    }
                    var imageFi   = new FileInfo(imagePath);
                    var imageDest = Path.Join(data.configFolder, imageFi.Name);

                    // download the image
                    if (data.overwrite || !File.Exists(imageDest))
                    {
                        if (messageHandler.MustCancel)
                        {
                            throw new Exception("Operation cancelled");
                        }

                        await downloaderService.DownloadFile(pack.Repository, $"{pack.Overlays.Src}/{imageFi.Name}", imageDest);
                    }
                }

                messageHandler.Done($"Installed {installed} overlays", null);
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }
예제 #8
0
        /// <summary>
        /// Converts a INI file to CSV
        /// </summary>
        /// <param name="main">The main file</param>
        /// <param name="target">The target folder to create files into</param>
        /// <param name="messageHandler">The message handler.</param>
        public async Task ConvertIni(string main, string target, IMessageHandler messageHandler)
        {
            messageHandler.Init("INI conversion");

            try {
                var data = new Dictionary <string, List <IniEntry> >();

                var mainInfo = new FileInfo(main);

                using (var source = new StreamReader(main)) {
                    var isFolderSetting = false;
                    var currentSection  = "";

                    while (!source.EndOfStream)
                    {
                        var line = (await source.ReadLineAsync()).Trim();

                        // progress up to 50%
                        messageHandler.Progress("Reading source file", 100, (int)(source.BaseStream.Position / mainInfo.Length * 50));

                        // ignore empty lines and comments
                        if (string.IsNullOrWhiteSpace(line) || line.StartsWith(";"))
                        {
                            continue;
                        }

                        // ignore folder settings
                        if (line == "[FOLDER_SETTINGS]")
                        {
                            isFolderSetting = true;
                            continue;
                        }

                        if (isFolderSetting && !line.StartsWith("["))
                        {
                            continue;
                        }

                        // we're out of folder settings
                        isFolderSetting = false;

                        // found a section
                        if (line.StartsWith("["))
                        {
                            currentSection = line;

                            // add to data
                            if (!data.ContainsKey(currentSection))
                            {
                                data.Add(currentSection, new List <IniEntry>());
                            }

                            continue;
                        }

                        // we're in a section data
                        if (line.IndexOf("=") > 0)
                        {
                            // game=value
                            var split = line.Split("=", StringSplitOptions.TrimEntries);
                            data[currentSection].Add(new IniEntry {
                                game = split[0], value = split[1]
                            });
                        }
                        else
                        {
                            // simple games list
                            data[currentSection].Add(new IniEntry {
                                game = line
                            });
                        }
                    }
                }

                // create a file for each non-empty section
                var i = 0;
                foreach (var entry in data.Where(d => d.Value.Any()))
                {
                    i++;

                    // file name = sanitized section name, or source name if there's only one section
                    var name = data.Count > 1 ? Sanitize(entry.Key.Trim("[]".ToCharArray())) : mainInfo.Name.Replace(".ini", "");
                    name += ".csv";

                    var path = Path.Join(target, name);

                    // create increments to not overwrite existing conversions
                    var j         = 0;
                    var finalPath = path;
                    while (File.Exists(finalPath))
                    {
                        finalPath = path.Replace(".csv", $" ({++j}).csv");
                    }
                    path = finalPath;

                    // progress from 50%
                    messageHandler.Progress($"Creating file {name}", 100, 50 + (i / data.Count * 50));

                    // write into file
                    using (var output = new StreamWriter(path)) {
                        await output.WriteLineAsync(headerIniRow);

                        foreach (var iniEntry in entry.Value)
                        {
                            await output.WriteLineAsync($"{iniEntry.game}{defaultDelimiter}{iniEntry.value}{defaultDelimiter}");
                        }
                    }
                }

                messageHandler.Done("INI file converted", target);
            }
            catch (Exception ex) {
                messageHandler.Error(ex);
            }
        }