2020-11-15 00:46:38 +01:00
|
|
|
#include "views/view_tools.hpp"
|
|
|
|
|
|
|
|
#include <cstring>
|
2020-11-15 21:31:04 +01:00
|
|
|
#include <regex>
|
2020-11-28 21:55:52 +01:00
|
|
|
#include <optional>
|
2020-11-15 00:46:38 +01:00
|
|
|
|
2020-11-30 21:45:48 +01:00
|
|
|
#include "providers/provider.hpp"
|
2020-12-22 18:10:01 +01:00
|
|
|
#include "helpers/plugin_handler.hpp"
|
2020-11-28 21:55:52 +01:00
|
|
|
#include "helpers/utils.hpp"
|
2020-11-23 16:19:58 +01:00
|
|
|
|
2020-11-24 18:12:08 +01:00
|
|
|
#include <llvm/Demangle/Demangle.h>
|
|
|
|
|
2020-11-15 00:46:38 +01:00
|
|
|
namespace hex {
|
|
|
|
|
2020-12-27 15:39:06 +01:00
|
|
|
ViewTools::ViewTools() : View("Tools") {
|
2020-11-15 21:31:04 +01:00
|
|
|
this->m_mangledBuffer = new char[0xF'FFFF];
|
|
|
|
std::memset(this->m_mangledBuffer, 0x00, 0xF'FFFF);
|
|
|
|
|
|
|
|
this->m_regexInput = new char[0xF'FFFF];
|
|
|
|
this->m_regexPattern = new char[0xF'FFFF];
|
|
|
|
this->m_replacePattern = new char[0xF'FFFF];
|
|
|
|
std::memset(this->m_regexInput, 0x00, 0xF'FFFF);
|
|
|
|
std::memset(this->m_regexPattern, 0x00, 0xF'FFFF);
|
|
|
|
std::memset(this->m_replacePattern, 0x00, 0xF'FFFF);
|
2020-11-28 21:55:52 +01:00
|
|
|
|
|
|
|
|
|
|
|
this->m_mathInput = new char[0xFFFF];
|
|
|
|
std::memset(this->m_mathInput, 0x00, 0xFFFF);
|
|
|
|
this->m_mathEvaluator.registerStandardVariables();
|
|
|
|
this->m_mathEvaluator.registerStandardFunctions();
|
2020-11-30 21:45:48 +01:00
|
|
|
|
2020-11-28 21:55:52 +01:00
|
|
|
this->m_mathEvaluator.setFunction("clear", [this](auto args) -> std::optional<long double> {
|
|
|
|
this->m_mathHistory.clear();
|
|
|
|
this->m_lastMathError.clear();
|
2020-11-30 21:45:48 +01:00
|
|
|
this->m_mathEvaluator.getVariables().clear();
|
|
|
|
this->m_mathEvaluator.registerStandardVariables();
|
2020-11-28 21:55:52 +01:00
|
|
|
std::memset(this->m_mathInput, 0x00, 0xFFFF);
|
|
|
|
|
|
|
|
return { };
|
|
|
|
}, 0, 0);
|
2020-11-30 21:45:48 +01:00
|
|
|
|
|
|
|
this->m_mathEvaluator.setFunction("read", [this](auto args) -> std::optional<long double> {
|
|
|
|
u8 value = 0;
|
|
|
|
|
2021-01-04 00:19:56 +01:00
|
|
|
auto provider = *SharedData::get().currentProvider;
|
2020-12-27 15:39:06 +01:00
|
|
|
if (provider == nullptr || !provider->isReadable() || args[0] >= provider->getActualSize())
|
2020-11-30 21:45:48 +01:00
|
|
|
return { };
|
|
|
|
|
2020-12-27 15:39:06 +01:00
|
|
|
provider->read(args[0], &value, sizeof(u8));
|
2020-11-30 21:45:48 +01:00
|
|
|
|
|
|
|
return value;
|
|
|
|
}, 1, 1);
|
|
|
|
|
|
|
|
this->m_mathEvaluator.setFunction("write", [this](auto args) -> std::optional<long double> {
|
2021-01-04 00:19:56 +01:00
|
|
|
auto provider = *SharedData::get().currentProvider;
|
2020-12-27 15:39:06 +01:00
|
|
|
if (provider == nullptr || !provider->isWritable() || args[0] >= provider->getActualSize())
|
2020-11-30 21:45:48 +01:00
|
|
|
return { };
|
|
|
|
|
|
|
|
if (args[1] > 0xFF)
|
|
|
|
return { };
|
|
|
|
|
|
|
|
u8 value = args[1];
|
2020-12-27 15:39:06 +01:00
|
|
|
provider->write(args[0], &value, sizeof(u8));
|
2020-11-30 21:45:48 +01:00
|
|
|
|
|
|
|
return { };
|
|
|
|
}, 2, 2);
|
2020-11-15 00:46:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ViewTools::~ViewTools() {
|
|
|
|
delete[] this->m_mangledBuffer;
|
2020-11-15 21:31:04 +01:00
|
|
|
|
|
|
|
delete[] this->m_regexInput;
|
|
|
|
delete[] this->m_regexPattern;
|
2020-11-27 09:09:59 +01:00
|
|
|
delete[] this->m_replacePattern;
|
2020-11-28 21:55:52 +01:00
|
|
|
|
|
|
|
delete[] this->m_mathInput;
|
2020-11-15 00:46:38 +01:00
|
|
|
}
|
|
|
|
|
2020-11-15 02:50:56 +01:00
|
|
|
void ViewTools::drawDemangler() {
|
2020-11-24 18:12:08 +01:00
|
|
|
if (ImGui::CollapsingHeader("Itanium/MSVC demangler")) {
|
2020-11-15 21:31:04 +01:00
|
|
|
if (ImGui::InputText("Mangled name", this->m_mangledBuffer, 0xF'FFFF)) {
|
2020-11-24 18:12:08 +01:00
|
|
|
this->m_demangledName = llvm::demangle(this->m_mangledBuffer);
|
2020-11-15 00:46:38 +01:00
|
|
|
}
|
|
|
|
|
2020-11-24 02:59:49 +01:00
|
|
|
ImGui::InputText("Demangled name", this->m_demangledName.data(), this->m_demangledName.size(), ImGuiInputTextFlags_ReadOnly);
|
2020-11-15 21:31:04 +01:00
|
|
|
ImGui::NewLine();
|
2020-11-15 02:50:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ViewTools::drawASCIITable() {
|
|
|
|
if (ImGui::CollapsingHeader("ASCII table")) {
|
|
|
|
ImGui::BeginTable("##asciitable", 4);
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
ImGui::TableSetupColumn("");
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
for (u8 tablePart = 0; tablePart < 4; tablePart++) {
|
|
|
|
ImGui::BeginTable("##asciitablepart", this->m_asciiTableShowOctal ? 4 : 3, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg);
|
|
|
|
ImGui::TableSetupColumn("dec");
|
|
|
|
if (this->m_asciiTableShowOctal)
|
|
|
|
ImGui::TableSetupColumn("oct");
|
|
|
|
ImGui::TableSetupColumn("hex");
|
|
|
|
ImGui::TableSetupColumn("char");
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
|
|
|
|
u32 rowCount = 0;
|
|
|
|
for (u8 i = 0; i < 0x80 / 4; i++) {
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%02d", i + 32 * tablePart);
|
2020-11-15 00:46:38 +01:00
|
|
|
|
2020-11-15 02:50:56 +01:00
|
|
|
if (this->m_asciiTableShowOctal) {
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("0o%02o", i + 32 * tablePart);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("0x%02x", i + 32 * tablePart);
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2020-11-23 16:19:58 +01:00
|
|
|
ImGui::Text("%s", makePrintable(i + 32 * tablePart).c_str());
|
2020-11-15 02:50:56 +01:00
|
|
|
|
|
|
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ((rowCount % 2) == 0) ? 0xFF101010 : 0xFF303030);
|
|
|
|
|
|
|
|
rowCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
}
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
|
|
|
ImGui::Checkbox("Show octal", &this->m_asciiTableShowOctal);
|
2020-11-15 21:31:04 +01:00
|
|
|
ImGui::NewLine();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ViewTools::drawRegexReplacer() {
|
|
|
|
if (ImGui::CollapsingHeader("Regex replacer")) {
|
|
|
|
bool shouldInvalidate;
|
|
|
|
|
|
|
|
shouldInvalidate = ImGui::InputText("Regex pattern", this->m_regexPattern, 0xF'FFFF);
|
|
|
|
shouldInvalidate = ImGui::InputText("Replace pattern", this->m_replacePattern, 0xF'FFFF) || shouldInvalidate;
|
|
|
|
shouldInvalidate = ImGui::InputTextMultiline("Input", this->m_regexInput, 0xF'FFFF) || shouldInvalidate;
|
|
|
|
|
|
|
|
if (shouldInvalidate) {
|
|
|
|
try {
|
|
|
|
this->m_regexOutput = std::regex_replace(this->m_regexInput, std::regex(this->m_regexPattern), this->m_replacePattern);
|
|
|
|
} catch (std::regex_error&) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::InputTextMultiline("Output", this->m_regexOutput.data(), this->m_regexOutput.size(), ImVec2(0, 0), ImGuiInputTextFlags_ReadOnly);
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ViewTools::drawColorPicker() {
|
|
|
|
if (ImGui::CollapsingHeader("Color picker")) {
|
2020-11-24 00:01:44 +01:00
|
|
|
ImGui::SetNextItemWidth(300.0F);
|
2020-11-15 21:31:04 +01:00
|
|
|
ImGui::ColorPicker4("Color Picker", this->m_pickedColor.data(),
|
|
|
|
ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_AlphaBar | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHex);
|
|
|
|
ImGui::NewLine();
|
2020-11-15 02:50:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-28 21:55:52 +01:00
|
|
|
void ViewTools::drawMathEvaluator() {
|
|
|
|
if (ImGui::CollapsingHeader("Calculator")) {
|
|
|
|
if (ImGui::InputText("Input", this->m_mathInput, 0xFFFF, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll)) {
|
|
|
|
ImGui::SetKeyboardFocusHere();
|
|
|
|
std::optional<long double> result;
|
|
|
|
|
|
|
|
try {
|
|
|
|
result = this->m_mathEvaluator.evaluate(this->m_mathInput);
|
|
|
|
} catch (std::invalid_argument &e) {
|
|
|
|
this->m_lastMathError = e.what();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result.has_value()) {
|
|
|
|
this->m_mathHistory.push_back(result.value());
|
|
|
|
std::memset(this->m_mathInput, 0x00, 0xFFFF);
|
|
|
|
this->m_lastMathError.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this->m_lastMathError.empty())
|
|
|
|
ImGui::TextColored(ImColor(0xA00040FF), "Last Error: %s", this->m_lastMathError.c_str());
|
|
|
|
else
|
|
|
|
ImGui::NewLine();
|
|
|
|
|
2021-01-11 00:27:00 +01:00
|
|
|
enum class MathDisplayType { Standard, Scientific, Engineering, Programmer } mathDisplayType;
|
2020-11-28 21:55:52 +01:00
|
|
|
if (ImGui::BeginTabBar("##mathFormatTabBar")) {
|
|
|
|
if (ImGui::BeginTabItem("Standard")) {
|
|
|
|
mathDisplayType = MathDisplayType::Standard;
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
if (ImGui::BeginTabItem("Scientific")) {
|
|
|
|
mathDisplayType = MathDisplayType::Scientific;
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
2021-01-11 00:27:00 +01:00
|
|
|
if (ImGui::BeginTabItem("Engineering")) {
|
|
|
|
mathDisplayType = MathDisplayType::Engineering;
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
2020-11-28 21:55:52 +01:00
|
|
|
if (ImGui::BeginTabItem("Programmer")) {
|
|
|
|
mathDisplayType = MathDisplayType::Programmer;
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTabBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ImGui::BeginTable("##mathWrapper", 2)) {
|
|
|
|
ImGui::TableSetupColumn("##results");
|
|
|
|
ImGui::TableSetupColumn("##variables", ImGuiTableColumnFlags_WidthStretch, 0.7);
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
if (ImGui::BeginTable("##mathHistory", 1, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, 400))) {
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
|
|
|
ImGui::TableSetupColumn("History");
|
|
|
|
|
|
|
|
ImGuiListClipper clipper;
|
|
|
|
clipper.Begin(this->m_mathHistory.size());
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
while (clipper.Step()) {
|
|
|
|
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
2020-11-30 21:45:48 +01:00
|
|
|
if (i == 0)
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, ImU32(ImColor(0xA5, 0x45, 0x45)));
|
|
|
|
|
2020-11-28 21:55:52 +01:00
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
switch (mathDisplayType) {
|
|
|
|
case MathDisplayType::Standard:
|
|
|
|
ImGui::Text("%.3Lf", this->m_mathHistory[(this->m_mathHistory.size() - 1) - i]);
|
|
|
|
break;
|
|
|
|
case MathDisplayType::Scientific:
|
|
|
|
ImGui::Text("%.6Le", this->m_mathHistory[(this->m_mathHistory.size() - 1) - i]);
|
|
|
|
break;
|
2021-01-11 00:27:00 +01:00
|
|
|
case MathDisplayType::Engineering:
|
|
|
|
ImGui::Text("%s", hex::toEngineeringString(this->m_mathHistory[(this->m_mathHistory.size() - 1) - i]).c_str());
|
|
|
|
break;
|
2020-11-28 21:55:52 +01:00
|
|
|
case MathDisplayType::Programmer:
|
|
|
|
ImGui::Text("0x%llX (%llu)",
|
|
|
|
u64(this->m_mathHistory[(this->m_mathHistory.size() - 1) - i]),
|
|
|
|
u64(this->m_mathHistory[(this->m_mathHistory.size() - 1) - i]));
|
|
|
|
break;
|
|
|
|
}
|
2020-11-30 21:45:48 +01:00
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
ImGui::PopStyleColor();
|
2020-11-28 21:55:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
clipper.End();
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
if (ImGui::BeginTable("##mathVariables", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(0, 400))) {
|
|
|
|
ImGui::TableSetupScrollFreeze(0, 1);
|
|
|
|
ImGui::TableSetupColumn("Name");
|
|
|
|
ImGui::TableSetupColumn("Value");
|
|
|
|
|
|
|
|
ImGui::TableHeadersRow();
|
|
|
|
for (const auto &[name, value] : this->m_mathEvaluator.getVariables()) {
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted(name.c_str());
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
switch (mathDisplayType) {
|
|
|
|
case MathDisplayType::Standard:
|
|
|
|
ImGui::Text("%.3Lf", value);
|
|
|
|
break;
|
|
|
|
case MathDisplayType::Scientific:
|
|
|
|
ImGui::Text("%.6Le", value);
|
|
|
|
break;
|
2021-01-11 00:27:00 +01:00
|
|
|
case MathDisplayType::Engineering:
|
|
|
|
ImGui::Text("%s", hex::toEngineeringString(value).c_str());
|
|
|
|
break;
|
2020-11-28 21:55:52 +01:00
|
|
|
case MathDisplayType::Programmer:
|
|
|
|
ImGui::Text("0x%llX (%llu)", u64(value), u64(value));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-22 18:10:01 +01:00
|
|
|
void ViewTools::drawContent() {
|
2020-11-23 23:57:19 +01:00
|
|
|
if (ImGui::Begin("Tools", &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) {
|
2020-11-15 00:46:38 +01:00
|
|
|
|
2020-11-15 02:50:56 +01:00
|
|
|
this->drawDemangler();
|
|
|
|
this->drawASCIITable();
|
2020-11-15 21:31:04 +01:00
|
|
|
this->drawRegexReplacer();
|
2020-11-28 21:55:52 +01:00
|
|
|
this->drawMathEvaluator();
|
2020-11-15 21:31:04 +01:00
|
|
|
this->drawColorPicker();
|
2020-11-15 00:46:38 +01:00
|
|
|
|
2020-12-22 18:10:01 +01:00
|
|
|
for (const auto& plugin : PluginHandler::getPlugins())
|
|
|
|
plugin.drawToolsEntry();
|
|
|
|
|
2020-11-15 00:46:38 +01:00
|
|
|
}
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
|
2020-12-22 18:10:01 +01:00
|
|
|
void ViewTools::drawMenu() {
|
2020-11-23 23:57:19 +01:00
|
|
|
|
2020-11-15 00:46:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|