Beispiel #1
0
        static void Main(string[] args)
        {
            // Parse args. All CLI args override the configuration loaded from the file
            Options o = ParseArgs(args);

            // Read configuration file, or get a new default configuration if no file exists
            AppConfiguration config = ParseConfig(o.ConfigFile, o);

            // Get the emulator configuration
            EmulatorConfiguration emulators = ParseEmulators(config, o);

            if (o.Frontend)
            {
                HideConsole();
                InitializeFrontend();
            }
            else if (o.Gui)
            {
                HideConsole();
                InitializeGui();
            }
            else
            {
                ShowConsole();
                ConsoleProcessor.Main(emulators, o);
                // Pausing after completion is done for when you forced the console on
                // because the app is set to compile as a windowed app instead of a console app
                // but when it is, i get no console display even when i force the console to open
                // using ShowConsole(), and when outputting as a console app I have to press a key
                // twice. Removing it for now.
                //Console.WriteLine("Press any key to exit...");
                //Console.ReadKey();
            }
        }
Beispiel #2
0
 /// <summary>
 /// This method walks through every configured emulator and uses it to find roms and
 /// turn those roms into shortcuts for Steam.
 /// Each rom will be turned into a shortcut where the Target is the configured emulator EXE,
 /// the Launch Options will be the configured emulator parameters (with substitutions), including
 /// rom file and any emulator start parameters like fullscreen mode or config files, and whose
 /// name is parsed from the rom regex grouping, or from the rom filename if no grouping is specified.
 /// Icons will also be assigned, once I figure out how that works. To start with, icons will be
 /// loaded from files using the image regex.
 /// </summary>
 /// <param name="emulators"></param>
 /// <param name="shortcuts"></param>
 private static void GenerateShortcutsFromRoms(EmulatorConfiguration emulators, ICollection <Shortcut> shortcuts)
 {
     foreach (Emulator emu in emulators)
     {
         GenerateSteamShortcutsFromRoms(emu, shortcuts);
     }
 }
Beispiel #3
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="emulatorsFilename"></param>
 /// <returns></returns>
 private static EmulatorConfiguration ParseEmulators(AppConfiguration config, Options options)
 {
     if (File.Exists(options.EmulatorsFile))
     {
         return(EmulatorConfiguration.Parse(options.EmulatorsFile, config));
     }
     else
     {
         return(null);
     }
 }
