Compare commits

..

1 Commits

Author SHA1 Message Date
FengChen
539ee9f4e8 video_core: Fix gpu thread deadlock 2022-07-13 15:07:51 +08:00
69 changed files with 510 additions and 586 deletions

View File

@@ -6,17 +6,7 @@ set -e
ccache -s
mkdir build || true && cd build
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
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"
ninja

View File

@@ -4,10 +4,5 @@ mkdir -p "ccache" || true
chmod a+x ./.ci/scripts/linux/docker.sh
# the UID for the container yuzu user is 1027
sudo chown -R 1027 ./
# The environment variables listed below:
# AZURECIREPO TITLEBARFORMATIDLE TITLEBARFORMATRUNNING DISPLAYVERSION
# are requested in src/common/CMakeLists.txt and appear to be provided somewhere in Azure DevOps
docker run -e AZURECIREPO -e TITLEBARFORMATIDLE -e TITLEBARFORMATRUNNING -e DISPLAYVERSION -e ENABLE_COMPATIBILITY_REPORTING -e CCACHE_DIR=/yuzu/ccache -v "$(pwd):/yuzu" -w /yuzu yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.ci/scripts/linux/docker.sh "$1"
docker run -e ENABLE_COMPATIBILITY_REPORTING -e CCACHE_DIR=/yuzu/ccache -v "$(pwd):/yuzu" -w /yuzu yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.ci/scripts/linux/docker.sh "$1"
sudo chown -R $UID ./

View File

@@ -6,6 +6,10 @@ 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
@@ -20,7 +24,6 @@ cmake .. \
-DUSE_CCACHE=ON \
-DYUZU_USE_BUNDLED_SDL2=OFF \
-DYUZU_USE_EXTERNAL_SDL2=OFF \
-DYUZU_TESTS=OFF \
-GNinja
ninja yuzu yuzu-cmd
@@ -62,7 +65,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 -nv {} package/ ';'
find ${FFMPEG_DLL_PATH} -type f -regex ".*\.dll" -exec cp -v {} package/ ';'
# copy libraries from yuzu.exe path
find "$(pwd)/build/bin/" -type f -regex ".*\.dll" -exec cp -v {} package/ ';'

View File

@@ -6,7 +6,9 @@ parameters:
steps:
- script: choco install vulkan-sdk
displayName: 'Install vulkan-sdk'
- 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 ..
- 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 ..
displayName: 'Configure CMake'
- task: MSBuild@1
displayName: 'Build'

View File

@@ -13,7 +13,7 @@ jobs:
container: yuzuemu/build-environments:linux-transifex
if: ${{ github.repository == 'yuzu-emu/yuzu' && !github.head_ref }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
submodules: recursive
fetch-depth: 0

View File

@@ -12,7 +12,7 @@ jobs:
image: yuzuemu/build-environments:linux-clang-format
options: -u 1001
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
submodules: false
- name: 'Verify Formatting'
@@ -35,12 +35,12 @@ jobs:
image: yuzuemu/build-environments:${{ matrix.image }}
options: -u 1001
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
submodules: recursive
fetch-depth: 0
- name: Set up cache
uses: actions/cache@v3
uses: actions/cache@v2
id: ccache-restore
with:
path: ~/.ccache
@@ -69,7 +69,7 @@ jobs:
runs-on: windows-2019
steps:
- name: Set up cache
uses: actions/cache@v3
uses: actions/cache@v2
with:
path: ~/.buildcache
key: ${{ runner.os }}-msvc-${{ github.sha }}
@@ -80,6 +80,7 @@ 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
@@ -88,7 +89,7 @@ jobs:
echo %PATH% >> %GITHUB_PATH%
- name: Set up MSVC
uses: ilammy/msvc-dev-cmd@v1
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
submodules: recursive
fetch-depth: 0
@@ -99,7 +100,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 -DYUZU_TESTS=OFF -DYUZU_USE_BUNDLED_VCPKG=ON
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
- name: Build
run: cmake --build build
- name: Cache Summary

7
.gitmodules vendored
View File

@@ -34,12 +34,9 @@
[submodule "SDL"]
path = externals/SDL
url = https://github.com/libsdl-org/SDL.git
[submodule "cpp-httplib"]
[submodule "externals/cpp-httplib"]
path = externals/cpp-httplib
url = https://github.com/yhirose/cpp-httplib.git
[submodule "ffmpeg"]
[submodule "externals/ffmpeg/ffmpeg"]
path = externals/ffmpeg/ffmpeg
url = https://git.ffmpeg.org/ffmpeg.git
[submodule "vcpkg"]
path = externals/vcpkg
url = https://github.com/Microsoft/vcpkg.git

View File

@@ -35,16 +35,6 @@ 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)
@@ -154,34 +144,82 @@ endif()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
# System imported libraries
# If not found, download any missing through Conan
# =======================================================================
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)
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")
endif()
if (YUZU_TESTS)
find_package(Catch2 2.13.7 REQUIRED CONFIG)
endif()
macro(yuzu_find_packages)
set(options FORCE_REQUIRED)
cmake_parse_arguments(FN "${options}" "" "" ${ARGN})
find_package(Boost 1.73.0 COMPONENTS context)
# 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)
if (Boost_FOUND)
set(Boost_LIBRARIES Boost::boost)
# Conditionally add Boost::context only if the found Boost package provides it
# Conditionally add Boost::context only if the active version of the Conan or system 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(FATAL_ERROR "Boost 1.73.0 or newer not found")
message(STATUS "Boost 1.79.0 or newer not found, falling back to Conan")
list(APPEND CONAN_REQUIRED_LIBS "boost/1.79.0")
endif()
# boost:asio has functions that require AcceptEx et al
@@ -189,9 +227,19 @@ 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")
@@ -282,6 +330,9 @@ 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)
@@ -352,8 +403,71 @@ if (ENABLE_SDL2)
endif()
endif()
# TODO(lat9nq): Determine what if any of this we still need
#
# 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()
# 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

