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, &GameController::gameStarted, this, &OverrideView::gameStarted);
60 connect(controller, &GameController::gameStopped, this, &OverrideView::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, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides);
71 connect(m_ui.hwAutodetect, &QAbstractButton::clicked, this, &OverrideView::updateOverrides);
72 connect(m_ui.hwRTC, &QAbstractButton::clicked, this, &OverrideView::updateOverrides);
73 connect(m_ui.hwGyro, &QAbstractButton::clicked, this, &OverrideView::updateOverrides);
74 connect(m_ui.hwLight, &QAbstractButton::clicked, this, &OverrideView::updateOverrides);
75 connect(m_ui.hwTilt, &QAbstractButton::clicked, this, &OverrideView::updateOverrides);
76 connect(m_ui.hwRumble, &QAbstractButton::clicked, this, &OverrideView::updateOverrides);
77 connect(m_ui.hwGBPlayer, &QAbstractButton::clicked, this, &OverrideView::updateOverrides);
78
79 connect(m_ui.gbModel, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides);
80 connect(m_ui.mbc, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides);
81
82 connect(m_ui.tabWidget, &QTabWidget::currentChanged, this, &OverrideView::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, &QDialogButtonBox::accepted, this, &OverrideView::saveOverride);
91 connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, &QWidget::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}