diff --git a/CHANGES b/CHANGES index 178f4307a..76886e80c 100644 --- a/CHANGES +++ b/CHANGES @@ -57,6 +57,7 @@ Emulation fixes: - GB MBC: Fix some MBC3 bit masking - GB Video: Fix state after skipping BIOS (fixes mgba.io/i/1715 and mgba.io/i/1716) - GBA: Fix timing advancing too quickly in rare cases + - GBA: Clear GBP connection on reset - GBA Audio: Fix deserializing SOUNDCNT_L - GBA Audio: Fix stereo in XQ audio - GBA Audio: Fix volume/mute in XQ audio (fixes mgba.io/i/1864) @@ -109,6 +110,7 @@ Other fixes: - Qt: Fix drawing on macOS break when using OpenGL (fixes mgba.io/i/1899) - Qt: Load/save bytes from memory viewer in the order visible (fixes mgba.io/i/1900) - Qt: Fix stride changing when toggling SGB borders (fixes mgba.io/i/1898) + - Qt: Fix aliasing on background logo (fixes mgba.io/i/1886) - mGUI: Fix closing down a game if an exit is signalled - mVL: Fix injecting accidentally draining non-injection buffer - SM83: Simplify register pair access on big endian diff --git a/src/gba/core.c b/src/gba/core.c index 13df13bdc..cc6afbbb9 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -304,6 +304,7 @@ static void _GBACoreLoadConfig(struct mCore* core, const struct mCoreConfig* con mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections"); mCoreConfigCopyValue(&core->config, config, "gba.bios"); + mCoreConfigCopyValue(&core->config, config, "gba.forceGbp"); mCoreConfigCopyValue(&core->config, config, "gba.audioHle"); #ifndef DISABLE_THREADING @@ -562,6 +563,7 @@ static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChe static void _GBACoreReset(struct mCore* core) { struct GBACore* gbacore = (struct GBACore*) core; struct GBA* gba = (struct GBA*) core->board; + int fakeBool; if (gbacore->renderer.outputBuffer #if defined(BUILD_GLES2) || defined(BUILD_GLES3) || gbacore->glRenderer.outputTex != (unsigned) -1 @@ -571,7 +573,6 @@ static void _GBACoreReset(struct mCore* core) { if (gbacore->renderer.outputBuffer) { renderer = &gbacore->renderer.d; } - int fakeBool ATTRIBUTE_UNUSED; #if defined(BUILD_GLES2) || defined(BUILD_GLES3) if (gbacore->glRenderer.outputTex != (unsigned) -1 && mCoreConfigGetIntValue(&core->config, "hwaccelVideo", &fakeBool) && fakeBool) { mCoreConfigGetIntValue(&core->config, "videoScale", &gbacore->glRenderer.scale); @@ -609,7 +610,17 @@ static void _GBACoreReset(struct mCore* core) { } #endif + bool forceGbp = false; + if (mCoreConfigGetIntValue(&core->config, "gba.forceGbp", &fakeBool)) { + forceGbp = fakeBool; + } + if (!forceGbp) { + gba->memory.hw.devices &= ~HW_GB_PLAYER_DETECTION; + } GBAOverrideApplyDefaults(gba, gbacore->overrides); + if (forceGbp) { + gba->memory.hw.devices |= HW_GB_PLAYER_DETECTION; + } #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 if (!gba->biosVf && core->opts.useBios) { diff --git a/src/gba/gba.c b/src/gba/gba.c index dd2e0bd25..39e5508bf 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -216,6 +216,12 @@ void GBAReset(struct ARMCore* cpu) { GBASIOReset(&gba->sio); + // GB Player SIO control should not be engaged before detection, even if we already know it's GBP + gba->memory.hw.devices &= ~HW_GB_PLAYER; + if (gba->sio.drivers.normal == &gba->memory.hw.gbpDriver.d) { + GBASIOSetDriver(&gba->sio, NULL, SIO_NORMAL_32); + } + bool isELF = false; #ifdef USE_ELF struct ELF* elf = ELFOpen(gba->romVf); diff --git a/src/gba/hardware.c b/src/gba/hardware.c index 1defb314d..93384115d 100644 --- a/src/gba/hardware.c +++ b/src/gba/hardware.c @@ -539,13 +539,14 @@ void GBAHardwarePlayerUpdate(struct GBA* gba) { gba->memory.hw.gbpTxPosition = 0; return; } - if (gba->keyCallback || gba->sio.drivers.normal) { + if (gba->keyCallback) { return; } if (GBAHardwarePlayerCheckScreen(&gba->video)) { gba->memory.hw.devices |= HW_GB_PLAYER; gba->memory.hw.gbpInputsPosted = 0; gba->keyCallback = &gba->memory.hw.gbpCallback.d; + // TODO: Check if the SIO driver is actually used first GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32); } } diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 69caafdc5..1aec545e3 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -142,6 +142,14 @@ static void _reloadSettings(void) { } } +#ifdef M_CORE_GBA + var.key = "mgba_force_gbp"; + var.value = 0; + if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + mCoreConfigSetDefaultIntValue(&core->config, "gba.forceGbp", strcmp(var.value, "ON") == 0); + } +#endif + mCoreConfigLoadDefaults(&core->config, &opts); mCoreLoadConfig(core); } diff --git a/src/platform/libretro/libretro_core_options.h b/src/platform/libretro/libretro_core_options.h index 93e3ab3bd..b42655e11 100644 --- a/src/platform/libretro/libretro_core_options.h +++ b/src/platform/libretro/libretro_core_options.h @@ -174,6 +174,17 @@ struct retro_core_option_definition option_defs_us[] = { "OFF" }, #endif + { + "mgba_force_gbp", + "Enable Game Boy Player Rumble (requires restart)", + "Enabling this will allow compatible games with the Game Boy Player boot logo to make the controller rumble. Due to how Nintendo decided this feature should work, it may cause glitches such as flickering or lag in some of these games.", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL }, + }, + "OFF" + }, { NULL, NULL, NULL, {{0}}, NULL }, }; diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index f0ecb93d6..c229fd18d 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -161,10 +161,7 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi #elif defined(M_CORE_GB) resizeFrame(QSize(GB_VIDEO_HORIZONTAL_PIXELS * i, GB_VIDEO_VERTICAL_PIXELS * i)); #endif - m_screenWidget->setPixmap(m_logo); - m_screenWidget->setCenteredAspectRatio(m_logo.width(), m_logo.height()); - m_screenWidget->setDimensions(m_logo.width(), m_logo.height()); - m_screenWidget->setLockIntegerScaling(false); + setLogo(); setCentralWidget(m_screenWidget); connect(this, &Window::shutdown, m_logView, &QWidget::hide); @@ -288,11 +285,6 @@ void Window::reloadConfig() { } m_display->resizeContext(); } - if (m_display) { - m_display->lockAspectRatio(opts->lockAspectRatio); - m_display->filter(opts->resampleVideo); - } - m_screenWidget->filter(opts->resampleVideo); m_inputController.setScreensaverSuspendable(opts->suspendScreensaver); } @@ -810,6 +802,7 @@ void Window::gameStarted() { m_config->updateOption("lockIntegerScaling"); m_config->updateOption("lockAspectRatio"); m_config->updateOption("interframeBlending"); + m_config->updateOption("resampleVideo"); m_config->updateOption("showOSD"); if (m_savedScale > 0) { resizeFrame(size * m_savedScale); @@ -879,11 +872,7 @@ void Window::gameStopped() { } setWindowFilePath(QString()); detachWidget(m_display.get()); - m_screenWidget->setCenteredAspectRatio(m_logo.width(), m_logo.height()); - m_screenWidget->setDimensions(m_logo.width(), m_logo.height()); - m_screenWidget->setLockIntegerScaling(false); - m_screenWidget->setPixmap(m_logo); - m_screenWidget->unsetCursor(); + setLogo(); if (m_display) { #ifdef M_CORE_GB m_display->setMinimumSize(GB_VIDEO_HORIZONTAL_PIXELS, GB_VIDEO_VERTICAL_PIXELS); @@ -980,7 +969,6 @@ void Window::reloadDisplayDriver() { m_display->lockIntegerScaling(opts->lockIntegerScaling); m_display->interframeBlending(opts->interframeBlending); m_display->filter(opts->resampleVideo); - m_screenWidget->filter(opts->resampleVideo); m_config->updateOption("showOSD"); #if defined(BUILD_GL) || defined(BUILD_GLES2) if (opts->shader) { @@ -1499,7 +1487,9 @@ void Window::setupMenu(QMenuBar* menubar) { if (m_display) { m_display->filter(value.toBool()); } - m_screenWidget->filter(value.toBool()); + if (m_controller) { + m_screenWidget->filter(value.toBool()); + } }, this); m_config->updateOption("resampleVideo"); @@ -1978,6 +1968,16 @@ void Window::attachDisplay() { changeRenderer(); } +void Window::setLogo() { + m_screenWidget->setPixmap(m_logo); + m_screenWidget->setCenteredAspectRatio(m_logo.width(), m_logo.height()); + m_screenWidget->setDimensions(m_logo.width(), m_logo.height()); + m_screenWidget->setLockIntegerScaling(false); + m_screenWidget->setLockAspectRatio(true); + m_screenWidget->filter(true); + m_screenWidget->unsetCursor(); +} + WindowBackground::WindowBackground(QWidget* parent) : QWidget(parent) { diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 96a609404..fa5b8ce6d 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -142,6 +142,8 @@ private slots: void updateFrame(); + void setLogo(); + private: static const int FPS_TIMER_INTERVAL = 2000; static const int MUST_RESTART_TIMEOUT = 10000;