mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Added a button to the "Gecko Codes" panel to download/parse codes from geckocodes.org. Codes that require modifiers (the XXXX business) will still not work properly, though they should load/save fine. A few more code types should work now. (All non-ASM type codes should at least attempt to run :p) Hacked a param into IniFile::GetLines to disable removal of text after # chars, so codes with # in the name/notes should load fine.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5949 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@@ -350,7 +350,7 @@ bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) c
|
||||
}
|
||||
|
||||
// Return a list of all lines in a section
|
||||
bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines) const
|
||||
bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines, const bool remove_comments) const
|
||||
{
|
||||
const Section* section = GetSection(sectionName);
|
||||
if (!section)
|
||||
@@ -360,15 +360,19 @@ bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines)
|
||||
for (std::vector<std::string>::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
|
||||
{
|
||||
std::string line = StripSpaces(*iter);
|
||||
int commentPos = (int)line.find('#');
|
||||
if (commentPos == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (commentPos != (int)std::string::npos)
|
||||
if (remove_comments)
|
||||
{
|
||||
line = StripSpaces(line.substr(0, commentPos));
|
||||
int commentPos = (int)line.find('#');
|
||||
if (commentPos == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (commentPos != (int)std::string::npos)
|
||||
{
|
||||
line = StripSpaces(line.substr(0, commentPos));
|
||||
}
|
||||
}
|
||||
|
||||
lines.push_back(line);
|
||||
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
bool GetKeys(const char* sectionName, std::vector<std::string>& keys) const;
|
||||
|
||||
void SetLines(const char* sectionName, const std::vector<std::string> &lines);
|
||||
bool GetLines(const char* sectionName, std::vector<std::string>& lines) const;
|
||||
bool GetLines(const char* sectionName, std::vector<std::string>& lines, const bool remove_comments = true) const;
|
||||
|
||||
bool DeleteKey(const char* sectionName, const char* key);
|
||||
bool DeleteSection(const char* sectionName);
|
||||
|
||||
+218
-128
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,8 @@ namespace Gecko
|
||||
|
||||
struct Code
|
||||
{
|
||||
Code() : address(0), data(0) {}
|
||||
|
||||
union
|
||||
{
|
||||
u32 address;
|
||||
@@ -50,11 +52,14 @@ namespace Gecko
|
||||
//};
|
||||
};
|
||||
|
||||
std::string original_line;
|
||||
|
||||
u32 GetAddress() const;
|
||||
};
|
||||
|
||||
std::vector<Code> codes;
|
||||
std::string name, description, creator;
|
||||
std::string name, creator;
|
||||
std::vector<std::string> notes;
|
||||
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Gecko
|
||||
void LoadCodes(const IniFile& inifile, std::vector<GeckoCode>& gcodes)
|
||||
{
|
||||
std::vector<std::string> lines;
|
||||
inifile.GetLines(GECKO_CODE_INI_SECTION, lines);
|
||||
inifile.GetLines(GECKO_CODE_INI_SECTION, lines, false);
|
||||
|
||||
GeckoCode gcode;
|
||||
|
||||
@@ -29,6 +29,8 @@ void LoadCodes(const IniFile& inifile, std::vector<GeckoCode>& gcodes)
|
||||
|
||||
std::istringstream ss(*lines_iter);
|
||||
|
||||
int read_state = 0;
|
||||
|
||||
switch ((*lines_iter)[0])
|
||||
{
|
||||
|
||||
@@ -46,30 +48,24 @@ void LoadCodes(const IniFile& inifile, std::vector<GeckoCode>& gcodes)
|
||||
gcode.name = StripSpaces(gcode.name);
|
||||
// read the code creator name
|
||||
std::getline(ss, gcode.creator, ']');
|
||||
read_state = 0;
|
||||
break;
|
||||
|
||||
// description
|
||||
// notes
|
||||
case '*':
|
||||
ss.seekg(1);
|
||||
std::getline(ss, gcode.description);
|
||||
break;
|
||||
|
||||
// start of code option list
|
||||
case ':':
|
||||
// TODO:
|
||||
gcode.notes.push_back(std::string(++lines_iter->begin(), lines_iter->end()));
|
||||
break;
|
||||
|
||||
// either part of the code, or an option choice
|
||||
default :
|
||||
// TODO: check if we are reading an option list
|
||||
{
|
||||
GeckoCode::Code new_code;
|
||||
// TODO: support options
|
||||
new_code.original_line = *lines_iter;
|
||||
ss >> std::hex >> new_code.address >> new_code.data;
|
||||
gcode.codes.push_back(new_code);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -100,10 +96,6 @@ void SaveGeckoCode(std::vector<std::string>& lines, const GeckoCode& gcode)
|
||||
}
|
||||
|
||||
lines.push_back(name);
|
||||
|
||||
// save the description
|
||||
if (gcode.description.size())
|
||||
lines.push_back(std::string("*") + gcode.description);
|
||||
|
||||
// save all the code lines
|
||||
std::vector<GeckoCode::Code>::const_iterator
|
||||
@@ -112,13 +104,17 @@ void SaveGeckoCode(std::vector<std::string>& lines, const GeckoCode& gcode)
|
||||
for (; codes_iter!=codes_end; ++codes_iter)
|
||||
{
|
||||
//ss << std::hex << codes_iter->address << ' ' << codes_iter->data;
|
||||
lines.push_back(StringFromFormat("%08X %08X", codes_iter->address, codes_iter->data));
|
||||
//lines.push_back(StringFromFormat("%08X %08X", codes_iter->address, codes_iter->data));
|
||||
lines.push_back(codes_iter->original_line);
|
||||
//ss.clear();
|
||||
}
|
||||
|
||||
//lines.push_back("BLAH");
|
||||
|
||||
// TODO: save the options
|
||||
// save the notes
|
||||
std::vector<std::string>::const_iterator
|
||||
notes_iter = gcode.notes.begin(),
|
||||
notes_end = gcode.notes.end();
|
||||
for (; notes_iter!=notes_end; ++notes_iter)
|
||||
lines.push_back(std::string("*") + *notes_iter);
|
||||
}
|
||||
|
||||
void SaveCodes(IniFile& inifile, const std::vector<GeckoCode>& gcodes)
|
||||
|
||||
@@ -34,7 +34,7 @@ extern std::vector<ActionReplay::ARCode> arCodes;
|
||||
static wxCheatsWindow *g_cheat_window;
|
||||
|
||||
wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
|
||||
: wxFrame(parent, wxID_ANY, wxT("Action Replay"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
: wxFrame(parent, wxID_ANY, wxT("Cheats Manager"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
|
||||
{
|
||||
::g_cheat_window = this;
|
||||
|
||||
@@ -201,8 +201,8 @@ CheatSearchTab::CheatSearchTab(wxWindow* const parent)
|
||||
// filter types in the compare dropdown
|
||||
static const wxString searches[] = {
|
||||
wxT("Unknown"),
|
||||
wxT("Not Equals"),
|
||||
wxT("Equals"),
|
||||
wxT("Not Equal"),
|
||||
wxT("Equal"),
|
||||
wxT("Greater Than"),
|
||||
wxT("Less Than"),
|
||||
// TODO: Implement between search.
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
|
||||
#include "GeckoCodeDiag.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _WINSOCK2API_
|
||||
#endif
|
||||
#include <SFML/Network/Http.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#define _connect_macro_(b, f, c, s) (b)->Connect(wxID_ANY, (c), wxCommandEventHandler(f), (wxObject*)0, (wxEvtHandler*)s)
|
||||
|
||||
namespace Gecko
|
||||
{
|
||||
|
||||
static const wxString wxstr_name(wxT("Name: ")),
|
||||
wxstr_description(wxT("Description: ")),
|
||||
wxstr_notes(wxT("Notes: ")),
|
||||
wxstr_creator(wxT("Creator: "));
|
||||
|
||||
CodeConfigPanel::CodeConfigPanel(wxWindow* const parent)
|
||||
@@ -19,41 +26,40 @@ CodeConfigPanel::CodeConfigPanel(wxWindow* const parent)
|
||||
|
||||
m_infobox.label_name = new wxStaticText(this, -1, wxstr_name);
|
||||
m_infobox.label_creator = new wxStaticText(this, -1, wxstr_creator);
|
||||
m_infobox.label_description = new wxStaticText(this, -1, wxstr_description);
|
||||
m_infobox.label_notes = new wxStaticText(this, -1, wxstr_notes);
|
||||
m_infobox.textctrl_notes = new wxTextCtrl(this, -1, wxEmptyString, wxDefaultPosition, wxSize(64, -1), wxTE_MULTILINE | wxTE_READONLY);
|
||||
m_infobox.listbox_codes = new wxListBox(this, -1, wxDefaultPosition, wxSize(-1, 64));
|
||||
|
||||
// TODO: buttons to add/edit codes
|
||||
|
||||
// sizers
|
||||
wxBoxSizer* const sizer_infobox = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_infobox->Add(m_infobox.label_name, 0, wxLEFT | wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_creator, 0, wxLEFT | wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_description, 0, wxLEFT | wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.listbox_codes, 0, wxLEFT | wxBOTTOM, 5);
|
||||
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);
|
||||
|
||||
//wxBoxSizer* const sizer_horz = new wxBoxSizer(wxHORIZONTAL);
|
||||
//sizer_horz->Add(sizer_infobox, 1, 0);
|
||||
// button sizer
|
||||
wxBoxSizer* const sizer_buttons = new wxBoxSizer(wxVERTICAL);
|
||||
wxButton* const btn_download = new wxButton(this, -1, wxT("Download Codes (WiiRD Database)"), wxDefaultPosition, wxSize(128, -1));
|
||||
_connect_macro_(btn_download, CodeConfigPanel::DownloadCodes, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
sizer_buttons->Add(btn_download, 0, wxEXPAND);
|
||||
|
||||
// silly
|
||||
//if (show_apply_button)
|
||||
//{
|
||||
// wxButton* const btn_apply = new wxButton(this, -1, wxT("Apply Changes"), wxDefaultPosition, wxSize(128, -1));
|
||||
// _connect_macro_(btn_apply, CodeConfigPanel::ApplyChanges, wxEVT_COMMAND_BUTTON_CLICKED, this);
|
||||
// sizer_horz->Add(btn_apply, 0, wxALIGN_RIGHT | wxALIGN_BOTTOM);
|
||||
//}
|
||||
// horizontal sizer
|
||||
wxBoxSizer* const sizer_horz = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_horz->Add(sizer_infobox, 1, wxEXPAND);
|
||||
sizer_horz->Add(sizer_buttons, 1, wxLEFT | wxALIGN_BOTTOM, 5);
|
||||
|
||||
wxBoxSizer* const sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_main->Add(m_listbox_gcodes, 1, wxALL | wxEXPAND, 5);
|
||||
sizer_main->Add(sizer_infobox, 0, wxALL | wxEXPAND, 5);
|
||||
sizer_main->Add(sizer_horz, 0, wxALL | wxEXPAND, 5);
|
||||
|
||||
SetSizerAndFit(sizer_main);
|
||||
}
|
||||
|
||||
void CodeConfigPanel::LoadCodes(const IniFile& inifile)
|
||||
void CodeConfigPanel::UpdateCodeList()
|
||||
{
|
||||
m_gcodes.clear();
|
||||
Gecko::LoadCodes(inifile, m_gcodes);
|
||||
|
||||
m_listbox_gcodes->Clear();
|
||||
// add the codes to the listbox
|
||||
std::vector<GeckoCode>::const_iterator
|
||||
@@ -70,6 +76,16 @@ void CodeConfigPanel::LoadCodes(const IniFile& inifile)
|
||||
UpdateInfoBox(evt);
|
||||
}
|
||||
|
||||
void CodeConfigPanel::LoadCodes(const IniFile& inifile, const std::string& gameid)
|
||||
{
|
||||
m_gameid = gameid;
|
||||
|
||||
m_gcodes.clear();
|
||||
Gecko::LoadCodes(inifile, m_gcodes);
|
||||
|
||||
UpdateCodeList();
|
||||
}
|
||||
|
||||
void CodeConfigPanel::ToggleCode(wxCommandEvent& evt)
|
||||
{
|
||||
const int sel = evt.GetInt(); // this right?
|
||||
@@ -85,7 +101,16 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
|
||||
if (sel > -1)
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxstr_name + wxString::FromAscii(m_gcodes[sel].name.c_str()));
|
||||
m_infobox.label_description->SetLabel(wxstr_description + wxString::FromAscii(m_gcodes[sel].description.c_str()));
|
||||
|
||||
// notes textctrl
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
std::vector<std::string>::const_iterator
|
||||
notes_iter = m_gcodes[sel].notes.begin(),
|
||||
notes_end = m_gcodes[sel].notes.end();
|
||||
for (; notes_iter!=notes_end; ++notes_iter)
|
||||
m_infobox.textctrl_notes->AppendText(wxString::FromAscii(notes_iter->c_str()));
|
||||
m_infobox.textctrl_notes->ScrollLines(-99); // silly
|
||||
|
||||
m_infobox.label_creator->SetLabel(wxstr_creator + wxString::FromAscii(m_gcodes[sel].creator.c_str()));
|
||||
|
||||
// add codes to info listbox
|
||||
@@ -98,15 +123,135 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
|
||||
else
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxstr_name);
|
||||
m_infobox.label_description->SetLabel(wxstr_description);
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
m_infobox.label_creator->SetLabel(wxstr_creator);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeConfigPanel::ApplyChanges(wxCommandEvent&)
|
||||
//void CodeConfigPanel::ApplyChanges(wxCommandEvent&)
|
||||
//{
|
||||
// Gecko::SetActiveCodes(m_gcodes);
|
||||
//}
|
||||
|
||||
void CodeConfigPanel::DownloadCodes(wxCommandEvent&)
|
||||
{
|
||||
Gecko::SetActiveCodes(m_gcodes);
|
||||
if (m_gameid.empty())
|
||||
return;
|
||||
|
||||
sf::Http::Request req;
|
||||
req.SetURI("/txt.php?txt=" + m_gameid);
|
||||
|
||||
sf::Http http;
|
||||
http.SetHost("geckocodes.org");
|
||||
|
||||
const sf::Http::Response resp = http.SendRequest(req, 5.0f);
|
||||
|
||||
if (sf::Http::Response::Ok == resp.GetStatus())
|
||||
{
|
||||
// temp vector containing parsed codes
|
||||
std::vector<GeckoCode> gcodes;
|
||||
|
||||
// parse the codes
|
||||
std::istringstream ss(resp.GetBody());
|
||||
|
||||
// debug
|
||||
//PanicAlert("File size is %i bytes.", ss.str().size());
|
||||
|
||||
std::string line;
|
||||
|
||||
// make sure the txt file is for this game
|
||||
// eh w/e
|
||||
//std::getline(ss, line);
|
||||
//if (line != m_gameid)
|
||||
// PanicAlert("Bad code file.");
|
||||
|
||||
// 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;
|
||||
|
||||
while ((std::getline(ss, line).good()))
|
||||
{
|
||||
// empty line
|
||||
if (0 == line.size() || line == "\r" || line == "\n") // \r\n checks might not be needed
|
||||
{
|
||||
// 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 :
|
||||
gcode.name = line; // TODO: parse creator name in []s
|
||||
read_state = 1;
|
||||
break;
|
||||
|
||||
// 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;
|
||||
|
||||
// read comment lines
|
||||
case 2 :
|
||||
// append comment line
|
||||
gcode.notes.push_back(line);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// add the last code
|
||||
if (gcode.codes.size())
|
||||
gcodes.push_back(gcode);
|
||||
|
||||
if (gcodes.size())
|
||||
{
|
||||
PanicAlert("Downloaded %i codes.", gcodes.size());
|
||||
|
||||
// append the codes to the code list
|
||||
std::vector<GeckoCode>::const_iterator
|
||||
gcodes_iter = gcodes.begin(),
|
||||
gcodes_end = gcodes.end();
|
||||
for (; gcodes_iter!= gcodes_end; ++gcodes_iter)
|
||||
m_gcodes.push_back(*gcodes_iter);
|
||||
|
||||
// refresh the list
|
||||
UpdateCodeList();
|
||||
}
|
||||
else
|
||||
PanicAlert("File contained no codes.");
|
||||
}
|
||||
else
|
||||
PanicAlert("Failed to download codes.");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -17,22 +17,28 @@ public:
|
||||
CodeConfigPanel(wxWindow* const parent);
|
||||
|
||||
|
||||
void LoadCodes(const IniFile& inifile);
|
||||
void LoadCodes(const IniFile& inifile, const std::string& gameid = "");
|
||||
const std::vector<GeckoCode>& GetCodes() const { return m_gcodes; }
|
||||
|
||||
protected:
|
||||
void UpdateInfoBox(wxCommandEvent&);
|
||||
void ToggleCode(wxCommandEvent& evt);
|
||||
void ApplyChanges(wxCommandEvent&);
|
||||
void DownloadCodes(wxCommandEvent&);
|
||||
//void ApplyChanges(wxCommandEvent&);
|
||||
|
||||
void UpdateCodeList();
|
||||
|
||||
private:
|
||||
std::vector<GeckoCode> m_gcodes;
|
||||
|
||||
std::string m_gameid;
|
||||
|
||||
// wxwidgets stuff
|
||||
wxCheckListBox *m_listbox_gcodes;
|
||||
struct
|
||||
{
|
||||
wxStaticText *label_name, *label_description, *label_creator;
|
||||
wxStaticText *label_name, *label_notes, *label_creator;
|
||||
wxTextCtrl *textctrl_notes;
|
||||
wxListBox *listbox_codes;
|
||||
} m_infobox;
|
||||
|
||||
@@ -43,3 +49,4 @@ private:
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -882,7 +882,7 @@ void CISOProperties::LoadGameConfig()
|
||||
|
||||
PatchList_Load();
|
||||
ActionReplayList_Load();
|
||||
m_geckocode_panel->LoadCodes(GameIni);
|
||||
m_geckocode_panel->LoadCodes(GameIni, OpenISO->GetUniqueID());
|
||||
}
|
||||
|
||||
bool CISOProperties::SaveGameConfig()
|
||||
|
||||
Reference in New Issue
Block a user