mirror of https://github.com/mgba-emu/mgba.git
Qt: Memory viewer now supports editing decimal values directly (closes #1705)
This commit is contained in:
parent
ffbd0695bb
commit
ff1e5f2de8
1
CHANGES
1
CHANGES
|
@ -62,6 +62,7 @@ Misc:
|
|||
- 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)
|
||||
|
|
|
@ -13,6 +13,97 @@
|
|||
|
||||
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)
|
||||
|
@ -21,6 +112,9 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
|
|||
|
||||
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;
|
||||
size_t nBlocks = core->listMemoryBlocks(core, &info);
|
||||
|
@ -39,9 +133,21 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
|
|||
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 @@ void MemoryView::updateStatus() {
|
|||
|
||||
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 @@ void MemoryView::updateStatus() {
|
|||
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 @@ void MemoryView::saveRange() {
|
|||
memdump->setSegment(m_ui.segments->value());
|
||||
memdump->setByteCount(m_selection.second - m_selection.first);
|
||||
memdump->show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* 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 @@ private slots:
|
|||
|
||||
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;
|
||||
|
|
|
@ -190,6 +190,9 @@
|
|||
</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 @@
|
|||
</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 @@
|
|||
<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>
|
||||
|
|
Loading…
Reference in New Issue