2
externals/SDL vendored

1
externals/vcpkg vendored

Submodule externals/vcpkg deleted from cef0b3ec76

View File

@@ -182,9 +182,8 @@ 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 (TARGET zstd::zstd)
if (MSVC)
target_link_libraries(common PRIVATE zstd::zstd)
else()
target_link_libraries(common PRIVATE
$<IF:$<TARGET_EXISTS:zstd::libzstd_shared>,zstd::libzstd_shared,zstd::libzstd_static>)
target_link_libraries(common PRIVATE zstd)
endif()

View File

@@ -146,16 +146,7 @@ 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 {

View File

@@ -18,16 +18,14 @@
/// Helper macros to insert unused bytes or words to properly align structs. These values will be
/// zero-initialized.
#define INSERT_PADDING_BYTES(num_bytes) \
[[maybe_unused]] std::array<u8, num_bytes> CONCAT2(pad, __LINE__) {}
std::array<u8, num_bytes> CONCAT2(pad, __LINE__) {}
#define INSERT_PADDING_WORDS(num_words) \
[[maybe_unused]] std::array<u32, num_words> CONCAT2(pad, __LINE__) {}
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) \
[[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__)
#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__)
#ifndef _MSC_VER

View File

@@ -128,7 +128,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Service, PM) \
SUB(Service, PREPO) \
SUB(Service, PSC) \
SUB(Service, PTM) \
SUB(Service, PSM) \
SUB(Service, SET) \
SUB(Service, SM) \
SUB(Service, SPL) \

View File

@@ -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_PTM, ///< The PTM service
Service_PSM, ///< The PSM service
Service_SET, ///< The SET (Settings) service
Service_SM, ///< The SM (Service manager) service
Service_SPL, ///< The SPL service

View File

@@ -185,6 +185,7 @@ 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);

View File

