diff --git a/cmake/build_helpers.cmake b/cmake/build_helpers.cmake index f03439cbc..c8fcf468e 100644 --- a/cmake/build_helpers.cmake +++ b/cmake/build_helpers.cmake @@ -145,7 +145,8 @@ macro(createPackage) add_custom_command(TARGET imhex POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ - $/plugins/$) + $/plugins/$ + DEPENDS ${plugin}) endforeach() add_custom_command(TARGET imhex POST_BUILD diff --git a/plugins/builtin/source/content/data_processor_nodes.cpp b/plugins/builtin/source/content/data_processor_nodes.cpp index 1cf82d4d4..136b4f79b 100644 --- a/plugins/builtin/source/content/data_processor_nodes.cpp +++ b/plugins/builtin/source/content/data_processor_nodes.cpp @@ -16,10 +16,9 @@ namespace hex::plugin::builtin { } void process(prv::Overlay *dataOverlay) override { - std::vector data; - data.resize(sizeof(this->m_value)); + std::vector data(sizeof(this->m_value), 0); - std::copy(&this->m_value, &this->m_value + 1, data.data()); + std::memcpy(data.data(), &this->m_value, sizeof(u64)); this->getAttributes()[0].getOutputData() = data; } @@ -63,16 +62,10 @@ namespace hex::plugin::builtin { } void process(prv::Overlay *dataOverlay) override { - std::vector output(sizeof(u64), 0x00); - - output[0] = this->m_color.Value.x * 0xFF; - this->getAttributes()[0].getOutputData() = output; - output[0] = this->m_color.Value.y * 0xFF; - this->getAttributes()[1].getOutputData() = output; - output[0] = this->m_color.Value.z * 0xFF; - this->getAttributes()[2].getOutputData() = output; - output[0] = this->m_color.Value.w * 0xFF; - this->getAttributes()[3].getOutputData() = output; + this->getAttributes()[0].getOutputData() = hex::toBytes(this->m_color.Value.x * 0xFF); + this->getAttributes()[1].getOutputData() = hex::toBytes(this->m_color.Value.y * 0xFF); + this->getAttributes()[2].getOutputData() = hex::toBytes(this->m_color.Value.z * 0xFF); + this->getAttributes()[3].getOutputData() = hex::toBytes(this->m_color.Value.w * 0xFF); } private: @@ -102,6 +95,9 @@ namespace hex::plugin::builtin { connectedInput->getParentNode()->process(dataOverlay); + if (connectedInput->getOutputData().size() < sizeof(u64)) + return; + this->m_value = *reinterpret_cast(connectedInput->getOutputData().data()); } @@ -131,6 +127,9 @@ namespace hex::plugin::builtin { connectedInput->getParentNode()->process(dataOverlay); + if (connectedInput->getOutputData().size() < sizeof(float)) + return; + this->m_value = *reinterpret_cast(connectedInput->getOutputData().data()); } @@ -154,6 +153,8 @@ namespace hex::plugin::builtin { for (auto &byte : output) byte = ~byte; + + this->getAttributes()[1].getOutputData() = output; } }; @@ -202,6 +203,8 @@ namespace hex::plugin::builtin { for (u32 i = 0; i < output.size(); i++) output[i] = inputA[i] | inputB[i]; + + this->getAttributes()[2].getOutputData() = output; } }; @@ -225,6 +228,8 @@ namespace hex::plugin::builtin { for (u32 i = 0; i < output.size(); i++) output[i] = inputA[i] ^ inputB[i]; + + this->getAttributes()[2].getOutputData() = output; } }; @@ -277,6 +282,243 @@ namespace hex::plugin::builtin { } }; + class NodeCastIntegerToBuffer : public dp::Node { + public: + NodeCastIntegerToBuffer() : Node("Integer to Buffer", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "In"), dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Buffer, "Out") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputInteger = this->getConnectedInputAttribute(0); + if (connectedInputInteger == nullptr) + return; + + connectedInputInteger->getParentNode()->process(dataOverlay); + + std::vector output(sizeof(u64), 0); + + auto &inputData = connectedInputInteger->getOutputData(); + + if (!inputData.empty()) + std::copy(inputData.begin(), inputData.end(), output.begin()); + + this->getAttributes()[1].getOutputData() = output; + } + }; + + class NodeCastBufferToInteger : public dp::Node { + public: + NodeCastBufferToInteger() : Node("Buffer to Integer", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "In"), dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Out") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputBuffer = this->getConnectedInputAttribute(0); + if (connectedInputBuffer == nullptr) + return; + + connectedInputBuffer->getParentNode()->process(dataOverlay); + + std::vector output(sizeof(u64), 0); + + auto &inputData = connectedInputBuffer->getOutputData(); + + if (!inputData.empty()) + std::copy(inputData.begin(), inputData.end(), output.begin()); + + this->getAttributes()[1].getOutputData() = output; + } + }; + + class NodeIf : public dp::Node { + public: + NodeIf() : Node("If", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Condition"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "True"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Buffer, "False"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Buffer, "Output") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputCondition = this->getConnectedInputAttribute(0); + auto connectedInputTrue = this->getConnectedInputAttribute(1); + auto connectedInputFalse = this->getConnectedInputAttribute(2); + if (connectedInputCondition == nullptr || connectedInputTrue == nullptr || connectedInputFalse == nullptr) + return; + + connectedInputCondition->getParentNode()->process(dataOverlay); + connectedInputTrue->getParentNode()->process(dataOverlay); + connectedInputFalse->getParentNode()->process(dataOverlay); + + if (*reinterpret_cast(connectedInputCondition->getOutputData().data()) != 0) + this->getAttributes()[3].getOutputData() = connectedInputTrue->getOutputData(); + else + this->getAttributes()[3].getOutputData() = connectedInputFalse->getOutputData(); + + } + }; + + class NodeEquals : public dp::Node { + public: + NodeEquals() : Node("Equals", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input A"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input B"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Output") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputInputA = this->getConnectedInputAttribute(0); + auto connectedInputInputB = this->getConnectedInputAttribute(1); + if (connectedInputInputA == nullptr || connectedInputInputB == nullptr) + return; + + connectedInputInputA->getParentNode()->process(dataOverlay); + connectedInputInputB->getParentNode()->process(dataOverlay); + + auto &inputA = connectedInputInputA->getOutputData(); + auto &inputB = connectedInputInputB->getOutputData(); + + if (inputA.empty() || inputB.empty()) + return; + + if (*reinterpret_cast(inputA.data()) == *reinterpret_cast(inputB.data())) + this->getAttributes()[2].getOutputData() = hex::toBytes(1); + else + this->getAttributes()[2].getOutputData() = hex::toBytes(0); + + } + }; + + class NodeNot : public dp::Node { + public: + NodeNot() : Node("Not", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Output") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputInput = this->getConnectedInputAttribute(0); + if (connectedInputInput == nullptr) + return; + + connectedInputInput->getParentNode()->process(dataOverlay); + + + auto &input = connectedInputInput->getOutputData(); + if (input.empty()) + return; + + if (*reinterpret_cast(connectedInputInput->getOutputData().data()) == 0) + this->getAttributes()[1].getOutputData() = hex::toBytes(1); + else + this->getAttributes()[1].getOutputData() = hex::toBytes(0); + + } + }; + + class NodeGreaterThan : public dp::Node { + public: + NodeGreaterThan() : Node("Greater Than", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input A"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input B"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Output") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputInputA = this->getConnectedInputAttribute(0); + auto connectedInputInputB = this->getConnectedInputAttribute(1); + if (connectedInputInputA == nullptr || connectedInputInputB == nullptr) + return; + + connectedInputInputA->getParentNode()->process(dataOverlay); + connectedInputInputB->getParentNode()->process(dataOverlay); + + auto &inputA = connectedInputInputA->getOutputData(); + auto &inputB = connectedInputInputB->getOutputData(); + + if (inputA.empty() || inputB.empty()) + return; + + if (*reinterpret_cast(inputA.data()) > *reinterpret_cast(inputB.data())) + this->getAttributes()[2].getOutputData() = hex::toBytes(1); + else + this->getAttributes()[2].getOutputData() = hex::toBytes(0); + + } + }; + + class NodeLessThan : public dp::Node { + public: + NodeLessThan() : Node("Less Than", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input A"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input B"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Output") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputInputA = this->getConnectedInputAttribute(0); + auto connectedInputInputB = this->getConnectedInputAttribute(1); + if (connectedInputInputA == nullptr || connectedInputInputB == nullptr) + return; + + auto &inputA = connectedInputInputA->getOutputData(); + auto &inputB = connectedInputInputB->getOutputData(); + + if (inputA.empty() || inputB.empty()) + return; + + if (*reinterpret_cast(inputA.data()) < *reinterpret_cast(inputB.data())) + this->getAttributes()[2].getOutputData() = hex::toBytes(1); + else + this->getAttributes()[2].getOutputData() = hex::toBytes(0); + + } + }; + + class NodeBoolAND : public dp::Node { + public: + NodeBoolAND() : Node("Boolean AND", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input A"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input B"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Output") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputInputA = this->getConnectedInputAttribute(0); + auto connectedInputInputB = this->getConnectedInputAttribute(1); + if (connectedInputInputA == nullptr || connectedInputInputB == nullptr) + return; + + connectedInputInputA->getParentNode()->process(dataOverlay); + connectedInputInputB->getParentNode()->process(dataOverlay); + + auto &inputA = connectedInputInputA->getOutputData(); + auto &inputB = connectedInputInputB->getOutputData(); + + if (inputA.empty() || inputB.empty()) + return; + + if (*reinterpret_cast(inputA.data()) && *reinterpret_cast(inputB.data())) + this->getAttributes()[2].getOutputData() = hex::toBytes(1); + else + this->getAttributes()[2].getOutputData() = hex::toBytes(0); + + } + }; + + class NodeBoolOR : public dp::Node { + public: + NodeBoolOR() : Node("Boolean OR", { dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input A"), + dp::Attribute(dp::Attribute::IOType::In, dp::Attribute::Type::Integer, "Input B"), + dp::Attribute(dp::Attribute::IOType::Out, dp::Attribute::Type::Integer, "Output") }) {} + + void process(prv::Overlay *dataOverlay) override { + auto connectedInputInputA = this->getConnectedInputAttribute(0); + auto connectedInputInputB = this->getConnectedInputAttribute(1); + if (connectedInputInputA == nullptr || connectedInputInputB == nullptr) + return; + + connectedInputInputA->getParentNode()->process(dataOverlay); + connectedInputInputB->getParentNode()->process(dataOverlay); + + auto &inputA = connectedInputInputA->getOutputData(); + auto &inputB = connectedInputInputB->getOutputData(); + + if (inputA.empty() || inputB.empty()) + return; + + if (*reinterpret_cast(inputA.data()) || *reinterpret_cast(inputB.data())) + this->getAttributes()[2].getOutputData() = hex::toBytes(1); + else + this->getAttributes()[2].getOutputData() = hex::toBytes(0); + + } + }; + void registerDataProcessorNodes() { ContentRegistry::DataProcessorNode::add("Constants", "Integer"); ContentRegistry::DataProcessorNode::add("Constants", "Float"); @@ -288,6 +530,17 @@ namespace hex::plugin::builtin { ContentRegistry::DataProcessorNode::add("Data Access", "Read"); ContentRegistry::DataProcessorNode::add("Data Access", "Write"); + ContentRegistry::DataProcessorNode::add("Casting", "Integer to Buffer"); + ContentRegistry::DataProcessorNode::add("Casting", "Buffer to Integer"); + + ContentRegistry::DataProcessorNode::add("Control Flow", "If"); + ContentRegistry::DataProcessorNode::add("Control Flow", "Equals"); + ContentRegistry::DataProcessorNode::add("Control Flow", "Not"); + ContentRegistry::DataProcessorNode::add("Control Flow", "Greater Than"); + ContentRegistry::DataProcessorNode::add("Control Flow", "Less Than"); + ContentRegistry::DataProcessorNode::add("Control Flow", "AND"); + ContentRegistry::DataProcessorNode::add("Control Flow", "OR"); + ContentRegistry::DataProcessorNode::add("Bitwise Operations", "AND"); ContentRegistry::DataProcessorNode::add("Bitwise Operations", "OR"); ContentRegistry::DataProcessorNode::add("Bitwise Operations", "XOR"); diff --git a/plugins/libimhex/include/hex/helpers/utils.hpp b/plugins/libimhex/include/hex/helpers/utils.hpp index 0bc35075c..771e97d1c 100644 --- a/plugins/libimhex/include/hex/helpers/utils.hpp +++ b/plugins/libimhex/include/hex/helpers/utils.hpp @@ -172,6 +172,14 @@ namespace hex { std::vector readFile(std::string_view path); + template + std::vector toBytes(T value) { + std::vector bytes(sizeof(T)); + std::memcpy(bytes.data(), &value, sizeof(T)); + + return bytes; + } + #define SCOPE_EXIT(func) ScopeExit TOKEN_CONCAT(scopeGuard, __COUNTER__)([&] { func }) class ScopeExit { public: