mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-02 13:01:27 +12:00
Qt: Hex validator for address/instruction inputs (#17113)
This commit is contained in:
parent
79b63556bb
commit
c8f5659090
6 changed files with 91 additions and 14 deletions
|
@ -1458,6 +1458,7 @@
|
|||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\hex_validator.h" />
|
||||
<ClInclude Include="rpcs3qt\movie_item.h" />
|
||||
<ClInclude Include="rpcs3qt\movie_item_base.h" />
|
||||
<ClInclude Include="rpcs3qt\numbered_widget_item.h" />
|
||||
|
|
|
@ -1415,6 +1415,9 @@
|
|||
<ClInclude Include="rpcs3qt\video_label.h">
|
||||
<Filter>Gui\widgets</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\hex_validator.h">
|
||||
<Filter>Gui\utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "call_stack_list.h"
|
||||
#include "input_dialog.h"
|
||||
#include "qt_utils.h"
|
||||
#include "hex_validator.h"
|
||||
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
@ -1404,15 +1405,14 @@ void debugger_frame::ShowGotoAddressDialog()
|
|||
// Address expression input
|
||||
QLineEdit* expression_input(new QLineEdit(m_goto_dialog));
|
||||
expression_input->setFont(m_mono);
|
||||
expression_input->setMaxLength(18);
|
||||
|
||||
if (const auto thread = get_cpu(); !thread || thread->get_class() != thread_class::spu)
|
||||
{
|
||||
expression_input->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,8}$"), this));
|
||||
expression_input->setValidator(new HexValidator(expression_input));
|
||||
}
|
||||
else
|
||||
{
|
||||
expression_input->setValidator(new QRegularExpressionValidator(QRegularExpression("^(0[xX])?0*[a-fA-F0-9]{0,5}$"), this));
|
||||
expression_input->setValidator(new HexValidator(expression_input));
|
||||
}
|
||||
|
||||
// Ok/Cancel
|
||||
|
@ -1451,7 +1451,7 @@ void debugger_frame::ShowGotoAddressDialog()
|
|||
// This also works if no thread is selected and has been selected before
|
||||
if (result == QDialog::Accepted && cpu == get_cpu() && cpu == cpu_check())
|
||||
{
|
||||
PerformGoToRequest(expression_input->text());
|
||||
PerformGoToRequest(normalize_hex_qstring(expression_input->text()));
|
||||
}
|
||||
|
||||
m_goto_dialog = nullptr;
|
||||
|
|
71
rpcs3/rpcs3qt/hex_validator.h
Normal file
71
rpcs3/rpcs3qt/hex_validator.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
#pragma once
|
||||
|
||||
#include <QValidator>
|
||||
#include <QRegularExpression>
|
||||
|
||||
class HexValidator : public QValidator
|
||||
{
|
||||
public:
|
||||
explicit HexValidator(QObject* parent = nullptr, int max_bits = 32)
|
||||
: QValidator(parent)
|
||||
, m_max_bits(max_bits)
|
||||
{}
|
||||
|
||||
State validate(QString& input, int& pos) const override
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
|
||||
QString stripped = input.toLower().remove(' ');
|
||||
|
||||
if (stripped.startsWith("0x"))
|
||||
stripped = stripped.mid(2);
|
||||
|
||||
if (stripped.endsWith("h"))
|
||||
stripped.chop(1);
|
||||
|
||||
if (stripped.isEmpty())
|
||||
return QValidator::Intermediate;
|
||||
|
||||
if (stripped.length() > 16)
|
||||
return QValidator::Invalid;
|
||||
|
||||
static const QRegularExpression hex_re("^[0-9a-f]+$");
|
||||
if (!hex_re.match(stripped).hasMatch())
|
||||
return QValidator::Invalid;
|
||||
|
||||
QString sig = stripped;
|
||||
sig.remove(QRegularExpression("^0+"));
|
||||
const int sig_nibbles = sig.isEmpty() ? 1 : sig.length();
|
||||
if (sig_nibbles > (m_max_bits + 3) / 4)
|
||||
return QValidator::Invalid;
|
||||
|
||||
bool ok = false;
|
||||
const qulonglong value = stripped.toULongLong(&ok, 16);
|
||||
if (!ok)
|
||||
return QValidator::Invalid;
|
||||
|
||||
if (m_max_bits < 64)
|
||||
{
|
||||
const qulonglong max_val = (qulonglong(1) << m_max_bits) - 1;
|
||||
if (value > max_val)
|
||||
return QValidator::Invalid;
|
||||
}
|
||||
|
||||
return QValidator::Acceptable;
|
||||
}
|
||||
|
||||
private:
|
||||
const int m_max_bits;
|
||||
};
|
||||
|
||||
inline QString normalize_hex_qstring(const QString& input)
|
||||
{
|
||||
QString s = input;
|
||||
s.remove(' ');
|
||||
s = s.toLower();
|
||||
if (s.startsWith("0x"))
|
||||
s = s.mid(2);
|
||||
if (s.endsWith('h'))
|
||||
s.chop(1);
|
||||
return s;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include "instruction_editor_dialog.h"
|
||||
#include "hex_validator.h"
|
||||
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
|
@ -44,8 +45,8 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, C
|
|||
|
||||
m_instr = new QLineEdit(this);
|
||||
m_instr->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
m_instr->setMaxLength(8);
|
||||
m_instr->setMaximumWidth(65);
|
||||
m_instr->setValidator(new HexValidator(m_instr));
|
||||
m_instr->setMaximumWidth(130);
|
||||
|
||||
m_disasm->change_mode(cpu_disasm_mode::normal);
|
||||
m_disasm->disasm(m_pc);
|
||||
|
@ -109,7 +110,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, C
|
|||
}
|
||||
|
||||
bool ok;
|
||||
const ulong opcode = m_instr->text().toULong(&ok, 16);
|
||||
const ulong opcode = normalize_hex_qstring(m_instr->text()).toULong(&ok, 16);
|
||||
if (!ok || opcode > u32{umax})
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to parse PPU instruction."));
|
||||
|
@ -152,7 +153,7 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, C
|
|||
void instruction_editor_dialog::updatePreview() const
|
||||
{
|
||||
bool ok;
|
||||
const be_t<u32> opcode{static_cast<u32>(m_instr->text().toULong(&ok, 16))};
|
||||
const be_t<u32> opcode{static_cast<u32>(normalize_hex_qstring(m_instr->text()).toULong(&ok, 16))};
|
||||
m_disasm->change_ptr(reinterpret_cast<const u8*>(&opcode) - std::intptr_t{m_pc});
|
||||
|
||||
if (ok && m_disasm->disasm(m_pc))
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Emu/Memory/vm.h"
|
||||
|
||||
#include "memory_viewer_panel.h"
|
||||
#include "hex_validator.h"
|
||||
|
||||
#include "Emu/Cell/SPUThread.h"
|
||||
#include "Emu/CPU/CPUDisAsm.h"
|
||||
|
@ -94,10 +95,10 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDis
|
|||
m_addr_line = new QLineEdit(this);
|
||||
m_addr_line->setPlaceholderText("00000000");
|
||||
m_addr_line->setFont(mono);
|
||||
m_addr_line->setMaxLength(18);
|
||||
m_addr_line->setFixedWidth(75);
|
||||
m_addr_line->setValidator(new HexValidator(m_addr_line));
|
||||
m_addr_line->setFixedWidth(100);
|
||||
m_addr_line->setFocus();
|
||||
m_addr_line->setValidator(new QRegularExpressionValidator(QRegularExpression(m_type == thread_class::spu ? "^(0[xX])?0*[a-fA-F0-9]{0,5}$" : "^(0[xX])?0*[a-fA-F0-9]{0,8}$"), this));
|
||||
m_addr_line->setAlignment(Qt::AlignCenter);
|
||||
hbox_tools_mem_addr->addWidget(m_addr_line);
|
||||
tools_mem_addr->setLayout(hbox_tools_mem_addr);
|
||||
|
||||
|
@ -287,7 +288,8 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDis
|
|||
QGroupBox* group_search = new QGroupBox(tr("Memory Search"), this);
|
||||
QPushButton* button_collapse_viewer = new QPushButton(reinterpret_cast<const char*>(u8"Ʌ"), group_search);
|
||||
button_collapse_viewer->setFixedWidth(QLabel(button_collapse_viewer->text()).sizeHint().width() * 3);
|
||||
|
||||
button_collapse_viewer->setAutoDefault(false);
|
||||
|
||||
m_search_line = new QLineEdit(group_search);
|
||||
m_search_line->setFixedWidth(QLabel(QString("This is the very length of the lineedit due to hidpi reasons.").chopped(4)).sizeHint().width());
|
||||
m_search_line->setPlaceholderText(tr("Search..."));
|
||||
|
@ -424,8 +426,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDis
|
|||
connect(m_addr_line, &QLineEdit::returnPressed, [this]()
|
||||
{
|
||||
bool ok = false;
|
||||
const QString text = m_addr_line->text();
|
||||
const u32 addr = (text.startsWith("0x", Qt::CaseInsensitive) ? text.right(text.size() - 2) : text).toULong(&ok, 16);
|
||||
const u32 addr = normalize_hex_qstring(m_addr_line->text()).toULong(&ok, 16);
|
||||
if (ok) m_addr = addr;
|
||||
|
||||
scroll(0); // Refresh
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue