summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DolphinWX/Src/CheatsWindow.cpp557
-rw-r--r--Source/Core/DolphinWX/Src/CheatsWindow.h101
-rw-r--r--Source/Core/DolphinWX/Src/FrameTools.cpp2
-rw-r--r--Source/Core/DolphinWX/Src/ISOProperties.h5
4 files changed, 550 insertions, 115 deletions
diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.cpp b/Source/Core/DolphinWX/Src/CheatsWindow.cpp
index 12e1bf1a6b..1fd0925654 100644
--- a/Source/Core/DolphinWX/Src/CheatsWindow.cpp
+++ b/Source/Core/DolphinWX/Src/CheatsWindow.cpp
@@ -19,128 +19,214 @@
#include "CheatsWindow.h"
#include "ActionReplay.h"
#include "Core.h"
+#include "ConfigManager.h"
+#include "ISOProperties.h"
+#include "HW/Memmap.h"
-using namespace ActionReplay;
+#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler(f), (wxObject*)0, (wxEvtHandler*)s)
-BEGIN_EVENT_TABLE(wxCheatsWindow, wxWindow)
- EVT_SIZE( wxCheatsWindow::OnEvent_Window_Resize)
- EVT_CLOSE( wxCheatsWindow::OnEvent_Window_Close)
- EVT_BUTTON(ID_BUTTON_CLOSE, wxCheatsWindow::OnEvent_ButtonClose_Press)
- EVT_LISTBOX(ID_CHECKLISTBOX_CHEATSLIST, wxCheatsWindow::OnEvent_CheatsList_ItemSelected)
- EVT_CHECKLISTBOX(ID_CHECKLISTBOX_CHEATSLIST, wxCheatsWindow::OnEvent_CheatsList_ItemToggled)
- EVT_BUTTON(ID_BUTTON_APPLYCODES, wxCheatsWindow::OnEvent_ButtonUpdateCodes_Press)
- EVT_BUTTON(ID_BUTTON_UPDATELOG, wxCheatsWindow::OnEvent_ButtonUpdateLog_Press)
- EVT_CHECKBOX(ID_CHECKBOX_LOGAR, wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange)
-END_EVENT_TABLE()
+#define MAX_CHEAT_SEARCH_RESULTS_DISPLAY 256
-wxCheatsWindow::wxCheatsWindow(wxFrame* parent, const wxPoint& pos, const wxSize& size) :
- wxFrame(parent, wxID_ANY, _T("Action Replay"), pos, size, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
+extern std::vector<ActionReplay::ARCode> arCodes;
+
+// meh
+static wxCheatsWindow *g_cheat_window;
+
+wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
+ : wxFrame(parent, wxID_ANY, wxT("Action Replay"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
{
+ ::g_cheat_window = this;
+
// Create the GUI controls
Init_ChildControls();
- // Setup Window
- SetBackgroundColour(wxColour(COLOR_GRAY));
- SetSize(size);
- SetPosition(pos);
-
// Load Data
Load_ARCodes();
- Layout();
+ Center();
Show();
}
-wxCheatsWindow::~wxCheatsWindow()
-{
- // On Disposal
-}
-
void wxCheatsWindow::Init_ChildControls()
{
+ wxPanel* const panel = new wxPanel(this);
+
// Main Notebook
- m_Notebook_Main = new wxNotebook(this, ID_NOTEBOOK_MAIN, wxDefaultPosition, wxDefaultSize);
- // --- Tabs ---
- // $ Cheats List Tab
- m_Tab_Cheats = new wxPanel(m_Notebook_Main, ID_TAB_CHEATS, wxDefaultPosition, wxDefaultSize);
- m_CheckListBox_CheatsList = new wxCheckListBox(m_Tab_Cheats, ID_CHECKLISTBOX_CHEATSLIST, wxDefaultPosition, wxSize(300, 0), m_CheatStringList, wxLB_HSCROLL, wxDefaultValidator);
- m_Label_Codename = new wxStaticText(m_Tab_Cheats, ID_LABEL_CODENAME, _T("Name: "), wxDefaultPosition, wxDefaultSize);
- m_GroupBox_Info = new wxStaticBox(m_Tab_Cheats, ID_GROUPBOX_INFO, _T("Code Info"), wxDefaultPosition, wxDefaultSize);
- m_Button_ApplyCodes = new wxButton(m_Tab_Cheats, ID_BUTTON_APPLYCODES, _T("Apply Changes"), wxDefaultPosition, wxDefaultSize);
- m_Label_NumCodes = new wxStaticText(m_Tab_Cheats, ID_LABEL_NUMCODES, _T("Number Of Codes: "), wxDefaultPosition, wxDefaultSize);
- m_ListBox_CodesList = new wxListBox(m_Tab_Cheats, ID_LISTBOX_CODESLIST, wxDefaultPosition, wxSize(120, 150), 0, 0, wxLB_HSCROLL);
+ m_Notebook_Main = new wxNotebook(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize);
+
+ // --- Tabs ---
+ // $ Cheats List Tab
+ m_Tab_Cheats = new wxPanel(m_Notebook_Main, wxID_ANY, wxDefaultPosition, wxDefaultSize);
- wxBoxSizer* sCheatsListH = new wxBoxSizer(wxHORIZONTAL);
- sCheatsListH->Add(m_CheckListBox_CheatsList, 1, wxALL|wxEXPAND, 5);
+ m_CheckListBox_CheatsList = new wxCheckListBox(m_Tab_Cheats, wxID_ANY, wxDefaultPosition, wxSize(300, 0), m_CheatStringList, wxLB_HSCROLL, wxDefaultValidator);
+ _connect_macro_(m_CheckListBox_CheatsList, wxCheatsWindow::OnEvent_CheatsList_ItemSelected, wxEVT_COMMAND_LISTBOX_SELECTED, this);
+ _connect_macro_(m_CheckListBox_CheatsList, wxCheatsWindow::OnEvent_CheatsList_ItemToggled, wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, this);
- 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, 0, wxALL, 5);
+ m_Label_Codename = new wxStaticText(m_Tab_Cheats, wxID_ANY, _T("Name: "), wxDefaultPosition, wxDefaultSize);
+ m_GroupBox_Info = new wxStaticBox(m_Tab_Cheats, wxID_ANY, _T("Code Info"), wxDefaultPosition, wxDefaultSize);
+
+ wxButton* const button_applycodes = new wxButton(m_Tab_Cheats, wxID_ANY, _T("Apply Changes"), wxDefaultPosition, wxDefaultSize);
+ _connect_macro_(button_applycodes, wxCheatsWindow::OnEvent_ButtonUpdateCodes_Press, wxEVT_COMMAND_BUTTON_CLICKED, this);
- wxBoxSizer* sB1 = new wxBoxSizer(wxVERTICAL);
- sB1->Add(m_Button_ApplyCodes, 0, wxALL, 5);
- sB1->Add(sGroupBoxInfo, 0, wxALL, 5);
+ m_Label_NumCodes = new wxStaticText(m_Tab_Cheats, wxID_ANY, _T("Number Of Codes: "), wxDefaultPosition, wxDefaultSize);
+ m_ListBox_CodesList = new wxListBox(m_Tab_Cheats, wxID_ANY, wxDefaultPosition, wxSize(120, 150), 0, 0, wxLB_HSCROLL);
- m_Sizer_TabCheats = new wxGridBagSizer();
- m_Sizer_TabCheats->AddGrowableRow(0);
- m_Sizer_TabCheats->Add(sCheatsListH, wxGBPosition(0, 0), wxGBSpan(1, 1), wxEXPAND|wxALL, 5);
- m_Sizer_TabCheats->Add(sB1, wxGBPosition(0, 1), wxGBSpan(1, 1), wxALIGN_LEFT|wxALL, 5);
+ 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);
- m_Tab_Cheats->SetSizer(m_Sizer_TabCheats);
- m_Tab_Cheats->Layout();
+ wxBoxSizer* sB1 = new wxBoxSizer(wxVERTICAL);
+ sB1->Add(button_applycodes, 0, wxALL | wxEXPAND, 5);
+ sB1->Add(sGroupBoxInfo, 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(sB1, 0, wxALIGN_LEFT | wxEXPAND | wxALL, 5);
- // $ Log Tab
- m_Tab_Log = new wxPanel(m_Notebook_Main, ID_TAB_LOG, wxDefaultPosition, wxDefaultSize);
+ m_Tab_Cheats->SetSizerAndFit(sizer_tab_cheats);
- m_Button_UpdateLog = new wxButton(m_Tab_Log, ID_BUTTON_UPDATELOG, wxT("Update"));
- m_CheckBox_LogAR = new wxCheckBox(m_Tab_Log, ID_CHECKBOX_LOGAR, wxT("Enable AR Logging"));
- m_CheckBox_LogAR->SetValue(IsSelfLogging());
- m_TextCtrl_Log = new wxTextCtrl(m_Tab_Log, ID_TEXTCTRL_LOG, wxT(""), wxDefaultPosition, wxSize(100, 600), wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
+ // $ Cheat Search Tab
+ wxPanel* const tab_cheat_search = new CheatSearchTab(m_Notebook_Main);
- wxBoxSizer *HStrip1 = new wxBoxSizer(wxHORIZONTAL);
- HStrip1->Add(m_CheckBox_LogAR, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5);
- HStrip1->Add(m_Button_UpdateLog, 0, wxALL, 5);
+ // $ Log Tab
+ m_Tab_Log = new wxPanel(m_Notebook_Main, wxID_ANY, wxDefaultPosition, wxDefaultSize);
- wxBoxSizer *sTabLog = new wxBoxSizer(wxVERTICAL);
- sTabLog->Add(HStrip1, 0, wxALL, 5);
- sTabLog->Add(m_TextCtrl_Log, 1, wxALL|wxEXPAND, 5);
+ wxButton* const button_updatelog = new wxButton(m_Tab_Log, wxID_ANY, wxT("Update"));
+ _connect_macro_(button_updatelog, wxCheatsWindow::OnEvent_ButtonUpdateLog_Press, wxEVT_COMMAND_BUTTON_CLICKED, this);
- m_Tab_Log->SetSizer(sTabLog);
- m_Tab_Log->Layout();
+ m_CheckBox_LogAR = new wxCheckBox(m_Tab_Log, wxID_ANY, wxT("Enable AR Logging"));
+ _connect_macro_(m_CheckBox_LogAR, wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange, wxEVT_COMMAND_CHECKBOX_CLICKED, this);
+
+ m_CheckBox_LogAR->SetValue(ActionReplay::IsSelfLogging());
+ m_TextCtrl_Log = new wxTextCtrl(m_Tab_Log, wxID_ANY, wxT(""), 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, _T("Codes List"));
+ m_Notebook_Main->AddPage(tab_cheat_search, _T("Cheat Search"));
m_Notebook_Main->AddPage(m_Tab_Log, _T("Logging"));
// Button Strip
- m_Button_Close = new wxButton(this, ID_BUTTON_CLOSE, _T("Close"), wxDefaultPosition, wxDefaultSize);
+ wxButton* const button_close = new wxButton(panel, wxID_ANY, _T("Close"), wxDefaultPosition, wxDefaultSize);
+ _connect_macro_(button_close, wxCheatsWindow::OnEvent_ButtonClose_Press, wxEVT_COMMAND_BUTTON_CLICKED, this);
wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
- sButtons->Add(m_Button_Close, 0, wxALL, 5);
+ sButtons->Add(button_close, 1, 0, 0);
- wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
+ wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL);
sMain->Add(m_Notebook_Main, 1, wxEXPAND|wxALL, 5);
- sMain->Add(sButtons, 0, wxALL, 5);
- SetSizer(sMain);
- Layout();
+ sMain->Add(sButtons, 0, wxRIGHT | wxBOTTOM | wxALIGN_RIGHT, 5);
+ panel->SetSizerAndFit(sMain);
- Fit();
+ wxBoxSizer* const frame_szr = new wxBoxSizer(wxVERTICAL);
+ frame_szr->Add(panel, 1, wxEXPAND);
+ SetSizerAndFit(frame_szr);
}
-void wxCheatsWindow::OnEvent_Window_Resize(wxSizeEvent& WXUNUSED (event))
+
+CheatSearchTab::CheatSearchTab(wxWindow* const parent)
+ : wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize)
{
- Layout();
+ // new search box
+ size_radiobtn.rad_8 = new wxRadioButton(this, -1, wxT("8 bit"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
+ size_radiobtn.rad_16 = new wxRadioButton(this, -1, wxT("16 bit"));
+ size_radiobtn.rad_32 = new wxRadioButton(this, -1, wxT("32 bit"));
+ size_radiobtn.rad_8->SetValue(true);
+
+ wxButton* const button_start_search = new wxButton(this, -1, wxT("Start"));
+ _connect_macro_(button_start_search, CheatSearchTab::StartNewSearch, wxEVT_COMMAND_BUTTON_CLICKED, this);
+
+ wxStaticBoxSizer* const sizer_cheat_new_search = new wxStaticBoxSizer(wxHORIZONTAL, this, wxT("New Search"));
+ sizer_cheat_new_search->Add(size_radiobtn.rad_8, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
+ sizer_cheat_new_search->Add(size_radiobtn.rad_16, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
+ sizer_cheat_new_search->Add(size_radiobtn.rad_32, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
+ sizer_cheat_new_search->Add(button_start_search, 0, wxRIGHT | wxBOTTOM | wxALIGN_CENTER_VERTICAL, 5);
+
+ // results box
+ lbox_search_results = new wxListBox(this, -1, wxDefaultPosition, wxDefaultSize);
+ label_results_count = new wxStaticText(this, -1, wxT("Count:"));
+
+ wxButton* const button_cheat_search_copy_address = new wxButton(this, -1, wxT("Create AR Code"));
+ _connect_macro_(button_cheat_search_copy_address, CheatSearchTab::CreateARCode, wxEVT_COMMAND_BUTTON_CLICKED, this);
+
+ wxStaticBoxSizer* const sizer_cheat_search_results = new wxStaticBoxSizer(wxVERTICAL, this, wxT("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);
+
+ // filter box
+ // x value box
+ value_x_radiobtn.rad_oldvalue = new wxRadioButton(this, -1, wxT("Old Value"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
+ value_x_radiobtn.rad_uservalue = new wxRadioButton(this, -1, wxT(""));
+ value_x_radiobtn.rad_oldvalue->SetValue(true);
+
+ textctrl_value_x = new wxTextCtrl(this, -1, wxT("0x0"), wxDefaultPosition, wxSize(96,-1));
+
+ 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);
+
+ wxStaticBoxSizer* const sizer_cheat_search_filter_x = new wxStaticBoxSizer(wxVERTICAL, this, wxT("X"));
+ 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, 5);
+
+ // filter types
+ filter_radiobtn.rad_none = new wxRadioButton(this, -1, wxT("None"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
+ filter_radiobtn.rad_notequal = new wxRadioButton(this, -1, wxT("!= X"));
+ filter_radiobtn.rad_equal = new wxRadioButton(this, -1, wxT("= X"));
+ filter_radiobtn.rad_greater = new wxRadioButton(this, -1, wxT("> X"));
+ filter_radiobtn.rad_less = new wxRadioButton(this, -1, wxT("< X"));
+ filter_radiobtn.rad_none->SetValue(true);
+
+ wxStaticBoxSizer* const sizer_cheat_search_filter = new wxStaticBoxSizer(wxVERTICAL, this, wxT("Search Filter"));
+ sizer_cheat_search_filter->Add(sizer_cheat_search_filter_x, 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
+ sizer_cheat_search_filter->Add(filter_radiobtn.rad_none, 0, wxALL, 5);
+ sizer_cheat_search_filter->Add(filter_radiobtn.rad_notequal, 0, wxALL, 5);
+ sizer_cheat_search_filter->Add(filter_radiobtn.rad_equal, 0, wxALL, 5);
+ sizer_cheat_search_filter->Add(filter_radiobtn.rad_greater, 0, wxALL, 5);
+ sizer_cheat_search_filter->Add(filter_radiobtn.rad_less, 0, wxALL, 5);
+
+ wxButton* const button_cheat_search_update = new wxButton(this, -1, wxT("Search"));
+ _connect_macro_(button_cheat_search_update, CheatSearchTab::FilterCheatSearchResults, wxEVT_COMMAND_BUTTON_CLICKED, this);
+
+ // left sizer
+ wxBoxSizer* const sizer_left = new wxBoxSizer(wxVERTICAL);
+ sizer_left->Add(sizer_cheat_new_search, 0, wxBOTTOM, 5);
+ sizer_left->Add(sizer_cheat_search_results, 1, wxEXPAND, 5);
+
+ // right sizer
+ wxBoxSizer* const sizer_right = new wxBoxSizer(wxVERTICAL);
+ sizer_right->Add(sizer_cheat_search_filter, 0, wxEXPAND | wxBOTTOM, 5);
+ sizer_right->AddStretchSpacer(1);
+ sizer_right->Add(button_cheat_search_update, 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))
{
Destroy();
}
-void wxCheatsWindow::OnEvent_Window_Close(wxCloseEvent& WXUNUSED (event))
-{
- Destroy();
-}
+
void wxCheatsWindow::Load_ARCodes()
{
+ using namespace ActionReplay;
+
+ m_CheckListBox_CheatsList->Clear();
+
indexList.clear();
size_t size = GetCodeListSize();
for (size_t i = 0; i < size; i++)
@@ -154,8 +240,11 @@ void wxCheatsWindow::Load_ARCodes()
indexList.push_back(ind);
}
}
+
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++)
{
@@ -177,8 +266,8 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& WXUNUSED (e
}
}
}
- m_Sizer_TabCheats->Layout();
}
+
void wxCheatsWindow::OnEvent_CheatsList_ItemToggled(wxCommandEvent& WXUNUSED (event))
{
int index = m_CheckListBox_CheatsList->GetSelection();
@@ -186,22 +275,23 @@ void wxCheatsWindow::OnEvent_CheatsList_ItemToggled(wxCommandEvent& WXUNUSED (ev
{
if ((int)indexList[i].uiIndex == index)
{
- SetARCode_IsActive(m_CheckListBox_CheatsList->IsChecked(index), indexList[i].index);
+ ActionReplay::SetARCode_IsActive(m_CheckListBox_CheatsList->IsChecked(index), indexList[i].index);
}
}
}
+
void wxCheatsWindow::OnEvent_ButtonUpdateCodes_Press(wxCommandEvent& WXUNUSED (event))
{
for (size_t i = 0; i < indexList.size(); i++)
{
- SetARCode_IsActive(m_CheckListBox_CheatsList->IsChecked(indexList[i].uiIndex), indexList[i].index);
+ ActionReplay::SetARCode_IsActive(m_CheckListBox_CheatsList->IsChecked(indexList[i].uiIndex), indexList[i].index);
}
}
void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (event))
{
m_TextCtrl_Log->Clear();
- const std::vector<std::string> &arLog = GetSelfLog();
+ const std::vector<std::string> &arLog = ActionReplay::GetSelfLog();
for (u32 i = 0; i < arLog.size(); i++)
{
m_TextCtrl_Log->AppendText(wxString::FromAscii(arLog[i].c_str()));
@@ -210,5 +300,310 @@ void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED (eve
void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& WXUNUSED (event))
{
- EnableSelfLogging(m_CheckBox_LogAR->IsChecked());
+ ActionReplay::EnableSelfLogging(m_CheckBox_LogAR->IsChecked());
+}
+
+void CheatSearchTab::StartNewSearch(wxCommandEvent& WXUNUSED (event))
+{
+ search_results.clear();
+
+ search_type_size =
+ size_radiobtn.rad_8->GetValue() +
+ (size_radiobtn.rad_16->GetValue() << 1) +
+ (size_radiobtn.rad_32->GetValue() << 2);
+
+ const u8* const memptr = Memory::GetPointer(0);
+ if (NULL == memptr)
+ {
+ PanicAlert("A game is not currently running.");
+ }
+ else
+ {
+ 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 (NULL == memptr)
+ {
+ PanicAlert("A game is not currently running.");
+ }
+ else
+ {
+ std::vector<CheatSearchResult>::iterator
+ i = search_results.begin(),
+ e = search_results.end();
+ std::vector<CheatSearchResult> filtered_results;
+
+ int filter_mask = 0;
+ // determine the selected filter
+ // 1 : equal
+ // 2 : greater-than
+ // 4 : less-than
+ if (filter_radiobtn.rad_none->GetValue())
+ filter_mask = 7;
+ else if (filter_radiobtn.rad_notequal->GetValue())
+ filter_mask = 6;
+ else if (filter_radiobtn.rad_equal->GetValue())
+ filter_mask = 1;
+ else if (filter_radiobtn.rad_greater->GetValue())
+ filter_mask = 2;
+ else if (filter_radiobtn.rad_less->GetValue())
+ filter_mask = 4;
+
+
+ if (value_x_radiobtn.rad_oldvalue->GetValue()) // using old value comparison
+ {
+ for (; i!=e; ++i)
+ {
+ // with big endian, can just use memcmp for ><= comparison
+ int cmp_result = memcmp(memptr + i->address, &i->old_value, 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(&i->old_value, memptr + i->address, search_type_size);
+ filtered_results.push_back(*i);
+ }
+ }
+ }
+ 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
+ {
+ long parsed_x_val = 0;
+ int val_base = 10;
+
+ wxString x_val = textctrl_value_x->GetLabel();
+ if (wxT("0x") == x_val.substr(0,2))
+ {
+ //x_val = x_val.substr(2); // wxwidgets seems fine parsing a "0x0000" string
+ val_base = 16;
+ }
+
+ if (false == x_val.ToLong(&parsed_x_val, val_base))
+ {
+ PanicAlert("You must enter a valid decimal or hex 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 <u32 vals (8/16bit) to start of the user_x_val for the comparisons i use below
+ // #endif
+ }
+
+ for (; i!=e; ++i)
+ {
+ // with big endian, can just use memcmp for ><= comparison
+ int cmp_result = memcmp(memptr + i->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(&i->old_value, memptr + i->address, search_type_size);
+ filtered_results.push_back(*i);
+ }
+ }
+ }
+
+ search_results.swap(filtered_results);
+
+ UpdateCheatSearchResultsList();
+ }
+}
+
+void CheatSearchTab::UpdateCheatSearchResultsList()
+{
+ lbox_search_results->Clear();
+
+ wxString count_label = wxString::Format(wxT("Count: %i"), search_results.size());
+ if (search_results.size() > MAX_CHEAT_SEARCH_RESULTS_DISPLAY)
+ {
+ count_label += wxT(" (too many to display)");
+ }
+ else
+ {
+ std::vector<CheatSearchResult>::const_iterator
+ i = search_results.begin(),
+ e = search_results.end();
+ for (; i!=e; ++i)
+ {
+ u32 display_value = i->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
+
+ static wxChar rowfmt[] = wxT("0x%08x 0x%0|x %u/%i");
+ rowfmt[14] = (wxChar)(wxT('0') + search_type_size*2);
+
+ lbox_search_results->Append(
+ wxString::Format(rowfmt, i->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* const arcode_dlg = new CreateCodeDialog(this, address);
+ arcode_dlg->ShowModal();
+ }
+}
+
+CreateCodeDialog::CreateCodeDialog(wxWindow* const parent, const u32 address)
+ : wxDialog(parent, -1, wxT("Create AR Code"), wxDefaultPosition)
+ , code_address(address)
+{
+ wxPanel* const panel = new wxPanel(this);
+
+ wxStaticText* const label_name = new wxStaticText(panel, -1, wxT("Name: "));
+ textctrl_name = new wxTextCtrl(panel, -1, wxEmptyString, wxDefaultPosition, wxSize(256,-1));
+
+ wxStaticText* const label_code = new wxStaticText(panel, -1, wxT("Code: "));
+ textctrl_code = new wxTextCtrl(panel, -1, wxString::Format(wxT("0x%08x"), address));
+ textctrl_code->Disable();
+
+ wxStaticText* const label_value = new wxStaticText(panel, -1, wxT("Value: "));
+ textctrl_value = new wxTextCtrl(panel, -1, wxT("0"));
+
+ checkbox_use_hex = new wxCheckBox(panel, -1, wxT("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, 0, 0, 0);
+
+ wxButton* const btn_ok = new wxButton(panel, -1, wxT("OK"));
+ _connect_macro_(btn_ok, CreateCodeDialog::PressOK, wxEVT_COMMAND_BUTTON_CLICKED, this);
+ wxButton* const btn_cancel = new wxButton(panel, -1, wxT("Cancel"));
+ _connect_macro_(btn_cancel, CreateCodeDialog::PressCancel, wxEVT_COMMAND_BUTTON_CLICKED, this);
+
+ // button sizer
+ wxBoxSizer* const sizer_buttons = new wxBoxSizer(wxHORIZONTAL);
+ sizer_buttons->Add(btn_ok, 0, wxRIGHT, 5);
+ sizer_buttons->Add(btn_cancel, 0, 0, 0);
+
+ // main sizer
+ wxBoxSizer* const sizer_panel = new wxBoxSizer(wxVERTICAL);
+ sizer_panel->Add(label_name, 0, wxALL, 5);
+ sizer_panel->Add(textctrl_name, 0, wxALL, 5);
+ sizer_panel->Add(label_code, 0, wxALL, 5);
+ sizer_panel->Add(textctrl_code, 0, wxALL, 5);
+ sizer_panel->Add(sizer_value_label, 0, wxALL, 5);
+ sizer_panel->Add(textctrl_value, 0, wxALL, 5);
+ sizer_panel->Add(sizer_buttons, 0, wxALL | wxALIGN_RIGHT, 5);
+
+ panel->SetSizerAndFit(sizer_panel);
+
+ // panel sizer
+ wxBoxSizer* const sizer_main = new wxBoxSizer(wxHORIZONTAL);
+ sizer_main->Add(panel, 1, wxEXPAND, 5);
+
+ SetSizerAndFit(sizer_main);
+}
+
+void CreateCodeDialog::PressOK(wxCommandEvent&)
+{
+ const wxString code_name = textctrl_name->GetValue();
+ if (code_name.empty())
+ {
+ PanicAlert("You must enter a name!");
+ return;
+ }
+
+ long code_value;
+ if (false == textctrl_value->GetValue().ToLong(&code_value, 10 + checkbox_use_hex->GetValue()*6))
+ {
+ PanicAlert("Invalid Value!");
+ return;
+ }
+
+ //wxString full_code = textctrl_code->GetValue();
+ //full_code += wxT(' ');
+ //full_code += wxString::Format(wxT("0x%08x"), code_value);
+
+ // create the new code
+ ActionReplay::ARCode new_cheat;
+ new_cheat.active = false;
+ new_cheat.name = std::string(code_name.ToAscii());
+ 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();
+
+ Destroy();
+}
+
+void CreateCodeDialog::PressCancel(wxCommandEvent&)
+{
+ Destroy();
}
diff --git a/Source/Core/DolphinWX/Src/CheatsWindow.h b/Source/Core/DolphinWX/Src/CheatsWindow.h
index 79da56dde7..73b04e6dcb 100644
--- a/Source/Core/DolphinWX/Src/CheatsWindow.h
+++ b/Source/Core/DolphinWX/Src/CheatsWindow.h
@@ -25,24 +25,90 @@
#include <wx/imaglist.h>
#include <wx/treectrl.h>
#include <wx/gbsizer.h>
+#include <wx/textctrl.h>
#include <wx/notebook.h>
#include <wx/mimetype.h>
#include <wx/colour.h>
#include <wx/listbox.h>
+
#include <string>
+#include <vector>
#include "ActionReplay.h"
#include "Filesystem.h"
#include "IniFile.h"
-class wxCheatsWindow : public wxFrame
+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&);
+};
+
+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<CheatSearchResult> search_results;
+ unsigned int search_type_size;
+
+ wxListBox* lbox_search_results;
+ wxStaticText* label_results_count;
+ wxTextCtrl* textctrl_value_x;
+
+ struct
+ {
+ wxRadioButton *rad_8, *rad_16, *rad_32;
- wxCheatsWindow(wxFrame* parent, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
+ } size_radiobtn;
- virtual ~wxCheatsWindow();
+ struct
+ {
+ wxRadioButton *rad_none, *rad_equal, *rad_notequal, *rad_greater, *rad_less;
+
+ } filter_radiobtn;
+
+ struct
+ {
+ wxRadioButton *rad_oldvalue, *rad_uservalue;
+
+ } value_x_radiobtn;
+
+ void UpdateCheatSearchResultsList();
+
+ void StartNewSearch(wxCommandEvent& event);
+ void FilterCheatSearchResults(wxCommandEvent& event);
+ void CreateARCode(wxCommandEvent&);
+};
+
+class wxCheatsWindow : public wxFrame
+{
+ friend class CreateCodeDialog;
+
+ public:
+ wxCheatsWindow(wxWindow* const parent);
protected:
@@ -52,20 +118,14 @@ class wxCheatsWindow : public wxFrame
};
// Event Table
- DECLARE_EVENT_TABLE();
+ //DECLARE_EVENT_TABLE();
// --- GUI Controls ---
- wxGridBagSizer* m_Sizer_TabCheats;
-
wxNotebook *m_Notebook_Main;
wxPanel *m_Tab_Cheats;
wxPanel *m_Tab_Log;
- wxButton *m_Button_Close;
- wxButton *m_Button_ApplyCodes;
- wxButton *m_Button_UpdateLog;
-
wxCheckBox *m_CheckBox_LogAR;
wxStaticText *m_Label_Codename;
@@ -83,32 +143,11 @@ class wxCheatsWindow : public wxFrame
std::vector<ARCodeIndex> indexList;
- // GUI IDs
- enum
- {
- ID_NOTEBOOK_MAIN,
- ID_TAB_CHEATS,
- ID_TAB_LOG,
- ID_BUTTON_CLOSE,
- ID_CHECKLISTBOX_CHEATSLIST,
- ID_LABEL_CODENAME,
- ID_GROUPBOX_INFO,
- ID_BUTTON_APPLYCODES,
- ID_LABEL_NUMCODES,
- ID_LISTBOX_CODESLIST,
- ID_BUTTON_UPDATELOG,
- ID_CHECKBOX_LOGAR,
- ID_TEXTCTRL_LOG
- };
-
void Init_ChildControls();
void Load_ARCodes();
// --- Wx Events Handlers ---
- // $ Window
- void OnEvent_Window_Resize(wxSizeEvent& event);
- void OnEvent_Window_Close(wxCloseEvent& event);
// $ Close Button
void OnEvent_ButtonClose_Press(wxCommandEvent& event);
diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp
index 2ec31b816f..af1589f41c 100644
--- a/Source/Core/DolphinWX/Src/FrameTools.cpp
+++ b/Source/Core/DolphinWX/Src/FrameTools.cpp
@@ -1059,7 +1059,7 @@ void CFrame::OnOpenLuaWindow(wxCommandEvent& WXUNUSED (event))
void CFrame::OnShow_CheatsWindow(wxCommandEvent& WXUNUSED (event))
{
- CheatsWindow = new wxCheatsWindow(this, wxDefaultPosition, wxSize(600, 390));
+ CheatsWindow = new wxCheatsWindow(this);
}
void CFrame::OnLoadWiiMenu(wxCommandEvent& event)
diff --git a/Source/Core/DolphinWX/Src/ISOProperties.h b/Source/Core/DolphinWX/Src/ISOProperties.h
index 8aa58a491f..3ea5973dbe 100644
--- a/Source/Core/DolphinWX/Src/ISOProperties.h
+++ b/Source/Core/DolphinWX/Src/ISOProperties.h
@@ -51,6 +51,9 @@ class CISOProperties : public wxDialog
bool bRefreshList;
+ void ActionReplayList_Load();
+ bool SaveGameConfig();
+
private:
DECLARE_EVENT_TABLE();
@@ -249,10 +252,8 @@ class CISOProperties : public wxDialog
std::string GameIniFile;
void LoadGameConfig();
- bool SaveGameConfig();
void PatchList_Load();
void PatchList_Save();
- void ActionReplayList_Load();
void ActionReplayList_Save();
void ChangeBannerDetails(int lang);
};