all repos — mgba @ 55679df8fc49fca3d5f8584d16b90e9bb734a922

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