Files
archived-Reclass/src/scanner.h
IChooseYou e999c664b8 feat: tree lines, scanner improvements, themes, tooltips, README overhaul
- Tree line connectors (Unicode box-drawing ├─ └─ │) at arbitrary depth
- Fix editor overwriting tree chars at depth 2+ (applyMarginText Pass 2)
- Scanner: unknown value scan, comparison rescan modes (Changed/Unchanged/Increased/Decreased)
- New Tailwind theme (tw.json), WCAG contrast fixes for warm/mid themes
- Tooltip system (rcxtooltip.h)
- Comprehensive README rewrite with full feature inventory
- New tests for compose tree lines, scanner, tooltips

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 09:21:09 -07:00

118 lines
4.0 KiB
C++

#pragma once
#include "providers/provider.h"
#include <QObject>
#include <QByteArray>
#include <QString>
#include <QVector>
#include <QFutureWatcher>
#include <atomic>
#include <memory>
namespace rcx {
// ── Value scan types ──
enum class ValueType {
Int8, Int16, Int32, Int64,
UInt8, UInt16, UInt32, UInt64,
Float, Double,
Vec2, Vec3, Vec4,
UTF8, UTF16,
HexBytes
};
// ── Scan condition (Cheat Engine-style) ──
enum class ScanCondition {
ExactValue, // first scan + rescan: match specific bytes
UnknownValue, // first scan only: capture all aligned addresses
Changed, // rescan: current != previous
Unchanged, // rescan: current == previous
Increased, // rescan: current > previous (numeric)
Decreased // rescan: current < previous (numeric)
};
// ── Scan request / result ──
struct ScanRequest {
QByteArray pattern; // literal bytes to match (empty for UnknownValue)
QByteArray mask; // 0xFF = must match, 0x00 = wildcard
bool filterExecutable = false; // only scan +x regions
bool filterWritable = false; // only scan +w regions
int alignment = 1; // 1 = every byte, 4 = dword, 8 = qword
int maxResults = 50000;
ScanCondition condition = ScanCondition::ExactValue;
int valueSize = 4; // bytes per value (for unknown scans)
uint64_t startAddress = 0; // 0 = no limit (scan all regions)
uint64_t endAddress = 0; // 0 = no limit (scan all regions)
};
struct ScanResult {
uint64_t address;
QString regionModule;
QByteArray scanValue; // cached bytes at scan/update time
QByteArray previousValue; // value before last update
};
// ── Pattern parsing ──
// Parse IDA-style signature string ("48 8B ?? 05") into pattern + mask.
// Returns true on success. On failure, sets errorMsg.
bool parseSignature(const QString& input, QByteArray& pattern, QByteArray& mask,
QString* errorMsg = nullptr);
// Serialize a typed value into raw bytes for exact-match scanning.
// Returns true on success. On failure, sets errorMsg.
bool serializeValue(ValueType type, const QString& input,
QByteArray& pattern, QByteArray& mask,
QString* errorMsg = nullptr);
// Natural alignment for a value type (used as default alignment for value scans).
int naturalAlignment(ValueType type);
// Byte-size for a value type (used for unknown scans and rescan read size).
int valueSizeForType(ValueType type);
// ── Scan engine ──
class ScanEngine : public QObject {
Q_OBJECT
public:
explicit ScanEngine(QObject* parent = nullptr);
void start(std::shared_ptr<Provider> provider, const ScanRequest& req);
void startRescan(std::shared_ptr<Provider> provider,
QVector<ScanResult> results, int readSize,
ScanCondition condition = ScanCondition::ExactValue,
ValueType valueType = ValueType::Int32,
const QByteArray& filterPattern = {},
const QByteArray& filterMask = {});
void abort();
bool isRunning() const;
signals:
void progress(int percent);
void finished(QVector<ScanResult> results);
void rescanFinished(QVector<ScanResult> results);
void error(QString message);
private:
QVector<ScanResult> runScan(std::shared_ptr<Provider> prov, const ScanRequest& req);
QVector<ScanResult> runRescan(std::shared_ptr<Provider> prov,
QVector<ScanResult> results, int readSize,
ScanCondition condition, ValueType valueType,
const QByteArray& filterPattern,
const QByteArray& filterMask);
std::atomic<bool> m_abort{false};
QFutureWatcher<QVector<ScanResult>>* m_watcher = nullptr;
};
} // namespace rcx
Q_DECLARE_METATYPE(QVector<rcx::ScanResult>)