Added cheat code support (GG & PAR)

This commit is contained in:
Sour 2019-10-12 22:40:25 -04:00
parent c9a94e029f
commit 9aba01ba0c
30 changed files with 1569 additions and 46 deletions

48
Core/CheatManager.cpp Normal file
View file

@ -0,0 +1,48 @@
#include "stdafx.h"
#include "CheatManager.h"
#include "MessageManager.h"
#include "Console.h"
CheatManager::CheatManager(Console* console)
{
_console = console;
}
void CheatManager::AddCheat(uint32_t addr, uint8_t value)
{
_cheats.push_back({ addr, value });
_hasCheats = true;
_bankHasCheats[addr >> 16] = true;
}
void CheatManager::SetCheats(uint32_t codes[], uint32_t length)
{
auto lock = _console->AcquireLock();
bool hasCheats = !_cheats.empty();
ClearCheats(false);
for(uint32_t i = 0; i < length; i++) {
AddCheat(codes[i] >> 8, codes[i] & 0xFF);
}
if(length > 1) {
MessageManager::DisplayMessage("Cheats", "CheatsApplied", std::to_string(length));
} else if(length == 1) {
MessageManager::DisplayMessage("Cheats", "CheatApplied");
} else if(hasCheats) {
MessageManager::DisplayMessage("Cheats", "CheatsDisabled");
}
}
void CheatManager::ClearCheats(bool showMessage)
{
auto lock = _console->AcquireLock();
if(showMessage && !_cheats.empty()) {
MessageManager::DisplayMessage("Cheats", "CheatsDisabled");
}
_cheats.clear();
_hasCheats = false;
memset(_bankHasCheats, 0, sizeof(_bankHasCheats));
}

41
Core/CheatManager.h Normal file
View file

@ -0,0 +1,41 @@
#pragma once
#include "stdafx.h"
class Console;
struct CheatCode
{
uint32_t Address;
uint8_t Value;
};
class CheatManager
{
private:
Console* _console;
bool _hasCheats = false;
bool _bankHasCheats[0x100] = {};
vector<CheatCode> _cheats;
void AddCheat(uint32_t addr, uint8_t value);
public:
CheatManager(Console* console);
void SetCheats(uint32_t codes[], uint32_t length);
void ClearCheats(bool showMessage = true);
__forceinline void ApplyCheat(uint32_t addr, uint8_t &value);
};
__forceinline void CheatManager::ApplyCheat(uint32_t addr, uint8_t &value)
{
if(_hasCheats && _bankHasCheats[addr >> 16]) {
for(CheatCode &cheat : _cheats) {
if(cheat.Address == addr) {
value = cheat.Value;
break;
}
}
}
}

View file

@ -29,6 +29,7 @@
#include "ConsoleLock.h"
#include "MovieManager.h"
#include "BatteryManager.h"
#include "CheatManager.h"
#include "../Utilities/Serializer.h"
#include "../Utilities/Timer.h"
#include "../Utilities/VirtualFile.h"
@ -61,6 +62,7 @@ void Console::Initialize()
_saveStateManager.reset(new SaveStateManager(shared_from_this()));
_soundMixer.reset(new SoundMixer(this));
_debugHud.reset(new DebugHud());
_cheatManager.reset(new CheatManager(this));
_videoDecoder->StartThread();
_videoRenderer->StartThread();
@ -285,6 +287,8 @@ bool Console::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom)
shared_ptr<BaseCartridge> cart = BaseCartridge::CreateCartridge(this, romFile, patchFile);
if(cart) {
_cheatManager->ClearCheats(false);
if(stopRom) {
Stop(false);
}
@ -573,6 +577,11 @@ shared_ptr<BatteryManager> Console::GetBatteryManager()
return _batteryManager;
}
shared_ptr<CheatManager> Console::GetCheatManager()
{
return _cheatManager;
}
shared_ptr<Cpu> Console::GetCpu()
{
return _cpu;

View file

@ -24,6 +24,7 @@ class EmuSettings;
class SaveStateManager;
class RewindManager;
class BatteryManager;
class CheatManager;
enum class MemoryOperationType;
enum class SnesMemoryType;
enum class EventType;
@ -52,6 +53,7 @@ private:
shared_ptr<EmuSettings> _settings;
shared_ptr<SaveStateManager> _saveStateManager;
shared_ptr<RewindManager> _rewindManager;
shared_ptr<CheatManager> _cheatManager;
thread::id _emulationThreadId;
@ -113,6 +115,7 @@ public:
shared_ptr<RewindManager> GetRewindManager();
shared_ptr<DebugHud> GetDebugHud();
shared_ptr<BatteryManager> GetBatteryManager();
shared_ptr<CheatManager> GetCheatManager();
shared_ptr<Cpu> GetCpu();
shared_ptr<Ppu> GetPpu();

View file

@ -49,6 +49,7 @@
<ClInclude Include="BaseControlDevice.h" />
<ClInclude Include="BaseCoprocessor.h" />
<ClInclude Include="BatteryManager.h" />
<ClInclude Include="CheatManager.h" />
<ClInclude Include="Cpu.Shared.h" />
<ClInclude Include="CpuBwRamHandler.h" />
<ClInclude Include="CpuDebugger.h" />
@ -192,6 +193,7 @@
<ClCompile Include="Breakpoint.cpp" />
<ClCompile Include="BreakpointManager.cpp" />
<ClCompile Include="CallstackManager.cpp" />
<ClCompile Include="CheatManager.cpp" />
<ClCompile Include="CodeDataLogger.cpp" />
<ClCompile Include="Console.cpp" />
<ClCompile Include="ConsoleLock.cpp" />

View file

@ -407,6 +407,9 @@
<ClInclude Include="DmaControllerTypes.h">
<Filter>SNES</Filter>
</ClInclude>
<ClInclude Include="CheatManager.h">
<Filter>Misc</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
@ -656,6 +659,9 @@
<ClCompile Include="BatteryManager.cpp">
<Filter>Misc</Filter>
</ClCompile>
<ClCompile Include="CheatManager.cpp">
<Filter>Misc</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="SNES">

View file

@ -15,6 +15,7 @@
#include "Gsu.h"
#include "Cx4.h"
#include "BaseCoprocessor.h"
#include "CheatManager.h"
#include "../Utilities/Serializer.h"
#include "../Utilities/HexUtilities.h"
@ -28,6 +29,7 @@ void MemoryManager::Initialize(Console *console)
_cpu = console->GetCpu().get();
_ppu = console->GetPpu().get();
_cart = console->GetCartridge().get();
_cheatManager = console->GetCheatManager().get();
_workRam = new uint8_t[MemoryManager::WorkRamSize];
_console->GetSettings()->InitializeRam(_workRam, MemoryManager::WorkRamSize);
@ -256,6 +258,7 @@ uint8_t MemoryManager::Read(uint32_t addr, MemoryOperationType type)
value = _openBus;
LogDebug("[Debug] Read - missing handler: $" + HexUtilities::ToHex(addr));
}
_cheatManager->ApplyCheat(addr, value);
_console->ProcessMemoryRead<CpuType::Cpu>(addr, value, type);
IncMasterClock4();
@ -292,6 +295,7 @@ uint8_t MemoryManager::ReadDma(uint32_t addr, bool forBusA)
value = _openBus;
LogDebug("[Debug] Read - missing handler: $" + HexUtilities::ToHex(addr));
}
_cheatManager->ApplyCheat(addr, value);
_console->ProcessMemoryRead<CpuType::Cpu>(addr, value, MemoryOperationType::DmaRead);
return value;
}