@@ -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, bool ranged = false>
template <typename Type>
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) requires(!ranged)
: value{default_val}, default_value{default_val}, label{name} {}
explicit Setting(const Type& default_val, const std::string& name)
: value{default_val}, default_value{default_val}, ranged{false}, 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) requires(ranged)
: value{default_val},
default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {}
const std::string& name)
: value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val},
ranged{true}, 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,6 +207,7 @@ 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
};
@@ -218,8 +219,8 @@ protected:
*
* By default, the global setting is used.
*/
template <typename Type, bool ranged = false>
class SwitchableSetting : virtual public Setting<Type, ranged> {
template <typename Type>
class SwitchableSetting : virtual public Setting<Type> {
public:
/**
* Sets a default value, label, and setting value.
@@ -227,7 +228,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) requires(!ranged)
explicit SwitchableSetting(const Type& default_val, const std::string& name)
: Setting<Type>{default_val, name} {}
virtual ~SwitchableSetting() = default;
@@ -240,8 +241,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) requires(ranged)
: Setting<Type, true>{default_val, min_val, max_val, name} {}
const std::string& name)
: Setting<Type>{default_val, min_val, max_val, name} {}
/**
* Tells this setting to represent either the global or custom setting when other member
@@ -289,7 +290,7 @@ public:
* @param val The new value
*/
void SetValue(const Type& val) override {
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val};
if (use_global) {
std::swap(this->value, temp);
} else {
@@ -305,7 +306,7 @@ public:
* @returns A reference to the current setting value
*/
const Type& operator=(const Type& val) override {
Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
Type temp{(this->ranged) ? std::clamp(val, this->minimum, this->maximum) : val};
if (use_global) {
std::swap(this->value, temp);
return this->value;
@@ -373,15 +374,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, true> volume{100, 0, 100, "volume"};
SwitchableSetting<u8> 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, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
CPUAccuracy::Paranoid, "cpu_accuracy"};
SwitchableSetting<CPUAccuracy> 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"};
@@ -408,7 +409,7 @@ struct Values {
true, "cpuopt_unsafe_ignore_global_monitor"};
// Renderer
SwitchableSetting<RendererBackend, true> renderer_backend{
SwitchableSetting<RendererBackend> renderer_backend{
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"};
Setting<bool> renderer_debug{false, "debug"};
Setting<bool> renderer_shader_feedback{false, "shader_feedback"};
@@ -422,26 +423,28 @@ 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, true> fullscreen_mode{
SwitchableSetting<FullscreenMode> fullscreen_mode{
#ifdef _WIN32
FullscreenMode::Borderless,
#else
FullscreenMode::Exclusive,
#endif
FullscreenMode::Borderless, FullscreenMode::Exclusive, "fullscreen_mode"};
SwitchableSetting<int, true> aspect_ratio{0, 0, 3, "aspect_ratio"};
SwitchableSetting<int, true> max_anisotropy{0, 0, 5, "max_anisotropy"};
SwitchableSetting<int> aspect_ratio{0, 0, 3, "aspect_ratio"};
SwitchableSetting<int> max_anisotropy{0, 0, 5, "max_anisotropy"};
SwitchableSetting<bool> use_speed_limit{true, "use_speed_limit"};
SwitchableSetting<u16, true> speed_limit{100, 0, 9999, "speed_limit"};
SwitchableSetting<u16> speed_limit{100, 0, 9999, "speed_limit"};
SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
SwitchableSetting<GPUAccuracy, true> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal,
GPUAccuracy::Extreme, "gpu_accuracy"};
SwitchableSetting<GPUAccuracy> 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<ShaderBackend, true> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL,
ShaderBackend::SPIRV, "shader_backend"};
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<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};
SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
@@ -457,10 +460,10 @@ struct Values {
s64 custom_rtc_differential;
Setting<s32> current_user{0, "current_user"};
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"};
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"};
// Controls
InputSetting<std::array<PlayerInput, 10>> players;
@@ -482,7 +485,7 @@ struct Values {
Setting<bool> tas_loop{false, "tas_loop"};
Setting<bool> mouse_panning{false, "mouse_panning"};
Setting<u8, true> mouse_panning_sensitivity{10, 1, 100, "mouse_panning_sensitivity"};
Setting<u8> 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"};

View File

@@ -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 = caps.tsc_frequency ? caps.tsc_frequency : EstimateRDTSCFrequency();
rtsc_frequency = EstimateRDTSCFrequency();
}
// Fallback to StandardWallClock if the hardware TSC does not have the precision greater than:

View File

@@ -161,22 +161,6 @@ 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];

View File

@@ -30,11 +30,6 @@ 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;

View File

@@ -605,10 +605,6 @@ 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

View File

@@ -147,6 +147,7 @@ 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());
}

View File

@@ -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::MemoryAbort;
static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::UserDefined5;
static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6;
protected:

View File

@@ -52,7 +52,7 @@ public:
if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
return std::nullopt;
}
return memory.Read32(vaddr);
return MemoryRead32(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, memory.Read32(pc));
num_instructions, MemoryRead32(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, memory.Read32(pc), parent.IsInThumbMode());
exception, pc, MemoryRead32(pc), parent.IsInThumbMode());
}
}
@@ -155,7 +155,7 @@ public:
const auto match{parent.MatchingWatchpoint(addr, size, type)};
if (match) {
parent.halted_watchpoint = match;
parent.jit.load()->HaltExecution(ARM_Interface::watchpoint);
ReturnException(parent.jit.load()->Regs()[15], ARM_Interface::watchpoint);
return false;
}
@@ -204,6 +204,7 @@ 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()) {
@@ -214,6 +215,7 @@ 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

View File

@@ -56,7 +56,7 @@ public:
if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
return std::nullopt;
}
return memory.Read32(vaddr);
return MemoryRead32(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, memory.Read32(pc));
num_instructions, MemoryRead32(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, memory.Read32(pc));
static_cast<std::size_t>(exception), pc, MemoryRead32(pc));
}
}
@@ -198,7 +198,7 @@ public:
const auto match{parent.MatchingWatchpoint(addr, size, type)};
if (match) {
parent.halted_watchpoint = match;
parent.jit.load()->HaltExecution(ARM_Interface::watchpoint);
ReturnException(parent.jit.load()->GetPC(), ARM_Interface::watchpoint);
return false;
}
@@ -264,6 +264,7 @@ 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()) {
@@ -274,6 +275,7 @@ 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

View File

@@ -30,19 +30,19 @@ public:
explicit KCodeMemory(KernelCore& kernel_);
Result Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size);
void Finalize() override;
void Finalize();
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 override {
bool IsInitialized() const {
return m_is_initialized;
}
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
KProcess* GetOwner() const override {
KProcess* GetOwner() const {
return m_owner;
}
VAddr GetSourceAddress() const {

View File

@@ -290,7 +290,7 @@ protected:
void Get(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.RawString());
ProfileBase profile_base{};
UserData data{};
ProfileData 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(UserData)) {
LOG_ERROR(Service_ACC, "UserData buffer too small!");
if (user_data.size() < sizeof(ProfileData)) {
LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_BUFFER);
return;
}
UserData data;
std::memcpy(&data, user_data.data(), sizeof(UserData));
ProfileData data;
std::memcpy(&data, user_data.data(), sizeof(ProfileData));
if (!profile_manager.SetProfileBaseAndData(user_id, base, data)) {
LOG_ERROR(Service_ACC, "Failed to update user data and base!");
LOG_ERROR(Service_ACC, "Failed to update profile 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(UserData)) {
LOG_ERROR(Service_ACC, "UserData buffer too small!");
if (user_data.size() < sizeof(ProfileData)) {
LOG_ERROR(Service_ACC, "ProfileData buffer too small!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_INVALID_BUFFER);
return;
}
UserData data;
std::memcpy(&data, user_data.data(), sizeof(UserData));
ProfileData data;
std::memcpy(&data, user_data.data(), sizeof(ProfileData));
Common::FS::IOFile image(GetImagePath(user_id), Common::FS::FileAccessMode::Write,
Common::FS::FileType::BinaryFile);

View File

@@ -22,7 +22,7 @@ struct UserRaw {
UUID uuid2{};
u64 timestamp{};
ProfileUsername username{};
UserData extra_data{};
ProfileData 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,
UserData& data) const {
ProfileData& data) const {
if (GetProfileBase(index, profile)) {
data = profiles[*index].data;
return true;
@@ -272,14 +272,15 @@ 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, UserData& data) const {
bool ProfileManager::GetProfileBaseAndData(UUID uuid, ProfileBase& profile,
ProfileData& 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,
UserData& data) const {
ProfileData& data) const {
return GetProfileBaseAndData(user.user_uuid, profile, data);
}
@@ -317,7 +318,7 @@ bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
}
bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new,
const UserData& data_new) {
const ProfileData& data_new) {
const auto index = GetUserIndex(uuid);
if (index.has_value() && SetProfileBase(uuid, profile_new)) {
profiles[*index].data = data_new;

View File

@@ -22,7 +22,7 @@ using UserIDArray = std::array<Common::UUID, MAX_USERS>;
/// Contains extra data related to a user.
/// TODO: RE this structure
struct UserData {
struct ProfileData {
INSERT_PADDING_WORDS_NOINIT(1);
u32 icon_id;
u8 bg_color_id;
@@ -30,7 +30,7 @@ struct UserData {
INSERT_PADDING_BYTES_NOINIT(0x10);
INSERT_PADDING_BYTES_NOINIT(0x60);
};
static_assert(sizeof(UserData) == 0x80, "UserData structure has incorrect size");
static_assert(sizeof(ProfileData) == 0x80, "ProfileData 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{};
UserData data{}; // TODO(ognik): Work out what this is
ProfileData data{}; // TODO(ognik): Work out what this is
bool is_open{};
};
@@ -74,9 +74,10 @@ 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,
UserData& data) const;
bool GetProfileBaseAndData(Common::UUID uuid, ProfileBase& profile, UserData& data) const;
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile, UserData& data) const;
ProfileData& data) const;
bool GetProfileBaseAndData(Common::UUID uuid, ProfileBase& profile, ProfileData& data) const;
bool GetProfileBaseAndData(const ProfileInfo& user, ProfileBase& profile,
ProfileData& data) const;
std::size_t GetUserCount() const;
std::size_t GetOpenUserCount() const;
bool UserExists(Common::UUID uuid) const;
@@ -92,7 +93,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 UserData& data_new);
const ProfileData& data_new);
private:
void ParseUserSaveFile();

View File

@@ -238,7 +238,6 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
{130, nullptr, "FriendInvitationSetApplicationParameter"},
{131, nullptr, "FriendInvitationClearApplicationParameter"},
{132, nullptr, "FriendInvitationPushApplicationParameter"},
{140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
{900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
};
// clang-format on
@@ -636,10 +635,6 @@ void AppletMessageQueue::RequestExit() {
PushMessage(AppletMessage::Exit);
}
void AppletMessageQueue::RequestResume() {
PushMessage(AppletMessage::Resume);
}
void AppletMessageQueue::FocusStateChanged() {
PushMessage(AppletMessage::FocusStateChanged);
}
@@ -1315,8 +1310,6 @@ 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"},

View File

@@ -90,7 +90,6 @@ public:
AppletMessage PopMessage();
std::size_t GetMessageCount() const;
void RequestExit();
void RequestResume();
void FocusStateChanged();
void OperationModeChanged();

View File

@@ -140,8 +140,8 @@ public:
{20401, nullptr, "UnregisterSystemApplicationDeliveryTask"},
{20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"},
{30100, &IBcatService::SetPassphrase, "SetPassphrase"},
{30101, nullptr, "Unknown30101"},
{30102, nullptr, "Unknown30102"},
{30101, nullptr, "Unknown"},
{30102, nullptr, "Unknown2"},
{30200, nullptr, "RegisterBackgroundDeliveryTask"},
{30201, nullptr, "UnregisterBackgroundDeliveryTask"},
{30202, nullptr, "BlockDeliveryTask"},

View File

@@ -181,11 +181,6 @@ 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"},

View File

@@ -214,12 +214,8 @@ public:
{76, nullptr, "Unknown76"},
{100, nullptr, "Unknown100"},
{101, nullptr, "Unknown101"},
{110, nullptr, "Unknown110"},
{111, nullptr, "Unknown111"},
{112, nullptr, "Unknown112"},
{113, nullptr, "Unknown113"},
{114, nullptr, "Unknown114"},
{115, nullptr, "Unknown115"},
{110, nullptr, "Unknown102"},
{111, nullptr, "Unknown103"},
};
// clang-format on

View File

@@ -6,13 +6,7 @@
namespace Service::Fatal {
Fatal_P::Fatal_P(std::shared_ptr<Module> module_, Core::System& system_)
: Interface(std::move(module_), system_, "fatal:p") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetFatalEvent"},
{10, nullptr, "GetFatalContext"},
};
RegisterHandlers(functions);
}
: Interface(std::move(module_), system_, "fatal:p") {}
Fatal_P::~Fatal_P() = default;

View File

@@ -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 15ms of each other.
// Filter out non-zero vibrations that are within 10ms 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(15)) {
milliseconds(10)) {
return false;
}

View File

@@ -30,19 +30,6 @@ 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{};
@@ -284,7 +271,6 @@ 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");
@@ -293,7 +279,6 @@ private:
rb.Push(ResultSuccess);
rb.PushIpcInterface<IScanRequest>(system);
}
void CreateRequest(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
@@ -302,7 +287,6 @@ private:
rb.Push(ResultSuccess);
rb.PushIpcInterface<IRequest>(system);
}
void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -351,14 +335,12 @@ 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");
@@ -372,7 +354,6 @@ private:
rb.Push(ResultSuccess);
rb.PushRaw(*ipv4);
}
void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called");
@@ -388,7 +369,6 @@ private:
rb.PushIpcInterface<INetworkProfile>(system);
rb.PushRaw<u128>(uuid);
}
void GetCurrentIpConfigInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -425,7 +405,6 @@ private:
rb.Push(ResultSuccess);
rb.PushRaw<IpConfigInfo>(ip_config_info);
}
void IsWirelessCommunicationEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -433,24 +412,6 @@ 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");
@@ -462,7 +423,6 @@ private:
rb.Push<u8>(0);
}
}
void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@@ -496,7 +456,7 @@ IGeneralService::IGeneralService(Core::System& system_)
{15, &IGeneralService::GetCurrentIpConfigInfo, "GetCurrentIpConfigInfo"},
{16, nullptr, "SetWirelessCommunicationEnabled"},
{17, &IGeneralService::IsWirelessCommunicationEnabled, "IsWirelessCommunicationEnabled"},
{18, &IGeneralService::GetInternetConnectionStatus, "GetInternetConnectionStatus"},
{18, nullptr, "GetInternetConnectionStatus"},
{19, nullptr, "SetEthernetCommunicationEnabled"},
{20, &IGeneralService::IsEthernetCommunicationEnabled, "IsEthernetCommunicationEnabled"},
{21, &IGeneralService::IsAnyInternetRequestAccepted, "IsAnyInternetRequestAccepted"},

