ActionReplay: Fix ISOProperties corrupting active code set

ISOProperties loads codes using ActionReplay::LoadCodes which actually applies
the codes to the global state. If a game is running then that games receives
all the codes (and ACTIVE status) from the second game being shown in
ISOProperties which is not desirable.
This commit is contained in:
EmptyChaos
2016-04-19 21:19:31 +00:00
parent 0fa9233c1a
commit 25b072ff2b
9 changed files with 124 additions and 45 deletions

View File

@ -6,6 +6,7 @@
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <functional>
#include <string>
#include <vector>
#include <wx/button.h>
@ -38,12 +39,19 @@
#include "DolphinWX/Cheats/CreateCodeDialog.h"
#include "DolphinWX/Cheats/GeckoCodeDiag.h"
namespace
{
wxDEFINE_EVENT(DOLPHIN_EVT_UPDATE_CHEAT_LIST, wxThreadEvent);
}
wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
: wxDialog(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxDIALOG_NO_PARENT)
{
// Create the GUI controls
Init_ChildControls();
m_ar_callback_token = ActionReplay::RegisterCodeChangeCallback(std::bind(&wxCheatsWindow::OnActionReplayModified, this));
// load codes
UpdateGUI();
@ -54,6 +62,7 @@ wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
wxCheatsWindow::~wxCheatsWindow()
{
ActionReplay::UnregisterCodeChangeCallback(m_ar_callback_token);
main_frame->g_CheatsWindow = nullptr;
}
@ -126,7 +135,7 @@ void wxCheatsWindow::Init_ChildControls()
button_cancel->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this);
Bind(wxEVT_CLOSE_WINDOW, &wxCheatsWindow::OnEvent_Close, this);
Bind(UPDATE_CHEAT_LIST_EVENT, &wxCheatsWindow::OnEvent_CheatsList_Update, this);
Bind(DOLPHIN_EVT_UPDATE_CHEAT_LIST, &wxCheatsWindow::OnEvent_CheatsList_Update, this);
wxStdDialogButtonSizer* const sButtons = new wxStdDialogButtonSizer();
sButtons->AddButton(m_button_apply);
@ -232,24 +241,30 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemToggled(wxCommandEvent& WXUNUSED(eve
{
if ((int)code_index.uiIndex == index)
{
m_ar_ignore_callback = true;
ActionReplay::SetARCode_IsActive(m_checklistbox_cheats_list->IsChecked(index), code_index.index);
}
}
}
void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& event)
void wxCheatsWindow::OnEvent_CheatsList_Update(wxThreadEvent&)
{
if (m_ar_ignore_callback)
{
m_ar_ignore_callback = false;
return;
}
Load_ARCodes();
}
void wxCheatsWindow::OnActionReplayModified()
{
// NOTE: This is an arbitrary thread context
GetEventHandler()->QueueEvent(new wxThreadEvent(DOLPHIN_EVT_UPDATE_CHEAT_LIST));
}
void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
{
// Apply AR Code changes
for (const ARCodeIndex& code_index : m_index_list)
{
ActionReplay::SetARCode_IsActive(m_checklistbox_cheats_list->IsChecked(code_index.uiIndex), code_index.index);
}
// Apply Gecko Code changes
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());
@ -265,11 +280,15 @@ void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
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::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& WXUNUSED(event))

View File

@ -72,6 +72,10 @@ private:
IniFile m_gameini_local;
std::string m_gameini_local_path;
// ActionReplay::UnregisterCodeChangeCallback handle
void* m_ar_callback_token = nullptr;
bool m_ar_ignore_callback = false;
void Init_ChildControls();
void Load_ARCodes();
@ -86,7 +90,8 @@ private:
// Cheats List
void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event);
void OnEvent_CheatsList_ItemToggled(wxCommandEvent& event);
void OnEvent_CheatsList_Update(wxCommandEvent& event);
void OnEvent_CheatsList_Update(wxThreadEvent& event);
void OnActionReplayModified();
// Apply Changes Button
void OnEvent_ApplyChanges_Press(wxCommandEvent& event);

View File

@ -14,9 +14,6 @@
#include "DolphinWX/WxUtils.h"
#include "DolphinWX/Cheats/CreateCodeDialog.h"
// Fired when an ActionReplay code is created.
wxDEFINE_EVENT(UPDATE_CHEAT_LIST_EVENT, wxCommandEvent);
CreateCodeDialog::CreateCodeDialog(wxWindow* const parent, const u32 address)
: wxDialog(parent, wxID_ANY, _("Create AR Code"))
, m_code_address(address)
@ -80,24 +77,21 @@ void CreateCodeDialog::PressOK(wxCommandEvent& ev)
// create the new code
ActionReplay::ARCode new_cheat;
new_cheat.active = false;
new_cheat.user_defined = true;
new_cheat.name = WxStrToStr(code_name);
const ActionReplay::AREntry new_entry(m_code_address, code_value);
new_cheat.ops.push_back(new_entry);
new_cheat.ops.emplace_back(ActionReplay::AREntry(m_code_address, code_value));
ActionReplay::AddCode(new_cheat);
// pretty hacky - add the code to the gameini
// FIXME: The save logic should be ActionReplay since it mirrors the parser
{
CISOProperties isoprops(GameListItem(SConfig::GetInstance().m_LastFilename, std::unordered_map<std::string, std::string>()), this);
CISOProperties isoprops(GameListItem(SConfig::GetInstance().m_LastFilename, {}), this);
// add the code to the isoproperties arcode list
isoprops.AddARCode(new_cheat);
// save the gameini
isoprops.SaveGameConfig();
isoprops.ActionReplayList_Load(); // loads the new arcodes
//ActionReplay::UpdateActiveList();
}
// Propagate back to the parent frame to update the cheat list.
GetEventHandler()->AddPendingEvent(wxCommandEvent(UPDATE_CHEAT_LIST_EVENT));
Close();
}

View File

@ -12,8 +12,6 @@
class wxCheckBox;
class wxTextCtrl;
wxDECLARE_EVENT(UPDATE_CHEAT_LIST_EVENT, wxCommandEvent);
class CreateCodeDialog final : public wxDialog
{
public: