Compare commits

..

23 Commits

Author SHA1 Message Date
WerWolv
63edfb8d52 tests: Fixed compiling of bitfield test 2022-01-12 09:17:14 +01:00
WerWolv
8d3ca3292e build: Bumped version to 1.13.2 2022-01-12 09:07:49 +01:00
WerWolv
25df658653 fix: ImHex directories not being created correctly 2022-01-12 09:02:03 +01:00
WerWolv
6b20a9bdd5 patterns: Fix local variables holding larger values than allowed 2022-01-12 08:59:14 +01:00
WerWolv
d399a6427a sys: Use custom literals for scaled values 2022-01-11 23:48:18 +01:00
WerWolv
2f1a707fd3 ui: Improve layout of hex editor footer 2022-01-11 23:05:02 +01:00
WerWolv
cbfe52c756 patterns/ui: Limit displaying of array entries to 50 with option to double click last entry for more 2022-01-11 22:38:50 +01:00
WerWolv
3c1f0057ae patterns: Improve PatternData size as much as possible 2022-01-11 22:38:04 +01:00
WerWolv
1a9bd12af0 fix: Crash when closing certain popups 2022-01-11 20:29:06 +01:00
WerWolv
1b853c6a84 sys: Trigger breakpoint in debug mode when a signal is raised 2022-01-11 20:28:57 +01:00
WerWolv
b9034523b5 patterns: Allow [[format]] attribute to work with custom types 2022-01-11 19:35:28 +01:00
WerWolv
5af9af1e5a ux: Make undocked windows show up in task bar 2022-01-11 16:02:11 +01:00
WerWolv
eac9fe1b70 git: Added deb and AppImage nightly to readme 2022-01-11 00:48:31 +01:00
WerWolv
3cecc0693b git: Added ImHex webpage link to readme 2022-01-11 00:43:08 +01:00
WerWolv
0e6446b3ef build: Bumped version to 1.13.1 2022-01-10 22:16:02 +01:00
WerWolv
b496fedea8 tests: Fixed pointer test 2022-01-10 22:15:05 +01:00
WerWolv
dc064008f3 build: Fix use of libromfs in plugin templates 2022-01-10 22:06:37 +01:00
WerWolv
652896bd3a lang: Added missing translation 2022-01-10 21:44:42 +01:00
WerWolv
1fe6dc4c6e fix: Occasional crash when disassembling files 2022-01-10 21:38:52 +01:00
WerWolv
e35ea13f60 sys: Improved view const-correctness 2022-01-10 21:05:37 +01:00
WerWolv
e1fb0a5d72 ui: Fixed settings window being huge 2022-01-10 21:05:18 +01:00
WerWolv
e204ef629f patterns: Fixed passing structs to functions as argument
Fixes #385
2022-01-10 20:02:18 +01:00
WerWolv
d2704242f2 patterns: Fixed pointer_base attribute
Hopefully takes care of #367
2022-01-10 00:40:34 +01:00
38 changed files with 359 additions and 363 deletions

View File

@@ -1,11 +1,12 @@
cmake_minimum_required(VERSION 3.16)
# Updating the version here will update it throughout ImHex as well
set(IMHEX_VERSION "1.13.0")
set(IMHEX_VERSION "1.13.2")
project(imhex VERSION ${IMHEX_VERSION})
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
set(IMHEX_BASE_FOLDER ${CMAKE_CURRENT_SOURCE_DIR})
include("${CMAKE_SOURCE_DIR}/cmake/build_helpers.cmake")
# List plugin names here. Project name must match folder name

View File

@@ -1,4 +1,4 @@
<h1 align="center">:mag: ImHex</h1>
<a href="https://imhex.werwolv.net"><h1 align="center" >:mag: ImHex</h1></a>
<p align="center">A Hex Editor for Reverse Engineers, Programmers and people who value their retinas when working at 3 AM.</p>
@@ -123,7 +123,9 @@ Nightlies are available via GitHub Actions [here](https://github.com/WerWolv/ImH
- [DMG](https://nightly.link/WerWolv/ImHex/workflows/build/master/macOS%20DMG.zip)
- Linux • __x86_64__
- [ELF](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20ELF.zip)
- [DEB](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20DEB.zip)
- [Flatpak](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20Flatpak.zip)
- [AppImage](https://nightly.link/WerWolv/ImHex/workflows/build/master/Linux%20AppImage.zip)
## Compiling

View File

@@ -268,7 +268,7 @@ struct MemoryEditor
const float height_separator = style.ItemSpacing.y;
float footer_height = 0;
if (OptShowOptions)
footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 1;
footer_height += height_separator + ImGui::GetFrameHeightWithSpacing() * 2;
ImGui::BeginChild("offset", ImVec2(0, s.LineHeight), false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav);
ImGui::Text("%*c ", s.AddrDigitsCount, ' ');
@@ -731,7 +731,7 @@ struct MemoryEditor
if (GotoAddr < mem_size)
{
ImGui::BeginChild("##scrolling");
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (GotoAddr / Cols) * ImGui::GetTextLineHeight());
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + (GotoAddr / Cols) * ImGui::GetTextLineHeight() * 2);
ImGui::EndChild();
}
GotoAddr = (size_t)-1;

View File

@@ -11,8 +11,6 @@
namespace hex::plugin::builtin {
namespace prv { class Provider; }
class ViewCommandPalette : public View {
public:
ViewCommandPalette();
@@ -20,12 +18,12 @@ namespace hex::plugin::builtin {
void drawContent() override;
void drawMenu() override;
bool isAvailable() override { return true; }
bool shouldProcess() override { return true; }
[[nodiscard]] bool isAvailable() const override { return true; }
[[nodiscard]] bool shouldProcess() const override { return true; }
bool hasViewMenuItemEntry() override { return false; }
ImVec2 getMinSize() override { return ImVec2(400, 100); }
ImVec2 getMaxSize() override { return ImVec2(400, 100); }
[[nodiscard]] bool hasViewMenuItemEntry() const override { return false; }
[[nodiscard]] ImVec2 getMinSize() const override { return ImVec2(400, 100); }
[[nodiscard]] ImVec2 getMaxSize() const override { return ImVec2(400, 100); }
private:
enum class MatchType {

View File

@@ -20,11 +20,11 @@ namespace hex::plugin::builtin {
void drawContent() override;
void drawMenu() override;
bool isAvailable() override { return true; }
bool isAvailable() const override { return true; }
bool hasViewMenuItemEntry() override { return false; }
bool hasViewMenuItemEntry() const override { return false; }
ImVec2 getMinSize() override {
ImVec2 getMinSize() const override {
return ImVec2(400, 300);
}

View File

@@ -13,14 +13,14 @@ namespace hex::plugin::builtin {
class ViewProviderSettings : public hex::View {
public:
ViewProviderSettings();
~ViewProviderSettings();
~ViewProviderSettings() override;
void drawContent() override;
void drawAlwaysVisible() override;
bool hasViewMenuItemEntry() override;
[[nodiscard]] bool hasViewMenuItemEntry() const override;
bool isAvailable();
[[nodiscard]] bool isAvailable() const override;
};
}

View File

@@ -14,9 +14,13 @@ namespace hex::plugin::builtin {
void drawContent() override;
void drawMenu() override;
bool isAvailable() override { return true; }
[[nodiscard]] bool isAvailable() const override { return true; }
bool hasViewMenuItemEntry() override { return false; }
[[nodiscard]] bool hasViewMenuItemEntry() const override { return false; }
[[nodiscard]] ImVec2 getMinSize() const override {
return scaled(ImVec2(500, 300));
}
};
}

View File

@@ -35,8 +35,8 @@ namespace hex::plugin::builtin {
void drawContent() override;
void drawMenu() override;
bool isAvailable() override { return true; }
bool hasViewMenuItemEntry() override { return false; }
[[nodiscard]] bool isAvailable() const override { return true; }
[[nodiscard]] bool hasViewMenuItemEntry() const override { return false; }
private:
Net m_net;

View File

@@ -55,7 +55,7 @@ namespace hex::plugin::builtin {
ImGui::SameLine();
ImGui::SmallProgressBar(taskProgress, (ImGui::GetCurrentWindow()->MenuBarHeight() - 10 * SharedData::globalScale) / 2.0);
ImGui::SmallProgressBar(taskProgress, (ImGui::GetCurrentWindow()->MenuBarHeight() - 10_scaled) / 2.0);
ImGui::InfoTooltip(taskName.c_str());
}
@@ -133,7 +133,7 @@ namespace hex::plugin::builtin {
if (ImHexApi::Provider::isValid())
preview = providers[SharedData::currentProvider]->getName();
ImGui::SetNextItemWidth(200 * SharedData::globalScale);
ImGui::SetNextItemWidth(200_scaled);
if (ImGui::BeginCombo("", preview.c_str())) {
for (int i = 0; i < providers.size(); i++) {

View File

@@ -48,7 +48,7 @@ namespace hex::plugin::builtin {
if (ImHexApi::Provider::isValid() && provider >= 0)
preview = providers[provider]->getName();
ImGui::SetNextItemWidth(200 * SharedData::globalScale);
ImGui::SetNextItemWidth(200_scaled);
if (ImGui::BeginCombo("", preview.c_str())) {
for (int i = 0; i < providers.size(); i++) {

View File

@@ -281,31 +281,34 @@ namespace hex::plugin::builtin {
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.bytes"_lang);
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.title"_lang);
ImGuiListClipper clipper;
clipper.Begin(this->m_disassembly.size());
if (!this->m_disassembling) {
ImGuiListClipper clipper;
clipper.Begin(this->m_disassembly.size());
ImGui::TableHeadersRow();
while (clipper.Step()) {
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::Selectable(("##DisassemblyLine"s + std::to_string(i)).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
EventManager::post<RequestSelectionChange>(Region { this->m_disassembly[i].offset, this->m_disassembly[i].size });
ImGui::TableHeadersRow();
while (clipper.Step()) {
for (u64 i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
const auto &instruction = this->m_disassembly[i];
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::Selectable(("##DisassemblyLine"s + std::to_string(i)).c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
EventManager::post<RequestSelectionChange>(Region { instruction.offset, instruction.size });
}
ImGui::SameLine();
ImGui::TextFormatted("0x{0:X}", instruction.address);
ImGui::TableNextColumn();
ImGui::TextFormatted("0x{0:X}", instruction.offset);
ImGui::TableNextColumn();
ImGui::TextUnformatted(instruction.bytes.c_str());
ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFFD69C56), "{}", instruction.mnemonic);
ImGui::SameLine();
ImGui::TextUnformatted(instruction.operators.c_str());
}
ImGui::SameLine();
ImGui::TextFormatted("0x{0:X}", this->m_disassembly[i].address);
ImGui::TableNextColumn();
ImGui::TextFormatted("0x{0:X}", this->m_disassembly[i].offset);
ImGui::TableNextColumn();
ImGui::TextUnformatted(this->m_disassembly[i].bytes.c_str());
ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFFD69C56), "{}", this->m_disassembly[i].mnemonic);
ImGui::SameLine();
ImGui::TextUnformatted(this->m_disassembly[i].operators.c_str());
}
}
clipper.End();
clipper.End();
}
ImGui::EndTable();
}

View File

@@ -113,7 +113,7 @@ namespace hex::plugin::builtin {
}
void ViewHelp::drawAboutPopup() {
ImGui::SetNextWindowSize(ImVec2(600, 350) * SharedData::globalScale, ImGuiCond_Always);
ImGui::SetNextWindowSize(scaled(ImVec2(600, 350)), ImGuiCond_Always);
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.help.about.name").c_str(), &this->m_aboutWindowOpen, ImGuiWindowFlags_NoResize)) {
if (ImGui::IsKeyDown(ImGui::GetKeyIndex(ImGuiKey_Escape)))

View File

@@ -175,11 +175,11 @@ namespace hex::plugin::builtin {
}
if (provider->getPageCount() > 1) {
ImGui::SameLine();
ImGui::NewLine();
ImGui::TextFormatted("hex.builtin.view.hexeditor.page"_lang, provider->getCurrentPage() + 1, provider->getPageCount());
auto linePos = ImGui::GetCursorPosY() - 15_scaled;
ImGui::SameLine();
ImGui::SetCursorPosY(linePos);
if (ImGui::ArrowButton("prevPage", ImGuiDir_Left)) {
provider->setCurrentPage(provider->getCurrentPage() - 1);
@@ -194,6 +194,13 @@ namespace hex::plugin::builtin {
EventManager::post<EventRegionSelected>(Region { std::min(this->m_memoryEditor.DataPreviewAddr, this->m_memoryEditor.DataPreviewAddrEnd), 1 });
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
ImGui::SetCursorPosY(linePos);
ImGui::TextFormatted("hex.builtin.view.hexeditor.page"_lang, provider->getCurrentPage() + 1, provider->getPageCount());
}
this->drawSearchPopup();

View File

@@ -17,14 +17,14 @@ namespace hex::plugin::builtin {
}
static bool beginPatternDataTable(prv::Provider* &provider, const std::vector<pl::PatternData*> &patterns, std::vector<pl::PatternData*> &sortedPatterns) {
if (ImGui::BeginTable("##patterndatatable", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
if (ImGui::BeginTable("##patterndatatable", 6, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.var_name"_lang, 0, -1, ImGui::GetID("name"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.color"_lang, 0, -1, ImGui::GetID("color"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.offset"_lang, 0, -1, ImGui::GetID("offset"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.size"_lang, 0, -1, ImGui::GetID("size"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.type"_lang, 0, -1, ImGui::GetID("type"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.value"_lang, 0, -1, ImGui::GetID("value"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.var_name"_lang, 0, 0, ImGui::GetID("name"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.color"_lang, 0, 0, ImGui::GetID("color"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.offset"_lang, 0, 0, ImGui::GetID("offset"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.size"_lang, 0, 0, ImGui::GetID("size"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.type"_lang, 0, 0, ImGui::GetID("type"));
ImGui::TableSetupColumn("hex.builtin.view.pattern_data.value"_lang, 0, 0, ImGui::GetID("value"));
auto sortSpecs = ImGui::TableGetSortSpecs();

View File

@@ -52,11 +52,11 @@ namespace hex::plugin::builtin {
}
}
bool ViewProviderSettings::hasViewMenuItemEntry() {
bool ViewProviderSettings::hasViewMenuItemEntry() const {
return this->isAvailable();
}
bool ViewProviderSettings::isAvailable() {
bool ViewProviderSettings::isAvailable() const {
auto provider = hex::ImHexApi::Provider::get();
return provider != nullptr && provider->hasInterface();

View File

@@ -21,7 +21,6 @@ namespace hex::plugin::builtin {
void ViewSettings::drawContent() {
ImGui::SetNextWindowSize(ImVec2(500, 300) * SharedData::globalScale, ImGuiCond_Always);
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.settings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoResize)) {
if (ImGui::BeginTabBar("settings")) {
for (auto &[category, entries] : ContentRegistry::Settings::getEntries()) {

View File

@@ -218,7 +218,7 @@ namespace hex::plugin::builtin {
}
void ViewStore::drawContent() {
ImGui::SetNextWindowSizeConstraints(ImVec2(600, 400) * SharedData::globalScale, ImVec2(FLT_MAX, FLT_MAX));
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(600, 400)), ImVec2(FLT_MAX, FLT_MAX));
if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.store.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_AlwaysAutoResize)) {
if (this->m_apiRequest.valid()) {
if (this->m_apiRequest.wait_for(0s) != std::future_status::ready)

View File

@@ -185,6 +185,7 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.hexeditor.script.script.title", "Loader Script: Skript öffnen" },
{ "hex.builtin.view.hexeditor.script.file", "Datei" },
{ "hex.builtin.view.hexeditor.script.file.title", "Loader Script: Datei öffnen" },
{ "hex.builtin.view.hexeditor.processing", "Importieren / Exportieren" },
{ "hex.builtin.view.hexeditor.menu.file.open_file", "Datei öffnen..." },
{ "hex.builtin.view.hexeditor.menu.file.open_recent", "Kürzlich geöffnete Dateien" },

View File

@@ -188,7 +188,7 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.hexeditor.script.script.title", "Loader Script: Open Script" },
{ "hex.builtin.view.hexeditor.script.file", "File" },
{ "hex.builtin.view.hexeditor.script.file.title", "Loader Script: Open File" },
{ "hex.builtin.view.hexeditor.processing", "Processing" },
{ "hex.builtin.view.hexeditor.processing", "Importing / Exporting" },
{ "hex.builtin.view.hexeditor.menu.file.open_file", "Open File..." },
{ "hex.builtin.view.hexeditor.menu.file.open_recent", "Open Recent" },

View File

@@ -188,6 +188,7 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.hexeditor.script.script.title", "Caricatore Script: Apri Script" },
{ "hex.builtin.view.hexeditor.script.file", "File" },
{ "hex.builtin.view.hexeditor.script.file.title", "Caricatore Script: Apri File" },
//{ "hex.builtin.view.hexeditor.processing", "Importing / Exporting" },
{ "hex.builtin.view.hexeditor.menu.file.open_file", "Apri File..." },
{ "hex.builtin.view.hexeditor.menu.file.save", "Salva" },

View File

@@ -185,6 +185,7 @@ namespace hex::plugin::builtin {
{ "hex.builtin.view.hexeditor.script.script.title", "加载器脚本:打开脚本" },
{ "hex.builtin.view.hexeditor.script.file", "文件" },
{ "hex.builtin.view.hexeditor.script.file.title", "加载器脚本:打开文件" },
//{ "hex.builtin.view.hexeditor.processing", "Importing / Exporting" },
{ "hex.builtin.view.hexeditor.menu.file.open_file", "打开文件..." },
{ "hex.builtin.view.hexeditor.menu.file.open_recent", "打开最近" },

View File

@@ -13,7 +13,7 @@ set_target_properties(microtar PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../external/nativefiledialog ${CMAKE_CURRENT_BINARY_DIR}/external/nativefiledialog EXCLUDE_FROM_ALL)
set_target_properties(nfd PROPERTIES POSITION_INDEPENDENT_CODE ON)
set(LIBROMFS_RESOURCE_LOCATION ${CMAKE_SOURCE_DIR}/res/resources)
set(LIBROMFS_RESOURCE_LOCATION ${IMHEX_BASE_FOLDER}/res/resources)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../external/libromfs ${CMAKE_CURRENT_BINARY_DIR}/external/libromfs EXCLUDE_FROM_ALL)
set_target_properties(libromfs PROPERTIES POSITION_INDEPENDENT_CODE ON)

View File

@@ -19,6 +19,6 @@ namespace hex {
std::string getExecutablePath();
std::vector<std::string> getPath(ImHexPath path);
std::vector<std::string> getPath(ImHexPath path, bool listNonExisting = false);
}

View File

@@ -23,8 +23,14 @@
#define TOKEN_CONCAT(x, y) TOKEN_CONCAT_IMPL(x, y)
#define ANONYMOUS_VARIABLE(prefix) TOKEN_CONCAT(prefix, __COUNTER__)
struct ImVec2;
namespace hex {
long double operator""_scaled(long double value);
long double operator""_scaled(unsigned long long value);
ImVec2 scaled(const ImVec2 &vector);
std::string to_string(u128 value);
std::string to_string(s128 value);
@@ -109,6 +115,11 @@ namespace hex {
return result;
}
[[nodiscard]]
constexpr uint64_t bitmask(uint8_t bits) {
return (uint64_t(1) << (bits)) - 1;
}
template<typename T>
constexpr T changeEndianess(T value, size_t size, std::endian endian) {
if (endian == std::endian::native)

View File

@@ -718,16 +718,14 @@ namespace hex::pl {
LogConsole::abortEvaluation("pointer base function needs exactly one parameter", node);
if (auto pointerPattern = dynamic_cast<PatternDataPointer*>(pattern)) {
u128 value = 0;
evaluator->getProvider()->read(pattern->getOffset(), &value, pattern->getSize());
value = hex::changeEndianess(value, pattern->getSize(), pattern->getEndian());
u128 pointerValue = pointerPattern->getPointedAtAddress();
auto result = function.func(evaluator, { value });
auto result = function.func(evaluator, { pointerValue });
if (!result.has_value())
LogConsole::abortEvaluation("pointer base function did not return a value", node);
pointerPattern->rebase(Token::literalToUnsigned(result.value()));
pointerPattern->setPointedAtAddress(Token::literalToUnsigned(result.value()) + pointerValue);
} else {
LogConsole::abortEvaluation("pointer_base attribute may only be applied to a pointer");
}
@@ -1130,24 +1128,27 @@ namespace hex::pl {
}, offset->getValue());
}
auto offset = evaluator->dataOffset();
auto startOffset = evaluator->dataOffset();
auto sizePattern = this->m_sizeType->createPatterns(evaluator).front();
ON_SCOPE_EXIT { delete sizePattern; };
auto pattern = new PatternDataPointer(offset, sizePattern->getSize(), evaluator);
auto pattern = new PatternDataPointer(startOffset, sizePattern->getSize(), evaluator);
pattern->setVariableName(this->m_name);
applyVariableAttributes(evaluator, this, pattern);
offset = evaluator->dataOffset();
auto endOffset = evaluator->dataOffset();
{
u128 pointerAddress = 0;
evaluator->getProvider()->read(pattern->getOffset(), &pointerAddress, pattern->getSize());
pointerAddress = hex::changeEndianess(pointerAddress, sizePattern->getSize(), sizePattern->getEndian());
evaluator->dataOffset() = pointerAddress;
evaluator->dataOffset() = startOffset;
pattern->setPointedAtAddress(pointerAddress);
applyVariableAttributes(evaluator, this, pattern);
evaluator->dataOffset() = pattern->getPointedAtAddress();
auto pointedAtPattern = this->m_type->createPatterns(evaluator).front();
@@ -1155,7 +1156,7 @@ namespace hex::pl {
pattern->setEndian(sizePattern->getEndian());
}
evaluator->dataOffset() = offset;
evaluator->dataOffset() = endOffset;
return { pattern };
}
@@ -1447,7 +1448,7 @@ namespace hex::pl {
// If a field is named padding, it was created through a padding expression and only advances the bit position
if (name != "padding") {
auto field = new PatternDataBitfieldField(evaluator->dataOffset(), bitOffset, bitSize, evaluator);
auto field = new PatternDataBitfieldField(evaluator->dataOffset(), bitOffset, bitSize, pattern, evaluator);
field->setVariableName(name);
fields.push_back(field);
}
@@ -1504,69 +1505,37 @@ namespace hex::pl {
auto pattern = this->createPatterns(evaluator).front();
ON_SCOPE_EXIT { delete pattern; };
auto readValue = [&evaluator](auto &value, PatternData *pattern) {
if (pattern->isLocal()) {
auto &literal = evaluator->getStack()[pattern->getOffset()];
std::visit(overloaded {
[&](std::string &assignmentValue) { },
[&](PatternData *assignmentValue) { },
[&](auto &&assignmentValue) { value = assignmentValue; }
}, literal);
}
else
evaluator->getProvider()->read(pattern->getOffset(), &value, pattern->getSize());
value = hex::changeEndianess(value, pattern->getSize(), pattern->getEndian());
};
auto readString = [&evaluator](std::string &value, PatternData *pattern) {
if (pattern->isLocal()) {
auto &literal = evaluator->getStack()[pattern->getOffset()];
std::visit(overloaded {
[&](std::string &assignmentValue) { value = assignmentValue; },
[&](auto &&assignmentValue) { }
}, literal);
}
else {
value.resize(pattern->getSize());
evaluator->getProvider()->read(pattern->getOffset(), value.data(), value.size());
value.erase(std::find(value.begin(), value.end(), '\0'), value.end());
}
};
Token::Literal literal;
if (dynamic_cast<PatternDataUnsigned*>(pattern) || dynamic_cast<PatternDataEnum*>(pattern)) {
u128 value = 0;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
literal = value;
} else if (dynamic_cast<PatternDataSigned*>(pattern)) {
s128 value = 0;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
value = hex::signExtend(pattern->getSize() * 8, value);
literal = value;
} else if (dynamic_cast<PatternDataFloat*>(pattern)) {
if (pattern->getSize() == sizeof(u16)) {
u16 value = 0;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
literal = double(float16ToFloat32(value));
} else if (pattern->getSize() == sizeof(float)) {
float value = 0;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
literal = double(value);
} else if (pattern->getSize() == sizeof(double)) {
double value = 0;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
literal = value;
} else LogConsole::abortEvaluation("invalid floating point type access", this);
} else if (dynamic_cast<PatternDataCharacter*>(pattern)) {
char value = 0;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
literal = value;
} else if (dynamic_cast<PatternDataBoolean*>(pattern)) {
bool value = false;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
literal = value;
} else if (dynamic_cast<PatternDataString*>(pattern)) {
std::string value;
@@ -1581,7 +1550,7 @@ namespace hex::pl {
if (!dynamic_cast<PatternDataString*>(assignmentValue) && !dynamic_cast<PatternDataCharacter*>(assignmentValue))
LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this);
readString(value, assignmentValue);
readVariable(evaluator, value, assignmentValue);
},
[&, this](auto &&assignmentValue) { LogConsole::abortEvaluation(hex::format("cannot assign '{}' to string", pattern->getTypeName()), this); }
}, literal);
@@ -1595,7 +1564,7 @@ namespace hex::pl {
literal = value;
} else if (auto bitfieldFieldPattern = dynamic_cast<PatternDataBitfieldField*>(pattern)) {
u64 value = 0;
readValue(value, pattern);
readVariable(evaluator, value, pattern);
literal = u128(hex::extract(bitfieldFieldPattern->getBitOffset() + (bitfieldFieldPattern->getBitSize() - 1), bitfieldFieldPattern->getBitOffset(), value));
} else {
literal = pattern->clone();
@@ -1716,15 +1685,26 @@ namespace hex::pl {
currPattern = newPattern;
}
if (auto structPattern = dynamic_cast<PatternDataStruct*>(currPattern))
PatternData *indexPattern;
if (currPattern->isLocal()) {
auto stackLiteral = evaluator->getStack()[currPattern->getOffset()];
if (auto stackPattern = std::get_if<PatternData*>(&stackLiteral); stackPattern != nullptr)
indexPattern = *stackPattern;
else
return { currPattern };
}
else
indexPattern = currPattern;
if (auto structPattern = dynamic_cast<PatternDataStruct*>(indexPattern))
searchScope = structPattern->getMembers();
else if (auto unionPattern = dynamic_cast<PatternDataUnion*>(currPattern))
else if (auto unionPattern = dynamic_cast<PatternDataUnion*>(indexPattern))
searchScope = unionPattern->getMembers();
else if (auto bitfieldPattern = dynamic_cast<PatternDataBitfield*>(currPattern))
else if (auto bitfieldPattern = dynamic_cast<PatternDataBitfield*>(indexPattern))
searchScope = bitfieldPattern->getFields();
else if (auto dynamicArrayPattern = dynamic_cast<PatternDataDynamicArray*>(currPattern))
else if (auto dynamicArrayPattern = dynamic_cast<PatternDataDynamicArray*>(indexPattern))
searchScope = dynamicArrayPattern->getEntries();
else if (auto staticArrayPattern = dynamic_cast<PatternDataStaticArray*>(currPattern))
else if (auto staticArrayPattern = dynamic_cast<PatternDataStaticArray*>(indexPattern))
searchScope = { staticArrayPattern->getTemplate() };
}
@@ -1737,6 +1717,34 @@ namespace hex::pl {
private:
Path m_path;
void readVariable(Evaluator *evaluator, auto &value, PatternData *variablePattern) const {
constexpr bool isString = std::same_as<std::remove_cvref_t<decltype(value)>, std::string>;
if (variablePattern->isLocal()) {
auto &literal = evaluator->getStack()[variablePattern->getOffset()];
std::visit(overloaded {
[&](std::string &assignmentValue) {
if constexpr (isString) value = assignmentValue;
},
[&](PatternData *assignmentValue) { readVariable(evaluator, value, assignmentValue); },
[&](auto &&assignmentValue) { value = assignmentValue; }
}, literal);
}
else {
if constexpr (isString) {
value.resize(variablePattern->getSize());
evaluator->getProvider()->read(variablePattern->getOffset(), value.data(), value.size());
value.erase(std::find(value.begin(), value.end(), '\0'), value.end());
} else {
evaluator->getProvider()->read(variablePattern->getOffset(), &value, variablePattern->getSize());
}
}
if constexpr (!isString)
value = hex::changeEndianess(value, variablePattern->getSize(), variablePattern->getEndian());
}
};
class ASTNodeScopeResolution : public ASTNode {

View File

@@ -7,9 +7,11 @@
#include <vector>
#include <hex/pattern_language/log_console.hpp>
#include <hex/api/content_registry.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/concepts.hpp>
namespace hex::prv { class Provider; }

View File

@@ -74,14 +74,14 @@ namespace hex::pl {
this->m_evaluator->patternDestroyed();
}
private:
protected:
Evaluator *m_evaluator = nullptr;
};
class PatternData : public PatternCreationLimiter {
public:
PatternData(u64 offset, size_t size, Evaluator *evaluator, u32 color = 0)
: PatternCreationLimiter(evaluator), m_offset(offset), m_size(size), m_color(color), m_parent(nullptr), m_evaluator(evaluator) {
: PatternCreationLimiter(evaluator), m_offset(offset), m_size(size), m_color(color) {
constexpr u32 Palette[] = { 0x70b4771f, 0x700e7fff, 0x702ca02c, 0x702827d6, 0x70bd6794, 0x704b568c, 0x70c277e3, 0x707f7f7f, 0x7022bdbc, 0x70cfbe17 };
if (color != 0)
@@ -100,7 +100,7 @@ namespace hex::pl {
virtual PatternData* clone() = 0;
[[nodiscard]] u64 getOffset() const { return this->m_offset; }
virtual void setOffset(u64 offset) { this->m_offset = offset; }
void setOffset(u64 offset) { this->m_offset = offset; }
[[nodiscard]] size_t getSize() const { return this->m_size; }
void setSize(size_t size) { this->m_size = size; }
@@ -120,9 +120,6 @@ namespace hex::pl {
[[nodiscard]] std::endian getEndian() const { return this->m_endian; }
void setEndian(std::endian endian) { this->m_endian = endian; }
[[nodiscard]] PatternData* getParent() const { return this->m_parent; }
void setParent(PatternData *parent) { this->m_parent = parent; }
[[nodiscard]] std::string getDisplayName() const { return this->m_displayName.value_or(this->m_variableName); }
void setDisplayName(const std::string &name) { this->m_displayName = name; }
@@ -136,26 +133,14 @@ namespace hex::pl {
virtual void createEntry(prv::Provider* &provider) = 0;
[[nodiscard]] virtual std::string getFormattedName() const = 0;
virtual std::optional<u32> highlightBytes(size_t offset) {
auto currOffset = this->getOffset();
if (offset >= currOffset && offset < (currOffset + this->getSize()))
return this->getColor();
else
return { };
}
virtual std::map<u64, u32> getHighlightedAddresses() {
if (this->isHidden()) return { };
if (this->m_highlightedAddresses.empty()) {
for (u64 i = 0; i < this->getSize(); i++)
this->m_highlightedAddresses.insert({ this->getOffset() + i, this->getColor() });
}
return this->m_highlightedAddresses;
}
std::map<u64, u32> result;
for (u64 i = 0; i < this->getSize(); i++)
result.insert({ this->getOffset() + i, this->getColor() });
virtual void clearHighlightedAddresses() {
this->m_highlightedAddresses.clear();
return result;
}
virtual void sort(ImGuiTableSortSpecs *sortSpecs, prv::Provider *provider) { }
@@ -258,6 +243,28 @@ namespace hex::pl {
this->m_local == other.m_local;
}
[[nodiscard]]
std::string formatDisplayValue(const std::string &value, const Token::Literal &literal) const {
if (!this->m_formatterFunction.has_value())
return value;
else {
try {
auto result = this->m_formatterFunction->func(this->getEvaluator(), { literal });
if (result.has_value()) {
if (auto displayValue = std::get_if<std::string>(&result.value()); displayValue != nullptr)
return *displayValue;
else
return "???";
} else {
return "???";
}
} catch (LogConsole::EvaluateError &error) {
return "Error: " + error.second;
}
}
}
protected:
void createDefaultEntry(const std::string &value, const Token::Literal &literal) const {
ImGui::TableNextRow();
@@ -278,19 +285,7 @@ namespace hex::pl {
ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName());
ImGui::TableNextColumn();
if (!this->m_formatterFunction.has_value())
ImGui::TextUnformatted(value.c_str());
else {
auto result = this->m_formatterFunction->func(this->getEvaluator(), { literal });
if (result.has_value()) {
if (auto displayValue = std::get_if<std::string>(&result.value()); displayValue != nullptr)
ImGui::TextUnformatted(displayValue->c_str());
} else {
ImGui::TextUnformatted("???");
}
}
ImGui::TextFormatted("{}", formatDisplayValue(value, literal));
}
void drawCommentTooltip() const {
@@ -303,7 +298,6 @@ namespace hex::pl {
protected:
std::endian m_endian = std::endian::native;
std::map<u64, u32> m_highlightedAddresses;
bool m_hidden = false;
private:
@@ -316,11 +310,9 @@ namespace hex::pl {
std::optional<std::string> m_comment;
std::string m_typeName;
Evaluator *m_evaluator = nullptr;
std::optional<ContentRegistry::PatternLanguage::Function> m_formatterFunction;
std::optional<ContentRegistry::PatternLanguage::Function> m_transformFunction;
PatternData *m_parent;
bool m_local = false;
};
@@ -378,7 +370,7 @@ namespace hex::pl {
ImGui::TableNextColumn();
ImGui::TextFormattedColored(ImColor(0xFF9BC64D), "{}", this->getFormattedName());
ImGui::TableNextColumn();
ImGui::TextFormatted("*(0x{0})", data);
ImGui::TextFormatted("{}", formatDisplayValue(hex::format("*(0x{0:X})", data), u128(data)));
if (open) {
this->m_pointedAt->createEntry(provider);
@@ -387,25 +379,13 @@ namespace hex::pl {
}
}
std::optional<u32> highlightBytes(size_t offset) override {
if (offset >= this->getOffset() && offset < (this->getOffset() + this->getSize()))
return this->getColor();
else if (auto color = this->m_pointedAt->highlightBytes(offset); color.has_value())
return color.value();
else
return { };
}
std::map<u64, u32> getHighlightedAddresses() override {
if (this->m_highlightedAddresses.empty()) {
auto ownAddresses = PatternData::getHighlightedAddresses();
auto pointedToAddresses = this->m_pointedAt->getHighlightedAddresses();
ownAddresses.merge(pointedToAddresses);
this->m_highlightedAddresses = ownAddresses;
}
return this->m_highlightedAddresses;
return ownAddresses;
}
[[nodiscard]] std::string getFormattedName() const override {
std::string result = this->m_pointedAt->getFormattedName() + "* : ";
@@ -423,6 +403,15 @@ namespace hex::pl {
void setPointedAtPattern(PatternData *pattern) {
this->m_pointedAt = pattern;
this->m_pointedAt->setVariableName(hex::format("*({})", this->getVariableName()));
this->m_pointedAt->setOffset(this->m_pointedAtAddress);
}
void setPointedAtAddress(u64 address) {
this->m_pointedAtAddress = address;
}
[[nodiscard]] u64 getPointedAtAddress() const {
return this->m_pointedAtAddress;
}
[[nodiscard]] PatternData* getPointedAtPattern() {
@@ -440,14 +429,18 @@ namespace hex::pl {
}
void rebase(u64 base) {
if (this->m_pointedAt != nullptr)
this->m_pointedAt->setOffset((this->m_pointedAt->getOffset() - this->m_pointerBase) + base);
if (this->m_pointedAt != nullptr) {
this->m_pointedAtAddress = (this->m_pointedAt->getOffset() - this->m_pointerBase) + base;
this->m_pointedAt->setOffset(this->m_pointedAtAddress);
}
this->m_pointerBase = base;
}
private:
PatternData *m_pointedAt = nullptr;
u64 m_pointedAtAddress = 0;
u64 m_pointerBase = 0;
};
@@ -752,17 +745,6 @@ namespace hex::pl {
return new PatternDataDynamicArray(*this);
}
void setOffset(u64 offset) override {
if (!this->isLocal()) {
for (auto &entry : this->m_entries) {
entry->setOffset(offset + (entry->getOffset() - this->getOffset()));
}
}
PatternData::setOffset(offset);
}
void setColor(u32 color) override {
PatternData::setColor(color);
for (auto &entry : this->m_entries)
@@ -796,41 +778,40 @@ namespace hex::pl {
ImGui::TextUnformatted("]");
ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }");
ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
}
if (open) {
for (auto &member : this->m_entries)
member->draw(provider);
for (u64 i = 0; i < this->m_entries.size(); i++) {
this->m_entries[i]->draw(provider);
if (i >= (this->m_displayEnd - 1)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Selectable("... (Double-click to see more items)", false, ImGuiSelectableFlags_SpanAllColumns);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
this->m_displayEnd += 50;
break;
}
}
if (!this->isInlined())
ImGui::TreePop();
} else {
this->m_displayEnd = 50;
}
}
std::optional<u32> highlightBytes(size_t offset) override{
for (auto &entry : this->m_entries) {
if (auto color = entry->highlightBytes(offset); color.has_value())
return color.value();
}
return { };
}
std::map<u64, u32> getHighlightedAddresses() override {
if (this->m_highlightedAddresses.empty()) {
for (auto &entry : this->m_entries) {
this->m_highlightedAddresses.merge(entry->getHighlightedAddresses());
}
std::map<u64, u32> result;
for (auto &entry : this->m_entries) {
result.merge(entry->getHighlightedAddresses());
}
return this->m_highlightedAddresses;
}
void clearHighlightedAddresses() override {
for (auto &entry : this->m_entries)
entry->clearHighlightedAddresses();
PatternData::clearHighlightedAddresses();
return result;
}
[[nodiscard]] std::string getFormattedName() const override {
@@ -846,7 +827,6 @@ namespace hex::pl {
for (auto &entry : this->m_entries) {
entry->setColor(this->getColor());
entry->setParent(this);
}
}
@@ -868,6 +848,7 @@ namespace hex::pl {
private:
std::vector<PatternData*> m_entries;
u64 m_displayEnd = 50;
};
class PatternDataStaticArray : public PatternData, public Inlinable {
@@ -916,7 +897,7 @@ namespace hex::pl {
ImGui::TextUnformatted("]");
ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }");
ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
}
if (open) {
@@ -925,48 +906,39 @@ namespace hex::pl {
entry->setVariableName(hex::format("[{0}]", index));
entry->setOffset(this->getOffset() + index * this->m_template->getSize());
entry->draw(provider);
if (index >= (this->m_displayEnd - 1)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Selectable("... (Double-click to see more items)", false, ImGuiSelectableFlags_SpanAllColumns);
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
this->m_displayEnd += 50;
break;
}
}
delete entry;
if (!this->isInlined())
ImGui::TreePop();
} else {
this->m_displayEnd = 50;
}
}
std::optional<u32> highlightBytes(size_t offset) override{
auto entry = this->m_template->clone();
ON_SCOPE_EXIT { delete entry; };
if (offset < this->getOffset() || offset >= this->getOffset() + this->getSize())
return { };
auto index = (offset - this->getOffset()) / this->m_template->getSize();
entry->setOffset(this->getOffset() + this->m_template->getSize() * index);
if (auto color = entry->highlightBytes(offset); color.has_value())
return color.value();
else
return { };
}
std::map<u64, u32> getHighlightedAddresses() override {
if (this->m_highlightedAddresses.empty()) {
auto entry = this->m_template->clone();
auto startOffset = this->m_template->getOffset();
for (u64 address = this->getOffset(); address < this->getOffset() + this->getSize(); address += this->m_template->getSize()) {
entry->setOffset(address);
entry->clearHighlightedAddresses();
this->m_highlightedAddresses.merge(entry->getHighlightedAddresses());
}
delete entry;
std::map<u64, u32> result;
for (u64 address = this->getOffset(); address < this->getOffset() + this->getSize(); address += this->m_template->getSize()) {
this->m_template->setOffset(address);
result.merge(this->m_template->getHighlightedAddresses());
}
return this->m_highlightedAddresses;
}
this->m_template->setOffset(startOffset);
void clearHighlightedAddresses() override {
this->m_template->clearHighlightedAddresses();
PatternData::clearHighlightedAddresses();
return result;
}
void setColor(u32 color) override {
@@ -996,7 +968,6 @@ namespace hex::pl {
this->setColor(this->m_template->getColor());
this->m_template->setEndian(templ->getEndian());
this->m_template->setParent(this);
}
[[nodiscard]] bool operator==(const PatternData &other) const override {
@@ -1010,6 +981,7 @@ namespace hex::pl {
private:
PatternData *m_template;
size_t m_entryCount;
u64 m_displayEnd = 50;
};
class PatternDataStruct : public PatternData, public Inlinable {
@@ -1033,16 +1005,6 @@ namespace hex::pl {
return new PatternDataStruct(*this);
}
void setOffset(u64 offset) override {
if (!this->isLocal()) {
for (auto &member: this->m_members) {
member->setOffset(offset + (member->getOffset() - this->getOffset()));
}
}
PatternData::setOffset(offset);
}
void createEntry(prv::Provider* &provider) override {
bool open = true;
@@ -1059,7 +1021,7 @@ namespace hex::pl {
ImGui::TableNextColumn();
ImGui::TextColored(ImColor(0xFFD69C56), "struct"); ImGui::SameLine(); ImGui::TextUnformatted(this->getTypeName().c_str());
ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }");
ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
}
if (open) {
@@ -1072,29 +1034,13 @@ namespace hex::pl {
}
std::optional<u32> highlightBytes(size_t offset) override{
for (auto &member : this->m_members) {
if (auto color = member->highlightBytes(offset); color.has_value())
return color.value();
}
return { };
}
std::map<u64, u32> getHighlightedAddresses() override {
if (this->m_highlightedAddresses.empty()) {
for (auto &member : this->m_members) {
this->m_highlightedAddresses.merge(member->getHighlightedAddresses());
}
std::map<u64, u32> result;
for (auto &member : this->m_members) {
result.merge(member->getHighlightedAddresses());
}
return this->m_highlightedAddresses;
}
void clearHighlightedAddresses() override {
for (auto &member : this->m_members)
member->clearHighlightedAddresses();
PatternData::clearHighlightedAddresses();
return result;
}
void setColor(u32 color) override {
@@ -1129,7 +1075,6 @@ namespace hex::pl {
if (member == nullptr) continue;
this->m_members.push_back(member);
member->setParent(this);
}
this->m_sortedMembers = this->m_members;
@@ -1178,16 +1123,6 @@ namespace hex::pl {
return new PatternDataUnion(*this);
}
void setOffset(u64 offset) override {
if (!this->isLocal()) {
for (auto &member: this->m_members) {
member->setOffset(offset + (member->getOffset() - this->getOffset()));
}
}
PatternData::setOffset(offset);
}
void createEntry(prv::Provider* &provider) override {
bool open = true;
@@ -1205,7 +1140,7 @@ namespace hex::pl {
ImGui::TextColored(ImColor(0xFFD69C56), "union"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str());
ImGui::TableNextColumn();
ImGui::TextUnformatted("{ ... }");
ImGui::TextFormatted("{}", this->formatDisplayValue("{ ... }", this));
}
if (open) {
@@ -1218,29 +1153,14 @@ namespace hex::pl {
}
std::optional<u32> highlightBytes(size_t offset) override{
for (auto &member : this->m_members) {
if (auto color = member->highlightBytes(offset); color.has_value())
return color.value();
}
return { };
}
std::map<u64, u32> getHighlightedAddresses() override {
if (this->m_highlightedAddresses.empty()) {
for (auto &member : this->m_members) {
this->m_highlightedAddresses.merge(member->getHighlightedAddresses());
}
std::map<u64, u32> result;
for (auto &member : this->m_members) {
result.merge(member->getHighlightedAddresses());
}
return this->m_highlightedAddresses;
}
void clearHighlightedAddresses() override {
for (auto &member : this->m_members)
member->clearHighlightedAddresses();
PatternData::clearHighlightedAddresses();
return result;
}
void setColor(u32 color) override {
@@ -1274,7 +1194,6 @@ namespace hex::pl {
if (member == nullptr) continue;
this->m_members.push_back(member);
member->setParent(this);
}
this->m_sortedMembers = this->m_members;
@@ -1359,7 +1278,7 @@ namespace hex::pl {
ImGui::TableNextColumn();
ImGui::TextColored(ImColor(0xFFD69C56), "enum"); ImGui::SameLine(); ImGui::TextUnformatted(PatternData::getTypeName().c_str());
ImGui::TableNextColumn();
ImGui::TextFormatted("{} (0x{:0{}X})", valueString.c_str(), value, this->getSize() * 2);
ImGui::TextFormatted("{}", this->formatDisplayValue(hex::format("{} (0x{:0{}X})", valueString.c_str(), value, this->getSize() * 2), this));
}
[[nodiscard]] std::string getFormattedName() const override {
@@ -1397,8 +1316,8 @@ namespace hex::pl {
class PatternDataBitfieldField : public PatternData {
public:
PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, Evaluator *evaluator, u32 color = 0)
: m_bitOffset(bitOffset), m_bitSize(bitSize), PatternData(offset, 0, evaluator, color) {
PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, PatternData *bitField, Evaluator *evaluator, u32 color = 0)
: m_bitOffset(bitOffset), m_bitSize(bitSize), m_bitField(bitField), PatternData(offset, 0, evaluator, color) {
}
@@ -1407,10 +1326,10 @@ namespace hex::pl {
}
void createEntry(prv::Provider* &provider) override {
std::vector<u8> value(this->getParent()->getSize(), 0);
provider->read(this->getParent()->getOffset(), &value[0], value.size());
std::vector<u8> value(this->m_bitField->getSize(), 0);
provider->read(this->m_bitField->getOffset(), &value[0], value.size());
if (this->getParent()->getEndian() == std::endian::little)
if (this->m_bitField->getEndian() == std::endian::little)
std::reverse(value.begin(), value.end());
ImGui::TableNextRow();
@@ -1435,7 +1354,7 @@ namespace hex::pl {
u8 numBytes = (this->m_bitSize / 8) + 1;
u64 extractedValue = hex::extract(this->m_bitOffset + (this->m_bitSize - 1), this->m_bitOffset, value);
ImGui::TextFormatted("{0} (0x{1:X})", extractedValue, extractedValue);
ImGui::TextFormatted("{}", this->formatDisplayValue(hex::format("{0} (0x{1:X})", extractedValue, extractedValue), this));
}
}
@@ -1462,6 +1381,7 @@ namespace hex::pl {
private:
u8 m_bitOffset, m_bitSize;
PatternData *m_bitField;
};
class PatternDataBitfield : public PatternData, public Inlinable {
@@ -1512,7 +1432,7 @@ namespace hex::pl {
valueString += hex::format("{0:02X} ", i);
valueString += "}";
ImGui::TextUnformatted(valueString.c_str());
ImGui::TextFormatted("{}", this->formatDisplayValue(valueString, this));
}
if (open) {
@@ -1540,7 +1460,6 @@ namespace hex::pl {
for (auto &field : this->m_fields) {
field->setSize(this->getSize());
field->setColor(this->getColor());
field->setParent(this);
}
}

View File

@@ -33,8 +33,8 @@ namespace hex {
virtual void drawContent() = 0;
virtual void drawAlwaysVisible() { }
virtual void drawMenu();
virtual bool isAvailable();
virtual bool shouldProcess() { return this->isAvailable() && this->getWindowOpenState(); }
virtual bool isAvailable() const;
virtual bool shouldProcess() const { return this->isAvailable() && this->getWindowOpenState(); }
static void doLater(std::function<void()> &&function);
static std::vector<std::function<void()>>& getDeferedCalls();
@@ -45,11 +45,12 @@ namespace hex {
static void showErrorPopup(const std::string &errorMessage);
static void showFatalPopup(const std::string &errorMessage);
virtual bool hasViewMenuItemEntry();
virtual ImVec2 getMinSize();
virtual ImVec2 getMaxSize();
virtual bool hasViewMenuItemEntry() const;
virtual ImVec2 getMinSize() const;
virtual ImVec2 getMaxSize() const;
bool& getWindowOpenState();
const bool& getWindowOpenState() const;
[[nodiscard]] const std::string& getUnlocalizedName() const;

View File

@@ -36,7 +36,7 @@ namespace hex {
#endif
}
std::vector<std::string> getPath(ImHexPath path) {
std::vector<std::string> getPath(ImHexPath path, bool listNonExisting) {
std::vector<std::string> result;
#if defined(OS_WINDOWS)
@@ -195,9 +195,11 @@ namespace hex {
}
#endif
result.erase(std::remove_if(result.begin(), result.end(), [](const auto& path){
return !std::filesystem::is_directory(path);
}), result.end());
if (!listNonExisting) {
result.erase(std::remove_if(result.begin(), result.end(), [](const auto& path){
return !std::filesystem::is_directory(path);
}), result.end());
}
return result;
}

View File

@@ -6,6 +6,7 @@
#include <filesystem>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/shared_data.hpp>
#if defined (OS_WINDOWS)
#include <windows.h>
@@ -18,6 +19,18 @@
namespace hex {
long double operator""_scaled(long double value) {
return value * SharedData::globalScale;
}
long double operator""_scaled(unsigned long long value) {
return value * SharedData::globalScale;
}
ImVec2 scaled(const ImVec2 &vector) {
return vector * SharedData::globalScale;
}
std::string to_string(u128 value) {
char data[45] = { 0 };

View File

@@ -81,11 +81,11 @@ namespace hex::pl {
Token::Literal castedLiteral = std::visit(overloaded {
[&](double &value) -> Token::Literal {
if (dynamic_cast<PatternDataUnsigned*>(pattern))
return u128(value);
return u128(value) & bitmask(pattern->getSize() * 8);
else if (dynamic_cast<PatternDataSigned*>(pattern))
return s128(value);
return s128(value) & bitmask(pattern->getSize() * 8);
else if (dynamic_cast<PatternDataFloat*>(pattern))
return value;
return pattern->getSize() == sizeof(float) ? double(float(value)) : value;
else
LogConsole::abortEvaluation(hex::format("cannot cast type 'double' to type '{}'", pattern->getTypeName()));
},
@@ -102,18 +102,18 @@ namespace hex::pl {
LogConsole::abortEvaluation(hex::format("cannot cast type '{}' to type '{}'", value->getTypeName(), pattern->getTypeName()));
},
[&](auto &&value) -> Token::Literal {
if (dynamic_cast<PatternDataUnsigned*>(pattern))
return u128(value);
if (dynamic_cast<PatternDataUnsigned*>(pattern) || dynamic_cast<PatternDataEnum*>(pattern))
return u128(value) & bitmask(pattern->getSize() * 8);
else if (dynamic_cast<PatternDataSigned*>(pattern))
return s128(value);
return s128(value) & bitmask(pattern->getSize() * 8);
else if (dynamic_cast<PatternDataCharacter*>(pattern))
return char(value);
else if (dynamic_cast<PatternDataBoolean*>(pattern))
return bool(value);
else if (dynamic_cast<PatternDataFloat*>(pattern))
return double(value);
return pattern->getSize() == sizeof(float) ? double(float(value)) : value;
else
LogConsole::abortEvaluation(hex::format("cannot cast type 'string' to type '{}'", pattern->getTypeName()));
LogConsole::abortEvaluation(hex::format("cannot cast integer literal to type '{}'", pattern->getTypeName()));
}
}, value);

View File

@@ -14,7 +14,7 @@ namespace hex {
void View::drawMenu() { }
bool View::isAvailable() {
bool View::isAvailable() const {
return ImHexApi::Provider::isValid() && ImHexApi::Provider::get()->isAvailable();
}
@@ -23,7 +23,7 @@ namespace hex {
}
void View::drawCommonInterfaces() {
ImGui::SetNextWindowSizeConstraints(ImVec2(400, 100) * SharedData::globalScale, ImVec2(600, 300) * SharedData::globalScale);
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
if (ImGui::BeginPopupModal("hex.common.info"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextWrapped("%s", SharedData::popupMessage.c_str());
ImGui::NewLine();
@@ -35,7 +35,7 @@ namespace hex {
ImGui::EndPopup();
}
ImGui::SetNextWindowSizeConstraints(ImVec2(400, 100) * SharedData::globalScale, ImVec2(600, 300) * SharedData::globalScale);
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
if (ImGui::BeginPopupModal("hex.common.error"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextWrapped("%s", SharedData::popupMessage.c_str());
ImGui::NewLine();
@@ -47,7 +47,7 @@ namespace hex {
ImGui::EndPopup();
}
ImGui::SetNextWindowSizeConstraints(ImVec2(400, 100) * SharedData::globalScale, ImVec2(600, 300) * SharedData::globalScale);
ImGui::SetNextWindowSizeConstraints(scaled(ImVec2(400, 100)), scaled(ImVec2(600, 300)));
if (ImGui::BeginPopupModal("hex.common.fatal"_lang, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::TextWrapped("%s", SharedData::popupMessage.c_str());
ImGui::NewLine();
@@ -80,15 +80,15 @@ namespace hex {
View::doLater([] { ImGui::OpenPopup("hex.common.fatal"_lang); });
}
bool View::hasViewMenuItemEntry() {
bool View::hasViewMenuItemEntry() const {
return true;
}
ImVec2 View::getMinSize() {
return ImVec2(480, 720) * SharedData::globalScale;
ImVec2 View::getMinSize() const {
return scaled(ImVec2(480, 720));
}
ImVec2 View::getMaxSize() {
ImVec2 View::getMaxSize() const {
return { FLT_MAX, FLT_MAX };
}
@@ -97,6 +97,10 @@ namespace hex {
return this->m_windowOpen;
}
const bool& View::getWindowOpenState() const {
return this->m_windowOpen;
}
const std::string& View::getUnlocalizedName() const {
return this->m_unlocalizedViewName;
}

View File

@@ -175,7 +175,7 @@ namespace hex::init {
}
}
this->m_window = glfwCreateWindow(640 * SharedData::globalScale, 400 * SharedData::globalScale, "Starting ImHex...", nullptr, nullptr);
this->m_window = glfwCreateWindow(640_scaled, 400_scaled, "Starting ImHex...", nullptr, nullptr);
if (this->m_window == nullptr) {
log::fatal("Failed to create GLFW window!");
exit(EXIT_FAILURE);
@@ -203,7 +203,7 @@ namespace hex::init {
ImFontConfig cfg;
cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true;
cfg.SizePixels = 13.0f * SharedData::globalScale;
cfg.SizePixels = 13.0_scaled;
io.Fonts->AddFontDefault(&cfg);
cfg.MergeMode = true;
@@ -214,7 +214,7 @@ namespace hex::init {
};
std::uint8_t *px;
int w, h;
io.Fonts->AddFontFromMemoryCompressedTTF(font_awesome_compressed_data, font_awesome_compressed_size, 11.0f * SharedData::globalScale, &cfg, fontAwesomeRange);
io.Fonts->AddFontFromMemoryCompressedTTF(font_awesome_compressed_data, font_awesome_compressed_size, 11.0_scaled, &cfg, fontAwesomeRange);
io.Fonts->GetTexDataAsRGBA32(&px, &w, &h);
// Create new font atlas

View File

@@ -70,7 +70,7 @@ namespace hex::init {
};
for (auto path : paths) {
for (auto &folder : hex::getPath(path)) {
for (auto &folder : hex::getPath(path, true)) {
try {
std::filesystem::create_directories(folder);
} catch (...) {
@@ -136,7 +136,7 @@ namespace hex::init {
fonts->Clear();
cfg.OversampleH = cfg.OversampleV = 1, cfg.PixelSnapH = true;
cfg.SizePixels = 13.0f * SharedData::fontScale;
cfg.SizePixels = 13.0F * SharedData::fontScale;
fonts->AddFontDefault(&cfg);
} else {
// Load custom font
@@ -151,9 +151,9 @@ namespace hex::init {
cfg.MergeMode = true;
fonts->AddFontFromMemoryCompressedTTF(font_awesome_compressed_data, font_awesome_compressed_size, 13.0f * SharedData::fontScale, &cfg, fontAwesomeRange);
fonts->AddFontFromMemoryCompressedTTF(codicons_compressed_data, codicons_compressed_size, 13.0f * SharedData::fontScale, &cfg, codiconsRange);
fonts->AddFontFromMemoryCompressedTTF(unifont_compressed_data, unifont_compressed_size, 13.0f * SharedData::fontScale, &cfg, unifontRange);
fonts->AddFontFromMemoryCompressedTTF(font_awesome_compressed_data, font_awesome_compressed_size, 13.0F * SharedData::fontScale, &cfg, fontAwesomeRange);
fonts->AddFontFromMemoryCompressedTTF(codicons_compressed_data, codicons_compressed_size, 13.0F * SharedData::fontScale, &cfg, codiconsRange);
fonts->AddFontFromMemoryCompressedTTF(unifont_compressed_data, unifont_compressed_size, 13.0F * SharedData::fontScale, &cfg, unifontRange);
ImGuiFreeType::BuildFontAtlas(fonts);

View File

@@ -319,10 +319,14 @@
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - buttonSize.x * 6);
#if defined(DEBUG)
if (ImGui::TitleBarButton(ICON_VS_DEBUG, buttonSize)) {
if (ImGui::GetIO().KeyCtrl && ImGui::GetIO().KeyShift) {
if (ImGui::GetIO().KeyCtrl) {
// Explicitly trigger a segfault by writing to an invalid memory location
// Used for debugging crashes
*reinterpret_cast<u8*>(0x10) = 0x10;
} else if (ImGui::GetIO().KeyShift) {
// Explicitly trigger an abort by throwing an uncaught exception
// Used for debugging exception errors
throw std::runtime_error("Debug Error");
} else {
hex::openWebpage("https://imhex.werwolv.net/debug");
}

View File

@@ -12,6 +12,7 @@
#include <iostream>
#include <numeric>
#include <thread>
#include <assert.h>
#include <romfs/romfs.hpp>
@@ -259,9 +260,19 @@ namespace hex {
auto signalHandler = [](int signalNumber) {
EventManager::post<EventAbnormalTermination>(signalNumber);
if (std::uncaught_exceptions() > 0) {
log::fatal("Uncaught exception thrown!");
}
// Let's not loop on this...
std::signal(signalNumber, nullptr);
std::raise(signalNumber);
#if defined(DEBUG)
assert(false);
#else
std::raise(signalNumber);
#endif
};
std::signal(SIGTERM, signalHandler);
@@ -406,7 +417,7 @@ namespace hex {
static char title[256];
ImFormatString(title, IM_ARRAYSIZE(title), "%s/DockSpace_%08X", ImGui::GetCurrentWindow()->Name, ImGui::GetID("MainDock"));
if (ImGui::Begin(title)) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10 * SharedData::globalScale, 10 * SharedData::globalScale));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10_scaled, 10_scaled));
if (ImGui::BeginChild("Welcome Screen", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoScrollWithMouse)) {
this->drawWelcomeScreen();
}
@@ -517,10 +528,12 @@ namespace hex {
}
if (view->getWindowOpenState()) {
bool hasWindow = ImGui::FindWindowByName(View::toWindowName(view->getUnlocalizedName()).c_str()) != nullptr;
auto window = ImGui::FindWindowByName(View::toWindowName(view->getUnlocalizedName()).c_str());
bool hasWindow = window != nullptr;
bool focused = false;
if (hasWindow) {
if (hasWindow && !(window->Flags & ImGuiWindowFlags_Popup)) {
ImGui::Begin(View::toWindowName(view->getUnlocalizedName()).c_str());
focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows);
@@ -585,7 +598,7 @@ namespace hex {
ImGui::UnderlinedText("hex.welcome.header.start"_lang);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5 * SharedData::globalScale);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
{
if (ImGui::IconHyperlink(ICON_VS_NEW_FILE, "hex.welcome.start.create_file"_lang))
EventManager::post<RequestOpenWindow>("Create File");
@@ -613,7 +626,7 @@ namespace hex {
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 9);
ImGui::TableNextColumn();
ImGui::UnderlinedText("hex.welcome.start.recent"_lang);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5 * SharedData::globalScale);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
{
if (!SharedData::recentFilePaths.empty()) {
for (auto &path : SharedData::recentFilePaths) {
@@ -638,7 +651,7 @@ namespace hex {
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetTextLineHeightWithSpacing() * 6);
ImGui::TableNextColumn();
ImGui:: UnderlinedText("hex.welcome.header.help"_lang);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5 * SharedData::globalScale);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5_scaled);
{
if (ImGui::IconHyperlink(ICON_VS_GITHUB, "hex.welcome.help.repo"_lang)) hex::openWebpage("hex.welcome.help.repo.link"_lang);
if (ImGui::IconHyperlink(ICON_VS_ORGANIZATION, "hex.welcome.help.gethelp"_lang)) hex::openWebpage("hex.welcome.help.gethelp.link"_lang);
@@ -765,7 +778,7 @@ namespace hex {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
this->m_windowTitle = "ImHex";
this->m_window = glfwCreateWindow(1280 * SharedData::globalScale, 720 * SharedData::globalScale, this->m_windowTitle.c_str(), nullptr, nullptr);
this->m_window = glfwCreateWindow(1280_scaled, 720_scaled, this->m_windowTitle.c_str(), nullptr, nullptr);
glfwSetWindowUserPointer(this->m_window, this);
@@ -890,7 +903,7 @@ namespace hex {
EventManager::post<EventWindowClosing>(window);
});
glfwSetWindowSizeLimits(this->m_window, 720 * SharedData::globalScale, 480 * SharedData::globalScale, GLFW_DONT_CARE, GLFW_DONT_CARE);
glfwSetWindowSizeLimits(this->m_window, 720_scaled, 480_scaled, GLFW_DONT_CARE, GLFW_DONT_CARE);
glfwShowWindow(this->m_window);
}
@@ -916,7 +929,7 @@ namespace hex {
for (auto &entry : SharedData::fontAtlas->ConfigData)
io.Fonts->ConfigData.push_back(entry);
io.ConfigViewportsNoTaskBarIcon = true;
io.ConfigViewportsNoTaskBarIcon = false;
io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB;
io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT;
io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT;

View File

@@ -10,10 +10,10 @@ namespace hex::test {
auto testBitfield = create<PatternDataBitfield>("TestBitfield", "testBitfield", 0x12, (4 * 4) / 8, nullptr);
testBitfield->setEndian(std::endian::big);
testBitfield->setFields({
create<PatternDataBitfieldField>("", "a", 0x12, 0, 4, nullptr),
create<PatternDataBitfieldField>("", "b", 0x12, 4, 4, nullptr),
create<PatternDataBitfieldField>("", "c", 0x12, 8, 4, nullptr),
create<PatternDataBitfieldField>("", "d", 0x12, 12, 4, nullptr)
create<PatternDataBitfieldField>("", "a", 0x12, 0, 4, testBitfield, nullptr),
create<PatternDataBitfieldField>("", "b", 0x12, 4, 4, testBitfield, nullptr),
create<PatternDataBitfieldField>("", "c", 0x12, 8, 4, testBitfield, nullptr),
create<PatternDataBitfieldField>("", "d", 0x12, 12, 4, testBitfield, nullptr)
});
addPattern(testBitfield);

View File

@@ -10,6 +10,8 @@ namespace hex::test {
// placementPointer
{
auto placementPointer = create<PatternDataPointer>("", "placementPointer", 0x0C, sizeof(u8), nullptr);
placementPointer->setPointedAtAddress(0x49);
auto pointedTo = create<PatternDataUnsigned>("u32", "", 0x49, sizeof(u32), nullptr);
placementPointer->setPointedAtPattern(pointedTo);
addPattern(placementPointer);