View file

@ -13,6 +13,7 @@ class BaseCartridge;
class Console;
class Ppu;
class Cpu;
class CheatManager;
enum class MemoryOperationType;
class MemoryManager : public ISerializable
@ -30,6 +31,7 @@ private:
Ppu* _ppu;
Cpu* _cpu;
BaseCartridge* _cart;
CheatManager* _cheatManager;
MemoryMappings _mappings;
vector<unique_ptr<IMemoryHandler>> _workRamHandlers;

View file

@ -354,6 +354,7 @@ enum class EmulatorShortcut
ToggleOsd,
ToggleAlwaysOnTop,
ToggleDebugInfo,
ToggleCheats,
ToggleBgLayer0,
ToggleBgLayer1,

View file

@ -10,6 +10,7 @@
#include "../Core/INotificationListener.h"
#include "../Core/KeyManager.h"
#include "../Core/ShortcutKeyHandler.h"
#include "../Core/CheatManager.h"
#include "../Utilities/ArchiveReader.h"
#include "../Utilities/FolderUtilities.h"
#include "InteropNotificationListeners.h"
@ -213,6 +214,9 @@ extern "C" {
{
return _console->GetVideoDecoder()->GetScreenSize(ignoreScale);
}
DllExport void __stdcall ClearCheats() { _console->GetCheatManager()->ClearCheats(); }
DllExport void __stdcall SetCheats(uint32_t codes[], uint32_t length) { _console->GetCheatManager()->SetCheats(codes, length); }
DllExport void __stdcall WriteLogEntry(char* message) { MessageManager::Log(message); }

159
UI/Config/CheatCodes.cs Normal file
View file

@ -0,0 +1,159 @@
using Mesen.GUI.Config;
using Mesen.GUI.Debugger;
using Mesen.GUI.Debugger.Labels;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace Mesen.GUI.Config
{
public class CheatCodes
{
private static string FilePath { get { return Path.Combine(ConfigManager.CheatFolder, EmuApi.GetRomInfo().GetRomName() + ".xml"); } }
public List<CheatCode> Cheats = new List<CheatCode>();
public static CheatCodes LoadCheatCodes()
{
return Deserialize(CheatCodes.FilePath);
}
private static CheatCodes Deserialize(string path)
{
CheatCodes cheats = new CheatCodes();
if(File.Exists(path)) {
try {
XmlSerializer xmlSerializer = new XmlSerializer(typeof(CheatCodes));
using(TextReader textReader = new StreamReader(path)) {
cheats = (CheatCodes)xmlSerializer.Deserialize(textReader);
}
} catch { }
}
return cheats;
}
public void Save()
{
try {
XmlWriterSettings ws = new XmlWriterSettings();
ws.NewLineHandling = NewLineHandling.Entitize;
ws.Indent = true;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(CheatCodes));
using(XmlWriter xmlWriter = XmlWriter.Create(CheatCodes.FilePath, ws)) {
xmlSerializer.Serialize(xmlWriter, this);
}
} catch {
}
}
public static void ApplyCheats()
{
if(ConfigManager.Config.Cheats.DisableAllCheats) {
EmuApi.ClearCheats();
} else {
CheatCodes.ApplyCheats(LoadCheatCodes().Cheats);
}
}
public static void ApplyCheats(List<CheatCode> cheats)
{
List<UInt32> encodedCheats = new List<uint>();
foreach(CheatCode cheat in cheats) {
if(cheat.Enabled) {
encodedCheats.AddRange(cheat.GetEncodedCheats());
}
}
EmuApi.SetCheats(encodedCheats.ToArray(), (UInt32)encodedCheats.Count);
}
}
public class CheatCode
{
private static string _convertTable = "DF4709156BC8A23E";
public string Description;
public CheatFormat Format;
public bool Enabled;
public string Codes;
public List<UInt32> GetEncodedCheats()
{
List<UInt32> encodedCheats = new List<UInt32>();
foreach(string code in this.Codes.Split('\n')) {
if(code.Trim().Length > 0) {
encodedCheats.Add(GetEncodedCheat(code, this.Format));
}
}
return encodedCheats;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach(string code in this.Codes.Split('\n')) {
if(code.Trim().Length > 0) {
if(sb.Length != 0) {
sb.Append(", ");
}
sb.Append(code);
}
}
return sb.ToString();
}
public static UInt32 GetEncodedCheat(string code, CheatFormat format)
{
code = code.Trim();
UInt32 encodedCheat = 0;
if(format == CheatFormat.ProActionReplay && UInt32.TryParse(code, System.Globalization.NumberStyles.HexNumber, null, out encodedCheat)) {
return encodedCheat;
} else if(format == CheatFormat.GameGenie) {
return ConvertGameGenie(code);
}
throw new Exception("Invalid cheat code");
}
public static uint ConvertGameGenie(string code)
{
code = code.Trim().ToUpper();
uint rawValue = 0;
for(int i = 0; i < code.Length; i++) {
if(code[i] != '-') {
rawValue <<= 4;
rawValue |= (uint)_convertTable.IndexOf(code[i]);
}
}
uint address = (
((rawValue & 0x3C00) << 10) |
((rawValue & 0x3C) << 14) |
((rawValue & 0xF00000) >> 8) |
((rawValue & 0x03) << 10) |
((rawValue & 0xC000) >> 6) |
((rawValue & 0xF0000) >> 12) |
((rawValue & 0x3C0) >> 6)
);
uint value = rawValue >> 24;
return ((address << 8) | value);
}
}
public enum CheatFormat
{
GameGenie = 0,
ProActionReplay = 1,
}
}

View file

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Mesen.GUI.Config
{
public class CheatWindowConfig
{
public Size WindowSize = new Size(0, 0);
public Point WindowLocation;
public bool DisableAllCheats = false;
}
}

View file

@ -210,6 +210,8 @@ namespace Mesen.GUI.Config
public static string ScreenshotFolder { get { return GetFolder(DefaultScreenshotFolder, Config.Preferences.ScreenshotFolder, Config.Preferences.OverrideScreenshotFolder); } }
public static string WaveFolder { get { return GetFolder(DefaultWaveFolder, Config.Preferences.WaveFolder, Config.Preferences.OverrideWaveFolder); } }
public static string CheatFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Cheats"), null, false); } }
public static string DebuggerFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Debugger"), null, false); } }
public static string FirmwareFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Firmware"), null, false); } }
public static string DownloadFolder { get { return GetFolder(Path.Combine(ConfigManager.HomeFolder, "Downloads"), null, false); } }

View file

@ -24,6 +24,7 @@ namespace Mesen.GUI.Config
public RecentItems RecentFiles;
public AviRecordConfig AviRecord;
public MovieRecordConfig MovieRecord;
public CheatWindowConfig Cheats;
public Point WindowLocation;
public Size WindowSize;
public bool NeedInputReinit = true;
@ -40,6 +41,7 @@ namespace Mesen.GUI.Config
Preferences = new PreferencesConfig();
AviRecord = new AviRecordConfig();
MovieRecord = new MovieRecordConfig();
Cheats = new CheatWindowConfig();
}
~Configuration()

