all repos — mgba @ 61a657afcf031e9d33242d1bb8fbf2028b6a70e6

mGBA Game Boy Advance Emulator

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

  1/* Copyright (c) 2013-2016 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 "OverrideView.h"
  7
  8#include <QPushButton>
  9
 10#include "ConfigController.h"
 11#include "GameController.h"
 12
 13#ifdef M_CORE_GBA
 14#include "GBAOverride.h"
 15#include <mgba/internal/gba/gba.h>
 16#endif
 17
 18#ifdef M_CORE_GB
 19#include "GBOverride.h"
 20#include <mgba/internal/gb/gb.h>
 21#endif
 22
 23using namespace QGBA;
 24
 25#ifdef M_CORE_GB
 26QList<enum GBModel> OverrideView::s_gbModelList;
 27QList<enum GBMemoryBankControllerType> OverrideView::s_mbcList;
 28#endif
 29
 30OverrideView::OverrideView(GameController* controller, ConfigController* config, QWidget* parent)
 31	: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
 32	, m_controller(controller)
 33	, m_config(config)
 34{
 35#ifdef M_CORE_GB
 36	if (s_mbcList.isEmpty()) {
 37		// NB: Keep in sync with OverrideView.ui
 38		s_mbcList.append(GB_MBC_AUTODETECT);
 39		s_mbcList.append(GB_MBC_NONE);
 40		s_mbcList.append(GB_MBC1);
 41		s_mbcList.append(GB_MBC2);
 42		s_mbcList.append(GB_MBC3);
 43		s_mbcList.append(GB_MBC3_RTC);
 44		s_mbcList.append(GB_MBC5);
 45		s_mbcList.append(GB_MBC5_RUMBLE);
 46		s_mbcList.append(GB_MBC7);
 47		s_mbcList.append(GB_HuC3);
 48	}
 49	if (s_gbModelList.isEmpty()) {
 50		// NB: Keep in sync with OverrideView.ui
 51		s_gbModelList.append(GB_MODEL_AUTODETECT);
 52		s_gbModelList.append(GB_MODEL_DMG);
 53		s_gbModelList.append(GB_MODEL_CGB);
 54		s_gbModelList.append(GB_MODEL_AGB);
 55	}
 56#endif
 57	m_ui.setupUi(this);
 58
 59	connect(controller, SIGNAL(gameStarted(mCoreThread*, const QString&)), this, SLOT(gameStarted(mCoreThread*)));
 60	connect(controller, SIGNAL(gameStopped(mCoreThread*)), this, SLOT(gameStopped()));
 61
 62	connect(m_ui.hwAutodetect, &QAbstractButton::toggled, [this] (bool enabled) {
 63		m_ui.hwRTC->setEnabled(!enabled);
 64		m_ui.hwGyro->setEnabled(!enabled);
 65		m_ui.hwLight->setEnabled(!enabled);
 66		m_ui.hwTilt->setEnabled(!enabled);
 67		m_ui.hwRumble->setEnabled(!enabled);
 68	});
 69
 70	connect(m_ui.savetype, SIGNAL(currentIndexChanged(int)), this, SLOT(updateOverrides()));
 71	connect(m_ui.hwAutodetect, SIGNAL(clicked()), this, SLOT(updateOverrides()));
 72	connect(m_ui.hwRTC, SIGNAL(clicked()), this, SLOT(updateOverrides()));
 73	connect(m_ui.hwGyro, SIGNAL(clicked()), this, SLOT(updateOverrides()));
 74	connect(m_ui.hwLight, SIGNAL(clicked()), this, SLOT(updateOverrides()));
 75	connect(m_ui.hwTilt, SIGNAL(clicked()), this, SLOT(updateOverrides()));
 76	connect(m_ui.hwRumble, SIGNAL(clicked()), this, SLOT(updateOverrides()));
 77	connect(m_ui.hwGBPlayer, SIGNAL(clicked()), this, SLOT(updateOverrides()));
 78
 79	connect(m_ui.gbModel, SIGNAL(currentIndexChanged(int)), this, SLOT(updateOverrides()));
 80	connect(m_ui.mbc, SIGNAL(currentIndexChanged(int)), this, SLOT(updateOverrides()));
 81
 82	connect(m_ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateOverrides()));
 83#ifndef M_CORE_GBA
 84	m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.tabGBA));
 85#endif
 86#ifndef M_CORE_GB
 87	m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.tabGB));
 88#endif
 89
 90	connect(m_ui.buttonBox, SIGNAL(accepted()), this, SLOT(saveOverride()));
 91	connect(m_ui.buttonBox, SIGNAL(rejected()), this, SLOT(close()));
 92	m_ui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
 93
 94	if (controller->isLoaded()) {
 95		gameStarted(controller->thread());
 96	}
 97}
 98
 99void OverrideView::saveOverride() {
100	if (!m_config) {
101		return;
102	}
103	m_config->saveOverride(*m_controller->override());
104}
105
106void OverrideView::updateOverrides() {
107#ifdef M_CORE_GBA
108	if (m_ui.tabWidget->currentWidget() == m_ui.tabGBA) {
109		GBAOverride* gba = new GBAOverride;
110		memset(gba->override.id, 0, 4);
111		gba->override.savetype = static_cast<SavedataType>(m_ui.savetype->currentIndex() - 1);
112		gba->override.hardware = HW_NO_OVERRIDE;
113		gba->override.idleLoop = IDLE_LOOP_NONE;
114		gba->override.mirroring = false;
115
116		if (!m_ui.hwAutodetect->isChecked()) {
117			gba->override.hardware = HW_NONE;
118			if (m_ui.hwRTC->isChecked()) {
119				gba->override.hardware |= HW_RTC;
120			}
121			if (m_ui.hwGyro->isChecked()) {
122				gba->override.hardware |= HW_GYRO;
123			}
124			if (m_ui.hwLight->isChecked()) {
125				gba->override.hardware |= HW_LIGHT_SENSOR;
126			}
127			if (m_ui.hwTilt->isChecked()) {
128				gba->override.hardware |= HW_TILT;
129			}
130			if (m_ui.hwRumble->isChecked()) {
131				gba->override.hardware |= HW_RUMBLE;
132			}
133		}
134		if (m_ui.hwGBPlayer->isChecked()) {
135			gba->override.hardware |= HW_GB_PLAYER_DETECTION;
136		}
137
138		bool ok;
139		uint32_t parsedIdleLoop = m_ui.idleLoop->text().toInt(&ok, 16);
140		if (ok) {
141			gba->override.idleLoop = parsedIdleLoop;
142		}
143
144		if (gba->override.savetype != SAVEDATA_AUTODETECT || gba->override.hardware != HW_NO_OVERRIDE ||
145		    gba->override.idleLoop != IDLE_LOOP_NONE) {
146			m_controller->setOverride(gba);
147		} else {
148			m_controller->clearOverride();
149			delete gba;
150		}
151	}
152#endif
153#ifdef M_CORE_GB
154	if (m_ui.tabWidget->currentWidget() == m_ui.tabGB) {
155		GBOverride* gb = new GBOverride;
156		gb->override.mbc = s_mbcList[m_ui.mbc->currentIndex()];
157		gb->override.model = s_gbModelList[m_ui.gbModel->currentIndex()];
158		if (gb->override.mbc != GB_MBC_AUTODETECT || gb->override.model != GB_MODEL_AUTODETECT) {
159			m_controller->setOverride(gb);
160		} else {
161			m_controller->clearOverride();
162			delete gb;
163		}
164	}
165#endif
166}
167
168void OverrideView::gameStarted(mCoreThread* thread) {
169	if (!thread->core) {
170		gameStopped();
171		return;
172	}
173
174	m_ui.tabWidget->setEnabled(false);
175	m_ui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
176
177	switch (thread->core->platform(thread->core)) {
178#ifdef M_CORE_GBA
179	case PLATFORM_GBA: {
180		m_ui.tabWidget->setCurrentWidget(m_ui.tabGBA);
181		GBA* gba = static_cast<GBA*>(thread->core->board);
182		m_ui.savetype->setCurrentIndex(gba->memory.savedata.type + 1);
183		m_ui.hwRTC->setChecked(gba->memory.hw.devices & HW_RTC);
184		m_ui.hwGyro->setChecked(gba->memory.hw.devices & HW_GYRO);
185		m_ui.hwLight->setChecked(gba->memory.hw.devices & HW_LIGHT_SENSOR);
186		m_ui.hwTilt->setChecked(gba->memory.hw.devices & HW_TILT);
187		m_ui.hwRumble->setChecked(gba->memory.hw.devices & HW_RUMBLE);
188		m_ui.hwGBPlayer->setChecked(gba->memory.hw.devices & HW_GB_PLAYER_DETECTION);
189
190		if (gba->idleLoop != IDLE_LOOP_NONE) {
191			m_ui.idleLoop->setText(QString::number(gba->idleLoop, 16));
192		} else {
193			m_ui.idleLoop->clear();
194		}
195		break;
196	}
197#endif
198#ifdef M_CORE_GB
199	case PLATFORM_GB: {
200		m_ui.tabWidget->setCurrentWidget(m_ui.tabGB);
201		GB* gb = static_cast<GB*>(thread->core->board);
202		int mbc = s_mbcList.indexOf(gb->memory.mbcType);
203		if (mbc >= 0) {
204			m_ui.mbc->setCurrentIndex(mbc);
205		} else {
206			m_ui.mbc->setCurrentIndex(0);
207		}
208		int model = s_gbModelList.indexOf(gb->model);
209		if (model >= 0) {
210			m_ui.gbModel->setCurrentIndex(model);
211		} else {
212			m_ui.gbModel->setCurrentIndex(0);
213		}
214		break;
215	}
216#endif
217	case PLATFORM_NONE:
218		break;
219	}
220}
221
222void OverrideView::gameStopped() {
223	m_ui.tabWidget->setEnabled(true);
224	m_ui.savetype->setCurrentIndex(0);
225	m_ui.idleLoop->clear();
226	m_ui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
227
228	m_ui.mbc->setCurrentIndex(0);
229	m_ui.gbModel->setCurrentIndex(0);
230
231	updateOverrides();
232}