From 1ad45edd6e5af315c51ed94571a537fd37c933da Mon Sep 17 00:00:00 2001 From: bicarus-dev <202771338+bicarus-dev@users.noreply.github.com> Date: Sat, 9 Aug 2025 03:01:10 -0700 Subject: [PATCH] sdvx: remove -sdvxdisablecams, simplify camera hook (#350) ## Link to GitHub Issue, if one exists #345 ## Description of change Simplify camera hook in SDVX5/6. Camera hook will always be installed and return 0 cameras. Deprecate `-sdvxdisablecams` option as it is no longer needed as a result of this change. ## Testing Tested SDVX5 final, SDVX6 year 1, and a recent SDVX6 build. --- src/spice2x/games/sdvx/camera.cpp | 122 ++---------------------------- src/spice2x/games/sdvx/sdvx.cpp | 13 ++-- src/spice2x/games/sdvx/sdvx.h | 1 - src/spice2x/launcher/launcher.cpp | 3 - src/spice2x/launcher/options.cpp | 7 +- 5 files changed, 17 insertions(+), 129 deletions(-) diff --git a/src/spice2x/games/sdvx/camera.cpp b/src/spice2x/games/sdvx/camera.cpp index 20762e1..7d1c1fb 100644 --- a/src/spice2x/games/sdvx/camera.cpp +++ b/src/spice2x/games/sdvx/camera.cpp @@ -14,134 +14,24 @@ #include #include "avs/game.h" -#include "hooks/cfgmgr32hook.h" #include "util/detour.h" -#include "util/memutils.h" #include "util/utils.h" -static VTBL_TYPE(IMFActivate, GetAllocatedString) GetAllocatedString_orig = nullptr; - -static decltype(MFEnumDeviceSources) *MFEnumDeviceSources_orig = nullptr; - namespace games::sdvx { - static std::wstring CAMERA0_ID; - - static HRESULT WINAPI GetAllocatedString_hook(IMFActivate* This, REFGUID guidKey, LPWSTR *ppwszValue, - UINT32 *pcchLength) { - // call the original - HRESULT result = GetAllocatedString_orig(This, guidKey, ppwszValue, pcchLength); - - // try first camera - wchar_t *pwc = nullptr; - if (CAMERA0_ID.length() == 23) - pwc = wcsstr(*ppwszValue, CAMERA0_ID.c_str()); - - // check if camera could be identified - if (pwc) { - - // fake the USB IDs - pwc[4] = L'2'; - pwc[5] = L'8'; - pwc[6] = L'8'; - pwc[7] = L'c'; - pwc[13] = L'0'; - pwc[14] = L'0'; - pwc[15] = L'0'; - pwc[16] = L'2'; - pwc[21] = L'0'; - pwc[22] = L'0'; - } - - // return original result - return result; - } - - static void hook_camera(IMFActivate* camera, size_t no, std::wstring camera_id, std::string camera_instance) { - - // don't hook if camera 0 is already hooked - if (CAMERA0_ID.length() > 0) - return; - - // save the camera ID - CAMERA0_ID = camera_id; - - // cfgmgr hook - CFGMGR32_HOOK_SETTING camera_setting; - camera_setting.device_instance = 0xDEADBEEF; - camera_setting.parent_instance = ~camera_setting.device_instance; - camera_setting.device_id = "USB\\VEN_1022&DEV_7908"; - camera_setting.device_node_id = "USB\\VID_288C&PID_0002&MI_00\\?&????????&?&????"; - if (camera_instance.length() == 17) { - for (int i = 0; i < 17; i++) { - camera_setting.device_node_id[28 + i] = camera_instance[i]; - } - } - cfgmgr32hook_add(camera_setting); - - // save original method for later use - if (GetAllocatedString_orig == nullptr) { - GetAllocatedString_orig = camera->lpVtbl->GetAllocatedString; - } - - // hook allocated string method for camera identification - memutils::VProtectGuard camera_guard(camera->lpVtbl); - camera->lpVtbl->GetAllocatedString = GetAllocatedString_hook; - } - static HRESULT WINAPI MFEnumDeviceSources_hook(IMFAttributes *pAttributes, IMFActivate ***pppSourceActivate, UINT32 *pcSourceActivate) { - // call original function - HRESULT result_orig = MFEnumDeviceSources_orig(pAttributes, pppSourceActivate, pcSourceActivate); - - // check for capture devices - if (FAILED(result_orig) || !*pcSourceActivate) { - return result_orig; - } - - // iterate cameras - size_t cam_hook_num = 0; - for (size_t cam_num = 0; cam_num < *pcSourceActivate && cam_hook_num < 1; cam_num++) { - - // flip - size_t cam_num_flipped = cam_num; - - // get camera link - IMFActivate *camera = (*pppSourceActivate)[cam_num_flipped]; - LPWSTR camera_link_lpwstr; - UINT32 camera_link_length; - if (SUCCEEDED(camera->lpVtbl->GetAllocatedString( - camera, - MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, - &camera_link_lpwstr, - &camera_link_length))) { - - // cut name to make ID - std::wstring camera_link_ws = std::wstring(camera_link_lpwstr); - std::wstring camera_id = camera_link_ws.substr(8, 23); - - // get camera instance - std::string camera_link = ws2s(camera_link_ws); - std::string camera_instance = camera_link.substr(32, 17); - - // hook the camera - hook_camera(camera, cam_hook_num, camera_id, camera_instance); - - // increase camera hook number - cam_hook_num++; - - } - } - - // return result - return result_orig; + *pppSourceActivate = nullptr; + *pcSourceActivate = 0; + log_misc("sdvx", "MFEnumDeviceSources_hook called, returning 0 cameras"); + return S_OK; } void camera_init() { // camera media framework hook - MFEnumDeviceSources_orig = detour::iat_try( - "MFEnumDeviceSources", MFEnumDeviceSources_hook, avs::game::DLL_INSTANCE); + log_info("sdvx", "installing camera hooks..."); + detour::iat_try("MFEnumDeviceSources", MFEnumDeviceSources_hook, avs::game::DLL_INSTANCE); } } diff --git a/src/spice2x/games/sdvx/sdvx.cpp b/src/spice2x/games/sdvx/sdvx.cpp index 0bd77ec..1936142 100644 --- a/src/spice2x/games/sdvx/sdvx.cpp +++ b/src/spice2x/games/sdvx/sdvx.cpp @@ -39,7 +39,6 @@ namespace games::sdvx { const char *ORIGINAL_ASIO_DEVICE_NAME = "XONAR SOUND CARD(64)"; // settings - bool DISABLECAMS = false; bool NATIVETOUCH = false; uint8_t DIGITAL_KNOB_SENS = 16; SdvxOverlayPosition OVERLAY_POS = SDVX_OVERLAY_BOTTOM; @@ -369,17 +368,17 @@ namespace games::sdvx { winuser_hook_init(avs::game::DLL_INSTANCE); // hook camera - if (!DISABLECAMS) { - camera_init(); - } + camera_init(); - // RGB CAMERA error ignore - if (!replace_pattern( + // RGB CAMERA error ignore for SDVX5 + // SDVX5: boot sequence triggers camera error if camera is not detected + // SDVX6: boots fine, but game title screen in attract loop will have camera error (cosmetic only) + if (replace_pattern( avs::game::DLL_INSTANCE, "418D480484C074218D51FD", "????????????9090??????", 0, 0)) { - log_info("sdvx", "did not find matching signature for camera error patch"); + log_info("sdvx", "applied camera error patch (sdvx5)"); } // remove log spam diff --git a/src/spice2x/games/sdvx/sdvx.h b/src/spice2x/games/sdvx/sdvx.h index 86faed4..32f5655 100644 --- a/src/spice2x/games/sdvx/sdvx.h +++ b/src/spice2x/games/sdvx/sdvx.h @@ -17,7 +17,6 @@ namespace games::sdvx { }; // settings - extern bool DISABLECAMS; extern bool NATIVETOUCH; extern uint8_t DIGITAL_KNOB_SENS; extern std::optional ASIO_DRIVER; diff --git a/src/spice2x/launcher/launcher.cpp b/src/spice2x/launcher/launcher.cpp index a8df23e..ebedc9c 100644 --- a/src/spice2x/launcher/launcher.cpp +++ b/src/spice2x/launcher/launcher.cpp @@ -433,9 +433,6 @@ int main_implementation(int argc, char *argv[]) { if (options[launcher::Options::LoadSoundVoltexModule].value_bool()) { attach_sdvx = true; } - if (options[launcher::Options::SDVXDisableCameras].value_bool()) { - games::sdvx::DISABLECAMS = true; - } if (options[launcher::Options::SDVXNativeTouch].value_bool()) { games::sdvx::NATIVETOUCH = true; } diff --git a/src/spice2x/launcher/options.cpp b/src/spice2x/launcher/options.cpp index 32b4e99..8a6f9ad 100644 --- a/src/spice2x/launcher/options.cpp +++ b/src/spice2x/launcher/options.cpp @@ -717,10 +717,13 @@ static const std::vector OPTION_DEFINITIONS = { .category = "Game Options (Advanced)", }, { - .title = "SDVX Disable Cameras", + .title = "SDVX Disable Cameras (DEPRECATED - no longer needed)", .name = "sdvxdisablecams", - .desc = "Disables cameras", + .desc = "This option does nothing.\n\n" + "This option was used in the past to fix cameras in SDVX5 but this is no longer " + "needed as camera check will always be skipped with a built-in patch.", .type = OptionType::Bool, + .hidden = true, .game_name = "Sound Voltex", .category = "Game Options", },