View file

@ -50,6 +50,7 @@ namespace Mesen.GUI.Config.Shortcuts
ToggleOsd,
ToggleAlwaysOnTop,
ToggleDebugInfo,
ToggleCheats,
ToggleBgLayer0,
ToggleBgLayer1,

View file

@ -53,6 +53,7 @@ namespace Mesen.GUI.Debugger.Workspace
try {
XmlWriterSettings ws = new XmlWriterSettings();
ws.NewLineHandling = NewLineHandling.Entitize;
ws.Indent = true;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(DebugWorkspace));
using(XmlWriter xmlWriter = XmlWriter.Create(_filePath, ws)) {

View file

@ -445,56 +445,25 @@
<Form ID="frmCheatList" Title="Cheats">
<Control ID="tabCheats">Cheats</Control>
<Control ID="btnAddCheat">Add Cheat</Control>
<Control ID="btnDelete">Delete</Control>
<Control ID="btnDeleteCheat">Delete selected cheats</Control>
<Control ID="btnDeleteGameCheats">Delete all cheats for selected game</Control>
<Control ID="btnDeleteCheat">Delete</Control>
<Control ID="mnuAddCheat">Add cheat...</Control>
<Control ID="mnuDeleteGameCheats">Delete</Control>
<Control ID="mnuDeleteCheat">Delete</Control>
<Control ID="colGameName">Game</Control>
<Control ID="colCheatName">Cheat Name</Control>
<Control ID="colCode">Code</Control>
<Control ID="btnImport">Import</Control>
<Control ID="btnImportCheatDB">From Cheat Database</Control>
<Control ID="btnImportFromFile">From File (XML, CHT)</Control>
<Control ID="btnExport">Export</Control>
<Control ID="btnExportAllCheats">All Cheats</Control>
<Control ID="btnExportGame">Selected Game</Control>
<Control ID="mnuExportGame">Export</Control>
<Control ID="btnExportSelectedCheats">Selected Cheats</Control>
<Control ID="mnuExportSelectedCheats">Export</Control>
<Control ID="chkDisableCheats">Disable all cheats</Control>
<Control ID="tpgCheatFinder">Cheat Finder</Control>
<Control ID="grpFilters">Filters</Control>
<Control ID="btnReset">Reset</Control>
<Control ID="btnUndo">Undo</Control>
<Control ID="lblCurrentValue">Current value is</Control>
<Control ID="lblPreviousValue">Previous value was</Control>
<Control ID="btnAddCurrentFilter">Add Filter</Control>
<Control ID="btnAddPrevFilter">Add Filter</Control>
<Control ID="btnCreateCheat">Create Cheat</Control>
<Control ID="mnuCreateCheat">Create Cheat</Control>
<Control ID="lblAtAddress">at</Control>
<Control ID="chkPauseGameWhileWindowActive">Automatically pause game when this window is active</Control>
<Control ID="btnOK">OK</Control>
<Control ID="btnCancel">Cancel</Control>
</Form>
<Form ID="frmCheat" Title="Edit Cheat">
<Control ID="label2">Game:</Control>
<Control ID="label1">Cheat Name:</Control>
<Control ID="grpCode">Code</Control>
<Control ID="radCustom">Custom:</Control>
<Control ID="radGameGenie">Game Genie:</Control>
<Control ID="radProActionRocky">Pro Action Rocky:</Control>
<Control ID="lblAddress">Address:</Control>
<Control ID="lblNewValue">New Value:</Control>
<Control ID="radRelativeAddress">Memory</Control>
<Control ID="radAbsoluteAddress">Game Code</Control>
<Control ID="chkCompareValue">Compare Value</Control>
<Control ID="btnBrowse">Browse...</Control>
<Control ID="lblDescription">Description:</Control>
<Control ID="grpCode">Codes</Control>
<Control ID="radGameGenie">Game Genie (e.g: A1B2-C3D4)</Control>
<Control ID="radProActionReplay">Pro Action Replay (e.g: AAAAAAVV)</Control>
<Control ID="chkEnabled">Cheat Enabled</Control>
<Control ID="lblHint">To enter multiple codes, enter 1 code per line.</Control>
<Control ID="lblInvalidCodes">Some codes do not match the selected format.</Control>
<Control ID="btnOK">OK</Control>
<Control ID="btnCancel">Cancel</Control>
</Form>

View file

@ -84,6 +84,7 @@ namespace Mesen.GUI.Emulation
case EmulatorShortcut.ToggleOsd: ToggleOsd(); break;
case EmulatorShortcut.ToggleAlwaysOnTop: ToggleAlwaysOnTop(); break;
case EmulatorShortcut.ToggleDebugInfo: ToggleDebugInfo(); break;
case EmulatorShortcut.ToggleCheats: ToggleCheats(); break;
case EmulatorShortcut.MaxSpeed: ToggleMaxSpeed(); break;
case EmulatorShortcut.ToggleFullscreen: _displayManager.ToggleFullscreen(); restoreFullscreen = false; break;
@ -265,6 +266,12 @@ namespace Mesen.GUI.Emulation
}
}
private void ToggleCheats()
{
InvertConfigFlag(ref ConfigManager.Config.Cheats.DisableAllCheats);
CheatCodes.ApplyCheats();
}
private void ToggleOsd()
{
InvertConfigFlag(ref ConfigManager.Config.Preferences.DisableOsd);

View file

@ -65,6 +65,7 @@ namespace Mesen.GUI.Forms.Config
EmulatorShortcut.ToggleOsd,
EmulatorShortcut.ToggleAlwaysOnTop,
EmulatorShortcut.ToggleAudio,
EmulatorShortcut.ToggleCheats,
EmulatorShortcut.ToggleBgLayer0,
EmulatorShortcut.ToggleBgLayer1,

343
UI/Forms/Tools/frmCheat.Designer.cs generated Normal file
View file

@ -0,0 +1,343 @@
namespace Mesen.GUI.Forms
{
partial class frmCheat
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.lblDescription = new System.Windows.Forms.Label();
this.txtCheatName = new System.Windows.Forms.TextBox();
this.grpCode = new System.Windows.Forms.GroupBox();
this.tlpAdd = new System.Windows.Forms.TableLayoutPanel();
this.tlpInvalidCodes = new System.Windows.Forms.TableLayoutPanel();
this.pictureBox2 = new System.Windows.Forms.PictureBox();
this.lblInvalidCodes = new System.Windows.Forms.Label();
this.radGameGenie = new System.Windows.Forms.RadioButton();
this.radProActionReplay = new System.Windows.Forms.RadioButton();
this.txtCodes = new System.Windows.Forms.TextBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.picHint = new System.Windows.Forms.PictureBox();
this.lblHint = new System.Windows.Forms.Label();
this.txtRawCodes = new System.Windows.Forms.TextBox();
this.chkEnabled = new System.Windows.Forms.CheckBox();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
this.tableLayoutPanel2.SuspendLayout();
this.grpCode.SuspendLayout();
this.tlpAdd.SuspendLayout();
this.tlpInvalidCodes.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
this.tableLayoutPanel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picHint)).BeginInit();
this.tableLayoutPanel3.SuspendLayout();
this.SuspendLayout();
//
// baseConfigPanel
//
this.baseConfigPanel.Location = new System.Drawing.Point(0, 262);
this.baseConfigPanel.Size = new System.Drawing.Size(410, 29);
this.baseConfigPanel.TabIndex = 4;
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 3;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.Controls.Add(this.lblDescription, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.txtCheatName, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.grpCode, 0, 2);
this.tableLayoutPanel2.Controls.Add(this.chkEnabled, 0, 1);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 3;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel2.Size = new System.Drawing.Size(410, 262);
this.tableLayoutPanel2.TabIndex = 4;
//
// lblDescription
//
this.lblDescription.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblDescription.AutoSize = true;
this.lblDescription.Location = new System.Drawing.Point(3, 6);
this.lblDescription.Name = "lblDescription";
this.lblDescription.Size = new System.Drawing.Size(63, 13);
this.lblDescription.TabIndex = 1;
this.lblDescription.Text = "Description:";
//
// txtCheatName
//
this.tableLayoutPanel2.SetColumnSpan(this.txtCheatName, 2);
this.txtCheatName.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtCheatName.Location = new System.Drawing.Point(72, 3);
this.txtCheatName.MaxLength = 255;
this.txtCheatName.Name = "txtCheatName";
this.txtCheatName.Size = new System.Drawing.Size(335, 20);
this.txtCheatName.TabIndex = 2;
//
// grpCode
//
this.tableLayoutPanel2.SetColumnSpan(this.grpCode, 3);
this.grpCode.Controls.Add(this.tlpAdd);
this.grpCode.Dock = System.Windows.Forms.DockStyle.Fill;
this.grpCode.Location = new System.Drawing.Point(3, 52);
this.grpCode.Name = "grpCode";
this.grpCode.Size = new System.Drawing.Size(404, 207);
this.grpCode.TabIndex = 3;
this.grpCode.TabStop = false;
this.grpCode.Text = "Codes";
//
// tlpAdd
//
this.tlpAdd.ColumnCount = 2;
this.tlpAdd.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpAdd.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tlpAdd.Controls.Add(this.tlpInvalidCodes, 0, 2);
this.tlpAdd.Controls.Add(this.txtCodes, 0, 1);
this.tlpAdd.Controls.Add(this.tableLayoutPanel1, 0, 3);
this.tlpAdd.Controls.Add(this.txtRawCodes, 1, 1);
this.tlpAdd.Controls.Add(this.tableLayoutPanel3, 0, 0);
this.tlpAdd.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpAdd.Location = new System.Drawing.Point(3, 16);
this.tlpAdd.Name = "tlpAdd";
this.tlpAdd.RowCount = 5;
this.tlpAdd.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpAdd.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpAdd.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpAdd.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpAdd.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tlpAdd.Size = new System.Drawing.Size(398, 188);
this.tlpAdd.TabIndex = 0;
//
// tlpInvalidCodes
//
this.tlpInvalidCodes.ColumnCount = 2;
this.tlpAdd.SetColumnSpan(this.tlpInvalidCodes, 2);
this.tlpInvalidCodes.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tlpInvalidCodes.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpInvalidCodes.Controls.Add(this.pictureBox2, 0, 0);
this.tlpInvalidCodes.Controls.Add(this.lblInvalidCodes, 1, 0);
this.tlpInvalidCodes.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpInvalidCodes.Location = new System.Drawing.Point(0, 148);
this.tlpInvalidCodes.Margin = new System.Windows.Forms.Padding(0);
this.tlpInvalidCodes.Name = "tlpInvalidCodes";
this.tlpInvalidCodes.RowCount = 1;
this.tlpInvalidCodes.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpInvalidCodes.Size = new System.Drawing.Size(398, 20);
this.tlpInvalidCodes.TabIndex = 7;
//
// pictureBox2
//
this.pictureBox2.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.pictureBox2.Image = global::Mesen.GUI.Properties.Resources.Warning;
this.pictureBox2.Location = new System.Drawing.Point(0, 1);
this.pictureBox2.Margin = new System.Windows.Forms.Padding(0);
this.pictureBox2.Name = "pictureBox2";
this.pictureBox2.Size = new System.Drawing.Size(17, 17);
this.pictureBox2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.pictureBox2.TabIndex = 5;
this.pictureBox2.TabStop = false;
//
// lblInvalidCodes
//
this.lblInvalidCodes.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblInvalidCodes.AutoSize = true;
this.lblInvalidCodes.Location = new System.Drawing.Point(20, 3);
this.lblInvalidCodes.Name = "lblInvalidCodes";
this.lblInvalidCodes.Size = new System.Drawing.Size(227, 13);
this.lblInvalidCodes.TabIndex = 4;
this.lblInvalidCodes.Text = "Some codes do not match the selected format.";
//
// radGameGenie
//
this.radGameGenie.AutoSize = true;
this.radGameGenie.Checked = true;
this.radGameGenie.Location = new System.Drawing.Point(3, 3);
this.radGameGenie.Name = "radGameGenie";
this.radGameGenie.Size = new System.Drawing.Size(144, 17);
this.radGameGenie.TabIndex = 2;
this.radGameGenie.TabStop = true;
this.radGameGenie.Text = "Game Genie (0000-0000)";
this.radGameGenie.UseVisualStyleBackColor = true;
this.radGameGenie.CheckedChanged += new System.EventHandler(this.radFormat_CheckedChanged);
//
// radProActionReplay
//
this.radProActionReplay.AutoSize = true;
this.radProActionReplay.Location = new System.Drawing.Point(153, 3);
this.radProActionReplay.Name = "radProActionReplay";
this.radProActionReplay.Size = new System.Drawing.Size(175, 17);
this.radProActionReplay.TabIndex = 2;
this.radProActionReplay.Text = "Pro Action Replay (AAAAAAVV)";
this.radProActionReplay.UseVisualStyleBackColor = true;
this.radProActionReplay.CheckedChanged += new System.EventHandler(this.radFormat_CheckedChanged);
//
// txtCodes
//
this.txtCodes.AcceptsReturn = true;
this.txtCodes.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtCodes.Location = new System.Drawing.Point(3, 26);
this.txtCodes.Multiline = true;
this.txtCodes.Name = "txtCodes";
this.txtCodes.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtCodes.Size = new System.Drawing.Size(193, 119);
this.txtCodes.TabIndex = 3;
this.txtCodes.TextChanged += new System.EventHandler(this.txtCodes_TextChanged);
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tlpAdd.SetColumnSpan(this.tableLayoutPanel1, 2);
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.picHint, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.lblHint, 1, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 168);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 1;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(398, 20);
this.tableLayoutPanel1.TabIndex = 5;
//
// picHint
//
this.picHint.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.picHint.Image = global::Mesen.GUI.Properties.Resources.Help;
this.picHint.Location = new System.Drawing.Point(0, 1);
this.picHint.Margin = new System.Windows.Forms.Padding(0);
this.picHint.Name = "picHint";
this.picHint.Size = new System.Drawing.Size(17, 17);
this.picHint.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.picHint.TabIndex = 5;
this.picHint.TabStop = false;
//
// lblHint
//
this.lblHint.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblHint.AutoSize = true;
this.lblHint.Location = new System.Drawing.Point(20, 3);
this.lblHint.Name = "lblHint";
this.lblHint.Size = new System.Drawing.Size(223, 13);
this.lblHint.TabIndex = 4;
this.lblHint.Text = "To enter multiple codes, enter 1 code per line.";
//
// txtRawCodes
//
this.txtRawCodes.Dock = System.Windows.Forms.DockStyle.Fill;
this.txtRawCodes.Location = new System.Drawing.Point(202, 26);
this.txtRawCodes.Multiline = true;
this.txtRawCodes.Name = "txtRawCodes";
this.txtRawCodes.ReadOnly = true;
this.txtRawCodes.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.txtRawCodes.Size = new System.Drawing.Size(193, 119);
this.txtRawCodes.TabIndex = 8;
//
// chkEnabled
//
this.chkEnabled.AutoSize = true;
this.tableLayoutPanel2.SetColumnSpan(this.chkEnabled, 2);
this.chkEnabled.Location = new System.Drawing.Point(3, 29);
this.chkEnabled.Name = "chkEnabled";
this.chkEnabled.Size = new System.Drawing.Size(96, 17);
this.chkEnabled.TabIndex = 6;
this.chkEnabled.Text = "Cheat Enabled";
this.chkEnabled.UseVisualStyleBackColor = true;
//
// tableLayoutPanel3
//
this.tableLayoutPanel3.ColumnCount = 3;
this.tlpAdd.SetColumnSpan(this.tableLayoutPanel3, 2);
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.Controls.Add(this.radProActionReplay, 1, 0);
this.tableLayoutPanel3.Controls.Add(this.radGameGenie, 0, 0);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 1;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.Size = new System.Drawing.Size(398, 23);
this.tableLayoutPanel3.TabIndex = 9;
//
// frmCheat
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(410, 291);
this.Controls.Add(this.tableLayoutPanel2);
this.MinimumSize = new System.Drawing.Size(426, 330);
this.Name = "frmCheat";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Edit Cheat";
this.Controls.SetChildIndex(this.baseConfigPanel, 0);
this.Controls.SetChildIndex(this.tableLayoutPanel2, 0);
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.grpCode.ResumeLayout(false);
this.tlpAdd.ResumeLayout(false);
this.tlpAdd.PerformLayout();
this.tlpInvalidCodes.ResumeLayout(false);
this.tlpInvalidCodes.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picHint)).EndInit();
this.tableLayoutPanel3.ResumeLayout(false);
this.tableLayoutPanel3.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.Label lblDescription;
private System.Windows.Forms.TextBox txtCheatName;
private System.Windows.Forms.GroupBox grpCode;
private System.Windows.Forms.TableLayoutPanel tlpAdd;
private System.Windows.Forms.RadioButton radGameGenie;
private System.Windows.Forms.RadioButton radProActionReplay;
private System.Windows.Forms.TextBox txtCodes;
private System.Windows.Forms.CheckBox chkEnabled;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label lblHint;
private System.Windows.Forms.PictureBox picHint;
private System.Windows.Forms.TableLayoutPanel tlpInvalidCodes;
private System.Windows.Forms.PictureBox pictureBox2;
private System.Windows.Forms.Label lblInvalidCodes;
private System.Windows.Forms.TextBox txtRawCodes;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
}
}