View File

@@ -34,7 +34,6 @@ 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;

View File

@@ -287,21 +287,9 @@ s64 NVFlinger::GetNextTicks() const {
static constexpr s64 max_hertz = 120LL;
const auto& settings = Settings::values;
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));
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);
}
} // namespace Service::NVFlinger

View File

@@ -9,8 +9,10 @@
#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::PTM {
namespace Service::PSM {
class IPsmSession final : public ServiceFramework<IPsmSession> {
public:
@@ -55,7 +57,7 @@ public:
private:
void BindStateChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PTM, "called");
LOG_DEBUG(Service_PSM, "called");
should_signal = true;
@@ -65,7 +67,7 @@ private:
}
void UnbindStateChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_PTM, "called");
LOG_DEBUG(Service_PSM, "called");
should_signal = false;
@@ -76,7 +78,7 @@ private:
void SetChargerTypeChangeEventEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto state = rp.Pop<bool>();
LOG_DEBUG(Service_PTM, "called, state={}", state);
LOG_DEBUG(Service_PSM, "called, state={}", state);
should_signal_charger_type = state;
@@ -87,7 +89,7 @@ private:
void SetPowerSupplyChangeEventEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto state = rp.Pop<bool>();
LOG_DEBUG(Service_PTM, "called, state={}", state);
LOG_DEBUG(Service_PSM, "called, state={}", state);
should_signal_power_supply = state;
@@ -98,7 +100,7 @@ private:
void SetBatteryVoltageStateChangeEventEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto state = rp.Pop<bool>();
LOG_DEBUG(Service_PTM, "called, state={}", state);
LOG_DEBUG(Service_PSM, "called, state={}", state);
should_signal_battery_voltage = state;
@@ -115,58 +117,76 @@ private:
Kernel::KEvent* state_change_event;
};
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"},
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,
};
// clang-format on
RegisterHandlers(functions);
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);
}
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
} // namespace Service::PSM

