diff --git a/src/BizHawk.Client.Common/config/ConfigService.cs b/src/BizHawk.Client.Common/config/ConfigService.cs index 392ace453f..641d5a8b05 100644 --- a/src/BizHawk.Client.Common/config/ConfigService.cs +++ b/src/BizHawk.Client.Common/config/ConfigService.cs @@ -1,7 +1,11 @@ using System; using System.IO; using System.Reflection; + +using BizHawk.Common; + using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; #pragma warning disable 618 @@ -30,6 +34,68 @@ namespace BizHawk.Client.Common }; } + public static bool IsFromSameVersion(string filepath, out string msg) + { + // "2.5.1" => 0x02050100 + static int VersionStrToInt(string s) + { + var a = s.Split('.'); + var v = 0; + var i = 0; + while (i < 4) + { + v <<= 8; + if (i < a.Length) v += byte.TryParse(a[i], out var b) ? b : 0; + i++; + } + return v; + } + const string MSGFMT_NEWER = "Your config file ({0}) is from a newer version of EmuHawk, {2} (this is {1}). It may fail to load."; + const string MSGFMT_OLDER = "Your config file ({0}) is from an older version of EmuHawk, {2} (this is {1}). It may fail to load."; + const string MSGFMT_PRE_2_3_3 = "Your config file ({0}) is corrupted, or is from an older version of EmuHawk, predating 2.3.3 (this is {1}). It may fail to load."; + const string MSGFMT_PRE_2_5 = "Your config file ({0}) is corrupted, or is from an older version of EmuHawk, predating 2.5 (this is {1}). It may fail to load."; + + if (!new FileInfo(filepath).Exists) + { + msg = null; + return true; + } + string cfgVersionStr = null; + try + { + cfgVersionStr = JObject.Parse(File.ReadAllText(filepath))["LastWrittenFrom"]?.Value(); + } + catch (Exception) + { + // ignored + } + if (cfgVersionStr == VersionInfo.MainVersion) + { + msg = null; + return true; + } + string fmt; + if (cfgVersionStr == null) + { + fmt = MSGFMT_PRE_2_3_3; + } + else + { + var cfgVersion = VersionStrToInt(cfgVersionStr); + if (cfgVersion < 0x02050000) + { + fmt = MSGFMT_PRE_2_5; + } + else + { + var thisVersion = VersionStrToInt(VersionInfo.MainVersion); + fmt = cfgVersion < thisVersion ? MSGFMT_OLDER : MSGFMT_NEWER; + } + } + msg = string.Format(fmt, Path.GetFileName(filepath), VersionInfo.MainVersion, cfgVersionStr); + return false; + } + /// internal error public static T Load(string filepath) where T : new() { diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index b490d1065d..5d4eb9772f 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -2783,6 +2783,10 @@ namespace BizHawk.Client.EmuHawk private void LoadConfigFile(string iniPath) { + if (!VersionInfo.DeveloperBuild && !ConfigService.IsFromSameVersion(iniPath, out var msg)) + { + new MsgBox(msg, "Mismatched version in config file", MessageBoxIcon.Warning).ShowDialog(); + } Config = ConfigService.Load(iniPath); Config.ResolveDefaults(); InitControls(); // rebind hotkeys diff --git a/src/BizHawk.Client.EmuHawk/Program.cs b/src/BizHawk.Client.EmuHawk/Program.cs index 3ecd21632d..be4771d6c9 100644 --- a/src/BizHawk.Client.EmuHawk/Program.cs +++ b/src/BizHawk.Client.EmuHawk/Program.cs @@ -11,6 +11,7 @@ using Microsoft.VisualBasic.ApplicationServices; using BizHawk.Common; using BizHawk.Common.PathExtensions; using BizHawk.Client.Common; +using BizHawk.Client.EmuHawk.CustomControls; using OSTC = EXE_PROJECT.OSTailoredCode; @@ -110,12 +111,20 @@ namespace BizHawk.Client.EmuHawk try { + if (!VersionInfo.DeveloperBuild && !ConfigService.IsFromSameVersion(Config.DefaultIniPath, out var msg)) + { + new MsgBox(msg, "Mismatched version in config file", MessageBoxIcon.Warning).ShowDialog(); + } GlobalWin.Config = ConfigService.Load(Config.DefaultIniPath); } catch (Exception e) { - new ExceptionBox(e).ShowDialog(); - new ExceptionBox("Since your config file is corrupted or from a different BizHawk version, we're going to recreate it. Back it up before proceeding if you want to investigate further.").ShowDialog(); + new ExceptionBox(string.Join("\n", + "It appears your config file (config.ini) is corrupted; an exception was thrown while loading it.", + "On closing this warning, EmuHawk will delete your config file and generate a new one. You can go make a backup now if you'd like to look into diffs.", + "The caught exception was:", + e.ToString() + )).ShowDialog(); File.Delete(Config.DefaultIniPath); GlobalWin.Config = ConfigService.Load(Config.DefaultIniPath); }