all repos — mgba @ a2c1ef2fcc0d3aab083962eb1efa09feee819c54

mGBA Game Boy Advance Emulator

GB: Add per-game color overrides
Vicki Pfau vi@endrift.com
Sat, 24 Jun 2017 09:39:36 -0700
commit

a2c1ef2fcc0d3aab083962eb1efa09feee819c54

parent

b61b8a0d2be4d4ac39b497b4ce85259250eec3d7

M include/mgba/internal/gb/overrides.hinclude/mgba/internal/gb/overrides.h

@@ -16,6 +16,8 @@ struct GBCartridgeOverride {

int headerCrc32; enum GBModel model; enum GBMemoryBankControllerType mbc; + + uint32_t gbColors[4]; }; struct Configuration;
M src/gb/overrides.csrc/gb/overrides.c

@@ -13,7 +13,7 @@ #include <mgba-util/crc32.h>

static const struct GBCartridgeOverride _overrides[] = { // None yet - { 0, 0, 0 } + { 0, 0, 0, { 0 } } }; bool GBOverrideFind(const struct Configuration* config, struct GBCartridgeOverride* override) {

@@ -35,6 +35,12 @@ char sectionName[24] = "";

snprintf(sectionName, sizeof(sectionName), "gb.override.%08X", override->headerCrc32); const char* model = ConfigurationGetValue(config, sectionName, "model"); const char* mbc = ConfigurationGetValue(config, sectionName, "mbc"); + const char* pal[4] = { + ConfigurationGetValue(config, sectionName, "pal[0]"), + ConfigurationGetValue(config, sectionName, "pal[1]"), + ConfigurationGetValue(config, sectionName, "pal[2]"), + ConfigurationGetValue(config, sectionName, "pal[3]") + }; if (model) { if (strcasecmp(model, "DMG") == 0) {

@@ -63,6 +69,21 @@ override->mbc = type;

found = true; } } + + if (pal[0] && pal[1] && pal[2] && pal[3]) { + int i; + for (i = 0; i < 4; ++i) { + char* end; + unsigned long value = strtoul(pal[i], &end, 10); + if (end == &pal[i][1] && *end == 'x') { + value = strtoul(pal[i], &end, 16); + } + if (*end) { + continue; + } + override->gbColors[i] = value; + } + } } return found; }

@@ -89,6 +110,12 @@ break;

} ConfigurationSetValue(config, sectionName, "model", model); + if (override->gbColors[0] | override->gbColors[1] | override->gbColors[2] | override->gbColors[3]) { + ConfigurationSetIntValue(config, sectionName, "pal[0]", override->gbColors[0]); + ConfigurationSetIntValue(config, sectionName, "pal[1]", override->gbColors[1]); + ConfigurationSetIntValue(config, sectionName, "pal[2]", override->gbColors[2]); + ConfigurationSetIntValue(config, sectionName, "pal[3]", override->gbColors[3]); + } if (override->mbc != GB_MBC_AUTODETECT) { ConfigurationSetIntValue(config, sectionName, "mbc", override->mbc); } else {

@@ -104,6 +131,13 @@

if (override->mbc != GB_MBC_AUTODETECT) { gb->memory.mbcType = override->mbc; GBMBCInit(gb); + } + + if (override->gbColors[0] | override->gbColors[1] | override->gbColors[2] | override->gbColors[3]) { + GBVideoSetPalette(&gb->video, 0, override->gbColors[0]); + GBVideoSetPalette(&gb->video, 1, override->gbColors[1]); + GBVideoSetPalette(&gb->video, 2, override->gbColors[2]); + GBVideoSetPalette(&gb->video, 3, override->gbColors[3]); } }
M src/platform/qt/OverrideView.cppsrc/platform/qt/OverrideView.cpp

@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "OverrideView.h" +#include <QColorDialog> #include <QPushButton> #include "ConfigController.h"

@@ -79,6 +80,21 @@

