all repos — mgba @ ff1e5f2de8ba93834cdd73ef1c3f4b9f59f2580b

mGBA Game Boy Advance Emulator

Qt: Memory viewer now supports editing decimal values directly (closes #1705)
Vicki Pfau vi@endrift.com
Sun, 16 Aug 2020 21:06:48 -0700
commit

ff1e5f2de8ba93834cdd73ef1c3f4b9f59f2580b

parent

ffbd0695bb75ee4eae618854b5d37abd00436b7b

4 files changed, 191 insertions(+), 4 deletions(-)

jump to
M CHANGESCHANGES

@@ -62,6 +62,7 @@ - mGUI: Show battery percentage

- Qt: Renderer can be changed while a game is running - Qt: Add hex index to palette view - Qt: Add transformation matrix info to sprite view + - Qt: Memory viewer now supports editing decimal values directly (closes mgba.io/i/1705) - Util: Reset vector size on deinit 0.8.3: (2020-08-03)
M src/platform/qt/MemoryView.cppsrc/platform/qt/MemoryView.cpp

@@ -13,6 +13,97 @@ #include <mgba/core/core.h>

using namespace QGBA; +IntValidator::IntValidator(bool isSigned, QObject* parent) + : QValidator(parent) + , m_signed(isSigned) +{ +} + +QValidator::State IntValidator::validate(QString& input, int&) const { + if (input.isEmpty()) { + return QValidator::Intermediate; + } + if (input.size() == 1 && input[0] == '-') { + if (m_signed) { + return QValidator::Intermediate; + } else { + return QValidator::Invalid; + } + } + if (input[0].isSpace()) { + return QValidator::Invalid; + } + if (input[input.size() - 1].isSpace()) { + return QValidator::Invalid; + } + if (input.size() > 1 && input[0] == '0') { + return QValidator::Invalid; + } + + bool ok = false; + qlonglong val = locale().toLongLong(input, &ok); + if (!ok) { + return QValidator::Invalid; + } + + qlonglong hardmax; + qlonglong hardmin; + qlonglong max; + qlonglong min; + + if (m_signed) { + switch (m_width) { + case 1: + hardmax = 999LL; + hardmin = -999LL; + max = 0x7FLL; + min = -0x80LL; + break; + case 2: + hardmax = 99999LL; + hardmin = -99999LL; + max = 0x7FFFLL; + min = -0x8000LL; + break; + case 4: + hardmax = 9999999999LL; + hardmin = -9999999999LL; + max = 0x7FFFFFFFLL; + min = -0x80000000LL; + break; + default: + return QValidator::Invalid; + } + } else { + hardmin = 0; + min = 0; + + switch (m_width) { + case 1: + hardmax = 999LL; + max = 0xFFLL; + break; + case 2: + hardmax = 99999LL; + max = 0xFFFFLL; + break; + case 4: + hardmax = 9999999999LL; + max = 0xFFFFFFFFLL; + break; + default: + return QValidator::Invalid; + } + } + if (val < hardmin || val > hardmax) { + return QValidator::Invalid; + } + if (val < min || val > max) { + return QValidator::Intermediate; + } + return QValidator::Acceptable; +} + MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* parent) : QWidget(parent) , m_controller(controller)

@@ -20,6 +111,9 @@ {

m_ui.setupUi(this); m_ui.hexfield->setController(controller); + + m_ui.sintVal->setValidator(&m_sintValidator); + m_ui.uintVal->setValidator(&m_uintValidator); mCore* core = m_controller->thread()->core; const mCoreMemoryBlock* info;

@@ -39,9 +133,21 @@ m_ui.regions->addItem(tr(info[i].longName));

} } - connect(m_ui.width8, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(1); }); - connect(m_ui.width16, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(2); }); - connect(m_ui.width32, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(4); }); + connect(m_ui.width8, &QAbstractButton::clicked, [this]() { + m_ui.hexfield->setAlignment(1); + m_sintValidator.setWidth(1); + m_uintValidator.setWidth(1); + }); + connect(m_ui.width16, &QAbstractButton::clicked, [this]() { + m_ui.hexfield->setAlignment(2); + m_sintValidator.setWidth(2); + m_uintValidator.setWidth(2); + }); + connect(m_ui.width32, &QAbstractButton::clicked, [this]() { + m_ui.hexfield->setAlignment(4); + m_sintValidator.setWidth(4); + m_uintValidator.setWidth(4); + }); connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress)); connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);

@@ -60,6 +166,41 @@ connect(m_ui.paste, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::paste);

