From f0769233e675ae754176f6b516c0f8584bd8b4cf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 18 Oct 2014 17:32:50 -0400 Subject: [PATCH 1/4] DolphinWX: Split cheat window components into their own source files --- Source/Core/DolphinWX/CMakeLists.txt | 6 +- .../Core/DolphinWX/Cheats/CheatSearchTab.cpp | 318 ++++++++ Source/Core/DolphinWX/Cheats/CheatSearchTab.h | 65 ++ Source/Core/DolphinWX/Cheats/CheatsWindow.cpp | 285 ++++++++ Source/Core/DolphinWX/Cheats/CheatsWindow.h | 105 +++ .../DolphinWX/Cheats/CreateCodeDialog.cpp | 109 +++ .../Core/DolphinWX/Cheats/CreateCodeDialog.h | 32 + .../DolphinWX/{ => Cheats}/GeckoCodeDiag.cpp | 2 +- .../DolphinWX/{ => Cheats}/GeckoCodeDiag.h | 0 Source/Core/DolphinWX/CheatsWindow.cpp | 681 ------------------ Source/Core/DolphinWX/CheatsWindow.h | 163 ----- Source/Core/DolphinWX/DolphinWX.vcxproj | 16 +- .../Core/DolphinWX/DolphinWX.vcxproj.filters | 39 +- Source/Core/DolphinWX/FrameTools.cpp | 2 +- Source/Core/DolphinWX/ISOProperties.cpp | 2 +- 15 files changed, 958 insertions(+), 867 deletions(-) create mode 100644 Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp create mode 100644 Source/Core/DolphinWX/Cheats/CheatSearchTab.h create mode 100644 Source/Core/DolphinWX/Cheats/CheatsWindow.cpp create mode 100644 Source/Core/DolphinWX/Cheats/CheatsWindow.h create mode 100644 Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp create mode 100644 Source/Core/DolphinWX/Cheats/CreateCodeDialog.h rename Source/Core/DolphinWX/{ => Cheats}/GeckoCodeDiag.cpp (99%) rename Source/Core/DolphinWX/{ => Cheats}/GeckoCodeDiag.h (100%) delete mode 100644 Source/Core/DolphinWX/CheatsWindow.cpp delete mode 100644 Source/Core/DolphinWX/CheatsWindow.h diff --git a/Source/Core/DolphinWX/CMakeLists.txt b/Source/Core/DolphinWX/CMakeLists.txt index 8a007d059336..8d179653f03b 100644 --- a/Source/Core/DolphinWX/CMakeLists.txt +++ b/Source/Core/DolphinWX/CMakeLists.txt @@ -24,8 +24,11 @@ endif() set(GUI_SRCS ARCodeAddEdit.cpp AboutDolphin.cpp - CheatsWindow.cpp ConfigMain.cpp + Cheats/CheatSearchTab.cpp + Cheats/CheatsWindow.cpp + Cheats/CreateCodeDialog.cpp + Cheats/GeckoCodeDiag.cpp Debugger/BreakpointDlg.cpp Debugger/BreakpointView.cpp Debugger/BreakpointWindow.cpp @@ -47,7 +50,6 @@ set(GUI_SRCS FrameAui.cpp FrameTools.cpp GameListCtrl.cpp - GeckoCodeDiag.cpp HotkeyDlg.cpp ISOFile.cpp ISOProperties.cpp diff --git a/Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp b/Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp new file mode 100644 index 000000000000..49781e826cbf --- /dev/null +++ b/Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp @@ -0,0 +1,318 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common/CommonFuncs.h" +#include "Common/CommonTypes.h" +#include "Common/StringUtil.h" +#include "Core/HW/Memmap.h" +#include "DolphinWX/WxUtils.h" +#include "DolphinWX/Cheats/CheatSearchTab.h" +#include "DolphinWX/Cheats/CreateCodeDialog.h" + +namespace +{ + const int MAX_CHEAT_SEARCH_RESULTS_DISPLAY = 1024; +} + +CheatSearchTab::CheatSearchTab(wxWindow* const parent) + : wxPanel(parent, -1) +{ + // first scan button + m_btn_init_scan = new wxButton(this, -1, _("New Scan")); + m_btn_init_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::StartNewSearch, this); + + // next scan button + m_btn_next_scan = new wxButton(this, -1, _("Next Scan")); + m_btn_next_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::FilterCheatSearchResults, this); + m_btn_next_scan->Disable(); + + // data size radio buttons + m_size_radiobtn.rad_8 = new wxRadioButton(this, -1, _("8 bit"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); + m_size_radiobtn.rad_16 = new wxRadioButton(this, -1, _("16 bit")); + m_size_radiobtn.rad_32 = new wxRadioButton(this, -1, _("32 bit")); + m_size_radiobtn.rad_8->SetValue(true); + + // data sizes groupbox + wxStaticBoxSizer* const sizer_cheat_new_search = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Data Size")); + sizer_cheat_new_search->Add(m_size_radiobtn.rad_8, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5); + sizer_cheat_new_search->Add(m_size_radiobtn.rad_16, 0, wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5); + sizer_cheat_new_search->Add(m_size_radiobtn.rad_32, 0, wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5); + + // result controls + m_lbox_search_results = new wxListBox(this, -1); + m_label_results_count = new wxStaticText(this, -1, _("Count:")); + + // create AR code button + wxButton* const button_cheat_search_copy_address = new wxButton(this, -1, _("Create AR Code")); + button_cheat_search_copy_address->Bind(wxEVT_BUTTON, &CheatSearchTab::CreateARCode, this); + + // results groupbox + wxStaticBoxSizer* const sizer_cheat_search_results = new wxStaticBoxSizer(wxVERTICAL, this, _("Results")); + sizer_cheat_search_results->Add(m_label_results_count, 0, wxALIGN_LEFT | wxALL, 5); + sizer_cheat_search_results->Add(m_lbox_search_results, 1, wxEXPAND | wxALL, 5); + sizer_cheat_search_results->Add(button_cheat_search_copy_address, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5); + + // Search value radio buttons + m_value_x_radiobtn.rad_oldvalue = new wxRadioButton(this, -1, _("Previous Value"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); + m_value_x_radiobtn.rad_uservalue = new wxRadioButton(this, -1, ""); + m_value_x_radiobtn.rad_oldvalue->SetValue(true); + + // search value textbox + m_textctrl_value_x = new wxTextCtrl(this, -1, "0x0", wxDefaultPosition, wxSize(96,-1)); + m_textctrl_value_x->Bind(wxEVT_SET_FOCUS, &CheatSearchTab::ApplyFocus, this); + + wxBoxSizer* const sizer_cheat_filter_text = new wxBoxSizer(wxHORIZONTAL); + sizer_cheat_filter_text->Add(m_value_x_radiobtn.rad_uservalue, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5); + sizer_cheat_filter_text->Add(m_textctrl_value_x, 1, wxALIGN_CENTER_VERTICAL, 5); + + // value groupbox + wxStaticBoxSizer* const sizer_cheat_search_filter_x = new wxStaticBoxSizer(wxVERTICAL, this, _("Value")); + sizer_cheat_search_filter_x->Add(m_value_x_radiobtn.rad_oldvalue, 0, wxLEFT | wxRIGHT | wxBOTTOM, 5); + sizer_cheat_search_filter_x->Add(sizer_cheat_filter_text, 0, wxALL | wxEXPAND, 5); + + // filter types in the compare dropdown + static const wxString searches[] = { + _("Unknown"), + _("Not Equal"), + _("Equal"), + _("Greater Than"), + _("Less Than"), + // TODO: Implement between search. + //_("Between"), + }; + + m_search_type = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, sizeof(searches)/sizeof(*searches), searches); + m_search_type->Select(0); + + wxStaticBoxSizer* const sizer_cheat_search_filter = new wxStaticBoxSizer(wxVERTICAL, this, _("Search Filter")); + sizer_cheat_search_filter->Add(sizer_cheat_search_filter_x, 0, wxALL | wxEXPAND, 5); + sizer_cheat_search_filter->Add(m_search_type, 0, wxALL, 5); + + // left sizer + wxBoxSizer* const sizer_left = new wxBoxSizer(wxVERTICAL); + sizer_left->Add(sizer_cheat_search_results, 1, wxEXPAND, 5); + + // button sizer + wxBoxSizer* boxButtons = new wxBoxSizer(wxHORIZONTAL); + boxButtons->Add(m_btn_init_scan, 1, wxRIGHT, 5); + boxButtons->Add(m_btn_next_scan, 1); + + // right sizer + wxBoxSizer* const sizer_right = new wxBoxSizer(wxVERTICAL); + sizer_right->Add(sizer_cheat_new_search, 0, wxBOTTOM, 5); + sizer_right->Add(sizer_cheat_search_filter, 0, wxEXPAND | wxBOTTOM, 5); + sizer_right->AddStretchSpacer(1); + sizer_right->Add(boxButtons, 0, wxTOP | wxEXPAND, 5); + + // main sizer + wxBoxSizer* const sizer_main = new wxBoxSizer(wxHORIZONTAL); + sizer_main->Add(sizer_left, 1, wxEXPAND | wxALL, 5); + sizer_main->Add(sizer_right, 0, wxEXPAND | wxALL, 5); + + SetSizerAndFit(sizer_main); +} + +void CheatSearchTab::StartNewSearch(wxCommandEvent& WXUNUSED (event)) +{ + const u8* const memptr = Memory::GetPointer(0); + if (memptr == nullptr) + { + WxUtils::ShowErrorDialog(_("A game is not currently running.")); + return; + } + + // Determine the user-selected data size for this search. + m_search_type_size = + m_size_radiobtn.rad_8->GetValue() + + (m_size_radiobtn.rad_16->GetValue() << 1) + + (m_size_radiobtn.rad_32->GetValue() << 2); + + // Set up the search results efficiently to prevent automatic re-allocations. + m_search_results.clear(); + m_search_results.reserve(Memory::RAM_SIZE / m_search_type_size); + + // Enable the "Next Scan" button. + m_btn_next_scan->Enable(); + + CheatSearchResult r; + // can I assume cheatable values will be aligned like this? + for (u32 addr = 0; addr != Memory::RAM_SIZE; addr += m_search_type_size) + { + r.address = addr; + memcpy(&r.old_value, memptr + addr, m_search_type_size); + m_search_results.push_back(r); + } + + UpdateCheatSearchResultsList(); +} + + +void CheatSearchTab::FilterCheatSearchResults(wxCommandEvent&) +{ + const u8* const memptr = Memory::GetPointer(0); + if (memptr == nullptr) + { + WxUtils::ShowErrorDialog(_("A game is not currently running.")); + return; + } + + // Set up the sub-search results efficiently to prevent automatic re-allocations. + std::vector filtered_results; + filtered_results.reserve(m_search_results.size()); + + // Determine the selected filter + // 1 : equal + // 2 : greater-than + // 4 : less-than + + const int filters[] = {7, 6, 1, 2, 4}; + int filter_mask = filters[m_search_type->GetSelection()]; + + if (m_value_x_radiobtn.rad_oldvalue->GetValue()) // using old value comparison + { + for (CheatSearchResult& result : m_search_results) + { + // with big endian, can just use memcmp for ><= comparison + int cmp_result = memcmp(memptr + result.address, &result.old_value,m_search_type_size); + if (cmp_result < 0) + cmp_result = 4; + else + cmp_result = cmp_result ? 2 : 1; + + if (cmp_result & filter_mask) + { + memcpy(&result.old_value, memptr + result.address, m_search_type_size); + filtered_results.push_back(result); + } + } + } + else // using user entered x value comparison + { + u32 user_x_val; + + // parse the user entered x value + if (filter_mask != 7) // don't need the value for the "None" filter + { + unsigned long parsed_x_val = 0; + wxString x_val = m_textctrl_value_x->GetValue(); + + if (!x_val.ToULong(&parsed_x_val, 0)) + { + WxUtils::ShowErrorDialog(_("You must enter a valid decimal, hexadecimal or octal value.")); + return; + } + + user_x_val = (u32)parsed_x_val; + + // #ifdef LIL_ENDIAN :p + switch (m_search_type_size) + { + case 1 : + break; + case 2 : + *(u16*)&user_x_val = Common::swap16((u8*)&user_x_val); + break; + case 4 : + user_x_val = Common::swap32(user_x_val); + break; + } + // #elseif BIG_ENDIAN + // would have to move <= comparison + int cmp_result = memcmp(memptr + result.address, &user_x_val, m_search_type_size); + if (cmp_result < 0) + cmp_result = 4; + else if (cmp_result) + cmp_result = 2; + else + cmp_result = 1; + + if (cmp_result & filter_mask) + { + memcpy(&result.old_value, memptr + result.address, m_search_type_size); + filtered_results.push_back(result); + } + } + } + + m_search_results.swap(filtered_results); + + UpdateCheatSearchResultsList(); +} + +void CheatSearchTab::ApplyFocus(wxEvent& ev) +{ + ev.Skip(); + m_value_x_radiobtn.rad_uservalue->SetValue(true); +} + +void CheatSearchTab::UpdateCheatSearchResultsList() +{ + m_lbox_search_results->Clear(); + + wxString count_label = _("Count:") + wxString::Format(" %lu", + (unsigned long)m_search_results.size()); + if (m_search_results.size() > MAX_CHEAT_SEARCH_RESULTS_DISPLAY) + { + count_label += _(" (too many to display)"); + } + else + { + for (const CheatSearchResult& result : m_search_results) + { + u32 display_value = result.old_value; + + // #ifdef LIL_ENDIAN :p + switch (m_search_type_size) + { + case 1 : + break; + case 2 : + *(u16*)&display_value = Common::swap16((u8*)&display_value); + break; + case 4 : + display_value = Common::swap32(display_value); + break; + } + // #elseif BIG_ENDIAN + // need to do some stuff in here (for 8 and 16bit) for bigendian + // #endif + std::string rowfmt = StringFromFormat("0x%%08x 0x%%0%ux %%u/%%i", m_search_type_size*2); + + m_lbox_search_results->Append( + wxString::Format(rowfmt.c_str(), result.address, display_value, display_value, display_value)); + } + } + + m_label_results_count->SetLabel(count_label); +} + +void CheatSearchTab::CreateARCode(wxCommandEvent&) +{ + const int sel = m_lbox_search_results->GetSelection(); + if (sel >= 0) + { + const u32 address = m_search_results[sel].address | ((m_search_type_size & ~1) << 24); + + CreateCodeDialog arcode_dlg(this, address); + arcode_dlg.ShowModal(); + } +} diff --git a/Source/Core/DolphinWX/Cheats/CheatSearchTab.h b/Source/Core/DolphinWX/Cheats/CheatSearchTab.h new file mode 100644 index 000000000000..1bdb13a32809 --- /dev/null +++ b/Source/Core/DolphinWX/Cheats/CheatSearchTab.h @@ -0,0 +1,65 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +class wxButton; +class wxChoice; +class wxCommandEvent; +class wxEvent; +class wxListBox; +class wxStaticText; +class wxTextCtrl; +class wxWindow; + +class CheatSearchTab final : public wxPanel +{ +public: + CheatSearchTab(wxWindow* const parent); + +private: + class CheatSearchResult final + { + public: + CheatSearchResult() : address(0), old_value(0) {} + + u32 address; + u32 old_value; + }; + + std::vector m_search_results; + unsigned int m_search_type_size; + + wxChoice* m_search_type; + wxListBox* m_lbox_search_results; + wxStaticText* m_label_results_count; + wxTextCtrl* m_textctrl_value_x; + + wxButton* m_btn_init_scan; + wxButton* m_btn_next_scan; + + struct + { + wxRadioButton* rad_8; + wxRadioButton* rad_16; + wxRadioButton* rad_32; + + } m_size_radiobtn; + + struct + { + wxRadioButton* rad_oldvalue; + wxRadioButton* rad_uservalue; + + } m_value_x_radiobtn; + + void UpdateCheatSearchResultsList(); + void StartNewSearch(wxCommandEvent& event); + void FilterCheatSearchResults(wxCommandEvent& event); + void CreateARCode(wxCommandEvent&); + void ApplyFocus(wxEvent&); +}; diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp new file mode 100644 index 000000000000..f151cf4aef45 --- /dev/null +++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp @@ -0,0 +1,285 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/IniFile.h" +#include "Common/StringUtil.h" +#include "Core/ActionReplay.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/CoreParameter.h" +#include "Core/GeckoCode.h" +#include "Core/GeckoCodeConfig.h" +#include "DolphinWX/Frame.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" + +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(); + + // load codes + UpdateGUI(); + + SetSize(wxSize(-1, 600)); + Center(); + Show(); +} + +wxCheatsWindow::~wxCheatsWindow() +{ + main_frame->g_CheatsWindow = nullptr; +} + +void wxCheatsWindow::Init_ChildControls() +{ + wxPanel* const panel = new wxPanel(this); + + // Main Notebook + m_notebook_main = new wxNotebook(panel, wxID_ANY); + + // --- Tabs --- + // 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->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_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_num_codes, 0, wxALL, 5); + sGroupBoxInfo->Add(m_listbox_codes_list, 1, wxALL, 5); + + wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxHORIZONTAL); + sizer_tab_cheats->Add(m_checklistbox_cheats_list, 1, wxEXPAND | wxTOP | wxBOTTOM | wxLEFT, 10); + sizer_tab_cheats->Add(sGroupBoxInfo, 0, wxALIGN_LEFT | wxEXPAND | wxALL, 5); + + m_tab_cheats->SetSizerAndFit(sizer_tab_cheats); + + // Cheat Search Tab + wxPanel* const tab_cheat_search = new CheatSearchTab(m_notebook_main); + + // Log Tab + m_tab_log = new wxPanel(m_notebook_main, wxID_ANY); + + wxButton* const button_updatelog = new wxButton(m_tab_log, wxID_ANY, _("Update")); + button_updatelog->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonUpdateLog_Press, 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); + + m_checkbox_log_ar->SetValue(ActionReplay::IsSelfLogging()); + m_textctrl_log = new wxTextCtrl(m_tab_log, wxID_ANY, "", wxDefaultPosition, wxSize(100, -1), wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); + + wxBoxSizer *HStrip1 = new wxBoxSizer(wxHORIZONTAL); + HStrip1->Add(m_checkbox_log_ar, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); + HStrip1->Add(button_updatelog, 0, wxALL, 5); + + wxBoxSizer *sTabLog = new wxBoxSizer(wxVERTICAL); + sTabLog->Add(HStrip1, 0, wxALL, 5); + sTabLog->Add(m_textctrl_log, 1, wxALL|wxEXPAND, 5); + + m_tab_log->SetSizerAndFit(sTabLog); + + // Add Tabs to Notebook + m_notebook_main->AddPage(m_tab_cheats, _("AR Codes")); + m_geckocode_panel = new Gecko::CodeConfigPanel(m_notebook_main); + m_notebook_main->AddPage(m_geckocode_panel, _("Gecko Codes")); + m_notebook_main->AddPage(tab_cheat_search, _("Cheat Search")); + m_notebook_main->AddPage(m_tab_log, _("Logging")); + + // Button Strip + m_button_apply = new wxButton(panel, wxID_APPLY, _("Apply")); + m_button_apply->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this); + wxButton* const button_cancel = new wxButton(panel, wxID_CANCEL, _("Cancel")); + button_cancel->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this); + + Bind(wxEVT_CLOSE_WINDOW, &wxCheatsWindow::OnEvent_Close, this); + + wxStdDialogButtonSizer* const sButtons = new wxStdDialogButtonSizer(); + sButtons->AddButton(m_button_apply); + sButtons->AddButton(button_cancel); + sButtons->Realize(); + + wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL); + sMain->Add(m_notebook_main, 1, wxEXPAND|wxALL, 5); + sMain->Add(sButtons, 0, wxRIGHT | wxBOTTOM | wxALIGN_RIGHT, 5); + panel->SetSizerAndFit(sMain); + + wxBoxSizer* const frame_szr = new wxBoxSizer(wxVERTICAL); + frame_szr->Add(panel, 1, wxEXPAND); + SetSizerAndFit(frame_szr); +} + +void wxCheatsWindow::OnEvent_ButtonClose_Press(wxCommandEvent& WXUNUSED (event)) +{ + Close(); +} + +void wxCheatsWindow::OnEvent_Close(wxCloseEvent& ev) +{ + Destroy(); +} + +// load codes for a new ISO ID +void wxCheatsWindow::UpdateGUI() +{ + // load code + m_gameini_default = SConfig::GetInstance().m_LocalCoreStartupParameter.LoadDefaultGameIni(); + m_gameini_local = SConfig::GetInstance().m_LocalCoreStartupParameter.LoadLocalGameIni(); + m_gameini_local_path = SConfig::GetInstance().m_LocalCoreStartupParameter.m_strGameIniLocal; + Load_ARCodes(); + Load_GeckoCodes(); + + // enable controls + m_button_apply->Enable(Core::IsRunning()); + + wxString title = _("Cheats Manager"); + + // write the ISO name in the title + if (Core::IsRunning()) + SetTitle(title + ": " + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + " - " + SConfig::GetInstance().m_LocalCoreStartupParameter.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++) + { + 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); + } +} + +void wxCheatsWindow::Load_GeckoCodes() +{ + m_geckocode_panel->LoadCodes(m_gameini_default, m_gameini_local, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID(), true); +} + +void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (event)) +{ + 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: %lu", (unsigned long)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)); + } + } + } +} + +void wxCheatsWindow::OnEvent_CheatsList_ItemToggled(wxCommandEvent& WXUNUSED (event)) +{ + int index = m_checklistbox_cheats_list->GetSelection(); + for (const ARCodeIndex& code_index : m_index_list) + { + if ((int)code_index.uiIndex == index) + { + ActionReplay::SetARCode_IsActive(m_checklistbox_cheats_list->IsChecked(index), code_index.index); + } + } +} + +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()); + + // Save gameini, with changed gecko codes + if (m_gameini_local_path.size()) + { + Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes()); + m_gameini_local.Save(m_gameini_local_path); + } + + ev.Skip(); +} + +void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (event)) +{ + m_textctrl_log->Clear(); + for (const std::string& text : ActionReplay::GetSelfLog()) + { + m_textctrl_log->AppendText(StrToWxStr(text)); + } +} + +void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& WXUNUSED (event)) +{ + ActionReplay::EnableSelfLogging(m_checkbox_log_ar->IsChecked()); +} diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.h b/Source/Core/DolphinWX/Cheats/CheatsWindow.h new file mode 100644 index 000000000000..2a83909db66e --- /dev/null +++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.h @@ -0,0 +1,105 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "Common/CommonTypes.h" +#include "Common/IniFile.h" + +class wxButton; +class wxCheckBox; +class wxCheckListBox; +class wxChoice; +class wxCloseEvent; +class wxCommandEvent; +class wxEvent; +class wxListBox; +class wxNotebook; +class wxRadioButton; +class wxStaticBox; +class wxStaticText; +class wxTextCtrl; +class wxWindow; + +namespace Gecko +{ + class CodeConfigPanel; +} + +class wxCheatsWindow final : public wxDialog +{ + friend class CreateCodeDialog; + +public: + wxCheatsWindow(wxWindow* const parent); + ~wxCheatsWindow(); + void UpdateGUI(); + +private: + struct ARCodeIndex + { + u32 uiIndex; + size_t index; + }; + + // --- GUI Controls --- + wxButton* m_button_apply; + wxNotebook* m_notebook_main; + + wxPanel* m_tab_cheats; + wxPanel* m_tab_log; + + wxCheckBox* m_checkbox_log_ar; + + wxStaticText* m_label_code_name; + wxStaticText* m_label_num_codes; + + wxCheckListBox* m_checklistbox_cheats_list; + + wxTextCtrl* m_textctrl_log; + + wxListBox* m_listbox_codes_list; + + wxStaticBox* m_groupbox_info; + + wxArrayString m_cheat_string_list; + + std::vector m_index_list; + + Gecko::CodeConfigPanel* m_geckocode_panel; + IniFile m_gameini_default; + IniFile m_gameini_local; + std::string m_gameini_local_path; + + void Init_ChildControls(); + + void Load_ARCodes(); + void Load_GeckoCodes(); + + // --- Wx Events Handlers --- + + // Close Button + void OnEvent_ButtonClose_Press(wxCommandEvent& event); + void OnEvent_Close(wxCloseEvent& ev); + + // Cheats List + void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event); + void OnEvent_CheatsList_ItemToggled(wxCommandEvent& event); + + // Apply Changes Button + void OnEvent_ApplyChanges_Press(wxCommandEvent& event); + + // Update Log Button + void OnEvent_ButtonUpdateLog_Press(wxCommandEvent& event); + + // Enable Logging Checkbox + void OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& event); +}; diff --git a/Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp new file mode 100644 index 000000000000..b266e9d7ab45 --- /dev/null +++ b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp @@ -0,0 +1,109 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Core/ActionReplay.h" +#include "Core/ConfigManager.h" +#include "DolphinWX/ISOProperties.h" +#include "DolphinWX/WxUtils.h" +#include "DolphinWX/Cheats/CreateCodeDialog.h" + +CreateCodeDialog::CreateCodeDialog(wxWindow* const parent, const u32 address) + : wxDialog(parent, -1, _("Create AR Code")) + , m_code_address(address) +{ + wxStaticText* const label_name = new wxStaticText(this, -1, _("Name: ")); + m_textctrl_name = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxSize(256,-1)); + + wxStaticText* const label_code = new wxStaticText(this, -1, _("Code: ")); + m_textctrl_code = new wxTextCtrl(this, -1, wxString::Format("0x%08x", address)); + m_textctrl_code->Disable(); + + wxStaticText* const label_value = new wxStaticText(this, -1, _("Value: ")); + m_textctrl_value = new wxTextCtrl(this, -1, "0"); + + m_checkbox_use_hex = new wxCheckBox(this, -1, _("Use Hex")); + m_checkbox_use_hex->SetValue(true); + + wxBoxSizer* const sizer_value_label = new wxBoxSizer(wxHORIZONTAL); + sizer_value_label->Add(label_value, 0, wxRIGHT, 5); + sizer_value_label->Add(m_checkbox_use_hex); + + // main sizer + wxBoxSizer* const sizer_main = new wxBoxSizer(wxVERTICAL); + sizer_main->Add(label_name, 0, wxALL, 5); + sizer_main->Add(m_textctrl_name, 0, wxALL, 5); + sizer_main->Add(label_code, 0, wxALL, 5); + sizer_main->Add(m_textctrl_code, 0, wxALL, 5); + sizer_main->Add(sizer_value_label, 0, wxALL, 5); + sizer_main->Add(m_textctrl_value, 0, wxALL, 5); + sizer_main->Add(CreateButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT), 0, wxALL, 5); + + Bind(wxEVT_BUTTON, &CreateCodeDialog::PressOK, this, wxID_OK); + Bind(wxEVT_BUTTON, &CreateCodeDialog::PressCancel, this, wxID_CANCEL); + Bind(wxEVT_CLOSE_WINDOW, &CreateCodeDialog::OnEvent_Close, this); + + SetSizerAndFit(sizer_main); + SetFocus(); +} + +void CreateCodeDialog::PressOK(wxCommandEvent& ev) +{ + const wxString code_name = m_textctrl_name->GetValue(); + if (code_name.empty()) + { + WxUtils::ShowErrorDialog(_("You must enter a name.")); + return; + } + + long code_value; + int base = m_checkbox_use_hex->IsChecked() ? 16 : 10; + if (!m_textctrl_value->GetValue().ToLong(&code_value, base)) + { + WxUtils::ShowErrorDialog(_("Invalid value.")); + return; + } + + //wxString full_code = textctrl_code->GetValue(); + //full_code += ' '; + //full_code += wxString::Format("0x%08x", code_value); + + // create the new code + ActionReplay::ARCode new_cheat; + new_cheat.active = false; + new_cheat.name = WxStrToStr(code_name); + const ActionReplay::AREntry new_entry(m_code_address, code_value); + new_cheat.ops.push_back(new_entry); + + // pretty hacky - add the code to the gameini + { + CISOProperties isoprops(SConfig::GetInstance().m_LastFilename, this); + // add the code to the isoproperties arcode list + arCodes.push_back(new_cheat); + // save the gameini + isoprops.SaveGameConfig(); + isoprops.ActionReplayList_Load(); // loads the new arcodes + //ActionReplay::UpdateActiveList(); + } + + Close(); +} + +void CreateCodeDialog::PressCancel(wxCommandEvent& ev) +{ + Close(); +} + +void CreateCodeDialog::OnEvent_Close(wxCloseEvent& ev) +{ + Destroy(); +} diff --git a/Source/Core/DolphinWX/Cheats/CreateCodeDialog.h b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.h new file mode 100644 index 000000000000..bcb10e92cc31 --- /dev/null +++ b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.h @@ -0,0 +1,32 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include + +#include "Common/CommonTypes.h" + +class wxCheckBox; +class wxCommandEvent; +class wxTextCtrl; +class wxWindow; + +class CreateCodeDialog final : public wxDialog +{ +public: + CreateCodeDialog(wxWindow* const parent, const u32 address); + +private: + const u32 m_code_address; + + wxTextCtrl* m_textctrl_name; + wxTextCtrl* m_textctrl_code; + wxTextCtrl* m_textctrl_value; + wxCheckBox* m_checkbox_use_hex; + + void PressOK(wxCommandEvent&); + void PressCancel(wxCommandEvent&); + void OnEvent_Close(wxCloseEvent& ev); +}; diff --git a/Source/Core/DolphinWX/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp similarity index 99% rename from Source/Core/DolphinWX/GeckoCodeDiag.cpp rename to Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp index 20a9cf69cb42..d1ced11ff213 100644 --- a/Source/Core/DolphinWX/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.cpp @@ -27,8 +27,8 @@ #include "Core/Core.h" #include "Core/GeckoCode.h" #include "Core/GeckoCodeConfig.h" -#include "DolphinWX/GeckoCodeDiag.h" #include "DolphinWX/WxUtils.h" +#include "DolphinWX/Cheats/GeckoCodeDiag.h" class IniFile; diff --git a/Source/Core/DolphinWX/GeckoCodeDiag.h b/Source/Core/DolphinWX/Cheats/GeckoCodeDiag.h similarity index 100% rename from Source/Core/DolphinWX/GeckoCodeDiag.h rename to Source/Core/DolphinWX/Cheats/GeckoCodeDiag.h diff --git a/Source/Core/DolphinWX/CheatsWindow.cpp b/Source/Core/DolphinWX/CheatsWindow.cpp deleted file mode 100644 index e392fa50b1dd..000000000000 --- a/Source/Core/DolphinWX/CheatsWindow.cpp +++ /dev/null @@ -1,681 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "Common/IniFile.h" -#include "Common/StringUtil.h" -#include "Core/ActionReplay.h" -#include "Core/ConfigManager.h" -#include "Core/Core.h" -#include "Core/CoreParameter.h" -#include "Core/GeckoCode.h" -#include "Core/GeckoCodeConfig.h" -#include "Core/HW/Memmap.h" -#include "DolphinWX/CheatsWindow.h" -#include "DolphinWX/Frame.h" -#include "DolphinWX/GeckoCodeDiag.h" -#include "DolphinWX/ISOProperties.h" -#include "DolphinWX/Main.h" -#include "DolphinWX/WxUtils.h" - -class wxWindow; - -#define MAX_CHEAT_SEARCH_RESULTS_DISPLAY 256 - -// meh -static wxCheatsWindow *g_cheat_window; - -wxCheatsWindow::wxCheatsWindow(wxWindow* const parent) - : wxDialog(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxDIALOG_NO_PARENT) -{ - ::g_cheat_window = this; - - // Create the GUI controls - Init_ChildControls(); - - // load codes - UpdateGUI(); - - SetSize(wxSize(-1, 600)); - Center(); - Show(); -} - -wxCheatsWindow::~wxCheatsWindow() -{ - main_frame->g_CheatsWindow = nullptr; - ::g_cheat_window = nullptr; -} - -void wxCheatsWindow::Init_ChildControls() -{ - wxPanel* const panel = new wxPanel(this); - - // Main Notebook - m_Notebook_Main = new wxNotebook(panel, wxID_ANY); - - // --- Tabs --- - // $ Cheats List Tab - m_Tab_Cheats = new wxPanel(m_Notebook_Main, wxID_ANY); - - m_CheckListBox_CheatsList = new wxCheckListBox(m_Tab_Cheats, wxID_ANY, wxDefaultPosition, wxSize(300, 0), m_CheatStringList, wxLB_HSCROLL, wxDefaultValidator); - m_CheckListBox_CheatsList->Bind(wxEVT_LISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemSelected, this); - m_CheckListBox_CheatsList->Bind(wxEVT_CHECKLISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemToggled, this); - - m_Label_Codename = new wxStaticText(m_Tab_Cheats, wxID_ANY, _("Name: ")); - m_GroupBox_Info = new wxStaticBox(m_Tab_Cheats, wxID_ANY, _("Code Info")); - - m_Label_NumCodes = new wxStaticText(m_Tab_Cheats, wxID_ANY, _("Number Of Codes: ")); - m_ListBox_CodesList = 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_Codename, 0, wxALL, 5); - sGroupBoxInfo->Add(m_Label_NumCodes, 0, wxALL, 5); - sGroupBoxInfo->Add(m_ListBox_CodesList, 1, wxALL, 5); - - wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxHORIZONTAL); - sizer_tab_cheats->Add(m_CheckListBox_CheatsList, 1, wxEXPAND | wxTOP | wxBOTTOM | wxLEFT, 10); - sizer_tab_cheats->Add(sGroupBoxInfo, 0, wxALIGN_LEFT | wxEXPAND | wxALL, 5); - - m_Tab_Cheats->SetSizerAndFit(sizer_tab_cheats); - - // $ Cheat Search Tab - wxPanel* const tab_cheat_search = new CheatSearchTab(m_Notebook_Main); - - // $ Log Tab - m_Tab_Log = new wxPanel(m_Notebook_Main, wxID_ANY); - - wxButton* const button_updatelog = new wxButton(m_Tab_Log, wxID_ANY, _("Update")); - button_updatelog->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonUpdateLog_Press, this); - - m_CheckBox_LogAR = new wxCheckBox(m_Tab_Log, wxID_ANY, _("Enable AR Logging")); - m_CheckBox_LogAR->Bind(wxEVT_CHECKBOX, &wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange, this); - - m_CheckBox_LogAR->SetValue(ActionReplay::IsSelfLogging()); - m_TextCtrl_Log = new wxTextCtrl(m_Tab_Log, wxID_ANY, "", wxDefaultPosition, wxSize(100, -1), wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP); - - wxBoxSizer *HStrip1 = new wxBoxSizer(wxHORIZONTAL); - HStrip1->Add(m_CheckBox_LogAR, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5); - HStrip1->Add(button_updatelog, 0, wxALL, 5); - - wxBoxSizer *sTabLog = new wxBoxSizer(wxVERTICAL); - sTabLog->Add(HStrip1, 0, wxALL, 5); - sTabLog->Add(m_TextCtrl_Log, 1, wxALL|wxEXPAND, 5); - - m_Tab_Log->SetSizerAndFit(sTabLog); - - // Add Tabs to Notebook - m_Notebook_Main->AddPage(m_Tab_Cheats, _("AR Codes")); - m_geckocode_panel = new Gecko::CodeConfigPanel(m_Notebook_Main); - m_Notebook_Main->AddPage(m_geckocode_panel, _("Gecko Codes")); - m_Notebook_Main->AddPage(tab_cheat_search, _("Cheat Search")); - m_Notebook_Main->AddPage(m_Tab_Log, _("Logging")); - - // Button Strip - button_apply = new wxButton(panel, wxID_APPLY, _("Apply")); - button_apply->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this); - wxButton* const button_cancel = new wxButton(panel, wxID_CANCEL, _("Cancel")); - button_cancel->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this); - - Bind(wxEVT_CLOSE_WINDOW, &wxCheatsWindow::OnEvent_Close, this); - - wxStdDialogButtonSizer* const sButtons = new wxStdDialogButtonSizer(); - sButtons->AddButton(button_apply); - sButtons->AddButton(button_cancel); - sButtons->Realize(); - - wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL); - sMain->Add(m_Notebook_Main, 1, wxEXPAND|wxALL, 5); - sMain->Add(sButtons, 0, wxRIGHT | wxBOTTOM | wxALIGN_RIGHT, 5); - panel->SetSizerAndFit(sMain); - - wxBoxSizer* const frame_szr = new wxBoxSizer(wxVERTICAL); - frame_szr->Add(panel, 1, wxEXPAND); - SetSizerAndFit(frame_szr); -} - -CheatSearchTab::CheatSearchTab(wxWindow* const parent) - : wxPanel(parent, -1) -{ - // first scan button - btnInitScan = new wxButton(this, -1, _("New Scan")); - btnInitScan->Bind(wxEVT_BUTTON, &CheatSearchTab::StartNewSearch, this); - - // next scan button - btnNextScan = new wxButton(this, -1, _("Next Scan")); - btnNextScan->Bind(wxEVT_BUTTON, &CheatSearchTab::FilterCheatSearchResults, this); - btnNextScan->Disable(); - - // data size radio buttons - size_radiobtn.rad_8 = new wxRadioButton(this, -1, _("8 bit"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); - size_radiobtn.rad_16 = new wxRadioButton(this, -1, _("16 bit")); - size_radiobtn.rad_32 = new wxRadioButton(this, -1, _("32 bit")); - size_radiobtn.rad_8->SetValue(true); - - // data sizes groupbox - wxStaticBoxSizer* const sizer_cheat_new_search = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Data Size")); - sizer_cheat_new_search->Add(size_radiobtn.rad_8, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5); - sizer_cheat_new_search->Add(size_radiobtn.rad_16, 0, wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5); - sizer_cheat_new_search->Add(size_radiobtn.rad_32, 0, wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5); - - // result controls - lbox_search_results = new wxListBox(this, -1); - label_results_count = new wxStaticText(this, -1, _("Count:")); - - // create AR code button - wxButton* const button_cheat_search_copy_address = new wxButton(this, -1, _("Create AR Code")); - button_cheat_search_copy_address->Bind(wxEVT_BUTTON, &CheatSearchTab::CreateARCode, this); - - // results groupbox - wxStaticBoxSizer* const sizer_cheat_search_results = new wxStaticBoxSizer(wxVERTICAL, this, _("Results")); - sizer_cheat_search_results->Add(label_results_count, 0, wxALIGN_LEFT | wxALL, 5); - sizer_cheat_search_results->Add(lbox_search_results, 1, wxEXPAND | wxALL, 5); - sizer_cheat_search_results->Add(button_cheat_search_copy_address, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5); - - // Search value radio buttons - value_x_radiobtn.rad_oldvalue = new wxRadioButton(this, -1, _("Previous Value"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP); - value_x_radiobtn.rad_uservalue = new wxRadioButton(this, -1, ""); - value_x_radiobtn.rad_oldvalue->SetValue(true); - - // search value textbox - textctrl_value_x = new wxTextCtrl(this, -1, "0x0", wxDefaultPosition, wxSize(96,-1)); - textctrl_value_x->Bind(wxEVT_SET_FOCUS, &CheatSearchTab::ApplyFocus, this); - - wxBoxSizer* const sizer_cheat_filter_text = new wxBoxSizer(wxHORIZONTAL); - sizer_cheat_filter_text->Add(value_x_radiobtn.rad_uservalue, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5); - sizer_cheat_filter_text->Add(textctrl_value_x, 1, wxALIGN_CENTER_VERTICAL, 5); - - // value groupbox - wxStaticBoxSizer* const sizer_cheat_search_filter_x = new wxStaticBoxSizer(wxVERTICAL, this, _("Value")); - sizer_cheat_search_filter_x->Add(value_x_radiobtn.rad_oldvalue, 0, wxLEFT | wxRIGHT | wxBOTTOM, 5); - sizer_cheat_search_filter_x->Add(sizer_cheat_filter_text, 0, wxALL | wxEXPAND, 5); - - // filter types in the compare dropdown - static const wxString searches[] = { - _("Unknown"), - _("Not Equal"), - _("Equal"), - _("Greater Than"), - _("Less Than"), - // TODO: Implement between search. - //_("Between"), - }; - - search_type = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, sizeof(searches)/sizeof(*searches), searches); - search_type->Select(0); - - wxStaticBoxSizer* const sizer_cheat_search_filter = new wxStaticBoxSizer(wxVERTICAL, this, _("Search Filter")); - sizer_cheat_search_filter->Add(sizer_cheat_search_filter_x, 0, wxALL | wxEXPAND, 5); - sizer_cheat_search_filter->Add(search_type, 0, wxALL, 5); - - // left sizer - wxBoxSizer* const sizer_left = new wxBoxSizer(wxVERTICAL); - sizer_left->Add(sizer_cheat_search_results, 1, wxEXPAND, 5); - - // button sizer - wxBoxSizer* boxButtons = new wxBoxSizer(wxHORIZONTAL); - boxButtons->Add(btnInitScan, 1, wxRIGHT, 5); - boxButtons->Add(btnNextScan, 1); - - // right sizer - wxBoxSizer* const sizer_right = new wxBoxSizer(wxVERTICAL); - sizer_right->Add(sizer_cheat_new_search, 0, wxBOTTOM, 5); - sizer_right->Add(sizer_cheat_search_filter, 0, wxEXPAND | wxBOTTOM, 5); - sizer_right->AddStretchSpacer(1); - sizer_right->Add(boxButtons, 0, wxTOP | wxEXPAND, 5); - - // main sizer - wxBoxSizer* const sizer_main = new wxBoxSizer(wxHORIZONTAL); - sizer_main->Add(sizer_left, 1, wxEXPAND | wxALL, 5); - sizer_main->Add(sizer_right, 0, wxEXPAND | wxALL, 5); - - SetSizerAndFit(sizer_main); -} - -void wxCheatsWindow::OnEvent_ButtonClose_Press(wxCommandEvent& WXUNUSED (event)) -{ - Close(); -} - -void wxCheatsWindow::OnEvent_Close(wxCloseEvent& ev) -{ - Destroy(); -} - -// load codes for a new ISO ID -void wxCheatsWindow::UpdateGUI() -{ - // load code - m_gameini_default = SConfig::GetInstance().m_LocalCoreStartupParameter.LoadDefaultGameIni(); - m_gameini_local = SConfig::GetInstance().m_LocalCoreStartupParameter.LoadLocalGameIni(); - m_gameini_local_path = SConfig::GetInstance().m_LocalCoreStartupParameter.m_strGameIniLocal; - Load_ARCodes(); - Load_GeckoCodes(); - - // enable controls - button_apply->Enable(Core::IsRunning()); - - wxString title = _("Cheats Manager"); - - // write the ISO name in the title - if (Core::IsRunning()) - SetTitle(title + ": " + SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID() + " - " + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strName); - else - SetTitle(title); -} - -void wxCheatsWindow::Load_ARCodes() -{ - using namespace ActionReplay; - - m_CheckListBox_CheatsList->Clear(); - - if (!Core::IsRunning()) - return; - - indexList.clear(); - size_t size = GetCodeListSize(); - for (size_t i = 0; i < size; i++) - { - ARCode code = GetARCode(i); - ARCodeIndex ind; - u32 index = m_CheckListBox_CheatsList->Append(StrToWxStr(code.name)); - m_CheckListBox_CheatsList->Check(index, code.active); - ind.index = i; - ind.uiIndex = index; - indexList.push_back(ind); - } -} - -void wxCheatsWindow::Load_GeckoCodes() -{ - m_geckocode_panel->LoadCodes(m_gameini_default, m_gameini_local, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID(), true); -} - -void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (event)) -{ - using namespace ActionReplay; - - int index = m_CheckListBox_CheatsList->GetSelection(); - for (size_t i = 0; i < indexList.size(); i++) - { - if ((int)indexList[i].uiIndex == index) - { - ARCode code = GetARCode(i); - m_Label_Codename->SetLabel(_("Name: ") + StrToWxStr(code.name)); - - std::string numcodes = StringFromFormat("Number of Codes: %lu", (unsigned long)code.ops.size()); - m_Label_NumCodes->SetLabel(StrToWxStr(numcodes)); - m_ListBox_CodesList->Clear(); - - for (const AREntry& entry : code.ops) - { - std::string ops = StringFromFormat("%08x %08x", entry.cmd_addr, entry.value); - m_ListBox_CodesList->Append(StrToWxStr(ops)); - } - } - } -} - -void wxCheatsWindow::OnEvent_CheatsList_ItemToggled(wxCommandEvent& WXUNUSED (event)) -{ - int index = m_CheckListBox_CheatsList->GetSelection(); - for (const ARCodeIndex& code_index : indexList) - { - if ((int)code_index.uiIndex == index) - { - ActionReplay::SetARCode_IsActive(m_CheckListBox_CheatsList->IsChecked(index), code_index.index); - } - } -} - -void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev) -{ - // Apply AR Code changes - for (const ARCodeIndex& code_index : indexList) - { - ActionReplay::SetARCode_IsActive(m_CheckListBox_CheatsList->IsChecked(code_index.uiIndex), code_index.index); - } - - // Apply Gecko Code changes - Gecko::SetActiveCodes(m_geckocode_panel->GetCodes()); - - // Save gameini, with changed gecko codes - if (m_gameini_local_path.size()) - { - Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes()); - m_gameini_local.Save(m_gameini_local_path); - } - - ev.Skip(); -} - -void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (event)) -{ - m_TextCtrl_Log->Clear(); - for (const std::string& text : ActionReplay::GetSelfLog()) - { - m_TextCtrl_Log->AppendText(StrToWxStr(text)); - } -} - -void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& WXUNUSED (event)) -{ - ActionReplay::EnableSelfLogging(m_CheckBox_LogAR->IsChecked()); -} - -void CheatSearchTab::StartNewSearch(wxCommandEvent& WXUNUSED (event)) -{ - const u8* const memptr = Memory::GetPointer(0); - if (nullptr == memptr) - { - WxUtils::ShowErrorDialog(_("A game is not currently running.")); - return; - } - - // Determine the user-selected data size for this search. - search_type_size = - size_radiobtn.rad_8->GetValue() + - (size_radiobtn.rad_16->GetValue() << 1) + - (size_radiobtn.rad_32->GetValue() << 2); - - // Set up the search results efficiently to prevent automatic re-allocations. - search_results.clear(); - search_results.reserve(Memory::RAM_SIZE / search_type_size); - - // Enable the "Next Scan" button. - btnNextScan->Enable(); - - CheatSearchResult r; - // can I assume cheatable values will be aligned like this? - for (u32 addr = 0; addr != Memory::RAM_SIZE; addr += search_type_size) - { - r.address = addr; - memcpy(&r.old_value, memptr + addr, search_type_size); - search_results.push_back(r); - } - - UpdateCheatSearchResultsList(); -} - -void CheatSearchTab::FilterCheatSearchResults(wxCommandEvent&) -{ - const u8* const memptr = Memory::GetPointer(0); - if (nullptr == memptr) - { - WxUtils::ShowErrorDialog(_("A game is not currently running.")); - return; - } - - // Set up the sub-search results efficiently to prevent automatic re-allocations. - std::vector filtered_results; - filtered_results.reserve(search_results.size()); - - - // Determine the selected filter - // 1 : equal - // 2 : greater-than - // 4 : less-than - - const int filters[] = {7, 6, 1, 2, 4}; - int filter_mask = filters[search_type->GetSelection()]; - - if (value_x_radiobtn.rad_oldvalue->GetValue()) // using old value comparison - { - for (CheatSearchResult& result : search_results) - { - // with big endian, can just use memcmp for ><= comparison - int cmp_result = memcmp(memptr + result.address, &result.old_value, search_type_size); - if (cmp_result < 0) - cmp_result = 4; - else - cmp_result = cmp_result ? 2 : 1; - - if (cmp_result & filter_mask) - { - memcpy(&result.old_value, memptr + result.address, search_type_size); - filtered_results.push_back(result); - } - } - } - else // using user entered x value comparison - { - u32 user_x_val; - - // parse the user entered x value - if (filter_mask != 7) // don't need the value for the "None" filter - { - unsigned long parsed_x_val = 0; - wxString x_val = textctrl_value_x->GetValue(); - - if (!x_val.ToULong(&parsed_x_val, 0)) - { - WxUtils::ShowErrorDialog(_("You must enter a valid decimal, hexadecimal or octal value.")); - return; - } - - user_x_val = (u32)parsed_x_val; - - // #ifdef LIL_ENDIAN :p - switch (search_type_size) - { - case 1 : - break; - case 2 : - *(u16*)&user_x_val = Common::swap16((u8*)&user_x_val); - break; - case 4 : - user_x_val = Common::swap32(user_x_val); - break; - } - // #elseif BIG_ENDIAN - // would have to move <= comparison - int cmp_result = memcmp(memptr + result.address, &user_x_val, search_type_size); - if (cmp_result < 0) - cmp_result = 4; - else if (cmp_result) - cmp_result = 2; - else - cmp_result = 1; - - if (cmp_result & filter_mask) - { - memcpy(&result.old_value, memptr + result.address, search_type_size); - filtered_results.push_back(result); - } - } - } - - search_results.swap(filtered_results); - - UpdateCheatSearchResultsList(); -} - -void CheatSearchTab::ApplyFocus(wxEvent& ev) -{ - ev.Skip(); - value_x_radiobtn.rad_uservalue->SetValue(true); -} - -void CheatSearchTab::UpdateCheatSearchResultsList() -{ - lbox_search_results->Clear(); - - wxString count_label = _("Count:") + wxString::Format(" %lu", - (unsigned long)search_results.size()); - if (search_results.size() > MAX_CHEAT_SEARCH_RESULTS_DISPLAY) - { - count_label += _(" (too many to display)"); - } - else - { - for (const CheatSearchResult& result : search_results) - { - u32 display_value = result.old_value; - - // #ifdef LIL_ENDIAN :p - switch (search_type_size) - { - case 1 : - break; - case 2 : - *(u16*)&display_value = Common::swap16((u8*)&display_value); - break; - case 4 : - display_value = Common::swap32(display_value); - break; - } - // #elseif BIG_ENDIAN - // need to do some stuff in here (for 8 and 16bit) for bigendian - // #endif - std::string rowfmt = StringFromFormat("0x%%08x 0x%%0%ux %%u/%%i", search_type_size*2); - - lbox_search_results->Append( - wxString::Format(rowfmt.c_str(), result.address, display_value, display_value, display_value)); - } - } - - label_results_count->SetLabel(count_label); -} - -void CheatSearchTab::CreateARCode(wxCommandEvent&) -{ - const int sel = lbox_search_results->GetSelection(); - if (sel >= 0) - { - const u32 address = search_results[sel].address | ((search_type_size & ~1) << 24); - - CreateCodeDialog arcode_dlg(this, address); - arcode_dlg.ShowModal(); - } -} - -CreateCodeDialog::CreateCodeDialog(wxWindow* const parent, const u32 address) - : wxDialog(parent, -1, _("Create AR Code")) - , code_address(address) -{ - wxStaticText* const label_name = new wxStaticText(this, -1, _("Name: ")); - textctrl_name = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxSize(256,-1)); - - wxStaticText* const label_code = new wxStaticText(this, -1, _("Code: ")); - textctrl_code = new wxTextCtrl(this, -1, wxString::Format("0x%08x", address)); - textctrl_code->Disable(); - - wxStaticText* const label_value = new wxStaticText(this, -1, _("Value: ")); - textctrl_value = new wxTextCtrl(this, -1, "0"); - - checkbox_use_hex = new wxCheckBox(this, -1, _("Use Hex")); - checkbox_use_hex->SetValue(true); - - wxBoxSizer* const sizer_value_label = new wxBoxSizer(wxHORIZONTAL); - sizer_value_label->Add(label_value, 0, wxRIGHT, 5); - sizer_value_label->Add(checkbox_use_hex); - - // main sizer - wxBoxSizer* const sizer_main = new wxBoxSizer(wxVERTICAL); - sizer_main->Add(label_name, 0, wxALL, 5); - sizer_main->Add(textctrl_name, 0, wxALL, 5); - sizer_main->Add(label_code, 0, wxALL, 5); - sizer_main->Add(textctrl_code, 0, wxALL, 5); - sizer_main->Add(sizer_value_label, 0, wxALL, 5); - sizer_main->Add(textctrl_value, 0, wxALL, 5); - sizer_main->Add(CreateButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT), 0, wxALL, 5); - - Bind(wxEVT_BUTTON, &CreateCodeDialog::PressOK, this, wxID_OK); - Bind(wxEVT_BUTTON, &CreateCodeDialog::PressCancel, this, wxID_CANCEL); - Bind(wxEVT_CLOSE_WINDOW, &CreateCodeDialog::OnEvent_Close, this); - - SetSizerAndFit(sizer_main); - SetFocus(); -} - -void CreateCodeDialog::PressOK(wxCommandEvent& ev) -{ - const wxString code_name = textctrl_name->GetValue(); - if (code_name.empty()) - { - WxUtils::ShowErrorDialog(_("You must enter a name.")); - return; - } - - long code_value; - int base = checkbox_use_hex->IsChecked() ? 16 : 10; - if (!textctrl_value->GetValue().ToLong(&code_value, base)) - { - WxUtils::ShowErrorDialog(_("Invalid value.")); - return; - } - - //wxString full_code = textctrl_code->GetValue(); - //full_code += ' '; - //full_code += wxString::Format("0x%08x", code_value); - - // create the new code - ActionReplay::ARCode new_cheat; - new_cheat.active = false; - new_cheat.name = WxStrToStr(code_name); - const ActionReplay::AREntry new_entry(code_address, code_value); - new_cheat.ops.push_back(new_entry); - - // pretty hacky - add the code to the gameini - { - CISOProperties isoprops(SConfig::GetInstance().m_LastFilename, this); - // add the code to the isoproperties arcode list - arCodes.push_back(new_cheat); - // save the gameini - isoprops.SaveGameConfig(); - isoprops.ActionReplayList_Load(); // loads the new arcodes - //ActionReplay::UpdateActiveList(); - } - - // refresh arcode list in other tab - ::g_cheat_window->Load_ARCodes(); - - Close(); -} - -void CreateCodeDialog::PressCancel(wxCommandEvent& ev) -{ - Close(); -} - -void CreateCodeDialog::OnEvent_Close(wxCloseEvent& ev) -{ - Destroy(); -} diff --git a/Source/Core/DolphinWX/CheatsWindow.h b/Source/Core/DolphinWX/CheatsWindow.h deleted file mode 100644 index 7a82822f56f1..000000000000 --- a/Source/Core/DolphinWX/CheatsWindow.h +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include "Common/CommonTypes.h" -#include "Common/IniFile.h" - -class wxButton; -class wxCheckBox; -class wxCheckListBox; -class wxChoice; -class wxCloseEvent; -class wxCommandEvent; -class wxEvent; -class wxListBox; -class wxNotebook; -class wxRadioButton; -class wxStaticBox; -class wxStaticText; -class wxTextCtrl; -class wxWindow; - -namespace Gecko { class CodeConfigPanel; } - -class CreateCodeDialog : public wxDialog -{ -public: - CreateCodeDialog(wxWindow* const parent, const u32 address); - -protected: - - const u32 code_address; - - wxTextCtrl *textctrl_name, *textctrl_code, *textctrl_value; - wxCheckBox *checkbox_use_hex; - - void PressOK(wxCommandEvent&); - void PressCancel(wxCommandEvent&); - void OnEvent_Close(wxCloseEvent& ev); -}; - -class CheatSearchTab : public wxPanel -{ -public: - CheatSearchTab(wxWindow* const parent); - -protected: - - class CheatSearchResult - { - public: - CheatSearchResult() : address(0), old_value(0) {} - - u32 address; - u32 old_value; - }; - - std::vector search_results; - unsigned int search_type_size; - - wxChoice* search_type; - wxListBox* lbox_search_results; - wxStaticText* label_results_count; - wxTextCtrl* textctrl_value_x; - wxButton *btnInitScan, *btnNextScan; - - struct - { - wxRadioButton *rad_8, *rad_16, *rad_32; - - } size_radiobtn; - - struct - { - wxRadioButton *rad_oldvalue, *rad_uservalue; - - } value_x_radiobtn; - - void UpdateCheatSearchResultsList(); - void StartNewSearch(wxCommandEvent& event); - void FilterCheatSearchResults(wxCommandEvent& event); - void CreateARCode(wxCommandEvent&); - void ApplyFocus(wxEvent&); -}; - -class wxCheatsWindow : public wxDialog -{ - friend class CreateCodeDialog; - - public: - wxCheatsWindow(wxWindow* const parent); - ~wxCheatsWindow(); - void UpdateGUI(); - - protected: - - struct ARCodeIndex { - u32 uiIndex; - size_t index; - }; - - // --- GUI Controls --- - wxButton* button_apply; - wxNotebook *m_Notebook_Main; - - wxPanel *m_Tab_Cheats; - wxPanel *m_Tab_Log; - - wxCheckBox *m_CheckBox_LogAR; - - wxStaticText *m_Label_Codename; - wxStaticText *m_Label_NumCodes; - - wxCheckListBox *m_CheckListBox_CheatsList; - - wxTextCtrl *m_TextCtrl_Log; - - wxListBox *m_ListBox_CodesList; - - wxStaticBox *m_GroupBox_Info; - - wxArrayString m_CheatStringList; - - std::vector indexList; - - Gecko::CodeConfigPanel *m_geckocode_panel; - IniFile m_gameini_default; - IniFile m_gameini_local; - std::string m_gameini_local_path; - - void Init_ChildControls(); - - void Load_ARCodes(); - void Load_GeckoCodes(); - - // --- Wx Events Handlers --- - - // $ Close Button - void OnEvent_ButtonClose_Press(wxCommandEvent& event); - void OnEvent_Close(wxCloseEvent& ev); - - // $ Cheats List - void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event); - void OnEvent_CheatsList_ItemToggled(wxCommandEvent& event); - - // $ Apply Changes Button - void OnEvent_ApplyChanges_Press(wxCommandEvent& event); - - // $ Update Log Button - void OnEvent_ButtonUpdateLog_Press(wxCommandEvent& event); - - // $ Enable Logging Checkbox - void OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& event); -}; diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj index 69fa015d15da..124315d86373 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj @@ -1,4 +1,4 @@ - + @@ -50,7 +50,10 @@ - + + + + @@ -73,7 +76,6 @@ - @@ -102,8 +104,11 @@ - + + + + @@ -122,7 +127,6 @@ - @@ -189,7 +193,7 @@ {6bbd47cf-91fd-4077-b676-8b76980178a9} - + {604C8368-F34A-4D55-82C8-CC92A0C13254} diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters index f2d5c6f3835b..24854b77d757 100644 --- a/Source/Core/DolphinWX/DolphinWX.vcxproj.filters +++ b/Source/Core/DolphinWX/DolphinWX.vcxproj.filters @@ -4,6 +4,9 @@ {0c0288ac-1168-4534-b3d3-051b9981f842} + + {20acf084-7e31-4b1e-beec-b99bac38a681} + {ef70fd67-8f30-467a-8af0-ea0d48837f04} @@ -33,6 +36,18 @@ + + GUI\Cheats + + + GUI\Cheats + + + GUI\Cheats + + + GUI\Cheats + GUI\Debugger @@ -105,9 +120,6 @@ GUI - - GUI - GUI @@ -126,9 +138,6 @@ GUI - - GUI - GUI @@ -162,6 +171,18 @@ + + GUI\Cheats + + + GUI\Cheats + + + GUI\Cheats + + + GUI\Cheats + GUI\Debugger @@ -231,9 +252,6 @@ GUI - - GUI - GUI @@ -246,9 +264,6 @@ GUI - - GUI - GUI diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index df0ea784d037..ac899aee1fc9 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -62,7 +62,6 @@ #include "DiscIO/NANDContentLoader.h" #include "DolphinWX/AboutDolphin.h" -#include "DolphinWX/CheatsWindow.h" #include "DolphinWX/ConfigMain.h" #include "DolphinWX/FifoPlayerDlg.h" #include "DolphinWX/Frame.h" @@ -78,6 +77,7 @@ #include "DolphinWX/WiimoteConfigDiag.h" #include "DolphinWX/WXInputBase.h" #include "DolphinWX/WxUtils.h" +#include "DolphinWX/Cheats/CheatsWindow.h" #include "DolphinWX/Debugger/CodeWindow.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" diff --git a/Source/Core/DolphinWX/ISOProperties.cpp b/Source/Core/DolphinWX/ISOProperties.cpp index 6e6ca808183b..34f59c1ab1ae 100644 --- a/Source/Core/DolphinWX/ISOProperties.cpp +++ b/Source/Core/DolphinWX/ISOProperties.cpp @@ -69,11 +69,11 @@ #include "DiscIO/Volume.h" #include "DiscIO/VolumeCreator.h" #include "DolphinWX/ARCodeAddEdit.h" -#include "DolphinWX/GeckoCodeDiag.h" #include "DolphinWX/ISOFile.h" #include "DolphinWX/ISOProperties.h" #include "DolphinWX/PatchAddEdit.h" #include "DolphinWX/WxUtils.h" +#include "DolphinWX/Cheats/GeckoCodeDiag.h" #include "DolphinWX/resources/isoprop_disc.xpm" #include "DolphinWX/resources/isoprop_file.xpm" #include "DolphinWX/resources/isoprop_folder.xpm" From 90eaf9519cdac1b0411249aaefaf34dd20edf4a7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 18 Oct 2014 21:12:44 -0400 Subject: [PATCH 2/4] CheatsWindow: Remove unnecessary wxPanel in the wxDialog We can simply size the controls within the dialog directly. --- Source/Core/DolphinWX/Cheats/CheatsWindow.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp index f151cf4aef45..9796f6a48c55 100644 --- a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp +++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp @@ -67,10 +67,8 @@ wxCheatsWindow::~wxCheatsWindow() void wxCheatsWindow::Init_ChildControls() { - wxPanel* const panel = new wxPanel(this); - // Main Notebook - m_notebook_main = new wxNotebook(panel, wxID_ANY); + m_notebook_main = new wxNotebook(this, wxID_ANY); // --- Tabs --- // Cheats List Tab @@ -130,9 +128,9 @@ void wxCheatsWindow::Init_ChildControls() m_notebook_main->AddPage(m_tab_log, _("Logging")); // Button Strip - m_button_apply = new wxButton(panel, wxID_APPLY, _("Apply")); + 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(panel, wxID_CANCEL, _("Cancel")); + wxButton* const button_cancel = new wxButton(this, wxID_CANCEL, _("Cancel")); button_cancel->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this); Bind(wxEVT_CLOSE_WINDOW, &wxCheatsWindow::OnEvent_Close, this); @@ -145,11 +143,7 @@ void wxCheatsWindow::Init_ChildControls() wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL); sMain->Add(m_notebook_main, 1, wxEXPAND|wxALL, 5); sMain->Add(sButtons, 0, wxRIGHT | wxBOTTOM | wxALIGN_RIGHT, 5); - panel->SetSizerAndFit(sMain); - - wxBoxSizer* const frame_szr = new wxBoxSizer(wxVERTICAL); - frame_szr->Add(panel, 1, wxEXPAND); - SetSizerAndFit(frame_szr); + SetSizerAndFit(sMain); } void wxCheatsWindow::OnEvent_ButtonClose_Press(wxCommandEvent& WXUNUSED (event)) From e7939a6b4422e55844642d9382ad1aac7e952f6d Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 18 Oct 2014 21:28:36 -0400 Subject: [PATCH 3/4] DolphinWX: Reimplement cheat listbox updating, but without a global Just use event handling. --- Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp | 1 + Source/Core/DolphinWX/Cheats/CheatsWindow.cpp | 6 ++++++ Source/Core/DolphinWX/Cheats/CheatsWindow.h | 1 + Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp | 6 ++++++ Source/Core/DolphinWX/Cheats/CreateCodeDialog.h | 4 +++- 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp b/Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp index 49781e826cbf..279ac5591500 100644 --- a/Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp +++ b/Source/Core/DolphinWX/Cheats/CheatSearchTab.cpp @@ -313,6 +313,7 @@ void CheatSearchTab::CreateARCode(wxCommandEvent&) const u32 address = m_search_results[sel].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(); } } diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp index 9796f6a48c55..03f63cf24204 100644 --- a/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp +++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.cpp @@ -134,6 +134,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); wxStdDialogButtonSizer* const sButtons = new wxStdDialogButtonSizer(); sButtons->AddButton(m_button_apply); @@ -243,6 +244,11 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemToggled(wxCommandEvent& WXUNUSED (ev } } +void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& event) +{ + Load_ARCodes(); +} + void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev) { // Apply AR Code changes diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.h b/Source/Core/DolphinWX/Cheats/CheatsWindow.h index 2a83909db66e..8586930fbc7c 100644 --- a/Source/Core/DolphinWX/Cheats/CheatsWindow.h +++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.h @@ -93,6 +93,7 @@ class wxCheatsWindow final : public wxDialog // Cheats List void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event); void OnEvent_CheatsList_ItemToggled(wxCommandEvent& event); + void OnEvent_CheatsList_Update(wxCommandEvent& event); // Apply Changes Button void OnEvent_ApplyChanges_Press(wxCommandEvent& event); diff --git a/Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp index b266e9d7ab45..aa4c0edbcc02 100644 --- a/Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp +++ b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.cpp @@ -17,6 +17,9 @@ #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, -1, _("Create AR Code")) , m_code_address(address) @@ -95,6 +98,9 @@ void CreateCodeDialog::PressOK(wxCommandEvent& ev) //ActionReplay::UpdateActiveList(); } + // Propagate back to the parent frame to update the cheat list. + GetEventHandler()->AddPendingEvent(wxCommandEvent(UPDATE_CHEAT_LIST_EVENT)); + Close(); } diff --git a/Source/Core/DolphinWX/Cheats/CreateCodeDialog.h b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.h index bcb10e92cc31..97aed1728d69 100644 --- a/Source/Core/DolphinWX/Cheats/CreateCodeDialog.h +++ b/Source/Core/DolphinWX/Cheats/CreateCodeDialog.h @@ -5,14 +5,16 @@ #pragma once #include +#include #include "Common/CommonTypes.h" class wxCheckBox; -class wxCommandEvent; class wxTextCtrl; class wxWindow; +wxDECLARE_EVENT(UPDATE_CHEAT_LIST_EVENT, wxCommandEvent); + class CreateCodeDialog final : public wxDialog { public: From 650192390c0ec683302b56cac89ea30b2920a9ea Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 18 Oct 2014 21:38:14 -0400 Subject: [PATCH 4/4] CheatsWindow: unfriend CreateCodeDialog. This is no longer needed. --- Source/Core/DolphinWX/Cheats/CheatsWindow.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Core/DolphinWX/Cheats/CheatsWindow.h b/Source/Core/DolphinWX/Cheats/CheatsWindow.h index 8586930fbc7c..ebe21be6e06d 100644 --- a/Source/Core/DolphinWX/Cheats/CheatsWindow.h +++ b/Source/Core/DolphinWX/Cheats/CheatsWindow.h @@ -36,8 +36,6 @@ namespace Gecko class wxCheatsWindow final : public wxDialog { - friend class CreateCodeDialog; - public: wxCheatsWindow(wxWindow* const parent); ~wxCheatsWindow();