#include #include #include #include #include #include #include #include #include namespace hex::plugin::builtin { namespace { void entropyMiniMapVisualizer(u64, std::span data, std::vector &output) { std::array frequencies = { 0 }; for (u8 byte : data) frequencies[byte] += 1; double entropy = 0.0; for (u32 frequency : frequencies) { if (frequency == 0) continue; double probability = static_cast(frequency) / data.size(); entropy -= probability * std::log2(probability); } // Calculate color ImColor color = ImColor::HSV(0.0F, 0.0F, 1.0F); if (entropy > 0.0) { double hue = std::clamp(entropy / 8.0, 0.0, 1.0); color = ImColor::HSV(static_cast(hue) / 0.75F, 0.8F, 1.0F); } output.push_back(color); } void zerosCountMiniMapVisualizer(u64, std::span data, std::vector &output) { u32 zerosCount = 0; for (u8 byte : data) { if (byte == 0x00) zerosCount += 1; } output.push_back(ImColor::HSV(0.0F, 0.0F, 1.0F - (double(zerosCount) / data.size()))); } void zerosMiniMapVisualizer(u64, std::span data, std::vector &output) { for (u8 byte : data) { if (byte == 0x00) output.push_back(ImColor(1.0F, 1.0F, 1.0F, 1.0F)); else output.push_back(ImColor(0.0F, 0.0F, 0.0F, 1.0F)); } } void byteTypeMiniMapVisualizer(u64, std::span data, std::vector &output) { for (u8 byte : data) { if (std::isalpha(byte)) output.emplace_back(1.0F, 0.0F, 0.0F, 1.0F); else if (std::isdigit(byte)) output.emplace_back(0.0F, 1.0F, 0.0F, 1.0F); else if (std::isspace(byte)) output.emplace_back(0.0F, 0.0F, 1.0F, 1.0F); else if (std::iscntrl(byte)) output.emplace_back(0.5F, 0.5F, 0.5F, 1.0F); else output.emplace_back(0.0F, 0.0F, 0.0F, 1.0F); } } void asciiCountMiniMapVisualizer(u64, std::span data, std::vector &output) { u8 asciiCount = 0; for (u8 byte : data) { if (std::isprint(byte)) asciiCount += 1; } output.push_back(ImColor::HSV(0.5F, 0.5F, (double(asciiCount) / data.size()))); } void byteMagnitudeMiniMapVisualizer(u64, std::span data, std::vector &output) { for (u8 byte : data) { output.push_back(ImColor::HSV(0.0F, 0.0F, static_cast(byte) / 255.0F)); } } void highlightsMiniMapVisualizer(u64 address, std::span data, std::vector &output) { for (size_t i = 0; i < data.size(); i += 1) { std::optional result; for (const auto &[id, callback] : ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions()) { if (auto color = callback(address + i, data.data() + i, 1, result.has_value()); color.has_value()) result = color; } if (!result.has_value()) { for (const auto &[id, highlighting] : ImHexApi::HexEditor::impl::getBackgroundHighlights()) { if (highlighting.getRegion().overlaps({ address, 1 })) { result = highlighting.getColor(); break; } } } if (result.has_value()) { result->Value.w = 1.0F; } else { if (auto region = ImHexApi::HexEditor::getSelection(); region.has_value()) { if (region->overlaps({ address + i, 1 })) result = 0x60C08080; } } output.push_back(result.value_or(ImColor())); } } } void registerMiniMapVisualizers() { ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.entropy", entropyMiniMapVisualizer); ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.zero_count", zerosCountMiniMapVisualizer); ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.zeros", zerosMiniMapVisualizer); ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.ascii_count", asciiCountMiniMapVisualizer); ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.byte_type", byteTypeMiniMapVisualizer); ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.highlights", highlightsMiniMapVisualizer); ContentRegistry::HexEditor::addMiniMapVisualizer("hex.builtin.minimap_visualizer.byte_magnitude", byteMagnitudeMiniMapVisualizer); } }