mirror of
https://github.com/libretro/MesenCE.git
synced 2026-11-11 11:11:25 -10:00
Opening the game menu would display the "resume" option, making it impossible to pause (and keep the emulator paused after the menu is closed) by using the menu
1341 lines
50 KiB
C#
1341 lines
50 KiB
C#
using Avalonia.Controls;
|
|
using Avalonia.Threading;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using Mesen.Config;
|
|
using Mesen.Config.Shortcuts;
|
|
using Mesen.Controls;
|
|
using Mesen.Debugger.Utilities;
|
|
using Mesen.Debugger.ViewModels;
|
|
using Mesen.Debugger.Windows;
|
|
using Mesen.Interop;
|
|
using Mesen.Localization;
|
|
using Mesen.Utilities;
|
|
using Mesen.Windows;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Mesen.ViewModels
|
|
{
|
|
public partial class MainMenuViewModel : ViewModelBase
|
|
{
|
|
public MainWindowViewModel MainWindow { get; set; }
|
|
|
|
[ObservableProperty] public partial List<object> FileMenuItems { get; set; } = new();
|
|
[ObservableProperty] public partial List<object> GameMenuItems { get; set; } = new();
|
|
[ObservableProperty] public partial List<object> OptionsMenuItems { get; set; } = new();
|
|
[ObservableProperty] public partial List<object> ToolsMenuItems { get; set; } = new();
|
|
[ObservableProperty] public partial List<object> DebugMenuItems { get; set; } = new();
|
|
[ObservableProperty] public partial List<object> HelpMenuItems { get; set; } = new();
|
|
|
|
private RomInfo RomInfo => MainWindow.RomInfo;
|
|
private bool IsGameRunning => RomInfo.Format != RomFormat.Unknown;
|
|
private bool IsFdsGame => RomInfo.Format == RomFormat.Fds;
|
|
private bool IsVsSystemGame => RomInfo.Format == RomFormat.VsSystem || RomInfo.Format == RomFormat.VsDualSystem;
|
|
private bool IsVsDualSystemGame => RomInfo.Format == RomFormat.VsDualSystem;
|
|
private List<RecentItem> RecentItems => ConfigManager.Config.RecentFiles.Items;
|
|
|
|
public bool AutoPaused { get; set; } = false;
|
|
|
|
private ConfigWindow? _cfgWindow = null;
|
|
private MainMenuAction _selectControllerAction = new();
|
|
|
|
[Obsolete("For designer only")]
|
|
public MainMenuViewModel() : this(new MainWindowViewModel()) { }
|
|
|
|
public MainMenuViewModel(MainWindowViewModel windowModel)
|
|
{
|
|
MainWindow = windowModel;
|
|
}
|
|
|
|
private void OpenConfig(MainWindow wnd, ConfigWindowTab tab)
|
|
{
|
|
if(_cfgWindow == null) {
|
|
_cfgWindow = new ConfigWindow(tab);
|
|
_cfgWindow.Closed += CfgWindow_Closed;
|
|
_cfgWindow.ShowCentered((Control)wnd);
|
|
} else {
|
|
(_cfgWindow.DataContext as ConfigViewModel)!.SelectTab(tab);
|
|
_cfgWindow.BringToFront();
|
|
}
|
|
}
|
|
|
|
private void CfgWindow_Closed(object? sender, EventArgs e)
|
|
{
|
|
_cfgWindow = null;
|
|
if(ConfigManager.Config.Preferences.GameSelectionScreenMode == GameSelectionMode.Disabled && MainWindow.RecentGames.Visible) {
|
|
MainWindow.RecentGames.Visible = false;
|
|
} else if(ConfigManager.Config.Preferences.GameSelectionScreenMode != GameSelectionMode.Disabled && !IsGameRunning) {
|
|
MainWindow.RecentGames.Init(GameScreenMode.RecentGames);
|
|
}
|
|
}
|
|
|
|
public void Initialize(MainWindow wnd)
|
|
{
|
|
InitFileMenu(wnd);
|
|
InitGameMenu(wnd);
|
|
InitOptionsMenu(wnd);
|
|
InitToolMenu(wnd);
|
|
InitDebugMenu(wnd);
|
|
InitHelpMenu(wnd);
|
|
}
|
|
|
|
private void InitFileMenu(MainWindow wnd)
|
|
{
|
|
FileMenuItems = new List<object>() {
|
|
new MainMenuAction(EmulatorShortcut.OpenFile) { ActionType = ActionType.Open },
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.SaveState,
|
|
SubActions = new List<object> {
|
|
GetSaveStateMenuItem(1, true),
|
|
GetSaveStateMenuItem(2, true),
|
|
GetSaveStateMenuItem(3, true),
|
|
GetSaveStateMenuItem(4, true),
|
|
GetSaveStateMenuItem(5, true),
|
|
GetSaveStateMenuItem(6, true),
|
|
GetSaveStateMenuItem(7, true),
|
|
GetSaveStateMenuItem(8, true),
|
|
GetSaveStateMenuItem(9, true),
|
|
GetSaveStateMenuItem(10, true),
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.SaveStateDialog) { ActionType = ActionType.SaveStateDialog },
|
|
new MainMenuAction(EmulatorShortcut.SaveStateToFile) { ActionType = ActionType.SaveStateToFile },
|
|
}
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.LoadState,
|
|
SubActions = new List<object> {
|
|
GetSaveStateMenuItem(1, false),
|
|
GetSaveStateMenuItem(2, false),
|
|
GetSaveStateMenuItem(3, false),
|
|
GetSaveStateMenuItem(4, false),
|
|
GetSaveStateMenuItem(5, false),
|
|
GetSaveStateMenuItem(6, false),
|
|
GetSaveStateMenuItem(7, false),
|
|
GetSaveStateMenuItem(8, false),
|
|
GetSaveStateMenuItem(9, false),
|
|
GetSaveStateMenuItem(10, false),
|
|
new ContextMenuSeparator(),
|
|
GetSaveStateMenuItem(11, false),
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.LoadStateDialog) { ActionType = ActionType.LoadStateDialog },
|
|
new MainMenuAction(EmulatorShortcut.LoadStateFromFile) { ActionType = ActionType.LoadStateFromFile },
|
|
}
|
|
},
|
|
|
|
new MainMenuAction(EmulatorShortcut.LoadLastSession) {
|
|
ActionType = ActionType.LoadLastSession,
|
|
IsEnabled = () => File.Exists(Path.Combine(ConfigManager.RecentGamesFolder, MainWindow.RomInfo.GetRomName() + ".rgd"))
|
|
},
|
|
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.RecentFiles,
|
|
IsEnabled = () => ConfigManager.Config.RecentFiles.Items.Count > 0,
|
|
SubActions = new List<object>() {
|
|
GetRecentMenuItem(0),
|
|
GetRecentMenuItem(1),
|
|
GetRecentMenuItem(2),
|
|
GetRecentMenuItem(3),
|
|
GetRecentMenuItem(4),
|
|
GetRecentMenuItem(5),
|
|
GetRecentMenuItem(6),
|
|
GetRecentMenuItem(7),
|
|
GetRecentMenuItem(8),
|
|
GetRecentMenuItem(9)
|
|
}
|
|
},
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.Exit) { ActionType = ActionType.Exit },
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetRecentMenuItem(int index)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
DynamicText = () => index < RecentItems.Count ? RecentItems[index].DisplayText : "",
|
|
CustomShortcutText = () => index < RecentItems.Count ? RecentItems[index].ShortenedFolder : "",
|
|
IsVisible = () => index < RecentItems.Count,
|
|
OnClick = () => {
|
|
if(index < RecentItems.Count) {
|
|
LoadRomHelper.LoadRom(RecentItems[index].RomFile, RecentItems[index].PatchFile);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetSaveStateMenuItem(int slot, bool forSave)
|
|
{
|
|
EmulatorShortcut shortcut;
|
|
if(forSave) {
|
|
shortcut = (EmulatorShortcut)((int)EmulatorShortcut.SaveStateSlot1 + slot - 1);
|
|
} else {
|
|
shortcut = (EmulatorShortcut)((int)EmulatorShortcut.LoadStateSlot1 + slot - 1);
|
|
}
|
|
|
|
bool isAutoSaveSlot = slot == 11;
|
|
|
|
return new MainMenuAction(shortcut) {
|
|
ActionType = ActionType.Custom,
|
|
DynamicText = () => {
|
|
string statePath = Path.Combine(ConfigManager.SaveStateFolder, EmuApi.GetRomInfo().GetRomName() + "_" + slot + "." + FileDialogHelper.MesenSaveStateExt);
|
|
string slotName = isAutoSaveSlot ? "Auto" : slot.ToString();
|
|
|
|
string header;
|
|
if(!File.Exists(statePath)) {
|
|
header = slotName + ". " + ResourceHelper.GetMessage("EmptyState");
|
|
} else {
|
|
DateTime dateTime = new FileInfo(statePath).LastWriteTime;
|
|
header = slotName + ". " + dateTime.ToShortDateString() + " " + dateTime.ToShortTimeString();
|
|
}
|
|
return header;
|
|
},
|
|
OnClick = () => {
|
|
if(forSave) {
|
|
EmuApi.SaveState((uint)slot);
|
|
} else {
|
|
EmuApi.LoadState((uint)slot);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private void InitGameMenu(MainWindow wnd)
|
|
{
|
|
GameMenuItems = new List<object>() {
|
|
new MainMenuAction(EmulatorShortcut.Pause) { ActionType = ActionType.Pause, IsVisible = () => !EmuApi.IsPaused() && !ConfigManager.Config.Preferences.PauseWhenInMenusAndConfig },
|
|
new MainMenuAction(EmulatorShortcut.Pause) { ActionType = ActionType.Resume, IsVisible = () => EmuApi.IsPaused() && !ConfigManager.Config.Preferences.PauseWhenInMenusAndConfig },
|
|
new MainMenuAction(EmulatorShortcut.Pause) {
|
|
ActionType = ActionType.Resume,
|
|
IsVisible = () => ConfigManager.Config.Preferences.PauseWhenInMenusAndConfig && !AutoPaused,
|
|
OnClick = () => AutoPaused = true
|
|
},
|
|
new MainMenuAction(EmulatorShortcut.Pause) {
|
|
ActionType = ActionType.Pause,
|
|
IsVisible = () => ConfigManager.Config.Preferences.PauseWhenInMenusAndConfig && AutoPaused,
|
|
OnClick = () => AutoPaused = false
|
|
},
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.Reset) { ActionType = ActionType.Reset },
|
|
new MainMenuAction(EmulatorShortcut.PowerCycle) { ActionType = ActionType.PowerCycle },
|
|
new MainMenuAction(EmulatorShortcut.ReloadRom) { ActionType = ActionType.ReloadRom },
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.PowerOff) { ActionType = ActionType.PowerOff },
|
|
|
|
new ContextMenuSeparator() { IsVisible = () => IsGameRunning && RomInfo.ConsoleType != ConsoleType.Gameboy && RomInfo.Format != RomFormat.GameGear && RomInfo.ConsoleType != ConsoleType.Gba },
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.GameConfig,
|
|
IsVisible = () => IsGameRunning && RomInfo.ConsoleType != ConsoleType.Gameboy && RomInfo.Format != RomFormat.GameGear && RomInfo.ConsoleType != ConsoleType.Gba,
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => {
|
|
new GameConfigWindow().ShowCenteredDialog((Control)wnd);
|
|
}
|
|
},
|
|
|
|
new ContextMenuSeparator() { IsVisible = () => IsFdsGame },
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.SelectDisk,
|
|
IsVisible = () => IsFdsGame,
|
|
SubActions = new List<object>() {
|
|
GetFdsInsertDiskItem(0),
|
|
GetFdsInsertDiskItem(1),
|
|
GetFdsInsertDiskItem(2),
|
|
GetFdsInsertDiskItem(3),
|
|
GetFdsInsertDiskItem(4),
|
|
GetFdsInsertDiskItem(5),
|
|
GetFdsInsertDiskItem(6),
|
|
GetFdsInsertDiskItem(7),
|
|
}
|
|
},
|
|
|
|
new MainMenuAction(EmulatorShortcut.FdsEjectDisk) {
|
|
ActionType = ActionType.EjectDisk,
|
|
IsVisible = () => IsFdsGame,
|
|
},
|
|
|
|
new ContextMenuSeparator() { IsVisible = () => IsVsSystemGame },
|
|
|
|
new MainMenuAction(EmulatorShortcut.VsInsertCoin1) { ActionType = ActionType.InsertCoin1, IsVisible = () => IsVsSystemGame },
|
|
new MainMenuAction(EmulatorShortcut.VsInsertCoin2) { ActionType = ActionType.InsertCoin2, IsVisible = () => IsVsSystemGame },
|
|
new MainMenuAction(EmulatorShortcut.VsInsertCoin3) { ActionType = ActionType.InsertCoin3, IsVisible = () => IsVsDualSystemGame },
|
|
new MainMenuAction(EmulatorShortcut.VsInsertCoin4) { ActionType = ActionType.InsertCoin4, IsVisible = () => IsVsDualSystemGame },
|
|
|
|
new ContextMenuSeparator() { IsVisible = () => EmuApi.IsShortcutAllowed(EmulatorShortcut.InputBarcode) || EmuApi.IsShortcutAllowed(EmulatorShortcut.RecordTape) || EmuApi.IsShortcutAllowed(EmulatorShortcut.StopRecordTape) },
|
|
|
|
new MainMenuAction(EmulatorShortcut.InputBarcode) {
|
|
ActionType = ActionType.InputBarcode,
|
|
IsVisible = () => EmuApi.IsShortcutAllowed(EmulatorShortcut.InputBarcode)
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.TapeRecorder,
|
|
IsVisible = () => EmuApi.IsShortcutAllowed(EmulatorShortcut.RecordTape) || EmuApi.IsShortcutAllowed(EmulatorShortcut.StopRecordTape),
|
|
SubActions = new() {
|
|
new MainMenuAction(EmulatorShortcut.LoadTape) {
|
|
ActionType = ActionType.Play,
|
|
},
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.RecordTape) {
|
|
ActionType = ActionType.Record,
|
|
},
|
|
new MainMenuAction(EmulatorShortcut.StopRecordTape) {
|
|
ActionType = ActionType.Stop,
|
|
},
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetFdsInsertDiskItem(int diskSide)
|
|
{
|
|
return new MainMenuAction(EmulatorShortcut.FdsInsertDiskNumber) {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = "Disk " + ((diskSide / 2) + 1) + " Side " + ((diskSide % 2 == 0) ? "A" : "B"),
|
|
ShortcutParam = (uint)diskSide,
|
|
IsVisible = () => EmuApi.IsShortcutAllowed(EmulatorShortcut.FdsInsertDiskNumber, (uint)diskSide)
|
|
};
|
|
}
|
|
|
|
private void InitOptionsMenu(MainWindow wnd)
|
|
{
|
|
OptionsMenuItems = new List<object>() {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Speed,
|
|
SubActions = new List<object> {
|
|
GetSpeedMenuItem(ActionType.NormalSpeed, 100),
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.IncreaseSpeed) {
|
|
ActionType = ActionType.IncreaseSpeed
|
|
},
|
|
new MainMenuAction(EmulatorShortcut.DecreaseSpeed) {
|
|
ActionType = ActionType.DecreaseSpeed
|
|
},
|
|
GetSpeedMenuItem(ActionType.MaximumSpeed, 0, EmulatorShortcut.MaxSpeed),
|
|
new ContextMenuSeparator(),
|
|
GetSpeedMenuItem(ActionType.TripleSpeed, 300),
|
|
GetSpeedMenuItem(ActionType.DoubleSpeed, 200),
|
|
GetSpeedMenuItem(ActionType.HalfSpeed, 50),
|
|
GetSpeedMenuItem(ActionType.QuarterSpeed, 25),
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.ToggleFps) {
|
|
ActionType = ActionType.ShowFps,
|
|
IsSelected = () => ConfigManager.Config.Preferences.ShowFps
|
|
}
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.VideoScale,
|
|
SubActions = new List<object>() {
|
|
GetScaleMenuItem(1, EmulatorShortcut.SetScale1x),
|
|
GetScaleMenuItem(2, EmulatorShortcut.SetScale2x),
|
|
GetScaleMenuItem(3, EmulatorShortcut.SetScale3x),
|
|
GetScaleMenuItem(4, EmulatorShortcut.SetScale4x),
|
|
GetScaleMenuItem(5, EmulatorShortcut.SetScale5x),
|
|
GetScaleMenuItem(6, EmulatorShortcut.SetScale6x),
|
|
GetScaleMenuItem(7, EmulatorShortcut.SetScale7x),
|
|
GetScaleMenuItem(8, EmulatorShortcut.SetScale8x),
|
|
GetScaleMenuItem(9, EmulatorShortcut.SetScale9x),
|
|
GetScaleMenuItem(10, EmulatorShortcut.SetScale10x),
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction(EmulatorShortcut.ToggleFullscreen) {
|
|
ActionType = ActionType.Fullscreen
|
|
},
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.VideoFilter,
|
|
SubActions = new List<object>() {
|
|
GetVideoFilterMenuItem(VideoFilterType.None),
|
|
new ContextMenuSeparator(),
|
|
GetVideoFilterMenuItem(VideoFilterType.NtscBlargg),
|
|
GetVideoFilterMenuItem(VideoFilterType.NtscBisqwit),
|
|
new ContextMenuSeparator(),
|
|
GetVideoFilterMenuItem(VideoFilterType.LcdGrid),
|
|
new ContextMenuSeparator(),
|
|
GetVideoFilterMenuItem(VideoFilterType.xBRZ2x),
|
|
GetVideoFilterMenuItem(VideoFilterType.xBRZ3x),
|
|
GetVideoFilterMenuItem(VideoFilterType.xBRZ4x),
|
|
GetVideoFilterMenuItem(VideoFilterType.xBRZ5x),
|
|
GetVideoFilterMenuItem(VideoFilterType.xBRZ6x),
|
|
new ContextMenuSeparator(),
|
|
GetVideoFilterMenuItem(VideoFilterType.HQ2x),
|
|
GetVideoFilterMenuItem(VideoFilterType.HQ3x),
|
|
GetVideoFilterMenuItem(VideoFilterType.HQ4x),
|
|
new ContextMenuSeparator(),
|
|
GetVideoFilterMenuItem(VideoFilterType.Scale2x),
|
|
GetVideoFilterMenuItem(VideoFilterType.Scale3x),
|
|
GetVideoFilterMenuItem(VideoFilterType.Scale4x),
|
|
new ContextMenuSeparator(),
|
|
GetVideoFilterMenuItem(VideoFilterType._2xSai),
|
|
GetVideoFilterMenuItem(VideoFilterType.Super2xSai),
|
|
GetVideoFilterMenuItem(VideoFilterType.SuperEagle),
|
|
new ContextMenuSeparator(),
|
|
GetVideoFilterMenuItem(VideoFilterType.Prescale2x),
|
|
GetVideoFilterMenuItem(VideoFilterType.Prescale3x),
|
|
GetVideoFilterMenuItem(VideoFilterType.Prescale4x),
|
|
GetVideoFilterMenuItem(VideoFilterType.Prescale6x),
|
|
GetVideoFilterMenuItem(VideoFilterType.Prescale8x),
|
|
GetVideoFilterMenuItem(VideoFilterType.Prescale10x),
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.ToggleBilinearInterpolation,
|
|
IsSelected = () => ConfigManager.Config.Video.UseBilinearInterpolation,
|
|
OnClick = () => {
|
|
ConfigManager.Config.Video.UseBilinearInterpolation = !ConfigManager.Config.Video.UseBilinearInterpolation;
|
|
ConfigManager.Config.Video.ApplyConfig();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.AspectRatio,
|
|
SubActions = new List<object>() {
|
|
GetAspectRatioMenuItem(VideoAspectRatio.NoStretching),
|
|
new ContextMenuSeparator(),
|
|
GetAspectRatioMenuItem(VideoAspectRatio.Auto),
|
|
new ContextMenuSeparator(),
|
|
GetAspectRatioMenuItem(VideoAspectRatio.NTSC),
|
|
GetAspectRatioMenuItem(VideoAspectRatio.PAL),
|
|
GetAspectRatioMenuItem(VideoAspectRatio.Standard),
|
|
GetAspectRatioMenuItem(VideoAspectRatio.Widescreen),
|
|
new ContextMenuSeparator(),
|
|
GetAspectRatioMenuItem(VideoAspectRatio.Custom),
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Region,
|
|
IsEnabled = () => IsGameRunning,
|
|
IsVisible = () => (
|
|
!IsGameRunning ||
|
|
MainWindow.RomInfo.ConsoleType != ConsoleType.Gameboy && MainWindow.RomInfo.ConsoleType != ConsoleType.Gba
|
|
),
|
|
SubActions = new List<object>() {
|
|
GetRegionMenuItem(ConsoleRegion.Auto),
|
|
GetPcEngineModelMenuItem(PceConsoleType.Auto),
|
|
GetWsModelMenuItem(WsModel.Auto),
|
|
new ContextMenuSeparator(),
|
|
GetRegionMenuItem(ConsoleRegion.Ntsc),
|
|
GetRegionMenuItem(ConsoleRegion.NtscJapan),
|
|
GetRegionMenuItem(ConsoleRegion.Pal),
|
|
GetRegionMenuItem(ConsoleRegion.Dendy),
|
|
GetPcEngineModelMenuItem(PceConsoleType.PcEngine),
|
|
GetPcEngineModelMenuItem(PceConsoleType.SuperGrafx),
|
|
GetPcEngineModelMenuItem(PceConsoleType.TurboGrafx),
|
|
GetWsModelMenuItem(WsModel.Monochrome),
|
|
GetWsModelMenuItem(WsModel.Color),
|
|
GetWsModelMenuItem(WsModel.SwanCrystal),
|
|
GetWsModelMenuItem(WsModel.PocketChallenge),
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Region,
|
|
DynamicText = () => ResourceHelper.GetEnumText(ActionType.Region) + (MainWindow.RomInfo.ConsoleType != ConsoleType.Gameboy ? " (GB)" : ""),
|
|
IsVisible = () => IsGameRunning && MainWindow.RomInfo.CpuTypes.Contains(CpuType.Gameboy),
|
|
SubActions = new List<object>() {
|
|
GetGameboyModelMenuItem(GameboyModel.AutoFavorBest),
|
|
GetGameboyModelMenuItem(GameboyModel.AutoFavorGbc),
|
|
GetGameboyModelMenuItem(GameboyModel.AutoFavorSgb),
|
|
GetGameboyModelMenuItem(GameboyModel.AutoFavorGb),
|
|
new ContextMenuSeparator(),
|
|
GetGameboyModelMenuItem(GameboyModel.Gameboy),
|
|
GetGameboyModelMenuItem(GameboyModel.GameboyColor),
|
|
GetGameboyModelMenuItem(GameboyModel.SuperGameboy),
|
|
}
|
|
},
|
|
|
|
new ContextMenuSeparator(),
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Audio,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Audio)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Emulation,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Emulation)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Input,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Input)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Video,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Video)
|
|
},
|
|
|
|
new ContextMenuSeparator(),
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Nes,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Nes)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Snes,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Snes)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Gameboy,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Gameboy)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Gba,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Gba)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.PcEngine,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.PcEngine)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Sms,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Sms)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Ws,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Ws)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.OtherConsoles,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.OtherConsoles)
|
|
},
|
|
new ContextMenuSeparator(),
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Preferences,
|
|
OnClick = () => OpenConfig(wnd, ConfigWindowTab.Preferences)
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetAspectRatioMenuItem(VideoAspectRatio aspectRatio)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = ResourceHelper.GetEnumText(aspectRatio),
|
|
IsSelected = () => {
|
|
ConsoleOverrideConfig? overrides = ConsoleOverrideConfig.GetActiveOverride();
|
|
if(overrides?.OverrideAspectRatio == true) {
|
|
return aspectRatio == overrides.AspectRatio;
|
|
}
|
|
return aspectRatio == ConfigManager.Config.Video.AspectRatio;
|
|
},
|
|
OnClick = () => {
|
|
ConsoleOverrideConfig? overrides = ConsoleOverrideConfig.GetActiveOverride();
|
|
if(overrides?.OverrideAspectRatio == true) {
|
|
overrides.AspectRatio = aspectRatio;
|
|
} else {
|
|
ConfigManager.Config.Video.AspectRatio = aspectRatio;
|
|
}
|
|
ConfigManager.Config.Video.ApplyConfig();
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetRegionMenuItem(ConsoleRegion region)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
DynamicText = () => {
|
|
if(region == ConsoleRegion.Pal && MainWindow.RomInfo.Format == RomFormat.GameGear) {
|
|
return "PAL (60 FPS)"; //GG is 60fps even when region is PAL
|
|
}
|
|
return ResourceHelper.GetEnumText(region);
|
|
},
|
|
IsVisible = () => {
|
|
if(MainWindow.RomInfo.ConsoleType == ConsoleType.PcEngine || MainWindow.RomInfo.ConsoleType == ConsoleType.Gameboy || MainWindow.RomInfo.ConsoleType == ConsoleType.Ws) {
|
|
return false;
|
|
}
|
|
|
|
return region switch {
|
|
ConsoleRegion.Ntsc => true,
|
|
ConsoleRegion.NtscJapan => MainWindow.RomInfo.Format == RomFormat.GameGear,
|
|
ConsoleRegion.Pal => true,
|
|
ConsoleRegion.Dendy => MainWindow.RomInfo.ConsoleType == ConsoleType.Nes,
|
|
ConsoleRegion.Auto or _ => true
|
|
};
|
|
},
|
|
IsSelected = () => MainWindow.RomInfo.ConsoleType switch {
|
|
ConsoleType.Snes => ConfigManager.Config.Snes.Region == region,
|
|
ConsoleType.Nes => ConfigManager.Config.Nes.Region == region,
|
|
ConsoleType.Sms => (
|
|
MainWindow.RomInfo.Format switch {
|
|
RomFormat.ColecoVision => ConfigManager.Config.Cv.Region,
|
|
RomFormat.GameGear => ConfigManager.Config.Sms.GameGearRegion,
|
|
_ => ConfigManager.Config.Sms.Region
|
|
} == region
|
|
),
|
|
_ => region == ConsoleRegion.Auto
|
|
},
|
|
OnClick = () => {
|
|
switch(MainWindow.RomInfo.ConsoleType) {
|
|
case ConsoleType.Snes:
|
|
ConfigManager.Config.Snes.Region = region;
|
|
ConfigManager.Config.Snes.ApplyConfig();
|
|
break;
|
|
|
|
case ConsoleType.Nes:
|
|
ConfigManager.Config.Nes.Region = region;
|
|
ConfigManager.Config.Nes.ApplyConfig();
|
|
break;
|
|
|
|
case ConsoleType.Sms:
|
|
switch(MainWindow.RomInfo.Format) {
|
|
default: case RomFormat.Sms: ConfigManager.Config.Sms.Region = region; break;
|
|
case RomFormat.GameGear: ConfigManager.Config.Sms.GameGearRegion = region; break;
|
|
case RomFormat.ColecoVision: ConfigManager.Config.Cv.Region = region; break;
|
|
}
|
|
ConfigManager.Config.Sms.ApplyConfig();
|
|
ConfigManager.Config.Cv.ApplyConfig();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetPcEngineModelMenuItem(PceConsoleType model)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = ResourceHelper.GetEnumText(model),
|
|
IsVisible = () => MainWindow.RomInfo.ConsoleType == ConsoleType.PcEngine,
|
|
IsSelected = () => ConfigManager.Config.PcEngine.ConsoleType == model,
|
|
OnClick = () => {
|
|
ConfigManager.Config.PcEngine.ConsoleType = model;
|
|
ConfigManager.Config.PcEngine.ApplyConfig();
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetWsModelMenuItem(WsModel model)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = ResourceHelper.GetEnumText(model),
|
|
IsVisible = () => MainWindow.RomInfo.ConsoleType == ConsoleType.Ws,
|
|
IsSelected = () => ConfigManager.Config.Ws.Model == model,
|
|
OnClick = () => {
|
|
ConfigManager.Config.Ws.Model = model;
|
|
ConfigManager.Config.Ws.ApplyConfig();
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetGameboyModelMenuItem(GameboyModel model)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = ResourceHelper.GetEnumText(model),
|
|
IsSelected = () => ConfigManager.Config.Gameboy.Model == model,
|
|
OnClick = () => {
|
|
ConfigManager.Config.Gameboy.Model = model;
|
|
ConfigManager.Config.Gameboy.ApplyConfig();
|
|
}
|
|
};
|
|
}
|
|
|
|
private bool AllowFilterType(VideoFilterType filter)
|
|
{
|
|
switch(filter) {
|
|
case VideoFilterType.NtscBisqwit: return MainWindow.RomInfo.ConsoleType == ConsoleType.Nes;
|
|
default: return true;
|
|
}
|
|
}
|
|
|
|
private MainMenuAction GetVideoFilterMenuItem(VideoFilterType filter)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = ResourceHelper.GetEnumText(filter),
|
|
IsEnabled = () => AllowFilterType(filter),
|
|
IsSelected = () => {
|
|
ConsoleOverrideConfig? overrides = ConsoleOverrideConfig.GetActiveOverride();
|
|
if(overrides?.OverrideVideoFilter == true) {
|
|
return filter == overrides.VideoFilter;
|
|
}
|
|
return filter == ConfigManager.Config.Video.VideoFilter;
|
|
},
|
|
OnClick = () => {
|
|
ConsoleOverrideConfig? overrides = ConsoleOverrideConfig.GetActiveOverride();
|
|
if(overrides?.OverrideVideoFilter == true) {
|
|
overrides.VideoFilter = filter;
|
|
} else {
|
|
ConfigManager.Config.Video.VideoFilter = filter;
|
|
}
|
|
ConfigManager.Config.Video.ApplyConfig();
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetScaleMenuItem(int scale, EmulatorShortcut shortcut)
|
|
{
|
|
return new MainMenuAction(shortcut) {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = scale + "x",
|
|
IsSelected = () => (int)((double)MainWindow.RendererSize.Height / EmuApi.GetBaseScreenSize().Height) == scale
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetSpeedMenuItem(ActionType action, int speed, EmulatorShortcut? shortcut = null)
|
|
{
|
|
MainMenuAction item = new MainMenuAction(shortcut) {
|
|
ActionType = action,
|
|
IsSelected = () => ConfigManager.Config.Emulation.EmulationSpeed == speed,
|
|
};
|
|
|
|
if(shortcut == null) {
|
|
item.OnClick = () => {
|
|
ConfigManager.Config.Emulation.EmulationSpeed = (uint)speed;
|
|
ConfigManager.Config.Emulation.ApplyConfig();
|
|
};
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
private MainMenuAction GetMoviesMenu(MainWindow wnd)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.Movies,
|
|
SubActions = new List<object> {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Play,
|
|
IsEnabled = () => IsGameRunning && !RecordApi.MovieRecording() && !RecordApi.MoviePlaying(),
|
|
OnClick = async () => {
|
|
string? filename = await FileDialogHelper.OpenFile(ConfigManager.MovieFolder, wnd, FileDialogHelper.MovieFileExt);
|
|
if(filename != null) {
|
|
RecordApi.MoviePlay(filename);
|
|
}
|
|
}
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Record,
|
|
IsEnabled = () => IsGameRunning && !RecordApi.MovieRecording() && !RecordApi.MoviePlaying(),
|
|
OnClick = () => {
|
|
new MovieRecordWindow() {
|
|
DataContext = new MovieRecordConfigViewModel()
|
|
}.ShowCenteredDialog((Control)wnd);
|
|
}
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Stop,
|
|
IsEnabled = () => IsGameRunning && (RecordApi.MovieRecording() || RecordApi.MoviePlaying()),
|
|
OnClick = () => {
|
|
RecordApi.MovieStop();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private void InitToolMenu(MainWindow wnd)
|
|
{
|
|
ToolsMenuItems = new List<object>() {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Cheats,
|
|
IsEnabled = () => IsGameRunning && MainWindow.RomInfo.ConsoleType.SupportsCheats(),
|
|
OnClick = () => {
|
|
ApplicationHelper.GetOrCreateUniqueWindow(wnd, () => new CheatListWindow());
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.HistoryViewer,
|
|
IsEnabled = () => IsGameRunning && HistoryApi.HistoryViewerEnabled(),
|
|
OnClick = () => {
|
|
ApplicationHelper.GetOrCreateUniqueWindow(null, () => new HistoryViewerWindow());
|
|
}
|
|
},
|
|
|
|
GetMoviesMenu(wnd),
|
|
GetNetPlayMenu(wnd),
|
|
|
|
new ContextMenuSeparator(),
|
|
|
|
GetSoundRecorderMenu(wnd),
|
|
GetVideoRecorderMenu(wnd),
|
|
|
|
new ContextMenuSeparator() {
|
|
IsVisible = () => MainWindow.RomInfo.ConsoleType == ConsoleType.Nes && MainWindow.RomInfo.Format != RomFormat.Nsf
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.HdPacks,
|
|
IsVisible = () => MainWindow.RomInfo.ConsoleType == ConsoleType.Nes && MainWindow.RomInfo.Format != RomFormat.Nsf,
|
|
SubActions = new List<object> {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.InstallHdPack,
|
|
OnClick = () => InstallHdPack(wnd)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.HdPackBuilder,
|
|
OnClick = () => {
|
|
ApplicationHelper.GetOrCreateUniqueWindow(wnd, () => new HdPackBuilderWindow());
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
new ContextMenuSeparator(),
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.LogWindow,
|
|
OnClick = () => {
|
|
ApplicationHelper.GetOrCreateUniqueWindow(wnd, () => new LogWindow());
|
|
}
|
|
},
|
|
|
|
new MainMenuAction(EmulatorShortcut.TakeScreenshot) {
|
|
ActionType = ActionType.TakeScreenshot,
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.SaveSpcFile,
|
|
IsVisible = () => MainWindow.RomInfo.CpuTypes.Contains(CpuType.Spc),
|
|
OnClick = () => {
|
|
ApplicationHelper.GetOrCreateUniqueWindow(wnd, () => new SaveSpcFileWindow());
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetVideoRecorderMenu(MainWindow wnd)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.VideoRecorder,
|
|
SubActions = new List<object> {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Record,
|
|
IsEnabled = () => IsGameRunning && !RecordApi.AviIsRecording(),
|
|
OnClick = () => {
|
|
new VideoRecordWindow() {
|
|
DataContext = new VideoRecordConfigViewModel()
|
|
}.ShowCenteredDialog((Control)wnd);
|
|
}
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Stop,
|
|
IsEnabled = () => IsGameRunning && RecordApi.AviIsRecording(),
|
|
OnClick = () => {
|
|
RecordApi.AviStop();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetSoundRecorderMenu(MainWindow wnd)
|
|
{
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.SoundRecorder,
|
|
SubActions = new List<object> {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Record,
|
|
IsEnabled = () => IsGameRunning && !RecordApi.WaveIsRecording(),
|
|
OnClick = async () => {
|
|
string? filename = await FileDialogHelper.SaveFile(ConfigManager.WaveFolder, EmuApi.GetRomInfo().GetRomName() + ".wav", wnd, FileDialogHelper.WaveExt);
|
|
if(filename != null) {
|
|
RecordApi.WaveRecord(filename);
|
|
}
|
|
}
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Stop,
|
|
IsEnabled = () => IsGameRunning && RecordApi.WaveIsRecording(),
|
|
OnClick = () => {
|
|
RecordApi.WaveStop();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
private MainMenuAction GetNetPlayMenu(MainWindow wnd)
|
|
{
|
|
_selectControllerAction = new MainMenuAction() {
|
|
ActionType = ActionType.SelectController,
|
|
IsEnabled = () => NetplayApi.IsConnected() || NetplayApi.IsServerRunning(),
|
|
SubActions = new()
|
|
};
|
|
|
|
return new MainMenuAction() {
|
|
ActionType = ActionType.NetPlay,
|
|
SubActions = new List<object> {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Connect,
|
|
IsEnabled = () => !NetplayApi.IsConnected() && !NetplayApi.IsServerRunning(),
|
|
OnClick = () => {
|
|
new NetplayConnectWindow() {
|
|
DataContext = ConfigManager.Config.Netplay.Clone()
|
|
}.ShowCenteredDialog((Control)wnd);
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.Disconnect,
|
|
IsEnabled = () => NetplayApi.IsConnected(),
|
|
OnClick = () => {
|
|
NetplayApi.Disconnect();
|
|
}
|
|
},
|
|
|
|
new ContextMenuSeparator(),
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.StartServer,
|
|
IsEnabled = () => !NetplayApi.IsConnected() && !NetplayApi.IsServerRunning(),
|
|
OnClick = () => {
|
|
new NetplayStartServerWindow() {
|
|
DataContext = ConfigManager.Config.Netplay.Clone()
|
|
}.ShowCenteredDialog((Control)wnd);
|
|
}
|
|
},
|
|
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.StopServer,
|
|
IsEnabled = () => NetplayApi.IsServerRunning(),
|
|
OnClick = () => {
|
|
NetplayApi.StopServer();
|
|
}
|
|
},
|
|
|
|
new ContextMenuSeparator(),
|
|
|
|
_selectControllerAction
|
|
}
|
|
};
|
|
}
|
|
|
|
private void InitDebugMenu(Window wnd)
|
|
{
|
|
Func<bool> isSuperGameBoy = () => MainWindow.RomInfo.ConsoleType == ConsoleType.Snes && MainWindow.RomInfo.Format == RomFormat.Gb;
|
|
Func<bool> isNesFormat = () => MainWindow.RomInfo.ConsoleType == ConsoleType.Nes && (MainWindow.RomInfo.Format == RomFormat.iNes || MainWindow.RomInfo.Format == RomFormat.VsSystem || MainWindow.RomInfo.Format == RomFormat.VsDualSystem);
|
|
|
|
DebugMenuItems = new List<object>() {
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenDebugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenDebugger),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(MainWindow.RomInfo.ConsoleType.GetMainCpuType())
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenSpcDebugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenSpcDebugger),
|
|
IsVisible = () => MainWindow.RomInfo.CpuTypes.Contains(CpuType.Spc),
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(CpuType.Spc)
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenCx4Debugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenCx4Debugger),
|
|
IsVisible = () => MainWindow.RomInfo.CpuTypes.Contains(CpuType.Cx4),
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(CpuType.Cx4)
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenNecDspDebugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenNecDspDebugger),
|
|
IsVisible = () => MainWindow.RomInfo.CpuTypes.Contains(CpuType.NecDsp),
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(CpuType.NecDsp)
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenGsuDebugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenGsuDebugger),
|
|
IsVisible = () => MainWindow.RomInfo.CpuTypes.Contains(CpuType.Gsu),
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(CpuType.Gsu)
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenSa1Debugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenSa1Debugger),
|
|
IsVisible = () => MainWindow.RomInfo.CpuTypes.Contains(CpuType.Sa1),
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(CpuType.Sa1)
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenSt018Debugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenSt018Debugger),
|
|
IsVisible = () => MainWindow.RomInfo.CpuTypes.Contains(CpuType.St018),
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(CpuType.St018)
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenGameboyDebugger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenGameboyDebugger),
|
|
IsVisible = () => MainWindow.RomInfo.ConsoleType == ConsoleType.Snes && MainWindow.RomInfo.CpuTypes.Contains(CpuType.Gameboy),
|
|
OnClick = () => DebuggerWindow.GetOrOpenWindow(CpuType.Gameboy)
|
|
},
|
|
new ContextMenuSeparator(),
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenEventViewer,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenEventViewer),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => EventViewerWindow.GetOrOpenWindow(MainWindow.RomInfo.ConsoleType.GetMainCpuType())
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenMemoryTools,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenMemoryTools),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new MemoryToolsWindow())
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenRegisterViewer,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenRegisterViewer),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new RegisterViewerWindow(new RegisterViewerWindowViewModel()))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenTraceLogger,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenTraceLogger),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.GetOrOpenDebugWindow(() => new TraceLoggerWindow(new TraceLoggerViewModel()))
|
|
},
|
|
new ContextMenuSeparator(),
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenTilemapViewer,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenTilemapViewer),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new TilemapViewerWindow(MainWindow.RomInfo.ConsoleType.GetMainCpuType()))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenTileViewer,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenTileViewer),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new TileViewerWindow(MainWindow.RomInfo.ConsoleType.GetMainCpuType()))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenSpriteViewer,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenSpriteViewer),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new SpriteViewerWindow(MainWindow.RomInfo.ConsoleType.GetMainCpuType()))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenPaletteViewer,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenPaletteViewer),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new PaletteViewerWindow(MainWindow.RomInfo.ConsoleType.GetMainCpuType()))
|
|
},
|
|
new ContextMenuSeparator(),
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenAssembler,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenAssembler),
|
|
IsEnabled = () => IsGameRunning && MainWindow.RomInfo.ConsoleType.GetMainCpuType().SupportsAssembler(),
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new AssemblerWindow(new AssemblerWindowViewModel(MainWindow.RomInfo.ConsoleType.GetMainCpuType())))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenDebugLog,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenDebugLog),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.GetOrOpenDebugWindow(() => new DebugLogWindow())
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenMemorySearch,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenMemorySearch),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.GetOrOpenDebugWindow(() => new MemorySearchWindow())
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenProfiler,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenProfiler),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.GetOrOpenDebugWindow(() => new ProfilerWindow())
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenScriptWindow,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenScriptWindow),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new ScriptWindow(new ScriptWindowViewModel(null)))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenWatchWindow,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenWatchWindow),
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.GetOrOpenDebugWindow(() => new WatchWindow(new WatchWindowViewModel()))
|
|
},
|
|
new ContextMenuSeparator() { IsVisible = isSuperGameBoy },
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenTilemapViewer,
|
|
HintText = () => "GB",
|
|
IsVisible = isSuperGameBoy,
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new TilemapViewerWindow(CpuType.Gameboy))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenTileViewer,
|
|
HintText = () => "GB",
|
|
IsVisible = isSuperGameBoy,
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new TileViewerWindow(CpuType.Gameboy))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenSpriteViewer,
|
|
HintText = () => "GB",
|
|
IsVisible = isSuperGameBoy,
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new SpriteViewerWindow(CpuType.Gameboy))
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenPaletteViewer,
|
|
HintText = () => "GB",
|
|
IsVisible = isSuperGameBoy,
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new PaletteViewerWindow(CpuType.Gameboy))
|
|
},
|
|
|
|
new ContextMenuSeparator() { IsVisible = isSuperGameBoy },
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenEventViewer,
|
|
HintText = () => "GB",
|
|
IsVisible = isSuperGameBoy,
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => EventViewerWindow.GetOrOpenWindow(CpuType.Gameboy)
|
|
},
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenAssembler,
|
|
HintText = () => "GB",
|
|
IsVisible = isSuperGameBoy,
|
|
IsEnabled = () => IsGameRunning,
|
|
OnClick = () => DebugWindowManager.OpenDebugWindow(() => new AssemblerWindow(new AssemblerWindowViewModel(CpuType.Gameboy)))
|
|
},
|
|
|
|
new ContextMenuSeparator() { IsVisible = isNesFormat },
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenNesHeaderEditor,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenNesHeaderEditor),
|
|
IsVisible = isNesFormat,
|
|
OnClick = () => new NesHeaderEditWindow().ShowCenteredDialog((Control)wnd)
|
|
},
|
|
|
|
new ContextMenuSeparator(),
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.OpenDebugSettings,
|
|
Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.OpenDebugSettings),
|
|
OnClick = () => DebuggerConfigWindow.Open(DebugConfigWindowTab.Debugger, wnd)
|
|
}
|
|
};
|
|
|
|
DebugShortcutManager.RegisterActions(wnd, DebugMenuItems);
|
|
}
|
|
|
|
private void InitHelpMenu(Window wnd)
|
|
{
|
|
HelpMenuItems = new List<object>() {
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.OnlineHelp,
|
|
IsVisible = () => false,
|
|
OnClick = () => ApplicationHelper.OpenBrowser("https://www.mesen.ca/documentation/")
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.CommandLineHelp,
|
|
OnClick = () => { new CommandLineHelpWindow().ShowCenteredDialog((Control)wnd); }
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.CheckForUpdates,
|
|
OnClick = () => CheckForUpdate(wnd, false)
|
|
},
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.ReportBug,
|
|
IsVisible = () => false,
|
|
OnClick = () => ApplicationHelper.OpenBrowser("https://www.mesen.ca/reportbug/")
|
|
},
|
|
new ContextMenuSeparator(),
|
|
new MainMenuAction() {
|
|
ActionType = ActionType.About,
|
|
OnClick = () => {
|
|
new AboutWindow().ShowCenteredDialog((Control)wnd);
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
public void CheckForUpdate(Window mainWindow, bool silent)
|
|
{
|
|
Task.Run(async () => {
|
|
UpdatePromptViewModel? updateInfo = await UpdatePromptViewModel.GetUpdateInformation(silent);
|
|
if(updateInfo == null) {
|
|
if(!silent) {
|
|
Dispatcher.UIThread.Post(() => {
|
|
MesenMsgBox.Show(null, "UpdateDownloadFailed", MessageBoxButtons.OK, MessageBoxIcon.Info);
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(updateInfo.LatestVersion > updateInfo.InstalledVersion) {
|
|
Dispatcher.UIThread.Post(async () => {
|
|
UpdatePromptWindow updatePrompt = new UpdatePromptWindow(updateInfo);
|
|
if(await updatePrompt.ShowCenteredDialog<bool>(mainWindow) == true) {
|
|
mainWindow.Close();
|
|
}
|
|
});
|
|
} else if(!silent) {
|
|
Dispatcher.UIThread.Post(() => {
|
|
MesenMsgBox.Show(null, "MesenUpToDate", MessageBoxButtons.OK, MessageBoxIcon.Info);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
private async void InstallHdPack(Window wnd)
|
|
{
|
|
string? filename = await FileDialogHelper.OpenFile(null, wnd, FileDialogHelper.ZipExt);
|
|
if(filename == null) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
using(FileStream? stream = FileHelper.OpenRead(filename)) {
|
|
if(stream == null) {
|
|
return;
|
|
}
|
|
|
|
ZipArchive zip = new ZipArchive(stream);
|
|
|
|
//Find the hires.txt file
|
|
ZipArchiveEntry? hiresEntry = null;
|
|
|
|
//Find the most top-level hires.txt file in the zip
|
|
int minDepth = int.MaxValue;
|
|
foreach(ZipArchiveEntry entry in zip.Entries) {
|
|
if(entry.Name == "hires.txt") {
|
|
string? folder = Path.GetDirectoryName(entry.FullName);
|
|
int depth = 0;
|
|
if(folder != null) {
|
|
do {
|
|
depth++;
|
|
} while((folder = Path.GetDirectoryName(folder)) != null);
|
|
}
|
|
if(depth < minDepth) {
|
|
minDepth = depth;
|
|
hiresEntry = entry;
|
|
if(depth == 0) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(hiresEntry == null) {
|
|
await MesenMsgBox.Show(wnd, "InstallHdPackInvalidPack", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
|
|
using Stream entryStream = hiresEntry.Open();
|
|
using StreamReader reader = new StreamReader(entryStream);
|
|
string hiresData = reader.ReadToEnd();
|
|
RomInfo romInfo = EmuApi.GetRomInfo();
|
|
|
|
//If there's a "supportedRom" tag, check if it matches the current ROM
|
|
Regex supportedRomRegex = new Regex("<supportedRom>([^\\n]*)");
|
|
Match match = supportedRomRegex.Match(hiresData);
|
|
if(match.Success) {
|
|
if(!match.Groups[1].Value.ToUpper().Contains(EmuApi.GetRomHash(HashType.Sha1).ToUpper())) {
|
|
await MesenMsgBox.Show(wnd, "InstallHdPackWrongRom", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
}
|
|
|
|
//Extract HD pack
|
|
try {
|
|
string targetFolder = Path.Combine(ConfigManager.HdPackFolder, romInfo.GetRomName());
|
|
if(Directory.Exists(targetFolder)) {
|
|
//Warn if the folder already exists
|
|
if(await MesenMsgBox.Show(wnd, "InstallHdPackConfirmOverwrite", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, targetFolder) != DialogResult.OK) {
|
|
return;
|
|
}
|
|
} else {
|
|
Directory.CreateDirectory(targetFolder);
|
|
}
|
|
|
|
string hiresFileFolder = hiresEntry.FullName.Substring(0, hiresEntry.FullName.Length - "hires.txt".Length);
|
|
foreach(ZipArchiveEntry entry in zip.Entries) {
|
|
//Extract only the files in the same subfolder as the hires.txt file (and only if they have a name & size > 0)
|
|
if(!string.IsNullOrWhiteSpace(entry.Name) && entry.Length > 0 && entry.FullName.StartsWith(hiresFileFolder)) {
|
|
string filePath = Path.Combine(targetFolder, entry.FullName.Substring(hiresFileFolder.Length));
|
|
string? fileFolder = Path.GetDirectoryName(filePath);
|
|
if(fileFolder != null) {
|
|
Directory.CreateDirectory(fileFolder);
|
|
}
|
|
entry.ExtractToFile(filePath, true);
|
|
}
|
|
}
|
|
} catch(Exception ex) {
|
|
await MesenMsgBox.Show(wnd, "InstallHdPackError", MessageBoxButtons.OK, MessageBoxIcon.Error, ex.ToString());
|
|
return;
|
|
}
|
|
|
|
//Turn on HD Pack support automatically after installation succeeds
|
|
if(!ConfigManager.Config.Nes.EnableHdPacks) {
|
|
ConfigManager.Config.Nes.EnableHdPacks = true;
|
|
ConfigManager.Config.Nes.ApplyConfig();
|
|
}
|
|
|
|
if(await MesenMsgBox.Show(wnd, "InstallHdPackConfirmReset", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK) {
|
|
//Power cycle game if the user agrees
|
|
LoadRomHelper.PowerCycle();
|
|
}
|
|
}
|
|
} catch {
|
|
//Invalid file (file missing, not a zip file, etc.)
|
|
await MesenMsgBox.Show(wnd, "InstallHdPackInvalidZipFile", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
|
|
public bool UpdateNetplayMenu()
|
|
{
|
|
if(!NetplayApi.IsServerRunning() && !NetplayApi.IsConnected()) {
|
|
return false;
|
|
}
|
|
|
|
List<object> controllerActions = new();
|
|
|
|
NetplayControllerInfo clientPort = NetplayApi.NetPlayGetControllerPort();
|
|
|
|
int playerIndex = 1;
|
|
NetplayControllerUsageInfo[] controllers = NetplayApi.NetPlayGetControllerList();
|
|
|
|
for(int i = 0; i < controllers.Length; i++) {
|
|
NetplayControllerUsageInfo controller = controllers[i];
|
|
if(controller.Type == ControllerType.None) {
|
|
//Skip this controller/port (when type is none, the "port" for hardware buttons, etc.)
|
|
continue;
|
|
}
|
|
|
|
MainMenuAction action = new();
|
|
action.ActionType = ActionType.Custom;
|
|
action.CustomText = ResourceHelper.GetMessage("Player") + " " + playerIndex + " (" + ResourceHelper.GetEnumText(controller.Type) + ")";
|
|
action.IsSelected = () => controller.Port.Port == clientPort.Port && controller.Port.SubPort == clientPort.SubPort;
|
|
action.IsEnabled = () => !controller.InUse;
|
|
action.OnClick = () => NetplayApi.NetPlaySelectController(controller.Port);
|
|
controllerActions.Add(action);
|
|
playerIndex++;
|
|
}
|
|
|
|
if(controllerActions.Count > 0) {
|
|
controllerActions.Add(new ContextMenuSeparator());
|
|
}
|
|
|
|
controllerActions.Add(new MainMenuAction() {
|
|
ActionType = ActionType.Custom,
|
|
CustomText = ResourceHelper.GetEnumText(ControllerType.None),
|
|
IsSelected = () => clientPort.Port == 0xFF,
|
|
OnClick = () => NetplayApi.NetPlaySelectController(new NetplayControllerInfo() { Port = 0xFF })
|
|
});
|
|
|
|
_selectControllerAction.SubActions = controllerActions;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|