View File

@@ -3,29 +3,16 @@
#pragma once
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service::PTM {
namespace Service::SM {
class ServiceManager;
}
class PSM final : public ServiceFramework<PSM> {
public:
explicit PSM(Core::System& system_);
~PSM() override;
namespace Service::PSM {
private:
enum class ChargerType : u32 {
Unplugged = 0,
RegularCharger = 1,
LowPowerCharger = 2,
Unknown = 3,
};
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system);
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
} // namespace Service::PSM

View File

@@ -1,18 +0,0 @@
// 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

View File

@@ -1,18 +0,0 @@
// 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

View File

@@ -1,41 +0,0 @@
// 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

View File

@@ -1,25 +0,0 @@
// 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

View File

@@ -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/ptm.h"
#include "core/hle/service/ptm/psm.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);
PTM::InstallInterfaces(*sm, system);
PSM::InstallInterfaces(*sm, system);
Set::InstallInterfaces(*sm, system);
Sockets::InstallInterfaces(*sm, system);
SPL::InstallInterfaces(*sm, system);

View File

@@ -720,25 +720,7 @@ std::pair<s32, Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message)
if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF};
}
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};
return Translate(file_descriptors[fd]->socket->Recv(flags, message));
}
std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,

View File

@@ -438,15 +438,8 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en
using namespace std::chrono_literals;
while (initialized) {
SDL_PumpEvents();
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);
std::this_thread::sleep_for(1ms);
}
});
}
@@ -464,7 +457,6 @@ SDLDriver::~SDLDriver() {
initialized = false;
if (start_thread) {
poll_thread.join();
vibration_thread.join();
SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
}
}

