diff --git a/src/spice2x/games/sdvx/sdvx.cpp b/src/spice2x/games/sdvx/sdvx.cpp index 0e15b3c..802b51e 100644 --- a/src/spice2x/games/sdvx/sdvx.cpp +++ b/src/spice2x/games/sdvx/sdvx.cpp @@ -48,7 +48,7 @@ namespace games::sdvx { SdvxOverlayPosition OVERLAY_POS = SDVX_OVERLAY_BOTTOM; bool ENABLE_COM_PORT_SCAN_HOOK = false; - std::optional SOUND_OUTPUT_DEVICE = std::nullopt; + bool USE_ASIO = false; std::optional ASIO_DRIVER = std::nullopt; // states @@ -57,13 +57,22 @@ namespace games::sdvx { static HKEY real_asio_device_reg_handle = nullptr; static LONG WINAPI RegOpenKeyA_hook(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult) { - if (lpSubKey != nullptr && phkResult != nullptr) { - if (hKey == HKEY_LOCAL_MACHINE && - ASIO_DRIVER.has_value() && - _stricmp(lpSubKey, "software\\asio") == 0) - { - *phkResult = PARENT_ASIO_REG_HANDLE; + if (lpSubKey != nullptr && + phkResult != nullptr && + hKey == HKEY_LOCAL_MACHINE && + _stricmp(lpSubKey, "software\\asio") == 0) { + // prevent the game from randomly picking an ASIO device + if (!USE_ASIO) { + log_info( + "sdvx::asio", + "game tried to access HKLM\\SOFTWARE\\ASIO but ASIO is disabled; " + "access prevented, ASIO init will fail"); + return ERROR_FILE_NOT_FOUND; + } + // convince the game to use our hook (so we can swap in the preferred device) + if (ASIO_DRIVER.has_value()) { + *phkResult = PARENT_ASIO_REG_HANDLE; return RegOpenKeyA_orig(hKey, lpSubKey, &real_asio_reg_handle); } } @@ -110,7 +119,7 @@ namespace games::sdvx { lpSubKey != nullptr && phkResult != nullptr && _stricmp(lpSubKey, "HARDWARE\\DEVICEMAP\\SERIALCOMM") == 0) { log_info("sdvx::io", "hook access to HKLM\\HARDWARE\\DEVICEMAP\\SERIALCOMM to force COM1 ICCA"); - return 2; // ERROR_FILE_NOT_FOUND + return ERROR_FILE_NOT_FOUND; } return RegOpenKeyExA_orig(hKey, lpSubKey, ulOptions, samDesired, phkResult); @@ -230,6 +239,32 @@ namespace games::sdvx { return false; } + void SDVXGame::detect_sound_output_device() { + USE_ASIO = false; + // if the user specified a value for -sdvxasio, use asio + if (ASIO_DRIVER.has_value()) { + log_misc( + "sdvx", + "-sdvxasio is set to \"{}\"", ASIO_DRIVER.value()); + USE_ASIO = true; + } else { + // see if XONAR AE is present; if so, use that + HKEY subkey; + LSTATUS result; + result = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\ASIO\\XONAR SOUND CARD(64)", &subkey); + if (result == ERROR_SUCCESS) { + RegCloseKey(subkey); + USE_ASIO = true; + log_misc( + "sdvx", + "found HKLM\\SOFTWARE\\ASIO\\XONAR SOUND CARD(64)"); + } + } + if (!USE_ASIO) { + log_misc("sdvx", "asio not configured"); + } + } + typedef void **(__fastcall *volume_set_t)(uint64_t, uint64_t, uint64_t); static volume_set_t volume_set_orig = nullptr; static void **__fastcall volume_set_hook(uint64_t vol_sound, uint64_t vol_woofer, uint64_t vol_headphone) { @@ -323,6 +358,10 @@ namespace games::sdvx { } #endif +#ifdef SPICE64 + this->detect_sound_output_device(); +#endif + } void SDVXGame::attach() { diff --git a/src/spice2x/games/sdvx/sdvx.h b/src/spice2x/games/sdvx/sdvx.h index 98b7440..e6fa328 100644 --- a/src/spice2x/games/sdvx/sdvx.h +++ b/src/spice2x/games/sdvx/sdvx.h @@ -39,5 +39,6 @@ namespace games::sdvx { // not depend on the fact that SDVX module is active (since it can be // inactive on cabs or partial I/O setup) bool VALKYRIE_MODEL = false; + void detect_sound_output_device(); }; }