all repos — mgba @ a75c019fab24f045069cb9a923d02795f4d6f564

mGBA Game Boy Advance Emulator

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

  1/* Copyright (c) 2013-2014 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "GBAApp.h"
  7
  8#include "AudioProcessor.h"
  9#include "Display.h"
 10#include "GameController.h"
 11#include "Window.h"
 12#include "VFileDevice.h"
 13
 14#include <QFileInfo>
 15#include <QFileOpenEvent>
 16#include <QIcon>
 17
 18extern "C" {
 19#include "platform/commandline.h"
 20#include "util/nointro.h"
 21#include "util/socket.h"
 22}
 23
 24using namespace QGBA;
 25
 26static GBAApp* g_app = nullptr;
 27
 28mLOG_DEFINE_CATEGORY(QT, "Qt");
 29
 30GBAApp::GBAApp(int& argc, char* argv[])
 31	: QApplication(argc, argv)
 32	, m_windows{}
 33	, m_db(nullptr)
 34{
 35	g_app = this;
 36
 37#ifdef BUILD_SDL
 38	SDL_Init(SDL_INIT_NOPARACHUTE);
 39#endif
 40
 41#ifndef Q_OS_MAC
 42	setWindowIcon(QIcon(":/res/mgba-1024.png"));
 43#endif
 44
 45	SocketSubsystemInit();
 46	qRegisterMetaType<const uint32_t*>("const uint32_t*");
 47	qRegisterMetaType<mCoreThread*>("mCoreThread*");
 48
 49	QApplication::setApplicationName(projectName);
 50	QApplication::setApplicationVersion(projectVersion);
 51
 52	if (!m_configController.getQtOption("displayDriver").isNull()) {
 53		Display::setDriver(static_cast<Display::Driver>(m_configController.getQtOption("displayDriver").toInt()));
 54	}
 55
 56	mArguments args;
 57	mGraphicsOpts graphicsOpts;
 58	mSubParser subparser;
 59	initParserForGraphics(&subparser, &graphicsOpts);
 60	bool loaded = m_configController.parseArguments(&args, argc, argv, &subparser);
 61	if (loaded && args.showHelp) {
 62		usage(argv[0], subparser.usage);
 63		::exit(0);
 64		return;
 65	}
 66
 67	reloadGameDB();
 68
 69	if (!m_configController.getQtOption("audioDriver").isNull()) {
 70		AudioProcessor::setDriver(static_cast<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt()));
 71	}
 72	Window* w = new Window(&m_configController);
 73	connect(w, &Window::destroyed, [this]() {
 74		m_windows[0] = nullptr;
 75	});
 76	m_windows[0] = w;
 77
 78	if (loaded) {
 79		w->argumentsPassed(&args);
 80	} else {
 81		w->loadConfig();
 82	}
 83	freeArguments(&args);
 84
 85	if (graphicsOpts.multiplier) {
 86		w->resizeFrame(VIDEO_HORIZONTAL_PIXELS * graphicsOpts.multiplier, VIDEO_VERTICAL_PIXELS * graphicsOpts.multiplier);
 87	}
 88	if (graphicsOpts.fullscreen) {
 89		w->enterFullScreen();
 90	}
 91
 92	w->show();
 93
 94	w->controller()->setMultiplayerController(&m_multiplayer);
 95	w->multiplayerChanged();
 96}
 97
 98bool GBAApp::event(QEvent* event) {
 99	if (event->type() == QEvent::FileOpen) {
100		m_windows[0]->controller()->loadGame(static_cast<QFileOpenEvent*>(event)->file());
101		return true;
102	}
103	return QApplication::event(event);
104}
105
106Window* GBAApp::newWindow() {
107	if (m_multiplayer.attached() >= MAX_GBAS) {
108		return nullptr;
109	}
110	Window* w = new Window(&m_configController, m_multiplayer.attached());
111	int windowId = m_multiplayer.attached();
112	connect(w, &Window::destroyed, [this, windowId]() {
113		m_windows[windowId] = nullptr;
114	});
115	m_windows[windowId] = w;
116	w->setAttribute(Qt::WA_DeleteOnClose);
117	w->loadConfig();
118	w->show();
119	w->controller()->setMultiplayerController(&m_multiplayer);
120	w->multiplayerChanged();
121	return w;
122}
123
124GBAApp* GBAApp::app() {
125	return g_app;
126}
127
128void GBAApp::pauseAll(QList<int>* paused) {
129	for (int i = 0; i < MAX_GBAS; ++i) {
130		if (!m_windows[i] || !m_windows[i]->controller()->isLoaded() || m_windows[i]->controller()->isPaused()) {
131			continue;
132		}
133		m_windows[i]->controller()->setPaused(true);
134		paused->append(i);
135	}
136}
137
138void GBAApp::continueAll(const QList<int>* paused) {
139	for (int i : *paused) {
140		m_windows[i]->controller()->setPaused(false);
141	}
142}
143
144QString GBAApp::getOpenFileName(QWidget* owner, const QString& title, const QString& filter) {
145	QList<int> paused;
146	pauseAll(&paused);
147	QString filename = QFileDialog::getOpenFileName(owner, title, m_configController.getQtOption("lastDirectory").toString(), filter);
148	continueAll(&paused);
149	if (!filename.isEmpty()) {
150		m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path());
151	}
152	return filename;
153}
154
155QString GBAApp::getSaveFileName(QWidget* owner, const QString& title, const QString& filter) {
156	QList<int> paused;
157	pauseAll(&paused);
158	QString filename = QFileDialog::getSaveFileName(owner, title, m_configController.getQtOption("lastDirectory").toString(), filter);
159	continueAll(&paused);
160	if (!filename.isEmpty()) {
161		m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path());
162	}
163	return filename;
164}
165
166QString GBAApp::getOpenDirectoryName(QWidget* owner, const QString& title) {
167	QList<int> paused;
168	pauseAll(&paused);
169	QString filename = QFileDialog::getExistingDirectory(owner, title, m_configController.getQtOption("lastDirectory").toString());
170	continueAll(&paused);
171	if (!filename.isEmpty()) {
172		m_configController.setQtOption("lastDirectory", QFileInfo(filename).dir().path());
173	}
174	return filename;
175}
176
177QFileDialog* GBAApp::getOpenFileDialog(QWidget* owner, const QString& title, const QString& filter) {
178	FileDialog* dialog = new FileDialog(this, owner, title, filter);
179	dialog->setAcceptMode(QFileDialog::AcceptOpen);
180	return dialog;
181}
182
183QFileDialog* GBAApp::getSaveFileDialog(QWidget* owner, const QString& title, const QString& filter) {
184	FileDialog* dialog = new FileDialog(this, owner, title, filter);
185	dialog->setAcceptMode(QFileDialog::AcceptSave);
186	return dialog;
187}
188
189QString GBAApp::dataDir() {
190#ifdef DATA_DIR
191	QString path = QString::fromUtf8(DATA_DIR);
192#else
193	QString path = QCoreApplication::applicationDirPath();
194#ifdef Q_OS_MAC
195	path += QLatin1String("/../Resources");
196#endif
197#endif
198	return path;
199}
200
201bool GBAApp::reloadGameDB() {
202	NoIntroDB* db = nullptr;
203	VFile* vf = VFileDevice::open(dataDir() + "/nointro.dat", O_RDONLY);
204	if (vf) {
205		db = NoIntroDBLoad(vf);
206		vf->close(vf);
207	}
208	if (db && m_db) {
209		NoIntroDBDestroy(m_db);
210	}
211	if (db) {
212		m_db = db;
213		return true;
214	}
215	return false;
216}
217
218GBAApp::FileDialog::FileDialog(GBAApp* app, QWidget* parent, const QString& caption, const QString& filter)
219	: QFileDialog(parent, caption, app->m_configController.getQtOption("lastDirectory").toString(), filter)
220	, m_app(app)
221{
222}
223
224int GBAApp::FileDialog::exec() {
225	QList<int> paused;
226	m_app->pauseAll(&paused);
227	bool didAccept = QFileDialog::exec() == QDialog::Accepted;
228	QStringList filenames = selectedFiles();
229	if (!filenames.isEmpty()) {
230		m_app->m_configController.setQtOption("lastDirectory", QFileInfo(filenames[0]).dir().path());
231	}
232	m_app->continueAll(&paused);
233	return didAccept;
234}