mirror of https://github.com/mgba-emu/mgba.git
Add missing GDB classes
This commit is contained in:
parent
412890d838
commit
c621fb16d8
|
@ -0,0 +1,71 @@
|
|||
#include "GDBController.h"
|
||||
|
||||
#include "GameController.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
GDBController::GDBController(GameController* controller, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_gameController(controller)
|
||||
, m_port(2345)
|
||||
, m_bindAddress(0)
|
||||
{
|
||||
GDBStubCreate(&m_gdbStub);
|
||||
}
|
||||
|
||||
ushort GDBController::port() {
|
||||
return m_port;
|
||||
}
|
||||
|
||||
uint32_t GDBController::bindAddress() {
|
||||
return m_bindAddress;
|
||||
}
|
||||
|
||||
bool GDBController::isAttached() {
|
||||
return m_gameController->debugger() == &m_gdbStub.d;
|
||||
}
|
||||
|
||||
void GDBController::setPort(ushort port) {
|
||||
m_port = port;
|
||||
}
|
||||
|
||||
void GDBController::setBindAddress(uint32_t bindAddress) {
|
||||
m_bindAddress = bindAddress;
|
||||
}
|
||||
|
||||
void GDBController::attach() {
|
||||
if (isAttached()) {
|
||||
return;
|
||||
}
|
||||
m_gameController->setDebugger(&m_gdbStub.d);
|
||||
}
|
||||
|
||||
void GDBController::detach() {
|
||||
if (!isAttached()) {
|
||||
return;
|
||||
}
|
||||
bool wasPaused = m_gameController->isPaused();
|
||||
disconnect(m_gameController, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateGDB()));
|
||||
m_gameController->setPaused(true);
|
||||
GDBStubShutdown(&m_gdbStub);
|
||||
m_gameController->setDebugger(nullptr);
|
||||
m_gameController->setPaused(wasPaused);
|
||||
}
|
||||
|
||||
void GDBController::listen() {
|
||||
if (!isAttached()) {
|
||||
attach();
|
||||
}
|
||||
bool wasPaused = m_gameController->isPaused();
|
||||
connect(m_gameController, SIGNAL(frameAvailable(const uint32_t*)), this, SLOT(updateGDB()));
|
||||
m_gameController->setPaused(true);
|
||||
GDBStubListen(&m_gdbStub, m_port, m_bindAddress);
|
||||
m_gameController->setPaused(wasPaused);
|
||||
}
|
||||
|
||||
void GDBController::updateGDB() {
|
||||
bool wasPaused = m_gameController->isPaused();
|
||||
m_gameController->setPaused(true);
|
||||
GDBStubUpdate(&m_gdbStub);
|
||||
m_gameController->setPaused(wasPaused);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef QGBA_GDB_CONTROLLER
|
||||
#define QGBA_GDB_CONTROLLER
|
||||
|
||||
#include <QObject>
|
||||
|
||||
extern "C" {
|
||||
#include "gdb-stub.h"
|
||||
}
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class GameController;
|
||||
|
||||
class GDBController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GDBController(GameController* controller, QObject* parent = nullptr);
|
||||
|
||||
public:
|
||||
ushort port();
|
||||
uint32_t bindAddress();
|
||||
bool isAttached();
|
||||
|
||||
public slots:
|
||||
void setPort(ushort port);
|
||||
void setBindAddress(uint32_t bindAddress);
|
||||
void attach();
|
||||
void detach();
|
||||
void listen();
|
||||
|
||||
private slots:
|
||||
void updateGDB();
|
||||
|
||||
private:
|
||||
GDBStub m_gdbStub;
|
||||
GameController* m_gameController;
|
||||
|
||||
ushort m_port;
|
||||
uint32_t m_bindAddress;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,96 @@
|
|||
#include "GDBWindow.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "GDBController.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
GDBWindow::GDBWindow(GDBController* controller, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_gdbController(controller)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowFullscreenButtonHint);
|
||||
QVBoxLayout* mainSegment = new QVBoxLayout;
|
||||
setLayout(mainSegment);
|
||||
QGroupBox* settings = new QGroupBox(tr("Server settings"));
|
||||
mainSegment->addWidget(settings);
|
||||
|
||||
QGridLayout* settingsGrid = new QGridLayout;
|
||||
settings->setLayout(settingsGrid);
|
||||
|
||||
QLabel* portLabel = new QLabel(tr("Local port"));
|
||||
settingsGrid->addWidget(portLabel, 0, 0, Qt::AlignRight);
|
||||
QLabel* bindAddressLabel = new QLabel(tr("Bind address"));
|
||||
settingsGrid->addWidget(bindAddressLabel, 1, 0, Qt::AlignRight);
|
||||
|
||||
m_portEdit = new QLineEdit("2345");
|
||||
m_portEdit->setMaxLength(5);
|
||||
connect(m_portEdit, SIGNAL(textChanged(const QString&)), this, SLOT(portChanged(const QString&)));
|
||||
settingsGrid->addWidget(m_portEdit, 0, 1, Qt::AlignLeft);
|
||||
|
||||
m_bindAddressEdit = new QLineEdit("0.0.0.0");
|
||||
m_bindAddressEdit->setMaxLength(15);
|
||||
connect(m_bindAddressEdit, SIGNAL(textChanged(const QString&)), this, SLOT(bindAddressChanged(const QString&)));
|
||||
settingsGrid->addWidget(m_bindAddressEdit, 1, 1, Qt::AlignLeft);
|
||||
|
||||
m_startStopButton = new QPushButton(tr("Start"));
|
||||
connect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(listen()));
|
||||
connect(m_startStopButton, SIGNAL(clicked()), this, SLOT(started()));
|
||||
mainSegment->addWidget(m_startStopButton);
|
||||
}
|
||||
|
||||
void GDBWindow::portChanged(const QString& portString) {
|
||||
bool ok = false;
|
||||
ushort port = portString.toUShort(&ok);
|
||||
if (ok) {
|
||||
m_gdbController->setPort(port);
|
||||
}
|
||||
}
|
||||
|
||||
void GDBWindow::bindAddressChanged(const QString& bindAddressString) {
|
||||
bool ok = false;
|
||||
QStringList parts = bindAddressString.split('.');
|
||||
if (parts.length() != 4) {
|
||||
return;
|
||||
}
|
||||
int i;
|
||||
uint32_t address = 0;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
ushort octet = parts[i].toUShort(&ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
if (octet > 0xFF) {
|
||||
return;
|
||||
}
|
||||
address <<= 8;
|
||||
address += octet;
|
||||
}
|
||||
m_gdbController->setBindAddress(address);
|
||||
}
|
||||
|
||||
void GDBWindow::started() {
|
||||
m_portEdit->setEnabled(false);
|
||||
m_bindAddressEdit->setEnabled(false);
|
||||
m_startStopButton->setText(tr("Stop"));
|
||||
disconnect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(listen()));
|
||||
disconnect(m_startStopButton, SIGNAL(clicked()), this, SLOT(started()));
|
||||
connect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(detach()));
|
||||
connect(m_startStopButton, SIGNAL(clicked()), this, SLOT(stopped()));
|
||||
}
|
||||
|
||||
void GDBWindow::stopped() {
|
||||
m_portEdit->setEnabled(true);
|
||||
m_bindAddressEdit->setEnabled(true);
|
||||
m_startStopButton->setText(tr("Start"));
|
||||
disconnect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(detach()));
|
||||
disconnect(m_startStopButton, SIGNAL(clicked()), this, SLOT(stopped()));
|
||||
connect(m_startStopButton, SIGNAL(clicked()), m_gdbController, SLOT(listen()));
|
||||
connect(m_startStopButton, SIGNAL(clicked()), this, SLOT(started()));
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef QGBA_GDB_WINDOW
|
||||
#define QGBA_GDB_WINDOW
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QLineEdit;
|
||||
class QPushButton;
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class GDBController;
|
||||
|
||||
class GDBWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GDBWindow(GDBController* controller, QWidget* parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void portChanged(const QString&);
|
||||
void bindAddressChanged(const QString&);
|
||||
|
||||
void started();
|
||||
void stopped();
|
||||
|
||||
private:
|
||||
GDBController* m_gdbController;
|
||||
|
||||
QLineEdit* m_portEdit;
|
||||
QLineEdit* m_bindAddressEdit;
|
||||
QPushButton* m_startStopButton;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue