all repos — mgba @ 1a50718c26c6336b77cb119d0b1a4b399a6434e5

mGBA Game Boy Advance Emulator

Qt: Start I/O viewer
Jeffrey Pfau jeffrey@endrift.com
Sat, 10 Oct 2015 20:26:52 -0700
commit

1a50718c26c6336b77cb119d0b1a4b399a6434e5

parent

47eabe1bc78729082e2b65235e99940a51b7ccc7

M CHANGESCHANGES

@@ -1,4 +1,6 @@

0.4.0: (Future) +Features: + - I/O viewer Bugfixes: - Qt: Windows no longer spawn in the top left on first launch - Qt: Fix install path of XDG desktop file with DESTDIR
M src/platform/qt/CMakeLists.txtsrc/platform/qt/CMakeLists.txt

@@ -75,6 +75,7 @@ GIFView.cpp

GameController.cpp GamepadAxisEvent.cpp GamepadButtonEvent.cpp + IOViewer.cpp InputController.cpp InputProfile.cpp KeyEditor.cpp

@@ -101,6 +102,7 @@ qt5_wrap_ui(UI_FILES

AboutScreen.ui CheatsView.ui GIFView.ui + IOViewer.ui LoadSaveState.ui LogView.ui MemoryView.ui
A src/platform/qt/IOViewer.cpp

@@ -0,0 +1,169 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ +#include "IOViewer.h" + +#include "GameController.h" + +#include <QFontDatabase> + +extern "C" { +#include "gba/io.h" +} + +using namespace QGBA; + +IOViewer::IOViewer(GameController* controller, QWidget* parent) + : QDialog(parent) + , m_controller(controller) +{ + m_ui.setupUi(this); + + for (unsigned i = 0; i < REG_MAX >> 1; ++i) { + const char* reg = GBAIORegisterNames[i]; + if (!reg) { + continue; + } + m_ui.regSelect->addItem(QString::asprintf("0x0400%04X: %s", i << 1, reg), i << 1); + } + + const QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont); + m_ui.regValue->setFont(font); + + connect(m_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonPressed(QAbstractButton*))); + connect(m_ui.buttonBox, SIGNAL(rejected()), this, SLOT(close())); + connect(m_ui.regSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(selectRegister())); + + connect(m_ui.b0, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b1, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b2, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b3, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b4, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b5, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b6, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b7, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b8, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.b9, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.bA, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.bB, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.bC, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.bD, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.bE, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + connect(m_ui.bF, SIGNAL(toggled(bool)), this, SLOT(bitFlipped())); + + selectRegister(0); +} + +void IOViewer::update() { + m_value = 0; + m_controller->threadInterrupt(); + if (m_controller->isLoaded()) { + m_value = GBAIORead(m_controller->thread()->gba, m_register); + } + m_controller->threadContinue(); + + m_ui.regValue->setText(QString::asprintf("0x%04X", m_value)); + bool signalsBlocked; + signalsBlocked = m_ui.b0->blockSignals(true); + m_ui.b0->setChecked(m_value & 0x0001 ? Qt::Checked : Qt::Unchecked); + m_ui.b0->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b1->blockSignals(true); + m_ui.b1->setChecked(m_value & 0x0002 ? Qt::Checked : Qt::Unchecked); + m_ui.b1->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b2->blockSignals(true); + m_ui.b2->setChecked(m_value & 0x0004 ? Qt::Checked : Qt::Unchecked); + m_ui.b2->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b3->blockSignals(true); + m_ui.b3->setChecked(m_value & 0x0008 ? Qt::Checked : Qt::Unchecked); + m_ui.b3->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b4->blockSignals(true); + m_ui.b4->setChecked(m_value & 0x0010 ? Qt::Checked : Qt::Unchecked); + m_ui.b4->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b5->blockSignals(true); + m_ui.b5->setChecked(m_value & 0x0020 ? Qt::Checked : Qt::Unchecked); + m_ui.b5->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b6->blockSignals(true); + m_ui.b6->setChecked(m_value & 0x0040 ? Qt::Checked : Qt::Unchecked); + m_ui.b6->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b7->blockSignals(true); + m_ui.b7->setChecked(m_value & 0x0080 ? Qt::Checked : Qt::Unchecked); + m_ui.b7->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b8->blockSignals(true); + m_ui.b8->setChecked(m_value & 0x0100 ? Qt::Checked : Qt::Unchecked); + m_ui.b8->blockSignals(signalsBlocked); + signalsBlocked = m_ui.b9->blockSignals(true); + m_ui.b9->setChecked(m_value & 0x0200 ? Qt::Checked : Qt::Unchecked); + m_ui.b9->blockSignals(signalsBlocked); + signalsBlocked = m_ui.bA->blockSignals(true); + m_ui.bA->setChecked(m_value & 0x0400 ? Qt::Checked : Qt::Unchecked); + m_ui.bA->blockSignals(signalsBlocked); + signalsBlocked = m_ui.bB->blockSignals(true); + m_ui.bB->setChecked(m_value & 0x0800 ? Qt::Checked : Qt::Unchecked); + m_ui.bB->blockSignals(signalsBlocked); + signalsBlocked = m_ui.bC->blockSignals(true); + m_ui.bC->setChecked(m_value & 0x1000 ? Qt::Checked : Qt::Unchecked); + m_ui.bC->blockSignals(signalsBlocked); + signalsBlocked = m_ui.bD->blockSignals(true); + m_ui.bD->setChecked(m_value & 0x2000 ? Qt::Checked : Qt::Unchecked); + m_ui.bD->blockSignals(signalsBlocked); + signalsBlocked = m_ui.bE->blockSignals(true); + m_ui.bE->setChecked(m_value & 0x4000 ? Qt::Checked : Qt::Unchecked); + m_ui.bE->blockSignals(signalsBlocked); + signalsBlocked = m_ui.bF->blockSignals(true); + m_ui.bF->setChecked(m_value & 0x8000 ? Qt::Checked : Qt::Unchecked); + m_ui.bF->blockSignals(signalsBlocked); +} + +void IOViewer::bitFlipped() { + m_value = 0; + m_value |= m_ui.b0->isChecked() << 0x0; + m_value |= m_ui.b1->isChecked() << 0x1; + m_value |= m_ui.b2->isChecked() << 0x2; + m_value |= m_ui.b3->isChecked() << 0x3; + m_value |= m_ui.b4->isChecked() << 0x4; + m_value |= m_ui.b5->isChecked() << 0x5; + m_value |= m_ui.b6->isChecked() << 0x6; + m_value |= m_ui.b7->isChecked() << 0x7; + m_value |= m_ui.b8->isChecked() << 0x8; + m_value |= m_ui.b9->isChecked() << 0x9; + m_value |= m_ui.bA->isChecked() << 0xA; + m_value |= m_ui.bB->isChecked() << 0xB; + m_value |= m_ui.bC->isChecked() << 0xC; + m_value |= m_ui.bD->isChecked() << 0xD; + m_value |= m_ui.bE->isChecked() << 0xE; + m_value |= m_ui.bF->isChecked() << 0xF; + m_ui.regValue->setText(QString::asprintf("0x%04X", m_value)); +} + +void IOViewer::writeback() { + m_controller->threadInterrupt(); + if (m_controller->isLoaded()) { + GBAIOWrite(m_controller->thread()->gba, m_register, m_value); + } + m_controller->threadContinue(); + update(); +} + +void IOViewer::selectRegister(unsigned address) { + m_register = address; + update(); +} + +void IOViewer::selectRegister() { + selectRegister(m_ui.regSelect->currentData().toUInt()); +} + +void IOViewer::buttonPressed(QAbstractButton* button) { + switch (m_ui.buttonBox->standardButton(button)) { + case QDialogButtonBox::Reset: + update(); + break; + case QDialogButtonBox::Apply: + writeback(); + break; + default: + break; + } +}
A src/platform/qt/IOViewer.h

@@ -0,0 +1,44 @@

+/* Copyright (c) 2013-2015 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ +#ifndef QGBA_IOVIEWER +#define QGBA_IOVIEWER + +#include <QDialog> + +#include "ui_IOViewer.h" + +namespace QGBA { + +class GameController; + +class IOViewer : public QDialog { +Q_OBJECT + +public: + IOViewer(GameController* controller, QWidget* parent = nullptr); + +public slots: + void update(); + void selectRegister(unsigned address); + +private slots: + void buttonPressed(QAbstractButton* button); + void bitFlipped(); + void writeback(); + void selectRegister(); + +private: + Ui::IOViewer m_ui; + + unsigned m_register; + uint16_t m_value; + + GameController* m_controller; +}; + +} + +#endif
A src/platform/qt/IOViewer.ui

@@ -0,0 +1,414 @@

+<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>IOViewer</class> + <widget class="QWidget" name="IOViewer"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>343</width> + <height>342</height> + </rect> + </property> + <property name="windowTitle"> + <string>I/O Viewer</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QComboBox" name="regSelect"/> + </item> + <item alignment="Qt::AlignRight|Qt::AlignTop"> + <widget class="QLabel" name="regValue"> + <property name="text"> + <string>0x0000</string> + </property> + </widget> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="12" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b3"/> + </item> + <item row="0" column="11" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b4"/> + </item> + <item row="0" column="13" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b2"/> + </item> + <item row="0" column="15" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b0"/> + </item> + <item row="1" column="13" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l2"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>2</string> + </property> + </widget> + </item> + <item row="0" column="10" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b5"/> + </item> + <item row="0" column="14" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b1"/> + </item> + <item row="1" column="10" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l5"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>5</string> + </property> + </widget> + </item> + <item row="1" column="11" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l4"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>4</string> + </property> + </widget> + </item> + <item row="1" column="8" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l7"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>7</string> + </property> + </widget> + </item> + <item row="1" column="15" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l0"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>0</string> + </property> + </widget> + </item> + <item row="0" column="9" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b6"/> + </item> + <item row="1" column="6" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="l9"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>9</string> + </property> + </widget> + </item> + <item row="0" column="6" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b9"/> + </item> + <item row="1" column="14" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l1"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>1</string> + </property> + </widget> + </item> + <item row="1" column="12" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l3"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>3</string> + </property> + </widget> + </item> + <item row="0" column="0" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="bF"/> + </item> + <item row="1" column="7" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="l8"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>8</string> + </property> + </widget> + </item> + <item row="0" column="2" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="bD"/> + </item> + <item row="0" column="1" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="bE"/> + </item> + <item row="1" column="3" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="lC"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>C</string> + </property> + </widget> + </item> + <item row="1" column="1" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="lE"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>E</string> + </property> + </widget> + </item> + <item row="0" column="3" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="bC"/> + </item> + <item row="0" column="5"> + <widget class="QCheckBox" name="bA"/> + </item> + <item row="1" column="9" alignment="Qt::AlignHCenter|Qt::AlignTop"> + <widget class="QLabel" name="l6"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>6</string> + </property> + </widget> + </item> + <item row="0" column="7" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b8"/> + </item> + <item row="0" column="4" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="bB"/> + </item> + <item row="0" column="8" alignment="Qt::AlignHCenter"> + <widget class="QCheckBox" name="b7"/> + </item> + <item row="1" column="2" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="lD"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>D</string> + </property> + </widget> + </item> + <item row="1" column="0" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="lF"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>F</string> + </property> + </widget> + </item> + <item row="1" column="5" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="lA"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>A</string> + </property> + </widget> + </item> + <item row="1" column="4" alignment="Qt::AlignHCenter"> + <widget class="QLabel" name="lB"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>80</height> + </size> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>B</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Apply|QDialogButtonBox::Close|QDialogButtonBox::Reset</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>regSelect</tabstop> + <tabstop>b0</tabstop> + <tabstop>b1</tabstop> + <tabstop>b2</tabstop> + <tabstop>b3</tabstop> + <tabstop>b4</tabstop> + <tabstop>b5</tabstop> + <tabstop>b6</tabstop> + <tabstop>b7</tabstop> + <tabstop>bE</tabstop> + <tabstop>b8</tabstop> + <tabstop>b9</tabstop> + <tabstop>bA</tabstop> + <tabstop>bB</tabstop> + <tabstop>bC</tabstop> + <tabstop>bD</tabstop> + <tabstop>bF</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -24,6 +24,7 @@ #include "GBAKeyEditor.h"

#include "GDBController.h" #include "GDBWindow.h" #include "GIFView.h" +#include "IOViewer.h" #include "LoadSaveState.h" #include "LogView.h" #include "MultiplayerController.h"

@@ -372,6 +373,11 @@

void Window::openMemoryWindow() { MemoryView* memoryWindow = new MemoryView(m_controller); openView(memoryWindow); +} + +void Window::openIOViewer() { + IOViewer* ioViewer = new IOViewer(m_controller); + openView(ioViewer); } void Window::openAboutScreen() {

@@ -1163,6 +1169,11 @@ QAction* memoryView = new QAction(tr("View memory..."), toolsMenu);

connect(memoryView, SIGNAL(triggered()), this, SLOT(openMemoryWindow())); m_gameActions.append(memoryView); addControlledAction(toolsMenu, memoryView, "memoryView"); + + QAction* ioViewer = new QAction(tr("View &I/O registers..."), toolsMenu); + connect(ioViewer, SIGNAL(triggered()), this, SLOT(openIOViewer())); + m_gameActions.append(ioViewer); + addControlledAction(toolsMenu, ioViewer, "ioViewer"); ConfigOption* skipBios = m_config->addOption("skipBios"); skipBios->connect([this](const QVariant& value) {
M src/platform/qt/Window.hsrc/platform/qt/Window.h

@@ -84,6 +84,7 @@ void openCheatsWindow();

void openPaletteWindow(); void openMemoryWindow(); + void openIOViewer(); void openAboutScreen();