using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Xml.Serialization; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using System.Text.RegularExpressions; using System.Reflection; using System.Windows.Forms; namespace Mesen.GUI.Config { class ConfigManager { private static Configuration _config; private static Configuration _dirtyConfig; public static bool DoNotSaveSettings { get; set; } public static string DefaultPortableFolder { get { return Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); } } public static string DefaultDocumentsFolder { get { if(Program.IsMono) { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), ".config", "mesen"); } else { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Mesen"); } } } public static string DefaultAviFolder { get { return Path.Combine(HomeFolder, "Avi"); } } public static string DefaultMovieFolder { get { return Path.Combine(HomeFolder, "Movies"); } } public static string DefaultSaveDataFolder { get { return Path.Combine(HomeFolder, "Saves"); } } public static string DefaultSaveStateFolder { get { return Path.Combine(HomeFolder, "SaveStates"); } } public static string DefaultScreenshotFolder { get { return Path.Combine(HomeFolder, "Screenshots"); } } public static string DefaultWaveFolder { get { return Path.Combine(HomeFolder, "Wave"); } } public static void InitHomeFolder() { string portableFolder = DefaultPortableFolder; string legacyPortableFolder = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Mesen"); string documentsFolder = DefaultDocumentsFolder; //Linux only string legacyDocumentsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Mesen"); string portableConfig = Path.Combine(portableFolder, "settings.xml"); string legacyPortableConfig = Path.Combine(legacyPortableFolder, "settings.xml"); string documentsConfig = Path.Combine(documentsFolder, "settings.xml"); string legacyDocumentsConfig = Path.Combine(legacyDocumentsFolder, "settings.xml"); HomeFolder = null; if(File.Exists(portableConfig)) { HomeFolder = portableFolder; } else if(File.Exists(legacyPortableConfig)) { HomeFolder = legacyPortableFolder; } else if(Program.IsMono && File.Exists(legacyDocumentsConfig)) { HomeFolder = legacyDocumentsFolder; } else if(File.Exists(documentsConfig)) { HomeFolder = documentsFolder; } } public static string GetConfigFile() { InitHomeFolder(); if(!string.IsNullOrWhiteSpace(HomeFolder)) { return Path.Combine(HomeFolder, "settings.xml"); } else { return null; } } public static void CreateConfig(bool portable) { if(portable) { HomeFolder = DefaultPortableFolder; } else { HomeFolder = DefaultDocumentsFolder; } LoadConfig(); } private static object _initLock = new object(); private static void LoadConfig() { if(_config == null) { lock(_initLock) { if(_config == null) { if(File.Exists(ConfigFile)) { _config = Configuration.Deserialize(ConfigFile); _dirtyConfig = Configuration.Deserialize(ConfigFile); } else { //Create new config file and save it to disk _config = new Configuration(); _dirtyConfig = new Configuration(); _config.Save(); } } } } } private static void ApplySetting(Type type, object instance, string name, string value) { FieldInfo[] fields = type.GetFields(); foreach(FieldInfo info in fields) { if(string.Compare(info.Name, name, true) == 0) { try { if(info.FieldType == typeof(int) || info.FieldType == typeof(uint) || info.FieldType == typeof(double)) { MinMaxAttribute minMaxAttribute = info.GetCustomAttribute(typeof(MinMaxAttribute)) as MinMaxAttribute; if(minMaxAttribute != null) { if(info.FieldType == typeof(int)) { int result; if(int.TryParse(value, out result)) { if(result >= (int)minMaxAttribute.Min && result <= (int)minMaxAttribute.Max) { info.SetValue(instance, result); } } } else if(info.FieldType == typeof(uint)) { uint result; if(uint.TryParse(value, out result)) { if(result >= (uint)(int)minMaxAttribute.Min && result <= (uint)(int)minMaxAttribute.Max) { info.SetValue(instance, result); } } } else if(info.FieldType == typeof(double)) { double result; if(double.TryParse(value, out result)) { if(result >= (double)minMaxAttribute.Min && result <= (double)minMaxAttribute.Max) { info.SetValue(instance, result); } } } } else { ValidValuesAttribute validValuesAttribute = info.GetCustomAttribute(typeof(ValidValuesAttribute)) as ValidValuesAttribute; if(validValuesAttribute != null) { uint result; if(uint.TryParse(value, out result)) { if(validValuesAttribute.ValidValues.Contains(result)) { info.SetValue(instance, result); } } } } } else if(info.FieldType == typeof(bool)) { if(string.Compare(value, "false", true) == 0) { info.SetValue(instance, false); } else if(string.Compare(value, "true", true) == 0) { info.SetValue(instance, true); } } else if(info.FieldType.IsEnum) { int indexOf = Enum.GetNames(info.FieldType).Select((enumValue) => enumValue.ToLower()).ToList().IndexOf(value.ToLower()); if(indexOf >= 0) { info.SetValue(instance, indexOf); } } } catch { } break; } } } public static void ProcessSwitches(List switches) { Regex regex = new Regex("/([a-z0-9_A-Z.]+)=([a-z0-9_A-Z.\\-]+)"); foreach(string param in switches) { Match match = regex.Match(param); if(match.Success) { string switchName = match.Groups[1].Value; string switchValue = match.Groups[2].Value; ApplySetting(typeof(VideoInfo), Config.VideoInfo, switchName, switchValue); ApplySetting(typeof(AudioInfo), Config.AudioInfo, switchName, switchValue); ApplySetting(typeof(EmulationInfo), Config.EmulationInfo, switchName, switchValue); ApplySetting(typeof(Configuration), Config, switchName, switchValue); } } } public static void SaveConfig() { _config.Save(); } public static string HomeFolder { get; private set; } public static string GetFolder(string defaultFolderName, string overrideFolder, bool useOverride) { string folder; if(useOverride) { folder = overrideFolder; } else { folder = defaultFolderName; } if(!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } return folder; } public static string AviFolder { get { return GetFolder(DefaultAviFolder, Config.PreferenceInfo.AviFolder, Config.PreferenceInfo.OverrideAviFolder); } } public static string MovieFolder { get { return GetFolder(DefaultMovieFolder, Config.PreferenceInfo.MovieFolder, Config.PreferenceInfo.OverrideMovieFolder); } } public static string SaveFolder { get { return GetFolder(DefaultSaveDataFolder, Config.PreferenceInfo.SaveDataFolder, Config.PreferenceInfo.OverrideSaveDataFolder); } } public static string SaveStateFolder { get { return GetFolder(DefaultSaveStateFolder, Config.PreferenceInfo.SaveStateFolder, Config.PreferenceInfo.OverrideSaveStateFolder); } } public static string ScreenshotFolder { get { return GetFolder(DefaultScreenshotFolder, Config.PreferenceInfo.ScreenshotFolder, Config.PreferenceInfo.OverrideScreenshotFolder); } } public static string WaveFolder { get { return GetFolder(DefaultWaveFolder, Config.PreferenceInfo.WaveFolder, Config.PreferenceInfo.OverrideWaveFolder); } } public static string DebuggerFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Debugger"), null, false); } } public static string DownloadFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Downloads"), null, false); } } public static string BackupFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Backups"), null, false); } } public static string TestFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Tests"), null, false); } } public static string HdPackFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "HdPacks"), null, false); } } public static string RecentGamesFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "RecentGames"), null, false); } } public static string FontFolder { get { return GetFolder(Environment.GetFolderPath(Environment.SpecialFolder.Fonts, Environment.SpecialFolderOption.Create), null, false); } } public static string ConfigFile { get { if(HomeFolder == null) { //Initializes the HomeFolder property InitHomeFolder(); } if(!Directory.Exists(HomeFolder)) { Directory.CreateDirectory(HomeFolder); } return Path.Combine(HomeFolder, "settings.xml"); } } public static Configuration Config { get { LoadConfig(); return _dirtyConfig; } } private static DateTime _lastSaveTime = DateTime.MinValue; public static void ApplyChanges() { _config.NeedToSave = false; _config = _dirtyConfig.Clone(); _config.NeedToSave = true; if((DateTime.Now - _lastSaveTime).Seconds > 1) { ConfigManager.SaveConfig(); _lastSaveTime = DateTime.Now; } } public static void RejectChanges() { _dirtyConfig = _config.Clone(); } public static void RevertToBackup(Configuration config) { _config = config; _dirtyConfig = _config.Clone(); } public static void ResetSettings() { DefaultKeyMappingType defaultMappings = Config.InputInfo.DefaultMapping; _dirtyConfig = new Configuration(); Config.InputInfo.DefaultMapping = defaultMappings; Config.InitializeDefaults(); ApplyChanges(); Config.ApplyConfig(); } public static void RestartMesen(bool preventSave = false) { if(preventSave) { DoNotSaveSettings = true; } if(Program.IsMono) { System.Diagnostics.Process.Start("mono", "\"" + Assembly.GetEntryAssembly().Location + "\" /delayrestart"); } else { System.Diagnostics.Process.Start(Assembly.GetEntryAssembly().Location, "/delayrestart"); } } } }