View file

@ -0,0 +1,89 @@
using Mesen.GUI.Config;
using Mesen.GUI.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Forms
{
public partial class frmCheat : BaseConfigForm
{
public frmCheat(CheatCode cheat)
{
InitializeComponent();
this.Icon = Resources.CheatCode;
this.Entity = cheat;
AddBinding(nameof(CheatCode.Description), txtCheatName);
AddBinding(nameof(CheatCode.Enabled), chkEnabled);
AddBinding(nameof(CheatCode.Codes), txtCodes);
radGameGenie.Checked = cheat.Format == CheatFormat.GameGenie;
radProActionReplay.Checked = cheat.Format == CheatFormat.ProActionReplay;
}
protected override bool ValidateInput()
{
Regex validate = new Regex(radGameGenie.Checked ? "^[a-f0-9]{4}-[a-f0-9]{4}$" : "^[a-f0-9]{8}$", RegexOptions.IgnoreCase);
int validCodeCount = 0;
foreach(string code in txtCodes.Text.Split(new string[1] { Environment.NewLine }, StringSplitOptions.None)) {
string trimmedCode = code.Trim();
if(trimmedCode.Length > 0) {
if(validate.IsMatch(trimmedCode)) {
validCodeCount++;
} else {
tlpInvalidCodes.Visible = true;
return false;
}
}
}
tlpInvalidCodes.Visible = false;
return validCodeCount > 0;
}
protected override void OnApply()
{
((CheatCode)this.Entity).Format = radGameGenie.Checked ? CheatFormat.GameGenie : CheatFormat.ProActionReplay;
}
private void GenerateRawCodes()
{
StringBuilder sb = new StringBuilder();
Regex validate = new Regex(radGameGenie.Checked ? "^[a-f0-9]{4}-[a-f0-9]{4}$" : "^[a-f0-9]{8}$", RegexOptions.IgnoreCase);
foreach(string code in txtCodes.Text.Split(new string[1] { Environment.NewLine }, StringSplitOptions.None)) {
string trimmedCode = code.Trim();
if(trimmedCode.Length > 0) {
if(!validate.IsMatch(trimmedCode)) {
sb.AppendLine("[invalid code]");
} else {
uint encodedCheat = CheatCode.GetEncodedCheat(trimmedCode, radGameGenie.Checked ? CheatFormat.GameGenie : CheatFormat.ProActionReplay);
sb.AppendLine("$" + (encodedCheat >> 8).ToString("X6") + " = $" + (encodedCheat & 0xFF).ToString("X2"));
}
} else {
sb.AppendLine("");
}
}
txtRawCodes.Text = sb.ToString();
}
private void txtCodes_TextChanged(object sender, EventArgs e)
{
GenerateRawCodes();
}
private void radFormat_CheckedChanged(object sender, EventArgs e)
{
GenerateRawCodes();
}
}
}

