CheatWindow.cs
1 using Gtk; 2 using LibHac.Tools.FsSystem; 3 using Ryujinx.HLE.FileSystem; 4 using Ryujinx.HLE.HOS; 5 using Ryujinx.UI.App.Common; 6 using Ryujinx.UI.Common.Configuration; 7 using System; 8 using System.Collections.Generic; 9 using System.IO; 10 using System.Linq; 11 using GUI = Gtk.Builder.ObjectAttribute; 12 13 namespace Ryujinx.UI.Windows 14 { 15 public class CheatWindow : Window 16 { 17 private readonly string _enabledCheatsPath; 18 private readonly bool _noCheatsFound; 19 20 #pragma warning disable CS0649, IDE0044 // Field is never assigned to, Add readonly modifier 21 [GUI] Label _baseTitleInfoLabel; 22 [GUI] TextView _buildIdTextView; 23 [GUI] TreeView _cheatTreeView; 24 [GUI] Button _saveButton; 25 #pragma warning restore CS0649, IDE0044 26 27 public CheatWindow(VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : this(new Builder("Ryujinx.Gtk3.UI.Windows.CheatWindow.glade"), virtualFileSystem, titleId, titleName, titlePath) { } 28 29 private CheatWindow(Builder builder, VirtualFileSystem virtualFileSystem, ulong titleId, string titleName, string titlePath) : base(builder.GetRawOwnedObject("_cheatWindow")) 30 { 31 builder.Autoconnect(this); 32 33 IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks 34 ? IntegrityCheckLevel.ErrorOnInvalid 35 : IntegrityCheckLevel.None; 36 37 _baseTitleInfoLabel.Text = $"Cheats Available for {titleName} [{titleId:X16}]"; 38 _buildIdTextView.Buffer.Text = $"BuildId: {ApplicationData.GetBuildId(virtualFileSystem, checkLevel, titlePath)}"; 39 40 string modsBasePath = ModLoader.GetModsBasePath(); 41 string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, titleId.ToString("X16")); 42 43 _enabledCheatsPath = System.IO.Path.Combine(titleModsPath, "cheats", "enabled.txt"); 44 45 _cheatTreeView.Model = new TreeStore(typeof(bool), typeof(string), typeof(string), typeof(string)); 46 47 CellRendererToggle enableToggle = new(); 48 enableToggle.Toggled += (sender, args) => 49 { 50 _cheatTreeView.Model.GetIter(out TreeIter treeIter, new TreePath(args.Path)); 51 bool newValue = !(bool)_cheatTreeView.Model.GetValue(treeIter, 0); 52 _cheatTreeView.Model.SetValue(treeIter, 0, newValue); 53 54 if (_cheatTreeView.Model.IterChildren(out TreeIter childIter, treeIter)) 55 { 56 do 57 { 58 _cheatTreeView.Model.SetValue(childIter, 0, newValue); 59 } 60 while (_cheatTreeView.Model.IterNext(ref childIter)); 61 } 62 }; 63 64 _cheatTreeView.AppendColumn("Enabled", enableToggle, "active", 0); 65 _cheatTreeView.AppendColumn("Name", new CellRendererText(), "text", 1); 66 _cheatTreeView.AppendColumn("Path", new CellRendererText(), "text", 2); 67 68 var buildIdColumn = _cheatTreeView.AppendColumn("Build Id", new CellRendererText(), "text", 3); 69 buildIdColumn.Visible = false; 70 71 string[] enabled = Array.Empty<string>(); 72 73 if (File.Exists(_enabledCheatsPath)) 74 { 75 enabled = File.ReadAllLines(_enabledCheatsPath); 76 } 77 78 int cheatAdded = 0; 79 80 var mods = new ModLoader.ModCache(); 81 82 ModLoader.QueryContentsDir(mods, new DirectoryInfo(System.IO.Path.Combine(modsBasePath, "contents")), titleId); 83 84 string currentCheatFile = string.Empty; 85 string buildId = string.Empty; 86 TreeIter parentIter = default; 87 88 foreach (var cheat in mods.Cheats) 89 { 90 if (cheat.Path.FullName != currentCheatFile) 91 { 92 currentCheatFile = cheat.Path.FullName; 93 string parentPath = currentCheatFile.Replace(titleModsPath, ""); 94 95 buildId = System.IO.Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper(); 96 parentIter = ((TreeStore)_cheatTreeView.Model).AppendValues(false, buildId, parentPath, ""); 97 } 98 99 string cleanName = cheat.Name[1..^7]; 100 ((TreeStore)_cheatTreeView.Model).AppendValues(parentIter, enabled.Contains($"{buildId}-{cheat.Name}"), cleanName, "", buildId); 101 102 cheatAdded++; 103 } 104 105 if (cheatAdded == 0) 106 { 107 ((TreeStore)_cheatTreeView.Model).AppendValues(false, "No Cheats Found", "", ""); 108 _cheatTreeView.GetColumn(0).Visible = false; 109 110 _noCheatsFound = true; 111 112 _saveButton.Visible = false; 113 } 114 115 _cheatTreeView.ExpandAll(); 116 } 117 118 private void SaveButton_Clicked(object sender, EventArgs args) 119 { 120 if (_noCheatsFound) 121 { 122 return; 123 } 124 125 List<string> enabledCheats = new(); 126 127 if (_cheatTreeView.Model.GetIterFirst(out TreeIter parentIter)) 128 { 129 do 130 { 131 if (_cheatTreeView.Model.IterChildren(out TreeIter childIter, parentIter)) 132 { 133 do 134 { 135 var enabled = (bool)_cheatTreeView.Model.GetValue(childIter, 0); 136 137 if (enabled) 138 { 139 var name = _cheatTreeView.Model.GetValue(childIter, 1).ToString(); 140 var buildId = _cheatTreeView.Model.GetValue(childIter, 3).ToString(); 141 142 enabledCheats.Add($"{buildId}-<{name} Cheat>"); 143 } 144 } 145 while (_cheatTreeView.Model.IterNext(ref childIter)); 146 } 147 } 148 while (_cheatTreeView.Model.IterNext(ref parentIter)); 149 } 150 151 Directory.CreateDirectory(System.IO.Path.GetDirectoryName(_enabledCheatsPath)); 152 153 File.WriteAllLines(_enabledCheatsPath, enabledCheats); 154 155 Dispose(); 156 } 157 158 private void CancelButton_Clicked(object sender, EventArgs args) 159 { 160 Dispose(); 161 } 162 } 163 }