diff --git a/CMakeLists.txt b/CMakeLists.txt index 31bc5b6..5c5a668 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 3.20) project(XboxAudio2 LANGUAGES CXX ASM_MASM) +add_subdirectory(lib) file(GLOB_RECURSE XAUDIO_SOURCES CONFIGURE_DEPENDS "include/*.h" "source/*.cpp" "source/*.h" "source/*.asm") add_library(XAudio2_9 SHARED ${XAUDIO_SOURCES}) @@ -12,3 +13,6 @@ target_link_libraries(XAudio2_9 PRIVATE ${FFMPEG_LIBRARIES}) find_package(wil CONFIG REQUIRED) target_link_libraries(XAudio2_9 PRIVATE WIL::WIL) + +target_link_directories(XAudio2_9 PRIVATE lib) +target_link_libraries(XAudio2_9 PRIVATE kernelx) diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..bb9c022 --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,2 @@ +*.exp +*.lib diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..2eb4cd5 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,18 @@ +file(GLOB DEF_FILES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/*.def") +cmake_path(CONVERT "${DEF_FILES}" TO_NATIVE_PATH_LIST DEF_FILES) + +foreach(DEF_FILE ${DEF_FILES}) + get_filename_component(DEF_NAME_WE "${DEF_FILE}" NAME_WE) + + execute_process( + COMMAND lib + /machine:x64 + "/def:${DEF_FILE}" + "/out:${CMAKE_CURRENT_SOURCE_DIR}\\${DEF_NAME_WE}.lib" + RESULT_VARIABLE LIB_RESULT + ERROR_VARIABLE LIB_ERROR) + + if(NOT LIB_RESULT EQUAL 0) + message(FATAL_ERROR "${LIB_ERROR}") + endif() +endforeach() diff --git a/lib/kernelx.def b/lib/kernelx.def new file mode 100644 index 0000000..173c53a --- /dev/null +++ b/lib/kernelx.def @@ -0,0 +1,3 @@ +LIBRARY kernelx.dll +EXPORTS + GetVersionExW diff --git a/source/xaudio2.cpp b/source/xaudio2.cpp index 932e66d..7783d96 100644 --- a/source/xaudio2.cpp +++ b/source/xaudio2.cpp @@ -47,25 +47,38 @@ BOOL WINAPI DllMain( _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) { + OSVERSIONINFOW OsVersion = { sizeof(OsVersion) }; + if (fdwReason != DLL_PROCESS_ATTACH) return TRUE; - // TODO: Dynamic check -#if 1 - OrdinalProc1 = GetProcAddress(hinstDLL, "CreateAudioReverb"); - OrdinalProc2 = GetProcAddress(hinstDLL, "CreateAudioVolumeMeter"); - OrdinalProc3 = GetProcAddress(hinstDLL, "CreateFX"); - OrdinalProc4 = GetProcAddress(hinstDLL, "CreateXAudio2Object"); - OrdinalProc5 = GetProcAddress(hinstDLL, "X3DAudioCalculate"); - OrdinalProc6 = GetProcAddress(hinstDLL, "X3DAudioInitialize"); -#else - OrdinalProc1 = GetProcAddress(hinstDLL, "XAudio2Create"); - OrdinalProc2 = GetProcAddress(hinstDLL, "CreateAudioReverb"); - OrdinalProc3 = GetProcAddress(hinstDLL, "CreateAudioVolumeMeter"); - OrdinalProc4 = GetProcAddress(hinstDLL, "CreateFX"); - OrdinalProc5 = GetProcAddress(hinstDLL, "X3DAudioCalculate"); - OrdinalProc6 = GetProcAddress(hinstDLL, "X3DAudioInitialize"); -#endif + // This should link to kernelx.dll!GetVersionExW. +#pragma warning(suppress : 28159) + if (!GetVersionExW(&OsVersion)) + return FALSE; + + // 6.2.10698.0 is the oldest known OS version with CreateXAudio2Object. + if (OsVersion.dwMajorVersion > 6 || + (OsVersion.dwMajorVersion == 6 && OsVersion.dwMinorVersion > 2) || + (OsVersion.dwMajorVersion == 6 && OsVersion.dwMinorVersion == 2 && OsVersion.dwBuildNumber >= 10698)) + { + OrdinalProc1 = GetProcAddress(hinstDLL, "CreateAudioReverb"); + OrdinalProc2 = GetProcAddress(hinstDLL, "CreateAudioVolumeMeter"); + OrdinalProc3 = GetProcAddress(hinstDLL, "CreateFX"); + OrdinalProc4 = GetProcAddress(hinstDLL, "CreateXAudio2Object"); + OrdinalProc5 = GetProcAddress(hinstDLL, "X3DAudioCalculate"); + OrdinalProc6 = GetProcAddress(hinstDLL, "X3DAudioInitialize"); + } + else + { + OrdinalProc1 = GetProcAddress(hinstDLL, "XAudio2Create"); + OrdinalProc2 = GetProcAddress(hinstDLL, "CreateAudioReverb"); + OrdinalProc3 = GetProcAddress(hinstDLL, "CreateAudioVolumeMeter"); + OrdinalProc4 = GetProcAddress(hinstDLL, "CreateFX"); + OrdinalProc5 = GetProcAddress(hinstDLL, "X3DAudioCalculate"); + OrdinalProc6 = GetProcAddress(hinstDLL, "X3DAudioInitialize"); + } + return TRUE; }