View file

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

293
UI/Forms/Tools/frmCheatList.Designer.cs generated Normal file
View file

@ -0,0 +1,293 @@
using Mesen.GUI.Controls;
namespace Mesen.GUI.Forms
{
partial class frmCheatList
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tabMain = new System.Windows.Forms.TabControl();
this.tabCheats = new System.Windows.Forms.TabPage();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.lstCheats = new Mesen.GUI.Controls.MyListView();
this.colCheatName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colCodes = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.contextMenuCheats = new System.Windows.Forms.ContextMenuStrip(this.components);
this.mnuAddCheat = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEditCheat = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDeleteCheat = new System.Windows.Forms.ToolStripMenuItem();
this.tsCheatActions = new Mesen.GUI.Controls.ctrlMesenToolStrip();
this.btnAddCheat = new System.Windows.Forms.ToolStripButton();
this.btnEditCheat = new System.Windows.Forms.ToolStripButton();
this.btnDeleteCheat = new System.Windows.Forms.ToolStripButton();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.chkDisableCheats = new System.Windows.Forms.CheckBox();
this.colEnabled = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.baseConfigPanel.SuspendLayout();
this.tabMain.SuspendLayout();
this.tabCheats.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.contextMenuCheats.SuspendLayout();
this.tsCheatActions.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.SuspendLayout();
//
// baseConfigPanel
//
this.baseConfigPanel.Controls.Add(this.chkDisableCheats);
this.baseConfigPanel.Location = new System.Drawing.Point(0, 324);
this.baseConfigPanel.Size = new System.Drawing.Size(446, 29);
this.baseConfigPanel.TabIndex = 4;
this.baseConfigPanel.Controls.SetChildIndex(this.chkDisableCheats, 0);
//
// tabMain
//
this.tabMain.Controls.Add(this.tabCheats);
this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabMain.Location = new System.Drawing.Point(0, 0);
this.tabMain.Margin = new System.Windows.Forms.Padding(0);
this.tabMain.Name = "tabMain";
this.tabMain.SelectedIndex = 0;
this.tabMain.Size = new System.Drawing.Size(446, 324);
this.tabMain.TabIndex = 0;
//
// tabCheats
//
this.tabCheats.Controls.Add(this.tableLayoutPanel1);
this.tabCheats.Location = new System.Drawing.Point(4, 22);
this.tabCheats.Name = "tabCheats";
this.tabCheats.Padding = new System.Windows.Forms.Padding(3);
this.tabCheats.Size = new System.Drawing.Size(438, 298);
this.tabCheats.TabIndex = 0;
this.tabCheats.Text = "Cheats";
this.tabCheats.UseVisualStyleBackColor = true;
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel1.Controls.Add(this.lstCheats, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.tsCheatActions, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 2;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(432, 292);
this.tableLayoutPanel1.TabIndex = 0;
//
// lstCheats
//
this.lstCheats.CheckBoxes = true;
this.lstCheats.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colEnabled,
this.colCheatName,
this.colCodes});
this.lstCheats.ContextMenuStrip = this.contextMenuCheats;
this.lstCheats.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstCheats.FullRowSelect = true;
this.lstCheats.GridLines = true;
this.lstCheats.HideSelection = false;
this.lstCheats.Location = new System.Drawing.Point(0, 26);
this.lstCheats.Margin = new System.Windows.Forms.Padding(0, 3, 0, 0);
this.lstCheats.Name = "lstCheats";
this.lstCheats.Size = new System.Drawing.Size(432, 266);
this.lstCheats.TabIndex = 1;
this.lstCheats.UseCompatibleStateImageBehavior = false;
this.lstCheats.View = System.Windows.Forms.View.Details;
this.lstCheats.SelectedIndexChanged += new System.EventHandler(this.lstCheats_SelectedIndexChanged);
this.lstCheats.DoubleClick += new System.EventHandler(this.lstCheats_DoubleClick);
//
// colCheatName
//
this.colCheatName.Name = "colCheatName";
this.colCheatName.Text = "Cheat Name";
this.colCheatName.Width = 250;
//
// colCodes
//
this.colCodes.Name = "colCodes";
this.colCodes.Text = "Codes";
this.colCodes.Width = 304;
//
// contextMenuCheats
//
this.contextMenuCheats.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuAddCheat,
this.mnuEditCheat,
this.mnuDeleteCheat});
this.contextMenuCheats.Name = "contextMenuCheats";
this.contextMenuCheats.Size = new System.Drawing.Size(160, 70);
//
// mnuAddCheat
//
this.mnuAddCheat.Image = global::Mesen.GUI.Properties.Resources.Add;
this.mnuAddCheat.Name = "mnuAddCheat";
this.mnuAddCheat.ShortcutKeys = System.Windows.Forms.Keys.Insert;
this.mnuAddCheat.Size = new System.Drawing.Size(159, 22);
this.mnuAddCheat.Text = "Add cheat...";
this.mnuAddCheat.Click += new System.EventHandler(this.mnuAddCheat_Click);
//
// mnuEditCheat
//
this.mnuEditCheat.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.mnuEditCheat.Name = "mnuEditCheat";
this.mnuEditCheat.ShortcutKeyDisplayString = "Dbl-Click";
this.mnuEditCheat.Size = new System.Drawing.Size(159, 22);
this.mnuEditCheat.Text = "Edit";
this.mnuEditCheat.Click += new System.EventHandler(this.mnuEditCheat_Click);
//
// mnuDeleteCheat
//
this.mnuDeleteCheat.Enabled = false;
this.mnuDeleteCheat.Image = global::Mesen.GUI.Properties.Resources.Close;
this.mnuDeleteCheat.Name = "mnuDeleteCheat";
this.mnuDeleteCheat.ShortcutKeys = System.Windows.Forms.Keys.Delete;
this.mnuDeleteCheat.Size = new System.Drawing.Size(159, 22);
this.mnuDeleteCheat.Text = "Delete";
this.mnuDeleteCheat.Click += new System.EventHandler(this.btnDeleteCheat_Click);
//
// tsCheatActions
//
this.tsCheatActions.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.btnAddCheat,
this.btnEditCheat,
this.btnDeleteCheat});
this.tsCheatActions.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.Flow;
this.tsCheatActions.Location = new System.Drawing.Point(0, 0);
this.tsCheatActions.Name = "tsCheatActions";
this.tsCheatActions.Size = new System.Drawing.Size(432, 23);
this.tsCheatActions.TabIndex = 6;
this.tsCheatActions.Text = "toolStrip1";
//
// btnAddCheat
//
this.btnAddCheat.Image = global::Mesen.GUI.Properties.Resources.Add;
this.btnAddCheat.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnAddCheat.Name = "btnAddCheat";
this.btnAddCheat.Size = new System.Drawing.Size(83, 20);
this.btnAddCheat.Text = "Add Cheat";
this.btnAddCheat.Click += new System.EventHandler(this.mnuAddCheat_Click);
//
// btnEditCheat
//
this.btnEditCheat.Image = global::Mesen.GUI.Properties.Resources.Edit;
this.btnEditCheat.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnEditCheat.Name = "btnEditCheat";
this.btnEditCheat.Size = new System.Drawing.Size(47, 20);
this.btnEditCheat.Text = "Edit";
this.btnEditCheat.Click += new System.EventHandler(this.mnuEditCheat_Click);
//
// btnDeleteCheat
//
this.btnDeleteCheat.Image = global::Mesen.GUI.Properties.Resources.Close;
this.btnDeleteCheat.ImageTransparentColor = System.Drawing.Color.Magenta;
this.btnDeleteCheat.Name = "btnDeleteCheat";
this.btnDeleteCheat.Size = new System.Drawing.Size(60, 20);
this.btnDeleteCheat.Text = "Delete";
this.btnDeleteCheat.Click += new System.EventHandler(this.btnDeleteCheat_Click);
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 1;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Controls.Add(this.tabMain, 0, 0);
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 2;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.Size = new System.Drawing.Size(446, 324);
this.tableLayoutPanel2.TabIndex = 2;
//
// chkDisableCheats
//
this.chkDisableCheats.AutoSize = true;
this.chkDisableCheats.Location = new System.Drawing.Point(7, 7);
this.chkDisableCheats.Name = "chkDisableCheats";
this.chkDisableCheats.Size = new System.Drawing.Size(109, 17);
this.chkDisableCheats.TabIndex = 3;
this.chkDisableCheats.Text = "Disable all cheats";
this.chkDisableCheats.UseVisualStyleBackColor = true;
this.chkDisableCheats.CheckedChanged += new System.EventHandler(this.chkDisableCheats_CheckedChanged);
//
// colEnabled
//
this.colEnabled.Text = "";
this.colEnabled.Width = 21;
//
// frmCheatList
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(446, 353);
this.Controls.Add(this.tableLayoutPanel2);
this.MinimumSize = new System.Drawing.Size(415, 316);
this.Name = "frmCheatList";
this.ShowInTaskbar = true;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Cheats";
this.Controls.SetChildIndex(this.baseConfigPanel, 0);
this.Controls.SetChildIndex(this.tableLayoutPanel2, 0);
this.baseConfigPanel.ResumeLayout(false);
this.baseConfigPanel.PerformLayout();
this.tabMain.ResumeLayout(false);
this.tabCheats.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.contextMenuCheats.ResumeLayout(false);
this.tsCheatActions.ResumeLayout(false);
this.tsCheatActions.PerformLayout();
this.tableLayoutPanel2.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TabControl tabMain;
private System.Windows.Forms.TabPage tabCheats;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private MyListView lstCheats;
private System.Windows.Forms.ColumnHeader colCheatName;
private System.Windows.Forms.ContextMenuStrip contextMenuCheats;
private System.Windows.Forms.ToolStripMenuItem mnuAddCheat;
private System.Windows.Forms.ToolStripMenuItem mnuDeleteCheat;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.CheckBox chkDisableCheats;
private ctrlMesenToolStrip tsCheatActions;
private System.Windows.Forms.ToolStripButton btnAddCheat;
private System.Windows.Forms.ColumnHeader colCodes;
private System.Windows.Forms.ToolStripMenuItem mnuEditCheat;
private System.Windows.Forms.ToolStripButton btnEditCheat;
private System.Windows.Forms.ToolStripButton btnDeleteCheat;
private System.Windows.Forms.ColumnHeader colEnabled;
}
}

