all repos — mgba @ f33e9c060f89e68d9501d0c2c548e571bdafc5f1

mGBA Game Boy Advance Emulator

Qt: Configurable game overrides for Game Pak devices
Jeffrey Pfau jeffrey@endrift.com
Sun, 25 Jan 2015 15:21:48 -0800
commit

f33e9c060f89e68d9501d0c2c548e571bdafc5f1

parent

f4fcdf35d4d88616a3bda9bce7384df0e83a6964

M src/gba/gba-gpio.csrc/gba/gba-gpio.c

@@ -38,9 +38,13 @@ 0 // Empty

}; void GBAGPIOInit(struct GBACartridgeGPIO* gpio, uint16_t* base) { + gpio->gpioBase = base; + GBAGPIOClear(gpio); +} + +void GBAGPIOClear(struct GBACartridgeGPIO* gpio) { gpio->gpioDevices = GPIO_NONE; gpio->direction = GPIO_WRITE_ONLY; - gpio->gpioBase = base; gpio->pinState = 0; gpio->direction = 0; }
M src/gba/gba-gpio.hsrc/gba/gba-gpio.h

@@ -11,6 +11,7 @@

#define IS_GPIO_REGISTER(reg) ((reg) == GPIO_REG_DATA || (reg) == GPIO_REG_DIRECTION || (reg) == GPIO_REG_CONTROL) enum GPIODevice { + GPIO_NO_OVERRIDE = 0x8000, GPIO_NONE = 0, GPIO_RTC = 1, GPIO_RUMBLE = 2,

@@ -114,6 +115,7 @@ int tiltState;

}; void GBAGPIOInit(struct GBACartridgeGPIO* gpio, uint16_t* gpioBase); +void GBAGPIOClear(struct GBACartridgeGPIO* gpio); void GBAGPIOWrite(struct GBACartridgeGPIO* gpio, uint32_t address, uint16_t value); void GBAGPIOInitRTC(struct GBACartridgeGPIO* gpio);
M src/gba/gba-overrides.csrc/gba/gba-overrides.c

