From 94f93727cffc2249cae83b9582f82c843f25a652 Mon Sep 17 00:00:00 2001
From: Xpl0itR <xpl0itr@outlook.com>
Date: Tue, 9 Feb 2021 09:24:37 +0000
Subject: [PATCH] Load default config when an invalid config is found (#1008)

- Bind toggle events after setting up their current values. This fixes the issue where the config is saved 10 times when the main window is opened :grimacing:

- Write to disk immediately to decrease the chances of corruption
---
 .../Configuration/ConfigurationFileFormat.cs  | 18 ++++++--
 Ryujinx/Program.cs                            | 44 ++++++++++---------
 Ryujinx/Ui/MainWindow.cs                      | 13 +++++-
 Ryujinx/Ui/MainWindow.glade                   | 10 -----
 4 files changed, 50 insertions(+), 35 deletions(-)

diff --git a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
index 72cc579c78..79993d879f 100644
--- a/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
+++ b/Ryujinx.Common/Configuration/ConfigurationFileFormat.cs
@@ -227,9 +227,20 @@ namespace Ryujinx.Configuration
         /// Loads a configuration file from disk
         /// </summary>
         /// <param name="path">The path to the JSON configuration file</param>
-        public static ConfigurationFileFormat Load(string path)
+        public static bool TryLoad(string path, out ConfigurationFileFormat configurationFileFormat)
         {
-            return JsonHelper.DeserializeFromFile<ConfigurationFileFormat>(path);
+            try
+            {
+                configurationFileFormat = JsonHelper.DeserializeFromFile<ConfigurationFileFormat>(path);
+
+                return true;
+            }
+            catch
+            {
+                configurationFileFormat = null;
+
+                return false;
+            }
         }
 
         /// <summary>
@@ -238,7 +249,8 @@ namespace Ryujinx.Configuration
         /// <param name="path">The path to the JSON configuration file</param>
         public void SaveConfig(string path)
         {
-            File.WriteAllText(path, JsonHelper.Serialize(this, true));
+            using FileStream fileStream = File.Create(path, 4096, FileOptions.WriteThrough);
+            JsonHelper.Serialize(fileStream, this, true);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs
index 29043bb8ee..c6d3b1bd14 100644
--- a/Ryujinx/Program.cs
+++ b/Ryujinx/Program.cs
@@ -89,30 +89,32 @@ namespace Ryujinx
             string localConfigurationPath   = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config.json");
             string appDataConfigurationPath = Path.Combine(AppDataManager.BaseDirPath,            "Config.json");
 
-            // Now load the configuration as the other subsystems are now registered.
-            if (File.Exists(localConfigurationPath))
+            // Now load the configuration as the other subsystems are now registered
+            ConfigurationPath = File.Exists(localConfigurationPath)
+                ? localConfigurationPath
+                : File.Exists(appDataConfigurationPath)
+                    ? appDataConfigurationPath
+                    : null;
+
+            if (ConfigurationPath == null)
             {
-                ConfigurationPath = localConfigurationPath;
-
-                ConfigurationFileFormat configurationFileFormat = ConfigurationFileFormat.Load(localConfigurationPath);
-
-                ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath);
-            }
-            else if (File.Exists(appDataConfigurationPath))
-            {
-                ConfigurationPath = appDataConfigurationPath;
-
-                ConfigurationFileFormat configurationFileFormat = ConfigurationFileFormat.Load(appDataConfigurationPath);
-
-                ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath);
-            }
-            else
-            {
-                // No configuration, we load the default values and save it on disk.
+                // No configuration, we load the default values and save it to disk
                 ConfigurationPath = appDataConfigurationPath;
 
                 ConfigurationState.Instance.LoadDefault();
-                ConfigurationState.Instance.ToFileFormat().SaveConfig(appDataConfigurationPath);
+                ConfigurationState.Instance.ToFileFormat().SaveConfig(ConfigurationPath);
+            }
+            else
+            {
+                if (ConfigurationFileFormat.TryLoad(ConfigurationPath, out ConfigurationFileFormat configurationFileFormat))
+                {
+                    ConfigurationState.Instance.Load(configurationFileFormat, ConfigurationPath);
+                }
+                else
+                {
+                    ConfigurationState.Instance.LoadDefault();
+                    Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location {ConfigurationPath}");
+                }
             }
 
             if (startFullscreenArg)
@@ -120,7 +122,7 @@ namespace Ryujinx
                 ConfigurationState.Instance.Ui.StartFullscreen.Value = true;
             }
 
-            // Logging system informations.
+            // Logging system information.
             PrintSystemInfo();
 
             // Initialize Gtk.
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index 7697376bd5..92a2b4f1ca 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -157,6 +157,17 @@ namespace Ryujinx.Ui
             if (ConfigurationState.Instance.Ui.GuiColumns.FileSizeColumn)   _fileSizeToggle.Active   = true;
             if (ConfigurationState.Instance.Ui.GuiColumns.PathColumn)       _pathToggle.Active       = true;
 
+            _favToggle.Toggled        += Fav_Toggled;
+            _iconToggle.Toggled       += Icon_Toggled;
+            _appToggle.Toggled        += App_Toggled;
+            _developerToggle.Toggled  += Developer_Toggled;
+            _versionToggle.Toggled    += Version_Toggled;
+            _timePlayedToggle.Toggled += TimePlayed_Toggled;
+            _lastPlayedToggle.Toggled += LastPlayed_Toggled;
+            _fileExtToggle.Toggled    += FileExt_Toggled;
+            _fileSizeToggle.Toggled   += FileSize_Toggled;
+            _pathToggle.Toggled       += Path_Toggled;
+
             _gameTable.Model = _tableStore = new ListStore(
                 typeof(bool),
                 typeof(Gdk.Pixbuf),
@@ -1142,7 +1153,7 @@ namespace Ryujinx.Ui
             UpdateColumns();
         }
 
-        private void Title_Toggled(object sender, EventArgs args)
+        private void App_Toggled(object sender, EventArgs args)
         {
             ConfigurationState.Instance.Ui.GuiColumns.AppColumn.Value = _appToggle.Active;
 
diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade
index 6cefe08aa3..688f0e2553 100644
--- a/Ryujinx/Ui/MainWindow.glade
+++ b/Ryujinx/Ui/MainWindow.glade
@@ -171,7 +171,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Favorite Games Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Favorite Games Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="Fav_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -181,7 +180,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Icon Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Icon Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="Icon_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -191,7 +189,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Title Name/ID Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Title Name/ID Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="Title_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -201,7 +198,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Developer Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Developer Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="Developer_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -211,7 +207,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Version Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Version Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="Version_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -221,7 +216,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Time Played Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Time Played Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="TimePlayed_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -231,7 +225,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Last Played Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Last Played Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="LastPlayed_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -241,7 +234,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable file extension column in the game list</property>
                                 <property name="label" translatable="yes">Enable File Ext Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="FileExt_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -251,7 +243,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable File Size Column in the game list</property>
                                 <property name="label" translatable="yes">Enable File Size Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="FileSize_Toggled" swapped="no"/>
                               </object>
                             </child>
                             <child>
@@ -261,7 +252,6 @@
                                 <property name="tooltip_text" translatable="yes">Enable or Disable Path Column in the game list</property>
                                 <property name="label" translatable="yes">Enable Path Column</property>
                                 <property name="use_underline">True</property>
-                                <signal name="toggled" handler="Path_Toggled" swapped="no"/>
                               </object>
                             </child>
                           </object>