View file

@ -0,0 +1,228 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Config;
using Mesen.GUI.Debugger;
using Mesen.GUI.Properties;
namespace Mesen.GUI.Forms
{
public partial class frmCheatList : BaseConfigForm
{
private List<CheatCode> _cheats;
private NotificationListener _notifListener;
public frmCheatList()
{
InitializeComponent();
}
private static frmCheatList _instance = null;
public static void ShowWindow()
{
if(_instance != null) {
DebugWindowManager.BringToFront(_instance);
}
frmCheatList frm = new frmCheatList();
_instance = frm;
frm.Closed += (s, e) => { _instance = null; };
frm.Show(null, Application.OpenForms[0]);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if(!DesignMode) {
this.Icon = Resources.CheatCode;
_notifListener = new NotificationListener();
_notifListener.OnNotification += OnNotification;
InitCheatList();
UpdateMenuItems();
chkDisableCheats.Checked = ConfigManager.Config.Cheats.DisableAllCheats;
RestoreLocation(ConfigManager.Config.Cheats.WindowLocation, ConfigManager.Config.Cheats.WindowSize);
}
}
private void InitCheatList()
{
_cheats = new List<CheatCode>(CheatCodes.LoadCheatCodes().Cheats);
UpdateCheatList();
}
private void OnNotification(NotificationEventArgs e)
{
switch(e.NotificationType) {
case ConsoleNotificationType.GameLoaded:
this.BeginInvoke((Action)(() => {
InitCheatList();
}));
break;
case ConsoleNotificationType.BeforeEmulationStop:
this.Invoke((Action)(() => {
Close();
}));
break;
}
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
_notifListener?.Dispose();
ConfigManager.Config.Cheats.WindowLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location;
ConfigManager.Config.Cheats.WindowSize = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Size : this.Size;
if(this.DialogResult == DialogResult.OK) {
ConfigManager.Config.Cheats.DisableAllCheats = chkDisableCheats.Checked;
(new CheatCodes() { Cheats = _cheats }).Save();
}
ConfigManager.ApplyChanges();
CheatCodes.ApplyCheats();
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
ResizeColumns();
}
protected override void OnResizeEnd(EventArgs e)
{
base.OnResizeEnd(e);
ResizeColumns();
}
private void ResizeColumns()
{
colCodes.Width = lstCheats.ClientSize.Width - colEnabled.Width - colCheatName.Width - 10;
}
private void ApplyCheats()
{
if(chkDisableCheats.Checked) {
EmuApi.ClearCheats();
} else {
CheatCodes.ApplyCheats(_cheats);
}
}
private void UpdateCheatList()
{
lstCheats.BeginUpdate();
lstCheats.Sorting = SortOrder.None;
lstCheats.Items.Clear();
lstCheats.ItemChecked -= lstCheats_ItemChecked;
foreach(CheatCode cheat in _cheats) {
ListViewItem item = lstCheats.Items.Add("");
item.SubItems.Add(string.IsNullOrWhiteSpace(cheat.Description) ? "[n/a]" : cheat.Description);
item.SubItems.Add(cheat.ToString());
item.Tag = cheat;
item.Checked = cheat.Enabled;
}
lstCheats.Sorting = SortOrder.Ascending;
lstCheats.ItemChecked += lstCheats_ItemChecked;
lstCheats.EndUpdate();
ResizeColumns();
}
private void mnuAddCheat_Click(object sender, EventArgs e)
{
CheatCode newCheat = new CheatCode() { Enabled = true };
using(frmCheat frm = new frmCheat(newCheat)) {
if(frm.ShowDialog(this) == DialogResult.OK) {
AddCheats(new List<CheatCode>() { newCheat });
}
}
}
private void EditCheat()
{
if(lstCheats.SelectedItems.Count == 1) {
using(frmCheat frm = new frmCheat((CheatCode)lstCheats.SelectedItems[0].Tag)) {
if(frm.ShowDialog(this) == DialogResult.OK) {
UpdateCheatList();
ApplyCheats();
}
}
}
}
private void lstCheats_DoubleClick(object sender, EventArgs e)
{
EditCheat();
}
private void lstCheats_ItemChecked(object sender, ItemCheckedEventArgs e)
{
if(e.Item.Tag is CheatCode) {
((CheatCode)e.Item.Tag).Enabled = e.Item.Checked;
ApplyCheats();
lstCheats.SelectedItems.Clear();
}
}
private void lstCheats_SelectedIndexChanged(object sender, EventArgs e)
{
UpdateMenuItems();
}
private void UpdateMenuItems()
{
mnuDeleteCheat.Enabled = btnDeleteCheat.Enabled = lstCheats.SelectedItems.Count > 0;
mnuEditCheat.Enabled = btnEditCheat.Enabled = lstCheats.SelectedItems.Count == 1;
}
private void DeleteSelectedCheats()
{
if(lstCheats.SelectedItems.Count > 0) {
foreach(ListViewItem item in lstCheats.SelectedItems) {
CheatCode cheat = item.Tag as CheatCode;
_cheats.Remove(cheat);
}
ApplyCheats();
UpdateCheatList();
}
}
private void btnDeleteCheat_Click(object sender, EventArgs e)
{
DeleteSelectedCheats();
}
private void AddCheats(List<CheatCode> cheats)
{
if(cheats.Count > 0) {
foreach(CheatCode cheat in cheats) {
_cheats.Add(cheat);
}
UpdateCheatList();
ApplyCheats();
}
}
private void chkDisableCheats_CheckedChanged(object sender, EventArgs e)
{
ApplyCheats();
}
private void mnuEditCheat_Click(object sender, EventArgs e)
{
EditCheat();
}
}
}

