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}