188 lines
5.5 KiB
C++
Executable file
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;
|
|
}
|