mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-30 09:39:46 -06:00
Reformat all the things. Have fun with merge conflicts.
This commit is contained in:
@ -23,328 +23,329 @@
|
||||
#include "Core/ActionReplay.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "DolphinWX/Cheats/CheatSearchTab.h"
|
||||
#include "DolphinWX/Cheats/CreateCodeDialog.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int MAX_CHEAT_SEARCH_RESULTS_DISPLAY = 1024;
|
||||
const unsigned int MAX_CHEAT_SEARCH_RESULTS_DISPLAY = 1024;
|
||||
}
|
||||
|
||||
CheatSearchTab::CheatSearchTab(wxWindow* const parent)
|
||||
: wxPanel(parent)
|
||||
CheatSearchTab::CheatSearchTab(wxWindow* const parent) : wxPanel(parent)
|
||||
{
|
||||
m_update_timer.SetOwner(this);
|
||||
Bind(wxEVT_TIMER, &CheatSearchTab::OnTimerUpdate, this);
|
||||
m_update_timer.SetOwner(this);
|
||||
Bind(wxEVT_TIMER, &CheatSearchTab::OnTimerUpdate, this);
|
||||
|
||||
// first scan button
|
||||
m_btn_init_scan = new wxButton(this, wxID_ANY, _("New Scan"));
|
||||
m_btn_init_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::OnNewScanClicked, this);
|
||||
// first scan button
|
||||
m_btn_init_scan = new wxButton(this, wxID_ANY, _("New Scan"));
|
||||
m_btn_init_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::OnNewScanClicked, this);
|
||||
|
||||
// next scan button
|
||||
m_btn_next_scan = new wxButton(this, wxID_ANY, _("Next Scan"));
|
||||
m_btn_next_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::OnNextScanClicked, this);
|
||||
m_btn_next_scan->Disable();
|
||||
// next scan button
|
||||
m_btn_next_scan = new wxButton(this, wxID_ANY, _("Next Scan"));
|
||||
m_btn_next_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::OnNextScanClicked, this);
|
||||
m_btn_next_scan->Disable();
|
||||
|
||||
// data sizes radiobox
|
||||
std::array<wxString, 3> data_size_names = { { _("8-bit"), _("16-bit"), _("32-bit") } };
|
||||
m_data_sizes = new wxRadioBox(this, wxID_ANY, _("Data Size"), wxDefaultPosition, wxDefaultSize, static_cast<int>(data_size_names.size()), data_size_names.data());
|
||||
// data sizes radiobox
|
||||
std::array<wxString, 3> data_size_names = {{_("8-bit"), _("16-bit"), _("32-bit")}};
|
||||
m_data_sizes = new wxRadioBox(this, wxID_ANY, _("Data Size"), wxDefaultPosition, wxDefaultSize,
|
||||
static_cast<int>(data_size_names.size()), data_size_names.data());
|
||||
|
||||
// ListView for search results
|
||||
m_lview_search_results = new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SINGLE_SEL);
|
||||
ResetListViewColumns();
|
||||
// ListView for search results
|
||||
m_lview_search_results = new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxLC_REPORT | wxLC_SINGLE_SEL);
|
||||
ResetListViewColumns();
|
||||
|
||||
// Result count
|
||||
m_label_results_count = new wxStaticText(this, wxID_ANY, _("Count:"));
|
||||
// Result count
|
||||
m_label_results_count = new wxStaticText(this, wxID_ANY, _("Count:"));
|
||||
|
||||
// create AR code button
|
||||
wxButton* const button_cheat_search_copy_address = new wxButton(this, wxID_ANY, _("Create AR Code"));
|
||||
button_cheat_search_copy_address->Bind(wxEVT_BUTTON, &CheatSearchTab::OnCreateARCodeClicked, this);
|
||||
// create AR code button
|
||||
wxButton* const button_cheat_search_copy_address =
|
||||
new wxButton(this, wxID_ANY, _("Create AR Code"));
|
||||
button_cheat_search_copy_address->Bind(wxEVT_BUTTON, &CheatSearchTab::OnCreateARCodeClicked,
|
||||
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_lview_search_results, 1, wxEXPAND | wxALL, 5);
|
||||
sizer_cheat_search_results->Add(button_cheat_search_copy_address, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
|
||||
// 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_lview_search_results, 1, wxEXPAND | wxALL, 5);
|
||||
sizer_cheat_search_results->Add(button_cheat_search_copy_address, 0,
|
||||
wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
|
||||
|
||||
// search value textbox
|
||||
m_textctrl_value_x = new wxTextCtrl(this, wxID_ANY, "0x0", wxDefaultPosition, wxSize(96, -1));
|
||||
// search value textbox
|
||||
m_textctrl_value_x = new wxTextCtrl(this, wxID_ANY, "0x0", wxDefaultPosition, wxSize(96, -1));
|
||||
|
||||
wxBoxSizer* const sizer_cheat_filter_text = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_cheat_filter_text->Add(m_textctrl_value_x, 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
wxBoxSizer* const sizer_cheat_filter_text = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_cheat_filter_text->Add(m_textctrl_value_x, 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
// Filter types in the compare dropdown
|
||||
// TODO: Implement between search
|
||||
wxArrayString filters;
|
||||
filters.Add(_("Unknown"));
|
||||
filters.Add(_("Not Equal"));
|
||||
filters.Add(_("Equal"));
|
||||
filters.Add(_("Greater Than"));
|
||||
filters.Add(_("Less Than"));
|
||||
// Filter types in the compare dropdown
|
||||
// TODO: Implement between search
|
||||
wxArrayString filters;
|
||||
filters.Add(_("Unknown"));
|
||||
filters.Add(_("Not Equal"));
|
||||
filters.Add(_("Equal"));
|
||||
filters.Add(_("Greater Than"));
|
||||
filters.Add(_("Less Than"));
|
||||
|
||||
m_search_type = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, filters);
|
||||
m_search_type->Select(0);
|
||||
m_search_type = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, filters);
|
||||
m_search_type->Select(0);
|
||||
|
||||
wxStaticBoxSizer* const sizer_cheat_search_filter = new wxStaticBoxSizer(wxVERTICAL, this, _("Search (clear to use previous value)"));
|
||||
sizer_cheat_search_filter->Add(sizer_cheat_filter_text, 0, wxALL | wxEXPAND, 5);
|
||||
sizer_cheat_search_filter->Add(m_search_type, 0, wxALL, 5);
|
||||
wxStaticBoxSizer* const sizer_cheat_search_filter =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Search (clear to use previous value)"));
|
||||
sizer_cheat_search_filter->Add(sizer_cheat_filter_text, 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);
|
||||
// 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);
|
||||
// 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(m_data_sizes, 0, wxEXPAND | 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);
|
||||
// right sizer
|
||||
wxBoxSizer* const sizer_right = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_right->Add(m_data_sizes, 0, wxEXPAND | 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);
|
||||
// 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);
|
||||
SetSizerAndFit(sizer_main);
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnNewScanClicked(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
if (!Core::IsRunningAndStarted())
|
||||
{
|
||||
WxUtils::ShowErrorDialog(_("A game is not currently running."));
|
||||
return;
|
||||
}
|
||||
if (!Core::IsRunningAndStarted())
|
||||
{
|
||||
WxUtils::ShowErrorDialog(_("A game is not currently running."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the user-selected data size for this search.
|
||||
m_search_type_size = (1 << m_data_sizes->GetSelection());
|
||||
// Determine the user-selected data size for this search.
|
||||
m_search_type_size = (1 << m_data_sizes->GetSelection());
|
||||
|
||||
// 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);
|
||||
// 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();
|
||||
// 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, &Memory::m_pRAM[addr], m_search_type_size);
|
||||
m_search_results.push_back(r);
|
||||
}
|
||||
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, &Memory::m_pRAM[addr], m_search_type_size);
|
||||
m_search_results.push_back(r);
|
||||
}
|
||||
|
||||
UpdateCheatSearchResultsList();
|
||||
UpdateCheatSearchResultsList();
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnNextScanClicked(wxCommandEvent&)
|
||||
{
|
||||
if (!Core::IsRunningAndStarted())
|
||||
{
|
||||
WxUtils::ShowErrorDialog(_("A game is not currently running."));
|
||||
return;
|
||||
}
|
||||
if (!Core::IsRunningAndStarted())
|
||||
{
|
||||
WxUtils::ShowErrorDialog(_("A game is not currently running."));
|
||||
return;
|
||||
}
|
||||
|
||||
u32 user_x_val = 0;
|
||||
bool blank_user_value = m_textctrl_value_x->IsEmpty();
|
||||
if (!blank_user_value)
|
||||
{
|
||||
if (!ParseUserEnteredValue(&user_x_val))
|
||||
return;
|
||||
}
|
||||
u32 user_x_val = 0;
|
||||
bool blank_user_value = m_textctrl_value_x->IsEmpty();
|
||||
if (!blank_user_value)
|
||||
{
|
||||
if (!ParseUserEnteredValue(&user_x_val))
|
||||
return;
|
||||
}
|
||||
|
||||
FilterCheatSearchResults(user_x_val, blank_user_value);
|
||||
FilterCheatSearchResults(user_x_val, blank_user_value);
|
||||
|
||||
UpdateCheatSearchResultsList();
|
||||
UpdateCheatSearchResultsList();
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnCreateARCodeClicked(wxCommandEvent&)
|
||||
{
|
||||
long idx = m_lview_search_results->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
if (idx == wxNOT_FOUND)
|
||||
return;
|
||||
long idx = m_lview_search_results->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
if (idx == wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
const u32 address = m_search_results[idx].address | ((m_search_type_size & ~1) << 24);
|
||||
const u32 address = m_search_results[idx].address | ((m_search_type_size & ~1) << 24);
|
||||
|
||||
CreateCodeDialog arcode_dlg(this, address);
|
||||
arcode_dlg.ShowModal();
|
||||
CreateCodeDialog arcode_dlg(this, address);
|
||||
arcode_dlg.ShowModal();
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnTimerUpdate(wxTimerEvent&)
|
||||
{
|
||||
if (Core::GetState() != Core::CORE_RUN)
|
||||
return;
|
||||
if (Core::GetState() != Core::CORE_RUN)
|
||||
return;
|
||||
|
||||
// Only update the currently visible list rows.
|
||||
long first = m_lview_search_results->GetTopItem();
|
||||
long last = std::min(m_lview_search_results->GetItemCount(), m_lview_search_results->GetCountPerPage());
|
||||
// Only update the currently visible list rows.
|
||||
long first = m_lview_search_results->GetTopItem();
|
||||
long last =
|
||||
std::min(m_lview_search_results->GetItemCount(), m_lview_search_results->GetCountPerPage());
|
||||
|
||||
m_lview_search_results->Freeze();
|
||||
m_lview_search_results->Freeze();
|
||||
|
||||
while (first < last)
|
||||
{
|
||||
UpdateCheatSearchResultItem(first);
|
||||
first++;
|
||||
}
|
||||
while (first < last)
|
||||
{
|
||||
UpdateCheatSearchResultItem(first);
|
||||
first++;
|
||||
}
|
||||
|
||||
m_lview_search_results->Thaw();
|
||||
m_lview_search_results->Thaw();
|
||||
}
|
||||
|
||||
void CheatSearchTab::UpdateCheatSearchResultsList()
|
||||
{
|
||||
m_update_timer.Stop();
|
||||
m_lview_search_results->ClearAll();
|
||||
ResetListViewColumns();
|
||||
m_update_timer.Stop();
|
||||
m_lview_search_results->ClearAll();
|
||||
ResetListViewColumns();
|
||||
|
||||
wxString count_label = wxString::Format(_("Count: %lu"),
|
||||
(unsigned long)m_search_results.size());
|
||||
if (m_search_results.size() > MAX_CHEAT_SEARCH_RESULTS_DISPLAY)
|
||||
{
|
||||
count_label += _(" (too many to display)");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lview_search_results->Freeze();
|
||||
wxString count_label = wxString::Format(_("Count: %lu"), (unsigned long)m_search_results.size());
|
||||
if (m_search_results.size() > MAX_CHEAT_SEARCH_RESULTS_DISPLAY)
|
||||
{
|
||||
count_label += _(" (too many to display)");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lview_search_results->Freeze();
|
||||
|
||||
for (size_t i = 0; i < m_search_results.size(); i++)
|
||||
{
|
||||
// Insert into the list control.
|
||||
wxString address_string = wxString::Format("0x%08X", m_search_results[i].address);
|
||||
long index = m_lview_search_results->InsertItem(static_cast<long>(i), address_string);
|
||||
for (size_t i = 0; i < m_search_results.size(); i++)
|
||||
{
|
||||
// Insert into the list control.
|
||||
wxString address_string = wxString::Format("0x%08X", m_search_results[i].address);
|
||||
long index = m_lview_search_results->InsertItem(static_cast<long>(i), address_string);
|
||||
|
||||
UpdateCheatSearchResultItem(index);
|
||||
}
|
||||
UpdateCheatSearchResultItem(index);
|
||||
}
|
||||
|
||||
m_lview_search_results->Thaw();
|
||||
m_lview_search_results->Thaw();
|
||||
|
||||
// Half-second update interval
|
||||
m_update_timer.Start(500);
|
||||
}
|
||||
// Half-second update interval
|
||||
m_update_timer.Start(500);
|
||||
}
|
||||
|
||||
m_label_results_count->SetLabel(count_label);
|
||||
m_label_results_count->SetLabel(count_label);
|
||||
}
|
||||
|
||||
void CheatSearchTab::UpdateCheatSearchResultItem(long index)
|
||||
{
|
||||
u32 address_value = 0;
|
||||
std::memcpy(&address_value, &Memory::m_pRAM[m_search_results[index].address], m_search_type_size);
|
||||
u32 address_value = 0;
|
||||
std::memcpy(&address_value, &Memory::m_pRAM[m_search_results[index].address], m_search_type_size);
|
||||
|
||||
u32 display_value = SwapValue(address_value);
|
||||
u32 display_value = SwapValue(address_value);
|
||||
|
||||
wxString buf;
|
||||
buf.Printf("0x%08X", display_value);
|
||||
m_lview_search_results->SetItem(index, 1, buf);
|
||||
wxString buf;
|
||||
buf.Printf("0x%08X", display_value);
|
||||
m_lview_search_results->SetItem(index, 1, buf);
|
||||
|
||||
float display_value_float = 0.0f;
|
||||
std::memcpy(&display_value_float, &display_value, sizeof(u32));
|
||||
buf.Printf("%e", display_value_float);
|
||||
m_lview_search_results->SetItem(index, 2, buf);
|
||||
float display_value_float = 0.0f;
|
||||
std::memcpy(&display_value_float, &display_value, sizeof(u32));
|
||||
buf.Printf("%e", display_value_float);
|
||||
m_lview_search_results->SetItem(index, 2, buf);
|
||||
|
||||
double display_value_double = 0.0;
|
||||
std::memcpy(&display_value_double, &display_value, sizeof(u32));
|
||||
buf.Printf("%e", display_value_double);
|
||||
m_lview_search_results->SetItem(index, 3, buf);
|
||||
double display_value_double = 0.0;
|
||||
std::memcpy(&display_value_double, &display_value, sizeof(u32));
|
||||
buf.Printf("%e", display_value_double);
|
||||
m_lview_search_results->SetItem(index, 3, buf);
|
||||
}
|
||||
|
||||
enum class ComparisonMask
|
||||
{
|
||||
EQUAL = 0x1,
|
||||
GREATER_THAN = 0x2,
|
||||
LESS_THAN = 0x4
|
||||
EQUAL = 0x1,
|
||||
GREATER_THAN = 0x2,
|
||||
LESS_THAN = 0x4
|
||||
};
|
||||
|
||||
static ComparisonMask operator | (ComparisonMask comp1, ComparisonMask comp2)
|
||||
static ComparisonMask operator|(ComparisonMask comp1, ComparisonMask comp2)
|
||||
{
|
||||
return static_cast<ComparisonMask>(static_cast<int>(comp1) |
|
||||
static_cast<int>(comp2));
|
||||
return static_cast<ComparisonMask>(static_cast<int>(comp1) | static_cast<int>(comp2));
|
||||
}
|
||||
|
||||
static ComparisonMask operator & (ComparisonMask comp1, ComparisonMask comp2)
|
||||
static ComparisonMask operator&(ComparisonMask comp1, ComparisonMask comp2)
|
||||
{
|
||||
return static_cast<ComparisonMask>(static_cast<int>(comp1) &
|
||||
static_cast<int>(comp2));
|
||||
return static_cast<ComparisonMask>(static_cast<int>(comp1) & static_cast<int>(comp2));
|
||||
}
|
||||
|
||||
void CheatSearchTab::FilterCheatSearchResults(u32 value, bool prev)
|
||||
{
|
||||
static const std::array<ComparisonMask, 5> filters{{
|
||||
ComparisonMask::EQUAL | ComparisonMask::GREATER_THAN | ComparisonMask::LESS_THAN, // Unknown
|
||||
ComparisonMask::GREATER_THAN | ComparisonMask::LESS_THAN, // Not Equal
|
||||
ComparisonMask::EQUAL,
|
||||
ComparisonMask::GREATER_THAN,
|
||||
ComparisonMask::LESS_THAN
|
||||
}};
|
||||
ComparisonMask filter_mask = filters[m_search_type->GetSelection()];
|
||||
static const std::array<ComparisonMask, 5> filters{
|
||||
{ComparisonMask::EQUAL | ComparisonMask::GREATER_THAN | ComparisonMask::LESS_THAN, // Unknown
|
||||
ComparisonMask::GREATER_THAN | ComparisonMask::LESS_THAN, // Not Equal
|
||||
ComparisonMask::EQUAL, ComparisonMask::GREATER_THAN, ComparisonMask::LESS_THAN}};
|
||||
ComparisonMask filter_mask = filters[m_search_type->GetSelection()];
|
||||
|
||||
std::vector<CheatSearchResult> filtered_results;
|
||||
filtered_results.reserve(m_search_results.size());
|
||||
std::vector<CheatSearchResult> filtered_results;
|
||||
filtered_results.reserve(m_search_results.size());
|
||||
|
||||
for (CheatSearchResult& result : m_search_results)
|
||||
{
|
||||
if (prev)
|
||||
value = result.old_value;
|
||||
for (CheatSearchResult& result : m_search_results)
|
||||
{
|
||||
if (prev)
|
||||
value = result.old_value;
|
||||
|
||||
// with big endian, can just use memcmp for ><= comparison
|
||||
int cmp_result = std::memcmp(&Memory::m_pRAM[result.address], &value, m_search_type_size);
|
||||
ComparisonMask cmp_mask;
|
||||
if (cmp_result < 0)
|
||||
cmp_mask = ComparisonMask::LESS_THAN;
|
||||
else if (cmp_result)
|
||||
cmp_mask = ComparisonMask::GREATER_THAN;
|
||||
else
|
||||
cmp_mask = ComparisonMask::EQUAL;
|
||||
// with big endian, can just use memcmp for ><= comparison
|
||||
int cmp_result = std::memcmp(&Memory::m_pRAM[result.address], &value, m_search_type_size);
|
||||
ComparisonMask cmp_mask;
|
||||
if (cmp_result < 0)
|
||||
cmp_mask = ComparisonMask::LESS_THAN;
|
||||
else if (cmp_result)
|
||||
cmp_mask = ComparisonMask::GREATER_THAN;
|
||||
else
|
||||
cmp_mask = ComparisonMask::EQUAL;
|
||||
|
||||
if (static_cast<int>(cmp_mask & filter_mask))
|
||||
{
|
||||
std::memcpy(&result.old_value, &Memory::m_pRAM[result.address], m_search_type_size);
|
||||
filtered_results.push_back(result);
|
||||
}
|
||||
}
|
||||
if (static_cast<int>(cmp_mask & filter_mask))
|
||||
{
|
||||
std::memcpy(&result.old_value, &Memory::m_pRAM[result.address], m_search_type_size);
|
||||
filtered_results.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
m_search_results.swap(filtered_results);
|
||||
m_search_results.swap(filtered_results);
|
||||
}
|
||||
|
||||
void CheatSearchTab::ResetListViewColumns()
|
||||
{
|
||||
m_lview_search_results->AppendColumn(_("Address"));
|
||||
m_lview_search_results->AppendColumn(_("Value"));
|
||||
m_lview_search_results->AppendColumn(_("Value (float)"));
|
||||
m_lview_search_results->AppendColumn(_("Value (double)"));
|
||||
m_lview_search_results->AppendColumn(_("Address"));
|
||||
m_lview_search_results->AppendColumn(_("Value"));
|
||||
m_lview_search_results->AppendColumn(_("Value (float)"));
|
||||
m_lview_search_results->AppendColumn(_("Value (double)"));
|
||||
}
|
||||
|
||||
bool CheatSearchTab::ParseUserEnteredValue(u32* out) const
|
||||
{
|
||||
unsigned long parsed_x_val = 0;
|
||||
wxString x_val = m_textctrl_value_x->GetValue();
|
||||
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 false;
|
||||
}
|
||||
if (!x_val.ToULong(&parsed_x_val, 0))
|
||||
{
|
||||
WxUtils::ShowErrorDialog(_("You must enter a valid decimal, hexadecimal or octal value."));
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = SwapValue(static_cast<u32>(parsed_x_val));
|
||||
return true;
|
||||
*out = SwapValue(static_cast<u32>(parsed_x_val));
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 CheatSearchTab::SwapValue(u32 value) const
|
||||
{
|
||||
switch (m_search_type_size)
|
||||
{
|
||||
case 2:
|
||||
*(u16*)&value = Common::swap16((u8*)&value);
|
||||
break;
|
||||
case 4:
|
||||
value = Common::swap32(value);
|
||||
break;
|
||||
}
|
||||
switch (m_search_type_size)
|
||||
{
|
||||
case 2:
|
||||
*(u16*)&value = Common::swap16((u8*)&value);
|
||||
break;
|
||||
case 4:
|
||||
value = Common::swap32(value);
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
return value;
|
||||
}
|
||||
|
@ -20,42 +20,41 @@ class wxTextCtrl;
|
||||
class CheatSearchTab final : public wxPanel
|
||||
{
|
||||
public:
|
||||
CheatSearchTab(wxWindow* const parent);
|
||||
CheatSearchTab(wxWindow* const parent);
|
||||
|
||||
private:
|
||||
class CheatSearchResult final
|
||||
{
|
||||
public:
|
||||
CheatSearchResult() : address(0), old_value(0) {}
|
||||
class CheatSearchResult final
|
||||
{
|
||||
public:
|
||||
CheatSearchResult() : address(0), old_value(0) {}
|
||||
u32 address;
|
||||
u32 old_value;
|
||||
};
|
||||
|
||||
u32 address;
|
||||
u32 old_value;
|
||||
};
|
||||
void UpdateCheatSearchResultsList();
|
||||
void UpdateCheatSearchResultItem(long index);
|
||||
void FilterCheatSearchResults(u32 value, bool prev);
|
||||
void ResetListViewColumns();
|
||||
bool ParseUserEnteredValue(u32* out) const;
|
||||
u32 SwapValue(u32 value) const;
|
||||
|
||||
void UpdateCheatSearchResultsList();
|
||||
void UpdateCheatSearchResultItem(long index);
|
||||
void FilterCheatSearchResults(u32 value, bool prev);
|
||||
void ResetListViewColumns();
|
||||
bool ParseUserEnteredValue(u32* out) const;
|
||||
u32 SwapValue(u32 value) const;
|
||||
void OnNewScanClicked(wxCommandEvent&);
|
||||
void OnNextScanClicked(wxCommandEvent&);
|
||||
void OnCreateARCodeClicked(wxCommandEvent&);
|
||||
void OnTimerUpdate(wxTimerEvent&);
|
||||
|
||||
void OnNewScanClicked(wxCommandEvent&);
|
||||
void OnNextScanClicked(wxCommandEvent&);
|
||||
void OnCreateARCodeClicked(wxCommandEvent&);
|
||||
void OnTimerUpdate(wxTimerEvent&);
|
||||
std::vector<CheatSearchResult> m_search_results;
|
||||
unsigned int m_search_type_size;
|
||||
|
||||
std::vector<CheatSearchResult> m_search_results;
|
||||
unsigned int m_search_type_size;
|
||||
wxChoice* m_search_type;
|
||||
wxListView* m_lview_search_results;
|
||||
wxStaticText* m_label_results_count;
|
||||
wxTextCtrl* m_textctrl_value_x;
|
||||
|
||||
wxChoice* m_search_type;
|
||||
wxListView* m_lview_search_results;
|
||||
wxStaticText* m_label_results_count;
|
||||
wxTextCtrl* m_textctrl_value_x;
|
||||
wxButton* m_btn_init_scan;
|
||||
wxButton* m_btn_next_scan;
|
||||
|
||||
wxButton* m_btn_init_scan;
|
||||
wxButton* m_btn_next_scan;
|
||||
wxRadioBox* m_data_sizes;
|
||||
|
||||
wxRadioBox* m_data_sizes;
|
||||
|
||||
wxTimer m_update_timer;
|
||||
wxTimer m_update_timer;
|
||||
};
|
||||
|
@ -32,281 +32,291 @@
|
||||
#include "Core/Core.h"
|
||||
#include "Core/GeckoCode.h"
|
||||
#include "Core/GeckoCodeConfig.h"
|
||||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
#include "DolphinWX/Main.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "DolphinWX/Cheats/CheatSearchTab.h"
|
||||
#include "DolphinWX/Cheats/CheatsWindow.h"
|
||||
#include "DolphinWX/Cheats/CreateCodeDialog.h"
|
||||
#include "DolphinWX/Cheats/GeckoCodeDiag.h"
|
||||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
#include "DolphinWX/Main.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
wxDEFINE_EVENT(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, wxCommandEvent);
|
||||
|
||||
struct wxCheatsWindow::CodeData : public wxClientData
|
||||
{
|
||||
ActionReplay::ARCode code;
|
||||
ActionReplay::ARCode code;
|
||||
};
|
||||
|
||||
wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
|
||||
: wxDialog(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxDIALOG_NO_PARENT)
|
||||
: wxDialog(parent, wxID_ANY, "", wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX |
|
||||
wxDIALOG_NO_PARENT)
|
||||
{
|
||||
// Create the GUI controls
|
||||
Init_ChildControls();
|
||||
// Create the GUI controls
|
||||
Init_ChildControls();
|
||||
|
||||
// load codes
|
||||
UpdateGUI();
|
||||
wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnEvent_CheatsList_Update, this);
|
||||
// load codes
|
||||
UpdateGUI();
|
||||
wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnEvent_CheatsList_Update, this);
|
||||
|
||||
SetSize(wxSize(-1, 600));
|
||||
Center();
|
||||
Show();
|
||||
SetSize(wxSize(-1, 600));
|
||||
Center();
|
||||
Show();
|
||||
}
|
||||
|
||||
wxCheatsWindow::~wxCheatsWindow()
|
||||
{
|
||||
main_frame->g_CheatsWindow = nullptr;
|
||||
main_frame->g_CheatsWindow = nullptr;
|
||||
}
|
||||
|
||||
void wxCheatsWindow::Init_ChildControls()
|
||||
{
|
||||
// Main Notebook
|
||||
m_notebook_main = new wxNotebook(this, wxID_ANY);
|
||||
// Main Notebook
|
||||
m_notebook_main = new wxNotebook(this, wxID_ANY);
|
||||
|
||||
// --- Tabs ---
|
||||
// Cheats List Tab
|
||||
m_tab_cheats = new wxPanel(m_notebook_main, 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), 0, nullptr, wxLB_HSCROLL);
|
||||
m_checklistbox_cheats_list->Bind(wxEVT_LISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemSelected, this);
|
||||
m_checklistbox_cheats_list = new wxCheckListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition,
|
||||
wxSize(300, 0), 0, nullptr, wxLB_HSCROLL);
|
||||
m_checklistbox_cheats_list->Bind(wxEVT_LISTBOX, &wxCheatsWindow::OnEvent_CheatsList_ItemSelected,
|
||||
this);
|
||||
|
||||
m_label_code_name = new wxStaticText(m_tab_cheats, wxID_ANY, _("Name: "), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_groupbox_info = new wxStaticBox(m_tab_cheats, wxID_ANY, _("Code Info"));
|
||||
m_label_code_name = new wxStaticText(m_tab_cheats, wxID_ANY, _("Name: "), wxDefaultPosition,
|
||||
wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
m_groupbox_info = new wxStaticBox(m_tab_cheats, wxID_ANY, _("Code Info"));
|
||||
|
||||
m_label_num_codes = new wxStaticText(m_tab_cheats, wxID_ANY, _("Number Of Codes: "));
|
||||
m_listbox_codes_list = new wxListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition, wxSize(120, 150), 0, nullptr, wxLB_HSCROLL);
|
||||
m_label_num_codes = new wxStaticText(m_tab_cheats, wxID_ANY, _("Number Of Codes: "));
|
||||
m_listbox_codes_list = new wxListBox(m_tab_cheats, wxID_ANY, wxDefaultPosition, wxSize(120, 150),
|
||||
0, nullptr, wxLB_HSCROLL);
|
||||
|
||||
wxStaticBoxSizer* sGroupBoxInfo = new wxStaticBoxSizer(m_groupbox_info, wxVERTICAL);
|
||||
sGroupBoxInfo->Add(m_label_code_name, 0, wxEXPAND | wxALL, 5);
|
||||
sGroupBoxInfo->Add(m_label_num_codes, 0, wxALL, 5);
|
||||
sGroupBoxInfo->Add(m_listbox_codes_list, 1, wxALL, 5);
|
||||
wxStaticBoxSizer* sGroupBoxInfo = new wxStaticBoxSizer(m_groupbox_info, wxVERTICAL);
|
||||
sGroupBoxInfo->Add(m_label_code_name, 0, wxEXPAND | wxALL, 5);
|
||||
sGroupBoxInfo->Add(m_label_num_codes, 0, wxALL, 5);
|
||||
sGroupBoxInfo->Add(m_listbox_codes_list, 1, wxALL, 5);
|
||||
|
||||
wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxHORIZONTAL);
|
||||
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);
|
||||
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);
|
||||
m_tab_cheats->SetSizerAndFit(sizer_tab_cheats);
|
||||
|
||||
// Cheat Search Tab
|
||||
wxPanel* const tab_cheat_search = new CheatSearchTab(m_notebook_main);
|
||||
// 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);
|
||||
// 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);
|
||||
wxButton* const button_clearlog = new wxButton(m_tab_log, wxID_ANY, _("Clear"));
|
||||
button_clearlog->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnClearActionReplayLog, this);
|
||||
wxButton* const button_updatelog = new wxButton(m_tab_log, wxID_ANY, _("Update"));
|
||||
button_updatelog->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonUpdateLog_Press, this);
|
||||
wxButton* const button_clearlog = new wxButton(m_tab_log, wxID_ANY, _("Clear"));
|
||||
button_clearlog->Bind(wxEVT_BUTTON, &wxCheatsWindow::OnClearActionReplayLog, this);
|
||||
|
||||
m_checkbox_log_ar = new wxCheckBox(m_tab_log, wxID_ANY, _("Enable AR Logging"));
|
||||
m_checkbox_log_ar->Bind(wxEVT_CHECKBOX, &wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange, this);
|
||||
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);
|
||||
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);
|
||||
HStrip1->Add(button_clearlog, 0, wxALL, 5);
|
||||
wxBoxSizer* HStrip1 = new wxBoxSizer(wxHORIZONTAL);
|
||||
HStrip1->Add(m_checkbox_log_ar, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
HStrip1->Add(button_updatelog, 0, wxALL, 5);
|
||||
HStrip1->Add(button_clearlog, 0, wxALL, 5);
|
||||
|
||||
wxBoxSizer *sTabLog = new wxBoxSizer(wxVERTICAL);
|
||||
sTabLog->Add(HStrip1, 0, wxALL, 5);
|
||||
sTabLog->Add(m_textctrl_log, 1, wxALL | wxEXPAND, 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);
|
||||
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"));
|
||||
// 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"));
|
||||
|
||||
Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this, wxID_APPLY);
|
||||
Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this, wxID_CANCEL);
|
||||
Bind(wxEVT_CLOSE_WINDOW, &wxCheatsWindow::OnEvent_Close, this);
|
||||
Bind(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, &wxCheatsWindow::OnNewARCodeCreated, this);
|
||||
Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this, wxID_APPLY);
|
||||
Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ButtonClose_Press, this, wxID_CANCEL);
|
||||
Bind(wxEVT_CLOSE_WINDOW, &wxCheatsWindow::OnEvent_Close, this);
|
||||
Bind(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, &wxCheatsWindow::OnNewARCodeCreated, this);
|
||||
|
||||
wxStdDialogButtonSizer* const sButtons = CreateStdDialogButtonSizer(wxAPPLY | wxCANCEL);
|
||||
m_button_apply = sButtons->GetApplyButton();
|
||||
SetEscapeId(wxID_CANCEL);
|
||||
SetAffirmativeId(wxID_CANCEL);
|
||||
wxStdDialogButtonSizer* const sButtons = CreateStdDialogButtonSizer(wxAPPLY | wxCANCEL);
|
||||
m_button_apply = sButtons->GetApplyButton();
|
||||
SetEscapeId(wxID_CANCEL);
|
||||
SetAffirmativeId(wxID_CANCEL);
|
||||
|
||||
wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_notebook_main, 1, wxEXPAND | wxALL, 5);
|
||||
sMain->Add(sButtons, 0, wxRIGHT | wxBOTTOM | wxALIGN_RIGHT, 5);
|
||||
SetSizerAndFit(sMain);
|
||||
wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_notebook_main, 1, wxEXPAND | wxALL, 5);
|
||||
sMain->Add(sButtons, 0, wxRIGHT | wxBOTTOM | wxALIGN_RIGHT, 5);
|
||||
SetSizerAndFit(sMain);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_ButtonClose_Press(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
Close();
|
||||
Close();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_Close(wxCloseEvent& ev)
|
||||
{
|
||||
Destroy();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// load codes for a new ISO ID
|
||||
void wxCheatsWindow::UpdateGUI()
|
||||
{
|
||||
// load code
|
||||
const SConfig& parameters = SConfig::GetInstance();
|
||||
m_gameini_default = parameters.LoadDefaultGameIni();
|
||||
m_gameini_local = parameters.LoadLocalGameIni();
|
||||
m_game_id = parameters.GetUniqueID();
|
||||
m_game_revision = parameters.m_revision;
|
||||
m_gameini_local_path = File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini";
|
||||
Load_ARCodes();
|
||||
Load_GeckoCodes();
|
||||
// load code
|
||||
const SConfig& parameters = SConfig::GetInstance();
|
||||
m_gameini_default = parameters.LoadDefaultGameIni();
|
||||
m_gameini_local = parameters.LoadLocalGameIni();
|
||||
m_game_id = parameters.GetUniqueID();
|
||||
m_game_revision = parameters.m_revision;
|
||||
m_gameini_local_path = File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini";
|
||||
Load_ARCodes();
|
||||
Load_GeckoCodes();
|
||||
|
||||
// enable controls
|
||||
m_button_apply->Enable(Core::IsRunning());
|
||||
// enable controls
|
||||
m_button_apply->Enable(Core::IsRunning());
|
||||
|
||||
wxString title = _("Cheat Manager");
|
||||
wxString title = _("Cheat Manager");
|
||||
|
||||
// write the ISO name in the title
|
||||
if (Core::IsRunning())
|
||||
SetTitle(title + StrToWxStr(": " + m_game_id + " - " + parameters.m_strName));
|
||||
else
|
||||
SetTitle(title);
|
||||
// write the ISO name in the title
|
||||
if (Core::IsRunning())
|
||||
SetTitle(title + StrToWxStr(": " + m_game_id + " - " + parameters.m_strName));
|
||||
else
|
||||
SetTitle(title);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::Load_ARCodes()
|
||||
{
|
||||
m_checklistbox_cheats_list->Clear();
|
||||
m_checklistbox_cheats_list->Clear();
|
||||
|
||||
if (!Core::IsRunning())
|
||||
return;
|
||||
if (!Core::IsRunning())
|
||||
return;
|
||||
|
||||
m_checklistbox_cheats_list->Freeze();
|
||||
for (auto& code : ActionReplay::LoadCodes(m_gameini_default, m_gameini_local))
|
||||
{
|
||||
CodeData* cd = new CodeData();
|
||||
cd->code = std::move(code);
|
||||
int index = m_checklistbox_cheats_list->Append(wxCheckListBox::EscapeMnemonics(StrToWxStr(cd->code.name)),
|
||||
cd);
|
||||
m_checklistbox_cheats_list->Check(index, cd->code.active);
|
||||
}
|
||||
m_checklistbox_cheats_list->Thaw();
|
||||
m_checklistbox_cheats_list->Freeze();
|
||||
for (auto& code : ActionReplay::LoadCodes(m_gameini_default, m_gameini_local))
|
||||
{
|
||||
CodeData* cd = new CodeData();
|
||||
cd->code = std::move(code);
|
||||
int index = m_checklistbox_cheats_list->Append(
|
||||
wxCheckListBox::EscapeMnemonics(StrToWxStr(cd->code.name)), cd);
|
||||
m_checklistbox_cheats_list->Check(index, cd->code.active);
|
||||
}
|
||||
m_checklistbox_cheats_list->Thaw();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::Load_GeckoCodes()
|
||||
{
|
||||
m_geckocode_panel->LoadCodes(m_gameini_default, m_gameini_local, SConfig::GetInstance().GetUniqueID(), true);
|
||||
m_geckocode_panel->LoadCodes(m_gameini_default, m_gameini_local,
|
||||
SConfig::GetInstance().GetUniqueID(), true);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnNewARCodeCreated(wxCommandEvent& ev)
|
||||
{
|
||||
auto code = static_cast<ActionReplay::ARCode*>(ev.GetClientData());
|
||||
ActionReplay::AddCode(*code);
|
||||
auto code = static_cast<ActionReplay::ARCode*>(ev.GetClientData());
|
||||
ActionReplay::AddCode(*code);
|
||||
|
||||
CodeData* cd = new CodeData();
|
||||
cd->code = *code;
|
||||
int idx = m_checklistbox_cheats_list->Append(wxCheckListBox::EscapeMnemonics(StrToWxStr(code->name)),
|
||||
cd);
|
||||
m_checklistbox_cheats_list->Check(idx, code->active);
|
||||
CodeData* cd = new CodeData();
|
||||
cd->code = *code;
|
||||
int idx = m_checklistbox_cheats_list->Append(
|
||||
wxCheckListBox::EscapeMnemonics(StrToWxStr(code->name)), cd);
|
||||
m_checklistbox_cheats_list->Check(idx, code->active);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_CheatsList_ItemSelected(wxCommandEvent& event)
|
||||
{
|
||||
CodeData* cd = static_cast<CodeData*>(event.GetClientObject());
|
||||
CodeData* cd = static_cast<CodeData*>(event.GetClientObject());
|
||||
|
||||
m_label_code_name->SetLabelText(_("Name: ") + StrToWxStr(cd->code.name));
|
||||
m_label_code_name->Wrap(m_label_code_name->GetSize().GetWidth());
|
||||
m_label_code_name->InvalidateBestSize();
|
||||
m_label_num_codes->SetLabelText(wxString::Format("%s%zu", _("Number Of Codes: "), cd->code.ops.size()));
|
||||
m_label_code_name->SetLabelText(_("Name: ") + StrToWxStr(cd->code.name));
|
||||
m_label_code_name->Wrap(m_label_code_name->GetSize().GetWidth());
|
||||
m_label_code_name->InvalidateBestSize();
|
||||
m_label_num_codes->SetLabelText(
|
||||
wxString::Format("%s%zu", _("Number Of Codes: "), cd->code.ops.size()));
|
||||
|
||||
m_listbox_codes_list->Freeze();
|
||||
m_listbox_codes_list->Clear();
|
||||
for (const ActionReplay::AREntry& entry : cd->code.ops)
|
||||
{
|
||||
m_listbox_codes_list->Append(wxString::Format("%08x %08x", entry.cmd_addr, entry.value));
|
||||
}
|
||||
m_listbox_codes_list->Thaw();
|
||||
m_listbox_codes_list->Freeze();
|
||||
m_listbox_codes_list->Clear();
|
||||
for (const ActionReplay::AREntry& entry : cd->code.ops)
|
||||
{
|
||||
m_listbox_codes_list->Append(wxString::Format("%08x %08x", entry.cmd_addr, entry.value));
|
||||
}
|
||||
m_listbox_codes_list->Thaw();
|
||||
|
||||
m_tab_cheats->Layout();
|
||||
m_tab_cheats->Layout();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_CheatsList_Update(wxCommandEvent& ev)
|
||||
{
|
||||
ev.Skip();
|
||||
if (WxStrToStr(ev.GetString()) != m_game_id)
|
||||
return;
|
||||
if (m_ignore_ini_callback)
|
||||
{
|
||||
m_ignore_ini_callback = false;
|
||||
return;
|
||||
}
|
||||
UpdateGUI();
|
||||
ev.Skip();
|
||||
if (WxStrToStr(ev.GetString()) != m_game_id)
|
||||
return;
|
||||
if (m_ignore_ini_callback)
|
||||
{
|
||||
m_ignore_ini_callback = false;
|
||||
return;
|
||||
}
|
||||
UpdateGUI();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
|
||||
{
|
||||
// Convert embedded metadata back into ARCode vector and update active states
|
||||
std::vector<ActionReplay::ARCode> code_vec;
|
||||
code_vec.reserve(m_checklistbox_cheats_list->GetCount());
|
||||
for (unsigned int i = 0; i < m_checklistbox_cheats_list->GetCount(); ++i)
|
||||
{
|
||||
CodeData* cd = static_cast<CodeData*>(m_checklistbox_cheats_list->GetClientObject(i));
|
||||
cd->code.active = m_checklistbox_cheats_list->IsChecked(i);
|
||||
code_vec.push_back(cd->code);
|
||||
}
|
||||
// Convert embedded metadata back into ARCode vector and update active states
|
||||
std::vector<ActionReplay::ARCode> code_vec;
|
||||
code_vec.reserve(m_checklistbox_cheats_list->GetCount());
|
||||
for (unsigned int i = 0; i < m_checklistbox_cheats_list->GetCount(); ++i)
|
||||
{
|
||||
CodeData* cd = static_cast<CodeData*>(m_checklistbox_cheats_list->GetClientObject(i));
|
||||
cd->code.active = m_checklistbox_cheats_list->IsChecked(i);
|
||||
code_vec.push_back(cd->code);
|
||||
}
|
||||
|
||||
// Apply Action Replay code changes
|
||||
ActionReplay::ApplyCodes(code_vec);
|
||||
// Apply Action Replay code changes
|
||||
ActionReplay::ApplyCodes(code_vec);
|
||||
|
||||
// Apply Gecko Code changes
|
||||
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());
|
||||
// Apply Gecko Code changes
|
||||
Gecko::SetActiveCodes(m_geckocode_panel->GetCodes());
|
||||
|
||||
// Save gameini, with changed codes
|
||||
if (m_gameini_local_path.size())
|
||||
{
|
||||
ActionReplay::SaveCodes(&m_gameini_local, code_vec);
|
||||
Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes());
|
||||
m_gameini_local.Save(m_gameini_local_path);
|
||||
// Save gameini, with changed codes
|
||||
if (m_gameini_local_path.size())
|
||||
{
|
||||
ActionReplay::SaveCodes(&m_gameini_local, code_vec);
|
||||
Gecko::SaveCodes(m_gameini_local, m_geckocode_panel->GetCodes());
|
||||
m_gameini_local.Save(m_gameini_local_path);
|
||||
|
||||
wxCommandEvent ini_changed(DOLPHIN_EVT_LOCAL_INI_CHANGED);
|
||||
ini_changed.SetString(StrToWxStr(m_game_id));
|
||||
ini_changed.SetInt(m_game_revision);
|
||||
m_ignore_ini_callback = true;
|
||||
wxTheApp->ProcessEvent(ini_changed);
|
||||
}
|
||||
wxCommandEvent ini_changed(DOLPHIN_EVT_LOCAL_INI_CHANGED);
|
||||
ini_changed.SetString(StrToWxStr(m_game_id));
|
||||
ini_changed.SetInt(m_game_revision);
|
||||
m_ignore_ini_callback = true;
|
||||
wxTheApp->ProcessEvent(ini_changed);
|
||||
}
|
||||
|
||||
ev.Skip();
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxBeginBusyCursor();
|
||||
m_textctrl_log->Freeze();
|
||||
m_textctrl_log->Clear();
|
||||
for (const std::string& text : ActionReplay::GetSelfLog())
|
||||
{
|
||||
m_textctrl_log->AppendText(StrToWxStr(text));
|
||||
}
|
||||
m_textctrl_log->Thaw();
|
||||
wxEndBusyCursor();
|
||||
wxBeginBusyCursor();
|
||||
m_textctrl_log->Freeze();
|
||||
m_textctrl_log->Clear();
|
||||
for (const std::string& text : ActionReplay::GetSelfLog())
|
||||
{
|
||||
m_textctrl_log->AppendText(StrToWxStr(text));
|
||||
}
|
||||
m_textctrl_log->Thaw();
|
||||
wxEndBusyCursor();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnClearActionReplayLog(wxCommandEvent& event)
|
||||
{
|
||||
ActionReplay::ClearSelfLog();
|
||||
OnEvent_ButtonUpdateLog_Press(event);
|
||||
ActionReplay::ClearSelfLog();
|
||||
OnEvent_ButtonUpdateLog_Press(event);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
ActionReplay::EnableSelfLogging(m_checkbox_log_ar->IsChecked());
|
||||
ActionReplay::EnableSelfLogging(m_checkbox_log_ar->IsChecked());
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ class wxTextCtrl;
|
||||
|
||||
namespace Gecko
|
||||
{
|
||||
class CodeConfigPanel;
|
||||
class CodeConfigPanel;
|
||||
}
|
||||
|
||||
wxDECLARE_EVENT(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, wxCommandEvent);
|
||||
@ -34,66 +34,66 @@ wxDECLARE_EVENT(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, wxCommandEvent);
|
||||
class wxCheatsWindow final : public wxDialog
|
||||
{
|
||||
public:
|
||||
wxCheatsWindow(wxWindow* const parent);
|
||||
~wxCheatsWindow();
|
||||
void UpdateGUI();
|
||||
wxCheatsWindow(wxWindow* const parent);
|
||||
~wxCheatsWindow();
|
||||
void UpdateGUI();
|
||||
|
||||
private:
|
||||
struct CodeData;
|
||||
struct CodeData;
|
||||
|
||||
// --- GUI Controls ---
|
||||
wxButton* m_button_apply;
|
||||
wxNotebook* m_notebook_main;
|
||||
// --- GUI Controls ---
|
||||
wxButton* m_button_apply;
|
||||
wxNotebook* m_notebook_main;
|
||||
|
||||
wxPanel* m_tab_cheats;
|
||||
wxPanel* m_tab_log;
|
||||
wxPanel* m_tab_cheats;
|
||||
wxPanel* m_tab_log;
|
||||
|
||||
wxCheckBox* m_checkbox_log_ar;
|
||||
wxCheckBox* m_checkbox_log_ar;
|
||||
|
||||
wxStaticText* m_label_code_name;
|
||||
wxStaticText* m_label_num_codes;
|
||||
wxStaticText* m_label_code_name;
|
||||
wxStaticText* m_label_num_codes;
|
||||
|
||||
wxCheckListBox* m_checklistbox_cheats_list;
|
||||
wxCheckListBox* m_checklistbox_cheats_list;
|
||||
|
||||
wxTextCtrl* m_textctrl_log;
|
||||
wxTextCtrl* m_textctrl_log;
|
||||
|
||||
wxListBox* m_listbox_codes_list;
|
||||
wxListBox* m_listbox_codes_list;
|
||||
|
||||
wxStaticBox* m_groupbox_info;
|
||||
wxStaticBox* m_groupbox_info;
|
||||
|
||||
Gecko::CodeConfigPanel* m_geckocode_panel;
|
||||
IniFile m_gameini_default;
|
||||
IniFile m_gameini_local;
|
||||
std::string m_gameini_local_path;
|
||||
std::string m_game_id;
|
||||
u32 m_game_revision;
|
||||
Gecko::CodeConfigPanel* m_geckocode_panel;
|
||||
IniFile m_gameini_default;
|
||||
IniFile m_gameini_local;
|
||||
std::string m_gameini_local_path;
|
||||
std::string m_game_id;
|
||||
u32 m_game_revision;
|
||||
|
||||
bool m_ignore_ini_callback = false;
|
||||
bool m_ignore_ini_callback = false;
|
||||
|
||||
void Init_ChildControls();
|
||||
void Init_ChildControls();
|
||||
|
||||
void Load_ARCodes();
|
||||
void Load_GeckoCodes();
|
||||
void Load_ARCodes();
|
||||
void Load_GeckoCodes();
|
||||
|
||||
// --- Wx Events Handlers ---
|
||||
// Cheat Search
|
||||
void OnNewARCodeCreated(wxCommandEvent& ev);
|
||||
// --- Wx Events Handlers ---
|
||||
// Cheat Search
|
||||
void OnNewARCodeCreated(wxCommandEvent& ev);
|
||||
|
||||
// Close Button
|
||||
void OnEvent_ButtonClose_Press(wxCommandEvent& event);
|
||||
void OnEvent_Close(wxCloseEvent& ev);
|
||||
// Close Button
|
||||
void OnEvent_ButtonClose_Press(wxCommandEvent& event);
|
||||
void OnEvent_Close(wxCloseEvent& ev);
|
||||
|
||||
// Cheats List
|
||||
void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event);
|
||||
void OnEvent_CheatsList_Update(wxCommandEvent& event);
|
||||
// Cheats List
|
||||
void OnEvent_CheatsList_ItemSelected(wxCommandEvent& event);
|
||||
void OnEvent_CheatsList_Update(wxCommandEvent& event);
|
||||
|
||||
// Apply Changes Button
|
||||
void OnEvent_ApplyChanges_Press(wxCommandEvent& event);
|
||||
// Apply Changes Button
|
||||
void OnEvent_ApplyChanges_Press(wxCommandEvent& event);
|
||||
|
||||
// Update Log Button
|
||||
void OnEvent_ButtonUpdateLog_Press(wxCommandEvent& event);
|
||||
void OnClearActionReplayLog(wxCommandEvent& event);
|
||||
// Update Log Button
|
||||
void OnEvent_ButtonUpdateLog_Press(wxCommandEvent& event);
|
||||
void OnClearActionReplayLog(wxCommandEvent& event);
|
||||
|
||||
// Enable Logging Checkbox
|
||||
void OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& event);
|
||||
// Enable Logging Checkbox
|
||||
void OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& event);
|
||||
};
|
||||
|
@ -10,87 +10,87 @@
|
||||
|
||||
#include "Core/ActionReplay.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "DolphinWX/ISOProperties.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "DolphinWX/Cheats/CheatsWindow.h"
|
||||
#include "DolphinWX/Cheats/CreateCodeDialog.h"
|
||||
#include "DolphinWX/ISOProperties.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
CreateCodeDialog::CreateCodeDialog(wxWindow* const parent, const u32 address)
|
||||
: wxDialog(parent, wxID_ANY, _("Create AR Code"))
|
||||
, m_code_address(address)
|
||||
: wxDialog(parent, wxID_ANY, _("Create AR Code")), m_code_address(address)
|
||||
{
|
||||
wxStaticText* const label_name = new wxStaticText(this, wxID_ANY, _("Name: "));
|
||||
m_textctrl_name = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(256, -1));
|
||||
wxStaticText* const label_name = new wxStaticText(this, wxID_ANY, _("Name: "));
|
||||
m_textctrl_name =
|
||||
new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(256, -1));
|
||||
|
||||
wxStaticText* const label_code = new wxStaticText(this, wxID_ANY, _("Code: "));
|
||||
m_textctrl_code = new wxTextCtrl(this, wxID_ANY, wxString::Format("0x%08x", address));
|
||||
m_textctrl_code->Disable();
|
||||
wxStaticText* const label_code = new wxStaticText(this, wxID_ANY, _("Code: "));
|
||||
m_textctrl_code = new wxTextCtrl(this, wxID_ANY, wxString::Format("0x%08x", address));
|
||||
m_textctrl_code->Disable();
|
||||
|
||||
wxStaticText* const label_value = new wxStaticText(this, wxID_ANY, _("Value: "));
|
||||
m_textctrl_value = new wxTextCtrl(this, wxID_ANY, "0");
|
||||
wxStaticText* const label_value = new wxStaticText(this, wxID_ANY, _("Value: "));
|
||||
m_textctrl_value = new wxTextCtrl(this, wxID_ANY, "0");
|
||||
|
||||
m_checkbox_use_hex = new wxCheckBox(this, wxID_ANY, _("Use Hex"));
|
||||
m_checkbox_use_hex->SetValue(true);
|
||||
m_checkbox_use_hex = new wxCheckBox(this, wxID_ANY, _("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);
|
||||
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);
|
||||
// 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);
|
||||
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();
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// create the new code
|
||||
ActionReplay::ARCode new_cheat;
|
||||
new_cheat.active = false;
|
||||
new_cheat.user_defined = true;
|
||||
new_cheat.name = WxStrToStr(code_name);
|
||||
new_cheat.ops.emplace_back(ActionReplay::AREntry(m_code_address, code_value));
|
||||
// create the new code
|
||||
ActionReplay::ARCode new_cheat;
|
||||
new_cheat.active = false;
|
||||
new_cheat.user_defined = true;
|
||||
new_cheat.name = WxStrToStr(code_name);
|
||||
new_cheat.ops.emplace_back(ActionReplay::AREntry(m_code_address, code_value));
|
||||
|
||||
wxCommandEvent add_event(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, GetId());
|
||||
add_event.SetClientData(&new_cheat);
|
||||
GetParent()->GetEventHandler()->ProcessEvent(add_event);
|
||||
wxCommandEvent add_event(DOLPHIN_EVT_ADD_NEW_ACTION_REPLAY_CODE, GetId());
|
||||
add_event.SetClientData(&new_cheat);
|
||||
GetParent()->GetEventHandler()->ProcessEvent(add_event);
|
||||
|
||||
Close();
|
||||
Close();
|
||||
}
|
||||
|
||||
void CreateCodeDialog::PressCancel(wxCommandEvent& ev)
|
||||
{
|
||||
Close();
|
||||
Close();
|
||||
}
|
||||
|
||||
void CreateCodeDialog::OnEvent_Close(wxCloseEvent& ev)
|
||||
{
|
||||
Destroy();
|
||||
Destroy();
|
||||
}
|
||||
|
@ -15,17 +15,17 @@ class wxTextCtrl;
|
||||
class CreateCodeDialog final : public wxDialog
|
||||
{
|
||||
public:
|
||||
CreateCodeDialog(wxWindow* const parent, const u32 address);
|
||||
CreateCodeDialog(wxWindow* const parent, const u32 address);
|
||||
|
||||
private:
|
||||
const u32 m_code_address;
|
||||
const u32 m_code_address;
|
||||
|
||||
wxTextCtrl* m_textctrl_name;
|
||||
wxTextCtrl* m_textctrl_code;
|
||||
wxTextCtrl* m_textctrl_value;
|
||||
wxCheckBox* m_checkbox_use_hex;
|
||||
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);
|
||||
void PressOK(wxCommandEvent&);
|
||||
void PressCancel(wxCommandEvent&);
|
||||
void OnEvent_Close(wxCloseEvent& ev);
|
||||
};
|
||||
|
@ -2,10 +2,10 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <SFML/Network/Http.hpp>
|
||||
#include <wx/button.h>
|
||||
#include <wx/checklst.h>
|
||||
#include <wx/listbox.h>
|
||||
@ -20,287 +20,284 @@
|
||||
#include "Core/Core.h"
|
||||
#include "Core/GeckoCode.h"
|
||||
#include "Core/GeckoCodeConfig.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "DolphinWX/Cheats/GeckoCodeDiag.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
namespace Gecko
|
||||
{
|
||||
static const wxString wxstr_name(wxTRANSLATE("Name: ")), wxstr_notes(wxTRANSLATE("Notes: ")),
|
||||
wxstr_creator(wxTRANSLATE("Creator: "));
|
||||
|
||||
static const wxString wxstr_name(wxTRANSLATE("Name: ")),
|
||||
wxstr_notes(wxTRANSLATE("Notes: ")),
|
||||
wxstr_creator(wxTRANSLATE("Creator: "));
|
||||
|
||||
CodeConfigPanel::CodeConfigPanel(wxWindow* const parent)
|
||||
: wxPanel(parent)
|
||||
CodeConfigPanel::CodeConfigPanel(wxWindow* const parent) : wxPanel(parent)
|
||||
{
|
||||
m_listbox_gcodes = new wxCheckListBox(this, wxID_ANY);
|
||||
m_listbox_gcodes->Bind(wxEVT_LISTBOX, &CodeConfigPanel::UpdateInfoBox, this);
|
||||
m_listbox_gcodes->Bind(wxEVT_CHECKLISTBOX, &CodeConfigPanel::ToggleCode, this);
|
||||
m_listbox_gcodes = new wxCheckListBox(this, wxID_ANY);
|
||||
m_listbox_gcodes->Bind(wxEVT_LISTBOX, &CodeConfigPanel::UpdateInfoBox, this);
|
||||
m_listbox_gcodes->Bind(wxEVT_CHECKLISTBOX, &CodeConfigPanel::ToggleCode, this);
|
||||
|
||||
m_infobox.label_name = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_name));
|
||||
m_infobox.label_creator = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_creator));
|
||||
m_infobox.label_notes = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_notes));
|
||||
m_infobox.textctrl_notes = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(64, -1), wxTE_MULTILINE | wxTE_READONLY);
|
||||
m_infobox.listbox_codes = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 64));
|
||||
m_infobox.label_name = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_name));
|
||||
m_infobox.label_creator = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_creator));
|
||||
m_infobox.label_notes = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_notes));
|
||||
m_infobox.textctrl_notes = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(64, -1), wxTE_MULTILINE | wxTE_READONLY);
|
||||
m_infobox.listbox_codes = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 64));
|
||||
|
||||
// TODO: buttons to add/edit codes
|
||||
// TODO: buttons to add/edit codes
|
||||
|
||||
// sizers
|
||||
wxBoxSizer* const sizer_infobox = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_infobox->Add(m_infobox.label_name, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_creator, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_notes, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.textctrl_notes, 0, wxBOTTOM | wxEXPAND, 5);
|
||||
sizer_infobox->Add(m_infobox.listbox_codes, 1, wxEXPAND, 5);
|
||||
// sizers
|
||||
wxBoxSizer* const sizer_infobox = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_infobox->Add(m_infobox.label_name, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_creator, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_notes, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.textctrl_notes, 0, wxBOTTOM | wxEXPAND, 5);
|
||||
sizer_infobox->Add(m_infobox.listbox_codes, 1, wxEXPAND, 5);
|
||||
|
||||
// button sizer
|
||||
wxBoxSizer* const sizer_buttons = new wxBoxSizer(wxHORIZONTAL);
|
||||
btn_download = new wxButton(this, wxID_ANY, _("Download Codes (WiiRD Database)"), wxDefaultPosition, wxSize(128, -1));
|
||||
btn_download->Disable();
|
||||
btn_download->Bind(wxEVT_BUTTON, &CodeConfigPanel::DownloadCodes, this);
|
||||
sizer_buttons->AddStretchSpacer(1);
|
||||
sizer_buttons->Add(btn_download, 1, wxEXPAND);
|
||||
// button sizer
|
||||
wxBoxSizer* const sizer_buttons = new wxBoxSizer(wxHORIZONTAL);
|
||||
btn_download = new wxButton(this, wxID_ANY, _("Download Codes (WiiRD Database)"),
|
||||
wxDefaultPosition, wxSize(128, -1));
|
||||
btn_download->Disable();
|
||||
btn_download->Bind(wxEVT_BUTTON, &CodeConfigPanel::DownloadCodes, this);
|
||||
sizer_buttons->AddStretchSpacer(1);
|
||||
sizer_buttons->Add(btn_download, 1, wxEXPAND);
|
||||
|
||||
// horizontal sizer
|
||||
wxBoxSizer* const sizer_vert = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_vert->Add(sizer_infobox, 1, wxEXPAND);
|
||||
sizer_vert->Add(sizer_buttons, 0, wxEXPAND | wxTOP, 5);
|
||||
// horizontal sizer
|
||||
wxBoxSizer* const sizer_vert = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_vert->Add(sizer_infobox, 1, wxEXPAND);
|
||||
sizer_vert->Add(sizer_buttons, 0, wxEXPAND | wxTOP, 5);
|
||||
|
||||
wxBoxSizer* const sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_main->Add(m_listbox_gcodes, 1, wxALL | wxEXPAND, 5);
|
||||
sizer_main->Add(sizer_vert, 0, wxALL | wxEXPAND, 5);
|
||||
wxBoxSizer* const sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_main->Add(m_listbox_gcodes, 1, wxALL | wxEXPAND, 5);
|
||||
sizer_main->Add(sizer_vert, 0, wxALL | wxEXPAND, 5);
|
||||
|
||||
SetSizerAndFit(sizer_main);
|
||||
SetSizerAndFit(sizer_main);
|
||||
}
|
||||
|
||||
void CodeConfigPanel::UpdateCodeList(bool checkRunning)
|
||||
{
|
||||
// disable the button if it doesn't have an effect
|
||||
btn_download->Enable((!checkRunning || Core::IsRunning()) && !m_gameid.empty());
|
||||
// disable the button if it doesn't have an effect
|
||||
btn_download->Enable((!checkRunning || Core::IsRunning()) && !m_gameid.empty());
|
||||
|
||||
m_listbox_gcodes->Clear();
|
||||
// add the codes to the listbox
|
||||
for (const GeckoCode& code : m_gcodes)
|
||||
{
|
||||
m_listbox_gcodes->Append(StrToWxStr(code.name));
|
||||
if (code.enabled)
|
||||
{
|
||||
m_listbox_gcodes->Check(m_listbox_gcodes->GetCount()-1, true);
|
||||
}
|
||||
}
|
||||
m_listbox_gcodes->Clear();
|
||||
// add the codes to the listbox
|
||||
for (const GeckoCode& code : m_gcodes)
|
||||
{
|
||||
m_listbox_gcodes->Append(StrToWxStr(code.name));
|
||||
if (code.enabled)
|
||||
{
|
||||
m_listbox_gcodes->Check(m_listbox_gcodes->GetCount() - 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
wxCommandEvent evt;
|
||||
UpdateInfoBox(evt);
|
||||
wxCommandEvent evt;
|
||||
UpdateInfoBox(evt);
|
||||
}
|
||||
|
||||
void CodeConfigPanel::LoadCodes(const IniFile& globalIni, const IniFile& localIni, const std::string& gameid, bool checkRunning)
|
||||
void CodeConfigPanel::LoadCodes(const IniFile& globalIni, const IniFile& localIni,
|
||||
const std::string& gameid, bool checkRunning)
|
||||
{
|
||||
m_gameid = gameid;
|
||||
m_gameid = gameid;
|
||||
|
||||
m_gcodes.clear();
|
||||
if (!checkRunning || Core::IsRunning())
|
||||
Gecko::LoadCodes(globalIni, localIni, m_gcodes);
|
||||
m_gcodes.clear();
|
||||
if (!checkRunning || Core::IsRunning())
|
||||
Gecko::LoadCodes(globalIni, localIni, m_gcodes);
|
||||
|
||||
UpdateCodeList(checkRunning);
|
||||
UpdateCodeList(checkRunning);
|
||||
}
|
||||
|
||||
void CodeConfigPanel::ToggleCode(wxCommandEvent& evt)
|
||||
{
|
||||
const int sel = evt.GetInt(); // this right?
|
||||
if (sel > -1)
|
||||
m_gcodes[sel].enabled = m_listbox_gcodes->IsChecked(sel);
|
||||
const int sel = evt.GetInt(); // this right?
|
||||
if (sel > -1)
|
||||
m_gcodes[sel].enabled = m_listbox_gcodes->IsChecked(sel);
|
||||
}
|
||||
|
||||
void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
|
||||
{
|
||||
m_infobox.listbox_codes->Clear();
|
||||
const int sel = m_listbox_gcodes->GetSelection();
|
||||
m_infobox.listbox_codes->Clear();
|
||||
const int sel = m_listbox_gcodes->GetSelection();
|
||||
|
||||
if (sel > -1)
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + StrToWxStr(m_gcodes[sel].name));
|
||||
if (sel > -1)
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + StrToWxStr(m_gcodes[sel].name));
|
||||
|
||||
// notes textctrl
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
for (const std::string& note : m_gcodes[sel].notes)
|
||||
{
|
||||
m_infobox.textctrl_notes->AppendText(StrToWxStr(note));
|
||||
}
|
||||
m_infobox.textctrl_notes->ScrollLines(-99); // silly
|
||||
// notes textctrl
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
for (const std::string& note : m_gcodes[sel].notes)
|
||||
{
|
||||
m_infobox.textctrl_notes->AppendText(StrToWxStr(note));
|
||||
}
|
||||
m_infobox.textctrl_notes->ScrollLines(-99); // silly
|
||||
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) + StrToWxStr(m_gcodes[sel].creator));
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) +
|
||||
StrToWxStr(m_gcodes[sel].creator));
|
||||
|
||||
// add codes to info listbox
|
||||
for (const GeckoCode::Code& code : m_gcodes[sel].codes)
|
||||
{
|
||||
m_infobox.listbox_codes->Append(wxString::Format("%08X %08X", code.address, code.data));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name));
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator));
|
||||
}
|
||||
// add codes to info listbox
|
||||
for (const GeckoCode::Code& code : m_gcodes[sel].codes)
|
||||
{
|
||||
m_infobox.listbox_codes->Append(wxString::Format("%08X %08X", code.address, code.data));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name));
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator));
|
||||
}
|
||||
}
|
||||
|
||||
void CodeConfigPanel::DownloadCodes(wxCommandEvent&)
|
||||
{
|
||||
if (m_gameid.empty())
|
||||
return;
|
||||
if (m_gameid.empty())
|
||||
return;
|
||||
|
||||
std::string gameid = m_gameid;
|
||||
std::string gameid = m_gameid;
|
||||
|
||||
switch (m_gameid[0])
|
||||
{
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'G':
|
||||
break;
|
||||
default:
|
||||
// All channels (WiiWare, VirtualConsole, etc) are identified by their first four characters
|
||||
gameid = m_gameid.substr(0, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (m_gameid[0])
|
||||
{
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'G':
|
||||
break;
|
||||
default:
|
||||
// All channels (WiiWare, VirtualConsole, etc) are identified by their first four characters
|
||||
gameid = m_gameid.substr(0, 4);
|
||||
break;
|
||||
}
|
||||
sf::Http::Request req;
|
||||
req.setUri("/txt.php?txt=" + gameid);
|
||||
|
||||
sf::Http::Request req;
|
||||
req.setUri("/txt.php?txt=" + gameid);
|
||||
sf::Http http;
|
||||
http.setHost("geckocodes.org");
|
||||
|
||||
sf::Http http;
|
||||
http.setHost("geckocodes.org");
|
||||
const sf::Http::Response resp = http.sendRequest(req, sf::seconds(5));
|
||||
|
||||
const sf::Http::Response resp = http.sendRequest(req, sf::seconds(5));
|
||||
if (sf::Http::Response::Ok == resp.getStatus())
|
||||
{
|
||||
// temp vector containing parsed codes
|
||||
std::vector<GeckoCode> gcodes;
|
||||
|
||||
if (sf::Http::Response::Ok == resp.getStatus())
|
||||
{
|
||||
// temp vector containing parsed codes
|
||||
std::vector<GeckoCode> gcodes;
|
||||
// parse the codes
|
||||
std::istringstream ss(resp.getBody());
|
||||
|
||||
// parse the codes
|
||||
std::istringstream ss(resp.getBody());
|
||||
std::string line;
|
||||
|
||||
std::string line;
|
||||
// seek past the header, get to the first code
|
||||
std::getline(ss, line);
|
||||
std::getline(ss, line);
|
||||
std::getline(ss, line);
|
||||
|
||||
// seek past the header, get to the first code
|
||||
std::getline(ss, line);
|
||||
std::getline(ss, line);
|
||||
std::getline(ss, line);
|
||||
int read_state = 0;
|
||||
GeckoCode gcode;
|
||||
|
||||
int read_state = 0;
|
||||
GeckoCode gcode;
|
||||
while ((std::getline(ss, line).good()))
|
||||
{
|
||||
// Remove \r at the end of the line for files using windows line endings, std::getline only
|
||||
// removes \n
|
||||
line = StripSpaces(line);
|
||||
|
||||
while ((std::getline(ss, line).good()))
|
||||
{
|
||||
// Remove \r at the end of the line for files using windows line endings, std::getline only removes \n
|
||||
line = StripSpaces(line);
|
||||
if (line.empty())
|
||||
{
|
||||
// add the code
|
||||
if (gcode.codes.size())
|
||||
gcodes.push_back(gcode);
|
||||
gcode = GeckoCode();
|
||||
read_state = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.empty())
|
||||
{
|
||||
// add the code
|
||||
if (gcode.codes.size())
|
||||
gcodes.push_back(gcode);
|
||||
gcode = GeckoCode();
|
||||
read_state = 0;
|
||||
continue;
|
||||
}
|
||||
switch (read_state)
|
||||
{
|
||||
// read new code
|
||||
case 0:
|
||||
{
|
||||
std::istringstream ssline(line);
|
||||
// stop at [ character (beginning of contributor name)
|
||||
std::getline(ssline, gcode.name, '[');
|
||||
gcode.name = StripSpaces(gcode.name);
|
||||
gcode.user_defined = true;
|
||||
// read the code creator name
|
||||
std::getline(ssline, gcode.creator, ']');
|
||||
read_state = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
switch (read_state)
|
||||
{
|
||||
// read new code
|
||||
case 0 :
|
||||
{
|
||||
std::istringstream ssline(line);
|
||||
// stop at [ character (beginning of contributor name)
|
||||
std::getline(ssline, gcode.name, '[');
|
||||
gcode.name = StripSpaces(gcode.name);
|
||||
gcode.user_defined = true;
|
||||
// read the code creator name
|
||||
std::getline(ssline, gcode.creator, ']');
|
||||
read_state = 1;
|
||||
}
|
||||
break;
|
||||
// read code lines
|
||||
case 1:
|
||||
{
|
||||
std::istringstream ssline(line);
|
||||
std::string addr, data;
|
||||
ssline >> addr >> data;
|
||||
ssline.seekg(0);
|
||||
|
||||
// read code lines
|
||||
case 1 :
|
||||
{
|
||||
std::istringstream ssline(line);
|
||||
std::string addr, data;
|
||||
ssline >> addr >> data;
|
||||
ssline.seekg(0);
|
||||
// check if this line a code, silly, but the dumb txt file comment lines can start with
|
||||
// valid hex chars :/
|
||||
if (8 == addr.length() && 8 == data.length())
|
||||
{
|
||||
GeckoCode::Code new_code;
|
||||
new_code.original_line = line;
|
||||
ssline >> std::hex >> new_code.address >> new_code.data;
|
||||
gcode.codes.push_back(new_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
gcode.notes.push_back(line);
|
||||
read_state = 2; // start reading comments
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// check if this line a code, silly, but the dumb txt file comment lines can start with valid hex chars :/
|
||||
if (8 == addr.length() && 8 == data.length())
|
||||
{
|
||||
GeckoCode::Code new_code;
|
||||
new_code.original_line = line;
|
||||
ssline >> std::hex >> new_code.address >> new_code.data;
|
||||
gcode.codes.push_back(new_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
gcode.notes.push_back(line);
|
||||
read_state = 2; // start reading comments
|
||||
}
|
||||
// read comment lines
|
||||
case 2:
|
||||
// append comment line
|
||||
gcode.notes.push_back(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
// add the last code
|
||||
if (gcode.codes.size())
|
||||
gcodes.push_back(gcode);
|
||||
|
||||
// read comment lines
|
||||
case 2 :
|
||||
// append comment line
|
||||
gcode.notes.push_back(line);
|
||||
break;
|
||||
if (gcodes.size())
|
||||
{
|
||||
unsigned long added_count = 0;
|
||||
|
||||
}
|
||||
}
|
||||
// append the codes to the code list
|
||||
for (const GeckoCode& code : gcodes)
|
||||
{
|
||||
// only add codes which do not already exist
|
||||
std::vector<GeckoCode>::const_iterator existing_gcodes_iter = m_gcodes.begin(),
|
||||
existing_gcodes_end = m_gcodes.end();
|
||||
for (;; ++existing_gcodes_iter)
|
||||
{
|
||||
if (existing_gcodes_end == existing_gcodes_iter)
|
||||
{
|
||||
m_gcodes.push_back(code);
|
||||
++added_count;
|
||||
break;
|
||||
}
|
||||
|
||||
// add the last code
|
||||
if (gcode.codes.size())
|
||||
gcodes.push_back(gcode);
|
||||
// code exists
|
||||
if (existing_gcodes_iter->Compare(code))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gcodes.size())
|
||||
{
|
||||
unsigned long added_count = 0;
|
||||
wxMessageBox(wxString::Format(_("Downloaded %lu codes. (added %lu)"),
|
||||
(unsigned long)gcodes.size(), added_count));
|
||||
|
||||
// append the codes to the code list
|
||||
for (const GeckoCode& code : gcodes)
|
||||
{
|
||||
// only add codes which do not already exist
|
||||
std::vector<GeckoCode>::const_iterator
|
||||
existing_gcodes_iter = m_gcodes.begin(),
|
||||
existing_gcodes_end = m_gcodes.end();
|
||||
for (;; ++existing_gcodes_iter)
|
||||
{
|
||||
if (existing_gcodes_end == existing_gcodes_iter)
|
||||
{
|
||||
m_gcodes.push_back(code);
|
||||
++added_count;
|
||||
break;
|
||||
}
|
||||
|
||||
// code exists
|
||||
if (existing_gcodes_iter->Compare(code))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wxMessageBox(wxString::Format(_("Downloaded %lu codes. (added %lu)"),
|
||||
(unsigned long)gcodes.size(), added_count));
|
||||
|
||||
// refresh the list
|
||||
UpdateCodeList();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxMessageBox(_("File contained no codes."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WxUtils::ShowErrorDialog(_("Failed to download codes."));
|
||||
}
|
||||
// refresh the list
|
||||
UpdateCodeList();
|
||||
}
|
||||
else
|
||||
{
|
||||
wxMessageBox(_("File contained no codes."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WxUtils::ShowErrorDialog(_("Failed to download codes."));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -19,39 +19,35 @@ class wxTextCtrl;
|
||||
|
||||
namespace Gecko
|
||||
{
|
||||
|
||||
|
||||
class CodeConfigPanel : public wxPanel
|
||||
{
|
||||
public:
|
||||
CodeConfigPanel(wxWindow* const parent);
|
||||
|
||||
|
||||
void LoadCodes(const IniFile& globalIni, const IniFile& localIni, const std::string& gameid = "", bool checkRunning = false);
|
||||
const std::vector<GeckoCode>& GetCodes() const { return m_gcodes; }
|
||||
CodeConfigPanel(wxWindow* const parent);
|
||||
|
||||
void LoadCodes(const IniFile& globalIni, const IniFile& localIni, const std::string& gameid = "",
|
||||
bool checkRunning = false);
|
||||
const std::vector<GeckoCode>& GetCodes() const { return m_gcodes; }
|
||||
protected:
|
||||
void UpdateInfoBox(wxCommandEvent&);
|
||||
void ToggleCode(wxCommandEvent& evt);
|
||||
void DownloadCodes(wxCommandEvent&);
|
||||
//void ApplyChanges(wxCommandEvent&);
|
||||
void UpdateInfoBox(wxCommandEvent&);
|
||||
void ToggleCode(wxCommandEvent& evt);
|
||||
void DownloadCodes(wxCommandEvent&);
|
||||
// void ApplyChanges(wxCommandEvent&);
|
||||
|
||||
void UpdateCodeList(bool checkRunning = false);
|
||||
void UpdateCodeList(bool checkRunning = false);
|
||||
|
||||
private:
|
||||
std::vector<GeckoCode> m_gcodes;
|
||||
std::vector<GeckoCode> m_gcodes;
|
||||
|
||||
std::string m_gameid;
|
||||
std::string m_gameid;
|
||||
|
||||
// wxwidgets stuff
|
||||
wxCheckListBox* m_listbox_gcodes;
|
||||
struct
|
||||
{
|
||||
wxStaticText* label_name, *label_notes, *label_creator;
|
||||
wxTextCtrl* textctrl_notes;
|
||||
wxListBox* listbox_codes;
|
||||
} m_infobox;
|
||||
wxButton* btn_download;
|
||||
// wxwidgets stuff
|
||||
wxCheckListBox* m_listbox_gcodes;
|
||||
struct
|
||||
{
|
||||
wxStaticText *label_name, *label_notes, *label_creator;
|
||||
wxTextCtrl* textctrl_notes;
|
||||
wxListBox* listbox_codes;
|
||||
} m_infobox;
|
||||
wxButton* btn_download;
|
||||
};
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user