Qt: Start I/O viewer

This commit is contained in:
Jeffrey Pfau 2015-10-10 20:26:52 -07:00
parent 47eabe1bc7
commit 1a50718c26
7 changed files with 643 additions and 0 deletions

View File

@ -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

View File

@ -75,6 +75,7 @@ set(SOURCE_FILES
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

View File

@ -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;
}
}

View File

@ -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

414
src/platform/qt/IOViewer.ui Normal file
View File

@ -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>

View File

@ -24,6 +24,7 @@
#include "GDBController.h"
#include "GDBWindow.h"
#include "GIFView.h"
#include "IOViewer.h"
#include "LoadSaveState.h"
#include "LogView.h"
#include "MultiplayerController.h"
@ -374,6 +375,11 @@ void Window::openMemoryWindow() {
openView(memoryWindow);
}
void Window::openIOViewer() {
IOViewer* ioViewer = new IOViewer(m_controller);
openView(ioViewer);
}
void Window::openAboutScreen() {
AboutScreen* about = new AboutScreen();
openView(about);
@ -1164,6 +1170,11 @@ void Window::setupMenu(QMenuBar* menubar) {
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_controller->setSkipBIOS(value.toBool());

View File

@ -84,6 +84,7 @@ public slots:
void openPaletteWindow();
void openMemoryWindow();
void openIOViewer();
void openAboutScreen();