From 81a6259fd1de4bbdfc40ce9ee5a29178d3dab34c Mon Sep 17 00:00:00 2001 From: omegadox Date: Sat, 25 Oct 2008 10:11:35 +0000 Subject: [PATCH] Added option "Enable cheats" to dolphin config and some AR code changes. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@952 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/ActionReplay.cpp | 146 ++++++++++++----------- Source/Core/Core/Src/CoreParameter.h | 1 + Source/Core/DolphinWX/Src/Config.cpp | 2 + Source/Core/DolphinWX/Src/ConfigMain.cpp | 13 +- Source/Core/DolphinWX/Src/ConfigMain.h | 3 + 5 files changed, 94 insertions(+), 71 deletions(-) diff --git a/Source/Core/Core/Src/ActionReplay.cpp b/Source/Core/Core/Src/ActionReplay.cpp index 7966bd8e83..77eb8d46b0 100644 --- a/Source/Core/Core/Src/ActionReplay.cpp +++ b/Source/Core/Core/Src/ActionReplay.cpp @@ -32,11 +32,11 @@ #include "IniFile.h" #include "HW/Memmap.h" #include "ActionReplay.h" +#include "Core.h" namespace { // These should be turned into locals in RunActionReplayCode, and passed as parameters to the others. -static u32 cmd_addr; static u8 cmd; static u32 addr; static u32 data; @@ -46,6 +46,7 @@ static u8 type; static u8 zcode; static bool doFillNSlide = false; static bool doMemoryCopy = false; +static bool fail = false; static u32 addr_last; static u32 val_last; static std::vector::const_iterator iter; @@ -66,6 +67,9 @@ void DoARZeroCode_MemoryCopy(); // Parses the Action Replay section of a game ini file. void LoadActionReplayCodes(IniFile &ini) { + if (!Core::GetStartupParameter().bEnableCheats) + return; // If cheats are off, do not load them + std::vector lines; ARCode currentCode; arCodes.clear(); @@ -76,16 +80,33 @@ void LoadActionReplayCodes(IniFile &ini) for (std::vector::const_iterator it = lines.begin(); it != lines.end(); ++it) { std::string line = *it; - std::vector pieces; + std::vector pieces; + + // Check if the line is a name of the code + if (line[0] == '+' || line[0] == '$') { + if (currentCode.ops.size() > 0) { + arCodes.push_back(currentCode); + currentCode.ops.clear(); + } + currentCode.name = line; + if (line[0] == '+') currentCode.active = true; + else currentCode.active = false; + continue; + } + SplitString(line, " ", pieces); + + // Check if the AR code is decrypted if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8) { - // Smells like a decrypted Action Replay code, great! Decode! AREntry op; - bool success = TryParseUInt(std::string("0x") + pieces[0], &op.cmd_addr); - success |= TryParseUInt(std::string("0x") + pieces[1], &op.value); - if (!success) - PanicAlert("Invalid AR code line: %s", line.c_str()); + bool success_addr = TryParseUInt(std::string("0x") + pieces[0], &op.cmd_addr); + bool success_val = TryParseUInt(std::string("0x") + pieces[1], &op.value); + if (!(success_addr | success_val)) { + PanicAlert("Action Replay Error: invalid AR code line: %s", line.c_str()); + if (!success_addr) PanicAlert("The address is invalid"); + if (!success_val) PanicAlert("The value is invalid"); + } else currentCode.ops.push_back(op); } @@ -97,28 +118,6 @@ void LoadActionReplayCodes(IniFile &ini) // Encrypted AR code PanicAlert("Dolphin does not yet support encrypted AR codes."); } - else if (line.size() > 1) - { - // OK, name line. This is the start of a new code. Push the old one, prepare the new one. - if (currentCode.ops.size()) - arCodes.push_back(currentCode); - currentCode.name = "(invalid)"; - currentCode.ops.clear(); - - if (line[0] == '+') - { - // Active code - name line. - line = StripSpaces(line.substr(1)); - currentCode.name = line; - currentCode.active = true; - } - else - { - // Inactive code. - currentCode.name = line; - currentCode.active = false; - } - } } } @@ -129,26 +128,28 @@ void LoadActionReplayCodes(IniFile &ini) void ActionReplayRunAllActive() { - for (std::vector::const_iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter) - if (iter->active) - RunActionReplayCode(*iter, false); + if (Core::GetStartupParameter().bEnableCheats && !fail) { + for (std::vector::const_iterator iter = arCodes.begin(); iter != arCodes.end(); ++iter) + if (iter->active) + RunActionReplayCode(*iter, false); + } } // The mechanism is slightly different than what the real AR uses, so there may be compatibility problems. // For example, some authors have created codes that add features to AR. Hacks for popular ones can be added here, // but the problem is not generally solvable. +// TODO: what is "nowIsBootup" for? void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) { code = arcode; for (iter = code.ops.begin(); iter != code.ops.end(); ++iter) { - cmd_addr = iter->cmd_addr; cmd = iter->cmd_addr >> 24; addr = iter->cmd_addr; data = iter->value; - subtype = ((cmd_addr >> 30) & 0x03); + subtype = ((addr >> 30) & 0x03); w = (cmd & 0x07); - type = ((cmd_addr >> 27) & 0x07); + type = ((addr >> 27) & 0x07); zcode = ((data >> 29) & 0x07); // Do Fill & Slide @@ -166,11 +167,12 @@ void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) { // ActionReplay program self modification codes if (addr >= 0x00002000 && addr < 0x00003000) { PanicAlert("This action replay simulator does not support codes that modify Action Replay itself."); + fail = true; return; } // skip these weird init lines - if (iter == code.ops.begin() && cmd == 1) continue; + if (iter == code.ops.begin() && cmd == 1) continue; // Zero codes if (addr == 0x0) // Check if the code is a zero code @@ -184,8 +186,9 @@ void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) { break; case 0x03: // Executes all codes in the same row // Todo: Set register 1BB4 to 1 - PanicAlert("Zero code 3 is not supported"); - continue; + PanicAlert("Zero 3 code not supported"); + fail = true; + return; case 0x04: // Fill & Slide or Memory Copy if (((addr >> 25) & 0x03) == 0x3) { doMemoryCopy = true; @@ -199,7 +202,8 @@ void RunActionReplayCode(const ARCode &arcode, bool nowIsBootup) { continue; default: PanicAlert("Zero code unknown to dolphin: %08x",zcode); - continue; + fail = true; + return; } } @@ -229,7 +233,7 @@ void DoARSubtype_RamWriteAndFill() { if (w < 0x8) // Check the value W in 0xZWXXXXXXX { - u32 new_addr = ( (addr & 0x01FFFFFF) | 0x80000000); + u32 new_addr = ((addr & 0x01FFFFFF) | 0x80000000); switch ((addr >> 25) & 0x03) { case 0x00: // Byte write @@ -254,7 +258,9 @@ void DoARSubtype_RamWriteAndFill() Memory::Write_U32(data, new_addr); break; default: - break; // TODO(Omega): maybe add a PanicAlert here? + PanicAlert("Action Replay Error: Invalid size in Ram Write And Fill (%s)",code.name.c_str()); + fail = true; + return; } } } @@ -264,7 +270,7 @@ void DoARSubtype_WriteToPointer() { if (w < 0x8) { - u32 new_addr = ( addr | 0x80000000); + u32 new_addr = ((addr & 0x01FFFFFF) | 0x80000000); switch ((addr >> 25) & 0x03) { case 0x00: // Byte write to pointer [40] @@ -290,8 +296,9 @@ void DoARSubtype_WriteToPointer() break; default: - PanicAlert("AR Method Error (Write To Pointer): w = %08x, addr = %08x", w, addr); - break; + PanicAlert("Action Replay Error: Invalid size in Write To Pointer (%s)",code.name.c_str()); + fail = true; + return; } } } @@ -300,8 +307,8 @@ void DoARSubtype_AddCode() { if (w < 0x8) { - u32 new_addr = ( addr & 0x81FFFFFF); - switch ((addr >> 25) & 0x03) + u32 new_addr = (addr & 0x81FFFFFF); + switch ((new_addr >> 25) & 0x03) { case 0x0: // Byte add Memory::Write_U8(Memory::Read_U8(new_addr) + (data & 0xFF), new_addr); @@ -322,7 +329,9 @@ void DoARSubtype_AddCode() break; } default: - break; + PanicAlert("Action Replay Error: Invalid size in Add Code (%s)",code.name.c_str()); + fail = true; + return; } } } @@ -330,20 +339,12 @@ void DoARSubtype_AddCode() void DoARSubtype_MasterCodeAndWriteToCCXXXXXX() { // code not yet implemented - TODO - - //if (w < 0x8) - //{ - // u32 new_addr = (addr | 0x80000000); - // switch ((new_addr >> 25) & 0x03) - // { - // case 0x2: - // { - - // } - // } - //} + PanicAlert("Action Replay Error: Master Code and Write To CCXXXXXX not implemented (%s)",code.name.c_str()); + fail = true; + return; } +// TODO(Omega): I think this needs cleanup, there might be a better way to code this part void DoARSubtype_Other() { switch (cmd & 0xFE) @@ -407,15 +408,16 @@ void DoARSubtype_Other() break; } default: - PanicAlert("Unknown Action Replay command %02x (%08x %08x)", cmd, iter->cmd_addr, iter->value); - break; + PanicAlert("Action Replay Error: Unknown Action Replay command %02x (%08x %08x)(%s)", cmd, iter->cmd_addr, iter->value, code.name.c_str()); + fail = true; + return; } } void DoARZeroCode_FillAndSlide() { u32 new_addr = (addr_last & 0x81FFFFFF); u8 size = ((new_addr >> 25) & 0x03); - u32 addr_incr; + int addr_incr; u32 val = addr; int val_incr; u8 write_num = ((data & 0x78000) >> 16); // Z2 @@ -449,8 +451,7 @@ void DoARZeroCode_FillAndSlide() Memory::Write_U8(val & 0xFF, new_addr + j); } val += val_incr; - if (val_incr < 0) curr_addr -= addr_incr; - else curr_addr += addr_incr; + curr_addr += addr_incr; } break; case 0x1: // Halfword for(int i=0; i < write_num; i++) { @@ -459,17 +460,19 @@ void DoARZeroCode_FillAndSlide() Memory::Write_U8(val & 0xFFFF, new_addr + j * 2); } val += val_incr; - if (val_incr < 0) curr_addr -= addr_incr; - else curr_addr += addr_incr; + curr_addr += addr_incr; } break; case 0x2: // Word for(int i=0; i < write_num; i++) { Memory::Write_U16(val, new_addr); val += val_incr; - if (val_incr < 0) curr_addr -= addr_incr; - else curr_addr += addr_incr; + curr_addr += addr_incr; } break; - default: break; + default: + PanicAlert("Action Replay Error: Invalid size in Fill and Slide (%s)",code.name.c_str()); + doFillNSlide = false; + fail = true; + return; } doFillNSlide = false; return; @@ -492,4 +495,9 @@ void DoARZeroCode_MemoryCopy() } return; } } + else { + PanicAlert("Action Replay Error: Invalid value (&08x) in Memory Copy (%s)", (data & ~0x7FFF), code.name.c_str()); + fail = true; + return; + } } \ No newline at end of file diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h index f304e10b7c..c77c3d4b1e 100644 --- a/Source/Core/Core/Src/CoreParameter.h +++ b/Source/Core/Core/Src/CoreParameter.h @@ -50,6 +50,7 @@ struct SCoreStartupParameter bool bUseFastMem; bool bLockThreads; bool bOptimizeQuantizers; + bool bEnableCheats; bool bRunCompareServer; bool bRunCompareClient; diff --git a/Source/Core/DolphinWX/Src/Config.cpp b/Source/Core/DolphinWX/Src/Config.cpp index 15e4b1dd5b..8cd9a758c4 100644 --- a/Source/Core/DolphinWX/Src/Config.cpp +++ b/Source/Core/DolphinWX/Src/Config.cpp @@ -72,6 +72,7 @@ void SConfig::SaveSettings() ini.Set("Core", "DefaultGCM", m_LocalCoreStartupParameter.m_strDefaultGCM); ini.Set("Core", "DVDRoot", m_LocalCoreStartupParameter.m_strDVDRoot); ini.Set("Core", "OptimizeQuantizers", m_LocalCoreStartupParameter.bOptimizeQuantizers); + ini.Set("Core", "EnableCheats", m_LocalCoreStartupParameter.bEnableCheats); ini.Set("Core", "SelectedLanguage", m_LocalCoreStartupParameter.SelectedLanguage); ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer); ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient); @@ -128,6 +129,7 @@ void SConfig::LoadSettings() ini.Get("Core", "DefaultGCM", &m_LocalCoreStartupParameter.m_strDefaultGCM); ini.Get("Core", "DVDRoot", &m_LocalCoreStartupParameter.m_strDVDRoot); ini.Get("Core", "OptimizeQuantizers", &m_LocalCoreStartupParameter.bOptimizeQuantizers, true); + ini.Get("Core", "EnableCheats", &m_LocalCoreStartupParameter.bEnableCheats, false); ini.Get("Core", "SelectedLanguage", &m_LocalCoreStartupParameter.SelectedLanguage, 0); ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false); ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 65c6b1aa40..e11ee328a7 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -37,6 +37,7 @@ EVT_CHECKBOX(ID_USEDUALCORE, CConfigMain::UseDualCoreCheck) EVT_CHECKBOX(ID_LOCKTHREADS, CConfigMain::LockThreadsCheck) EVT_CHECKBOX(ID_OPTIMIZEQUANTIZERS, CConfigMain::OptimizeQuantizersCheck) EVT_CHECKBOX(ID_IDLESKIP, CConfigMain::SkipIdleCheck) +EVT_CHECKBOX(ID_ENABLECHEATS, CConfigMain::EnableCheatsCheck) EVT_CHOICE(ID_CONSOLELANG, CConfigMain::ConsoleLangChanged) EVT_LISTBOX(ID_ISOPATHS, CConfigMain::ISOPathsSelectionChanged) EVT_BUTTON(ID_ADDISOPATH, CConfigMain::AddRemoveISOPaths) @@ -109,6 +110,8 @@ void CConfigMain::CreateGUIControls() OptimizeQuantizers->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bOptimizeQuantizers); SkipIdle = new wxCheckBox(GeneralPage, ID_IDLESKIP, wxT("Use idle skipping"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); SkipIdle->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle); + EnableCheats = new wxCheckBox(GeneralPage, ID_ENABLECHEATS, wxT("Enable cheats"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + EnableCheats->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats); wxArrayString arrayStringFor_ConsoleLang; arrayStringFor_ConsoleLang.Add(wxT("English")); arrayStringFor_ConsoleLang.Add(wxT("German")); @@ -127,8 +130,9 @@ void CConfigMain::CreateGUIControls() sGeneral->Add(LockThreads, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5); sGeneral->Add(OptimizeQuantizers, wxGBPosition(4, 0), wxGBSpan(1, 2), wxALL, 5); sGeneral->Add(SkipIdle, wxGBPosition(5, 0), wxGBSpan(1, 2), wxALL, 5); - sGeneral->Add(ConsoleLangText, wxGBPosition(6, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); - sGeneral->Add(ConsoleLang, wxGBPosition(6, 1), wxGBSpan(1, 1), wxALL, 5); + sGeneral->Add(EnableCheats, wxGBPosition(6, 0), wxGBSpan(1, 2), wxALL, 5); + sGeneral->Add(ConsoleLangText, wxGBPosition(7, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxALL, 5); + sGeneral->Add(ConsoleLang, wxGBPosition(7, 1), wxGBSpan(1, 1), wxALL, 5); GeneralPage->SetSizer(sGeneral); sGeneral->Layout(); @@ -272,6 +276,11 @@ void CConfigMain::SkipIdleCheck(wxCommandEvent& WXUNUSED (event)) SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle = SkipIdle->IsChecked(); } +void CConfigMain::EnableCheatsCheck(wxCommandEvent& WXUNUSED (event)) +{ + SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats = EnableCheats->IsChecked(); +} + void CConfigMain::ConsoleLangChanged(wxCommandEvent& WXUNUSED (event)) { SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage = ConsoleLang->GetSelection(); diff --git a/Source/Core/DolphinWX/Src/ConfigMain.h b/Source/Core/DolphinWX/Src/ConfigMain.h index 1d46244f05..f9e0980d63 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.h +++ b/Source/Core/DolphinWX/Src/ConfigMain.h @@ -65,6 +65,7 @@ class CConfigMain wxCheckBox* LockThreads; wxCheckBox* OptimizeQuantizers; wxCheckBox* SkipIdle; + wxCheckBox* EnableCheats; wxStaticText* ConsoleLangText; wxChoice* ConsoleLang; @@ -105,6 +106,7 @@ class CConfigMain ID_LOCKTHREADS, ID_OPTIMIZEQUANTIZERS, ID_IDLESKIP, + ID_ENABLECHEATS, ID_CONSOLELANG_TEXT, ID_CONSOLELANG, ID_ISOPATHS, @@ -142,6 +144,7 @@ class CConfigMain void LockThreadsCheck(wxCommandEvent& event); void OptimizeQuantizersCheck(wxCommandEvent& event); void SkipIdleCheck(wxCommandEvent& event); + void EnableCheatsCheck(wxCommandEvent& event); void ConsoleLangChanged(wxCommandEvent& event); void ISOPathsSelectionChanged(wxCommandEvent& event); void AddRemoveISOPaths(wxCommandEvent& event);