GB: Add SGB palettes, options for selecting which palettes

This commit is contained in:
Vicki Pfau 2021-05-08 16:23:52 -07:00
parent 38c8ff241e
commit 1640d00e87
6 changed files with 642 additions and 397 deletions

View File

@ -1,6 +1,7 @@
0.10.0: (Future) 0.10.0: (Future)
Features: Features:
- Presets for Game Boy palettes - Presets for Game Boy palettes
- Add Super Game Boy palettes for original Game Boy games
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data - Tool for converting scanned pictures of e-Reader cards to raw dotcode data
- Cheat code support in homebrew ports - Cheat code support in homebrew ports
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks - Support for combo "Super Game Boy Color" SGB + GBC ROM hacks

View File

@ -12,6 +12,13 @@ CXX_GUARD_START
#include <mgba/gb/interface.h> #include <mgba/gb/interface.h>
enum GBColorLookup {
GB_COLORS_NONE = 0,
GB_COLORS_CGB = 1,
GB_COLORS_SGB = 2,
GB_COLORS_SGB_CGB_FALLBACK = GB_COLORS_CGB | GB_COLORS_SGB
};
struct GBCartridgeOverride { struct GBCartridgeOverride {
int headerCrc32; int headerCrc32;
enum GBModel model; enum GBModel model;
@ -27,7 +34,7 @@ struct GBColorPreset {
struct Configuration; struct Configuration;
bool GBOverrideFind(const struct Configuration*, struct GBCartridgeOverride* override); bool GBOverrideFind(const struct Configuration*, struct GBCartridgeOverride* override);
bool GBOverrideColorFind(struct GBCartridgeOverride* override); bool GBOverrideColorFind(struct GBCartridgeOverride* override, enum GBColorLookup);
void GBOverrideSave(struct Configuration*, const struct GBCartridgeOverride* override); void GBOverrideSave(struct Configuration*, const struct GBCartridgeOverride* override);
size_t GBColorPresetList(const struct GBColorPreset** presets); size_t GBColorPresetList(const struct GBColorPreset** presets);

View File

@ -224,6 +224,7 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf
mCoreConfigCopyValue(&core->config, config, "cgb.model"); mCoreConfigCopyValue(&core->config, config, "cgb.model");
mCoreConfigCopyValue(&core->config, config, "cgb.hybridModel"); mCoreConfigCopyValue(&core->config, config, "cgb.hybridModel");
mCoreConfigCopyValue(&core->config, config, "cgb.sgbModel"); mCoreConfigCopyValue(&core->config, config, "cgb.sgbModel");
mCoreConfigCopyValue(&core->config, config, "gb.colors");
mCoreConfigCopyValue(&core->config, config, "useCgbColors"); mCoreConfigCopyValue(&core->config, config, "useCgbColors");
mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections"); mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections");
@ -482,13 +483,18 @@ static void _GBCoreReset(struct mCore* core) {
} }
if (gb->memory.rom) { if (gb->memory.rom) {
int doColorOverride = 0; int doColorOverride = GB_COLORS_NONE;
mCoreConfigGetIntValue(&core->config, "useCgbColors", &doColorOverride); mCoreConfigGetIntValue(&core->config, "gb.colors", &doColorOverride);
if (doColorOverride == GB_COLORS_NONE) {
// Backwards compat for renamed setting
mCoreConfigGetIntValue(&core->config, "useCgbColors", &doColorOverride);
}
struct GBCartridgeOverride override; struct GBCartridgeOverride override;
const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
override.headerCrc32 = doCrc32(cart, sizeof(*cart)); override.headerCrc32 = doCrc32(cart, sizeof(*cart));
bool modelOverride = GBOverrideFind(gbcore->overrides, &override) || (doColorOverride && GBOverrideColorFind(&override)); bool modelOverride = GBOverrideFind(gbcore->overrides, &override) || (doColorOverride && GBOverrideColorFind(&override, doColorOverride));
if (modelOverride) { if (modelOverride) {
GBOverrideApply(gb, &override); GBOverrideApply(gb, &override);
} }

View File

@ -88,7 +88,7 @@
#define UNIFORM_PAL(A, B, C, D) { PAL_ENTRY(A, B, C, D), PAL_ENTRY(A, B, C, D), PAL_ENTRY(A, B, C, D) } #define UNIFORM_PAL(A, B, C, D) { PAL_ENTRY(A, B, C, D), PAL_ENTRY(A, B, C, D), PAL_ENTRY(A, B, C, D) }
#define SGB_PAL(A) { PAL ## A, PAL ## A, PAL ## A } #define SGB_PAL(A) { PAL ## A, PAL ## A, PAL ## A }
static const struct GBCartridgeOverride _colorOverrides[] = { static const struct GBCartridgeOverride _gbcOverrides[] = {
// Adventures of Lolo (Europe) // Adventures of Lolo (Europe)
{ 0xFBE65286, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, PALETTE(0, 28, 3) }, { 0xFBE65286, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, PALETTE(0, 28, 3) },
@ -524,6 +524,145 @@ static const struct GBCartridgeOverride _colorOverrides[] = {
{ 0, 0, 0, { 0 } } { 0, 0, 0, { 0 } }
}; };
static const struct GBCartridgeOverride _sgbOverrides[] = {
// Alleyway (World)
{ 0xCBAA161B, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3F) },
// Baseball (World)
{ 0xE02904BD, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2G) },
// Dr. Mario (World)
{ 0xA3C2C1E9, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3B) },
// Dr. Mario (World) (Rev A)
{ 0x69975661, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3B) },
// F-1 Race (World)
{ 0x8434CB2C, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(4F) },
// F-1 Race (World) (Rev A)
{ 0xBA63383B, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(4F) },
// Game Boy Wars (Japan)
{ 0x03E3ED72, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3E) },
// Golf (World)
{ 0x885C242D, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3H) },
// Hoshi no Kirby (Japan)
{ 0x4AA02A13, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2C) },
// Hoshi no Kirby (Japan) (Rev A)
{ 0x88D03280, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2C) },
// Kaeru no Tame ni Kane wa Naru (Japan)
{ 0x7F805941, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2A) },
// Kid Icarus - Of Myths and Monsters (USA, Europe)
{ 0x5D93DB0F, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2F) },
// Kirby no Pinball (Japan)
{ 0x89239AED, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1C) },
// Kirby's Dream Land (USA, Europe)
{ 0x302017CC, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2C) },
// Kirby's Pinball Land (USA, Europe)
{ 0x9C4AA9D8, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1C) },
// Legend of Zelda, The - Link's Awakening (Canada)
{ 0x9F54D47B, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
// Legend of Zelda, The - Link's Awakening (France)
{ 0x441D7FAD, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
// Legend of Zelda, The - Link's Awakening (Germany)
{ 0x838D65D6, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
// Legend of Zelda, The - Link's Awakening (USA, Europe) (Rev A)
{ 0x24CAAB4D, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
// Legend of Zelda, The - Link's Awakening (USA, Europe) (Rev B)
{ 0xBCBB6BDB, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
// Legend of Zelda, The - Link's Awakening (USA, Europe)
{ 0x9A193109, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
// Metroid II - Return of Samus (World)
{ 0xBDCCC648, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(4G) },
// QIX (World)
{ 0x5EECB346, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(4A) },
// SolarStriker (World)
{ 0x981620E7, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1G) },
// Super Mario Land (World)
{ 0x6C0ACA9F, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1F) },
// Super Mario Land (World) (Rev A)
{ 0xCA117ACC, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1F) },
// Super Mario Land 2 - 6 Golden Coins (USA, Europe) (Rev A)
{ 0x423E09E6, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3D) },
// Super Mario Land 2 - 6 Golden Coins (USA, Europe) (Rev B)
{ 0x445A0358, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3D) },
// Super Mario Land 2 - 6 Golden Coins (USA, Europe)
{ 0xDE2960A1, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3D) },
// Super Mario Land 2 - 6-tsu no Kinka (Japan)
{ 0xD47CED78, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3D) },
// Super Mario Land 2 - 6-tsu no Kinka (Japan) (Rev A)
{ 0xA4B4F9F9, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3D) },
// Super Mario Land 2 - 6-tsu no Kinka (Japan) (Rev B)
{ 0x5842F25D, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3D) },
// Tennis (World)
{ 0xD2BEBF08, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3G) },
// Tetris (World)
{ 0xE906C6A6, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3A) },
// Tetris (World) (Rev A)
{ 0x4674B43F, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3A) },
// Wario Land - Super Mario Land 3 (World)
{ 0xF1EA10E9, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1B) },
// X (Japan)
{ 0xFED4C47F, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(4D) },
// Yakuman (Japan)
{ 0x40604F17, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3C) },
// Yakuman (Japan) (Rev A)
{ 0x2959ACFC, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(3C) },
// Yoshi (USA)
{ 0xAB1605B9, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2D) },
// Yoshi no Cookie (Japan)
{ 0x841753DA, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1D) },
// Yoshi no Tamago (Japan)
{ 0xD4098A6B, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(2D) },
// Yoshi's Cookie (USA, Europe)
{ 0x940EDD87, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1D) },
// Zelda no Densetsu - Yume o Miru Shima (Japan)
{ 0x259C9A82, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
// Zelda no Densetsu - Yume o Miru Shima (Japan) (Rev A)
{ 0x61F269CD, GB_MODEL_AUTODETECT, GB_MBC_AUTODETECT, SGB_PAL(1E) },
{ 0, 0, 0, { 0 } }
};
static const struct GBCartridgeOverride _overrides[] = { static const struct GBCartridgeOverride _overrides[] = {
// Pokemon Spaceworld 1997 demo // Pokemon Spaceworld 1997 demo
{ 0x232a067d, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (debug) { 0x232a067d, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (debug)
@ -586,12 +725,22 @@ static const struct GBColorPreset _colorPresets[] = {
{ "SGB 4-H", SGB_PAL(4H), }, { "SGB 4-H", SGB_PAL(4H), },
}; };
bool GBOverrideColorFind(struct GBCartridgeOverride* override) { bool GBOverrideColorFind(struct GBCartridgeOverride* override, enum GBColorLookup order) {
int i; int i;
for (i = 0; _colorOverrides[i].headerCrc32; ++i) { if (order & GB_COLORS_SGB) {
if (override->headerCrc32 == _colorOverrides[i].headerCrc32) { for (i = 0; _gbcOverrides[i].headerCrc32; ++i) {
memcpy(override->gbColors, _colorOverrides[i].gbColors, sizeof(override->gbColors)); if (override->headerCrc32 == _sgbOverrides[i].headerCrc32) {
return true; memcpy(override->gbColors, _sgbOverrides[i].gbColors, sizeof(override->gbColors));
return true;
}
}
}
if (order & GB_COLORS_CGB) {
for (i = 0; _gbcOverrides[i].headerCrc32; ++i) {
if (override->headerCrc32 == _gbcOverrides[i].headerCrc32) {
memcpy(override->gbColors, _gbcOverrides[i].gbColors, sizeof(override->gbColors));
return true;
}
} }
} }
return false; return false;

View File

@ -399,7 +399,6 @@ void SettingsView::updateConfig() {
saveSetting("gbc.bios", m_ui.gbcBios); saveSetting("gbc.bios", m_ui.gbcBios);
saveSetting("sgb.bios", m_ui.sgbBios); saveSetting("sgb.bios", m_ui.sgbBios);
saveSetting("sgb.borders", m_ui.sgbBorders); saveSetting("sgb.borders", m_ui.sgbBorders);
saveSetting("useCgbColors", m_ui.useCgbColors);
saveSetting("useBios", m_ui.useBios); saveSetting("useBios", m_ui.useBios);
saveSetting("skipBios", m_ui.skipBios); saveSetting("skipBios", m_ui.skipBios);
saveSetting("sampleRate", m_ui.sampleRate); saveSetting("sampleRate", m_ui.sampleRate);
@ -578,6 +577,18 @@ void SettingsView::updateConfig() {
m_controller->setOption(color.toUtf8().constData(), m_gbColors[colorId] & ~0xFF000000); m_controller->setOption(color.toUtf8().constData(), m_gbColors[colorId] & ~0xFF000000);
} }
int gbColors = GB_COLORS_CGB;
if (m_ui.gbColor->isChecked()) {
gbColors = GB_COLORS_NONE;
} else if (m_ui.cgbColor->isChecked()) {
gbColors = GB_COLORS_CGB;
} else if (m_ui.sgbColor->isChecked()) {
gbColors = GB_COLORS_SGB;
} else if (m_ui.scgbColor->isChecked()) {
gbColors = GB_COLORS_SGB_CGB_FALLBACK;
}
saveSetting("gb.colors", gbColors);
#endif #endif
m_controller->write(); m_controller->write();
@ -593,7 +604,6 @@ void SettingsView::reloadConfig() {
loadSetting("gbc.bios", m_ui.gbcBios); loadSetting("gbc.bios", m_ui.gbcBios);
loadSetting("sgb.bios", m_ui.sgbBios); loadSetting("sgb.bios", m_ui.sgbBios);
loadSetting("sgb.borders", m_ui.sgbBorders, true); loadSetting("sgb.borders", m_ui.sgbBorders, true);
loadSetting("useCgbColors", m_ui.useCgbColors, true);
loadSetting("useBios", m_ui.useBios); loadSetting("useBios", m_ui.useBios);
loadSetting("skipBios", m_ui.skipBios); loadSetting("skipBios", m_ui.skipBios);
loadSetting("audioBuffers", m_ui.audioBufferSize); loadSetting("audioBuffers", m_ui.audioBufferSize);
@ -725,6 +735,22 @@ void SettingsView::reloadConfig() {
int index = m_ui.cgbSgbModel->findData(model); int index = m_ui.cgbSgbModel->findData(model);
m_ui.cgbSgbModel->setCurrentIndex(index >= 0 ? index : 0); m_ui.cgbSgbModel->setCurrentIndex(index >= 0 ? index : 0);
} }
switch (m_controller->getOption("gb.colors", m_controller->getOption("useCgbColors", true).toInt()).toInt()) {
case GB_COLORS_NONE:
m_ui.gbColor->setChecked(true);
break;
default:
case GB_COLORS_CGB:
m_ui.cgbColor->setChecked(true);
break;
case GB_COLORS_SGB:
m_ui.sgbColor->setChecked(true);
break;
case GB_COLORS_SGB_CGB_FALLBACK:
m_ui.scgbColor->setChecked(true);
break;
}
#endif #endif
int hwaccelVideo = m_controller->getOption("hwaccelVideo", 0).toInt(); int hwaccelVideo = m_controller->getOption("hwaccelVideo", 0).toInt();

View File

@ -23,13 +23,6 @@
<property name="sizeConstraint"> <property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum> <enum>QLayout::SetFixedSize</enum>
</property> </property>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QListWidget" name="tabs"> <widget class="QListWidget" name="tabs">
<property name="sizePolicy"> <property name="sizePolicy">
@ -89,6 +82,13 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QStackedWidget" name="stackedWidget"> <widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex"> <property name="currentIndex">
@ -1495,391 +1495,444 @@
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="gb"> <widget class="QWidget" name="gb">
<layout class="QFormLayout" name="formLayout_1"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item row="0" column="0"> <item>
<widget class="QLabel" name="label_29"> <widget class="QGroupBox" name="groupBox_2">
<property name="text"> <property name="title">
<string>Game Boy-only model:</string> <string>Models</string>
</property> </property>
<layout class="QFormLayout" name="formLayout_9">
<item row="0" column="0">
<widget class="QLabel" name="label_29">
<property name="text">
<string>GB only:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="gbModel"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_32">
<property name="text">
<string>SGB compatible:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="sgbModel"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_33">
<property name="text">
<string>GBC only:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cgbModel"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_38">
<property name="text">
<string>GBC compatible:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="cgbHybridModel"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_39">
<property name="text">
<string>SGB and GBC compatible:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="cgbSgbModel"/>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="sgbBorders">
<property name="text">
<string>Super Game Boy borders</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item>
<widget class="QComboBox" name="gbModel"/> <widget class="QGroupBox" name="groupBox">
</item> <property name="title">
<item row="1" column="0"> <string>Game Boy palette</string>
<widget class="QLabel" name="label_32">
<property name="text">
<string>Super Game Boy model:</string>
</property> </property>
<layout class="QFormLayout" name="formLayout_8">
<item row="0" column="0">
<widget class="QLabel" name="label_40">
<property name="text">
<string>Preset:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="colorPreset"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_28">
<property name="text">
<string>Default BG colors:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<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>
<item row="2" column="0">
<widget class="QLabel" name="label_69">
<property name="text">
<string>Default sprite colors 1:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QFrame" name="color4">
<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="color5">
<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="color6">
<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="color7">
<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>
<item row="3" column="0">
<widget class="QLabel" name="label_70">
<property name="text">
<string>Default sprite colors 2:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_37">
<item>
<widget class="QFrame" name="color8">
<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="color9">
<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="color10">
<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="color11">
<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>
<item row="4" column="0" colspan="2">
<widget class="Line" name="line_19">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QRadioButton" name="gbColor">
<property name="text">
<string>Default color palette only</string>
</property>
<attribute name="buttonGroup">
<string notr="true">gbColors</string>
</attribute>
</widget>
</item>
<item row="6" column="1">
<widget class="QRadioButton" name="sgbColor">
<property name="text">
<string>SGB color palette if available</string>
</property>
<attribute name="buttonGroup">
<string notr="true">gbColors</string>
</attribute>
</widget>
</item>
<item row="7" column="1">
<widget class="QRadioButton" name="cgbColor">
<property name="text">
<string>GBC color palette if available</string>
</property>
<attribute name="buttonGroup">
<string notr="true">gbColors</string>
</attribute>
</widget>
</item>
<item row="8" column="1">
<widget class="QRadioButton" name="scgbColor">
<property name="text">
<string>SGB (preferred) or GBC color palette if available</string>
</property>
<attribute name="buttonGroup">
<string notr="true">gbColors</string>
</attribute>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item>
<widget class="QComboBox" name="sgbModel"/> <widget class="QGroupBox" name="groupBox_3">
</item> <property name="title">
<item row="2" column="0"> <string>Game Boy Camera</string>
<widget class="QLabel" name="label_33">
<property name="text">
<string>Game Boy Color-only model:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="cgbModel"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_38">
<property name="text">
<string>Game Boy/Game Boy Color model:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="cgbHybridModel"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_39">
<property name="text">
<string>Super Game Boy/Game Boy Color model:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="cgbSgbModel"/>
</item>
<item row="5" column="0" colspan="2">
<widget class="Line" name="line_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_40">
<property name="text">
<string>Preset:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="colorPreset"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_28">
<property name="text">
<string>Default BG colors:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<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>
<item row="8" column="0">
<widget class="QLabel" name="label_69">
<property name="text">
<string>Default sprite colors 1:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QFrame" name="color4">
<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="color5">
<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="color6">
<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="color7">
<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>
<item row="9" column="0">
<widget class="QLabel" name="label_70">
<property name="text">
<string>Default sprite colors 2:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_37">
<item>
<widget class="QFrame" name="color8">
<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="color9">
<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="color10">
<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="color11">
<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>
<item row="10" column="1">
<widget class="QCheckBox" name="useCgbColors">
<property name="text">
<string>Use GBC colors in GB games</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QCheckBox" name="sgbBorders">
<property name="text">
<string>Super Game Boy borders</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="2">
<widget class="Line" name="line_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="13" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Camera driver:</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QComboBox" name="cameraDriver">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="label_35">
<property name="text">
<string>Camera:</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QComboBox" name="camera">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<layout class="QFormLayout" name="formLayout_10">
<item row="0" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Driver:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="cameraDriver">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_35">
<property name="text">
<string>Source:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="camera">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -2083,4 +2136,7 @@
</hints> </hints>
</connection> </connection>
</connections> </connections>
<buttongroups>
<buttongroup name="gbColors"/>
</buttongroups>
</ui> </ui>