all repos — mgba @ 742538dc432a3d85b66318eded435a73dfce0f5c

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