mirror of
https://github.com/libretro/Mesen.git
synced 2025-01-19 07:12:48 +00:00
Cheats: Apply all cheats at once (fixes game crashes that could occur because the game could run a full frame between each cheat)
This commit is contained in:
parent
94dd9683d1
commit
ecea158f50
@ -84,7 +84,6 @@ CodeInfo CheatManager::GetPARCodeInfo(uint32_t parCode)
|
||||
|
||||
void CheatManager::AddCode(CodeInfo &code)
|
||||
{
|
||||
Console::Pause();
|
||||
if(code.IsRelativeAddress) {
|
||||
if(_relativeCheatCodes[code.Address] == nullptr) {
|
||||
_relativeCheatCodes[code.Address].reset(new vector<CodeInfo>());
|
||||
@ -94,19 +93,18 @@ void CheatManager::AddCode(CodeInfo &code)
|
||||
_absoluteCheatCodes.push_back(code);
|
||||
}
|
||||
MessageManager::SendNotification(ConsoleNotificationType::CheatAdded);
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
void CheatManager::AddGameGenieCode(string code)
|
||||
{
|
||||
CodeInfo info = Instance->GetGGCodeInfo(code);
|
||||
Instance->AddCode(info);
|
||||
CodeInfo info = GetGGCodeInfo(code);
|
||||
AddCode(info);
|
||||
}
|
||||
|
||||
void CheatManager::AddProActionRockyCode(uint32_t code)
|
||||
{
|
||||
CodeInfo info = Instance->GetPARCodeInfo(code);
|
||||
Instance->AddCode(info);
|
||||
CodeInfo info = GetPARCodeInfo(code);
|
||||
AddCode(info);
|
||||
}
|
||||
|
||||
void CheatManager::AddCustomCode(uint32_t address, uint8_t value, int32_t compareValue, bool isRelativeAddress)
|
||||
@ -117,29 +115,26 @@ void CheatManager::AddCustomCode(uint32_t address, uint8_t value, int32_t compar
|
||||
code.CompareValue = compareValue;
|
||||
code.IsRelativeAddress = isRelativeAddress;
|
||||
|
||||
Instance->AddCode(code);
|
||||
AddCode(code);
|
||||
}
|
||||
|
||||
void CheatManager::ClearCodes()
|
||||
{
|
||||
bool cheatRemoved = false;
|
||||
Console::Pause();
|
||||
|
||||
for(int i = 0; i <= 0xFFFF; i++) {
|
||||
if(!Instance->_relativeCheatCodes[i]) {
|
||||
if(!_relativeCheatCodes[i]) {
|
||||
cheatRemoved = true;
|
||||
}
|
||||
Instance->_relativeCheatCodes[i] = nullptr;
|
||||
_relativeCheatCodes[i].reset();
|
||||
}
|
||||
|
||||
cheatRemoved |= Instance->_absoluteCheatCodes.size() > 0;
|
||||
Instance->_absoluteCheatCodes.clear();
|
||||
cheatRemoved |= _absoluteCheatCodes.size() > 0;
|
||||
_absoluteCheatCodes.clear();
|
||||
|
||||
if(cheatRemoved) {
|
||||
MessageManager::SendNotification(ConsoleNotificationType::CheatRemoved);
|
||||
}
|
||||
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
void CheatManager::ApplyRamCodes(uint16_t addr, uint8_t &value)
|
||||
@ -182,6 +177,24 @@ vector<CodeInfo> CheatManager::GetCheats()
|
||||
return cheats;
|
||||
}
|
||||
|
||||
void CheatManager::SetCheats(CheatInfo cheats[], uint32_t length)
|
||||
{
|
||||
Console::Pause();
|
||||
|
||||
Instance->ClearCodes();
|
||||
|
||||
for(uint32_t i = 0; i < length; i++) {
|
||||
CheatInfo &cheat = cheats[i];
|
||||
switch(cheat.CheatType) {
|
||||
case CheatType::Custom: Instance->AddCustomCode(cheat.Address, cheat.Value, cheat.UseCompareValue ? cheat.CompareValue : -1, cheat.IsRelativeAddress); break;
|
||||
case CheatType::GameGenie: Instance->AddGameGenieCode(cheat.GameGenieCode); break;
|
||||
case CheatType::ProActionRocky: Instance->AddProActionRockyCode(cheat.ProActionRockyCode); break;
|
||||
}
|
||||
}
|
||||
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
void CheatManager::SetCheats(vector<CodeInfo> &cheats)
|
||||
{
|
||||
//Used by NetPlay
|
||||
|
@ -10,6 +10,25 @@ struct CodeInfo
|
||||
bool IsRelativeAddress;
|
||||
};
|
||||
|
||||
enum class CheatType
|
||||
{
|
||||
GameGenie = 0,
|
||||
ProActionRocky = 1,
|
||||
Custom = 2
|
||||
};
|
||||
|
||||
struct CheatInfo
|
||||
{
|
||||
CheatType CheatType;
|
||||
uint32_t ProActionRockyCode;
|
||||
uint32_t Address;
|
||||
char GameGenieCode[9];
|
||||
uint8_t Value;
|
||||
uint8_t CompareValue;
|
||||
bool UseCompareValue;
|
||||
bool IsRelativeAddress;
|
||||
};
|
||||
|
||||
class CheatManager
|
||||
{
|
||||
private:
|
||||
@ -21,16 +40,18 @@ private:
|
||||
CodeInfo GetGGCodeInfo(string ggCode);
|
||||
CodeInfo GetPARCodeInfo(uint32_t parCode);
|
||||
void AddCode(CodeInfo &code);
|
||||
|
||||
void AddGameGenieCode(string code);
|
||||
void AddProActionRockyCode(uint32_t code);
|
||||
void AddCustomCode(uint32_t address, uint8_t value, int32_t compareValue = -1, bool isRelativeAddress = true);
|
||||
void ClearCodes();
|
||||
|
||||
public:
|
||||
CheatManager();
|
||||
|
||||
static void AddGameGenieCode(string code);
|
||||
static void AddProActionRockyCode(uint32_t code);
|
||||
static void AddCustomCode(uint32_t address, uint8_t value, int32_t compareValue = -1, bool isRelativeAddress = true);
|
||||
static void ClearCodes();
|
||||
static vector<CodeInfo> GetCheats();
|
||||
static void SetCheats(vector<CodeInfo> &cheats);
|
||||
static void SetCheats(CheatInfo cheats[], uint32_t length);
|
||||
|
||||
static void ApplyRamCodes(uint16_t addr, uint8_t &value);
|
||||
static void ApplyPrgCodes(uint8_t *prgRam, uint32_t prgSize);
|
||||
|
@ -41,45 +41,41 @@ namespace Mesen.GUI.Config
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public void ApplyCheat()
|
||||
{
|
||||
switch(CheatType) {
|
||||
case CheatType.Custom:
|
||||
InteropEmu.CheatAddCustom(Address, Value, UseCompareValue ? CompareValue : -1, IsRelativeAddress);
|
||||
break;
|
||||
|
||||
case Config.CheatType.GameGenie:
|
||||
InteropEmu.CheatAddGameGenie(GameGenieCode);
|
||||
break;
|
||||
|
||||
case Config.CheatType.ProActionRocky:
|
||||
InteropEmu.CheatAddProActionRocky(ProActionRockyCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ClearCheats()
|
||||
{
|
||||
InteropEmu.CheatClear();
|
||||
InteropEmu.SetCheats(new InteropCheatInfo[] { }, 0);
|
||||
}
|
||||
|
||||
private InteropCheatInfo ToInterop()
|
||||
{
|
||||
byte[] ggCode = Encoding.UTF8.GetBytes(GameGenieCode ?? "");
|
||||
Array.Resize(ref ggCode, 9);
|
||||
|
||||
return new InteropCheatInfo() {
|
||||
CheatType = CheatType,
|
||||
GameGenieCode = ggCode,
|
||||
ProActionRockyCode = ProActionRockyCode,
|
||||
Address = Address,
|
||||
Value = Value,
|
||||
CompareValue = CompareValue,
|
||||
UseCompareValue = UseCompareValue,
|
||||
IsRelativeAddress = IsRelativeAddress
|
||||
};
|
||||
}
|
||||
|
||||
public static void ApplyCheats()
|
||||
{
|
||||
InteropEmu.CheatClear();
|
||||
|
||||
if(!ConfigManager.Config.DisableAllCheats) {
|
||||
string crc = InteropEmu.GetRomInfo().GetPrgCrcString();
|
||||
int cheatCount = 0;
|
||||
foreach(CheatInfo cheat in ConfigManager.Config.Cheats.Where(c => c.GameCrc == crc)) {
|
||||
if(cheat.Enabled) {
|
||||
cheat.ApplyCheat();
|
||||
cheatCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(cheatCount > 0) {
|
||||
InteropEmu.DisplayMessage("Cheats", cheatCount > 1 ? "CheatsApplied" : "CheatApplied", cheatCount.ToString());
|
||||
InteropCheatInfo[] cheats = ConfigManager.Config.Cheats.Where(c => c.GameCrc == crc).Select(cheat => cheat.ToInterop()).ToArray();
|
||||
InteropEmu.SetCheats(cheats, (UInt32)cheats.Length);
|
||||
|
||||
if(cheats.Length > 0) {
|
||||
InteropEmu.DisplayMessage("Cheats", cheats.Length > 1 ? "CheatsApplied" : "CheatApplied", cheats.Length.ToString());
|
||||
}
|
||||
} else {
|
||||
ClearCheats();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1048,8 +1048,10 @@ namespace Mesen.GUI.Forms
|
||||
_cheatListWindow = new frmCheatList();
|
||||
_cheatListWindow.Show(sender, this);
|
||||
_cheatListWindow.FormClosed += (s, evt) => {
|
||||
_cheatListWindow = null;
|
||||
CheatInfo.ApplyCheats();
|
||||
if(_cheatListWindow.DialogResult == DialogResult.OK) {
|
||||
CheatInfo.ApplyCheats();
|
||||
}
|
||||
_cheatListWindow = null;
|
||||
};
|
||||
} else {
|
||||
_cheatListWindow.Focus();
|
||||
|
@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Forms;
|
||||
|
||||
namespace Mesen.GUI
|
||||
@ -119,10 +120,7 @@ namespace Mesen.GUI
|
||||
[DllImport(DLLPath)] public static extern void VsInsertCoin(UInt32 port);
|
||||
[DllImport(DLLPath)] public static extern void VsSetGameConfig(PpuModel model, VsInputType inputType, byte dipSwitches);
|
||||
|
||||
[DllImport(DLLPath)] public static extern void CheatAddCustom(UInt32 address, Byte value, Int32 compareValue, [MarshalAs(UnmanagedType.I1)]bool isRelativeAddress);
|
||||
[DllImport(DLLPath)] public static extern void CheatAddGameGenie([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(UTF8Marshaler))]string code);
|
||||
[DllImport(DLLPath)] public static extern void CheatAddProActionRocky(UInt32 code);
|
||||
[DllImport(DLLPath)] public static extern void CheatClear();
|
||||
[DllImport(DLLPath)] public static extern void SetCheats([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]InteropCheatInfo[] cheats, UInt32 length);
|
||||
|
||||
[DllImport(DLLPath)] private static extern void SetFlags(EmulationFlags flags);
|
||||
[DllImport(DLLPath)] private static extern void ClearFlags(EmulationFlags flags);
|
||||
@ -701,6 +699,21 @@ namespace Mesen.GUI
|
||||
}
|
||||
};
|
||||
|
||||
public struct InteropCheatInfo
|
||||
{
|
||||
public CheatType CheatType;
|
||||
public UInt32 ProActionRockyCode;
|
||||
public UInt32 Address;
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]
|
||||
public byte[] GameGenieCode;
|
||||
public byte Value;
|
||||
public byte CompareValue;
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool UseCompareValue;
|
||||
[MarshalAs(UnmanagedType.I1)]
|
||||
public bool IsRelativeAddress;
|
||||
}
|
||||
|
||||
public struct InteropBreakpoint
|
||||
{
|
||||
public BreakpointType Type;
|
||||
|
@ -317,10 +317,7 @@ namespace InteropEmu {
|
||||
|
||||
DllExport bool __stdcall RomTestRecording() { return _autoRomTest != nullptr; }
|
||||
|
||||
DllExport void __stdcall CheatAddCustom(uint32_t address, uint8_t value, int32_t compareValue, bool isRelativeAddress) { CheatManager::AddCustomCode(address, value, compareValue, isRelativeAddress); }
|
||||
DllExport void __stdcall CheatAddGameGenie(char* code) { CheatManager::AddGameGenieCode(code); }
|
||||
DllExport void __stdcall CheatAddProActionRocky(uint32_t code) { CheatManager::AddProActionRockyCode(code); }
|
||||
DllExport void __stdcall CheatClear() { CheatManager::ClearCodes(); }
|
||||
DllExport void __stdcall SetCheats(CheatInfo cheats[], uint32_t length) { CheatManager::SetCheats(cheats, length); }
|
||||
|
||||
DllExport void __stdcall SetFlags(EmulationFlags flags) { EmulationSettings::SetFlags(flags); }
|
||||
DllExport void __stdcall ClearFlags(EmulationFlags flags) { EmulationSettings::ClearFlags(flags); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user