1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.IO; 7 using System.Linq; 8 using System.Text; 9 using System.Threading.Tasks; 10 using System.Windows.Forms; 11 using Mesen.GUI.Config; 12 using Mesen.GUI.GoogleDriveIntegration; 13 14 namespace Mesen.GUI.Forms.Config 15 { 16 public partial class frmPreferences : BaseConfigForm 17 { 18 public bool NeedRestart { get; private set; } 19 frmPreferences()20 public frmPreferences() 21 { 22 InitializeComponent(); 23 24 Entity = ConfigManager.Config.PreferenceInfo; 25 26 AddBinding("DisplayLanguage", cboDisplayLanguage); 27 28 AddBinding("AutomaticallyCheckForUpdates", chkAutomaticallyCheckForUpdates); 29 AddBinding("SingleInstance", chkSingleInstance); 30 AddBinding("AutoLoadIpsPatches", chkAutoLoadIps); 31 AddBinding("DeveloperMode", chkDeveloperMode); 32 33 AddBinding("AssociateNesFiles", chkNesFormat); 34 AddBinding("AssociateFdsFiles", chkFdsFormat); 35 AddBinding("AssociateMmoFiles", chkMmoFormat); 36 AddBinding("AssociateNsfFiles", chkNsfFormat); 37 AddBinding("AssociateMstFiles", chkMstFormat); 38 AddBinding("AssociateUnfFiles", chkUnfFormat); 39 40 AddBinding("DisableMouseResize", chkDisableMouseResize); 41 42 AddBinding("NsfAutoDetectSilence", chkNsfAutoDetectSilence); 43 AddBinding("NsfMoveToNextTrackAfterTime", chkNsfMoveToNextTrackAfterTime); 44 AddBinding("NsfMoveToNextTrackTime", nudNsfMoveToNextTrackTime); 45 AddBinding("NsfAutoDetectSilenceDelay", nudNsfAutoDetectSilenceDelay); 46 AddBinding("NsfEnableApuIrqs", chkNsfEnableApuIrqs); 47 48 AddBinding("VsDualVideoOutput", cboVsDualVideoOutput); 49 AddBinding("VsDualAudioOutput", cboVsDualAudioOutput); 50 51 AddBinding("FdsAutoLoadDisk", chkFdsAutoLoadDisk); 52 AddBinding("FdsFastForwardOnLoad", chkFdsFastForwardOnLoad); 53 AddBinding("FdsAutoInsertDisk", chkFdsAutoInsertDisk); 54 55 AddBinding("PauseWhenInBackground", chkPauseWhenInBackground); 56 AddBinding("PauseWhenInMenusAndConfig", chkPauseInMenuAndConfig); 57 AddBinding("PauseWhenInDebuggingTools", chkPauseInDebugger); 58 59 AddBinding("AllowBackgroundInput", chkAllowBackgroundInput); 60 AddBinding("ConfirmExitResetPower", chkConfirmExitResetPower); 61 62 AddBinding("PauseOnMovieEnd", chkPauseOnMovieEnd); 63 64 AddBinding("AlwaysOnTop", chkAlwaysOnTop); 65 66 AddBinding("DisableGameDatabase", chkDisableGameDatabase); 67 AddBinding("DisableHighResolutionTimer", chkDisableHighResolutionTimer); 68 AddBinding("DisableOsd", chkDisableOsd); 69 70 AddBinding("AutoSave", chkAutoSave); 71 AddBinding("AutoSaveDelay", nudAutoSave); 72 AddBinding("AutoSaveNotify", chkAutoSaveNotify); 73 AddBinding("AllowMismatchingSaveStates", chkAllowMismatchingSaveStates); 74 75 AddBinding("DisplayMovieIcons", chkDisplayMovieIcons); 76 AddBinding("HidePauseOverlay", chkHidePauseOverlay); 77 78 AddBinding("AutoHideMenu", chkAutoHideMenu); 79 AddBinding("DisplayTitleBarInfo", chkDisplayTitleBarInfo); 80 81 AddBinding("ShowFullPathInRecents", chkShowFullPathInRecents); 82 83 AddBinding("ShowFrameCounter", chkShowFrameCounter); 84 AddBinding("ShowGameTimer", chkShowGameTimer); 85 86 AddBinding("DisableGameSelectionScreen", chkDisableGameSelectionScreen); 87 AddBinding("GameSelectionScreenResetGame", chkGameSelectionScreenResetGame); 88 89 AddBinding("RewindBufferSize", nudRewindBufferSize); 90 91 AddBinding("ShowVsConfigOnLoad", chkShowVsConfigOnLoad); 92 93 AddBinding("GameFolder", psGame); 94 AddBinding("AviFolder", psAvi); 95 AddBinding("MovieFolder", psMovies); 96 AddBinding("SaveDataFolder", psSaveData); 97 AddBinding("SaveStateFolder", psSaveStates); 98 AddBinding("ScreenshotFolder", psScreenshots); 99 AddBinding("WaveFolder", psWave); 100 101 AddBinding("OverrideGameFolder", chkGameOverride); 102 AddBinding("OverrideAviFolder", chkAviOverride); 103 AddBinding("OverrideMovieFolder", chkMoviesOverride); 104 AddBinding("OverrideSaveDataFolder", chkSaveDataOverride); 105 AddBinding("OverrideSaveStateFolder", chkSaveStatesOverride); 106 AddBinding("OverrideScreenshotFolder", chkScreenshotsOverride); 107 AddBinding("OverrideWaveFolder", chkWaveOverride); 108 109 radStorageDocuments.Checked = ConfigManager.HomeFolder == ConfigManager.DefaultDocumentsFolder; 110 radStoragePortable.Checked = !radStorageDocuments.Checked; 111 112 UpdateLocationText(); 113 UpdateFolderOverrideUi(); 114 UpdateCloudDisplay(); 115 116 if(Program.IsMono) { 117 //This option does nothing on Linux, hide it. 118 chkDisableHighResolutionTimer.Visible = false; 119 } 120 } 121 UpdateConfig()122 protected override void UpdateConfig() 123 { 124 base.UpdateConfig(); 125 ctrlEmulatorShortcuts.UpdateConfig(); 126 } 127 OnFormClosed(FormClosedEventArgs e)128 protected override void OnFormClosed(FormClosedEventArgs e) 129 { 130 base.OnFormClosed(e); 131 PreferenceInfo.ApplyConfig(); 132 } 133 chkPauseWhenInBackground_CheckedChanged(object sender, EventArgs e)134 private void chkPauseWhenInBackground_CheckedChanged(object sender, EventArgs e) 135 { 136 chkAllowBackgroundInput.Enabled = !chkPauseWhenInBackground.Checked; 137 if(!chkAllowBackgroundInput.Enabled) { 138 chkAllowBackgroundInput.Checked = false; 139 } 140 } 141 btnOpenMesenFolder_Click(object sender, EventArgs e)142 private void btnOpenMesenFolder_Click(object sender, EventArgs e) 143 { 144 System.Diagnostics.Process.Start(ConfigManager.HomeFolder); 145 } 146 UpdateCloudDisplay()147 private void UpdateCloudDisplay() 148 { 149 if(!this.IsDisposed) { 150 if(this.InvokeRequired) { 151 this.BeginInvoke((MethodInvoker)(() => this.UpdateCloudDisplay())); 152 } else { 153 this.tlpCloudSaveDesc.Visible = !ConfigManager.Config.PreferenceInfo.CloudSaveIntegration; 154 this.tlpCloudSaveEnabled.Visible = ConfigManager.Config.PreferenceInfo.CloudSaveIntegration; 155 } 156 } 157 } 158 TryEnableSync(bool retry = true)159 private void TryEnableSync(bool retry = true) 160 { 161 if(CloudSyncHelper.EnableSync()) { 162 if(!CloudSyncHelper.Sync()) { 163 if(retry) { 164 TryEnableSync(false); 165 } else { 166 MesenMsgBox.Show("GoogleDriveIntegrationError", MessageBoxButtons.OK, MessageBoxIcon.Error); 167 } 168 } else { 169 UpdateCloudDisplay(); 170 } 171 } else { 172 MesenMsgBox.Show("GoogleDriveIntegrationError", MessageBoxButtons.OK, MessageBoxIcon.Error); 173 } 174 } 175 btnEnableIntegration_Click(object sender, EventArgs e)176 private void btnEnableIntegration_Click(object sender, EventArgs e) 177 { 178 Task.Run(() => TryEnableSync()); 179 } 180 btnDisableIntegration_Click(object sender, EventArgs e)181 private void btnDisableIntegration_Click(object sender, EventArgs e) 182 { 183 Task.Run(() => { 184 CloudSyncHelper.DisableSync(); 185 UpdateCloudDisplay(); 186 }); 187 } 188 tmrSyncDateTime_Tick(object sender, EventArgs e)189 private void tmrSyncDateTime_Tick(object sender, EventArgs e) 190 { 191 btnDisableIntegration.Enabled = !CloudSyncHelper.Syncing; 192 btnResync.Enabled = btnDisableIntegration.Enabled; 193 194 if(ConfigManager.Config.PreferenceInfo.CloudLastSync != DateTime.MinValue) { 195 lblLastSyncDateTime.Text = ConfigManager.Config.PreferenceInfo.CloudLastSync.ToLongDateString() + " " + ConfigManager.Config.PreferenceInfo.CloudLastSync.ToLongTimeString(); 196 } else { 197 lblLastSyncDateTime.Text = ""; 198 } 199 } 200 btnResync_Click(object sender, EventArgs e)201 private void btnResync_Click(object sender, EventArgs e) 202 { 203 Task.Run(() => CloudSyncHelper.Sync()); 204 } 205 chkAutoSave_CheckedChanged(object sender, EventArgs e)206 private void chkAutoSave_CheckedChanged(object sender, EventArgs e) 207 { 208 nudAutoSave.Enabled = chkAutoSave.Checked; 209 chkAutoSaveNotify.Enabled = chkAutoSave.Checked; 210 } 211 btnResetSettings_Click(object sender, EventArgs e)212 private void btnResetSettings_Click(object sender, EventArgs e) 213 { 214 if(MesenMsgBox.Show("ResetSettingsConfirmation", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) { 215 ConfigManager.ResetSettings(); 216 this.Close(); 217 } 218 } 219 OnFormClosing(FormClosingEventArgs e)220 protected override void OnFormClosing(FormClosingEventArgs e) 221 { 222 if(this.DialogResult == DialogResult.OK) { 223 if(!ValidateFolderSettings()) { 224 e.Cancel = true; 225 return; 226 } 227 228 if(radStorageDocuments.Checked != (ConfigManager.HomeFolder == ConfigManager.DefaultDocumentsFolder)) { 229 //Need to copy files and display confirmation 230 string targetFolder = radStorageDocuments.Checked ? ConfigManager.DefaultDocumentsFolder : ConfigManager.DefaultPortableFolder; 231 if(MesenMsgBox.Show("CopyMesenDataPrompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, ConfigManager.HomeFolder, targetFolder) == DialogResult.OK) { 232 try { 233 //Save any other changes before copying the data 234 UpdateObject(); 235 ConfigManager.ApplyChanges(); 236 237 MigrateData(ConfigManager.HomeFolder, targetFolder); 238 } catch(Exception ex) { 239 MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString()); 240 e.Cancel = true; 241 } 242 } else { 243 e.Cancel = true; 244 return; 245 } 246 } 247 } else { 248 base.OnFormClosing(e); 249 } 250 } 251 MigrateData(string source, string target)252 private bool MigrateData(string source, string target) 253 { 254 using(frmCopyFiles frm = new frmCopyFiles(source, target)) { 255 frm.ShowDialog(this); 256 if(frm.Exception != null) { 257 throw frm.Exception; 258 } 259 } 260 if(File.Exists(Path.Combine(source, "settings.backup.xml"))) { 261 File.Delete(Path.Combine(source, "settings.backup.xml")); 262 } 263 File.Move(Path.Combine(source, "settings.xml"), Path.Combine(source, "settings.backup.xml")); 264 265 ConfigManager.InitHomeFolder(); 266 ConfigManager.SaveConfig(); 267 268 ConfigManager.RestartMesen(true); 269 this.NeedRestart = true; 270 271 return true; 272 } 273 ValidateFolderSettings()274 private bool ValidateFolderSettings() 275 { 276 bool result = true; 277 List<string> invalidFolders = new List<string>(); 278 try { 279 if(chkGameOverride.Checked && !CheckFolderPermissions(psGame.Text, false)) { 280 invalidFolders.Add(chkGameOverride.Text.Replace(":", "").Trim()); 281 } 282 if(chkAviOverride.Checked && !CheckFolderPermissions(psAvi.Text)) { 283 invalidFolders.Add(chkAviOverride.Text.Replace(":", "").Trim()); 284 } 285 if(chkMoviesOverride.Checked && !CheckFolderPermissions(psMovies.Text)) { 286 invalidFolders.Add(chkMoviesOverride.Text.Replace(":", "").Trim()); 287 } 288 if(chkSaveDataOverride.Checked && !CheckFolderPermissions(psSaveData.Text)) { 289 invalidFolders.Add(chkSaveDataOverride.Text.Replace(":", "").Trim()); 290 } 291 if(chkSaveStatesOverride.Checked && !CheckFolderPermissions(psSaveStates.Text)) { 292 invalidFolders.Add(chkSaveStatesOverride.Text.Replace(":", "").Trim()); 293 } 294 if(chkScreenshotsOverride.Checked && !CheckFolderPermissions(psScreenshots.Text)) { 295 invalidFolders.Add(chkScreenshotsOverride.Text.Replace(":", "").Trim()); 296 } 297 if(chkWaveOverride.Checked && !CheckFolderPermissions(psWave.Text)) { 298 invalidFolders.Add(chkWaveOverride.Text.Replace(":", "").Trim()); 299 } 300 301 result = invalidFolders.Count == 0; 302 } catch { 303 result = false; 304 } 305 if(!result) { 306 MesenMsgBox.Show("InvalidPaths", MessageBoxButtons.OK, MessageBoxIcon.Error, string.Join(Environment.NewLine, invalidFolders)); 307 } 308 return result; 309 } 310 CheckFolderPermissions(string folder, bool checkWritePermission = true)311 private bool CheckFolderPermissions(string folder, bool checkWritePermission = true) 312 { 313 if(!Directory.Exists(folder)) { 314 try { 315 if(string.IsNullOrWhiteSpace(folder)) { 316 return false; 317 } 318 Directory.CreateDirectory(folder); 319 } catch { 320 return false; 321 } 322 } 323 if(checkWritePermission) { 324 try { 325 File.WriteAllText(Path.Combine(folder, "test.txt"), ""); 326 File.Delete(Path.Combine(folder, "test.txt")); 327 } catch { 328 return false; 329 } 330 } 331 return true; 332 } 333 UpdateFolderOverrideUi()334 private void UpdateFolderOverrideUi() 335 { 336 psGame.Enabled = chkGameOverride.Checked; 337 psAvi.Enabled = chkAviOverride.Checked; 338 psMovies.Enabled = chkMoviesOverride.Checked; 339 psSaveData.Enabled = chkSaveDataOverride.Checked; 340 psSaveStates.Enabled = chkSaveStatesOverride.Checked; 341 psScreenshots.Enabled = chkScreenshotsOverride.Checked; 342 psWave.Enabled = chkWaveOverride.Checked; 343 344 psGame.DisabledText = ResourceHelper.GetMessage("LastFolderUsed"); 345 psAvi.DisabledText = ConfigManager.DefaultAviFolder; 346 psMovies.DisabledText = ConfigManager.DefaultMovieFolder; 347 psSaveData.DisabledText = ConfigManager.DefaultSaveDataFolder; 348 psSaveStates.DisabledText = ConfigManager.DefaultSaveStateFolder; 349 psScreenshots.DisabledText = ConfigManager.DefaultScreenshotFolder; 350 psWave.DisabledText = ConfigManager.DefaultWaveFolder; 351 } 352 UpdateLocationText()353 private void UpdateLocationText() 354 { 355 lblLocation.Text = radStorageDocuments.Checked ? ConfigManager.DefaultDocumentsFolder : ConfigManager.DefaultPortableFolder; 356 } 357 chkOverride_CheckedChanged(object sender, EventArgs e)358 private void chkOverride_CheckedChanged(object sender, EventArgs e) 359 { 360 UpdateFolderOverrideUi(); 361 } 362 radStorageDocuments_CheckedChanged(object sender, EventArgs e)363 private void radStorageDocuments_CheckedChanged(object sender, EventArgs e) 364 { 365 UpdateLocationText(); 366 } 367 } 368 } 369