cellGem: implement quaternion transformation

This commit is contained in:
Megamouse 2024-11-29 05:38:44 +01:00
parent 3d11b6efa3
commit a31ebc248e
18 changed files with 606 additions and 50 deletions

4
.gitmodules vendored
View File

@ -100,3 +100,7 @@
path = 3rdparty/opencv/opencv
url = ../../Megamouse/opencv_minimal.git
ignore = dirty
[submodule "3rdparty/fusion/fusion"]
path = 3rdparty/fusion/fusion
url = ../../xioTechnologies/Fusion.git
ignore = dirty

View File

@ -346,6 +346,9 @@ add_subdirectory(rtmidi EXCLUDE_FROM_ALL)
# OPENCV
add_subdirectory(opencv EXCLUDE_FROM_ALL)
# FUSION
add_subdirectory(fusion EXCLUDE_FROM_ALL)
# add nice ALIAS targets for ease of use
if(USE_SYSTEM_LIBUSB)
add_library(3rdparty::libusb ALIAS usb-1.0-shared)
@ -377,3 +380,4 @@ add_library(3rdparty::sdl2 ALIAS ${SDL2_TARGET})
add_library(3rdparty::miniupnpc ALIAS libminiupnpc-static)
add_library(3rdparty::rtmidi ALIAS rtmidi)
add_library(3rdparty::opencv ALIAS ${OPENCV_TARGET})
add_library(3rdparty::fusion ALIAS Fusion)

1
3rdparty/fusion/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1 @@
add_subdirectory(fusion EXCLUDE_FROM_ALL)

1
3rdparty/fusion/fusion vendored Submodule

@ -0,0 +1 @@
Subproject commit fecf2f0af3bd23cbba553ceedc2bc6c1cd410fc1

75
3rdparty/fusion/fusion.vcxproj vendored Normal file
View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClInclude Include="fusion\Fusion\Fusion.h" />
<ClInclude Include="fusion\Fusion\FusionAhrs.h" />
<ClInclude Include="fusion\Fusion\FusionAxes.h" />
<ClInclude Include="fusion\Fusion\FusionCalibration.h" />
<ClInclude Include="fusion\Fusion\FusionCompass.h" />
<ClInclude Include="fusion\Fusion\FusionConvention.h" />
<ClInclude Include="fusion\Fusion\FusionMath.h" />
<ClInclude Include="fusion\Fusion\FusionOffset.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="fusion\Fusion\FusionAhrs.c" />
<ClCompile Include="fusion\Fusion\FusionCompass.c" />
<ClCompile Include="fusion\Fusion\FusionOffset.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<RootNamespace>Fusion</RootNamespace>
<ProjectGuid>{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}</ProjectGuid>
</PropertyGroup>
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default_macros.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
</PropertyGroup>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_default.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<ExceptionHandling>Sync</ExceptionHandling>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
</ClCompile>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

29
3rdparty/fusion/fusion.vcxproj.filters vendored Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="fusion\Fusion\Fusion.h" />
<ClInclude Include="fusion\Fusion\FusionAhrs.h" />
<ClInclude Include="fusion\Fusion\FusionAxes.h" />
<ClInclude Include="fusion\Fusion\FusionCalibration.h" />
<ClInclude Include="fusion\Fusion\FusionCompass.h" />
<ClInclude Include="fusion\Fusion\FusionConvention.h" />
<ClInclude Include="fusion\Fusion\FusionMath.h" />
<ClInclude Include="fusion\Fusion\FusionOffset.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="fusion\Fusion\FusionAhrs.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="fusion\Fusion\FusionCompass.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="fusion\Fusion\FusionOffset.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -7,6 +7,7 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vcxproj", "{C4A10229-4712-4BD2-B63E-50D93C67A038}"
ProjectSection(ProjectDependencies) = postProject
{2C902C67-985C-4BE0-94A3-E0FE2EB929A3} = {2C902C67-985C-4BE0-94A3-E0FE2EB929A3}
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {3C67A2FF-4710-402A-BE3E-31B0CB0576DF}
{5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0} = {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}
{8846A9AA-5539-4C91-8301-F54260E1A07A} = {8846A9AA-5539-4C91-8301-F54260E1A07A}
{939FE206-1182-ABC3-1234-FEAB88E98404} = {939FE206-1182-ABC3-1234-FEAB88E98404}
@ -46,6 +47,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
{2C902C67-985C-4BE0-94A3-E0FE2EB929A3} = {2C902C67-985C-4BE0-94A3-E0FE2EB929A3}
{3384223A-6D97-4799-9862-359F85312892} = {3384223A-6D97-4799-9862-359F85312892}
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {3C67A2FF-4710-402A-BE3E-31B0CB0576DF}
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}
{508C291A-3D18-49F5-B25D-F7C8DB92CB21} = {508C291A-3D18-49F5-B25D-F7C8DB92CB21}
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C} = {5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}
@ -103,6 +105,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "7zip", "3rdparty\7zip\7zip.
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openal-soft", "3rdparty\openal\openal-soft.vcxproj", "{8846A9AA-5539-4C91-8301-F54260E1A07A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fusion", "3rdparty\fusion\fusion.vcxproj", "{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -211,6 +215,10 @@ Global
{8846A9AA-5539-4C91-8301-F54260E1A07A}.Debug|x64.Build.0 = Debug|x64
{8846A9AA-5539-4C91-8301-F54260E1A07A}.Release|x64.ActiveCfg = Release|x64
{8846A9AA-5539-4C91-8301-F54260E1A07A}.Release|x64.Build.0 = Release|x64
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Debug|x64.ActiveCfg = Debug|x64
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Debug|x64.Build.0 = Debug|x64
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Release|x64.ActiveCfg = Release|x64
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -243,6 +251,7 @@ Global
{4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{8846A9AA-5539-4C91-8301-F54260E1A07A} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06CC7920-E085-4B81-9582-8DE8AAD42510}

View File

@ -82,6 +82,7 @@ target_sources(rpcs3
Input/mm_joystick_handler.cpp
Input/pad_thread.cpp
Input/product_info.cpp
Input/ps_move_calibration.cpp
Input/ps_move_config.cpp
Input/ps_move_handler.cpp
Input/ps_move_tracker.cpp
@ -110,6 +111,7 @@ target_link_libraries(rpcs3
3rdparty::libcurl
3rdparty::zlib
3rdparty::opencv
3rdparty::fusion
${ADDITIONAL_LIBS})
# Unix display manager

View File

@ -903,7 +903,7 @@ static inline void pos_to_gem_image_state(u32 gem_num, const gem_config::gem_con
}
}
static inline void pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max, const ps_move_data& move_data)
{
const auto& shared_data = g_fxo->get<gem_camera_shared>();
@ -932,16 +932,28 @@ static inline void pos_to_gem_state(u32 gem_num, const gem_config::gem_controlle
gem_state->pos[2] = controller.distance_mm;
gem_state->pos[3] = 0.f;
gem_state->quat[0] = 320.f - image_x;
gem_state->quat[1] = (y_pos / scaling_width) - 180.f;
gem_state->quat[2] = 1200.f;
// TODO: calculate handle position based on our world coordinate and the angles
gem_state->handle_pos[0] = camera_x;
gem_state->handle_pos[1] = camera_y;
gem_state->handle_pos[2] = controller.distance_mm + 10.0f;
gem_state->handle_pos[3] = 0.f;
// Calculate orientation
if (g_cfg.io.move == move_handler::real)
{
gem_state->quat[0] = move_data.quaternion[1]; // x
gem_state->quat[1] = move_data.quaternion[2]; // y
gem_state->quat[2] = move_data.quaternion[3]; // z
gem_state->quat[3] = move_data.quaternion[0]; // w
}
else
{
gem_state->quat[0] = 320.f - image_x;
gem_state->quat[1] = (y_pos / scaling_width) - 180.f;
gem_state->quat[2] = 1200.f;
gem_state->quat[3] = 1.f;
}
if (g_cfg.io.show_move_cursor)
{
draw_overlay_cursor(gem_num, controller, x_pos, y_pos, x_max, y_max);
@ -1056,7 +1068,7 @@ static inline void ds3_get_stick_values(u32 gem_num, const std::shared_ptr<Pad>&
}
template <typename T>
static void ds3_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, T& gem_state)
static void ds3_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& controller, T& gem_state)
{
if (!gem_state || !is_input_allowed())
{
@ -1078,7 +1090,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller&
if constexpr (std::is_same_v<T, vm::ptr<CellGemState>>)
{
pos_to_gem_state(gem_num, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
pos_to_gem_state(gem_num, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y, {});
}
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
{
@ -1087,7 +1099,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller&
}
template <typename T>
static void ps_move_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, T& gem_state)
static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& controller, T& gem_state)
{
if (!gem_state || !is_input_allowed())
{
@ -1114,7 +1126,7 @@ static void ps_move_pos_to_gem_state(u32 gem_num, const gem_config::gem_controll
gem_state->accel[1] = pad->move_data.accelerometer_y * 1000; // linear velocity in mm/s²
gem_state->accel[2] = pad->move_data.accelerometer_z * 1000; // linear velocity in mm/s²
pos_to_gem_state(gem_num, controller, gem_state, info.x_pos, info.y_pos, info.x_max, info.y_max);
pos_to_gem_state(gem_num, controller, gem_state, info.x_pos, info.y_pos, info.x_max, info.y_max, pad->move_data);
}
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
{
@ -1272,7 +1284,7 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
}
template <typename T>
static void mouse_pos_to_gem_state(u32 mouse_no, const gem_config::gem_controller& controller, T& gem_state)
static void mouse_pos_to_gem_state(u32 mouse_no, gem_config::gem_controller& controller, T& gem_state)
{
if (!gem_state || !is_input_allowed())
{
@ -1295,7 +1307,7 @@ static void mouse_pos_to_gem_state(u32 mouse_no, const gem_config::gem_controlle
if constexpr (std::is_same_v<T, vm::ptr<CellGemState>>)
{
pos_to_gem_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
pos_to_gem_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max, {});
}
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
{
@ -1345,7 +1357,7 @@ static bool gun_input_to_pad(u32 gem_no, be_t<u16>& digital_buttons, be_t<u16>&
}
template <typename T>
static void gun_pos_to_gem_state(u32 gem_no, const gem_config::gem_controller& controller, T& gem_state)
static void gun_pos_to_gem_state(u32 gem_no, gem_config::gem_controller& controller, T& gem_state)
{
if (!gem_state || !is_input_allowed())
return;
@ -1363,7 +1375,7 @@ static void gun_pos_to_gem_state(u32 gem_no, const gem_config::gem_controller& c
if constexpr (std::is_same_v<T, vm::ptr<CellGemState>>)
{
pos_to_gem_state(gem_no, controller, gem_state, x_pos, y_pos, x_max, y_max);
pos_to_gem_state(gem_no, controller, gem_state, x_pos, y_pos, x_max, y_max, {});
}
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
{
@ -1800,7 +1812,7 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
if (g_cfg.io.move != move_handler::null)
{
auto& shared_data = g_fxo->get<gem_camera_shared>();
const auto& controller = gem.controllers[gem_num];
auto& controller = gem.controllers[gem_num];
gem_image_state->frame_timestamp = shared_data.frame_timestamp_us.load();
gem_image_state->timestamp = gem_image_state->frame_timestamp + 10;
@ -2130,7 +2142,6 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
gem_state->timestamp = (get_guest_system_time() - gem.start_timestamp_us);
gem_state->camera_pitch_angle = 0.f;
gem_state->quat[3] = 1.f;
switch (g_cfg.io.move)
{

View File

@ -466,12 +466,13 @@ struct ps_move_data
bool external_device_read_requested = false;
bool external_device_write_requested = false;
std::array<f32, 4> quaternion { 1.0f, 0.0f, 0.0f, 0.0f }; // quaternion orientation (x,y,z,w) of controller relative to default (facing the camera with buttons up)
f32 accelerometer_x = 0; // linear velocity in m/s²
f32 accelerometer_y = 0; // linear velocity in m/s²
f32 accelerometer_z = 0; // linear velocity in m/s²
f32 gyro_x = 0; // linear velocity in m/s²
f32 gyro_y = 0; // linear velocity in m/s²
f32 gyro_z = 0; // linear velocity in m/s²
f32 gyro_x = 0; // angular velocity in rad/s
f32 gyro_y = 0; // angular velocity in rad/s
f32 gyro_z = 0; // angular velocity in rad/s
s16 temperature = 0;
};

View File

@ -0,0 +1,240 @@
#include "stdafx.h"
#include "ps_move_calibration.h"
LOG_CHANNEL(move_log, "Move");
// This is basically the same as in ps move api
static inline s32 psmove_calibration_decode_16bit_unsigned(const u8* data, u32 offset)
{
const u8 low = data[offset] & 0xFF;
const u8 high = (data[offset + 1]) & 0xFF;
return (low | (high << 8)) - zero_shift;
}
static inline s16 psmove_calibration_decode_16bit_signed(const u8* data, u32 offset)
{
const u16 low = data[offset] & 0xFF;
const u16 high = (data[offset + 1]) & 0xFF;
return static_cast<s16>(low | (high << 8));
}
static inline u32 psmove_calibration_decode_12bits(const u8* data, u32 offset)
{
const u8 low = data[offset] & 0xFF;
const u8 high = (data[offset + 1]) & 0xFF;
return low | (high << 8);
}
static inline f32 psmove_calibration_decode_float(const u8* data, u32 offset)
{
union
{
uint32_t u32;
float f;
} v {
.u32 = static_cast<u32>( (data[offset] & 0xFF) |
((data[offset + 1] & 0xFF) << 8) |
((data[offset + 2] & 0xFF) << 16) |
((data[offset + 3] & 0xFF) << 24))
};
return v.f;
}
static void psmove_dump_calibration(const reports::ps_move_calibration_blob& calibration, const ps_move_device& device)
{
int t, x, y, z;
float fx, fy, fz;
const u8* data = calibration.data.data();
switch (device.model)
{
case ps_move_model::ZCM1:
t = psmove_calibration_decode_12bits(data, 0x02);
move_log.error("Temperature: 0x%04X", t);
for (int orientation = 0; orientation < 6; orientation++)
{
x = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * orientation);
y = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * orientation + 2);
z = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * orientation + 4);
move_log.error("Orientation #%d: (%5d | %5d | %5d)", orientation, x, y, z);
}
t = psmove_calibration_decode_12bits(data, 0x42);
move_log.error("Temperature: 0x%04X", t);
for (int orientation = 0; orientation < 3; orientation++)
{
x = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * orientation);
y = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * orientation + 2);
z = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * orientation + 4);
move_log.error("Gyro %c, 80 rpm: (%5d | %5d | %5d)", "XYZ"[orientation], x, y, z);
}
t = psmove_calibration_decode_12bits(data, 0x28);
x = psmove_calibration_decode_16bit_unsigned(data, 0x2a);
y = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 2);
z = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 4);
move_log.error("Temperature: 0x%04X", t);
move_log.error("Gyro, 0 rpm (@0x2a): (%5d | %5d | %5d)", x, y, z);
t = psmove_calibration_decode_12bits(data, 0x30);
x = psmove_calibration_decode_16bit_unsigned(data, 0x32);
y = psmove_calibration_decode_16bit_unsigned(data, 0x32 + 2);
z = psmove_calibration_decode_16bit_unsigned(data, 0x32 + 4);
move_log.error("Temperature: 0x%04X", t);
move_log.error("Gyro, 0 rpm (@0x32): (%5d | %5d | %5d)", x, y, z);
t = psmove_calibration_decode_12bits(data, 0x5c);
fx = psmove_calibration_decode_float(data, 0x5e);
fy = psmove_calibration_decode_float(data, 0x5e + 4);
fz = psmove_calibration_decode_float(data, 0x5e + 8);
move_log.error("Temperature: 0x%04X", t);
move_log.error("Vector @0x5e: (%f | %f | %f)", fx, fy, fz);
fx = psmove_calibration_decode_float(data, 0x6a);
fy = psmove_calibration_decode_float(data, 0x6a + 4);
fz = psmove_calibration_decode_float(data, 0x6a + 8);
move_log.error("Vector @0x6a: (%f | %f | %f)", fx, fy, fz);
move_log.error("byte @0x3f: 0x%02x", static_cast<u8>(data[0x3f]));
move_log.error("float @0x76: %f", psmove_calibration_decode_float(data, 0x76));
move_log.error("float @0x7a: %f", psmove_calibration_decode_float(data, 0x7a));
break;
case ps_move_model::ZCM2:
for (int orientation = 0; orientation < 6; orientation++)
{
x = psmove_calibration_decode_16bit_signed(data, 0x04 + 6 * orientation);
y = psmove_calibration_decode_16bit_signed(data, 0x04 + 6 * orientation + 2);
z = psmove_calibration_decode_16bit_signed(data, 0x04 + 6 * orientation + 4);
move_log.error("Orientation #%d: (%5d | %5d | %5d)", orientation, x, y, z);
}
x = psmove_calibration_decode_16bit_signed(data, 0x26);
y = psmove_calibration_decode_16bit_signed(data, 0x26 + 2);
z = psmove_calibration_decode_16bit_signed(data, 0x26 + 4);
move_log.error("Gyro Bias?, 0 rpm (@0x26): (%5d | %5d | %5d)", x, y, z);
for (int orientation = 0; orientation < 6; orientation++)
{
x = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * orientation);
y = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * orientation + 2);
z = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * orientation + 4);
move_log.error("Gyro %c, 90 rpm: (%5d | %5d | %5d)", "XYZXYZ"[orientation], x, y, z);
}
break;
}
}
void psmove_calibration_get_usb_accel_values(const reports::ps_move_calibration_blob& calibration, ps_move_device& device)
{
const u8* data = calibration.data.data();
int x1 = 0, x2 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0;
switch (device.model)
{
case ps_move_model::ZCM1:
// Minimum (negative) value of each axis
x1 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 1);
y1 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 5 + 2);
z1 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 2 + 4);
// Maximum (positive) value of each axis
x2 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 3);
y2 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 4 + 2);
z2 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 0 + 4);
break;
case ps_move_model::ZCM2:
// Minimum (negative) value of each axis
x1 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 1);
y1 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 3 + 2);
z1 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 5 + 4);
// Maximum (positive) value of each axis
x2 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 0);
y2 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 2 + 2);
z2 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 4 + 4);
break;
}
device.calibration.accel_x_factor = 2.0f / static_cast<float>(x2 - x1);
device.calibration.accel_y_factor = 2.0f / static_cast<float>(y2 - y1);
device.calibration.accel_z_factor = 2.0f / static_cast<float>(z2 - z1);
device.calibration.accel_x_offset = -(device.calibration.accel_x_factor * static_cast<float>(x1)) - 1.0f;
device.calibration.accel_y_offset = -(device.calibration.accel_y_factor * static_cast<float>(x1)) - 1.0f;
device.calibration.accel_z_offset = -(device.calibration.accel_z_factor * static_cast<float>(x1)) - 1.0f;
}
void psmove_calibration_get_usb_gyro_values(const reports::ps_move_calibration_blob& calibration, ps_move_device& device)
{
const u8* data = calibration.data.data();
constexpr f32 PI = 3.14159265f;
constexpr f32 rpm_to_rad_per_sec = (2.0f * PI) / 60.0f;
switch (device.model)
{
case ps_move_model::ZCM1:
{
const int bx = psmove_calibration_decode_16bit_unsigned(data, 0x2a);
const int by = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 2);
const int bz = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 4);
const int x = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * 0) - bx;
const int y = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * 1 + 2) - by;
const int z = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * 2 + 4) - bz;
constexpr f32 calibration_rpm = 80.0f;
constexpr f32 factor = calibration_rpm * rpm_to_rad_per_sec;
// Per frame drift taken into account using adjusted gain values
device.calibration.gyro_x_gain = factor / static_cast<float>(x);
device.calibration.gyro_y_gain = factor / static_cast<float>(y);
device.calibration.gyro_z_gain = factor / static_cast<float>(z);
device.calibration.gyro_x_offset = 0;
device.calibration.gyro_y_offset = 0;
device.calibration.gyro_z_offset = 0;
break;
}
case ps_move_model::ZCM2:
{
// Minimum (negative) value of each axis
const int x1 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 3);
const int y1 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 4 + 2);
const int z1 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 5 + 4);
// Maximum (positive) values of each axis
const int x2 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 0);
const int y2 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 1 + 2);
const int z2 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 2 + 4);
const int dx = psmove_calibration_decode_16bit_signed(data, 0x26);
const int dy = psmove_calibration_decode_16bit_signed(data, 0x26 + 2);
const int dz = psmove_calibration_decode_16bit_signed(data, 0x26 + 4);
constexpr f32 calibration_rpm = 90.0f;
constexpr f32 calibration_hi = calibration_rpm * rpm_to_rad_per_sec;
constexpr f32 calibration_low = -calibration_rpm * rpm_to_rad_per_sec;
constexpr f32 factor = calibration_hi - calibration_low;
// Compute the gain value (the slope of the gyro reading/angular speed line)
device.calibration.gyro_x_gain = factor / static_cast<f32>(x2 - x1);
device.calibration.gyro_y_gain = factor / static_cast<f32>(y2 - y1);
device.calibration.gyro_z_gain = factor / static_cast<f32>(z2 - z1);
device.calibration.gyro_x_offset = static_cast<f32>(dx);
device.calibration.gyro_y_offset = static_cast<f32>(dy);
device.calibration.gyro_z_offset = static_cast<f32>(dz);
break;
}
}
}
void psmove_parse_calibration(const reports::ps_move_calibration_blob& calibration, ps_move_device& device)
{
psmove_dump_calibration(calibration, device);
psmove_calibration_get_usb_accel_values(calibration, device);
psmove_calibration_get_usb_gyro_values(calibration, device);
}

View File

@ -0,0 +1,5 @@
#pragma once
#include "ps_move_handler.h"
void psmove_parse_calibration(const reports::ps_move_calibration_blob& calibration, ps_move_device& device);

View File

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "ps_move_handler.h"
#include "ps_move_calibration.h"
#include "Emu/Io/pad_config.h"
#include "Emu/System.h"
#include "Emu/system_config.h"
@ -57,11 +58,6 @@ namespace
usb_charging = 0xEE,
usb_charged = 0xEF,
};
enum
{
zero_shift = 0x8000,
};
}
const ps_move_input_report_common& ps_move_device::input_report_common() const
@ -223,7 +219,7 @@ hid_device* ps_move_handler::connect_move_device(ps_move_device* device, std::st
if (hid_set_nonblocking(device->bt_device, 1) == -1)
{
move_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->bt_device));
move_log.error("connect_move_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->bt_device));
device->close();
return nullptr;
}
@ -239,7 +235,7 @@ hid_device* ps_move_handler::connect_move_device(ps_move_device* device, std::st
if (hid_set_nonblocking(device->hidDevice, 1) == -1)
{
move_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->hidDevice));
move_log.error("connect_move_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->hidDevice));
device->close();
return nullptr;
}
@ -315,6 +311,60 @@ void ps_move_handler::check_add_device(hid_device* hidDevice, std::string_view p
device->hidDevice = hidDevice;
device->path = path;
// Get calibration
device->calibration.is_valid = true;
ps_move_calibration_blob calibration {};
for (int i = 0; i < 2; i++)
{
std::array<u8, PSMOVE_CALIBRATION_SIZE> cal {};
cal[0] = 0x10;
const int res = hid_get_feature_report(device->hidDevice, cal.data(), cal.size());
if (res < 0)
{
move_log.error("connect_move_device: hid_get_feature_report 0x10 (calibration) failed! result=%d, error=%s", res, hid_error(device->hidDevice));
device->calibration.is_valid = false;
break;
}
int src_offset = 0;
int dest_offset = 0;
if ((cal[1] == 0x01 && device->model == ps_move_model::ZCM1) ||
(cal[1] == 0x81 && device->model == ps_move_model::ZCM2))
{
// This is the second block
dest_offset = PSMOVE_CALIBRATION_SIZE;
src_offset = 2;
}
else if (cal[1] == 0x82 && device->model == ps_move_model::ZCM1)
{
// This is the third block
dest_offset = 2 * PSMOVE_CALIBRATION_SIZE - 2;
src_offset = 2;
}
else if (cal[1] != 0x00) // Check if this is the first block (offsets stay 0)
{
move_log.error("connect_move_device: Failed to read calibration: cal=0x%x'", cal[1]);
device->calibration.is_valid = false;
break;
}
std::memcpy(&calibration.data[dest_offset], &cal[src_offset], cal.size() - src_offset);
}
if (device->calibration.is_valid)
{
psmove_parse_calibration(calibration, *device);
}
// Initialize Fusion
FusionAhrsInitialise(&device->ahrs);
device->ahrs.settings.convention = FusionConvention::FusionConventionEnu;
FusionAhrsSetSettings(&device->ahrs, &device->ahrs.settings);
FusionAhrsReset(&device->ahrs);
// Activate
if (send_output_report(device) == -1)
{
@ -620,34 +670,48 @@ void ps_move_handler::get_extended_info(const pad_ensemble& binding)
const ps_move_input_report_common& input = dev->input_report_common();
constexpr f32 MOVE_ONE_G = 4096.0f; // This is just a rough estimate and probably depends on the device
// The default position is flat on the ground, pointing forward.
// The accelerometers constantly measure G forces.
// The gyros measure changes in orientation and will reset when the device isn't moved anymore.
s16 accel_x = input.accel_x_2; // Increases if the device is rolled to the left
s16 accel_y = input.accel_y_2; // Increases if the device is pitched upwards
s16 accel_z = input.accel_z_2; // Increases if the device is moved upwards
s16 gyro_x = input.gyro_x_2; // Increases if the device is pitched upwards
s16 gyro_y = input.gyro_y_2; // Increases if the device is rolled to the right
s16 gyro_z = input.gyro_z_2; // Increases if the device is yawed to the left
s16 accel_x = input.accel_x_1; // Increases if the device is rolled to the left
s16 accel_y = input.accel_y_1; // Increases if the device is pitched upwards
s16 accel_z = input.accel_z_1; // Increases if the device is moved upwards
s16 gyro_x = input.gyro_x_1; // Increases if the device is pitched upwards
s16 gyro_y = input.gyro_y_1; // Increases if the device is rolled to the right
s16 gyro_z = input.gyro_z_1; // Increases if the device is yawed to the left
if (dev->model == ps_move_model::ZCM1)
{
accel_x -= zero_shift;
accel_y -= zero_shift;
accel_z -= zero_shift;
gyro_x -= zero_shift;
gyro_y -= zero_shift;
gyro_z -= zero_shift;
accel_x = (input.accel_x_1 + input.accel_x_2) / 2 - zero_shift;
accel_y = (input.accel_y_1 + input.accel_y_2) / 2 - zero_shift;
accel_z = (input.accel_z_1 + input.accel_z_2) / 2 - zero_shift;
gyro_x = (input.gyro_x_1 + input.gyro_x_2) / 2 - zero_shift;
gyro_y = (input.gyro_y_1 + input.gyro_y_2) / 2 - zero_shift;
gyro_z = (input.gyro_z_1 + input.gyro_z_2) / 2 - zero_shift;
}
// Apply calibration
if (dev->calibration.is_valid)
{
pad->move_data.accelerometer_x = accel_x * dev->calibration.accel_x_factor + dev->calibration.accel_x_offset;
pad->move_data.accelerometer_y = accel_y * dev->calibration.accel_y_factor + dev->calibration.accel_y_offset;
pad->move_data.accelerometer_z = accel_z * dev->calibration.accel_z_factor + dev->calibration.accel_z_offset;
pad->move_data.gyro_x = (gyro_x - dev->calibration.gyro_x_offset) * dev->calibration.gyro_x_gain;
pad->move_data.gyro_y = (gyro_y - dev->calibration.gyro_y_offset) * dev->calibration.gyro_y_gain;
pad->move_data.gyro_z = (gyro_z - dev->calibration.gyro_z_offset) * dev->calibration.gyro_z_gain;
}
else
{
constexpr f32 MOVE_ONE_G = 4096.0f; // This is just a rough estimate and probably depends on the device
pad->move_data.accelerometer_x = accel_x / MOVE_ONE_G;
pad->move_data.accelerometer_y = accel_y / MOVE_ONE_G;
pad->move_data.accelerometer_z = accel_z / MOVE_ONE_G;
pad->move_data.gyro_x = gyro_x / MOVE_ONE_G;
pad->move_data.gyro_y = gyro_y / MOVE_ONE_G;
pad->move_data.gyro_z = gyro_z / MOVE_ONE_G;
}
pad->move_data.accelerometer_x = accel_x / MOVE_ONE_G;
pad->move_data.accelerometer_y = accel_y / MOVE_ONE_G;
pad->move_data.accelerometer_z = accel_z / MOVE_ONE_G;
pad->move_data.gyro_x = accel_x / MOVE_ONE_G;
pad->move_data.gyro_y = accel_y / MOVE_ONE_G;
pad->move_data.gyro_z = accel_z / MOVE_ONE_G;
pad->move_data.temperature = ((input.temperature << 4) | ((input.magnetometer_x & 0xF0) >> 4));
pad->m_sensors[0].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * pad->move_data.accelerometer_x * -1.0f));
@ -655,6 +719,58 @@ void ps_move_handler::get_extended_info(const pad_ensemble& binding)
pad->m_sensors[2].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * pad->move_data.accelerometer_z));
pad->m_sensors[3].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * pad->move_data.gyro_z * -1.0f));
// Get elapsed time since last update
const u64 now_us = get_system_time();
const float elapsed_sec = (dev->last_ahrs_update_time_us == 0) ? 0.0f : ((now_us - dev->last_ahrs_update_time_us) / 1'000'000.0f);
dev->last_ahrs_update_time_us = now_us;
// The ps move handler's axis may differ from the Fusion axis, so we have to map them correctly.
// Don't ask how the axis work. It's basically been trial and error.
ensure(dev->ahrs.settings.convention == FusionConvention::FusionConventionEnu); // East-North-Up
const FusionVector accelerometer{
.axis {
.x = -pad->move_data.accelerometer_x,
.y = +pad->move_data.accelerometer_y,
.z = +pad->move_data.accelerometer_z
}
};
static constexpr f32 PI = 3.14159265f;
const auto rad_to_degree = [](f32 radians) -> f32 { return radians * 180.0f / PI; };
const FusionVector gyroscope{
.axis {
.x = +rad_to_degree(pad->move_data.gyro_x),
.y = +rad_to_degree(pad->move_data.gyro_z),
.z = -rad_to_degree(pad->move_data.gyro_y)
}
};
FusionVector magnetometer {};
// TODO: use magnetometer if possible
//if (dev->model == ps_move_model::ZCM1)
//{
// const ps_move_input_report_ZCM1& input = dev->input_report_ZCM1;
// magnetometer = FusionVector{
// .axis {
// .x = input.magnetometer_x2,
// .y = input.magnetometer_y,
// .z = input.magnetometer_z
// }
// };
//}
// Update Fusion
FusionAhrsUpdate(&dev->ahrs, gyroscope, accelerometer, magnetometer, elapsed_sec);
// Get quaternion
const FusionQuaternion quaternion = FusionAhrsGetQuaternion(&dev->ahrs);
pad->move_data.quaternion[0] = quaternion.array[0];
pad->move_data.quaternion[1] = quaternion.array[1];
pad->move_data.quaternion[2] = quaternion.array[2];
pad->move_data.quaternion[3] = quaternion.array[3];
handle_external_device(binding);
}

View File

@ -2,6 +2,15 @@
#include "hid_pad_handler.h"
#ifndef _MSC_VER
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif
#include "3rdparty/fusion/fusion/Fusion/Fusion.h"
#ifndef _MSC_VER
#pragma GCC diagnostic pop
#endif
#include <unordered_map>
namespace reports
@ -80,14 +89,50 @@ namespace reports
{
std::array<u8, 4> data{}; // TODO
};
// Buffer size for calibration data
constexpr u32 PSMOVE_CALIBRATION_SIZE = 49;
// Three blocks, minus header (2 bytes) for blocks 2,3
constexpr u32 PSMOVE_ZCM1_CALIBRATION_BLOB_SIZE = PSMOVE_CALIBRATION_SIZE * 3 - 2 * 2;
// Three blocks, minus header (2 bytes) for block 2
constexpr u32 PSMOVE_ZCM2_CALIBRATION_BLOB_SIZE = PSMOVE_CALIBRATION_SIZE * 2 - 2 * 1;
struct ps_move_calibration_blob
{
std::array<u8, std::max(PSMOVE_ZCM1_CALIBRATION_BLOB_SIZE, PSMOVE_ZCM2_CALIBRATION_BLOB_SIZE)> data{};
};
}
enum
{
zero_shift = 0x8000,
};
enum class ps_move_model
{
ZCM1, // PS3
ZCM2, // PS4
};
struct ps_move_calibration
{
bool is_valid = false;
f32 accel_x_factor = 1.0f;
f32 accel_y_factor = 1.0f;
f32 accel_z_factor = 1.0f;
f32 accel_x_offset = 0.0f;
f32 accel_y_offset = 0.0f;
f32 accel_z_offset = 0.0f;
f32 gyro_x_gain = 1.0f;
f32 gyro_y_gain = 1.0f;
f32 gyro_z_gain = 1.0f;
f32 gyro_x_offset = 0.0f;
f32 gyro_y_offset = 0.0f;
f32 gyro_z_offset = 0.0f;
};
class ps_move_device : public HidDevice
{
public:
@ -98,6 +143,10 @@ public:
reports::ps_move_output_report last_output_report{};
steady_clock::time_point last_output_report_time;
u32 external_device_id = 0;
ps_move_calibration calibration{};
FusionAhrs ahrs {}; // Used to calculate quaternions from sensor data
u64 last_ahrs_update_time_us = 0; // Last ahrs update
const reports::ps_move_input_report_common& input_report_common() const;
};