connect(m_ui.load, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::load); connect(m_ui.loadTBL, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::loadTBL); + + connect(m_ui.sintVal, &QLineEdit::returnPressed, this, [this]() { + int align = m_ui.hexfield->alignment(); + mCore* core = m_controller->thread()->core; + int32_t value = m_ui.sintVal->text().toInt(); + switch (align) { + case 1: + core->rawWrite8(core, m_selection.first, m_ui.segments->value(), value); + break; + case 2: + core->rawWrite16(core, m_selection.first, m_ui.segments->value(), value); + break; + case 4: + core->rawWrite32(core, m_selection.first, m_ui.segments->value(), value); + break; + } + update(); + }); + connect(m_ui.uintVal, &QLineEdit::returnPressed, this, [this]() { + int align = m_ui.hexfield->alignment(); + mCore* core = m_controller->thread()->core; + uint32_t value = m_ui.uintVal->text().toUInt(); + switch (align) { + case 1: + core->rawWrite8(core, m_selection.first, m_ui.segments->value(), value); + break; + case 2: + core->rawWrite16(core, m_selection.first, m_ui.segments->value(), value); + break; + case 4: + core->rawWrite32(core, m_selection.first, m_ui.segments->value(), value); + break; + } + update(); + }); } void MemoryView::setIndex(int index) {

@@ -116,7 +257,9 @@ m_ui.stringVal->setText(text);

if (m_selection.first & (align - 1) || m_selection.second - m_selection.first != align) { m_ui.sintVal->clear(); + m_ui.sintVal->setReadOnly(true); m_ui.uintVal->clear(); + m_ui.uintVal->setReadOnly(true); return; } union {

@@ -144,6 +287,8 @@ m_ui.sintVal->setText(QString::number(value.i32));

m_ui.uintVal->setText(QString::number(value.u32)); break; } + m_ui.sintVal->setReadOnly(false); + m_ui.uintVal->setReadOnly(false); } void MemoryView::saveRange() {

@@ -153,4 +298,4 @@ memdump->setAddress(m_selection.first);

memdump->setSegment(m_ui.segments->value()); memdump->setByteCount(m_selection.second - m_selection.first); memdump->show(); -}+}
M src/platform/qt/MemoryView.hsrc/platform/qt/MemoryView.h

@@ -5,6 +5,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once +#include <QValidator> + #include "MemoryModel.h" #include "ui_MemoryView.h"

@@ -13,6 +15,20 @@ namespace QGBA {

class CoreController; +class IntValidator : public QValidator { +Q_OBJECT + +public: + IntValidator(bool isSigned, QObject* parent = nullptr); + + virtual QValidator::State validate(QString& input, int& pos) const override; + void setWidth(int bytes) { m_width = bytes; } + +private: + int m_width = 1; + bool m_signed; +}; + class MemoryView : public QWidget { Q_OBJECT

@@ -32,6 +48,8 @@ void saveRange();

private: Ui::MemoryView m_ui; + IntValidator m_sintValidator{true}; + IntValidator m_uintValidator{false}; std::shared_ptr<CoreController> m_controller; QPair<uint32_t, uint32_t> m_region;
M src/platform/qt/MemoryView.uisrc/platform/qt/MemoryView.ui

@@ -190,6 +190,9 @@ </widget>

</item> <item> <widget class="QLineEdit" name="uintVal"> + <property name="maxLength"> + <number>10</number> + </property> <property name="readOnly"> <bool>true</bool> </property>

@@ -208,6 +211,9 @@ </widget>

</item> <item> <widget class="QLineEdit" name="sintVal"> + <property name="maxLength"> + <number>11</number> + </property> <property name="readOnly"> <bool>true</bool> </property>

@@ -304,6 +310,23 @@ <header>MemoryModel.h</header>

<container>1</container> </customwidget> </customwidgets> + <tabstops> + <tabstop>regions</tabstop> + <tabstop>segments</tabstop> + <tabstop>setAddress</tabstop> + <tabstop>width8</tabstop> + <tabstop>width16</tabstop> + <tabstop>width32</tabstop> + <tabstop>sintVal</tabstop> + <tabstop>uintVal</tabstop> + <tabstop>stringVal</tabstop> + <tabstop>loadTBL</tabstop> + <tabstop>copy</tabstop> + <tabstop>paste</tabstop> + <tabstop>save</tabstop> + <tabstop>saveRange</tabstop> + <tabstop>load</tabstop> + </tabstops> <resources/> <connections/> </ui>