connect(m_ui.gbModel, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides); connect(m_ui.mbc, &QComboBox::currentTextChanged, this, &OverrideView::updateOverrides); + QPalette palette = m_ui.color0->palette(); + palette.setColor(backgroundRole(), QColor(0xF8, 0xF8, 0xF8)); + m_ui.color0->setPalette(palette); + palette.setColor(backgroundRole(), QColor(0xA8, 0xA8, 0xA8)); + m_ui.color1->setPalette(palette); + palette.setColor(backgroundRole(), QColor(0x50, 0x50, 0x50)); + m_ui.color2->setPalette(palette); + palette.setColor(backgroundRole(), QColor(0x00, 0x00, 0x00)); + m_ui.color3->setPalette(palette); + + m_ui.color0->installEventFilter(this); + m_ui.color1->installEventFilter(this); + m_ui.color2->installEventFilter(this); + m_ui.color3->installEventFilter(this); + connect(m_ui.tabWidget, &QTabWidget::currentChanged, this, &OverrideView::updateOverrides); #ifndef M_CORE_GBA m_ui.tabWidget->removeTab(m_ui.tabWidget->indexOf(m_ui.tabGBA));

@@ -96,6 +112,42 @@ gameStarted(controller->thread());

} } +bool OverrideView::eventFilter(QObject* obj, QEvent* event) { +#ifdef M_CORE_GB + if (event->type() != QEvent::MouseButtonRelease) { + return false; + } + int colorId; + if (obj == m_ui.color0) { + colorId = 0; + } else if (obj == m_ui.color1) { + colorId = 1; + } else if (obj == m_ui.color2) { + colorId = 2; + } else if (obj == m_ui.color3) { + colorId = 3; + } else { + return false; + } + + QWidget* swatch = static_cast<QWidget*>(obj); + + QColorDialog* colorPicker = new QColorDialog; + colorPicker->setAttribute(Qt::WA_DeleteOnClose); + colorPicker->open(); + connect(colorPicker, &QColorDialog::colorSelected, [this, swatch, colorId](const QColor& color) { + QPalette palette = swatch->palette(); + palette.setColor(backgroundRole(), color); + swatch->setPalette(palette); + m_gbColors[colorId] = color.rgb(); + updateOverrides(); + }); + return true; +#else + return false; +#endif +} + void OverrideView::saveOverride() { if (!m_config) { return;

@@ -155,7 +207,13 @@ if (m_ui.tabWidget->currentWidget() == m_ui.tabGB) {

GBOverride* gb = new GBOverride; gb->override.mbc = s_mbcList[m_ui.mbc->currentIndex()]; gb->override.model = s_gbModelList[m_ui.gbModel->currentIndex()]; - if (gb->override.mbc != GB_MBC_AUTODETECT || gb->override.model != GB_MODEL_AUTODETECT) { + gb->override.gbColors[0] = m_gbColors[0]; + gb->override.gbColors[1] = m_gbColors[1]; + gb->override.gbColors[2] = m_gbColors[2]; + gb->override.gbColors[3] = m_gbColors[3]; + bool hasOverride = gb->override.mbc != GB_MBC_AUTODETECT || gb->override.model != GB_MODEL_AUTODETECT; + hasOverride = hasOverride || (m_gbColors[0] | m_gbColors[1] | m_gbColors[2] | m_gbColors[3]); + if (hasOverride) { m_controller->setOverride(gb); } else { m_controller->clearOverride();
M src/platform/qt/OverrideView.hsrc/platform/qt/OverrideView.h

@@ -36,6 +36,9 @@ void updateOverrides();

void gameStarted(mCoreThread*); void gameStopped(); +protected: + bool eventFilter(QObject* obj, QEvent* event) override; + private: Ui::OverrideView m_ui;

@@ -43,6 +46,8 @@ GameController* m_controller;

ConfigController* m_config; #ifdef M_CORE_GB + uint32_t m_gbColors[4]{}; + static QList<enum GBModel> s_gbModelList; static QList<enum GBMemoryBankControllerType> s_mbcList; #endif
M src/platform/qt/OverrideView.uisrc/platform/qt/OverrideView.ui

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

<rect> <x>0</x> <y>0</y> - <width>443</width> - <height>282</height> + <width>444</width> + <height>284</height> </rect> </property> <property name="sizePolicy">

@@ -325,6 +325,93 @@ <string>HuC-3</string>

</property> </item> </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Colors</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QFrame" name="color0"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="color1"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="color2"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="color3"> + <property name="minimumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + </item> + </layout> </item> </layout> </widget>