View File

@@ -128,6 +128,5 @@ private:
std::atomic<bool> initialized = false;
std::thread poll_thread;
std::thread vibration_thread;
};
} // namespace InputCommon

View File

@@ -34,7 +34,6 @@ void DmaPusher::DispatchCalls() {
}
gpu.FlushCommands();
gpu.SyncGuestHost();
gpu.OnCommandListEnd();
}
bool DmaPusher::Step() {

View File

@@ -107,14 +107,6 @@ struct GPU::Impl {
rasterizer->SyncGuestHost();
}
/// Signal the ending of command list.
void OnCommandListEnd() {
if (is_async) {
// This command only applies to asynchronous GPU mode
gpu_thread.OnCommandListEnd();
}
}
/// Request a host GPU memory flush from the CPU.
[[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size) {
std::unique_lock lck{flush_request_mutex};
@@ -765,10 +757,6 @@ void GPU::SyncGuestHost() {
impl->SyncGuestHost();
}
void GPU::OnCommandListEnd() {
impl->OnCommandListEnd();
}
u64 GPU::RequestFlush(VAddr addr, std::size_t size) {
return impl->RequestFlush(addr, size);
}

View File

@@ -77,6 +77,9 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer,
void ThreadManager::SubmitList(Tegra::CommandList&& entries) {
PushCommand(SubmitListCommand(std::move(entries)));
if (is_async) {
PushCommand(OnCommandListEndCommand());
}
}
void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
@@ -107,10 +110,6 @@ void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) {
rasterizer->OnCPUWrite(addr, size);
}
void ThreadManager::OnCommandListEnd() {
PushCommand(OnCommandListEndCommand());
}
u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) {
if (!is_async) {
// In synchronous GPU mode, block the caller until the command has executed

View File

@@ -129,8 +129,6 @@ public:
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
void FlushAndInvalidateRegion(VAddr addr, u64 size);
void OnCommandListEnd();
private:
/// Pushes a command to be executed by the GPU thread
u64 PushCommand(CommandData&& command_data, bool block = false);

View File

@@ -87,12 +87,8 @@ u32 GetBytesPerPixel(const Tegra::FramebufferConfig& framebuffer) {
}
std::size_t GetSizeInBytes(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)};
return size_bytes;
return static_cast<std::size_t>(framebuffer.stride) *
static_cast<std::size_t>(framebuffer.height) * GetBytesPerPixel(framebuffer);
}
VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
@@ -173,8 +169,9 @@ 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{GetSizeInBytes(framebuffer)};
const u64 size_bytes{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
framebuffer.stride, framebuffer.height,
1, block_height_log2, 0)};
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);

View File

@@ -38,7 +38,7 @@ VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
if (found_mailbox != modes.end()) {
return VK_PRESENT_MODE_MAILBOX_KHR;
}
if (!Settings::values.use_speed_limit.GetValue()) {
if (Settings::values.disable_fps_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.use_speed_limit.GetValue();
current_fps_unlocked = Settings::values.disable_fps_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.use_speed_limit.GetValue();
return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue();
}
bool Swapchain::NeedsPresentModeUpdate() const {

View File

@@ -2,8 +2,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef YUZU_USE_QT_WEB_ENGINE
#include <bit>
#include <QApplication>
#include <QKeyEvent>
@@ -213,10 +211,8 @@ 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(button_index),
QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(static_cast<u8>(button)),
[this, button](const QVariant& variant) {
if (variant.toBool()) {
switch (button) {
@@ -240,7 +236,7 @@ void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() {
page()->runJavaScript(
QStringLiteral("if (yuzu_key_callbacks[%1] != null) { yuzu_key_callbacks[%1](); }")
.arg(button_index));
.arg(static_cast<u8>(button)));
}
};

View File

@@ -143,8 +143,8 @@ void Config::ReadBasicSetting(Settings::Setting<std::string>& setting) {
}
}
template <typename Type, bool ranged>
void Config::ReadBasicSetting(Settings::Setting<Type, ranged>& setting) {
template <typename Type>
void Config::ReadBasicSetting(Settings::Setting<Type>& 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, bool ranged>
void Config::WriteBasicSetting(const Settings::Setting<Type, ranged>& setting) {
template <typename Type>
void Config::WriteBasicSetting(const Settings::Setting<Type>& 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, bool ranged>
void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting) {
template <typename Type>
void Config::WriteGlobalSetting(const Settings::SwitchableSetting<Type>& setting) {
const QString name = QString::fromStdString(setting.GetLabel());
const Type& value = setting.GetValue(global);
if (!global) {
@@ -668,6 +668,7 @@ 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);
@@ -1236,6 +1237,7 @@ 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)),
@@ -1419,8 +1421,8 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value)
return result;
}
template <typename Type, bool ranged>
void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting) {
template <typename Type>
void Config::ReadGlobalSetting(Settings::SwitchableSetting<Type>& setting) {
QString name = QString::fromStdString(setting.GetLabel());
const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool();
setting.SetGlobal(use_global);

View File

@@ -159,8 +159,8 @@ private:
*
* @param The setting
*/
template <typename Type, bool ranged>
void ReadGlobalSetting(Settings::SwitchableSetting<Type, ranged>& setting);
template <typename Type>
void ReadGlobalSetting(Settings::SwitchableSetting<Type>& 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, bool ranged>
void WriteGlobalSetting(const Settings::SwitchableSetting<Type, ranged>& setting);
template <typename Type>
void WriteGlobalSetting(const Settings::SwitchableSetting<Type>& 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, bool ranged>
void ReadBasicSetting(Settings::Setting<Type, ranged>& setting);
template <typename Type>
void ReadBasicSetting(Settings::Setting<Type>& 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, bool ranged>
void WriteBasicSetting(const Settings::Setting<Type, ranged>& setting);
template <typename Type>
void WriteBasicSetting(const Settings::Setting<Type>& setting);
ConfigType type;
std::unique_ptr<QSettings> qt_config;

View File

@@ -27,9 +27,8 @@ 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, bool ranged>
void ApplyPerGameSetting(Settings::SwitchableSetting<Type, ranged>* setting,
const QComboBox* combobox) {
template <typename Type>
void ApplyPerGameSetting(Settings::SwitchableSetting<Type>* setting, const QComboBox* combobox) {
if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) {
setting->SetValue(static_cast<Type>(combobox->currentIndex()));
} else if (!Settings::IsConfiguringGlobal()) {
@@ -46,9 +45,8 @@ void ApplyPerGameSetting(Settings::SwitchableSetting<Type, ranged>* setting,
// Sets a Qt UI element given a Settings::Setting
void SetPerGameSetting(QCheckBox* checkbox, const Settings::SwitchableSetting<bool>* setting);
template <typename Type, bool ranged>
void SetPerGameSetting(QComboBox* combobox,
const Settings::SwitchableSetting<Type, ranged>* setting) {
template <typename Type>
void SetPerGameSetting(QComboBox* combobox, const Settings::SwitchableSetting<Type>* setting) {
combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX
: static_cast<int>(setting->GetValue()) +
ConfigurationShared::USE_GLOBAL_OFFSET);

View File

@@ -27,6 +27,9 @@ 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;
@@ -49,6 +52,8 @@ 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()) {
@@ -56,6 +61,11 @@ 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());
}
}
@@ -92,6 +102,8 @@ 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() ==
@@ -107,6 +119,13 @@ 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());
}
}
}
@@ -152,4 +171,9 @@ 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);
});
}

