Reformat all the things. Have fun with merge conflicts.

This commit is contained in:
Pierre Bourdon
2016-06-24 10:43:46 +02:00
parent 2115e8a4a6
commit 3570c7f03a
1116 changed files with 187405 additions and 180344 deletions

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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());
}

View File

@ -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);
};

View File

@ -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();
}

View File

@ -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);
};

View File

@ -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."));
}
}
}

View File

@ -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;
};
}