all repos — mgba @ 6d12ef81a50c5ff070d2062ef256a6a4187eda86

mGBA Game Boy Advance Emulator

src/platform/qt/Window.cpp (view raw)

  1#include "Window.h"
  2
  3#include <QFileDialog>
  4#include <QKeyEvent>
  5#include <QKeySequence>
  6#include <QMenuBar>
  7
  8#include "GDBWindow.h"
  9#include "GDBController.h"
 10
 11using namespace QGBA;
 12
 13Window::Window(QWidget* parent)
 14	: QMainWindow(parent)
 15	, m_audioThread(nullptr)
 16#ifdef USE_GDB_STUB
 17	, m_gdbController(nullptr)
 18#endif
 19{
 20	setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 21	setMinimumSize(240, 160);
 22
 23	m_controller = new GameController(this);
 24	m_display = new Display();
 25	setCentralWidget(m_display);
 26	connect(m_controller, SIGNAL(gameStarted(GBAThread*)), this, SLOT(gameStarted(GBAThread*)));
 27	connect(m_controller, SIGNAL(gameStopped(GBAThread*)), m_display, SLOT(stopDrawing()));
 28	connect(m_controller, SIGNAL(gameStopped(GBAThread*)), this, SLOT(gameStopped()));
 29	connect(this, SIGNAL(startDrawing(const uint32_t*, GBAThread*)), m_display, SLOT(startDrawing(const uint32_t*, GBAThread*)), Qt::QueuedConnection);
 30	connect(this, SIGNAL(shutdown()), m_display, SLOT(stopDrawing()));
 31
 32	setupMenu(menuBar());
 33}
 34
 35GBAKey Window::mapKey(int qtKey) {
 36	switch (qtKey) {
 37	case Qt::Key_Z:
 38		return GBA_KEY_A;
 39		break;
 40	case Qt::Key_X:
 41		return GBA_KEY_B;
 42		break;
 43	case Qt::Key_A:
 44		return GBA_KEY_L;
 45		break;
 46	case Qt::Key_S:
 47		return GBA_KEY_R;
 48		break;
 49	case Qt::Key_Return:
 50		return GBA_KEY_START;
 51		break;
 52	case Qt::Key_Backspace:
 53		return GBA_KEY_SELECT;
 54		break;
 55	case Qt::Key_Up:
 56		return GBA_KEY_UP;
 57		break;
 58	case Qt::Key_Down:
 59		return GBA_KEY_DOWN;
 60		break;
 61	case Qt::Key_Left:
 62		return GBA_KEY_LEFT;
 63		break;
 64	case Qt::Key_Right:
 65		return GBA_KEY_RIGHT;
 66		break;
 67	default:
 68		return GBA_KEY_NONE;
 69	}
 70}
 71
 72void Window::selectROM() {
 73	QString filename = QFileDialog::getOpenFileName(this, tr("Select ROM"));
 74	if (!filename.isEmpty()) {
 75		m_controller->loadGame(filename);
 76	}
 77}
 78
 79#ifdef USE_GDB_STUB
 80void Window::gdbOpen() {
 81	if (!m_gdbController) {
 82		m_gdbController = new GDBController(m_controller, this);
 83	}
 84	GDBWindow* window = new GDBWindow(m_gdbController);
 85	window->show();
 86}
 87#endif
 88
 89void Window::keyPressEvent(QKeyEvent* event) {
 90	if (event->isAutoRepeat()) {
 91		QWidget::keyPressEvent(event);
 92		return;
 93	}
 94	GBAKey key = mapKey(event->key());
 95	if (key == GBA_KEY_NONE) {
 96		QWidget::keyPressEvent(event);
 97		return;
 98	}
 99	m_controller->keyPressed(key);
100	event->accept();
101}
102
103void Window::keyReleaseEvent(QKeyEvent* event) {
104	if (event->isAutoRepeat()) {
105		QWidget::keyReleaseEvent(event);
106		return;
107	}
108	GBAKey key = mapKey(event->key());
109	if (key == GBA_KEY_NONE) {
110		QWidget::keyPressEvent(event);
111		return;
112	}
113	m_controller->keyReleased(key);
114	event->accept();
115}
116
117void Window::closeEvent(QCloseEvent* event) {
118	emit shutdown();
119	QMainWindow::closeEvent(event);
120}
121
122void Window::gameStarted(GBAThread* context) {
123	emit startDrawing(m_controller->drawContext(), context);
124	foreach (QAction* action, m_gameActions) {
125		action->setDisabled(false);
126	}
127	if (!m_audioThread) {
128		m_audioThread = new AudioThread(this);
129		connect(this, SIGNAL(shutdown()), m_audioThread, SLOT(shutdown()));
130		m_audioThread->setInput(context);
131		m_audioThread->start(QThread::HighPriority);
132	} else {
133		m_audioThread->resume();
134	}
135}
136
137void Window::gameStopped() {
138	foreach (QAction* action, m_gameActions) {
139		action->setDisabled(true);
140	}
141	m_audioThread->pause();
142}
143
144void Window::setupMenu(QMenuBar* menubar) {
145	menubar->clear();
146	QMenu* fileMenu = menubar->addMenu(tr("&File"));
147	fileMenu->addAction(tr("Load &ROM..."), this, SLOT(selectROM()), QKeySequence::Open);
148	fileMenu->addAction(tr("Sh&utdown"), m_controller, SLOT(closeGame()));
149
150	QMenu* emulationMenu = menubar->addMenu(tr("&Emulation"));
151	QAction* pause = new QAction(tr("&Pause"), 0);
152	pause->setChecked(false);
153	pause->setCheckable(true);
154	pause->setShortcut(tr("Ctrl+P"));
155	pause->setDisabled(true);
156	connect(pause, SIGNAL(triggered(bool)), m_controller, SLOT(setPaused(bool)));
157	m_gameActions.append(pause);
158	emulationMenu->addAction(pause);
159
160	QAction* frameAdvance = new QAction(tr("&Next frame"), 0);
161	frameAdvance->setShortcut(tr("Ctrl+N"));
162	frameAdvance->setDisabled(true);
163	connect(frameAdvance, SIGNAL(triggered()), m_controller, SLOT(frameAdvance()));
164	m_gameActions.append(frameAdvance);
165	emulationMenu->addAction(frameAdvance);
166
167	QMenu* debuggingMenu = menubar->addMenu(tr("&Debugging"));
168#ifdef USE_GDB_STUB
169	QAction* gdbWindow = new QAction(tr("Start &GDB server..."), nullptr);
170	connect(gdbWindow, SIGNAL(triggered()), this, SLOT(gdbOpen()));
171	debuggingMenu->addAction(gdbWindow);
172#endif
173}