View File

@@ -27,6 +27,87 @@
<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>

View File

@@ -166,7 +166,7 @@
<item>
<widget class="QRadioButton" name="radioUndocked">
<property name="text">
<string>Handheld</string>
<string>Undocked</string>
</property>
</widget>
</item>

View File

@@ -1059,7 +1059,7 @@ void GMainWindow::InitializeHotkeys() {
Settings::values.volume.SetValue(static_cast<u8>(new_volume));
});
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {
Settings::values.use_speed_limit.SetValue(!Settings::values.use_speed_limit.GetValue());
Settings::values.disable_fps_limit.SetValue(!Settings::values.disable_fps_limit.GetValue());
});
connect_shortcut(QStringLiteral("Toggle Mouse Panning"), [&] {
Settings::values.mouse_panning = !Settings::values.mouse_panning;
@@ -1131,7 +1131,6 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
OnPauseGame();
} else if (!emu_thread->IsRunning() && auto_paused && state == Qt::ApplicationActive) {
auto_paused = false;
RequestGameResume();
OnStartGame();
}
}
@@ -1484,6 +1483,9 @@ 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();
@@ -2571,7 +2573,6 @@ void GMainWindow::OnPauseContinueGame() {
if (emu_thread->IsRunning()) {
OnPauseGame();
} else {
RequestGameResume();
OnStartGame();
}
}
@@ -3276,7 +3277,7 @@ void GMainWindow::UpdateStatusBar() {
} else {
emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0));
}
if (!Settings::values.use_speed_limit) {
if (Settings::values.disable_fps_limit) {
game_fps_label->setText(
tr("Game: %1 FPS (Unlocked)").arg(results.average_game_fps, 0, 'f', 0));
} else {
@@ -3751,21 +3752,6 @@ 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());

View File

@@ -244,7 +244,6 @@ private:
bool ConfirmChangeGame();
bool ConfirmForceLockedExit();
void RequestGameExit();
void RequestGameResume();
void closeEvent(QCloseEvent* event) override;
private slots:

View File

@@ -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, bool ranged>
void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
template <typename Type>
void Config::ReadSetting(const std::string& group, Settings::Setting<Type>& setting) {
setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(),
static_cast<long>(setting.GetDefault())));
}
@@ -310,6 +310,8 @@ 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);

View File

@@ -33,6 +33,6 @@ private:
* @param group The name of the INI group
* @param setting The yuzu setting to modify
*/
template <typename Type, bool ranged>
void ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting);
template <typename Type>
void ReadSetting(const std::string& group, Settings::Setting<Type>& setting);
};

View File

@@ -330,6 +330,10 @@ 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
@@ -430,6 +434,9 @@ 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

View File

@@ -1,29 +0,0 @@
{
"$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"
]
}