mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
Merge branch 'master' into cellAdec
This commit is contained in:
commit
8d4a0537ae
45 changed files with 997 additions and 131 deletions
|
@ -71,13 +71,14 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
|||
git clone https://github.com/engnr/qt-downloader.git
|
||||
cd qt-downloader
|
||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||
# nested Qt 6.8.0 URL workaround
|
||||
sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
# nested Qt 6.8.1 URL workaround
|
||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
cd "/tmp/Qt"
|
||||
"$BREW_X64_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml
|
||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||
"$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats
|
||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.8.1 workaround
|
||||
"$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
||||
fi
|
||||
|
||||
cd "$WORKDIR"
|
||||
|
|
|
@ -39,13 +39,14 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
|||
git clone https://github.com/engnr/qt-downloader.git
|
||||
cd qt-downloader
|
||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||
# nested Qt 6.8.0 URL workaround
|
||||
sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
# nested Qt 6.8.1 URL workaround
|
||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||
cd "/tmp/Qt"
|
||||
"$BREW_X64_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml
|
||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||
"$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats
|
||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.8.1 workaround
|
||||
"$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
||||
fi
|
||||
|
||||
cd "$WORKDIR"
|
||||
|
|
|
@ -77,7 +77,7 @@ for url in $DEP_URLS; do
|
|||
|
||||
# shellcheck disable=SC1003
|
||||
case "$url" in
|
||||
*qt*) checksum=$(curl -fL "${url}.sha1"); algo="sha1"; outDir='C:\Qt\' ;;
|
||||
*qt*) checksum=$(curl -fL "${url}.sha1"); algo="sha1"; outDir="$QTDIR/" ;;
|
||||
*llvm*) checksum=$(curl -fL "${url}.sha256"); algo="sha256"; outDir="./build/lib_ext/Release-x64" ;;
|
||||
*glslang*) checksum=$(curl -fL "${url}.sha256"); algo="sha256"; outDir="./build/lib_ext/Release-x64" ;;
|
||||
*Vulkan*)
|
||||
|
|
|
@ -7,7 +7,7 @@ env:
|
|||
BUILD_SOURCEBRANCHNAME: $CIRRUS_BRANCH
|
||||
RPCS3_TOKEN: ENCRYPTED[100ebb8e3552bf2021d0ef55dccda3e58d27be5b6cab0b0b92843ef490195d3c4edaefa087e4a3b425caa6392300b9b1]
|
||||
QT_VER_MAIN: '6'
|
||||
QT_VER: '6.8.0'
|
||||
QT_VER: '6.8.1'
|
||||
|
||||
# windows_task:
|
||||
# matrix:
|
||||
|
@ -21,7 +21,7 @@ env:
|
|||
# COMPILER: msvc
|
||||
# BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}\artifacts\
|
||||
# QT_VER_MSVC: 'msvc2022'
|
||||
# QT_DATE: '202410030750'
|
||||
# QT_DATE: '202411221531'
|
||||
# QTDIR: C:\Qt\${QT_VER}\${QT_VER_MSVC}_64
|
||||
# VULKAN_VER: '1.3.268.0'
|
||||
# VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
||||
|
|
4
.gitmodules
vendored
4
.gitmodules
vendored
|
@ -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
|
||||
|
|
4
3rdparty/CMakeLists.txt
vendored
4
3rdparty/CMakeLists.txt
vendored
|
@ -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
1
3rdparty/fusion/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
add_subdirectory(fusion EXCLUDE_FROM_ALL)
|
1
3rdparty/fusion/fusion
vendored
Submodule
1
3rdparty/fusion/fusion
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit fecf2f0af3bd23cbba553ceedc2bc6c1cd410fc1
|
75
3rdparty/fusion/fusion.vcxproj
vendored
Normal file
75
3rdparty/fusion/fusion.vcxproj
vendored
Normal 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
29
3rdparty/fusion/fusion.vcxproj.filters
vendored
Normal 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>
|
10
BUILDING.md
10
BUILDING.md
|
@ -19,26 +19,26 @@ The following tools are required to build RPCS3 on Windows 10 or later:
|
|||
with standalone **CMake** tool.
|
||||
|
||||
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
|
||||
- [Qt 6.8.0](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
|
||||
- [Qt 6.8.1](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
|
||||
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
||||
|
||||
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
|
||||
|
||||
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
|
||||
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.8.0\msvc2022_64\`
|
||||
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.8.1\msvc2022_64\`
|
||||
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
|
||||
|
||||
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
|
||||
|
||||
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
|
||||
- add and set the `CMAKE_PREFIX_PATH` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.8.0\msvc2022_64\`
|
||||
- add and set the `CMAKE_PREFIX_PATH` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.8.1\msvc2022_64\`
|
||||
|
||||
### Linux
|
||||
|
||||
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
|
||||
- Clang 17+ or GCC 13+
|
||||
- [CMake 3.28.0+](https://www.cmake.org/download/)
|
||||
- [Qt 6.8.0](https://www.qt.io/download-qt-installer)
|
||||
- [Qt 6.8.1](https://www.qt.io/download-qt-installer)
|
||||
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
||||
- [SDL2](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
|
||||
|
||||
|
@ -119,7 +119,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
|
|||
##### Configuring the Qt Plugin (if used)
|
||||
|
||||
1) go to `Extensions->Qt VS Tools->Qt Versions`
|
||||
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.8.0\msvc2022_64`, version will fill in automatically
|
||||
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.8.1\msvc2022_64`, version will fill in automatically
|
||||
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
|
||||
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
|
||||
|
||||
|
|
|
@ -69,9 +69,9 @@ jobs:
|
|||
variables:
|
||||
COMPILER: msvc
|
||||
QT_VER_MAIN: '6'
|
||||
QT_VER: '6.8.0'
|
||||
QT_VER: '6.8.1'
|
||||
QT_VER_MSVC: 'msvc2022'
|
||||
QT_DATE: '202410030750'
|
||||
QT_DATE: '202411221531'
|
||||
QTDIR: C:\Qt\$(QT_VER)\$(QT_VER_MSVC)_64
|
||||
VULKAN_VER: '1.3.268.0'
|
||||
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
||||
|
@ -132,7 +132,7 @@ jobs:
|
|||
UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-mac"
|
||||
RELEASE_MESSAGE: "../GitHubReleaseMessage.txt"
|
||||
ARTDIR: $(Build.ArtifactStagingDirectory)
|
||||
QT_VER: '6.8.0'
|
||||
QT_VER: '6.7.3'
|
||||
QT_VER_MAIN: '6'
|
||||
LLVM_COMPILER_VER: '16'
|
||||
|
||||
|
@ -193,7 +193,7 @@ jobs:
|
|||
UPLOAD_REPO_FULL_NAME: "RPCS3/rpcs3-binaries-mac-arm64"
|
||||
RELEASE_MESSAGE: "../GitHubReleaseMessage.txt"
|
||||
ARTDIR: $(Build.ArtifactStagingDirectory)
|
||||
QT_VER: '6.8.0'
|
||||
QT_VER: '6.7.3'
|
||||
QT_VER_MAIN: '6'
|
||||
LLVM_COMPILER_VER: '16'
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -506,6 +506,7 @@ target_sources(rpcs3_emu PRIVATE
|
|||
RSX/GL/OpenGL.cpp
|
||||
RSX/GL/upscalers/fsr1/fsr_pass.cpp
|
||||
RSX/GSRender.cpp
|
||||
RSX/Host/MM.cpp
|
||||
RSX/Host/RSXDMAWriter.cpp
|
||||
RSX/Null/NullGSRender.cpp
|
||||
RSX/NV47/FW/draw_call.cpp
|
||||
|
|
|
@ -232,8 +232,8 @@ public:
|
|||
u8 rumble = 0; // Rumble intensity
|
||||
gem_color sphere_rgb = {}; // RGB color of the sphere LED
|
||||
u32 hue = 0; // Tracking hue of the motion controller
|
||||
f32 distance_mm{1500.0f}; // Distance from the camera in mm
|
||||
f32 radius{10.0f}; // Radius of the sphere in camera pixels
|
||||
f32 distance_mm{3000.0f}; // Distance from the camera in mm
|
||||
f32 radius{5.0f}; // Radius of the sphere in camera pixels
|
||||
bool radius_valid = true; // If the radius and distance of the sphere was computed.
|
||||
|
||||
bool is_calibrating{false}; // Whether or not we are currently calibrating
|
||||
|
@ -716,8 +716,9 @@ public:
|
|||
return hue < m_hues.size() && m_hues[hue] < 20; // potentially true if less than 20 pixels have the hue
|
||||
}
|
||||
|
||||
ps_move_info& get_info(u32 gem_num)
|
||||
ps_move_info get_info(u32 gem_num)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
return ::at32(m_info, gem_num);
|
||||
}
|
||||
|
||||
|
@ -903,7 +904,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>();
|
||||
|
||||
|
@ -918,9 +919,13 @@ static inline void pos_to_gem_state(u32 gem_num, const gem_config::gem_controlle
|
|||
const f32 image_x = static_cast<f32>(x_pos) / scaling_width;
|
||||
const f32 image_y = static_cast<f32>(y_pos) / scaling_height;
|
||||
|
||||
// Half of the camera image
|
||||
const f32 half_width = shared_data.width / 2.f;
|
||||
const f32 half_height = shared_data.height / 2.f;
|
||||
|
||||
// Centered image coordinates in pixels
|
||||
const f32 centered_x = image_x - (shared_data.width / 2.f);
|
||||
const f32 centered_y = (shared_data.height / 2.f) - image_y; // Image coordinates increase downwards, so we have to invert this
|
||||
const f32 centered_x = image_x - half_width;
|
||||
const f32 centered_y = half_height - image_y; // Image coordinates increase downwards, so we have to invert this
|
||||
|
||||
// Camera coordinates in mm (centered, so it's the same as world coordinates)
|
||||
const f32 camera_x = centered_x * mmPerPixel;
|
||||
|
@ -932,16 +937,47 @@ 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
|
||||
{
|
||||
static constexpr f32 PI = 3.14159265f;
|
||||
const auto degree_to_rad = [](f32 degree) -> f32 { return degree * PI / 180.0f; };
|
||||
|
||||
static constexpr f32 CONE = 10.0f / 2.0f;
|
||||
const f32 roll = -degree_to_rad((image_y - half_height) / half_height * CONE); // This is actually the pitch
|
||||
const f32 pitch = -degree_to_rad((image_x - half_width) / half_width * CONE); // This is actually the yaw
|
||||
const f32 yaw = degree_to_rad(0.0f);
|
||||
const f32 cr = std::cos(roll * 0.5f);
|
||||
const f32 sr = std::sin(roll * 0.5f);
|
||||
const f32 cp = std::cos(pitch * 0.5f);
|
||||
const f32 sp = std::sin(pitch * 0.5f);
|
||||
const f32 cy = std::cos(yaw * 0.5f);
|
||||
const f32 sy = std::sin(yaw * 0.5f);
|
||||
|
||||
const f32 q_x = sr * cp * cy - cr * sp * sy;
|
||||
const f32 q_y = cr * sp * cy + sr * cp * sy;
|
||||
const f32 q_z = cr * cp * sy - sr * sp * cy;
|
||||
const f32 q_w = cr * cp * cy + sr * sp * sy;
|
||||
|
||||
gem_state->quat[0] = q_x;
|
||||
gem_state->quat[1] = q_y;
|
||||
gem_state->quat[2] = q_z;
|
||||
gem_state->quat[3] = q_w;
|
||||
}
|
||||
|
||||
if (g_cfg.io.show_move_cursor)
|
||||
{
|
||||
draw_overlay_cursor(gem_num, controller, x_pos, y_pos, x_max, y_max);
|
||||
|
@ -1056,7 +1092,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 +1114,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 +1123,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())
|
||||
{
|
||||
|
@ -1104,12 +1140,17 @@ static void ps_move_pos_to_gem_state(u32 gem_num, const gem_config::gem_controll
|
|||
return;
|
||||
}
|
||||
|
||||
auto& tracker = g_fxo->get<named_thread<gem_tracker>>(); // Let's not lock the mutex. This not really important here
|
||||
const ps_move_info& info = tracker.get_info(gem_num);
|
||||
auto& tracker = g_fxo->get<named_thread<gem_tracker>>();
|
||||
const ps_move_info info = tracker.get_info(gem_num);
|
||||
|
||||
if constexpr (std::is_same_v<T, vm::ptr<CellGemState>>)
|
||||
{
|
||||
pos_to_gem_state(gem_num, controller, gem_state, info.x_pos, info.y_pos, info.x_max, info.y_max);
|
||||
gem_state->temperature = pad->move_data.temperature;
|
||||
gem_state->accel[0] = pad->move_data.accelerometer_x * 1000; // linear velocity in mm/s²
|
||||
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, pad->move_data);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
|
||||
{
|
||||
|
@ -1267,7 +1308,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())
|
||||
{
|
||||
|
@ -1290,7 +1331,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>>)
|
||||
{
|
||||
|
@ -1340,7 +1381,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;
|
||||
|
@ -1358,7 +1399,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>>)
|
||||
{
|
||||
|
@ -1795,7 +1836,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;
|
||||
|
@ -1866,7 +1907,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
|
|||
{
|
||||
case move_handler::real:
|
||||
{
|
||||
// Get temperature
|
||||
// Get temperature and sensor data
|
||||
{
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
|
||||
|
@ -1876,6 +1917,12 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
|
|||
if (pad && pad->m_pad_handler == pad_handler::move && (pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
{
|
||||
inertial_state->temperature = pad->move_data.temperature;
|
||||
inertial_state->accelerometer[0] = pad->move_data.accelerometer_x;
|
||||
inertial_state->accelerometer[1] = pad->move_data.accelerometer_y;
|
||||
inertial_state->accelerometer[2] = pad->move_data.accelerometer_z;
|
||||
inertial_state->gyro[0] = pad->move_data.gyro_x;
|
||||
inertial_state->gyro[1] = pad->move_data.gyro_y;
|
||||
inertial_state->gyro[2] = pad->move_data.gyro_z;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2119,14 +2166,13 @@ 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)
|
||||
{
|
||||
case move_handler::real:
|
||||
{
|
||||
auto& tracker = g_fxo->get<named_thread<gem_tracker>>(); // Let's not lock the mutex. This not really important here
|
||||
const ps_move_info& info = tracker.get_info(gem_num);
|
||||
auto& tracker = g_fxo->get<named_thread<gem_tracker>>();
|
||||
const ps_move_info info = tracker.get_info(gem_num);
|
||||
|
||||
ds3_input_to_pad(gem_num, gem_state->pad.digitalbuttons, gem_state->pad.analog_T);
|
||||
ps_move_pos_to_gem_state(gem_num, controller, gem_state);
|
||||
|
|
|
@ -333,6 +333,10 @@ void lv2_socket_p2p::close()
|
|||
auto& nc = g_fxo->get<p2p_context>();
|
||||
{
|
||||
std::lock_guard lock(nc.list_p2p_ports_mutex);
|
||||
|
||||
if (!nc.list_p2p_ports.contains(port))
|
||||
return;
|
||||
|
||||
auto& p2p_port = ::at32(nc.list_p2p_ports, port);
|
||||
{
|
||||
std::lock_guard lock(p2p_port.bound_p2p_vports_mutex);
|
||||
|
|
|
@ -516,9 +516,14 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
|
||||
const auto render = rsx::get_current_renderer();
|
||||
|
||||
if (!render->dma_address || context_id != 0x55555555)
|
||||
if (!render->dma_address)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
return { CELL_EINVAL, "dma_address is 0" };
|
||||
}
|
||||
|
||||
if (context_id != 0x55555555)
|
||||
{
|
||||
return { CELL_EINVAL, "context_id is 0x%x", context_id };
|
||||
}
|
||||
|
||||
auto &driverInfo = vm::_ref<RsxDriverInfo>(render->driver_info);
|
||||
|
@ -534,7 +539,6 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
set_rsx_dmactl(render, get_put);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x100: // Display mode set
|
||||
break;
|
||||
case 0x101: // Display sync set, cellGcmSetFlipMode
|
||||
|
@ -594,9 +598,8 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
|
||||
return {};
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x103: // Display Queue
|
||||
{
|
||||
// NOTE: There currently seem to only be 2 active heads on PS3
|
||||
|
@ -615,9 +618,8 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
{
|
||||
render->post_vblank_event(get_system_time());
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x104: // Display buffer
|
||||
{
|
||||
const u8 id = a3 & 0xFF;
|
||||
|
@ -641,9 +643,8 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
render->display_buffers[id].offset = offset;
|
||||
|
||||
render->display_buffers_count = std::max<u32>(id + 1, render->display_buffers_count);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x105: // destroy buffer?
|
||||
break;
|
||||
|
||||
|
@ -684,9 +685,8 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
{
|
||||
flipStatus = (flipStatus & static_cast<u32>(a4)) | static_cast<u32>(a5);
|
||||
});
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10D: // Called by cellGcmInitCursor
|
||||
break;
|
||||
|
||||
|
@ -721,7 +721,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
{
|
||||
if (!size || !pitch)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
return { CELL_EINVAL, "size or pitch are 0 (size=%d, pitch=%d)", size, pitch };
|
||||
}
|
||||
|
||||
u32 limit = -1;
|
||||
|
@ -735,7 +735,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
|
||||
if (!range.valid() || range.end >= limit)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
return { CELL_EINVAL, "range invalid (valid=%d, end=%d, limit=%d)", range.valid(), range.end, limit };
|
||||
}
|
||||
|
||||
// Hardcoded value in gcm
|
||||
|
@ -757,7 +757,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
{
|
||||
if (render->iomap_table.ea[io] == umax)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
return { CELL_EINVAL, "iomap_table ea is umax" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -770,9 +770,8 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
tile.base = base;
|
||||
tile.bank = base;
|
||||
tile.bound = bound;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x301: // Depth-buffer (Z-cull)
|
||||
{
|
||||
//a4 high = region = (1 << 0) | (zFormat << 4) | (aaFormat << 8);
|
||||
|
@ -806,7 +805,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
// width and height are not allowed to be zero (checked by range.valid())
|
||||
if (!cull_range.valid() || cull_range.end >= 3u << 20 || offset >= render->local_mem_size)
|
||||
{
|
||||
return CELL_EINVAL;
|
||||
return { CELL_EINVAL, "cull_range invalid (valid=%d, end=%d, offset=%d, local_mem_size=%d)", cull_range.valid(), cull_range.end, offset, render->local_mem_size };
|
||||
}
|
||||
|
||||
if (a5 & 0xF0000000)
|
||||
|
@ -835,8 +834,8 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
zcull.sRef = ((a6 >> 32) >> 16) & 0xFF;
|
||||
zcull.sMask = ((a6 >> 32) >> 24) & 0xFF;
|
||||
zcull.bound = bound;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x302: // something with zcull
|
||||
break;
|
||||
|
@ -867,13 +866,12 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
render->send_event(0, SYS_RSX_EVENT_FLIP_BASE << 1, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xFED: // hack: vblank command
|
||||
{
|
||||
if (cpu_thread::get_current<ppu_thread>())
|
||||
{
|
||||
// VBLANK/RSX thread only
|
||||
return CELL_EINVAL;
|
||||
return { CELL_EINVAL, "wrong thread" };
|
||||
}
|
||||
|
||||
// NOTE: There currently seem to only be 2 active heads on PS3
|
||||
|
@ -916,7 +914,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
|
|||
}
|
||||
|
||||
default:
|
||||
return CELL_EINVAL;
|
||||
return { CELL_EINVAL, "unsupported package id %d", package_id };
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
|
|
|
@ -466,12 +466,13 @@ struct ps_move_data
|
|||
bool external_device_read_requested = false;
|
||||
bool external_device_write_requested = false;
|
||||
|
||||
s16 accelerometer_x = 0;
|
||||
s16 accelerometer_y = 0;
|
||||
s16 accelerometer_z = 0;
|
||||
s16 gyro_x = 0;
|
||||
s16 gyro_y = 0;
|
||||
s16 gyro_z = 0;
|
||||
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; // 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;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "TextureUtils.h"
|
||||
|
||||
#include "Emu/Memory/vm.h"
|
||||
#include "Emu/RSX/Host/MM.h"
|
||||
#include "util/vm.hpp"
|
||||
|
||||
#include <list>
|
||||
|
@ -29,8 +30,7 @@ namespace rsx
|
|||
{
|
||||
ensure(range.is_page_range());
|
||||
|
||||
//rsx_log.error("memory_protect(0x%x, 0x%x, %x)", static_cast<u32>(range.start), static_cast<u32>(range.length()), static_cast<u32>(prot));
|
||||
utils::memory_protect(vm::base(range.start), range.length(), prot);
|
||||
rsx::mm_protect(vm::base(range.start), range.length(), prot);
|
||||
|
||||
#ifdef TEXTURE_CACHE_DEBUG
|
||||
tex_cache_checker.set_protection(range, prot);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "Emu/Memory/vm_locking.h"
|
||||
#include "Emu/RSX/rsx_methods.h"
|
||||
#include "Emu/RSX/Host/MM.h"
|
||||
#include "Emu/RSX/Host/RSXDMAWriter.h"
|
||||
#include "Emu/RSX/NV47/HW/context_accessors.define.h"
|
||||
|
||||
|
@ -1082,6 +1083,8 @@ void GLGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou
|
|||
|
||||
bool GLGSRender::on_access_violation(u32 address, bool is_writing)
|
||||
{
|
||||
rsx::mm_flush(address);
|
||||
|
||||
const bool can_flush = is_current_thread();
|
||||
const rsx::invalidation_cause cause = is_writing
|
||||
? (can_flush ? rsx::invalidation_cause::write : rsx::invalidation_cause::deferred_write)
|
||||
|
|
110
rpcs3/Emu/RSX/Host/MM.cpp
Normal file
110
rpcs3/Emu/RSX/Host/MM.cpp
Normal file
|
@ -0,0 +1,110 @@
|
|||
#include "stdafx.h"
|
||||
#include "MM.h"
|
||||
#include <Emu/RSX/Common/simple_array.hpp>
|
||||
#include <Emu/RSX/RSXOffload.h>
|
||||
|
||||
#include <Emu/Memory/vm.h>
|
||||
#include <Emu/IdManager.h>
|
||||
#include <Emu/system_config.h>
|
||||
#include <Utilities/address_range.h>
|
||||
#include <Utilities/mutex.h>
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
rsx::simple_array<MM_block> g_deferred_mprotect_queue;
|
||||
shared_mutex g_mprotect_queue_lock;
|
||||
|
||||
void mm_flush_mprotect_queue_internal()
|
||||
{
|
||||
for (const auto& block : g_deferred_mprotect_queue)
|
||||
{
|
||||
utils::memory_protect(reinterpret_cast<void*>(block.start), block.length, block.prot);
|
||||
}
|
||||
|
||||
g_deferred_mprotect_queue.clear();
|
||||
}
|
||||
|
||||
void mm_defer_mprotect_internal(u64 start, u64 length, utils::protection prot)
|
||||
{
|
||||
// We could stack and merge requests here, but that is more trouble than it is truly worth.
|
||||
// A fresh call to memory_protect only takes a few nanoseconds of setup overhead, it is not worth the risk of hanging because of conflicts.
|
||||
g_deferred_mprotect_queue.push_back({ start, length, prot });
|
||||
}
|
||||
|
||||
void mm_protect(void* ptr, u64 length, utils::protection prot)
|
||||
{
|
||||
if (g_cfg.video.disable_async_host_memory_manager)
|
||||
{
|
||||
utils::memory_protect(ptr, length, prot);
|
||||
return;
|
||||
}
|
||||
|
||||
// Naive merge. Eventually it makes more sense to do conflict resolution, but it's not as important.
|
||||
const auto start = reinterpret_cast<u64>(ptr);
|
||||
const auto end = start + length;
|
||||
|
||||
std::lock_guard lock(g_mprotect_queue_lock);
|
||||
|
||||
if (prot == utils::protection::rw || prot == utils::protection::wx)
|
||||
{
|
||||
// Basically an unlock op. Flush if any overlap is detected
|
||||
for (const auto& block : g_deferred_mprotect_queue)
|
||||
{
|
||||
if (block.overlaps(start, end))
|
||||
{
|
||||
mm_flush_mprotect_queue_internal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
utils::memory_protect(ptr, length, prot);
|
||||
return;
|
||||
}
|
||||
|
||||
// No, Ro, etc.
|
||||
mm_defer_mprotect_internal(start, length, prot);
|
||||
}
|
||||
|
||||
void mm_flush()
|
||||
{
|
||||
std::lock_guard lock(g_mprotect_queue_lock);
|
||||
mm_flush_mprotect_queue_internal();
|
||||
}
|
||||
|
||||
void mm_flush(u32 vm_address)
|
||||
{
|
||||
std::lock_guard lock(g_mprotect_queue_lock);
|
||||
if (g_deferred_mprotect_queue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto addr = reinterpret_cast<u64>(vm::base(vm_address));
|
||||
for (const auto& block : g_deferred_mprotect_queue)
|
||||
{
|
||||
if (block.overlaps(addr))
|
||||
{
|
||||
mm_flush_mprotect_queue_internal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mm_flush_lazy()
|
||||
{
|
||||
if (!g_cfg.video.multithreaded_rsx)
|
||||
{
|
||||
mm_flush();
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard lock(g_mprotect_queue_lock);
|
||||
if (g_deferred_mprotect_queue.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& rsxdma = g_fxo->get<rsx::dma_manager>();
|
||||
rsxdma.backend_ctrl(mm_backend_ctrl::cmd_mm_flush, nullptr);
|
||||
}
|
||||
}
|
40
rpcs3/Emu/RSX/Host/MM.h
Normal file
40
rpcs3/Emu/RSX/Host/MM.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <util/types.hpp>
|
||||
#include <util/vm.hpp>
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
struct MM_block
|
||||
{
|
||||
u64 start;
|
||||
u64 length;
|
||||
utils::protection prot;
|
||||
|
||||
inline bool overlaps(u64 start, u64 end) const
|
||||
{
|
||||
// [Start, End] is not a proper closed range, there is an off-by-one by design.
|
||||
// FIXME: Use address_range64
|
||||
const u64 this_end = this->start + this->length;
|
||||
return (this->start < end && start < this_end);
|
||||
}
|
||||
|
||||
inline bool overlaps(u64 addr) const
|
||||
{
|
||||
// [Start, End] is not a proper closed range, there is an off-by-one by design.
|
||||
// FIXME: Use address_range64
|
||||
const u64 this_end = this->start + this->length;
|
||||
return (addr >= start && addr < this_end);
|
||||
}
|
||||
};
|
||||
|
||||
enum mm_backend_ctrl : u32
|
||||
{
|
||||
cmd_mm_flush = 0x81000000,
|
||||
};
|
||||
|
||||
void mm_protect(void* start, u64 length, utils::protection prot);
|
||||
void mm_flush_lazy();
|
||||
void mm_flush(u32 vm_address);
|
||||
void mm_flush();
|
||||
}
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
namespace rsx
|
||||
{
|
||||
void mm_flush_lazy();
|
||||
void mm_flush();
|
||||
|
||||
namespace util
|
||||
{
|
||||
template <bool FlushDMA, bool FlushPipe>
|
||||
|
@ -24,17 +27,24 @@ namespace rsx
|
|||
return;
|
||||
}
|
||||
|
||||
if constexpr (FlushDMA)
|
||||
if constexpr (FlushDMA || FlushPipe)
|
||||
{
|
||||
// If the backend handled the request, this call will basically be a NOP
|
||||
g_fxo->get<rsx::dma_manager>().sync();
|
||||
}
|
||||
// Release op must be acoompanied by MM flush.
|
||||
// FlushPipe implicitly does a MM flush but FlushDMA does not. Trigger the flush here
|
||||
rsx::mm_flush();
|
||||
|
||||
if constexpr (FlushPipe)
|
||||
{
|
||||
// Manually flush the pipeline.
|
||||
// It is possible to stream report writes using the host GPU, but that generates too much submit traffic.
|
||||
RSX(ctx)->sync();
|
||||
if constexpr (FlushDMA)
|
||||
{
|
||||
// If the backend handled the request, this call will basically be a NOP
|
||||
g_fxo->get<rsx::dma_manager>().sync();
|
||||
}
|
||||
|
||||
if constexpr (FlushPipe)
|
||||
{
|
||||
// Manually flush the pipeline.
|
||||
// It is possible to stream report writes using the host GPU, but that generates too much submit traffic.
|
||||
RSX(ctx)->sync();
|
||||
}
|
||||
}
|
||||
|
||||
if (handled)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Common/time.hpp"
|
||||
#include "Core/RSXReservationLock.hpp"
|
||||
#include "Core/RSXEngLock.hpp"
|
||||
#include "Host/MM.h"
|
||||
#include "Host/RSXDMAWriter.h"
|
||||
#include "NV47/HW/context.h"
|
||||
#include "Program/GLSLCommon.h"
|
||||
|
@ -2603,8 +2604,14 @@ namespace rsx
|
|||
rsx_log.error("Depth texture bound to pipeline with unexpected format 0x%X", format);
|
||||
}
|
||||
}
|
||||
else if (!backend_config.supports_hw_renormalization)
|
||||
else if (!backend_config.supports_hw_renormalization /* &&
|
||||
tex.min_filter() == rsx::texture_minify_filter::nearest &&
|
||||
tex.mag_filter() == rsx::texture_magnify_filter::nearest*/)
|
||||
{
|
||||
// FIXME: This check should only apply to point-sampled textures. However, it severely regresses some games (id tech 5).
|
||||
// This is because even when filtering is active, the error from the PS3 texture expansion still applies.
|
||||
// A proper fix is to expand these formats into BGRA8 when high texture precision is required. That requires different GUI settings and inflation shaders, so it will be handled separately.
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_A1R5G5B5:
|
||||
|
@ -3175,6 +3182,8 @@ namespace rsx
|
|||
{
|
||||
m_eng_interrupt_mask.clear(rsx::pipe_flush_interrupt);
|
||||
|
||||
mm_flush();
|
||||
|
||||
if (zcull_ctrl->has_pending())
|
||||
{
|
||||
zcull_ctrl->sync(this);
|
||||
|
@ -3627,10 +3636,25 @@ namespace rsx
|
|||
on_invalidate_memory_range(m_invalidated_memory_range, rsx::invalidation_cause::read);
|
||||
}
|
||||
|
||||
// Host sync
|
||||
rsx::mm_flush();
|
||||
|
||||
on_invalidate_memory_range(m_invalidated_memory_range, rsx::invalidation_cause::unmap);
|
||||
m_invalidated_memory_range.invalidate();
|
||||
}
|
||||
|
||||
void thread::renderctl(u32 request_code, void* args)
|
||||
{
|
||||
switch (request_code)
|
||||
{
|
||||
case rsx::mm_backend_ctrl::cmd_mm_flush:
|
||||
rsx::mm_flush();
|
||||
break;
|
||||
default:
|
||||
fmt::throw_exception("Unknown backend request: 0x%x", request_code);
|
||||
}
|
||||
}
|
||||
|
||||
//Pause/cont wrappers for FIFO ctrl. Never call this from rsx thread itself!
|
||||
void thread::pause()
|
||||
{
|
||||
|
@ -3696,6 +3720,9 @@ namespace rsx
|
|||
{
|
||||
bool pause_emulator = false;
|
||||
|
||||
// MM sync. This is a pre-emptive operation, so we can use a deferred request.
|
||||
rsx::mm_flush_lazy();
|
||||
|
||||
// Marks the end of a frame scope GPU-side
|
||||
if (g_user_asked_for_frame_capture.exchange(false) && !capture_current_frame)
|
||||
{
|
||||
|
|
|
@ -404,7 +404,7 @@ namespace rsx
|
|||
virtual void notify_tile_unbound(u32 /*tile*/) {}
|
||||
|
||||
// control
|
||||
virtual void renderctl(u32 /*request_code*/, void* /*args*/) {}
|
||||
virtual void renderctl(u32 request_code, void* args);
|
||||
|
||||
// zcull
|
||||
void notify_zcull_info_changed();
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace vk
|
|||
enum // callback commands
|
||||
{
|
||||
rctrl_queue_submit = 0x80000000,
|
||||
rctrl_run_gc = 0x80000001
|
||||
rctrl_run_gc = 0x80000001,
|
||||
};
|
||||
|
||||
struct submit_packet
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "vkutils/scratch.h"
|
||||
|
||||
#include "Emu/RSX/rsx_methods.h"
|
||||
#include "Emu/RSX/Host/MM.h"
|
||||
#include "Emu/RSX/Host/RSXDMAWriter.h"
|
||||
#include "Emu/RSX/NV47/HW/context_accessors.define.h"
|
||||
#include "Emu/Memory/vm_locking.h"
|
||||
|
@ -1010,6 +1011,8 @@ VKGSRender::~VKGSRender()
|
|||
|
||||
bool VKGSRender::on_access_violation(u32 address, bool is_writing)
|
||||
{
|
||||
rsx::mm_flush(address);
|
||||
|
||||
vk::texture_cache::thrashed_set result;
|
||||
{
|
||||
const rsx::invalidation_cause cause = is_writing ? rsx::invalidation_cause::deferred_write : rsx::invalidation_cause::deferred_read;
|
||||
|
@ -2460,6 +2463,9 @@ void VKGSRender::close_and_submit_command_buffer(vk::fence* pFence, VkSemaphore
|
|||
{
|
||||
ensure(!m_queue_status.test_and_set(flush_queue_state::flushing));
|
||||
|
||||
// Host MM sync before executing anything on the GPU
|
||||
rsx::mm_flush();
|
||||
|
||||
// Workaround for deadlock occuring during RSX offloader fault
|
||||
// TODO: Restructure command submission infrastructure to avoid this condition
|
||||
const bool sync_success = g_fxo->get<rsx::dma_manager>().sync();
|
||||
|
@ -2824,7 +2830,7 @@ void VKGSRender::renderctl(u32 request_code, void* args)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
fmt::throw_exception("Unhandled request code 0x%x", request_code);
|
||||
rsx::thread::renderctl(request_code, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,7 @@ struct cfg_root : cfg::node
|
|||
cfg::_bool decr_memory_layout{ this, "DECR memory layout", false}; // Force enable increased allowed main memory range as DECR console
|
||||
cfg::_bool host_label_synchronization{ this, "Allow Host GPU Labels", false };
|
||||
cfg::_bool disable_msl_fast_math{ this, "Disable MSL Fast Math", false };
|
||||
cfg::_bool disable_async_host_memory_manager{ this, "Disable Asynchronous Memory Manager", false, true };
|
||||
cfg::_enum<output_scaling_mode> output_scaling{ this, "Output Scaling Mode", output_scaling_mode::bilinear, true };
|
||||
|
||||
struct node_vk : cfg::node
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
void operator()();
|
||||
|
||||
PadInfo& GetInfo() { return m_info; }
|
||||
auto& GetPads() { return m_pads; }
|
||||
std::array<std::shared_ptr<Pad>, CELL_PAD_MAX_PORT_NUM>& GetPads() { return m_pads; }
|
||||
void SetRumble(const u32 pad, u8 large_motor, bool small_motor);
|
||||
void SetIntercepted(bool intercepted);
|
||||
|
||||
|
|
244
rpcs3/Input/ps_move_calibration.cpp
Normal file
244
rpcs3/Input/ps_move_calibration.cpp
Normal file
|
@ -0,0 +1,244 @@
|
|||
#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();
|
||||
|
||||
std::string msg;
|
||||
|
||||
switch (device.model)
|
||||
{
|
||||
case ps_move_model::ZCM1:
|
||||
t = psmove_calibration_decode_12bits(data, 0x02);
|
||||
fmt::append(msg, "Temperature: 0x%04X\n", 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);
|
||||
fmt::append(msg, "Orientation #%d: (%5d | %5d | %5d)\n", orientation, x, y, z);
|
||||
}
|
||||
|
||||
t = psmove_calibration_decode_12bits(data, 0x42);
|
||||
fmt::append(msg, "Temperature: 0x%04X\n", 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);
|
||||
fmt::append(msg, "Gyro %c, 80 rpm: (%5d | %5d | %5d)\n", "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);
|
||||
fmt::append(msg, "Temperature: 0x%04X\n", t);
|
||||
fmt::append(msg, "Gyro, 0 rpm (@0x2a): (%5d | %5d | %5d)\n", 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);
|
||||
fmt::append(msg, "Temperature: 0x%04X\n", t);
|
||||
fmt::append(msg, "Gyro, 0 rpm (@0x32): (%5d | %5d | %5d)\n", 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);
|
||||
fmt::append(msg, "Temperature: 0x%04X\n", t);
|
||||
fmt::append(msg, "Vector @0x5e: (%f | %f | %f)\n", 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);
|
||||
fmt::append(msg, "Vector @0x6a: (%f | %f | %f)\n", fx, fy, fz);
|
||||
|
||||
fmt::append(msg, "byte @0x3f: 0x%02x\n", static_cast<u8>(data[0x3f]));
|
||||
fmt::append(msg, "float @0x76: %f\n", psmove_calibration_decode_float(data, 0x76));
|
||||
fmt::append(msg, "float @0x7a: %f\n", 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);
|
||||
fmt::append(msg, "Orientation #%d: (%5d | %5d | %5d)\n", 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);
|
||||
fmt::append(msg, "Gyro Bias?, 0 rpm (@0x26): (%5d | %5d | %5d)\n", 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);
|
||||
fmt::append(msg, "Gyro %c, 90 rpm: (%5d | %5d | %5d)\n", "XYZXYZ"[orientation], x, y, z);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
move_log.notice("Calibration:\n%s", msg);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
5
rpcs3/Input/ps_move_calibration.h
Normal file
5
rpcs3/Input/ps_move_calibration.h
Normal 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);
|
|
@ -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,61 @@ 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;
|
||||
device->ahrs.settings.gain = 0.0f; // If gain is set, the algorithm tries to adjust the orientation over time.
|
||||
FusionAhrsSetSettings(&device->ahrs, &device->ahrs.settings);
|
||||
FusionAhrsReset(&device->ahrs);
|
||||
|
||||
// Activate
|
||||
if (send_output_report(device) == -1)
|
||||
{
|
||||
|
@ -620,41 +671,107 @@ 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;
|
||||
}
|
||||
|
||||
pad->m_sensors[0].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * (accel_x / MOVE_ONE_G) * -1.0f));
|
||||
pad->m_sensors[1].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * (accel_z / MOVE_ONE_G) * -1.0f));
|
||||
pad->m_sensors[2].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * (accel_y / MOVE_ONE_G)));
|
||||
pad->m_sensors[3].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * (gyro_z / MOVE_ONE_G) * -1.0f));
|
||||
// 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;
|
||||
pad->move_data.accelerometer_y = accel_y;
|
||||
pad->move_data.accelerometer_z = accel_z;
|
||||
pad->move_data.gyro_x = gyro_x;
|
||||
pad->move_data.gyro_y = gyro_y;
|
||||
pad->move_data.gyro_z = gyro_z;
|
||||
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));
|
||||
pad->m_sensors[1].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * pad->move_data.accelerometer_y * -1.0f));
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -40,6 +40,26 @@ ps_move_tracker<DiagnosticsEnabled>::~ps_move_tracker()
|
|||
}
|
||||
}
|
||||
|
||||
template <bool DiagnosticsEnabled>
|
||||
void ps_move_tracker<DiagnosticsEnabled>::set_valid(ps_move_info& info, u32 index, bool valid)
|
||||
{
|
||||
u32& fail_count = ::at32(m_fail_count, index);
|
||||
|
||||
if (info.valid && !valid)
|
||||
{
|
||||
// Ignore a couple of untracked frames. This reduces noise.
|
||||
if (++fail_count >= 3)
|
||||
{
|
||||
info.valid = valid;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
info.valid = valid;
|
||||
fail_count = 0; // Reset fail count
|
||||
};
|
||||
|
||||
template <bool DiagnosticsEnabled>
|
||||
void ps_move_tracker<DiagnosticsEnabled>::set_image_data(const void* buf, u64 size, u32 width, u32 height, s32 format)
|
||||
{
|
||||
|
@ -136,7 +156,7 @@ void ps_move_tracker<DiagnosticsEnabled>::init_workers()
|
|||
|
||||
// Find contours
|
||||
ps_move_info& info = m_info[index];
|
||||
ps_move_info new_info{};
|
||||
ps_move_info new_info = info;
|
||||
process_contours(new_info, index);
|
||||
|
||||
if (new_info.valid)
|
||||
|
@ -179,6 +199,7 @@ void ps_move_tracker<DiagnosticsEnabled>::process_image()
|
|||
{
|
||||
ps_move_info& info = m_info[index];
|
||||
info.valid = false;
|
||||
m_fail_count[index] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +324,6 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
const u32 height = m_height;
|
||||
const bool wrapped_hue = config.min_hue > config.max_hue; // e.g. min=355, max=5 (red)
|
||||
|
||||
info.valid = false;
|
||||
info.x_max = width;
|
||||
info.y_max = height;
|
||||
|
||||
|
@ -362,7 +382,10 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
cv::findContours(binary, all_contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
|
||||
|
||||
if (all_contours.empty())
|
||||
{
|
||||
set_valid(info, index, false);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::vector<cv::Point>> contours;
|
||||
contours.reserve(all_contours.size());
|
||||
|
@ -406,7 +429,10 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
}
|
||||
|
||||
if (best_index == umax)
|
||||
{
|
||||
set_valid(info, index, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate distance from sphere to camera
|
||||
const f32 sphere_radius_pixels = radii[best_index];
|
||||
|
@ -417,11 +443,28 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
const f32 distance_mm = (focal_length_pixels * CELL_GEM_SPHERE_RADIUS_MM) / sphere_radius_pixels;
|
||||
|
||||
// Set results
|
||||
info.valid = true;
|
||||
info.distance_mm = distance_mm;
|
||||
info.radius = sphere_radius_pixels;
|
||||
info.x_pos = std::clamp(static_cast<u32>(centers[best_index].x), 0u, width);
|
||||
info.y_pos = std::clamp(static_cast<u32>(centers[best_index].y), 0u, height);
|
||||
set_valid(info, index, true);
|
||||
|
||||
const u32 x_pos = std::clamp(static_cast<u32>(centers[best_index].x), 0u, width);
|
||||
const u32 y_pos = std::clamp(static_cast<u32>(centers[best_index].y), 0u, height);
|
||||
|
||||
// Only set new values if the new shape and position are relatively similar to the old ones.
|
||||
const auto distance_travelled = [](int x1, int y1, int x2, int y2)
|
||||
{
|
||||
return std::sqrt(std::pow(x2 - x1, 2) + pow(y2 - y1, 2));
|
||||
};
|
||||
const bool shape_matches = std::abs(info.radius - sphere_radius_pixels) < (info.radius * 2) &&
|
||||
distance_travelled(info.x_pos, info.y_pos, x_pos, y_pos) < (info.radius * 8);
|
||||
|
||||
if (shape_matches || ++m_shape_fail_count[index] >= 3)
|
||||
{
|
||||
info.distance_mm = distance_mm;
|
||||
info.radius = sphere_radius_pixels;
|
||||
info.x_pos = x_pos;
|
||||
info.y_pos = y_pos;
|
||||
|
||||
m_shape_fail_count[index] = 0; // Reset fail count
|
||||
}
|
||||
|
||||
if constexpr (!DiagnosticsEnabled)
|
||||
return;
|
||||
|
|
|
@ -71,6 +71,8 @@ private:
|
|||
void calculate_values();
|
||||
};
|
||||
|
||||
void set_valid(ps_move_info& info, u32 index, bool valid);
|
||||
|
||||
u32 m_width = 0;
|
||||
u32 m_height = 0;
|
||||
s32 m_format = 0;
|
||||
|
@ -90,6 +92,8 @@ private:
|
|||
|
||||
std::array<std::vector<u8>, CELL_GEM_MAX_NUM> m_image_hue_filtered{};
|
||||
std::array<std::vector<u8>, CELL_GEM_MAX_NUM> m_image_binary{};
|
||||
std::array<u32, CELL_GEM_MAX_NUM> m_fail_count{};
|
||||
std::array<u32, CELL_GEM_MAX_NUM> m_shape_fail_count{};
|
||||
|
||||
std::array<u32, 360> m_hues{};
|
||||
std::array<ps_move_info, CELL_GEM_MAX_NUM> m_info{};
|
||||
|
|
|
@ -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>
|
||||
|
@ -104,6 +104,7 @@
|
|||
<ClCompile Include="Emu\perf_monitor.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\texture_cache.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Core\RSXContext.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Host\MM.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Host\RSXDMAWriter.cpp" />
|
||||
<ClCompile Include="Emu\RSX\NV47\FW\draw_call.cpp" />
|
||||
<ClCompile Include="Emu\RSX\NV47\FW\reg_context.cpp" />
|
||||
|
@ -621,6 +622,7 @@
|
|||
<ClInclude Include="Emu\RSX\Core\RSXDisplay.h" />
|
||||
<ClInclude Include="Emu\RSX\Core\RSXReservationLock.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Core\RSXVertexTypes.h" />
|
||||
<ClInclude Include="Emu\RSX\Host\MM.h" />
|
||||
<ClInclude Include="Emu\RSX\Host\RSXDMAWriter.h" />
|
||||
<ClInclude Include="Emu\RSX\NV47\FW\draw_call.hpp" />
|
||||
<ClInclude Include="Emu\RSX\NV47\FW\draw_call.inc.h" />
|
||||
|
|
|
@ -1312,6 +1312,9 @@
|
|||
<ClCompile Include="Emu\RSX\Host\RSXDMAWriter.cpp">
|
||||
<Filter>Emu\GPU\RSX\Host Mini-Driver</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\Host\MM.cpp">
|
||||
<Filter>Emu\GPU\RSX\Host Mini-Driver</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
|
@ -2644,6 +2647,9 @@
|
|||
<ClInclude Include="Emu\RSX\Host\RSXDMAWriter.h">
|
||||
<Filter>Emu\GPU\RSX\Host Mini-Driver</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Host\MM.h">
|
||||
<Filter>Emu\GPU\RSX\Host Mini-Driver</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -160,4 +160,5 @@ target_link_libraries(rpcs3_ui
|
|||
3rdparty::wolfssl
|
||||
3rdparty::libcurl
|
||||
3rdparty::opencv
|
||||
3rdparty::fusion
|
||||
3rdparty::rtmidi)
|
||||
|
|
|
@ -103,6 +103,7 @@ enum class emu_settings_type
|
|||
DisableMSLFastMath,
|
||||
OutputScalingMode,
|
||||
ForceHwMSAAResolve,
|
||||
DisableAsyncHostMM,
|
||||
|
||||
// Performance Overlay
|
||||
PerfOverlayEnabled,
|
||||
|
@ -294,6 +295,7 @@ inline static const std::map<emu_settings_type, cfg_location> settings_location
|
|||
{ emu_settings_type::DisableMSLFastMath, { "Video", "Disable MSL Fast Math"}},
|
||||
{ emu_settings_type::OutputScalingMode, { "Video", "Output Scaling Mode"}},
|
||||
{ emu_settings_type::ForceHwMSAAResolve, { "Video", "Force Hardware MSAA Resolve"}},
|
||||
{ emu_settings_type::DisableAsyncHostMM, { "Video", "Disable Asynchronous Memory Manager"}},
|
||||
|
||||
// Vulkan
|
||||
{ emu_settings_type::VulkanAsyncTextureUploads, { "Video", "Vulkan", "Asynchronous Texture Streaming 2"}},
|
||||
|
|
|
@ -1593,6 +1593,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
|||
ui->disableMslFastMath->setVisible(false);
|
||||
#endif
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->disableAsyncHostMM, emu_settings_type::DisableAsyncHostMM);
|
||||
SubscribeTooltip(ui->disableAsyncHostMM, tooltips.settings.disable_async_host_mm);
|
||||
|
||||
// Comboboxes
|
||||
|
||||
m_emu_settings->EnhanceComboBox(ui->maxSPURSThreads, emu_settings_type::MaxSPURSThreads, true);
|
||||
|
|
|
@ -2695,6 +2695,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disableAsyncHostMM">
|
||||
<property name="text">
|
||||
<string>Disable Asynchronous Memory Manager</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -40,6 +40,7 @@ public:
|
|||
const QString allow_host_labels = tr("Allows the host GPU to synchronize with CELL directly. This incurs a performance penalty, but exposes the true state of GPU objects to the guest CPU. Can help eliminate visual noise and glitching at the cost of performance. Use with caution.");
|
||||
const QString force_hw_MSAA = tr("Forces MSAA to use the host GPU's resolve capabilities for all sampling operations.\nThis option incurs a performance penalty as well as the risk of visual artifacts but can yield crisper visuals when MSAA is enabled.");
|
||||
const QString disable_vertex_cache = tr("Disables the vertex cache.\nMight resolve missing or flickering graphics output.\nMay degrade performance.");
|
||||
const QString disable_async_host_mm = tr("Force host memory management calls to be inlined instead of handled asynchronously.\nThis can cause severe performance degradation and stuttering in some games.\nThis option is only needed by developers to debug problems with texture cache memory protection.");
|
||||
const QString zcull_operation_mode = tr("Changes ZCULL report synchronization behaviour. Experiment to find the best option for your game. Approximate mode is recommended for most games.\n· Precise is the most accurate to PS3 behaviour. Required for accurate visuals in some titles such as Demon's Souls and The Darkness.\n· Approximate is a much faster way to generate occlusion data which may not always match what the PS3 would generate. Works well with most PS3 games.\n· Relaxed changes the synchronization method completely and can greatly improve performance in some games or completely break others.");
|
||||
const QString max_spurs_threads = tr("Limits the maximum number of SPURS threads in each thread group.\nMay improve performance in some cases, especially on systems with limited number of hardware threads.\nLimiting the number of threads is likely to cause crashes; it's recommended to keep this at the default value.");
|
||||
const QString sleep_timers_accuracy = tr("Changes the sleep period accuracy.\n'As Host' uses default accuracy of the underlying operating system, while 'All Timers' attempts to improve it.\n'Usleep Only' limits the adjustments to usleep syscall only.\nCan affect performance in unexpected ways.");
|
||||
|
|
Loading…
Add table
Reference in a new issue