summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorEmptyChaos <EmptyChaos@users.noreply.github.com>2016-07-23 01:05:04 +0000
committerEmptyChaos <EmptyChaos@users.noreply.github.com>2016-08-31 14:32:12 +1000
commit00a4404045d28beef129d027dc9eaae33ab44703 (patch)
tree053dc2a16c1027e358fe4ae089854c72d25fb799 /Source
parentdef0b42fb7002dc14340fa54562dd878c115557e (diff)
CheatManager/ISOProperties: Refactor ActionReplay tabs as a class
Refactor Action Replay code into its own class like Gecko Codes.
Diffstat (limited to 'Source')
-rw-r--r--Source/Core/Core/ARDecrypt.cpp16
-rw-r--r--Source/Core/Core/ARDecrypt.h2
-rw-r--r--Source/Core/Core/ActionReplay.cpp4
-rw-r--r--Source/Core/Core/ActionReplay.h4
-rw-r--r--Source/Core/DolphinWX/ARCodeAddEdit.cpp188
-rw-r--r--Source/Core/DolphinWX/ARCodeAddEdit.h38
-rw-r--r--Source/Core/DolphinWX/CMakeLists.txt3
-rw-r--r--Source/Core/DolphinWX/Cheats/ARCodeAddEdit.cpp193
-rw-r--r--Source/Core/DolphinWX/Cheats/ARCodeAddEdit.h29
-rw-r--r--Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.cpp291
-rw-r--r--Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.h89
-rw-r--r--Source/Core/DolphinWX/Cheats/CheatsWindow.cpp118
-rw-r--r--Source/Core/DolphinWX/Cheats/CheatsWindow.h22
-rw-r--r--Source/Core/DolphinWX/DolphinWX.vcxproj8
-rw-r--r--Source/Core/DolphinWX/DolphinWX.vcxproj.filters22
-rw-r--r--Source/Core/DolphinWX/ISOProperties.cpp146
-rw-r--r--Source/Core/DolphinWX/ISOProperties.h20
17 files changed, 706 insertions, 487 deletions
diff --git a/Source/Core/Core/ARDecrypt.cpp b/Source/Core/Core/ARDecrypt.cpp
index d336ddd276..cb6b393423 100644
--- a/Source/Core/Core/ARDecrypt.cpp
+++ b/Source/Core/Core/ARDecrypt.cpp
@@ -454,7 +454,7 @@ static int alphatobin(u32* dst, const std::vector<std::string>& alpha, int size)
return ret;
}
-void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>& ops)
+void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>* ops)
{
// The almighty buildseeds() function!! without this, the crypto routines are useless
buildseeds();
@@ -469,9 +469,9 @@ void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>& ops)
if ((ret = alphatobin(uCodes, vCodes, (int)vCodes.size())))
{
+ // Return value is index + 1, 0 being the success flag value.
PanicAlertT("Action Replay Code Decryption Error:\nParity Check Failed\n\nCulprit Code:\n%s",
- vCodes[ret].c_str());
- batchdecrypt(uCodes, (u16)vCodes.size() << 1);
+ vCodes[ret - 1].c_str());
}
else if (!batchdecrypt(uCodes, (u16)vCodes.size() << 1))
{
@@ -481,10 +481,7 @@ void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>& ops)
for (size_t i = 0; i < (vCodes.size() << 1); i += 2)
{
- AREntry op;
- op.cmd_addr = uCodes[i];
- op.value = uCodes[i + 1];
- ops.push_back(op);
+ ops->emplace_back(uCodes[i], uCodes[i + 1]);
// PanicAlert("Decrypted AR Code without verification code:\n%08X %08X", uCodes[i],
// uCodes[i+1]);
}
@@ -494,10 +491,7 @@ void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>& ops)
// Skip passing the verification code back
for (size_t i = 2; i < (vCodes.size() << 1); i += 2)
{
- AREntry op;
- op.cmd_addr = uCodes[i];
- op.value = uCodes[i + 1];
- ops.push_back(op);
+ ops->emplace_back(uCodes[i], uCodes[i + 1]);
// PanicAlert("Decrypted AR Code:\n%08X %08X", uCodes[i], uCodes[i+1]);
}
}
diff --git a/Source/Core/Core/ARDecrypt.h b/Source/Core/Core/ARDecrypt.h
index 897ecb19c8..399b5d0dc0 100644
--- a/Source/Core/Core/ARDecrypt.h
+++ b/Source/Core/Core/ARDecrypt.h
@@ -11,6 +11,6 @@
namespace ActionReplay
{
-void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>& ops);
+void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>* ops);
} // namespace
diff --git a/Source/Core/Core/ActionReplay.cpp b/Source/Core/Core/ActionReplay.cpp
index c0055d771b..0e9b8aff15 100644
--- a/Source/Core/Core/ActionReplay.cpp
+++ b/Source/Core/Core/ActionReplay.cpp
@@ -184,7 +184,7 @@ std::vector<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_in
}
if (encrypted_lines.size())
{
- DecryptARCode(encrypted_lines, current_code.ops);
+ DecryptARCode(encrypted_lines, &current_code.ops);
codes.push_back(current_code);
current_code.ops.clear();
encrypted_lines.clear();
@@ -242,7 +242,7 @@ std::vector<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_in
}
if (encrypted_lines.size())
{
- DecryptARCode(encrypted_lines, current_code.ops);
+ DecryptARCode(encrypted_lines, &current_code.ops);
codes.push_back(current_code);
}
}
diff --git a/Source/Core/Core/ActionReplay.h b/Source/Core/Core/ActionReplay.h
index d6f617cd12..2a94018ee3 100644
--- a/Source/Core/Core/ActionReplay.h
+++ b/Source/Core/Core/ActionReplay.h
@@ -19,6 +19,10 @@ struct AREntry
u32 cmd_addr;
u32 value;
};
+constexpr bool operator==(const AREntry& left, const AREntry& right)
+{
+ return left.cmd_addr == right.cmd_addr && left.value == right.value;
+}
struct ARCode
{
diff --git a/Source/Core/DolphinWX/ARCodeAddEdit.cpp b/Source/Core/DolphinWX/ARCodeAddEdit.cpp
deleted file mode 100644
index c756b00d02..0000000000
--- a/Source/Core/DolphinWX/ARCodeAddEdit.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <cstddef>
-#include <cstdlib>
-#include <string>
-#include <vector>
-#include <wx/dialog.h>
-#include <wx/gbsizer.h>
-#include <wx/msgdlg.h>
-#include <wx/sizer.h>
-#include <wx/spinbutt.h>
-#include <wx/stattext.h>
-#include <wx/textctrl.h>
-
-#include "Common/CommonTypes.h"
-#include "Common/Logging/Log.h"
-#include "Common/MsgHandler.h"
-#include "Common/StringUtil.h"
-#include "Core/ARDecrypt.h"
-#include "Core/ActionReplay.h"
-#include "DolphinWX/ARCodeAddEdit.h"
-#include "DolphinWX/WxUtils.h"
-
-CARCodeAddEdit::CARCodeAddEdit(int _selection, std::vector<ActionReplay::ARCode>* _arCodes,
- wxWindow* parent, wxWindowID id, const wxString& title,
- const wxPoint& position, const wxSize& size, long style)
- : wxDialog(parent, id, title, position, size, style), arCodes(_arCodes), selection(_selection)
-{
- Bind(wxEVT_BUTTON, &CARCodeAddEdit::SaveCheatData, this, wxID_OK);
-
- ActionReplay::ARCode tempEntries;
- wxString currentName;
-
- if (selection == wxNOT_FOUND)
- {
- tempEntries.name = "";
- }
- else
- {
- currentName = StrToWxStr(arCodes->at(selection).name);
- tempEntries = arCodes->at(selection);
- }
-
- wxBoxSizer* sEditCheat = new wxBoxSizer(wxVERTICAL);
- wxStaticBoxSizer* sbEntry = new wxStaticBoxSizer(wxVERTICAL, this, _("Cheat Code"));
- wxGridBagSizer* sgEntry = new wxGridBagSizer(0, 0);
-
- wxStaticText* EditCheatNameText = new wxStaticText(this, wxID_ANY, _("Name:"));
- wxStaticText* EditCheatCodeText = new wxStaticText(this, wxID_ANY, _("Code:"));
-
- EditCheatName = new wxTextCtrl(this, wxID_ANY, wxEmptyString);
- EditCheatName->SetValue(currentName);
-
- EntrySelection = new wxSpinButton(this);
- EntrySelection->SetRange(1, std::max((int)arCodes->size(), 1));
- EntrySelection->SetValue((int)(arCodes->size() - selection));
- EntrySelection->Bind(wxEVT_SPIN, &CARCodeAddEdit::ChangeEntry, this);
-
- EditCheatCode = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(300, 100),
- wxTE_MULTILINE);
-
- UpdateTextCtrl(tempEntries);
-
- sgEntry->Add(EditCheatNameText, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER | wxALL, 5);
- sgEntry->Add(EditCheatCodeText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER | wxALL, 5);
- sgEntry->Add(EditCheatName, wxGBPosition(0, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
- sgEntry->Add(EntrySelection, wxGBPosition(0, 2), wxGBSpan(2, 1), wxEXPAND | wxALL, 5);
- sgEntry->Add(EditCheatCode, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
- sgEntry->AddGrowableCol(1);
- sgEntry->AddGrowableRow(1);
- sbEntry->Add(sgEntry, 1, wxEXPAND | wxALL);
-
- sEditCheat->Add(sbEntry, 1, wxEXPAND | wxALL, 5);
- sEditCheat->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxALL, 5);
-
- SetSizerAndFit(sEditCheat);
- SetFocus();
-}
-
-void CARCodeAddEdit::ChangeEntry(wxSpinEvent& event)
-{
- ActionReplay::ARCode currentCode = arCodes->at((int)arCodes->size() - event.GetPosition());
- EditCheatName->SetValue(StrToWxStr(currentCode.name));
- UpdateTextCtrl(currentCode);
-}
-
-void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED(event))
-{
- std::vector<ActionReplay::AREntry> decryptedLines;
- std::vector<std::string> encryptedLines;
-
- // Split the entered cheat into lines.
- std::vector<std::string> userInputLines;
- SplitString(WxStrToStr(EditCheatCode->GetValue()), '\n', userInputLines);
-
- for (size_t i = 0; i < userInputLines.size(); i++)
- {
- // Make sure to ignore unneeded whitespace characters.
- std::string line_str = StripSpaces(userInputLines[i]);
-
- if (line_str == "")
- continue;
-
- // Let's parse the current line. Is it in encrypted or decrypted form?
- std::vector<std::string> pieces;
- SplitString(line_str, ' ', pieces);
-
- if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8)
- {
- // Decrypted code line.
- u32 addr = std::stoul(pieces[0], nullptr, 16);
- u32 value = std::stoul(pieces[1], nullptr, 16);
-
- decryptedLines.emplace_back(addr, value);
- continue;
- }
- else if (pieces.size() == 1)
- {
- SplitString(line_str, '-', pieces);
-
- if (pieces.size() == 3 && pieces[0].size() == 4 && pieces[1].size() == 4 &&
- pieces[2].size() == 5)
- {
- // Encrypted code line. We'll have to decode it later.
- encryptedLines.push_back(pieces[0] + pieces[1] + pieces[2]);
- continue;
- }
- }
-
- // If the above-mentioned conditions weren't met, then something went wrong.
- if (!PanicYesNoT("Unable to parse line %u of the entered AR code as a valid "
- "encrypted or decrypted code. Make sure you typed it correctly.\n"
- "Would you like to ignore this line and continue parsing?",
- (unsigned)(i + 1)))
- {
- return;
- }
- }
-
- // If the entered code was in encrypted form, we decode it here.
- if (encryptedLines.size())
- {
- // TODO: what if both decrypted AND encrypted lines are entered into a single AR code?
- ActionReplay::DecryptARCode(encryptedLines, decryptedLines);
- }
-
- // Codes with no lines appear to be deleted/hidden from the list. Let's prevent that.
- if (!decryptedLines.size())
- {
- WxUtils::ShowErrorDialog(_("The resulting decrypted AR code doesn't contain any lines."));
- return;
- }
-
- if (selection == wxNOT_FOUND)
- {
- // Add a new AR cheat code.
- ActionReplay::ARCode newCheat;
-
- newCheat.name = WxStrToStr(EditCheatName->GetValue());
- newCheat.ops = decryptedLines;
- newCheat.active = true;
- newCheat.user_defined = true;
-
- arCodes->push_back(newCheat);
- }
- else
- {
- // Update the currently-selected AR cheat code.
- arCodes->at(selection).name = WxStrToStr(EditCheatName->GetValue());
- arCodes->at(selection).ops = decryptedLines;
- }
-
- AcceptAndClose();
-}
-
-void CARCodeAddEdit::UpdateTextCtrl(ActionReplay::ARCode arCode)
-{
- EditCheatCode->Clear();
-
- if (arCode.name != "")
- {
- for (auto& op : arCode.ops)
- EditCheatCode->AppendText(wxString::Format("%08X %08X\n", op.cmd_addr, op.value));
- }
-}
diff --git a/Source/Core/DolphinWX/ARCodeAddEdit.h b/Source/Core/DolphinWX/ARCodeAddEdit.h
deleted file mode 100644
index 5377276f63..0000000000
--- a/Source/Core/DolphinWX/ARCodeAddEdit.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2008 Dolphin Emulator Project
-// Licensed under GPLv2+
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <wx/dialog.h>
-
-class wxSpinButton;
-class wxSpinEvent;
-class wxTextCtrl;
-
-namespace ActionReplay
-{
-struct ARCode;
-}
-
-class CARCodeAddEdit : public wxDialog
-{
-public:
- CARCodeAddEdit(int _selection, std::vector<ActionReplay::ARCode>* _arCodes, wxWindow* parent,
- wxWindowID id = wxID_ANY, const wxString& title = _("Edit ActionReplay Code"),
- const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
- long style = wxDEFAULT_DIALOG_STYLE);
-
-private:
- wxTextCtrl* EditCheatName;
- wxSpinButton* EntrySelection;
- wxTextCtrl* EditCheatCode;
-
- std::vector<ActionReplay::ARCode>* arCodes;
-
- void SaveCheatData(wxCommandEvent& event);
- void ChangeEntry(wxSpinEvent& event);
- void UpdateTextCtrl(ActionReplay::ARCode arCode);
-
- int selection;
-};
diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt
index 9e89e73987..fc6a786a7f 100644
--- a/Source/Core/DolphinWX/CMakeLists.txt
+++ b/Source/Core/DolphinWX/CMakeLists.txt
@@ -1,7 +1,8 @@
set(GUI_SRCS
- ARCodeAddEdit.cpp
AboutDolphin.cpp
ControllerConfigDiag.cpp
+ Cheats/ActionReplayCodesPanel.cpp
+ Cheats/ARCodeAddEdit.cpp
Cheats/CheatSearchTab.cpp
Cheats/CheatsWindow.cpp
Cheats/CreateCodeDialog.cpp
diff --git a/Source/Core/DolphinWX/Cheats/ARCodeAddEdit.cpp b/Source/Core/DolphinWX/Cheats/ARCodeAddEdit.cpp
new file mode 100644
index 0000000000..3162e52211
--- /dev/null
+++ b/Source/Core/DolphinWX/Cheats/ARCodeAddEdit.cpp
@@ -0,0 +1,193 @@
+// Copyright 2008 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <string>
+#include <utility>
+#include <vector>
+#include <wx/button.h>
+#include <wx/dialog.h>
+#include <wx/gbsizer.h>
+#include <wx/msgdlg.h>
+#include <wx/sizer.h>
+#include <wx/statbox.h>
+#include <wx/stattext.h>
+#include <wx/stockitem.h>
+#include <wx/textctrl.h>
+
+#include "Common/CommonTypes.h"
+#include "Common/StringUtil.h"
+#include "Core/ARDecrypt.h"
+#include "Core/ActionReplay.h"
+#include "DolphinWX/Cheats/ARCodeAddEdit.h"
+#include "DolphinWX/WxUtils.h"
+
+ARCodeAddEdit::ARCodeAddEdit(ActionReplay::ARCode code, wxWindow* parent, wxWindowID id,
+ const wxString& title, const wxPoint& position, const wxSize& size,
+ long style)
+ : wxDialog(parent, id, title, position, size, style), m_code(std::move(code))
+{
+ CreateGUI();
+}
+
+void ARCodeAddEdit::CreateGUI()
+{
+ const int space10 = FromDIP(10);
+ const int space5 = FromDIP(5);
+
+ wxBoxSizer* sEditCheat = new wxBoxSizer(wxVERTICAL);
+ wxStaticBoxSizer* sbEntry = new wxStaticBoxSizer(wxVERTICAL, this, _("Cheat Code"));
+ wxGridBagSizer* sgEntry = new wxGridBagSizer(space10, space10);
+
+ wxStaticText* lbl_cheat_name = new wxStaticText(sbEntry->GetStaticBox(), wxID_ANY, _("Name:"));
+ wxStaticText* lbl_cheat_codes = new wxStaticText(sbEntry->GetStaticBox(), wxID_ANY, _("Code:"));
+
+ m_txt_cheat_name = new wxTextCtrl(sbEntry->GetStaticBox(), wxID_ANY, wxEmptyString);
+ m_txt_cheat_name->SetValue(StrToWxStr(m_code.name));
+
+ m_cheat_codes =
+ new wxTextCtrl(sbEntry->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition,
+ wxDLG_UNIT(this, wxSize(240, 128)), wxTE_MULTILINE);
+ for (const auto& op : m_code.ops)
+ m_cheat_codes->AppendText(wxString::Format("%08X %08X\n", op.cmd_addr, op.value));
+
+ {
+ wxFont font{m_cheat_codes->GetFont()};
+ font.SetFamily(wxFONTFAMILY_TELETYPE);
+#ifdef _WIN32
+ // Windows uses Courier New for monospace even though there are better fonts.
+ font.SetFaceName("Consolas");
+#endif
+ m_cheat_codes->SetFont(font);
+ }
+
+ sgEntry->Add(lbl_cheat_name, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER);
+ sgEntry->Add(lbl_cheat_codes, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER);
+ sgEntry->Add(m_txt_cheat_name, wxGBPosition(0, 1), wxGBSpan(1, 1), wxEXPAND);
+ sgEntry->Add(m_cheat_codes, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND);
+ sgEntry->AddGrowableCol(1);
+ sgEntry->AddGrowableRow(1);
+ sbEntry->Add(sgEntry, 1, wxEXPAND | wxALL, space5);
+
+ // OS X UX: ID_NO becomes "Don't Save" when paired with wxID_SAVE
+ wxStdDialogButtonSizer* buttons = new wxStdDialogButtonSizer();
+ buttons->AddButton(new wxButton(this, wxID_SAVE));
+ buttons->AddButton(new wxButton(this, wxID_NO, wxGetStockLabel(wxID_CANCEL)));
+ buttons->Realize();
+
+ sEditCheat->AddSpacer(space5);
+ sEditCheat->Add(sbEntry, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ sEditCheat->AddSpacer(space10);
+ sEditCheat->Add(buttons, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ sEditCheat->AddSpacer(space5);
+
+ Bind(wxEVT_BUTTON, &ARCodeAddEdit::SaveCheatData, this, wxID_SAVE);
+
+ SetEscapeId(wxID_NO);
+ SetAffirmativeId(wxID_SAVE);
+ SetSizerAndFit(sEditCheat);
+}
+
+void ARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED(event))
+{
+ std::vector<ActionReplay::AREntry> decrypted_lines;
+ std::vector<std::string> encrypted_lines;
+
+ // Split the entered cheat into lines.
+ std::vector<std::string> input_lines;
+ SplitString(WxStrToStr(m_cheat_codes->GetValue()), '\n', input_lines);
+
+ for (size_t i = 0; i < input_lines.size(); i++)
+ {
+ // Make sure to ignore unneeded whitespace characters.
+ std::string line_str = StripSpaces(input_lines[i]);
+
+ if (line_str.empty())
+ continue;
+
+ // Let's parse the current line. Is it in encrypted or decrypted form?
+ std::vector<std::string> pieces;
+ SplitString(line_str, ' ', pieces);
+
+ if (pieces.size() == 2 && pieces[0].size() == 8 && pieces[1].size() == 8)
+ {
+ // Decrypted code line.
+ u32 addr = std::stoul(pieces[0], nullptr, 16);
+ u32 value = std::stoul(pieces[1], nullptr, 16);
+
+ decrypted_lines.emplace_back(addr, value);
+ continue;
+ }
+ else if (pieces.size() == 1)
+ {
+ SplitString(line_str, '-', pieces);
+
+ if (pieces.size() == 3 && pieces[0].size() == 4 && pieces[1].size() == 4 &&
+ pieces[2].size() == 5)
+ {
+ // Encrypted code line. We'll have to decode it later.
+ encrypted_lines.emplace_back(pieces[0] + pieces[1] + pieces[2]);
+ continue;
+ }
+ }
+
+ // If the above-mentioned conditions weren't met, then something went wrong.
+ if (wxMessageBox(
+ wxString::Format(_("Unable to parse line %u of the entered AR code as a valid "
+ "encrypted or decrypted code. Make sure you typed it correctly.\n\n"
+ "Would you like to ignore this line and continue parsing?"),
+ (unsigned)(i + 1)),
+ _("Parsing Error"), wxYES_NO | wxICON_ERROR, this) == wxNO)
+ {
+ return;
+ }
+ }
+
+ // If the entered code was in encrypted form, we decode it here.
+ if (!encrypted_lines.empty())
+ {
+ // If the code contains a mixture of encrypted and unencrypted lines then we can't process it.
+ int mode = wxYES;
+ if (!decrypted_lines.empty())
+ {
+ mode =
+ wxMessageBox(_("This Action Replay code contains both encrypted and unencrypted lines; "
+ "you should check that you have entered it correctly.\n\n"
+ "Do you want to discard all unencrypted lines?"),
+ _("Invalid Mixed Code"), wxYES_NO | wxCANCEL | wxICON_ERROR, this);
+ // YES = Discard the unencrypted lines then decrypt the encrypted ones instead.
+ // NO = Discard the encrypted lines, keep the unencrypted ones
+ // CANCEL = Stop and let the user go back to editing
+ if (mode == wxCANCEL)
+ return;
+ if (mode == wxYES)
+ decrypted_lines.clear();
+ }
+
+ if (mode == wxYES)
+ ActionReplay::DecryptARCode(encrypted_lines, &decrypted_lines);
+ }
+
+ // There's no point creating a code with no content.
+ if (decrypted_lines.empty())
+ {
+ WxUtils::ShowErrorDialog(_("The resulting decrypted AR code doesn't contain any lines."));
+ return;
+ }
+
+ ActionReplay::ARCode new_code;
+ new_code.name = WxStrToStr(m_txt_cheat_name->GetValue());
+ new_code.ops = std::move(decrypted_lines);
+ new_code.active = true;
+ new_code.user_defined = true;
+
+ if (new_code.name != m_code.name || new_code.ops != m_code.ops)
+ {
+ m_code = std::move(new_code);
+ AcceptAndClose();
+ }
+ else
+ {
+ EndDialog(GetEscapeId());
+ }
+}
diff --git a/Source/Core/DolphinWX/Cheats/ARCodeAddEdit.h b/Source/Core/DolphinWX/Cheats/ARCodeAddEdit.h
new file mode 100644
index 0000000000..670da1ae5f
--- /dev/null
+++ b/Source/Core/DolphinWX/Cheats/ARCodeAddEdit.h
@@ -0,0 +1,29 @@
+// Copyright 2008 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <wx/dialog.h>
+
+#include "Core/ActionReplay.h"
+
+class wxTextCtrl;
+
+class ARCodeAddEdit final : public wxDialog
+{
+public:
+ ARCodeAddEdit(ActionReplay::ARCode code, wxWindow* parent, wxWindowID id = wxID_ANY,
+ const wxString& title = _("Edit ActionReplay Code"),
+ const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
+ long style = wxDEFAULT_DIALOG_STYLE);
+
+ const ActionReplay::ARCode& GetCode() const { return m_code; }
+private:
+ void CreateGUI();
+ void SaveCheatData(wxCommandEvent& event);
+
+ ActionReplay::ARCode m_code;
+ wxTextCtrl* m_txt_cheat_name;
+ wxTextCtrl* m_cheat_codes;
+};
diff --git a/Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.cpp b/Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.cpp
new file mode 100644
index 0000000000..7d03372ab1
--- /dev/null
+++ b/Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.cpp
@@ -0,0 +1,291 @@
+// Copyright 2016 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <wx/button.h>
+#include <wx/checklst.h>
+#include <wx/font.h>
+#include <wx/listbox.h>
+#include <wx/sizer.h>
+#include <wx/statbox.h>
+#include <wx/stattext.h>
+
+#include "DolphinWX/Cheats/ARCodeAddEdit.h"
+#include "DolphinWX/Cheats/ActionReplayCodesPanel.h"
+#include "DolphinWX/WxUtils.h"
+
+wxDEFINE_EVENT(DOLPHIN_EVT_ARCODE_TOGGLED, wxCommandEvent);
+
+ActionReplayCodesPanel::ActionReplayCodesPanel(wxWindow* parent, Style styles) : wxPanel(parent)
+{
+ SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
+ CreateGUI();
+ SetCodePanelStyle(styles);
+}
+
+ActionReplayCodesPanel::~ActionReplayCodesPanel()
+{
+}
+
+void ActionReplayCodesPanel::LoadCodes(const IniFile& global_ini, const IniFile& local_ini)
+{
+ m_codes = ActionReplay::LoadCodes(global_ini, local_ini);
+ m_was_modified = false;
+ Repopulate();
+}
+
+void ActionReplayCodesPanel::SaveCodes(IniFile* local_ini)
+{
+ ActionReplay::SaveCodes(local_ini, m_codes);
+ m_was_modified = false;
+}
+
+void ActionReplayCodesPanel::AppendNewCode(const ActionReplay::ARCode& code)
+{
+ m_codes.push_back(code);
+ int idx = m_checklist_cheats->Append(m_checklist_cheats->EscapeMnemonics(StrToWxStr(code.name)));
+ if (code.active)
+ m_checklist_cheats->Check(idx);
+ m_was_modified = true;
+ GenerateToggleEvent(code);
+}
+
+void ActionReplayCodesPanel::Clear()
+{
+ m_was_modified = false;
+ m_codes.clear();
+ m_codes.shrink_to_fit();
+ Repopulate();
+}
+
+void ActionReplayCodesPanel::SetCodePanelStyle(Style styles)
+{
+ m_styles = styles;
+ m_side_panel->GetStaticBox()->Show(!!(styles & STYLE_SIDE_PANEL));
+ m_modify_buttons->Show(!!(styles & STYLE_MODIFY_BUTTONS));
+ UpdateSidePanel();
+ UpdateModifyButtons();
+ Layout();
+}
+
+void ActionReplayCodesPanel::CreateGUI()
+{
+ // STYLE_LIST
+ m_checklist_cheats = new wxCheckListBox(this, wxID_ANY);
+
+ // STYLE_SIDE_PANEL
+ m_side_panel = new wxStaticBoxSizer(wxVERTICAL, this, _("Code Info"));
+ m_label_code_name = new wxStaticText(m_side_panel->GetStaticBox(), wxID_ANY, _("Name: "),
+ wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
+ m_label_num_codes =
+ new wxStaticText(m_side_panel->GetStaticBox(), wxID_ANY, _("Number of Codes: ") + '0');
+
+ m_list_codes = new wxListBox(m_side_panel->GetStaticBox(), wxID_ANY);
+ {
+ wxFont monospace{m_list_codes->GetFont()};
+ monospace.SetFamily(wxFONTFAMILY_TELETYPE);
+#ifdef _WIN32
+ monospace.SetFaceName("Consolas"); // Windows always uses Courier New
+#endif
+ m_list_codes->SetFont(monospace);
+ }
+
+ const int space5 = FromDIP(5);
+
+ m_side_panel->AddSpacer(space5);
+ m_side_panel->Add(m_label_code_name, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ m_side_panel->AddSpacer(space5);
+ m_side_panel->Add(m_label_num_codes, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ m_side_panel->AddSpacer(space5);
+ m_side_panel->Add(m_list_codes, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ m_side_panel->AddSpacer(space5);
+ m_side_panel->SetMinSize(FromDIP(wxSize(180, -1)));
+
+ // STYLE_MODIFY_BUTTONS
+ m_modify_buttons = new wxPanel(this);
+ wxButton* btn_add_code = new wxButton(m_modify_buttons, wxID_ANY, _("&Add New Code..."));
+ m_btn_edit_code = new wxButton(m_modify_buttons, wxID_ANY, _("&Edit Code..."));
+ m_btn_remove_code = new wxButton(m_modify_buttons, wxID_ANY, _("&Remove Code"));
+
+ wxBoxSizer* button_layout = new wxBoxSizer(wxHORIZONTAL);
+ button_layout->Add(btn_add_code);
+ button_layout->AddStretchSpacer();
+ button_layout->Add(m_btn_edit_code);
+ button_layout->Add(m_btn_remove_code);
+ m_modify_buttons->SetSizer(button_layout);
+
+ // Top level layouts
+ wxBoxSizer* panel_layout = new wxBoxSizer(wxHORIZONTAL);
+ panel_layout->Add(m_checklist_cheats, 1, wxEXPAND);
+ panel_layout->Add(m_side_panel, 0, wxEXPAND | wxLEFT, space5);
+
+ wxBoxSizer* main_layout = new wxBoxSizer(wxVERTICAL);
+ main_layout->Add(panel_layout, 1, wxEXPAND);
+ main_layout->Add(m_modify_buttons, 0, wxEXPAND | wxTOP, space5);
+
+ m_checklist_cheats->Bind(wxEVT_LISTBOX, &ActionReplayCodesPanel::OnCodeSelectionChanged, this);
+ m_checklist_cheats->Bind(wxEVT_LISTBOX_DCLICK, &ActionReplayCodesPanel::OnCodeDoubleClick, this);
+ m_checklist_cheats->Bind(wxEVT_CHECKLISTBOX, &ActionReplayCodesPanel::OnCodeChecked, this);
+ btn_add_code->Bind(wxEVT_BUTTON, &ActionReplayCodesPanel::OnAddNewCodeClick, this);
+ m_btn_edit_code->Bind(wxEVT_BUTTON, &ActionReplayCodesPanel::OnEditCodeClick, this);
+ m_btn_remove_code->Bind(wxEVT_BUTTON, &ActionReplayCodesPanel::OnRemoveCodeClick, this);
+
+ SetSizer(main_layout);
+}
+
+void ActionReplayCodesPanel::Repopulate()
+{
+ // If the code editor is open then it's invalidated now.
+ // (whatever it was doing is no longer relevant)
+ if (m_editor)
+ m_editor->EndModal(wxID_NO);
+
+ m_checklist_cheats->Freeze();
+ m_checklist_cheats->Clear();
+
+ for (const auto& code : m_codes)
+ {
+ int idx =
+ m_checklist_cheats->Append(m_checklist_cheats->EscapeMnemonics(StrToWxStr(code.name)));
+ if (code.active)
+ m_checklist_cheats->Check(idx);
+ }
+ m_checklist_cheats->Thaw();
+
+ // Clear side panel contents since selection is invalidated
+ UpdateSidePanel();
+ UpdateModifyButtons();
+}
+
+void ActionReplayCodesPanel::UpdateSidePanel()
+{
+ if (!(m_styles & STYLE_SIDE_PANEL))
+ return;
+
+ wxString name;
+ std::size_t code_count = 0;
+ if (m_checklist_cheats->GetSelection() != wxNOT_FOUND)
+ {
+ auto& code = m_codes.at(m_checklist_cheats->GetSelection());
+ name = StrToWxStr(code.name);
+ code_count = code.ops.size();
+
+ m_list_codes->Freeze();
+ m_list_codes->Clear();
+ for (const auto& entry : code.ops)
+ {
+ m_list_codes->Append(wxString::Format("%08X %08X", entry.cmd_addr, entry.value));
+ }
+ m_list_codes->Thaw();
+ }
+ else
+ {
+ m_list_codes->Clear();
+ }
+
+ m_label_code_name->SetLabelText(_("Name: ") + name);
+ m_label_code_name->Wrap(m_label_code_name->GetSize().GetWidth());
+ m_label_code_name->InvalidateBestSize();
+ m_label_num_codes->SetLabelText(wxString::Format("%s%zu", _("Number of Codes: "), code_count));
+ Layout();
+}
+
+void ActionReplayCodesPanel::UpdateModifyButtons()
+{
+ if (!(m_styles & STYLE_MODIFY_BUTTONS))
+ return;
+
+ bool is_user_defined = true;
+ bool enable_buttons = false;
+ if (m_checklist_cheats->GetSelection() != wxNOT_FOUND)
+ {
+ is_user_defined = m_codes.at(m_checklist_cheats->GetSelection()).user_defined;
+ enable_buttons = true;
+ }
+
+ m_btn_edit_code->SetLabel(is_user_defined ? _("&Edit Code...") : _("Clone and &Edit Code..."));
+ m_btn_edit_code->Enable(enable_buttons);
+ m_btn_remove_code->Enable(enable_buttons && is_user_defined);
+ Layout();
+}
+
+void ActionReplayCodesPanel::GenerateToggleEvent(const ActionReplay::ARCode& code)
+{
+ wxCommandEvent toggle_event{DOLPHIN_EVT_ARCODE_TOGGLED, GetId()};
+ toggle_event.SetClientData(const_cast<ActionReplay::ARCode*>(&code));
+ if (!GetEventHandler()->ProcessEvent(toggle_event))
+ {
+ // Because wxWS_EX_BLOCK_EVENTS affects all events, propagation needs to be done manually.
+ GetParent()->GetEventHandler()->ProcessEvent(toggle_event);
+ }
+}
+
+void ActionReplayCodesPanel::OnCodeChecked(wxCommandEvent& ev)
+{
+ auto& code = m_codes.at(ev.GetSelection());
+ code.active = m_checklist_cheats->IsChecked(ev.GetSelection());
+ m_was_modified = true;
+ GenerateToggleEvent(code);
+}
+
+void ActionReplayCodesPanel::OnCodeSelectionChanged(wxCommandEvent&)
+{
+ UpdateSidePanel();
+ UpdateModifyButtons();
+}
+
+void ActionReplayCodesPanel::OnCodeDoubleClick(wxCommandEvent& ev)
+{
+ if (!(m_styles & STYLE_MODIFY_BUTTONS))
+ return;
+
+ OnEditCodeClick(ev);
+}
+
+void ActionReplayCodesPanel::OnAddNewCodeClick(wxCommandEvent&)
+{
+ ARCodeAddEdit editor{{}, this, wxID_ANY, _("Add ActionReplay Code")};
+ m_editor = &editor;
+ if (editor.ShowModal() == wxID_SAVE)
+ AppendNewCode(editor.GetCode());
+ m_editor = nullptr;
+}
+
+void ActionReplayCodesPanel::OnEditCodeClick(wxCommandEvent&)
+{
+ int idx = m_checklist_cheats->GetSelection();
+ wxASSERT(idx != wxNOT_FOUND);
+ auto& code = m_codes.at(idx);
+ // If the code is from the global INI then we'll have to clone it.
+ if (!code.user_defined)
+ {
+ ARCodeAddEdit editor{code, this, wxID_ANY, _("Duplicate Bundled ActionReplay Code")};
+ m_editor = &editor;
+ if (editor.ShowModal() == wxID_SAVE)
+ AppendNewCode(editor.GetCode());
+ m_editor = nullptr;
+ return;
+ }
+
+ ARCodeAddEdit editor{code, this};
+ m_editor = &editor;
+ if (editor.ShowModal() == wxID_SAVE)
+ {
+ code = editor.GetCode();
+ m_checklist_cheats->SetString(idx, m_checklist_cheats->EscapeMnemonics(StrToWxStr(code.name)));
+ m_checklist_cheats->Check(idx, code.active);
+ m_was_modified = true;
+ UpdateSidePanel();
+ GenerateToggleEvent(code);
+ }
+ m_editor = nullptr;
+}
+
+void ActionReplayCodesPanel::OnRemoveCodeClick(wxCommandEvent&)
+{
+ int idx = m_checklist_cheats->GetSelection();
+ wxASSERT(idx != wxNOT_FOUND);
+ m_codes.erase(m_codes.begin() + idx);
+ m_checklist_cheats->Delete(idx);
+ m_was_modified = true;
+}
diff --git a/Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.h b/Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.h
new file mode 100644
index 0000000000..bdb5370142
--- /dev/null
+++ b/Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.h
@@ -0,0 +1,89 @@
+// Copyright 2016 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <wx/panel.h>
+
+#include "Core/ActionReplay.h"
+
+class wxButton;
+class wxCheckListBox;
+class wxListBox;
+class wxStaticBoxSizer;
+class wxStaticText;
+
+class ARCodeAddEdit;
+class IniFile;
+
+// GetClientData() -> ActionReplay::ARCode* [immutable]
+wxDECLARE_EVENT(DOLPHIN_EVT_ARCODE_TOGGLED, wxCommandEvent);
+
+class ActionReplayCodesPanel final : public wxPanel
+{
+public:
+ enum Style
+ {
+ STYLE_LIST = 0, // Show checklist
+ STYLE_SIDE_PANEL = 1, // Show side panel displaying code content
+ STYLE_MODIFY_BUTTONS = 2 // Show buttons for adding/editing/removing codes
+ };
+
+ explicit ActionReplayCodesPanel(wxWindow* parent, Style styles = STYLE_LIST);
+ ~ActionReplayCodesPanel() override;
+
+ void LoadCodes(const IniFile& global_ini, const IniFile& local_ini);
+ const std::vector<ActionReplay::ARCode>& GetCodes() { return m_codes; }
+ void SaveCodes(IniFile* local_ini);
+ void AppendNewCode(const ActionReplay::ARCode& code);
+ void Clear();
+
+ bool IsModified() const { return m_was_modified; }
+ void ClearModified() { m_was_modified = false; }
+ Style GetCodePanelStyle() const { return m_styles; }
+ void SetCodePanelStyle(Style style);
+
+private:
+ void CreateGUI();
+ void Repopulate();
+ void UpdateSidePanel();
+ void UpdateModifyButtons();
+ void GenerateToggleEvent(const ActionReplay::ARCode& code);
+ void OnCodeSelectionChanged(wxCommandEvent&);
+ void OnCodeChecked(wxCommandEvent&);
+ void OnCodeDoubleClick(wxCommandEvent&);
+ void OnAddNewCodeClick(wxCommandEvent&);
+ void OnEditCodeClick(wxCommandEvent&);
+ void OnRemoveCodeClick(wxCommandEvent&);
+
+ std::vector<ActionReplay::ARCode> m_codes;
+
+ wxStaticText* m_label_code_name = nullptr;
+ wxStaticText* m_label_num_codes = nullptr;
+ wxCheckListBox* m_checklist_cheats = nullptr;
+ wxListBox* m_list_codes = nullptr;
+ wxPanel* m_modify_buttons = nullptr;
+ wxButton* m_btn_edit_code = nullptr;
+ wxButton* m_btn_remove_code = nullptr;
+ wxStaticBoxSizer* m_side_panel = nullptr;
+
+ ARCodeAddEdit* m_editor = nullptr;
+
+ Style m_styles = STYLE_LIST;
+ bool m_was_modified = false;
+};
+
+constexpr ActionReplayCodesPanel::Style operator|(ActionReplayCodesPanel::Style a,
+ ActionReplayCodesPanel::Style b)
+{
+ return static_cast<ActionReplayCodesPanel::Style>(static_cast<int>(a) | b);
+}
+
+constexpr ActionReplayCodesPanel::Style operator&(ActionReplayCodesPanel::Style a,
+ ActionReplayCodesPanel::Style b)
+{
+ return static_cast<ActionReplayCodesPanel::Style>(static_cast<int>(a) & b);
+}
diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp
index ef96aaa601..a6c6bad730 100644
--- a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp
+++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp
@@ -32,6 +32,7 @@
#include "Core/Core.h"
#include "Core/GeckoCode.h"
#include "Core/GeckoCodeConfig.h"
+#include "DolphinWX/Cheats/ActionReplayCodesPanel.h"
#include "DolphinWX/Cheats/CheatSearchTab.h"
#include "DolphinWX/Cheats/CheatsWindow.h"
#include "DolphinWX/Cheats/CreateCodeDialog.h"
@@ -58,7 +59,7 @@ wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
// load codes
UpdateGUI();
- wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnEvent_CheatsList_Update, this);
+ wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnLocalGameIniModified, this);
SetSize(wxSize(-1, 600));
Center();
@@ -77,31 +78,16 @@ void wxCheatsWindow::Init_ChildControls()
// --- Tabs ---
// Cheats List Tab
- m_tab_cheats = new wxPanel(m_notebook_main, wxID_ANY);
+ wxPanel* tab_cheats = new wxPanel(m_notebook_main, wxID_ANY);
- m_checklistbox_cheats_list = new wxCheckListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition,
- wxSize(300, 0), 0, nullptr, wxLB_HSCROLL);
- m_checklistbox_cheats_list->Bind(wxEVT_LISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemSelected,
- this);
-
- m_label_code_name = new wxStaticText(m_tab_cheats, wxID_ANY, _("Name: "), wxDefaultPosition,
- wxDefaultSize, wxST_NO_AUTORESIZE);
- m_groupbox_info = new wxStaticBox(m_tab_cheats, wxID_ANY, _("Code Info"));
-
- m_label_num_codes = new wxStaticText(m_tab_cheats, wxID_ANY, _("Number Of Codes: "));
- m_listbox_codes_list = new wxListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition, wxSize(120, 150),
- 0, nullptr, wxLB_HSCROLL);
-
- wxStaticBoxSizer* sGroupBoxInfo = new wxStaticBoxSizer(m_groupbox_info, wxVERTICAL);
- sGroupBoxInfo->Add(m_label_code_name, 0, wxEXPAND | wxALL, 5);
- sGroupBoxInfo->Add(m_label_num_codes, 0, wxALL, 5);
- sGroupBoxInfo->Add(m_listbox_codes_list, 1, wxALL, 5);
+ m_ar_codes_panel =
+ new ActionReplayCodesPanel(tab_cheats, ActionReplayCodesPanel::STYLE_SIDE_PANEL |
+ ActionReplayCodesPanel::STYLE_MODIFY_BUTTONS);
wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxHORIZONTAL);
- sizer_tab_cheats->Add(m_checklistbox_cheats_list, 1, wxEXPAND | wxTOP | wxBOTTOM | wxLEFT, 10);
- sizer_tab_cheats->Add(sGroupBoxInfo, 0, wxALIGN_LEFT | wxEXPAND | wxALL, 5);
+ sizer_tab_cheats->Add(m_ar_codes_panel, 1, wxEXPAND | wxALL, 5);
- m_tab_cheats->SetSizerAndFit(sizer_tab_cheats);
+ tab_cheats->SetSizerAndFit(sizer_tab_cheats);
// Cheat Search Tab
wxPanel* const tab_cheat_search = new CheatSearchTab(m_notebook_main);
@@ -134,7 +120,7 @@ void wxCheatsWindow::Init_ChildControls()
m_tab_log->SetSizerAndFit(sTabLog);
// Add Tabs to Notebook
- m_notebook_main->AddPage(m_tab_cheats, _("AR Codes"));
+ m_notebook_main->AddPage(tab_cheats, _("AR Codes"));
m_geckocode_panel = new Gecko::CodeConfigPanel(m_notebook_main);
m_notebook_main->AddPage(m_geckocode_panel, _("Gecko Codes"));
m_notebook_main->AddPage(tab_cheat_search, _("Cheat Search"));
@@ -193,21 +179,17 @@ void wxCheatsWindow::UpdateGUI()
void wxCheatsWindow::Load_ARCodes()
{
- m_checklistbox_cheats_list->Clear();
-
if (!Core::IsRunning())
+ {
+ m_ar_codes_panel->Clear();
+ m_ar_codes_panel->Disable();
return;
-
- m_checklistbox_cheats_list->Freeze();
- for (auto& code : ActionReplay::LoadCodes(m_gameini_default, m_gameini_local))
+ }
+ else if (!m_ar_codes_panel->IsEnabled())
{
- CodeData* cd = new CodeData();
- cd->code = std::move(code);
- int index = m_checklistbox_cheats_list->Append(
- wxCheckListBox::EscapeMnemonics(StrToWxStr(cd->code.name)), cd);
- m_checklistbox_cheats_list->Check(index, cd->code.active);
+ m_ar_codes_panel->Enable();
}
- m_checklistbox_cheats_list->Thaw();
+ m_ar_codes_panel->LoadCodes(m_gameini_default, m_gameini_local);
}
void wxCheatsWindow::Load_GeckoCodes()
@@ -220,36 +202,10 @@ void wxCheatsWindow::OnNewARCodeCreated(wxCommandEvent& ev)
{
auto code = static_cast<ActionReplay::ARCode*>(ev.GetClientData());
ActionReplay::AddCode(*code);
-
- CodeData* cd = new CodeData();
- cd->code = *code;
- int idx = m_checklistbox_cheats_list->Append(
- wxCheckListBox::EscapeMnemonics(StrToWxStr(code->name)), cd);
- m_checklistbox_cheats_list->Check(idx, code->active);
+ m_ar_codes_panel->AppendNewCode(*code);
}
-void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& event)
-{
- CodeData* cd = static_cast<CodeData*>(event.GetClientObject());
-
- m_label_code_name->SetLabelText(_("Name: ") + StrToWxStr(cd->code.name));
- m_label_code_name->Wrap(m_label_code_name->GetSize().GetWidth());
- m_label_code_name->InvalidateBestSize();
- m_label_num_codes->SetLabelText(
- wxString::Format("%s%zu", _("Number Of Codes: "), cd->code.ops.size()));
-
- m_listbox_codes_list->Freeze();
- m_listbox_codes_list->Clear();
- for (const ActionReplay::AREntry& entry : cd->code.ops)
- {
- m_listbox_codes_list->Append(wxString::Format("%08x %08x", entry.cmd_addr, entry.value));
- }
- m_listbox_codes_list->Thaw();
-
- m_tab_cheats->Layout();
-}
-
-void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& ev)
+void wxCheatsWindow::OnLocalGameIniModified(wxCommandEvent& ev)
{
ev.Skip();
if (WxStrToStr(ev.GetString()) != m_game_id)
@@ -264,18 +220,8 @@ void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& ev)
void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
{
- // Convert embedded metadata back into ARCode vector and update active states
- std::vector<ActionReplay::ARCode> code_vec;
- code_vec.reserve(m_checklistbox_cheats_list->GetCount());
- for (unsigned int i = 0; i < m_checklistbox_cheats_list->GetCount(); ++i)
- {
- CodeData* cd = static_cast<CodeData*>(m_checklistbox_cheats_list->GetClientObject(i));
- cd->code.active = m_checklistbox_cheats_list->IsChecked(i);
- code_vec.push_back(cd->code);
- }
-
// Apply Action Replay code changes
- ActionReplay::ApplyCodes(code_vec);
+ ActionReplay::ApplyCodes(m_ar_codes_panel->GetCodes());
// Apply Gecko Code changes
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());
@@ -283,7 +229,7 @@ void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
// Save gameini, with changed codes
if (m_gameini_local_path.size())
{
- ActionReplay::SaveCodes(&m_gameini_local, code_vec);
+ m_ar_codes_panel->SaveCodes(&m_gameini_local);
Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes());
m_gameini_local.Save(m_gameini_local_path);
@@ -302,9 +248,31 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED(even
wxBeginBusyCursor();
m_textctrl_log->Freeze();
m_textctrl_log->Clear();
+ // This horrible mess is because the Windows Textbox Widget suffers from
+ // a Shlemiel The Painter problem where it keeps allocating new memory each
+ // time some text is appended then memcpys to the new buffer. This happens
+ // for every single line resulting in the operation taking minutes instead of
+ // seconds.
+ // Why not just append all of the text all at once? Microsoft decided that it
+ // would be clever to accept as much text as will fit in the internal buffer
+ // then silently discard the rest. We have to iteratively append the text over
+ // and over until the internal buffer becomes big enough to hold all of it.
+ // (wxWidgets should have hidden this platform detail but it sucks)
+ wxString super_string;
+ super_string.reserve(1024 * 1024);
for (const std::string& text : ActionReplay::GetSelfLog())
{
- m_textctrl_log->AppendText(StrToWxStr(text));
+ super_string.append(StrToWxStr(text));
+ }
+ while (!super_string.empty())
+ {
+ // Read "GetLastPosition" as "Size", there's no size function.
+ wxTextPos start = m_textctrl_log->GetLastPosition();
+ m_textctrl_log->AppendText(super_string);
+ wxTextPos end = m_textctrl_log->GetLastPosition();
+ if (start == end)
+ break;
+ super_string.erase(0, end - start);
}
m_textctrl_log->Thaw();
wxEndBusyCursor();
diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.h b/Source/Core/DolphinWX/Cheats/CheatsWindow.h
index 252b0c890b..4302cb8af0 100644
--- a/Source/Core/DolphinWX/Cheats/CheatsWindow.h
+++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.h
@@ -16,18 +16,14 @@
class wxButton;
class wxCheckBox;
-class wxCheckListBox;
-class wxCloseEvent;
-class wxListBox;
class wxNotebook;
-class wxStaticBox;
-class wxStaticText;
class wxTextCtrl;
namespace Gecko
{
class CodeConfigPanel;
}
+class ActionReplayCodesPanel;
wxDECLARE_EVENT(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, wxCommandEvent);
@@ -45,22 +41,13 @@ private:
wxButton* m_button_apply;
wxNotebook* m_notebook_main;
- wxPanel* m_tab_cheats;
wxPanel* m_tab_log;
wxCheckBox* m_checkbox_log_ar;
- wxStaticText* m_label_code_name;
- wxStaticText* m_label_num_codes;
-
- wxCheckListBox* m_checklistbox_cheats_list;
-
wxTextCtrl* m_textctrl_log;
- wxListBox* m_listbox_codes_list;
-
- wxStaticBox* m_groupbox_info;
-
+ ActionReplayCodesPanel* m_ar_codes_panel;
Gecko::CodeConfigPanel* m_geckocode_panel;
IniFile m_gameini_default;
IniFile m_gameini_local;
@@ -83,9 +70,8 @@ private:
void OnEvent_ButtonClose_Press(wxCommandEvent& event);
void OnEvent_Close(wxCloseEvent& ev);
- // Cheats List
- void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event);
- void OnEvent_CheatsList_Update(wxCommandEvent& event);
+ // Changes to the INI (affects cheat listings)
+ void OnLocalGameIniModified(wxCommandEvent& event);
// Apply Changes Button
void OnEvent_ApplyChanges_Press(wxCommandEvent& event);
diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj
index 56b5ed630a..0738037a43 100644
--- a/Source/Core/DolphinWX/DolphinWX.vcxproj
+++ b/Source/Core/DolphinWX/DolphinWX.vcxproj
@@ -56,7 +56,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AboutDolphin.cpp" />
- <ClCompile Include="ARCodeAddEdit.cpp" />
+ <ClCompile Include="Cheats\ActionReplayCodesPanel.cpp" />
+ <ClCompile Include="Cheats\ARCodeAddEdit.cpp" />
<ClCompile Include="Cheats\CheatSearchTab.cpp" />
<ClCompile Include="Cheats\CheatsWindow.cpp" />
<ClCompile Include="Cheats\CreateCodeDialog.cpp" />
@@ -119,6 +120,8 @@
<ClCompile Include="WxUtils.cpp" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="Cheats\ActionReplayCodesPanel.h" />
+ <ClInclude Include="Cheats\ARCodeAddEdit.h" />
<ClInclude Include="Config\AdvancedConfigPane.h" />
<ClInclude Include="Config\AudioConfigPane.h" />
<ClInclude Include="Config\GameCubeConfigPane.h" />
@@ -133,7 +136,6 @@
<ClInclude Include="NetPlay\PadMapDialog.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="AboutDolphin.h" />
- <ClInclude Include="ARCodeAddEdit.h" />
<ClInclude Include="Cheats\CheatSearchTab.h" />
<ClInclude Include="Cheats\CheatsWindow.h" />
<ClInclude Include="Cheats\CreateCodeDialog.h" />
@@ -265,4 +267,4 @@
<Message Text="Copy: @(BinaryFiles) -&gt; $(BinaryOutputDir)" Importance="High" />
<Copy SourceFiles="@(BinaryFiles)" DestinationFolder="$(BinaryOutputDir)" />
</Target>
-</Project>
+</Project> \ No newline at end of file
diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters
index 0480ca0de8..b060d540c0 100644
--- a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters
+++ b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="GUI">
@@ -121,9 +121,6 @@
<ClCompile Include="AboutDolphin.cpp">
<Filter>GUI</Filter>
</ClCompile>
- <ClCompile Include="ARCodeAddEdit.cpp">
- <Filter>GUI</Filter>
- </ClCompile>
<ClCompile Include="FifoPlayerDlg.cpp">
<Filter>GUI</Filter>
</ClCompile>
@@ -202,6 +199,12 @@
<ClCompile Include="NetPlay\PadMapDialog.cpp">
<Filter>GUI\NetPlay</Filter>
</ClCompile>
+ <ClCompile Include="Cheats\ActionReplayCodesPanel.cpp">
+ <Filter>GUI\Cheats</Filter>
+ </ClCompile>
+ <ClCompile Include="Cheats\ARCodeAddEdit.cpp">
+ <Filter>GUI\Cheats</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Main.h" />
@@ -291,9 +294,6 @@
<ClInclude Include="AboutDolphin.h">
<Filter>GUI</Filter>
</ClInclude>
- <ClInclude Include="ARCodeAddEdit.h">
- <Filter>GUI</Filter>
- </ClInclude>
<ClInclude Include="FifoPlayerDlg.h">
<Filter>GUI</Filter>
</ClInclude>
@@ -369,6 +369,12 @@
<ClInclude Include="NetPlay\PadMapDialog.h">
<Filter>GUI\NetPlay</Filter>
</ClInclude>
+ <ClInclude Include="Cheats\ActionReplayCodesPanel.h">
+ <Filter>GUI\Cheats</Filter>
+ </ClInclude>
+ <ClInclude Include="Cheats\ARCodeAddEdit.h">
+ <Filter>GUI\Cheats</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />
@@ -381,4 +387,4 @@
<ItemGroup>
<Image Include="$(CoreDir)..\..\Installer\Dolphin.ico" />
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/Source/Core/DolphinWX/ISOProperties.cpp b/Source/Core/DolphinWX/ISOProperties.cpp
index 74352fd5ca..e8b30dddfe 100644
--- a/Source/Core/DolphinWX/ISOProperties.cpp
+++ b/Source/Core/DolphinWX/ISOProperties.cpp
@@ -54,7 +54,6 @@
#include "Common/MD5.h"
#include "Common/StringUtil.h"
#include "Common/SysConf.h"
-#include "Core/ActionReplay.h"
#include "Core/Boot/Boot.h"
#include "Core/ConfigManager.h"
#include "Core/GeckoCodeConfig.h"
@@ -64,7 +63,7 @@
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
#include "DiscIO/VolumeCreator.h"
-#include "DolphinWX/ARCodeAddEdit.h"
+#include "DolphinWX/Cheats/ActionReplayCodesPanel.h"
#include "DolphinWX/Cheats/GeckoCodeDiag.h"
#include "DolphinWX/Globals.h"
#include "DolphinWX/ISOFile.h"
@@ -79,14 +78,10 @@ EVT_BUTTON(ID_EDITCONFIG, CISOProperties::OnEditConfig)
EVT_BUTTON(ID_MD5SUMCOMPUTE, CISOProperties::OnComputeMD5Sum)
EVT_BUTTON(ID_SHOWDEFAULTCONFIG, CISOProperties::OnShowDefaultConfig)
EVT_CHOICE(ID_EMUSTATE, CISOProperties::OnEmustateChanged)
-EVT_LISTBOX(ID_PATCHES_LIST, CISOProperties::ListSelectionChanged)
+EVT_LISTBOX(ID_PATCHES_LIST, CISOProperties::PatchListSelectionChanged)
EVT_BUTTON(ID_EDITPATCH, CISOProperties::PatchButtonClicked)
EVT_BUTTON(ID_ADDPATCH, CISOProperties::PatchButtonClicked)
EVT_BUTTON(ID_REMOVEPATCH, CISOProperties::PatchButtonClicked)
-EVT_LISTBOX(ID_CHEATS_LIST, CISOProperties::ListSelectionChanged)
-EVT_BUTTON(ID_EDITCHEAT, CISOProperties::ActionReplayButtonClicked)
-EVT_BUTTON(ID_ADDCHEAT, CISOProperties::ActionReplayButtonClicked)
-EVT_BUTTON(ID_REMOVECHEAT, CISOProperties::ActionReplayButtonClicked)
EVT_MENU(IDM_BNRSAVEAS, CISOProperties::OnBannerImageSave)
EVT_TREE_ITEM_RIGHT_CLICK(ID_TREECTRL, CISOProperties::OnRightClickOnTree)
EVT_MENU(IDM_EXTRACTFILE, CISOProperties::OnExtractFile)
@@ -96,7 +91,6 @@ EVT_MENU(IDM_EXTRACTAPPLOADER, CISOProperties::OnExtractDataFromHeader)
EVT_MENU(IDM_EXTRACTDOL, CISOProperties::OnExtractDataFromHeader)
EVT_MENU(IDM_CHECKINTEGRITY, CISOProperties::CheckPartitionIntegrity)
EVT_CHOICE(ID_LANG, CISOProperties::OnChangeBannerLang)
-EVT_CHECKLISTBOX(ID_CHEATS_LIST, CISOProperties::OnActionReplayCodeChecked)
END_EVENT_TABLE()
CISOProperties::CISOProperties(const GameListItem& game_list_item, wxWindow* parent, wxWindowID id,
@@ -476,24 +470,12 @@ void CISOProperties::CreateGUIControls()
m_PatchPage->SetSizer(sPatchPage);
// Action Replay Cheats
- wxBoxSizer* const sCheats = new wxBoxSizer(wxVERTICAL);
- Cheats = new wxCheckListBox(m_CheatPage, ID_CHEATS_LIST, wxDefaultPosition, wxDefaultSize, 0,
- nullptr, wxLB_HSCROLL);
- wxBoxSizer* const sCheatButtons = new wxBoxSizer(wxHORIZONTAL);
- EditCheat = new wxButton(m_CheatPage, ID_EDITCHEAT, _("Edit..."));
- wxButton* const AddCheat = new wxButton(m_CheatPage, ID_ADDCHEAT, _("Add..."));
- RemoveCheat = new wxButton(m_CheatPage, ID_REMOVECHEAT, _("Remove"));
- EditCheat->Disable();
- RemoveCheat->Disable();
-
- wxBoxSizer* sCheatPage = new wxBoxSizer(wxVERTICAL);
- sCheats->Add(Cheats, 1, wxEXPAND | wxALL, 0);
- sCheatButtons->Add(EditCheat, 0, wxEXPAND | wxALL, 0);
- sCheatButtons->AddStretchSpacer();
- sCheatButtons->Add(AddCheat, 0, wxEXPAND | wxALL, 0);
- sCheatButtons->Add(RemoveCheat, 0, wxEXPAND | wxALL, 0);
- sCheats->Add(sCheatButtons, 0, wxEXPAND | wxALL, 0);
- sCheatPage->Add(sCheats, 1, wxEXPAND | wxALL, 5);
+ m_ar_code_panel =
+ new ActionReplayCodesPanel(m_CheatPage, ActionReplayCodesPanel::STYLE_MODIFY_BUTTONS);
+
+ wxBoxSizer* const sCheatPage = new wxBoxSizer(wxVERTICAL);
+ // TODO: Cheat disabled warning.
+ sCheatPage->Add(m_ar_code_panel, 1, wxEXPAND | wxALL, 5);
m_CheatPage->SetSizer(sCheatPage);
wxStaticText* const m_InternalNameText =
@@ -1131,7 +1113,7 @@ void CISOProperties::LoadGameConfig()
Convergence->SetValue(iTemp);
PatchList_Load();
- ActionReplayList_Load();
+ m_ar_code_panel->LoadCodes(GameIniDefault, GameIniLocal);
m_geckocode_panel->LoadCodes(GameIniDefault, GameIniLocal, m_open_iso->GetUniqueID());
}
@@ -1217,7 +1199,7 @@ bool CISOProperties::SaveGameConfig()
SAVE_IF_NOT_DEFAULT("Video_Stereoscopy", "StereoConvergence", Convergence->GetValue(), 0);
PatchList_Save();
- ActionReplayList_Save();
+ m_ar_code_panel->SaveCodes(&GameIniLocal);
Gecko::SaveCodes(GameIniLocal, m_geckocode_panel->GetCodes());
bool success = GameIniLocal.Save(GameIniFileLocal);
@@ -1327,45 +1309,20 @@ void CISOProperties::OnShowDefaultConfig(wxCommandEvent& WXUNUSED(event))
}
}
-void CISOProperties::ListSelectionChanged(wxCommandEvent& event)
+void CISOProperties::PatchListSelectionChanged(wxCommandEvent& event)
{
- switch (event.GetId())
+ if (Patches->GetSelection() == wxNOT_FOUND ||
+ DefaultPatches.find(Patches->GetString(Patches->GetSelection()).ToStdString()) !=
+ DefaultPatches.end())
{
- case ID_PATCHES_LIST:
- if (Patches->GetSelection() == wxNOT_FOUND ||
- DefaultPatches.find(Patches->GetString(Patches->GetSelection()).ToStdString()) !=
- DefaultPatches.end())
- {
- EditPatch->Disable();
- RemovePatch->Disable();
- }
- else
- {
- EditPatch->Enable();
- RemovePatch->Enable();
- }
- break;
- case ID_CHEATS_LIST:
- if (Cheats->GetSelection() == wxNOT_FOUND ||
- DefaultCheats.find(
- Cheats->RemoveMnemonics(Cheats->GetString(Cheats->GetSelection())).ToStdString()) !=
- DefaultCheats.end())
- {
- EditCheat->Disable();
- RemoveCheat->Disable();
- }
- else
- {
- EditCheat->Enable();
- RemoveCheat->Enable();
- }
- break;
+ EditPatch->Disable();
+ RemovePatch->Disable();
+ }
+ else
+ {
+ EditPatch->Enable();
+ RemovePatch->Enable();
}
-}
-
-void CISOProperties::OnActionReplayCodeChecked(wxCommandEvent& event)
-{
- arCodes[event.GetSelection()].active = Cheats->IsChecked(event.GetSelection());
}
void CISOProperties::PatchList_Load()
@@ -1452,67 +1409,6 @@ void CISOProperties::PatchButtonClicked(wxCommandEvent& event)
RemovePatch->Disable();
}
-void CISOProperties::ActionReplayList_Load()
-{
- arCodes = ActionReplay::LoadCodes(GameIniDefault, GameIniLocal);
- DefaultCheats.clear();
-
- Cheats->Freeze();
- Cheats->Clear();
- for (const ActionReplay::ARCode& arCode : arCodes)
- {
- int idx = Cheats->Append(Cheats->EscapeMnemonics(StrToWxStr(arCode.name)));
- Cheats->Check(idx, arCode.active);
- if (!arCode.user_defined)
- DefaultCheats.insert(arCode.name);
- }
- Cheats->Thaw();
-}
-
-void CISOProperties::ActionReplayList_Save()
-{
- ActionReplay::SaveCodes(&GameIniLocal, arCodes);
-}
-
-void CISOProperties::ActionReplayButtonClicked(wxCommandEvent& event)
-{
- int selection = Cheats->GetSelection();
-
- switch (event.GetId())
- {
- case ID_EDITCHEAT:
- {
- CARCodeAddEdit dlg(selection, &arCodes, this);
- dlg.ShowModal();
- Raise();
- }
- break;
- case ID_ADDCHEAT:
- {
- CARCodeAddEdit dlg(-1, &arCodes, this, 1, _("Add ActionReplay Code"));
- int res = dlg.ShowModal();
- Raise();
- if (res == wxID_OK)
- {
- Cheats->Append(StrToWxStr(arCodes.back().name));
- Cheats->Check((unsigned int)(arCodes.size() - 1), arCodes.back().active);
- }
- }
- break;
- case ID_REMOVECHEAT:
- arCodes.erase(arCodes.begin() + Cheats->GetSelection());
- Cheats->Delete(Cheats->GetSelection());
- break;
- }
-
- ActionReplayList_Save();
- Cheats->Clear();
- ActionReplayList_Load();
-
- EditCheat->Disable();
- RemoveCheat->Disable();
-}
-
void CISOProperties::OnChangeBannerLang(wxCommandEvent& event)
{
ChangeBannerDetails(OpenGameListItem.GetLanguages()[event.GetSelection()]);
diff --git a/Source/Core/DolphinWX/ISOProperties.h b/Source/Core/DolphinWX/ISOProperties.h
index d3671dc48a..125ff29967 100644
--- a/Source/Core/DolphinWX/ISOProperties.h
+++ b/Source/Core/DolphinWX/ISOProperties.h
@@ -14,10 +14,8 @@
#include <wx/treebase.h>
#include "Common/IniFile.h"
-#include "Core/ActionReplay.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
-#include "DolphinWX/ARCodeAddEdit.h"
#include "DolphinWX/ISOFile.h"
#include "DolphinWX/PatchAddEdit.h"
@@ -40,6 +38,7 @@ namespace Gecko
{
class CodeConfigPanel;
}
+class ActionReplayCodesPanel;
class WiiPartition final : public wxTreeItemData
{
@@ -78,7 +77,6 @@ private:
std::unique_ptr<DiscIO::IFileSystem> m_filesystem;
std::vector<PatchEngine::Patch> onFrame;
- std::vector<ActionReplay::ARCode> arCodes;
PHackData m_PHack_Data;
// Core
@@ -103,10 +101,6 @@ private:
wxButton* EditPatch;
wxButton* RemovePatch;
- wxCheckListBox* Cheats;
- wxButton* EditCheat;
- wxButton* RemoveCheat;
-
wxTextCtrl* m_InternalName;
wxTextCtrl* m_GameID;
wxTextCtrl* m_Country;
@@ -126,6 +120,7 @@ private:
wxTreeCtrl* m_Treectrl;
wxTreeItemId RootId;
+ ActionReplayCodesPanel* m_ar_code_panel;
Gecko::CodeConfigPanel* m_geckocode_panel;
enum
@@ -159,10 +154,6 @@ private:
ID_EDITPATCH,
ID_ADDPATCH,
ID_REMOVEPATCH,
- ID_CHEATS_LIST,
- ID_EDITCHEAT,
- ID_ADDCHEAT,
- ID_REMOVECHEAT,
ID_GPUDETERMINISM,
ID_DEPTHPERCENTAGE,
ID_CONVERGENCE,
@@ -201,10 +192,8 @@ private:
void OnEditConfig(wxCommandEvent& event);
void OnComputeMD5Sum(wxCommandEvent& event);
void OnShowDefaultConfig(wxCommandEvent& event);
- void ListSelectionChanged(wxCommandEvent& event);
- void OnActionReplayCodeChecked(wxCommandEvent& event);
+ void PatchListSelectionChanged(wxCommandEvent& event);
void PatchButtonClicked(wxCommandEvent& event);
- void ActionReplayButtonClicked(wxCommandEvent& event);
void RightClickOnBanner(wxMouseEvent& event);
void OnBannerImageSave(wxCommandEvent& event);
void OnRightClickOnTree(wxTreeEvent& event);
@@ -231,7 +220,6 @@ private:
std::string game_id;
std::set<std::string> DefaultPatches;
- std::set<std::string> DefaultCheats;
void LoadGameConfig();
bool SaveGameConfig();
@@ -239,8 +227,6 @@ private:
void GenerateLocalIniModified();
void PatchList_Load();
void PatchList_Save();
- void ActionReplayList_Load();
- void ActionReplayList_Save();
void ChangeBannerDetails(DiscIO::Language language);
long GetElementStyle(const char* section, const char* key);