Skip to content

Commit

Permalink
Merge pull request #3776 from EmptyChaos/ar-isoprop-corrupt
Browse files Browse the repository at this point in the history
ActionReplay: Fix ISOProperties corrupting active code set
  • Loading branch information
delroth committed Jun 5, 2016
2 parents 96acd3e + 309d0e5 commit c514a48
Show file tree
Hide file tree
Showing 17 changed files with 494 additions and 419 deletions.
361 changes: 187 additions & 174 deletions Source/Core/Core/ActionReplay.cpp

Large diffs are not rendered by default.

18 changes: 10 additions & 8 deletions Source/Core/Core/ActionReplay.h
Expand Up @@ -30,14 +30,16 @@ struct ARCode
};

void RunAllActive();
bool RunCode(const ARCode &arcode);
void LoadCodes(const IniFile &globalini, const IniFile &localIni, bool forceLoad);
void LoadCodes(std::vector<ARCode> &_arCodes, IniFile &globalini, IniFile &localIni);
size_t GetCodeListSize();
ARCode GetARCode(size_t index);
void SetARCode_IsActive(bool active, size_t index);
void UpdateActiveList();

void ApplyCodes(const std::vector<ARCode>& codes);
void AddCode(ARCode new_code);
void LoadAndApplyCodes(const IniFile& global_ini, const IniFile& local_ini);

std::vector<ARCode> LoadCodes(const IniFile& global_ini, const IniFile& local_ini);
void SaveCodes(IniFile* local_ini, const std::vector<ARCode>& codes);

void EnableSelfLogging(bool enable);
const std::vector<std::string> &GetSelfLog();
std::vector<std::string> GetSelfLog();
void ClearSelfLog();
bool IsSelfLogging();
} // namespace
2 changes: 1 addition & 1 deletion Source/Core/Core/PatchEngine.cpp
Expand Up @@ -166,7 +166,7 @@ void LoadPatches()
IniFile localIni = SConfig::GetInstance().LoadLocalGameIni();

LoadPatchSection("OnFrame", onFrame, globalIni, localIni);
ActionReplay::LoadCodes(globalIni, localIni, false);
ActionReplay::LoadAndApplyCodes(globalIni, localIni);

// lil silly
std::vector<Gecko::GeckoCode> gcodes;
Expand Down
1 change: 1 addition & 0 deletions Source/Core/DolphinWX/ARCodeAddEdit.cpp
Expand Up @@ -160,6 +160,7 @@ void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED(event))
newCheat.name = WxStrToStr(EditCheatName->GetValue());
newCheat.ops = decryptedLines;
newCheat.active = true;
newCheat.user_defined = true;

arCodes->push_back(newCheat);
}
Expand Down
1 change: 0 additions & 1 deletion Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp
Expand Up @@ -174,7 +174,6 @@ void CheatSearchTab::OnCreateARCodeClicked(wxCommandEvent&)
const u32 address = m_search_results[idx].address | ((m_search_type_size & ~1) << 24);

CreateCodeDialog arcode_dlg(this, address);
arcode_dlg.SetExtraStyle(arcode_dlg.GetExtraStyle() & ~wxWS_EX_BLOCK_EVENTS);
arcode_dlg.ShowModal();
}

Expand Down
162 changes: 98 additions & 64 deletions Source/Core/DolphinWX/Cheats/CheatsWindow.cpp
Expand Up @@ -7,7 +7,9 @@
#include <cstdio>
#include <cstring>
#include <string>
#include <utility>
#include <vector>
#include <wx/app.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/checklst.h>
Expand All @@ -31,13 +33,21 @@
#include "Core/GeckoCode.h"
#include "Core/GeckoCodeConfig.h"
#include "DolphinWX/Frame.h"
#include "DolphinWX/Globals.h"
#include "DolphinWX/Main.h"
#include "DolphinWX/WxUtils.h"
#include "DolphinWX/Cheats/CheatSearchTab.h"
#include "DolphinWX/Cheats/CheatsWindow.h"
#include "DolphinWX/Cheats/CreateCodeDialog.h"
#include "DolphinWX/Cheats/GeckoCodeDiag.h"

wxDEFINE_EVENT(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, wxCommandEvent);

struct wxCheatsWindow::CodeData : public wxClientData
{
ActionReplay::ARCode code;
};

wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
: wxDialog(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxDIALOG_NO_PARENT)
{
Expand All @@ -46,6 +56,7 @@ wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)

// load codes
UpdateGUI();
wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnEvent_CheatsList_Update, this);

SetSize(wxSize(-1, 600));
Center();
Expand All @@ -66,18 +77,17 @@ void wxCheatsWindow::Init_ChildControls()
// Cheats List Tab
m_tab_cheats = new wxPanel(m_notebook_main, wxID_ANY);

m_checklistbox_cheats_list = new wxCheckListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition, wxSize(300, 0), m_cheat_string_list, wxLB_HSCROLL, wxDefaultValidator);
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_checklistbox_cheats_list->Bind(wxEVT_CHECKLISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemToggled, this);

m_label_code_name = new wxStaticText(m_tab_cheats, wxID_ANY, _("Name: "));
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, wxALL, 5);
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);

Expand All @@ -95,6 +105,8 @@ void wxCheatsWindow::Init_ChildControls()

wxButton* const button_updatelog = new wxButton(m_tab_log, wxID_ANY, _("Update"));
button_updatelog->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonUpdateLog_Press, this);
wxButton* const button_clearlog = new wxButton(m_tab_log, wxID_ANY, _("Clear"));
button_clearlog->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnClearActionReplayLog, this);

m_checkbox_log_ar = new wxCheckBox(m_tab_log, wxID_ANY, _("Enable AR Logging"));
m_checkbox_log_ar->Bind(wxEVT_CHECKBOX, &wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange, this);
Expand All @@ -105,6 +117,7 @@ void wxCheatsWindow::Init_ChildControls()
wxBoxSizer *HStrip1 = new wxBoxSizer(wxHORIZONTAL);
HStrip1->Add(m_checkbox_log_ar, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
HStrip1->Add(button_updatelog, 0, wxALL, 5);
HStrip1->Add(button_clearlog, 0, wxALL, 5);

wxBoxSizer *sTabLog = new wxBoxSizer(wxVERTICAL);
sTabLog->Add(HStrip1, 0, wxALL, 5);
Expand All @@ -119,19 +132,15 @@ void wxCheatsWindow::Init_ChildControls()
m_notebook_main->AddPage(tab_cheat_search, _("Cheat Search"));
m_notebook_main->AddPage(m_tab_log, _("Logging"));

// Button Strip
m_button_apply = new wxButton(this, wxID_APPLY, _("Apply"));
m_button_apply->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this);
wxButton* const button_cancel = new wxButton(this, wxID_CANCEL, _("Cancel"));
button_cancel->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this);

Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this, wxID_APPLY);
Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this, wxID_CANCEL);
Bind(wxEVT_CLOSE_WINDOW, &wxCheatsWindow::OnEvent_Close, this);
Bind(UPDATE_CHEAT_LIST_EVENT, &wxCheatsWindow::OnEvent_CheatsList_Update, this);
Bind(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, &wxCheatsWindow::OnNewARCodeCreated, this);

wxStdDialogButtonSizer* const sButtons = new wxStdDialogButtonSizer();
sButtons->AddButton(m_button_apply);
sButtons->AddButton(button_cancel);
sButtons->Realize();
wxStdDialogButtonSizer* const sButtons = CreateStdDialogButtonSizer(wxAPPLY | wxCANCEL);
m_button_apply = sButtons->GetApplyButton();
SetEscapeId(wxID_CANCEL);
SetAffirmativeId(wxID_CANCEL);

wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL);
sMain->Add(m_notebook_main, 1, wxEXPAND | wxALL, 5);
Expand All @@ -156,7 +165,9 @@ void wxCheatsWindow::UpdateGUI()
const SConfig& parameters = SConfig::GetInstance();
m_gameini_default = parameters.LoadDefaultGameIni();
m_gameini_local = parameters.LoadLocalGameIni();
m_gameini_local_path = File::GetUserPath(D_GAMESETTINGS_IDX) + parameters.GetUniqueID() + ".ini";
m_game_id = parameters.GetUniqueID();
m_game_revision = parameters.m_revision;
m_gameini_local_path = File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini";
Load_ARCodes();
Load_GeckoCodes();

Expand All @@ -167,109 +178,132 @@ void wxCheatsWindow::UpdateGUI()

// write the ISO name in the title
if (Core::IsRunning())
SetTitle(title + ": " + parameters.GetUniqueID() + " - " + parameters.m_strName);
SetTitle(title + StrToWxStr(": " + m_game_id + " - " + parameters.m_strName));
else
SetTitle(title);
}

void wxCheatsWindow::Load_ARCodes()
{
using namespace ActionReplay;

m_checklistbox_cheats_list->Clear();

if (!Core::IsRunning())
return;

m_index_list.clear();
size_t size = GetCodeListSize();
for (size_t i = 0; i < size; i++)
m_checklistbox_cheats_list->Freeze();
for (auto& code : ActionReplay::LoadCodes(m_gameini_default, m_gameini_local))
{
ARCode code = GetARCode(i);
ARCodeIndex ind;
u32 index = m_checklistbox_cheats_list->Append(StrToWxStr(code.name));
m_checklistbox_cheats_list->Check(index, code.active);
ind.index = i;
ind.uiIndex = index;
m_index_list.push_back(ind);
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_checklistbox_cheats_list->Thaw();
}

void wxCheatsWindow::Load_GeckoCodes()
{
m_geckocode_panel->LoadCodes(m_gameini_default, m_gameini_local, SConfig::GetInstance().GetUniqueID(), true);
}

void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED(event))
void wxCheatsWindow::OnNewARCodeCreated(wxCommandEvent& ev)
{
using namespace ActionReplay;

int index = m_checklistbox_cheats_list->GetSelection();
for (size_t i = 0; i < m_index_list.size(); i++)
{
if ((int)m_index_list[i].uiIndex == index)
{
ARCode code = GetARCode(i);
m_label_code_name->SetLabel(_("Name: ") + StrToWxStr(code.name));

std::string numcodes = StringFromFormat("Number of Codes: %zu", code.ops.size());
m_label_num_codes->SetLabel(StrToWxStr(numcodes));
m_listbox_codes_list->Clear();

for (const AREntry& entry : code.ops)
{
std::string ops = StringFromFormat("%08x %08x", entry.cmd_addr, entry.value);
m_listbox_codes_list->Append(StrToWxStr(ops));
}
}
}
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);
}

void wxCheatsWindow::OnEvent_CheatsList_ItemToggled(wxCommandEvent& WXUNUSED(event))
void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& event)
{
int index = m_checklistbox_cheats_list->GetSelection();
for (const ARCodeIndex& code_index : m_index_list)
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)
{
if ((int)code_index.uiIndex == index)
{
ActionReplay::SetARCode_IsActive(m_checklistbox_cheats_list->IsChecked(index), code_index.index);
}
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& event)
void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& ev)
{
Load_ARCodes();
ev.Skip();
if (WxStrToStr(ev.GetString()) != m_game_id)
return;
if (m_ignore_ini_callback)
{
m_ignore_ini_callback = false;
return;
}
UpdateGUI();
}

void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
{
// Apply AR Code changes
for (const ARCodeIndex& code_index : m_index_list)
// 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)
{
ActionReplay::SetARCode_IsActive(m_checklistbox_cheats_list->IsChecked(code_index.uiIndex), code_index.index);
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);

// Apply Gecko Code changes
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());

// Save gameini, with changed gecko codes
// Save gameini, with changed codes
if (m_gameini_local_path.size())
{
ActionReplay::SaveCodes(&m_gameini_local, code_vec);
Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes());
m_gameini_local.Save(m_gameini_local_path);

wxCommandEvent ini_changed(DOLPHIN_EVT_LOCAL_INI_CHANGED);
ini_changed.SetString(StrToWxStr(m_game_id));
ini_changed.SetInt(m_game_revision);
m_ignore_ini_callback = true;
wxTheApp->ProcessEvent(ini_changed);
}

ev.Skip();
}

void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED(event))
{
wxBeginBusyCursor();
m_textctrl_log->Freeze();
m_textctrl_log->Clear();
for (const std::string& text : ActionReplay::GetSelfLog())
{
m_textctrl_log->AppendText(StrToWxStr(text));
}
m_textctrl_log->Thaw();
wxEndBusyCursor();
}

void wxCheatsWindow::OnClearActionReplayLog(wxCommandEvent& event)
{
ActionReplay::ClearSelfLog();
OnEvent_ButtonUpdateLog_Press(event);
}

void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& WXUNUSED(event))
Expand Down

0 comments on commit c514a48

Please sign in to comment.