1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Diagnostics; 5 using System.Drawing; 6 using System.Drawing.Text; 7 using System.IO; 8 using System.Linq; 9 using System.Net; 10 using System.Text; 11 using System.Text.RegularExpressions; 12 using System.Threading; 13 using System.Threading.Tasks; 14 using System.Windows.Forms; 15 using System.Xml; 16 using Mesen.GUI.Config; 17 using Mesen.GUI.Debugger; 18 using Mesen.GUI.Forms.Cheats; 19 using Mesen.GUI.Forms.Config; 20 using Mesen.GUI.Forms.HdPackEditor; 21 using Mesen.GUI.Forms.NetPlay; 22 using Mesen.GUI.GoogleDriveIntegration; 23 using Mesen.GUI.Properties; 24 25 namespace Mesen.GUI.Forms 26 { 27 public partial class frmMain : BaseInputForm 28 { 29 private InteropEmu.NotificationListener _notifListener; 30 private Thread _emuThread; 31 private frmLogWindow _logWindow; 32 private frmCheatList _cheatListWindow; 33 private frmHistoryViewer _historyViewerWindow; 34 private frmHdPackEditor _hdPackEditorWindow; 35 private ResourcePath? _currentRomPath = null; 36 37 private string _movieToRecord = null; 38 private List<string> _luaScriptsToLoad = new List<string>(); 39 private bool _loadLastSessionRequested = false; 40 41 private Image _pauseButton = Resources.Pause; 42 private Image _playButton = Resources.Play; 43 private string _currentGame = null; 44 private bool _customSize = false; 45 private double? _switchOptionScale = null; 46 private bool _fullscreenRequested = false; 47 private FormWindowState _originalWindowState; 48 private Size _originalWindowMinimumSize; 49 private bool _fullscreenMode = false; 50 private Size? _nonNsfSize = null; 51 private Size _nonNsfMinimumSize; 52 private bool _isNsfPlayerMode = false; 53 private object _loadRomLock = new object(); 54 private int _romLoadCounter = 0; 55 private bool _showUpgradeMessage = false; 56 private float _yFactor = 1; 57 private bool _enableResize = false; 58 private bool _overrideWindowSize = false; 59 private bool _shuttingDown = false; 60 private bool _isDualSystem = false; 61 62 private frmFullscreenRenderer _frmFullscreenRenderer = null; 63 64 private Dictionary<EmulatorShortcut, Func<bool>> _actionEnabledFuncs = new Dictionary<EmulatorShortcut, Func<bool>>(); 65 66 private string[] _commandLineArgs; 67 private bool _noAudio = false; 68 private bool _noVideo = false; 69 private bool _noInput = false; 70 71 private PrivateFontCollection _fonts = new PrivateFontCollection(); 72 frmMain(string[] args)73 public frmMain(string[] args) 74 { 75 ThemeHelper.InitTheme(this.BackColor); 76 InitializeComponent(); 77 78 ThemeHelper.ExcludeFromTheme(panelInfo); 79 ThemeHelper.ExcludeFromTheme(panelRenderer); 80 81 this.StartPosition = FormStartPosition.CenterScreen; 82 83 Version currentVersion = new Version(InteropEmu.GetMesenVersion()); 84 lblVersion.Text = currentVersion.ToString(); 85 86 if(!Program.IsMono) { 87 _fonts.AddFontFile(Path.Combine(ConfigManager.HomeFolder, "Resources", "PixelFont.ttf")); 88 lblVersion.Font = new Font(_fonts.Families[0], 10); 89 } else { 90 lblVersion.Margin = new Padding(0, 0, 3, 0); 91 picIcon.Margin = new Padding(3, 5, 3, 3); 92 } 93 94 #if AUTOBUILD 95 string devVersion = ResourceManager.ReadZippedResource("DevBuild.txt"); 96 if(devVersion != null) { 97 Size versionSize = TextRenderer.MeasureText(devVersion, lblVersion.Font); 98 lblVersion.Text = devVersion; 99 lblVersion.Anchor = AnchorStyles.Right; 100 int newWidth = versionSize.Width + 30; 101 panelInfo.Left -= newWidth - panelInfo.Width; 102 panelInfo.Width = newWidth; 103 } 104 #endif 105 106 _commandLineArgs = (string[])args.Clone(); 107 108 Application.AddMessageFilter(this); 109 this.Resize += ResizeRecentGames; 110 this.FormClosed += (s, e) => Application.RemoveMessageFilter(this); 111 } 112 ProcessCommandLineArguments(List<string> switches, bool forStartup)113 public void ProcessCommandLineArguments(List<string> switches, bool forStartup) 114 { 115 if(forStartup) { 116 _noVideo = switches.Contains("/novideo"); 117 _noAudio = switches.Contains("/noaudio"); 118 _noInput = switches.Contains("/noinput"); 119 } 120 121 if(switches.Contains("/donotsavesettings")) { 122 ConfigManager.DoNotSaveSettings = true; 123 } 124 125 if(switches.Contains("/loadlastsession")) { 126 _loadLastSessionRequested = true; 127 } 128 129 Regex recordMovieCommand = new Regex("/recordmovie=([^\"]+)"); 130 foreach(string command in switches) { 131 Match match = recordMovieCommand.Match(command); 132 if(match.Success) { 133 string moviePath = match.Groups[1].Value; 134 string folder = Path.GetDirectoryName(moviePath); 135 if(string.IsNullOrWhiteSpace(folder)) { 136 moviePath = Path.Combine(ConfigManager.MovieFolder, moviePath); 137 } else if(!Path.IsPathRooted(moviePath)) { 138 moviePath = Path.Combine(Program.OriginalFolder, moviePath); 139 } 140 if(!moviePath.ToLower().EndsWith(".mmo")) { 141 moviePath += ".mmo"; 142 } 143 _movieToRecord = moviePath; 144 break; 145 } 146 } 147 148 ConfigManager.ProcessSwitches(switches); 149 } 150 LoadGameFromCommandLine(List<string> switches)151 public void LoadGameFromCommandLine(List<string> switches) 152 { 153 string romPath; 154 CommandLineHelper.GetRomPathFromCommandLine(switches, out romPath, out _luaScriptsToLoad); 155 156 if(romPath != null) { 157 this.LoadFile(romPath); 158 } else { 159 if(_emuThread == null) { 160 //When no ROM is loaded, only process Lua scripts if a ROM was specified as a command line param 161 _luaScriptsToLoad.Clear(); 162 _movieToRecord = null; 163 _loadLastSessionRequested = false; 164 } else { 165 //No game was specified, but a game is running already, load the scripts right away 166 ProcessPostLoadCommandSwitches(); 167 } 168 } 169 } 170 ProcessPostLoadCommandSwitches()171 private void ProcessPostLoadCommandSwitches() 172 { 173 if(_luaScriptsToLoad.Count > 0) { 174 foreach(string luaScript in _luaScriptsToLoad) { 175 frmScript scriptWindow = DebugWindowManager.OpenScriptWindow(true); 176 scriptWindow.LoadScriptFile(luaScript); 177 } 178 _luaScriptsToLoad.Clear(); 179 } 180 181 if(_movieToRecord != null) { 182 if(InteropEmu.MovieRecording()) { 183 InteropEmu.MovieStop(); 184 } 185 RecordMovieOptions options = new RecordMovieOptions(_movieToRecord, "", "", RecordMovieFrom.StartWithSaveData); 186 InteropEmu.MovieRecord(ref options); 187 _movieToRecord = null; 188 } 189 190 if(_loadLastSessionRequested) { 191 _loadLastSessionRequested = false; 192 LoadLastSession(); 193 } 194 } 195 OnLoad(EventArgs e)196 protected override void OnLoad(EventArgs e) 197 { 198 ResourceHelper.LoadResources(ConfigManager.Config.PreferenceInfo.DisplayLanguage); 199 ResourceHelper.UpdateEmuLanguage(); 200 201 base.OnLoad(e); 202 203 #if HIDETESTMENU 204 mnuTests.Visible = false; 205 #endif 206 InteropEmu.InitDll(); 207 208 _notifListener = new InteropEmu.NotificationListener(InteropEmu.ConsoleId.Master); 209 _notifListener.OnNotification += _notifListener_OnNotification; 210 211 menuTimer.Start(); 212 213 InteropEmu.ScreenSize originalSize = InteropEmu.GetScreenSize(false); 214 VideoInfo.ApplyConfig(); 215 this.ProcessCommandLineArguments(CommandLineHelper.PreprocessCommandLineArguments(_commandLineArgs, true), true); 216 VideoInfo.ApplyConfig(); 217 InteropEmu.ScreenSize newSize = InteropEmu.GetScreenSize(false); 218 if(originalSize.Width != newSize.Width || originalSize.Height != newSize.Height) { 219 _overrideWindowSize = true; 220 } 221 222 InitializeEmulationSpeedMenu(); 223 224 UpdateVideoSettings(); 225 226 InitializeCore(); 227 PerformUpgrade(); 228 InitializeEmu(); 229 230 TopMost = ConfigManager.Config.PreferenceInfo.AlwaysOnTop; 231 232 UpdateMenus(); 233 UpdateRecentFiles(); 234 235 UpdateViewerSize(); 236 237 InitializeStateMenu(mnuSaveState, true); 238 InitializeStateMenu(mnuLoadState, false); 239 240 if(ConfigManager.Config.WindowLocation.HasValue) { 241 this.StartPosition = FormStartPosition.Manual; 242 this.Location = ConfigManager.Config.WindowLocation.Value; 243 } 244 245 if(ConfigManager.Config.PreferenceInfo.CloudSaveIntegration) { 246 Task.Run(() => CloudSyncHelper.Sync()); 247 } 248 249 if(ConfigManager.Config.PreferenceInfo.AutomaticallyCheckForUpdates) { 250 CheckForUpdates(false); 251 } 252 253 if(ConfigManager.Config.WindowSize.HasValue && !_overrideWindowSize) { 254 this.ClientSize = ConfigManager.Config.WindowSize.Value; 255 } 256 257 mnuDebugDualSystemSecondaryCpu.Checked = ConfigManager.Config.DebugInfo.DebugConsoleId == InteropEmu.ConsoleId.Slave; 258 InteropEmu.DebugSetDebuggerConsole(ConfigManager.Config.DebugInfo.DebugConsoleId); 259 260 BaseForm.StartBackgroundTimer(); 261 } 262 ProcessFullscreenSwitch(List<string> switches)263 private void ProcessFullscreenSwitch(List<string> switches) 264 { 265 if(switches.Contains("/fullscreen")) { 266 double scale = ConfigManager.Config.VideoInfo.VideoScale; 267 if(!ConfigManager.Config.VideoInfo.UseExclusiveFullscreen) { 268 //Go into fullscreen mode right away 269 SetFullscreenState(true); 270 } 271 272 _fullscreenRequested = true; 273 foreach(string option in switches) { 274 if(option.StartsWith("/videoscale=")) { 275 _switchOptionScale = scale; 276 } 277 } 278 } 279 } 280 OnShown(EventArgs e)281 protected override void OnShown(EventArgs e) 282 { 283 base.OnShown(e); 284 285 if(ConfigManager.Config.PreferenceInfo.DisableMouseResize) { 286 //This must be in the OnShown event, otherwise the application won't show up in the taskbar until it is given focus 287 this.FormBorderStyle = FormBorderStyle.Fixed3D; 288 } 289 290 this.BindShortcuts(); 291 292 if(ConfigManager.Config.WindowSize.HasValue && !_overrideWindowSize) { 293 this.Size = ConfigManager.Config.WindowSize.Value; 294 } 295 296 this.LoadGameFromCommandLine(CommandLineHelper.PreprocessCommandLineArguments(_commandLineArgs, false)); 297 298 this.menuStrip.VisibleChanged += new System.EventHandler(this.menuStrip_VisibleChanged); 299 this.UpdateRendererLocation(); 300 301 if(_showUpgradeMessage) { 302 MesenMsgBox.Show("UpgradeSuccess", MessageBoxButtons.OK, MessageBoxIcon.Information); 303 _showUpgradeMessage = false; 304 } 305 306 //Ensure the resize event is not fired until the form is fully shown 307 //This is needed when DPI display settings is not set to 100% 308 _enableResize = true; 309 310 ProcessFullscreenSwitch(CommandLineHelper.PreprocessCommandLineArguments(_commandLineArgs, true)); 311 } 312 OnClosing(CancelEventArgs e)313 protected override void OnClosing(CancelEventArgs e) 314 { 315 if(ConfigManager.Config.PreferenceInfo.ConfirmExitResetPower && MesenMsgBox.Show("ConfirmExit", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK) { 316 e.Cancel = true; 317 return; 318 } 319 320 if(!_shuttingDown && Program.IsMono) { 321 //This appears to prevent Mono from locking up when closing the form 322 Task.Run(() => { 323 StopEmu(); 324 _shuttingDown = true; 325 this.BeginInvoke((Action)(() => this.Close())); 326 }); 327 e.Cancel = true; 328 return; 329 } 330 331 _shuttingDown = true; 332 CursorManager.StopTimers(); 333 BaseForm.StopBackgroundTimer(); 334 _logWindow?.Close(); 335 _historyViewerWindow?.Close(); 336 _cheatListWindow?.Close(); 337 _hdPackEditorWindow?.Close(); 338 _frmFullscreenRenderer?.Close(); 339 340 //Stop menu update timer, and process all pending events before stopping the core 341 //This prevents some rare crashes on shutdown 342 menuTimer.Stop(); 343 Application.DoEvents(); 344 345 if(_notifListener != null) { 346 _notifListener.Dispose(); 347 _notifListener = null; 348 } 349 DebugWindowManager.CloseAll(); 350 351 ConfigManager.Config.EmulationInfo.EmulationSpeed = InteropEmu.GetEmulationSpeed(); 352 ConfigManager.Config.WindowLocation = this.WindowState == FormWindowState.Normal ? this.Location : this.RestoreBounds.Location; 353 ConfigManager.Config.WindowSize = this.WindowState == FormWindowState.Normal ? this.Size : this.RestoreBounds.Size; 354 355 if(this._nonNsfSize.HasValue) { 356 ConfigManager.Config.WindowSize = this._nonNsfSize.Value; 357 } 358 359 ConfigManager.ApplyChanges(); 360 361 StopEmu(); 362 363 if(ConfigManager.Config.PreferenceInfo.CloudSaveIntegration) { 364 CloudSyncHelper.Sync(); 365 } 366 367 InteropEmu.Release(); 368 369 ConfigManager.SaveConfig(); 370 371 base.OnClosing(e); 372 } 373 menuTimer_Tick(object sender, EventArgs e)374 private void menuTimer_Tick(object sender, EventArgs e) 375 { 376 this.UpdateMenus(); 377 } 378 InitializeCore()379 void InitializeCore() 380 { 381 InteropEmu.InitializeEmu(ConfigManager.HomeFolder, this.Handle, ctrlRenderer.Handle, _noAudio, _noVideo, _noInput); 382 } 383 InitializeEmu()384 void InitializeEmu() 385 { 386 if(ConfigManager.Config.PreferenceInfo.OverrideGameFolder && Directory.Exists(ConfigManager.Config.PreferenceInfo.GameFolder)) { 387 InteropEmu.AddKnownGameFolder(ConfigManager.Config.PreferenceInfo.GameFolder); 388 } 389 foreach(RecentItem recentItem in ConfigManager.Config.RecentFiles) { 390 InteropEmu.AddKnownGameFolder(recentItem.RomFile.Folder); 391 } 392 393 ConfigManager.Config.InitializeDefaults(); 394 ConfigManager.ApplyChanges(); 395 ConfigManager.Config.ApplyConfig(); 396 397 UpdateEmulationFlags(); 398 } 399 UpdateViewerSize(bool forceUpdate = false)400 private void UpdateViewerSize(bool forceUpdate = false) 401 { 402 this.Resize -= frmMain_Resize; 403 404 InteropEmu.ScreenSize size = InteropEmu.GetScreenSize(false); 405 406 if(forceUpdate || (!_customSize && this.WindowState != FormWindowState.Maximized)) { 407 Size sizeGap = this.Size - this.ClientSize; 408 409 bool doubleScreenMode = _isDualSystem && ConfigManager.Config.PreferenceInfo.VsDualVideoOutput == VsDualOutputOption.Both; 410 int width = doubleScreenMode ? (size.Width * 2) : size.Width; 411 412 UpdateScaleMenu(size.Scale); 413 this.ClientSize = new Size(Math.Max(this.MinimumSize.Width - sizeGap.Width, width), Math.Max(this.MinimumSize.Height - sizeGap.Height, size.Height + (this.HideMenuStrip ? 0 : menuStrip.Height))); 414 } 415 416 ctrlRenderer.Size = new Size(size.Width, size.Height); 417 UpdateRendererPosition(); 418 419 if(this.HideMenuStrip) { 420 this.menuStrip.Visible = false; 421 } 422 423 this.Resize += frmMain_Resize; 424 } 425 UpdateRendererPosition()426 private void UpdateRendererPosition() 427 { 428 ctrlRenderer.Top = (panelRenderer.Height - ctrlRenderer.Height) / 2; 429 430 if(_isDualSystem) { 431 UpdateDualSystemViewer(); 432 } else { 433 ctrlRenderer.Left = (panelRenderer.Width - ctrlRenderer.Width) / 2; 434 ctrlRendererDualSystem.Visible = false; 435 } 436 } 437 UpdateDualSystemViewer()438 private void UpdateDualSystemViewer() 439 { 440 ctrlRendererDualSystem.Size = new Size(ctrlRenderer.Width, ctrlRenderer.Height); 441 ctrlRendererDualSystem.Top = (panelRenderer.Height - ctrlRenderer.Height) / 2; 442 443 if(ConfigManager.Config.PreferenceInfo.VsDualVideoOutput == VsDualOutputOption.Both) { 444 ctrlRenderer.Left = (panelRenderer.Width / 2 - ctrlRenderer.Width) / 2; 445 ctrlRendererDualSystem.Left = ctrlRenderer.Left + ctrlRenderer.Width; 446 447 ctrlRendererDualSystem.Visible = true; 448 } else { 449 ctrlRenderer.Left = (panelRenderer.Width - ctrlRenderer.Width) / 2; 450 ctrlRendererDualSystem.Left = (panelRenderer.Width - ctrlRenderer.Width) / 2; 451 452 if(ConfigManager.Config.PreferenceInfo.VsDualVideoOutput == VsDualOutputOption.SlaveOnly) { 453 ctrlRendererDualSystem.Visible = true; 454 ctrlRendererDualSystem.BringToFront(); 455 } else { 456 ctrlRendererDualSystem.Visible = false; 457 } 458 } 459 } 460 ScaleControl(SizeF factor, BoundsSpecified specified)461 protected override void ScaleControl(SizeF factor, BoundsSpecified specified) 462 { 463 _yFactor = factor.Height; 464 base.ScaleControl(factor, specified); 465 } 466 ResizeRecentGames(object sender, EventArgs e)467 private void ResizeRecentGames(object sender, EventArgs e) 468 { 469 if(this.ClientSize.Height < 400 * _yFactor) { 470 ctrlRecentGames.Height = this.ClientSize.Height - (int)((125 - Math.Min(50, 400 - (int)(this.ClientSize.Height / _yFactor))) * _yFactor); 471 } else { 472 ctrlRecentGames.Height = this.ClientSize.Height - (int)(125 * _yFactor); 473 } 474 ctrlRecentGames.Width = this.ClientSize.Width; 475 ctrlRecentGames.Top = (this.HideMenuStrip && this.menuStrip.Visible) ? -menuStrip.Height : 0; 476 } 477 frmMain_Resize(object sender, EventArgs e)478 private void frmMain_Resize(object sender, EventArgs e) 479 { 480 if(_enableResize && this.WindowState != FormWindowState.Minimized) { 481 SetScaleBasedOnWindowSize(); 482 UpdateRendererPosition(); 483 } 484 } 485 SetScaleBasedOnDimensions(Size dimensions, bool allowVsDualScreen)486 private void SetScaleBasedOnDimensions(Size dimensions, bool allowVsDualScreen) 487 { 488 _customSize = true; 489 InteropEmu.ScreenSize size = InteropEmu.GetScreenSize(true); 490 491 if(allowVsDualScreen && _isDualSystem && ConfigManager.Config.PreferenceInfo.VsDualVideoOutput == VsDualOutputOption.Both) { 492 size = new InteropEmu.ScreenSize() { 493 Width = size.Width * 2, 494 Height = size.Height, 495 Scale = size.Scale 496 }; 497 } 498 499 double verticalScale = (double)dimensions.Height / size.Height; 500 double horizontalScale = (double)dimensions.Width / size.Width; 501 double scale = Math.Min(verticalScale, horizontalScale); 502 if(_fullscreenMode && ConfigManager.Config.VideoInfo.FullscreenForceIntegerScale) { 503 scale = Math.Floor(scale); 504 } 505 UpdateScaleMenu(scale); 506 VideoInfo.ApplyConfig(); 507 } 508 SetScaleBasedOnWindowSize()509 private void SetScaleBasedOnWindowSize() 510 { 511 SetScaleBasedOnDimensions(panelRenderer.ClientSize, true); 512 } 513 SetScaleBasedOnScreenSize()514 private void SetScaleBasedOnScreenSize() 515 { 516 SetScaleBasedOnDimensions(Screen.FromControl(this).Bounds.Size, false); 517 } 518 StopExclusiveFullscreenMode()519 private void StopExclusiveFullscreenMode() 520 { 521 if(_frmFullscreenRenderer != null) { 522 _frmFullscreenRenderer.Close(); 523 } 524 } 525 StartExclusiveFullscreenMode()526 private void StartExclusiveFullscreenMode() 527 { 528 Size screenSize = Screen.FromControl(this).Bounds.Size; 529 _frmFullscreenRenderer = new frmFullscreenRenderer(); 530 _frmFullscreenRenderer.Shown += (object sender, EventArgs e) => { 531 ctrlRenderer.Visible = false; 532 SetScaleBasedOnScreenSize(); 533 InteropEmu.SetFullscreenMode(true, _frmFullscreenRenderer.Handle, (UInt32)screenSize.Width, (UInt32)screenSize.Height); 534 }; 535 _frmFullscreenRenderer.FormClosing += (object sender, FormClosingEventArgs e) => { 536 InteropEmu.SetFullscreenMode(false, ctrlRenderer.Handle, (UInt32)screenSize.Width, (UInt32)screenSize.Height); 537 _frmFullscreenRenderer = null; 538 ctrlRenderer.Visible = true; 539 _fullscreenMode = false; 540 frmMain_Resize(null, EventArgs.Empty); 541 }; 542 543 Screen currentScreen = Screen.FromHandle(this.Handle); 544 _frmFullscreenRenderer.StartPosition = FormStartPosition.Manual; 545 _frmFullscreenRenderer.Top = currentScreen.Bounds.Top; 546 _frmFullscreenRenderer.Left = currentScreen.Bounds.Left; 547 _frmFullscreenRenderer.Show(); 548 } 549 StartFullscreenWindowMode(bool saveState)550 private void StartFullscreenWindowMode(bool saveState) 551 { 552 this.menuStrip.Visible = false; 553 if(saveState) { 554 _originalWindowState = this.WindowState; 555 _originalWindowMinimumSize = this.MinimumSize; 556 } 557 this.MinimumSize = new Size(0, 0); 558 this.WindowState = FormWindowState.Normal; 559 this.FormBorderStyle = FormBorderStyle.None; 560 this.WindowState = FormWindowState.Maximized; 561 SetScaleBasedOnWindowSize(); 562 } 563 StopFullscreenWindowMode()564 private void StopFullscreenWindowMode() 565 { 566 this.menuStrip.Visible = true; 567 this.WindowState = _originalWindowState; 568 this.MinimumSize = _originalWindowMinimumSize; 569 this.FormBorderStyle = ConfigManager.Config.PreferenceInfo.DisableMouseResize ? FormBorderStyle.Fixed3D : FormBorderStyle.Sizable; 570 this.frmMain_Resize(null, EventArgs.Empty); 571 } 572 SetFullscreenState(bool enabled)573 private void SetFullscreenState(bool enabled) 574 { 575 if(this._isNsfPlayerMode) { 576 enabled = false; 577 } 578 579 if(_fullscreenMode == enabled) { 580 //Fullscreen mode already matches, no need to do anything 581 return; 582 } 583 584 //Setup message to show on screen when paused while in fullscreen (instructions to revert to windowed mode) 585 InteropEmu.SetPauseScreenMessage(""); 586 if(enabled) { 587 ShortcutKeyInfo shortcut = ConfigManager.Config.PreferenceInfo.ShortcutKeys1.Find(ski => ski.Shortcut == EmulatorShortcut.ToggleFullscreen); 588 if(shortcut == null || shortcut.KeyCombination.IsEmpty) { 589 shortcut = ConfigManager.Config.PreferenceInfo.ShortcutKeys2.Find(ski => ski.Shortcut == EmulatorShortcut.ToggleFullscreen); 590 } 591 592 if(shortcut != null && !shortcut.KeyCombination.IsEmpty) { 593 InteropEmu.SetPauseScreenMessage(ResourceHelper.GetMessage("PressToExitFullscreen", shortcut.KeyCombination.ToString())); 594 } 595 } 596 597 bool saveState = !_fullscreenMode; 598 _fullscreenMode = enabled; 599 mnuFullscreen.Checked = enabled; 600 601 if(ConfigManager.Config.VideoInfo.UseExclusiveFullscreen) { 602 if(_emuThread != null) { 603 if(enabled) { 604 StartExclusiveFullscreenMode(); 605 } else { 606 StopExclusiveFullscreenMode(); 607 } 608 } 609 } else { 610 this.Resize -= frmMain_Resize; 611 if(enabled) { 612 StartFullscreenWindowMode(saveState); 613 } else { 614 StopFullscreenWindowMode(); 615 } 616 this.Resize += frmMain_Resize; 617 UpdateViewerSize(); 618 } 619 } 620 621 private bool HideMenuStrip 622 { 623 get 624 { 625 return (_fullscreenMode && !ConfigManager.Config.VideoInfo.UseExclusiveFullscreen) || ConfigManager.Config.PreferenceInfo.AutoHideMenu; 626 } 627 } 628 ctrlRenderer_MouseMove(object sender, MouseEventArgs e)629 private void ctrlRenderer_MouseMove(object sender, MouseEventArgs e) 630 { 631 if(sender != this.ctrlRecentGames) { 632 CursorManager.OnMouseMove((Control)sender); 633 } 634 635 if(this.HideMenuStrip && !this.menuStrip.ContainsFocus) { 636 if(sender == ctrlRenderer) { 637 this.menuStrip.Visible = ctrlRenderer.Top + e.Y < 30; 638 } else { 639 this.menuStrip.Visible = e.Y < 30; 640 } 641 } 642 } 643 ctrlRenderer_MouseClick(object sender, MouseEventArgs e)644 private void ctrlRenderer_MouseClick(object sender, MouseEventArgs e) 645 { 646 if(this.HideMenuStrip) { 647 this.menuStrip.Visible = false; 648 } 649 CursorManager.CaptureMouse(); 650 } 651 _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)652 private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e) 653 { 654 switch(e.NotificationType) { 655 case InteropEmu.ConsoleNotificationType.GameLoaded: 656 VideoInfo.ApplyOverscanConfig(); 657 _currentGame = InteropEmu.GetRomInfo().GetRomName(); 658 InteropEmu.SetNesModel(ConfigManager.Config.Region); 659 InitializeNsfMode(true); 660 CheatInfo.ApplyCheats(); 661 GameSpecificInfo.ApplyGameSpecificConfig(); 662 UpdateStateMenu(mnuSaveState, true); 663 UpdateStateMenu(mnuLoadState, false); 664 if(ConfigManager.Config.PreferenceInfo.ShowVsConfigOnLoad && InteropEmu.IsVsSystem()) { 665 this.Invoke((MethodInvoker)(() => { 666 this.ShowGameConfig(); 667 })); 668 } 669 670 this.StartEmuThread(); 671 this.BeginInvoke((MethodInvoker)(() => { 672 UpdateViewerSize(); 673 ProcessPostLoadCommandSwitches(); 674 })); 675 break; 676 677 case InteropEmu.ConsoleNotificationType.GameReset: 678 InitializeNsfMode(); 679 break; 680 681 case InteropEmu.ConsoleNotificationType.DisconnectedFromServer: 682 this.BeginInvoke((MethodInvoker)(() => { 683 ConfigManager.Config.ApplyConfig(); 684 })); 685 break; 686 687 case InteropEmu.ConsoleNotificationType.EmulationStopped: 688 InitializeNsfMode(); 689 break; 690 691 case InteropEmu.ConsoleNotificationType.GameStopped: 692 this._currentGame = null; 693 CheatInfo.ClearCheats(); 694 this.BeginInvoke((MethodInvoker)(() => { 695 if(_hdPackEditorWindow != null) { 696 _hdPackEditorWindow.Close(); 697 } 698 if(!ConfigManager.Config.PreferenceInfo.DisableGameSelectionScreen) { 699 ctrlRecentGames.Initialize(); 700 } 701 if(e.Parameter == IntPtr.Zero) { 702 //We are completely stopping the emulation, close fullscreen mode 703 StopExclusiveFullscreenMode(); 704 } 705 })); 706 break; 707 708 case InteropEmu.ConsoleNotificationType.BeforeEmulationStop: 709 //Close all debugger windows before continuing. 710 this.Invoke((Action)(() => { 711 DebugWindowManager.CloseAll(); 712 })); 713 break; 714 715 case InteropEmu.ConsoleNotificationType.ResolutionChanged: 716 this.BeginInvoke((MethodInvoker)(() => { 717 ProcessResolutionChanged(); 718 })); 719 break; 720 721 case InteropEmu.ConsoleNotificationType.FdsBiosNotFound: 722 this.BeginInvoke((MethodInvoker)(() => { 723 SelectFdsBiosPrompt(); 724 })); 725 break; 726 727 case InteropEmu.ConsoleNotificationType.ExecuteShortcut: 728 this.BeginInvoke((MethodInvoker)(() => { 729 ExecuteShortcut((EmulatorShortcut)e.Parameter); 730 })); 731 break; 732 733 case InteropEmu.ConsoleNotificationType.CodeBreak: 734 this.BeginInvoke((MethodInvoker)(() => { 735 if(DebugWindowManager.GetDebugger() == null) { 736 DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger); 737 } 738 })); 739 break; 740 741 case InteropEmu.ConsoleNotificationType.VsDualSystemStarted: 742 _isDualSystem = true; 743 this.BeginInvoke((MethodInvoker)(() => { 744 UpdateViewerSize(true); 745 InteropEmu.InitializeDualSystem(this.Handle, ctrlRendererDualSystem.Handle); 746 })); 747 break; 748 749 case InteropEmu.ConsoleNotificationType.VsDualSystemStopped: 750 _isDualSystem = false; 751 InteropEmu.ReleaseDualSystemAudioVideo(); 752 this.BeginInvoke((MethodInvoker)(() => { 753 UpdateViewerSize(true); 754 })); 755 break; 756 } 757 758 if(e.NotificationType != InteropEmu.ConsoleNotificationType.PpuFrameDone) { 759 UpdateMenus(); 760 } 761 } 762 ProcessResolutionChanged()763 private void ProcessResolutionChanged() 764 { 765 //Force scale specified by command line options, when using /fullscreen 766 if(_fullscreenRequested) { 767 SetFullscreenState(true); 768 if(_switchOptionScale.HasValue) { 769 //If a VideoScale is specified in command line, apply it 770 SetScale(_switchOptionScale.Value); 771 } 772 _fullscreenRequested = false; 773 } else if(_switchOptionScale.HasValue) { 774 //For exclusive fullscreen, resolution changed will be called twice, need to set the scale one more time here 775 SetScale(_switchOptionScale.Value); 776 _switchOptionScale = null; 777 } else { 778 UpdateViewerSize(); 779 } 780 } 781 BindShortcuts()782 private void BindShortcuts() 783 { 784 Func<bool> notClient = () => { return !InteropEmu.IsConnected(); }; 785 Func<bool> runningNotClient = () => { return _emuThread != null && !InteropEmu.IsConnected(); }; 786 Func<bool> runningNotClientNotMovie = () => { return _emuThread != null && !InteropEmu.IsConnected() && !InteropEmu.MoviePlaying(); }; 787 788 Func<bool> runningNotNsf = () => { return _emuThread != null && !InteropEmu.IsNsf(); }; 789 Func<bool> runningFdsNoAutoInsert = () => { return _emuThread != null && InteropEmu.FdsGetSideCount() > 0 && !InteropEmu.FdsIsAutoInsertDiskEnabled() && !InteropEmu.MoviePlaying() && !InteropEmu.IsConnected(); }; 790 Func<bool> runningFdsMultipleDisks = () => { return runningFdsNoAutoInsert() && InteropEmu.FdsGetSideCount() > 1; }; 791 Func<bool> runningVsSystem = () => { return _emuThread != null && InteropEmu.IsVsSystem() && !InteropEmu.MoviePlaying() && !InteropEmu.IsConnected(); }; 792 Func<bool> runningVsDualSystem = () => { return runningVsSystem() && InteropEmu.IsVsDualSystem(); }; 793 Func<bool> hasBarcodeReader = () => { return InteropEmu.GetAvailableFeatures().HasFlag(ConsoleFeatures.BarcodeReader) && !InteropEmu.IsConnected(); }; 794 795 Func<bool> enableLoadLastSession = () => { 796 string recentGameFile = _currentRomPath.HasValue ? Path.Combine(ConfigManager.RecentGamesFolder, Path.GetFileNameWithoutExtension(_currentRomPath.Value.FileName) + ".rgd") : ""; 797 return _emuThread != null && File.Exists(recentGameFile) && !ConfigManager.Config.PreferenceInfo.DisableGameSelectionScreen; 798 }; 799 800 BindShortcut(mnuOpen, EmulatorShortcut.OpenFile); 801 BindShortcut(mnuExit, EmulatorShortcut.Exit); 802 BindShortcut(mnuIncreaseSpeed, EmulatorShortcut.IncreaseSpeed, notClient); 803 BindShortcut(mnuDecreaseSpeed, EmulatorShortcut.DecreaseSpeed, notClient); 804 BindShortcut(mnuEmuSpeedMaximumSpeed, EmulatorShortcut.MaxSpeed, notClient); 805 806 BindShortcut(mnuPause, EmulatorShortcut.Pause, runningNotClient); 807 BindShortcut(mnuReset, EmulatorShortcut.Reset, runningNotClientNotMovie); 808 BindShortcut(mnuPowerCycle, EmulatorShortcut.PowerCycle, runningNotClientNotMovie); 809 BindShortcut(mnuPowerOff, EmulatorShortcut.PowerOff, runningNotClient); 810 811 BindShortcut(mnuSwitchDiskSide, EmulatorShortcut.SwitchDiskSide, runningFdsMultipleDisks); 812 BindShortcut(mnuEjectDisk, EmulatorShortcut.EjectDisk, runningFdsNoAutoInsert); 813 814 BindShortcut(mnuInsertCoin1, EmulatorShortcut.InsertCoin1, runningVsSystem); 815 BindShortcut(mnuInsertCoin2, EmulatorShortcut.InsertCoin2, runningVsSystem); 816 BindShortcut(mnuInsertCoin3, EmulatorShortcut.InsertCoin3, runningVsDualSystem); 817 BindShortcut(mnuInsertCoin4, EmulatorShortcut.InsertCoin4, runningVsDualSystem); 818 819 BindShortcut(mnuInputBarcode, EmulatorShortcut.InputBarcode, hasBarcodeReader); 820 821 BindShortcut(mnuShowFPS, EmulatorShortcut.ToggleFps); 822 823 BindShortcut(mnuScale1x, EmulatorShortcut.SetScale1x); 824 BindShortcut(mnuScale2x, EmulatorShortcut.SetScale2x); 825 BindShortcut(mnuScale3x, EmulatorShortcut.SetScale3x); 826 BindShortcut(mnuScale4x, EmulatorShortcut.SetScale4x); 827 BindShortcut(mnuScale5x, EmulatorShortcut.SetScale5x); 828 BindShortcut(mnuScale6x, EmulatorShortcut.SetScale6x); 829 830 BindShortcut(mnuFullscreen, EmulatorShortcut.ToggleFullscreen); 831 832 BindShortcut(mnuLoadLastSession, EmulatorShortcut.LoadLastSession, enableLoadLastSession); 833 834 BindShortcut(mnuTakeScreenshot, EmulatorShortcut.TakeScreenshot, runningNotNsf); 835 BindShortcut(mnuRandomGame, EmulatorShortcut.LoadRandomGame); 836 837 mnuDebugDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenDebugger)); 838 mnuDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenDebugger)); 839 mnuApuViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenApuViewer)); 840 mnuAssembler.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenAssembler)); 841 mnuMemoryViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenMemoryTools)); 842 mnuEventViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenEventViewer)); 843 mnuPpuViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenPpuViewer)); 844 mnuScriptWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenScriptWindow)); 845 mnuTraceLogger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTraceLogger)); 846 mnuTextHooker.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTextHooker)); 847 mnuProfiler.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenProfiler)); 848 mnuWatchWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenWatchWindow)); 849 850 mnuOpenNametableViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenNametableViewer)); 851 mnuOpenChrViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenChrViewer)); 852 mnuOpenSpriteViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenSpriteViewer)); 853 mnuOpenPaletteViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenPaletteViewer)); 854 } 855 BindShortcut(ToolStripMenuItem item, EmulatorShortcut shortcut, Func<bool> isActionEnabled = null)856 private void BindShortcut(ToolStripMenuItem item, EmulatorShortcut shortcut, Func<bool> isActionEnabled = null) 857 { 858 item.Click += (object sender, EventArgs e) => { 859 if(isActionEnabled == null || isActionEnabled()) { 860 ExecuteShortcut(shortcut); 861 } 862 }; 863 864 _actionEnabledFuncs[shortcut] = isActionEnabled; 865 866 if(item.OwnerItem is ToolStripMenuItem) { 867 Action updateShortcut = () => { 868 int keyIndex = ConfigManager.Config.PreferenceInfo.ShortcutKeys1.FindIndex((ShortcutKeyInfo shortcutInfo) => shortcutInfo.Shortcut == shortcut); 869 if(keyIndex >= 0) { 870 item.ShortcutKeyDisplayString = ConfigManager.Config.PreferenceInfo.ShortcutKeys1[keyIndex].KeyCombination.ToString(); 871 } else { 872 keyIndex = ConfigManager.Config.PreferenceInfo.ShortcutKeys2.FindIndex((ShortcutKeyInfo shortcutInfo) => shortcutInfo.Shortcut == shortcut); 873 if(keyIndex >= 0) { 874 item.ShortcutKeyDisplayString = ConfigManager.Config.PreferenceInfo.ShortcutKeys2[keyIndex].KeyCombination.ToString(); 875 } else { 876 item.ShortcutKeyDisplayString = ""; 877 } 878 } 879 item.Enabled = isActionEnabled == null || isActionEnabled(); 880 }; 881 882 updateShortcut(); 883 884 //Update item shortcut text when its parent opens 885 ((ToolStripMenuItem)item.OwnerItem).DropDownOpening += (object sender, EventArgs e) => { updateShortcut(); }; 886 } 887 } 888 ExecuteShortcut(EmulatorShortcut shortcut)889 private void ExecuteShortcut(EmulatorShortcut shortcut) 890 { 891 Func<bool> isActionEnabled; 892 if(_actionEnabledFuncs.TryGetValue(shortcut, out isActionEnabled)) { 893 isActionEnabled = _actionEnabledFuncs[shortcut]; 894 if(isActionEnabled != null && !isActionEnabled()) { 895 //Action disabled 896 return; 897 } 898 } 899 900 bool restoreFullscreen = _frmFullscreenRenderer != null; 901 902 switch(shortcut) { 903 case EmulatorShortcut.Pause: PauseEmu(); break; 904 case EmulatorShortcut.Reset: this.ResetEmu(); break; 905 case EmulatorShortcut.PowerCycle: this.PowerCycleEmu(); break; 906 case EmulatorShortcut.PowerOff: Task.Run(() => InteropEmu.Stop()); break; 907 case EmulatorShortcut.Exit: this.Close(); break; 908 909 case EmulatorShortcut.ToggleCheats: ToggleCheats(); break; 910 case EmulatorShortcut.ToggleAudio: ToggleAudio(); break; 911 case EmulatorShortcut.ToggleFps: ToggleFps(); break; 912 case EmulatorShortcut.ToggleBackground: ToggleBackground(); break; 913 case EmulatorShortcut.ToggleSprites: ToggleSprites(); break; 914 case EmulatorShortcut.ToggleGameTimer: ToggleGameTimer(); break; 915 case EmulatorShortcut.ToggleFrameCounter: ToggleFrameCounter(); break; 916 case EmulatorShortcut.ToggleLagCounter: ToggleLagCounter(); break; 917 case EmulatorShortcut.ToggleOsd: ToggleOsd(); break; 918 case EmulatorShortcut.ToggleAlwaysOnTop: ToggleAlwaysOnTop(); break; 919 case EmulatorShortcut.ToggleDebugInfo: ToggleDebugInfo(); break; 920 case EmulatorShortcut.MaxSpeed: ToggleMaxSpeed(); break; 921 case EmulatorShortcut.ToggleFullscreen: ToggleFullscreen(); restoreFullscreen = false; break; 922 923 case EmulatorShortcut.OpenFile: OpenFile(); break; 924 case EmulatorShortcut.IncreaseSpeed: InteropEmu.IncreaseEmulationSpeed(); break; 925 case EmulatorShortcut.DecreaseSpeed: InteropEmu.DecreaseEmulationSpeed(); break; 926 case EmulatorShortcut.SwitchDiskSide: InteropEmu.FdsSwitchDiskSide(); break; 927 case EmulatorShortcut.EjectDisk: InteropEmu.FdsEjectDisk(); break; 928 929 case EmulatorShortcut.SetScale1x: SetScale(1); break; 930 case EmulatorShortcut.SetScale2x: SetScale(2); break; 931 case EmulatorShortcut.SetScale3x: SetScale(3); break; 932 case EmulatorShortcut.SetScale4x: SetScale(4); break; 933 case EmulatorShortcut.SetScale5x: SetScale(5); break; 934 case EmulatorShortcut.SetScale6x: SetScale(6); break; 935 936 case EmulatorShortcut.InsertCoin1: InteropEmu.VsInsertCoin(0); break; 937 case EmulatorShortcut.InsertCoin2: InteropEmu.VsInsertCoin(1); break; 938 case EmulatorShortcut.InsertCoin3: InteropEmu.VsInsertCoin(2); break; 939 case EmulatorShortcut.InsertCoin4: InteropEmu.VsInsertCoin(3); break; 940 941 case EmulatorShortcut.InputBarcode: 942 using(frmInputBarcode frm = new frmInputBarcode()) { 943 frm.ShowDialog(this, this); 944 } 945 break; 946 947 case EmulatorShortcut.TakeScreenshot: InteropEmu.TakeScreenshot(); break; 948 case EmulatorShortcut.LoadRandomGame: LoadRandomGame(); break; 949 950 case EmulatorShortcut.LoadStateFromFile: LoadStateFromFile(); break; 951 case EmulatorShortcut.SaveStateToFile: SaveStateToFile(); break; 952 953 case EmulatorShortcut.SaveStateSlot1: SaveState(1); break; 954 case EmulatorShortcut.SaveStateSlot2: SaveState(2); break; 955 case EmulatorShortcut.SaveStateSlot3: SaveState(3); break; 956 case EmulatorShortcut.SaveStateSlot4: SaveState(4); break; 957 case EmulatorShortcut.SaveStateSlot5: SaveState(5); break; 958 case EmulatorShortcut.SaveStateSlot6: SaveState(6); break; 959 case EmulatorShortcut.SaveStateSlot7: SaveState(7); break; 960 case EmulatorShortcut.SaveStateSlot8: SaveState(8); break; 961 case EmulatorShortcut.SaveStateSlot9: SaveState(9); break; 962 case EmulatorShortcut.SaveStateSlot10: SaveState(10); break; 963 case EmulatorShortcut.LoadStateSlot1: LoadState(1); break; 964 case EmulatorShortcut.LoadStateSlot2: LoadState(2); break; 965 case EmulatorShortcut.LoadStateSlot3: LoadState(3); break; 966 case EmulatorShortcut.LoadStateSlot4: LoadState(4); break; 967 case EmulatorShortcut.LoadStateSlot5: LoadState(5); break; 968 case EmulatorShortcut.LoadStateSlot6: LoadState(6); break; 969 case EmulatorShortcut.LoadStateSlot7: LoadState(7); break; 970 case EmulatorShortcut.LoadStateSlot8: LoadState(8); break; 971 case EmulatorShortcut.LoadStateSlot9: LoadState(9); break; 972 case EmulatorShortcut.LoadStateSlot10: LoadState(10); break; 973 case EmulatorShortcut.LoadStateSlotAuto: LoadState(11); break; 974 975 case EmulatorShortcut.LoadLastSession: LoadLastSession(); break; 976 } 977 978 if(restoreFullscreen && _frmFullscreenRenderer == null && !_shuttingDown) { 979 //Need to restore fullscreen mode after showing a dialog 980 this.SetFullscreenState(true); 981 } 982 } 983 ToggleFullscreen()984 private void ToggleFullscreen() 985 { 986 SetFullscreenState(!_fullscreenMode); 987 } 988 ToggleMaxSpeed()989 private void ToggleMaxSpeed() 990 { 991 if(ConfigManager.Config.EmulationInfo.EmulationSpeed == 0) { 992 SetEmulationSpeed(100); 993 } else { 994 SetEmulationSpeed(0); 995 } 996 } 997 ToggleFps()998 private void ToggleFps() 999 { 1000 mnuShowFPS.Checked = !mnuShowFPS.Checked; 1001 UpdateEmulationFlags(); 1002 } 1003 ToggleAudio()1004 private void ToggleAudio() 1005 { 1006 ConfigManager.Config.AudioInfo.EnableAudio = !ConfigManager.Config.AudioInfo.EnableAudio; 1007 AudioInfo.ApplyConfig(); 1008 ConfigManager.ApplyChanges(); 1009 } 1010 ToggleFrameCounter()1011 private void ToggleFrameCounter() 1012 { 1013 ConfigManager.Config.PreferenceInfo.ShowFrameCounter = !ConfigManager.Config.PreferenceInfo.ShowFrameCounter; 1014 PreferenceInfo.ApplyConfig(); 1015 ConfigManager.ApplyChanges(); 1016 } 1017 ToggleLagCounter()1018 private void ToggleLagCounter() 1019 { 1020 ConfigManager.Config.EmulationInfo.ShowLagCounter = !ConfigManager.Config.EmulationInfo.ShowLagCounter; 1021 EmulationInfo.ApplyConfig(); 1022 ConfigManager.ApplyChanges(); 1023 } 1024 ToggleGameTimer()1025 private void ToggleGameTimer() 1026 { 1027 ConfigManager.Config.PreferenceInfo.ShowGameTimer = !ConfigManager.Config.PreferenceInfo.ShowGameTimer; 1028 PreferenceInfo.ApplyConfig(); 1029 ConfigManager.ApplyChanges(); 1030 } 1031 ToggleOsd()1032 private void ToggleOsd() 1033 { 1034 ConfigManager.Config.PreferenceInfo.DisableOsd = !ConfigManager.Config.PreferenceInfo.DisableOsd; 1035 PreferenceInfo.ApplyConfig(); 1036 ConfigManager.ApplyChanges(); 1037 } 1038 ToggleAlwaysOnTop()1039 private void ToggleAlwaysOnTop() 1040 { 1041 ConfigManager.Config.PreferenceInfo.AlwaysOnTop = !ConfigManager.Config.PreferenceInfo.AlwaysOnTop; 1042 ConfigManager.ApplyChanges(); 1043 this.TopMost = ConfigManager.Config.PreferenceInfo.AlwaysOnTop; 1044 } 1045 ToggleSprites()1046 private void ToggleSprites() 1047 { 1048 ConfigManager.Config.VideoInfo.DisableSprites = !ConfigManager.Config.VideoInfo.DisableSprites; 1049 VideoInfo.ApplyConfig(); 1050 ConfigManager.ApplyChanges(); 1051 } 1052 ToggleBackground()1053 private void ToggleBackground() 1054 { 1055 ConfigManager.Config.VideoInfo.DisableBackground = !ConfigManager.Config.VideoInfo.DisableBackground; 1056 VideoInfo.ApplyConfig(); 1057 ConfigManager.ApplyChanges(); 1058 } 1059 ToggleDebugInfo()1060 private void ToggleDebugInfo() 1061 { 1062 ConfigManager.Config.PreferenceInfo.DisplayDebugInfo = !ConfigManager.Config.PreferenceInfo.DisplayDebugInfo; 1063 PreferenceInfo.ApplyConfig(); 1064 ConfigManager.ApplyChanges(); 1065 } 1066 ToggleCheats()1067 private void ToggleCheats() 1068 { 1069 ConfigManager.Config.DisableAllCheats = !ConfigManager.Config.DisableAllCheats; 1070 if(ConfigManager.Config.DisableAllCheats) { 1071 InteropEmu.DisplayMessage("Cheats", "CheatsDisabled"); 1072 } 1073 CheatInfo.ApplyCheats(); 1074 ConfigManager.ApplyChanges(); 1075 } 1076 UpdateMenus()1077 private void UpdateMenus() 1078 { 1079 if(_shuttingDown) { 1080 return; 1081 } 1082 1083 try { 1084 if(this.InvokeRequired) { 1085 this.BeginInvoke((MethodInvoker)(() => this.UpdateMenus())); 1086 } else { 1087 bool running = _emuThread != null; 1088 bool devMode = ConfigManager.Config.PreferenceInfo.DeveloperMode; 1089 mnuDebug.Visible = devMode; 1090 1091 panelInfo.Visible = !running; 1092 ctrlRecentGames.Visible = !running; 1093 1094 ctrlLoading.Visible = (_romLoadCounter > 0); 1095 1096 UpdateWindowTitle(); 1097 1098 bool isNetPlayClient = InteropEmu.IsConnected(); 1099 1100 mnuSaveState.Enabled = (running && !isNetPlayClient && !InteropEmu.IsNsf()); 1101 mnuLoadState.Enabled = (running && !isNetPlayClient && !InteropEmu.IsNsf() && !InteropEmu.MoviePlaying() && !InteropEmu.MovieRecording()); 1102 1103 mnuPause.Text = InteropEmu.IsPaused() ? ResourceHelper.GetMessage("Resume") : ResourceHelper.GetMessage("Pause"); 1104 mnuPause.Image = InteropEmu.IsPaused() ? _playButton : _pauseButton; 1105 1106 bool netPlay = InteropEmu.IsServerRunning() || isNetPlayClient; 1107 1108 mnuStartServer.Enabled = !isNetPlayClient; 1109 mnuConnect.Enabled = !InteropEmu.IsServerRunning(); 1110 mnuNetPlaySelectController.Enabled = isNetPlayClient || InteropEmu.IsServerRunning(); 1111 if(mnuNetPlaySelectController.Enabled) { 1112 int availableControllers = InteropEmu.NetPlayGetAvailableControllers(); 1113 int currentControllerPort = InteropEmu.NetPlayGetControllerPort(); 1114 mnuNetPlayPlayer1.Enabled = (availableControllers & 0x01) == 0x01; 1115 mnuNetPlayPlayer2.Enabled = (availableControllers & 0x02) == 0x02; 1116 mnuNetPlayPlayer3.Enabled = (availableControllers & 0x04) == 0x04; 1117 mnuNetPlayPlayer4.Enabled = (availableControllers & 0x08) == 0x08; 1118 1119 bool isFamicom = InteropEmu.GetConsoleType() == ConsoleType.Famicom; 1120 mnuNetPlayPlayer5.Visible = isFamicom; 1121 mnuNetPlayPlayer5.Enabled = (availableControllers & 0x10) == 0x10 && InteropEmu.GetExpansionDevice() != InteropEmu.ExpansionPortDevice.FourPlayerAdapter; 1122 1123 mnuNetPlayPlayer1.Text = ResourceHelper.GetMessage("PlayerNumber", "1") + " (" + ResourceHelper.GetEnumText(InteropEmu.NetPlayGetControllerType(0)) + ")"; 1124 mnuNetPlayPlayer2.Text = ResourceHelper.GetMessage("PlayerNumber", "2") + " (" + ResourceHelper.GetEnumText(InteropEmu.NetPlayGetControllerType(1)) + ")"; 1125 mnuNetPlayPlayer3.Text = ResourceHelper.GetMessage("PlayerNumber", "3") + " (" + ResourceHelper.GetEnumText(InteropEmu.NetPlayGetControllerType(2)) + ")"; 1126 mnuNetPlayPlayer4.Text = ResourceHelper.GetMessage("PlayerNumber", "4") + " (" + ResourceHelper.GetEnumText(InteropEmu.NetPlayGetControllerType(3)) + ")"; 1127 mnuNetPlayPlayer5.Text = ResourceHelper.GetMessage("ExpansionDevice") + " (" + ResourceHelper.GetEnumText(InteropEmu.GetExpansionDevice()) + ")"; 1128 1129 mnuNetPlayPlayer1.Checked = (currentControllerPort == 0); 1130 mnuNetPlayPlayer2.Checked = (currentControllerPort == 1); 1131 mnuNetPlayPlayer3.Checked = (currentControllerPort == 2); 1132 mnuNetPlayPlayer4.Checked = (currentControllerPort == 3); 1133 mnuNetPlayPlayer5.Checked = (currentControllerPort == 4); 1134 mnuNetPlaySpectator.Checked = (currentControllerPort == 0xFF); 1135 1136 mnuNetPlaySpectator.Enabled = true; 1137 } 1138 1139 mnuStartServer.Text = InteropEmu.IsServerRunning() ? ResourceHelper.GetMessage("StopServer") : ResourceHelper.GetMessage("StartServer"); 1140 mnuConnect.Text = isNetPlayClient ? ResourceHelper.GetMessage("Disconnect") : ResourceHelper.GetMessage("ConnectToServer"); 1141 1142 mnuCheats.Enabled = !isNetPlayClient; 1143 mnuEmulationSpeed.Enabled = !isNetPlayClient; 1144 mnuInput.Enabled = !isNetPlayClient; 1145 mnuRegion.Enabled = !isNetPlayClient; 1146 1147 bool moviePlaying = InteropEmu.MoviePlaying(); 1148 bool movieRecording = InteropEmu.MovieRecording(); 1149 mnuPlayMovie.Enabled = !netPlay && !moviePlaying && !movieRecording; 1150 mnuStopMovie.Enabled = running && !netPlay && (moviePlaying || movieRecording); 1151 mnuRecordMovie.Enabled = running && !moviePlaying && !movieRecording && !isNetPlayClient; 1152 mnuGameConfig.Enabled = !moviePlaying && !movieRecording; 1153 mnuHistoryViewer.Enabled = running && InteropEmu.HistoryViewerEnabled(); 1154 1155 bool waveRecording = InteropEmu.WaveIsRecording(); 1156 mnuWaveRecord.Enabled = running && !waveRecording; 1157 mnuWaveStop.Enabled = running && waveRecording; 1158 1159 bool aviRecording = InteropEmu.AviIsRecording(); 1160 mnuAviRecord.Enabled = running && !aviRecording; 1161 mnuAviStop.Enabled = running && aviRecording; 1162 mnuVideoRecorder.Enabled = !_isNsfPlayerMode; 1163 1164 bool testRecording = InteropEmu.RomTestRecording(); 1165 mnuTestRun.Enabled = !netPlay && !moviePlaying && !movieRecording; 1166 mnuTestStopRecording.Enabled = running && testRecording; 1167 mnuTestRecordStart.Enabled = running && !isNetPlayClient && !moviePlaying && !movieRecording; 1168 mnuTestRecordNow.Enabled = running && !moviePlaying && !movieRecording; 1169 mnuTestRecordMovie.Enabled = !netPlay && !moviePlaying && !movieRecording; 1170 mnuTestRecordTest.Enabled = !netPlay && !moviePlaying && !movieRecording; 1171 mnuTestRecordFrom.Enabled = (mnuTestRecordStart.Enabled || mnuTestRecordNow.Enabled || mnuTestRecordMovie.Enabled || mnuTestRecordTest.Enabled); 1172 1173 bool tapeRecording = InteropEmu.IsRecordingTapeFile(); 1174 mnuTapeRecorder.Enabled = !isNetPlayClient; 1175 mnuLoadTapeFile.Enabled = !isNetPlayClient; 1176 mnuStartRecordTapeFile.Enabled = !tapeRecording && !isNetPlayClient; 1177 mnuStopRecordTapeFile.Enabled = tapeRecording; 1178 1179 mnuDebugger.Visible = !devMode; 1180 mnuDebugger.Enabled = !devMode && running; 1181 mnuDebugDebugger.Enabled = devMode && running; 1182 mnuApuViewer.Enabled = running; 1183 mnuAssembler.Enabled = running; 1184 mnuMemoryViewer.Enabled = running; 1185 mnuEventViewer.Enabled = running; 1186 mnuPpuViewer.Enabled = running; 1187 mnuScriptWindow.Enabled = running; 1188 mnuTextHooker.Enabled = running; 1189 mnuTraceLogger.Enabled = running; 1190 mnuProfiler.Enabled = running; 1191 mnuWatchWindow.Enabled = running; 1192 1193 mnuPpuViewerCompact.Enabled = running; 1194 mnuOpenNametableViewer.Enabled = running; 1195 mnuOpenChrViewer.Enabled = running; 1196 mnuOpenSpriteViewer.Enabled = running; 1197 mnuOpenPaletteViewer.Enabled = running; 1198 1199 #if !HIDETESTMENU 1200 //Keep this option hidden for now, until some remaining issues are fixed. 1201 mnuDebugDualSystemSecondaryCpu.Visible = _isDualSystem; 1202 sepDebugDualSystemSecondaryCpu.Visible = _isDualSystem; 1203 #else 1204 mnuDebugDualSystemSecondaryCpu.Visible = false; 1205 sepDebugDualSystemSecondaryCpu.Visible = false; 1206 #endif 1207 1208 mnuInstallHdPack.Enabled = running; 1209 mnuHdPackEditor.Enabled = !netPlay && running; 1210 1211 mnuNetPlay.Enabled = !InteropEmu.IsNsf(); 1212 if(running && InteropEmu.IsNsf()) { 1213 mnuPowerCycle.Enabled = false; 1214 mnuMovies.Enabled = mnuPlayMovie.Enabled = mnuStopMovie.Enabled = mnuRecordMovie.Enabled = false; 1215 } 1216 1217 mnuRegionAuto.Checked = ConfigManager.Config.Region == NesModel.Auto; 1218 mnuRegionNtsc.Checked = ConfigManager.Config.Region == NesModel.NTSC; 1219 mnuRegionPal.Checked = ConfigManager.Config.Region == NesModel.PAL; 1220 mnuRegionDendy.Checked = ConfigManager.Config.Region == NesModel.Dendy; 1221 1222 bool autoInsertDisabled = !InteropEmu.FdsIsAutoInsertDiskEnabled(); 1223 mnuSelectDisk.Enabled = autoInsertDisabled; 1224 1225 bool isHdPackLoader = InteropEmu.IsHdPpu(); 1226 mnuNtscFilter.Enabled = !isHdPackLoader; 1227 mnuNtscBisqwitQuarterFilter.Enabled = !isHdPackLoader; 1228 mnuNtscBisqwitHalfFilter.Enabled = !isHdPackLoader; 1229 mnuNtscBisqwitFullFilter.Enabled = !isHdPackLoader; 1230 } 1231 } catch { } 1232 } 1233 UpdateWindowTitle()1234 private void UpdateWindowTitle() 1235 { 1236 string title = "Mesen"; 1237 if(!string.IsNullOrWhiteSpace(_currentGame)) { 1238 title += " - " + _currentGame; 1239 } 1240 if(ConfigManager.Config.PreferenceInfo.DisplayTitleBarInfo) { 1241 title += string.Format(" - {0}x{1} ({2:0.##}x, {3}) - {4}", ctrlRenderer.Width, ctrlRenderer.Height, ConfigManager.Config.VideoInfo.VideoScale, ResourceHelper.GetEnumText(ConfigManager.Config.VideoInfo.AspectRatio), ResourceHelper.GetEnumText(ConfigManager.Config.VideoInfo.VideoFilter)); 1242 } 1243 this.Text = title; 1244 } 1245 StartEmuThread()1246 private void StartEmuThread() 1247 { 1248 if(_emuThread == null) { 1249 _emuThread = new Thread(() => { 1250 try { 1251 InteropEmu.Run(); 1252 _emuThread = null; 1253 } catch(Exception ex) { 1254 MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString()); 1255 _emuThread = null; 1256 } 1257 }); 1258 _emuThread.Start(); 1259 } 1260 UpdateMenus(); 1261 } 1262 StopEmu()1263 private void StopEmu() 1264 { 1265 InteropEmu.Stop(); 1266 } 1267 PauseEmu()1268 private void PauseEmu() 1269 { 1270 frmDebugger debugger = DebugWindowManager.GetDebugger(); 1271 if(debugger != null) { 1272 debugger.TogglePause(); 1273 } else { 1274 if(InteropEmu.IsPaused()) { 1275 InteropEmu.Resume(); 1276 } else { 1277 InteropEmu.Pause(); 1278 } 1279 1280 ctrlNsfPlayer.UpdateText(); 1281 } 1282 } 1283 ResetEmu()1284 private void ResetEmu() 1285 { 1286 if(!ConfigManager.Config.PreferenceInfo.ConfirmExitResetPower || MesenMsgBox.Show("ConfirmReset", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) { 1287 InteropEmu.Reset(); 1288 } 1289 } 1290 PowerCycleEmu()1291 private void PowerCycleEmu() 1292 { 1293 if(!ConfigManager.Config.PreferenceInfo.ConfirmExitResetPower || MesenMsgBox.Show("ConfirmPowerCycle", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK) { 1294 InteropEmu.PowerCycle(); 1295 } 1296 } 1297 ProcessCmdKey(ref Message msg, Keys keyData)1298 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 1299 { 1300 if(!this.menuStrip.Enabled) { 1301 //Make sure we disable all shortcut keys while the bar is disabled (i.e when running tests) 1302 return false; 1303 } 1304 1305 if(this.HideMenuStrip && (keyData & Keys.Alt) == Keys.Alt) { 1306 if(this.menuStrip.Visible && !this.menuStrip.ContainsFocus) { 1307 this.menuStrip.Visible = false; 1308 } else { 1309 this.menuStrip.Visible = true; 1310 this.menuStrip.Focus(); 1311 } 1312 } 1313 1314 #if !HIDETESTMENU 1315 if(keyData == Keys.Pause) { 1316 if(InteropEmu.RomTestRecording()) { 1317 InteropEmu.RomTestStop(); 1318 } else { 1319 InteropEmu.RomTestRecord(ConfigManager.TestFolder + "\\" + InteropEmu.GetRomInfo().GetRomName() + ".mtp", true); 1320 } 1321 } 1322 #endif 1323 1324 return base.ProcessCmdKey(ref msg, keyData); 1325 } 1326 SelectFdsBiosPrompt()1327 private void SelectFdsBiosPrompt() 1328 { 1329 if(MesenMsgBox.Show("FdsBiosNotFound", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) { 1330 using(OpenFileDialog ofd = new OpenFileDialog()) { 1331 ofd.SetFilter(ResourceHelper.GetMessage("FilterAll")); 1332 if(ofd.ShowDialog(this) == DialogResult.OK) { 1333 string hash = MD5Helper.GetMD5Hash(ofd.FileName).ToLowerInvariant(); 1334 if(hash == "ca30b50f880eb660a320674ed365ef7a" || hash == "c1a9e9415a6adde3c8563c622d4c9fce") { 1335 File.Copy(ofd.FileName, Path.Combine(ConfigManager.HomeFolder, "FdsBios.bin")); 1336 LoadROM(_currentRomPath.Value, ConfigManager.Config.PreferenceInfo.AutoLoadIpsPatches); 1337 } else { 1338 MesenMsgBox.Show("InvalidFdsBios", MessageBoxButtons.OK, MessageBoxIcon.Error); 1339 } 1340 } 1341 } 1342 } 1343 } 1344 frmMain_DragDrop(object sender, DragEventArgs e)1345 private void frmMain_DragDrop(object sender, DragEventArgs e) 1346 { 1347 try { 1348 string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); 1349 if(File.Exists(files[0])) { 1350 LoadFile(files[0]); 1351 this.Activate(); 1352 } else { 1353 InteropEmu.DisplayMessage("Error", "File not found: " + files[0]); 1354 } 1355 } catch(Exception ex) { 1356 MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString()); 1357 } 1358 } 1359 frmMain_DragEnter(object sender, DragEventArgs e)1360 private void frmMain_DragEnter(object sender, DragEventArgs e) 1361 { 1362 try { 1363 if(e.Data != null && e.Data.GetDataPresent(DataFormats.FileDrop)) { 1364 e.Effect = DragDropEffects.Copy; 1365 } else { 1366 InteropEmu.DisplayMessage("Error", "Unsupported operation."); 1367 } 1368 } catch(Exception ex) { 1369 MesenMsgBox.Show("UnexpectedError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString()); 1370 } 1371 } 1372 ctrlRenderer_DoubleClick(object sender, EventArgs e)1373 private void ctrlRenderer_DoubleClick(object sender, EventArgs e) 1374 { 1375 if(!CursorManager.NeedMouseIcon && !CursorManager.AllowMouseCapture && !DebugWindowManager.HasOpenedWindow) { 1376 //Disable double clicking (used to switch to fullscreen mode) when using a mouse-controlled device (or when debugger is opened) 1377 ToggleFullscreen(); 1378 } 1379 } 1380 panelRenderer_Click(object sender, EventArgs e)1381 private void panelRenderer_Click(object sender, EventArgs e) 1382 { 1383 if(this.HideMenuStrip) { 1384 this.menuStrip.Visible = false; 1385 } 1386 CursorManager.CaptureMouse(); 1387 1388 ctrlRenderer.Focus(); 1389 } 1390 ctrlRenderer_Enter(object sender, EventArgs e)1391 private void ctrlRenderer_Enter(object sender, EventArgs e) 1392 { 1393 if(this.HideMenuStrip) { 1394 this.menuStrip.Visible = false; 1395 } 1396 } 1397 menuStrip_VisibleChanged(object sender, EventArgs e)1398 private void menuStrip_VisibleChanged(object sender, EventArgs e) 1399 { 1400 this.UpdateRendererLocation(); 1401 } 1402 UpdateRendererLocation()1403 private void UpdateRendererLocation() 1404 { 1405 if(this.HideMenuStrip) { 1406 IntPtr handle = this.Handle; 1407 this.BeginInvoke((MethodInvoker)(() => { 1408 int rendererTop = (panelRenderer.Height + (this.menuStrip.Visible ? menuStrip.Height : 0) - ctrlRenderer.Height) / 2; 1409 this.ctrlRenderer.Top = rendererTop + (this.menuStrip.Visible ? -menuStrip.Height : 0); 1410 this.ctrlRecentGames.Top = this.menuStrip.Visible ? -menuStrip.Height : 0; 1411 })); 1412 } 1413 } 1414 InitializeNsfMode(bool gameLoaded = false)1415 private void InitializeNsfMode(bool gameLoaded = false) 1416 { 1417 if(this.InvokeRequired) { 1418 if(InteropEmu.IsNsf()) { 1419 if(InteropEmu.IsConnected()) { 1420 InteropEmu.Disconnect(); 1421 } 1422 if(InteropEmu.IsServerRunning()) { 1423 InteropEmu.StopServer(); 1424 } 1425 } 1426 this.BeginInvoke((MethodInvoker)(() => this.InitializeNsfMode(gameLoaded))); 1427 } else { 1428 if(InteropEmu.IsNsf()) { 1429 this.SetFullscreenState(false); 1430 1431 if(gameLoaded) { 1432 //Force emulation speed to 100 when loading a NSF 1433 SetEmulationSpeed(100); 1434 } 1435 1436 if(!this._isNsfPlayerMode) { 1437 this._nonNsfSize = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Size : this.Size; 1438 this._nonNsfMinimumSize = this.MinimumSize; 1439 this.Size = ctrlNsfPlayer.WindowMinimumSize; 1440 this.MinimumSize = ctrlNsfPlayer.WindowMinimumSize; 1441 } 1442 this._isNsfPlayerMode = true; 1443 this.ctrlNsfPlayer.UpdateText(); 1444 this.ctrlNsfPlayer.Visible = true; 1445 this.ctrlNsfPlayer.Focus(); 1446 1447 NsfHeader header = InteropEmu.NsfGetHeader(); 1448 if(header.HasSongName) { 1449 _currentGame = header.GetSongName(); 1450 } 1451 } else if(this._isNsfPlayerMode) { 1452 this.MinimumSize = this._nonNsfMinimumSize; 1453 this.Size = this._nonNsfSize.Value; 1454 this._nonNsfSize = null; 1455 this._isNsfPlayerMode = false; 1456 this.ctrlNsfPlayer.Visible = false; 1457 } 1458 } 1459 } 1460 panelRenderer_MouseLeave(object sender, EventArgs e)1461 private void panelRenderer_MouseLeave(object sender, EventArgs e) 1462 { 1463 CursorManager.OnMouseLeave(); 1464 } 1465 ctrlRecentGames_OnRecentGameLoaded(Controls.RecentGameInfo gameInfo)1466 private void ctrlRecentGames_OnRecentGameLoaded(Controls.RecentGameInfo gameInfo) 1467 { 1468 _currentRomPath = gameInfo.RomPath; 1469 } 1470 ctrlNsfPlayer_MouseMove(object sender, MouseEventArgs e)1471 private void ctrlNsfPlayer_MouseMove(object sender, MouseEventArgs e) 1472 { 1473 if(this.HideMenuStrip && !this.menuStrip.ContainsFocus) { 1474 Point nsfPlayerPosition = this.ctrlNsfPlayer.PointToClient(((Control)sender).PointToScreen(e.Location)); 1475 this.menuStrip.Visible = nsfPlayerPosition.Y < 30; 1476 } 1477 } 1478 mnu_DropDownOpened(object sender, EventArgs e)1479 private void mnu_DropDownOpened(object sender, EventArgs e) 1480 { 1481 _inMenu++; 1482 } 1483 mnu_DropDownClosed(object sender, EventArgs e)1484 private void mnu_DropDownClosed(object sender, EventArgs e) 1485 { 1486 Task.Run(() => { 1487 Thread.Sleep(100); 1488 this.BeginInvoke((Action)(() => { 1489 _inMenu--; 1490 })); 1491 }); 1492 } 1493 } 1494 } 1495