Beispiel #4
0
        public static void Main(EmulatorConfiguration emulators, Options o)
        {
            if (emulators == null)
            {
                // Error out?
                Console.Error.WriteLine("Couldn't read emulator configuration from file " + o.EmulatorsFile);
                return;
            }
            SteamTools steam = new SteamTools();

            string shortcutsFile = o.ShortcutsFile;
            string user          = null;

            if ("steam".Equals(o.Output))
            {
                if (String.IsNullOrWhiteSpace(shortcutsFile))
                {
                    // Load Steam shortcuts. SteamTools will worry about where the file is and how to read it
                    string steamBase = SteamTools.GetSteamLocation();
                    if (steamBase == null)
                    {
                        Console.Error.WriteLine("No Steam installation found.");
                        return;
                    }
                    Console.WriteLine($"Found Steam installed at '{steamBase}'", steamBase);

                    string[] users = SteamTools.GetUsers(steamBase);
                    if (users.Length == 0)
                    {
                        Console.Error.WriteLine("No Steam users found.");
                        return;
                    }
                    else if (users.Length > 1)
                    {
                        if (!string.IsNullOrWhiteSpace(o.SteamUser))
                        {
                            user = o.SteamUser;
                        }
                        else
                        {
                            Console.Error.WriteLine("More than 1 Steam user found and no Steam User found in command line options, quitting...");
                            return;
                        }
                    }
                    else
                    {
                        user = users[0];
                    }

                    Console.WriteLine($"Using Steam user '{user}'", user);

                    shortcutsFile = SteamTools.GetShortcutsFile(steamBase, user);
                }
                Console.WriteLine($"Loading Steam shortcuts file '{shortcutsFile}'", shortcutsFile);

                SteamShortcuts shortcuts = SteamTools.LoadShortcuts(shortcutsFile);

                // Analyze all emulator configs, read matching roms, create new shortcuts for each rom
                GenerateShortcutsFromRoms(emulators, shortcuts);
                // Don't do anything if Steam is going!
                if (steam.IsSteamRunning())
                {
                    Console.Error.WriteLine("Steam is running! Exit Steam before running this app.");
                    return;
                }

                SteamTools.WriteSteamShortcuts(shortcuts, shortcutsFile);
                SteamTools.AddGridImages(shortcuts, user);
                return;
            }
            else
            {
                ICollection <Shortcut> shortcuts;
                if (!string.IsNullOrWhiteSpace(o.Input))
                {
                    FileStream file = System.IO.File.OpenRead(o.Input);
                    // TODO: error checking on file open.

                    shortcuts = ReadShortcuts(file);
                    file.Close();
                }
                else
                {
                    shortcuts = new List <Shortcut>();

                    // Analyze all emulator configs, read matching roms, create new shortcuts for each rom
                    GenerateShortcutsFromRoms(emulators, shortcuts);
                }

                // Write the steam shortcuts back to the file
                if ("console".Equals(o.Output))
                {
                    PrintShortcuts(shortcuts);
                }
                else if (string.IsNullOrWhiteSpace(o.Output) || "none".Equals(o.Output))
                {
                    // do nothing
                }
                else
                {
                    // Anything else is a file or directory

                    // A path with an extension is hopefully a valid path to a file for saving the results
                    if (Path.HasExtension(o.Output))
                    {
                        try
                        {
                            string path = Path.GetFullPath(o.Output);
                            if (path == null) // I feel like this shouldn't happen, since it would throw an exception rather than returning null
                            {
                                Console.Error.WriteLine($"The output path '{o.Output}' is null, empty or not a valid windows path.");
                                return;
                            }
                            string filename = Path.GetFileName(path);
                            string dirname  = Path.GetDirectoryName(path);
                            Directory.CreateDirectory(dirname);
                            StreamWriter outfile = System.IO.File.CreateText(path);

                            WriteShortcutsFile(shortcuts, outfile);
                            outfile.Close();
                        }
                        catch (System.Security.SecurityException)
                        {
                            Console.Error.WriteLine($"Security exception when trying to open file {o.Output} for writing.");
                            return;
                        }
                        catch (UnauthorizedAccessException)
                        {
                            Console.Error.WriteLine($"You don't have permission to open file {o.Output} for writing.");
                            return;
                        }
                        catch (ArgumentException)
                        {
                            Console.Error.WriteLine($"The output path '{o.Output}' is null, empty or not a valid windows path.");
                            return;
                        }
                        catch (PathTooLongException)
                        {
                            Console.Error.WriteLine($"The output path '{o.Output}' is too long.");
                            return;
                        }
                        catch (NotSupportedException e)
                        {
                            Console.Error.WriteLine($"Threw NotSupportedException when trying to open file at '{o.Output}', with this message: {e.Message}");
                            return;
                        }
                    }
                    else // otherwise we're looking at a directoy, where we spit out windows shortcuts
                    {
                        try
                        {
                            string path = Path.GetFullPath(o.Output);
                            if (path == null) // I feel like this shouldn't happen, since it would throw an exception rather than returning null
                            {
                                Console.Error.WriteLine($"The output path '{o.Output}' is null, empty or not a valid windows path.");
                                return;
                            }
                            DirectoryInfo dir = null;
                            try
                            {
                                dir = Directory.CreateDirectory(path);
                            }
                            catch (ArgumentException)
                            {
                                Console.Error.WriteLine($"The output directory '{o.Output}' is null, empty or not a valid windows path.");
                                return;
                            }
                            MakeWindowsShortcuts(shortcuts, dir);
                        }
                        catch (System.Security.SecurityException)
                        {
                            Console.Error.WriteLine($"Security exception when trying to write shortcuts to directory '{o.Output}'.");
                            return;
                        }
                        catch (UnauthorizedAccessException)
                        {
                            Console.Error.WriteLine($"You don't have permission to access directory '{o.Output}'.");
                            return;
                        }
                        catch (PathTooLongException)
                        {
                            Console.Error.WriteLine($"The output path '{o.Output}' is too long.");
                            return;
                        }
                        catch (NotSupportedException e)
                        {
                            Console.Error.WriteLine($"Threw NotSupportedException when trying to write shortcuts to directory '{o.Output}', with this message: {e.Message}");
                            return;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Document this, here and in the actual code
        /// </summary>
        /// <param name="emulatorsFilename"></param>
        /// <returns></returns>
        internal static EmulatorConfiguration Parse(string emulatorsFilename, AppConfiguration appConfig)
        {
            // TODO: Should the defined variables be cleared between calls to parse?
            var     parser = new FileIniDataParser();
            IniData data   = parser.ReadFile(emulatorsFilename);
            EmulatorConfiguration config = new EmulatorConfiguration
            {
                emulators = new List <Emulator>()
            };

            foreach (KeyData key in data.Global)
            {
                config.keys[key.KeyName] = config.ExpandVariables(key.Value, config.keys);
            }

            foreach (SectionData section in data.Sections)
            {
                Emulator emu = new Emulator
                {
                    Category = section.SectionName
                };

                // config.keys has global keys, and we have a local set of keys that has global keys and keys defined in this section
                Dictionary <string, string> emuKeys = new Dictionary <string, string>(config.keys);
                foreach (KeyData key in section.Keys)
                {
                    // see the documentation for Validate for more info on these attributes and what they should be
                    switch (key.KeyName)
                    {
                    case "Category":       if (!string.IsNullOrWhiteSpace(key.Value))
                        {
                            emu.Category = config.ExpandVariables(key.Value, emuKeys);
                        }
                        break;

                    case "Platform":       emu.Executable = config.ExpandVariables(key.Value, emuKeys); break;

                    case "Executable":     emu.Executable = config.ExpandVariables(key.Value, emuKeys); break;

                    case "StartIn":        emu.StartIn = config.ExpandVariables(key.Value, emuKeys); break;

                    case "Parameters":     emu.Parameters = config.ExpandVariables(key.Value, emuKeys); break;

                    case "RomBasePath":    emu.RomBasePath = config.ExpandVariables(key.Value, emuKeys);    break;

                    case "TitlePattern":   emu.TitlePattern = config.ExpandVariables(key.Value, emuKeys); break;

                    case "RomRegex":       emu.RomRegex = config.ExpandVariables(key.Value, emuKeys);   break;

                    case "GridBasePath":   emu.GridBasePath = config.ExpandVariables(key.Value, emuKeys);  break;

                    case "GridRegex":      emu.GridRegex = config.ExpandVariables(key.Value, emuKeys); break;

                    case "IconBasePath":   emu.IconBasePath = config.ExpandVariables(key.Value, emuKeys); break;

                    case "IconRegex":      emu.IconRegex = config.ExpandVariables(key.Value, emuKeys); break;

                    case "BoxartBasePath": emu.BoxartBasePath = config.ExpandVariables(key.Value, emuKeys); break;

                    case "BoxartRegex":    emu.BoxartRegex = config.ExpandVariables(key.Value, emuKeys); break;

                    default:     // Default is to add new key/value pairs for use elsewhere
                        emuKeys[key.KeyName] = config.ExpandVariables(key.Value, emuKeys);
                        break;
                    }
                }

                emu.SetDefaults(appConfig);
                emu.ExpandVariables();
                config.emulators.Add(emu);
            }
            Validate(config);
            return(config);
        }
 /// <summary>
 /// Validates the emu config, ensuring that all required variables are provided,
 /// values are in the correct format and paths are valid.
 /// This doesn't validate that the executable exists or that the parameters
 /// are valid for the executable, but paths must be valid.
 /// The values stored in each emulator will be validated.
 /// Any failures to valid will be thrown altogether in an exception.
 /// Also, ANY attributes that contain an unexpanded %{...} variable will result in a warning.
 ///
 /// Category: (required) Replaces the emu category if it is not empty, otherwise the category is the section name. Should always be valid.
 ///           Error if missing (shouldn't be missing).
 ///           Error if contains characters not allowed in a file path.
 /// Platform: (optional) Should be a lowercase platform "code" like nes,snes,wii. For now I don't validate this value, just store it.
 ///           No errors or warnings.
 /// Executable: (required) An executable program.
 ///             Error if missing.
 ///             Error if not a valid URI.
 ///             Warning if file doesn't exist.
 /// StartIn: (required) Technically optional but if missing it will be defaulted to the parent of the executable. This is the working directory for the executable and should be a valid URI.
 ///          Error if missing (shouldn't be missing).
 ///          Error if not a valid URI.
 ///          Warning if directory doesn't exist.
 /// Parameters: (optional) The parameters to pass to the executable. Can be anything.
 ///          No errors or warnings.
 /// RomBasePath: (required) The directory that you keep all your roms in. RomRegex will match child paths to this directory.
 ///              Error if missing.
 ///              Error if not a valid path.
 ///              Error if directory doesn't exist.
 /// RomRegex: (required) Regular expression to match relative rom paths.
 ///           Error if missing.
 ///           Error if not a valid regular expression.
 /// TitlePattern: (optional) Text to use as each rom's title. There should be at least one rom-specific substitution parameter in it or every rom will have the same title!
 ///               If missing, defaults to %n.
 ///               Warning if no rom-specific substitutions are included - %P, %p, %R, %r, %n, %D, %d
 /// IconBasePath: (optional) The base directory that contains .ico or .exe files to use for rom shortcut icons.
 ///               Error if path not valid.
 ///               Error if directory doesn't exist.
 /// IconRegex: (optional) Regex file used to locate an icon for each rom. Can be the same icon for each rom, or use rom-specific substitution parameters to get different icons for each rom.
 ///            Error if path not valid.
 ///            Error if directory doesn't exist.
 /// GridBasePath: (optional) The base directory that contains image files to use for the steam grid.
 ///                Error if path not valid.
 ///                Error if directory doesn't exist.
 /// GridRegex: (optional) Regex file used to locate a steam grid image for each rom. Can be the same image for each rom, or use rom-specific substitution parameters to get different icons for each rom.
 ///            Error if not a valid regular expression.
 /// BoxartBasePath: (optional) The base directory that contains box art image files.
 ///                 Error if path not valid.
 ///                 Error if directory doesn't exist.
 /// BoxartRegex: (optional) Regex file used to locate the box art image for each rom. Can be the same image for each rom, or use rom-specific substitution parameters to get different icons for each rom.
 ///              Error if not a valid regular expression.
 /// </summary>
 /// <exception cref="ParseError">Errors and warnings indicated any part of the config that failed validation.</exception>
 /// <param name="config">Emulator config to validate.</param>
 private static void Validate(EmulatorConfiguration config)
 {
     // TODO: Validate parsed configuration
 }