mirror of https://github.com/bsnes-emu/bsnes.git
229 lines
6.3 KiB
C++
229 lines
6.3 KiB
C++
CheatDatabase::CheatDatabase() {
|
|
cheatDatabase = this;
|
|
|
|
layout.setMargin(5);
|
|
selectAllButton.setText("Select All").onActivate([&] {
|
|
for(auto item : cheatList.items()) item.setChecked(true);
|
|
});
|
|
unselectAllButton.setText("Unselect All").onActivate([&] {
|
|
for(auto item : cheatList.items()) item.setChecked(false);
|
|
});
|
|
addCheatsButton.setText("Add Cheats").onActivate([&] {
|
|
addCheats();
|
|
});
|
|
|
|
setSize({800, 400});
|
|
setAlignment({0.5, 1.0});
|
|
setDismissable();
|
|
}
|
|
|
|
auto CheatDatabase::findCheats() -> void {
|
|
auto sha256 = emulator->sha256();
|
|
|
|
auto document = BML::unserialize(string::read(locate("cheats.bml")));
|
|
for(auto game : document.find("cartridge")) {
|
|
if(game["sha256"].text() != sha256) continue;
|
|
|
|
cheatList.reset();
|
|
for(auto cheat : game.find("cheat")) {
|
|
cheatList.append(ListViewItem()
|
|
.setCheckable()
|
|
.setText(cheat["description"].text())
|
|
.setProperty("code", cheat["code"].text())
|
|
);
|
|
}
|
|
|
|
setTitle(game["name"].text());
|
|
setVisible();
|
|
return;
|
|
}
|
|
|
|
MessageDialog().setParent(*toolsWindow).setText("Sorry, no cheats were found for this game.").information();
|
|
}
|
|
|
|
auto CheatDatabase::addCheats() -> void {
|
|
for(auto item : cheatList.items()) {
|
|
if(item.checked()) {
|
|
toolsWindow->cheatEditor.addCheat({item.text(), item.property("code"), false});
|
|
}
|
|
}
|
|
setVisible(false);
|
|
}
|
|
|
|
//
|
|
|
|
CheatWindow::CheatWindow() {
|
|
cheatWindow = this;
|
|
|
|
layout.setMargin(5);
|
|
nameLabel.setText("Name:");
|
|
nameValue.onActivate([&] { if(acceptButton.enabled()) acceptButton.doActivate(); });
|
|
nameValue.onChange([&] { doChange(); });
|
|
codeLabel.setText("Code:");
|
|
codeValue.onActivate([&] { if(acceptButton.enabled()) acceptButton.doActivate(); });
|
|
codeValue.onChange([&] { doChange(); });
|
|
enableOption.setText("Enable");
|
|
acceptButton.onActivate([&] { doAccept(); });
|
|
cancelButton.setText("Cancel").onActivate([&] { setVisible(false); });
|
|
|
|
setSize({400, layout.minimumSize().height()});
|
|
setDismissable();
|
|
}
|
|
|
|
auto CheatWindow::show(Cheat cheat) -> void {
|
|
nameValue.setText(cheat.name);
|
|
codeValue.setText(cheat.code);
|
|
enableOption.setChecked(cheat.enable);
|
|
doChange();
|
|
setTitle(!cheat.name ? "Add Cheat" : "Edit Cheat");
|
|
setCentered(*toolsWindow);
|
|
setVisible();
|
|
setFocused();
|
|
nameValue.setFocused();
|
|
acceptButton.setText(!cheat.name ? "Add" : "Edit");
|
|
}
|
|
|
|
auto CheatWindow::doChange() -> void {
|
|
bool valid = true;
|
|
nameValue.setBackgroundColor(nameValue.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
|
|
codeValue.setBackgroundColor(codeValue.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
|
|
acceptButton.setEnabled(valid);
|
|
}
|
|
|
|
auto CheatWindow::doAccept() -> void {
|
|
Cheat cheat = {nameValue.text().strip(), codeValue.text().strip(), enableOption.checked()};
|
|
if(acceptButton.text() == "Add") {
|
|
toolsWindow->cheatEditor.addCheat(cheat);
|
|
} else {
|
|
toolsWindow->cheatEditor.editCheat(cheat);
|
|
}
|
|
setVisible(false);
|
|
}
|
|
|
|
//
|
|
|
|
CheatEditor::CheatEditor(TabFrame* parent) : TabFrameItem(parent) {
|
|
setIcon(Icon::Edit::Replace);
|
|
setText("Cheat Editor");
|
|
|
|
layout.setMargin(5);
|
|
cheatList.setBatchable();
|
|
cheatList.onActivate([&] {
|
|
editButton.doActivate();
|
|
});
|
|
cheatList.onChange([&] {
|
|
auto batched = cheatList.batched();
|
|
editButton.setEnabled(batched.size() == 1);
|
|
removeButton.setEnabled(batched.size() >= 1);
|
|
});
|
|
cheatList.onToggle([&](TableViewCell) {
|
|
synchronizeCodes();
|
|
});
|
|
findCheatsButton.setText("Find Cheats ...").onActivate([&] {
|
|
cheatDatabase->findCheats();
|
|
});
|
|
addButton.setText("Add").onActivate([&] {
|
|
cheatWindow->show();
|
|
});
|
|
editButton.setText("Edit").onActivate([&] {
|
|
if(auto item = cheatList.selected()) {
|
|
cheatWindow->show(cheats[item.offset()]);
|
|
}
|
|
});
|
|
removeButton.setText("Remove").onActivate([&] {
|
|
removeCheats();
|
|
});
|
|
|
|
//do not display "Find Cheats" button if there is no cheat database available
|
|
if(!file::exists(locate("cheats.bml"))) findCheatsButton.setVisible(false);
|
|
}
|
|
|
|
auto CheatEditor::refresh() -> void {
|
|
cheatList.reset();
|
|
cheatList.append(TableViewHeader().setVisible(false)
|
|
.append(TableViewColumn())
|
|
.append(TableViewColumn().setExpandable())
|
|
);
|
|
for(auto& cheat : cheats) {
|
|
cheatList.append(TableViewItem()
|
|
.append(TableViewCell().setCheckable().setChecked(cheat.enable))
|
|
.append(TableViewCell().setText(cheat.name))
|
|
);
|
|
}
|
|
cheatList.resizeColumns().doChange();
|
|
}
|
|
|
|
auto CheatEditor::addCheat(Cheat cheat) -> void {
|
|
cheats.append(cheat);
|
|
cheats.sort();
|
|
refresh();
|
|
for(uint index : range(cheats)) {
|
|
if(cheats[index] == cheat) { cheatList.item(index).setSelected(); break; }
|
|
}
|
|
cheatList.doChange();
|
|
synchronizeCodes();
|
|
}
|
|
|
|
auto CheatEditor::editCheat(Cheat cheat) -> void {
|
|
if(auto item = cheatList.selected()) {
|
|
cheats[item.offset()] = cheat;
|
|
cheats.sort();
|
|
refresh();
|
|
for(uint index : range(cheats)) {
|
|
if(cheats[index] == cheat) { cheatList.item(index).setSelected(); break; }
|
|
}
|
|
cheatList.doChange();
|
|
synchronizeCodes();
|
|
}
|
|
}
|
|
|
|
auto CheatEditor::removeCheats() -> void {
|
|
if(auto batched = cheatList.batched()) {
|
|
if(MessageDialog("Are you sure you want to permanently remove the selected cheat(s)?")
|
|
.setParent(*toolsWindow).question() == "Yes") {
|
|
for(uint index : rrange(batched)) cheats.remove(batched[index].offset());
|
|
cheats.sort();
|
|
refresh();
|
|
synchronizeCodes();
|
|
}
|
|
}
|
|
}
|
|
|
|
auto CheatEditor::loadCheats() -> void {
|
|
cheats.reset();
|
|
auto location = program->cheatPath();
|
|
auto document = BML::unserialize(string::read(location));
|
|
for(auto cheat : document.find("cheat")) {
|
|
cheats.append({cheat["name"].text(), cheat["code"].text(), (bool)cheat["enable"]});
|
|
}
|
|
cheats.sort();
|
|
refresh();
|
|
synchronizeCodes();
|
|
}
|
|
|
|
auto CheatEditor::saveCheats() -> void {
|
|
string document;
|
|
for(auto cheat : cheats) {
|
|
document.append("cheat\n");
|
|
document.append(" name: ", cheat.name, "\n");
|
|
document.append(" code: ", cheat.code, "\n");
|
|
if(cheat.enable)
|
|
document.append(" enable\n");
|
|
document.append("\n");
|
|
}
|
|
auto location = program->cheatPath();
|
|
if(document) {
|
|
file::write(location, document);
|
|
} else {
|
|
file::remove(location);
|
|
}
|
|
}
|
|
|
|
auto CheatEditor::synchronizeCodes() -> void {
|
|
string_vector codes;
|
|
for(auto& cheat : cheats) {
|
|
if(cheat.enable) codes.append(cheat.code);
|
|
}
|
|
emulator->cheatSet(codes);
|
|
}
|