diff --git a/CMakeLists.txt b/CMakeLists.txt
index da1a9eec10..2fa3769f8f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -756,7 +756,7 @@ if(NOT ENABLE_QT)
set(USE_MGBA 0)
endif()
if(USE_MGBA)
- dolphin_find_optional_system_library(LIBMGBA Externals/mGBA)
+ dolphin_find_optional_system_library(LIBMGBA Externals/mGBA 0.11)
endif()
find_package(SYSTEMD)
diff --git a/Externals/mGBA/CMakeLists.txt b/Externals/mGBA/CMakeLists.txt
index f48231e352..122e484b2d 100644
--- a/Externals/mGBA/CMakeLists.txt
+++ b/Externals/mGBA/CMakeLists.txt
@@ -3,7 +3,7 @@ set(USE_LZMA ON)
add_subdirectory(mgba EXCLUDE_FROM_ALL)
dolphin_disable_warnings(mgba)
-target_compile_definitions(mgba PUBLIC HAVE_CRC32)
+target_compile_definitions(mgba PUBLIC HAVE_CRC32 ENABLE_VFS ENABLE_DIRECTORIES)
target_link_libraries(mgba ZLIB::ZLIB)
if(NOT MSVC)
diff --git a/Externals/mGBA/exports.props b/Externals/mGBA/exports.props
index 34e6c4f02d..ddc8446c6d 100644
--- a/Externals/mGBA/exports.props
+++ b/Externals/mGBA/exports.props
@@ -3,6 +3,7 @@
$(ExternalsDir)mGBA\mgba\include;%(AdditionalIncludeDirectories)
+ ENABLE_VFS;ENABLE_DIRECTORIES;%(PreprocessorDefinitions)
diff --git a/Externals/mGBA/mgba b/Externals/mGBA/mgba
index 8739b22fbc..0b40863f64 160000
--- a/Externals/mGBA/mgba
+++ b/Externals/mGBA/mgba
@@ -1 +1 @@
-Subproject commit 8739b22fbc90fdf0b4f6612ef9c0520f0ba44a51
+Subproject commit 0b40863f64d0940f333fa1c638e75f86f8a26a33
diff --git a/Externals/mGBA/mgba.vcxproj b/Externals/mGBA/mgba.vcxproj
index d1235246e3..026b9b9267 100644
--- a/Externals/mGBA/mgba.vcxproj
+++ b/Externals/mGBA/mgba.vcxproj
@@ -18,7 +18,7 @@
mgba\include;mgba\src;mgba\src\third-party\lzma;%(AdditionalIncludeDirectories)
- BUILD_STATIC;M_CORE_GB;M_CORE_GBA;USE_LZMA;_7ZIP_PPMD_SUPPPORT;HAVE_STRDUP;HAVE_SETLOCALE;HAVE_CHMOD;HAVE_UMASK;HAVE_CRC32;%(PreprocessorDefinitions)
+ BUILD_STATIC;M_CORE_GB;M_CORE_GBA;USE_LZMA;_7ZIP_PPMD_SUPPPORT;HAVE_STRDUP;HAVE_SETLOCALE;HAVE_CHMOD;HAVE_UMASK;HAVE_CRC32;ENABLE_VFS;ENABLE_VFS_FD;ENABLE_DIRECTORIES;%(PreprocessorDefinitions)
"$(CScript)" /nologo /E:JScript "make_version.c.js"
@@ -67,7 +67,9 @@
-
+
+ $(IntDir)obj2\
+
@@ -95,6 +97,7 @@
+
$(IntDir)obj3\
@@ -138,13 +141,14 @@
$(IntDir)obj2\
-
$(IntDir)obj2\
$(IntDir)obj2\
+
+
@@ -153,6 +157,9 @@
+
+
+
@@ -177,7 +184,6 @@
$(IntDir)obj3\
-
@@ -206,7 +212,6 @@
$(IntDir)obj3\
-
diff --git a/Source/Core/Core/HW/GBACore.cpp b/Source/Core/Core/HW/GBACore.cpp
index b25414f3b1..272b458fc5 100644
--- a/Source/Core/Core/HW/GBACore.cpp
+++ b/Source/Core/Core/HW/GBACore.cpp
@@ -9,19 +9,19 @@
#include
#undef PYCPARSE
#include
-#include
#include
#include
#include
#include
+
#include
#include
#include
#include
#include "AudioCommon/AudioCommon.h"
+
#include "Common/ChunkFile.h"
-#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/Crypto/SHA1.h"
@@ -30,6 +30,7 @@
#include "Common/MinizipUtil.h"
#include "Common/ScopeGuard.h"
#include "Common/Thread.h"
+
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
@@ -46,8 +47,7 @@ mLogger s_stub_logger = {
[](mLogger*, int category, mLogLevel level, const char* format, va_list args) {}, nullptr};
} // namespace
-constexpr auto SAMPLES = 512;
-constexpr auto SAMPLE_RATE = 48000;
+constexpr size_t AUDIO_BUFFER_SIZE = 512;
// libmGBA does not return the correct frequency for some GB models
static u32 GetCoreFrequency(mCore* core)
@@ -225,9 +225,9 @@ bool Core::Start(u64 gc_ticks)
}
rom_guard.Dismiss();
- std::array game_title{};
- m_core->getGameTitle(m_core, game_title.data());
- m_game_title = game_title.data();
+ mGameInfo info;
+ m_core->getGameInfo(m_core, &info);
+ m_game_title = info.title;
m_save_path = NetPlay::IsNetPlayRunning() ? NetPlay::GetGBASavePath(m_device_number) :
GetSavePath(m_rom_path, m_device_number);
@@ -241,7 +241,7 @@ bool Core::Start(u64 gc_ticks)
SetSIODriver();
SetVideoBuffer();
- SetSampleRates();
+ SetAudioBufferSize();
AddCallbacks();
SetAVStream();
SetupEvent();
@@ -386,18 +386,19 @@ void Core::SetSIODriver()
if (m_core->platform(m_core) != mPLATFORM_GBA)
return;
- GBASIOJOYCreate(&m_sio_driver);
- GBASIOSetDriver(&static_cast<::GBA*>(m_core->board)->sio, &m_sio_driver, SIO_JOYBUS);
-
m_sio_driver.core = this;
- m_sio_driver.load = [](GBASIODriver* driver) {
+ m_sio_driver.init = [](GBASIODriver* driver) {
static_cast(driver)->core->m_link_enabled = true;
return true;
};
- m_sio_driver.unload = [](GBASIODriver* driver) {
- static_cast(driver)->core->m_link_enabled = false;
- return true;
+ m_sio_driver.handlesMode = [](GBASIODriver* driver, GBASIOMode mode) {
+ return mode == GBA_SIO_JOYBUS;
};
+ m_sio_driver.deinit = [](GBASIODriver* driver) {
+ static_cast(driver)->core->m_link_enabled = false;
+ };
+
+ GBASIOSetDriver(&static_cast<::GBA*>(m_core->board)->sio, &m_sio_driver);
}
void Core::SetVideoBuffer()
@@ -410,15 +411,9 @@ void Core::SetVideoBuffer()
host->GameChanged();
}
-void Core::SetSampleRates()
+void Core::SetAudioBufferSize()
{
- m_core->setAudioBufferSize(m_core, SAMPLES);
- blip_set_rates(m_core->getAudioChannel(m_core, 0), m_core->frequency(m_core), SAMPLE_RATE);
- blip_set_rates(m_core->getAudioChannel(m_core, 1), m_core->frequency(m_core), SAMPLE_RATE);
-
- SoundStream* sound_stream = m_system.GetSoundStream();
- sound_stream->GetMixer()->SetGBAInputSampleRateDivisors(
- m_device_number, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / SAMPLE_RATE);
+ m_core->setAudioBufferSize(m_core, AUDIO_BUFFER_SIZE);
}
void Core::AddCallbacks()
@@ -445,14 +440,26 @@ void Core::SetAVStream()
auto core = static_cast(stream)->core;
core->SetVideoBuffer();
};
- m_stream.postAudioBuffer = [](mAVStream* stream, blip_t* left, blip_t* right) {
- auto core = static_cast(stream)->core;
- std::vector buffer(SAMPLES * 2);
- blip_read_samples(left, &buffer[0], SAMPLES, 1);
- blip_read_samples(right, &buffer[1], SAMPLES, 1);
+ m_stream.audioRateChanged = [](mAVStream* stream, unsigned rate) {
+ auto* core = static_cast(stream)->core;
+ auto* const sound_stream = core->m_system.GetSoundStream();
+ sound_stream->GetMixer()->SetGBAInputSampleRateDivisors(
+ core->m_device_number, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / rate);
+ };
+ m_stream.postAudioBuffer = [](mAVStream* stream, mAudioBuffer* audio_buffer) {
+ size_t sample_count = mAudioBufferAvailable(audio_buffer);
+ const size_t required_buffer_size = sample_count * audio_buffer->channels;
- SoundStream* sound_stream = core->m_system.GetSoundStream();
- sound_stream->GetMixer()->PushGBASamples(core->m_device_number, &buffer[0], SAMPLES);
+ auto* const av_stream = static_cast(stream);
+ if (required_buffer_size > av_stream->sample_buffer.size())
+ av_stream->sample_buffer.reset(required_buffer_size);
+
+ sample_count = mAudioBufferRead(audio_buffer, av_stream->sample_buffer.data(), sample_count);
+
+ auto* const core = av_stream->core;
+ auto* const sound_stream = core->m_system.GetSoundStream();
+ sound_stream->GetMixer()->PushGBASamples(core->m_device_number, av_stream->sample_buffer.data(),
+ sample_count);
};
m_core->setAVStream(m_core, &m_stream);
}
@@ -733,9 +740,9 @@ bool Core::GetRomInfo(const char* rom_path, std::array& hash, std::strin
return false;
}
- std::array game_title{};
- core->getGameTitle(core, game_title.data());
- title = game_title.data();
+ mGameInfo info;
+ core->getGameInfo(core, &info);
+ title = info.title;
core->deinit(core);
return true;
diff --git a/Source/Core/Core/HW/GBACore.h b/Source/Core/Core/HW/GBACore.h
index 6fd4b86e0c..72faa1bec5 100644
--- a/Source/Core/Core/HW/GBACore.h
+++ b/Source/Core/Core/HW/GBACore.h
@@ -21,6 +21,7 @@
#include
#include
+#include "Common/Buffer.h"
#include "Common/CommonTypes.h"
class GBAHostInterface;
@@ -40,6 +41,7 @@ struct SIODriver : GBASIODriver
struct AVStream : mAVStream
{
Core* core;
+ Common::UniqueBuffer sample_buffer;
};
struct CoreInfo
@@ -106,7 +108,7 @@ private:
void SetSIODriver();
void SetVideoBuffer();
- void SetSampleRates();
+ void SetAudioBufferSize();
void AddCallbacks();
void SetAVStream();
void SetupEvent();