View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="contextMenuCheats.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
</metadata>
<metadata name="tsCheatActions.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>267, 17</value>
</metadata>
</root>

View file

@ -126,6 +126,7 @@
this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripSeparator();
this.mnuLogWindow = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRandomGame = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTakeScreenshot = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDebug = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDebugger = new System.Windows.Forms.ToolStripMenuItem();
@ -151,7 +152,7 @@
this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem();
this.pnlRenderer = new System.Windows.Forms.Panel();
this.ctrlRecentGames = new Mesen.GUI.Controls.ctrlRecentGames();
this.mnuRandomGame = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCheats = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMain.SuspendLayout();
this.pnlRenderer.SuspendLayout();
this.SuspendLayout();
@ -780,6 +781,7 @@
// mnuTools
//
this.mnuTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuCheats,
this.mnuMovies,
this.toolStripMenuItem25,
this.mnuSoundRecorder,
@ -906,6 +908,13 @@
this.toolStripMenuItem7.Name = "toolStripMenuItem7";
this.toolStripMenuItem7.Size = new System.Drawing.Size(179, 6);
//
// mnuRandomGame
//
this.mnuRandomGame.Image = global::Mesen.GUI.Properties.Resources.Dice;
this.mnuRandomGame.Name = "mnuRandomGame";
this.mnuRandomGame.Size = new System.Drawing.Size(182, 22);
this.mnuRandomGame.Text = "Load Random Game";
//
// mnuTakeScreenshot
//
this.mnuTakeScreenshot.Image = global::Mesen.GUI.Properties.Resources.Camera;
@ -1106,12 +1115,12 @@
this.ctrlRecentGames.TabIndex = 1;
this.ctrlRecentGames.Visible = false;
//
// mnuRandomGame
// mnuCheats
//
this.mnuRandomGame.Image = global::Mesen.GUI.Properties.Resources.Dice;
this.mnuRandomGame.Name = "mnuRandomGame";
this.mnuRandomGame.Size = new System.Drawing.Size(182, 22);
this.mnuRandomGame.Text = "Load Random Game";
this.mnuCheats.Image = global::Mesen.GUI.Properties.Resources.CheatCode;
this.mnuCheats.Name = "mnuCheats";
this.mnuCheats.Size = new System.Drawing.Size(182, 22);
this.mnuCheats.Text = "Cheats";
//
// frmMain
//
@ -1263,5 +1272,6 @@
private System.Windows.Forms.ToolStripMenuItem mnuBilinearInterpolation;
private System.Windows.Forms.ToolStripMenuItem mnuRegisterViewer;
private System.Windows.Forms.ToolStripMenuItem mnuRandomGame;
private System.Windows.Forms.ToolStripMenuItem mnuCheats;
}
}

