mirror of
https://github.com/SourMesen/Mesen2.git
synced 2025-04-02 10:21:44 -04:00
189 lines
5.7 KiB
C#
189 lines
5.7 KiB
C#
using ReactiveUI.Fody.Helpers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reactive.Linq;
|
|
using System.Linq;
|
|
using Mesen.Debugger.Utilities;
|
|
using Mesen.Config;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Mesen.Windows;
|
|
using Avalonia.Collections;
|
|
using Mesen.Interop;
|
|
using Avalonia.Controls.Selection;
|
|
using DataBoxControl;
|
|
using System.ComponentModel;
|
|
using Mesen.Utilities;
|
|
using Avalonia.VisualTree;
|
|
using Mesen.Debugger;
|
|
|
|
namespace Mesen.ViewModels
|
|
{
|
|
public class CheatListWindowViewModel : DisposableViewModel
|
|
{
|
|
[Reactive] public MesenList<CheatCode> Cheats { get; private set; } = new();
|
|
[Reactive] public List<ContextMenuAction> ToolbarActions { get; private set; } = new();
|
|
[Reactive] public bool DisableAllCheats { get; set; } = false;
|
|
|
|
[Reactive] public SelectionModel<CheatCode> Selection { get; set; } = new();
|
|
[Reactive] public SortState SortState { get; set; } = new();
|
|
|
|
public CheatWindowConfig Config { get; }
|
|
|
|
private CheatCodes _cheatCodes = new();
|
|
|
|
public CheatListWindowViewModel()
|
|
{
|
|
Config = ConfigManager.Config.Cheats;
|
|
Selection.SingleSelect = false;
|
|
|
|
LoadCheats();
|
|
DisableAllCheats = Config.DisableAllCheats;
|
|
|
|
SortState.SetColumnSort("Description", ListSortDirection.Ascending, true);
|
|
Sort();
|
|
}
|
|
|
|
private Dictionary<string, Func<CheatCode, CheatCode, int>> _comparers = new() {
|
|
{ "Enabled", (a, b) => a.Enabled.CompareTo(b.Enabled) },
|
|
{ "Description", (a, b) => string.Compare(a.Description, b.Description, StringComparison.OrdinalIgnoreCase) },
|
|
{ "Codes", (a, b) => string.Compare(a.Codes, b.Codes, StringComparison.OrdinalIgnoreCase) }
|
|
};
|
|
|
|
public void Sort(object? param = null)
|
|
{
|
|
List<int> selectedIndexes = Selection.SelectedIndexes.ToList();
|
|
List<CheatCode> sortedCheats = new List<CheatCode>(Cheats);
|
|
SortHelper.SortList(sortedCheats, SortState.SortOrder, _comparers, "Codes");
|
|
Cheats.Replace(sortedCheats);
|
|
Selection.SelectIndexes(selectedIndexes, Cheats.Count);
|
|
}
|
|
|
|
public void LoadCheats()
|
|
{
|
|
_cheatCodes = CheatCodes.LoadCheatCodes();
|
|
Cheats = new MesenList<CheatCode>(_cheatCodes.Cheats);
|
|
}
|
|
|
|
public void SaveCheats()
|
|
{
|
|
ConfigManager.Config.Cheats.DisableAllCheats = DisableAllCheats;
|
|
_cheatCodes.Cheats = new List<CheatCode>(Cheats);
|
|
_cheatCodes.Save();
|
|
}
|
|
|
|
public void ApplyCheats()
|
|
{
|
|
if(DisableAllCheats) {
|
|
EmuApi.ClearCheats();
|
|
} else {
|
|
CheatCodes.ApplyCheats(Cheats);
|
|
}
|
|
}
|
|
|
|
public void InitActions(Control parent)
|
|
{
|
|
List<ContextMenuAction> toolbarActions = GetActions(parent);
|
|
toolbarActions.Add(new ContextMenuSeparator());
|
|
toolbarActions.Add(new ContextMenuAction() {
|
|
ActionType = ActionType.CheatDatabase,
|
|
AlwaysShowLabel = true,
|
|
IsEnabled = () => MainWindowViewModel.Instance.RomInfo.ConsoleType switch {
|
|
ConsoleType.Nes => true,
|
|
ConsoleType.Snes => true,
|
|
_ => false
|
|
},
|
|
OnClick = async () => {
|
|
ConsoleType consoleType = MainWindowViewModel.Instance.RomInfo.ConsoleType;
|
|
CheatDbGameEntry? dbEntry = await CheatDatabaseWindow.Show(consoleType, parent);
|
|
if(dbEntry != null && consoleType == MainWindowViewModel.Instance.RomInfo.ConsoleType) {
|
|
List<CheatCode> newCheats = new();
|
|
HashSet<string> existingCheats = new();
|
|
foreach(CheatCode cheatCode in Cheats) {
|
|
string key = cheatCode.Description + cheatCode.Codes + cheatCode.Type.ToString();
|
|
existingCheats.Add(key);
|
|
}
|
|
|
|
foreach(CheatDbCheatEntry cheatEntry in dbEntry.Cheats) {
|
|
CheatCode newCheat = new CheatCode();
|
|
newCheat.Description = cheatEntry.Desc;
|
|
newCheat.Enabled = false;
|
|
newCheat.Type = GetCheatType(consoleType, cheatEntry.Code);
|
|
newCheat.Codes = string.Join(Environment.NewLine, cheatEntry.Code.Split(";", StringSplitOptions.RemoveEmptyEntries));
|
|
|
|
string key = newCheat.Description + newCheat.Codes + newCheat.Type.ToString();
|
|
if(!existingCheats.Contains(key)) {
|
|
newCheats.Add(newCheat);
|
|
}
|
|
}
|
|
Cheats.AddRange(newCheats);
|
|
Sort();
|
|
ApplyCheats();
|
|
}
|
|
}
|
|
});
|
|
ToolbarActions = toolbarActions;
|
|
|
|
AddDisposables(DebugShortcutManager.CreateContextMenu(parent, GetActions(parent)));
|
|
}
|
|
|
|
private CheatType GetCheatType(ConsoleType consoleType, string code)
|
|
{
|
|
switch(consoleType) {
|
|
case ConsoleType.Snes:
|
|
return code.Contains("-") ? CheatType.SnesGameGenie : CheatType.SnesProActionReplay;
|
|
|
|
case ConsoleType.Nes:
|
|
return code.Contains(":") ? CheatType.NesCustom : CheatType.NesGameGenie;
|
|
|
|
default:
|
|
throw new Exception("Unsupported cheat type");
|
|
}
|
|
}
|
|
|
|
private List<ContextMenuAction> GetActions(Control parent)
|
|
{
|
|
return new List<ContextMenuAction> {
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.Add,
|
|
AlwaysShowLabel = true,
|
|
Shortcut = () => new DbgShortKeys(Key.Insert),
|
|
OnClick = async () => {
|
|
CheatCode newCheat = new CheatCode();
|
|
if(await CheatEditWindow.EditCheat(newCheat, parent)) {
|
|
Cheats.Add(newCheat);
|
|
Sort();
|
|
ApplyCheats();
|
|
}
|
|
}
|
|
},
|
|
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.Edit,
|
|
AlwaysShowLabel = true,
|
|
IsEnabled = () => Selection.SelectedItems.Count == 1,
|
|
OnClick = async () => {
|
|
if(Selection.SelectedItem is CheatCode cheat) {
|
|
await CheatEditWindow.EditCheat(cheat, parent);
|
|
Sort();
|
|
ApplyCheats();
|
|
}
|
|
}
|
|
},
|
|
|
|
new ContextMenuAction() {
|
|
ActionType = ActionType.Delete,
|
|
AlwaysShowLabel = true,
|
|
Shortcut = () => new DbgShortKeys(Key.Delete),
|
|
IsEnabled = () => Selection.SelectedItems.Count > 0,
|
|
OnClick = () => {
|
|
foreach(CheatCode cheat in Selection.SelectedItems.Cast<CheatCode>().ToArray()) {
|
|
Cheats.Remove(cheat);
|
|
}
|
|
ApplyCheats();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|