From 6ed20a51cc2d83e8c1ce37f355b54caca6669157 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Sun, 6 Oct 2024 21:31:56 +0000 Subject: [PATCH] build: unpack XAudio2_7.dll at init Use a Windows resource for the XAudio2_7.dll which may not be installed by the user. Unpack it at initialization of the XAudio2 driver into a temp directory and load it. Signed-off-by: Rafael Kitover --- src/wx/CMakeLists.txt | 14 ++++++ src/wx/audio/internal/xaudio2.cpp | 48 +++++++++++++++++++- src/wx/audio/internal/xaudio27-dll-path.h.in | 1 + src/wx/audio/internal/xaudio27-dll-rc.h | 6 +++ src/wx/wxvbam.rc | 3 ++ win32-deps | 2 +- 6 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/wx/audio/internal/xaudio27-dll-path.h.in create mode 100644 src/wx/audio/internal/xaudio27-dll-rc.h diff --git a/src/wx/CMakeLists.txt b/src/wx/CMakeLists.txt index 1913f995..b848389c 100644 --- a/src/wx/CMakeLists.txt +++ b/src/wx/CMakeLists.txt @@ -659,6 +659,20 @@ list(APPEND VBAM_LOCALIZABLE_FILES ${CMAKE_SOURCE_DIR}/src/core/gba/gbaLink.cpp ) +if(WIN32 AND (X86_64 OR X86_32) AND ENABLE_XAUDIO2) + if(NOT DEFINED XAUDIO_27_BIN_DIR) + set(XAUDIO_27_BIN_DIR ${CMAKE_SOURCE_DIR}/win32-deps/xaudio27-dll) + endif() + + if(X86_64) + set(XAUDIO_27_DLL ${XAUDIO_27_BIN_DIR}/x64/XAudio2_7.dll) + elseif(X86_32) + set(XAUDIO_27_DLL ${XAUDIO_27_BIN_DIR}/x86/XAudio2_7.dll) + endif() + + configure_file(audio/internal/xaudio27-dll-path.h.in ${CMAKE_BINARY_DIR}/xaudio27-dll-path.h) +endif() + if(APPLE) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks") diff --git a/src/wx/audio/internal/xaudio2.cpp b/src/wx/audio/internal/xaudio2.cpp index 338fa6ec..d87f68c9 100644 --- a/src/wx/audio/internal/xaudio2.cpp +++ b/src/wx/audio/internal/xaudio2.cpp @@ -2,9 +2,11 @@ #error "This file should only be compiled if XAudio2 is enabled" #endif +#include "wx/audio/internal/xaudio27-dll-rc.h" #include "wx/audio/internal/xaudio2.h" #include +#include #include #include @@ -19,8 +21,17 @@ #endif #include +#include +#include +#include +#include +#include #include +#include +#include +#include #include +#include #include "core/base/sound_driver.h" #include "core/base/system.h" // for systemMessage() @@ -199,6 +210,7 @@ public: void device_change(); + inline static wxString temp_dir_path; private: void close(); @@ -221,6 +233,10 @@ private: volatile bool device_changed; + wxDynamicLibrary xaudio2_dll; + typedef HRESULT (*func_XAudio2Create)(IXAudio2**, UINT32); + func_XAudio2Create dll_XAudio2Create = nullptr; + IXAudio2* xaud; IXAudio2MasteringVoice* mVoice; // listener IXAudio2SourceVoice* sVoice; // sound source @@ -245,11 +261,41 @@ XAudio2_Output::XAudio2_Output() { ZeroMemory(&buf, sizeof(buf)); ZeroMemory(&vState, sizeof(vState)); g_notifier.do_register(this); + + HRSRC res = FindResource(wxGetInstance(), MAKEINTRESOURCE(XAUDIO27_DLL_RC), RT_RCDATA); + + if (!res) + wxLogFatalError("Could not find resource for 'XAudio2_7.dll'."); + + HGLOBAL res_handle = LoadResource(NULL, res); + + if (!res_handle) + wxLogFatalError("Could not find resource for 'XAudio2_7.dll'."); + + uint64_t res_size = SizeofResource(NULL, res); + + char *res_data = (char *)LockResource(res_handle); + + wxString pid = wxString{} << wxProcessEvent{}.GetPid(); + temp_dir_path = wxFileName::GetTempDir() + "/visualboyadvance-m/" + pid; + wxDir{}.Make(temp_dir_path, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL); + wxString dll_path = temp_dir_path + "/XAudio2_7.dll"; + wxFile dll(dll_path, wxFile::write); + dll.Write((void *)res_data, res_size); + dll.Close(); + + xaudio2_dll.Load(dll_path, wxDL_VERBATIM | wxDL_QUIET); + dll_XAudio2Create = reinterpret_cast(xaudio2_dll.GetSymbol("XAudio2Create")); } XAudio2_Output::~XAudio2_Output() { g_notifier.do_unregister(this); close(); + + HMODULE hmod = xaudio2_dll.Detach(); + while(::FreeLibrary(hmod)) { + wxMilliSleep(50); + } } void XAudio2_Output::close() { @@ -291,7 +337,7 @@ bool XAudio2_Output::init(long sampleRate) { HRESULT hr; // Initialize XAudio2 - hr = XAudio2Create(&xaud, 0); + hr = dll_XAudio2Create(&xaud, 0); if (hr != S_OK) { wxLogError(_("The XAudio2 interface failed to initialize!")); diff --git a/src/wx/audio/internal/xaudio27-dll-path.h.in b/src/wx/audio/internal/xaudio27-dll-path.h.in new file mode 100644 index 00000000..203dad04 --- /dev/null +++ b/src/wx/audio/internal/xaudio27-dll-path.h.in @@ -0,0 +1 @@ +#define XAUDIO27_DLL_PATH "@XAUDIO_27_DLL@" diff --git a/src/wx/audio/internal/xaudio27-dll-rc.h b/src/wx/audio/internal/xaudio27-dll-rc.h new file mode 100644 index 00000000..444c773e --- /dev/null +++ b/src/wx/audio/internal/xaudio27-dll-rc.h @@ -0,0 +1,6 @@ +#ifndef XAUDIO27_RC_H +#define XAUDIO27_RC_H + +#define XAUDIO27_DLL_RC 301 + +#endif /* XAUDIO27_RC_H */ diff --git a/src/wx/wxvbam.rc b/src/wx/wxvbam.rc index 427cb8e9..4ee7a9d9 100644 --- a/src/wx/wxvbam.rc +++ b/src/wx/wxvbam.rc @@ -19,8 +19,11 @@ AAAAA_MAINICON ICON "icons/visualboyadvance-m.ico" #include "autoupdater/wxmsw/winsparkle-rc.h" #include "winsparkle-path.h" +#include "audio/internal/xaudio27-dll-rc.h" +#include "xaudio27-dll-path.h" WINSPARKLE_DLL_RC RCDATA WINSPARKLE_DLL_PATH +XAUDIO27_DLL_RC RCDATA XAUDIO27_DLL_PATH #endif /* NO_ONLINEUPDATES */ diff --git a/win32-deps b/win32-deps index 0a1cdd9c..b9cfd0b1 160000 --- a/win32-deps +++ b/win32-deps @@ -1 +1 @@ -Subproject commit 0a1cdd9c04f7727e2d477b070e846c5b971761de +Subproject commit b9cfd0b1ea6108c65c175e380a8c35e620ac1f24