mirror of
https://github.com/DerKoun/bsnes-hd.git
synced 2025-04-02 10:52:49 -04:00
145 lines
5.2 KiB
C++
145 lines
5.2 KiB
C++
auto CheatFinder::create() -> void {
|
|
setCollapsible();
|
|
setVisible(false);
|
|
|
|
searchList.setHeadered();
|
|
searchList.onActivate([&](auto cell) {
|
|
if(auto item = searchList.selected()) {
|
|
uint address = toHex(item.cell(0).text().trimLeft("0x", 1L));
|
|
string data = item.cell(1).text().trimLeft("0x", 1L).split(" ", 1L).first();
|
|
string code;
|
|
if(data.size() == 2) {
|
|
code.append(hex(address + 0, 6L), "=", data.slice(0, 2), "\n");
|
|
}
|
|
if(data.size() == 4) {
|
|
code.append(hex(address + 0, 6L), "=", data.slice(2, 2), "\n");
|
|
code.append(hex(address + 1, 6L), "=", data.slice(0, 2), "\n");
|
|
}
|
|
if(data.size() == 6) {
|
|
code.append(hex(address + 0, 6L), "=", data.slice(4, 2), "\n");
|
|
code.append(hex(address + 1, 6L), "=", data.slice(2, 2), "\n");
|
|
code.append(hex(address + 2, 6L), "=", data.slice(0, 2), "\n");
|
|
}
|
|
toolsWindow.show(1);
|
|
cheatEditor.addButton.doActivate();
|
|
cheatWindow.codeValue.setText(code).doChange();
|
|
}
|
|
});
|
|
searchValue.onActivate([&] { eventScan(); });
|
|
searchLabel.setText("Value:");
|
|
searchSize.append(ComboButtonItem().setText("Byte"));
|
|
searchSize.append(ComboButtonItem().setText("Word"));
|
|
searchSize.append(ComboButtonItem().setText("Long"));
|
|
searchMode.append(ComboButtonItem().setText("="));
|
|
searchMode.append(ComboButtonItem().setText("!="));
|
|
searchMode.append(ComboButtonItem().setText(">="));
|
|
searchMode.append(ComboButtonItem().setText("<="));
|
|
searchMode.append(ComboButtonItem().setText(">"));
|
|
searchMode.append(ComboButtonItem().setText("<"));
|
|
searchSpan.append(ComboButtonItem().setText("WRAM"));
|
|
searchSpan.append(ComboButtonItem().setText("All"));
|
|
searchScan.setText("Scan").onActivate([&] { eventScan(); });
|
|
searchClear.setText("Clear").onActivate([&] { eventClear(); });
|
|
|
|
refresh();
|
|
}
|
|
|
|
auto CheatFinder::restart() -> void {
|
|
searchValue.setText("");
|
|
searchSize.items().first().setSelected();
|
|
searchMode.items().first().setSelected();
|
|
searchSpan.items().first().setSelected();
|
|
candidates.reset();
|
|
refresh();
|
|
}
|
|
|
|
auto CheatFinder::refresh() -> void {
|
|
searchList.reset();
|
|
searchList.append(TableViewColumn().setText("Address"));
|
|
searchList.append(TableViewColumn().setText("Value"));
|
|
|
|
for(auto& candidate : candidates) {
|
|
TableViewItem item{&searchList};
|
|
item.append(TableViewCell().setText({"0x", hex(candidate.address, 6L)}));
|
|
if(candidate.size == 0) {
|
|
item.append(TableViewCell().setText({"0x", hex(candidate.data, 2L), " (", candidate.data, ")"}));
|
|
}
|
|
if(candidate.size == 1) {
|
|
item.append(TableViewCell().setText({"0x", hex(candidate.data, 4L), " (", candidate.data, ")"}));
|
|
}
|
|
if(candidate.size == 2) {
|
|
item.append(TableViewCell().setText({"0x", hex(candidate.data, 6L), " (", candidate.data, ")"}));
|
|
}
|
|
}
|
|
|
|
for(uint n : range(2)) {
|
|
Application::processEvents();
|
|
searchList.resizeColumns();
|
|
}
|
|
}
|
|
|
|
auto CheatFinder::eventScan() -> void {
|
|
uint32_t size = searchSize.selected().offset();
|
|
uint32_t mode = searchMode.selected().offset();
|
|
uint32_t span = searchSpan.selected().offset();
|
|
uint32_t data = searchValue.text().replace("$", "0x").replace("#", "").integer();
|
|
if(size == 0) data &= 0xff;
|
|
if(size == 1) data &= 0xffff;
|
|
if(size == 2) data &= 0xffffff;
|
|
|
|
if(!candidates) {
|
|
for(uint address : range(1 << 24)) {
|
|
if((address & 0x40e000) == 0x000000) continue; //00-3f,80-bf:0000-1fff (WRAM mirrors)
|
|
if((address & 0x40e000) == 0x002000) continue; //00-3f,80-bf:2000-3fff (I/O)
|
|
if((address & 0x40e000) == 0x004000) continue; //00-3f,80-bf:4000-5fff (I/O)
|
|
if(span == 0 && (address < 0x7e0000 || address > 0x7fffff)) continue;
|
|
|
|
auto value = read(size, address);
|
|
if(compare(mode, value, data)) {
|
|
candidates.append({address, value, size, mode, span});
|
|
if(candidates.size() >= 4096) break;
|
|
}
|
|
}
|
|
} else {
|
|
vector<CheatCandidate> result;
|
|
for(auto& candidate : candidates) {
|
|
uint address = candidate.address;
|
|
if((address & 0x40e000) == 0x000000) continue; //00-3f,80-bf:0000-1fff (WRAM mirrors)
|
|
if((address & 0x40e000) == 0x002000) continue; //00-3f,80-bf:2000-3fff (I/O)
|
|
if((address & 0x40e000) == 0x004000) continue; //00-3f,80-bf:4000-5fff (I/O)
|
|
if(span == 0 && (address < 0x7e0000 || address > 0x7fffff)) continue;
|
|
|
|
auto value = read(size, address);
|
|
if(compare(mode, value, data)) {
|
|
result.append({address, value, size, mode, span});
|
|
if(result.size() >= 4096) break;
|
|
}
|
|
}
|
|
candidates = result;
|
|
}
|
|
|
|
refresh();
|
|
}
|
|
|
|
auto CheatFinder::eventClear() -> void {
|
|
candidates.reset();
|
|
refresh();
|
|
}
|
|
|
|
auto CheatFinder::read(uint32_t size, uint32_t address) -> uint32_t {
|
|
uint32_t value = 0;
|
|
if(size >= 0) value |= emulator->read(address + 0) << 0;
|
|
if(size >= 1) value |= emulator->read(address + 1) << 8;
|
|
if(size >= 2) value |= emulator->read(address + 2) << 16;
|
|
return value;
|
|
}
|
|
|
|
auto CheatFinder::compare(uint32_t mode, uint32_t x, uint32_t y) -> bool {
|
|
if(mode == 0) return x == y;
|
|
if(mode == 1) return x != y;
|
|
if(mode == 2) return x >= y;
|
|
if(mode == 3) return x <= y;
|
|
if(mode == 4) return x > y;
|
|
if(mode == 5) return x < y;
|
|
return false;
|
|
}
|