mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
630 lines
11 KiB
C#
630 lines
11 KiB
C#
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Avalonia.Threading;
|
|
using Mesen.Config;
|
|
using Mesen.Config.Shortcuts;
|
|
using Mesen.Controls;
|
|
using Mesen.Interop;
|
|
using Mesen.Localization;
|
|
using Mesen.Utilities;
|
|
using Mesen.ViewModels;
|
|
using ReactiveUI;
|
|
using ReactiveUI.Fody.Helpers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reactive;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Mesen.Debugger.Utilities
|
|
{
|
|
public abstract class BaseMenuAction : ViewModelBase, IDisposable
|
|
{
|
|
public ActionType ActionType;
|
|
public string? CustomText { get; set; }
|
|
public Func<string>? DynamicText { get; set; }
|
|
public Func<string>? DynamicIcon { get; set; }
|
|
|
|
public virtual string Name
|
|
{
|
|
get
|
|
{
|
|
if(ActionType == ActionType.Custom) {
|
|
if(DynamicText != null) {
|
|
return DynamicText();
|
|
} else {
|
|
return CustomText ?? "";
|
|
}
|
|
}
|
|
|
|
string label = ResourceHelper.GetEnumText(ActionType);
|
|
if(HintText != null) {
|
|
string hint = HintText();
|
|
if(!string.IsNullOrWhiteSpace(hint)) {
|
|
label += " (" + hint + ")";
|
|
}
|
|
}
|
|
return label;
|
|
}
|
|
}
|
|
|
|
public Image? Icon
|
|
{
|
|
get
|
|
{
|
|
IconFileAttribute? attr = ActionType.GetAttribute<IconFileAttribute>();
|
|
if(!string.IsNullOrEmpty(attr?.Icon)) {
|
|
return ImageUtilities.FromAsset(attr.Icon);
|
|
} else if(DynamicIcon != null) {
|
|
return ImageUtilities.FromAsset("Assets/" + DynamicIcon() + ".png");
|
|
} else if(IsSelected?.Invoke() == true) {
|
|
return ImageUtilities.FromAsset("Assets/MenuItemChecked.png");
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
List<object>? _subActions;
|
|
public List<object>? SubActions
|
|
{
|
|
get => _subActions;
|
|
set
|
|
{
|
|
_subActions = value;
|
|
|
|
if(_subActions != null) {
|
|
Func<bool>? isEnabled = IsEnabled;
|
|
|
|
IsEnabled = () => {
|
|
if(isEnabled != null && !isEnabled()) {
|
|
return false;
|
|
}
|
|
|
|
foreach(object subAction in _subActions) {
|
|
if(subAction is BaseMenuAction act) {
|
|
if(act.IsEnabled == null || act.IsEnabled()) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
public Func<string>? HintText { get; set; }
|
|
public Func<bool>? IsEnabled { get; set; }
|
|
public Func<bool>? IsSelected { get; set; }
|
|
public Func<bool>? IsVisible { get; set; }
|
|
|
|
public bool AllowedWhenHidden { get; set; }
|
|
|
|
public abstract string ShortcutText { get; }
|
|
|
|
[Reactive] public string ActionName { get; set; } = "";
|
|
[Reactive] public Image? ActionIcon { get; set; }
|
|
[Reactive] public bool Enabled { get; set; }
|
|
[Reactive] public bool Visible { get; set; }
|
|
|
|
private ReactiveCommand<Unit, Unit>? _clickCommand;
|
|
public ReactiveCommand<Unit, Unit>? ClickCommand
|
|
{
|
|
get
|
|
{
|
|
Update();
|
|
return _clickCommand;
|
|
}
|
|
}
|
|
|
|
private Action _onClick = () => { };
|
|
public Action OnClick
|
|
{
|
|
get => _onClick;
|
|
set
|
|
{
|
|
_onClick = () => {
|
|
if((IsVisible == null || AllowedWhenHidden || IsVisible()) && (IsEnabled == null || IsEnabled())) {
|
|
if(ActionType == ActionType.Exit) {
|
|
//When using exit, the command is disposed while the command is running, which causes a crash
|
|
//Run the code in a posted action to prevent the crash
|
|
Dispatcher.UIThread.Post(() => { value(); });
|
|
} else {
|
|
value();
|
|
}
|
|
}
|
|
};
|
|
_clickCommand = ReactiveCommand.Create(_onClick, this.WhenAnyValue(x => x.Enabled));
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
ActionName = Name;
|
|
ActionIcon = Icon;
|
|
Enabled = IsEnabled?.Invoke() ?? true;
|
|
Visible = IsVisible?.Invoke() ?? true;
|
|
}
|
|
|
|
public virtual void Dispose()
|
|
{
|
|
_onClick = () => { };
|
|
_clickCommand?.Dispose();
|
|
_clickCommand = null;
|
|
IsSelected = null;
|
|
IsEnabled = null;
|
|
IsVisible = null;
|
|
if(_subActions != null) {
|
|
foreach(object subAction in _subActions) {
|
|
if(subAction is BaseMenuAction action) {
|
|
action.Dispose();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class MainMenuAction : BaseMenuAction
|
|
{
|
|
public EmulatorShortcut? Shortcut { get; set; }
|
|
public uint ShortcutParam { get; set; }
|
|
|
|
public Func<string>? CustomShortcutText { get; set; }
|
|
|
|
public MainMenuAction()
|
|
{
|
|
}
|
|
|
|
public MainMenuAction(EmulatorShortcut? shortcut)
|
|
{
|
|
if(shortcut.HasValue) {
|
|
Shortcut = shortcut.Value;
|
|
|
|
IsEnabled = () => EmuApi.IsShortcutAllowed(shortcut.Value, ShortcutParam);
|
|
|
|
OnClick = () => {
|
|
//Run outside the UI thread to avoid deadlocks, etc.
|
|
Task.Run(() => {
|
|
EmuApi.ExecuteShortcut(new ExecuteShortcutParams() { Shortcut = shortcut.Value, Param = ShortcutParam });
|
|
});
|
|
};
|
|
}
|
|
}
|
|
|
|
public override string ShortcutText
|
|
{
|
|
get
|
|
{
|
|
if(CustomShortcutText != null) {
|
|
return CustomShortcutText();
|
|
} else {
|
|
return Shortcut.HasValue ? Shortcut.Value.GetShortcutKeys()?.ToString() ?? "" : "";
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public class ContextMenuAction : BaseMenuAction
|
|
{
|
|
public Func<DbgShortKeys>? Shortcut { get; set; }
|
|
public override string ShortcutText => Shortcut?.Invoke().ToString() ?? "";
|
|
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
Shortcut = null;
|
|
}
|
|
}
|
|
|
|
public class ContextMenuSeparator : ContextMenuAction
|
|
{
|
|
public override string Name => "-";
|
|
}
|
|
|
|
public enum ActionType
|
|
{
|
|
Custom,
|
|
|
|
[IconFile("Copy")]
|
|
Copy,
|
|
|
|
[IconFile("Paste")]
|
|
Paste,
|
|
|
|
[IconFile("SelectAll")]
|
|
SelectAll,
|
|
|
|
[IconFile("EditLabel")]
|
|
EditLabel,
|
|
|
|
[IconFile("Add")]
|
|
AddWatch,
|
|
|
|
[IconFile("BreakpointEnableDisable")]
|
|
EditBreakpoint,
|
|
|
|
MarkSelectionAs,
|
|
|
|
[IconFile("Accept")]
|
|
MarkAsCode,
|
|
|
|
[IconFile("CheatCode")]
|
|
MarkAsData,
|
|
|
|
[IconFile("Help")]
|
|
MarkAsUnidentified,
|
|
|
|
[IconFile("Add")]
|
|
Add,
|
|
|
|
[IconFile("Edit")]
|
|
Edit,
|
|
|
|
[IconFile("Close")]
|
|
Delete,
|
|
|
|
[IconFile("Breakpoint")]
|
|
AddBreakpoint,
|
|
|
|
[IconFile("MoveUp")]
|
|
MoveUp,
|
|
|
|
[IconFile("MoveDown")]
|
|
MoveDown,
|
|
|
|
WatchDecimalDisplay,
|
|
WatchHexDisplay,
|
|
WatchBinaryDisplay,
|
|
|
|
RowDisplayFormat,
|
|
RowFormatBinary,
|
|
RowFormatHex8Bits,
|
|
RowFormatHex16Bits,
|
|
RowFormatHex24Bits,
|
|
RowFormatSigned8Bits,
|
|
RowFormatSigned16Bits,
|
|
RowFormatSigned24Bits,
|
|
RowFormatUnsigned,
|
|
|
|
[IconFile("Close")]
|
|
ClearFormat,
|
|
|
|
[IconFile("Import")]
|
|
Import,
|
|
|
|
[IconFile("Export")]
|
|
Export,
|
|
|
|
ShowConsoleStatus,
|
|
ShowBreakpointList,
|
|
ShowWatchList,
|
|
ShowLabelList,
|
|
ShowCallStack,
|
|
|
|
ShowSettingsPanel,
|
|
ShowMemoryMappings,
|
|
|
|
[IconFile("Settings")]
|
|
Preferences,
|
|
|
|
[IconFile("MediaPlay")]
|
|
Continue,
|
|
|
|
[IconFile("MediaPause")]
|
|
Break,
|
|
|
|
[IconFile("StepInto")]
|
|
StepInto,
|
|
|
|
[IconFile("StepOver")]
|
|
StepOver,
|
|
|
|
[IconFile("StepOut")]
|
|
StepOut,
|
|
|
|
[IconFile("StepBack")]
|
|
StepBack,
|
|
|
|
[IconFile("RunPpuCycle")]
|
|
RunPpuCycle,
|
|
|
|
[IconFile("RunPpuScanline")]
|
|
RunPpuScanline,
|
|
|
|
[IconFile("RunPpuFrame")]
|
|
RunPpuFrame,
|
|
|
|
[IconFile("StepNmi")]
|
|
RunToNmi,
|
|
|
|
[IconFile("StepIrq")]
|
|
RunToIrq,
|
|
|
|
BreakIn,
|
|
BreakOn,
|
|
|
|
[IconFile("Refresh")]
|
|
Reset,
|
|
|
|
[IconFile("PowerCycle")]
|
|
PowerCycle,
|
|
|
|
[IconFile("Script")]
|
|
NewScript,
|
|
|
|
[IconFile("MediaPlay")]
|
|
RunScript,
|
|
|
|
[IconFile("MediaStop")]
|
|
StopScript,
|
|
|
|
[IconFile("Folder")]
|
|
Open,
|
|
|
|
[IconFile("SaveFloppy")]
|
|
Save,
|
|
|
|
SaveAs,
|
|
|
|
[IconFile("Exit")]
|
|
Exit,
|
|
|
|
[IconFile("Help")]
|
|
HelpApiReference,
|
|
|
|
RecentScripts,
|
|
|
|
[IconFile("Refresh")]
|
|
Refresh,
|
|
EnableAutoRefresh,
|
|
RefreshOnBreakPause,
|
|
|
|
ZoomIn,
|
|
ZoomOut,
|
|
|
|
[IconFile("Expand")]
|
|
GoToLocation,
|
|
|
|
[IconFile("Export")]
|
|
ExportToPng,
|
|
|
|
[IconFile("VerticalLayout")]
|
|
ViewInTileViewer,
|
|
|
|
[IconFile("CheatCode")]
|
|
ViewInMemoryViewer,
|
|
|
|
LoadTblFile,
|
|
ResetTblMappings,
|
|
GoToAddress,
|
|
GoToAll,
|
|
|
|
[IconFile("Debugger")]
|
|
OpenDebugger,
|
|
|
|
[IconFile("EventViewer")]
|
|
OpenEventViewer,
|
|
|
|
[IconFile("CheatCode")]
|
|
OpenMemoryTools,
|
|
|
|
[IconFile("RegisterIcon")]
|
|
OpenRegisterViewer,
|
|
|
|
[IconFile("LogWindow")]
|
|
OpenTraceLogger,
|
|
|
|
[IconFile("VideoOptions")]
|
|
OpenTilemapViewer,
|
|
|
|
[IconFile("VerticalLayout")]
|
|
OpenTileViewer,
|
|
|
|
[IconFile("PerfTracker")]
|
|
OpenSpriteViewer,
|
|
|
|
[IconFile("VideoFilter")]
|
|
OpenPaletteViewer,
|
|
|
|
[IconFile("Chip")]
|
|
OpenAssembler,
|
|
|
|
[IconFile("LogWindow")]
|
|
OpenDebugLog,
|
|
|
|
[IconFile("Speed")]
|
|
OpenProfiler,
|
|
|
|
[IconFile("Script")]
|
|
OpenScriptWindow,
|
|
|
|
[IconFile("Settings")]
|
|
OpenDebugSettings,
|
|
|
|
[IconFile("SpcDebugger")]
|
|
OpenSpcDebugger,
|
|
[IconFile("Cx4Debugger")]
|
|
OpenCx4Debugger,
|
|
[IconFile("NecDspDebugger")]
|
|
OpenNecDspDebugger,
|
|
[IconFile("GsuDebugger")]
|
|
OpenGsuDebugger,
|
|
[IconFile("Sa1Debugger")]
|
|
OpenSa1Debugger,
|
|
[IconFile("GameboyDebugger")]
|
|
OpenGameboyDebugger,
|
|
|
|
[IconFile("CheatCode")]
|
|
Cheats,
|
|
[IconFile("HistoryViewer")]
|
|
HistoryViewer,
|
|
[IconFile("Movie")]
|
|
Movies,
|
|
[IconFile("MediaPlay")]
|
|
Play,
|
|
[IconFile("Record")]
|
|
Record,
|
|
[IconFile("MediaStop")]
|
|
Stop,
|
|
|
|
[IconFile("Network")]
|
|
NetPlay,
|
|
Connect,
|
|
Disconnect,
|
|
StartServer,
|
|
StopServer,
|
|
SelectController,
|
|
|
|
[IconFile("Microphone")]
|
|
SoundRecorder,
|
|
[IconFile("VideoRecorder")]
|
|
VideoRecorder,
|
|
|
|
[IconFile("HdPack")]
|
|
HdPacks,
|
|
[IconFile("Import")]
|
|
InstallHdPack,
|
|
[IconFile("HdPack")]
|
|
HdPackBuilder,
|
|
|
|
[IconFile("LogWindow")]
|
|
LogWindow,
|
|
|
|
[IconFile("Camera")]
|
|
TakeScreenshot,
|
|
|
|
[IconFile("Help")]
|
|
OnlineHelp,
|
|
[IconFile("Update")]
|
|
CheckForUpdates,
|
|
[IconFile("Exclamation")]
|
|
About,
|
|
[IconFile("Comment")]
|
|
ReportBug,
|
|
|
|
[IconFile("Speed")]
|
|
Speed,
|
|
NormalSpeed,
|
|
DoubleSpeed,
|
|
TripleSpeed,
|
|
MaximumSpeed,
|
|
HalfSpeed,
|
|
QuarterSpeed,
|
|
IncreaseSpeed,
|
|
DecreaseSpeed,
|
|
ShowFps,
|
|
|
|
[IconFile("Fullscreen")]
|
|
VideoScale,
|
|
Fullscreen,
|
|
|
|
[IconFile("VideoFilter")]
|
|
VideoFilter,
|
|
[IconFile("WebBrowser")]
|
|
Region,
|
|
|
|
[IconFile("Audio")]
|
|
Audio,
|
|
[IconFile("DipSwitches")]
|
|
Emulation,
|
|
[IconFile("Controller")]
|
|
Input,
|
|
[IconFile("VideoOptions")]
|
|
Video,
|
|
[IconFile("NesIcon")]
|
|
Nes,
|
|
[IconFile("SnesIcon")]
|
|
Snes,
|
|
[IconFile("GameboyIcon")]
|
|
Gameboy,
|
|
[IconFile("MediaPause")]
|
|
Pause,
|
|
[IconFile("MediaStop")]
|
|
PowerOff,
|
|
[IconFile("MediaPlay")]
|
|
Resume,
|
|
|
|
[IconFile("SaveFloppy")]
|
|
SelectDisk,
|
|
[IconFile("MediaEject")]
|
|
EjectDisk,
|
|
|
|
[IconFile("Coins")]
|
|
InsertCoin1,
|
|
[IconFile("Coins")]
|
|
InsertCoin2,
|
|
[IconFile("Coins")]
|
|
InsertCoin3,
|
|
[IconFile("Coins")]
|
|
InsertCoin4,
|
|
|
|
SaveState,
|
|
LoadState,
|
|
[IconFile("SplitView")]
|
|
SaveStateDialog,
|
|
[IconFile("SaveFloppy")]
|
|
SaveStateToFile,
|
|
[IconFile("SplitView")]
|
|
LoadStateDialog,
|
|
[IconFile("Folder")]
|
|
LoadStateFromFile,
|
|
|
|
RecentFiles,
|
|
LoadLastSession,
|
|
|
|
[IconFile("SaveFloppy")]
|
|
SaveRomAs,
|
|
[IconFile("CheatCode")]
|
|
SaveEditsAsIps,
|
|
|
|
[IconFile("Breakpoint")]
|
|
ToggleBreakpoint,
|
|
|
|
[IconFile("Edit")]
|
|
EditSelectedCode,
|
|
|
|
[IconFile("Debugger")]
|
|
ViewInDebugger,
|
|
|
|
[IconFile("Breakpoint")]
|
|
SetBreakpoint,
|
|
|
|
[IconFile("Close")]
|
|
RemoveBreakpoint,
|
|
|
|
[IconFile("BreakpointEnableDisable")]
|
|
EnableBreakpoint,
|
|
|
|
[IconFile("BreakpointEnableDisable")]
|
|
DisableBreakpoint,
|
|
|
|
[IconFile("Edit")]
|
|
CodeWindowEditBreakpoint,
|
|
|
|
CodeDataLogger,
|
|
[IconFile("Refresh")]
|
|
ResetCdl,
|
|
[IconFile("Folder")]
|
|
LoadCdl,
|
|
[IconFile("SaveFloppy")]
|
|
SaveCdl,
|
|
|
|
MoveProgramCounter,
|
|
ShowToolbar,
|
|
|
|
[IconFile("Refresh")]
|
|
ResetWorkspace,
|
|
[IconFile("TabContent")]
|
|
Workspace,
|
|
|
|
[IconFile("Import")]
|
|
ImportLabels,
|
|
[IconFile("Export")]
|
|
ExportLabels,
|
|
|
|
[IconFile("Import")]
|
|
ImportWatchEntries,
|
|
[IconFile("Export")]
|
|
ExportWatchEntries,
|
|
}
|
|
}
|