@@ -173,27 +173,35 @@ return found;

} void GBAOverrideApply(struct GBA* gba, const struct GBACartridgeOverride* override) { - GBASavedataForceType(&gba->memory.savedata, override->savetype); - - if (override->hardware & GPIO_RTC) { - GBAGPIOInitRTC(&gba->memory.gpio); + if (override->savetype != SAVEDATA_AUTODETECT) { + GBASavedataForceType(&gba->memory.savedata, override->savetype); } - if (override->hardware & GPIO_GYRO) { - GBAGPIOInitGyro(&gba->memory.gpio); - } + if (override->hardware != GPIO_NO_OVERRIDE) { + GBAGPIOClear(&gba->memory.gpio); - if (override->hardware & GPIO_RUMBLE) { - GBAGPIOInitRumble(&gba->memory.gpio); - } + if (override->hardware & GPIO_RTC) { + GBAGPIOInitRTC(&gba->memory.gpio); + } - if (override->hardware & GPIO_LIGHT_SENSOR) { - GBAGPIOInitLightSensor(&gba->memory.gpio); - } + if (override->hardware & GPIO_GYRO) { + GBAGPIOInitGyro(&gba->memory.gpio); + } - if (override->hardware & GPIO_TILT) { - GBAGPIOInitTilt(&gba->memory.gpio); + if (override->hardware & GPIO_RUMBLE) { + GBAGPIOInitRumble(&gba->memory.gpio); + } + + if (override->hardware & GPIO_LIGHT_SENSOR) { + GBAGPIOInitLightSensor(&gba->memory.gpio); + } + + if (override->hardware & GPIO_TILT) { + GBAGPIOInitTilt(&gba->memory.gpio); + } } - gba->busyLoop = override->idleLoop; + if (override->idleLoop != 0xFFFFFFFF) { + gba->busyLoop = override->idleLoop; + } }
M src/gba/gba-savedata.csrc/gba/gba-savedata.c

@@ -113,6 +113,11 @@ return true;

} void GBASavedataForceType(struct GBASavedata* savedata, enum SavedataType type) { + if (savedata->type != SAVEDATA_AUTODETECT) { + struct VFile* vf = savedata->vf; + GBASavedataDeinit(savedata); + GBASavedataInit(savedata, vf); + } switch (type) { case SAVEDATA_FLASH512: case SAVEDATA_FLASH1M:
M src/gba/gba-thread.csrc/gba/gba-thread.c

@@ -8,7 +8,6 @@

#include "arm.h" #include "gba.h" #include "gba-config.h" -#include "gba-overrides.h" #include "gba-serialize.h" #include "debugger/debugger.h"

@@ -145,6 +144,9 @@ const struct GBACartridge* cart = (const struct GBACartridge*) gba.memory.rom;

memcpy(override.id, &cart->id, sizeof(override.id)); if (GBAOverrideFind(threadContext->overrides, &override)) { GBAOverrideApply(&gba, &override); + } + if (threadContext->hasOverride) { + GBAOverrideApply(&gba, &threadContext->override); } if (threadContext->bios && GBAIsBIOS(threadContext->bios)) {
M src/gba/gba-thread.hsrc/gba/gba-thread.h

@@ -10,6 +10,7 @@ #include "util/common.h"

#include "gba.h" #include "gba-input.h" +#include "gba-overrides.h" #include "util/threading.h"

@@ -71,6 +72,9 @@ const char* fname;

int activeKeys; struct GBAAVStream* stream; struct Configuration* overrides; + + bool hasOverride; + struct GBACartridgeOverride override; // Run-time options int frameskip;
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -140,6 +140,11 @@ delete m_renderer;

delete[] m_drawContext; } +void GameController::setOverride(const GBACartridgeOverride& override) { + m_threadContext.override = override; + m_threadContext.hasOverride = true; +} + #ifdef USE_GDB_STUB ARMDebugger* GameController::debugger() { return m_threadContext.debugger;
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -56,6 +56,9 @@

void setInputController(InputController* controller) { m_inputController = controller; } void setOverrides(Configuration* overrides) { m_threadContext.overrides = overrides; } + void setOverride(const GBACartridgeOverride& override); + void clearOverride() { m_threadContext.hasOverride = false; } + #ifdef USE_GDB_STUB ARMDebugger* debugger(); void setDebugger(ARMDebugger*);
M src/platform/qt/GamePakView.cppsrc/platform/qt/GamePakView.cpp

@@ -38,46 +38,99 @@ connect(m_ui.timeNow, &QPushButton::clicked, [controller, this] () {

m_ui.time->setDateTime(QDateTime::currentDateTime()); }); + connect(m_ui.hwAutodetect, &QAbstractButton::toggled, [this] (bool enabled) { + m_ui.hwRTC->setEnabled(!enabled); + m_ui.hwGyro->setEnabled(!enabled); + m_ui.hwLight->setEnabled(!enabled); + m_ui.hwTilt->setEnabled(!enabled); + m_ui.hwRumble->setEnabled(!enabled); + }); + + connect(m_ui.savetype, SIGNAL(currentIndexChanged(int)), this, SLOT(updateOverrides())); + connect(m_ui.hwAutodetect, SIGNAL(clicked()), this, SLOT(updateOverrides())); + connect(m_ui.hwRTC, SIGNAL(clicked()), this, SLOT(updateOverrides())); + connect(m_ui.hwGyro, SIGNAL(clicked()), this, SLOT(updateOverrides())); + connect(m_ui.hwLight, SIGNAL(clicked()), this, SLOT(updateOverrides())); + connect(m_ui.hwTilt, SIGNAL(clicked()), this, SLOT(updateOverrides())); + connect(m_ui.hwRumble, SIGNAL(clicked()), this, SLOT(updateOverrides())); + if (controller->isLoaded()) { gameStarted(controller->thread()); } } +void GamePakView::updateOverrides() { + GBACartridgeOverride override = { + "", + static_cast<SavedataType>(m_ui.savetype->currentIndex() - 1), + GPIO_NO_OVERRIDE, + 0xFFFFFFFF + }; + + if (!m_ui.hwAutodetect->isChecked()) { + override.hardware = GPIO_NONE; + if (m_ui.hwRTC->isChecked()) { + override.hardware |= GPIO_RTC; + } + if (m_ui.hwGyro->isChecked()) { + override.hardware |= GPIO_GYRO; + } + if (m_ui.hwLight->isChecked()) { + override.hardware |= GPIO_LIGHT_SENSOR; + } + if (m_ui.hwTilt->isChecked()) { + override.hardware |= GPIO_TILT; + } + if (m_ui.hwRumble->isChecked()) { + override.hardware |= GPIO_RUMBLE; + } + } + + if (override.savetype != SAVEDATA_AUTODETECT || override.hardware != GPIO_NO_OVERRIDE) { + m_controller->setOverride(override); + } else { + m_controller->clearOverride(); + } +} + void GamePakView::gameStarted(GBAThread* thread) { if (!thread->gba) { gameStopped(); return; } - SavedataType savetype = thread->gba->memory.savedata.type; - if (m_ui.savetype->currentIndex() > 0) { - if (savetype > SAVEDATA_FORCE_NONE) { - VFile* vf = thread->gba->memory.savedata.vf; - GBASavedataDeinit(&thread->gba->memory.savedata); - GBASavedataInit(&thread->gba->memory.savedata, vf); - } - savetype = static_cast<SavedataType>(m_ui.savetype->currentIndex() - 1); - GBASavedataForceType(&thread->gba->memory.savedata, savetype); - } - - if (savetype > SAVEDATA_AUTODETECT) { - m_ui.savetype->setCurrentIndex(savetype + 1); - } + m_ui.savetype->setCurrentIndex(thread->gba->memory.savedata.type + 1); m_ui.savetype->setEnabled(false); - m_ui.sensorRTC->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_RTC); - m_ui.sensorGyro->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_GYRO); - m_ui.sensorLight->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_LIGHT_SENSOR); - m_ui.sensorTilt->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_TILT); + m_ui.hwAutodetect->setEnabled(false); + m_ui.hwRTC->setEnabled(false); + m_ui.hwGyro->setEnabled(false); + m_ui.hwLight->setEnabled(false); + m_ui.hwTilt->setEnabled(false); + m_ui.hwRumble->setEnabled(false); + + m_ui.hwRTC->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_RTC); + m_ui.hwGyro->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_GYRO); + m_ui.hwLight->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_LIGHT_SENSOR); + m_ui.hwTilt->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_TILT); + m_ui.hwRumble->setChecked(thread->gba->memory.gpio.gpioDevices & GPIO_RUMBLE); } void GamePakView::gameStopped() { m_ui.savetype->setCurrentIndex(0); m_ui.savetype->setEnabled(true); - m_ui.sensorRTC->setChecked(false); - m_ui.sensorGyro->setChecked(false); - m_ui.sensorLight->setChecked(false); - m_ui.sensorTilt->setChecked(false); + m_ui.hwAutodetect->setEnabled(true); + m_ui.hwRTC->setEnabled(!m_ui.hwAutodetect->isChecked()); + m_ui.hwGyro->setEnabled(!m_ui.hwAutodetect->isChecked()); + m_ui.hwLight->setEnabled(!m_ui.hwAutodetect->isChecked()); + m_ui.hwTilt->setEnabled(!m_ui.hwAutodetect->isChecked()); + m_ui.hwRumble->setEnabled(!m_ui.hwAutodetect->isChecked()); + + m_ui.hwRTC->setChecked(false); + m_ui.hwGyro->setChecked(false); + m_ui.hwLight->setChecked(false); + m_ui.hwTilt->setChecked(false); + m_ui.hwRumble->setChecked(false); } void GamePakView::setLuminanceValue(int value) {
M src/platform/qt/GamePakView.hsrc/platform/qt/GamePakView.h

@@ -23,6 +23,7 @@ public:

GamePakView(GameController* controller, QWidget* parent = nullptr); private slots: + void updateOverrides(); void gameStarted(GBAThread*); void gameStopped(); void setLuminanceValue(int);
M src/platform/qt/GamePakView.uisrc/platform/qt/GamePakView.ui

@@ -6,8 +6,8 @@ <property name="geometry">

<rect> <x>0</x> <y>0</y> - <width>259</width> - <height>373</height> + <width>251</width> + <height>391</height> </rect> </property> <property name="sizePolicy">

@@ -39,15 +39,12 @@ </item>

<item row="2" column="0"> <widget class="QLabel" name="label_2"> <property name="text"> - <string>Sensors</string> + <string>Hardware</string> </property> </widget> </item> <item row="2" column="1"> - <widget class="QCheckBox" name="sensorAutodetect"> - <property name="enabled"> - <bool>false</bool> - </property> + <widget class="QCheckBox" name="hwAutodetect"> <property name="text"> <string>Autodetect</string> </property>

@@ -57,7 +54,7 @@ </property>

</widget> </item> <item row="3" column="1"> - <widget class="QCheckBox" name="sensorRTC"> + <widget class="QCheckBox" name="hwRTC"> <property name="enabled"> <bool>false</bool> </property>

@@ -67,7 +64,7 @@ </property>

</widget> </item> <item row="4" column="1"> - <widget class="QCheckBox" name="sensorGyro"> + <widget class="QCheckBox" name="hwGyro"> <property name="enabled"> <bool>false</bool> </property>

@@ -77,7 +74,7 @@ </property>

</widget> </item> <item row="5" column="1"> - <widget class="QCheckBox" name="sensorTilt"> + <widget class="QCheckBox" name="hwTilt"> <property name="enabled"> <bool>false</bool> </property>

@@ -87,7 +84,7 @@ </property>

</widget> </item> <item row="6" column="1"> - <widget class="QCheckBox" name="sensorLight"> + <widget class="QCheckBox" name="hwLight"> <property name="enabled"> <bool>false</bool> </property>

@@ -134,6 +131,16 @@ <item row="0" column="0">

<widget class="QLabel" name="label"> <property name="text"> <string>Save type</string> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QCheckBox" name="hwRumble"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Rumble</string> </property> </widget> </item>