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: Renderer can be changed while a game is running
|
||||||
- Qt: Add hex index to palette view
|
- Qt: Add hex index to palette view
|
||||||
- Qt: Add transformation matrix info to sprite 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
|
- Util: Reset vector size on deinit
|
||||||
|
|
||||||
0.8.3: (2020-08-03)
|
0.8.3: (2020-08-03)
|
||||||
|
|
|
@ -13,6 +13,97 @@
|
||||||
|
|
||||||
using namespace QGBA;
|
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)
|
MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, m_controller(controller)
|
, m_controller(controller)
|
||||||
|
@ -21,6 +112,9 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
|
||||||
|
|
||||||
m_ui.hexfield->setController(controller);
|
m_ui.hexfield->setController(controller);
|
||||||
|
|
||||||
|
m_ui.sintVal->setValidator(&m_sintValidator);
|
||||||
|
m_ui.uintVal->setValidator(&m_uintValidator);
|
||||||
|
|
||||||
mCore* core = m_controller->thread()->core;
|
mCore* core = m_controller->thread()->core;
|
||||||
const mCoreMemoryBlock* info;
|
const mCoreMemoryBlock* info;
|
||||||
size_t nBlocks = core->listMemoryBlocks(core, &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.width8, &QAbstractButton::clicked, [this]() {
|
||||||
connect(m_ui.width16, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(2); });
|
m_ui.hexfield->setAlignment(1);
|
||||||
connect(m_ui.width32, &QAbstractButton::clicked, [this]() { m_ui.hexfield->setAlignment(4); });
|
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),
|
connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||||
this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress));
|
this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress));
|
||||||
connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);
|
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.load, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::load);
|
||||||
|
|
||||||
connect(m_ui.loadTBL, &QAbstractButton::clicked, m_ui.hexfield, &MemoryModel::loadTBL);
|
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) {
|
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) {
|
if (m_selection.first & (align - 1) || m_selection.second - m_selection.first != align) {
|
||||||
m_ui.sintVal->clear();
|
m_ui.sintVal->clear();
|
||||||
|
m_ui.sintVal->setReadOnly(true);
|
||||||
m_ui.uintVal->clear();
|
m_ui.uintVal->clear();
|
||||||
|
m_ui.uintVal->setReadOnly(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
union {
|
union {
|
||||||
|
@ -144,6 +287,8 @@ void MemoryView::updateStatus() {
|
||||||
m_ui.uintVal->setText(QString::number(value.u32));
|
m_ui.uintVal->setText(QString::number(value.u32));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
m_ui.sintVal->setReadOnly(false);
|
||||||
|
m_ui.uintVal->setReadOnly(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryView::saveRange() {
|
void MemoryView::saveRange() {
|
||||||
|
@ -153,4 +298,4 @@ void MemoryView::saveRange() {
|
||||||
memdump->setSegment(m_ui.segments->value());
|
memdump->setSegment(m_ui.segments->value());
|
||||||
memdump->setByteCount(m_selection.second - m_selection.first);
|
memdump->setByteCount(m_selection.second - m_selection.first);
|
||||||
memdump->show();
|
memdump->show();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QValidator>
|
||||||
|
|
||||||
#include "MemoryModel.h"
|
#include "MemoryModel.h"
|
||||||
|
|
||||||
#include "ui_MemoryView.h"
|
#include "ui_MemoryView.h"
|
||||||
|
@ -13,6 +15,20 @@ namespace QGBA {
|
||||||
|
|
||||||
class CoreController;
|
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 {
|
class MemoryView : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -32,6 +48,8 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MemoryView m_ui;
|
Ui::MemoryView m_ui;
|
||||||
|
IntValidator m_sintValidator{true};
|
||||||
|
IntValidator m_uintValidator{false};
|
||||||
|
|
||||||
std::shared_ptr<CoreController> m_controller;
|
std::shared_ptr<CoreController> m_controller;
|
||||||
QPair<uint32_t, uint32_t> m_region;
|
QPair<uint32_t, uint32_t> m_region;
|
||||||
|
|
|
@ -190,6 +190,9 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="uintVal">
|
<widget class="QLineEdit" name="uintVal">
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -208,6 +211,9 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="sintVal">
|
<widget class="QLineEdit" name="sintVal">
|
||||||
|
<property name="maxLength">
|
||||||
|
<number>11</number>
|
||||||
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
@ -304,6 +310,23 @@
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</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/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
Loading…
Reference in New Issue