mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
drs: rgb camera hook (#524)
## Link to GitHub Issue, if one exists n/a ## Description of change Add plug&play hooks for RGB camera in DRS. ## Testing Seems to work with my crappy Logitech C270 Camera options (brightness etc) seem to work in test menu as well). Tested by another user with realsense camera + logitech camera, both cams were detected correctly.
This commit is contained in:
@@ -441,6 +441,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
games/scotto/io.cpp
|
games/scotto/io.cpp
|
||||||
games/drs/drs.cpp
|
games/drs/drs.cpp
|
||||||
games/drs/io.cpp
|
games/drs/io.cpp
|
||||||
|
games/drs/rgb_cam.cpp
|
||||||
games/we/we.cpp
|
games/we/we.cpp
|
||||||
games/we/io.cpp
|
games/we/io.cpp
|
||||||
games/we/touchpanel.cpp
|
games/we/touchpanel.cpp
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "util/detour.h"
|
#include "util/detour.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/memutils.h"
|
#include "util/memutils.h"
|
||||||
|
#include "rgb_cam.h"
|
||||||
|
|
||||||
#pragma pack(push)
|
#pragma pack(push)
|
||||||
|
|
||||||
@@ -150,6 +151,7 @@ namespace games::drs {
|
|||||||
char DRS_TAPELED[DRS_TAPELED_COLS_TOTAL][3] {};
|
char DRS_TAPELED[DRS_TAPELED_COLS_TOTAL][3] {};
|
||||||
bool DISABLE_TOUCH = false;
|
bool DISABLE_TOUCH = false;
|
||||||
bool TRANSPOSE_TOUCH = false;
|
bool TRANSPOSE_TOUCH = false;
|
||||||
|
bool RGB_CAMERA_HOOK = false;
|
||||||
|
|
||||||
std::vector<TouchEvent> TOUCH_EVENTS;
|
std::vector<TouchEvent> TOUCH_EVENTS;
|
||||||
|
|
||||||
@@ -313,6 +315,10 @@ namespace games::drs {
|
|||||||
} else {
|
} else {
|
||||||
log_info("drs", "no native input method detected");
|
log_info("drs", "no native input method detected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RGB_CAMERA_HOOK) {
|
||||||
|
init_rgb_camera_hook();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DRSGame::detach() {
|
void DRSGame::detach() {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ namespace games::drs {
|
|||||||
extern std::vector<TouchEvent> TOUCH_EVENTS;
|
extern std::vector<TouchEvent> TOUCH_EVENTS;
|
||||||
extern bool DISABLE_TOUCH;
|
extern bool DISABLE_TOUCH;
|
||||||
extern bool TRANSPOSE_TOUCH;
|
extern bool TRANSPOSE_TOUCH;
|
||||||
|
extern bool RGB_CAMERA_HOOK;
|
||||||
|
|
||||||
void fire_touches(drs_touch_t *events, size_t event_count);
|
void fire_touches(drs_touch_t *events, size_t event_count);
|
||||||
void start_touch();
|
void start_touch();
|
||||||
|
|||||||
@@ -0,0 +1,170 @@
|
|||||||
|
#include "games/drs/rgb_cam.h"
|
||||||
|
|
||||||
|
// set version to Windows 7 to enable Media Foundation functions
|
||||||
|
#ifdef _WIN32_WINNT
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#endif
|
||||||
|
#define _WIN32_WINNT 0x0601
|
||||||
|
|
||||||
|
// turn on C-style COM objects
|
||||||
|
#define CINTERFACE
|
||||||
|
|
||||||
|
#include <mfobjects.h>
|
||||||
|
#include <mfidl.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "avs/game.h"
|
||||||
|
#include "cfg/configurator.h"
|
||||||
|
#include "hooks/cfgmgr32hook.h"
|
||||||
|
#include "util/detour.h"
|
||||||
|
#include "util/memutils.h"
|
||||||
|
#include "util/logging.h"
|
||||||
|
#include "util/utils.h"
|
||||||
|
|
||||||
|
static VTBL_TYPE(IMFActivate, GetAllocatedString) GetAllocatedString_orig = nullptr;
|
||||||
|
static decltype(MFEnumDeviceSources) *MFEnumDeviceSources_orig = nullptr;
|
||||||
|
|
||||||
|
namespace games::drs {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Camera related stuff
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
// log the cam name
|
||||||
|
log_misc("drs::rgbcam", "obtained {}", ws2s(*ppwszValue));
|
||||||
|
|
||||||
|
// 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';
|
||||||
|
|
||||||
|
log_misc("drs::rgbcam", "replaced {}", ws2s(*ppwszValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
// return original result
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hook_camera(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_8086&DEV_8C2D";
|
||||||
|
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);
|
||||||
|
|
||||||
|
log_info("drs::rgbcam", "hooked camera @ {}", ws2s(camera_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hook_camera_vtable(IMFActivate *camera) {
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get camera
|
||||||
|
IMFActivate *camera = **pppSourceActivate;
|
||||||
|
|
||||||
|
// save original method for later use
|
||||||
|
if (GetAllocatedString_orig == nullptr) {
|
||||||
|
GetAllocatedString_orig = camera->lpVtbl->GetAllocatedString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hook allocated string method for camera identification
|
||||||
|
hook_camera_vtable(camera);
|
||||||
|
|
||||||
|
// get camera link
|
||||||
|
LPWSTR camera_link_lpwstr;
|
||||||
|
UINT32 camera_link_length;
|
||||||
|
if (SUCCEEDED(GetAllocatedString_orig(
|
||||||
|
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);
|
||||||
|
|
||||||
|
log_info("drs::rgbcam", "found video capture device: {}", ws2s(camera_link_ws));
|
||||||
|
|
||||||
|
// only support cameras that start with \\?\usb
|
||||||
|
if (!string_begins_with(camera_link_ws, L"\\\\?\\usb")) {
|
||||||
|
return result_orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_id, camera_instance);
|
||||||
|
} else {
|
||||||
|
log_warning("drs::rgbcam", "failed to open camera");
|
||||||
|
}
|
||||||
|
|
||||||
|
// return result
|
||||||
|
return result_orig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_rgb_camera_hook() {
|
||||||
|
log_info("drs::rgbcam", "initializing camera hook");
|
||||||
|
|
||||||
|
cfgmgr32hook_init(avs::game::DLL_INSTANCE);
|
||||||
|
|
||||||
|
// camera media framework hook
|
||||||
|
MFEnumDeviceSources_orig = detour::iat_try(
|
||||||
|
"MFEnumDeviceSources", MFEnumDeviceSources_hook, avs::game::DLL_INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace games::drs {
|
||||||
|
void init_rgb_camera_hook();
|
||||||
|
}
|
||||||
@@ -1118,6 +1118,9 @@ int main_implementation(int argc, char *argv[]) {
|
|||||||
if (options[launcher::Options::spice2x_DRSTransposeTouch].value_bool()) {
|
if (options[launcher::Options::spice2x_DRSTransposeTouch].value_bool()) {
|
||||||
games::drs::TRANSPOSE_TOUCH = true;
|
games::drs::TRANSPOSE_TOUCH = true;
|
||||||
}
|
}
|
||||||
|
if (options[launcher::Options::DRSRGBCameraHook].value_bool()) {
|
||||||
|
games::drs::RGB_CAMERA_HOOK = true;
|
||||||
|
}
|
||||||
if (options[launcher::Options::spice2x_AutoCard].is_active()) {
|
if (options[launcher::Options::spice2x_AutoCard].is_active()) {
|
||||||
const auto text = options[launcher::Options::spice2x_AutoCard].value_text();
|
const auto text = options[launcher::Options::spice2x_AutoCard].value_text();
|
||||||
if (text == "p1") {
|
if (text == "p1") {
|
||||||
|
|||||||
@@ -2219,6 +2219,17 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
|||||||
.game_name = "DANCERUSH",
|
.game_name = "DANCERUSH",
|
||||||
.category = "Game Options",
|
.category = "Game Options",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// DRSRGBCameraHook
|
||||||
|
.title = "DRS RGB Camera Hook",
|
||||||
|
.name = "drsrgbcamhook",
|
||||||
|
.desc = "Hook into the RGB camera detection and attempt to use your own non-official webcam. "
|
||||||
|
"Not every webcam will be compatible with this; YMMV.\n\n"
|
||||||
|
"Note: this is NOT for the motion camera - you still need a real RealSense camera for that!",
|
||||||
|
.type = OptionType::Bool,
|
||||||
|
.game_name = "DANCERUSH",
|
||||||
|
.category = "Game Options",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// spice2x_IIDXNativeTouch
|
// spice2x_IIDXNativeTouch
|
||||||
.title = "IIDX Native Touch Handling",
|
.title = "IIDX Native Touch Handling",
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ namespace launcher {
|
|||||||
spice2x_IIDXWindowedTDJ,
|
spice2x_IIDXWindowedTDJ,
|
||||||
spice2x_DRSDisableTouch,
|
spice2x_DRSDisableTouch,
|
||||||
spice2x_DRSTransposeTouch,
|
spice2x_DRSTransposeTouch,
|
||||||
|
DRSRGBCameraHook,
|
||||||
spice2x_IIDXNativeTouch,
|
spice2x_IIDXNativeTouch,
|
||||||
spice2x_IIDXNoSub,
|
spice2x_IIDXNoSub,
|
||||||
spice2x_IIDXEmulateSubscreenKeypadTouch,
|
spice2x_IIDXEmulateSubscreenKeypadTouch,
|
||||||
|
|||||||
Reference in New Issue
Block a user