mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
CheatManager/ISOProperties: Refactor ActionReplay tabs as a class
Refactor Action Replay code into its own class like Gecko Codes.
This commit is contained in:
@ -454,7 +454,7 @@ static int alphatobin(u32* dst, const std::vector<std::string>& alpha, int size)
|
|||||||
return ret;
|
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
|
// The almighty buildseeds() function!! without this, the crypto routines are useless
|
||||||
buildseeds();
|
buildseeds();
|
||||||
@ -469,9 +469,9 @@ void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>& ops)
|
|||||||
|
|
||||||
if ((ret = alphatobin(uCodes, vCodes, (int)vCodes.size())))
|
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",
|
PanicAlertT("Action Replay Code Decryption Error:\nParity Check Failed\n\nCulprit Code:\n%s",
|
||||||
vCodes[ret].c_str());
|
vCodes[ret - 1].c_str());
|
||||||
batchdecrypt(uCodes, (u16)vCodes.size() << 1);
|
|
||||||
}
|
}
|
||||||
else if (!batchdecrypt(uCodes, (u16)vCodes.size() << 1))
|
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)
|
for (size_t i = 0; i < (vCodes.size() << 1); i += 2)
|
||||||
{
|
{
|
||||||
AREntry op;
|
ops->emplace_back(uCodes[i], uCodes[i + 1]);
|
||||||
op.cmd_addr = uCodes[i];
|
|
||||||
op.value = uCodes[i + 1];
|
|
||||||
ops.push_back(op);
|
|
||||||
// PanicAlert("Decrypted AR Code without verification code:\n%08X %08X", uCodes[i],
|
// PanicAlert("Decrypted AR Code without verification code:\n%08X %08X", uCodes[i],
|
||||||
// uCodes[i+1]);
|
// uCodes[i+1]);
|
||||||
}
|
}
|
||||||
@ -494,10 +491,7 @@ void DecryptARCode(std::vector<std::string> vCodes, std::vector<AREntry>& ops)
|
|||||||
// Skip passing the verification code back
|
// Skip passing the verification code back
|
||||||
for (size_t i = 2; i < (vCodes.size() << 1); i += 2)
|
for (size_t i = 2; i < (vCodes.size() << 1); i += 2)
|
||||||
{
|
{
|
||||||
AREntry op;
|
ops->emplace_back(uCodes[i], uCodes[i + 1]);
|
||||||
op.cmd_addr = uCodes[i];
|
|
||||||
op.value = uCodes[i + 1];
|
|
||||||
ops.push_back(op);
|
|
||||||
// PanicAlert("Decrypted AR Code:\n%08X %08X", uCodes[i], uCodes[i+1]);
|
// PanicAlert("Decrypted AR Code:\n%08X %08X", uCodes[i], uCodes[i+1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,6 @@
|
|||||||
|
|
||||||
namespace ActionReplay
|
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
|
} // namespace
|
||||||
|
@ -184,7 +184,7 @@ std::vector<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_in
|
|||||||
}
|
}
|
||||||
if (encrypted_lines.size())
|
if (encrypted_lines.size())
|
||||||
{
|
{
|
||||||
DecryptARCode(encrypted_lines, current_code.ops);
|
DecryptARCode(encrypted_lines, ¤t_code.ops);
|
||||||
codes.push_back(current_code);
|
codes.push_back(current_code);
|
||||||
current_code.ops.clear();
|
current_code.ops.clear();
|
||||||
encrypted_lines.clear();
|
encrypted_lines.clear();
|
||||||
@ -242,7 +242,7 @@ std::vector<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_in
|
|||||||
}
|
}
|
||||||
if (encrypted_lines.size())
|
if (encrypted_lines.size())
|
||||||
{
|
{
|
||||||
DecryptARCode(encrypted_lines, current_code.ops);
|
DecryptARCode(encrypted_lines, ¤t_code.ops);
|
||||||
codes.push_back(current_code);
|
codes.push_back(current_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@ struct AREntry
|
|||||||
u32 cmd_addr;
|
u32 cmd_addr;
|
||||||
u32 value;
|
u32 value;
|
||||||
};
|
};
|
||||||
|
constexpr bool operator==(const AREntry& left, const AREntry& right)
|
||||||
|
{
|
||||||
|
return left.cmd_addr == right.cmd_addr && left.value == right.value;
|
||||||
|
}
|
||||||
|
|
||||||
struct ARCode
|
struct ARCode
|
||||||
{
|
{
|
||||||
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
};
|
|
@ -1,7 +1,8 @@
|
|||||||
set(GUI_SRCS
|
set(GUI_SRCS
|
||||||
ARCodeAddEdit.cpp
|
|
||||||
AboutDolphin.cpp
|
AboutDolphin.cpp
|
||||||
ControllerConfigDiag.cpp
|
ControllerConfigDiag.cpp
|
||||||
|
Cheats/ActionReplayCodesPanel.cpp
|
||||||
|
Cheats/ARCodeAddEdit.cpp
|
||||||
Cheats/CheatSearchTab.cpp
|
Cheats/CheatSearchTab.cpp
|
||||||
Cheats/CheatsWindow.cpp
|
Cheats/CheatsWindow.cpp
|
||||||
Cheats/CreateCodeDialog.cpp
|
Cheats/CreateCodeDialog.cpp
|
||||||
|
193
Source/Core/DolphinWX/Cheats/ARCodeAddEdit.cpp
Normal file
193
Source/Core/DolphinWX/Cheats/ARCodeAddEdit.cpp
Normal file
@ -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());
|
||||||
|
}
|
||||||
|
}
|
29
Source/Core/DolphinWX/Cheats/ARCodeAddEdit.h
Normal file
29
Source/Core/DolphinWX/Cheats/ARCodeAddEdit.h
Normal file
@ -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;
|
||||||
|
};
|
291
Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.cpp
Normal file
291
Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.cpp
Normal file
@ -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;
|
||||||
|
}
|
89
Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.h
Normal file
89
Source/Core/DolphinWX/Cheats/ActionReplayCodesPanel.h
Normal file
@ -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);
|
||||||
|
}
|
@ -32,6 +32,7 @@
|
|||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/GeckoCode.h"
|
#include "Core/GeckoCode.h"
|
||||||
#include "Core/GeckoCodeConfig.h"
|
#include "Core/GeckoCodeConfig.h"
|
||||||
|
#include "DolphinWX/Cheats/ActionReplayCodesPanel.h"
|
||||||
#include "DolphinWX/Cheats/CheatSearchTab.h"
|
#include "DolphinWX/Cheats/CheatSearchTab.h"
|
||||||
#include "DolphinWX/Cheats/CheatsWindow.h"
|
#include "DolphinWX/Cheats/CheatsWindow.h"
|
||||||
#include "DolphinWX/Cheats/CreateCodeDialog.h"
|
#include "DolphinWX/Cheats/CreateCodeDialog.h"
|
||||||
@ -58,7 +59,7 @@ wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
|
|||||||
|
|
||||||
// load codes
|
// load codes
|
||||||
UpdateGUI();
|
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));
|
SetSize(wxSize(-1, 600));
|
||||||
Center();
|
Center();
|
||||||
@ -77,31 +78,16 @@ void wxCheatsWindow::Init_ChildControls()
|
|||||||
|
|
||||||
// --- Tabs ---
|
// --- Tabs ---
|
||||||
// Cheats List Tab
|
// 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,
|
m_ar_codes_panel =
|
||||||
wxSize(300, 0), 0, nullptr, wxLB_HSCROLL);
|
new ActionReplayCodesPanel(tab_cheats, ActionReplayCodesPanel::STYLE_SIDE_PANEL |
|
||||||
m_checklistbox_cheats_list->Bind(wxEVT_LISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemSelected,
|
ActionReplayCodesPanel::STYLE_MODIFY_BUTTONS);
|
||||||
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);
|
|
||||||
|
|
||||||
wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxHORIZONTAL);
|
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(m_ar_codes_panel, 1, wxEXPAND | wxALL, 5);
|
||||||
sizer_tab_cheats->Add(sGroupBoxInfo, 0, wxALIGN_LEFT | wxEXPAND | wxALL, 5);
|
|
||||||
|
|
||||||
m_tab_cheats->SetSizerAndFit(sizer_tab_cheats);
|
tab_cheats->SetSizerAndFit(sizer_tab_cheats);
|
||||||
|
|
||||||
// Cheat Search Tab
|
// Cheat Search Tab
|
||||||
wxPanel* const tab_cheat_search = new CheatSearchTab(m_notebook_main);
|
wxPanel* const tab_cheat_search = new CheatSearchTab(m_notebook_main);
|
||||||
@ -134,7 +120,7 @@ void wxCheatsWindow::Init_ChildControls()
|
|||||||
m_tab_log->SetSizerAndFit(sTabLog);
|
m_tab_log->SetSizerAndFit(sTabLog);
|
||||||
|
|
||||||
// Add Tabs to Notebook
|
// 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_geckocode_panel = new Gecko::CodeConfigPanel(m_notebook_main);
|
||||||
m_notebook_main->AddPage(m_geckocode_panel, _("Gecko Codes"));
|
m_notebook_main->AddPage(m_geckocode_panel, _("Gecko Codes"));
|
||||||
m_notebook_main->AddPage(tab_cheat_search, _("Cheat Search"));
|
m_notebook_main->AddPage(tab_cheat_search, _("Cheat Search"));
|
||||||
@ -193,21 +179,17 @@ void wxCheatsWindow::UpdateGUI()
|
|||||||
|
|
||||||
void wxCheatsWindow::Load_ARCodes()
|
void wxCheatsWindow::Load_ARCodes()
|
||||||
{
|
{
|
||||||
m_checklistbox_cheats_list->Clear();
|
|
||||||
|
|
||||||
if (!Core::IsRunning())
|
if (!Core::IsRunning())
|
||||||
return;
|
|
||||||
|
|
||||||
m_checklistbox_cheats_list->Freeze();
|
|
||||||
for (auto& code : ActionReplay::LoadCodes(m_gameini_default, m_gameini_local))
|
|
||||||
{
|
{
|
||||||
CodeData* cd = new CodeData();
|
m_ar_codes_panel->Clear();
|
||||||
cd->code = std::move(code);
|
m_ar_codes_panel->Disable();
|
||||||
int index = m_checklistbox_cheats_list->Append(
|
return;
|
||||||
wxCheckListBox::EscapeMnemonics(StrToWxStr(cd->code.name)), cd);
|
|
||||||
m_checklistbox_cheats_list->Check(index, cd->code.active);
|
|
||||||
}
|
}
|
||||||
m_checklistbox_cheats_list->Thaw();
|
else if (!m_ar_codes_panel->IsEnabled())
|
||||||
|
{
|
||||||
|
m_ar_codes_panel->Enable();
|
||||||
|
}
|
||||||
|
m_ar_codes_panel->LoadCodes(m_gameini_default, m_gameini_local);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCheatsWindow::Load_GeckoCodes()
|
void wxCheatsWindow::Load_GeckoCodes()
|
||||||
@ -220,36 +202,10 @@ void wxCheatsWindow::OnNewARCodeCreated(wxCommandEvent& ev)
|
|||||||
{
|
{
|
||||||
auto code = static_cast<ActionReplay::ARCode*>(ev.GetClientData());
|
auto code = static_cast<ActionReplay::ARCode*>(ev.GetClientData());
|
||||||
ActionReplay::AddCode(*code);
|
ActionReplay::AddCode(*code);
|
||||||
|
m_ar_codes_panel->AppendNewCode(*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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& event)
|
void wxCheatsWindow::OnLocalGameIniModified(wxCommandEvent& ev)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
ev.Skip();
|
ev.Skip();
|
||||||
if (WxStrToStr(ev.GetString()) != m_game_id)
|
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)
|
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
|
// Apply Action Replay code changes
|
||||||
ActionReplay::ApplyCodes(code_vec);
|
ActionReplay::ApplyCodes(m_ar_codes_panel->GetCodes());
|
||||||
|
|
||||||
// Apply Gecko Code changes
|
// Apply Gecko Code changes
|
||||||
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());
|
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());
|
||||||
@ -283,7 +229,7 @@ void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
|
|||||||
// Save gameini, with changed codes
|
// Save gameini, with changed codes
|
||||||
if (m_gameini_local_path.size())
|
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());
|
Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes());
|
||||||
m_gameini_local.Save(m_gameini_local_path);
|
m_gameini_local.Save(m_gameini_local_path);
|
||||||
|
|
||||||
@ -302,9 +248,31 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED(even
|
|||||||
wxBeginBusyCursor();
|
wxBeginBusyCursor();
|
||||||
m_textctrl_log->Freeze();
|
m_textctrl_log->Freeze();
|
||||||
m_textctrl_log->Clear();
|
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())
|
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();
|
m_textctrl_log->Thaw();
|
||||||
wxEndBusyCursor();
|
wxEndBusyCursor();
|
||||||
|
@ -16,18 +16,14 @@
|
|||||||
|
|
||||||
class wxButton;
|
class wxButton;
|
||||||
class wxCheckBox;
|
class wxCheckBox;
|
||||||
class wxCheckListBox;
|
|
||||||
class wxCloseEvent;
|
|
||||||
class wxListBox;
|
|
||||||
class wxNotebook;
|
class wxNotebook;
|
||||||
class wxStaticBox;
|
|
||||||
class wxStaticText;
|
|
||||||
class wxTextCtrl;
|
class wxTextCtrl;
|
||||||
|
|
||||||
namespace Gecko
|
namespace Gecko
|
||||||
{
|
{
|
||||||
class CodeConfigPanel;
|
class CodeConfigPanel;
|
||||||
}
|
}
|
||||||
|
class ActionReplayCodesPanel;
|
||||||
|
|
||||||
wxDECLARE_EVENT(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, wxCommandEvent);
|
wxDECLARE_EVENT(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, wxCommandEvent);
|
||||||
|
|
||||||
@ -45,22 +41,13 @@ private:
|
|||||||
wxButton* m_button_apply;
|
wxButton* m_button_apply;
|
||||||
wxNotebook* m_notebook_main;
|
wxNotebook* m_notebook_main;
|
||||||
|
|
||||||
wxPanel* m_tab_cheats;
|
|
||||||
wxPanel* m_tab_log;
|
wxPanel* m_tab_log;
|
||||||
|
|
||||||
wxCheckBox* m_checkbox_log_ar;
|
wxCheckBox* m_checkbox_log_ar;
|
||||||
|
|
||||||
wxStaticText* m_label_code_name;
|
|
||||||
wxStaticText* m_label_num_codes;
|
|
||||||
|
|
||||||
wxCheckListBox* m_checklistbox_cheats_list;
|
|
||||||
|
|
||||||
wxTextCtrl* m_textctrl_log;
|
wxTextCtrl* m_textctrl_log;
|
||||||
|
|
||||||
wxListBox* m_listbox_codes_list;
|
ActionReplayCodesPanel* m_ar_codes_panel;
|
||||||
|
|
||||||
wxStaticBox* m_groupbox_info;
|
|
||||||
|
|
||||||
Gecko::CodeConfigPanel* m_geckocode_panel;
|
Gecko::CodeConfigPanel* m_geckocode_panel;
|
||||||
IniFile m_gameini_default;
|
IniFile m_gameini_default;
|
||||||
IniFile m_gameini_local;
|
IniFile m_gameini_local;
|
||||||
@ -83,9 +70,8 @@ private:
|
|||||||
void OnEvent_ButtonClose_Press(wxCommandEvent& event);
|
void OnEvent_ButtonClose_Press(wxCommandEvent& event);
|
||||||
void OnEvent_Close(wxCloseEvent& ev);
|
void OnEvent_Close(wxCloseEvent& ev);
|
||||||
|
|
||||||
// Cheats List
|
// Changes to the INI (affects cheat listings)
|
||||||
void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event);
|
void OnLocalGameIniModified(wxCommandEvent& event);
|
||||||
void OnEvent_CheatsList_Update(wxCommandEvent& event);
|
|
||||||
|
|
||||||
// Apply Changes Button
|
// Apply Changes Button
|
||||||
void OnEvent_ApplyChanges_Press(wxCommandEvent& event);
|
void OnEvent_ApplyChanges_Press(wxCommandEvent& event);
|
||||||
|
@ -56,7 +56,8 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AboutDolphin.cpp" />
|
<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\CheatSearchTab.cpp" />
|
||||||
<ClCompile Include="Cheats\CheatsWindow.cpp" />
|
<ClCompile Include="Cheats\CheatsWindow.cpp" />
|
||||||
<ClCompile Include="Cheats\CreateCodeDialog.cpp" />
|
<ClCompile Include="Cheats\CreateCodeDialog.cpp" />
|
||||||
@ -119,6 +120,8 @@
|
|||||||
<ClCompile Include="WxUtils.cpp" />
|
<ClCompile Include="WxUtils.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="Cheats\ActionReplayCodesPanel.h" />
|
||||||
|
<ClInclude Include="Cheats\ARCodeAddEdit.h" />
|
||||||
<ClInclude Include="Config\AdvancedConfigPane.h" />
|
<ClInclude Include="Config\AdvancedConfigPane.h" />
|
||||||
<ClInclude Include="Config\AudioConfigPane.h" />
|
<ClInclude Include="Config\AudioConfigPane.h" />
|
||||||
<ClInclude Include="Config\GameCubeConfigPane.h" />
|
<ClInclude Include="Config\GameCubeConfigPane.h" />
|
||||||
@ -133,7 +136,6 @@
|
|||||||
<ClInclude Include="NetPlay\PadMapDialog.h" />
|
<ClInclude Include="NetPlay\PadMapDialog.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
<ClInclude Include="AboutDolphin.h" />
|
<ClInclude Include="AboutDolphin.h" />
|
||||||
<ClInclude Include="ARCodeAddEdit.h" />
|
|
||||||
<ClInclude Include="Cheats\CheatSearchTab.h" />
|
<ClInclude Include="Cheats\CheatSearchTab.h" />
|
||||||
<ClInclude Include="Cheats\CheatsWindow.h" />
|
<ClInclude Include="Cheats\CheatsWindow.h" />
|
||||||
<ClInclude Include="Cheats\CreateCodeDialog.h" />
|
<ClInclude Include="Cheats\CreateCodeDialog.h" />
|
||||||
|
@ -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">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="GUI">
|
<Filter Include="GUI">
|
||||||
@ -121,9 +121,6 @@
|
|||||||
<ClCompile Include="AboutDolphin.cpp">
|
<ClCompile Include="AboutDolphin.cpp">
|
||||||
<Filter>GUI</Filter>
|
<Filter>GUI</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="ARCodeAddEdit.cpp">
|
|
||||||
<Filter>GUI</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="FifoPlayerDlg.cpp">
|
<ClCompile Include="FifoPlayerDlg.cpp">
|
||||||
<Filter>GUI</Filter>
|
<Filter>GUI</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -202,6 +199,12 @@
|
|||||||
<ClCompile Include="NetPlay\PadMapDialog.cpp">
|
<ClCompile Include="NetPlay\PadMapDialog.cpp">
|
||||||
<Filter>GUI\NetPlay</Filter>
|
<Filter>GUI\NetPlay</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Cheats\ActionReplayCodesPanel.cpp">
|
||||||
|
<Filter>GUI\Cheats</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Cheats\ARCodeAddEdit.cpp">
|
||||||
|
<Filter>GUI\Cheats</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Main.h" />
|
<ClInclude Include="Main.h" />
|
||||||
@ -291,9 +294,6 @@
|
|||||||
<ClInclude Include="AboutDolphin.h">
|
<ClInclude Include="AboutDolphin.h">
|
||||||
<Filter>GUI</Filter>
|
<Filter>GUI</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="ARCodeAddEdit.h">
|
|
||||||
<Filter>GUI</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="FifoPlayerDlg.h">
|
<ClInclude Include="FifoPlayerDlg.h">
|
||||||
<Filter>GUI</Filter>
|
<Filter>GUI</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@ -369,6 +369,12 @@
|
|||||||
<ClInclude Include="NetPlay\PadMapDialog.h">
|
<ClInclude Include="NetPlay\PadMapDialog.h">
|
||||||
<Filter>GUI\NetPlay</Filter>
|
<Filter>GUI\NetPlay</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Cheats\ActionReplayCodesPanel.h">
|
||||||
|
<Filter>GUI\Cheats</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Cheats\ARCodeAddEdit.h">
|
||||||
|
<Filter>GUI\Cheats</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="CMakeLists.txt" />
|
<Text Include="CMakeLists.txt" />
|
||||||
|
@ -54,7 +54,6 @@
|
|||||||
#include "Common/MD5.h"
|
#include "Common/MD5.h"
|
||||||
#include "Common/StringUtil.h"
|
#include "Common/StringUtil.h"
|
||||||
#include "Common/SysConf.h"
|
#include "Common/SysConf.h"
|
||||||
#include "Core/ActionReplay.h"
|
|
||||||
#include "Core/Boot/Boot.h"
|
#include "Core/Boot/Boot.h"
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
#include "Core/GeckoCodeConfig.h"
|
#include "Core/GeckoCodeConfig.h"
|
||||||
@ -64,7 +63,7 @@
|
|||||||
#include "DiscIO/Filesystem.h"
|
#include "DiscIO/Filesystem.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
#include "DiscIO/VolumeCreator.h"
|
#include "DiscIO/VolumeCreator.h"
|
||||||
#include "DolphinWX/ARCodeAddEdit.h"
|
#include "DolphinWX/Cheats/ActionReplayCodesPanel.h"
|
||||||
#include "DolphinWX/Cheats/GeckoCodeDiag.h"
|
#include "DolphinWX/Cheats/GeckoCodeDiag.h"
|
||||||
#include "DolphinWX/Globals.h"
|
#include "DolphinWX/Globals.h"
|
||||||
#include "DolphinWX/ISOFile.h"
|
#include "DolphinWX/ISOFile.h"
|
||||||
@ -79,14 +78,10 @@ EVT_BUTTON(ID_EDITCONFIG, CISOProperties::OnEditConfig)
|
|||||||
EVT_BUTTON(ID_MD5SUMCOMPUTE, CISOProperties::OnComputeMD5Sum)
|
EVT_BUTTON(ID_MD5SUMCOMPUTE, CISOProperties::OnComputeMD5Sum)
|
||||||
EVT_BUTTON(ID_SHOWDEFAULTCONFIG, CISOProperties::OnShowDefaultConfig)
|
EVT_BUTTON(ID_SHOWDEFAULTCONFIG, CISOProperties::OnShowDefaultConfig)
|
||||||
EVT_CHOICE(ID_EMUSTATE, CISOProperties::OnEmustateChanged)
|
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_EDITPATCH, CISOProperties::PatchButtonClicked)
|
||||||
EVT_BUTTON(ID_ADDPATCH, CISOProperties::PatchButtonClicked)
|
EVT_BUTTON(ID_ADDPATCH, CISOProperties::PatchButtonClicked)
|
||||||
EVT_BUTTON(ID_REMOVEPATCH, 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_MENU(IDM_BNRSAVEAS, CISOProperties::OnBannerImageSave)
|
||||||
EVT_TREE_ITEM_RIGHT_CLICK(ID_TREECTRL, CISOProperties::OnRightClickOnTree)
|
EVT_TREE_ITEM_RIGHT_CLICK(ID_TREECTRL, CISOProperties::OnRightClickOnTree)
|
||||||
EVT_MENU(IDM_EXTRACTFILE, CISOProperties::OnExtractFile)
|
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_EXTRACTDOL, CISOProperties::OnExtractDataFromHeader)
|
||||||
EVT_MENU(IDM_CHECKINTEGRITY, CISOProperties::CheckPartitionIntegrity)
|
EVT_MENU(IDM_CHECKINTEGRITY, CISOProperties::CheckPartitionIntegrity)
|
||||||
EVT_CHOICE(ID_LANG, CISOProperties::OnChangeBannerLang)
|
EVT_CHOICE(ID_LANG, CISOProperties::OnChangeBannerLang)
|
||||||
EVT_CHECKLISTBOX(ID_CHEATS_LIST, CISOProperties::OnActionReplayCodeChecked)
|
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
CISOProperties::CISOProperties(const GameListItem& game_list_item, wxWindow* parent, wxWindowID id,
|
CISOProperties::CISOProperties(const GameListItem& game_list_item, wxWindow* parent, wxWindowID id,
|
||||||
@ -476,24 +470,12 @@ void CISOProperties::CreateGUIControls()
|
|||||||
m_PatchPage->SetSizer(sPatchPage);
|
m_PatchPage->SetSizer(sPatchPage);
|
||||||
|
|
||||||
// Action Replay Cheats
|
// Action Replay Cheats
|
||||||
wxBoxSizer* const sCheats = new wxBoxSizer(wxVERTICAL);
|
m_ar_code_panel =
|
||||||
Cheats = new wxCheckListBox(m_CheatPage, ID_CHEATS_LIST, wxDefaultPosition, wxDefaultSize, 0,
|
new ActionReplayCodesPanel(m_CheatPage, ActionReplayCodesPanel::STYLE_MODIFY_BUTTONS);
|
||||||
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);
|
wxBoxSizer* const sCheatPage = new wxBoxSizer(wxVERTICAL);
|
||||||
sCheats->Add(Cheats, 1, wxEXPAND | wxALL, 0);
|
// TODO: Cheat disabled warning.
|
||||||
sCheatButtons->Add(EditCheat, 0, wxEXPAND | wxALL, 0);
|
sCheatPage->Add(m_ar_code_panel, 1, wxEXPAND | wxALL, 5);
|
||||||
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_CheatPage->SetSizer(sCheatPage);
|
m_CheatPage->SetSizer(sCheatPage);
|
||||||
|
|
||||||
wxStaticText* const m_InternalNameText =
|
wxStaticText* const m_InternalNameText =
|
||||||
@ -1131,7 +1113,7 @@ void CISOProperties::LoadGameConfig()
|
|||||||
Convergence->SetValue(iTemp);
|
Convergence->SetValue(iTemp);
|
||||||
|
|
||||||
PatchList_Load();
|
PatchList_Load();
|
||||||
ActionReplayList_Load();
|
m_ar_code_panel->LoadCodes(GameIniDefault, GameIniLocal);
|
||||||
m_geckocode_panel->LoadCodes(GameIniDefault, GameIniLocal, m_open_iso->GetUniqueID());
|
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);
|
SAVE_IF_NOT_DEFAULT("Video_Stereoscopy", "StereoConvergence", Convergence->GetValue(), 0);
|
||||||
|
|
||||||
PatchList_Save();
|
PatchList_Save();
|
||||||
ActionReplayList_Save();
|
m_ar_code_panel->SaveCodes(&GameIniLocal);
|
||||||
Gecko::SaveCodes(GameIniLocal, m_geckocode_panel->GetCodes());
|
Gecko::SaveCodes(GameIniLocal, m_geckocode_panel->GetCodes());
|
||||||
|
|
||||||
bool success = GameIniLocal.Save(GameIniFileLocal);
|
bool success = GameIniLocal.Save(GameIniFileLocal);
|
||||||
@ -1327,11 +1309,8 @@ void CISOProperties::OnShowDefaultConfig(wxCommandEvent& WXUNUSED(event))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CISOProperties::ListSelectionChanged(wxCommandEvent& event)
|
void CISOProperties::PatchListSelectionChanged(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
switch (event.GetId())
|
|
||||||
{
|
|
||||||
case ID_PATCHES_LIST:
|
|
||||||
if (Patches->GetSelection() == wxNOT_FOUND ||
|
if (Patches->GetSelection() == wxNOT_FOUND ||
|
||||||
DefaultPatches.find(Patches->GetString(Patches->GetSelection()).ToStdString()) !=
|
DefaultPatches.find(Patches->GetString(Patches->GetSelection()).ToStdString()) !=
|
||||||
DefaultPatches.end())
|
DefaultPatches.end())
|
||||||
@ -1344,28 +1323,6 @@ void CISOProperties::ListSelectionChanged(wxCommandEvent& event)
|
|||||||
EditPatch->Enable();
|
EditPatch->Enable();
|
||||||
RemovePatch->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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CISOProperties::OnActionReplayCodeChecked(wxCommandEvent& event)
|
|
||||||
{
|
|
||||||
arCodes[event.GetSelection()].active = Cheats->IsChecked(event.GetSelection());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CISOProperties::PatchList_Load()
|
void CISOProperties::PatchList_Load()
|
||||||
@ -1452,67 +1409,6 @@ void CISOProperties::PatchButtonClicked(wxCommandEvent& event)
|
|||||||
RemovePatch->Disable();
|
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)
|
void CISOProperties::OnChangeBannerLang(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
ChangeBannerDetails(OpenGameListItem.GetLanguages()[event.GetSelection()]);
|
ChangeBannerDetails(OpenGameListItem.GetLanguages()[event.GetSelection()]);
|
||||||
|
@ -14,10 +14,8 @@
|
|||||||
#include <wx/treebase.h>
|
#include <wx/treebase.h>
|
||||||
|
|
||||||
#include "Common/IniFile.h"
|
#include "Common/IniFile.h"
|
||||||
#include "Core/ActionReplay.h"
|
|
||||||
#include "DiscIO/Filesystem.h"
|
#include "DiscIO/Filesystem.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
#include "DolphinWX/ARCodeAddEdit.h"
|
|
||||||
#include "DolphinWX/ISOFile.h"
|
#include "DolphinWX/ISOFile.h"
|
||||||
#include "DolphinWX/PatchAddEdit.h"
|
#include "DolphinWX/PatchAddEdit.h"
|
||||||
|
|
||||||
@ -40,6 +38,7 @@ namespace Gecko
|
|||||||
{
|
{
|
||||||
class CodeConfigPanel;
|
class CodeConfigPanel;
|
||||||
}
|
}
|
||||||
|
class ActionReplayCodesPanel;
|
||||||
|
|
||||||
class WiiPartition final : public wxTreeItemData
|
class WiiPartition final : public wxTreeItemData
|
||||||
{
|
{
|
||||||
@ -78,7 +77,6 @@ private:
|
|||||||
std::unique_ptr<DiscIO::IFileSystem> m_filesystem;
|
std::unique_ptr<DiscIO::IFileSystem> m_filesystem;
|
||||||
|
|
||||||
std::vector<PatchEngine::Patch> onFrame;
|
std::vector<PatchEngine::Patch> onFrame;
|
||||||
std::vector<ActionReplay::ARCode> arCodes;
|
|
||||||
PHackData m_PHack_Data;
|
PHackData m_PHack_Data;
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
@ -103,10 +101,6 @@ private:
|
|||||||
wxButton* EditPatch;
|
wxButton* EditPatch;
|
||||||
wxButton* RemovePatch;
|
wxButton* RemovePatch;
|
||||||
|
|
||||||
wxCheckListBox* Cheats;
|
|
||||||
wxButton* EditCheat;
|
|
||||||
wxButton* RemoveCheat;
|
|
||||||
|
|
||||||
wxTextCtrl* m_InternalName;
|
wxTextCtrl* m_InternalName;
|
||||||
wxTextCtrl* m_GameID;
|
wxTextCtrl* m_GameID;
|
||||||
wxTextCtrl* m_Country;
|
wxTextCtrl* m_Country;
|
||||||
@ -126,6 +120,7 @@ private:
|
|||||||
wxTreeCtrl* m_Treectrl;
|
wxTreeCtrl* m_Treectrl;
|
||||||
wxTreeItemId RootId;
|
wxTreeItemId RootId;
|
||||||
|
|
||||||
|
ActionReplayCodesPanel* m_ar_code_panel;
|
||||||
Gecko::CodeConfigPanel* m_geckocode_panel;
|
Gecko::CodeConfigPanel* m_geckocode_panel;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -159,10 +154,6 @@ private:
|
|||||||
ID_EDITPATCH,
|
ID_EDITPATCH,
|
||||||
ID_ADDPATCH,
|
ID_ADDPATCH,
|
||||||
ID_REMOVEPATCH,
|
ID_REMOVEPATCH,
|
||||||
ID_CHEATS_LIST,
|
|
||||||
ID_EDITCHEAT,
|
|
||||||
ID_ADDCHEAT,
|
|
||||||
ID_REMOVECHEAT,
|
|
||||||
ID_GPUDETERMINISM,
|
ID_GPUDETERMINISM,
|
||||||
ID_DEPTHPERCENTAGE,
|
ID_DEPTHPERCENTAGE,
|
||||||
ID_CONVERGENCE,
|
ID_CONVERGENCE,
|
||||||
@ -201,10 +192,8 @@ private:
|
|||||||
void OnEditConfig(wxCommandEvent& event);
|
void OnEditConfig(wxCommandEvent& event);
|
||||||
void OnComputeMD5Sum(wxCommandEvent& event);
|
void OnComputeMD5Sum(wxCommandEvent& event);
|
||||||
void OnShowDefaultConfig(wxCommandEvent& event);
|
void OnShowDefaultConfig(wxCommandEvent& event);
|
||||||
void ListSelectionChanged(wxCommandEvent& event);
|
void PatchListSelectionChanged(wxCommandEvent& event);
|
||||||
void OnActionReplayCodeChecked(wxCommandEvent& event);
|
|
||||||
void PatchButtonClicked(wxCommandEvent& event);
|
void PatchButtonClicked(wxCommandEvent& event);
|
||||||
void ActionReplayButtonClicked(wxCommandEvent& event);
|
|
||||||
void RightClickOnBanner(wxMouseEvent& event);
|
void RightClickOnBanner(wxMouseEvent& event);
|
||||||
void OnBannerImageSave(wxCommandEvent& event);
|
void OnBannerImageSave(wxCommandEvent& event);
|
||||||
void OnRightClickOnTree(wxTreeEvent& event);
|
void OnRightClickOnTree(wxTreeEvent& event);
|
||||||
@ -231,7 +220,6 @@ private:
|
|||||||
std::string game_id;
|
std::string game_id;
|
||||||
|
|
||||||
std::set<std::string> DefaultPatches;
|
std::set<std::string> DefaultPatches;
|
||||||
std::set<std::string> DefaultCheats;
|
|
||||||
|
|
||||||
void LoadGameConfig();
|
void LoadGameConfig();
|
||||||
bool SaveGameConfig();
|
bool SaveGameConfig();
|
||||||
@ -239,8 +227,6 @@ private:
|
|||||||
void GenerateLocalIniModified();
|
void GenerateLocalIniModified();
|
||||||
void PatchList_Load();
|
void PatchList_Load();
|
||||||
void PatchList_Save();
|
void PatchList_Save();
|
||||||
void ActionReplayList_Load();
|
|
||||||
void ActionReplayList_Save();
|
|
||||||
void ChangeBannerDetails(DiscIO::Language language);
|
void ChangeBannerDetails(DiscIO::Language language);
|
||||||
|
|
||||||
long GetElementStyle(const char* section, const char* key);
|
long GetElementStyle(const char* section, const char* key);
|
||||||
|
Reference in New Issue
Block a user