diff options
179 files changed, 1619 insertions, 1261 deletions
diff --git a/.ci/scripts/linux/docker.sh b/.ci/scripts/linux/docker.sh index 1af5ded3d..9b451d3ab 100755 --- a/.ci/scripts/linux/docker.sh +++ b/.ci/scripts/linux/docker.sh | |||
| @@ -30,10 +30,10 @@ make install DESTDIR=AppDir | |||
| 30 | rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester | 30 | rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester |
| 31 | 31 | ||
| 32 | # Download tools needed to build an AppImage | 32 | # Download tools needed to build an AppImage |
| 33 | wget -nc https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage | 33 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-x86_64.AppImage |
| 34 | wget -nc https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage | 34 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-plugin-qt-x86_64.AppImage |
| 35 | wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 | 35 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/AppRun-patched-x86_64 |
| 36 | wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so | 36 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so |
| 37 | # Set executable bit | 37 | # Set executable bit |
| 38 | chmod 755 \ | 38 | chmod 755 \ |
| 39 | AppRun-patched-x86_64 \ | 39 | AppRun-patched-x86_64 \ |
diff --git a/.ci/scripts/linux/upload.sh b/.ci/scripts/linux/upload.sh index b2ea07388..208cd0d04 100644 --- a/.ci/scripts/linux/upload.sh +++ b/.ci/scripts/linux/upload.sh | |||
| @@ -21,7 +21,7 @@ cp build/bin/yuzu "$DIR_NAME" | |||
| 21 | # Build an AppImage | 21 | # Build an AppImage |
| 22 | cd build | 22 | cd build |
| 23 | 23 | ||
| 24 | wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage | 24 | wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/appimagetool-x86_64.AppImage |
| 25 | chmod 755 appimagetool-x86_64.AppImage | 25 | chmod 755 appimagetool-x86_64.AppImage |
| 26 | 26 | ||
| 27 | if [ "${RELEASE_NAME}" = "mainline" ]; then | 27 | if [ "${RELEASE_NAME}" = "mainline" ]; then |
diff --git a/CMakeLists.txt b/CMakeLists.txt index c8e9ebf8a..3faa2b5ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -12,6 +12,8 @@ project(yuzu) | |||
| 12 | # OFF by default, but if ENABLE_SDL2 and MSVC are true then ON | 12 | # OFF by default, but if ENABLE_SDL2 and MSVC are true then ON |
| 13 | option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) | 13 | option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) |
| 14 | CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) | 14 | CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) |
| 15 | # On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion | ||
| 16 | CMAKE_DEPENDENT_OPTION(YUZU_ALLOW_SYSTEM_SDL2 "Try using system SDL2 before fallling back to one from externals" NOT UNIX "ENABLE_SDL2" OFF) | ||
| 15 | 17 | ||
| 16 | option(ENABLE_QT "Enable the Qt frontend" ON) | 18 | option(ENABLE_QT "Enable the Qt frontend" ON) |
| 17 | option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) | 19 | option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) |
| @@ -292,20 +294,24 @@ if (ENABLE_SDL2) | |||
| 292 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}") | 294 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}") |
| 293 | target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") | 295 | target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}") |
| 294 | else() | 296 | else() |
| 295 | find_package(SDL2 2.0.15 QUIET) | 297 | if (YUZU_ALLOW_SYSTEM_SDL2) |
| 296 | 298 | find_package(SDL2 2.0.15 QUIET) | |
| 297 | if (SDL2_FOUND) | 299 | |
| 298 | # Some installations don't set SDL2_LIBRARIES | 300 | if (SDL2_FOUND) |
| 299 | if("${SDL2_LIBRARIES}" STREQUAL "") | 301 | # Some installations don't set SDL2_LIBRARIES |
| 300 | message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2") | 302 | if("${SDL2_LIBRARIES}" STREQUAL "") |
| 301 | set(SDL2_LIBRARIES "SDL2::SDL2") | 303 | message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2") |
| 304 | set(SDL2_LIBRARIES "SDL2::SDL2") | ||
| 305 | endif() | ||
| 306 | |||
| 307 | include_directories(SYSTEM ${SDL2_INCLUDE_DIRS}) | ||
| 308 | add_library(SDL2 INTERFACE) | ||
| 309 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}") | ||
| 310 | else() | ||
| 311 | message(STATUS "SDL2 2.0.15 or newer not found, falling back to externals.") | ||
| 302 | endif() | 312 | endif() |
| 303 | |||
| 304 | include_directories(SYSTEM ${SDL2_INCLUDE_DIRS}) | ||
| 305 | add_library(SDL2 INTERFACE) | ||
| 306 | target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}") | ||
| 307 | else() | 313 | else() |
| 308 | message(STATUS "SDL2 2.0.15 or newer not found, falling back to externals.") | 314 | message(STATUS "Using SDL2 from externals.") |
| 309 | endif() | 315 | endif() |
| 310 | endif() | 316 | endif() |
| 311 | endif() | 317 | endif() |
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index e280e53d7..fe1c088ca 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt | |||
| @@ -47,8 +47,20 @@ target_include_directories(unicorn-headers INTERFACE ./unicorn/include) | |||
| 47 | 47 | ||
| 48 | # SDL2 | 48 | # SDL2 |
| 49 | if (NOT SDL2_FOUND AND ENABLE_SDL2) | 49 | if (NOT SDL2_FOUND AND ENABLE_SDL2) |
| 50 | # Yuzu itself needs: Events Joystick Haptic Sensor Timers | ||
| 51 | # Yuzu-cmd also needs: Video (depends on Loadso/Dlopen) | ||
| 52 | set(SDL_UNUSED_SUBSYSTEMS | ||
| 53 | Atomic Audio Render Power Threads | ||
| 54 | File CPUinfo Filesystem Locale) | ||
| 55 | foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS}) | ||
| 56 | string(TOUPPER ${_SUB} _OPT) | ||
| 57 | option(SDL_${_OPT} "" OFF) | ||
| 58 | endforeach() | ||
| 59 | |||
| 50 | set(SDL_STATIC ON) | 60 | set(SDL_STATIC ON) |
| 51 | set(SDL_SHARED OFF) | 61 | set(SDL_SHARED OFF) |
| 62 | option(HIDAPI "" ON) | ||
| 63 | |||
| 52 | add_subdirectory(SDL EXCLUDE_FROM_ALL) | 64 | add_subdirectory(SDL EXCLUDE_FROM_ALL) |
| 53 | add_library(SDL2 ALIAS SDL2-static) | 65 | add_library(SDL2 ALIAS SDL2-static) |
| 54 | endif() | 66 | endif() |
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8bd7e5f72..f30dd49a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
| @@ -54,6 +54,7 @@ if (MSVC) | |||
| 54 | /we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect | 54 | /we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect |
| 55 | /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? | 55 | /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? |
| 56 | /we4555 # Expression has no effect; expected expression with side-effect | 56 | /we4555 # Expression has no effect; expected expression with side-effect |
| 57 | /we4715 # 'function': not all control paths return a value | ||
| 57 | /we4834 # Discarding return value of function with 'nodiscard' attribute | 58 | /we4834 # Discarding return value of function with 'nodiscard' attribute |
| 58 | /we5038 # data member 'member1' will be initialized after data member 'member2' | 59 | /we5038 # data member 'member1' will be initialized after data member 'member2' |
| 59 | ) | 60 | ) |
diff --git a/src/common/parent_of_member.h b/src/common/parent_of_member.h index e0f8ab5c8..58c70b0e7 100644 --- a/src/common/parent_of_member.h +++ b/src/common/parent_of_member.h | |||
| @@ -109,7 +109,8 @@ struct OffsetOfCalculator { | |||
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | return (next - start) * sizeof(MemberType) + Offset; | 112 | return static_cast<ptrdiff_t>(static_cast<size_t>(next - start) * sizeof(MemberType) + |
| 113 | Offset); | ||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) { | 116 | static constexpr std::ptrdiff_t OffsetOf(MemberType ParentType::*member) { |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 702b6598d..e29cbf506 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -42,7 +42,7 @@ void LogSettings() { | |||
| 42 | log_setting("System_RegionIndex", values.region_index.GetValue()); | 42 | log_setting("System_RegionIndex", values.region_index.GetValue()); |
| 43 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); | 43 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); |
| 44 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); | 44 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); |
| 45 | log_setting("CPU_Accuracy", values.cpu_accuracy); | 45 | log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); |
| 46 | log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); | 46 | log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); |
| 47 | log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue()); | 47 | log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue()); |
| 48 | log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); | 48 | log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); |
| @@ -106,6 +106,12 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 106 | // Core | 106 | // Core |
| 107 | values.use_multi_core.SetGlobal(true); | 107 | values.use_multi_core.SetGlobal(true); |
| 108 | 108 | ||
| 109 | // CPU | ||
| 110 | values.cpu_accuracy.SetGlobal(true); | ||
| 111 | values.cpuopt_unsafe_unfuse_fma.SetGlobal(true); | ||
| 112 | values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true); | ||
| 113 | values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true); | ||
| 114 | |||
| 109 | // Renderer | 115 | // Renderer |
| 110 | values.renderer_backend.SetGlobal(true); | 116 | values.renderer_backend.SetGlobal(true); |
| 111 | values.vulkan_device.SetGlobal(true); | 117 | values.vulkan_device.SetGlobal(true); |
| @@ -130,7 +136,6 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 130 | values.region_index.SetGlobal(true); | 136 | values.region_index.SetGlobal(true); |
| 131 | values.time_zone_index.SetGlobal(true); | 137 | values.time_zone_index.SetGlobal(true); |
| 132 | values.rng_seed.SetGlobal(true); | 138 | values.rng_seed.SetGlobal(true); |
| 133 | values.custom_rtc.SetGlobal(true); | ||
| 134 | values.sound_index.SetGlobal(true); | 139 | values.sound_index.SetGlobal(true); |
| 135 | 140 | ||
| 136 | // Controls | 141 | // Controls |
diff --git a/src/common/settings.h b/src/common/settings.h index d39b4aa45..48085b9a9 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -115,7 +115,7 @@ struct Values { | |||
| 115 | Setting<bool> use_multi_core; | 115 | Setting<bool> use_multi_core; |
| 116 | 116 | ||
| 117 | // Cpu | 117 | // Cpu |
| 118 | CPUAccuracy cpu_accuracy; | 118 | Setting<CPUAccuracy> cpu_accuracy; |
| 119 | 119 | ||
| 120 | bool cpuopt_page_tables; | 120 | bool cpuopt_page_tables; |
| 121 | bool cpuopt_block_linking; | 121 | bool cpuopt_block_linking; |
| @@ -126,9 +126,9 @@ struct Values { | |||
| 126 | bool cpuopt_misc_ir; | 126 | bool cpuopt_misc_ir; |
| 127 | bool cpuopt_reduce_misalign_checks; | 127 | bool cpuopt_reduce_misalign_checks; |
| 128 | 128 | ||
| 129 | bool cpuopt_unsafe_unfuse_fma; | 129 | Setting<bool> cpuopt_unsafe_unfuse_fma; |
| 130 | bool cpuopt_unsafe_reduce_fp_error; | 130 | Setting<bool> cpuopt_unsafe_reduce_fp_error; |
| 131 | bool cpuopt_unsafe_inaccurate_nan; | 131 | Setting<bool> cpuopt_unsafe_inaccurate_nan; |
| 132 | 132 | ||
| 133 | // Renderer | 133 | // Renderer |
| 134 | Setting<RendererBackend> renderer_backend; | 134 | Setting<RendererBackend> renderer_backend; |
| @@ -157,7 +157,7 @@ struct Values { | |||
| 157 | // System | 157 | // System |
| 158 | Setting<std::optional<u32>> rng_seed; | 158 | Setting<std::optional<u32>> rng_seed; |
| 159 | // Measured in seconds since epoch | 159 | // Measured in seconds since epoch |
| 160 | Setting<std::optional<std::chrono::seconds>> custom_rtc; | 160 | std::optional<std::chrono::seconds> custom_rtc; |
| 161 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` | 161 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` |
| 162 | std::chrono::seconds custom_rtc_differential; | 162 | std::chrono::seconds custom_rtc_differential; |
| 163 | 163 | ||
diff --git a/src/common/tree.h b/src/common/tree.h index 3da49e422..18faa4a48 100644 --- a/src/common/tree.h +++ b/src/common/tree.h | |||
| @@ -43,6 +43,8 @@ | |||
| 43 | * The maximum height of a red-black tree is 2lg (n+1). | 43 | * The maximum height of a red-black tree is 2lg (n+1). |
| 44 | */ | 44 | */ |
| 45 | 45 | ||
| 46 | #include "common/assert.h" | ||
| 47 | |||
| 46 | namespace Common { | 48 | namespace Common { |
| 47 | template <typename T> | 49 | template <typename T> |
| 48 | class RBHead { | 50 | class RBHead { |
| @@ -322,9 +324,13 @@ void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) { | |||
| 322 | template <typename Node> | 324 | template <typename Node> |
| 323 | void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { | 325 | void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { |
| 324 | Node* tmp; | 326 | Node* tmp; |
| 325 | while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root()) { | 327 | while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) { |
| 326 | if (RB_LEFT(parent) == elm) { | 328 | if (RB_LEFT(parent) == elm) { |
| 327 | tmp = RB_RIGHT(parent); | 329 | tmp = RB_RIGHT(parent); |
| 330 | if (!tmp) { | ||
| 331 | ASSERT_MSG(false, "tmp is invalid!"); | ||
| 332 | break; | ||
| 333 | } | ||
| 328 | if (RB_IS_RED(tmp)) { | 334 | if (RB_IS_RED(tmp)) { |
| 329 | RB_SET_BLACKRED(tmp, parent); | 335 | RB_SET_BLACKRED(tmp, parent); |
| 330 | RB_ROTATE_LEFT(head, parent, tmp); | 336 | RB_ROTATE_LEFT(head, parent, tmp); |
| @@ -366,6 +372,11 @@ void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { | |||
| 366 | tmp = RB_LEFT(parent); | 372 | tmp = RB_LEFT(parent); |
| 367 | } | 373 | } |
| 368 | 374 | ||
| 375 | if (!tmp) { | ||
| 376 | ASSERT_MSG(false, "tmp is invalid!"); | ||
| 377 | break; | ||
| 378 | } | ||
| 379 | |||
| 369 | if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && | 380 | if ((RB_LEFT(tmp) == nullptr || RB_IS_BLACK(RB_LEFT(tmp))) && |
| 370 | (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { | 381 | (RB_RIGHT(tmp) == nullptr || RB_IS_BLACK(RB_RIGHT(tmp)))) { |
| 371 | RB_SET_COLOR(tmp, EntryColor::Red); | 382 | RB_SET_COLOR(tmp, EntryColor::Red); |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 83da30418..efb851f5a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -651,20 +651,17 @@ endif() | |||
| 651 | 651 | ||
| 652 | if (MSVC) | 652 | if (MSVC) |
| 653 | target_compile_options(core PRIVATE | 653 | target_compile_options(core PRIVATE |
| 654 | # 'expression' : signed/unsigned mismatch | 654 | /we4018 # 'expression' : signed/unsigned mismatch |
| 655 | /we4018 | 655 | /we4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) |
| 656 | # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point) | 656 | /we4245 # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch |
| 657 | /we4244 | 657 | /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data |
| 658 | # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch | 658 | /we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data |
| 659 | /we4245 | 659 | /we4305 # 'context' : truncation from 'type1' to 'type2' |
| 660 | # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data | 660 | /we4456 # Declaration of 'identifier' hides previous local declaration |
| 661 | /we4254 | 661 | /we4457 # Declaration of 'identifier' hides function parameter |
| 662 | # 'var' : conversion from 'size_t' to 'type', possible loss of data | 662 | /we4458 # Declaration of 'identifier' hides class member |
| 663 | /we4267 | 663 | /we4459 # Declaration of 'identifier' hides global declaration |
| 664 | # 'context' : truncation from 'type1' to 'type2' | 664 | /we4715 # 'function' : not all control paths return a value |
| 665 | /we4305 | ||
| 666 | # 'function' : not all control paths return a value | ||
| 667 | /we4715 | ||
| 668 | ) | 665 | ) |
| 669 | else() | 666 | else() |
| 670 | target_compile_options(core PRIVATE | 667 | target_compile_options(core PRIVATE |
| @@ -672,6 +669,7 @@ else() | |||
| 672 | -Werror=ignored-qualifiers | 669 | -Werror=ignored-qualifiers |
| 673 | -Werror=implicit-fallthrough | 670 | -Werror=implicit-fallthrough |
| 674 | -Werror=sign-compare | 671 | -Werror=sign-compare |
| 672 | -Werror=shadow | ||
| 675 | 673 | ||
| 676 | $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> | 674 | $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> |
| 677 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> | 675 | $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 42a37e84f..93d43e22e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -24,7 +24,7 @@ namespace Core { | |||
| 24 | 24 | ||
| 25 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | 25 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { |
| 26 | public: | 26 | public: |
| 27 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent) : parent(parent) {} | 27 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) : parent{parent_} {} |
| 28 | 28 | ||
| 29 | u8 MemoryRead8(u32 vaddr) override { | 29 | u8 MemoryRead8(u32 vaddr) override { |
| 30 | return parent.system.Memory().Read8(vaddr); | 30 | return parent.system.Memory().Read8(vaddr); |
| @@ -142,7 +142,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 142 | config.far_code_offset = 256 * 1024 * 1024; | 142 | config.far_code_offset = 256 * 1024 * 1024; |
| 143 | 143 | ||
| 144 | // Safe optimizations | 144 | // Safe optimizations |
| 145 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { | 145 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { |
| 146 | if (!Settings::values.cpuopt_page_tables) { | 146 | if (!Settings::values.cpuopt_page_tables) { |
| 147 | config.page_table = nullptr; | 147 | config.page_table = nullptr; |
| 148 | } | 148 | } |
| @@ -170,15 +170,15 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | // Unsafe optimizations | 172 | // Unsafe optimizations |
| 173 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { | 173 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
| 174 | config.unsafe_optimizations = true; | 174 | config.unsafe_optimizations = true; |
| 175 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | 175 | if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) { |
| 176 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 176 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 177 | } | 177 | } |
| 178 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { | 178 | if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) { |
| 179 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | 179 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; |
| 180 | } | 180 | } |
| 181 | if (Settings::values.cpuopt_unsafe_inaccurate_nan) { | 181 | if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { |
| 182 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | 182 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; |
| 183 | } | 183 | } |
| 184 | } | 184 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 653bb7a77..08fa85904 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -27,7 +27,7 @@ using Vector = Dynarmic::A64::Vector; | |||
| 27 | 27 | ||
| 28 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | 28 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { |
| 29 | public: | 29 | public: |
| 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {} | 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) : parent{parent_} {} |
| 31 | 31 | ||
| 32 | u8 MemoryRead8(u64 vaddr) override { | 32 | u8 MemoryRead8(u64 vaddr) override { |
| 33 | return parent.system.Memory().Read8(vaddr); | 33 | return parent.system.Memory().Read8(vaddr); |
| @@ -182,7 +182,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 182 | config.far_code_offset = 256 * 1024 * 1024; | 182 | config.far_code_offset = 256 * 1024 * 1024; |
| 183 | 183 | ||
| 184 | // Safe optimizations | 184 | // Safe optimizations |
| 185 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::DebugMode) { | 185 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { |
| 186 | if (!Settings::values.cpuopt_page_tables) { | 186 | if (!Settings::values.cpuopt_page_tables) { |
| 187 | config.page_table = nullptr; | 187 | config.page_table = nullptr; |
| 188 | } | 188 | } |
| @@ -210,15 +210,15 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | // Unsafe optimizations | 212 | // Unsafe optimizations |
| 213 | if (Settings::values.cpu_accuracy == Settings::CPUAccuracy::Unsafe) { | 213 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
| 214 | config.unsafe_optimizations = true; | 214 | config.unsafe_optimizations = true; |
| 215 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { | 215 | if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) { |
| 216 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 216 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 217 | } | 217 | } |
| 218 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { | 218 | if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) { |
| 219 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | 219 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; |
| 220 | } | 220 | } |
| 221 | if (Settings::values.cpuopt_unsafe_inaccurate_nan) { | 221 | if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { |
| 222 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | 222 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; |
| 223 | } | 223 | } |
| 224 | } | 224 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index dc6f4af3a..8597beddf 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h | |||
| @@ -18,7 +18,7 @@ class DynarmicCP15 final : public Dynarmic::A32::Coprocessor { | |||
| 18 | public: | 18 | public: |
| 19 | using CoprocReg = Dynarmic::A32::CoprocReg; | 19 | using CoprocReg = Dynarmic::A32::CoprocReg; |
| 20 | 20 | ||
| 21 | explicit DynarmicCP15(ARM_Dynarmic_32& parent) : parent(parent) {} | 21 | explicit DynarmicCP15(ARM_Dynarmic_32& parent_) : parent{parent_} {} |
| 22 | 22 | ||
| 23 | std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, | 23 | std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, |
| 24 | CoprocReg CRn, CoprocReg CRm, | 24 | CoprocReg CRn, CoprocReg CRm, |
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.cpp b/src/core/arm/dynarmic/arm_exclusive_monitor.cpp index 4e209f6a5..9426a3edf 100644 --- a/src/core/arm/dynarmic/arm_exclusive_monitor.cpp +++ b/src/core/arm/dynarmic/arm_exclusive_monitor.cpp | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | 9 | ||
| 10 | namespace Core { | 10 | namespace Core { |
| 11 | 11 | ||
| 12 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count) | 12 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_) |
| 13 | : monitor(core_count), memory{memory} {} | 13 | : monitor{core_count_}, memory{memory_} {} |
| 14 | 14 | ||
| 15 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; | 15 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; |
| 16 | 16 | ||
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.h b/src/core/arm/dynarmic/arm_exclusive_monitor.h index 964f4a55d..f9f056a59 100644 --- a/src/core/arm/dynarmic/arm_exclusive_monitor.h +++ b/src/core/arm/dynarmic/arm_exclusive_monitor.h | |||
| @@ -22,7 +22,7 @@ namespace Core { | |||
| 22 | 22 | ||
| 23 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { | 23 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { |
| 24 | public: | 24 | public: |
| 25 | explicit DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count); | 25 | explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_); |
| 26 | ~DynarmicExclusiveMonitor() override; | 26 | ~DynarmicExclusiveMonitor() override; |
| 27 | 27 | ||
| 28 | u8 ExclusiveRead8(std::size_t core_index, VAddr addr) override; | 28 | u8 ExclusiveRead8(std::size_t core_index, VAddr addr) override; |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 434bf3262..826a00ad6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -173,7 +173,7 @@ struct System::Impl { | |||
| 173 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( | 173 | const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( |
| 174 | std::chrono::system_clock::now().time_since_epoch()); | 174 | std::chrono::system_clock::now().time_since_epoch()); |
| 175 | Settings::values.custom_rtc_differential = | 175 | Settings::values.custom_rtc_differential = |
| 176 | Settings::values.custom_rtc.GetValue().value_or(current_time) - current_time; | 176 | Settings::values.custom_rtc.value_or(current_time) - current_time; |
| 177 | 177 | ||
| 178 | // Create a default fs if one doesn't already exist. | 178 | // Create a default fs if one doesn't already exist. |
| 179 | if (virtual_filesystem == nullptr) | 179 | if (virtual_filesystem == nullptr) |
| @@ -289,7 +289,8 @@ struct System::Impl { | |||
| 289 | 289 | ||
| 290 | telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", | 290 | telemetry_session->AddField(performance, "Shutdown_EmulationSpeed", |
| 291 | perf_results.emulation_speed * 100.0); | 291 | perf_results.emulation_speed * 100.0); |
| 292 | telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps); | 292 | telemetry_session->AddField(performance, "Shutdown_Framerate", |
| 293 | perf_results.average_game_fps); | ||
| 293 | telemetry_session->AddField(performance, "Shutdown_Frametime", | 294 | telemetry_session->AddField(performance, "Shutdown_Frametime", |
| 294 | perf_results.frametime * 1000.0); | 295 | perf_results.frametime * 1000.0); |
| 295 | telemetry_session->AddField(performance, "Mean_Frametime_MS", | 296 | telemetry_session->AddField(performance, "Mean_Frametime_MS", |
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index bdb374792..7e195346b 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | namespace Core { | 19 | namespace Core { |
| 20 | 20 | ||
| 21 | CpuManager::CpuManager(System& system) : system{system} {} | 21 | CpuManager::CpuManager(System& system_) : system{system_} {} |
| 22 | CpuManager::~CpuManager() = default; | 22 | CpuManager::~CpuManager() = default; |
| 23 | 23 | ||
| 24 | void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) { | 24 | void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) { |
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 9817017c0..140263b09 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -25,7 +25,7 @@ class System; | |||
| 25 | 25 | ||
| 26 | class CpuManager { | 26 | class CpuManager { |
| 27 | public: | 27 | public: |
| 28 | explicit CpuManager(System& system); | 28 | explicit CpuManager(System& system_); |
| 29 | CpuManager(const CpuManager&) = delete; | 29 | CpuManager(const CpuManager&) = delete; |
| 30 | CpuManager(CpuManager&&) = delete; | 30 | CpuManager(CpuManager&&) = delete; |
| 31 | 31 | ||
diff --git a/src/core/crypto/ctr_encryption_layer.cpp b/src/core/crypto/ctr_encryption_layer.cpp index 5c84bb0a4..1231da8e3 100644 --- a/src/core/crypto/ctr_encryption_layer.cpp +++ b/src/core/crypto/ctr_encryption_layer.cpp | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | namespace Core::Crypto { | 10 | namespace Core::Crypto { |
| 11 | 11 | ||
| 12 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, | 12 | CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, |
| 13 | std::size_t base_offset) | 13 | std::size_t base_offset_) |
| 14 | : EncryptionLayer(std::move(base_)), base_offset(base_offset), cipher(key_, Mode::CTR) {} | 14 | : EncryptionLayer(std::move(base_)), base_offset(base_offset_), cipher(key_, Mode::CTR) {} |
| 15 | 15 | ||
| 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { | 16 | std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { |
| 17 | if (length == 0) | 17 | if (length == 0) |
diff --git a/src/core/crypto/ctr_encryption_layer.h b/src/core/crypto/ctr_encryption_layer.h index a2429f001..f86f01b6f 100644 --- a/src/core/crypto/ctr_encryption_layer.h +++ b/src/core/crypto/ctr_encryption_layer.h | |||
| @@ -17,7 +17,7 @@ class CTREncryptionLayer : public EncryptionLayer { | |||
| 17 | public: | 17 | public: |
| 18 | using IVData = std::array<u8, 16>; | 18 | using IVData = std::array<u8, 16>; |
| 19 | 19 | ||
| 20 | CTREncryptionLayer(FileSys::VirtualFile base, Key128 key, std::size_t base_offset); | 20 | CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, std::size_t base_offset_); |
| 21 | 21 | ||
| 22 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; | 22 | std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; |
| 23 | 23 | ||
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 070ed439e..a4b739c63 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -458,7 +458,7 @@ static std::array<u8, size> operator^(const std::array<u8, size>& lhs, | |||
| 458 | const std::array<u8, size>& rhs) { | 458 | const std::array<u8, size>& rhs) { |
| 459 | std::array<u8, size> out; | 459 | std::array<u8, size> out; |
| 460 | std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(), | 460 | std::transform(lhs.begin(), lhs.end(), rhs.begin(), out.begin(), |
| 461 | [](u8 lhs, u8 rhs) { return u8(lhs ^ rhs); }); | 461 | [](u8 lhs_elem, u8 rhs_elem) { return u8(lhs_elem ^ rhs_elem); }); |
| 462 | return out; | 462 | return out; |
| 463 | } | 463 | } |
| 464 | 464 | ||
diff --git a/src/core/file_sys/nca_metadata.cpp b/src/core/file_sys/nca_metadata.cpp index 3596541b2..f5cb4aa8c 100644 --- a/src/core/file_sys/nca_metadata.cpp +++ b/src/core/file_sys/nca_metadata.cpp | |||
| @@ -39,10 +39,10 @@ CNMT::CNMT(VirtualFile file) { | |||
| 39 | } | 39 | } |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | CNMT::CNMT(CNMTHeader header, OptionalHeader opt_header, std::vector<ContentRecord> content_records, | 42 | CNMT::CNMT(CNMTHeader header_, OptionalHeader opt_header_, |
| 43 | std::vector<MetaRecord> meta_records) | 43 | std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_) |
| 44 | : header(std::move(header)), opt_header(std::move(opt_header)), | 44 | : header(std::move(header_)), opt_header(std::move(opt_header_)), |
| 45 | content_records(std::move(content_records)), meta_records(std::move(meta_records)) {} | 45 | content_records(std::move(content_records_)), meta_records(std::move(meta_records_)) {} |
| 46 | 46 | ||
| 47 | CNMT::~CNMT() = default; | 47 | CNMT::~CNMT() = default; |
| 48 | 48 | ||
diff --git a/src/core/file_sys/nca_metadata.h b/src/core/file_sys/nca_metadata.h index 53535e5f5..ce1138a17 100644 --- a/src/core/file_sys/nca_metadata.h +++ b/src/core/file_sys/nca_metadata.h | |||
| @@ -87,8 +87,8 @@ static_assert(sizeof(CNMTHeader) == 0x20, "CNMTHeader has incorrect size."); | |||
| 87 | class CNMT { | 87 | class CNMT { |
| 88 | public: | 88 | public: |
| 89 | explicit CNMT(VirtualFile file); | 89 | explicit CNMT(VirtualFile file); |
| 90 | CNMT(CNMTHeader header, OptionalHeader opt_header, std::vector<ContentRecord> content_records, | 90 | CNMT(CNMTHeader header_, OptionalHeader opt_header_, |
| 91 | std::vector<MetaRecord> meta_records); | 91 | std::vector<ContentRecord> content_records_, std::vector<MetaRecord> meta_records_); |
| 92 | ~CNMT(); | 92 | ~CNMT(); |
| 93 | 93 | ||
| 94 | u64 GetTitleID() const; | 94 | u64 GetTitleID() const; |
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp index 1fb66874e..b0cb65952 100644 --- a/src/core/file_sys/registered_cache.cpp +++ b/src/core/file_sys/registered_cache.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "core/crypto/key_manager.h" | 13 | #include "core/crypto/key_manager.h" |
| 14 | #include "core/file_sys/card_image.h" | 14 | #include "core/file_sys/card_image.h" |
| 15 | #include "core/file_sys/common_funcs.h" | ||
| 15 | #include "core/file_sys/content_archive.h" | 16 | #include "core/file_sys/content_archive.h" |
| 16 | #include "core/file_sys/nca_metadata.h" | 17 | #include "core/file_sys/nca_metadata.h" |
| 17 | #include "core/file_sys/registered_cache.h" | 18 | #include "core/file_sys/registered_cache.h" |
| @@ -592,6 +593,12 @@ InstallResult RegisteredCache::InstallEntry(const NSP& nsp, bool overwrite_if_ex | |||
| 592 | const CNMT cnmt(cnmt_file); | 593 | const CNMT cnmt(cnmt_file); |
| 593 | 594 | ||
| 594 | const auto title_id = cnmt.GetTitleID(); | 595 | const auto title_id = cnmt.GetTitleID(); |
| 596 | const auto version = cnmt.GetTitleVersion(); | ||
| 597 | |||
| 598 | if (title_id == GetBaseTitleID(title_id) && version == 0) { | ||
| 599 | return InstallResult::ErrorBaseInstall; | ||
| 600 | } | ||
| 601 | |||
| 595 | const auto result = RemoveExistingEntry(title_id); | 602 | const auto result = RemoveExistingEntry(title_id); |
| 596 | 603 | ||
| 597 | // Install Metadata File | 604 | // Install Metadata File |
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h index b31630014..d042aef90 100644 --- a/src/core/file_sys/registered_cache.h +++ b/src/core/file_sys/registered_cache.h | |||
| @@ -38,6 +38,7 @@ enum class InstallResult { | |||
| 38 | ErrorAlreadyExists, | 38 | ErrorAlreadyExists, |
| 39 | ErrorCopyFailed, | 39 | ErrorCopyFailed, |
| 40 | ErrorMetaFailed, | 40 | ErrorMetaFailed, |
| 41 | ErrorBaseInstall, | ||
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | struct ContentProviderEntry { | 44 | struct ContentProviderEntry { |
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index 80e560970..d51d469e3 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp | |||
| @@ -20,8 +20,8 @@ | |||
| 20 | 20 | ||
| 21 | namespace FileSys { | 21 | namespace FileSys { |
| 22 | 22 | ||
| 23 | NSP::NSP(VirtualFile file_, std::size_t program_index) | 23 | NSP::NSP(VirtualFile file_, std::size_t program_index_) |
| 24 | : file(std::move(file_)), program_index(program_index), status{Loader::ResultStatus::Success}, | 24 | : file(std::move(file_)), program_index(program_index_), status{Loader::ResultStatus::Success}, |
| 25 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { | 25 | pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} { |
| 26 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { | 26 | if (pfs->GetStatus() != Loader::ResultStatus::Success) { |
| 27 | status = pfs->GetStatus(); | 27 | status = pfs->GetStatus(); |
diff --git a/src/core/file_sys/submission_package.h b/src/core/file_sys/submission_package.h index 54581a6f3..ecb3b6f15 100644 --- a/src/core/file_sys/submission_package.h +++ b/src/core/file_sys/submission_package.h | |||
| @@ -27,7 +27,7 @@ enum class ContentRecordType : u8; | |||
| 27 | 27 | ||
| 28 | class NSP : public ReadOnlyVfsDirectory { | 28 | class NSP : public ReadOnlyVfsDirectory { |
| 29 | public: | 29 | public: |
| 30 | explicit NSP(VirtualFile file, std::size_t program_index = 0); | 30 | explicit NSP(VirtualFile file_, std::size_t program_index_ = 0); |
| 31 | ~NSP() override; | 31 | ~NSP() override; |
| 32 | 32 | ||
| 33 | Loader::ResultStatus GetStatus() const; | 33 | Loader::ResultStatus GetStatus() const; |
diff --git a/src/core/file_sys/vfs_concat.cpp b/src/core/file_sys/vfs_concat.cpp index 619081502..5f8c09124 100644 --- a/src/core/file_sys/vfs_concat.cpp +++ b/src/core/file_sys/vfs_concat.cpp | |||
| @@ -23,8 +23,8 @@ static bool VerifyConcatenationMapContinuity(const std::multimap<u64, VirtualFil | |||
| 23 | return map.begin()->first == 0; | 23 | return map.begin()->first == 0; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::string name) | 26 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::string name_) |
| 27 | : name(std::move(name)) { | 27 | : name(std::move(name_)) { |
| 28 | std::size_t next_offset = 0; | 28 | std::size_t next_offset = 0; |
| 29 | for (const auto& file : files_) { | 29 | for (const auto& file : files_) { |
| 30 | files.emplace(next_offset, file); | 30 | files.emplace(next_offset, file); |
| @@ -32,8 +32,8 @@ ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::s | |||
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name) | 35 | ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name_) |
| 36 | : files(std::move(files_)), name(std::move(name)) { | 36 | : files(std::move(files_)), name(std::move(name_)) { |
| 37 | ASSERT(VerifyConcatenationMapContinuity(files)); | 37 | ASSERT(VerifyConcatenationMapContinuity(files)); |
| 38 | } | 38 | } |
| 39 | 39 | ||
diff --git a/src/core/file_sys/vfs_concat.h b/src/core/file_sys/vfs_concat.h index 3397d32cd..cd32960a5 100644 --- a/src/core/file_sys/vfs_concat.h +++ b/src/core/file_sys/vfs_concat.h | |||
| @@ -14,8 +14,8 @@ namespace FileSys { | |||
| 14 | // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently | 14 | // Class that wraps multiple vfs files and concatenates them, making reads seamless. Currently |
| 15 | // read-only. | 15 | // read-only. |
| 16 | class ConcatenatedVfsFile : public VfsFile { | 16 | class ConcatenatedVfsFile : public VfsFile { |
| 17 | ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name); | 17 | explicit ConcatenatedVfsFile(std::vector<VirtualFile> files, std::string name_); |
| 18 | ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name); | 18 | explicit ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files, std::string name_); |
| 19 | 19 | ||
| 20 | public: | 20 | public: |
| 21 | ~ConcatenatedVfsFile() override; | 21 | ~ConcatenatedVfsFile() override; |
diff --git a/src/core/file_sys/vfs_layered.cpp b/src/core/file_sys/vfs_layered.cpp index 192740058..e093c4db2 100644 --- a/src/core/file_sys/vfs_layered.cpp +++ b/src/core/file_sys/vfs_layered.cpp | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | namespace FileSys { | 9 | namespace FileSys { |
| 10 | 10 | ||
| 11 | LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name) | 11 | LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs_, std::string name_) |
| 12 | : dirs(std::move(dirs)), name(std::move(name)) {} | 12 | : dirs(std::move(dirs_)), name(std::move(name_)) {} |
| 13 | 13 | ||
| 14 | LayeredVfsDirectory::~LayeredVfsDirectory() = default; | 14 | LayeredVfsDirectory::~LayeredVfsDirectory() = default; |
| 15 | 15 | ||
diff --git a/src/core/file_sys/vfs_layered.h b/src/core/file_sys/vfs_layered.h index cb4b32e91..cd6baf28c 100644 --- a/src/core/file_sys/vfs_layered.h +++ b/src/core/file_sys/vfs_layered.h | |||
| @@ -13,7 +13,7 @@ namespace FileSys { | |||
| 13 | // one and falling back to the one after. The highest priority directory (overwrites all others) | 13 | // one and falling back to the one after. The highest priority directory (overwrites all others) |
| 14 | // should be element 0 in the dirs vector. | 14 | // should be element 0 in the dirs vector. |
| 15 | class LayeredVfsDirectory : public VfsDirectory { | 15 | class LayeredVfsDirectory : public VfsDirectory { |
| 16 | LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name); | 16 | explicit LayeredVfsDirectory(std::vector<VirtualDir> dirs_, std::string name_); |
| 17 | 17 | ||
| 18 | public: | 18 | public: |
| 19 | ~LayeredVfsDirectory() override; | 19 | ~LayeredVfsDirectory() override; |
diff --git a/src/core/file_sys/vfs_libzip.cpp b/src/core/file_sys/vfs_libzip.cpp index 429d7bc8b..618eb658a 100644 --- a/src/core/file_sys/vfs_libzip.cpp +++ b/src/core/file_sys/vfs_libzip.cpp | |||
| @@ -3,7 +3,16 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <string> | 5 | #include <string> |
| 6 | |||
| 7 | #ifdef __GNUC__ | ||
| 8 | #pragma GCC diagnostic push | ||
| 9 | #pragma GCC diagnostic ignored "-Wshadow" | ||
| 10 | #endif | ||
| 6 | #include <zip.h> | 11 | #include <zip.h> |
| 12 | #ifdef __GNUC__ | ||
| 13 | #pragma GCC diagnostic pop | ||
| 14 | #endif | ||
| 15 | |||
| 7 | #include "common/logging/backend.h" | 16 | #include "common/logging/backend.h" |
| 8 | #include "core/file_sys/vfs.h" | 17 | #include "core/file_sys/vfs.h" |
| 9 | #include "core/file_sys/vfs_libzip.h" | 18 | #include "core/file_sys/vfs_libzip.h" |
diff --git a/src/core/file_sys/vfs_static.h b/src/core/file_sys/vfs_static.h index c840b24b9..f5b66cf71 100644 --- a/src/core/file_sys/vfs_static.h +++ b/src/core/file_sys/vfs_static.h | |||
| @@ -14,9 +14,9 @@ namespace FileSys { | |||
| 14 | 14 | ||
| 15 | class StaticVfsFile : public VfsFile { | 15 | class StaticVfsFile : public VfsFile { |
| 16 | public: | 16 | public: |
| 17 | explicit StaticVfsFile(u8 value, std::size_t size = 0, std::string name = "", | 17 | explicit StaticVfsFile(u8 value_, std::size_t size_ = 0, std::string name_ = "", |
| 18 | VirtualDir parent = nullptr) | 18 | VirtualDir parent_ = nullptr) |
| 19 | : value{value}, size{size}, name{std::move(name)}, parent{std::move(parent)} {} | 19 | : value{value_}, size{size_}, name{std::move(name_)}, parent{std::move(parent_)} {} |
| 20 | 20 | ||
| 21 | std::string GetName() const override { | 21 | std::string GetName() const override { |
| 22 | return name; | 22 | return name; |
diff --git a/src/core/file_sys/vfs_vector.cpp b/src/core/file_sys/vfs_vector.cpp index 1a3f06227..f64b88639 100644 --- a/src/core/file_sys/vfs_vector.cpp +++ b/src/core/file_sys/vfs_vector.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | #include "core/file_sys/vfs_vector.h" | 7 | #include "core/file_sys/vfs_vector.h" |
| 8 | 8 | ||
| 9 | namespace FileSys { | 9 | namespace FileSys { |
| 10 | VectorVfsFile::VectorVfsFile(std::vector<u8> initial_data, std::string name, VirtualDir parent) | 10 | VectorVfsFile::VectorVfsFile(std::vector<u8> initial_data, std::string name_, VirtualDir parent_) |
| 11 | : data(std::move(initial_data)), parent(std::move(parent)), name(std::move(name)) {} | 11 | : data(std::move(initial_data)), parent(std::move(parent_)), name(std::move(name_)) {} |
| 12 | 12 | ||
| 13 | VectorVfsFile::~VectorVfsFile() = default; | 13 | VectorVfsFile::~VectorVfsFile() = default; |
| 14 | 14 | ||
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h index c10c527b6..73f180070 100644 --- a/src/core/file_sys/vfs_vector.h +++ b/src/core/file_sys/vfs_vector.h | |||
| @@ -75,8 +75,8 @@ std::shared_ptr<ArrayVfsFile<Size>> MakeArrayFile(const std::array<u8, Size>& da | |||
| 75 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction | 75 | // An implementation of VfsFile that is backed by a vector optionally supplied upon construction |
| 76 | class VectorVfsFile : public VfsFile { | 76 | class VectorVfsFile : public VfsFile { |
| 77 | public: | 77 | public: |
| 78 | explicit VectorVfsFile(std::vector<u8> initial_data = {}, std::string name = "", | 78 | explicit VectorVfsFile(std::vector<u8> initial_data = {}, std::string name_ = "", |
| 79 | VirtualDir parent = nullptr); | 79 | VirtualDir parent_ = nullptr); |
| 80 | ~VectorVfsFile() override; | 80 | ~VectorVfsFile() override; |
| 81 | 81 | ||
| 82 | std::string GetName() const override; | 82 | std::string GetName() const override; |
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index cff49899a..e11ec0b0b 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | private: | 26 | private: |
| 27 | class Device : public Input::TouchDevice { | 27 | class Device : public Input::TouchDevice { |
| 28 | public: | 28 | public: |
| 29 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} | 29 | explicit Device(std::weak_ptr<TouchState>&& touch_state_) : touch_state(touch_state_) {} |
| 30 | Input::TouchStatus GetStatus() const override { | 30 | Input::TouchStatus GetStatus() const override { |
| 31 | if (auto state = touch_state.lock()) { | 31 | if (auto state = touch_state.lock()) { |
| 32 | std::lock_guard guard{state->mutex}; | 32 | std::lock_guard guard{state->mutex}; |
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 55b1716e4..602e12606 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h | |||
| @@ -32,7 +32,8 @@ enum class CommandType : u32 { | |||
| 32 | Control = 5, | 32 | Control = 5, |
| 33 | RequestWithContext = 6, | 33 | RequestWithContext = 6, |
| 34 | ControlWithContext = 7, | 34 | ControlWithContext = 7, |
| 35 | Unspecified, | 35 | TIPC_Close = 15, |
| 36 | TIPC_CommandRegion = 16, // Start of TIPC commands, this is an offset. | ||
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 38 | struct CommandHeader { | 39 | struct CommandHeader { |
| @@ -57,6 +58,20 @@ struct CommandHeader { | |||
| 57 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; | 58 | BitField<10, 4, BufferDescriptorCFlag> buf_c_descriptor_flags; |
| 58 | BitField<31, 1, u32> enable_handle_descriptor; | 59 | BitField<31, 1, u32> enable_handle_descriptor; |
| 59 | }; | 60 | }; |
| 61 | |||
| 62 | bool IsTipc() const { | ||
| 63 | return type.Value() >= CommandType::TIPC_CommandRegion; | ||
| 64 | } | ||
| 65 | |||
| 66 | bool IsCloseCommand() const { | ||
| 67 | switch (type.Value()) { | ||
| 68 | case CommandType::Close: | ||
| 69 | case CommandType::TIPC_Close: | ||
| 70 | return true; | ||
| 71 | default: | ||
| 72 | return false; | ||
| 73 | } | ||
| 74 | } | ||
| 60 | }; | 75 | }; |
| 61 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); | 76 | static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); |
| 62 | 77 | ||
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index d136be452..61bda3786 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include "core/hle/ipc.h" | 15 | #include "core/hle/ipc.h" |
| 16 | #include "core/hle/kernel/hle_ipc.h" | 16 | #include "core/hle/kernel/hle_ipc.h" |
| 17 | #include "core/hle/kernel/k_client_port.h" | 17 | #include "core/hle/kernel/k_client_port.h" |
| 18 | #include "core/hle/kernel/k_process.h" | ||
| 19 | #include "core/hle/kernel/k_resource_limit.h" | ||
| 18 | #include "core/hle/kernel/k_session.h" | 20 | #include "core/hle/kernel/k_session.h" |
| 19 | #include "core/hle/result.h" | 21 | #include "core/hle/result.h" |
| 20 | 22 | ||
| @@ -26,19 +28,19 @@ class RequestHelperBase { | |||
| 26 | protected: | 28 | protected: |
| 27 | Kernel::HLERequestContext* context = nullptr; | 29 | Kernel::HLERequestContext* context = nullptr; |
| 28 | u32* cmdbuf; | 30 | u32* cmdbuf; |
| 29 | ptrdiff_t index = 0; | 31 | u32 index = 0; |
| 30 | 32 | ||
| 31 | public: | 33 | public: |
| 32 | explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} | 34 | explicit RequestHelperBase(u32* command_buffer) : cmdbuf(command_buffer) {} |
| 33 | 35 | ||
| 34 | explicit RequestHelperBase(Kernel::HLERequestContext& context) | 36 | explicit RequestHelperBase(Kernel::HLERequestContext& ctx) |
| 35 | : context(&context), cmdbuf(context.CommandBuffer()) {} | 37 | : context(&ctx), cmdbuf(ctx.CommandBuffer()) {} |
| 36 | 38 | ||
| 37 | void Skip(u32 size_in_words, bool set_to_null) { | 39 | void Skip(u32 size_in_words, bool set_to_null) { |
| 38 | if (set_to_null) { | 40 | if (set_to_null) { |
| 39 | memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); | 41 | memset(cmdbuf + index, 0, size_in_words * sizeof(u32)); |
| 40 | } | 42 | } |
| 41 | index += static_cast<ptrdiff_t>(size_in_words); | 43 | index += size_in_words; |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 44 | /** | 46 | /** |
| @@ -51,11 +53,11 @@ public: | |||
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | u32 GetCurrentOffset() const { | 55 | u32 GetCurrentOffset() const { |
| 54 | return static_cast<u32>(index); | 56 | return index; |
| 55 | } | 57 | } |
| 56 | 58 | ||
| 57 | void SetCurrentOffset(u32 offset) { | 59 | void SetCurrentOffset(u32 offset) { |
| 58 | index = static_cast<ptrdiff_t>(offset); | 60 | index = offset; |
| 59 | } | 61 | } |
| 60 | }; | 62 | }; |
| 61 | 63 | ||
| @@ -69,23 +71,21 @@ public: | |||
| 69 | AlwaysMoveHandles = 1, | 71 | AlwaysMoveHandles = 1, |
| 70 | }; | 72 | }; |
| 71 | 73 | ||
| 72 | explicit ResponseBuilder(Kernel::HLERequestContext& ctx, u32 normal_params_size, | 74 | explicit ResponseBuilder(Kernel::HLERequestContext& ctx, u32 normal_params_size_, |
| 73 | u32 num_handles_to_copy = 0, u32 num_objects_to_move = 0, | 75 | u32 num_handles_to_copy_ = 0, u32 num_objects_to_move_ = 0, |
| 74 | Flags flags = Flags::None) | 76 | Flags flags = Flags::None) |
| 75 | : RequestHelperBase(ctx), normal_params_size(normal_params_size), | 77 | : RequestHelperBase(ctx), normal_params_size(normal_params_size_), |
| 76 | num_handles_to_copy(num_handles_to_copy), | 78 | num_handles_to_copy(num_handles_to_copy_), |
| 77 | num_objects_to_move(num_objects_to_move), kernel{ctx.kernel} { | 79 | num_objects_to_move(num_objects_to_move_), kernel{ctx.kernel} { |
| 78 | 80 | ||
| 79 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); | 81 | memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); |
| 80 | 82 | ||
| 81 | ctx.ClearIncomingObjects(); | ||
| 82 | |||
| 83 | IPC::CommandHeader header{}; | 83 | IPC::CommandHeader header{}; |
| 84 | 84 | ||
| 85 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory | 85 | // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory |
| 86 | // padding. | 86 | // padding. |
| 87 | u64 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | 87 | u32 raw_data_size = ctx.write_size = |
| 88 | 88 | ctx.IsTipc() ? normal_params_size - 1 : normal_params_size; | |
| 89 | u32 num_handles_to_move{}; | 89 | u32 num_handles_to_move{}; |
| 90 | u32 num_domain_objects{}; | 90 | u32 num_domain_objects{}; |
| 91 | const bool always_move_handles{ | 91 | const bool always_move_handles{ |
| @@ -97,10 +97,19 @@ public: | |||
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | if (ctx.Session()->IsDomain()) { | 99 | if (ctx.Session()->IsDomain()) { |
| 100 | raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; | 100 | raw_data_size += |
| 101 | static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects); | ||
| 102 | ctx.write_size += num_domain_objects; | ||
| 101 | } | 103 | } |
| 102 | 104 | ||
| 103 | header.data_size.Assign(static_cast<u32>(raw_data_size)); | 105 | if (ctx.IsTipc()) { |
| 106 | header.type.Assign(ctx.GetCommandType()); | ||
| 107 | } else { | ||
| 108 | raw_data_size += static_cast<u32>(sizeof(IPC::DataPayloadHeader) / sizeof(u32) + 4 + | ||
| 109 | normal_params_size); | ||
| 110 | } | ||
| 111 | |||
| 112 | header.data_size.Assign(raw_data_size); | ||
| 104 | if (num_handles_to_copy || num_handles_to_move) { | 113 | if (num_handles_to_copy || num_handles_to_move) { |
| 105 | header.enable_handle_descriptor.Assign(1); | 114 | header.enable_handle_descriptor.Assign(1); |
| 106 | } | 115 | } |
| @@ -108,25 +117,34 @@ public: | |||
| 108 | 117 | ||
| 109 | if (header.enable_handle_descriptor) { | 118 | if (header.enable_handle_descriptor) { |
| 110 | IPC::HandleDescriptorHeader handle_descriptor_header{}; | 119 | IPC::HandleDescriptorHeader handle_descriptor_header{}; |
| 111 | handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy); | 120 | handle_descriptor_header.num_handles_to_copy.Assign(num_handles_to_copy_); |
| 112 | handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); | 121 | handle_descriptor_header.num_handles_to_move.Assign(num_handles_to_move); |
| 113 | PushRaw(handle_descriptor_header); | 122 | PushRaw(handle_descriptor_header); |
| 123 | |||
| 124 | ctx.handles_offset = index; | ||
| 125 | |||
| 114 | Skip(num_handles_to_copy + num_handles_to_move, true); | 126 | Skip(num_handles_to_copy + num_handles_to_move, true); |
| 115 | } | 127 | } |
| 116 | 128 | ||
| 117 | AlignWithPadding(); | 129 | if (!ctx.IsTipc()) { |
| 130 | AlignWithPadding(); | ||
| 118 | 131 | ||
| 119 | if (ctx.Session()->IsDomain() && ctx.HasDomainMessageHeader()) { | 132 | if (ctx.Session()->IsDomain() && ctx.HasDomainMessageHeader()) { |
| 120 | IPC::DomainMessageHeader domain_header{}; | 133 | IPC::DomainMessageHeader domain_header{}; |
| 121 | domain_header.num_objects = num_domain_objects; | 134 | domain_header.num_objects = num_domain_objects; |
| 122 | PushRaw(domain_header); | 135 | PushRaw(domain_header); |
| 136 | } | ||
| 137 | |||
| 138 | IPC::DataPayloadHeader data_payload_header{}; | ||
| 139 | data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); | ||
| 140 | PushRaw(data_payload_header); | ||
| 123 | } | 141 | } |
| 124 | 142 | ||
| 125 | IPC::DataPayloadHeader data_payload_header{}; | 143 | data_payload_index = index; |
| 126 | data_payload_header.magic = Common::MakeMagic('S', 'F', 'C', 'O'); | ||
| 127 | PushRaw(data_payload_header); | ||
| 128 | 144 | ||
| 129 | datapayload_index = index; | 145 | ctx.data_payload_offset = index; |
| 146 | ctx.write_size += index; | ||
| 147 | ctx.domain_offset = static_cast<u32>(index + raw_data_size / sizeof(u32)); | ||
| 130 | } | 148 | } |
| 131 | 149 | ||
| 132 | template <class T> | 150 | template <class T> |
| @@ -134,6 +152,9 @@ public: | |||
| 134 | if (context->Session()->IsDomain()) { | 152 | if (context->Session()->IsDomain()) { |
| 135 | context->AddDomainObject(std::move(iface)); | 153 | context->AddDomainObject(std::move(iface)); |
| 136 | } else { | 154 | } else { |
| 155 | kernel.CurrentProcess()->GetResourceLimit()->Reserve( | ||
| 156 | Kernel::LimitableResource::Sessions, 1); | ||
| 157 | |||
| 137 | auto* session = Kernel::KSession::Create(kernel); | 158 | auto* session = Kernel::KSession::Create(kernel); |
| 138 | session->Initialize(nullptr, iface->GetServiceName()); | 159 | session->Initialize(nullptr, iface->GetServiceName()); |
| 139 | 160 | ||
| @@ -147,24 +168,6 @@ public: | |||
| 147 | PushIpcInterface<T>(std::make_shared<T>(std::forward<Args>(args)...)); | 168 | PushIpcInterface<T>(std::make_shared<T>(std::forward<Args>(args)...)); |
| 148 | } | 169 | } |
| 149 | 170 | ||
| 150 | void ValidateHeader() { | ||
| 151 | const std::size_t num_domain_objects = context->NumDomainObjects(); | ||
| 152 | const std::size_t num_move_objects = context->NumMoveObjects(); | ||
| 153 | ASSERT_MSG(!num_domain_objects || !num_move_objects, | ||
| 154 | "cannot move normal handles and domain objects"); | ||
| 155 | ASSERT_MSG((index - datapayload_index) == normal_params_size, | ||
| 156 | "normal_params_size value is incorrect"); | ||
| 157 | ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move, | ||
| 158 | "num_objects_to_move value is incorrect"); | ||
| 159 | ASSERT_MSG(context->NumCopyObjects() == num_handles_to_copy, | ||
| 160 | "num_handles_to_copy value is incorrect"); | ||
| 161 | } | ||
| 162 | |||
| 163 | // Validate on destruction, as there shouldn't be any case where we don't want it | ||
| 164 | ~ResponseBuilder() { | ||
| 165 | ValidateHeader(); | ||
| 166 | } | ||
| 167 | |||
| 168 | void PushImpl(s8 value); | 171 | void PushImpl(s8 value); |
| 169 | void PushImpl(s16 value); | 172 | void PushImpl(s16 value); |
| 170 | void PushImpl(s32 value); | 173 | void PushImpl(s32 value); |
| @@ -229,14 +232,14 @@ private: | |||
| 229 | u32 normal_params_size{}; | 232 | u32 normal_params_size{}; |
| 230 | u32 num_handles_to_copy{}; | 233 | u32 num_handles_to_copy{}; |
| 231 | u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent | 234 | u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent |
| 232 | std::ptrdiff_t datapayload_index{}; | 235 | u32 data_payload_index{}; |
| 233 | Kernel::KernelCore& kernel; | 236 | Kernel::KernelCore& kernel; |
| 234 | }; | 237 | }; |
| 235 | 238 | ||
| 236 | /// Push /// | 239 | /// Push /// |
| 237 | 240 | ||
| 238 | inline void ResponseBuilder::PushImpl(s32 value) { | 241 | inline void ResponseBuilder::PushImpl(s32 value) { |
| 239 | cmdbuf[index++] = static_cast<u32>(value); | 242 | cmdbuf[index++] = value; |
| 240 | } | 243 | } |
| 241 | 244 | ||
| 242 | inline void ResponseBuilder::PushImpl(u32 value) { | 245 | inline void ResponseBuilder::PushImpl(u32 value) { |
| @@ -384,7 +387,7 @@ public: | |||
| 384 | std::shared_ptr<T> PopIpcInterface() { | 387 | std::shared_ptr<T> PopIpcInterface() { |
| 385 | ASSERT(context->Session()->IsDomain()); | 388 | ASSERT(context->Session()->IsDomain()); |
| 386 | ASSERT(context->GetDomainMessageHeader().input_object_count > 0); | 389 | ASSERT(context->GetDomainMessageHeader().input_object_count > 0); |
| 387 | return context->GetDomainRequestHandler<T>(Pop<u32>() - 1); | 390 | return context->GetDomainHandler<T>(Pop<u32>() - 1); |
| 388 | } | 391 | } |
| 389 | }; | 392 | }; |
| 390 | 393 | ||
diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp index 7c87cbada..4f4e338e3 100644 --- a/src/core/hle/kernel/global_scheduler_context.cpp +++ b/src/core/hle/kernel/global_scheduler_context.cpp | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel) | 15 | GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel_) |
| 16 | : kernel{kernel}, scheduler_lock{kernel} {} | 16 | : kernel{kernel_}, scheduler_lock{kernel_} {} |
| 17 | 17 | ||
| 18 | GlobalSchedulerContext::~GlobalSchedulerContext() = default; | 18 | GlobalSchedulerContext::~GlobalSchedulerContext() = default; |
| 19 | 19 | ||
diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h index ba8b67fd1..6f44b534f 100644 --- a/src/core/hle/kernel/global_scheduler_context.h +++ b/src/core/hle/kernel/global_scheduler_context.h | |||
| @@ -34,7 +34,7 @@ class GlobalSchedulerContext final { | |||
| 34 | public: | 34 | public: |
| 35 | using LockType = KAbstractSchedulerLock<KScheduler>; | 35 | using LockType = KAbstractSchedulerLock<KScheduler>; |
| 36 | 36 | ||
| 37 | explicit GlobalSchedulerContext(KernelCore& kernel); | 37 | explicit GlobalSchedulerContext(KernelCore& kernel_); |
| 38 | ~GlobalSchedulerContext(); | 38 | ~GlobalSchedulerContext(); |
| 39 | 39 | ||
| 40 | /// Adds a new thread to the scheduler | 40 | /// Adds a new thread to the scheduler |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 93907f75e..9d069a78f 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -35,11 +35,11 @@ SessionRequestHandler::SessionRequestHandler() = default; | |||
| 35 | SessionRequestHandler::~SessionRequestHandler() = default; | 35 | SessionRequestHandler::~SessionRequestHandler() = default; |
| 36 | 36 | ||
| 37 | void SessionRequestHandler::ClientConnected(KServerSession* session) { | 37 | void SessionRequestHandler::ClientConnected(KServerSession* session) { |
| 38 | session->SetHleHandler(shared_from_this()); | 38 | session->SetSessionHandler(shared_from_this()); |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { | 41 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { |
| 42 | session->SetHleHandler(nullptr); | 42 | session->SetSessionHandler(nullptr); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, | 45 | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, |
| @@ -55,7 +55,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 55 | IPC::RequestParser rp(src_cmdbuf); | 55 | IPC::RequestParser rp(src_cmdbuf); |
| 56 | command_header = rp.PopRaw<IPC::CommandHeader>(); | 56 | command_header = rp.PopRaw<IPC::CommandHeader>(); |
| 57 | 57 | ||
| 58 | if (command_header->type == IPC::CommandType::Close) { | 58 | if (command_header->IsCloseCommand()) { |
| 59 | // Close does not populate the rest of the IPC header | 59 | // Close does not populate the rest of the IPC header |
| 60 | return; | 60 | return; |
| 61 | } | 61 | } |
| @@ -64,19 +64,15 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 64 | if (command_header->enable_handle_descriptor) { | 64 | if (command_header->enable_handle_descriptor) { |
| 65 | handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); | 65 | handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); |
| 66 | if (handle_descriptor_header->send_current_pid) { | 66 | if (handle_descriptor_header->send_current_pid) { |
| 67 | rp.Skip(2, false); | 67 | pid = rp.Pop<u64>(); |
| 68 | } | 68 | } |
| 69 | if (incoming) { | 69 | if (incoming) { |
| 70 | // Populate the object lists with the data in the IPC request. | 70 | // Populate the object lists with the data in the IPC request. |
| 71 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { | 71 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { |
| 72 | const u32 copy_handle{rp.Pop<Handle>()}; | 72 | incoming_copy_handles.push_back(rp.Pop<Handle>()); |
| 73 | copy_handles.push_back(copy_handle); | ||
| 74 | copy_objects.push_back(handle_table.GetObject(copy_handle).GetPointerUnsafe()); | ||
| 75 | } | 73 | } |
| 76 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { | 74 | for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { |
| 77 | const u32 move_handle{rp.Pop<Handle>()}; | 75 | incoming_move_handles.push_back(rp.Pop<Handle>()); |
| 78 | move_handles.push_back(move_handle); | ||
| 79 | move_objects.push_back(handle_table.GetObject(move_handle).GetPointerUnsafe()); | ||
| 80 | } | 76 | } |
| 81 | } else { | 77 | } else { |
| 82 | // For responses we just ignore the handles, they're empty and will be populated when | 78 | // For responses we just ignore the handles, they're empty and will be populated when |
| @@ -86,52 +82,56 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 86 | } | 82 | } |
| 87 | } | 83 | } |
| 88 | 84 | ||
| 89 | for (unsigned i = 0; i < command_header->num_buf_x_descriptors; ++i) { | 85 | for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { |
| 90 | buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); | 86 | buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); |
| 91 | } | 87 | } |
| 92 | for (unsigned i = 0; i < command_header->num_buf_a_descriptors; ++i) { | 88 | for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) { |
| 93 | buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 89 | buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 94 | } | 90 | } |
| 95 | for (unsigned i = 0; i < command_header->num_buf_b_descriptors; ++i) { | 91 | for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) { |
| 96 | buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 92 | buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 97 | } | 93 | } |
| 98 | for (unsigned i = 0; i < command_header->num_buf_w_descriptors; ++i) { | 94 | for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) { |
| 99 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 95 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 100 | } | 96 | } |
| 101 | 97 | ||
| 102 | buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; | 98 | const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; |
| 103 | 99 | ||
| 104 | // Padding to align to 16 bytes | 100 | if (!command_header->IsTipc()) { |
| 105 | rp.AlignWithPadding(); | 101 | // Padding to align to 16 bytes |
| 106 | 102 | rp.AlignWithPadding(); | |
| 107 | if (Session()->IsDomain() && ((command_header->type == IPC::CommandType::Request || | 103 | |
| 108 | command_header->type == IPC::CommandType::RequestWithContext) || | 104 | if (Session()->IsDomain() && |
| 109 | !incoming)) { | 105 | ((command_header->type == IPC::CommandType::Request || |
| 110 | // If this is an incoming message, only CommandType "Request" has a domain header | 106 | command_header->type == IPC::CommandType::RequestWithContext) || |
| 111 | // All outgoing domain messages have the domain header, if only incoming has it | 107 | !incoming)) { |
| 112 | if (incoming || domain_message_header) { | 108 | // If this is an incoming message, only CommandType "Request" has a domain header |
| 113 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); | 109 | // All outgoing domain messages have the domain header, if only incoming has it |
| 114 | } else { | 110 | if (incoming || domain_message_header) { |
| 115 | if (Session()->IsDomain()) { | 111 | domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); |
| 116 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | 112 | } else { |
| 113 | if (Session()->IsDomain()) { | ||
| 114 | LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | ||
| 115 | } | ||
| 117 | } | 116 | } |
| 118 | } | 117 | } |
| 119 | } | ||
| 120 | 118 | ||
| 121 | data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); | 119 | data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); |
| 122 | 120 | ||
| 123 | data_payload_offset = rp.GetCurrentOffset(); | 121 | data_payload_offset = rp.GetCurrentOffset(); |
| 124 | 122 | ||
| 125 | if (domain_message_header && domain_message_header->command == | 123 | if (domain_message_header && |
| 126 | IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { | 124 | domain_message_header->command == |
| 127 | // CloseVirtualHandle command does not have SFC* or any data | 125 | IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { |
| 128 | return; | 126 | // CloseVirtualHandle command does not have SFC* or any data |
| 129 | } | 127 | return; |
| 128 | } | ||
| 130 | 129 | ||
| 131 | if (incoming) { | 130 | if (incoming) { |
| 132 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); | 131 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); |
| 133 | } else { | 132 | } else { |
| 134 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); | 133 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); |
| 134 | } | ||
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | rp.SetCurrentOffset(buffer_c_offset); | 137 | rp.SetCurrentOffset(buffer_c_offset); |
| @@ -144,14 +144,14 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 144 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { | 144 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { |
| 145 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 145 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); |
| 146 | } else { | 146 | } else { |
| 147 | unsigned num_buf_c_descriptors = | 147 | u32 num_buf_c_descriptors = |
| 148 | static_cast<unsigned>(command_header->buf_c_descriptor_flags.Value()) - 2; | 148 | static_cast<u32>(command_header->buf_c_descriptor_flags.Value()) - 2; |
| 149 | 149 | ||
| 150 | // This is used to detect possible underflows, in case something is broken | 150 | // This is used to detect possible underflows, in case something is broken |
| 151 | // with the two ifs above and the flags value is == 0 || == 1. | 151 | // with the two ifs above and the flags value is == 0 || == 1. |
| 152 | ASSERT(num_buf_c_descriptors < 14); | 152 | ASSERT(num_buf_c_descriptors < 14); |
| 153 | 153 | ||
| 154 | for (unsigned i = 0; i < num_buf_c_descriptors; ++i) { | 154 | for (u32 i = 0; i < num_buf_c_descriptors; ++i) { |
| 155 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 155 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); |
| 156 | } | 156 | } |
| 157 | } | 157 | } |
| @@ -166,84 +166,55 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32 | |||
| 166 | ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, | 166 | ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, |
| 167 | u32_le* src_cmdbuf) { | 167 | u32_le* src_cmdbuf) { |
| 168 | ParseCommandBuffer(handle_table, src_cmdbuf, true); | 168 | ParseCommandBuffer(handle_table, src_cmdbuf, true); |
| 169 | if (command_header->type == IPC::CommandType::Close) { | 169 | |
| 170 | if (command_header->IsCloseCommand()) { | ||
| 170 | // Close does not populate the rest of the IPC header | 171 | // Close does not populate the rest of the IPC header |
| 171 | return RESULT_SUCCESS; | 172 | return RESULT_SUCCESS; |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | // The data_size already includes the payload header, the padding and the domain header. | 175 | std::copy_n(src_cmdbuf, IPC::COMMAND_BUFFER_LENGTH, cmd_buf.begin()); |
| 175 | std::size_t size = data_payload_offset + command_header->data_size - | 176 | |
| 176 | sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; | ||
| 177 | if (domain_message_header) | ||
| 178 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); | ||
| 179 | std::copy_n(src_cmdbuf, size, cmd_buf.begin()); | ||
| 180 | return RESULT_SUCCESS; | 177 | return RESULT_SUCCESS; |
| 181 | } | 178 | } |
| 182 | 179 | ||
| 183 | ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) { | 180 | ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) { |
| 181 | auto current_offset = handles_offset; | ||
| 184 | auto& owner_process = *requesting_thread.GetOwnerProcess(); | 182 | auto& owner_process = *requesting_thread.GetOwnerProcess(); |
| 185 | auto& handle_table = owner_process.GetHandleTable(); | 183 | auto& handle_table = owner_process.GetHandleTable(); |
| 186 | 184 | ||
| 187 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf; | 185 | for (auto& object : outgoing_copy_objects) { |
| 188 | memory.ReadBlock(owner_process, requesting_thread.GetTLSAddress(), dst_cmdbuf.data(), | 186 | Handle handle{}; |
| 189 | dst_cmdbuf.size() * sizeof(u32)); | 187 | if (object) { |
| 190 | 188 | R_TRY(handle_table.Add(&handle, object)); | |
| 191 | // The header was already built in the internal command buffer. Attempt to parse it to verify | ||
| 192 | // the integrity and then copy it over to the target command buffer. | ||
| 193 | ParseCommandBuffer(handle_table, cmd_buf.data(), false); | ||
| 194 | |||
| 195 | // The data_size already includes the payload header, the padding and the domain header. | ||
| 196 | std::size_t size = data_payload_offset + command_header->data_size - | ||
| 197 | sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4; | ||
| 198 | if (domain_message_header) | ||
| 199 | size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32); | ||
| 200 | |||
| 201 | std::copy_n(cmd_buf.begin(), size, dst_cmdbuf.data()); | ||
| 202 | |||
| 203 | if (command_header->enable_handle_descriptor) { | ||
| 204 | ASSERT_MSG(!move_objects.empty() || !copy_objects.empty(), | ||
| 205 | "Handle descriptor bit set but no handles to translate"); | ||
| 206 | // We write the translated handles at a specific offset in the command buffer, this space | ||
| 207 | // was already reserved when writing the header. | ||
| 208 | std::size_t current_offset = | ||
| 209 | (sizeof(IPC::CommandHeader) + sizeof(IPC::HandleDescriptorHeader)) / sizeof(u32); | ||
| 210 | ASSERT_MSG(!handle_descriptor_header->send_current_pid, "Sending PID is not implemented"); | ||
| 211 | |||
| 212 | ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy); | ||
| 213 | ASSERT(move_objects.size() == handle_descriptor_header->num_handles_to_move); | ||
| 214 | |||
| 215 | // We don't make a distinction between copy and move handles when translating since HLE | ||
| 216 | // services don't deal with handles directly. However, the guest applications might check | ||
| 217 | // for specific values in each of these descriptors. | ||
| 218 | for (auto& object : copy_objects) { | ||
| 219 | ASSERT(object != nullptr); | ||
| 220 | R_TRY(handle_table.Add(&dst_cmdbuf[current_offset++], object)); | ||
| 221 | } | 189 | } |
| 190 | cmd_buf[current_offset++] = handle; | ||
| 191 | } | ||
| 192 | for (auto& object : outgoing_move_objects) { | ||
| 193 | Handle handle{}; | ||
| 194 | if (object) { | ||
| 195 | R_TRY(handle_table.Add(&handle, object)); | ||
| 222 | 196 | ||
| 223 | for (auto& object : move_objects) { | 197 | // Close our reference to the object, as it is being moved to the caller. |
| 224 | ASSERT(object != nullptr); | 198 | object->Close(); |
| 225 | R_TRY(handle_table.Add(&dst_cmdbuf[current_offset++], object)); | ||
| 226 | } | 199 | } |
| 200 | cmd_buf[current_offset++] = handle; | ||
| 227 | } | 201 | } |
| 228 | 202 | ||
| 229 | // TODO(Subv): Translate the X/A/B/W buffers. | 203 | // Write the domain objects to the command buffer, these go after the raw untranslated data. |
| 230 | 204 | // TODO(Subv): This completely ignores C buffers. | |
| 231 | if (Session()->IsDomain() && domain_message_header) { | ||
| 232 | ASSERT(domain_message_header->num_objects == domain_objects.size()); | ||
| 233 | // Write the domain objects to the command buffer, these go after the raw untranslated data. | ||
| 234 | // TODO(Subv): This completely ignores C buffers. | ||
| 235 | std::size_t domain_offset = size - domain_message_header->num_objects; | ||
| 236 | 205 | ||
| 237 | for (const auto& object : domain_objects) { | 206 | if (Session()->IsDomain()) { |
| 238 | server_session->AppendDomainRequestHandler(object); | 207 | current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); |
| 239 | dst_cmdbuf[domain_offset++] = | 208 | for (const auto& object : outgoing_domain_objects) { |
| 209 | server_session->AppendDomainHandler(object); | ||
| 210 | cmd_buf[current_offset++] = | ||
| 240 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); | 211 | static_cast<u32_le>(server_session->NumDomainRequestHandlers()); |
| 241 | } | 212 | } |
| 242 | } | 213 | } |
| 243 | 214 | ||
| 244 | // Copy the translated command buffer back into the thread's command buffer area. | 215 | // Copy the translated command buffer back into the thread's command buffer area. |
| 245 | memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), dst_cmdbuf.data(), | 216 | memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(), |
| 246 | dst_cmdbuf.size() * sizeof(u32)); | 217 | write_size * sizeof(u32)); |
| 247 | 218 | ||
| 248 | return RESULT_SUCCESS; | 219 | return RESULT_SUCCESS; |
| 249 | } | 220 | } |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 21e384706..b47e363cc 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -11,7 +11,8 @@ | |||
| 11 | #include <string> | 11 | #include <string> |
| 12 | #include <type_traits> | 12 | #include <type_traits> |
| 13 | #include <vector> | 13 | #include <vector> |
| 14 | #include <boost/container/small_vector.hpp> | 14 | |
| 15 | #include "common/assert.h" | ||
| 15 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 16 | #include "common/concepts.h" | 17 | #include "common/concepts.h" |
| 17 | #include "common/swap.h" | 18 | #include "common/swap.h" |
| @@ -66,7 +67,8 @@ public: | |||
| 66 | * this request (ServerSession, Originator thread, Translated command buffer, etc). | 67 | * this request (ServerSession, Originator thread, Translated command buffer, etc). |
| 67 | * @returns ResultCode the result code of the translate operation. | 68 | * @returns ResultCode the result code of the translate operation. |
| 68 | */ | 69 | */ |
| 69 | virtual ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) = 0; | 70 | virtual ResultCode HandleSyncRequest(Kernel::KServerSession& session, |
| 71 | Kernel::HLERequestContext& context) = 0; | ||
| 70 | 72 | ||
| 71 | /** | 73 | /** |
| 72 | * Signals that a client has just connected to this HLE handler and keeps the | 74 | * Signals that a client has just connected to this HLE handler and keeps the |
| @@ -83,6 +85,69 @@ public: | |||
| 83 | void ClientDisconnected(KServerSession* session); | 85 | void ClientDisconnected(KServerSession* session); |
| 84 | }; | 86 | }; |
| 85 | 87 | ||
| 88 | using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>; | ||
| 89 | |||
| 90 | /** | ||
| 91 | * Manages the underlying HLE requests for a session, and whether (or not) the session should be | ||
| 92 | * treated as a domain. This is managed separately from server sessions, as this state is shared | ||
| 93 | * when objects are cloned. | ||
| 94 | */ | ||
| 95 | class SessionRequestManager final { | ||
| 96 | public: | ||
| 97 | SessionRequestManager() = default; | ||
| 98 | |||
| 99 | bool IsDomain() const { | ||
| 100 | return is_domain; | ||
| 101 | } | ||
| 102 | |||
| 103 | void ConvertToDomain() { | ||
| 104 | domain_handlers = {session_handler}; | ||
| 105 | is_domain = true; | ||
| 106 | } | ||
| 107 | |||
| 108 | std::size_t DomainHandlerCount() const { | ||
| 109 | return domain_handlers.size(); | ||
| 110 | } | ||
| 111 | |||
| 112 | bool HasSessionHandler() const { | ||
| 113 | return session_handler != nullptr; | ||
| 114 | } | ||
| 115 | |||
| 116 | SessionRequestHandler& SessionHandler() { | ||
| 117 | return *session_handler; | ||
| 118 | } | ||
| 119 | |||
| 120 | const SessionRequestHandler& SessionHandler() const { | ||
| 121 | return *session_handler; | ||
| 122 | } | ||
| 123 | |||
| 124 | void CloseDomainHandler(std::size_t index) { | ||
| 125 | if (index < DomainHandlerCount()) { | ||
| 126 | domain_handlers[index] = nullptr; | ||
| 127 | } else { | ||
| 128 | UNREACHABLE_MSG("Unexpected handler index {}", index); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | SessionRequestHandlerPtr DomainHandler(std::size_t index) const { | ||
| 133 | ASSERT_MSG(index < DomainHandlerCount(), "Unexpected handler index {}", index); | ||
| 134 | return domain_handlers.at(index); | ||
| 135 | } | ||
| 136 | |||
| 137 | void AppendDomainHandler(SessionRequestHandlerPtr&& handler) { | ||
| 138 | domain_handlers.emplace_back(std::move(handler)); | ||
| 139 | } | ||
| 140 | |||
| 141 | void SetSessionHandler(SessionRequestHandlerPtr&& handler) { | ||
| 142 | session_handler = std::move(handler); | ||
| 143 | } | ||
| 144 | |||
| 145 | private: | ||
| 146 | bool is_domain{}; | ||
| 147 | SessionRequestHandlerPtr session_handler; | ||
| 148 | std::vector<SessionRequestHandlerPtr> domain_handlers; | ||
| 149 | }; | ||
| 150 | |||
| 86 | /** | 151 | /** |
| 87 | * Class containing information about an in-flight IPC request being handled by an HLE service | 152 | * Class containing information about an in-flight IPC request being handled by an HLE service |
| 88 | * implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and | 153 | * implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and |
| @@ -128,15 +193,32 @@ public: | |||
| 128 | /// Writes data from this context back to the requesting process/thread. | 193 | /// Writes data from this context back to the requesting process/thread. |
| 129 | ResultCode WriteToOutgoingCommandBuffer(KThread& requesting_thread); | 194 | ResultCode WriteToOutgoingCommandBuffer(KThread& requesting_thread); |
| 130 | 195 | ||
| 131 | u32_le GetCommand() const { | 196 | u32_le GetHipcCommand() const { |
| 132 | return command; | 197 | return command; |
| 133 | } | 198 | } |
| 134 | 199 | ||
| 200 | u32_le GetTipcCommand() const { | ||
| 201 | return static_cast<u32_le>(command_header->type.Value()) - | ||
| 202 | static_cast<u32_le>(IPC::CommandType::TIPC_CommandRegion); | ||
| 203 | } | ||
| 204 | |||
| 205 | u32_le GetCommand() const { | ||
| 206 | return command_header->IsTipc() ? GetTipcCommand() : GetHipcCommand(); | ||
| 207 | } | ||
| 208 | |||
| 209 | bool IsTipc() const { | ||
| 210 | return command_header->IsTipc(); | ||
| 211 | } | ||
| 212 | |||
| 135 | IPC::CommandType GetCommandType() const { | 213 | IPC::CommandType GetCommandType() const { |
| 136 | return command_header->type; | 214 | return command_header->type; |
| 137 | } | 215 | } |
| 138 | 216 | ||
| 139 | unsigned GetDataPayloadOffset() const { | 217 | u64 GetPID() const { |
| 218 | return pid; | ||
| 219 | } | ||
| 220 | |||
| 221 | u32 GetDataPayloadOffset() const { | ||
| 140 | return data_payload_offset; | 222 | return data_payload_offset; |
| 141 | } | 223 | } |
| 142 | 224 | ||
| @@ -206,53 +288,32 @@ public: | |||
| 206 | bool CanWriteBuffer(std::size_t buffer_index = 0) const; | 288 | bool CanWriteBuffer(std::size_t buffer_index = 0) const; |
| 207 | 289 | ||
| 208 | Handle GetCopyHandle(std::size_t index) const { | 290 | Handle GetCopyHandle(std::size_t index) const { |
| 209 | return copy_handles.at(index); | 291 | return incoming_copy_handles.at(index); |
| 210 | } | 292 | } |
| 211 | 293 | ||
| 212 | Handle GetMoveHandle(std::size_t index) const { | 294 | Handle GetMoveHandle(std::size_t index) const { |
| 213 | return move_handles.at(index); | 295 | return incoming_move_handles.at(index); |
| 214 | } | 296 | } |
| 215 | 297 | ||
| 216 | void AddMoveObject(KAutoObject* object) { | 298 | void AddMoveObject(KAutoObject* object) { |
| 217 | move_objects.emplace_back(object); | 299 | outgoing_move_objects.emplace_back(object); |
| 218 | } | 300 | } |
| 219 | 301 | ||
| 220 | void AddCopyObject(KAutoObject* object) { | 302 | void AddCopyObject(KAutoObject* object) { |
| 221 | copy_objects.emplace_back(object); | 303 | outgoing_copy_objects.emplace_back(object); |
| 222 | } | 304 | } |
| 223 | 305 | ||
| 224 | void AddDomainObject(std::shared_ptr<SessionRequestHandler> object) { | 306 | void AddDomainObject(SessionRequestHandlerPtr object) { |
| 225 | domain_objects.emplace_back(std::move(object)); | 307 | outgoing_domain_objects.emplace_back(std::move(object)); |
| 226 | } | 308 | } |
| 227 | 309 | ||
| 228 | template <typename T> | 310 | template <typename T> |
| 229 | std::shared_ptr<T> GetDomainRequestHandler(std::size_t index) const { | 311 | std::shared_ptr<T> GetDomainHandler(std::size_t index) const { |
| 230 | return std::static_pointer_cast<T>(domain_request_handlers.at(index)); | 312 | return std::static_pointer_cast<T>(manager->DomainHandler(index)); |
| 231 | } | ||
| 232 | |||
| 233 | void SetDomainRequestHandlers( | ||
| 234 | const std::vector<std::shared_ptr<SessionRequestHandler>>& handlers) { | ||
| 235 | domain_request_handlers = handlers; | ||
| 236 | } | ||
| 237 | |||
| 238 | /// Clears the list of objects so that no lingering objects are written accidentally to the | ||
| 239 | /// response buffer. | ||
| 240 | void ClearIncomingObjects() { | ||
| 241 | move_objects.clear(); | ||
| 242 | copy_objects.clear(); | ||
| 243 | domain_objects.clear(); | ||
| 244 | } | ||
| 245 | |||
| 246 | std::size_t NumMoveObjects() const { | ||
| 247 | return move_objects.size(); | ||
| 248 | } | 313 | } |
| 249 | 314 | ||
| 250 | std::size_t NumCopyObjects() const { | 315 | void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) { |
| 251 | return copy_objects.size(); | 316 | manager = std::move(manager_); |
| 252 | } | ||
| 253 | |||
| 254 | std::size_t NumDomainObjects() const { | ||
| 255 | return domain_objects.size(); | ||
| 256 | } | 317 | } |
| 257 | 318 | ||
| 258 | std::string Description() const; | 319 | std::string Description() const; |
| @@ -274,12 +335,12 @@ private: | |||
| 274 | Kernel::KServerSession* server_session{}; | 335 | Kernel::KServerSession* server_session{}; |
| 275 | KThread* thread; | 336 | KThread* thread; |
| 276 | 337 | ||
| 277 | // TODO(yuriks): Check common usage of this and optimize size accordingly | 338 | std::vector<Handle> incoming_move_handles; |
| 278 | boost::container::small_vector<Handle, 8> move_handles; | 339 | std::vector<Handle> incoming_copy_handles; |
| 279 | boost::container::small_vector<Handle, 8> copy_handles; | 340 | |
| 280 | boost::container::small_vector<KAutoObject*, 8> move_objects; | 341 | std::vector<KAutoObject*> outgoing_move_objects; |
| 281 | boost::container::small_vector<KAutoObject*, 8> copy_objects; | 342 | std::vector<KAutoObject*> outgoing_copy_objects; |
| 282 | boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects; | 343 | std::vector<SessionRequestHandlerPtr> outgoing_domain_objects; |
| 283 | 344 | ||
| 284 | std::optional<IPC::CommandHeader> command_header; | 345 | std::optional<IPC::CommandHeader> command_header; |
| 285 | std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; | 346 | std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header; |
| @@ -291,11 +352,14 @@ private: | |||
| 291 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; | 352 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; |
| 292 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; | 353 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; |
| 293 | 354 | ||
| 294 | unsigned data_payload_offset{}; | ||
| 295 | unsigned buffer_c_offset{}; | ||
| 296 | u32_le command{}; | 355 | u32_le command{}; |
| 356 | u64 pid{}; | ||
| 357 | u32 write_size{}; | ||
| 358 | u32 data_payload_offset{}; | ||
| 359 | u32 handles_offset{}; | ||
| 360 | u32 domain_offset{}; | ||
| 297 | 361 | ||
| 298 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; | 362 | std::shared_ptr<SessionRequestManager> manager; |
| 299 | bool is_thread_waiting{}; | 363 | bool is_thread_waiting{}; |
| 300 | 364 | ||
| 301 | KernelCore& kernel; | 365 | KernelCore& kernel; |
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index 69ae405e6..10edede17 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp | |||
| @@ -70,14 +70,22 @@ constexpr size_t SlabCountExtraKThread = 160; | |||
| 70 | template <typename T> | 70 | template <typename T> |
| 71 | VAddr InitializeSlabHeap(Core::System& system, KMemoryLayout& memory_layout, VAddr address, | 71 | VAddr InitializeSlabHeap(Core::System& system, KMemoryLayout& memory_layout, VAddr address, |
| 72 | size_t num_objects) { | 72 | size_t num_objects) { |
| 73 | // TODO(bunnei): This is just a place holder. We should initialize the appropriate KSlabHeap for | ||
| 74 | // kernel object type T with the backing kernel memory pointer once we emulate kernel memory. | ||
| 75 | |||
| 73 | const size_t size = Common::AlignUp(sizeof(T) * num_objects, alignof(void*)); | 76 | const size_t size = Common::AlignUp(sizeof(T) * num_objects, alignof(void*)); |
| 74 | VAddr start = Common::AlignUp(address, alignof(T)); | 77 | VAddr start = Common::AlignUp(address, alignof(T)); |
| 75 | 78 | ||
| 79 | // This is intentionally empty. Once KSlabHeap is fully implemented, we can replace this with | ||
| 80 | // the pointer to emulated memory to pass along. Until then, KSlabHeap will just allocate/free | ||
| 81 | // host memory. | ||
| 82 | void* backing_kernel_memory{}; | ||
| 83 | |||
| 76 | if (size > 0) { | 84 | if (size > 0) { |
| 77 | const KMemoryRegion* region = memory_layout.FindVirtual(start + size - 1); | 85 | const KMemoryRegion* region = memory_layout.FindVirtual(start + size - 1); |
| 78 | ASSERT(region != nullptr); | 86 | ASSERT(region != nullptr); |
| 79 | ASSERT(region->IsDerivedFrom(KMemoryRegionType_KernelSlab)); | 87 | ASSERT(region->IsDerivedFrom(KMemoryRegionType_KernelSlab)); |
| 80 | T::InitializeSlabHeap(system.Kernel(), system.Memory().GetKernelBuffer(start, size), size); | 88 | T::InitializeSlabHeap(system.Kernel(), backing_kernel_memory, size); |
| 81 | } | 89 | } |
| 82 | 90 | ||
| 83 | return start + size; | 91 | return start + size; |
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index e14b915b9..4a12dee10 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp | |||
| @@ -91,7 +91,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) { | |||
| 91 | // Create a new session. | 91 | // Create a new session. |
| 92 | KSession* session = KSession::Create(kernel); | 92 | KSession* session = KSession::Create(kernel); |
| 93 | if (session == nullptr) { | 93 | if (session == nullptr) { |
| 94 | /* Decrement the session count. */ | 94 | // Decrement the session count. |
| 95 | const auto prev = num_sessions--; | 95 | const auto prev = num_sessions--; |
| 96 | if (prev == max_sessions) { | 96 | if (prev == max_sessions) { |
| 97 | this->NotifyAvailable(); | 97 | this->NotifyAvailable(); |
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index d00ce3ddd..8501156e8 100644 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h | |||
| @@ -31,6 +31,9 @@ public: | |||
| 31 | const KPort* GetParent() const { | 31 | const KPort* GetParent() const { |
| 32 | return parent; | 32 | return parent; |
| 33 | } | 33 | } |
| 34 | KPort* GetParent() { | ||
| 35 | return parent; | ||
| 36 | } | ||
| 34 | 37 | ||
| 35 | s32 GetNumSessions() const { | 38 | s32 GetNumSessions() const { |
| 36 | return num_sessions; | 39 | return num_sessions; |
diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index 362d0db28..ca2e539a7 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h | |||
| @@ -18,7 +18,8 @@ class KernelCore; | |||
| 18 | 18 | ||
| 19 | class KLightConditionVariable { | 19 | class KLightConditionVariable { |
| 20 | public: | 20 | public: |
| 21 | explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {} | 21 | explicit KLightConditionVariable(KernelCore& kernel_) |
| 22 | : thread_queue(kernel_), kernel(kernel_) {} | ||
| 22 | 23 | ||
| 23 | void Wait(KLightLock* lock, s64 timeout = -1) { | 24 | void Wait(KLightLock* lock, s64 timeout = -1) { |
| 24 | WaitImpl(lock, timeout); | 25 | WaitImpl(lock, timeout); |
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h index 540e518cd..6adfe1e34 100644 --- a/src/core/hle/kernel/k_linked_list.h +++ b/src/core/hle/kernel/k_linked_list.h | |||
| @@ -201,10 +201,10 @@ public: | |||
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | iterator insert(const_iterator pos, reference ref) { | 203 | iterator insert(const_iterator pos, reference ref) { |
| 204 | KLinkedListNode* node = KLinkedListNode::Allocate(kernel); | 204 | KLinkedListNode* new_node = KLinkedListNode::Allocate(kernel); |
| 205 | ASSERT(node != nullptr); | 205 | ASSERT(new_node != nullptr); |
| 206 | node->Initialize(std::addressof(ref)); | 206 | new_node->Initialize(std::addressof(ref)); |
| 207 | return iterator(BaseList::insert(pos.m_base_it, *node)); | 207 | return iterator(BaseList::insert(pos.m_base_it, *new_node)); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | void push_back(reference ref) { | 210 | void push_back(reference ref) { |
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp index 44bfeb0d5..fc7033564 100644 --- a/src/core/hle/kernel/k_memory_block_manager.cpp +++ b/src/core/hle/kernel/k_memory_block_manager.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | namespace Kernel { | 8 | namespace Kernel { |
| 9 | 9 | ||
| 10 | KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr) | 10 | KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr_, VAddr end_addr_) |
| 11 | : start_addr{start_addr}, end_addr{end_addr} { | 11 | : start_addr{start_addr_}, end_addr{end_addr_} { |
| 12 | const u64 num_pages{(end_addr - start_addr) / PageSize}; | 12 | const u64 num_pages{(end_addr - start_addr) / PageSize}; |
| 13 | memory_block_tree.emplace_back(start_addr, num_pages, KMemoryState::Free, | 13 | memory_block_tree.emplace_back(start_addr, num_pages, KMemoryState::Free, |
| 14 | KMemoryPermission::None, KMemoryAttribute::None); | 14 | KMemoryPermission::None, KMemoryAttribute::None); |
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h index e11cc70c8..d222da919 100644 --- a/src/core/hle/kernel/k_memory_block_manager.h +++ b/src/core/hle/kernel/k_memory_block_manager.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | using const_iterator = MemoryBlockTree::const_iterator; | 19 | using const_iterator = MemoryBlockTree::const_iterator; |
| 20 | 20 | ||
| 21 | public: | 21 | public: |
| 22 | KMemoryBlockManager(VAddr start_addr, VAddr end_addr); | 22 | KMemoryBlockManager(VAddr start_addr_, VAddr end_addr_); |
| 23 | 23 | ||
| 24 | iterator end() { | 24 | iterator end() { |
| 25 | return memory_block_tree.end(); | 25 | return memory_block_tree.end(); |
diff --git a/src/core/hle/kernel/k_page_linked_list.h b/src/core/hle/kernel/k_page_linked_list.h index 64024d01f..dfdac5321 100644 --- a/src/core/hle/kernel/k_page_linked_list.h +++ b/src/core/hle/kernel/k_page_linked_list.h | |||
| @@ -17,7 +17,7 @@ class KPageLinkedList final { | |||
| 17 | public: | 17 | public: |
| 18 | class Node final { | 18 | class Node final { |
| 19 | public: | 19 | public: |
| 20 | constexpr Node(u64 addr, std::size_t num_pages) : addr{addr}, num_pages{num_pages} {} | 20 | constexpr Node(u64 addr_, std::size_t num_pages_) : addr{addr_}, num_pages{num_pages_} {} |
| 21 | 21 | ||
| 22 | constexpr u64 GetAddress() const { | 22 | constexpr u64 GetAddress() const { |
| 23 | return addr; | 23 | return addr; |
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index d4ce98ee3..27dbf0ebc 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -58,7 +58,7 @@ constexpr std::size_t GetSizeInRange(const KMemoryInfo& info, VAddr start, VAddr | |||
| 58 | 58 | ||
| 59 | } // namespace | 59 | } // namespace |
| 60 | 60 | ||
| 61 | KPageTable::KPageTable(Core::System& system) : system{system} {} | 61 | KPageTable::KPageTable(Core::System& system_) : system{system_} {} |
| 62 | 62 | ||
| 63 | ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, | 63 | ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, |
| 64 | bool enable_aslr, VAddr code_addr, | 64 | bool enable_aslr, VAddr code_addr, |
| @@ -906,8 +906,8 @@ ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { | |||
| 906 | 906 | ||
| 907 | block_manager->UpdateLock( | 907 | block_manager->UpdateLock( |
| 908 | addr, size / PageSize, | 908 | addr, size / PageSize, |
| 909 | [](KMemoryBlockManager::iterator block, KMemoryPermission perm) { | 909 | [](KMemoryBlockManager::iterator block, KMemoryPermission permission) { |
| 910 | block->ShareToDevice(perm); | 910 | block->ShareToDevice(permission); |
| 911 | }, | 911 | }, |
| 912 | perm); | 912 | perm); |
| 913 | 913 | ||
| @@ -929,8 +929,8 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) | |||
| 929 | 929 | ||
| 930 | block_manager->UpdateLock( | 930 | block_manager->UpdateLock( |
| 931 | addr, size / PageSize, | 931 | addr, size / PageSize, |
| 932 | [](KMemoryBlockManager::iterator block, KMemoryPermission perm) { | 932 | [](KMemoryBlockManager::iterator block, KMemoryPermission permission) { |
| 933 | block->UnshareToDevice(perm); | 933 | block->UnshareToDevice(permission); |
| 934 | }, | 934 | }, |
| 935 | perm); | 935 | perm); |
| 936 | 936 | ||
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 8c2cc03eb..770c4841c 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -24,7 +24,7 @@ class KMemoryBlockManager; | |||
| 24 | 24 | ||
| 25 | class KPageTable final : NonCopyable { | 25 | class KPageTable final : NonCopyable { |
| 26 | public: | 26 | public: |
| 27 | explicit KPageTable(Core::System& system); | 27 | explicit KPageTable(Core::System& system_); |
| 28 | 28 | ||
| 29 | ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, | 29 | ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, |
| 30 | VAddr code_addr, std::size_t code_size, | 30 | VAddr code_addr, std::size_t code_size, |
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp index feb2bb11f..223c0b205 100644 --- a/src/core/hle/kernel/k_port.cpp +++ b/src/core/hle/kernel/k_port.cpp | |||
| @@ -56,11 +56,8 @@ ResultCode KPort::EnqueueSession(KServerSession* session) { | |||
| 56 | 56 | ||
| 57 | R_UNLESS(state == State::Normal, ResultPortClosed); | 57 | R_UNLESS(state == State::Normal, ResultPortClosed); |
| 58 | 58 | ||
| 59 | if (server.HasHLEHandler()) { | 59 | server.EnqueueSession(session); |
| 60 | server.GetHLEHandler()->ClientConnected(session); | 60 | server.GetSessionRequestHandler()->ClientConnected(server.AcceptSession()); |
| 61 | } else { | ||
| 62 | server.EnqueueSession(session); | ||
| 63 | } | ||
| 64 | 61 | ||
| 65 | return RESULT_SUCCESS; | 62 | return RESULT_SUCCESS; |
| 66 | } | 63 | } |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index e256e9415..2f82fbcd6 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -607,7 +607,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { | |||
| 607 | } | 607 | } |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core_id(core_id) { | 610 | KScheduler::KScheduler(Core::System& system_, s32 core_id_) : system{system_}, core_id{core_id_} { |
| 611 | switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this); | 611 | switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this); |
| 612 | state.needs_scheduling.store(true); | 612 | state.needs_scheduling.store(true); |
| 613 | state.interrupt_task_thread_runnable = false; | 613 | state.interrupt_task_thread_runnable = false; |
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index 13a2414e6..12cfae919 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h | |||
| @@ -30,7 +30,7 @@ class KThread; | |||
| 30 | 30 | ||
| 31 | class KScheduler final { | 31 | class KScheduler final { |
| 32 | public: | 32 | public: |
| 33 | explicit KScheduler(Core::System& system, s32 core_id); | 33 | explicit KScheduler(Core::System& system_, s32 core_id_); |
| 34 | ~KScheduler(); | 34 | ~KScheduler(); |
| 35 | 35 | ||
| 36 | /// Reschedules to the next available thread (call after current thread is suspended) | 36 | /// Reschedules to the next available thread (call after current thread is suspended) |
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h index b5d405744..a86af56dd 100644 --- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h +++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h | |||
| @@ -17,8 +17,8 @@ namespace Kernel { | |||
| 17 | 17 | ||
| 18 | class [[nodiscard]] KScopedSchedulerLockAndSleep { | 18 | class [[nodiscard]] KScopedSchedulerLockAndSleep { |
| 19 | public: | 19 | public: |
| 20 | explicit KScopedSchedulerLockAndSleep(KernelCore & kernel, KThread * t, s64 timeout) | 20 | explicit KScopedSchedulerLockAndSleep(KernelCore & kernel_, KThread * t, s64 timeout) |
| 21 | : kernel(kernel), thread(t), timeout_tick(timeout) { | 21 | : kernel(kernel_), thread(t), timeout_tick(timeout) { |
| 22 | // Lock the scheduler. | 22 | // Lock the scheduler. |
| 23 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); | 23 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); |
| 24 | } | 24 | } |
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h index e76792253..d1a757ec3 100644 --- a/src/core/hle/kernel/k_server_port.h +++ b/src/core/hle/kernel/k_server_port.h | |||
| @@ -32,26 +32,24 @@ public: | |||
| 32 | explicit KServerPort(KernelCore& kernel_); | 32 | explicit KServerPort(KernelCore& kernel_); |
| 33 | virtual ~KServerPort() override; | 33 | virtual ~KServerPort() override; |
| 34 | 34 | ||
| 35 | using HLEHandler = std::shared_ptr<SessionRequestHandler>; | ||
| 36 | |||
| 37 | void Initialize(KPort* parent_, std::string&& name_); | 35 | void Initialize(KPort* parent_, std::string&& name_); |
| 38 | 36 | ||
| 39 | /// Whether or not this server port has an HLE handler available. | 37 | /// Whether or not this server port has an HLE handler available. |
| 40 | bool HasHLEHandler() const { | 38 | bool HasSessionRequestHandler() const { |
| 41 | return hle_handler != nullptr; | 39 | return session_handler != nullptr; |
| 42 | } | 40 | } |
| 43 | 41 | ||
| 44 | /// Gets the HLE handler for this port. | 42 | /// Gets the HLE handler for this port. |
| 45 | HLEHandler GetHLEHandler() const { | 43 | SessionRequestHandlerPtr GetSessionRequestHandler() const { |
| 46 | return hle_handler; | 44 | return session_handler; |
| 47 | } | 45 | } |
| 48 | 46 | ||
| 49 | /** | 47 | /** |
| 50 | * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port | 48 | * Sets the HLE handler template for the port. ServerSessions crated by connecting to this port |
| 51 | * will inherit a reference to this handler. | 49 | * will inherit a reference to this handler. |
| 52 | */ | 50 | */ |
| 53 | void SetHleHandler(HLEHandler hle_handler_) { | 51 | void SetSessionHandler(SessionRequestHandlerPtr&& handler) { |
| 54 | hle_handler = std::move(hle_handler_); | 52 | session_handler = std::move(handler); |
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | void EnqueueSession(KServerSession* pending_session); | 55 | void EnqueueSession(KServerSession* pending_session); |
| @@ -73,7 +71,7 @@ private: | |||
| 73 | 71 | ||
| 74 | private: | 72 | private: |
| 75 | SessionList session_list; | 73 | SessionList session_list; |
| 76 | HLEHandler hle_handler; | 74 | SessionRequestHandlerPtr session_handler; |
| 77 | KPort* parent{}; | 75 | KPort* parent{}; |
| 78 | }; | 76 | }; |
| 79 | 77 | ||
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index b28cc2499..457fdfd60 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -23,7 +23,8 @@ | |||
| 23 | 23 | ||
| 24 | namespace Kernel { | 24 | namespace Kernel { |
| 25 | 25 | ||
| 26 | KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | 26 | KServerSession::KServerSession(KernelCore& kernel_) |
| 27 | : KSynchronizationObject{kernel_}, manager{std::make_shared<SessionRequestManager>()} {} | ||
| 27 | 28 | ||
| 28 | KServerSession::~KServerSession() { | 29 | KServerSession::~KServerSession() { |
| 29 | kernel.ReleaseServiceThread(service_thread); | 30 | kernel.ReleaseServiceThread(service_thread); |
| @@ -43,14 +44,8 @@ void KServerSession::Destroy() { | |||
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | void KServerSession::OnClientClosed() { | 46 | void KServerSession::OnClientClosed() { |
| 46 | // We keep a shared pointer to the hle handler to keep it alive throughout | 47 | if (manager->HasSessionHandler()) { |
| 47 | // the call to ClientDisconnected, as ClientDisconnected invalidates the | 48 | manager->SessionHandler().ClientDisconnected(this); |
| 48 | // hle_handler member itself during the course of the function executing. | ||
| 49 | std::shared_ptr<SessionRequestHandler> handler = hle_handler; | ||
| 50 | if (handler) { | ||
| 51 | // Note that after this returns, this server session's hle_handler is | ||
| 52 | // invalidated (set to null). | ||
| 53 | handler->ClientDisconnected(this); | ||
| 54 | } | 49 | } |
| 55 | } | 50 | } |
| 56 | 51 | ||
| @@ -66,12 +61,12 @@ bool KServerSession::IsSignaled() const { | |||
| 66 | return false; | 61 | return false; |
| 67 | } | 62 | } |
| 68 | 63 | ||
| 69 | void KServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) { | 64 | void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) { |
| 70 | domain_request_handlers.push_back(std::move(handler)); | 65 | manager->AppendDomainHandler(std::move(handler)); |
| 71 | } | 66 | } |
| 72 | 67 | ||
| 73 | std::size_t KServerSession::NumDomainRequestHandlers() const { | 68 | std::size_t KServerSession::NumDomainRequestHandlers() const { |
| 74 | return domain_request_handlers.size(); | 69 | return manager->DomainHandlerCount(); |
| 75 | } | 70 | } |
| 76 | 71 | ||
| 77 | ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { | 72 | ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { |
| @@ -80,14 +75,14 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co | |||
| 80 | } | 75 | } |
| 81 | 76 | ||
| 82 | // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs | 77 | // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs |
| 83 | context.SetDomainRequestHandlers(domain_request_handlers); | 78 | context.SetSessionRequestManager(manager); |
| 84 | 79 | ||
| 85 | // If there is a DomainMessageHeader, then this is CommandType "Request" | 80 | // If there is a DomainMessageHeader, then this is CommandType "Request" |
| 86 | const auto& domain_message_header = context.GetDomainMessageHeader(); | 81 | const auto& domain_message_header = context.GetDomainMessageHeader(); |
| 87 | const u32 object_id{domain_message_header.object_id}; | 82 | const u32 object_id{domain_message_header.object_id}; |
| 88 | switch (domain_message_header.command) { | 83 | switch (domain_message_header.command) { |
| 89 | case IPC::DomainMessageHeader::CommandType::SendMessage: | 84 | case IPC::DomainMessageHeader::CommandType::SendMessage: |
| 90 | if (object_id > domain_request_handlers.size()) { | 85 | if (object_id > manager->DomainHandlerCount()) { |
| 91 | LOG_CRITICAL(IPC, | 86 | LOG_CRITICAL(IPC, |
| 92 | "object_id {} is too big! This probably means a recent service call " | 87 | "object_id {} is too big! This probably means a recent service call " |
| 93 | "to {} needed to return a new interface!", | 88 | "to {} needed to return a new interface!", |
| @@ -95,12 +90,12 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co | |||
| 95 | UNREACHABLE(); | 90 | UNREACHABLE(); |
| 96 | return RESULT_SUCCESS; // Ignore error if asserts are off | 91 | return RESULT_SUCCESS; // Ignore error if asserts are off |
| 97 | } | 92 | } |
| 98 | return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); | 93 | return manager->DomainHandler(object_id - 1)->HandleSyncRequest(*this, context); |
| 99 | 94 | ||
| 100 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | 95 | case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { |
| 101 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); | 96 | LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); |
| 102 | 97 | ||
| 103 | domain_request_handlers[object_id - 1] = nullptr; | 98 | manager->CloseDomainHandler(object_id - 1); |
| 104 | 99 | ||
| 105 | IPC::ResponseBuilder rb{context, 2}; | 100 | IPC::ResponseBuilder rb{context, 2}; |
| 106 | rb.Push(RESULT_SUCCESS); | 101 | rb.Push(RESULT_SUCCESS); |
| @@ -133,14 +128,14 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { | |||
| 133 | if (IsDomain() && context.HasDomainMessageHeader()) { | 128 | if (IsDomain() && context.HasDomainMessageHeader()) { |
| 134 | result = HandleDomainSyncRequest(context); | 129 | result = HandleDomainSyncRequest(context); |
| 135 | // If there is no domain header, the regular session handler is used | 130 | // If there is no domain header, the regular session handler is used |
| 136 | } else if (hle_handler != nullptr) { | 131 | } else if (manager->HasSessionHandler()) { |
| 137 | // If this ServerSession has an associated HLE handler, forward the request to it. | 132 | // If this ServerSession has an associated HLE handler, forward the request to it. |
| 138 | result = hle_handler->HandleSyncRequest(context); | 133 | result = manager->SessionHandler().HandleSyncRequest(*this, context); |
| 139 | } | 134 | } |
| 140 | 135 | ||
| 141 | if (convert_to_domain) { | 136 | if (convert_to_domain) { |
| 142 | ASSERT_MSG(IsSession(), "ServerSession is already a domain instance."); | 137 | ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance."); |
| 143 | domain_request_handlers = {hle_handler}; | 138 | manager->ConvertToDomain(); |
| 144 | convert_to_domain = false; | 139 | convert_to_domain = false; |
| 145 | } | 140 | } |
| 146 | 141 | ||
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index 597d76d38..dd4de2904 100644 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <boost/intrusive/list.hpp> | 12 | #include <boost/intrusive/list.hpp> |
| 13 | 13 | ||
| 14 | #include "common/threadsafe_queue.h" | 14 | #include "common/threadsafe_queue.h" |
| 15 | #include "core/hle/kernel/hle_ipc.h" | ||
| 15 | #include "core/hle/kernel/k_synchronization_object.h" | 16 | #include "core/hle/kernel/k_synchronization_object.h" |
| 16 | #include "core/hle/kernel/service_thread.h" | 17 | #include "core/hle/kernel/service_thread.h" |
| 17 | #include "core/hle/result.h" | 18 | #include "core/hle/result.h" |
| @@ -64,8 +65,8 @@ public: | |||
| 64 | * instead of the regular IPC machinery. (The regular IPC machinery is currently not | 65 | * instead of the regular IPC machinery. (The regular IPC machinery is currently not |
| 65 | * implemented.) | 66 | * implemented.) |
| 66 | */ | 67 | */ |
| 67 | void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) { | 68 | void SetSessionHandler(SessionRequestHandlerPtr handler) { |
| 68 | hle_handler = std::move(hle_handler_); | 69 | manager->SetSessionHandler(std::move(handler)); |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | /** | 72 | /** |
| @@ -82,7 +83,7 @@ public: | |||
| 82 | 83 | ||
| 83 | /// Adds a new domain request handler to the collection of request handlers within | 84 | /// Adds a new domain request handler to the collection of request handlers within |
| 84 | /// this ServerSession instance. | 85 | /// this ServerSession instance. |
| 85 | void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler); | 86 | void AppendDomainHandler(SessionRequestHandlerPtr handler); |
| 86 | 87 | ||
| 87 | /// Retrieves the total number of domain request handlers that have been | 88 | /// Retrieves the total number of domain request handlers that have been |
| 88 | /// appended to this ServerSession instance. | 89 | /// appended to this ServerSession instance. |
| @@ -90,12 +91,7 @@ public: | |||
| 90 | 91 | ||
| 91 | /// Returns true if the session has been converted to a domain, otherwise False | 92 | /// Returns true if the session has been converted to a domain, otherwise False |
| 92 | bool IsDomain() const { | 93 | bool IsDomain() const { |
| 93 | return !IsSession(); | 94 | return manager->IsDomain(); |
| 94 | } | ||
| 95 | |||
| 96 | /// Returns true if this session has not been converted to a domain, otherwise false. | ||
| 97 | bool IsSession() const { | ||
| 98 | return domain_request_handlers.empty(); | ||
| 99 | } | 95 | } |
| 100 | 96 | ||
| 101 | /// Converts the session to a domain at the end of the current command | 97 | /// Converts the session to a domain at the end of the current command |
| @@ -103,6 +99,21 @@ public: | |||
| 103 | convert_to_domain = true; | 99 | convert_to_domain = true; |
| 104 | } | 100 | } |
| 105 | 101 | ||
| 102 | /// Gets the session request manager, which forwards requests to the underlying service | ||
| 103 | std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() { | ||
| 104 | return manager; | ||
| 105 | } | ||
| 106 | |||
| 107 | /// Gets the session request manager, which forwards requests to the underlying service | ||
| 108 | const std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() const { | ||
| 109 | return manager; | ||
| 110 | } | ||
| 111 | |||
| 112 | /// Sets the session request manager, which forwards requests to the underlying service | ||
| 113 | void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) { | ||
| 114 | manager = std::move(manager_); | ||
| 115 | } | ||
| 116 | |||
| 106 | private: | 117 | private: |
| 107 | /// Queues a sync request from the emulated application. | 118 | /// Queues a sync request from the emulated application. |
| 108 | ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); | 119 | ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); |
| @@ -114,11 +125,8 @@ private: | |||
| 114 | /// object handle. | 125 | /// object handle. |
| 115 | ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); | 126 | ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); |
| 116 | 127 | ||
| 117 | /// This session's HLE request handler (applicable when not a domain) | 128 | /// This session's HLE request handlers |
| 118 | std::shared_ptr<SessionRequestHandler> hle_handler; | 129 | std::shared_ptr<SessionRequestManager> manager; |
| 119 | |||
| 120 | /// This is the list of domain request handlers (after conversion to a domain) | ||
| 121 | std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; | ||
| 122 | 130 | ||
| 123 | /// When set to True, converts the session to a domain at the end of the command | 131 | /// When set to True, converts the session to a domain at the end of the command |
| 124 | bool convert_to_domain{}; | 132 | bool convert_to_domain{}; |
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index 16901e19c..a981fd1f6 100644 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h | |||
| @@ -66,6 +66,10 @@ public: | |||
| 66 | return port; | 66 | return port; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | KClientPort* GetParent() { | ||
| 70 | return port; | ||
| 71 | } | ||
| 72 | |||
| 69 | private: | 73 | private: |
| 70 | enum class State : u8 { | 74 | enum class State : u8 { |
| 71 | Invalid = 0, | 75 | Invalid = 0, |
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index 5ce9a1d7c..81d472a3e 100644 --- a/src/core/hle/kernel/k_slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h | |||
| @@ -4,165 +4,33 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | ||
| 8 | |||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/common_types.h" | ||
| 11 | |||
| 12 | namespace Kernel { | 7 | namespace Kernel { |
| 13 | 8 | ||
| 14 | namespace impl { | 9 | class KernelCore; |
| 15 | |||
| 16 | class KSlabHeapImpl final : NonCopyable { | ||
| 17 | public: | ||
| 18 | struct Node { | ||
| 19 | Node* next{}; | ||
| 20 | }; | ||
| 21 | |||
| 22 | constexpr KSlabHeapImpl() = default; | ||
| 23 | |||
| 24 | void Initialize(std::size_t size) { | ||
| 25 | ASSERT(head == nullptr); | ||
| 26 | obj_size = size; | ||
| 27 | } | ||
| 28 | |||
| 29 | constexpr std::size_t GetObjectSize() const { | ||
| 30 | return obj_size; | ||
| 31 | } | ||
| 32 | |||
| 33 | Node* GetHead() const { | ||
| 34 | return head; | ||
| 35 | } | ||
| 36 | |||
| 37 | void* Allocate() { | ||
| 38 | Node* ret = head.load(); | ||
| 39 | |||
| 40 | do { | ||
| 41 | if (ret == nullptr) { | ||
| 42 | break; | ||
| 43 | } | ||
| 44 | } while (!head.compare_exchange_weak(ret, ret->next)); | ||
| 45 | |||
| 46 | return ret; | ||
| 47 | } | ||
| 48 | |||
| 49 | void Free(void* obj) { | ||
| 50 | Node* node = static_cast<Node*>(obj); | ||
| 51 | |||
| 52 | Node* cur_head = head.load(); | ||
| 53 | do { | ||
| 54 | node->next = cur_head; | ||
| 55 | } while (!head.compare_exchange_weak(cur_head, node)); | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | std::atomic<Node*> head{}; | ||
| 60 | std::size_t obj_size{}; | ||
| 61 | }; | ||
| 62 | |||
| 63 | } // namespace impl | ||
| 64 | |||
| 65 | class KSlabHeapBase : NonCopyable { | ||
| 66 | public: | ||
| 67 | constexpr KSlabHeapBase() = default; | ||
| 68 | |||
| 69 | constexpr bool Contains(uintptr_t addr) const { | ||
| 70 | return start <= addr && addr < end; | ||
| 71 | } | ||
| 72 | |||
| 73 | constexpr std::size_t GetSlabHeapSize() const { | ||
| 74 | return (end - start) / GetObjectSize(); | ||
| 75 | } | ||
| 76 | |||
| 77 | constexpr std::size_t GetObjectSize() const { | ||
| 78 | return impl.GetObjectSize(); | ||
| 79 | } | ||
| 80 | 10 | ||
| 81 | constexpr uintptr_t GetSlabHeapAddress() const { | 11 | /// This is a placeholder class to manage slab heaps for kernel objects. For now, we just allocate |
| 82 | return start; | 12 | /// these with new/delete, but this can be re-implemented later to allocate these in emulated |
| 83 | } | 13 | /// memory. |
| 84 | |||
| 85 | std::size_t GetObjectIndexImpl(const void* obj) const { | ||
| 86 | return (reinterpret_cast<uintptr_t>(obj) - start) / GetObjectSize(); | ||
| 87 | } | ||
| 88 | |||
| 89 | std::size_t GetPeakIndex() const { | ||
| 90 | return GetObjectIndexImpl(reinterpret_cast<const void*>(peak)); | ||
| 91 | } | ||
| 92 | |||
| 93 | void* AllocateImpl() { | ||
| 94 | return impl.Allocate(); | ||
| 95 | } | ||
| 96 | |||
| 97 | void FreeImpl(void* obj) { | ||
| 98 | // Don't allow freeing an object that wasn't allocated from this heap | ||
| 99 | ASSERT(Contains(reinterpret_cast<uintptr_t>(obj))); | ||
| 100 | |||
| 101 | impl.Free(obj); | ||
| 102 | } | ||
| 103 | |||
| 104 | void InitializeImpl(std::size_t obj_size, void* memory, std::size_t memory_size) { | ||
| 105 | // Ensure we don't initialize a slab using null memory | ||
| 106 | ASSERT(memory != nullptr); | ||
| 107 | |||
| 108 | // Initialize the base allocator | ||
| 109 | impl.Initialize(obj_size); | ||
| 110 | |||
| 111 | // Set our tracking variables | ||
| 112 | const std::size_t num_obj = (memory_size / obj_size); | ||
| 113 | start = reinterpret_cast<uintptr_t>(memory); | ||
| 114 | end = start + num_obj * obj_size; | ||
| 115 | peak = start; | ||
| 116 | |||
| 117 | // Free the objects | ||
| 118 | u8* cur = reinterpret_cast<u8*>(end); | ||
| 119 | |||
| 120 | for (std::size_t i{}; i < num_obj; i++) { | ||
| 121 | cur -= obj_size; | ||
| 122 | impl.Free(cur); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | private: | ||
| 127 | using Impl = impl::KSlabHeapImpl; | ||
| 128 | |||
| 129 | Impl impl; | ||
| 130 | uintptr_t peak{}; | ||
| 131 | uintptr_t start{}; | ||
| 132 | uintptr_t end{}; | ||
| 133 | }; | ||
| 134 | 14 | ||
| 135 | template <typename T> | 15 | template <typename T> |
| 136 | class KSlabHeap final : public KSlabHeapBase { | 16 | class KSlabHeap final : NonCopyable { |
| 137 | public: | 17 | public: |
| 138 | constexpr KSlabHeap() : KSlabHeapBase() {} | 18 | KSlabHeap() = default; |
| 139 | 19 | ||
| 140 | void Initialize(void* memory, std::size_t memory_size) { | 20 | void Initialize([[maybe_unused]] void* memory, [[maybe_unused]] std::size_t memory_size) { |
| 141 | InitializeImpl(sizeof(T), memory, memory_size); | 21 | // Placeholder that should initialize the backing slab heap implementation. |
| 142 | } | 22 | } |
| 143 | 23 | ||
| 144 | T* Allocate() { | 24 | T* Allocate() { |
| 145 | T* obj = static_cast<T*>(AllocateImpl()); | 25 | return new T(); |
| 146 | if (obj != nullptr) { | ||
| 147 | new (obj) T(); | ||
| 148 | } | ||
| 149 | return obj; | ||
| 150 | } | 26 | } |
| 151 | 27 | ||
| 152 | T* AllocateWithKernel(KernelCore& kernel) { | 28 | T* AllocateWithKernel(KernelCore& kernel) { |
| 153 | T* obj = static_cast<T*>(AllocateImpl()); | 29 | return new T(kernel); |
| 154 | if (obj != nullptr) { | ||
| 155 | new (obj) T(kernel); | ||
| 156 | } | ||
| 157 | return obj; | ||
| 158 | } | 30 | } |
| 159 | 31 | ||
| 160 | void Free(T* obj) { | 32 | void Free(T* obj) { |
| 161 | FreeImpl(obj); | 33 | delete obj; |
| 162 | } | ||
| 163 | |||
| 164 | constexpr std::size_t GetObjectIndex(const T* obj) const { | ||
| 165 | return GetObjectIndexImpl(obj); | ||
| 166 | } | 34 | } |
| 167 | }; | 35 | }; |
| 168 | 36 | ||
diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index c52eba249..35d471dc5 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h | |||
| @@ -10,7 +10,7 @@ namespace Kernel { | |||
| 10 | 10 | ||
| 11 | class KThreadQueue { | 11 | class KThreadQueue { |
| 12 | public: | 12 | public: |
| 13 | explicit KThreadQueue(KernelCore& kernel) : kernel{kernel} {} | 13 | explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_} {} |
| 14 | 14 | ||
| 15 | bool IsEmpty() const { | 15 | bool IsEmpty() const { |
| 16 | return wait_list.empty(); | 16 | return wait_list.empty(); |
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index 838fd2b18..c2d0f1eaf 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h | |||
| @@ -52,7 +52,7 @@ public: | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | size_t GetSize() const { | 54 | size_t GetSize() const { |
| 55 | return is_initialized ? size * PageSize : 0; | 55 | return is_initialized ? size : 0; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | private: | 58 | private: |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index bd4e4d350..8b55df82e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include "core/hle/kernel/time_manager.h" | 44 | #include "core/hle/kernel/time_manager.h" |
| 45 | #include "core/hle/lock.h" | 45 | #include "core/hle/lock.h" |
| 46 | #include "core/hle/result.h" | 46 | #include "core/hle/result.h" |
| 47 | #include "core/hle/service/sm/sm.h" | ||
| 47 | #include "core/memory.h" | 48 | #include "core/memory.h" |
| 48 | 49 | ||
| 49 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); | 50 | MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); |
| @@ -656,6 +657,7 @@ struct KernelCore::Impl { | |||
| 656 | 657 | ||
| 657 | /// Map of named ports managed by the kernel, which can be retrieved using | 658 | /// Map of named ports managed by the kernel, which can be retrieved using |
| 658 | /// the ConnectToPort SVC. | 659 | /// the ConnectToPort SVC. |
| 660 | std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; | ||
| 659 | NamedPortTable named_ports; | 661 | NamedPortTable named_ports; |
| 660 | 662 | ||
| 661 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 663 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| @@ -844,18 +846,17 @@ void KernelCore::PrepareReschedule(std::size_t id) { | |||
| 844 | // TODO: Reimplement, this | 846 | // TODO: Reimplement, this |
| 845 | } | 847 | } |
| 846 | 848 | ||
| 847 | void KernelCore::AddNamedPort(std::string name, KClientPort* port) { | 849 | void KernelCore::RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory) { |
| 848 | port->Open(); | 850 | impl->service_interface_factory.emplace(std::move(name), factory); |
| 849 | impl->named_ports.emplace(std::move(name), port); | ||
| 850 | } | 851 | } |
| 851 | 852 | ||
| 852 | KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) { | 853 | KClientPort* KernelCore::CreateNamedServicePort(std::string name) { |
| 853 | return impl->named_ports.find(name); | 854 | auto search = impl->service_interface_factory.find(name); |
| 854 | } | 855 | if (search == impl->service_interface_factory.end()) { |
| 855 | 856 | UNIMPLEMENTED(); | |
| 856 | KernelCore::NamedPortTable::const_iterator KernelCore::FindNamedPort( | 857 | return {}; |
| 857 | const std::string& name) const { | 858 | } |
| 858 | return impl->named_ports.find(name); | 859 | return &search->second(impl->system.ServiceManager(), impl->system); |
| 859 | } | 860 | } |
| 860 | 861 | ||
| 861 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { | 862 | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 51aaccbc7..2d01e1ae0 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -27,6 +27,10 @@ class CoreTiming; | |||
| 27 | struct EventType; | 27 | struct EventType; |
| 28 | } // namespace Core::Timing | 28 | } // namespace Core::Timing |
| 29 | 29 | ||
| 30 | namespace Service::SM { | ||
| 31 | class ServiceManager; | ||
| 32 | } | ||
| 33 | |||
| 30 | namespace Kernel { | 34 | namespace Kernel { |
| 31 | 35 | ||
| 32 | class KClientPort; | 36 | class KClientPort; |
| @@ -51,6 +55,9 @@ class ServiceThread; | |||
| 51 | class Synchronization; | 55 | class Synchronization; |
| 52 | class TimeManager; | 56 | class TimeManager; |
| 53 | 57 | ||
| 58 | using ServiceInterfaceFactory = | ||
| 59 | std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>; | ||
| 60 | |||
| 54 | namespace Init { | 61 | namespace Init { |
| 55 | struct KSlabResourceCounts; | 62 | struct KSlabResourceCounts; |
| 56 | } | 63 | } |
| @@ -172,14 +179,11 @@ public: | |||
| 172 | 179 | ||
| 173 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | 180 | void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); |
| 174 | 181 | ||
| 175 | /// Adds a port to the named port table | 182 | /// Registers a named HLE service, passing a factory used to open a port to that service. |
| 176 | void AddNamedPort(std::string name, KClientPort* port); | 183 | void RegisterNamedService(std::string name, ServiceInterfaceFactory&& factory); |
| 177 | |||
| 178 | /// Finds a port within the named port table with the given name. | ||
| 179 | NamedPortTable::iterator FindNamedPort(const std::string& name); | ||
| 180 | 184 | ||
| 181 | /// Finds a port within the named port table with the given name. | 185 | /// Opens a port to a service previously registered with RegisterNamedService. |
| 182 | NamedPortTable::const_iterator FindNamedPort(const std::string& name) const; | 186 | KClientPort* CreateNamedServicePort(std::string name); |
| 183 | 187 | ||
| 184 | /// Determines whether or not the given port is a valid named port. | 188 | /// Determines whether or not the given port is a valid named port. |
| 185 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 189 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 7fea45f96..7f02d9471 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp | |||
| @@ -13,10 +13,10 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, | 16 | PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, |
| 17 | Kernel::KScheduler& scheduler, Core::CPUInterrupts& interrupts) | 17 | Core::CPUInterrupts& interrupts_) |
| 18 | : core_index{core_index}, system{system}, scheduler{scheduler}, | 18 | : core_index{core_index_}, system{system_}, scheduler{scheduler_}, |
| 19 | interrupts{interrupts}, guard{std::make_unique<Common::SpinLock>()} {} | 19 | interrupts{interrupts_}, guard{std::make_unique<Common::SpinLock>()} {} |
| 20 | 20 | ||
| 21 | PhysicalCore::~PhysicalCore() = default; | 21 | PhysicalCore::~PhysicalCore() = default; |
| 22 | 22 | ||
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index f2b0911aa..901f7e3b0 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h | |||
| @@ -28,8 +28,8 @@ namespace Kernel { | |||
| 28 | 28 | ||
| 29 | class PhysicalCore { | 29 | class PhysicalCore { |
| 30 | public: | 30 | public: |
| 31 | PhysicalCore(std::size_t core_index, Core::System& system, Kernel::KScheduler& scheduler, | 31 | PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, |
| 32 | Core::CPUInterrupts& interrupts); | 32 | Core::CPUInterrupts& interrupts_); |
| 33 | ~PhysicalCore(); | 33 | ~PhysicalCore(); |
| 34 | 34 | ||
| 35 | PhysicalCore(const PhysicalCore&) = delete; | 35 | PhysicalCore(const PhysicalCore&) = delete; |
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index 04be8a502..2ae80beca 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp | |||
| @@ -74,21 +74,17 @@ void ServiceThread::Impl::QueueSyncRequest(KSession& session, | |||
| 74 | { | 74 | { |
| 75 | std::unique_lock lock{queue_mutex}; | 75 | std::unique_lock lock{queue_mutex}; |
| 76 | 76 | ||
| 77 | auto* server_session{&session.GetServerSession()}; | ||
| 78 | |||
| 77 | // Open a reference to the session to ensure it is not closes while the service request | 79 | // Open a reference to the session to ensure it is not closes while the service request |
| 78 | // completes asynchronously. | 80 | // completes asynchronously. |
| 79 | session.Open(); | 81 | server_session->Open(); |
| 80 | 82 | ||
| 81 | requests.emplace([session_ptr{&session}, context{std::move(context)}]() { | 83 | requests.emplace([server_session, context{std::move(context)}]() { |
| 82 | // Close the reference. | 84 | // Close the reference. |
| 83 | SCOPE_EXIT({ session_ptr->Close(); }); | 85 | SCOPE_EXIT({ server_session->Close(); }); |
| 84 | |||
| 85 | // If the session has been closed, we are done. | ||
| 86 | if (session_ptr->IsServerClosed()) { | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | 86 | ||
| 90 | // Complete the service request. | 87 | // Complete the service request. |
| 91 | KScopedAutoObject server_session{&session_ptr->GetServerSession()}; | ||
| 92 | server_session->CompleteSyncRequest(*context); | 88 | server_session->CompleteSyncRequest(*context); |
| 93 | }); | 89 | }); |
| 94 | } | 90 | } |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 52011be9c..81e23f700 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -284,12 +284,11 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr po | |||
| 284 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 284 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 285 | 285 | ||
| 286 | // Find the client port. | 286 | // Find the client port. |
| 287 | const auto it = kernel.FindNamedPort(port_name); | 287 | auto port = kernel.CreateNamedServicePort(port_name); |
| 288 | if (!kernel.IsValidNamedPort(it)) { | 288 | if (!port) { |
| 289 | LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name); | 289 | LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name); |
| 290 | return ResultNotFound; | 290 | return ResultNotFound; |
| 291 | } | 291 | } |
| 292 | auto port = it->second; | ||
| 293 | 292 | ||
| 294 | // Reserve a handle for the port. | 293 | // Reserve a handle for the port. |
| 295 | // NOTE: Nintendo really does write directly to the output handle here. | 294 | // NOTE: Nintendo really does write directly to the output handle here. |
| @@ -820,10 +819,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle | |||
| 820 | return RESULT_SUCCESS; | 819 | return RESULT_SUCCESS; |
| 821 | } | 820 | } |
| 822 | 821 | ||
| 823 | Handle handle{}; | 822 | Handle resource_handle{}; |
| 824 | R_TRY(handle_table.Add(&handle, resource_limit)); | 823 | R_TRY(handle_table.Add(&resource_handle, resource_limit)); |
| 825 | 824 | ||
| 826 | *result = handle; | 825 | *result = resource_handle; |
| 827 | return RESULT_SUCCESS; | 826 | return RESULT_SUCCESS; |
| 828 | } | 827 | } |
| 829 | 828 | ||
diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 8feda7ad7..43968386f 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h | |||
| @@ -56,7 +56,7 @@ enum class ErrorModule : u32 { | |||
| 56 | PCIe = 120, | 56 | PCIe = 120, |
| 57 | Friends = 121, | 57 | Friends = 121, |
| 58 | BCAT = 122, | 58 | BCAT = 122, |
| 59 | SSL = 123, | 59 | SSLSrv = 123, |
| 60 | Account = 124, | 60 | Account = 124, |
| 61 | News = 125, | 61 | News = 125, |
| 62 | Mii = 126, | 62 | Mii = 126, |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 408e441dc..234173297 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -833,7 +833,7 @@ IStorageImpl::~IStorageImpl() = default; | |||
| 833 | 833 | ||
| 834 | class StorageDataImpl final : public IStorageImpl { | 834 | class StorageDataImpl final : public IStorageImpl { |
| 835 | public: | 835 | public: |
| 836 | explicit StorageDataImpl(std::vector<u8>&& buffer) : buffer{std::move(buffer)} {} | 836 | explicit StorageDataImpl(std::vector<u8>&& buffer_) : buffer{std::move(buffer_)} {} |
| 837 | 837 | ||
| 838 | std::vector<u8>& GetData() override { | 838 | std::vector<u8>& GetData() override { |
| 839 | return buffer; | 839 | return buffer; |
| @@ -1513,9 +1513,9 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { | |||
| 1513 | 1513 | ||
| 1514 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | 1514 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 1515 | system.GetContentProvider()}; | 1515 | system.GetContentProvider()}; |
| 1516 | auto res = pm.GetControlMetadata(); | 1516 | auto metadata = pm.GetControlMetadata(); |
| 1517 | if (res.first != nullptr) { | 1517 | if (metadata.first != nullptr) { |
| 1518 | return res; | 1518 | return metadata; |
| 1519 | } | 1519 | } |
| 1520 | 1520 | ||
| 1521 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | 1521 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), |
| @@ -1550,9 +1550,9 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { | |||
| 1550 | 1550 | ||
| 1551 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), | 1551 | const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), |
| 1552 | system.GetContentProvider()}; | 1552 | system.GetContentProvider()}; |
| 1553 | auto res = pm.GetControlMetadata(); | 1553 | auto metadata = pm.GetControlMetadata(); |
| 1554 | if (res.first != nullptr) { | 1554 | if (metadata.first != nullptr) { |
| 1555 | return res; | 1555 | return metadata; |
| 1556 | } | 1556 | } |
| 1557 | 1557 | ||
| 1558 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), | 1558 | const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id), |
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp index 00c174bb0..8bfa7c0e4 100644 --- a/src/core/hle/service/apm/controller.cpp +++ b/src/core/hle/service/apm/controller.cpp | |||
| @@ -15,11 +15,11 @@ namespace Service::APM { | |||
| 15 | 15 | ||
| 16 | constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7; | 16 | constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7; |
| 17 | 17 | ||
| 18 | Controller::Controller(Core::Timing::CoreTiming& core_timing) | 18 | Controller::Controller(Core::Timing::CoreTiming& core_timing_) |
| 19 | : core_timing{core_timing}, configs{ | 19 | : core_timing{core_timing_}, configs{ |
| 20 | {PerformanceMode::Handheld, DEFAULT_PERFORMANCE_CONFIGURATION}, | 20 | {PerformanceMode::Handheld, DEFAULT_PERFORMANCE_CONFIGURATION}, |
| 21 | {PerformanceMode::Docked, DEFAULT_PERFORMANCE_CONFIGURATION}, | 21 | {PerformanceMode::Docked, DEFAULT_PERFORMANCE_CONFIGURATION}, |
| 22 | } {} | 22 | } {} |
| 23 | 23 | ||
| 24 | Controller::~Controller() = default; | 24 | Controller::~Controller() = default; |
| 25 | 25 | ||
diff --git a/src/core/hle/service/apm/controller.h b/src/core/hle/service/apm/controller.h index af0c4cd34..8d48e0104 100644 --- a/src/core/hle/service/apm/controller.h +++ b/src/core/hle/service/apm/controller.h | |||
| @@ -50,7 +50,7 @@ enum class PerformanceMode : u8 { | |||
| 50 | // system during times of high load -- this simply maps to different PerformanceConfigs to use. | 50 | // system during times of high load -- this simply maps to different PerformanceConfigs to use. |
| 51 | class Controller { | 51 | class Controller { |
| 52 | public: | 52 | public: |
| 53 | explicit Controller(Core::Timing::CoreTiming& core_timing); | 53 | explicit Controller(Core::Timing::CoreTiming& core_timing_); |
| 54 | ~Controller(); | 54 | ~Controller(); |
| 55 | 55 | ||
| 56 | void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config); | 56 | void SetPerformanceConfiguration(PerformanceMode mode, PerformanceConfiguration config); |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 513bd3730..ae4284adf 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -169,10 +169,9 @@ private: | |||
| 169 | 169 | ||
| 170 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { | 170 | class IAudioDevice final : public ServiceFramework<IAudioDevice> { |
| 171 | public: | 171 | public: |
| 172 | explicit IAudioDevice(Core::System& system_, u32_le revision_num) | 172 | explicit IAudioDevice(Core::System& system_, Kernel::KEvent& buffer_event_, u32_le revision_) |
| 173 | : ServiceFramework{system_, "IAudioDevice"}, revision{revision_num}, | 173 | : ServiceFramework{system_, "IAudioDevice"}, buffer_event{buffer_event_}, revision{ |
| 174 | buffer_event{system.Kernel()}, audio_input_device_switch_event{system.Kernel()}, | 174 | revision_} { |
| 175 | audio_output_device_switch_event{system.Kernel()} { | ||
| 176 | static const FunctionInfo functions[] = { | 175 | static const FunctionInfo functions[] = { |
| 177 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, | 176 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, |
| 178 | {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, | 177 | {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"}, |
| @@ -189,18 +188,6 @@ public: | |||
| 189 | {13, nullptr, "GetAudioSystemMasterVolumeSetting"}, | 188 | {13, nullptr, "GetAudioSystemMasterVolumeSetting"}, |
| 190 | }; | 189 | }; |
| 191 | RegisterHandlers(functions); | 190 | RegisterHandlers(functions); |
| 192 | |||
| 193 | Kernel::KAutoObject::Create(std::addressof(buffer_event)); | ||
| 194 | buffer_event.Initialize("IAudioOutBufferReleasedEvent"); | ||
| 195 | |||
| 196 | // Should be similar to audio_output_device_switch_event | ||
| 197 | Kernel::KAutoObject::Create(std::addressof(audio_input_device_switch_event)); | ||
| 198 | audio_input_device_switch_event.Initialize("IAudioDevice:AudioInputDeviceSwitchedEvent"); | ||
| 199 | |||
| 200 | // Should only be signalled when an audio output device has been changed, example: speaker | ||
| 201 | // to headset | ||
| 202 | Kernel::KAutoObject::Create(std::addressof(audio_output_device_switch_event)); | ||
| 203 | audio_output_device_switch_event.Initialize("IAudioDevice:AudioOutputDeviceSwitchedEvent"); | ||
| 204 | } | 191 | } |
| 205 | 192 | ||
| 206 | private: | 193 | private: |
| @@ -310,7 +297,7 @@ private: | |||
| 310 | 297 | ||
| 311 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 298 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 312 | rb.Push(RESULT_SUCCESS); | 299 | rb.Push(RESULT_SUCCESS); |
| 313 | rb.PushCopyObjects(audio_input_device_switch_event.GetReadableEvent()); | 300 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 314 | } | 301 | } |
| 315 | 302 | ||
| 316 | void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { | 303 | void QueryAudioDeviceOutputEvent(Kernel::HLERequestContext& ctx) { |
| @@ -318,17 +305,16 @@ private: | |||
| 318 | 305 | ||
| 319 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 306 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 320 | rb.Push(RESULT_SUCCESS); | 307 | rb.Push(RESULT_SUCCESS); |
| 321 | rb.PushCopyObjects(audio_output_device_switch_event.GetReadableEvent()); | 308 | rb.PushCopyObjects(buffer_event.GetReadableEvent()); |
| 322 | } | 309 | } |
| 323 | 310 | ||
| 311 | Kernel::KEvent& buffer_event; | ||
| 324 | u32_le revision = 0; | 312 | u32_le revision = 0; |
| 325 | Kernel::KEvent buffer_event; | 313 | }; |
| 326 | Kernel::KEvent audio_input_device_switch_event; | ||
| 327 | Kernel::KEvent audio_output_device_switch_event; | ||
| 328 | 314 | ||
| 329 | }; // namespace Audio | 315 | AudRenU::AudRenU(Core::System& system_) |
| 316 | : ServiceFramework{system_, "audren:u"}, buffer_event{system.Kernel()} { | ||
| 330 | 317 | ||
| 331 | AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} { | ||
| 332 | // clang-format off | 318 | // clang-format off |
| 333 | static const FunctionInfo functions[] = { | 319 | static const FunctionInfo functions[] = { |
| 334 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, | 320 | {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, |
| @@ -340,6 +326,9 @@ AudRenU::AudRenU(Core::System& system_) : ServiceFramework{system_, "audren:u"} | |||
| 340 | // clang-format on | 326 | // clang-format on |
| 341 | 327 | ||
| 342 | RegisterHandlers(functions); | 328 | RegisterHandlers(functions); |
| 329 | |||
| 330 | Kernel::KAutoObject::Create(std::addressof(buffer_event)); | ||
| 331 | buffer_event.Initialize("IAudioOutBufferReleasedEvent"); | ||
| 343 | } | 332 | } |
| 344 | 333 | ||
| 345 | AudRenU::~AudRenU() = default; | 334 | AudRenU::~AudRenU() = default; |
| @@ -373,7 +362,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 373 | static constexpr u64 max_perf_detail_entries = 100; | 362 | static constexpr u64 max_perf_detail_entries = 100; |
| 374 | 363 | ||
| 375 | // Size of the data structure representing the bulk of the voice-related state. | 364 | // Size of the data structure representing the bulk of the voice-related state. |
| 376 | static constexpr u64 voice_state_size = 0x100; | 365 | static constexpr u64 voice_state_size_bytes = 0x100; |
| 377 | 366 | ||
| 378 | // Size of the upsampler manager data structure | 367 | // Size of the upsampler manager data structure |
| 379 | constexpr u64 upsampler_manager_size = 0x48; | 368 | constexpr u64 upsampler_manager_size = 0x48; |
| @@ -460,7 +449,8 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 460 | size += Common::AlignUp(voice_info_size * params.voice_count, info_field_alignment_size); | 449 | size += Common::AlignUp(voice_info_size * params.voice_count, info_field_alignment_size); |
| 461 | size += | 450 | size += |
| 462 | Common::AlignUp(voice_resource_size * params.voice_count, info_field_alignment_size); | 451 | Common::AlignUp(voice_resource_size * params.voice_count, info_field_alignment_size); |
| 463 | size += Common::AlignUp(voice_state_size * params.voice_count, info_field_alignment_size); | 452 | size += |
| 453 | Common::AlignUp(voice_state_size_bytes * params.voice_count, info_field_alignment_size); | ||
| 464 | return size; | 454 | return size; |
| 465 | }; | 455 | }; |
| 466 | 456 | ||
| @@ -662,7 +652,7 @@ void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { | |||
| 662 | // always assumes the initial release revision (REV1). | 652 | // always assumes the initial release revision (REV1). |
| 663 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 653 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 664 | rb.Push(RESULT_SUCCESS); | 654 | rb.Push(RESULT_SUCCESS); |
| 665 | rb.PushIpcInterface<IAudioDevice>(system, Common::MakeMagic('R', 'E', 'V', '1')); | 655 | rb.PushIpcInterface<IAudioDevice>(system, buffer_event, Common::MakeMagic('R', 'E', 'V', '1')); |
| 666 | } | 656 | } |
| 667 | 657 | ||
| 668 | void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { | 658 | void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { |
| @@ -684,7 +674,7 @@ void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& c | |||
| 684 | 674 | ||
| 685 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 675 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 686 | rb.Push(RESULT_SUCCESS); | 676 | rb.Push(RESULT_SUCCESS); |
| 687 | rb.PushIpcInterface<IAudioDevice>(system, revision); | 677 | rb.PushIpcInterface<IAudioDevice>(system, buffer_event, revision); |
| 688 | } | 678 | } |
| 689 | 679 | ||
| 690 | void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { | 680 | void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index 37e8b4716..0ee6f9542 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/k_event.h" | ||
| 7 | #include "core/hle/service/service.h" | 8 | #include "core/hle/service/service.h" |
| 8 | 9 | ||
| 9 | namespace Core { | 10 | namespace Core { |
| @@ -31,6 +32,7 @@ private: | |||
| 31 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); | 32 | void OpenAudioRendererImpl(Kernel::HLERequestContext& ctx); |
| 32 | 33 | ||
| 33 | std::size_t audren_instance_count = 0; | 34 | std::size_t audren_instance_count = 0; |
| 35 | Kernel::KEvent buffer_event; | ||
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| 36 | // Describes a particular audio feature that may be supported in a particular revision. | 38 | // Describes a particular audio feature that may be supported in a particular revision. |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 19c578b3a..ee5ec8cd6 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -50,8 +50,8 @@ public: | |||
| 50 | Enabled, | 50 | Enabled, |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | explicit OpusDecoderState(OpusDecoderPtr decoder, u32 sample_rate, u32 channel_count) | 53 | explicit OpusDecoderState(OpusDecoderPtr decoder_, u32 sample_rate_, u32 channel_count_) |
| 54 | : decoder{std::move(decoder)}, sample_rate{sample_rate}, channel_count{channel_count} {} | 54 | : decoder{std::move(decoder_)}, sample_rate{sample_rate_}, channel_count{channel_count_} {} |
| 55 | 55 | ||
| 56 | // Decodes interleaved Opus packets. Optionally allows reporting time taken to | 56 | // Decodes interleaved Opus packets. Optionally allows reporting time taken to |
| 57 | // perform the decoding, as well as any relevant extra behavior. | 57 | // perform the decoding, as well as any relevant extra behavior. |
| @@ -160,9 +160,9 @@ private: | |||
| 160 | 160 | ||
| 161 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { | 161 | class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { |
| 162 | public: | 162 | public: |
| 163 | explicit IHardwareOpusDecoderManager(Core::System& system_, OpusDecoderState decoder_state) | 163 | explicit IHardwareOpusDecoderManager(Core::System& system_, OpusDecoderState decoder_state_) |
| 164 | : ServiceFramework{system_, "IHardwareOpusDecoderManager"}, decoder_state{ | 164 | : ServiceFramework{system_, "IHardwareOpusDecoderManager"}, decoder_state{ |
| 165 | std::move(decoder_state)} { | 165 | std::move(decoder_state_)} { |
| 166 | // clang-format off | 166 | // clang-format off |
| 167 | static const FunctionInfo functions[] = { | 167 | static const FunctionInfo functions[] = { |
| 168 | {0, &IHardwareOpusDecoderManager::DecodeInterleavedOld, "DecodeInterleavedOld"}, | 168 | {0, &IHardwareOpusDecoderManager::DecodeInterleavedOld, "DecodeInterleavedOld"}, |
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index cee1774d1..d6d2f52e5 100644 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp | |||
| @@ -3,9 +3,18 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <fmt/ostream.h> | 5 | #include <fmt/ostream.h> |
| 6 | |||
| 7 | #ifdef __GNUC__ | ||
| 8 | #pragma GCC diagnostic push | ||
| 9 | #pragma GCC diagnostic ignored "-Wshadow" | ||
| 10 | #endif | ||
| 6 | #include <httplib.h> | 11 | #include <httplib.h> |
| 7 | #include <mbedtls/sha256.h> | 12 | #include <mbedtls/sha256.h> |
| 8 | #include <nlohmann/json.hpp> | 13 | #include <nlohmann/json.hpp> |
| 14 | #ifdef __GNUC__ | ||
| 15 | #pragma GCC diagnostic pop | ||
| 16 | #endif | ||
| 17 | |||
| 9 | #include "common/hex_util.h" | 18 | #include "common/hex_util.h" |
| 10 | #include "common/logging/backend.h" | 19 | #include "common/logging/backend.h" |
| 11 | #include "common/logging/log.h" | 20 | #include "common/logging/log.h" |
| @@ -178,8 +187,8 @@ bool VfsRawCopyDProgress(FileSys::VirtualDir src, FileSys::VirtualDir dest, | |||
| 178 | 187 | ||
| 179 | class Boxcat::Client { | 188 | class Boxcat::Client { |
| 180 | public: | 189 | public: |
| 181 | Client(std::string path, u64 title_id, u64 build_id) | 190 | Client(std::string path_, u64 title_id_, u64 build_id_) |
| 182 | : path(std::move(path)), title_id(title_id), build_id(build_id) {} | 191 | : path(std::move(path_)), title_id(title_id_), build_id(build_id_) {} |
| 183 | 192 | ||
| 184 | DownloadResult DownloadDataZip() { | 193 | DownloadResult DownloadDataZip() { |
| 185 | return DownloadInternal(fmt::format(BOXCAT_PATHNAME_DATA, title_id), TIMEOUT_SECONDS, | 194 | return DownloadInternal(fmt::format(BOXCAT_PATHNAME_DATA, title_id), TIMEOUT_SECONDS, |
diff --git a/src/core/hle/service/hid/controllers/controller_base.cpp b/src/core/hle/service/hid/controllers/controller_base.cpp index 8091db9d7..9d1e6db6a 100644 --- a/src/core/hle/service/hid/controllers/controller_base.cpp +++ b/src/core/hle/service/hid/controllers/controller_base.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::HID { | 7 | namespace Service::HID { |
| 8 | 8 | ||
| 9 | ControllerBase::ControllerBase(Core::System& system) : system(system) {} | 9 | ControllerBase::ControllerBase(Core::System& system_) : system(system_) {} |
| 10 | ControllerBase::~ControllerBase() = default; | 10 | ControllerBase::~ControllerBase() = default; |
| 11 | 11 | ||
| 12 | void ControllerBase::ActivateController() { | 12 | void ControllerBase::ActivateController() { |
diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index f47a9e61c..1556fb08e 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h | |||
| @@ -18,7 +18,7 @@ class System; | |||
| 18 | namespace Service::HID { | 18 | namespace Service::HID { |
| 19 | class ControllerBase { | 19 | class ControllerBase { |
| 20 | public: | 20 | public: |
| 21 | explicit ControllerBase(Core::System& system); | 21 | explicit ControllerBase(Core::System& system_); |
| 22 | virtual ~ControllerBase(); | 22 | virtual ~ControllerBase(); |
| 23 | 23 | ||
| 24 | // Called when the controller is initialized | 24 | // Called when the controller is initialized |
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index 9e5df3bb7..d311f754b 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp | |||
| @@ -23,7 +23,7 @@ constexpr f32 Square(s32 num) { | |||
| 23 | return static_cast<f32>(num * num); | 23 | return static_cast<f32>(num * num); |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | Controller_Gesture::Controller_Gesture(Core::System& system) : ControllerBase(system) {} | 26 | Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {} |
| 27 | Controller_Gesture::~Controller_Gesture() = default; | 27 | Controller_Gesture::~Controller_Gesture() = default; |
| 28 | 28 | ||
| 29 | void Controller_Gesture::OnInit() { | 29 | void Controller_Gesture::OnInit() { |
| @@ -211,15 +211,16 @@ void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, Touch | |||
| 211 | } | 211 | } |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | void Controller_Gesture::EndGesture(GestureProperties& gesture, GestureProperties& last_gesture, | 214 | void Controller_Gesture::EndGesture(GestureProperties& gesture, |
| 215 | TouchType& type, Attribute& attributes, f32 time_difference) { | 215 | GestureProperties& last_gesture_props, TouchType& type, |
| 216 | Attribute& attributes, f32 time_difference) { | ||
| 216 | const auto& last_entry = | 217 | const auto& last_entry = |
| 217 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | 218 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; |
| 218 | if (last_gesture.active_points != 0) { | 219 | if (last_gesture_props.active_points != 0) { |
| 219 | switch (last_entry.type) { | 220 | switch (last_entry.type) { |
| 220 | case TouchType::Touch: | 221 | case TouchType::Touch: |
| 221 | if (enable_press_and_tap) { | 222 | if (enable_press_and_tap) { |
| 222 | SetTapEvent(gesture, last_gesture, type, attributes); | 223 | SetTapEvent(gesture, last_gesture_props, type, attributes); |
| 223 | return; | 224 | return; |
| 224 | } | 225 | } |
| 225 | type = TouchType::Cancel; | 226 | type = TouchType::Cancel; |
| @@ -234,7 +235,7 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture, GesturePropertie | |||
| 234 | force_update = true; | 235 | force_update = true; |
| 235 | break; | 236 | break; |
| 236 | case TouchType::Pan: | 237 | case TouchType::Pan: |
| 237 | EndPanEvent(gesture, last_gesture, type, time_difference); | 238 | EndPanEvent(gesture, last_gesture_props, type, time_difference); |
| 238 | break; | 239 | break; |
| 239 | default: | 240 | default: |
| 240 | break; | 241 | break; |
| @@ -246,10 +247,11 @@ void Controller_Gesture::EndGesture(GestureProperties& gesture, GesturePropertie | |||
| 246 | } | 247 | } |
| 247 | } | 248 | } |
| 248 | 249 | ||
| 249 | void Controller_Gesture::SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture, | 250 | void Controller_Gesture::SetTapEvent(GestureProperties& gesture, |
| 250 | TouchType& type, Attribute& attributes) { | 251 | GestureProperties& last_gesture_props, TouchType& type, |
| 252 | Attribute& attributes) { | ||
| 251 | type = TouchType::Tap; | 253 | type = TouchType::Tap; |
| 252 | gesture = last_gesture; | 254 | gesture = last_gesture_props; |
| 253 | force_update = true; | 255 | force_update = true; |
| 254 | f32 tap_time_difference = | 256 | f32 tap_time_difference = |
| 255 | static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); | 257 | static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000); |
| @@ -259,8 +261,9 @@ void Controller_Gesture::SetTapEvent(GestureProperties& gesture, GestureProperti | |||
| 259 | } | 261 | } |
| 260 | } | 262 | } |
| 261 | 263 | ||
| 262 | void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture, | 264 | void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, |
| 263 | TouchType& type, f32 time_difference) { | 265 | GestureProperties& last_gesture_props, TouchType& type, |
| 266 | f32 time_difference) { | ||
| 264 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 267 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 265 | const auto& last_entry = | 268 | const auto& last_entry = |
| 266 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | 269 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; |
| @@ -272,13 +275,14 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, GesturePrope | |||
| 272 | last_pan_time_difference = time_difference; | 275 | last_pan_time_difference = time_difference; |
| 273 | 276 | ||
| 274 | // Promote to pinch type | 277 | // Promote to pinch type |
| 275 | if (std::abs(gesture.average_distance - last_gesture.average_distance) > pinch_threshold) { | 278 | if (std::abs(gesture.average_distance - last_gesture_props.average_distance) > |
| 279 | pinch_threshold) { | ||
| 276 | type = TouchType::Pinch; | 280 | type = TouchType::Pinch; |
| 277 | cur_entry.scale = gesture.average_distance / last_gesture.average_distance; | 281 | cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance; |
| 278 | } | 282 | } |
| 279 | 283 | ||
| 280 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture.angle) / | 284 | const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) / |
| 281 | (1 + (gesture.angle * last_gesture.angle))); | 285 | (1 + (gesture.angle * last_gesture_props.angle))); |
| 282 | // Promote to rotate type | 286 | // Promote to rotate type |
| 283 | if (std::abs(angle_between_two_lines) > angle_threshold) { | 287 | if (std::abs(angle_between_two_lines) > angle_threshold) { |
| 284 | type = TouchType::Rotate; | 288 | type = TouchType::Rotate; |
| @@ -287,8 +291,9 @@ void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture, GesturePrope | |||
| 287 | } | 291 | } |
| 288 | } | 292 | } |
| 289 | 293 | ||
| 290 | void Controller_Gesture::EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture, | 294 | void Controller_Gesture::EndPanEvent(GestureProperties& gesture, |
| 291 | TouchType& type, f32 time_difference) { | 295 | GestureProperties& last_gesture_props, TouchType& type, |
| 296 | f32 time_difference) { | ||
| 292 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 297 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 293 | const auto& last_entry = | 298 | const auto& last_entry = |
| 294 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | 299 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; |
| @@ -301,7 +306,7 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture, GestureProperti | |||
| 301 | 306 | ||
| 302 | // Set swipe event with parameters | 307 | // Set swipe event with parameters |
| 303 | if (curr_vel > swipe_threshold) { | 308 | if (curr_vel > swipe_threshold) { |
| 304 | SetSwipeEvent(gesture, last_gesture, type); | 309 | SetSwipeEvent(gesture, last_gesture_props, type); |
| 305 | return; | 310 | return; |
| 306 | } | 311 | } |
| 307 | 312 | ||
| @@ -312,13 +317,13 @@ void Controller_Gesture::EndPanEvent(GestureProperties& gesture, GestureProperti | |||
| 312 | force_update = true; | 317 | force_update = true; |
| 313 | } | 318 | } |
| 314 | 319 | ||
| 315 | void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture, | 320 | void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture, |
| 316 | TouchType& type) { | 321 | GestureProperties& last_gesture_props, TouchType& type) { |
| 317 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; | 322 | auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; |
| 318 | const auto& last_entry = | 323 | const auto& last_entry = |
| 319 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; | 324 | shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17]; |
| 320 | type = TouchType::Swipe; | 325 | type = TouchType::Swipe; |
| 321 | gesture = last_gesture; | 326 | gesture = last_gesture_props; |
| 322 | force_update = true; | 327 | force_update = true; |
| 323 | cur_entry.delta_x = last_entry.delta_x; | 328 | cur_entry.delta_x = last_entry.delta_x; |
| 324 | cur_entry.delta_y = last_entry.delta_y; | 329 | cur_entry.delta_y = last_entry.delta_y; |
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 18110a6ad..f46e29411 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h | |||
| @@ -128,32 +128,34 @@ private: | |||
| 128 | void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference); | 128 | void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference); |
| 129 | 129 | ||
| 130 | // Terminates exiting gesture | 130 | // Terminates exiting gesture |
| 131 | void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture, TouchType& type, | 131 | void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props, |
| 132 | Attribute& attributes, f32 time_difference); | 132 | TouchType& type, Attribute& attributes, f32 time_difference); |
| 133 | 133 | ||
| 134 | // Set current event to a tap event | 134 | // Set current event to a tap event |
| 135 | void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture, TouchType& type, | 135 | void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, |
| 136 | Attribute& attributes); | 136 | TouchType& type, Attribute& attributes); |
| 137 | 137 | ||
| 138 | // Calculates and set the extra parameters related to a pan event | 138 | // Calculates and set the extra parameters related to a pan event |
| 139 | void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture, | 139 | void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, |
| 140 | TouchType& type, f32 time_difference); | 140 | TouchType& type, f32 time_difference); |
| 141 | 141 | ||
| 142 | // Terminates the pan event | 142 | // Terminates the pan event |
| 143 | void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture, TouchType& type, | 143 | void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, |
| 144 | f32 time_difference); | 144 | TouchType& type, f32 time_difference); |
| 145 | 145 | ||
| 146 | // Set current event to a swipe event | 146 | // Set current event to a swipe event |
| 147 | void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture, | 147 | void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props, |
| 148 | TouchType& type); | 148 | TouchType& type); |
| 149 | 149 | ||
| 150 | // Returns an unused finger id, if there is no fingers avaliable MAX_FINGERS will be returned | 150 | // Returns an unused finger id, if there is no fingers available std::nullopt is returned. |
| 151 | std::optional<size_t> GetUnusedFingerID() const; | 151 | std::optional<size_t> GetUnusedFingerID() const; |
| 152 | 152 | ||
| 153 | /** If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no | 153 | /** |
| 154 | * If the touch is new it tries to assign a new finger id, if there is no fingers available no | ||
| 154 | * changes will be made. Updates the coordinates if the finger id it's already set. If the touch | 155 | * changes will be made. Updates the coordinates if the finger id it's already set. If the touch |
| 155 | * ends delays the output by one frame to set the end_touch flag before finally freeing the | 156 | * ends delays the output by one frame to set the end_touch flag before finally freeing the |
| 156 | * finger id */ | 157 | * finger id |
| 158 | */ | ||
| 157 | size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, | 159 | size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, |
| 158 | size_t finger_id); | 160 | size_t finger_id); |
| 159 | 161 | ||
diff --git a/src/core/hle/service/mii/manager.h b/src/core/hle/service/mii/manager.h index 2106a528a..ec7efa5f7 100644 --- a/src/core/hle/service/mii/manager.h +++ b/src/core/hle/service/mii/manager.h | |||
| @@ -89,7 +89,7 @@ static_assert(std::has_unique_object_representations_v<MiiInfo>, | |||
| 89 | #pragma pack(push, 4) | 89 | #pragma pack(push, 4) |
| 90 | 90 | ||
| 91 | struct MiiInfoElement { | 91 | struct MiiInfoElement { |
| 92 | MiiInfoElement(const MiiInfo& info, Source source) : info{info}, source{source} {} | 92 | MiiInfoElement(const MiiInfo& info_, Source source_) : info{info_}, source{source_} {} |
| 93 | 93 | ||
| 94 | MiiInfo info{}; | 94 | MiiInfo info{}; |
| 95 | Source source{}; | 95 | Source source{}; |
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index 26be9e45b..81f150a88 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp | |||
| @@ -253,8 +253,8 @@ private: | |||
| 253 | 253 | ||
| 254 | class MiiDBModule final : public ServiceFramework<MiiDBModule> { | 254 | class MiiDBModule final : public ServiceFramework<MiiDBModule> { |
| 255 | public: | 255 | public: |
| 256 | explicit MiiDBModule(Core::System& system_, const char* name) | 256 | explicit MiiDBModule(Core::System& system_, const char* name_) |
| 257 | : ServiceFramework{system_, name} { | 257 | : ServiceFramework{system_, name_} { |
| 258 | // clang-format off | 258 | // clang-format off |
| 259 | static const FunctionInfo functions[] = { | 259 | static const FunctionInfo functions[] = { |
| 260 | {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, | 260 | {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"}, |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 94ef3983a..76e3832df 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -368,7 +368,7 @@ private: | |||
| 368 | }, | 368 | }, |
| 369 | }; | 369 | }; |
| 370 | 370 | ||
| 371 | IPC::ResponseBuilder rb{ctx, 2 + sizeof(IpConfigInfo) / sizeof(u32)}; | 371 | IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; |
| 372 | rb.Push(RESULT_SUCCESS); | 372 | rb.Push(RESULT_SUCCESS); |
| 373 | rb.PushRaw<IpConfigInfo>(ip_config_info); | 373 | rb.PushRaw<IpConfigInfo>(ip_config_info); |
| 374 | } | 374 | } |
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h index b37f023df..5b73a5a34 100644 --- a/src/core/hle/service/nvdrv/devices/nvdevice.h +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h | |||
| @@ -21,7 +21,7 @@ namespace Service::Nvidia::Devices { | |||
| 21 | /// implement the ioctl interface. | 21 | /// implement the ioctl interface. |
| 22 | class nvdevice { | 22 | class nvdevice { |
| 23 | public: | 23 | public: |
| 24 | explicit nvdevice(Core::System& system) : system{system} {} | 24 | explicit nvdevice(Core::System& system_) : system{system_} {} |
| 25 | virtual ~nvdevice() = default; | 25 | virtual ~nvdevice() = default; |
| 26 | 26 | ||
| 27 | /** | 27 | /** |
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index bbef04a29..2cc0da124 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -52,7 +52,6 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | |||
| 52 | addr, offset, width, height, stride, static_cast<PixelFormat>(format), | 52 | addr, offset, width, height, stride, static_cast<PixelFormat>(format), |
| 53 | transform, crop_rect}; | 53 | transform, crop_rect}; |
| 54 | 54 | ||
| 55 | system.GetPerfStats().EndGameFrame(); | ||
| 56 | system.GetPerfStats().EndSystemFrame(); | 55 | system.GetPerfStats().EndSystemFrame(); |
| 57 | system.GPU().SwapBuffers(&framebuffer); | 56 | system.GPU().SwapBuffers(&framebuffer); |
| 58 | system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); | 57 | system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 229bf6350..24e3151cb 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | |||
| @@ -48,13 +48,13 @@ private: | |||
| 48 | public: | 48 | public: |
| 49 | constexpr BufferMap() = default; | 49 | constexpr BufferMap() = default; |
| 50 | 50 | ||
| 51 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size) | 51 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_) |
| 52 | : start_addr{start_addr}, end_addr{start_addr + size} {} | 52 | : start_addr{start_addr_}, end_addr{start_addr_ + size_} {} |
| 53 | 53 | ||
| 54 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size, VAddr cpu_addr, | 54 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_, VAddr cpu_addr_, |
| 55 | bool is_allocated) | 55 | bool is_allocated_) |
| 56 | : start_addr{start_addr}, end_addr{start_addr + size}, cpu_addr{cpu_addr}, | 56 | : start_addr{start_addr_}, end_addr{start_addr_ + size_}, cpu_addr{cpu_addr_}, |
| 57 | is_allocated{is_allocated} {} | 57 | is_allocated{is_allocated_} {} |
| 58 | 58 | ||
| 59 | constexpr VAddr StartAddr() const { | 59 | constexpr VAddr StartAddr() const { |
| 60 | return start_addr; | 60 | return start_addr; |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h index 14d0d210a..da10f5f41 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h | |||
| @@ -27,13 +27,13 @@ protected: | |||
| 27 | public: | 27 | public: |
| 28 | constexpr BufferMap() = default; | 28 | constexpr BufferMap() = default; |
| 29 | 29 | ||
| 30 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size) | 30 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_) |
| 31 | : start_addr{start_addr}, end_addr{start_addr + size} {} | 31 | : start_addr{start_addr_}, end_addr{start_addr_ + size_} {} |
| 32 | 32 | ||
| 33 | constexpr BufferMap(GPUVAddr start_addr, std::size_t size, VAddr cpu_addr, | 33 | constexpr BufferMap(GPUVAddr start_addr_, std::size_t size_, VAddr cpu_addr_, |
| 34 | bool is_allocated) | 34 | bool is_allocated_) |
| 35 | : start_addr{start_addr}, end_addr{start_addr + size}, cpu_addr{cpu_addr}, | 35 | : start_addr{start_addr_}, end_addr{start_addr_ + size_}, cpu_addr{cpu_addr_}, |
| 36 | is_allocated{is_allocated} {} | 36 | is_allocated{is_allocated_} {} |
| 37 | 37 | ||
| 38 | constexpr VAddr StartAddr() const { | 38 | constexpr VAddr StartAddr() const { |
| 39 | return start_addr; | 39 | return start_addr; |
diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.cpp b/src/core/hle/service/nvdrv/syncpoint_manager.cpp index 0151a03b7..3b6f55526 100644 --- a/src/core/hle/service/nvdrv/syncpoint_manager.cpp +++ b/src/core/hle/service/nvdrv/syncpoint_manager.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::Nvidia { | 9 | namespace Service::Nvidia { |
| 10 | 10 | ||
| 11 | SyncpointManager::SyncpointManager(Tegra::GPU& gpu) : gpu{gpu} {} | 11 | SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {} |
| 12 | 12 | ||
| 13 | SyncpointManager::~SyncpointManager() = default; | 13 | SyncpointManager::~SyncpointManager() = default; |
| 14 | 14 | ||
diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.h b/src/core/hle/service/nvdrv/syncpoint_manager.h index d395c5d0b..99f286474 100644 --- a/src/core/hle/service/nvdrv/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/syncpoint_manager.h | |||
| @@ -18,7 +18,7 @@ namespace Service::Nvidia { | |||
| 18 | 18 | ||
| 19 | class SyncpointManager final { | 19 | class SyncpointManager final { |
| 20 | public: | 20 | public: |
| 21 | explicit SyncpointManager(Tegra::GPU& gpu); | 21 | explicit SyncpointManager(Tegra::GPU& gpu_); |
| 22 | ~SyncpointManager(); | 22 | ~SyncpointManager(); |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 0b6e7430b..59ddf6298 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | 13 | ||
| 14 | namespace Service::NVFlinger { | 14 | namespace Service::NVFlinger { |
| 15 | 15 | ||
| 16 | BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id) | 16 | BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_) |
| 17 | : id(id), layer_id(layer_id), buffer_wait_event{kernel} { | 17 | : id(id_), layer_id(layer_id_), buffer_wait_event{kernel} { |
| 18 | Kernel::KAutoObject::Create(std::addressof(buffer_wait_event)); | 18 | Kernel::KAutoObject::Create(std::addressof(buffer_wait_event)); |
| 19 | buffer_wait_event.Initialize("BufferQueue:WaitEvent"); | 19 | buffer_wait_event.Initialize("BufferQueue:WaitEvent"); |
| 20 | } | 20 | } |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 4ec0b1506..61e337ac5 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h | |||
| @@ -54,7 +54,7 @@ public: | |||
| 54 | NativeWindowFormat = 2, | 54 | NativeWindowFormat = 2, |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | explicit BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id); | 57 | explicit BufferQueue(Kernel::KernelCore& kernel, u32 id_, u64 layer_id_); |
| 58 | ~BufferQueue(); | 58 | ~BufferQueue(); |
| 59 | 59 | ||
| 60 | enum class BufferTransformFlags : u32 { | 60 | enum class BufferTransformFlags : u32 { |
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 7fb9133c7..d1dbc659b 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -61,7 +61,7 @@ void NVFlinger::SplitVSync() { | |||
| 61 | } | 61 | } |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | NVFlinger::NVFlinger(Core::System& system) : system(system) { | 64 | NVFlinger::NVFlinger(Core::System& system_) : system(system_) { |
| 65 | displays.emplace_back(0, "Default", system); | 65 | displays.emplace_back(0, "Default", system); |
| 66 | displays.emplace_back(1, "External", system); | 66 | displays.emplace_back(1, "External", system); |
| 67 | displays.emplace_back(2, "Edid", system); | 67 | displays.emplace_back(2, "Edid", system); |
| @@ -139,11 +139,15 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | const u64 layer_id = next_layer_id++; | 141 | const u64 layer_id = next_layer_id++; |
| 142 | CreateLayerAtId(*display, layer_id); | ||
| 143 | return layer_id; | ||
| 144 | } | ||
| 145 | |||
| 146 | void NVFlinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { | ||
| 142 | const u32 buffer_queue_id = next_buffer_queue_id++; | 147 | const u32 buffer_queue_id = next_buffer_queue_id++; |
| 143 | buffer_queues.emplace_back( | 148 | buffer_queues.emplace_back( |
| 144 | std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id)); | 149 | std::make_unique<BufferQueue>(system.Kernel(), buffer_queue_id, layer_id)); |
| 145 | display->CreateLayer(layer_id, *buffer_queues.back()); | 150 | display.CreateLayer(layer_id, *buffer_queues.back()); |
| 146 | return layer_id; | ||
| 147 | } | 151 | } |
| 148 | 152 | ||
| 149 | void NVFlinger::CloseLayer(u64 layer_id) { | 153 | void NVFlinger::CloseLayer(u64 layer_id) { |
| @@ -154,9 +158,9 @@ void NVFlinger::CloseLayer(u64 layer_id) { | |||
| 154 | } | 158 | } |
| 155 | } | 159 | } |
| 156 | 160 | ||
| 157 | std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const { | 161 | std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) { |
| 158 | const auto lock_guard = Lock(); | 162 | const auto lock_guard = Lock(); |
| 159 | const auto* const layer = FindLayer(display_id, layer_id); | 163 | const auto* const layer = FindOrCreateLayer(display_id, layer_id); |
| 160 | 164 | ||
| 161 | if (layer == nullptr) { | 165 | if (layer == nullptr) { |
| 162 | return std::nullopt; | 166 | return std::nullopt; |
| @@ -232,6 +236,24 @@ const VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { | |||
| 232 | return display->FindLayer(layer_id); | 236 | return display->FindLayer(layer_id); |
| 233 | } | 237 | } |
| 234 | 238 | ||
| 239 | VI::Layer* NVFlinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { | ||
| 240 | auto* const display = FindDisplay(display_id); | ||
| 241 | |||
| 242 | if (display == nullptr) { | ||
| 243 | return nullptr; | ||
| 244 | } | ||
| 245 | |||
| 246 | auto* layer = display->FindLayer(layer_id); | ||
| 247 | |||
| 248 | if (layer == nullptr) { | ||
| 249 | LOG_DEBUG(Service, "Layer at id {} not found. Trying to create it.", layer_id); | ||
| 250 | CreateLayerAtId(*display, layer_id); | ||
| 251 | return display->FindLayer(layer_id); | ||
| 252 | } | ||
| 253 | |||
| 254 | return layer; | ||
| 255 | } | ||
| 256 | |||
| 235 | void NVFlinger::Compose() { | 257 | void NVFlinger::Compose() { |
| 236 | for (auto& display : displays) { | 258 | for (auto& display : displays) { |
| 237 | // Trigger vsync for this display at the end of drawing | 259 | // Trigger vsync for this display at the end of drawing |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index b0febdaec..d80fd07ef 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -45,7 +45,7 @@ class BufferQueue; | |||
| 45 | 45 | ||
| 46 | class NVFlinger final { | 46 | class NVFlinger final { |
| 47 | public: | 47 | public: |
| 48 | explicit NVFlinger(Core::System& system); | 48 | explicit NVFlinger(Core::System& system_); |
| 49 | ~NVFlinger(); | 49 | ~NVFlinger(); |
| 50 | 50 | ||
| 51 | /// Sets the NVDrv module instance to use to send buffers to the GPU. | 51 | /// Sets the NVDrv module instance to use to send buffers to the GPU. |
| @@ -67,7 +67,7 @@ public: | |||
| 67 | /// Finds the buffer queue ID of the specified layer in the specified display. | 67 | /// Finds the buffer queue ID of the specified layer in the specified display. |
| 68 | /// | 68 | /// |
| 69 | /// If an invalid display ID or layer ID is provided, then an empty optional is returned. | 69 | /// If an invalid display ID or layer ID is provided, then an empty optional is returned. |
| 70 | [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id) const; | 70 | [[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id); |
| 71 | 71 | ||
| 72 | /// Gets the vsync event for the specified display. | 72 | /// Gets the vsync event for the specified display. |
| 73 | /// | 73 | /// |
| @@ -100,6 +100,14 @@ private: | |||
| 100 | /// Finds the layer identified by the specified ID in the desired display. | 100 | /// Finds the layer identified by the specified ID in the desired display. |
| 101 | [[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const; | 101 | [[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const; |
| 102 | 102 | ||
| 103 | /// Finds the layer identified by the specified ID in the desired display, | ||
| 104 | /// or creates the layer if it is not found. | ||
| 105 | /// To be used when the system expects the specified ID to already exist. | ||
| 106 | [[nodiscard]] VI::Layer* FindOrCreateLayer(u64 display_id, u64 layer_id); | ||
| 107 | |||
| 108 | /// Creates a layer with the specified layer ID in the desired display. | ||
| 109 | void CreateLayerAtId(VI::Display& display, u64 layer_id); | ||
| 110 | |||
| 103 | static void VSyncThread(NVFlinger& nv_flinger); | 111 | static void VSyncThread(NVFlinger& nv_flinger); |
| 104 | 112 | ||
| 105 | void SplitVSync(); | 113 | void SplitVSync(); |
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp index e4d155c86..908e0a1e3 100644 --- a/src/core/hle/service/pctl/pctl.cpp +++ b/src/core/hle/service/pctl/pctl.cpp | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | namespace Service::PCTL { | 7 | namespace Service::PCTL { |
| 8 | 8 | ||
| 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, | 9 | PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 10 | Capability capability) | 10 | Capability capability_) |
| 11 | : Interface{system_, std::move(module_), name, capability} { | 11 | : Interface{system_, std::move(module_), name, capability_} { |
| 12 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
| 13 | {0, &PCTL::CreateService, "CreateService"}, | 13 | {0, &PCTL::CreateService, "CreateService"}, |
| 14 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, | 14 | {1, &PCTL::CreateServiceWithoutInitialize, "CreateServiceWithoutInitialize"}, |
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h index fd0a1e486..ea3b97823 100644 --- a/src/core/hle/service/pctl/pctl.h +++ b/src/core/hle/service/pctl/pctl.h | |||
| @@ -15,7 +15,7 @@ namespace Service::PCTL { | |||
| 15 | class PCTL final : public Module::Interface { | 15 | class PCTL final : public Module::Interface { |
| 16 | public: | 16 | public: |
| 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, | 17 | explicit PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, |
| 18 | Capability capability); | 18 | Capability capability_); |
| 19 | ~PCTL() override; | 19 | ~PCTL() override; |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index f4715935d..a43185c44 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp | |||
| @@ -31,8 +31,8 @@ std::optional<Kernel::KProcess*> SearchProcessList( | |||
| 31 | 31 | ||
| 32 | void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, | 32 | void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, |
| 33 | const std::vector<Kernel::KProcess*>& process_list) { | 33 | const std::vector<Kernel::KProcess*>& process_list) { |
| 34 | const auto process = SearchProcessList(process_list, [](const auto& process) { | 34 | const auto process = SearchProcessList(process_list, [](const auto& proc) { |
| 35 | return process->GetProcessID() == Kernel::KProcess::ProcessIDMin; | 35 | return proc->GetProcessID() == Kernel::KProcess::ProcessIDMin; |
| 36 | }); | 36 | }); |
| 37 | 37 | ||
| 38 | IPC::ResponseBuilder rb{ctx, 4}; | 38 | IPC::ResponseBuilder rb{ctx, 4}; |
| @@ -100,8 +100,8 @@ private: | |||
| 100 | LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); | 100 | LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); |
| 101 | 101 | ||
| 102 | const auto process = | 102 | const auto process = |
| 103 | SearchProcessList(kernel.GetProcessList(), [title_id](const auto& process) { | 103 | SearchProcessList(kernel.GetProcessList(), [title_id](const auto& proc) { |
| 104 | return process->GetTitleID() == title_id; | 104 | return proc->GetTitleID() == title_id; |
| 105 | }); | 105 | }); |
| 106 | 106 | ||
| 107 | if (!process.has_value()) { | 107 | if (!process.has_value()) { |
| @@ -140,8 +140,8 @@ private: | |||
| 140 | 140 | ||
| 141 | LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); | 141 | LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); |
| 142 | 142 | ||
| 143 | const auto process = SearchProcessList(process_list, [process_id](const auto& process) { | 143 | const auto process = SearchProcessList(process_list, [process_id](const auto& proc) { |
| 144 | return process->GetProcessID() == process_id; | 144 | return proc->GetProcessID() == process_id; |
| 145 | }); | 145 | }); |
| 146 | 146 | ||
| 147 | if (!process.has_value()) { | 147 | if (!process.has_value()) { |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 00e683c2f..fa61a5c7b 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -107,21 +107,22 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) | |||
| 107 | ASSERT(!port_installed); | 107 | ASSERT(!port_installed); |
| 108 | 108 | ||
| 109 | auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap(); | 109 | auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap(); |
| 110 | port->SetHleHandler(shared_from_this()); | 110 | port->SetSessionHandler(shared_from_this()); |
| 111 | port_installed = true; | 111 | port_installed = true; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) { | 114 | Kernel::KClientPort& ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) { |
| 115 | const auto guard = LockService(); | 115 | const auto guard = LockService(); |
| 116 | 116 | ||
| 117 | ASSERT(!port_installed); | 117 | ASSERT(!port_installed); |
| 118 | 118 | ||
| 119 | auto* port = Kernel::KPort::Create(kernel); | 119 | auto* port = Kernel::KPort::Create(kernel); |
| 120 | port->Initialize(max_sessions, false, service_name); | 120 | port->Initialize(max_sessions, false, service_name); |
| 121 | port->GetServerPort().SetHleHandler(shared_from_this()); | 121 | port->GetServerPort().SetSessionHandler(shared_from_this()); |
| 122 | kernel.AddNamedPort(service_name, &port->GetClientPort()); | ||
| 123 | 122 | ||
| 124 | port_installed = true; | 123 | port_installed = true; |
| 124 | |||
| 125 | return port->GetClientPort(); | ||
| 125 | } | 126 | } |
| 126 | 127 | ||
| 127 | void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { | 128 | void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { |
| @@ -132,6 +133,16 @@ void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* function | |||
| 132 | } | 133 | } |
| 133 | } | 134 | } |
| 134 | 135 | ||
| 136 | void ServiceFrameworkBase::RegisterHandlersBaseTipc(const FunctionInfoBase* functions, | ||
| 137 | std::size_t n) { | ||
| 138 | handlers_tipc.reserve(handlers_tipc.size() + n); | ||
| 139 | for (std::size_t i = 0; i < n; ++i) { | ||
| 140 | // Usually this array is sorted by id already, so hint to insert at the end | ||
| 141 | handlers_tipc.emplace_hint(handlers_tipc.cend(), functions[i].expected_header, | ||
| 142 | functions[i]); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 135 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, | 146 | void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, |
| 136 | const FunctionInfoBase* info) { | 147 | const FunctionInfoBase* info) { |
| 137 | auto cmd_buf = ctx.CommandBuffer(); | 148 | auto cmd_buf = ctx.CommandBuffer(); |
| @@ -166,33 +177,55 @@ void ServiceFrameworkBase::InvokeRequest(Kernel::HLERequestContext& ctx) { | |||
| 166 | handler_invoker(this, info->handler_callback, ctx); | 177 | handler_invoker(this, info->handler_callback, ctx); |
| 167 | } | 178 | } |
| 168 | 179 | ||
| 169 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) { | 180 | void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) { |
| 181 | boost::container::flat_map<u32, FunctionInfoBase>::iterator itr; | ||
| 182 | |||
| 183 | itr = handlers_tipc.find(ctx.GetCommand()); | ||
| 184 | |||
| 185 | const FunctionInfoBase* info = itr == handlers_tipc.end() ? nullptr : &itr->second; | ||
| 186 | if (info == nullptr || info->handler_callback == nullptr) { | ||
| 187 | return ReportUnimplementedFunction(ctx, info); | ||
| 188 | } | ||
| 189 | |||
| 190 | LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); | ||
| 191 | handler_invoker(this, info->handler_callback, ctx); | ||
| 192 | } | ||
| 193 | |||
| 194 | ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, | ||
| 195 | Kernel::HLERequestContext& ctx) { | ||
| 170 | const auto guard = LockService(); | 196 | const auto guard = LockService(); |
| 171 | 197 | ||
| 172 | switch (context.GetCommandType()) { | 198 | switch (ctx.GetCommandType()) { |
| 173 | case IPC::CommandType::Close: { | 199 | case IPC::CommandType::Close: |
| 174 | IPC::ResponseBuilder rb{context, 2}; | 200 | case IPC::CommandType::TIPC_Close: { |
| 201 | session.Close(); | ||
| 202 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 175 | rb.Push(RESULT_SUCCESS); | 203 | rb.Push(RESULT_SUCCESS); |
| 176 | return IPC::ERR_REMOTE_PROCESS_DEAD; | 204 | return IPC::ERR_REMOTE_PROCESS_DEAD; |
| 177 | } | 205 | } |
| 178 | case IPC::CommandType::ControlWithContext: | 206 | case IPC::CommandType::ControlWithContext: |
| 179 | case IPC::CommandType::Control: { | 207 | case IPC::CommandType::Control: { |
| 180 | system.ServiceManager().InvokeControlRequest(context); | 208 | system.ServiceManager().InvokeControlRequest(ctx); |
| 181 | break; | 209 | break; |
| 182 | } | 210 | } |
| 183 | case IPC::CommandType::RequestWithContext: | 211 | case IPC::CommandType::RequestWithContext: |
| 184 | case IPC::CommandType::Request: { | 212 | case IPC::CommandType::Request: { |
| 185 | InvokeRequest(context); | 213 | InvokeRequest(ctx); |
| 186 | break; | 214 | break; |
| 187 | } | 215 | } |
| 188 | default: | 216 | default: |
| 189 | UNIMPLEMENTED_MSG("command_type={}", context.GetCommandType()); | 217 | if (ctx.IsTipc()) { |
| 218 | InvokeRequestTipc(ctx); | ||
| 219 | break; | ||
| 220 | } | ||
| 221 | |||
| 222 | UNIMPLEMENTED_MSG("command_type={}", ctx.GetCommandType()); | ||
| 190 | } | 223 | } |
| 191 | 224 | ||
| 192 | // If emulation was shutdown, we are closing service threads, do not write the response back to | 225 | // If emulation was shutdown, we are closing service threads, do not write the response back to |
| 193 | // memory that may be shutting down as well. | 226 | // memory that may be shutting down as well. |
| 194 | if (system.IsPoweredOn()) { | 227 | if (system.IsPoweredOn()) { |
| 195 | context.WriteToOutgoingCommandBuffer(context.GetThread()); | 228 | ctx.WriteToOutgoingCommandBuffer(ctx.GetThread()); |
| 196 | } | 229 | } |
| 197 | 230 | ||
| 198 | return RESULT_SUCCESS; | 231 | return RESULT_SUCCESS; |
| @@ -207,7 +240,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system | |||
| 207 | 240 | ||
| 208 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); | 241 | system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false); |
| 209 | 242 | ||
| 210 | SM::ServiceManager::InstallInterfaces(sm, system); | 243 | system.Kernel().RegisterNamedService("sm:", SM::ServiceManager::InterfaceFactory); |
| 211 | 244 | ||
| 212 | Account::InstallInterfaces(system); | 245 | Account::InstallInterfaces(system); |
| 213 | AM::InstallInterfaces(*sm, *nv_flinger, system); | 246 | AM::InstallInterfaces(*sm, *nv_flinger, system); |
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 884951428..4c048173b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h | |||
| @@ -21,7 +21,9 @@ class System; | |||
| 21 | 21 | ||
| 22 | namespace Kernel { | 22 | namespace Kernel { |
| 23 | class HLERequestContext; | 23 | class HLERequestContext; |
| 24 | } | 24 | class KClientPort; |
| 25 | class KServerSession; | ||
| 26 | } // namespace Kernel | ||
| 25 | 27 | ||
| 26 | namespace Service { | 28 | namespace Service { |
| 27 | 29 | ||
| @@ -64,12 +66,19 @@ public: | |||
| 64 | 66 | ||
| 65 | /// Creates a port pair and registers this service with the given ServiceManager. | 67 | /// Creates a port pair and registers this service with the given ServiceManager. |
| 66 | void InstallAsService(SM::ServiceManager& service_manager); | 68 | void InstallAsService(SM::ServiceManager& service_manager); |
| 67 | /// Creates a port pair and registers it on the kernel's global port registry. | 69 | |
| 68 | void InstallAsNamedPort(Kernel::KernelCore& kernel); | 70 | /// Invokes a service request routine using the HIPC protocol. |
| 69 | /// Invokes a service request routine. | ||
| 70 | void InvokeRequest(Kernel::HLERequestContext& ctx); | 71 | void InvokeRequest(Kernel::HLERequestContext& ctx); |
| 72 | |||
| 73 | /// Invokes a service request routine using the HIPC protocol. | ||
| 74 | void InvokeRequestTipc(Kernel::HLERequestContext& ctx); | ||
| 75 | |||
| 76 | /// Creates a port pair and registers it on the kernel's global port registry. | ||
| 77 | Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel); | ||
| 78 | |||
| 71 | /// Handles a synchronization request for the service. | 79 | /// Handles a synchronization request for the service. |
| 72 | ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) override; | 80 | ResultCode HandleSyncRequest(Kernel::KServerSession& session, |
| 81 | Kernel::HLERequestContext& context) override; | ||
| 73 | 82 | ||
| 74 | protected: | 83 | protected: |
| 75 | /// Member-function pointer type of SyncRequest handlers. | 84 | /// Member-function pointer type of SyncRequest handlers. |
| @@ -102,6 +111,7 @@ private: | |||
| 102 | ~ServiceFrameworkBase() override; | 111 | ~ServiceFrameworkBase() override; |
| 103 | 112 | ||
| 104 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); | 113 | void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n); |
| 114 | void RegisterHandlersBaseTipc(const FunctionInfoBase* functions, std::size_t n); | ||
| 105 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); | 115 | void ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, const FunctionInfoBase* info); |
| 106 | 116 | ||
| 107 | /// Identifier string used to connect to the service. | 117 | /// Identifier string used to connect to the service. |
| @@ -116,6 +126,7 @@ private: | |||
| 116 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. | 126 | /// Function used to safely up-cast pointers to the derived class before invoking a handler. |
| 117 | InvokerFn* handler_invoker; | 127 | InvokerFn* handler_invoker; |
| 118 | boost::container::flat_map<u32, FunctionInfoBase> handlers; | 128 | boost::container::flat_map<u32, FunctionInfoBase> handlers; |
| 129 | boost::container::flat_map<u32, FunctionInfoBase> handlers_tipc; | ||
| 119 | 130 | ||
| 120 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. | 131 | /// Used to gain exclusive access to the service members, e.g. from CoreTiming thread. |
| 121 | Common::SpinLock lock_service; | 132 | Common::SpinLock lock_service; |
| @@ -144,17 +155,17 @@ protected: | |||
| 144 | /** | 155 | /** |
| 145 | * Constructs a FunctionInfo for a function. | 156 | * Constructs a FunctionInfo for a function. |
| 146 | * | 157 | * |
| 147 | * @param expected_header request header in the command buffer which will trigger dispatch | 158 | * @param expected_header_ request header in the command buffer which will trigger dispatch |
| 148 | * to this handler | 159 | * to this handler |
| 149 | * @param handler_callback member function in this service which will be called to handle | 160 | * @param handler_callback_ member function in this service which will be called to handle |
| 150 | * the request | 161 | * the request |
| 151 | * @param name human-friendly name for the request. Used mostly for logging purposes. | 162 | * @param name_ human-friendly name for the request. Used mostly for logging purposes. |
| 152 | */ | 163 | */ |
| 153 | FunctionInfo(u32 expected_header, HandlerFnP<Self> handler_callback, const char* name) | 164 | FunctionInfo(u32 expected_header_, HandlerFnP<Self> handler_callback_, const char* name_) |
| 154 | : FunctionInfoBase{ | 165 | : FunctionInfoBase{ |
| 155 | expected_header, | 166 | expected_header_, |
| 156 | // Type-erase member function pointer by casting it down to the base class. | 167 | // Type-erase member function pointer by casting it down to the base class. |
| 157 | static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback), name} {} | 168 | static_cast<HandlerFnP<ServiceFrameworkBase>>(handler_callback_), name_} {} |
| 158 | }; | 169 | }; |
| 159 | 170 | ||
| 160 | /** | 171 | /** |
| @@ -183,6 +194,20 @@ protected: | |||
| 183 | RegisterHandlersBase(functions, n); | 194 | RegisterHandlersBase(functions, n); |
| 184 | } | 195 | } |
| 185 | 196 | ||
| 197 | /// Registers handlers in the service. | ||
| 198 | template <std::size_t N> | ||
| 199 | void RegisterHandlersTipc(const FunctionInfo (&functions)[N]) { | ||
| 200 | RegisterHandlersTipc(functions, N); | ||
| 201 | } | ||
| 202 | |||
| 203 | /** | ||
| 204 | * Registers handlers in the service. Usually prefer using the other RegisterHandlers | ||
| 205 | * overload in order to avoid needing to specify the array size. | ||
| 206 | */ | ||
| 207 | void RegisterHandlersTipc(const FunctionInfo* functions, std::size_t n) { | ||
| 208 | RegisterHandlersBaseTipc(functions, n); | ||
| 209 | } | ||
| 210 | |||
| 186 | private: | 211 | private: |
| 187 | /** | 212 | /** |
| 188 | * This function is used to allow invocation of pointers to handlers stored in the base class | 213 | * This function is used to allow invocation of pointers to handlers stored in the base class |
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp index ee026e22f..147f12147 100644 --- a/src/core/hle/service/sm/controller.cpp +++ b/src/core/hle/service/sm/controller.cpp | |||
| @@ -4,8 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | ||
| 7 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/k_client_port.h" | ||
| 8 | #include "core/hle/kernel/k_client_session.h" | 10 | #include "core/hle/kernel/k_client_session.h" |
| 11 | #include "core/hle/kernel/k_port.h" | ||
| 12 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 13 | #include "core/hle/kernel/k_server_port.h" | ||
| 9 | #include "core/hle/kernel/k_server_session.h" | 14 | #include "core/hle/kernel/k_server_session.h" |
| 10 | #include "core/hle/kernel/k_session.h" | 15 | #include "core/hle/kernel/k_session.h" |
| 11 | #include "core/hle/service/sm/controller.h" | 16 | #include "core/hle/service/sm/controller.h" |
| @@ -13,7 +18,7 @@ | |||
| 13 | namespace Service::SM { | 18 | namespace Service::SM { |
| 14 | 19 | ||
| 15 | void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { | 20 | void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { |
| 16 | ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain"); | 21 | ASSERT_MSG(!ctx.Session()->IsDomain(), "Session is already a domain"); |
| 17 | LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); | 22 | LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); |
| 18 | ctx.Session()->ConvertToDomain(); | 23 | ctx.Session()->ConvertToDomain(); |
| 19 | 24 | ||
| @@ -26,15 +31,43 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { | |||
| 26 | // TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong | 31 | // TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong |
| 27 | // and that we probably want to actually make an entirely new Session, but we still need to | 32 | // and that we probably want to actually make an entirely new Session, but we still need to |
| 28 | // verify this on hardware. | 33 | // verify this on hardware. |
| 34 | |||
| 29 | LOG_DEBUG(Service, "called"); | 35 | LOG_DEBUG(Service, "called"); |
| 30 | 36 | ||
| 37 | auto& kernel = system.Kernel(); | ||
| 38 | auto* session = ctx.Session()->GetParent(); | ||
| 39 | auto* port = session->GetParent()->GetParent(); | ||
| 40 | |||
| 41 | // Reserve a new session from the process resource limit. | ||
| 42 | Kernel::KScopedResourceReservation session_reservation( | ||
| 43 | kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions); | ||
| 44 | if (!session_reservation.Succeeded()) { | ||
| 45 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 46 | rb.Push(Kernel::ResultLimitReached); | ||
| 47 | } | ||
| 48 | |||
| 49 | // Create a new session. | ||
| 50 | auto* clone = Kernel::KSession::Create(kernel); | ||
| 51 | clone->Initialize(&port->GetClientPort(), session->GetName()); | ||
| 52 | |||
| 53 | // Commit the session reservation. | ||
| 54 | session_reservation.Commit(); | ||
| 55 | |||
| 56 | // Enqueue the session with the named port. | ||
| 57 | port->EnqueueSession(&clone->GetServerSession()); | ||
| 58 | |||
| 59 | // Set the session request manager. | ||
| 60 | clone->GetServerSession().SetSessionRequestManager( | ||
| 61 | session->GetServerSession().GetSessionRequestManager()); | ||
| 62 | |||
| 63 | // We succeeded. | ||
| 31 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 64 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; |
| 32 | rb.Push(RESULT_SUCCESS); | 65 | rb.Push(RESULT_SUCCESS); |
| 33 | rb.PushMoveObjects(ctx.Session()->GetParent()->GetClientSession()); | 66 | rb.PushMoveObjects(clone->GetClientSession()); |
| 34 | } | 67 | } |
| 35 | 68 | ||
| 36 | void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { | 69 | void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { |
| 37 | LOG_WARNING(Service, "(STUBBED) called, using CloneCurrentObject"); | 70 | LOG_DEBUG(Service, "called"); |
| 38 | 71 | ||
| 39 | CloneCurrentObject(ctx); | 72 | CloneCurrentObject(ctx); |
| 40 | } | 73 | } |
| @@ -44,7 +77,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) { | |||
| 44 | 77 | ||
| 45 | IPC::ResponseBuilder rb{ctx, 3}; | 78 | IPC::ResponseBuilder rb{ctx, 3}; |
| 46 | rb.Push(RESULT_SUCCESS); | 79 | rb.Push(RESULT_SUCCESS); |
| 47 | rb.Push<u16>(0x1000); | 80 | rb.Push<u16>(0x8000); |
| 48 | } | 81 | } |
| 49 | 82 | ||
| 50 | // https://switchbrew.org/wiki/IPC_Marshalling | 83 | // https://switchbrew.org/wiki/IPC_Marshalling |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 568effbc9..a9bc7da74 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "core/hle/kernel/k_client_port.h" | 9 | #include "core/hle/kernel/k_client_port.h" |
| 10 | #include "core/hle/kernel/k_client_session.h" | 10 | #include "core/hle/kernel/k_client_session.h" |
| 11 | #include "core/hle/kernel/k_port.h" | 11 | #include "core/hle/kernel/k_port.h" |
| 12 | #include "core/hle/kernel/k_scoped_resource_reservation.h" | ||
| 12 | #include "core/hle/kernel/k_server_port.h" | 13 | #include "core/hle/kernel/k_server_port.h" |
| 13 | #include "core/hle/kernel/k_server_session.h" | 14 | #include "core/hle/kernel/k_server_session.h" |
| 14 | #include "core/hle/kernel/k_session.h" | 15 | #include "core/hle/kernel/k_session.h" |
| @@ -18,6 +19,7 @@ | |||
| 18 | 19 | ||
| 19 | namespace Service::SM { | 20 | namespace Service::SM { |
| 20 | 21 | ||
| 22 | constexpr ResultCode ERR_NOT_INITIALIZED(ErrorModule::SM, 2); | ||
| 21 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); | 23 | constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); |
| 22 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); | 24 | constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); |
| 23 | constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); | 25 | constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); |
| @@ -34,20 +36,17 @@ static ResultCode ValidateServiceName(const std::string& name) { | |||
| 34 | LOG_ERROR(Service_SM, "Invalid service name! service={}", name); | 36 | LOG_ERROR(Service_SM, "Invalid service name! service={}", name); |
| 35 | return ERR_INVALID_NAME; | 37 | return ERR_INVALID_NAME; |
| 36 | } | 38 | } |
| 37 | if (name.rfind('\0') != std::string::npos) { | ||
| 38 | LOG_ERROR(Service_SM, "A non null terminated service was passed"); | ||
| 39 | return ERR_INVALID_NAME; | ||
| 40 | } | ||
| 41 | return RESULT_SUCCESS; | 39 | return RESULT_SUCCESS; |
| 42 | } | 40 | } |
| 43 | 41 | ||
| 44 | void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system) { | 42 | Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core::System& system) { |
| 45 | ASSERT(self->sm_interface.expired()); | 43 | ASSERT(self.sm_interface.expired()); |
| 46 | 44 | ||
| 47 | auto sm = std::make_shared<SM>(self, system); | 45 | auto sm = std::make_shared<SM>(self, system); |
| 48 | sm->InstallAsNamedPort(system.Kernel()); | 46 | self.sm_interface = sm; |
| 49 | self->sm_interface = sm; | 47 | self.controller_interface = std::make_unique<Controller>(system); |
| 50 | self->controller_interface = std::make_unique<Controller>(system); | 48 | |
| 49 | return sm->CreatePort(system.Kernel()); | ||
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, | 52 | ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, |
| @@ -107,52 +106,81 @@ SM::~SM() = default; | |||
| 107 | void SM::Initialize(Kernel::HLERequestContext& ctx) { | 106 | void SM::Initialize(Kernel::HLERequestContext& ctx) { |
| 108 | LOG_DEBUG(Service_SM, "called"); | 107 | LOG_DEBUG(Service_SM, "called"); |
| 109 | 108 | ||
| 109 | is_initialized = true; | ||
| 110 | |||
| 110 | IPC::ResponseBuilder rb{ctx, 2}; | 111 | IPC::ResponseBuilder rb{ctx, 2}; |
| 111 | rb.Push(RESULT_SUCCESS); | 112 | rb.Push(RESULT_SUCCESS); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | void SM::GetService(Kernel::HLERequestContext& ctx) { | 115 | void SM::GetService(Kernel::HLERequestContext& ctx) { |
| 115 | IPC::RequestParser rp{ctx}; | 116 | auto result = GetServiceImpl(ctx); |
| 117 | if (result.Succeeded()) { | ||
| 118 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | ||
| 119 | rb.Push(result.Code()); | ||
| 120 | rb.PushMoveObjects(result.Unwrap()); | ||
| 121 | } else { | ||
| 122 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 123 | rb.Push(result.Code()); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | void SM::GetServiceTipc(Kernel::HLERequestContext& ctx) { | ||
| 128 | auto result = GetServiceImpl(ctx); | ||
| 129 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | ||
| 130 | rb.Push(result.Code()); | ||
| 131 | rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr); | ||
| 132 | } | ||
| 133 | |||
| 134 | static std::string PopServiceName(IPC::RequestParser& rp) { | ||
| 116 | auto name_buf = rp.PopRaw<std::array<char, 8>>(); | 135 | auto name_buf = rp.PopRaw<std::array<char, 8>>(); |
| 117 | auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | 136 | std::string result; |
| 137 | for (const auto& c : name_buf) { | ||
| 138 | if (c >= ' ' && c <= '~') { | ||
| 139 | result.push_back(c); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | return result; | ||
| 143 | } | ||
| 144 | |||
| 145 | ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ctx) { | ||
| 146 | if (!is_initialized) { | ||
| 147 | return ERR_NOT_INITIALIZED; | ||
| 148 | } | ||
| 118 | 149 | ||
| 119 | std::string name(name_buf.begin(), end); | 150 | IPC::RequestParser rp{ctx}; |
| 151 | std::string name(PopServiceName(rp)); | ||
| 120 | 152 | ||
| 121 | auto result = service_manager->GetServicePort(name); | 153 | // Find the named port. |
| 154 | auto result = service_manager.GetServicePort(name); | ||
| 122 | if (result.Failed()) { | 155 | if (result.Failed()) { |
| 123 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 124 | rb.Push(result.Code()); | ||
| 125 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw); | 156 | LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw); |
| 126 | if (name.length() == 0) | 157 | return result.Code(); |
| 127 | return; // LibNX Fix | ||
| 128 | UNIMPLEMENTED(); | ||
| 129 | return; | ||
| 130 | } | 158 | } |
| 131 | |||
| 132 | auto* port = result.Unwrap(); | 159 | auto* port = result.Unwrap(); |
| 133 | 160 | ||
| 161 | // Reserve a new session from the process resource limit. | ||
| 162 | Kernel::KScopedResourceReservation session_reservation( | ||
| 163 | kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions); | ||
| 164 | R_UNLESS(session_reservation.Succeeded(), Kernel::ResultLimitReached); | ||
| 165 | |||
| 166 | // Create a new session. | ||
| 134 | auto* session = Kernel::KSession::Create(kernel); | 167 | auto* session = Kernel::KSession::Create(kernel); |
| 135 | session->Initialize(&port->GetClientPort(), std::move(name)); | 168 | session->Initialize(&port->GetClientPort(), std::move(name)); |
| 136 | 169 | ||
| 137 | if (port->GetServerPort().GetHLEHandler()) { | 170 | // Commit the session reservation. |
| 138 | port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession()); | 171 | session_reservation.Commit(); |
| 139 | } else { | 172 | |
| 140 | port->EnqueueSession(&session->GetServerSession()); | 173 | // Enqueue the session with the named port. |
| 141 | } | 174 | port->EnqueueSession(&session->GetServerSession()); |
| 142 | 175 | ||
| 143 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); | 176 | LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); |
| 144 | IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; | 177 | |
| 145 | rb.Push(RESULT_SUCCESS); | 178 | return MakeResult(&session->GetClientSession()); |
| 146 | rb.PushMoveObjects(session->GetClientSession()); | ||
| 147 | } | 179 | } |
| 148 | 180 | ||
| 149 | void SM::RegisterService(Kernel::HLERequestContext& ctx) { | 181 | void SM::RegisterService(Kernel::HLERequestContext& ctx) { |
| 150 | IPC::RequestParser rp{ctx}; | 182 | IPC::RequestParser rp{ctx}; |
| 151 | 183 | std::string name(PopServiceName(rp)); | |
| 152 | const auto name_buf = rp.PopRaw<std::array<char, 8>>(); | ||
| 153 | const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | ||
| 154 | |||
| 155 | const std::string name(name_buf.begin(), end); | ||
| 156 | 184 | ||
| 157 | const auto is_light = static_cast<bool>(rp.PopRaw<u32>()); | 185 | const auto is_light = static_cast<bool>(rp.PopRaw<u32>()); |
| 158 | const auto max_session_count = rp.PopRaw<u32>(); | 186 | const auto max_session_count = rp.PopRaw<u32>(); |
| @@ -160,7 +188,7 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { | |||
| 160 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, | 188 | LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, |
| 161 | max_session_count, is_light); | 189 | max_session_count, is_light); |
| 162 | 190 | ||
| 163 | auto handle = service_manager->RegisterService(name, max_session_count); | 191 | auto handle = service_manager.RegisterService(name, max_session_count); |
| 164 | if (handle.Failed()) { | 192 | if (handle.Failed()) { |
| 165 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", | 193 | LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", |
| 166 | handle.Code().raw); | 194 | handle.Code().raw); |
| @@ -178,28 +206,31 @@ void SM::RegisterService(Kernel::HLERequestContext& ctx) { | |||
| 178 | 206 | ||
| 179 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { | 207 | void SM::UnregisterService(Kernel::HLERequestContext& ctx) { |
| 180 | IPC::RequestParser rp{ctx}; | 208 | IPC::RequestParser rp{ctx}; |
| 209 | std::string name(PopServiceName(rp)); | ||
| 181 | 210 | ||
| 182 | const auto name_buf = rp.PopRaw<std::array<char, 8>>(); | ||
| 183 | const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); | ||
| 184 | |||
| 185 | const std::string name(name_buf.begin(), end); | ||
| 186 | LOG_DEBUG(Service_SM, "called with name={}", name); | 211 | LOG_DEBUG(Service_SM, "called with name={}", name); |
| 187 | 212 | ||
| 188 | IPC::ResponseBuilder rb{ctx, 2}; | 213 | IPC::ResponseBuilder rb{ctx, 2}; |
| 189 | rb.Push(service_manager->UnregisterService(name)); | 214 | rb.Push(service_manager.UnregisterService(name)); |
| 190 | } | 215 | } |
| 191 | 216 | ||
| 192 | SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) | 217 | SM::SM(ServiceManager& service_manager_, Core::System& system_) |
| 193 | : ServiceFramework{system_, "sm:", 4}, | 218 | : ServiceFramework{system_, "sm:", 4}, |
| 194 | service_manager{std::move(service_manager_)}, kernel{system_.Kernel()} { | 219 | service_manager{service_manager_}, kernel{system_.Kernel()} { |
| 195 | static const FunctionInfo functions[] = { | 220 | RegisterHandlers({ |
| 196 | {0, &SM::Initialize, "Initialize"}, | 221 | {0, &SM::Initialize, "Initialize"}, |
| 197 | {1, &SM::GetService, "GetService"}, | 222 | {1, &SM::GetService, "GetService"}, |
| 198 | {2, &SM::RegisterService, "RegisterService"}, | 223 | {2, &SM::RegisterService, "RegisterService"}, |
| 199 | {3, &SM::UnregisterService, "UnregisterService"}, | 224 | {3, &SM::UnregisterService, "UnregisterService"}, |
| 200 | {4, nullptr, "DetachClient"}, | 225 | {4, nullptr, "DetachClient"}, |
| 201 | }; | 226 | }); |
| 202 | RegisterHandlers(functions); | 227 | RegisterHandlersTipc({ |
| 228 | {0, &SM::Initialize, "Initialize"}, | ||
| 229 | {1, &SM::GetServiceTipc, "GetService"}, | ||
| 230 | {2, &SM::RegisterService, "RegisterService"}, | ||
| 231 | {3, &SM::UnregisterService, "UnregisterService"}, | ||
| 232 | {4, nullptr, "DetachClient"}, | ||
| 233 | }); | ||
| 203 | } | 234 | } |
| 204 | 235 | ||
| 205 | } // namespace Service::SM | 236 | } // namespace Service::SM |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index af5010c3b..ea37f11d4 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -34,22 +34,26 @@ class Controller; | |||
| 34 | /// Interface to "sm:" service | 34 | /// Interface to "sm:" service |
| 35 | class SM final : public ServiceFramework<SM> { | 35 | class SM final : public ServiceFramework<SM> { |
| 36 | public: | 36 | public: |
| 37 | explicit SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_); | 37 | explicit SM(ServiceManager& service_manager_, Core::System& system_); |
| 38 | ~SM() override; | 38 | ~SM() override; |
| 39 | 39 | ||
| 40 | private: | 40 | private: |
| 41 | void Initialize(Kernel::HLERequestContext& ctx); | 41 | void Initialize(Kernel::HLERequestContext& ctx); |
| 42 | void GetService(Kernel::HLERequestContext& ctx); | 42 | void GetService(Kernel::HLERequestContext& ctx); |
| 43 | void GetServiceTipc(Kernel::HLERequestContext& ctx); | ||
| 43 | void RegisterService(Kernel::HLERequestContext& ctx); | 44 | void RegisterService(Kernel::HLERequestContext& ctx); |
| 44 | void UnregisterService(Kernel::HLERequestContext& ctx); | 45 | void UnregisterService(Kernel::HLERequestContext& ctx); |
| 45 | 46 | ||
| 46 | std::shared_ptr<ServiceManager> service_manager; | 47 | ResultVal<Kernel::KClientSession*> GetServiceImpl(Kernel::HLERequestContext& ctx); |
| 48 | |||
| 49 | ServiceManager& service_manager; | ||
| 50 | bool is_initialized{}; | ||
| 47 | Kernel::KernelCore& kernel; | 51 | Kernel::KernelCore& kernel; |
| 48 | }; | 52 | }; |
| 49 | 53 | ||
| 50 | class ServiceManager { | 54 | class ServiceManager { |
| 51 | public: | 55 | public: |
| 52 | static void InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system); | 56 | static Kernel::KClientPort& InterfaceFactory(ServiceManager& self, Core::System& system); |
| 53 | 57 | ||
| 54 | explicit ServiceManager(Kernel::KernelCore& kernel_); | 58 | explicit ServiceManager(Kernel::KernelCore& kernel_); |
| 55 | ~ServiceManager(); | 59 | ~ServiceManager(); |
| @@ -69,7 +73,7 @@ public: | |||
| 69 | if (port == nullptr) { | 73 | if (port == nullptr) { |
| 70 | return nullptr; | 74 | return nullptr; |
| 71 | } | 75 | } |
| 72 | return std::static_pointer_cast<T>(port->GetServerPort().GetHLEHandler()); | 76 | return std::static_pointer_cast<T>(port->GetServerPort().GetSessionRequestHandler()); |
| 73 | } | 77 | } |
| 74 | 78 | ||
| 75 | void InvokeControlRequest(Kernel::HLERequestContext& context); | 79 | void InvokeControlRequest(Kernel::HLERequestContext& context); |
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 2c8899ae0..3b072f6bc 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp | |||
| @@ -128,7 +128,7 @@ private: | |||
| 128 | 128 | ||
| 129 | LOG_WARNING(Service_SSL, "(STUBBED) called"); | 129 | LOG_WARNING(Service_SSL, "(STUBBED) called"); |
| 130 | 130 | ||
| 131 | IPC::ResponseBuilder rb{ctx, 2}; | 131 | IPC::ResponseBuilder rb{ctx, 4}; |
| 132 | rb.Push(RESULT_SUCCESS); | 132 | rb.Push(RESULT_SUCCESS); |
| 133 | rb.Push(client_id); | 133 | rb.Push(client_id); |
| 134 | } | 134 | } |
diff --git a/src/core/hle/service/time/ephemeral_network_system_clock_core.h b/src/core/hle/service/time/ephemeral_network_system_clock_core.h index 4c6cdef86..d12cb5335 100644 --- a/src/core/hle/service/time/ephemeral_network_system_clock_core.h +++ b/src/core/hle/service/time/ephemeral_network_system_clock_core.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Time::Clock { | |||
| 10 | 10 | ||
| 11 | class EphemeralNetworkSystemClockCore final : public SystemClockCore { | 11 | class EphemeralNetworkSystemClockCore final : public SystemClockCore { |
| 12 | public: | 12 | public: |
| 13 | explicit EphemeralNetworkSystemClockCore(SteadyClockCore& steady_clock_core) | 13 | explicit EphemeralNetworkSystemClockCore(SteadyClockCore& steady_clock_core_) |
| 14 | : SystemClockCore{steady_clock_core} {} | 14 | : SystemClockCore{steady_clock_core_} {} |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | } // namespace Service::Time::Clock | 17 | } // namespace Service::Time::Clock |
diff --git a/src/core/hle/service/time/local_system_clock_context_writer.h b/src/core/hle/service/time/local_system_clock_context_writer.h index 7050844c6..490d0ef3e 100644 --- a/src/core/hle/service/time/local_system_clock_context_writer.h +++ b/src/core/hle/service/time/local_system_clock_context_writer.h | |||
| @@ -12,8 +12,8 @@ namespace Service::Time::Clock { | |||
| 12 | 12 | ||
| 13 | class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback { | 13 | class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback { |
| 14 | public: | 14 | public: |
| 15 | explicit LocalSystemClockContextWriter(SharedMemory& shared_memory) | 15 | explicit LocalSystemClockContextWriter(SharedMemory& shared_memory_) |
| 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {} | 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {} |
| 17 | 17 | ||
| 18 | protected: | 18 | protected: |
| 19 | ResultCode Update() override { | 19 | ResultCode Update() override { |
diff --git a/src/core/hle/service/time/network_system_clock_context_writer.h b/src/core/hle/service/time/network_system_clock_context_writer.h index 94d8788ff..e2920b8eb 100644 --- a/src/core/hle/service/time/network_system_clock_context_writer.h +++ b/src/core/hle/service/time/network_system_clock_context_writer.h | |||
| @@ -12,8 +12,8 @@ namespace Service::Time::Clock { | |||
| 12 | 12 | ||
| 13 | class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback { | 13 | class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback { |
| 14 | public: | 14 | public: |
| 15 | explicit NetworkSystemClockContextWriter(SharedMemory& shared_memory) | 15 | explicit NetworkSystemClockContextWriter(SharedMemory& shared_memory_) |
| 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {} | 16 | : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {} |
| 17 | 17 | ||
| 18 | protected: | 18 | protected: |
| 19 | ResultCode Update() override { | 19 | ResultCode Update() override { |
diff --git a/src/core/hle/service/time/standard_local_system_clock_core.h b/src/core/hle/service/time/standard_local_system_clock_core.h index 8c1882eb1..6320c7af1 100644 --- a/src/core/hle/service/time/standard_local_system_clock_core.h +++ b/src/core/hle/service/time/standard_local_system_clock_core.h | |||
| @@ -10,8 +10,8 @@ namespace Service::Time::Clock { | |||
| 10 | 10 | ||
| 11 | class StandardLocalSystemClockCore final : public SystemClockCore { | 11 | class StandardLocalSystemClockCore final : public SystemClockCore { |
| 12 | public: | 12 | public: |
| 13 | explicit StandardLocalSystemClockCore(SteadyClockCore& steady_clock_core) | 13 | explicit StandardLocalSystemClockCore(SteadyClockCore& steady_clock_core_) |
| 14 | : SystemClockCore{steady_clock_core} {} | 14 | : SystemClockCore{steady_clock_core_} {} |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | } // namespace Service::Time::Clock | 17 | } // namespace Service::Time::Clock |
diff --git a/src/core/hle/service/time/standard_network_system_clock_core.h b/src/core/hle/service/time/standard_network_system_clock_core.h index c993bdf79..9d0aeaedb 100644 --- a/src/core/hle/service/time/standard_network_system_clock_core.h +++ b/src/core/hle/service/time/standard_network_system_clock_core.h | |||
| @@ -16,21 +16,21 @@ namespace Service::Time::Clock { | |||
| 16 | 16 | ||
| 17 | class StandardNetworkSystemClockCore final : public SystemClockCore { | 17 | class StandardNetworkSystemClockCore final : public SystemClockCore { |
| 18 | public: | 18 | public: |
| 19 | explicit StandardNetworkSystemClockCore(SteadyClockCore& steady_clock_core) | 19 | explicit StandardNetworkSystemClockCore(SteadyClockCore& steady_clock_core_) |
| 20 | : SystemClockCore{steady_clock_core} {} | 20 | : SystemClockCore{steady_clock_core_} {} |
| 21 | 21 | ||
| 22 | void SetStandardNetworkClockSufficientAccuracy(TimeSpanType value) { | 22 | void SetStandardNetworkClockSufficientAccuracy(TimeSpanType value) { |
| 23 | standard_network_clock_sufficient_accuracy = value; | 23 | standard_network_clock_sufficient_accuracy = value; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) const { | 26 | bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) const { |
| 27 | SystemClockContext context{}; | 27 | SystemClockContext clock_ctx{}; |
| 28 | if (GetClockContext(system, context) != RESULT_SUCCESS) { | 28 | if (GetClockContext(system, clock_ctx) != RESULT_SUCCESS) { |
| 29 | return {}; | 29 | return {}; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | s64 span{}; | 32 | s64 span{}; |
| 33 | if (context.steady_time_point.GetSpanBetween( | 33 | if (clock_ctx.steady_time_point.GetSpanBetween( |
| 34 | GetSteadyClockCore().GetCurrentTimePoint(system), span) != RESULT_SUCCESS) { | 34 | GetSteadyClockCore().GetCurrentTimePoint(system), span) != RESULT_SUCCESS) { |
| 35 | return {}; | 35 | return {}; |
| 36 | } | 36 | } |
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.cpp b/src/core/hle/service/time/standard_user_system_clock_core.cpp index 7f47b12b8..41bc01abd 100644 --- a/src/core/hle/service/time/standard_user_system_clock_core.cpp +++ b/src/core/hle/service/time/standard_user_system_clock_core.cpp | |||
| @@ -11,13 +11,13 @@ | |||
| 11 | namespace Service::Time::Clock { | 11 | namespace Service::Time::Clock { |
| 12 | 12 | ||
| 13 | StandardUserSystemClockCore::StandardUserSystemClockCore( | 13 | StandardUserSystemClockCore::StandardUserSystemClockCore( |
| 14 | StandardLocalSystemClockCore& local_system_clock_core, | 14 | StandardLocalSystemClockCore& local_system_clock_core_, |
| 15 | StandardNetworkSystemClockCore& network_system_clock_core, Core::System& system) | 15 | StandardNetworkSystemClockCore& network_system_clock_core_, Core::System& system_) |
| 16 | : SystemClockCore(local_system_clock_core.GetSteadyClockCore()), | 16 | : SystemClockCore(local_system_clock_core_.GetSteadyClockCore()), |
| 17 | local_system_clock_core{local_system_clock_core}, | 17 | local_system_clock_core{local_system_clock_core_}, |
| 18 | network_system_clock_core{network_system_clock_core}, auto_correction_enabled{}, | 18 | network_system_clock_core{network_system_clock_core_}, |
| 19 | auto_correction_time{SteadyClockTimePoint::GetRandom()}, auto_correction_event{ | 19 | auto_correction_time{SteadyClockTimePoint::GetRandom()}, auto_correction_event{ |
| 20 | system.Kernel()} { | 20 | system_.Kernel()} { |
| 21 | Kernel::KAutoObject::Create(std::addressof(auto_correction_event)); | 21 | Kernel::KAutoObject::Create(std::addressof(auto_correction_event)); |
| 22 | auto_correction_event.Initialize("StandardUserSystemClockCore:AutoCorrectionEvent"); | 22 | auto_correction_event.Initialize("StandardUserSystemClockCore:AutoCorrectionEvent"); |
| 23 | } | 23 | } |
| @@ -35,13 +35,13 @@ ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::Syst | |||
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system, | 37 | ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system, |
| 38 | SystemClockContext& context) const { | 38 | SystemClockContext& ctx) const { |
| 39 | if (const ResultCode result{ApplyAutomaticCorrection(system, false)}; | 39 | if (const ResultCode result{ApplyAutomaticCorrection(system, false)}; |
| 40 | result != RESULT_SUCCESS) { | 40 | result != RESULT_SUCCESS) { |
| 41 | return result; | 41 | return result; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | return local_system_clock_core.GetClockContext(system, context); | 44 | return local_system_clock_core.GetClockContext(system, ctx); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext&) { | 47 | ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext&) { |
| @@ -64,13 +64,13 @@ ResultCode StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& s | |||
| 64 | return ERROR_UNINITIALIZED_CLOCK; | 64 | return ERROR_UNINITIALIZED_CLOCK; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | SystemClockContext context{}; | 67 | SystemClockContext ctx{}; |
| 68 | if (const ResultCode result{network_system_clock_core.GetClockContext(system, context)}; | 68 | if (const ResultCode result{network_system_clock_core.GetClockContext(system, ctx)}; |
| 69 | result != RESULT_SUCCESS) { | 69 | result != RESULT_SUCCESS) { |
| 70 | return result; | 70 | return result; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | local_system_clock_core.SetClockContext(context); | 73 | local_system_clock_core.SetClockContext(ctx); |
| 74 | 74 | ||
| 75 | return RESULT_SUCCESS; | 75 | return RESULT_SUCCESS; |
| 76 | } | 76 | } |
diff --git a/src/core/hle/service/time/standard_user_system_clock_core.h b/src/core/hle/service/time/standard_user_system_clock_core.h index 1bff8a5af..bf9ec5e42 100644 --- a/src/core/hle/service/time/standard_user_system_clock_core.h +++ b/src/core/hle/service/time/standard_user_system_clock_core.h | |||
| @@ -23,13 +23,13 @@ class StandardNetworkSystemClockCore; | |||
| 23 | 23 | ||
| 24 | class StandardUserSystemClockCore final : public SystemClockCore { | 24 | class StandardUserSystemClockCore final : public SystemClockCore { |
| 25 | public: | 25 | public: |
| 26 | StandardUserSystemClockCore(StandardLocalSystemClockCore& local_system_clock_core, | 26 | StandardUserSystemClockCore(StandardLocalSystemClockCore& local_system_clock_core_, |
| 27 | StandardNetworkSystemClockCore& network_system_clock_core, | 27 | StandardNetworkSystemClockCore& network_system_clock_core_, |
| 28 | Core::System& system); | 28 | Core::System& system_); |
| 29 | 29 | ||
| 30 | ResultCode SetAutomaticCorrectionEnabled(Core::System& system, bool value); | 30 | ResultCode SetAutomaticCorrectionEnabled(Core::System& system, bool value); |
| 31 | 31 | ||
| 32 | ResultCode GetClockContext(Core::System& system, SystemClockContext& context) const override; | 32 | ResultCode GetClockContext(Core::System& system, SystemClockContext& ctx) const override; |
| 33 | 33 | ||
| 34 | bool IsAutomaticCorrectionEnabled() const { | 34 | bool IsAutomaticCorrectionEnabled() const { |
| 35 | return auto_correction_enabled; | 35 | return auto_correction_enabled; |
diff --git a/src/core/hle/service/time/system_clock_core.cpp b/src/core/hle/service/time/system_clock_core.cpp index 46fc8c6c3..2ef442b56 100644 --- a/src/core/hle/service/time/system_clock_core.cpp +++ b/src/core/hle/service/time/system_clock_core.cpp | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | namespace Service::Time::Clock { | 9 | namespace Service::Time::Clock { |
| 10 | 10 | ||
| 11 | SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core) | 11 | SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core_) |
| 12 | : steady_clock_core{steady_clock_core} { | 12 | : steady_clock_core{steady_clock_core_} { |
| 13 | context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId(); | 13 | context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId(); |
| 14 | } | 14 | } |
| 15 | 15 | ||
diff --git a/src/core/hle/service/time/system_clock_core.h b/src/core/hle/service/time/system_clock_core.h index 82a8b79ff..b8e6122bf 100644 --- a/src/core/hle/service/time/system_clock_core.h +++ b/src/core/hle/service/time/system_clock_core.h | |||
| @@ -21,7 +21,7 @@ class SystemClockContextUpdateCallback; | |||
| 21 | 21 | ||
| 22 | class SystemClockCore { | 22 | class SystemClockCore { |
| 23 | public: | 23 | public: |
| 24 | explicit SystemClockCore(SteadyClockCore& steady_clock_core); | 24 | explicit SystemClockCore(SteadyClockCore& steady_clock_core_); |
| 25 | virtual ~SystemClockCore(); | 25 | virtual ~SystemClockCore(); |
| 26 | 26 | ||
| 27 | SteadyClockCore& GetSteadyClockCore() const { | 27 | SteadyClockCore& GetSteadyClockCore() const { |
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp index fe01a3739..4f9684de8 100644 --- a/src/core/hle/service/time/time_manager.cpp +++ b/src/core/hle/service/time/time_manager.cpp | |||
| @@ -223,7 +223,7 @@ struct TimeManager::Impl final { | |||
| 223 | TimeZone::TimeZoneContentManager time_zone_content_manager; | 223 | TimeZone::TimeZoneContentManager time_zone_content_manager; |
| 224 | }; | 224 | }; |
| 225 | 225 | ||
| 226 | TimeManager::TimeManager(Core::System& system) : system{system} {} | 226 | TimeManager::TimeManager(Core::System& system_) : system{system_} {} |
| 227 | 227 | ||
| 228 | TimeManager::~TimeManager() = default; | 228 | TimeManager::~TimeManager() = default; |
| 229 | 229 | ||
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h index 4db8cc0e1..3af868d87 100644 --- a/src/core/hle/service/time/time_manager.h +++ b/src/core/hle/service/time/time_manager.h | |||
| @@ -30,7 +30,7 @@ class NetworkSystemClockContextWriter; | |||
| 30 | 30 | ||
| 31 | class TimeManager final { | 31 | class TimeManager final { |
| 32 | public: | 32 | public: |
| 33 | explicit TimeManager(Core::System& system); | 33 | explicit TimeManager(Core::System& system_); |
| 34 | ~TimeManager(); | 34 | ~TimeManager(); |
| 35 | 35 | ||
| 36 | void Initialize(); | 36 | void Initialize(); |
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp index eb57899f6..176ad0eee 100644 --- a/src/core/hle/service/time/time_sharedmemory.cpp +++ b/src/core/hle/service/time/time_sharedmemory.cpp | |||
| @@ -15,7 +15,7 @@ namespace Service::Time { | |||
| 15 | 15 | ||
| 16 | static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000}; | 16 | static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000}; |
| 17 | 17 | ||
| 18 | SharedMemory::SharedMemory(Core::System& system) : system(system) { | 18 | SharedMemory::SharedMemory(Core::System& system_) : system(system_) { |
| 19 | std::memset(system.Kernel().GetTimeSharedMem().GetPointer(), 0, SHARED_MEMORY_SIZE); | 19 | std::memset(system.Kernel().GetTimeSharedMem().GetPointer(), 0, SHARED_MEMORY_SIZE); |
| 20 | } | 20 | } |
| 21 | 21 | ||
diff --git a/src/core/hle/service/time/time_sharedmemory.h b/src/core/hle/service/time/time_sharedmemory.h index 1ad9a286d..d471b5d18 100644 --- a/src/core/hle/service/time/time_sharedmemory.h +++ b/src/core/hle/service/time/time_sharedmemory.h | |||
| @@ -14,7 +14,7 @@ namespace Service::Time { | |||
| 14 | 14 | ||
| 15 | class SharedMemory final { | 15 | class SharedMemory final { |
| 16 | public: | 16 | public: |
| 17 | explicit SharedMemory(Core::System& system); | 17 | explicit SharedMemory(Core::System& system_); |
| 18 | ~SharedMemory(); | 18 | ~SharedMemory(); |
| 19 | 19 | ||
| 20 | // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? | 20 | // TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this? |
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp index 3c8e71a3c..57f71e6f0 100644 --- a/src/core/hle/service/time/time_zone_content_manager.cpp +++ b/src/core/hle/service/time/time_zone_content_manager.cpp | |||
| @@ -68,8 +68,8 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) { | |||
| 68 | return location_name_cache; | 68 | return location_name_cache; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | TimeZoneContentManager::TimeZoneContentManager(Core::System& system) | 71 | TimeZoneContentManager::TimeZoneContentManager(Core::System& system_) |
| 72 | : system{system}, location_name_cache{BuildLocationNameCache(system)} {} | 72 | : system{system_}, location_name_cache{BuildLocationNameCache(system)} {} |
| 73 | 73 | ||
| 74 | void TimeZoneContentManager::Initialize(TimeManager& time_manager) { | 74 | void TimeZoneContentManager::Initialize(TimeManager& time_manager) { |
| 75 | std::string location_name; | 75 | std::string location_name; |
diff --git a/src/core/hle/service/time/time_zone_content_manager.h b/src/core/hle/service/time/time_zone_content_manager.h index 52dd1a020..cfa601084 100644 --- a/src/core/hle/service/time/time_zone_content_manager.h +++ b/src/core/hle/service/time/time_zone_content_manager.h | |||
| @@ -21,7 +21,7 @@ namespace Service::Time::TimeZone { | |||
| 21 | 21 | ||
| 22 | class TimeZoneContentManager final { | 22 | class TimeZoneContentManager final { |
| 23 | public: | 23 | public: |
| 24 | explicit TimeZoneContentManager(Core::System& system); | 24 | explicit TimeZoneContentManager(Core::System& system_); |
| 25 | 25 | ||
| 26 | void Initialize(TimeManager& time_manager); | 26 | void Initialize(TimeManager& time_manager); |
| 27 | 27 | ||
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index becbd36c1..0dd342dbf 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | 17 | ||
| 18 | namespace Service::VI { | 18 | namespace Service::VI { |
| 19 | 19 | ||
| 20 | Display::Display(u64 id, std::string name, Core::System& system) | 20 | Display::Display(u64 id, std::string name_, Core::System& system) |
| 21 | : id{id}, name{std::move(name)}, vsync_event{system.Kernel()} { | 21 | : display_id{id}, name{std::move(name_)}, vsync_event{system.Kernel()} { |
| 22 | Kernel::KAutoObject::Create(std::addressof(vsync_event)); | 22 | Kernel::KAutoObject::Create(std::addressof(vsync_event)); |
| 23 | vsync_event.Initialize(fmt::format("Display VSync Event {}", id)); | 23 | vsync_event.Initialize(fmt::format("Display VSync Event {}", id)); |
| 24 | } | 24 | } |
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 388ce6083..166f2a4cc 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -32,14 +32,14 @@ public: | |||
| 32 | /// Constructs a display with a given unique ID and name. | 32 | /// Constructs a display with a given unique ID and name. |
| 33 | /// | 33 | /// |
| 34 | /// @param id The unique ID for this display. | 34 | /// @param id The unique ID for this display. |
| 35 | /// @param name The name for this display. | 35 | /// @param name_ The name for this display. |
| 36 | /// | 36 | /// |
| 37 | Display(u64 id, std::string name, Core::System& system); | 37 | Display(u64 id, std::string name_, Core::System& system); |
| 38 | ~Display(); | 38 | ~Display(); |
| 39 | 39 | ||
| 40 | /// Gets the unique ID assigned to this display. | 40 | /// Gets the unique ID assigned to this display. |
| 41 | u64 GetID() const { | 41 | u64 GetID() const { |
| 42 | return id; | 42 | return display_id; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | /// Gets the name of this display | 45 | /// Gets the name of this display |
| @@ -96,7 +96,7 @@ public: | |||
| 96 | const Layer* FindLayer(u64 layer_id) const; | 96 | const Layer* FindLayer(u64 layer_id) const; |
| 97 | 97 | ||
| 98 | private: | 98 | private: |
| 99 | u64 id; | 99 | u64 display_id; |
| 100 | std::string name; | 100 | std::string name; |
| 101 | 101 | ||
| 102 | std::vector<std::shared_ptr<Layer>> layers; | 102 | std::vector<std::shared_ptr<Layer>> layers; |
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp index 954225c26..9bc382587 100644 --- a/src/core/hle/service/vi/layer/vi_layer.cpp +++ b/src/core/hle/service/vi/layer/vi_layer.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | namespace Service::VI { | 7 | namespace Service::VI { |
| 8 | 8 | ||
| 9 | Layer::Layer(u64 id, NVFlinger::BufferQueue& queue) : id{id}, buffer_queue{queue} {} | 9 | Layer::Layer(u64 id, NVFlinger::BufferQueue& queue) : layer_id{id}, buffer_queue{queue} {} |
| 10 | 10 | ||
| 11 | Layer::~Layer() = default; | 11 | Layer::~Layer() = default; |
| 12 | 12 | ||
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index c6bfd01f6..ebdd85505 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h | |||
| @@ -31,7 +31,7 @@ public: | |||
| 31 | 31 | ||
| 32 | /// Gets the ID for this layer. | 32 | /// Gets the ID for this layer. |
| 33 | u64 GetID() const { | 33 | u64 GetID() const { |
| 34 | return id; | 34 | return layer_id; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /// Gets a reference to the buffer queue this layer is using. | 37 | /// Gets a reference to the buffer queue this layer is using. |
| @@ -45,7 +45,7 @@ public: | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | private: | 47 | private: |
| 48 | u64 id; | 48 | u64 layer_id; |
| 49 | NVFlinger::BufferQueue& buffer_queue; | 49 | NVFlinger::BufferQueue& buffer_queue; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 32e47a43e..fdd2b4b4f 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -212,7 +212,7 @@ private: | |||
| 212 | 212 | ||
| 213 | class IGBPConnectRequestParcel : public Parcel { | 213 | class IGBPConnectRequestParcel : public Parcel { |
| 214 | public: | 214 | public: |
| 215 | explicit IGBPConnectRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 215 | explicit IGBPConnectRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 216 | Deserialize(); | 216 | Deserialize(); |
| 217 | } | 217 | } |
| 218 | 218 | ||
| @@ -274,8 +274,8 @@ private: | |||
| 274 | 274 | ||
| 275 | class IGBPSetPreallocatedBufferRequestParcel : public Parcel { | 275 | class IGBPSetPreallocatedBufferRequestParcel : public Parcel { |
| 276 | public: | 276 | public: |
| 277 | explicit IGBPSetPreallocatedBufferRequestParcel(std::vector<u8> buffer) | 277 | explicit IGBPSetPreallocatedBufferRequestParcel(std::vector<u8> buffer_) |
| 278 | : Parcel(std::move(buffer)) { | 278 | : Parcel(std::move(buffer_)) { |
| 279 | Deserialize(); | 279 | Deserialize(); |
| 280 | } | 280 | } |
| 281 | 281 | ||
| @@ -312,7 +312,7 @@ protected: | |||
| 312 | 312 | ||
| 313 | class IGBPCancelBufferRequestParcel : public Parcel { | 313 | class IGBPCancelBufferRequestParcel : public Parcel { |
| 314 | public: | 314 | public: |
| 315 | explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 315 | explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 316 | Deserialize(); | 316 | Deserialize(); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| @@ -338,7 +338,7 @@ protected: | |||
| 338 | 338 | ||
| 339 | class IGBPDequeueBufferRequestParcel : public Parcel { | 339 | class IGBPDequeueBufferRequestParcel : public Parcel { |
| 340 | public: | 340 | public: |
| 341 | explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 341 | explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 342 | Deserialize(); | 342 | Deserialize(); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| @@ -360,8 +360,8 @@ public: | |||
| 360 | 360 | ||
| 361 | class IGBPDequeueBufferResponseParcel : public Parcel { | 361 | class IGBPDequeueBufferResponseParcel : public Parcel { |
| 362 | public: | 362 | public: |
| 363 | explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence) | 363 | explicit IGBPDequeueBufferResponseParcel(u32 slot_, Nvidia::MultiFence& multi_fence_) |
| 364 | : slot(slot), multi_fence(multi_fence) {} | 364 | : slot(slot_), multi_fence(multi_fence_) {} |
| 365 | 365 | ||
| 366 | protected: | 366 | protected: |
| 367 | void SerializeData() override { | 367 | void SerializeData() override { |
| @@ -377,7 +377,7 @@ protected: | |||
| 377 | 377 | ||
| 378 | class IGBPRequestBufferRequestParcel : public Parcel { | 378 | class IGBPRequestBufferRequestParcel : public Parcel { |
| 379 | public: | 379 | public: |
| 380 | explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 380 | explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 381 | Deserialize(); | 381 | Deserialize(); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| @@ -391,7 +391,7 @@ public: | |||
| 391 | 391 | ||
| 392 | class IGBPRequestBufferResponseParcel : public Parcel { | 392 | class IGBPRequestBufferResponseParcel : public Parcel { |
| 393 | public: | 393 | public: |
| 394 | explicit IGBPRequestBufferResponseParcel(NVFlinger::IGBPBuffer buffer) : buffer(buffer) {} | 394 | explicit IGBPRequestBufferResponseParcel(NVFlinger::IGBPBuffer buffer_) : buffer(buffer_) {} |
| 395 | ~IGBPRequestBufferResponseParcel() override = default; | 395 | ~IGBPRequestBufferResponseParcel() override = default; |
| 396 | 396 | ||
| 397 | protected: | 397 | protected: |
| @@ -408,7 +408,7 @@ protected: | |||
| 408 | 408 | ||
| 409 | class IGBPQueueBufferRequestParcel : public Parcel { | 409 | class IGBPQueueBufferRequestParcel : public Parcel { |
| 410 | public: | 410 | public: |
| 411 | explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 411 | explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 412 | Deserialize(); | 412 | Deserialize(); |
| 413 | } | 413 | } |
| 414 | 414 | ||
| @@ -470,7 +470,7 @@ private: | |||
| 470 | 470 | ||
| 471 | class IGBPQueryRequestParcel : public Parcel { | 471 | class IGBPQueryRequestParcel : public Parcel { |
| 472 | public: | 472 | public: |
| 473 | explicit IGBPQueryRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { | 473 | explicit IGBPQueryRequestParcel(std::vector<u8> buffer_) : Parcel(std::move(buffer_)) { |
| 474 | Deserialize(); | 474 | Deserialize(); |
| 475 | } | 475 | } |
| 476 | 476 | ||
| @@ -484,7 +484,7 @@ public: | |||
| 484 | 484 | ||
| 485 | class IGBPQueryResponseParcel : public Parcel { | 485 | class IGBPQueryResponseParcel : public Parcel { |
| 486 | public: | 486 | public: |
| 487 | explicit IGBPQueryResponseParcel(u32 value) : value(value) {} | 487 | explicit IGBPQueryResponseParcel(u32 value_) : value{value_} {} |
| 488 | ~IGBPQueryResponseParcel() override = default; | 488 | ~IGBPQueryResponseParcel() override = default; |
| 489 | 489 | ||
| 490 | protected: | 490 | protected: |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 42f023258..022885c1b 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -22,8 +22,8 @@ | |||
| 22 | namespace Loader { | 22 | namespace Loader { |
| 23 | 23 | ||
| 24 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, | 24 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, |
| 25 | bool override_update) | 25 | bool override_update_) |
| 26 | : AppLoader(std::move(file_)), override_update(override_update) { | 26 | : AppLoader(std::move(file_)), override_update(override_update_) { |
| 27 | const auto file_dir = file->GetContainingDirectory(); | 27 | const auto file_dir = file->GetContainingDirectory(); |
| 28 | 28 | ||
| 29 | // Title ID | 29 | // Title ID |
| @@ -48,9 +48,9 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys | |||
| 48 | // Any png, jpeg, or bmp file | 48 | // Any png, jpeg, or bmp file |
| 49 | const auto& files = file_dir->GetFiles(); | 49 | const auto& files = file_dir->GetFiles(); |
| 50 | const auto icon_iter = | 50 | const auto icon_iter = |
| 51 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) { | 51 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& f) { |
| 52 | return file->GetExtension() == "png" || file->GetExtension() == "jpg" || | 52 | return f->GetExtension() == "png" || f->GetExtension() == "jpg" || |
| 53 | file->GetExtension() == "bmp" || file->GetExtension() == "jpeg"; | 53 | f->GetExtension() == "bmp" || f->GetExtension() == "jpeg"; |
| 54 | }); | 54 | }); |
| 55 | if (icon_iter != files.end()) | 55 | if (icon_iter != files.end()) |
| 56 | icon_data = (*icon_iter)->ReadAllBytes(); | 56 | icon_data = (*icon_iter)->ReadAllBytes(); |
| @@ -61,9 +61,8 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys | |||
| 61 | if (nacp_file == nullptr) { | 61 | if (nacp_file == nullptr) { |
| 62 | const auto& files = file_dir->GetFiles(); | 62 | const auto& files = file_dir->GetFiles(); |
| 63 | const auto nacp_iter = | 63 | const auto nacp_iter = |
| 64 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) { | 64 | std::find_if(files.begin(), files.end(), |
| 65 | return file->GetExtension() == "nacp"; | 65 | [](const FileSys::VirtualFile& f) { return f->GetExtension() == "nacp"; }); |
| 66 | }); | ||
| 67 | if (nacp_iter != files.end()) | 66 | if (nacp_iter != files.end()) |
| 68 | nacp_file = *nacp_iter; | 67 | nacp_file = *nacp_iter; |
| 69 | } | 68 | } |
| @@ -75,9 +74,9 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys | |||
| 75 | } | 74 | } |
| 76 | 75 | ||
| 77 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( | 76 | AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( |
| 78 | FileSys::VirtualDir directory, bool override_update) | 77 | FileSys::VirtualDir directory, bool override_update_) |
| 79 | : AppLoader(directory->GetFile("main")), dir(std::move(directory)), | 78 | : AppLoader(directory->GetFile("main")), dir(std::move(directory)), |
| 80 | override_update(override_update) {} | 79 | override_update(override_update_) {} |
| 81 | 80 | ||
| 82 | FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) { | 81 | FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) { |
| 83 | if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) { | 82 | if (FileSys::IsDirectoryExeFS(dir_file->GetContainingDirectory())) { |
| @@ -184,8 +183,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect | |||
| 184 | // Find the RomFS by searching for a ".romfs" file in this directory | 183 | // Find the RomFS by searching for a ".romfs" file in this directory |
| 185 | const auto& files = dir->GetFiles(); | 184 | const auto& files = dir->GetFiles(); |
| 186 | const auto romfs_iter = | 185 | const auto romfs_iter = |
| 187 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& file) { | 186 | std::find_if(files.begin(), files.end(), [](const FileSys::VirtualFile& f) { |
| 188 | return file->GetName().find(".romfs") != std::string::npos; | 187 | return f->GetName().find(".romfs") != std::string::npos; |
| 189 | }); | 188 | }); |
| 190 | 189 | ||
| 191 | // Register the RomFS if a ".romfs" file was found | 190 | // Register the RomFS if a ".romfs" file was found |
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h index a49a8b001..79a4d4db5 100644 --- a/src/core/loader/deconstructed_rom_directory.h +++ b/src/core/loader/deconstructed_rom_directory.h | |||
| @@ -24,11 +24,11 @@ namespace Loader { | |||
| 24 | class AppLoader_DeconstructedRomDirectory final : public AppLoader { | 24 | class AppLoader_DeconstructedRomDirectory final : public AppLoader { |
| 25 | public: | 25 | public: |
| 26 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file, | 26 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file, |
| 27 | bool override_update = false); | 27 | bool override_update_ = false); |
| 28 | 28 | ||
| 29 | // Overload to accept exefs directory. Must contain 'main' and 'main.npdm' | 29 | // Overload to accept exefs directory. Must contain 'main' and 'main.npdm' |
| 30 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory, | 30 | explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory, |
| 31 | bool override_update = false); | 31 | bool override_update_ = false); |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| 34 | * Identifies whether or not the given file is a deconstructed ROM directory. | 34 | * Identifies whether or not the given file is a deconstructed ROM directory. |
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 11b2d0837..d4808fb5b 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp | |||
| @@ -194,7 +194,7 @@ std::ostream& operator<<(std::ostream& os, ResultStatus status) { | |||
| 194 | return os; | 194 | return os; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | AppLoader::AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {} | 197 | AppLoader::AppLoader(FileSys::VirtualFile file_) : file(std::move(file_)) {} |
| 198 | AppLoader::~AppLoader() = default; | 198 | AppLoader::~AppLoader() = default; |
| 199 | 199 | ||
| 200 | /** | 200 | /** |
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 9eac11dec..edc8bb257 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h | |||
| @@ -147,7 +147,7 @@ public: | |||
| 147 | }; | 147 | }; |
| 148 | using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>; | 148 | using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>; |
| 149 | 149 | ||
| 150 | explicit AppLoader(FileSys::VirtualFile file); | 150 | explicit AppLoader(FileSys::VirtualFile file_); |
| 151 | virtual ~AppLoader(); | 151 | virtual ~AppLoader(); |
| 152 | 152 | ||
| 153 | /** | 153 | /** |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index b4c56e1c1..bf2ef7816 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -82,22 +82,6 @@ struct Memory::Impl { | |||
| 82 | return nullptr; | 82 | return nullptr; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | u8* GetKernelBuffer(VAddr start_vaddr, size_t size) { | ||
| 86 | // TODO(bunnei): This is just a workaround until we have kernel memory layout mapped & | ||
| 87 | // managed. Until then, we use this to allocate and access kernel memory regions. | ||
| 88 | |||
| 89 | auto search = kernel_memory_regions.find(start_vaddr); | ||
| 90 | if (search != kernel_memory_regions.end()) { | ||
| 91 | return search->second.get(); | ||
| 92 | } | ||
| 93 | |||
| 94 | std::unique_ptr<u8[]> new_memory_region{new u8[size]}; | ||
| 95 | u8* raw_ptr = new_memory_region.get(); | ||
| 96 | kernel_memory_regions[start_vaddr] = std::move(new_memory_region); | ||
| 97 | |||
| 98 | return raw_ptr; | ||
| 99 | } | ||
| 100 | |||
| 101 | u8 Read8(const VAddr addr) { | 85 | u8 Read8(const VAddr addr) { |
| 102 | return Read<u8>(addr); | 86 | return Read<u8>(addr); |
| 103 | } | 87 | } |
| @@ -727,7 +711,6 @@ struct Memory::Impl { | |||
| 727 | } | 711 | } |
| 728 | 712 | ||
| 729 | Common::PageTable* current_page_table = nullptr; | 713 | Common::PageTable* current_page_table = nullptr; |
| 730 | std::unordered_map<VAddr, std::unique_ptr<u8[]>> kernel_memory_regions; | ||
| 731 | Core::System& system; | 714 | Core::System& system; |
| 732 | }; | 715 | }; |
| 733 | 716 | ||
| @@ -765,10 +748,6 @@ u8* Memory::GetPointer(VAddr vaddr) { | |||
| 765 | return impl->GetPointer(vaddr); | 748 | return impl->GetPointer(vaddr); |
| 766 | } | 749 | } |
| 767 | 750 | ||
| 768 | u8* Memory::GetKernelBuffer(VAddr start_vaddr, size_t size) { | ||
| 769 | return impl->GetKernelBuffer(start_vaddr, size); | ||
| 770 | } | ||
| 771 | |||
| 772 | const u8* Memory::GetPointer(VAddr vaddr) const { | 751 | const u8* Memory::GetPointer(VAddr vaddr) const { |
| 773 | return impl->GetPointer(vaddr); | 752 | return impl->GetPointer(vaddr); |
| 774 | } | 753 | } |
diff --git a/src/core/memory.h b/src/core/memory.h index 345fd870d..c91eeced9 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -121,15 +121,6 @@ public: | |||
| 121 | */ | 121 | */ |
| 122 | u8* GetPointer(VAddr vaddr); | 122 | u8* GetPointer(VAddr vaddr); |
| 123 | 123 | ||
| 124 | /** | ||
| 125 | * Gets a pointer to the start of a kernel heap allocated memory region. Will allocate one if it | ||
| 126 | * does not already exist. | ||
| 127 | * | ||
| 128 | * @param start_vaddr Start virtual address for the memory region. | ||
| 129 | * @param size Size of the memory region. | ||
| 130 | */ | ||
| 131 | u8* GetKernelBuffer(VAddr start_vaddr, size_t size); | ||
| 132 | |||
| 133 | template <typename T> | 124 | template <typename T> |
| 134 | T* GetPointer(VAddr vaddr) { | 125 | T* GetPointer(VAddr vaddr) { |
| 135 | return reinterpret_cast<T*>(GetPointer(vaddr)); | 126 | return reinterpret_cast<T*>(GetPointer(vaddr)); |
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 0f5ef7954..46a7e09b4 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -37,8 +37,8 @@ std::string_view ExtractName(std::string_view data, std::size_t start_index, cha | |||
| 37 | } | 37 | } |
| 38 | } // Anonymous namespace | 38 | } // Anonymous namespace |
| 39 | 39 | ||
| 40 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) | 40 | StandardVmCallbacks::StandardVmCallbacks(System& system_, const CheatProcessMetadata& metadata_) |
| 41 | : metadata(metadata), system(system) {} | 41 | : metadata{metadata_}, system{system_} {} |
| 42 | 42 | ||
| 43 | StandardVmCallbacks::~StandardVmCallbacks() = default; | 43 | StandardVmCallbacks::~StandardVmCallbacks() = default; |
| 44 | 44 | ||
| @@ -174,11 +174,11 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const { | |||
| 174 | return out; | 174 | return out; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | CheatEngine::CheatEngine(Core::System& system, std::vector<CheatEntry> cheats, | 177 | CheatEngine::CheatEngine(System& system_, std::vector<CheatEntry> cheats_, |
| 178 | const std::array<u8, 0x20>& build_id) | 178 | const std::array<u8, 0x20>& build_id_) |
| 179 | : vm{std::make_unique<StandardVmCallbacks>(system, metadata)}, | 179 | : vm{std::make_unique<StandardVmCallbacks>(system_, metadata)}, |
| 180 | cheats(std::move(cheats)), core_timing{system.CoreTiming()}, system{system} { | 180 | cheats(std::move(cheats_)), core_timing{system_.CoreTiming()}, system{system_} { |
| 181 | metadata.main_nso_build_id = build_id; | 181 | metadata.main_nso_build_id = build_id_; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | CheatEngine::~CheatEngine() { | 184 | CheatEngine::~CheatEngine() { |
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h index 5e6f901ec..a8e041d9d 100644 --- a/src/core/memory/cheat_engine.h +++ b/src/core/memory/cheat_engine.h | |||
| @@ -25,7 +25,7 @@ namespace Core::Memory { | |||
| 25 | 25 | ||
| 26 | class StandardVmCallbacks : public DmntCheatVm::Callbacks { | 26 | class StandardVmCallbacks : public DmntCheatVm::Callbacks { |
| 27 | public: | 27 | public: |
| 28 | StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata); | 28 | StandardVmCallbacks(System& system_, const CheatProcessMetadata& metadata_); |
| 29 | ~StandardVmCallbacks() override; | 29 | ~StandardVmCallbacks() override; |
| 30 | 30 | ||
| 31 | void MemoryRead(VAddr address, void* data, u64 size) override; | 31 | void MemoryRead(VAddr address, void* data, u64 size) override; |
| @@ -38,7 +38,7 @@ private: | |||
| 38 | VAddr SanitizeAddress(VAddr address) const; | 38 | VAddr SanitizeAddress(VAddr address) const; |
| 39 | 39 | ||
| 40 | const CheatProcessMetadata& metadata; | 40 | const CheatProcessMetadata& metadata; |
| 41 | Core::System& system; | 41 | System& system; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | // Intermediary class that parses a text file or other disk format for storing cheats into a | 44 | // Intermediary class that parses a text file or other disk format for storing cheats into a |
| @@ -61,8 +61,8 @@ public: | |||
| 61 | // Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming | 61 | // Class that encapsulates a CheatList and manages its interaction with memory and CoreTiming |
| 62 | class CheatEngine final { | 62 | class CheatEngine final { |
| 63 | public: | 63 | public: |
| 64 | CheatEngine(Core::System& system_, std::vector<CheatEntry> cheats_, | 64 | CheatEngine(System& system_, std::vector<CheatEntry> cheats_, |
| 65 | const std::array<u8, 0x20>& build_id); | 65 | const std::array<u8, 0x20>& build_id_); |
| 66 | ~CheatEngine(); | 66 | ~CheatEngine(); |
| 67 | 67 | ||
| 68 | void Initialize(); | 68 | void Initialize(); |
diff --git a/src/core/memory/dmnt_cheat_vm.cpp b/src/core/memory/dmnt_cheat_vm.cpp index 48be80c12..dc04e37d2 100644 --- a/src/core/memory/dmnt_cheat_vm.cpp +++ b/src/core/memory/dmnt_cheat_vm.cpp | |||
| @@ -29,7 +29,8 @@ | |||
| 29 | 29 | ||
| 30 | namespace Core::Memory { | 30 | namespace Core::Memory { |
| 31 | 31 | ||
| 32 | DmntCheatVm::DmntCheatVm(std::unique_ptr<Callbacks> callbacks) : callbacks(std::move(callbacks)) {} | 32 | DmntCheatVm::DmntCheatVm(std::unique_ptr<Callbacks> callbacks_) |
| 33 | : callbacks(std::move(callbacks_)) {} | ||
| 33 | 34 | ||
| 34 | DmntCheatVm::~DmntCheatVm() = default; | 35 | DmntCheatVm::~DmntCheatVm() = default; |
| 35 | 36 | ||
diff --git a/src/core/memory/dmnt_cheat_vm.h b/src/core/memory/dmnt_cheat_vm.h index 21b86b72c..707bee82b 100644 --- a/src/core/memory/dmnt_cheat_vm.h +++ b/src/core/memory/dmnt_cheat_vm.h | |||
| @@ -293,7 +293,7 @@ public: | |||
| 293 | static constexpr std::size_t NumStaticRegisters = | 293 | static constexpr std::size_t NumStaticRegisters = |
| 294 | NumReadableStaticRegisters + NumWritableStaticRegisters; | 294 | NumReadableStaticRegisters + NumWritableStaticRegisters; |
| 295 | 295 | ||
| 296 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks); | 296 | explicit DmntCheatVm(std::unique_ptr<Callbacks> callbacks_); |
| 297 | ~DmntCheatVm(); | 297 | ~DmntCheatVm(); |
| 298 | 298 | ||
| 299 | std::size_t GetProgramSize() const { | 299 | std::size_t GetProgramSize() const { |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index c92337079..c42c437b7 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -27,7 +27,7 @@ constexpr std::size_t IgnoreFrames = 5; | |||
| 27 | 27 | ||
| 28 | namespace Core { | 28 | namespace Core { |
| 29 | 29 | ||
| 30 | PerfStats::PerfStats(u64 title_id) : title_id(title_id) {} | 30 | PerfStats::PerfStats(u64 title_id_) : title_id(title_id_) {} |
| 31 | 31 | ||
| 32 | PerfStats::~PerfStats() { | 32 | PerfStats::~PerfStats() { |
| 33 | if (!Settings::values.record_frame_times || title_id == 0) { | 33 | if (!Settings::values.record_frame_times || title_id == 0) { |
| @@ -69,9 +69,7 @@ void PerfStats::EndSystemFrame() { | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void PerfStats::EndGameFrame() { | 71 | void PerfStats::EndGameFrame() { |
| 72 | std::lock_guard lock{object_mutex}; | 72 | game_frames.fetch_add(1, std::memory_order_relaxed); |
| 73 | |||
| 74 | game_frames += 1; | ||
| 75 | } | 73 | } |
| 76 | 74 | ||
| 77 | double PerfStats::GetMeanFrametime() const { | 75 | double PerfStats::GetMeanFrametime() const { |
| @@ -94,10 +92,11 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us | |||
| 94 | const auto interval = duration_cast<DoubleSecs>(now - reset_point).count(); | 92 | const auto interval = duration_cast<DoubleSecs>(now - reset_point).count(); |
| 95 | 93 | ||
| 96 | const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; | 94 | const auto system_us_per_second = (current_system_time_us - reset_point_system_us) / interval; |
| 97 | 95 | const auto current_frames = static_cast<double>(game_frames.load(std::memory_order_relaxed)); | |
| 96 | const auto current_fps = current_frames / interval; | ||
| 98 | const PerfStatsResults results{ | 97 | const PerfStatsResults results{ |
| 99 | .system_fps = static_cast<double>(system_frames) / interval, | 98 | .system_fps = static_cast<double>(system_frames) / interval, |
| 100 | .game_fps = static_cast<double>(game_frames) / interval, | 99 | .average_game_fps = (current_fps + previous_fps) / 2.0, |
| 101 | .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / | 100 | .frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() / |
| 102 | static_cast<double>(system_frames), | 101 | static_cast<double>(system_frames), |
| 103 | .emulation_speed = system_us_per_second.count() / 1'000'000.0, | 102 | .emulation_speed = system_us_per_second.count() / 1'000'000.0, |
| @@ -108,7 +107,8 @@ PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us | |||
| 108 | reset_point_system_us = current_system_time_us; | 107 | reset_point_system_us = current_system_time_us; |
| 109 | accumulated_frametime = Clock::duration::zero(); | 108 | accumulated_frametime = Clock::duration::zero(); |
| 110 | system_frames = 0; | 109 | system_frames = 0; |
| 111 | game_frames = 0; | 110 | game_frames.store(0, std::memory_order_relaxed); |
| 111 | previous_fps = current_fps; | ||
| 112 | 112 | ||
| 113 | return results; | 113 | return results; |
| 114 | } | 114 | } |
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index 69256b960..e5d603717 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <atomic> | ||
| 8 | #include <chrono> | 9 | #include <chrono> |
| 9 | #include <cstddef> | 10 | #include <cstddef> |
| 10 | #include <mutex> | 11 | #include <mutex> |
| @@ -15,8 +16,8 @@ namespace Core { | |||
| 15 | struct PerfStatsResults { | 16 | struct PerfStatsResults { |
| 16 | /// System FPS (LCD VBlanks) in Hz | 17 | /// System FPS (LCD VBlanks) in Hz |
| 17 | double system_fps; | 18 | double system_fps; |
| 18 | /// Game FPS (GSP frame submissions) in Hz | 19 | /// Average game FPS (GPU frame renders) in Hz |
| 19 | double game_fps; | 20 | double average_game_fps; |
| 20 | /// Walltime per system frame, in seconds, excluding any waits | 21 | /// Walltime per system frame, in seconds, excluding any waits |
| 21 | double frametime; | 22 | double frametime; |
| 22 | /// Ratio of walltime / emulated time elapsed | 23 | /// Ratio of walltime / emulated time elapsed |
| @@ -29,7 +30,7 @@ struct PerfStatsResults { | |||
| 29 | */ | 30 | */ |
| 30 | class PerfStats { | 31 | class PerfStats { |
| 31 | public: | 32 | public: |
| 32 | explicit PerfStats(u64 title_id); | 33 | explicit PerfStats(u64 title_id_); |
| 33 | ~PerfStats(); | 34 | ~PerfStats(); |
| 34 | 35 | ||
| 35 | using Clock = std::chrono::high_resolution_clock; | 36 | using Clock = std::chrono::high_resolution_clock; |
| @@ -72,7 +73,7 @@ private: | |||
| 72 | /// Cumulative number of system frames (LCD VBlanks) presented since last reset | 73 | /// Cumulative number of system frames (LCD VBlanks) presented since last reset |
| 73 | u32 system_frames = 0; | 74 | u32 system_frames = 0; |
| 74 | /// Cumulative number of game frames (GSP frame submissions) since last reset | 75 | /// Cumulative number of game frames (GSP frame submissions) since last reset |
| 75 | u32 game_frames = 0; | 76 | std::atomic<u32> game_frames = 0; |
| 76 | 77 | ||
| 77 | /// Point when the previous system frame ended | 78 | /// Point when the previous system frame ended |
| 78 | Clock::time_point previous_frame_end = reset_point; | 79 | Clock::time_point previous_frame_end = reset_point; |
| @@ -80,6 +81,8 @@ private: | |||
| 80 | Clock::time_point frame_begin = reset_point; | 81 | Clock::time_point frame_begin = reset_point; |
| 81 | /// Total visible duration (including frame-limiting, etc.) of the previous system frame | 82 | /// Total visible duration (including frame-limiting, etc.) of the previous system frame |
| 82 | Clock::duration previous_frame_length = Clock::duration::zero(); | 83 | Clock::duration previous_frame_length = Clock::duration::zero(); |
| 84 | /// Previously computed fps | ||
| 85 | double previous_fps = 0; | ||
| 83 | }; | 86 | }; |
| 84 | 87 | ||
| 85 | class FrameLimiter { | 88 | class FrameLimiter { |
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 896add892..d1e807dd4 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -192,7 +192,7 @@ json GetHLERequestContextData(Kernel::HLERequestContext& ctx, Core::Memory::Memo | |||
| 192 | 192 | ||
| 193 | namespace Core { | 193 | namespace Core { |
| 194 | 194 | ||
| 195 | Reporter::Reporter(System& system) : system(system) {} | 195 | Reporter::Reporter(System& system_) : system(system_) {} |
| 196 | 196 | ||
| 197 | Reporter::~Reporter() = default; | 197 | Reporter::~Reporter() = default; |
| 198 | 198 | ||
diff --git a/src/core/reporter.h b/src/core/reporter.h index b2c2d9a2e..6fb6ebffa 100644 --- a/src/core/reporter.h +++ b/src/core/reporter.h | |||
| @@ -30,7 +30,7 @@ class System; | |||
| 30 | 30 | ||
| 31 | class Reporter { | 31 | class Reporter { |
| 32 | public: | 32 | public: |
| 33 | explicit Reporter(System& system); | 33 | explicit Reporter(System& system_); |
| 34 | ~Reporter(); | 34 | ~Reporter(); |
| 35 | 35 | ||
| 36 | // Used by fatal services | 36 | // Used by fatal services |
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index 7c4e7dd3b..7399c3648 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp | |||
| @@ -153,6 +153,11 @@ struct InputSubsystem::Impl { | |||
| 153 | // TODO return the correct motion device | 153 | // TODO return the correct motion device |
| 154 | return {}; | 154 | return {}; |
| 155 | } | 155 | } |
| 156 | #ifdef HAVE_SDL2 | ||
| 157 | if (params.Get("class", "") == "sdl") { | ||
| 158 | return sdl->GetMotionMappingForDevice(params); | ||
| 159 | } | ||
| 160 | #endif | ||
| 156 | return {}; | 161 | return {}; |
| 157 | } | 162 | } |
| 158 | 163 | ||
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index 42bbf14d4..b5d41bba4 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h | |||
| @@ -37,6 +37,9 @@ public: | |||
| 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { | 37 | virtual AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage&) { |
| 38 | return {}; | 38 | return {}; |
| 39 | } | 39 | } |
| 40 | virtual MotionMapping GetMotionMappingForDevice(const Common::ParamPackage&) { | ||
| 41 | return {}; | ||
| 42 | } | ||
| 40 | }; | 43 | }; |
| 41 | 44 | ||
| 42 | class NullState : public State { | 45 | class NullState : public State { |
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 288557968..b9b584b2a 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #endif | 29 | #endif |
| 30 | 30 | ||
| 31 | #include "common/logging/log.h" | 31 | #include "common/logging/log.h" |
| 32 | #include "common/math_util.h" | ||
| 32 | #include "common/param_package.h" | 33 | #include "common/param_package.h" |
| 33 | #include "common/settings_input.h" | 34 | #include "common/settings_input.h" |
| 34 | #include "common/threadsafe_queue.h" | 35 | #include "common/threadsafe_queue.h" |
| @@ -68,13 +69,57 @@ public: | |||
| 68 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, | 69 | SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, |
| 69 | SDL_GameController* game_controller) | 70 | SDL_GameController* game_controller) |
| 70 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, | 71 | : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, |
| 71 | sdl_controller{game_controller, &SDL_GameControllerClose} {} | 72 | sdl_controller{game_controller, &SDL_GameControllerClose} { |
| 73 | EnableMotion(); | ||
| 74 | } | ||
| 75 | |||
| 76 | void EnableMotion() { | ||
| 77 | if (sdl_controller) { | ||
| 78 | SDL_GameController* controller = sdl_controller.get(); | ||
| 79 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) && !has_accel) { | ||
| 80 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); | ||
| 81 | has_accel = true; | ||
| 82 | } | ||
| 83 | if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) && !has_gyro) { | ||
| 84 | SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE); | ||
| 85 | has_gyro = true; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 72 | 89 | ||
| 73 | void SetButton(int button, bool value) { | 90 | void SetButton(int button, bool value) { |
| 74 | std::lock_guard lock{mutex}; | 91 | std::lock_guard lock{mutex}; |
| 75 | state.buttons.insert_or_assign(button, value); | 92 | state.buttons.insert_or_assign(button, value); |
| 76 | } | 93 | } |
| 77 | 94 | ||
| 95 | void SetMotion(SDL_ControllerSensorEvent event) { | ||
| 96 | constexpr float gravity_constant = 9.80665f; | ||
| 97 | std::lock_guard lock{mutex}; | ||
| 98 | u64 time_difference = event.timestamp - last_motion_update; | ||
| 99 | last_motion_update = event.timestamp; | ||
| 100 | switch (event.sensor) { | ||
| 101 | case SDL_SENSOR_ACCEL: { | ||
| 102 | const Common::Vec3f acceleration = {-event.data[0], event.data[2], -event.data[1]}; | ||
| 103 | motion.SetAcceleration(acceleration / gravity_constant); | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | case SDL_SENSOR_GYRO: { | ||
| 107 | const Common::Vec3f gyroscope = {event.data[0], -event.data[2], event.data[1]}; | ||
| 108 | motion.SetGyroscope(gyroscope / (Common::PI * 2)); | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | // Ignore duplicated timestamps | ||
| 114 | if (time_difference == 0) { | ||
| 115 | return; | ||
| 116 | } | ||
| 117 | |||
| 118 | motion.SetGyroThreshold(0.0001f); | ||
| 119 | motion.UpdateRotation(time_difference * 1000); | ||
| 120 | motion.UpdateOrientation(time_difference * 1000); | ||
| 121 | } | ||
| 122 | |||
| 78 | bool GetButton(int button) const { | 123 | bool GetButton(int button) const { |
| 79 | std::lock_guard lock{mutex}; | 124 | std::lock_guard lock{mutex}; |
| 80 | return state.buttons.at(button); | 125 | return state.buttons.at(button); |
| @@ -121,6 +166,14 @@ public: | |||
| 121 | return std::make_tuple(x, y); | 166 | return std::make_tuple(x, y); |
| 122 | } | 167 | } |
| 123 | 168 | ||
| 169 | bool HasGyro() const { | ||
| 170 | return has_gyro; | ||
| 171 | } | ||
| 172 | |||
| 173 | bool HasAccel() const { | ||
| 174 | return has_accel; | ||
| 175 | } | ||
| 176 | |||
| 124 | const MotionInput& GetMotion() const { | 177 | const MotionInput& GetMotion() const { |
| 125 | return motion; | 178 | return motion; |
| 126 | } | 179 | } |
| @@ -173,8 +226,11 @@ private: | |||
| 173 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; | 226 | std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; |
| 174 | mutable std::mutex mutex; | 227 | mutable std::mutex mutex; |
| 175 | 228 | ||
| 176 | // Motion is initialized without PID values as motion input is not aviable for SDL2 | 229 | // Motion is initialized with the PID values |
| 177 | MotionInput motion{0.0f, 0.0f, 0.0f}; | 230 | MotionInput motion{0.3f, 0.005f, 0.0f}; |
| 231 | u64 last_motion_update{}; | ||
| 232 | bool has_gyro{false}; | ||
| 233 | bool has_accel{false}; | ||
| 178 | }; | 234 | }; |
| 179 | 235 | ||
| 180 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { | 236 | std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { |
| @@ -298,6 +354,12 @@ void SDLState::HandleGameControllerEvent(const SDL_Event& event) { | |||
| 298 | } | 354 | } |
| 299 | break; | 355 | break; |
| 300 | } | 356 | } |
| 357 | case SDL_CONTROLLERSENSORUPDATE: { | ||
| 358 | if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) { | ||
| 359 | joystick->SetMotion(event.csensor); | ||
| 360 | } | ||
| 361 | break; | ||
| 362 | } | ||
| 301 | case SDL_JOYDEVICEREMOVED: | 363 | case SDL_JOYDEVICEREMOVED: |
| 302 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); | 364 | LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); |
| 303 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); | 365 | CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); |
| @@ -451,6 +513,18 @@ private: | |||
| 451 | std::shared_ptr<SDLJoystick> joystick; | 513 | std::shared_ptr<SDLJoystick> joystick; |
| 452 | }; | 514 | }; |
| 453 | 515 | ||
| 516 | class SDLMotion final : public Input::MotionDevice { | ||
| 517 | public: | ||
| 518 | explicit SDLMotion(std::shared_ptr<SDLJoystick> joystick_) : joystick(std::move(joystick_)) {} | ||
| 519 | |||
| 520 | Input::MotionStatus GetStatus() const override { | ||
| 521 | return joystick->GetMotion().GetMotion(); | ||
| 522 | } | ||
| 523 | |||
| 524 | private: | ||
| 525 | std::shared_ptr<SDLJoystick> joystick; | ||
| 526 | }; | ||
| 527 | |||
| 454 | class SDLDirectionMotion final : public Input::MotionDevice { | 528 | class SDLDirectionMotion final : public Input::MotionDevice { |
| 455 | public: | 529 | public: |
| 456 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) | 530 | explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) |
| @@ -660,6 +734,10 @@ public: | |||
| 660 | 734 | ||
| 661 | auto joystick = state.GetSDLJoystickByGUID(guid, port); | 735 | auto joystick = state.GetSDLJoystickByGUID(guid, port); |
| 662 | 736 | ||
| 737 | if (params.Has("motion")) { | ||
| 738 | return std::make_unique<SDLMotion>(joystick); | ||
| 739 | } | ||
| 740 | |||
| 663 | if (params.Has("hat")) { | 741 | if (params.Has("hat")) { |
| 664 | const int hat = params.Get("hat", 0); | 742 | const int hat = params.Get("hat", 0); |
| 665 | const std::string direction_name = params.Get("direction", ""); | 743 | const std::string direction_name = params.Get("direction", ""); |
| @@ -719,6 +797,17 @@ SDLState::SDLState() { | |||
| 719 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); | 797 | RegisterFactory<VibrationDevice>("sdl", vibration_factory); |
| 720 | RegisterFactory<MotionDevice>("sdl", motion_factory); | 798 | RegisterFactory<MotionDevice>("sdl", motion_factory); |
| 721 | 799 | ||
| 800 | // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers | ||
| 801 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); | ||
| 802 | SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); | ||
| 803 | |||
| 804 | // Tell SDL2 to use the hidapi driver. This will allow joycons to be detected as a | ||
| 805 | // GameController and not a generic one | ||
| 806 | SDL_SetHint("SDL_JOYSTICK_HIDAPI_JOY_CONS", "1"); | ||
| 807 | |||
| 808 | // Turn off Pro controller home led | ||
| 809 | SDL_SetHint("SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED", "0"); | ||
| 810 | |||
| 722 | // If the frontend is going to manage the event loop, then we don't start one here | 811 | // If the frontend is going to manage the event loop, then we don't start one here |
| 723 | start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; | 812 | start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; |
| 724 | if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { | 813 | if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { |
| @@ -855,6 +944,13 @@ Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s | |||
| 855 | return params; | 944 | return params; |
| 856 | } | 945 | } |
| 857 | 946 | ||
| 947 | Common::ParamPackage BuildMotionParam(int port, std::string guid) { | ||
| 948 | Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}}); | ||
| 949 | params.Set("port", port); | ||
| 950 | params.Set("guid", std::move(guid)); | ||
| 951 | return params; | ||
| 952 | } | ||
| 953 | |||
| 858 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { | 954 | Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { |
| 859 | switch (event.type) { | 955 | switch (event.type) { |
| 860 | case SDL_JOYAXISMOTION: { | 956 | case SDL_JOYAXISMOTION: { |
| @@ -909,6 +1005,35 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve | |||
| 909 | } | 1005 | } |
| 910 | break; | 1006 | break; |
| 911 | } | 1007 | } |
| 1008 | case SDL_CONTROLLERSENSORUPDATE: { | ||
| 1009 | bool is_motion_shaking = false; | ||
| 1010 | constexpr float gyro_threshold = 5.0f; | ||
| 1011 | constexpr float accel_threshold = 11.0f; | ||
| 1012 | if (event.csensor.sensor == SDL_SENSOR_ACCEL) { | ||
| 1013 | const Common::Vec3f acceleration = {-event.csensor.data[0], event.csensor.data[2], | ||
| 1014 | -event.csensor.data[1]}; | ||
| 1015 | if (acceleration.Length() > accel_threshold) { | ||
| 1016 | is_motion_shaking = true; | ||
| 1017 | } | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | if (event.csensor.sensor == SDL_SENSOR_GYRO) { | ||
| 1021 | const Common::Vec3f gyroscope = {event.csensor.data[0], -event.csensor.data[2], | ||
| 1022 | event.csensor.data[1]}; | ||
| 1023 | if (gyroscope.Length() > gyro_threshold) { | ||
| 1024 | is_motion_shaking = true; | ||
| 1025 | } | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | if (!is_motion_shaking) { | ||
| 1029 | break; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | if (const auto joystick = state.GetSDLJoystickBySDLID(event.csensor.which)) { | ||
| 1033 | return BuildMotionParam(joystick->GetPort(), joystick->GetGUID()); | ||
| 1034 | } | ||
| 1035 | break; | ||
| 1036 | } | ||
| 912 | } | 1037 | } |
| 913 | return {}; | 1038 | return {}; |
| 914 | } | 1039 | } |
| @@ -1038,6 +1163,27 @@ AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& pa | |||
| 1038 | return mapping; | 1163 | return mapping; |
| 1039 | } | 1164 | } |
| 1040 | 1165 | ||
| 1166 | MotionMapping SDLState::GetMotionMappingForDevice(const Common::ParamPackage& params) { | ||
| 1167 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 1168 | return {}; | ||
| 1169 | } | ||
| 1170 | const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0)); | ||
| 1171 | auto* controller = joystick->GetSDLGameController(); | ||
| 1172 | if (controller == nullptr) { | ||
| 1173 | return {}; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | joystick->EnableMotion(); | ||
| 1177 | |||
| 1178 | if (!joystick->HasGyro() && !joystick->HasAccel()) { | ||
| 1179 | return {}; | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | MotionMapping mapping = {}; | ||
| 1183 | mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, | ||
| 1184 | BuildMotionParam(joystick->GetPort(), joystick->GetGUID())); | ||
| 1185 | return mapping; | ||
| 1186 | } | ||
| 1041 | namespace Polling { | 1187 | namespace Polling { |
| 1042 | class SDLPoller : public InputCommon::Polling::DevicePoller { | 1188 | class SDLPoller : public InputCommon::Polling::DevicePoller { |
| 1043 | public: | 1189 | public: |
| @@ -1151,6 +1297,7 @@ public: | |||
| 1151 | [[fallthrough]]; | 1297 | [[fallthrough]]; |
| 1152 | case SDL_JOYBUTTONUP: | 1298 | case SDL_JOYBUTTONUP: |
| 1153 | case SDL_JOYHATMOTION: | 1299 | case SDL_JOYHATMOTION: |
| 1300 | case SDL_CONTROLLERSENSORUPDATE: | ||
| 1154 | return {SDLEventToMotionParamPackage(state, event)}; | 1301 | return {SDLEventToMotionParamPackage(state, event)}; |
| 1155 | } | 1302 | } |
| 1156 | return std::nullopt; | 1303 | return std::nullopt; |
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 8b7363f56..121e01913 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h | |||
| @@ -57,6 +57,7 @@ public: | |||
| 57 | 57 | ||
| 58 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; | 58 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; |
| 59 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; | 59 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; |
| 60 | MotionMapping GetMotionMappingForDevice(const Common::ParamPackage& params) override; | ||
| 60 | 61 | ||
| 61 | private: | 62 | private: |
| 62 | void InitJoystick(int joystick_index); | 63 | void InitJoystick(int joystick_index); |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 8a38a380d..bc1dfab3d 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -86,6 +86,7 @@ private: | |||
| 86 | case Type::PadData: { | 86 | case Type::PadData: { |
| 87 | Response::PadData pad_data; | 87 | Response::PadData pad_data; |
| 88 | std::memcpy(&pad_data, &receive_buffer[sizeof(Header)], sizeof(Response::PadData)); | 88 | std::memcpy(&pad_data, &receive_buffer[sizeof(Header)], sizeof(Response::PadData)); |
| 89 | SanitizeMotion(pad_data); | ||
| 89 | callback.pad_data(std::move(pad_data)); | 90 | callback.pad_data(std::move(pad_data)); |
| 90 | break; | 91 | break; |
| 91 | } | 92 | } |
| @@ -114,6 +115,28 @@ private: | |||
| 114 | StartSend(timer.expiry()); | 115 | StartSend(timer.expiry()); |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 118 | void SanitizeMotion(Response::PadData& data) { | ||
| 119 | // Zero out any non number value | ||
| 120 | if (!std::isnormal(data.gyro.pitch)) { | ||
| 121 | data.gyro.pitch = 0; | ||
| 122 | } | ||
| 123 | if (!std::isnormal(data.gyro.roll)) { | ||
| 124 | data.gyro.roll = 0; | ||
| 125 | } | ||
| 126 | if (!std::isnormal(data.gyro.yaw)) { | ||
| 127 | data.gyro.yaw = 0; | ||
| 128 | } | ||
| 129 | if (!std::isnormal(data.accel.x)) { | ||
| 130 | data.accel.x = 0; | ||
| 131 | } | ||
| 132 | if (!std::isnormal(data.accel.y)) { | ||
| 133 | data.accel.y = 0; | ||
| 134 | } | ||
| 135 | if (!std::isnormal(data.accel.z)) { | ||
| 136 | data.accel.z = 0; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 117 | SocketCallback callback; | 140 | SocketCallback callback; |
| 118 | boost::asio::io_service io_service; | 141 | boost::asio::io_service io_service; |
| 119 | boost::asio::basic_waitable_timer<clock> timer; | 142 | boost::asio::basic_waitable_timer<clock> timer; |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 32dcbd693..de971041f 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -690,7 +690,10 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 | |||
| 690 | const VAddr cpu_addr = binding.cpu_addr; | 690 | const VAddr cpu_addr = binding.cpu_addr; |
| 691 | const u32 size = binding.size; | 691 | const u32 size = binding.size; |
| 692 | Buffer& buffer = slot_buffers[binding.buffer_id]; | 692 | Buffer& buffer = slot_buffers[binding.buffer_id]; |
| 693 | if (size <= uniform_buffer_skip_cache_size && !buffer.IsRegionGpuModified(cpu_addr, size)) { | 693 | const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && |
| 694 | size <= uniform_buffer_skip_cache_size && | ||
| 695 | !buffer.IsRegionGpuModified(cpu_addr, size); | ||
| 696 | if (use_fast_buffer) { | ||
| 694 | if constexpr (IS_OPENGL) { | 697 | if constexpr (IS_OPENGL) { |
| 695 | if (runtime.HasFastBufferSubData()) { | 698 | if (runtime.HasFastBufferSubData()) { |
| 696 | // Fast path for Nvidia | 699 | // Fast path for Nvidia |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index a38024242..37f7b24e1 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "core/frontend/emu_window.h" | 13 | #include "core/frontend/emu_window.h" |
| 14 | #include "core/hardware_interrupt_manager.h" | 14 | #include "core/hardware_interrupt_manager.h" |
| 15 | #include "core/memory.h" | 15 | #include "core/memory.h" |
| 16 | #include "core/perf_stats.h" | ||
| 16 | #include "video_core/engines/fermi_2d.h" | 17 | #include "video_core/engines/fermi_2d.h" |
| 17 | #include "video_core/engines/kepler_compute.h" | 18 | #include "video_core/engines/kepler_compute.h" |
| 18 | #include "video_core/engines/kepler_memory.h" | 19 | #include "video_core/engines/kepler_memory.h" |
| @@ -191,6 +192,10 @@ u64 GPU::GetTicks() const { | |||
| 191 | return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den; | 192 | return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den; |
| 192 | } | 193 | } |
| 193 | 194 | ||
| 195 | void GPU::RendererFrameEndNotify() { | ||
| 196 | system.GetPerfStats().EndGameFrame(); | ||
| 197 | } | ||
| 198 | |||
| 194 | void GPU::FlushCommands() { | 199 | void GPU::FlushCommands() { |
| 195 | rasterizer->FlushCommands(); | 200 | rasterizer->FlushCommands(); |
| 196 | } | 201 | } |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 8669e9940..29a867863 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
| @@ -247,6 +247,8 @@ public: | |||
| 247 | return use_nvdec; | 247 | return use_nvdec; |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | void RendererFrameEndNotify(); | ||
| 251 | |||
| 250 | enum class FenceOperation : u32 { | 252 | enum class FenceOperation : u32 { |
| 251 | Acquire = 0, | 253 | Acquire = 0, |
| 252 | Increment = 1, | 254 | Increment = 1, |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index b113f54db..3f4532ca7 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -241,7 +241,7 @@ Device::Device() { | |||
| 241 | has_variable_aoffi = TestVariableAoffi(); | 241 | has_variable_aoffi = TestVariableAoffi(); |
| 242 | has_component_indexing_bug = is_amd; | 242 | has_component_indexing_bug = is_amd; |
| 243 | has_precise_bug = TestPreciseBug(); | 243 | has_precise_bug = TestPreciseBug(); |
| 244 | has_broken_texture_view_formats = is_amd || is_intel; | 244 | has_broken_texture_view_formats = is_amd || (!is_linux && is_intel); |
| 245 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; | 245 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; |
| 246 | has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory; | 246 | has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory; |
| 247 | has_debugging_tool_attached = IsDebugToolAttached(extensions); | 247 | has_debugging_tool_attached = IsDebugToolAttached(extensions); |
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 623b43d8a..ffe9edc1b 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -543,8 +543,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src, | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 545 | void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, |
| 546 | const std::array<Offset2D, 2>& dst_region, | 546 | const Region2D& dst_region, const Region2D& src_region, |
| 547 | const std::array<Offset2D, 2>& src_region, | ||
| 548 | Tegra::Engines::Fermi2D::Filter filter, | 547 | Tegra::Engines::Fermi2D::Filter filter, |
| 549 | Tegra::Engines::Fermi2D::Operation operation) { | 548 | Tegra::Engines::Fermi2D::Operation operation) { |
| 550 | state_tracker.NotifyScissor0(); | 549 | state_tracker.NotifyScissor0(); |
| @@ -560,9 +559,9 @@ void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | |||
| 560 | const GLbitfield buffer_bits = dst->BufferBits(); | 559 | const GLbitfield buffer_bits = dst->BufferBits(); |
| 561 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; | 560 | const bool has_depth = (buffer_bits & ~GL_COLOR_BUFFER_BIT) != 0; |
| 562 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 561 | const bool is_linear = !has_depth && filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| 563 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region[0].x, src_region[0].y, | 562 | glBlitNamedFramebuffer(src->Handle(), dst->Handle(), src_region.start.x, src_region.start.y, |
| 564 | src_region[1].x, src_region[1].y, dst_region[0].x, dst_region[0].y, | 563 | src_region.end.x, src_region.end.y, dst_region.start.x, |
| 565 | dst_region[1].x, dst_region[1].y, buffer_bits, | 564 | dst_region.start.y, dst_region.end.x, dst_region.end.y, buffer_bits, |
| 566 | is_linear ? GL_LINEAR : GL_NEAREST); | 565 | is_linear ? GL_LINEAR : GL_NEAREST); |
| 567 | } | 566 | } |
| 568 | 567 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h index 3c871541b..df8be12ff 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.h +++ b/src/video_core/renderer_opengl/gl_texture_cache.h | |||
| @@ -28,7 +28,7 @@ using VideoCommon::ImageId; | |||
| 28 | using VideoCommon::ImageViewId; | 28 | using VideoCommon::ImageViewId; |
| 29 | using VideoCommon::ImageViewType; | 29 | using VideoCommon::ImageViewType; |
| 30 | using VideoCommon::NUM_RT; | 30 | using VideoCommon::NUM_RT; |
| 31 | using VideoCommon::Offset2D; | 31 | using VideoCommon::Region2D; |
| 32 | using VideoCommon::RenderTargets; | 32 | using VideoCommon::RenderTargets; |
| 33 | 33 | ||
| 34 | struct ImageBufferMap { | 34 | struct ImageBufferMap { |
| @@ -73,10 +73,8 @@ public: | |||
| 73 | 73 | ||
| 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); | 74 | void EmulateCopyImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); |
| 75 | 75 | ||
| 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, | 76 | void BlitFramebuffer(Framebuffer* dst, Framebuffer* src, const Region2D& dst_region, |
| 77 | const std::array<Offset2D, 2>& dst_region, | 77 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 78 | const std::array<Offset2D, 2>& src_region, | ||
| 79 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 80 | Tegra::Engines::Fermi2D::Operation operation); | 78 | Tegra::Engines::Fermi2D::Operation operation); |
| 81 | 79 | ||
| 82 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, | 80 | void AccelerateImageUpload(Image& image, const ImageBufferMap& map, |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index cc2e499f9..a718bff7a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -155,6 +155,7 @@ void RendererOpenGL::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 155 | 155 | ||
| 156 | ++m_current_frame; | 156 | ++m_current_frame; |
| 157 | 157 | ||
| 158 | gpu.RendererFrameEndNotify(); | ||
| 158 | rasterizer.TickFrame(); | 159 | rasterizer.TickFrame(); |
| 159 | 160 | ||
| 160 | context->SwapBuffers(); | 161 | context->SwapBuffers(); |
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp index 1f6a169ae..b7f5b8bc2 100644 --- a/src/video_core/renderer_vulkan/blit_image.cpp +++ b/src/video_core/renderer_vulkan/blit_image.cpp | |||
| @@ -289,16 +289,15 @@ void UpdateTwoTexturesDescriptorSet(const Device& device, VkDescriptorSet descri | |||
| 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); | 289 | device.GetLogical().UpdateDescriptorSets(write_descriptor_sets, nullptr); |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | 292 | void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Region2D& dst_region, |
| 293 | const std::array<Offset2D, 2>& dst_region, | 293 | const Region2D& src_region) { |
| 294 | const std::array<Offset2D, 2>& src_region) { | ||
| 295 | const VkOffset2D offset{ | 294 | const VkOffset2D offset{ |
| 296 | .x = std::min(dst_region[0].x, dst_region[1].x), | 295 | .x = std::min(dst_region.start.x, dst_region.end.x), |
| 297 | .y = std::min(dst_region[0].y, dst_region[1].y), | 296 | .y = std::min(dst_region.start.y, dst_region.end.y), |
| 298 | }; | 297 | }; |
| 299 | const VkExtent2D extent{ | 298 | const VkExtent2D extent{ |
| 300 | .width = static_cast<u32>(std::abs(dst_region[1].x - dst_region[0].x)), | 299 | .width = static_cast<u32>(std::abs(dst_region.end.x - dst_region.start.x)), |
| 301 | .height = static_cast<u32>(std::abs(dst_region[1].y - dst_region[0].y)), | 300 | .height = static_cast<u32>(std::abs(dst_region.end.y - dst_region.start.y)), |
| 302 | }; | 301 | }; |
| 303 | const VkViewport viewport{ | 302 | const VkViewport viewport{ |
| 304 | .x = static_cast<float>(offset.x), | 303 | .x = static_cast<float>(offset.x), |
| @@ -313,11 +312,12 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, | |||
| 313 | .offset = offset, | 312 | .offset = offset, |
| 314 | .extent = extent, | 313 | .extent = extent, |
| 315 | }; | 314 | }; |
| 316 | const float scale_x = static_cast<float>(src_region[1].x - src_region[0].x); | 315 | const float scale_x = static_cast<float>(src_region.end.x - src_region.start.x); |
| 317 | const float scale_y = static_cast<float>(src_region[1].y - src_region[0].y); | 316 | const float scale_y = static_cast<float>(src_region.end.y - src_region.start.y); |
| 318 | const PushConstants push_constants{ | 317 | const PushConstants push_constants{ |
| 319 | .tex_scale = {scale_x, scale_y}, | 318 | .tex_scale = {scale_x, scale_y}, |
| 320 | .tex_offset = {static_cast<float>(src_region[0].x), static_cast<float>(src_region[0].y)}, | 319 | .tex_offset = {static_cast<float>(src_region.start.x), |
| 320 | static_cast<float>(src_region.start.y)}, | ||
| 321 | }; | 321 | }; |
| 322 | cmdbuf.SetViewport(0, viewport); | 322 | cmdbuf.SetViewport(0, viewport); |
| 323 | cmdbuf.SetScissor(0, scissor); | 323 | cmdbuf.SetScissor(0, scissor); |
| @@ -353,8 +353,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, | |||
| 353 | BlitImageHelper::~BlitImageHelper() = default; | 353 | BlitImageHelper::~BlitImageHelper() = default; |
| 354 | 354 | ||
| 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 355 | void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 356 | const std::array<Offset2D, 2>& dst_region, | 356 | const Region2D& dst_region, const Region2D& src_region, |
| 357 | const std::array<Offset2D, 2>& src_region, | ||
| 358 | Tegra::Engines::Fermi2D::Filter filter, | 357 | Tegra::Engines::Fermi2D::Filter filter, |
| 359 | Tegra::Engines::Fermi2D::Operation operation) { | 358 | Tegra::Engines::Fermi2D::Operation operation) { |
| 360 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; | 359 | const bool is_linear = filter == Tegra::Engines::Fermi2D::Filter::Bilinear; |
| @@ -383,8 +382,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageV | |||
| 383 | 382 | ||
| 384 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, | 383 | void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, |
| 385 | VkImageView src_depth_view, VkImageView src_stencil_view, | 384 | VkImageView src_depth_view, VkImageView src_stencil_view, |
| 386 | const std::array<Offset2D, 2>& dst_region, | 385 | const Region2D& dst_region, const Region2D& src_region, |
| 387 | const std::array<Offset2D, 2>& src_region, | ||
| 388 | Tegra::Engines::Fermi2D::Filter filter, | 386 | Tegra::Engines::Fermi2D::Filter filter, |
| 389 | Tegra::Engines::Fermi2D::Operation operation) { | 387 | Tegra::Engines::Fermi2D::Operation operation) { |
| 390 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); | 388 | ASSERT(filter == Tegra::Engines::Fermi2D::Filter::Point); |
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h index 43fd3d737..0d81a06ed 100644 --- a/src/video_core/renderer_vulkan/blit_image.h +++ b/src/video_core/renderer_vulkan/blit_image.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Vulkan { | 14 | namespace Vulkan { |
| 15 | 15 | ||
| 16 | using VideoCommon::Offset2D; | 16 | using VideoCommon::Region2D; |
| 17 | 17 | ||
| 18 | class Device; | 18 | class Device; |
| 19 | class Framebuffer; | 19 | class Framebuffer; |
| @@ -35,15 +35,13 @@ public: | |||
| 35 | ~BlitImageHelper(); | 35 | ~BlitImageHelper(); |
| 36 | 36 | ||
| 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, | 37 | void BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, |
| 38 | const std::array<Offset2D, 2>& dst_region, | 38 | const Region2D& dst_region, const Region2D& src_region, |
| 39 | const std::array<Offset2D, 2>& src_region, | ||
| 40 | Tegra::Engines::Fermi2D::Filter filter, | 39 | Tegra::Engines::Fermi2D::Filter filter, |
| 41 | Tegra::Engines::Fermi2D::Operation operation); | 40 | Tegra::Engines::Fermi2D::Operation operation); |
| 42 | 41 | ||
| 43 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, | 42 | void BlitDepthStencil(const Framebuffer* dst_framebuffer, VkImageView src_depth_view, |
| 44 | VkImageView src_stencil_view, const std::array<Offset2D, 2>& dst_region, | 43 | VkImageView src_stencil_view, const Region2D& dst_region, |
| 45 | const std::array<Offset2D, 2>& src_region, | 44 | const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, |
| 46 | Tegra::Engines::Fermi2D::Filter filter, | ||
| 47 | Tegra::Engines::Fermi2D::Operation operation); | 45 | Tegra::Engines::Fermi2D::Operation operation); |
| 48 | 46 | ||
| 49 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); | 47 | void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view); |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 2e0cf4232..3986eb172 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -154,6 +154,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 154 | if (swapchain.Present(render_semaphore)) { | 154 | if (swapchain.Present(render_semaphore)) { |
| 155 | blit_screen.Recreate(); | 155 | blit_screen.Recreate(); |
| 156 | } | 156 | } |
| 157 | gpu.RendererFrameEndNotify(); | ||
| 157 | rasterizer.TickFrame(); | 158 | rasterizer.TickFrame(); |
| 158 | } | 159 | } |
| 159 | 160 | ||
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 017348e05..bdd0ce8bc 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp | |||
| @@ -490,8 +490,7 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 490 | write_barrier); | 490 | write_barrier); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const std::array<Offset2D, 2>& dst_region, | 493 | [[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, |
| 494 | const std::array<Offset2D, 2>& src_region, | ||
| 495 | const VkImageSubresourceLayers& dst_layers, | 494 | const VkImageSubresourceLayers& dst_layers, |
| 496 | const VkImageSubresourceLayers& src_layers) { | 495 | const VkImageSubresourceLayers& src_layers) { |
| 497 | return VkImageBlit{ | 496 | return VkImageBlit{ |
| @@ -499,13 +498,13 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 499 | .srcOffsets = | 498 | .srcOffsets = |
| 500 | { | 499 | { |
| 501 | { | 500 | { |
| 502 | .x = src_region[0].x, | 501 | .x = src_region.start.x, |
| 503 | .y = src_region[0].y, | 502 | .y = src_region.start.y, |
| 504 | .z = 0, | 503 | .z = 0, |
| 505 | }, | 504 | }, |
| 506 | { | 505 | { |
| 507 | .x = src_region[1].x, | 506 | .x = src_region.end.x, |
| 508 | .y = src_region[1].y, | 507 | .y = src_region.end.y, |
| 509 | .z = 1, | 508 | .z = 1, |
| 510 | }, | 509 | }, |
| 511 | }, | 510 | }, |
| @@ -513,42 +512,42 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im | |||
| 513 | .dstOffsets = | 512 | .dstOffsets = |
| 514 | { | 513 | { |
| 515 | { | 514 | { |
| 516 | .x = dst_region[0].x, | 515 | .x = dst_region.start.x, |
| 517 | .y = dst_region[0].y, | 516 | .y = dst_region.start.y, |
| 518 | .z = 0, | 517 | .z = 0, |
| 519 | }, | 518 | }, |
| 520 | { | 519 | { |
| 521 | .x = dst_region[1].x, | 520 | .x = dst_region.end.x, |
| 522 | .y = dst_region[1].y, | 521 | .y = dst_region.end.y, |
| 523 | .z = 1, | 522 | .z = 1, |
| 524 | }, | 523 | }, |
| 525 | }, | 524 | }, |
| 526 | }; | 525 | }; |
| 527 | } | 526 | } |
| 528 | 527 | ||
| 529 | [[nodiscard]] VkImageResolve MakeImageResolve(const std::array<Offset2D, 2>& dst_region, | 528 | [[nodiscard]] VkImageResolve MakeImageResolve(const Region2D& dst_region, |
| 530 | const std::array<Offset2D, 2>& src_region, | 529 | const Region2D& src_region, |
| 531 | const VkImageSubresourceLayers& dst_layers, | 530 | const VkImageSubresourceLayers& dst_layers, |
| 532 | const VkImageSubresourceLayers& src_layers) { | 531 | const VkImageSubresourceLayers& src_layers) { |
| 533 | return VkImageResolve{ | 532 | return VkImageResolve{ |
| 534 | .srcSubresource = src_layers, | 533 | .srcSubresource = src_layers, |
| 535 | .srcOffset = | 534 | .srcOffset = |
| 536 | { | 535 | { |
| 537 | .x = src_region[0].x, | 536 | .x = src_region.start.x, |
| 538 | .y = src_region[0].y, | 537 | .y = src_region.start.y, |
| 539 | .z = 0, | 538 | .z = 0, |
| 540 | }, | 539 | }, |
| 541 | .dstSubresource = dst_layers, | 540 | .dstSubresource = dst_layers, |
| 542 | .dstOffset = | 541 | .dstOffset = |
| 543 | { | 542 | { |
| 544 | .x = dst_region[0].x, | 543 | .x = dst_region.start.x, |
| 545 | .y = dst_region[0].y, | 544 | .y = dst_region.start.y, |
| 546 | .z = 0, | 545 | .z = 0, |
| 547 | }, | 546 | }, |
| 548 | .extent = | 547 | .extent = |
| 549 | { | 548 | { |
| 550 | .width = static_cast<u32>(dst_region[1].x - dst_region[0].x), | 549 | .width = static_cast<u32>(dst_region.end.x - dst_region.start.x), |
| 551 | .height = static_cast<u32>(dst_region[1].y - dst_region[0].y), | 550 | .height = static_cast<u32>(dst_region.end.y - dst_region.start.y), |
| 552 | .depth = 1, | 551 | .depth = 1, |
| 553 | }, | 552 | }, |
| 554 | }; | 553 | }; |
| @@ -602,8 +601,7 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) { | |||
| 602 | } | 601 | } |
| 603 | 602 | ||
| 604 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 603 | void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 605 | const std::array<Offset2D, 2>& dst_region, | 604 | const Region2D& dst_region, const Region2D& src_region, |
| 606 | const std::array<Offset2D, 2>& src_region, | ||
| 607 | Tegra::Engines::Fermi2D::Filter filter, | 605 | Tegra::Engines::Fermi2D::Filter filter, |
| 608 | Tegra::Engines::Fermi2D::Operation operation) { | 606 | Tegra::Engines::Fermi2D::Operation operation) { |
| 609 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); | 607 | const VkImageAspectFlags aspect_mask = ImageAspectMask(src.format); |
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 628785d5e..4a57d378b 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h | |||
| @@ -16,7 +16,7 @@ namespace Vulkan { | |||
| 16 | 16 | ||
| 17 | using VideoCommon::ImageId; | 17 | using VideoCommon::ImageId; |
| 18 | using VideoCommon::NUM_RT; | 18 | using VideoCommon::NUM_RT; |
| 19 | using VideoCommon::Offset2D; | 19 | using VideoCommon::Region2D; |
| 20 | using VideoCommon::RenderTargets; | 20 | using VideoCommon::RenderTargets; |
| 21 | using VideoCore::Surface::PixelFormat; | 21 | using VideoCore::Surface::PixelFormat; |
| 22 | 22 | ||
| @@ -71,8 +71,7 @@ struct TextureCacheRuntime { | |||
| 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); | 71 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); |
| 72 | 72 | ||
| 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, | 73 | void BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, |
| 74 | const std::array<Offset2D, 2>& dst_region, | 74 | const Region2D& dst_region, const Region2D& src_region, |
| 75 | const std::array<Offset2D, 2>& src_region, | ||
| 76 | Tegra::Engines::Fermi2D::Filter filter, | 75 | Tegra::Engines::Fermi2D::Filter filter, |
| 77 | Tegra::Engines::Fermi2D::Operation operation); | 76 | Tegra::Engines::Fermi2D::Operation operation); |
| 78 | 77 | ||
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 98e33c3a0..59b7c678b 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -148,7 +148,9 @@ public: | |||
| 148 | /// Blit an image with the given parameters | 148 | /// Blit an image with the given parameters |
| 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 149 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 150 | const Tegra::Engines::Fermi2D::Surface& src, | 150 | const Tegra::Engines::Fermi2D::Surface& src, |
| 151 | const Tegra::Engines::Fermi2D::Config& copy); | 151 | const Tegra::Engines::Fermi2D::Config& copy, |
| 152 | std::optional<Region2D> src_region_override = {}, | ||
| 153 | std::optional<Region2D> dst_region_override = {}); | ||
| 152 | 154 | ||
| 153 | /// Invalidate the contents of the color buffer index | 155 | /// Invalidate the contents of the color buffer index |
| 154 | /// These contents become unspecified, the cache can assume aggressive optimizations. | 156 | /// These contents become unspecified, the cache can assume aggressive optimizations. |
| @@ -615,7 +617,9 @@ void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { | |||
| 615 | template <class P> | 617 | template <class P> |
| 616 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 618 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 617 | const Tegra::Engines::Fermi2D::Surface& src, | 619 | const Tegra::Engines::Fermi2D::Surface& src, |
| 618 | const Tegra::Engines::Fermi2D::Config& copy) { | 620 | const Tegra::Engines::Fermi2D::Config& copy, |
| 621 | std::optional<Region2D> src_override, | ||
| 622 | std::optional<Region2D> dst_override) { | ||
| 619 | const BlitImages images = GetBlitImages(dst, src); | 623 | const BlitImages images = GetBlitImages(dst, src); |
| 620 | const ImageId dst_id = images.dst_id; | 624 | const ImageId dst_id = images.dst_id; |
| 621 | const ImageId src_id = images.src_id; | 625 | const ImageId src_id = images.src_id; |
| @@ -631,20 +635,42 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 631 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); | 635 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); |
| 632 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); | 636 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); |
| 633 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); | 637 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); |
| 634 | const std::array src_region{ | 638 | |
| 635 | Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y}, | 639 | // out of bounds texture blit checking |
| 636 | Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y}, | 640 | const bool use_override = src_override.has_value(); |
| 641 | const s32 src_x0 = copy.src_x0 >> src_samples_x; | ||
| 642 | s32 src_x1 = use_override ? src_override->end.x : copy.src_x1 >> src_samples_x; | ||
| 643 | const s32 src_y0 = copy.src_y0 >> src_samples_y; | ||
| 644 | const s32 src_y1 = copy.src_y1 >> src_samples_y; | ||
| 645 | |||
| 646 | const auto src_width = static_cast<s32>(src_image.info.size.width); | ||
| 647 | const bool width_oob = src_x1 > src_width; | ||
| 648 | const auto width_diff = width_oob ? src_x1 - src_width : 0; | ||
| 649 | if (width_oob) { | ||
| 650 | src_x1 = src_width; | ||
| 651 | } | ||
| 652 | |||
| 653 | const Region2D src_dimensions{ | ||
| 654 | Offset2D{.x = src_x0, .y = src_y0}, | ||
| 655 | Offset2D{.x = src_x1, .y = src_y1}, | ||
| 637 | }; | 656 | }; |
| 657 | const auto src_region = use_override ? *src_override : src_dimensions; | ||
| 638 | 658 | ||
| 639 | const std::optional src_base = src_image.TryFindBase(src.Address()); | 659 | const std::optional src_base = src_image.TryFindBase(src.Address()); |
| 640 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; | 660 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; |
| 641 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); | 661 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); |
| 642 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); | 662 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); |
| 643 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); | 663 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); |
| 644 | const std::array dst_region{ | 664 | |
| 645 | Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y}, | 665 | const s32 dst_x0 = copy.dst_x0 >> dst_samples_x; |
| 646 | Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y}, | 666 | const s32 dst_x1 = copy.dst_x1 >> dst_samples_x; |
| 667 | const s32 dst_y0 = copy.dst_y0 >> dst_samples_y; | ||
| 668 | const s32 dst_y1 = copy.dst_y1 >> dst_samples_y; | ||
| 669 | const Region2D dst_dimensions{ | ||
| 670 | Offset2D{.x = dst_x0, .y = dst_y0}, | ||
| 671 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y1}, | ||
| 647 | }; | 672 | }; |
| 673 | const auto dst_region = use_override ? *dst_override : dst_dimensions; | ||
| 648 | 674 | ||
| 649 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. | 675 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. |
| 650 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; | 676 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; |
| @@ -661,6 +687,21 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 661 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, | 687 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, |
| 662 | copy.operation); | 688 | copy.operation); |
| 663 | } | 689 | } |
| 690 | |||
| 691 | if (width_oob) { | ||
| 692 | // Continue copy of the oob region of the texture on the next row | ||
| 693 | auto oob_src = src; | ||
| 694 | oob_src.height++; | ||
| 695 | const Region2D src_region_override{ | ||
| 696 | Offset2D{.x = 0, .y = src_y0 + 1}, | ||
| 697 | Offset2D{.x = width_diff, .y = src_y1 + 1}, | ||
| 698 | }; | ||
| 699 | const Region2D dst_region_override{ | ||
| 700 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y0}, | ||
| 701 | Offset2D{.x = dst_x1, .y = dst_y1}, | ||
| 702 | }; | ||
| 703 | BlitImage(dst, oob_src, copy, src_region_override, dst_region_override); | ||
| 704 | } | ||
| 664 | } | 705 | } |
| 665 | 706 | ||
| 666 | template <class P> | 707 | template <class P> |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 2ad2d72a6..c9571f7e4 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h | |||
| @@ -64,6 +64,13 @@ struct Offset3D { | |||
| 64 | s32 z; | 64 | s32 z; |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | struct Region2D { | ||
| 68 | constexpr auto operator<=>(const Region2D&) const noexcept = default; | ||
| 69 | |||
| 70 | Offset2D start; | ||
| 71 | Offset2D end; | ||
| 72 | }; | ||
| 73 | |||
| 67 | struct Extent2D { | 74 | struct Extent2D { |
| 68 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; | 75 | constexpr auto operator<=>(const Extent2D&) const noexcept = default; |
| 69 | 76 | ||
diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp index 695b2ef5f..a2e0e6962 100644 --- a/src/yuzu/about_dialog.cpp +++ b/src/yuzu/about_dialog.cpp | |||
| @@ -9,17 +9,19 @@ | |||
| 9 | #include "yuzu/about_dialog.h" | 9 | #include "yuzu/about_dialog.h" |
| 10 | 10 | ||
| 11 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { | 11 | AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { |
| 12 | const auto branch_name = std::string(Common::g_scm_branch); | ||
| 13 | const auto description = std::string(Common::g_scm_desc); | ||
| 12 | const auto build_id = std::string(Common::g_build_id); | 14 | const auto build_id = std::string(Common::g_build_id); |
| 13 | const auto fmt = std::string(Common::g_title_bar_format_idle); | 15 | |
| 14 | const auto yuzu_build_version = | 16 | const auto yuzu_build = fmt::format("yuzu Development Build | {}-{}", branch_name, description); |
| 15 | fmt::format(fmt.empty() ? "yuzu Development Build" : fmt, std::string{}, std::string{}, | 17 | const auto override_build = fmt::format(std::string(Common::g_title_bar_format_idle), build_id); |
| 16 | std::string{}, std::string{}, std::string{}, build_id); | 18 | const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; |
| 17 | 19 | ||
| 18 | ui->setupUi(this); | 20 | ui->setupUi(this); |
| 19 | ui->labelLogo->setPixmap(QIcon::fromTheme(QStringLiteral("yuzu")).pixmap(200)); | 21 | ui->labelLogo->setPixmap(QIcon::fromTheme(QStringLiteral("yuzu")).pixmap(200)); |
| 20 | ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg( | 22 | ui->labelBuildInfo->setText( |
| 21 | QString::fromStdString(yuzu_build_version), QString::fromUtf8(Common::g_scm_branch), | 23 | ui->labelBuildInfo->text().arg(QString::fromStdString(yuzu_build_version), |
| 22 | QString::fromUtf8(Common::g_scm_desc), QString::fromUtf8(Common::g_build_date).left(10))); | 24 | QString::fromUtf8(Common::g_build_date).left(10))); |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | AboutDialog::~AboutDialog() = default; | 27 | AboutDialog::~AboutDialog() = default; |
diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index 1b320630c..27d81cd13 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui | |||
| @@ -70,7 +70,7 @@ | |||
| 70 | </sizepolicy> | 70 | </sizepolicy> |
| 71 | </property> | 71 | </property> |
| 72 | <property name="text"> | 72 | <property name="text"> |
| 73 | <string><html><head/><body><p>%1 | %2-%3 (%4)</p></body></html></string> | 73 | <string><html><head/><body><p>%1 (%2)</p></body></html></string> |
| 74 | </property> | 74 | </property> |
| 75 | </widget> | 75 | </widget> |
| 76 | </item> | 76 | </item> |
diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 653486493..b0f764994 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp | |||
| @@ -404,12 +404,16 @@ void QtSoftwareKeyboardDialog::ShowTextCheckDialog( | |||
| 404 | 404 | ||
| 405 | OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), | 405 | OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), |
| 406 | tr("Cancel"), tr("OK"), Qt::AlignCenter); | 406 | tr("Cancel"), tr("OK"), Qt::AlignCenter); |
| 407 | if (dialog.exec() == QDialog::Accepted) { | 407 | if (dialog.exec() != QDialog::Accepted) { |
| 408 | emit SubmitNormalText(SwkbdResult::Ok, current_text); | 408 | StartInputThread(); |
| 409 | break; | 409 | break; |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | StartInputThread(); | 412 | auto text = ui->topOSK->currentIndex() == 1 |
| 413 | ? ui->text_edit_osk->toPlainText().toStdU16String() | ||
| 414 | : ui->line_edit_osk->text().toStdU16String(); | ||
| 415 | |||
| 416 | emit SubmitNormalText(SwkbdResult::Ok, std::move(text)); | ||
| 413 | break; | 417 | break; |
| 414 | } | 418 | } |
| 415 | } | 419 | } |
| @@ -480,11 +484,7 @@ void QtSoftwareKeyboardDialog::open() { | |||
| 480 | void QtSoftwareKeyboardDialog::reject() { | 484 | void QtSoftwareKeyboardDialog::reject() { |
| 481 | // Pressing the ESC key in a dialog calls QDialog::reject(). | 485 | // Pressing the ESC key in a dialog calls QDialog::reject(). |
| 482 | // We will override this behavior to the "Cancel" action on the software keyboard. | 486 | // We will override this behavior to the "Cancel" action on the software keyboard. |
| 483 | if (is_inline) { | 487 | TranslateButtonPress(HIDButton::X); |
| 484 | emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); | ||
| 485 | } else { | ||
| 486 | emit SubmitNormalText(SwkbdResult::Cancel, current_text); | ||
| 487 | } | ||
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { | 490 | void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index e80a3df77..125feb86b 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -736,10 +736,16 @@ void Config::ReadPathValues() { | |||
| 736 | void Config::ReadCpuValues() { | 736 | void Config::ReadCpuValues() { |
| 737 | qt_config->beginGroup(QStringLiteral("Cpu")); | 737 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 738 | 738 | ||
| 739 | if (global) { | 739 | ReadSettingGlobal(Settings::values.cpu_accuracy, QStringLiteral("cpu_accuracy"), 0); |
| 740 | Settings::values.cpu_accuracy = static_cast<Settings::CPUAccuracy>( | 740 | |
| 741 | ReadSetting(QStringLiteral("cpu_accuracy"), 0).toInt()); | 741 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_unfuse_fma, |
| 742 | QStringLiteral("cpuopt_unsafe_unfuse_fma"), true); | ||
| 743 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error, | ||
| 744 | QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true); | ||
| 745 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 746 | QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true); | ||
| 742 | 747 | ||
| 748 | if (global) { | ||
| 743 | Settings::values.cpuopt_page_tables = | 749 | Settings::values.cpuopt_page_tables = |
| 744 | ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool(); | 750 | ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool(); |
| 745 | Settings::values.cpuopt_block_linking = | 751 | Settings::values.cpuopt_block_linking = |
| @@ -756,13 +762,6 @@ void Config::ReadCpuValues() { | |||
| 756 | ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); | 762 | ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); |
| 757 | Settings::values.cpuopt_reduce_misalign_checks = | 763 | Settings::values.cpuopt_reduce_misalign_checks = |
| 758 | ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); | 764 | ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); |
| 759 | |||
| 760 | Settings::values.cpuopt_unsafe_unfuse_fma = | ||
| 761 | ReadSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), true).toBool(); | ||
| 762 | Settings::values.cpuopt_unsafe_reduce_fp_error = | ||
| 763 | ReadSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true).toBool(); | ||
| 764 | Settings::values.cpuopt_unsafe_inaccurate_nan = | ||
| 765 | ReadSetting(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true).toBool(); | ||
| 766 | } | 765 | } |
| 767 | 766 | ||
| 768 | qt_config->endGroup(); | 767 | qt_config->endGroup(); |
| @@ -869,17 +868,14 @@ void Config::ReadSystemValues() { | |||
| 869 | } | 868 | } |
| 870 | } | 869 | } |
| 871 | 870 | ||
| 872 | bool custom_rtc_enabled; | 871 | if (global) { |
| 873 | ReadSettingGlobal(custom_rtc_enabled, QStringLiteral("custom_rtc_enabled"), false); | 872 | const auto custom_rtc_enabled = |
| 874 | bool custom_rtc_global = | 873 | ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool(); |
| 875 | global || qt_config->value(QStringLiteral("custom_rtc/use_global"), true).toBool(); | ||
| 876 | Settings::values.custom_rtc.SetGlobal(custom_rtc_global); | ||
| 877 | if (global || !custom_rtc_global) { | ||
| 878 | if (custom_rtc_enabled) { | 874 | if (custom_rtc_enabled) { |
| 879 | Settings::values.custom_rtc.SetValue( | 875 | Settings::values.custom_rtc = |
| 880 | std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong())); | 876 | std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong()); |
| 881 | } else { | 877 | } else { |
| 882 | Settings::values.custom_rtc.SetValue(std::nullopt); | 878 | Settings::values.custom_rtc = std::nullopt; |
| 883 | } | 879 | } |
| 884 | } | 880 | } |
| 885 | 881 | ||
| @@ -1313,10 +1309,19 @@ void Config::SavePathValues() { | |||
| 1313 | void Config::SaveCpuValues() { | 1309 | void Config::SaveCpuValues() { |
| 1314 | qt_config->beginGroup(QStringLiteral("Cpu")); | 1310 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 1315 | 1311 | ||
| 1316 | if (global) { | 1312 | WriteSettingGlobal(QStringLiteral("cpu_accuracy"), |
| 1317 | WriteSetting(QStringLiteral("cpu_accuracy"), | 1313 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)), |
| 1318 | static_cast<int>(Settings::values.cpu_accuracy), 0); | 1314 | Settings::values.cpu_accuracy.UsingGlobal(), |
| 1315 | static_cast<u32>(Settings::CPUAccuracy::Accurate)); | ||
| 1319 | 1316 | ||
| 1317 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_unfuse_fma"), | ||
| 1318 | Settings::values.cpuopt_unsafe_unfuse_fma, true); | ||
| 1319 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), | ||
| 1320 | Settings::values.cpuopt_unsafe_reduce_fp_error, true); | ||
| 1321 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), | ||
| 1322 | Settings::values.cpuopt_unsafe_inaccurate_nan, true); | ||
| 1323 | |||
| 1324 | if (global) { | ||
| 1320 | WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables, | 1325 | WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables, |
| 1321 | true); | 1326 | true); |
| 1322 | WriteSetting(QStringLiteral("cpuopt_block_linking"), Settings::values.cpuopt_block_linking, | 1327 | WriteSetting(QStringLiteral("cpuopt_block_linking"), Settings::values.cpuopt_block_linking, |
| @@ -1331,13 +1336,6 @@ void Config::SaveCpuValues() { | |||
| 1331 | WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); | 1336 | WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); |
| 1332 | WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), | 1337 | WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), |
| 1333 | Settings::values.cpuopt_reduce_misalign_checks, true); | 1338 | Settings::values.cpuopt_reduce_misalign_checks, true); |
| 1334 | |||
| 1335 | WriteSetting(QStringLiteral("cpuopt_unsafe_unfuse_fma"), | ||
| 1336 | Settings::values.cpuopt_unsafe_unfuse_fma, true); | ||
| 1337 | WriteSetting(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), | ||
| 1338 | Settings::values.cpuopt_unsafe_reduce_fp_error, true); | ||
| 1339 | WriteSetting(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), | ||
| 1340 | Settings::values.cpuopt_unsafe_inaccurate_nan, true); | ||
| 1341 | } | 1339 | } |
| 1342 | 1340 | ||
| 1343 | qt_config->endGroup(); | 1341 | qt_config->endGroup(); |
| @@ -1432,14 +1430,14 @@ void Config::SaveSystemValues() { | |||
| 1432 | Settings::values.rng_seed.GetValue(global).value_or(0), | 1430 | Settings::values.rng_seed.GetValue(global).value_or(0), |
| 1433 | Settings::values.rng_seed.UsingGlobal(), 0); | 1431 | Settings::values.rng_seed.UsingGlobal(), 0); |
| 1434 | 1432 | ||
| 1435 | WriteSettingGlobal(QStringLiteral("custom_rtc_enabled"), | 1433 | if (global) { |
| 1436 | Settings::values.custom_rtc.GetValue(global).has_value(), | 1434 | WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(), |
| 1437 | Settings::values.custom_rtc.UsingGlobal(), false); | 1435 | false); |
| 1438 | WriteSettingGlobal( | 1436 | WriteSetting(QStringLiteral("custom_rtc"), |
| 1439 | QStringLiteral("custom_rtc"), | 1437 | QVariant::fromValue<long long>( |
| 1440 | QVariant::fromValue<long long>( | 1438 | Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()), |
| 1441 | Settings::values.custom_rtc.GetValue(global).value_or(std::chrono::seconds{}).count()), | 1439 | 0); |
| 1442 | Settings::values.custom_rtc.UsingGlobal(), 0); | 1440 | } |
| 1443 | 1441 | ||
| 1444 | WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1); | 1442 | WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1); |
| 1445 | 1443 | ||
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 5a2c026b3..ce3355588 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -132,5 +132,6 @@ private: | |||
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT | 134 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT |
| 135 | Q_DECLARE_METATYPE(Settings::CPUAccuracy); | ||
| 135 | Q_DECLARE_METATYPE(Settings::RendererBackend); | 136 | Q_DECLARE_METATYPE(Settings::RendererBackend); |
| 136 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); | 137 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); |
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index 89be4a62d..096e42e94 100644 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp | |||
| @@ -13,32 +13,29 @@ | |||
| 13 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, | 13 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, |
| 14 | const QCheckBox* checkbox, | 14 | const QCheckBox* checkbox, |
| 15 | const CheckState& tracker) { | 15 | const CheckState& tracker) { |
| 16 | if (tracker == CheckState::Global) { | 16 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { |
| 17 | setting->SetGlobal(true); | ||
| 18 | } else { | ||
| 19 | setting->SetGlobal(false); | ||
| 20 | setting->SetValue(checkbox->checkState()); | 17 | setting->SetValue(checkbox->checkState()); |
| 18 | } else if (!Settings::IsConfiguringGlobal()) { | ||
| 19 | if (tracker == CheckState::Global) { | ||
| 20 | setting->SetGlobal(true); | ||
| 21 | } else { | ||
| 22 | setting->SetGlobal(false); | ||
| 23 | setting->SetValue(checkbox->checkState()); | ||
| 24 | } | ||
| 21 | } | 25 | } |
| 22 | } | 26 | } |
| 23 | 27 | ||
| 24 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting, | 28 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting, |
| 25 | const QComboBox* combobox) { | 29 | const QComboBox* combobox) { |
| 26 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 30 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { |
| 27 | setting->SetGlobal(true); | 31 | setting->SetValue(combobox->currentIndex()); |
| 28 | } else { | 32 | } else if (!Settings::IsConfiguringGlobal()) { |
| 29 | setting->SetGlobal(false); | 33 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { |
| 30 | setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET); | 34 | setting->SetGlobal(true); |
| 31 | } | 35 | } else { |
| 32 | } | 36 | setting->SetGlobal(false); |
| 33 | 37 | setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET); | |
| 34 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, | 38 | } |
| 35 | const QComboBox* combobox) { | ||
| 36 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 37 | setting->SetGlobal(true); | ||
| 38 | } else { | ||
| 39 | setting->SetGlobal(false); | ||
| 40 | setting->SetValue(static_cast<Settings::RendererBackend>( | ||
| 41 | combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 42 | } | 39 | } |
| 43 | } | 40 | } |
| 44 | 41 | ||
| @@ -51,27 +48,6 @@ void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, | |||
| 51 | } | 48 | } |
| 52 | } | 49 | } |
| 53 | 50 | ||
| 54 | void ConfigurationShared::SetPerGameSetting(QComboBox* combobox, | ||
| 55 | const Settings::Setting<int>* setting) { | ||
| 56 | combobox->setCurrentIndex(setting->UsingGlobal() | ||
| 57 | ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 58 | : setting->GetValue() + ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 59 | } | ||
| 60 | |||
| 61 | void ConfigurationShared::SetPerGameSetting( | ||
| 62 | QComboBox* combobox, const Settings::Setting<Settings::RendererBackend>* setting) { | ||
| 63 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 64 | : static_cast<int>(setting->GetValue()) + | ||
| 65 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 66 | } | ||
| 67 | |||
| 68 | void ConfigurationShared::SetPerGameSetting( | ||
| 69 | QComboBox* combobox, const Settings::Setting<Settings::GPUAccuracy>* setting) { | ||
| 70 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 71 | : static_cast<int>(setting->GetValue()) + | ||
| 72 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 73 | } | ||
| 74 | |||
| 75 | void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { | 51 | void ConfigurationShared::SetHighlight(QWidget* widget, bool highlighted) { |
| 76 | if (highlighted) { | 52 | if (highlighted) { |
| 77 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") | 53 | widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }") |
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index 5b344cdbd..1e0ef01ca 100644 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h | |||
| @@ -15,37 +15,45 @@ constexpr int USE_GLOBAL_INDEX = 0; | |||
| 15 | constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; | 15 | constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; |
| 16 | constexpr int USE_GLOBAL_OFFSET = 2; | 16 | constexpr int USE_GLOBAL_OFFSET = 2; |
| 17 | 17 | ||
| 18 | // CheckBoxes require a tracker for their state since we emulate a tristate CheckBox | ||
| 18 | enum class CheckState { | 19 | enum class CheckState { |
| 19 | Off, | 20 | Off, // Checkbox overrides to off/false |
| 20 | On, | 21 | On, // Checkbox overrides to on/true |
| 21 | Global, | 22 | Global, // Checkbox defers to the global state |
| 22 | Count, | 23 | Count, // Simply the number of states, not a valid checkbox state |
| 23 | }; | 24 | }; |
| 24 | 25 | ||
| 25 | // Global-aware apply and set functions | 26 | // Global-aware apply and set functions |
| 26 | 27 | ||
| 28 | // ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting | ||
| 27 | void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox, | 29 | void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox, |
| 28 | const CheckState& tracker); | 30 | const CheckState& tracker); |
| 29 | void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); | 31 | void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); |
| 30 | void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, | ||
| 31 | const QComboBox* combobox); | ||
| 32 | void ApplyPerGameSetting(Settings::Setting<Settings::GPUAccuracy>* setting, | ||
| 33 | const QComboBox* combobox); | ||
| 34 | 32 | ||
| 33 | // Sets a Qt UI element given a Settings::Setting | ||
| 35 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting); | 34 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting); |
| 36 | void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<int>* setting); | ||
| 37 | void SetPerGameSetting(QComboBox* combobox, | ||
| 38 | const Settings::Setting<Settings::RendererBackend>* setting); | ||
| 39 | void SetPerGameSetting(QComboBox* combobox, | ||
| 40 | const Settings::Setting<Settings::GPUAccuracy>* setting); | ||
| 41 | 35 | ||
| 36 | template <typename Type> | ||
| 37 | void SetPerGameSetting(QComboBox* combobox, const Settings::Setting<Type>* setting) { | ||
| 38 | combobox->setCurrentIndex(setting->UsingGlobal() ? ConfigurationShared::USE_GLOBAL_INDEX | ||
| 39 | : static_cast<int>(setting->GetValue()) + | ||
| 40 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 41 | } | ||
| 42 | |||
| 43 | // (Un)highlights a Qt UI element | ||
| 42 | void SetHighlight(QWidget* widget, bool highlighted); | 44 | void SetHighlight(QWidget* widget, bool highlighted); |
| 45 | |||
| 46 | // Sets up a QCheckBox like a tristate one, given a Setting | ||
| 43 | void SetColoredTristate(QCheckBox* checkbox, const Settings::Setting<bool>& setting, | 47 | void SetColoredTristate(QCheckBox* checkbox, const Settings::Setting<bool>& setting, |
| 44 | CheckState& tracker); | 48 | CheckState& tracker); |
| 45 | void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, | 49 | void SetColoredTristate(QCheckBox* checkbox, bool global, bool state, bool global_state, |
| 46 | CheckState& tracker); | 50 | CheckState& tracker); |
| 51 | |||
| 52 | // Sets up coloring of a QWidget `target` based on the state of a QComboBox, and calls | ||
| 53 | // InsertGlobalItem | ||
| 47 | void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global); | 54 | void SetColoredComboBox(QComboBox* combobox, QWidget* target, int global); |
| 48 | 55 | ||
| 56 | // Adds the "Use Global Configuration" selection and separator to the beginning of a QComboBox | ||
| 49 | void InsertGlobalItem(QComboBox* combobox, int global_index); | 57 | void InsertGlobalItem(QComboBox* combobox, int global_index); |
| 50 | 58 | ||
| 51 | } // namespace ConfigurationShared | 59 | } // namespace ConfigurationShared |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index f9507e228..fc0191432 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -99,6 +99,9 @@ void ConfigureAudio::SetVolumeIndicatorText(int percentage) { | |||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void ConfigureAudio::ApplyConfiguration() { | 101 | void ConfigureAudio::ApplyConfiguration() { |
| 102 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, | ||
| 103 | ui->toggle_audio_stretching, enable_audio_stretching); | ||
| 104 | |||
| 102 | if (Settings::IsConfiguringGlobal()) { | 105 | if (Settings::IsConfiguringGlobal()) { |
| 103 | Settings::values.sink_id = | 106 | Settings::values.sink_id = |
| 104 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) | 107 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) |
| @@ -108,19 +111,12 @@ void ConfigureAudio::ApplyConfiguration() { | |||
| 108 | .toStdString(); | 111 | .toStdString(); |
| 109 | 112 | ||
| 110 | // Guard if during game and set to game-specific value | 113 | // Guard if during game and set to game-specific value |
| 111 | if (Settings::values.enable_audio_stretching.UsingGlobal()) { | ||
| 112 | Settings::values.enable_audio_stretching.SetValue( | ||
| 113 | ui->toggle_audio_stretching->isChecked()); | ||
| 114 | } | ||
| 115 | if (Settings::values.volume.UsingGlobal()) { | 114 | if (Settings::values.volume.UsingGlobal()) { |
| 116 | Settings::values.volume.SetValue( | 115 | Settings::values.volume.SetValue( |
| 117 | static_cast<float>(ui->volume_slider->sliderPosition()) / | 116 | static_cast<float>(ui->volume_slider->sliderPosition()) / |
| 118 | ui->volume_slider->maximum()); | 117 | ui->volume_slider->maximum()); |
| 119 | } | 118 | } |
| 120 | } else { | 119 | } else { |
| 121 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, | ||
| 122 | ui->toggle_audio_stretching, | ||
| 123 | enable_audio_stretching); | ||
| 124 | if (ui->volume_combo_box->currentIndex() == 0) { | 120 | if (ui->volume_combo_box->currentIndex() == 0) { |
| 125 | Settings::values.volume.SetGlobal(true); | 121 | Settings::values.volume.SetGlobal(true); |
| 126 | } else { | 122 | } else { |
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 4f99bc80f..525c42ff0 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp | |||
| @@ -10,11 +10,14 @@ | |||
| 10 | #include "common/settings.h" | 10 | #include "common/settings.h" |
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "ui_configure_cpu.h" | 12 | #include "ui_configure_cpu.h" |
| 13 | #include "yuzu/configuration/configuration_shared.h" | ||
| 13 | #include "yuzu/configuration/configure_cpu.h" | 14 | #include "yuzu/configuration/configure_cpu.h" |
| 14 | 15 | ||
| 15 | ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureCpu) { | 16 | ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureCpu) { |
| 16 | ui->setupUi(this); | 17 | ui->setupUi(this); |
| 17 | 18 | ||
| 19 | SetupPerGameUI(); | ||
| 20 | |||
| 18 | SetConfiguration(); | 21 | SetConfiguration(); |
| 19 | 22 | ||
| 20 | connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, | 23 | connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, |
| @@ -29,19 +32,29 @@ void ConfigureCpu::SetConfiguration() { | |||
| 29 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 32 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 30 | 33 | ||
| 31 | ui->accuracy->setEnabled(runtime_lock); | 34 | ui->accuracy->setEnabled(runtime_lock); |
| 32 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy)); | ||
| 33 | UpdateGroup(static_cast<int>(Settings::values.cpu_accuracy)); | ||
| 34 | |||
| 35 | ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); | 35 | ui->cpuopt_unsafe_unfuse_fma->setEnabled(runtime_lock); |
| 36 | ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma); | ||
| 37 | ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); | 36 | ui->cpuopt_unsafe_reduce_fp_error->setEnabled(runtime_lock); |
| 38 | ui->cpuopt_unsafe_reduce_fp_error->setChecked(Settings::values.cpuopt_unsafe_reduce_fp_error); | ||
| 39 | ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock); | 37 | ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock); |
| 40 | ui->cpuopt_unsafe_inaccurate_nan->setChecked(Settings::values.cpuopt_unsafe_inaccurate_nan); | 38 | |
| 39 | ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()); | ||
| 40 | ui->cpuopt_unsafe_reduce_fp_error->setChecked( | ||
| 41 | Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()); | ||
| 42 | ui->cpuopt_unsafe_inaccurate_nan->setChecked( | ||
| 43 | Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()); | ||
| 44 | |||
| 45 | if (Settings::IsConfiguringGlobal()) { | ||
| 46 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue())); | ||
| 47 | } else { | ||
| 48 | ConfigurationShared::SetPerGameSetting(ui->accuracy, &Settings::values.cpu_accuracy); | ||
| 49 | ConfigurationShared::SetHighlight(ui->widget_accuracy, | ||
| 50 | !Settings::values.cpu_accuracy.UsingGlobal()); | ||
| 51 | } | ||
| 52 | UpdateGroup(ui->accuracy->currentIndex()); | ||
| 41 | } | 53 | } |
| 42 | 54 | ||
| 43 | void ConfigureCpu::AccuracyUpdated(int index) { | 55 | void ConfigureCpu::AccuracyUpdated(int index) { |
| 44 | if (static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) { | 56 | if (Settings::IsConfiguringGlobal() && |
| 57 | static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) { | ||
| 45 | const auto result = QMessageBox::warning(this, tr("Setting CPU to Debug Mode"), | 58 | const auto result = QMessageBox::warning(this, tr("Setting CPU to Debug Mode"), |
| 46 | tr("CPU Debug Mode is only intended for developer " | 59 | tr("CPU Debug Mode is only intended for developer " |
| 47 | "use. Are you sure you want to enable this?"), | 60 | "use. Are you sure you want to enable this?"), |
| @@ -54,16 +67,39 @@ void ConfigureCpu::AccuracyUpdated(int index) { | |||
| 54 | } | 67 | } |
| 55 | 68 | ||
| 56 | void ConfigureCpu::UpdateGroup(int index) { | 69 | void ConfigureCpu::UpdateGroup(int index) { |
| 57 | ui->unsafe_group->setVisible(static_cast<Settings::CPUAccuracy>(index) == | 70 | if (!Settings::IsConfiguringGlobal()) { |
| 58 | Settings::CPUAccuracy::Unsafe); | 71 | index -= ConfigurationShared::USE_GLOBAL_OFFSET; |
| 72 | } | ||
| 73 | const auto accuracy = static_cast<Settings::CPUAccuracy>(index); | ||
| 74 | ui->unsafe_group->setVisible(accuracy == Settings::CPUAccuracy::Unsafe); | ||
| 59 | } | 75 | } |
| 60 | 76 | ||
| 61 | void ConfigureCpu::ApplyConfiguration() { | 77 | void ConfigureCpu::ApplyConfiguration() { |
| 62 | Settings::values.cpu_accuracy = | 78 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_unfuse_fma, |
| 63 | static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex()); | 79 | ui->cpuopt_unsafe_unfuse_fma, |
| 64 | Settings::values.cpuopt_unsafe_unfuse_fma = ui->cpuopt_unsafe_unfuse_fma->isChecked(); | 80 | cpuopt_unsafe_unfuse_fma); |
| 65 | Settings::values.cpuopt_unsafe_reduce_fp_error = ui->cpuopt_unsafe_reduce_fp_error->isChecked(); | 81 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_reduce_fp_error, |
| 66 | Settings::values.cpuopt_unsafe_inaccurate_nan = ui->cpuopt_unsafe_inaccurate_nan->isChecked(); | 82 | ui->cpuopt_unsafe_reduce_fp_error, |
| 83 | cpuopt_unsafe_reduce_fp_error); | ||
| 84 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 85 | ui->cpuopt_unsafe_inaccurate_nan, | ||
| 86 | cpuopt_unsafe_inaccurate_nan); | ||
| 87 | |||
| 88 | if (Settings::IsConfiguringGlobal()) { | ||
| 89 | // Guard if during game and set to game-specific value | ||
| 90 | if (Settings::values.cpu_accuracy.UsingGlobal()) { | ||
| 91 | Settings::values.cpu_accuracy.SetValue( | ||
| 92 | static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex())); | ||
| 93 | } | ||
| 94 | } else { | ||
| 95 | if (ui->accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 96 | Settings::values.cpu_accuracy.SetGlobal(true); | ||
| 97 | } else { | ||
| 98 | Settings::values.cpu_accuracy.SetGlobal(false); | ||
| 99 | Settings::values.cpu_accuracy.SetValue(static_cast<Settings::CPUAccuracy>( | ||
| 100 | ui->accuracy->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 101 | } | ||
| 102 | } | ||
| 67 | } | 103 | } |
| 68 | 104 | ||
| 69 | void ConfigureCpu::changeEvent(QEvent* event) { | 105 | void ConfigureCpu::changeEvent(QEvent* event) { |
| @@ -77,3 +113,25 @@ void ConfigureCpu::changeEvent(QEvent* event) { | |||
| 77 | void ConfigureCpu::RetranslateUI() { | 113 | void ConfigureCpu::RetranslateUI() { |
| 78 | ui->retranslateUi(this); | 114 | ui->retranslateUi(this); |
| 79 | } | 115 | } |
| 116 | |||
| 117 | void ConfigureCpu::SetupPerGameUI() { | ||
| 118 | if (Settings::IsConfiguringGlobal()) { | ||
| 119 | return; | ||
| 120 | } | ||
| 121 | |||
| 122 | ConfigurationShared::SetColoredComboBox( | ||
| 123 | ui->accuracy, ui->widget_accuracy, | ||
| 124 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(true))); | ||
| 125 | ui->accuracy->removeItem(static_cast<u32>(Settings::CPUAccuracy::DebugMode) + | ||
| 126 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 127 | |||
| 128 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_unfuse_fma, | ||
| 129 | Settings::values.cpuopt_unsafe_unfuse_fma, | ||
| 130 | cpuopt_unsafe_unfuse_fma); | ||
| 131 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_reduce_fp_error, | ||
| 132 | Settings::values.cpuopt_unsafe_reduce_fp_error, | ||
| 133 | cpuopt_unsafe_reduce_fp_error); | ||
| 134 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_inaccurate_nan, | ||
| 135 | Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 136 | cpuopt_unsafe_inaccurate_nan); | ||
| 137 | } | ||
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index ef77b2e7e..8e2eeb7a6 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | #include <QWidget> | 8 | #include <QWidget> |
| 9 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | 10 | ||
| 11 | namespace ConfigurationShared { | ||
| 12 | enum class CheckState; | ||
| 13 | } | ||
| 14 | |||
| 11 | namespace Ui { | 15 | namespace Ui { |
| 12 | class ConfigureCpu; | 16 | class ConfigureCpu; |
| 13 | } | 17 | } |
| @@ -30,5 +34,11 @@ private: | |||
| 30 | 34 | ||
| 31 | void SetConfiguration(); | 35 | void SetConfiguration(); |
| 32 | 36 | ||
| 37 | void SetupPerGameUI(); | ||
| 38 | |||
| 33 | std::unique_ptr<Ui::ConfigureCpu> ui; | 39 | std::unique_ptr<Ui::ConfigureCpu> ui; |
| 40 | |||
| 41 | ConfigurationShared::CheckState cpuopt_unsafe_unfuse_fma; | ||
| 42 | ConfigurationShared::CheckState cpuopt_unsafe_reduce_fp_error; | ||
| 43 | ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan; | ||
| 34 | }; | 44 | }; |
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index bcd0962e9..d0e7e7bfe 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui | |||
| @@ -23,42 +23,44 @@ | |||
| 23 | </property> | 23 | </property> |
| 24 | <layout class="QVBoxLayout"> | 24 | <layout class="QVBoxLayout"> |
| 25 | <item> | 25 | <item> |
| 26 | <layout class="QHBoxLayout"> | 26 | <widget class="QWidget" name="widget_accuracy" native="true"> |
| 27 | <item> | 27 | <layout class="QHBoxLayout" name="layout_accuracy"> |
| 28 | <widget class="QLabel"> | 28 | <item> |
| 29 | <property name="text"> | 29 | <widget class="QLabel" name="label"> |
| 30 | <string>Accuracy:</string> | ||
| 31 | </property> | ||
| 32 | </widget> | ||
| 33 | </item> | ||
| 34 | <item> | ||
| 35 | <widget class="QComboBox" name="accuracy"> | ||
| 36 | <item> | ||
| 37 | <property name="text"> | 30 | <property name="text"> |
| 38 | <string>Accurate</string> | 31 | <string>Accuracy:</string> |
| 39 | </property> | 32 | </property> |
| 40 | </item> | 33 | </widget> |
| 41 | <item> | 34 | </item> |
| 42 | <property name="text"> | 35 | <item> |
| 43 | <string>Unsafe</string> | 36 | <widget class="QComboBox" name="accuracy"> |
| 44 | </property> | 37 | <item> |
| 45 | </item> | 38 | <property name="text"> |
| 46 | <item> | 39 | <string>Accurate</string> |
| 47 | <property name="text"> | 40 | </property> |
| 48 | <string>Enable Debug Mode</string> | 41 | </item> |
| 49 | </property> | 42 | <item> |
| 50 | </item> | 43 | <property name="text"> |
| 51 | </widget> | 44 | <string>Unsafe</string> |
| 52 | </item> | 45 | </property> |
| 53 | </layout> | 46 | </item> |
| 47 | <item> | ||
| 48 | <property name="text"> | ||
| 49 | <string>Enable Debug Mode</string> | ||
| 50 | </property> | ||
| 51 | </item> | ||
| 52 | </widget> | ||
| 53 | </item> | ||
| 54 | </layout> | ||
| 55 | </widget> | ||
| 54 | </item> | 56 | </item> |
| 55 | <item> | 57 | <item> |
| 56 | <widget class="QLabel"> | 58 | <widget class="QLabel" name="label"> |
| 57 | <property name="wordWrap"> | ||
| 58 | <bool>1</bool> | ||
| 59 | </property> | ||
| 60 | <property name="text"> | 59 | <property name="text"> |
| 61 | <string>We recommend setting accuracy to "Accurate".</string> | 60 | <string>We recommend setting accuracy to "Accurate".</string> |
| 61 | </property> | ||
| 62 | <property name="wordWrap"> | ||
| 63 | <bool>false</bool> | ||
| 62 | </property> | 64 | </property> |
| 63 | </widget> | 65 | </widget> |
| 64 | </item> | 66 | </item> |
| @@ -76,49 +78,49 @@ | |||
| 76 | </property> | 78 | </property> |
| 77 | <layout class="QVBoxLayout"> | 79 | <layout class="QVBoxLayout"> |
| 78 | <item> | 80 | <item> |
| 79 | <widget class="QLabel"> | 81 | <widget class="QLabel" name="label"> |
| 80 | <property name="wordWrap"> | ||
| 81 | <bool>1</bool> | ||
| 82 | </property> | ||
| 83 | <property name="text"> | 82 | <property name="text"> |
| 84 | <string>These settings reduce accuracy for speed.</string> | 83 | <string>These settings reduce accuracy for speed.</string> |
| 85 | </property> | 84 | </property> |
| 85 | <property name="wordWrap"> | ||
| 86 | <bool>false</bool> | ||
| 87 | </property> | ||
| 86 | </widget> | 88 | </widget> |
| 87 | </item> | 89 | </item> |
| 88 | <item> | 90 | <item> |
| 89 | <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma"> | 91 | <widget class="QCheckBox" name="cpuopt_unsafe_unfuse_fma"> |
| 90 | <property name="text"> | ||
| 91 | <string>Unfuse FMA (improve performance on CPUs without FMA)</string> | ||
| 92 | </property> | ||
| 93 | <property name="toolTip"> | 92 | <property name="toolTip"> |
| 94 | <string> | 93 | <string> |
| 95 | <div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div> | 94 | <div>This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.</div> |
| 96 | </string> | 95 | </string> |
| 97 | </property> | 96 | </property> |
| 97 | <property name="text"> | ||
| 98 | <string>Unfuse FMA (improve performance on CPUs without FMA)</string> | ||
| 99 | </property> | ||
| 98 | </widget> | 100 | </widget> |
| 99 | </item> | 101 | </item> |
| 100 | <item> | 102 | <item> |
| 101 | <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error"> | 103 | <widget class="QCheckBox" name="cpuopt_unsafe_reduce_fp_error"> |
| 102 | <property name="text"> | ||
| 103 | <string>Faster FRSQRTE and FRECPE</string> | ||
| 104 | </property> | ||
| 105 | <property name="toolTip"> | 104 | <property name="toolTip"> |
| 106 | <string> | 105 | <string> |
| 107 | <div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div> | 106 | <div>This option improves the speed of some approximate floating-point functions by using less accurate native approximations.</div> |
| 108 | </string> | 107 | </string> |
| 109 | </property> | 108 | </property> |
| 109 | <property name="text"> | ||
| 110 | <string>Faster FRSQRTE and FRECPE</string> | ||
| 111 | </property> | ||
| 110 | </widget> | 112 | </widget> |
| 111 | </item> | 113 | </item> |
| 112 | <item> | 114 | <item> |
| 113 | <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan"> | 115 | <widget class="QCheckBox" name="cpuopt_unsafe_inaccurate_nan"> |
| 114 | <property name="text"> | ||
| 115 | <string>Inaccurate NaN handling</string> | ||
| 116 | </property> | ||
| 117 | <property name="toolTip"> | 116 | <property name="toolTip"> |
| 118 | <string> | 117 | <string> |
| 119 | <div>This option improves speed by removing NaN checking. Please note this also reduces accuracy of certain floating-point instructions.</div> | 118 | <div>This option improves speed by removing NaN checking. Please note this also reduces accuracy of certain floating-point instructions.</div> |
| 120 | </string> | 119 | </string> |
| 121 | </property> | 120 | </property> |
| 121 | <property name="text"> | ||
| 122 | <string>Inaccurate NaN handling</string> | ||
| 123 | </property> | ||
| 122 | </widget> | 124 | </widget> |
| 123 | </item> | 125 | </item> |
| 124 | </layout> | 126 | </layout> |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index d812858b6..c9e60ee08 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | <item> | 23 | <item> |
| 24 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 24 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 25 | <item> | 25 | <item> |
| 26 | <widget class="QLabel" name="label_2"> | 26 | <widget class="QLabel" name="label_1"> |
| 27 | <property name="text"> | 27 | <property name="text"> |
| 28 | <string>Global Log Filter</string> | 28 | <string>Global Log Filter</string> |
| 29 | </property> | 29 | </property> |
| @@ -66,7 +66,7 @@ | |||
| 66 | </widget> | 66 | </widget> |
| 67 | </item> | 67 | </item> |
| 68 | <item> | 68 | <item> |
| 69 | <widget class="QLabel" name="label_3"> | 69 | <widget class="QLabel" name="label_2"> |
| 70 | <property name="font"> | 70 | <property name="font"> |
| 71 | <font> | 71 | <font> |
| 72 | <italic>true</italic> | 72 | <italic>true</italic> |
| @@ -92,7 +92,7 @@ | |||
| 92 | <item> | 92 | <item> |
| 93 | <layout class="QHBoxLayout" name="horizontalLayout_4"> | 93 | <layout class="QHBoxLayout" name="horizontalLayout_4"> |
| 94 | <item> | 94 | <item> |
| 95 | <widget class="QLabel" name="label_4"> | 95 | <widget class="QLabel" name="label_3"> |
| 96 | <property name="text"> | 96 | <property name="text"> |
| 97 | <string>Arguments String</string> | 97 | <string>Arguments String</string> |
| 98 | </property> | 98 | </property> |
| @@ -155,7 +155,7 @@ | |||
| 155 | </widget> | 155 | </widget> |
| 156 | </item> | 156 | </item> |
| 157 | <item> | 157 | <item> |
| 158 | <widget class="QLabel" name="label_5"> | 158 | <widget class="QLabel" name="label_4"> |
| 159 | <property name="font"> | 159 | <property name="font"> |
| 160 | <font> | 160 | <font> |
| 161 | <italic>true</italic> | 161 | <italic>true</italic> |
| @@ -200,7 +200,7 @@ | |||
| 200 | </widget> | 200 | </widget> |
| 201 | </item> | 201 | </item> |
| 202 | <item> | 202 | <item> |
| 203 | <widget class="QLabel" name="label_3"> | 203 | <widget class="QLabel" name="label_5"> |
| 204 | <property name="font"> | 204 | <property name="font"> |
| 205 | <font> | 205 | <font> |
| 206 | <italic>true</italic> | 206 | <italic>true</italic> |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 2fa88dcec..55a6a37bd 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -50,6 +50,9 @@ void ConfigureGeneral::SetConfiguration() { | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | void ConfigureGeneral::ApplyConfiguration() { | 52 | void ConfigureGeneral::ApplyConfiguration() { |
| 53 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core, | ||
| 54 | use_multi_core); | ||
| 55 | |||
| 53 | if (Settings::IsConfiguringGlobal()) { | 56 | if (Settings::IsConfiguringGlobal()) { |
| 54 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); | 57 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); |
| 55 | UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); | 58 | UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); |
| @@ -62,13 +65,7 @@ void ConfigureGeneral::ApplyConfiguration() { | |||
| 62 | Qt::Checked); | 65 | Qt::Checked); |
| 63 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); | 66 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); |
| 64 | } | 67 | } |
| 65 | if (Settings::values.use_multi_core.UsingGlobal()) { | ||
| 66 | Settings::values.use_multi_core.SetValue(ui->use_multi_core->isChecked()); | ||
| 67 | } | ||
| 68 | } else { | 68 | } else { |
| 69 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, | ||
| 70 | ui->use_multi_core, use_multi_core); | ||
| 71 | |||
| 72 | bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global; | 69 | bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global; |
| 73 | Settings::values.use_frame_limit.SetGlobal(global_frame_limit); | 70 | Settings::values.use_frame_limit.SetGlobal(global_frame_limit); |
| 74 | Settings::values.frame_limit.SetGlobal(global_frame_limit); | 71 | Settings::values.frame_limit.SetGlobal(global_frame_limit); |
| @@ -94,6 +91,9 @@ void ConfigureGeneral::RetranslateUI() { | |||
| 94 | 91 | ||
| 95 | void ConfigureGeneral::SetupPerGameUI() { | 92 | void ConfigureGeneral::SetupPerGameUI() { |
| 96 | if (Settings::IsConfiguringGlobal()) { | 93 | if (Settings::IsConfiguringGlobal()) { |
| 94 | // Disables each setting if: | ||
| 95 | // - A game is running (thus settings in use), and | ||
| 96 | // - A non-global setting is applied. | ||
| 97 | ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal()); | 97 | ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal()); |
| 98 | ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal()); | 98 | ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal()); |
| 99 | 99 | ||
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 0a7536617..fb9ec093c 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -106,6 +106,19 @@ void ConfigureGraphics::SetConfiguration() { | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | void ConfigureGraphics::ApplyConfiguration() { | 108 | void ConfigureGraphics::ApplyConfiguration() { |
| 109 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, | ||
| 110 | ui->fullscreen_mode_combobox); | ||
| 111 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, | ||
| 112 | ui->aspect_ratio_combobox); | ||
| 113 | |||
| 114 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, | ||
| 115 | ui->use_disk_shader_cache, use_disk_shader_cache); | ||
| 116 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, | ||
| 117 | ui->use_asynchronous_gpu_emulation, | ||
| 118 | use_asynchronous_gpu_emulation); | ||
| 119 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation, | ||
| 120 | ui->use_nvdec_emulation, use_nvdec_emulation); | ||
| 121 | |||
| 109 | if (Settings::IsConfiguringGlobal()) { | 122 | if (Settings::IsConfiguringGlobal()) { |
| 110 | // Guard if during game and set to game-specific value | 123 | // Guard if during game and set to game-specific value |
| 111 | if (Settings::values.renderer_backend.UsingGlobal()) { | 124 | if (Settings::values.renderer_backend.UsingGlobal()) { |
| @@ -114,22 +127,6 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 114 | if (Settings::values.vulkan_device.UsingGlobal()) { | 127 | if (Settings::values.vulkan_device.UsingGlobal()) { |
| 115 | Settings::values.vulkan_device.SetValue(vulkan_device); | 128 | Settings::values.vulkan_device.SetValue(vulkan_device); |
| 116 | } | 129 | } |
| 117 | if (Settings::values.fullscreen_mode.UsingGlobal()) { | ||
| 118 | Settings::values.fullscreen_mode.SetValue(ui->fullscreen_mode_combobox->currentIndex()); | ||
| 119 | } | ||
| 120 | if (Settings::values.aspect_ratio.UsingGlobal()) { | ||
| 121 | Settings::values.aspect_ratio.SetValue(ui->aspect_ratio_combobox->currentIndex()); | ||
| 122 | } | ||
| 123 | if (Settings::values.use_disk_shader_cache.UsingGlobal()) { | ||
| 124 | Settings::values.use_disk_shader_cache.SetValue(ui->use_disk_shader_cache->isChecked()); | ||
| 125 | } | ||
| 126 | if (Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()) { | ||
| 127 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | ||
| 128 | ui->use_asynchronous_gpu_emulation->isChecked()); | ||
| 129 | } | ||
| 130 | if (Settings::values.use_nvdec_emulation.UsingGlobal()) { | ||
| 131 | Settings::values.use_nvdec_emulation.SetValue(ui->use_nvdec_emulation->isChecked()); | ||
| 132 | } | ||
| 133 | if (Settings::values.bg_red.UsingGlobal()) { | 130 | if (Settings::values.bg_red.UsingGlobal()) { |
| 134 | Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); | 131 | Settings::values.bg_red.SetValue(static_cast<float>(bg_color.redF())); |
| 135 | Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); | 132 | Settings::values.bg_green.SetValue(static_cast<float>(bg_color.greenF())); |
| @@ -150,19 +147,6 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 150 | } | 147 | } |
| 151 | } | 148 | } |
| 152 | 149 | ||
| 153 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.fullscreen_mode, | ||
| 154 | ui->fullscreen_mode_combobox); | ||
| 155 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.aspect_ratio, | ||
| 156 | ui->aspect_ratio_combobox); | ||
| 157 | |||
| 158 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, | ||
| 159 | ui->use_disk_shader_cache, use_disk_shader_cache); | ||
| 160 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, | ||
| 161 | ui->use_asynchronous_gpu_emulation, | ||
| 162 | use_asynchronous_gpu_emulation); | ||
| 163 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation, | ||
| 164 | ui->use_nvdec_emulation, use_nvdec_emulation); | ||
| 165 | |||
| 166 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 150 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { |
| 167 | Settings::values.bg_red.SetGlobal(true); | 151 | Settings::values.bg_red.SetGlobal(true); |
| 168 | Settings::values.bg_green.SetGlobal(true); | 152 | Settings::values.bg_green.SetGlobal(true); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index c67609b0e..35bf9c6be 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -54,47 +54,23 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 54 | ui->gpu_accuracy->currentIndex() - | 54 | ui->gpu_accuracy->currentIndex() - |
| 55 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); | 55 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); |
| 56 | 56 | ||
| 57 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 58 | ui->anisotropic_filtering_combobox); | ||
| 59 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); | ||
| 60 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, | ||
| 61 | ui->use_assembly_shaders, use_assembly_shaders); | ||
| 62 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | ||
| 63 | ui->use_asynchronous_shaders, | ||
| 64 | use_asynchronous_shaders); | ||
| 65 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | ||
| 66 | ui->use_fast_gpu_time, use_fast_gpu_time); | ||
| 67 | |||
| 57 | if (Settings::IsConfiguringGlobal()) { | 68 | if (Settings::IsConfiguringGlobal()) { |
| 58 | // Must guard in case of a during-game configuration when set to be game-specific. | 69 | // Must guard in case of a during-game configuration when set to be game-specific. |
| 59 | if (Settings::values.gpu_accuracy.UsingGlobal()) { | 70 | if (Settings::values.gpu_accuracy.UsingGlobal()) { |
| 60 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); | 71 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); |
| 61 | } | 72 | } |
| 62 | if (Settings::values.use_vsync.UsingGlobal()) { | ||
| 63 | Settings::values.use_vsync.SetValue(ui->use_vsync->isChecked()); | ||
| 64 | } | ||
| 65 | if (Settings::values.use_assembly_shaders.UsingGlobal()) { | ||
| 66 | Settings::values.use_assembly_shaders.SetValue(ui->use_assembly_shaders->isChecked()); | ||
| 67 | } | ||
| 68 | if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { | ||
| 69 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 70 | ui->use_asynchronous_shaders->isChecked()); | ||
| 71 | } | ||
| 72 | if (Settings::values.use_asynchronous_shaders.UsingGlobal()) { | ||
| 73 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 74 | ui->use_asynchronous_shaders->isChecked()); | ||
| 75 | } | ||
| 76 | if (Settings::values.use_fast_gpu_time.UsingGlobal()) { | ||
| 77 | Settings::values.use_fast_gpu_time.SetValue(ui->use_fast_gpu_time->isChecked()); | ||
| 78 | } | ||
| 79 | if (Settings::values.max_anisotropy.UsingGlobal()) { | ||
| 80 | Settings::values.max_anisotropy.SetValue( | ||
| 81 | ui->anisotropic_filtering_combobox->currentIndex()); | ||
| 82 | } | ||
| 83 | } else { | 73 | } else { |
| 84 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 85 | ui->anisotropic_filtering_combobox); | ||
| 86 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, | ||
| 87 | use_vsync); | ||
| 88 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, | ||
| 89 | ui->use_assembly_shaders, use_assembly_shaders); | ||
| 90 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | ||
| 91 | ui->use_asynchronous_shaders, | ||
| 92 | use_asynchronous_shaders); | ||
| 93 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | ||
| 94 | ui->use_fast_gpu_time, use_fast_gpu_time); | ||
| 95 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | ||
| 96 | ui->anisotropic_filtering_combobox); | ||
| 97 | |||
| 98 | if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 74 | if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { |
| 99 | Settings::values.gpu_accuracy.SetGlobal(true); | 75 | Settings::values.gpu_accuracy.SetGlobal(true); |
| 100 | } else { | 76 | } else { |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index c9318c562..ab3512810 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -153,6 +153,10 @@ QString ButtonToText(const Common::ParamPackage& param) { | |||
| 153 | return QObject::tr("Button %1").arg(button_str); | 153 | return QObject::tr("Button %1").arg(button_str); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | if (param.Has("motion")) { | ||
| 157 | return QObject::tr("SDL Motion"); | ||
| 158 | } | ||
| 159 | |||
| 156 | return {}; | 160 | return {}; |
| 157 | } | 161 | } |
| 158 | 162 | ||
| @@ -1245,12 +1249,16 @@ void ConfigureInputPlayer::UpdateMappingWithDefaults() { | |||
| 1245 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; | 1249 | const auto& device = input_devices[ui->comboDevices->currentIndex()]; |
| 1246 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); | 1250 | auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); |
| 1247 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); | 1251 | auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); |
| 1252 | auto motion_mapping = input_subsystem->GetMotionMappingForDevice(device); | ||
| 1248 | for (std::size_t i = 0; i < buttons_param.size(); ++i) { | 1253 | for (std::size_t i = 0; i < buttons_param.size(); ++i) { |
| 1249 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; | 1254 | buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; |
| 1250 | } | 1255 | } |
| 1251 | for (std::size_t i = 0; i < analogs_param.size(); ++i) { | 1256 | for (std::size_t i = 0; i < analogs_param.size(); ++i) { |
| 1252 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; | 1257 | analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; |
| 1253 | } | 1258 | } |
| 1259 | for (std::size_t i = 0; i < motions_param.size(); ++i) { | ||
| 1260 | motions_param[i] = motion_mapping[static_cast<Settings::NativeMotion::Values>(i)]; | ||
| 1261 | } | ||
| 1254 | 1262 | ||
| 1255 | UpdateUI(); | 1263 | UpdateUI(); |
| 1256 | } | 1264 | } |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index bd91ebc42..f550567e2 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -52,6 +52,7 @@ ConfigurePerGame::~ConfigurePerGame() = default; | |||
| 52 | void ConfigurePerGame::ApplyConfiguration() { | 52 | void ConfigurePerGame::ApplyConfiguration() { |
| 53 | ui->addonsTab->ApplyConfiguration(); | 53 | ui->addonsTab->ApplyConfiguration(); |
| 54 | ui->generalTab->ApplyConfiguration(); | 54 | ui->generalTab->ApplyConfiguration(); |
| 55 | ui->cpuTab->ApplyConfiguration(); | ||
| 55 | ui->systemTab->ApplyConfiguration(); | 56 | ui->systemTab->ApplyConfiguration(); |
| 56 | ui->graphicsTab->ApplyConfiguration(); | 57 | ui->graphicsTab->ApplyConfiguration(); |
| 57 | ui->graphicsAdvancedTab->ApplyConfiguration(); | 58 | ui->graphicsAdvancedTab->ApplyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_per_game.ui b/src/yuzu/configuration/configure_per_game.ui index 25975b3b9..adf6d0b39 100644 --- a/src/yuzu/configuration/configure_per_game.ui +++ b/src/yuzu/configuration/configure_per_game.ui | |||
| @@ -235,6 +235,11 @@ | |||
| 235 | <string>System</string> | 235 | <string>System</string> |
| 236 | </attribute> | 236 | </attribute> |
| 237 | </widget> | 237 | </widget> |
| 238 | <widget class="ConfigureCpu" name="cpuTab"> | ||
| 239 | <attribute name="title"> | ||
| 240 | <string>CPU</string> | ||
| 241 | </attribute> | ||
| 242 | </widget> | ||
| 238 | <widget class="ConfigureGraphics" name="graphicsTab"> | 243 | <widget class="ConfigureGraphics" name="graphicsTab"> |
| 239 | <attribute name="title"> | 244 | <attribute name="title"> |
| 240 | <string>Graphics</string> | 245 | <string>Graphics</string> |
| @@ -311,6 +316,12 @@ | |||
| 311 | <header>configuration/configure_per_game_addons.h</header> | 316 | <header>configuration/configure_per_game_addons.h</header> |
| 312 | <container>1</container> | 317 | <container>1</container> |
| 313 | </customwidget> | 318 | </customwidget> |
| 319 | <customwidget> | ||
| 320 | <class>ConfigureCpu</class> | ||
| 321 | <extends>QWidget</extends> | ||
| 322 | <header>configuration/configure_cpu.h</header> | ||
| 323 | <container>1</container> | ||
| 324 | </customwidget> | ||
| 314 | </customwidgets> | 325 | </customwidgets> |
| 315 | <resources/> | 326 | <resources/> |
| 316 | <connections> | 327 | <connections> |
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 268ed44c3..85418f969 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -65,7 +65,7 @@ void ConfigureSystem::SetConfiguration() { | |||
| 65 | QStringLiteral("%1") | 65 | QStringLiteral("%1") |
| 66 | .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'}) | 66 | .arg(Settings::values.rng_seed.GetValue().value_or(0), 8, 16, QLatin1Char{'0'}) |
| 67 | .toUpper(); | 67 | .toUpper(); |
| 68 | const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or( | 68 | const auto rtc_time = Settings::values.custom_rtc.value_or( |
| 69 | std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); | 69 | std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); |
| 70 | 70 | ||
| 71 | ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); | 71 | ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value()); |
| @@ -73,9 +73,8 @@ void ConfigureSystem::SetConfiguration() { | |||
| 73 | Settings::values.rng_seed.UsingGlobal()); | 73 | Settings::values.rng_seed.UsingGlobal()); |
| 74 | ui->rng_seed_edit->setText(rng_seed); | 74 | ui->rng_seed_edit->setText(rng_seed); |
| 75 | 75 | ||
| 76 | ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value()); | 76 | ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.has_value()); |
| 77 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() && | 77 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.has_value()); |
| 78 | Settings::values.rng_seed.UsingGlobal()); | ||
| 79 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); | 78 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count())); |
| 80 | 79 | ||
| 81 | if (Settings::IsConfiguringGlobal()) { | 80 | if (Settings::IsConfiguringGlobal()) { |
| @@ -109,17 +108,17 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 109 | 108 | ||
| 110 | // Allow setting custom RTC even if system is powered on, | 109 | // Allow setting custom RTC even if system is powered on, |
| 111 | // to allow in-game time to be fast forwarded | 110 | // to allow in-game time to be fast forwarded |
| 112 | if (Settings::values.custom_rtc.UsingGlobal()) { | 111 | if (Settings::IsConfiguringGlobal()) { |
| 113 | if (ui->custom_rtc_checkbox->isChecked()) { | 112 | if (ui->custom_rtc_checkbox->isChecked()) { |
| 114 | Settings::values.custom_rtc.SetValue( | 113 | Settings::values.custom_rtc = |
| 115 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); | 114 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()); |
| 116 | if (system.IsPoweredOn()) { | 115 | if (system.IsPoweredOn()) { |
| 117 | const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() + | 116 | const s64 posix_time{Settings::values.custom_rtc->count() + |
| 118 | Service::Time::TimeManager::GetExternalTimeZoneOffset()}; | 117 | Service::Time::TimeManager::GetExternalTimeZoneOffset()}; |
| 119 | system.GetTimeManager().UpdateLocalSystemClockTime(posix_time); | 118 | system.GetTimeManager().UpdateLocalSystemClockTime(posix_time); |
| 120 | } | 119 | } |
| 121 | } else { | 120 | } else { |
| 122 | Settings::values.custom_rtc.SetValue(std::nullopt); | 121 | Settings::values.custom_rtc = std::nullopt; |
| 123 | } | 122 | } |
| 124 | } | 123 | } |
| 125 | 124 | ||
| @@ -127,21 +126,14 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 127 | return; | 126 | return; |
| 128 | } | 127 | } |
| 129 | 128 | ||
| 129 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, ui->combo_language); | ||
| 130 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); | ||
| 131 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, | ||
| 132 | ui->combo_time_zone); | ||
| 133 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); | ||
| 134 | |||
| 130 | if (Settings::IsConfiguringGlobal()) { | 135 | if (Settings::IsConfiguringGlobal()) { |
| 131 | // Guard if during game and set to game-specific value | 136 | // Guard if during game and set to game-specific value |
| 132 | if (Settings::values.language_index.UsingGlobal()) { | ||
| 133 | Settings::values.language_index.SetValue(ui->combo_language->currentIndex()); | ||
| 134 | } | ||
| 135 | if (Settings::values.region_index.UsingGlobal()) { | ||
| 136 | Settings::values.region_index.SetValue(ui->combo_region->currentIndex()); | ||
| 137 | } | ||
| 138 | if (Settings::values.time_zone_index.UsingGlobal()) { | ||
| 139 | Settings::values.time_zone_index.SetValue(ui->combo_time_zone->currentIndex()); | ||
| 140 | } | ||
| 141 | if (Settings::values.sound_index.UsingGlobal()) { | ||
| 142 | Settings::values.sound_index.SetValue(ui->combo_sound->currentIndex()); | ||
| 143 | } | ||
| 144 | |||
| 145 | if (Settings::values.rng_seed.UsingGlobal()) { | 137 | if (Settings::values.rng_seed.UsingGlobal()) { |
| 146 | if (ui->rng_seed_checkbox->isChecked()) { | 138 | if (ui->rng_seed_checkbox->isChecked()) { |
| 147 | Settings::values.rng_seed.SetValue( | 139 | Settings::values.rng_seed.SetValue( |
| @@ -151,13 +143,6 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 151 | } | 143 | } |
| 152 | } | 144 | } |
| 153 | } else { | 145 | } else { |
| 154 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, | ||
| 155 | ui->combo_language); | ||
| 156 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); | ||
| 157 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, | ||
| 158 | ui->combo_time_zone); | ||
| 159 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); | ||
| 160 | |||
| 161 | switch (use_rng_seed) { | 146 | switch (use_rng_seed) { |
| 162 | case ConfigurationShared::CheckState::On: | 147 | case ConfigurationShared::CheckState::On: |
| 163 | case ConfigurationShared::CheckState::Off: | 148 | case ConfigurationShared::CheckState::Off: |
| @@ -177,26 +162,6 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 177 | case ConfigurationShared::CheckState::Count: | 162 | case ConfigurationShared::CheckState::Count: |
| 178 | break; | 163 | break; |
| 179 | } | 164 | } |
| 180 | |||
| 181 | switch (use_custom_rtc) { | ||
| 182 | case ConfigurationShared::CheckState::On: | ||
| 183 | case ConfigurationShared::CheckState::Off: | ||
| 184 | Settings::values.custom_rtc.SetGlobal(false); | ||
| 185 | if (ui->custom_rtc_checkbox->isChecked()) { | ||
| 186 | Settings::values.custom_rtc.SetValue( | ||
| 187 | std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); | ||
| 188 | } else { | ||
| 189 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 190 | } | ||
| 191 | break; | ||
| 192 | case ConfigurationShared::CheckState::Global: | ||
| 193 | Settings::values.custom_rtc.SetGlobal(false); | ||
| 194 | Settings::values.custom_rtc.SetValue(std::nullopt); | ||
| 195 | Settings::values.custom_rtc.SetGlobal(true); | ||
| 196 | break; | ||
| 197 | case ConfigurationShared::CheckState::Count: | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | } | 165 | } |
| 201 | 166 | ||
| 202 | system.ApplySettings(); | 167 | system.ApplySettings(); |
| @@ -227,8 +192,6 @@ void ConfigureSystem::SetupPerGameUI() { | |||
| 227 | ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal()); | 192 | ui->combo_sound->setEnabled(Settings::values.sound_index.UsingGlobal()); |
| 228 | ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal()); | 193 | ui->rng_seed_checkbox->setEnabled(Settings::values.rng_seed.UsingGlobal()); |
| 229 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal()); | 194 | ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.UsingGlobal()); |
| 230 | ui->custom_rtc_checkbox->setEnabled(Settings::values.custom_rtc.UsingGlobal()); | ||
| 231 | ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.UsingGlobal()); | ||
| 232 | 195 | ||
| 233 | return; | 196 | return; |
| 234 | } | 197 | } |
| @@ -246,8 +209,7 @@ void ConfigureSystem::SetupPerGameUI() { | |||
| 246 | ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(), | 209 | ui->rng_seed_checkbox, Settings::values.rng_seed.UsingGlobal(), |
| 247 | Settings::values.rng_seed.GetValue().has_value(), | 210 | Settings::values.rng_seed.GetValue().has_value(), |
| 248 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); | 211 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); |
| 249 | ConfigurationShared::SetColoredTristate( | 212 | |
| 250 | ui->custom_rtc_checkbox, Settings::values.custom_rtc.UsingGlobal(), | 213 | ui->custom_rtc_checkbox->setVisible(false); |
| 251 | Settings::values.custom_rtc.GetValue().has_value(), | 214 | ui->custom_rtc_edit->setVisible(false); |
| 252 | Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc); | ||
| 253 | } | 215 | } |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 9e72acbf7..9275cba53 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -241,14 +241,15 @@ GMainWindow::GMainWindow() | |||
| 241 | ConnectMenuEvents(); | 241 | ConnectMenuEvents(); |
| 242 | ConnectWidgetEvents(); | 242 | ConnectWidgetEvents(); |
| 243 | 243 | ||
| 244 | const auto branch_name = std::string(Common::g_scm_branch); | ||
| 245 | const auto description = std::string(Common::g_scm_desc); | ||
| 244 | const auto build_id = std::string(Common::g_build_id); | 246 | const auto build_id = std::string(Common::g_build_id); |
| 245 | const auto fmt = std::string(Common::g_title_bar_format_idle); | ||
| 246 | const auto yuzu_build_version = | ||
| 247 | fmt::format(fmt.empty() ? "yuzu Development Build" : fmt, std::string{}, std::string{}, | ||
| 248 | std::string{}, std::string{}, std::string{}, build_id); | ||
| 249 | 247 | ||
| 250 | LOG_INFO(Frontend, "yuzu Version: {} | {}-{}", yuzu_build_version, Common::g_scm_branch, | 248 | const auto yuzu_build = fmt::format("yuzu Development Build | {}-{}", branch_name, description); |
| 251 | Common::g_scm_desc); | 249 | const auto override_build = fmt::format(std::string(Common::g_title_bar_format_idle), build_id); |
| 250 | const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; | ||
| 251 | |||
| 252 | LOG_INFO(Frontend, "yuzu Version: {}", yuzu_build_version); | ||
| 252 | #ifdef ARCHITECTURE_x86_64 | 253 | #ifdef ARCHITECTURE_x86_64 |
| 253 | const auto& caps = Common::GetCPUCaps(); | 254 | const auto& caps = Common::GetCPUCaps(); |
| 254 | std::string cpu_string = caps.cpu_string; | 255 | std::string cpu_string = caps.cpu_string; |
| @@ -1377,7 +1378,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { | |||
| 1377 | game_list->hide(); | 1378 | game_list->hide(); |
| 1378 | game_list_placeholder->hide(); | 1379 | game_list_placeholder->hide(); |
| 1379 | } | 1380 | } |
| 1380 | status_bar_update_timer.start(2000); | 1381 | status_bar_update_timer.start(500); |
| 1381 | async_status_button->setDisabled(true); | 1382 | async_status_button->setDisabled(true); |
| 1382 | multicore_status_button->setDisabled(true); | 1383 | multicore_status_button->setDisabled(true); |
| 1383 | renderer_status_button->setDisabled(true); | 1384 | renderer_status_button->setDisabled(true); |
| @@ -2101,6 +2102,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2101 | QStringList new_files{}; // Newly installed files that do not yet exist in the NAND | 2102 | QStringList new_files{}; // Newly installed files that do not yet exist in the NAND |
| 2102 | QStringList overwritten_files{}; // Files that overwrote those existing in the NAND | 2103 | QStringList overwritten_files{}; // Files that overwrote those existing in the NAND |
| 2103 | QStringList failed_files{}; // Files that failed to install due to errors | 2104 | QStringList failed_files{}; // Files that failed to install due to errors |
| 2105 | bool detected_base_install{}; // Whether a base game was attempted to be installed | ||
| 2104 | 2106 | ||
| 2105 | ui.action_Install_File_NAND->setEnabled(false); | 2107 | ui.action_Install_File_NAND->setEnabled(false); |
| 2106 | 2108 | ||
| @@ -2126,6 +2128,7 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2126 | 2128 | ||
| 2127 | while (!future.isFinished()) { | 2129 | while (!future.isFinished()) { |
| 2128 | QCoreApplication::processEvents(); | 2130 | QCoreApplication::processEvents(); |
| 2131 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); | ||
| 2129 | } | 2132 | } |
| 2130 | 2133 | ||
| 2131 | result = future.result(); | 2134 | result = future.result(); |
| @@ -2146,6 +2149,10 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2146 | case InstallResult::Failure: | 2149 | case InstallResult::Failure: |
| 2147 | failed_files.append(QFileInfo(file).fileName()); | 2150 | failed_files.append(QFileInfo(file).fileName()); |
| 2148 | break; | 2151 | break; |
| 2152 | case InstallResult::BaseInstallAttempted: | ||
| 2153 | failed_files.append(QFileInfo(file).fileName()); | ||
| 2154 | detected_base_install = true; | ||
| 2155 | break; | ||
| 2149 | } | 2156 | } |
| 2150 | 2157 | ||
| 2151 | --remaining; | 2158 | --remaining; |
| @@ -2153,6 +2160,13 @@ void GMainWindow::OnMenuInstallToNAND() { | |||
| 2153 | 2160 | ||
| 2154 | install_progress->close(); | 2161 | install_progress->close(); |
| 2155 | 2162 | ||
| 2163 | if (detected_base_install) { | ||
| 2164 | QMessageBox::warning( | ||
| 2165 | this, tr("Install Results"), | ||
| 2166 | tr("To avoid possible conflicts, we discourage users from installing base games to the " | ||
| 2167 | "NAND.\nPlease, only use this feature to install updates and DLC.")); | ||
| 2168 | } | ||
| 2169 | |||
| 2156 | const QString install_results = | 2170 | const QString install_results = |
| 2157 | (new_files.isEmpty() ? QString{} | 2171 | (new_files.isEmpty() ? QString{} |
| 2158 | : tr("%n file(s) were newly installed\n", "", new_files.size())) + | 2172 | : tr("%n file(s) were newly installed\n", "", new_files.size())) + |
| @@ -2214,11 +2228,14 @@ InstallResult GMainWindow::InstallNSPXCI(const QString& filename) { | |||
| 2214 | const auto res = | 2228 | const auto res = |
| 2215 | Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry( | 2229 | Core::System::GetInstance().GetFileSystemController().GetUserNANDContents()->InstallEntry( |
| 2216 | *nsp, true, qt_raw_copy); | 2230 | *nsp, true, qt_raw_copy); |
| 2217 | if (res == FileSys::InstallResult::Success) { | 2231 | switch (res) { |
| 2232 | case FileSys::InstallResult::Success: | ||
| 2218 | return InstallResult::Success; | 2233 | return InstallResult::Success; |
| 2219 | } else if (res == FileSys::InstallResult::OverwriteExisting) { | 2234 | case FileSys::InstallResult::OverwriteExisting: |
| 2220 | return InstallResult::Overwrite; | 2235 | return InstallResult::Overwrite; |
| 2221 | } else { | 2236 | case FileSys::InstallResult::ErrorBaseInstall: |
| 2237 | return InstallResult::BaseInstallAttempted; | ||
| 2238 | default: | ||
| 2222 | return InstallResult::Failure; | 2239 | return InstallResult::Failure; |
| 2223 | } | 2240 | } |
| 2224 | } | 2241 | } |
| @@ -2751,24 +2768,19 @@ void GMainWindow::MigrateConfigFiles() { | |||
| 2751 | 2768 | ||
| 2752 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, | 2769 | void GMainWindow::UpdateWindowTitle(const std::string& title_name, |
| 2753 | const std::string& title_version) { | 2770 | const std::string& title_version) { |
| 2754 | const auto full_name = std::string(Common::g_build_fullname); | ||
| 2755 | const auto branch_name = std::string(Common::g_scm_branch); | 2771 | const auto branch_name = std::string(Common::g_scm_branch); |
| 2756 | const auto description = std::string(Common::g_scm_desc); | 2772 | const auto description = std::string(Common::g_scm_desc); |
| 2757 | const auto build_id = std::string(Common::g_build_id); | 2773 | const auto build_id = std::string(Common::g_build_id); |
| 2758 | 2774 | ||
| 2759 | const auto date = | 2775 | const auto yuzu_title = fmt::format("yuzu | {}-{}", branch_name, description); |
| 2760 | QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd")).toStdString(); | 2776 | const auto override_title = fmt::format(std::string(Common::g_title_bar_format_idle), build_id); |
| 2777 | const auto window_title = override_title.empty() ? yuzu_title : override_title; | ||
| 2761 | 2778 | ||
| 2762 | if (title_name.empty()) { | 2779 | if (title_name.empty()) { |
| 2763 | const auto fmt = std::string(Common::g_title_bar_format_idle); | 2780 | setWindowTitle(QString::fromStdString(window_title)); |
| 2764 | setWindowTitle(QString::fromStdString(fmt::format(fmt.empty() ? "yuzu {0}| {1}-{2}" : fmt, | ||
| 2765 | full_name, branch_name, description, | ||
| 2766 | std::string{}, date, build_id))); | ||
| 2767 | } else { | 2781 | } else { |
| 2768 | const auto fmt = std::string(Common::g_title_bar_format_running); | 2782 | const auto run_title = fmt::format("{} | {} | {}", window_title, title_name, title_version); |
| 2769 | setWindowTitle(QString::fromStdString( | 2783 | setWindowTitle(QString::fromStdString(run_title)); |
| 2770 | fmt::format(fmt.empty() ? "yuzu {0}| {3} | {6} | {1}-{2}" : fmt, full_name, branch_name, | ||
| 2771 | description, title_name, date, build_id, title_version))); | ||
| 2772 | } | 2784 | } |
| 2773 | } | 2785 | } |
| 2774 | 2786 | ||
| @@ -2797,7 +2809,7 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2797 | } else { | 2809 | } else { |
| 2798 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); | 2810 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); |
| 2799 | } | 2811 | } |
| 2800 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 0)); | 2812 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0)); |
| 2801 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); | 2813 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); |
| 2802 | 2814 | ||
| 2803 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); | 2815 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 98a608fce..b3a5033ce 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -76,6 +76,7 @@ enum class InstallResult { | |||
| 76 | Success, | 76 | Success, |
| 77 | Overwrite, | 77 | Overwrite, |
| 78 | Failure, | 78 | Failure, |
| 79 | BaseInstallAttempted, | ||
| 79 | }; | 80 | }; |
| 80 | 81 | ||
| 81 | enum class ReinitializeKeyBehavior { | 82 | enum class ReinitializeKeyBehavior { |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 7e1d5f379..38d896d65 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -361,10 +361,10 @@ void Config::ReadValues() { | |||
| 361 | 361 | ||
| 362 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); | 362 | const auto custom_rtc_enabled = sdl2_config->GetBoolean("System", "custom_rtc_enabled", false); |
| 363 | if (custom_rtc_enabled) { | 363 | if (custom_rtc_enabled) { |
| 364 | Settings::values.custom_rtc.SetValue( | 364 | Settings::values.custom_rtc = |
| 365 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0))); | 365 | std::chrono::seconds(sdl2_config->GetInteger("System", "custom_rtc", 0)); |
| 366 | } else { | 366 | } else { |
| 367 | Settings::values.custom_rtc.SetValue(std::nullopt); | 367 | Settings::values.custom_rtc = std::nullopt; |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | Settings::values.language_index.SetValue( | 370 | Settings::values.language_index.SetValue( |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index d64f81106..06b20c975 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -215,7 +215,7 @@ void EmuWindow_SDL2::WaitEvent() { | |||
| 215 | const auto results = Core::System::GetInstance().GetAndResetPerfStats(); | 215 | const auto results = Core::System::GetInstance().GetAndResetPerfStats(); |
| 216 | const auto title = | 216 | const auto title = |
| 217 | fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, | 217 | fmt::format("yuzu {} | {}-{} | FPS: {:.0f} ({:.0f}%)", Common::g_build_fullname, |
| 218 | Common::g_scm_branch, Common::g_scm_desc, results.game_fps, | 218 | Common::g_scm_branch, Common::g_scm_desc, results.average_game_fps, |
| 219 | results.emulation_speed * 100.0); | 219 | results.emulation_speed * 100.0); |
| 220 | SDL_SetWindowTitle(render_window, title.c_str()); | 220 | SDL_SetWindowTitle(render_window, title.c_str()); |
| 221 | last_time = current_time; | 221 | last_time = current_time; |