lsnes/ui/tools/cheat-editor.cpp
2013-05-03 17:47:34 +03:00

188 lines
5.5 KiB
C++
Executable file

CheatEditor *cheatEditor = 0;
CheatEditor::CheatEditor() {
setTitle("Cheat Editor");
setGeometry({ 128, 128, 600, 360 });
windowManager->append(this, "CheatEditor");
cheatList.setHeaderText("Slot", "Code", "Description");
cheatList.setHeaderVisible();
cheatList.setCheckable();
codeLabel.setText("Code(s):");
descLabel.setText("Description:");
findButton.setText("Find Codes ...");
clearAllButton.setText("Clear All");
clearButton.setText("Clear");
append(layout);
layout.setMargin(5);
layout.append(cheatList, { ~0, ~0 }, 5);
layout.append(codeLayout, { ~0, 0 }, 5);
codeLayout.append(codeLabel, { 80, 0 }, 0);
codeLayout.append(codeEdit, { ~0, 0 }, 0);
layout.append(descLayout, { ~0, 0 }, 5);
descLayout.append(descLabel, { 80, 0 }, 0);
descLayout.append(descEdit, { ~0, 0 }, 0);
layout.append(controlLayout, { ~0, 0 }, 0);
controlLayout.append(findButton, { 100, 0 }, 0);
controlLayout.append(spacer, { ~0, 0 }, 0);
controlLayout.append(clearAllButton, { 80, 0 }, 5);
controlLayout.append(clearButton, { 80, 0 }, 0);
for(unsigned n = 0; n < 128; n++) cheatList.append("", "", "");
updateUI();
synchronize();
cheatList.onChange = { &CheatEditor::synchronize, this };
cheatList.onToggle = [&](unsigned) { updateInterface(); };
codeEdit.onChange = { &CheatEditor::updateCode, this };
descEdit.onChange = { &CheatEditor::updateDesc, this };
findButton.onActivate = { &CheatDatabase::findCodes, cheatDatabase };
clearAllButton.onActivate = { &CheatEditor::clearAll, this };
clearButton.onActivate = { &CheatEditor::clearSelected, this };
}
void CheatEditor::synchronize() {
layout.setEnabled(interface->cartridgeLoaded());
if(cheatList.selected()) {
unsigned n = cheatList.selection();
codeEdit.setText(cheatText[n][Code]);
descEdit.setText(cheatText[n][Desc]);
codeEdit.setEnabled(true);
descEdit.setEnabled(true);
clearButton.setEnabled(true);
} else {
codeEdit.setText("");
codeEdit.setEnabled(false);
descEdit.setText("");
descEdit.setEnabled(false);
clearButton.setEnabled(false);
}
}
void CheatEditor::updateUI() {
for(unsigned n = 0; n < 128; n++) {
string code = cheatText[n][Code];
string description = cheatText[n][Code] == "" && cheatText[n][Desc] == "" ? "(empty)" : cheatText[n][Desc];
lstring codes;
codes.split("+", code);
cheatList.modify(n, decimal<3>(n + 1), codes.size() == 1 ? code : string{ codes[0], "+..." }, description);
}
cheatList.autoSizeColumns();
}
void CheatEditor::updateInterface() {
lstring cheatCodes;
for(unsigned n = 0; n < 128; n++) {
string code = cheatText[n][Code];
if(cheatList.checked(n) && code != "") cheatCodes.append(code.replace(" ", ""));
}
interface->setCheatCodes(cheatCodes);
}
void CheatEditor::updateCode() {
unsigned n = cheatList.selection();
cheatText[n][Code] = codeEdit.text();
updateUI(), updateInterface();
}
void CheatEditor::updateDesc() {
unsigned n = cheatList.selection();
cheatText[n][Desc] = descEdit.text();
updateUI(), updateInterface();
}
void CheatEditor::clearAll() {
if(MessageWindow::question(*this, "Warning: all cheat codes will be permanently erased!\nAre you sure?")
== MessageWindow::Response::Yes) {
reset();
}
}
void CheatEditor::clearSelected() {
unsigned n = cheatList.selection();
cheatList.setChecked(n, false);
cheatText[n][Code] = "";
cheatText[n][Desc] = "";
codeEdit.setText("");
descEdit.setText("");
updateUI(), updateInterface();
}
void CheatEditor::reset() {
synchronize();
for(unsigned n = 0; n < 128; n++) {
cheatList.setChecked(n, false);
cheatText[n][Code] = "";
cheatText[n][Desc] = "";
}
codeEdit.setText("");
descEdit.setText("");
updateUI(), updateInterface();
}
bool CheatEditor::load(const string &filename) {
synchronize();
string data;
if(data.readfile(filename) == false) return false;
unsigned n = 0;
XML::Document document(data);
for(auto &cheat : document["cartridge"]) {
if(cheat.name != "cheat") continue;
cheatList.setChecked(n, cheat["enable"].data == "true");
cheatText[n][Code] = cheat["code"].data;
cheatText[n][Desc] = cheat["description"].data;
if(++n >= 128) break;
}
updateUI(), updateInterface();
return true;
}
bool CheatEditor::save(const string &filename) {
synchronize();
signed lastSave = -1;
for(signed n = 127; n >= 0; n--) {
if(cheatText[n][Code] != "" || cheatText[n][Desc] != "") {
lastSave = n;
break;
}
}
if(lastSave == -1) {
unlink(filename);
return true;
}
file fp;
if(fp.open(filename, file::mode::write) == false) return false;
fp.print("<?xml version='1.0' encoding='UTF-8'?>\n");
fp.print("<cartridge sha256='", interface->sha256(), "'>\n");
for(unsigned n = 0; n <= lastSave; n++) {
fp.print(" <cheat enable='", cheatList.checked(n) ? "true" : "false", "'>\n");
fp.print(" <description><![CDATA[", cheatText[n][Desc], "]]></description>\n");
fp.print(" <code><![CDATA[", cheatText[n][Code], "]]></code>\n");
fp.print(" </cheat>\n");
}
fp.print("</cartridge>\n");
fp.close();
return true;
}
bool CheatEditor::addCode(const string &code, const string &description) {
for(unsigned n = 0; n < 128; n++) {
if(cheatText[n][Code] == "" && cheatText[n][Desc] == "") {
cheatList.setChecked(n, false);
cheatText[n][Code] = code;
cheatText[n][Desc] = description;
return true;
}
}
return false;
}