Compare commits
64 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cda630417 | ||
|
|
da066e8ed8 | ||
|
|
d60b0e8655 | ||
|
|
58081a3664 | ||
|
|
5b4bef13e7 | ||
|
|
265d1d6979 | ||
|
|
4b93ea59db | ||
|
|
6e36f4d230 | ||
|
|
bcd0ca6076 | ||
|
|
a67776013d | ||
|
|
382b41b18f | ||
|
|
6f9bfb10d3 | ||
|
|
aab25d9b22 | ||
|
|
f5964fe2a9 | ||
|
|
caaf2368b6 | ||
|
|
742f67908c | ||
|
|
b4ee3fa39a | ||
|
|
09300abe92 | ||
|
|
ba8ea95624 | ||
|
|
a5bdf824e6 | ||
|
|
e4eb7acd49 | ||
|
|
8ca8281f4f | ||
|
|
6d160873c4 | ||
|
|
02282477e7 | ||
|
|
f8aaa59990 | ||
|
|
7d66f8339e | ||
|
|
b8813edc51 | ||
|
|
87bb44830b | ||
|
|
912cae21b0 | ||
|
|
93a4ca11fa | ||
|
|
a9a9999efd | ||
|
|
99fbdaf75b | ||
|
|
d2c0b45bca | ||
|
|
8266f63130 | ||
|
|
037ce7cb5f | ||
|
|
a1d2fb314e | ||
|
|
914ead075e | ||
|
|
30b23fb7b8 | ||
|
|
40e39ddd46 | ||
|
|
1002563776 | ||
|
|
fc503c3445 | ||
|
|
e991525d63 | ||
|
|
53fb4a78a3 | ||
|
|
1a85c18600 | ||
|
|
381381c7e0 | ||
|
|
2fed6dd7e1 | ||
|
|
9627c550a0 | ||
|
|
1584de951a | ||
|
|
2535e9d1ec | ||
|
|
8e0e2e95e6 | ||
|
|
32b522b1fd | ||
|
|
adc617ccc4 | ||
|
|
802bbb2263 | ||
|
|
a1c1ad096d | ||
|
|
1611c53c12 | ||
|
|
e71d457af9 | ||
|
|
b2ad4dd189 | ||
|
|
caef92a584 | ||
|
|
4fa625c4fa | ||
|
|
cbef6b1fca | ||
|
|
4f847621af | ||
|
|
b38509b030 | ||
|
|
c0264d2121 | ||
|
|
5e7e55b98a |
@@ -6,7 +6,17 @@ set -e
|
||||
ccache -s
|
||||
|
||||
mkdir build || true && cd build
|
||||
cmake .. -GNinja -DDISPLAY_VERSION=$1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/clang -DCMAKE_CXX_COMPILER=/usr/lib/ccache/clang++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_INSTALL_PREFIX="/usr"
|
||||
cmake .. \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/clang++ \
|
||||
-DCMAKE_C_COMPILER=/usr/lib/ccache/clang \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
-DDISPLAY_VERSION=$1 \
|
||||
-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON \
|
||||
-DENABLE_QT_TRANSLATION=ON \
|
||||
-DUSE_DISCORD_PRESENCE=ON \
|
||||
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
||||
-GNinja
|
||||
|
||||
ninja
|
||||
|
||||
|
||||
@@ -6,10 +6,6 @@ set -e
|
||||
|
||||
ccache -sv
|
||||
|
||||
mkdir -p "$HOME/.conan/profiles"
|
||||
wget -c "https://github.com/yuzu-emu/build-environments/raw/master/linux-mingw/default" -O "$HOME/.conan/profiles/default"
|
||||
wget -c "https://github.com/yuzu-emu/build-environments/raw/master/linux-mingw/settings.yml" -O "$HOME/.conan/settings.yml"
|
||||
|
||||
mkdir -p build && cd build
|
||||
export LDFLAGS="-fuse-ld=lld"
|
||||
# -femulated-tls required due to an incompatibility between GCC and Clang
|
||||
@@ -24,6 +20,7 @@ cmake .. \
|
||||
-DUSE_CCACHE=ON \
|
||||
-DYUZU_USE_BUNDLED_SDL2=OFF \
|
||||
-DYUZU_USE_EXTERNAL_SDL2=OFF \
|
||||
-DYUZU_TESTS=OFF \
|
||||
-GNinja
|
||||
ninja yuzu yuzu-cmd
|
||||
|
||||
@@ -65,7 +62,7 @@ python3 .ci/scripts/windows/scan_dll.py package/*.exe package/imageformats/*.dll
|
||||
# copy FFmpeg libraries
|
||||
EXTERNALS_PATH="$(pwd)/build/externals"
|
||||
FFMPEG_DLL_PATH="$(find "${EXTERNALS_PATH}" -maxdepth 1 -type d | grep 'ffmpeg-')/bin"
|
||||
find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
|
||||
find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -nv {} package/ ';'
|
||||
|
||||
# copy libraries from yuzu.exe path
|
||||
find "$(pwd)/build/bin/" -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
|
||||
|
||||
@@ -47,6 +47,49 @@ Copy-Item .\CMakeModules -Recurse -Destination $MSVC_SOURCE
|
||||
7z a -r -ttar $MSVC_SOURCE_TAR $MSVC_SOURCE
|
||||
7z a -r -txz $MSVC_SOURCE_TARXZ $MSVC_SOURCE_TAR
|
||||
|
||||
# Following section is quick hack to package artifacts differently for GitHub Actions
|
||||
if ("$env:GITHUB_ACTIONS" -eq "true") {
|
||||
echo "Hello GitHub Actions"
|
||||
|
||||
# Hopefully there is an exe in either .\build\bin or .\build\bin\Release
|
||||
cp .\build\bin\yuzu*.exe .\artifacts\
|
||||
Copy-Item "$BUILD_DIR\*" -Destination "artifacts" -Recurse
|
||||
Remove-Item .\artifacts\tests.exe -ErrorAction ignore
|
||||
|
||||
# None of the other GHA builds are including source, so commenting out today
|
||||
#Copy-Item $MSVC_SOURCE_TARXZ -Destination "artifacts"
|
||||
|
||||
# Are debug symbols important?
|
||||
# cp .\build\bin\yuzu*.pdb .\pdb\
|
||||
|
||||
# Write out a tag BUILD_TAG to environment for the Upload step
|
||||
# We're getting ${{ github.event.number }} as $env:PR_NUMBER"
|
||||
echo "env:PR_NUMBER: $env:PR_NUMBER"
|
||||
if (Test-Path env:PR_NUMBER) {
|
||||
$PR_NUMBER = $env:PR_NUMBER.Substring(2) -as [int]
|
||||
$PR_NUMBER_TAG = "pr"+([string]$PR_NUMBER).PadLeft(5,'0')
|
||||
if ($PR_NUMBER -gt 1){
|
||||
$BUILD_TAG="verify-$PR_NUMBER_TAG-$GITDATE-$GITREV"
|
||||
} else {
|
||||
$BUILD_TAG = "verify-$GITDATE-$GITREV"
|
||||
}
|
||||
} else {
|
||||
# If env:PR_NUMBER isn't set, we should still write out a variable
|
||||
$BUILD_TAG = "verify-$GITDATE-$GITREV"
|
||||
}
|
||||
echo "BUILD_TAG=$BUILD_TAG"
|
||||
echo "BUILD_TAG=$BUILD_TAG" >> $env:GITHUB_ENV
|
||||
|
||||
# For extra job, just the exe
|
||||
$INDIVIDUAL_EXE = "yuzu-msvc-$BUILD_TAG.exe"
|
||||
echo "INDIVIDUAL_EXE=$INDIVIDUAL_EXE"
|
||||
echo "INDIVIDUAL_EXE=$INDIVIDUAL_EXE" >> $env:GITHUB_ENV
|
||||
echo "Just the exe: $INDIVIDUAL_EXE"
|
||||
cp .\artifacts\yuzu.exe .\$INDIVIDUAL_EXE
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
# Build the final release artifacts
|
||||
Copy-Item $MSVC_SOURCE_TARXZ -Destination $RELEASE_DIST
|
||||
Copy-Item "$BUILD_DIR\*" -Destination $RELEASE_DIST -Recurse
|
||||
@@ -62,3 +105,7 @@ Get-ChildItem "$BUILD_DIR" -Recurse -Filter "QtWebEngineProcess*.exe" | Copy-Ite
|
||||
Get-ChildItem . -Filter "*.zip" | Copy-Item -destination "artifacts"
|
||||
Get-ChildItem . -Filter "*.7z" | Copy-Item -destination "artifacts"
|
||||
Get-ChildItem . -Filter "*.tar.xz" | Copy-Item -destination "artifacts"
|
||||
}
|
||||
# Extra items
|
||||
git status
|
||||
cp .\build\src\common\scm_rev.cpp .\artifacts
|
||||
|
||||
@@ -6,9 +6,7 @@ parameters:
|
||||
steps:
|
||||
- script: choco install vulkan-sdk
|
||||
displayName: 'Install vulkan-sdk'
|
||||
- script: python -m pip install --upgrade pip conan
|
||||
displayName: 'Install conan'
|
||||
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd ..
|
||||
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_TESTS=OFF -DYUZU_USE_BUNDLED_VCPKG=ON .. && cd ..
|
||||
displayName: 'Configure CMake'
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build'
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
container: yuzuemu/build-environments:linux-transifex
|
||||
if: ${{ github.repository == 'yuzu-emu/yuzu' && !github.head_ref }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
|
||||
20
.github/workflows/verify.yml
vendored
20
.github/workflows/verify.yml
vendored
@@ -3,6 +3,8 @@ name: 'yuzu verify'
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
env:
|
||||
PR_NUMBER: pr${{ github.event.number }}
|
||||
|
||||
jobs:
|
||||
format:
|
||||
@@ -12,7 +14,7 @@ jobs:
|
||||
image: yuzuemu/build-environments:linux-clang-format
|
||||
options: -u 1001
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
- name: 'Verify Formatting'
|
||||
@@ -35,12 +37,12 @@ jobs:
|
||||
image: yuzuemu/build-environments:${{ matrix.image }}
|
||||
options: -u 1001
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
id: ccache-restore
|
||||
with:
|
||||
path: ~/.ccache
|
||||
@@ -69,7 +71,7 @@ jobs:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.buildcache
|
||||
key: ${{ runner.os }}-msvc-${{ github.sha }}
|
||||
@@ -80,7 +82,6 @@ jobs:
|
||||
shell: cmd
|
||||
run: |
|
||||
choco install vulkan-sdk wget
|
||||
python -m pip install --upgrade pip conan
|
||||
call refreshenv
|
||||
wget https://github.com/mbitsnbites/buildcache/releases/download/v0.27.6/buildcache-windows.zip
|
||||
7z x buildcache-windows.zip
|
||||
@@ -89,7 +90,7 @@ jobs:
|
||||
echo %PATH% >> %GITHUB_PATH%
|
||||
- name: Set up MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
@@ -100,7 +101,7 @@ jobs:
|
||||
run: |
|
||||
glslangValidator --version
|
||||
mkdir build
|
||||
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release
|
||||
cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DCLANG_FORMAT_SUFFIX=discordplzdontclang -DYUZU_TESTS=OFF -DYUZU_USE_BUNDLED_VCPKG=ON
|
||||
- name: Build
|
||||
run: cmake --build build
|
||||
- name: Cache Summary
|
||||
@@ -113,3 +114,8 @@ jobs:
|
||||
with:
|
||||
name: msvc
|
||||
path: artifacts/
|
||||
- name: Upload EXE
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ env.INDIVIDUAL_EXE }}
|
||||
path: ${{ env.INDIVIDUAL_EXE }}
|
||||
|
||||
7
.gitmodules
vendored
7
.gitmodules
vendored
@@ -34,9 +34,12 @@
|
||||
[submodule "SDL"]
|
||||
path = externals/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
[submodule "externals/cpp-httplib"]
|
||||
[submodule "cpp-httplib"]
|
||||
path = externals/cpp-httplib
|
||||
url = https://github.com/yhirose/cpp-httplib.git
|
||||
[submodule "externals/ffmpeg/ffmpeg"]
|
||||
[submodule "ffmpeg"]
|
||||
path = externals/ffmpeg/ffmpeg
|
||||
url = https://git.ffmpeg.org/ffmpeg.git
|
||||
[submodule "vcpkg"]
|
||||
path = externals/vcpkg
|
||||
url = https://github.com/Microsoft/vcpkg.git
|
||||
|
||||
176
CMakeLists.txt
176
CMakeLists.txt
@@ -35,6 +35,16 @@ option(YUZU_USE_BUNDLED_OPUS "Compile bundled opus" ON)
|
||||
|
||||
option(YUZU_TESTS "Compile tests" ON)
|
||||
|
||||
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" OFF)
|
||||
|
||||
if (YUZU_USE_BUNDLED_VCPKG)
|
||||
include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
|
||||
elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
|
||||
# Disable manifest mode (use vcpkg classic mode) when using a custom vcpkg installation
|
||||
option(VCPKG_MANIFEST_MODE "")
|
||||
include("$ENV{VCPKG_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
|
||||
# Default to a Release build
|
||||
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
|
||||
@@ -144,82 +154,34 @@ endif()
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
# System imported libraries
|
||||
# If not found, download any missing through Conan
|
||||
# =======================================================================
|
||||
set(CONAN_CMAKE_SILENT_OUTPUT TRUE)
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
|
||||
if (YUZU_CONAN_INSTALLED)
|
||||
if (IS_MULTI_CONFIG)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake)
|
||||
else()
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
endif()
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
|
||||
conan_basic_setup()
|
||||
message(STATUS "Adding conan installed libraries to the search path")
|
||||
|
||||
find_package(fmt 8.0.1 REQUIRED CONFIG)
|
||||
find_package(lz4 1.8 REQUIRED)
|
||||
find_package(nlohmann_json 3.8 REQUIRED CONFIG)
|
||||
find_package(ZLIB 1.2 REQUIRED)
|
||||
|
||||
# Search for config-only package first (for vcpkg), then try non-config
|
||||
find_package(zstd 1.5 CONFIG)
|
||||
if (NOT zstd_FOUND)
|
||||
find_package(zstd 1.5 REQUIRED)
|
||||
endif()
|
||||
|
||||
macro(yuzu_find_packages)
|
||||
set(options FORCE_REQUIRED)
|
||||
cmake_parse_arguments(FN "${options}" "" "" ${ARGN})
|
||||
if (YUZU_TESTS)
|
||||
find_package(Catch2 2.13.7 REQUIRED CONFIG)
|
||||
endif()
|
||||
|
||||
# Cmake has a *serious* lack of 2D array or associative array...
|
||||
# Capitalization matters here. We need the naming to match the generated paths from Conan
|
||||
set(REQUIRED_LIBS
|
||||
# Cmake Pkg Prefix Version Conan Pkg
|
||||
"fmt 8.0.1 fmt/8.1.1"
|
||||
"lz4 1.8 lz4/1.9.2"
|
||||
"nlohmann_json 3.8 nlohmann_json/3.8.0"
|
||||
"ZLIB 1.2 zlib/1.2.11"
|
||||
"zstd 1.5 zstd/1.5.0"
|
||||
# can't use opus until AVX check is fixed: https://github.com/yuzu-emu/yuzu/pull/4068
|
||||
#"opus 1.3 opus/1.3.1"
|
||||
)
|
||||
if (YUZU_TESTS)
|
||||
list(APPEND REQUIRED_LIBS
|
||||
"Catch2 2.13.7 catch2/2.13.7"
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(PACKAGE ${REQUIRED_LIBS})
|
||||
string(REGEX REPLACE "[ \t\r\n]+" ";" PACKAGE_SPLIT ${PACKAGE})
|
||||
list(GET PACKAGE_SPLIT 0 PACKAGE_PREFIX)
|
||||
list(GET PACKAGE_SPLIT 1 PACKAGE_VERSION)
|
||||
list(GET PACKAGE_SPLIT 2 PACKAGE_CONAN)
|
||||
# This function is called twice, once to check if the packages exist on the system already
|
||||
# and a second time to check if conan installed them properly. The second check passes in FORCE_REQUIRED
|
||||
if (NOT ${PACKAGE_PREFIX}_FOUND)
|
||||
if (FN_FORCE_REQUIRED)
|
||||
find_package(${PACKAGE_PREFIX} ${PACKAGE_VERSION} REQUIRED)
|
||||
else()
|
||||
find_package(${PACKAGE_PREFIX} ${PACKAGE_VERSION})
|
||||
endif()
|
||||
endif()
|
||||
if (NOT ${PACKAGE_PREFIX}_FOUND)
|
||||
list(APPEND CONAN_REQUIRED_LIBS ${PACKAGE_CONAN})
|
||||
else()
|
||||
# Set a legacy findPackage.cmake style PACKAGE_LIBRARIES variable for subprojects that rely on this
|
||||
set(${PACKAGE_PREFIX}_LIBRARIES "${PACKAGE_PREFIX}::${PACKAGE_PREFIX}")
|
||||
endif()
|
||||
endforeach()
|
||||
unset(FN_FORCE_REQUIRED)
|
||||
endmacro()
|
||||
|
||||
find_package(Boost 1.73.0 COMPONENTS context headers)
|
||||
find_package(Boost 1.73.0 COMPONENTS context)
|
||||
if (Boost_FOUND)
|
||||
set(Boost_LIBRARIES Boost::boost)
|
||||
# Conditionally add Boost::context only if the active version of the Conan or system Boost package provides it
|
||||
# Conditionally add Boost::context only if the found Boost package provides it
|
||||
# The old version is missing Boost::context, so we want to avoid adding in that case
|
||||
# The new version requires adding Boost::context to prevent linking issues
|
||||
#
|
||||
# This one is used by Conan on subsequent CMake configures, not the first configure.
|
||||
if (TARGET Boost::context)
|
||||
list(APPEND Boost_LIBRARIES Boost::context)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Boost 1.79.0 or newer not found, falling back to Conan")
|
||||
list(APPEND CONAN_REQUIRED_LIBS "boost/1.79.0")
|
||||
message(FATAL_ERROR "Boost 1.73.0 or newer not found")
|
||||
endif()
|
||||
|
||||
# boost:asio has functions that require AcceptEx et al
|
||||
@@ -227,19 +189,9 @@ if (MINGW)
|
||||
find_library(MSWSOCK_LIBRARY mswsock REQUIRED)
|
||||
endif()
|
||||
|
||||
# Attempt to locate any packages that are required and report the missing ones in CONAN_REQUIRED_LIBS
|
||||
yuzu_find_packages()
|
||||
|
||||
# Qt5 requires that we find components, so it doesn't fit our pretty little find package function
|
||||
if(ENABLE_QT)
|
||||
set(QT_VERSION 5.15)
|
||||
# We want to load the generated conan qt config so that we get the QT_ROOT var so that we can use the official
|
||||
# Qt5Config inside the root folder instead of the conan generated one.
|
||||
if(EXISTS ${CMAKE_BINARY_DIR}/qtConfig.cmake)
|
||||
include(${CMAKE_BINARY_DIR}/qtConfig.cmake)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
endif()
|
||||
|
||||
# Check for system Qt on Linux, fallback to bundled Qt
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
@@ -330,9 +282,6 @@ if(ENABLE_QT)
|
||||
|
||||
set(YUZU_QT_NO_CMAKE_SYSTEM_PATH)
|
||||
|
||||
# Workaround for an issue where conan tries to build Qt from scratch instead of download prebuilt binaries
|
||||
set(QT_PREFIX_HINT)
|
||||
|
||||
if(YUZU_USE_BUNDLED_QT)
|
||||
if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64)
|
||||
set(QT_BUILD qt-5.15.2-msvc2019_64)
|
||||
@@ -351,12 +300,12 @@ if(ENABLE_QT)
|
||||
set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH")
|
||||
endif()
|
||||
if ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND YUZU_USE_BUNDLED_QT)
|
||||
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets DBus ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
|
||||
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent DBus ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
|
||||
else()
|
||||
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
|
||||
find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
|
||||
endif()
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
find_package(Qt5 COMPONENTS WebEngineCore WebEngineWidgets)
|
||||
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT_TRANSLATION)
|
||||
@@ -403,71 +352,8 @@ if (ENABLE_SDL2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Install any missing dependencies with conan install
|
||||
if (CONAN_REQUIRED_LIBS)
|
||||
message(STATUS "Packages ${CONAN_REQUIRED_LIBS} not found!")
|
||||
# Use Conan to fetch the libraries that aren't found
|
||||
# Download conan.cmake automatically, you can also just copy the conan.cmake file
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
|
||||
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/release/0.18/conan.cmake" "${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
endif()
|
||||
include(${CMAKE_BINARY_DIR}/conan.cmake)
|
||||
|
||||
conan_check(VERSION 1.45.0 REQUIRED)
|
||||
|
||||
# Manually add iconv to fix a dep conflict between qt and sdl2
|
||||
# We don't need to add it through find_package or anything since the other two can find it just fine
|
||||
if ("${CONAN_REQUIRED_LIBS}" MATCHES "qt" AND "${CONAN_REQUIRED_LIBS}" MATCHES "sdl")
|
||||
list(APPEND CONAN_REQUIRED_LIBS "libiconv/1.16")
|
||||
endif()
|
||||
if (IS_MULTI_CONFIG)
|
||||
conan_cmake_run(REQUIRES ${CONAN_REQUIRED_LIBS}
|
||||
OPTIONS ${CONAN_LIB_OPTIONS}
|
||||
BUILD missing
|
||||
CONFIGURATION_TYPES "Release;Debug"
|
||||
GENERATORS cmake_multi cmake_find_package_multi)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo_multi.cmake)
|
||||
else()
|
||||
conan_cmake_run(REQUIRES ${CONAN_REQUIRED_LIBS}
|
||||
OPTIONS ${CONAN_LIB_OPTIONS}
|
||||
BUILD missing
|
||||
GENERATORS cmake cmake_find_package_multi)
|
||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||
endif()
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
|
||||
conan_basic_setup()
|
||||
|
||||
set(YUZU_CONAN_INSTALLED TRUE CACHE BOOL "If true, the following builds will add conan to the lib search path" FORCE)
|
||||
|
||||
# Now that we've installed what we are missing, try to locate them again,
|
||||
# this time with required, so we bail if its not found.
|
||||
yuzu_find_packages(FORCE_REQUIRED)
|
||||
|
||||
if (NOT Boost_FOUND)
|
||||
find_package(Boost 1.73.0 REQUIRED COMPONENTS context headers)
|
||||
set(Boost_LIBRARIES Boost::boost)
|
||||
# Conditionally add Boost::context only if the active version of the Conan Boost package provides it
|
||||
# The old version is missing Boost::context, so we want to avoid adding in that case
|
||||
# The new version requires adding Boost::context to prevent linking issues
|
||||
if (TARGET Boost::context)
|
||||
list(APPEND Boost_LIBRARIES Boost::context)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Due to issues with variable scopes in functions, we need to also find_package(qt5) outside of the function
|
||||
if(ENABLE_QT)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
list(APPEND CMAKE_PREFIX_PATH "${CONAN_QT_ROOT_RELEASE}")
|
||||
find_package(Qt5 5.15 REQUIRED COMPONENTS Widgets)
|
||||
if (YUZU_USE_QT_WEB_ENGINE)
|
||||
find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
# TODO(lat9nq): Determine what if any of this we still need
|
||||
#
|
||||
# Reexport some targets that are named differently when using the upstream CmakeConfig vs the generated Conan config
|
||||
# In order to ALIAS targets to a new name, they first need to be IMPORTED_GLOBAL
|
||||
# Dynarmic checks for target `boost` and so we want to make sure it can find it through our system instead of using their external
|
||||
|
||||
@@ -19,9 +19,6 @@ function(copy_yuzu_Qt5_deps target_dir)
|
||||
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
|
||||
if (MSVC)
|
||||
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
|
||||
icudt*.dll
|
||||
icuin*.dll
|
||||
icuuc*.dll
|
||||
Qt5Core$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Gui$<$<CONFIG:Debug>:d>.*
|
||||
Qt5Widgets$<$<CONFIG:Debug>:d>.*
|
||||
@@ -37,18 +34,17 @@ function(copy_yuzu_Qt5_deps target_dir)
|
||||
Qt5Quick$<$<CONFIG:Debug>:d>.*
|
||||
Qt5QuickWidgets$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebChannel$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngine$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngineCore$<$<CONFIG:Debug>:d>.*
|
||||
Qt5WebEngineWidgets$<$<CONFIG:Debug>:d>.*
|
||||
QtWebEngineProcess$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
|
||||
windows_copy_files(${target_dir} ${Qt5_RESOURCES_DIR} ${DLL_DEST}
|
||||
qtwebengine_resources.pak
|
||||
icudtl.dat
|
||||
qtwebengine_devtools_resources.pak
|
||||
qtwebengine_resources.pak
|
||||
qtwebengine_resources_100p.pak
|
||||
qtwebengine_resources_200p.pak
|
||||
icudtl.dat
|
||||
)
|
||||
endif ()
|
||||
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
|
||||
@@ -56,7 +52,7 @@ function(copy_yuzu_Qt5_deps target_dir)
|
||||
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
|
||||
qjpeg$<$<CONFIG:Debug>:d>.*
|
||||
qgif$<$<CONFIG:Debug>:d>.*
|
||||
)
|
||||
)
|
||||
else()
|
||||
set(Qt5_DLLS
|
||||
"${Qt5_DLL_DIR}libQt5Core.so.5"
|
||||
|
||||
2
externals/SDL
vendored
2
externals/SDL
vendored
Submodule externals/SDL updated: e2ade2bfc4...b424665e08
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 7f84870712...91d1f944e3
1
externals/vcpkg
vendored
Submodule
1
externals/vcpkg
vendored
Submodule
Submodule externals/vcpkg added at cef0b3ec76
@@ -182,8 +182,9 @@ create_target_directory_groups(common)
|
||||
|
||||
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 xbyak)
|
||||
if (MSVC)
|
||||
if (TARGET zstd::zstd)
|
||||
target_link_libraries(common PRIVATE zstd::zstd)
|
||||
else()
|
||||
target_link_libraries(common PRIVATE zstd)
|
||||
target_link_libraries(common PRIVATE
|
||||
$<IF:$<TARGET_EXISTS:zstd::libzstd_shared>,zstd::libzstd_shared,zstd::libzstd_static>)
|
||||
endif()
|
||||
|
||||
@@ -146,7 +146,16 @@ public:
|
||||
}
|
||||
|
||||
constexpr void Assign(const T& value) {
|
||||
#ifdef _MSC_VER
|
||||
storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value));
|
||||
#else
|
||||
// Explicitly reload with memcpy to avoid compiler aliasing quirks
|
||||
// regarding optimization: GCC/Clang clobber chained stores to
|
||||
// different bitfields in the same struct with the last value.
|
||||
StorageTypeWithEndian storage_;
|
||||
std::memcpy(&storage_, &storage, sizeof(storage_));
|
||||
storage = static_cast<StorageType>((storage_ & ~mask) | FormatValue(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr T Value() const {
|
||||
|
||||
@@ -18,14 +18,16 @@
|
||||
/// Helper macros to insert unused bytes or words to properly align structs. These values will be
|
||||
/// zero-initialized.
|
||||
#define INSERT_PADDING_BYTES(num_bytes) \
|
||||
std::array<u8, num_bytes> CONCAT2(pad, __LINE__) {}
|
||||
[[maybe_unused]] std::array<u8, num_bytes> CONCAT2(pad, __LINE__) {}
|
||||
#define INSERT_PADDING_WORDS(num_words) \
|
||||
std::array<u32, num_words> CONCAT2(pad, __LINE__) {}
|
||||
[[maybe_unused]] std::array<u32, num_words> CONCAT2(pad, __LINE__) {}
|
||||
|
||||
/// These are similar to the INSERT_PADDING_* macros but do not zero-initialize the contents.
|
||||
/// This keeps the structure trivial to construct.
|
||||
#define INSERT_PADDING_BYTES_NOINIT(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__)
|
||||
#define INSERT_PADDING_WORDS_NOINIT(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__)
|
||||
#define INSERT_PADDING_BYTES_NOINIT(num_bytes) \
|
||||
[[maybe_unused]] std::array<u8, num_bytes> CONCAT2(pad, __LINE__)
|
||||
#define INSERT_PADDING_WORDS_NOINIT(num_words) \
|
||||
[[maybe_unused]] std::array<u32, num_words> CONCAT2(pad, __LINE__)
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Service, PM) \
|
||||
SUB(Service, PREPO) \
|
||||
SUB(Service, PSC) \
|
||||
SUB(Service, PSM) \
|
||||
SUB(Service, PTM) \
|
||||
SUB(Service, SET) \
|
||||
SUB(Service, SM) \
|
||||
SUB(Service, SPL) \
|
||||
|
||||
@@ -95,7 +95,7 @@ enum class Class : u8 {
|
||||
Service_PM, ///< The PM service
|
||||
Service_PREPO, ///< The PREPO (Play report) service
|
||||
Service_PSC, ///< The PSC service
|
||||
Service_PSM, ///< The PSM service
|
||||
Service_PTM, ///< The PTM service
|
||||
Service_SET, ///< The SET (Settings) service
|
||||
Service_SM, ///< The SM (Service manager) service
|
||||
Service_SPL, ///< The SPL service
|
||||
|
||||
@@ -185,7 +185,6 @@ void RestoreGlobalState(bool is_powered_on) {
|
||||
values.max_anisotropy.SetGlobal(true);
|
||||
values.use_speed_limit.SetGlobal(true);
|
||||
values.speed_limit.SetGlobal(true);
|
||||
values.fps_cap.SetGlobal(true);
|
||||
values.use_disk_shader_cache.SetGlobal(true);
|
||||
values.gpu_accuracy.SetGlobal(true);
|
||||
values.use_asynchronous_gpu_emulation.SetGlobal(true);
|
||||
|
||||
@@ -106,7 +106,7 @@ struct ResolutionScalingInfo {
|
||||
* configurations. Specifying a default value and label is required. A minimum and maximum range can
|
||||
* be specified for sanitization.
|
||||
*/
|
||||
template <typename Type>
|
||||
template <typename Type, bool ranged = false>
|
||||
class Setting {
|
||||
protected:
|
||||
Setting() = default;
|
||||
@@ -126,8 +126,8 @@ public:
|
||||
* @param default_val Intial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit Setting(const Type& default_val, const std::string& name)
|
||||
: value{default_val}, default_value{default_val}, ranged{false}, label{name} {}
|
||||
explicit Setting(const Type& default_val, const std::string& name) requires(!ranged)
|
||||
: value{default_val}, default_value{default_val}, label{name} {}
|
||||
virtual ~Setting() = default;
|
||||
|
||||
/**
|
||||
@@ -139,9 +139,9 @@ public:
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val,
|
||||
const std::string& name)
|
||||
: value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val},
|
||||
ranged{true}, label{name} {}
|
||||
const std::string& name) requires(ranged)
|
||||
: value{default_val},
|
||||
default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {}
|
||||
|
||||
/**
|
||||
* Returns a reference to the setting's value.
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
* @param val The desired value
|
||||
*/
|
||||
virtual void SetValue(const Type& val) {
|
||||
Type temp{(ranged) ? std::clamp(val, minimum, maximum) : val};
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ public:
|
||||
* @returns A reference to the setting
|
||||
*/
|
||||
virtual const Type& operator=(const Type& val) {
|
||||
Type temp{(ranged) ? std::clamp(val, minimum, maximum) : val};
|
||||
Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
|
||||
std::swap(value, temp);
|
||||
return value;
|
||||
}
|
||||
@@ -207,7 +207,6 @@ protected:
|
||||
const Type default_value{}; ///< The default value
|
||||
const Type maximum{}; ///< Maximum allowed value of the setting
|
||||
const Type minimum{}; ///< Minimum allowed value of the setting
|
||||
const bool ranged; ///< The setting has sanitization ranges
|
||||
const std::string label{}; ///< The setting's label
|
||||
};
|
||||
|
||||
@@ -219,8 +218,8 @@ protected:
|
||||
*
|
||||
* By default, the global setting is used.
|
||||
*/
|
||||
template <typename Type>
|
||||
class SwitchableSetting : virtual public Setting<Type> {
|
||||
template <typename Type, bool ranged = false>
|
||||
class SwitchableSetting : virtual public Setting<Type, ranged> {
|
||||
public:
|
||||
/**
|
||||
* Sets a default value, label, and setting value.
|
||||
@@ -228,7 +227,7 @@ public:
|
||||
* @param default_val Intial value of the setting, and default value of the setting
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit SwitchableSetting(const Type& default_val, const std::string& name)
|
||||
explicit SwitchableSetting(const Type& default_val, const std::string& name) requires(!ranged)
|
||||
: Setting<Type>{default_val, name} {}
|
||||
virtual ~SwitchableSetting() = default;
|
||||
|
||||
@@ -241,8 +240,8 @@ public:
|
||||
* @param name Label for the setting
|
||||
*/
|
||||
explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val,
|
||||
const std::string& name)
|
||||
: Setting<Type>{default_val, min_val, max_val, name} {}
|
||||
const std::string& name) requires(ranged)
|
||||
: Setting<Type, true>{default_val, min_val, max_val, name} {}
|
||||
|
||||
/**
|
||||
* Tells this setting to represent either the global or custom setting when other member
|
||||
@@ -290,7 +289,7 @@ public:
|
||||
* @param val The new value
|
||||
*/
|
||||
void SetValue(const Type& val) override {
|
||||
Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
} else {
|
||||
@@ -306,7 +305,7 @@ public:
|
||||
* @returns A reference to the current setting value
|
||||
*/
|
||||
const Type& operator=(const Type& val) override {
|
||||
Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
|
||||
if (use_global) {
|
||||
std::swap(this->value, temp);
|
||||
return this->value;
|
||||
@@ -374,15 +373,15 @@ struct Values {
|
||||
Setting<std::string> audio_device_id{"auto", "output_device"};
|
||||
Setting<std::string> sink_id{"auto", "output_engine"};
|
||||
Setting<bool> audio_muted{false, "audio_muted"};
|
||||
SwitchableSetting<u8> volume{100, 0, 100, "volume"};
|
||||
SwitchableSetting<u8, true> volume{100, 0, 100, "volume"};
|
||||
|
||||
// Core
|
||||
SwitchableSetting<bool> use_multi_core{true, "use_multi_core"};
|
||||
SwitchableSetting<bool> use_extended_memory_layout{false, "use_extended_memory_layout"};
|
||||
|
||||
// Cpu
|
||||
SwitchableSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
|
||||
CPUAccuracy::Paranoid, "cpu_accuracy"};
|
||||
SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
|
||||
CPUAccuracy::Paranoid, "cpu_accuracy"};
|
||||
// TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021
|
||||
Setting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"};
|
||||
Setting<bool> cpu_debug_mode{false, "cpu_debug_mode"};
|
||||
@@ -409,7 +408,7 @@ struct Values {
|
||||
true, "cpuopt_unsafe_ignore_global_monitor"};
|
||||
|
||||
// Renderer
|
||||
SwitchableSetting<RendererBackend> renderer_backend{
|
||||
SwitchableSetting<RendererBackend, true> renderer_backend{
|
||||
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"};
|
||||
Setting<bool> renderer_debug{false, "debug"};
|
||||
Setting<bool> renderer_shader_feedback{false, "shader_feedback"};
|
||||
@@ -423,28 +422,26 @@ struct Values {
|
||||
SwitchableSetting<AntiAliasing> anti_aliasing{AntiAliasing::None, "anti_aliasing"};
|
||||
// *nix platforms may have issues with the borderless windowed fullscreen mode.
|
||||
// Default to exclusive fullscreen on these platforms for now.
|
||||
SwitchableSetting<FullscreenMode> fullscreen_mode{
|
||||
SwitchableSetting<FullscreenMode, true> fullscreen_mode{
|
||||
#ifdef _WIN32
|
||||
FullscreenMode::Borderless,
|
||||
#else
|
||||
FullscreenMode::Exclusive,
|
||||
#endif
|
||||
FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
|
||||
SwitchableSetting<int> aspect_ratio{0, 0, 3, "aspect_ratio"};
|
||||
SwitchableSetting<int> max_anisotropy{0, 0, 5, "max_anisotropy"};
|
||||
SwitchableSetting<int, true> aspect_ratio{0, 0, 3, "aspect_ratio"};
|
||||
SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
|
||||
SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
|
||||
SwitchableSetting<u16> speed_limit{100, 0, 9999, "speed_limit"};
|
||||
SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
|
||||
SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
|
||||
SwitchableSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
|
||||
GPUAccuracy::Extreme, "gpu_accuracy"};
|
||||
SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
|
||||
GPUAccuracy::Extreme, "gpu_accuracy"};
|
||||
SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
|
||||
SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
|
||||
SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
|
||||
SwitchableSetting<bool> use_vsync{true, "use_vsync"};
|
||||
SwitchableSetting<u16> fps_cap{1000, 1, 1000, "fps_cap"};
|
||||
Setting<bool> disable_fps_limit{false, "disable_fps_limit"};
|
||||
SwitchableSetting<ShaderBackend> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
|
||||
ShaderBackend::SPIRV, "shader_backend"};
|
||||
SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
|
||||
ShaderBackend::SPIRV, "shader_backend"};
|
||||
SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
|
||||
SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
|
||||
|
||||
@@ -460,10 +457,10 @@ struct Values {
|
||||
s64 custom_rtc_differential;
|
||||
|
||||
Setting<s32> current_user{0, "current_user"};
|
||||
SwitchableSetting<s32> language_index{1, 0, 17, "language_index"};
|
||||
SwitchableSetting<s32> region_index{1, 0, 6, "region_index"};
|
||||
SwitchableSetting<s32> time_zone_index{0, 0, 45, "time_zone_index"};
|
||||
SwitchableSetting<s32> sound_index{1, 0, 2, "sound_index"};
|
||||
SwitchableSetting<s32, true> language_index{1, 0, 17, "language_index"};
|
||||
SwitchableSetting<s32, true> region_index{1, 0, 6, "region_index"};
|
||||
SwitchableSetting<s32, true> time_zone_index{0, 0, 45, "time_zone_index"};
|
||||
SwitchableSetting<s32, true> sound_index{1, 0, 2, "sound_index"};
|
||||
|
||||
// Controls
|
||||
InputSetting<std::array<PlayerInput, 10>> players;
|
||||
@@ -485,7 +482,7 @@ struct Values {
|
||||
Setting<bool> tas_loop{false, "tas_loop"};
|
||||
|
||||
Setting<bool> mouse_panning{false, "mouse_panning"};
|
||||
Setting<u8> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
|
||||
Setting<u8, true> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
|
||||
Setting<bool> mouse_enabled{false, "mouse_enabled"};
|
||||
|
||||
Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
|
||||
|
||||
@@ -67,7 +67,7 @@ std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency,
|
||||
const auto& caps = GetCPUCaps();
|
||||
u64 rtsc_frequency = 0;
|
||||
if (caps.invariant_tsc) {
|
||||
rtsc_frequency = EstimateRDTSCFrequency();
|
||||
rtsc_frequency = caps.tsc_frequency ? caps.tsc_frequency : EstimateRDTSCFrequency();
|
||||
}
|
||||
|
||||
// Fallback to StandardWallClock if the hardware TSC does not have the precision greater than:
|
||||
|
||||
@@ -161,6 +161,22 @@ static CPUCaps Detect() {
|
||||
caps.invariant_tsc = Common::Bit<8>(cpu_id[3]);
|
||||
}
|
||||
|
||||
if (max_std_fn >= 0x15) {
|
||||
__cpuid(cpu_id, 0x15);
|
||||
caps.tsc_crystal_ratio_denominator = cpu_id[0];
|
||||
caps.tsc_crystal_ratio_numerator = cpu_id[1];
|
||||
caps.crystal_frequency = cpu_id[2];
|
||||
// Some CPU models might not return a crystal frequency.
|
||||
// The CPU model can be detected to use the values from turbostat
|
||||
// https://github.com/torvalds/linux/blob/master/tools/power/x86/turbostat/turbostat.c#L5569
|
||||
// but it's easier to just estimate the TSC tick rate for these cases.
|
||||
if (caps.tsc_crystal_ratio_denominator) {
|
||||
caps.tsc_frequency = static_cast<u64>(caps.crystal_frequency) *
|
||||
caps.tsc_crystal_ratio_numerator /
|
||||
caps.tsc_crystal_ratio_denominator;
|
||||
}
|
||||
}
|
||||
|
||||
if (max_std_fn >= 0x16) {
|
||||
__cpuid(cpu_id, 0x16);
|
||||
caps.base_frequency = cpu_id[0];
|
||||
|
||||
@@ -30,6 +30,11 @@ struct CPUCaps {
|
||||
u32 max_frequency;
|
||||
u32 bus_frequency;
|
||||
|
||||
u32 tsc_crystal_ratio_denominator;
|
||||
u32 tsc_crystal_ratio_numerator;
|
||||
u32 crystal_frequency;
|
||||
u64 tsc_frequency; // Derived from the above three values
|
||||
|
||||
bool sse : 1;
|
||||
bool sse2 : 1;
|
||||
bool sse3 : 1;
|
||||
|
||||
@@ -605,6 +605,10 @@ add_library(core STATIC
|
||||
hle/service/psc/psc.h
|
||||
hle/service/ptm/psm.cpp
|
||||
hle/service/ptm/psm.h
|
||||
hle/service/ptm/ptm.cpp
|
||||
hle/service/ptm/ptm.h
|
||||
hle/service/ptm/ts.cpp
|
||||
hle/service/ptm/ts.h
|
||||
hle/service/kernel_helpers.cpp
|
||||
hle/service/kernel_helpers.h
|
||||
hle/service/service.cpp
|
||||
|
||||
@@ -147,7 +147,6 @@ void ARM_Interface::Run() {
|
||||
|
||||
// Notify the debugger and go to sleep if a watchpoint was hit.
|
||||
if (Has(hr, watchpoint)) {
|
||||
RewindBreakpointInstruction();
|
||||
if (system.DebuggerEnabled()) {
|
||||
system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint());
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ public:
|
||||
static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
|
||||
static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
|
||||
static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
|
||||
static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::UserDefined5;
|
||||
static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::MemoryAbort;
|
||||
static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return MemoryRead32(vaddr);
|
||||
return memory.Read32(vaddr);
|
||||
}
|
||||
|
||||
void MemoryWrite8(u32 vaddr, u8 value) override {
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
parent.LogBacktrace();
|
||||
LOG_ERROR(Core_ARM,
|
||||
"Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
|
||||
num_instructions, MemoryRead32(pc));
|
||||
num_instructions, memory.Read32(pc));
|
||||
}
|
||||
|
||||
void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
parent.LogBacktrace();
|
||||
LOG_CRITICAL(Core_ARM,
|
||||
"ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})",
|
||||
exception, pc, MemoryRead32(pc), parent.IsInThumbMode());
|
||||
exception, pc, memory.Read32(pc), parent.IsInThumbMode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
const auto match{parent.MatchingWatchpoint(addr, size, type)};
|
||||
if (match) {
|
||||
parent.halted_watchpoint = match;
|
||||
ReturnException(parent.jit.load()->Regs()[15], ARM_Interface::watchpoint);
|
||||
parent.jit.load()->HaltExecution(ARM_Interface::watchpoint);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -204,7 +204,6 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||
|
||||
// Code cache size
|
||||
config.code_cache_size = 512_MiB;
|
||||
config.far_code_offset = 400_MiB;
|
||||
|
||||
// Allow memory fault handling to work
|
||||
if (system.DebuggerEnabled()) {
|
||||
@@ -215,7 +214,6 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||
if (!page_table) {
|
||||
// Don't waste too much memory on null_jit
|
||||
config.code_cache_size = 8_MiB;
|
||||
config.far_code_offset = 4_MiB;
|
||||
}
|
||||
|
||||
// Safe optimizations
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return MemoryRead32(vaddr);
|
||||
return memory.Read32(vaddr);
|
||||
}
|
||||
|
||||
void MemoryWrite8(u64 vaddr, u8 value) override {
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
parent.LogBacktrace();
|
||||
LOG_ERROR(Core_ARM,
|
||||
"Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
|
||||
num_instructions, MemoryRead32(pc));
|
||||
num_instructions, memory.Read32(pc));
|
||||
}
|
||||
|
||||
void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op,
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
|
||||
parent.LogBacktrace();
|
||||
LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
|
||||
static_cast<std::size_t>(exception), pc, MemoryRead32(pc));
|
||||
static_cast<std::size_t>(exception), pc, memory.Read32(pc));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ public:
|
||||
const auto match{parent.MatchingWatchpoint(addr, size, type)};
|
||||
if (match) {
|
||||
parent.halted_watchpoint = match;
|
||||
ReturnException(parent.jit.load()->GetPC(), ARM_Interface::watchpoint);
|
||||
parent.jit.load()->HaltExecution(ARM_Interface::watchpoint);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -264,7 +264,6 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||
|
||||
// Code cache size
|
||||
config.code_cache_size = 512_MiB;
|
||||
config.far_code_offset = 400_MiB;
|
||||
|
||||
// Allow memory fault handling to work
|
||||
if (system.DebuggerEnabled()) {
|
||||
@@ -275,7 +274,6 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||
if (!page_table) {
|
||||
// Don't waste too much memory on null_jit
|
||||
config.code_cache_size = 8_MiB;
|
||||
config.far_code_offset = 4_MiB;
|
||||
}
|
||||
|
||||
// Safe optimizations
|
||||
|
||||
@@ -99,10 +99,8 @@ void EmulatedController::ReloadFromSettings() {
|
||||
// Other or debug controller should always be a pro controller
|
||||
if (npad_id_type != NpadIdType::Other) {
|
||||
SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
|
||||
original_npad_type = npad_type;
|
||||
} else {
|
||||
SetNpadStyleIndex(NpadStyleIndex::ProController);
|
||||
original_npad_type = npad_type;
|
||||
}
|
||||
|
||||
if (player.connected) {
|
||||
@@ -341,7 +339,6 @@ void EmulatedController::DisableConfiguration() {
|
||||
Disconnect();
|
||||
}
|
||||
SetNpadStyleIndex(tmp_npad_type);
|
||||
original_npad_type = tmp_npad_type;
|
||||
}
|
||||
|
||||
// Apply temporary connected status to the real controller
|
||||
@@ -953,27 +950,13 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
|
||||
if (!is_connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to reconnect with the original type
|
||||
if (npad_type != original_npad_type) {
|
||||
Disconnect();
|
||||
const auto current_npad_type = npad_type;
|
||||
SetNpadStyleIndex(original_npad_type);
|
||||
if (IsControllerSupported()) {
|
||||
Connect();
|
||||
return;
|
||||
}
|
||||
SetNpadStyleIndex(current_npad_type);
|
||||
Connect();
|
||||
}
|
||||
|
||||
if (IsControllerSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Disconnect();
|
||||
|
||||
// Fallback Fullkey controllers to Pro controllers
|
||||
// Fallback fullkey controllers to Pro controllers
|
||||
if (IsControllerFullkey() && supported_style_tag.fullkey) {
|
||||
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
|
||||
SetNpadStyleIndex(NpadStyleIndex::ProController);
|
||||
@@ -981,22 +964,6 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback Dual joycon controllers to Pro controllers
|
||||
if (npad_type == NpadStyleIndex::JoyconDual && supported_style_tag.fullkey) {
|
||||
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Pro controller", npad_type);
|
||||
SetNpadStyleIndex(NpadStyleIndex::ProController);
|
||||
Connect();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback Pro controllers to Dual joycon
|
||||
if (npad_type == NpadStyleIndex::ProController && supported_style_tag.joycon_dual) {
|
||||
LOG_WARNING(Service_HID, "Reconnecting controller type {} as Dual Joycons", npad_type);
|
||||
SetNpadStyleIndex(NpadStyleIndex::JoyconDual);
|
||||
Connect();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_HID, "Controller type {} is not supported. Disconnecting controller",
|
||||
npad_type);
|
||||
}
|
||||
|
||||
@@ -401,7 +401,6 @@ private:
|
||||
|
||||
const NpadIdType npad_id_type;
|
||||
NpadStyleIndex npad_type{NpadStyleIndex::None};
|
||||
NpadStyleIndex original_npad_type{NpadStyleIndex::None};
|
||||
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
||||
bool is_connected{false};
|
||||
bool is_configuring{false};
|
||||
|
||||
@@ -30,19 +30,19 @@ public:
|
||||
explicit KCodeMemory(KernelCore& kernel_);
|
||||
|
||||
Result Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size);
|
||||
void Finalize();
|
||||
void Finalize() override;
|
||||
|
||||
Result Map(VAddr address, size_t size);
|
||||
Result Unmap(VAddr address, size_t size);
|
||||
Result MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm);
|
||||
Result UnmapFromOwner(VAddr address, size_t size);
|
||||
|
||||
bool IsInitialized() const {
|
||||
bool IsInitialized() const override {
|
||||
return m_is_initialized;
|
||||
}
|
||||
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
|
||||
|
||||
KProcess* GetOwner() const {
|
||||
KProcess* GetOwner() const override {
|
||||
return m_owner;
|
||||
}
|
||||
VAddr GetSourceAddress() const {
|
||||
|
||||
@@ -308,14 +308,20 @@ void KThread::Finalize() {
|
||||
|
||||
auto it = waiter_list.begin();
|
||||
while (it != waiter_list.end()) {
|
||||
// Clear the lock owner
|
||||
it->SetLockOwner(nullptr);
|
||||
// Get the thread.
|
||||
KThread* const waiter = std::addressof(*it);
|
||||
|
||||
// The thread shouldn't be a kernel waiter.
|
||||
ASSERT(!IsKernelAddressKey(waiter->GetAddressKey()));
|
||||
|
||||
// Clear the lock owner.
|
||||
waiter->SetLockOwner(nullptr);
|
||||
|
||||
// Erase the waiter from our list.
|
||||
it = waiter_list.erase(it);
|
||||
|
||||
// Cancel the thread's wait.
|
||||
it->CancelWait(ResultInvalidState, true);
|
||||
waiter->CancelWait(ResultInvalidState, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ protected:
|
||||
void Get(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.RawString());
|
||||
ProfileBase profile_base{};
|
||||
ProfileData data{};
|
||||
UserData data{};
|
||||
if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) {
|
||||
ctx.WriteBuffer(data);
|
||||
IPC::ResponseBuilder rb{ctx, 16};
|
||||
@@ -373,18 +373,18 @@ protected:
|
||||
reinterpret_cast<const char*>(base.username.data()), base.username.size()),
|
||||
base.timestamp, base.user_uuid.RawString());
|
||||
|
||||
if (user_data.size() < sizeof(ProfileData)) {
|
||||
LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
|
||||
if (user_data.size() < sizeof(UserData)) {
|
||||
LOG_ERROR(Service_ACC, "UserData buffer too small!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERR_INVALID_BUFFER);
|
||||
return;
|
||||
}
|
||||
|
||||
ProfileData data;
|
||||
std::memcpy(&data, user_data.data(), sizeof(ProfileData));
|
||||
UserData data;
|
||||
std::memcpy(&data, user_data.data(), sizeof(UserData));
|
||||
|
||||
if (!profile_manager.SetProfileBaseAndData(user_id, base, data)) {
|
||||
LOG_ERROR(Service_ACC, "Failed to update profile data and base!");
|
||||
LOG_ERROR(Service_ACC, "Failed to update user data and base!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERR_FAILED_SAVE_DATA);
|
||||
return;
|
||||
@@ -406,15 +406,15 @@ protected:
|
||||
reinterpret_cast<const char*>(base.username.data()), base.username.size()),
|
||||
base.timestamp, base.user_uuid.RawString());
|
||||
|
||||
if (user_data.size() < sizeof(ProfileData)) {
|
||||
LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
|
||||
if (user_data.size() < sizeof(UserData)) {
|
||||
LOG_ERROR(Service_ACC, "UserData buffer too small!");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERR_INVALID_BUFFER);
|
||||
return;
|
||||
}
|
||||
|
||||
ProfileData data;
|
||||
std::memcpy(&data, user_data.data(), sizeof(ProfileData));
|
||||
UserData data;
|
||||
std::memcpy(&data, user_data.data(), sizeof(UserData));
|
||||
|
||||
Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Write,
|
||||
Common::FS::FileType::BinaryFile);
|
||||
|
||||
@@ -22,7 +22,7 @@ struct UserRaw {
|
||||
UUID uuid2{};
|
||||
u64 timestamp{};
|
||||
ProfileUsername username{};
|
||||
ProfileData extra_data{};
|
||||
UserData extra_data{};
|
||||
};
|
||||
static_assert(sizeof(UserRaw) == 0xC8, "UserRaw has incorrect size.");
|
||||
|
||||
@@ -263,7 +263,7 @@ UUID ProfileManager::GetLastOpenedUser() const {
|
||||
|
||||
/// Return the users profile base and the unknown arbitary data.
|
||||
bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
|
||||
ProfileData& data) const {
|
||||
UserData& data) const {
|
||||
if (GetProfileBase(index, profile)) {
|
||||
data = profiles[*index].data;
|
||||
return true;
|
||||
@@ -272,15 +272,14 @@ bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, Pro
|
||||
}
|
||||
|
||||
/// Return the users profile base and the unknown arbitary data.
|
||||
bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile,
|
||||
ProfileData& data) const {
|
||||
bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile, UserData& data) const {
|
||||
const auto idx = GetUserIndex(uuid);
|
||||
return GetProfileBaseAndData(idx, profile, data);
|
||||
}
|
||||
|
||||
/// Return the users profile base and the unknown arbitary data.
|
||||
bool ProfileManager::GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile,
|
||||
ProfileData& data) const {
|
||||
UserData& data) const {
|
||||
return GetProfileBaseAndData(user.user_uuid, profile, data);
|
||||
}
|
||||
|
||||
@@ -318,7 +317,7 @@ bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
|
||||
}
|
||||
|
||||
bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new,
|
||||
const ProfileData& data_new) {
|
||||
const UserData& data_new) {
|
||||
const auto index = GetUserIndex(uuid);
|
||||
if (index.has_value() && SetProfileBase(uuid, profile_new)) {
|
||||
profiles[*index].data = data_new;
|
||||
|
||||
@@ -22,7 +22,7 @@ using UserIDArray = std::array<Common::UUID, MAX_USERS>;
|
||||
|
||||
/// Contains extra data related to a user.
|
||||
/// TODO: RE this structure
|
||||
struct ProfileData {
|
||||
struct UserData {
|
||||
INSERT_PADDING_WORDS_NOINIT(1);
|
||||
u32 icon_id;
|
||||
u8 bg_color_id;
|
||||
@@ -30,7 +30,7 @@ struct ProfileData {
|
||||
INSERT_PADDING_BYTES_NOINIT(0x10);
|
||||
INSERT_PADDING_BYTES_NOINIT(0x60);
|
||||
};
|
||||
static_assert(sizeof(ProfileData) == 0x80, "ProfileData structure has incorrect size");
|
||||
static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
|
||||
|
||||
/// This holds general information about a users profile. This is where we store all the information
|
||||
/// based on a specific user
|
||||
@@ -38,7 +38,7 @@ struct ProfileInfo {
|
||||
Common::UUID user_uuid{};
|
||||
ProfileUsername username{};
|
||||
u64 creation_time{};
|
||||
ProfileData data{}; // TODO(ognik): Work out what this is
|
||||
UserData data{}; // TODO(ognik): Work out what this is
|
||||
bool is_open{};
|
||||
};
|
||||
|
||||
@@ -74,10 +74,9 @@ public:
|
||||
bool GetProfileBase(Common::UUID uuid, ProfileBase& profile) const;
|
||||
bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const;
|
||||
bool GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
|
||||
ProfileData& data) const;
|
||||
bool GetProfileBaseAndData(Common::UUID uuid, ProfileBase& profile, ProfileData& data) const;
|
||||
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile,
|
||||
ProfileData& data) const;
|
||||
UserData& data) const;
|
||||
bool GetProfileBaseAndData(Common::UUID uuid, ProfileBase& profile, UserData& data) const;
|
||||
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile, UserData& data) const;
|
||||
std::size_t GetUserCount() const;
|
||||
std::size_t GetOpenUserCount() const;
|
||||
bool UserExists(Common::UUID uuid) const;
|
||||
@@ -93,7 +92,7 @@ public:
|
||||
bool RemoveUser(Common::UUID uuid);
|
||||
bool SetProfileBase(Common::UUID uuid, const ProfileBase& profile_new);
|
||||
bool SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new,
|
||||
const ProfileData& data_new);
|
||||
const UserData& data_new);
|
||||
|
||||
private:
|
||||
void ParseUserSaveFile();
|
||||
|
||||
@@ -238,6 +238,7 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
|
||||
{130, nullptr, "FriendInvitationSetApplicationParameter"},
|
||||
{131, nullptr, "FriendInvitationClearApplicationParameter"},
|
||||
{132, nullptr, "FriendInvitationPushApplicationParameter"},
|
||||
{140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
|
||||
{900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
@@ -635,6 +636,10 @@ void AppletMessageQueue::RequestExit() {
|
||||
PushMessage(AppletMessage::Exit);
|
||||
}
|
||||
|
||||
void AppletMessageQueue::RequestResume() {
|
||||
PushMessage(AppletMessage::Resume);
|
||||
}
|
||||
|
||||
void AppletMessageQueue::FocusStateChanged() {
|
||||
PushMessage(AppletMessage::FocusStateChanged);
|
||||
}
|
||||
@@ -1310,6 +1315,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||
{33, &IApplicationFunctions::EndBlockingHomeButton, "EndBlockingHomeButton"},
|
||||
{34, nullptr, "SelectApplicationLicense"},
|
||||
{35, nullptr, "GetDeviceSaveDataSizeMax"},
|
||||
{36, nullptr, "GetLimitedApplicationLicense"},
|
||||
{37, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
|
||||
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
|
||||
{50, &IApplicationFunctions::GetPseudoDeviceId, "GetPseudoDeviceId"},
|
||||
{60, nullptr, "SetMediaPlaybackStateForApplication"},
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
AppletMessage PopMessage();
|
||||
std::size_t GetMessageCount() const;
|
||||
void RequestExit();
|
||||
void RequestResume();
|
||||
void FocusStateChanged();
|
||||
void OperationModeChanged();
|
||||
|
||||
|
||||
@@ -140,8 +140,8 @@ public:
|
||||
{20401, nullptr, "UnregisterSystemApplicationDeliveryTask"},
|
||||
{20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"},
|
||||
{30100, &IBcatService::SetPassphrase, "SetPassphrase"},
|
||||
{30101, nullptr, "Unknown"},
|
||||
{30102, nullptr, "Unknown2"},
|
||||
{30101, nullptr, "Unknown30101"},
|
||||
{30102, nullptr, "Unknown30102"},
|
||||
{30200, nullptr, "RegisterBackgroundDeliveryTask"},
|
||||
{30201, nullptr, "UnregisterBackgroundDeliveryTask"},
|
||||
{30202, nullptr, "BlockDeliveryTask"},
|
||||
|
||||
@@ -181,6 +181,11 @@ public:
|
||||
{147, nullptr, "RegisterAudioControlNotification"},
|
||||
{148, nullptr, "SendAudioControlPassthroughCommand"},
|
||||
{149, nullptr, "SendAudioControlSetAbsoluteVolumeCommand"},
|
||||
{150, nullptr, "AcquireAudioSinkVolumeLocallyChangedEvent"},
|
||||
{151, nullptr, "AcquireAudioSinkVolumeUpdateRequestCompletedEvent"},
|
||||
{152, nullptr, "GetAudioSinkVolume"},
|
||||
{153, nullptr, "RequestUpdateAudioSinkVolume"},
|
||||
{154, nullptr, "IsAudioSinkVolumeSupported"},
|
||||
{256, nullptr, "IsManufacturingMode"},
|
||||
{257, nullptr, "EmulateBluetoothCrash"},
|
||||
{258, nullptr, "GetBleChannelMap"},
|
||||
|
||||
@@ -214,8 +214,12 @@ public:
|
||||
{76, nullptr, "Unknown76"},
|
||||
{100, nullptr, "Unknown100"},
|
||||
{101, nullptr, "Unknown101"},
|
||||
{110, nullptr, "Unknown102"},
|
||||
{111, nullptr, "Unknown103"},
|
||||
{110, nullptr, "Unknown110"},
|
||||
{111, nullptr, "Unknown111"},
|
||||
{112, nullptr, "Unknown112"},
|
||||
{113, nullptr, "Unknown113"},
|
||||
{114, nullptr, "Unknown114"},
|
||||
{115, nullptr, "Unknown115"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -6,7 +6,13 @@
|
||||
namespace Service::Fatal {
|
||||
|
||||
Fatal_P::Fatal_P(std::shared_ptr<Module> module_, Core::System& system_)
|
||||
: Interface(std::move(module_), system_, "fatal:p") {}
|
||||
: Interface(std::move(module_), system_, "fatal:p") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetFatalEvent"},
|
||||
{10, nullptr, "GetFatalContext"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
Fatal_P::~Fatal_P() = default;
|
||||
|
||||
|
||||
@@ -838,11 +838,11 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
|
||||
|
||||
const auto now = steady_clock::now();
|
||||
|
||||
// Filter out non-zero vibrations that are within 10ms of each other.
|
||||
// Filter out non-zero vibrations that are within 15ms of each other.
|
||||
if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
|
||||
duration_cast<milliseconds>(
|
||||
now - controller.vibration[device_index].last_vibration_timepoint) <
|
||||
milliseconds(10)) {
|
||||
milliseconds(15)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,19 @@ enum class RequestState : u32 {
|
||||
Connected = 3,
|
||||
};
|
||||
|
||||
enum class InternetConnectionType : u8 {
|
||||
WiFi = 1,
|
||||
Ethernet = 2,
|
||||
};
|
||||
|
||||
enum class InternetConnectionStatus : u8 {
|
||||
ConnectingUnknown1,
|
||||
ConnectingUnknown2,
|
||||
ConnectingUnknown3,
|
||||
ConnectingUnknown4,
|
||||
Connected,
|
||||
};
|
||||
|
||||
struct IpAddressSetting {
|
||||
bool is_automatic{};
|
||||
Network::IPv4Address current_address{};
|
||||
@@ -271,6 +284,7 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid
|
||||
}
|
||||
|
||||
void CreateScanRequest(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
|
||||
@@ -279,6 +293,7 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IScanRequest>(system);
|
||||
}
|
||||
|
||||
void CreateRequest(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
|
||||
@@ -287,6 +302,7 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IRequest>(system);
|
||||
}
|
||||
|
||||
void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
@@ -335,12 +351,14 @@ private:
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void RemoveNetworkProfile(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
@@ -354,6 +372,7 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(*ipv4);
|
||||
}
|
||||
|
||||
void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NIFM, "called");
|
||||
|
||||
@@ -369,6 +388,7 @@ private:
|
||||
rb.PushIpcInterface<INetworkProfile>(system);
|
||||
rb.PushRaw<u128>(uuid);
|
||||
}
|
||||
|
||||
void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
@@ -405,6 +425,7 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw<IpConfigInfo>(ip_config_info);
|
||||
}
|
||||
|
||||
void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
@@ -412,6 +433,24 @@ private:
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(0);
|
||||
}
|
||||
|
||||
void GetInternetConnectionStatus(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
struct Output {
|
||||
InternetConnectionType type{InternetConnectionType::WiFi};
|
||||
u8 wifi_strength{3};
|
||||
InternetConnectionStatus state{InternetConnectionStatus::Connected};
|
||||
};
|
||||
static_assert(sizeof(Output) == 0x3, "Output has incorrect size.");
|
||||
|
||||
constexpr Output out{};
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(out);
|
||||
}
|
||||
|
||||
void IsEthernetCommunicationEnabled(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
@@ -423,6 +462,7 @@ private:
|
||||
rb.Push<u8>(0);
|
||||
}
|
||||
}
|
||||
|
||||
void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
@@ -456,7 +496,7 @@ IGeneralService::IGeneralService(Core::System& system_)
|
||||
{15, &IGeneralService::GetCurrentIpConfigInfo, "GetCurrentIpConfigInfo"},
|
||||
{16, nullptr, "SetWirelessCommunicationEnabled"},
|
||||
{17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
|
||||
{18, nullptr, "GetInternetConnectionStatus"},
|
||||
{18, &IGeneralService::GetInternetConnectionStatus, "GetInternetConnectionStatus"},
|
||||
{19, nullptr, "SetEthernetCommunicationEnabled"},
|
||||
{20, &IGeneralService::IsEthernetCommunicationEnabled, "IsEthernetCommunicationEnabled"},
|
||||
{21, &IGeneralService::IsAnyInternetRequestAccepted, "IsAnyInternetRequestAccepted"},
|
||||
|
||||
@@ -34,6 +34,7 @@ enum class TransactionId {
|
||||
|
||||
class IBinder {
|
||||
public:
|
||||
virtual ~IBinder() = default;
|
||||
virtual void Transact(Kernel::HLERequestContext& ctx, android::TransactionId code,
|
||||
u32 flags) = 0;
|
||||
virtual Kernel::KReadableEvent& GetNativeHandle() = 0;
|
||||
|
||||
@@ -287,9 +287,21 @@ s64 NVFlinger::GetNextTicks() const {
|
||||
static constexpr s64 max_hertz = 120LL;
|
||||
|
||||
const auto& settings = Settings::values;
|
||||
const bool unlocked_fps = settings.disable_fps_limit.GetValue();
|
||||
const s64 fps_cap = unlocked_fps ? static_cast<s64>(settings.fps_cap.GetValue()) : 1;
|
||||
return (1000000000 * (1LL << swap_interval)) / (max_hertz * fps_cap);
|
||||
auto speed_scale = 1.f;
|
||||
if (settings.use_multi_core.GetValue()) {
|
||||
if (settings.use_speed_limit.GetValue()) {
|
||||
// Scales the speed based on speed_limit setting on MC. SC is handled by
|
||||
// SpeedLimiter::DoSpeedLimiting.
|
||||
speed_scale = 100.f / settings.speed_limit.GetValue();
|
||||
} else {
|
||||
// Run at unlocked framerate.
|
||||
speed_scale = 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
const auto next_ticks = ((1000000000 * (1LL << swap_interval)) / max_hertz);
|
||||
|
||||
return static_cast<s64>(speed_scale * static_cast<float>(next_ticks));
|
||||
}
|
||||
|
||||
} // namespace Service::NVFlinger
|
||||
|
||||
@@ -9,10 +9,8 @@
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/ptm/psm.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::PSM {
|
||||
namespace Service::PTM {
|
||||
|
||||
class IPsmSession final : public ServiceFramework<IPsmSession> {
|
||||
public:
|
||||
@@ -57,7 +55,7 @@ public:
|
||||
|
||||
private:
|
||||
void BindStateChangeEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PSM, "called");
|
||||
LOG_DEBUG(Service_PTM, "called");
|
||||
|
||||
should_signal = true;
|
||||
|
||||
@@ -67,7 +65,7 @@ private:
|
||||
}
|
||||
|
||||
void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PSM, "called");
|
||||
LOG_DEBUG(Service_PTM, "called");
|
||||
|
||||
should_signal = false;
|
||||
|
||||
@@ -78,7 +76,7 @@ private:
|
||||
void SetChargerTypeChangeEventEnabled(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto state = rp.Pop<bool>();
|
||||
LOG_DEBUG(Service_PSM, "called, state={}", state);
|
||||
LOG_DEBUG(Service_PTM, "called, state={}", state);
|
||||
|
||||
should_signal_charger_type = state;
|
||||
|
||||
@@ -89,7 +87,7 @@ private:
|
||||
void SetPowerSupplyChangeEventEnabled(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto state = rp.Pop<bool>();
|
||||
LOG_DEBUG(Service_PSM, "called, state={}", state);
|
||||
LOG_DEBUG(Service_PTM, "called, state={}", state);
|
||||
|
||||
should_signal_power_supply = state;
|
||||
|
||||
@@ -100,7 +98,7 @@ private:
|
||||
void SetBatteryVoltageStateChangeEventEnabled(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto state = rp.Pop<bool>();
|
||||
LOG_DEBUG(Service_PSM, "called, state={}", state);
|
||||
LOG_DEBUG(Service_PTM, "called, state={}", state);
|
||||
|
||||
should_signal_battery_voltage = state;
|
||||
|
||||
@@ -117,76 +115,58 @@ private:
|
||||
Kernel::KEvent* state_change_event;
|
||||
};
|
||||
|
||||
class PSM final : public ServiceFramework<PSM> {
|
||||
public:
|
||||
explicit PSM(Core::System& system_) : ServiceFramework{system_, "psm"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"},
|
||||
{1, &PSM::GetChargerType, "GetChargerType"},
|
||||
{2, nullptr, "EnableBatteryCharging"},
|
||||
{3, nullptr, "DisableBatteryCharging"},
|
||||
{4, nullptr, "IsBatteryChargingEnabled"},
|
||||
{5, nullptr, "AcquireControllerPowerSupply"},
|
||||
{6, nullptr, "ReleaseControllerPowerSupply"},
|
||||
{7, &PSM::OpenSession, "OpenSession"},
|
||||
{8, nullptr, "EnableEnoughPowerChargeEmulation"},
|
||||
{9, nullptr, "DisableEnoughPowerChargeEmulation"},
|
||||
{10, nullptr, "EnableFastBatteryCharging"},
|
||||
{11, nullptr, "DisableFastBatteryCharging"},
|
||||
{12, nullptr, "GetBatteryVoltageState"},
|
||||
{13, nullptr, "GetRawBatteryChargePercentage"},
|
||||
{14, nullptr, "IsEnoughPowerSupplied"},
|
||||
{15, nullptr, "GetBatteryAgePercentage"},
|
||||
{16, nullptr, "GetBatteryChargeInfoEvent"},
|
||||
{17, nullptr, "GetBatteryChargeInfoFields"},
|
||||
{18, nullptr, "GetBatteryChargeCalibratedEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
~PSM() override = default;
|
||||
|
||||
private:
|
||||
void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PSM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(battery_charge_percentage);
|
||||
}
|
||||
|
||||
void GetChargerType(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PSM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(charger_type);
|
||||
}
|
||||
|
||||
void OpenSession(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PSM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IPsmSession>(system);
|
||||
}
|
||||
|
||||
enum class ChargerType : u32 {
|
||||
Unplugged = 0,
|
||||
RegularCharger = 1,
|
||||
LowPowerCharger = 2,
|
||||
Unknown = 3,
|
||||
PSM::PSM(Core::System& system_) : ServiceFramework{system_, "psm"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &PSM::GetBatteryChargePercentage, "GetBatteryChargePercentage"},
|
||||
{1, &PSM::GetChargerType, "GetChargerType"},
|
||||
{2, nullptr, "EnableBatteryCharging"},
|
||||
{3, nullptr, "DisableBatteryCharging"},
|
||||
{4, nullptr, "IsBatteryChargingEnabled"},
|
||||
{5, nullptr, "AcquireControllerPowerSupply"},
|
||||
{6, nullptr, "ReleaseControllerPowerSupply"},
|
||||
{7, &PSM::OpenSession, "OpenSession"},
|
||||
{8, nullptr, "EnableEnoughPowerChargeEmulation"},
|
||||
{9, nullptr, "DisableEnoughPowerChargeEmulation"},
|
||||
{10, nullptr, "EnableFastBatteryCharging"},
|
||||
{11, nullptr, "DisableFastBatteryCharging"},
|
||||
{12, nullptr, "GetBatteryVoltageState"},
|
||||
{13, nullptr, "GetRawBatteryChargePercentage"},
|
||||
{14, nullptr, "IsEnoughPowerSupplied"},
|
||||
{15, nullptr, "GetBatteryAgePercentage"},
|
||||
{16, nullptr, "GetBatteryChargeInfoEvent"},
|
||||
{17, nullptr, "GetBatteryChargeInfoFields"},
|
||||
{18, nullptr, "GetBatteryChargeCalibratedEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
u32 battery_charge_percentage{100}; // 100%
|
||||
ChargerType charger_type{ChargerType::RegularCharger};
|
||||
};
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
|
||||
std::make_shared<PSM>(system)->InstallAsService(sm);
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
} // namespace Service::PSM
|
||||
PSM::~PSM() = default;
|
||||
|
||||
void PSM::GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PTM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(battery_charge_percentage);
|
||||
}
|
||||
|
||||
void PSM::GetChargerType(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PTM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushEnum(charger_type);
|
||||
}
|
||||
|
||||
void PSM::OpenSession(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_PTM, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IPsmSession>(system);
|
||||
}
|
||||
|
||||
} // namespace Service::PTM
|
||||
|
||||
@@ -3,16 +3,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
namespace Service::PTM {
|
||||
|
||||
namespace Service::PSM {
|
||||
class PSM final : public ServiceFramework<PSM> {
|
||||
public:
|
||||
explicit PSM(Core::System& system_);
|
||||
~PSM() override;
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
|
||||
private:
|
||||
enum class ChargerType : u32 {
|
||||
Unplugged = 0,
|
||||
RegularCharger = 1,
|
||||
LowPowerCharger = 2,
|
||||
Unknown = 3,
|
||||
};
|
||||
|
||||
} // namespace Service::PSM
|
||||
void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx);
|
||||
void GetChargerType(Kernel::HLERequestContext& ctx);
|
||||
void OpenSession(Kernel::HLERequestContext& ctx);
|
||||
|
||||
u32 battery_charge_percentage{100};
|
||||
ChargerType charger_type{ChargerType::RegularCharger};
|
||||
};
|
||||
|
||||
} // namespace Service::PTM
|
||||
|
||||
18
src/core/hle/service/ptm/ptm.cpp
Normal file
18
src/core/hle/service/ptm/ptm.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/ptm/psm.h"
|
||||
#include "core/hle/service/ptm/ptm.h"
|
||||
#include "core/hle/service/ptm/ts.h"
|
||||
|
||||
namespace Service::PTM {
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
|
||||
std::make_shared<PSM>(system)->InstallAsService(sm);
|
||||
std::make_shared<TS>(system)->InstallAsService(sm);
|
||||
}
|
||||
|
||||
} // namespace Service::PTM
|
||||
18
src/core/hle/service/ptm/ptm.h
Normal file
18
src/core/hle/service/ptm/ptm.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::PTM {
|
||||
|
||||
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
|
||||
|
||||
} // namespace Service::PTM
|
||||
41
src/core/hle/service/ptm/ts.cpp
Normal file
41
src/core/hle/service/ptm/ts.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/ptm/ts.h"
|
||||
|
||||
namespace Service::PTM {
|
||||
|
||||
TS::TS(Core::System& system_) : ServiceFramework{system_, "ts"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetTemperatureRange"},
|
||||
{1, &TS::GetTemperature, "GetTemperature"},
|
||||
{2, nullptr, "SetMeasurementMode"},
|
||||
{3, nullptr, "GetTemperatureMilliC"},
|
||||
{4, nullptr, "OpenSession"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
TS::~TS() = default;
|
||||
|
||||
void TS::GetTemperature(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto location{rp.PopEnum<Location>()};
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called. location={}", location);
|
||||
|
||||
const s32 temperature = location == Location::Internal ? 35 : 20;
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(temperature);
|
||||
}
|
||||
|
||||
} // namespace Service::PTM
|
||||
25
src/core/hle/service/ptm/ts.h
Normal file
25
src/core/hle/service/ptm/ts.h
Normal file
@@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::PTM {
|
||||
|
||||
class TS final : public ServiceFramework<TS> {
|
||||
public:
|
||||
explicit TS(Core::System& system_);
|
||||
~TS() override;
|
||||
|
||||
private:
|
||||
enum class Location : u8 {
|
||||
Internal,
|
||||
External,
|
||||
};
|
||||
|
||||
void GetTemperature(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
} // namespace Service::PTM
|
||||
@@ -58,7 +58,7 @@
|
||||
#include "core/hle/service/pm/pm.h"
|
||||
#include "core/hle/service/prepo/prepo.h"
|
||||
#include "core/hle/service/psc/psc.h"
|
||||
#include "core/hle/service/ptm/psm.h"
|
||||
#include "core/hle/service/ptm/ptm.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/set/settings.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
@@ -287,7 +287,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
|
||||
PlayReport::InstallInterfaces(*sm, system);
|
||||
PM::InstallInterfaces(system);
|
||||
PSC::InstallInterfaces(*sm, system);
|
||||
PSM::InstallInterfaces(*sm, system);
|
||||
PTM::InstallInterfaces(*sm, system);
|
||||
Set::InstallInterfaces(*sm, system);
|
||||
Sockets::InstallInterfaces(*sm, system);
|
||||
SPL::InstallInterfaces(*sm, system);
|
||||
|
||||
@@ -720,7 +720,25 @@ std::pair<s32, Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message)
|
||||
if (!IsFileDescriptorValid(fd)) {
|
||||
return {-1, Errno::BADF};
|
||||
}
|
||||
return Translate(file_descriptors[fd]->socket->Recv(flags, message));
|
||||
|
||||
FileDescriptor& descriptor = *file_descriptors[fd];
|
||||
|
||||
// Apply flags
|
||||
if ((flags & FLAG_MSG_DONTWAIT) != 0) {
|
||||
flags &= ~FLAG_MSG_DONTWAIT;
|
||||
if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
|
||||
descriptor.socket->SetNonBlock(true);
|
||||
}
|
||||
}
|
||||
|
||||
const auto [ret, bsd_errno] = Translate(descriptor.socket->Recv(flags, message));
|
||||
|
||||
// Restore original state
|
||||
if ((descriptor.flags & FLAG_O_NONBLOCK) == 0) {
|
||||
descriptor.socket->SetNonBlock(false);
|
||||
}
|
||||
|
||||
return {ret, bsd_errno};
|
||||
}
|
||||
|
||||
std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
|
||||
|
||||
@@ -438,10 +438,17 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
|
||||
using namespace std::chrono_literals;
|
||||
while (initialized) {
|
||||
SDL_PumpEvents();
|
||||
SendVibrations();
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
});
|
||||
vibration_thread = std::thread([this] {
|
||||
Common::SetCurrentThreadName("yuzu:input:SDL_Vibration");
|
||||
using namespace std::chrono_literals;
|
||||
while (initialized) {
|
||||
SendVibrations();
|
||||
std::this_thread::sleep_for(10ms);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Because the events for joystick connection happens before we have our event watcher added, we
|
||||
// can just open all the joysticks right here
|
||||
@@ -457,6 +464,7 @@ SDLDriver::~SDLDriver() {
|
||||
initialized = false;
|
||||
if (start_thread) {
|
||||
poll_thread.join();
|
||||
vibration_thread.join();
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,5 +128,6 @@ private:
|
||||
std::atomic<bool> initialized = false;
|
||||
|
||||
std::thread poll_thread;
|
||||
std::thread vibration_thread;
|
||||
};
|
||||
} // namespace InputCommon
|
||||
|
||||
@@ -87,8 +87,12 @@ u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) {
|
||||
}
|
||||
|
||||
std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) {
|
||||
return static_cast<std::size_t>(framebuffer.stride) *
|
||||
static_cast<std::size_t>(framebuffer.height) * GetBytesPerPixel(framebuffer);
|
||||
// TODO(Rodrigo): Read this from HLE
|
||||
constexpr u32 block_height_log2 = 4;
|
||||
const u32 bytes_per_pixel = GetBytesPerPixel(framebuffer);
|
||||
const u64 size_bytes{Tegra::Texture::CalculateSize(
|
||||
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
|
||||
return size_bytes;
|
||||
}
|
||||
|
||||
VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
|
||||
@@ -169,9 +173,8 @@ VkSemaphore BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
||||
// TODO(Rodrigo): Read this from HLE
|
||||
constexpr u32 block_height_log2 = 4;
|
||||
const u32 bytes_per_pixel = GetBytesPerPixel(framebuffer);
|
||||
const u64 size_bytes{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
|
||||
framebuffer.stride, framebuffer.height,
|
||||
1, block_height_log2, 0)};
|
||||
const u64 size_bytes{GetSizeInBytes(framebuffer)};
|
||||
|
||||
Tegra::Texture::UnswizzleTexture(
|
||||
mapped_span.subspan(image_offset, size_bytes), std::span(host_ptr, size_bytes),
|
||||
bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
|
||||
|
||||
@@ -38,7 +38,7 @@ VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
|
||||
if (found_mailbox != modes.end()) {
|
||||
return VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
}
|
||||
if (Settings::values.disable_fps_limit.GetValue()) {
|
||||
if (!Settings::values.use_speed_limit.GetValue()) {
|
||||
// FIFO present mode locks the framerate to the monitor's refresh rate,
|
||||
// Find an alternative to surpass this limitation if FPS is unlocked.
|
||||
const auto found_imm = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR);
|
||||
@@ -205,7 +205,7 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u3
|
||||
|
||||
extent = swapchain_ci.imageExtent;
|
||||
current_srgb = srgb;
|
||||
current_fps_unlocked = Settings::values.disable_fps_limit.GetValue();
|
||||
current_fps_unlocked = !Settings::values.use_speed_limit.GetValue();
|
||||
|
||||
images = swapchain.GetImages();
|
||||
image_count = static_cast<u32>(images.size());
|
||||
@@ -259,7 +259,7 @@ void Swapchain::Destroy() {
|
||||
}
|
||||
|
||||
bool Swapchain::HasFpsUnlockChanged() const {
|
||||
return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue();
|
||||
return current_fps_unlocked != !Settings::values.use_speed_limit.GetValue();
|
||||
}
|
||||
|
||||
bool Swapchain::NeedsPresentModeUpdate() const {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#ifdef YUZU_USE_QT_WEB_ENGINE
|
||||
#include <bit>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QKeyEvent>
|
||||
|
||||
@@ -211,8 +213,10 @@ template <Core::HID::NpadButton... T>
|
||||
void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() {
|
||||
const auto f = [this](Core::HID::NpadButton button) {
|
||||
if (input_interpreter->IsButtonPressedOnce(button)) {
|
||||
const auto button_index = std::countr_zero(static_cast<u64>(button));
|
||||
|
||||
page()->runJavaScript(
|
||||
QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(static_cast<u8>(button)),
|
||||
QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(button_index),
|
||||
[this, button](const QVariant& variant) {
|
||||
if (variant.toBool()) {
|
||||
switch (button) {
|
||||
@@ -236,7 +240,7 @@ void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() {
|
||||
|
||||
page()->runJavaScript(
|
||||
QStringLiteral("if (yuzu_key_callbacks[%1] != null) { yuzu_key_callbacks[%1](); }")
|
||||
.arg(static_cast<u8>(button)));
|
||||
.arg(button_index));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -143,8 +143,8 @@ void Config::ReadBasicSetting(Settings::Setting<std::string>& setting) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Config::ReadBasicSetting(Settings::Setting<Type>& setting) {
|
||||
template <typename Type, bool ranged>
|
||||
void Config::ReadBasicSetting(Settings::Setting<Type, ranged>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const Type default_value = setting.GetDefault();
|
||||
if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) {
|
||||
@@ -164,16 +164,16 @@ void Config::WriteBasicSetting(const Settings::Setting<std::string>& setting) {
|
||||
qt_config->setValue(name, QString::fromStdString(value));
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Config::WriteBasicSetting(const Settings::Setting<Type>& setting) {
|
||||
template <typename Type, bool ranged>
|
||||
void Config::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const Type value = setting.GetValue();
|
||||
qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault());
|
||||
qt_config->setValue(name, value);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type>& setting) {
|
||||
template <typename Type, bool ranged>
|
||||
void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) {
|
||||
const QString name = QString::fromStdString(setting.GetLabel());
|
||||
const Type& value = setting.GetValue(global);
|
||||
if (!global) {
|
||||
@@ -668,7 +668,6 @@ void Config::ReadRendererValues() {
|
||||
ReadGlobalSetting(Settings::values.max_anisotropy);
|
||||
ReadGlobalSetting(Settings::values.use_speed_limit);
|
||||
ReadGlobalSetting(Settings::values.speed_limit);
|
||||
ReadGlobalSetting(Settings::values.fps_cap);
|
||||
ReadGlobalSetting(Settings::values.use_disk_shader_cache);
|
||||
ReadGlobalSetting(Settings::values.gpu_accuracy);
|
||||
ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation);
|
||||
@@ -1237,7 +1236,6 @@ void Config::SaveRendererValues() {
|
||||
WriteGlobalSetting(Settings::values.max_anisotropy);
|
||||
WriteGlobalSetting(Settings::values.use_speed_limit);
|
||||
WriteGlobalSetting(Settings::values.speed_limit);
|
||||
WriteGlobalSetting(Settings::values.fps_cap);
|
||||
WriteGlobalSetting(Settings::values.use_disk_shader_cache);
|
||||
WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()),
|
||||
static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)),
|
||||
@@ -1421,8 +1419,8 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value)
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type>& setting) {
|
||||
template <typename Type, bool ranged>
|
||||
void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting) {
|
||||
QString name = QString::fromStdString(setting.GetLabel());
|
||||
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
|
||||
setting.SetGlobal(use_global);
|
||||
|
||||
@@ -159,8 +159,8 @@ private:
|
||||
*
|
||||
* @param The setting
|
||||
*/
|
||||
template <typename Type>
|
||||
void ReadGlobalSetting(Settings::SwitchableSetting<Type>& setting);
|
||||
template <typename Type, bool ranged>
|
||||
void ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting);
|
||||
|
||||
/**
|
||||
* Sets a value to the qt_config using the setting's label and default value. If the config is a
|
||||
@@ -168,8 +168,8 @@ private:
|
||||
*
|
||||
* @param The setting
|
||||
*/
|
||||
template <typename Type>
|
||||
void WriteGlobalSetting(const Settings::SwitchableSetting<Type>& setting);
|
||||
template <typename Type, bool ranged>
|
||||
void WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting);
|
||||
|
||||
/**
|
||||
* Reads a value from the qt_config using the setting's label and default value and applies the
|
||||
@@ -177,15 +177,15 @@ private:
|
||||
*
|
||||
* @param The setting
|
||||
*/
|
||||
template <typename Type>
|
||||
void ReadBasicSetting(Settings::Setting<Type>& setting);
|
||||
template <typename Type, bool ranged>
|
||||
void ReadBasicSetting(Settings::Setting<Type, ranged>& setting);
|
||||
|
||||
/** Sets a value from the setting in the qt_config using the setting's label and default value.
|
||||
*
|
||||
* @param The setting
|
||||
*/
|
||||
template <typename Type>
|
||||
void WriteBasicSetting(const Settings::Setting<Type>& setting);
|
||||
template <typename Type, bool ranged>
|
||||
void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting);
|
||||
|
||||
ConfigType type;
|
||||
std::unique_ptr<QSettings> qt_config;
|
||||
|
||||
@@ -27,8 +27,9 @@ enum class CheckState {
|
||||
// ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting
|
||||
void ApplyPerGameSetting(Settings::SwitchableSetting<bool>* setting, const QCheckBox* checkbox,
|
||||
const CheckState& tracker);
|
||||
template <typename Type>
|
||||
void ApplyPerGameSetting(Settings::SwitchableSetting<Type>* setting, const QComboBox* combobox) {
|
||||
template <typename Type, bool ranged>
|
||||
void ApplyPerGameSetting(Settings::SwitchableSetting<Type, ranged>* setting,
|
||||
const QComboBox* combobox) {
|
||||
if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
|
||||
setting->SetValue(static_cast<Type>(combobox->currentIndex()));
|
||||
} else if (!Settings::IsConfiguringGlobal()) {
|
||||
@@ -45,8 +46,9 @@ void ApplyPerGameSetting(Settings::SwitchableSetting<Type>* setting, const QComb
|
||||
// Sets a Qt UI element given a Settings::Setting
|
||||
void SetPerGameSetting(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>* setting);
|
||||
|
||||
template <typename Type>
|
||||
void SetPerGameSetting(QComboBox* combobox, const Settings::SwitchableSetting<Type>* setting) {
|
||||
template <typename Type, bool ranged>
|
||||
void SetPerGameSetting(QComboBox* combobox,
|
||||
const Settings::SwitchableSetting<Type, ranged>* setting) {
|
||||
combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
|
||||
: static_cast<int>(setting->GetValue()) +
|
||||
ConfigurationShared::USE_GLOBAL_OFFSET);
|
||||
|
||||
@@ -27,9 +27,6 @@ ConfigureGeneral::ConfigureGeneral(const Core::System& system_, QWidget* parent)
|
||||
|
||||
connect(ui->button_reset_defaults, &QPushButton::clicked, this,
|
||||
&ConfigureGeneral::ResetDefaults);
|
||||
|
||||
ui->fps_cap_label->setVisible(Settings::IsConfiguringGlobal());
|
||||
ui->fps_cap_combobox->setVisible(!Settings::IsConfiguringGlobal());
|
||||
}
|
||||
|
||||
ConfigureGeneral::~ConfigureGeneral() = default;
|
||||
@@ -52,8 +49,6 @@ void ConfigureGeneral::SetConfiguration() {
|
||||
ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue());
|
||||
ui->speed_limit->setValue(Settings::values.speed_limit.GetValue());
|
||||
|
||||
ui->fps_cap->setValue(Settings::values.fps_cap.GetValue());
|
||||
|
||||
ui->button_reset_defaults->setEnabled(runtime_lock);
|
||||
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
@@ -61,11 +56,6 @@ void ConfigureGeneral::SetConfiguration() {
|
||||
} else {
|
||||
ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue() &&
|
||||
use_speed_limit != ConfigurationShared::CheckState::Global);
|
||||
|
||||
ui->fps_cap_combobox->setCurrentIndex(Settings::values.fps_cap.UsingGlobal() ? 0 : 1);
|
||||
ui->fps_cap->setEnabled(!Settings::values.fps_cap.UsingGlobal());
|
||||
ConfigurationShared::SetHighlight(ui->fps_cap_layout,
|
||||
!Settings::values.fps_cap.UsingGlobal());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +92,6 @@ void ConfigureGeneral::ApplyConfiguration() {
|
||||
UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked();
|
||||
UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();
|
||||
|
||||
Settings::values.fps_cap.SetValue(ui->fps_cap->value());
|
||||
|
||||
// Guard if during game and set to game-specific value
|
||||
if (Settings::values.use_speed_limit.UsingGlobal()) {
|
||||
Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() ==
|
||||
@@ -119,13 +107,6 @@ void ConfigureGeneral::ApplyConfiguration() {
|
||||
Qt::Checked);
|
||||
Settings::values.speed_limit.SetValue(ui->speed_limit->value());
|
||||
}
|
||||
|
||||
if (ui->fps_cap_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
|
||||
Settings::values.fps_cap.SetGlobal(true);
|
||||
} else {
|
||||
Settings::values.fps_cap.SetGlobal(false);
|
||||
Settings::values.fps_cap.SetValue(ui->fps_cap->value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,9 +152,4 @@ void ConfigureGeneral::SetupPerGameUI() {
|
||||
ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() &&
|
||||
(use_speed_limit != ConfigurationShared::CheckState::Global));
|
||||
});
|
||||
|
||||
connect(ui->fps_cap_combobox, qOverload<int>(&QComboBox::activated), this, [this](int index) {
|
||||
ui->fps_cap->setEnabled(index == 1);
|
||||
ConfigurationShared::SetHighlight(ui->fps_cap_layout, index == 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,87 +27,6 @@
|
||||
<layout class="QHBoxLayout" name="GeneralHorizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="GeneralVerticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="fps_cap_layout" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QComboBox" name="fps_cap_combobox">
|
||||
<property name="currentText">
|
||||
<string>Use global framerate cap</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Use global framerate cap</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Set framerate cap:</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="fps_cap_label">
|
||||
<property name="toolTip">
|
||||
<string>Requires the use of the FPS Limiter Toggle hotkey to take effect.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Framerate Cap</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="fps_cap">
|
||||
<property name="suffix">
|
||||
<string>x</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>500</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioUndocked">
|
||||
<property name="text">
|
||||
<string>Undocked</string>
|
||||
<string>Handheld</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -1059,7 +1059,7 @@ void GMainWindow::InitializeHotkeys() {
|
||||
Settings::values.volume.SetValue(static_cast<u8>(new_volume));
|
||||
});
|
||||
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
|
||||
Settings::values.disable_fps_limit.SetValue(!Settings::values.disable_fps_limit.GetValue());
|
||||
Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
|
||||
});
|
||||
connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
|
||||
Settings::values.mouse_panning = !Settings::values.mouse_panning;
|
||||
@@ -1131,6 +1131,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
|
||||
OnPauseGame();
|
||||
} else if (!emu_thread->IsRunning() && auto_paused && state == Qt::ApplicationActive) {
|
||||
auto_paused = false;
|
||||
RequestGameResume();
|
||||
OnStartGame();
|
||||
}
|
||||
}
|
||||
@@ -1483,9 +1484,6 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
|
||||
Config per_game_config(*system, config_file_name, Config::ConfigType::PerGameConfig);
|
||||
}
|
||||
|
||||
// Disable fps limit toggle when booting a new title
|
||||
Settings::values.disable_fps_limit.SetValue(false);
|
||||
|
||||
// Save configurations
|
||||
UpdateUISettings();
|
||||
game_list->SaveInterfaceLayout();
|
||||
@@ -2573,6 +2571,7 @@ void GMainWindow::OnPauseContinueGame() {
|
||||
if (emu_thread->IsRunning()) {
|
||||
OnPauseGame();
|
||||
} else {
|
||||
RequestGameResume();
|
||||
OnStartGame();
|
||||
}
|
||||
}
|
||||
@@ -3277,7 +3276,7 @@ void GMainWindow::UpdateStatusBar() {
|
||||
} else {
|
||||
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
|
||||
}
|
||||
if (Settings::values.disable_fps_limit) {
|
||||
if (!Settings::values.use_speed_limit) {
|
||||
game_fps_label->setText(
|
||||
tr("Game: %1 FPS (Unlocked)").arg(results.average_game_fps, 0, 'f', 0));
|
||||
} else {
|
||||
@@ -3752,6 +3751,21 @@ void GMainWindow::RequestGameExit() {
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::RequestGameResume() {
|
||||
auto& sm{system->ServiceManager()};
|
||||
auto applet_oe = sm.GetService<Service::AM::AppletOE>("appletOE");
|
||||
auto applet_ae = sm.GetService<Service::AM::AppletAE>("appletAE");
|
||||
|
||||
if (applet_oe != nullptr) {
|
||||
applet_oe->GetMessageQueue()->RequestResume();
|
||||
return;
|
||||
}
|
||||
|
||||
if (applet_ae != nullptr) {
|
||||
applet_ae->GetMessageQueue()->RequestResume();
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::filterBarSetChecked(bool state) {
|
||||
ui->action_Show_Filter_Bar->setChecked(state);
|
||||
emit(OnToggleFilterBar());
|
||||
|
||||
@@ -244,6 +244,7 @@ private:
|
||||
bool ConfirmChangeGame();
|
||||
bool ConfirmForceLockedExit();
|
||||
void RequestGameExit();
|
||||
void RequestGameResume();
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -99,8 +99,8 @@ void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& sett
|
||||
setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<Type>& setting) {
|
||||
template <typename Type, bool ranged>
|
||||
void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
|
||||
setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(),
|
||||
static_cast<long>(setting.GetDefault())));
|
||||
}
|
||||
@@ -310,8 +310,6 @@ void Config::ReadValues() {
|
||||
ReadSetting("Renderer", Settings::values.gpu_accuracy);
|
||||
ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation);
|
||||
ReadSetting("Renderer", Settings::values.use_vsync);
|
||||
ReadSetting("Renderer", Settings::values.fps_cap);
|
||||
ReadSetting("Renderer", Settings::values.disable_fps_limit);
|
||||
ReadSetting("Renderer", Settings::values.shader_backend);
|
||||
ReadSetting("Renderer", Settings::values.use_asynchronous_shaders);
|
||||
ReadSetting("Renderer", Settings::values.nvdec_emulation);
|
||||
|
||||
@@ -33,6 +33,6 @@ private:
|
||||
* @param group The name of the INI group
|
||||
* @param setting The yuzu setting to modify
|
||||
*/
|
||||
template <typename Type>
|
||||
void ReadSetting(const std::string& group, Settings::Setting<Type>& setting);
|
||||
template <typename Type, bool ranged>
|
||||
void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
|
||||
};
|
||||
|
||||
@@ -330,10 +330,6 @@ bg_red =
|
||||
bg_blue =
|
||||
bg_green =
|
||||
|
||||
# Caps the unlocked framerate to a multiple of the title's target FPS.
|
||||
# 1 - 1000: Target FPS multiple cap. 1000 (default)
|
||||
fps_cap =
|
||||
|
||||
[Audio]
|
||||
# Which audio output engine to use.
|
||||
# auto (default): Auto-select
|
||||
@@ -434,9 +430,6 @@ use_debug_asserts =
|
||||
use_auto_stub =
|
||||
# Enables/Disables the macro JIT compiler
|
||||
disable_macro_jit=false
|
||||
# Presents guest frames as they become available. Experimental.
|
||||
# false: Disabled (default), true: Enabled
|
||||
disable_fps_limit=false
|
||||
# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
|
||||
# false: Disabled (default), true: Enabled
|
||||
use_gdbstub=false
|
||||
|
||||
29
vcpkg.json
Normal file
29
vcpkg.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
|
||||
"name": "yuzu",
|
||||
"version": "1.0",
|
||||
"dependencies": [
|
||||
"boost-algorithm",
|
||||
"boost-asio",
|
||||
"boost-bind",
|
||||
"boost-config",
|
||||
"boost-container",
|
||||
"boost-context",
|
||||
"boost-crc",
|
||||
"boost-functional",
|
||||
"boost-icl",
|
||||
"boost-intrusive",
|
||||
"boost-mpl",
|
||||
"boost-process",
|
||||
"boost-range",
|
||||
"boost-spirit",
|
||||
"boost-test",
|
||||
"boost-timer",
|
||||
"boost-variant",
|
||||
"fmt",
|
||||
"lz4",
|
||||
"nlohmann-json",
|
||||
"zlib",
|
||||
"zstd"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user