diff --git a/src/controller.cpp b/src/controller.cpp index efcdc12..590e141 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -1226,6 +1226,34 @@ void RcxController::showContextMenu(RcxEditor* editor, int line, int nodeIdx, }); addedQuickConvert = true; } + if (node.kind == NodeKind::Hex64 || node.kind == NodeKind::Pointer64) { + menu.addAction("Change to fnptr64", [this, nodeId]() { + int ni = m_doc->tree.indexOfId(nodeId); + if (ni >= 0) changeNodeKind(ni, NodeKind::FuncPtr64); + }); + addedQuickConvert = true; + } + if (node.kind == NodeKind::Hex32 || node.kind == NodeKind::Pointer32) { + menu.addAction("Change to fnptr32", [this, nodeId]() { + int ni = m_doc->tree.indexOfId(nodeId); + if (ni >= 0) changeNodeKind(ni, NodeKind::FuncPtr32); + }); + addedQuickConvert = true; + } + if (node.kind == NodeKind::FuncPtr64) { + menu.addAction("Change to ptr64", [this, nodeId]() { + int ni = m_doc->tree.indexOfId(nodeId); + if (ni >= 0) changeNodeKind(ni, NodeKind::Pointer64); + }); + addedQuickConvert = true; + } + if (node.kind == NodeKind::FuncPtr32) { + menu.addAction("Change to ptr32", [this, nodeId]() { + int ni = m_doc->tree.indexOfId(nodeId); + if (ni >= 0) changeNodeKind(ni, NodeKind::Pointer32); + }); + addedQuickConvert = true; + } if (addedQuickConvert) menu.addSeparator(); @@ -2182,8 +2210,6 @@ void RcxController::onRefreshTick() { m_readGen = m_refreshGen; auto prov = m_doc->provider; - qDebug() << "[Refresh] reading" << ranges.size() << "ranges from base" - << Qt::hex << prov->base(); m_refreshWatcher->setFuture(QtConcurrent::run([prov, ranges]() -> PageMap { constexpr uint64_t kPageSize = 4096; constexpr uint64_t kPageMask = ~(kPageSize - 1); diff --git a/src/core.h b/src/core.h index 41f8316..b6474c3 100644 --- a/src/core.h +++ b/src/core.h @@ -26,6 +26,7 @@ enum class NodeKind : uint8_t { UInt8, UInt16, UInt32, UInt64, Float, Double, Bool, Pointer32, Pointer64, + FuncPtr32, FuncPtr64, Vec2, Vec3, Vec4, Mat4x4, UTF8, UTF16, Struct, Array @@ -78,6 +79,8 @@ inline constexpr KindMeta kKindMeta[] = { {NodeKind::Bool, "Bool", "bool", 1, 1, 1, KF_None}, {NodeKind::Pointer32, "Pointer32", "ptr32", 4, 1, 4, KF_None}, {NodeKind::Pointer64, "Pointer64", "ptr64", 8, 1, 8, KF_None}, + {NodeKind::FuncPtr32, "FuncPtr32", "fnptr32", 4, 1, 4, KF_None}, + {NodeKind::FuncPtr64, "FuncPtr64", "fnptr64", 8, 1, 8, KF_None}, {NodeKind::Vec2, "Vec2", "vec2", 8, 1, 4, KF_Vector}, {NodeKind::Vec3, "Vec3", "vec3", 12, 1, 4, KF_Vector}, {NodeKind::Vec4, "Vec4", "vec4", 16, 1, 4, KF_Vector}, @@ -136,6 +139,9 @@ inline constexpr bool isVectorKind(NodeKind k) { inline constexpr bool isMatrixKind(NodeKind k) { return k == NodeKind::Mat4x4; } +inline constexpr bool isFuncPtr(NodeKind k) { + return k == NodeKind::FuncPtr32 || k == NodeKind::FuncPtr64; +} inline QStringList allTypeNamesForUI(bool stripBrackets = false) { QStringList out; diff --git a/src/format.cpp b/src/format.cpp index a59ebd1..b548c32 100644 --- a/src/format.cpp +++ b/src/format.cpp @@ -273,6 +273,22 @@ static QString readValueImpl(const Node& node, const Provider& prov, if (!sym.isEmpty()) s += QStringLiteral(" ") + sym; return s; } + case NodeKind::FuncPtr32: { + uint32_t val = prov.readU32(addr); + if (!display) return rawHex(val, 8); + QString s = fmtPointer32(val); + QString sym = prov.getSymbol((uint64_t)val); + if (!sym.isEmpty()) s += QStringLiteral(" ") + sym; + return s; + } + case NodeKind::FuncPtr64: { + uint64_t val = prov.readU64(addr); + if (!display) return rawHex(val, 16); + QString s = fmtPointer64(val); + QString sym = prov.getSymbol(val); + if (!sym.isEmpty()) s += QStringLiteral(" ") + sym; + return s; + } case NodeKind::Vec2: case NodeKind::Vec3: case NodeKind::Vec4: { @@ -543,6 +559,14 @@ QByteArray parseValue(NodeKind kind, const QString& text, bool* ok) { qulonglong val = stripHex(s).toULongLong(ok, 16); return *ok ? toBytes(val) : QByteArray{}; } + case NodeKind::FuncPtr32: { + uint val = stripHex(s).toUInt(ok, 16); + return *ok ? toBytes(val) : QByteArray{}; + } + case NodeKind::FuncPtr64: { + qulonglong val = stripHex(s).toULongLong(ok, 16); + return *ok ? toBytes(val) : QByteArray{}; + } case NodeKind::UTF8: { *ok = true; if (s.startsWith('"') && s.endsWith('"')) @@ -571,7 +595,8 @@ QString validateValue(NodeKind kind, const QString& text) { // For integer/hex types, validate character set first bool isHexKind = (kind >= NodeKind::Hex8 && kind <= NodeKind::Hex64) - || kind == NodeKind::Pointer32 || kind == NodeKind::Pointer64; + || kind == NodeKind::Pointer32 || kind == NodeKind::Pointer64 + || kind == NodeKind::FuncPtr32 || kind == NodeKind::FuncPtr64; bool isIntKind = (kind >= NodeKind::Int8 && kind <= NodeKind::UInt64); if (isHexKind || isIntKind) { diff --git a/src/generator.cpp b/src/generator.cpp index ec2fa6a..67b674d 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -44,6 +44,8 @@ static QString cTypeName(NodeKind kind) { case NodeKind::Bool: return QStringLiteral("bool"); case NodeKind::Pointer32: return QStringLiteral("uint32_t"); case NodeKind::Pointer64: return QStringLiteral("uint64_t"); + case NodeKind::FuncPtr32: return QStringLiteral("uint32_t"); + case NodeKind::FuncPtr64: return QStringLiteral("uint64_t"); case NodeKind::Vec2: return QStringLiteral("float"); case NodeKind::Vec3: return QStringLiteral("float"); case NodeKind::Vec4: return QStringLiteral("float"); @@ -143,6 +145,10 @@ static QString emitField(GenContext& ctx, const Node& node) { } return QStringLiteral(" void* %1;").arg(name) + oc; } + case NodeKind::FuncPtr32: + return QStringLiteral(" void (*%1)();").arg(name) + oc; + case NodeKind::FuncPtr64: + return QStringLiteral(" void (*%1)();").arg(name) + oc; default: return QStringLiteral(" %1 %2;").arg(ctx.cType(node.kind), name) + oc; } diff --git a/src/main.cpp b/src/main.cpp index 22a1f38..a389c37 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -254,7 +254,7 @@ static void applyGlobalTheme(const rcx::Theme& theme) { pal.setColor(QPalette::HighlightedText, theme.text); pal.setColor(QPalette::ToolTipBase, theme.backgroundAlt); pal.setColor(QPalette::ToolTipText, theme.text); - pal.setColor(QPalette::Mid, theme.border); + pal.setColor(QPalette::Mid, theme.hover); pal.setColor(QPalette::Dark, theme.background); pal.setColor(QPalette::Light, theme.textFaint); pal.setColor(QPalette::Link, theme.indHoverSpan);