Qt: Fix issues with I/O viewer not properly synchronizing state

This commit is contained in:
Vicki Pfau 2020-12-12 23:42:13 -08:00
parent 672422d246
commit 6e40b38b63
3 changed files with 24 additions and 27 deletions

View File

@ -80,6 +80,7 @@ Other fixes:
- Qt: Pre-attach GDB stub when launching with -g (fixes mgba.io/i/1950) - Qt: Pre-attach GDB stub when launching with -g (fixes mgba.io/i/1950)
- Qt: Fix crash when editing shortcuts with none selected (fixes mgba.io/i/1964) - Qt: Fix crash when editing shortcuts with none selected (fixes mgba.io/i/1964)
- Qt: Fix crashing when no OpenGL context can be obtained - Qt: Fix crashing when no OpenGL context can be obtained
- Qt: Fix issues with I/O viewer not properly synchronizing state
- SM83: Simplify register pair access on big endian - SM83: Simplify register pair access on big endian
- SM83: Disassemble STOP as one byte - SM83: Disassemble STOP as one byte
- Wii: Fix crash on unloading irregularly sized GBA ROMs - Wii: Fix crash on unloading irregularly sized GBA ROMs

View File

@ -1072,17 +1072,16 @@ IOViewer::IOViewer(std::shared_ptr<CoreController> controller, QWidget* parent)
} }
void IOViewer::updateRegister() { void IOViewer::updateRegister() {
m_value = 0;
uint16_t value = 0;
{ {
CoreController::Interrupter interrupter(m_controller); CoreController::Interrupter interrupter(m_controller);
value = GBAView16(static_cast<ARMCore*>(m_controller->thread()->core->cpu), BASE_IO | m_register); m_value = GBAView16(static_cast<ARMCore*>(m_controller->thread()->core->cpu), BASE_IO | m_register);
} }
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 16; ++i) {
m_b[i]->setChecked(value & (1 << i)); QSignalBlocker blocker(m_b[i]);
m_b[i]->setChecked(m_value & (1 << i));
} }
m_value = value; m_ui.regValue->setText("0x" + QString("%1").arg(m_value, 4, 16, QChar('0')).toUpper());
emit valueChanged(); emit valueChanged();
} }
@ -1103,7 +1102,7 @@ void IOViewer::writeback() {
updateRegister(); updateRegister();
} }
void IOViewer::selectRegister(unsigned address) { void IOViewer::selectRegister(int address) {
m_register = address; m_register = address;
QGridLayout* box = static_cast<QGridLayout*>(m_ui.regDescription->layout()); QGridLayout* box = static_cast<QGridLayout*>(m_ui.regDescription->layout());
if (box) { if (box) {
@ -1130,7 +1129,10 @@ void IOViewer::selectRegister(unsigned address) {
check->setEnabled(!ri.readonly); check->setEnabled(!ri.readonly);
box->addWidget(check, i, 1, Qt::AlignRight); box->addWidget(check, i, 1, Qt::AlignRight);
connect(check, &QAbstractButton::toggled, m_b[ri.start], &QAbstractButton::setChecked); connect(check, &QAbstractButton::toggled, m_b[ri.start], &QAbstractButton::setChecked);
connect(m_b[ri.start], &QAbstractButton::toggled, check, &QAbstractButton::setChecked); connect(this, &IOViewer::valueChanged, check, [check, this, &ri] {
QSignalBlocker blocker(check);
check->setChecked(bool(m_value & (1 << ri.start)));
});
} else if (ri.items.empty()) { } else if (ri.items.empty()) {
QSpinBox* sbox = new QSpinBox; QSpinBox* sbox = new QSpinBox;
sbox->setEnabled(!ri.readonly); sbox->setEnabled(!ri.readonly);
@ -1140,20 +1142,16 @@ void IOViewer::selectRegister(unsigned address) {
connect(sbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [sbox, this, &ri](int v) { connect(sbox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [sbox, this, &ri](int v) {
for (int o = 0; o < ri.size; ++o) { for (int o = 0; o < ri.size; ++o) {
bool signalsBlocked = m_b[o + ri.start]->blockSignals(true); QSignalBlocker blocker(m_b[o + ri.start]);
m_b[o + ri.start]->setChecked(v & (1 << o)); m_b[o + ri.start]->setChecked(v & (1 << o));
m_b[o + ri.start]->blockSignals(signalsBlocked);
} }
bitFlipped();
}); });
auto connection = connect(this, &IOViewer::valueChanged, [sbox, &ri, this]() { connect(this, &IOViewer::valueChanged, sbox, [sbox, this, &ri]() {
QSignalBlocker blocker(sbox);
int v = (m_value >> ri.start) & ((1 << ri.size) - 1); int v = (m_value >> ri.start) & ((1 << ri.size) - 1);
bool signalsBlocked = sbox->blockSignals(true);
sbox->setValue(v); sbox->setValue(v);
sbox->blockSignals(signalsBlocked);
});
connect(sbox, &QObject::destroyed, [connection, this]() {
this->disconnect(connection);
}); });
} else { } else {
QComboBox* cbox = new QComboBox; QComboBox* cbox = new QComboBox;
@ -1170,24 +1168,22 @@ void IOViewer::selectRegister(unsigned address) {
connect(cbox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [cbox, this, &ri](int index) { connect(cbox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [cbox, this, &ri](int index) {
unsigned v = cbox->itemData(index).toUInt(); unsigned v = cbox->itemData(index).toUInt();
for (int o = 0; o < ri.size; ++o) { for (int o = 0; o < ri.size; ++o) {
bool signalsBlocked = m_b[o + ri.start]->blockSignals(true); QSignalBlocker blocker(m_b[o + ri.start]);
m_b[o + ri.start]->setChecked(v & (1 << o)); m_b[o + ri.start]->setChecked(v & (1 << o));
m_b[o + ri.start]->blockSignals(signalsBlocked);
} }
bitFlipped();
}); });
auto connection = connect(this, &IOViewer::valueChanged, [cbox, this, &ri]() { connect(this, &IOViewer::valueChanged, cbox, [cbox, this, &ri]() {
QSignalBlocker blocker(cbox);
unsigned v = (m_value >> ri.start) & ((1 << ri.size) - 1); unsigned v = (m_value >> ri.start) & ((1 << ri.size) - 1);
for (int i = 0; i < 1 << ri.size; ++i) { for (int i = 0; i < 1 << ri.size; ++i) {
if (cbox->itemData(i) == v) { if (cbox->itemData(i) == v) {
cbox->setCurrentIndex(i); cbox->setCurrentIndex(i);
break;
} }
} }
}); });
connect(cbox, &QObject::destroyed, [connection, this]() {
this->disconnect(connection);
});
} }
++i; ++i;
} }

View File

@ -21,19 +21,19 @@ Q_OBJECT
public: public:
struct RegisterItem { struct RegisterItem {
RegisterItem(const QString& description, uint start, uint size = 1, bool readonly = false) RegisterItem(const QString& description, uint start, int size = 1, bool readonly = false)
: start(start) : start(start)
, size(size) , size(size)
, readonly(readonly) , readonly(readonly)
, description(description) {} , description(description) {}
RegisterItem(const QString& description, uint start, uint size, QStringList items, bool readonly = false) RegisterItem(const QString& description, uint start, int size, QStringList items, bool readonly = false)
: start(start) : start(start)
, size(size) , size(size)
, readonly(readonly) , readonly(readonly)
, description(description) , description(description)
, items(items) {} , items(items) {}
uint start; uint start;
uint size; int size;
bool readonly; bool readonly;
QString description; QString description;
QStringList items; QStringList items;
@ -49,7 +49,7 @@ signals:
public slots: public slots:
void updateRegister(); void updateRegister();
void selectRegister(unsigned address); void selectRegister(int address);
private slots: private slots:
void buttonPressed(QAbstractButton* button); void buttonPressed(QAbstractButton* button);
@ -61,7 +61,7 @@ private:
static QList<RegisterDescription> s_registers; static QList<RegisterDescription> s_registers;
Ui::IOViewer m_ui; Ui::IOViewer m_ui;
unsigned m_register; int m_register;
uint16_t m_value; uint16_t m_value;
QCheckBox* m_b[16]; QCheckBox* m_b[16];