View file

@ -140,6 +140,8 @@ namespace Mesen.GUI.Forms
{
switch(e.NotificationType) {
case ConsoleNotificationType.GameLoaded:
CheatCodes.ApplyCheats();
this.BeginInvoke((Action)(() => {
UpdateDebuggerMenu();
ctrlRecentGames.Visible = false;
@ -239,7 +241,7 @@ namespace Mesen.GUI.Forms
_shortcuts.BindShortcut(mnuTakeScreenshot, EmulatorShortcut.TakeScreenshot, running);
_shortcuts.BindShortcut(mnuRandomGame, EmulatorShortcut.LoadRandomGame);
mnuDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenDebugger));
mnuSpcDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenSpcDebugger));
mnuSa1Debugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenSa1Debugger));
@ -289,6 +291,8 @@ namespace Mesen.GUI.Forms
mnuRegionNtsc.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Ntsc); };
mnuRegionPal.Click += (s, e) => { _shortcuts.SetRegion(ConsoleRegion.Pal); };
mnuCheats.Click += (s, e) => { frmCheatList.ShowWindow(); };
mnuDebugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger); };
mnuSpcDebugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.SpcDebugger); };
mnuSa1Debugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.Sa1Debugger); };
@ -328,6 +332,8 @@ namespace Mesen.GUI.Forms
mnuPaletteViewer.Enabled = running;
mnuEventViewer.Enabled = running;
mnuRegisterViewer.Enabled = running;
mnuCheats.Enabled = running;
}
private void ResizeRecentGames()

View file

@ -86,6 +86,9 @@ namespace Mesen.GUI
[DllImport(DllPath)] public static extern void SaveStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filepath);
[DllImport(DllPath)] public static extern void LoadStateFile([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]string filepath);
[DllImport(DllPath)] public static extern Int64 GetStateInfo(UInt32 stateIndex);
[DllImport(DllPath)] public static extern void SetCheats([In]UInt32[] cheats, UInt32 cheatCount);
[DllImport(DllPath)] public static extern void ClearCheats();
}
public struct ScreenSize

View file

@ -49,6 +49,7 @@ namespace Mesen.GUI
//Cache deserializers in another thread
new XmlSerializer(typeof(Configuration));
new XmlSerializer(typeof(DebugWorkspace));
new XmlSerializer(typeof(CheatCodes));
});
if(Type.GetType("Mono.Runtime") != null) {

View file

@ -215,8 +215,10 @@
<Compile Include="Config\ConfigAttributes.cs" />
<Compile Include="Config\Configuration.cs" />
<Compile Include="Config\ConfigManager.cs" />
<Compile Include="Config\CheatCodes.cs" />
<Compile Include="Config\InputConfig.cs" />
<Compile Include="Config\FileAssociationHelper.cs" />
<Compile Include="Config\CheatWindowConfig.cs" />
<Compile Include="Config\MovieRecordConfig.cs" />
<Compile Include="Config\PreferencesConfig.cs" />
<Compile Include="Config\Shortcuts\EmulatorShortcut.cs" />
@ -788,6 +790,18 @@
<Compile Include="Forms\Config\frmRecordMovie.Designer.cs">
<DependentUpon>frmRecordMovie.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Tools\frmCheat.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\Tools\frmCheat.Designer.cs">
<DependentUpon>frmCheat.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Tools\frmCheatList.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\Tools\frmCheatList.Designer.cs">
<DependentUpon>frmCheatList.cs</DependentUpon>
</Compile>
<Compile Include="Forms\Tools\frmLogWindow.cs">
<SubType>Form</SubType>
</Compile>
@ -1080,6 +1094,12 @@
<EmbeddedResource Include="Forms\Config\frmRecordMovie.resx">
<DependentUpon>frmRecordMovie.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Tools\frmCheat.resx">
<DependentUpon>frmCheat.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Tools\frmCheatList.resx">
<DependentUpon>frmCheatList.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\Tools\frmLogWindow.resx">
<DependentUpon>frmLogWindow.cs</DependentUpon>
</EmbeddedResource>