View File

@ -40,7 +40,7 @@
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<AdditionalIncludeDirectories>..\3rdparty\miniupnp\miniupnp\miniupnpc\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\flatbuffers\include;..\3rdparty\libusb\libusb\libusb;..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\zlib\zlib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm\include;$(VULKAN_SDK)\Include;..\3rdparty\zstd\zstd\lib</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\3rdparty\miniupnp\miniupnp\miniupnpc\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\flatbuffers\include;..\3rdparty\libusb\libusb\libusb;..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\zlib\zlib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm\include;$(VULKAN_SDK)\Include;..\3rdparty\zstd\zstd\lib;$(SolutionDir)3rdparty\fusion\fusion\Fusion</AdditionalIncludeDirectories>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AL_LIBTYPE_STATIC;MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;ZLIB_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AL_LIBTYPE_STATIC;MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;ZLIB_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions>

View File

@ -62,12 +62,12 @@
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include</IncludePath>
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include;$(SolutionDir)3rdparty\fusion\fusion\Fusion</IncludePath>
<LibraryPath>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)</LibraryPath>
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include</IncludePath>
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include;$(SolutionDir)3rdparty\fusion\fusion\Fusion</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
@ -89,7 +89,7 @@
<ExternalWarningLevel>TurnOffAllWarnings</ExternalWarningLevel>
</ClCompile>
<Link>
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Core.lib;Qt6Gui.lib;Qt6Widgets.lib;Qt6Concurrent.lib;Qt6Multimedia.lib;Qt6MultimediaWidgets.lib;Qt6Svg.lib;Qt6SvgWidgets.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Core.lib;Qt6Gui.lib;Qt6Widgets.lib;Qt6Concurrent.lib;Qt6Multimedia.lib;Qt6MultimediaWidgets.lib;Qt6Svg.lib;Qt6SvgWidgets.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;fusion.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\lib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\glslang;$(SolutionDir)build\lib_ext\$(CONFIGURATION)-$(PLATFORM);$(SolutionDir)3rdparty\discord-rpc\lib;$(QTDIR)\lib;$(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
@ -141,7 +141,7 @@
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Cored.lib;Qt6Guid.lib;Qt6Widgetsd.lib;Qt6Concurrentd.lib;Qt6Multimediad.lib;Qt6MultimediaWidgetsd.lib;Qt6Svgd.lib;Qt6SvgWidgetsd.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Cored.lib;Qt6Guid.lib;Qt6Widgetsd.lib;Qt6Concurrentd.lib;Qt6Multimediad.lib;Qt6MultimediaWidgetsd.lib;Qt6Svgd.lib;Qt6SvgWidgetsd.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;fusion.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\lib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\glslang;$(SolutionDir)3rdparty\discord-rpc\lib;$(SolutionDir)build\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;$(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /VERBOSE %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
@ -179,6 +179,7 @@
<ClCompile Include="Input\evdev_gun_handler.cpp" />
<ClCompile Include="Input\gui_pad_thread.cpp" />
<ClCompile Include="Input\hid_pad_handler.cpp" />
<ClCompile Include="Input\ps_move_calibration.cpp" />
<ClCompile Include="Input\ps_move_config.cpp" />
<ClCompile Include="Input\ps_move_tracker.cpp" />
<ClCompile Include="Input\raw_mouse_config.cpp" />
@ -971,6 +972,7 @@
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
</CustomBuild>
<ClInclude Include="Input\ps_move_calibration.h" />
<ClInclude Include="Input\ps_move_config.h" />
<ClInclude Include="Input\ps_move_tracker.h" />
<ClInclude Include="Input\raw_mouse_config.h" />

View File

@ -1143,6 +1143,9 @@
<ClCompile Include="Input\ps_move_config.cpp">
<Filter>Io\Move</Filter>
</ClCompile>
<ClCompile Include="Input\ps_move_calibration.cpp">
<Filter>Io\Move</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Input\ds4_pad_handler.h">
@ -1343,6 +1346,9 @@
<ClInclude Include="Input\ps_move_config.h">
<Filter>Io\Move</Filter>
</ClInclude>
<ClInclude Include="Input\ps_move_calibration.h">
<Filter>Io\Move</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">

View File

@ -160,4 +160,5 @@ target_link_libraries(rpcs3_ui
3rdparty::wolfssl
3rdparty::libcurl
3rdparty::opencv
3rdparty::fusion
3rdparty::rtmidi)