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