summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.ci/scripts/linux/docker.sh8
-rw-r--r--.ci/scripts/linux/upload.sh2
-rw-r--r--CMakeLists.txt30
-rw-r--r--externals/CMakeLists.txt12
m---------externals/ffmpeg0
m---------externals/mbedtls0
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/common/tree.h2
-rw-r--r--src/core/CMakeLists.txt26
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.h2
-rw-r--r--src/core/arm/dynarmic/arm_exclusive_monitor.cpp4
-rw-r--r--src/core/arm/dynarmic/arm_exclusive_monitor.h2
-rw-r--r--src/core/core.cpp3
-rw-r--r--src/core/cpu_manager.cpp2
-rw-r--r--src/core/cpu_manager.h2
-rw-r--r--src/core/crypto/ctr_encryption_layer.cpp4
-rw-r--r--src/core/crypto/ctr_encryption_layer.h2
-rw-r--r--src/core/crypto/key_manager.cpp2
-rw-r--r--src/core/file_sys/nca_metadata.cpp8
-rw-r--r--src/core/file_sys/nca_metadata.h4
-rw-r--r--src/core/file_sys/registered_cache.cpp7
-rw-r--r--src/core/file_sys/registered_cache.h1
-rw-r--r--src/core/file_sys/submission_package.cpp4
-rw-r--r--src/core/file_sys/submission_package.h2
-rw-r--r--src/core/file_sys/vfs_concat.cpp8
-rw-r--r--src/core/file_sys/vfs_concat.h4
-rw-r--r--src/core/file_sys/vfs_layered.cpp4
-rw-r--r--src/core/file_sys/vfs_layered.h2
-rw-r--r--src/core/file_sys/vfs_libzip.cpp9
-rw-r--r--src/core/file_sys/vfs_static.h6
-rw-r--r--src/core/file_sys/vfs_vector.cpp4
-rw-r--r--src/core/file_sys/vfs_vector.h4
-rw-r--r--src/core/frontend/emu_window.cpp2
-rw-r--r--src/core/hle/ipc.h17
-rw-r--r--src/core/hle/ipc_helpers.h86
-rw-r--r--src/core/hle/kernel/global_scheduler_context.cpp4
-rw-r--r--src/core/hle/kernel/global_scheduler_context.h2
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp149
-rw-r--r--src/core/hle/kernel/hle_ipc.h28
-rw-r--r--src/core/hle/kernel/k_auto_object.h6
-rw-r--r--src/core/hle/kernel/k_client_port.cpp12
-rw-r--r--src/core/hle/kernel/k_client_port.h2
-rw-r--r--src/core/hle/kernel/k_client_session.cpp3
-rw-r--r--src/core/hle/kernel/k_client_session.h2
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp3
-rw-r--r--src/core/hle/kernel/k_event.cpp5
-rw-r--r--src/core/hle/kernel/k_event.h2
-rw-r--r--src/core/hle/kernel/k_light_condition_variable.h3
-rw-r--r--src/core/hle/kernel/k_linked_list.h12
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.cpp38
-rw-r--r--src/core/hle/kernel/k_memory_block_manager.h2
-rw-r--r--src/core/hle/kernel/k_memory_region.h4
-rw-r--r--src/core/hle/kernel/k_page_linked_list.h2
-rw-r--r--src/core/hle/kernel/k_page_table.cpp10
-rw-r--r--src/core/hle/kernel/k_page_table.h2
-rw-r--r--src/core/hle/kernel/k_port.cpp4
-rw-r--r--src/core/hle/kernel/k_port.h2
-rw-r--r--src/core/hle/kernel/k_process.cpp16
-rw-r--r--src/core/hle/kernel/k_process.h4
-rw-r--r--src/core/hle/kernel/k_readable_event.cpp2
-rw-r--r--src/core/hle/kernel/k_readable_event.h2
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp4
-rw-r--r--src/core/hle/kernel/k_resource_limit.h2
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp22
-rw-r--r--src/core/hle/kernel/k_scheduler.h4
-rw-r--r--src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h4
-rw-r--r--src/core/hle/kernel/k_server_port.cpp2
-rw-r--r--src/core/hle/kernel/k_server_port.h2
-rw-r--r--src/core/hle/kernel/k_server_session.cpp6
-rw-r--r--src/core/hle/kernel/k_server_session.h2
-rw-r--r--src/core/hle/kernel/k_session.cpp6
-rw-r--r--src/core/hle/kernel/k_session.h2
-rw-r--r--src/core/hle/kernel/k_shared_memory.cpp16
-rw-r--r--src/core/hle/kernel/k_shared_memory.h15
-rw-r--r--src/core/hle/kernel/k_synchronization_object.cpp13
-rw-r--r--src/core/hle/kernel/k_thread.cpp32
-rw-r--r--src/core/hle/kernel/k_thread.h6
-rw-r--r--src/core/hle/kernel/k_thread_queue.h2
-rw-r--r--src/core/hle/kernel/k_transfer_memory.cpp4
-rw-r--r--src/core/hle/kernel/k_transfer_memory.h4
-rw-r--r--src/core/hle/kernel/k_writable_event.cpp3
-rw-r--r--src/core/hle/kernel/k_writable_event.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp37
-rw-r--r--src/core/hle/kernel/kernel.h18
-rw-r--r--src/core/hle/kernel/physical_core.cpp8
-rw-r--r--src/core/hle/kernel/physical_core.h4
-rw-r--r--src/core/hle/kernel/slab_helpers.h4
-rw-r--r--src/core/hle/kernel/svc.cpp13
-rw-r--r--src/core/hle/result.h2
-rw-r--r--src/core/hle/service/am/am.cpp14
-rw-r--r--src/core/hle/service/apm/controller.cpp10
-rw-r--r--src/core/hle/service/apm/controller.h2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp44
-rw-r--r--src/core/hle/service/audio/audren_u.h2
-rw-r--r--src/core/hle/service/audio/hwopus.cpp8
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp13
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/controller_base.h2
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp352
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h77
-rw-r--r--src/core/hle/service/mii/manager.h2
-rw-r--r--src/core/hle/service/mii/mii.cpp4
-rw-r--r--src/core/hle/service/nifm/nifm.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdevice.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h12
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h12
-rw-r--r--src/core/hle/service/nvdrv/syncpoint_manager.cpp2
-rw-r--r--src/core/hle/service/nvdrv/syncpoint_manager.h2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp4
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h2
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp32
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h12
-rw-r--r--src/core/hle/service/pctl/pctl.cpp4
-rw-r--r--src/core/hle/service/pctl/pctl.h2
-rw-r--r--src/core/hle/service/pm/pm.cpp12
-rw-r--r--src/core/hle/service/service.cpp55
-rw-r--r--src/core/hle/service/service.h47
-rw-r--r--src/core/hle/service/sm/controller.cpp14
-rw-r--r--src/core/hle/service/sm/sm.cpp107
-rw-r--r--src/core/hle/service/sm/sm.h10
-rw-r--r--src/core/hle/service/ssl/ssl.cpp42
-rw-r--r--src/core/hle/service/time/ephemeral_network_system_clock_core.h4
-rw-r--r--src/core/hle/service/time/local_system_clock_context_writer.h4
-rw-r--r--src/core/hle/service/time/network_system_clock_context_writer.h4
-rw-r--r--src/core/hle/service/time/standard_local_system_clock_core.h4
-rw-r--r--src/core/hle/service/time/standard_network_system_clock_core.h10
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.cpp22
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.h8
-rw-r--r--src/core/hle/service/time/system_clock_core.cpp4
-rw-r--r--src/core/hle/service/time/system_clock_core.h2
-rw-r--r--src/core/hle/service/time/time_manager.cpp2
-rw-r--r--src/core/hle/service/time/time_manager.h2
-rw-r--r--src/core/hle/service/time/time_sharedmemory.cpp2
-rw-r--r--src/core/hle/service/time/time_sharedmemory.h2
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp4
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.h2
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp4
-rw-r--r--src/core/hle/service/vi/display/vi_display.h8
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.cpp2
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h4
-rw-r--r--src/core/hle/service/vi/vi.cpp24
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp23
-rw-r--r--src/core/loader/deconstructed_rom_directory.h4
-rw-r--r--src/core/loader/loader.cpp2
-rw-r--r--src/core/loader/loader.h2
-rw-r--r--src/core/memory/cheat_engine.cpp14
-rw-r--r--src/core/memory/cheat_engine.h8
-rw-r--r--src/core/memory/dmnt_cheat_vm.cpp3
-rw-r--r--src/core/memory/dmnt_cheat_vm.h2
-rw-r--r--src/core/perf_stats.cpp14
-rw-r--r--src/core/perf_stats.h11
-rw-r--r--src/core/reporter.cpp2
-rw-r--r--src/core/reporter.h2
-rw-r--r--src/input_common/main.cpp5
-rw-r--r--src/input_common/sdl/sdl.h3
-rw-r--r--src/input_common/sdl/sdl_impl.cpp153
-rw-r--r--src/input_common/sdl/sdl_impl.h1
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h5
-rw-r--r--src/video_core/gpu.cpp5
-rw-r--r--src/video_core/gpu.h2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h8
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp1
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp26
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h10
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp38
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h5
-rw-r--r--src/video_core/texture_cache/texture_cache.h57
-rw-r--r--src/video_core/texture_cache/types.h7
-rw-r--r--src/yuzu/about_dialog.cpp16
-rw-r--r--src/yuzu/aboutdialog.ui2
-rw-r--r--src/yuzu/configuration/configure_debug.ui10
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp8
-rw-r--r--src/yuzu/configuration/configure_ui.cpp1
-rw-r--r--src/yuzu/main.cpp56
-rw-r--r--src/yuzu/main.h1
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp2
181 files changed, 1567 insertions, 818 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
30rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester 30rm -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
33wget -nc https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage 33wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-x86_64.AppImage
34wget -nc https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage 34wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/linuxdeploy-plugin-qt-x86_64.AppImage
35wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-x86_64 35wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/AppRun-patched-x86_64
36wget -nc https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-x86_64.so 36wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so
37# Set executable bit 37# Set executable bit
38chmod 755 \ 38chmod 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
22cd build 22cd build
23 23
24wget -nc https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage 24wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/appimagetool-x86_64.AppImage
25chmod 755 appimagetool-x86_64.AppImage 25chmod 755 appimagetool-x86_64.AppImage
26 26
27if [ "${RELEASE_NAME}" = "mainline" ]; then 27if [ "${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
13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) 13option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
14CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF) 14CMAKE_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
16CMAKE_DEPENDENT_OPTION(YUZU_ALLOW_SYSTEM_SDL2 "Try using system SDL2 before fallling back to one from externals" NOT UNIX "ENABLE_SDL2" OFF)
15 17
16option(ENABLE_QT "Enable the Qt frontend" ON) 18option(ENABLE_QT "Enable the Qt frontend" ON)
17option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) 19option(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()
311endif() 317endif()
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
49if (NOT SDL2_FOUND AND ENABLE_SDL2) 49if (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)
54endif() 66endif()
diff --git a/externals/ffmpeg b/externals/ffmpeg
Subproject 6b6b9e593dd4d3aaf75f48d40a13ef03bdef9fd Subproject 79e8d17024e6c6328a40fcee191ffd70798a9c6
diff --git a/externals/mbedtls b/externals/mbedtls
Subproject eac2416b8fdb2cb9c867a538100bf95326bad75 Subproject 8c88150ca139e06aa2aae8349df8292a88148ea
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/tree.h b/src/common/tree.h
index 3da49e422..9d2d0df4e 100644
--- a/src/common/tree.h
+++ b/src/common/tree.h
@@ -322,7 +322,7 @@ void RB_INSERT_COLOR(RBHead<Node>* head, Node* elm) {
322template <typename Node> 322template <typename Node>
323void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) { 323void RB_REMOVE_COLOR(RBHead<Node>* head, Node* parent, Node* elm) {
324 Node* tmp; 324 Node* tmp;
325 while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root()) { 325 while ((elm == nullptr || RB_IS_BLACK(elm)) && elm != head->Root() && parent != nullptr) {
326 if (RB_LEFT(parent) == elm) { 326 if (RB_LEFT(parent) == elm) {
327 tmp = RB_RIGHT(parent); 327 tmp = RB_RIGHT(parent);
328 if (RB_IS_RED(tmp)) { 328 if (RB_IS_RED(tmp)) {
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
652if (MSVC) 652if (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 )
669else() 666else()
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..ab3266916 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
25class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { 25class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
26public: 26public:
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);
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 653bb7a77..a4d830e48 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
28class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { 28class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
29public: 29public:
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);
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 {
18public: 18public:
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
10namespace Core { 10namespace Core {
11 11
12DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count) 12DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_)
13 : monitor(core_count), memory{memory} {} 13 : monitor{core_count_}, memory{memory_} {}
14 14
15DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; 15DynarmicExclusiveMonitor::~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
23class DynarmicExclusiveMonitor final : public ExclusiveMonitor { 23class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
24public: 24public:
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..47e70c157 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -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
19namespace Core { 19namespace Core {
20 20
21CpuManager::CpuManager(System& system) : system{system} {} 21CpuManager::CpuManager(System& system_) : system{system_} {}
22CpuManager::~CpuManager() = default; 22CpuManager::~CpuManager() = default;
23 23
24void CpuManager::ThreadStart(CpuManager& cpu_manager, std::size_t core) { 24void 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
26class CpuManager { 26class CpuManager {
27public: 27public:
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 @@
10namespace Core::Crypto { 10namespace Core::Crypto {
11 11
12CTREncryptionLayer::CTREncryptionLayer(FileSys::VirtualFile base_, Key128 key_, 12CTREncryptionLayer::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
16std::size_t CTREncryptionLayer::Read(u8* data, std::size_t length, std::size_t offset) const { 16std::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 {
17public: 17public:
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
42CNMT::CNMT(CNMTHeader header, OptionalHeader opt_header, std::vector<ContentRecord> content_records, 42CNMT::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
47CNMT::~CNMT() = default; 47CNMT::~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.");
87class CNMT { 87class CNMT {
88public: 88public:
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
43struct ContentProviderEntry { 44struct 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
21namespace FileSys { 21namespace FileSys {
22 22
23NSP::NSP(VirtualFile file_, std::size_t program_index) 23NSP::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
28class NSP : public ReadOnlyVfsDirectory { 28class NSP : public ReadOnlyVfsDirectory {
29public: 29public:
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
26ConcatenatedVfsFile::ConcatenatedVfsFile(std::vector<VirtualFile> files_, std::string name) 26ConcatenatedVfsFile::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
35ConcatenatedVfsFile::ConcatenatedVfsFile(std::multimap<u64, VirtualFile> files_, std::string name) 35ConcatenatedVfsFile::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.
16class ConcatenatedVfsFile : public VfsFile { 16class 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
20public: 20public:
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
9namespace FileSys { 9namespace FileSys {
10 10
11LayeredVfsDirectory::LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name) 11LayeredVfsDirectory::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
14LayeredVfsDirectory::~LayeredVfsDirectory() = default; 14LayeredVfsDirectory::~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.
15class LayeredVfsDirectory : public VfsDirectory { 15class LayeredVfsDirectory : public VfsDirectory {
16 LayeredVfsDirectory(std::vector<VirtualDir> dirs, std::string name); 16 explicit LayeredVfsDirectory(std::vector<VirtualDir> dirs_, std::string name_);
17 17
18public: 18public:
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
15class StaticVfsFile : public VfsFile { 15class StaticVfsFile : public VfsFile {
16public: 16public:
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
9namespace FileSys { 9namespace FileSys {
10VectorVfsFile::VectorVfsFile(std::vector<u8> initial_data, std::string name, VirtualDir parent) 10VectorVfsFile::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
13VectorVfsFile::~VectorVfsFile() = default; 13VectorVfsFile::~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
76class VectorVfsFile : public VfsFile { 76class VectorVfsFile : public VfsFile {
77public: 77public:
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:
26private: 26private:
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
38struct CommandHeader { 39struct 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};
61static_assert(sizeof(CommandHeader) == 8, "CommandHeader size is incorrect"); 76static_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 0906b8cfb..497f35d23 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 {
26protected: 28protected:
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
31public: 33public:
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,64 +71,79 @@ public:
69 AlwaysMoveHandles = 1, 71 AlwaysMoveHandles = 1,
70 }; 72 };
71 73
72 explicit ResponseBuilder(Kernel::HLERequestContext& context, 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(context), 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{context.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 context.ClearIncomingObjects(); 83 ctx.ClearIncomingObjects();
82 84
83 IPC::CommandHeader header{}; 85 IPC::CommandHeader header{};
84 86
85 // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory 87 // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory
86 // padding. 88 // padding.
87 u64 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; 89 u32 raw_data_size = ctx.IsTipc()
90 ? normal_params_size - 1
91 : sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size;
88 92
89 u32 num_handles_to_move{}; 93 u32 num_handles_to_move{};
90 u32 num_domain_objects{}; 94 u32 num_domain_objects{};
91 const bool always_move_handles{ 95 const bool always_move_handles{
92 (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; 96 (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0};
93 if (!context.Session()->IsDomain() || always_move_handles) { 97 if (!ctx.Session()->IsDomain() || always_move_handles) {
94 num_handles_to_move = num_objects_to_move; 98 num_handles_to_move = num_objects_to_move;
95 } else { 99 } else {
96 num_domain_objects = num_objects_to_move; 100 num_domain_objects = num_objects_to_move;
97 } 101 }
98 102
99 if (context.Session()->IsDomain()) { 103 if (ctx.Session()->IsDomain()) {
100 raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; 104 raw_data_size += static_cast<u32>(sizeof(DomainMessageHeader) / 4 + num_domain_objects);
101 } 105 }
102 106
107 if (ctx.IsTipc()) {
108 header.type.Assign(ctx.GetCommandType());
109 }
110
111 ctx.data_size = static_cast<u32>(raw_data_size);
103 header.data_size.Assign(static_cast<u32>(raw_data_size)); 112 header.data_size.Assign(static_cast<u32>(raw_data_size));
104 if (num_handles_to_copy || num_handles_to_move) { 113 if (num_handles_to_copy != 0 || num_handles_to_move != 0) {
105 header.enable_handle_descriptor.Assign(1); 114 header.enable_handle_descriptor.Assign(1);
106 } 115 }
107 PushRaw(header); 116 PushRaw(header);
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 (context.Session()->IsDomain() && context.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.domain_offset = index + raw_data_size / 4;
130 } 147 }
131 148
132 template <class T> 149 template <class T>
@@ -134,6 +151,9 @@ public:
134 if (context->Session()->IsDomain()) { 151 if (context->Session()->IsDomain()) {
135 context->AddDomainObject(std::move(iface)); 152 context->AddDomainObject(std::move(iface));
136 } else { 153 } else {
154 // kernel.CurrentProcess()->GetResourceLimit()->Reserve(
155 // Kernel::LimitableResource::Sessions, 1);
156
137 auto* session = Kernel::KSession::Create(kernel); 157 auto* session = Kernel::KSession::Create(kernel);
138 session->Initialize(nullptr, iface->GetServiceName()); 158 session->Initialize(nullptr, iface->GetServiceName());
139 159
@@ -152,7 +172,7 @@ public:
152 const std::size_t num_move_objects = context->NumMoveObjects(); 172 const std::size_t num_move_objects = context->NumMoveObjects();
153 ASSERT_MSG(!num_domain_objects || !num_move_objects, 173 ASSERT_MSG(!num_domain_objects || !num_move_objects,
154 "cannot move normal handles and domain objects"); 174 "cannot move normal handles and domain objects");
155 ASSERT_MSG((index - datapayload_index) == normal_params_size, 175 ASSERT_MSG((index - data_payload_index) == normal_params_size,
156 "normal_params_size value is incorrect"); 176 "normal_params_size value is incorrect");
157 ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move, 177 ASSERT_MSG((num_domain_objects + num_move_objects) == num_objects_to_move,
158 "num_objects_to_move value is incorrect"); 178 "num_objects_to_move value is incorrect");
@@ -229,14 +249,14 @@ private:
229 u32 normal_params_size{}; 249 u32 normal_params_size{};
230 u32 num_handles_to_copy{}; 250 u32 num_handles_to_copy{};
231 u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent 251 u32 num_objects_to_move{}; ///< Domain objects or move handles, context dependent
232 std::ptrdiff_t datapayload_index{}; 252 u32 data_payload_index{};
233 Kernel::KernelCore& kernel; 253 Kernel::KernelCore& kernel;
234}; 254};
235 255
236/// Push /// 256/// Push ///
237 257
238inline void ResponseBuilder::PushImpl(s32 value) { 258inline void ResponseBuilder::PushImpl(s32 value) {
239 cmdbuf[index++] = static_cast<u32>(value); 259 cmdbuf[index++] = value;
240} 260}
241 261
242inline void ResponseBuilder::PushImpl(u32 value) { 262inline void ResponseBuilder::PushImpl(u32 value) {
@@ -341,9 +361,9 @@ class RequestParser : public RequestHelperBase {
341public: 361public:
342 explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {} 362 explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {}
343 363
344 explicit RequestParser(Kernel::HLERequestContext& context) : RequestHelperBase(context) { 364 explicit RequestParser(Kernel::HLERequestContext& ctx) : RequestHelperBase(ctx) {
345 ASSERT_MSG(context.GetDataPayloadOffset(), "context is incomplete"); 365 ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete");
346 Skip(context.GetDataPayloadOffset(), false); 366 Skip(ctx.GetDataPayloadOffset(), false);
347 // Skip the u64 command id, it's already stored in the context 367 // Skip the u64 command id, it's already stored in the context
348 static constexpr u32 CommandIdSize = 2; 368 static constexpr u32 CommandIdSize = 2;
349 Skip(CommandIdSize, false); 369 Skip(CommandIdSize, false);
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
13namespace Kernel { 13namespace Kernel {
14 14
15GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel) 15GlobalSchedulerContext::GlobalSchedulerContext(KernelCore& kernel_)
16 : kernel{kernel}, scheduler_lock{kernel} {} 16 : kernel{kernel_}, scheduler_lock{kernel_} {}
17 17
18GlobalSchedulerContext::~GlobalSchedulerContext() = default; 18GlobalSchedulerContext::~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 {
34public: 34public:
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 b505d20a6..ce3466df8 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -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 }
@@ -99,39 +99,43 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
99 buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); 99 buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>());
100 } 100 }
101 101
102 buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; 102 const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size;
103 103
104 // Padding to align to 16 bytes 104 if (!command_header->IsTipc()) {
105 rp.AlignWithPadding(); 105 // Padding to align to 16 bytes
106 106 rp.AlignWithPadding();
107 if (Session()->IsDomain() && ((command_header->type == IPC::CommandType::Request || 107
108 command_header->type == IPC::CommandType::RequestWithContext) || 108 if (Session()->IsDomain() &&
109 !incoming)) { 109 ((command_header->type == IPC::CommandType::Request ||
110 // If this is an incoming message, only CommandType "Request" has a domain header 110 command_header->type == IPC::CommandType::RequestWithContext) ||
111 // All outgoing domain messages have the domain header, if only incoming has it 111 !incoming)) {
112 if (incoming || domain_message_header) { 112 // If this is an incoming message, only CommandType "Request" has a domain header
113 domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); 113 // All outgoing domain messages have the domain header, if only incoming has it
114 } else { 114 if (incoming || domain_message_header) {
115 if (Session()->IsDomain()) { 115 domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>();
116 LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); 116 } else {
117 if (Session()->IsDomain()) {
118 LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
119 }
117 } 120 }
118 } 121 }
119 }
120 122
121 data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); 123 data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>();
122 124
123 data_payload_offset = rp.GetCurrentOffset(); 125 data_payload_offset = rp.GetCurrentOffset();
124 126
125 if (domain_message_header && domain_message_header->command == 127 if (domain_message_header &&
126 IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { 128 domain_message_header->command ==
127 // CloseVirtualHandle command does not have SFC* or any data 129 IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) {
128 return; 130 // CloseVirtualHandle command does not have SFC* or any data
129 } 131 return;
132 }
130 133
131 if (incoming) { 134 if (incoming) {
132 ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); 135 ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I'));
133 } else { 136 } else {
134 ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); 137 ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O'));
138 }
135 } 139 }
136 140
137 rp.SetCurrentOffset(buffer_c_offset); 141 rp.SetCurrentOffset(buffer_c_offset);
@@ -166,84 +170,67 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
166ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, 170ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table,
167 u32_le* src_cmdbuf) { 171 u32_le* src_cmdbuf) {
168 ParseCommandBuffer(handle_table, src_cmdbuf, true); 172 ParseCommandBuffer(handle_table, src_cmdbuf, true);
169 if (command_header->type == IPC::CommandType::Close) { 173
174 if (command_header->IsCloseCommand()) {
170 // Close does not populate the rest of the IPC header 175 // Close does not populate the rest of the IPC header
171 return RESULT_SUCCESS; 176 return RESULT_SUCCESS;
172 } 177 }
173 178
174 // The data_size already includes the payload header, the padding and the domain header. 179 std::copy_n(src_cmdbuf, IPC::COMMAND_BUFFER_LENGTH, cmd_buf.begin());
175 std::size_t size = data_payload_offset + command_header->data_size - 180
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; 181 return RESULT_SUCCESS;
181} 182}
182 183
183ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& thread) { 184ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) {
184 auto& owner_process = *thread.GetOwnerProcess(); 185 auto current_offset = handles_offset;
186 auto& owner_process = *requesting_thread.GetOwnerProcess();
185 auto& handle_table = owner_process.GetHandleTable(); 187 auto& handle_table = owner_process.GetHandleTable();
186 188
187 std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf;
188 memory.ReadBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(),
189 dst_cmdbuf.size() * sizeof(u32));
190
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. 189 // 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 - 190 std::size_t 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 191
203 if (command_header->enable_handle_descriptor) { 192 if (IsTipc()) {
204 ASSERT_MSG(!move_objects.empty() || !copy_objects.empty(), 193 size = cmd_buf.size();
205 "Handle descriptor bit set but no handles to translate"); 194 } else {
206 // We write the translated handles at a specific offset in the command buffer, this space 195 size = data_payload_offset + data_size - sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4;
207 // was already reserved when writing the header. 196 if (Session()->IsDomain()) {
208 std::size_t current_offset = 197 size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32);
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 } 198 }
199 }
222 200
223 for (auto& object : move_objects) { 201 for (auto& object : copy_objects) {
224 ASSERT(object != nullptr); 202 Handle handle{};
225 R_TRY(handle_table.Add(&dst_cmdbuf[current_offset++], object)); 203 if (object) {
204 R_TRY(handle_table.Add(&handle, object));
226 } 205 }
206 cmd_buf[current_offset++] = handle;
227 } 207 }
208 for (auto& object : move_objects) {
209 Handle handle{};
210 if (object) {
211 R_TRY(handle_table.Add(&handle, object));
228 212
229 // TODO(Subv): Translate the X/A/B/W buffers. 213 // Close our reference to the object, as it is being moved to the caller.
214 object->Close();
215 }
216 cmd_buf[current_offset++] = handle;
217 }
230 218
231 if (Session()->IsDomain() && domain_message_header) { 219 // Write the domain objects to the command buffer, these go after the raw untranslated data.
232 ASSERT(domain_message_header->num_objects == domain_objects.size()); 220 // TODO(Subv): This completely ignores C buffers.
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 221
222 if (Session()->IsDomain()) {
223 current_offset = domain_offset - static_cast<u32>(domain_objects.size());
237 for (const auto& object : domain_objects) { 224 for (const auto& object : domain_objects) {
238 server_session->AppendDomainRequestHandler(object); 225 server_session->AppendDomainRequestHandler(object);
239 dst_cmdbuf[domain_offset++] = 226 cmd_buf[current_offset++] =
240 static_cast<u32_le>(server_session->NumDomainRequestHandlers()); 227 static_cast<u32_le>(server_session->NumDomainRequestHandlers());
241 } 228 }
242 } 229 }
243 230
244 // Copy the translated command buffer back into the thread's command buffer area. 231 // Copy the translated command buffer back into the thread's command buffer area.
245 memory.WriteBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), 232 memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(),
246 dst_cmdbuf.size() * sizeof(u32)); 233 size * sizeof(u32));
247 234
248 return RESULT_SUCCESS; 235 return RESULT_SUCCESS;
249} 236}
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index fa031c121..4fba300dc 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -66,7 +66,8 @@ public:
66 * this request (ServerSession, Originator thread, Translated command buffer, etc). 66 * this request (ServerSession, Originator thread, Translated command buffer, etc).
67 * @returns ResultCode the result code of the translate operation. 67 * @returns ResultCode the result code of the translate operation.
68 */ 68 */
69 virtual ResultCode HandleSyncRequest(Kernel::HLERequestContext& context) = 0; 69 virtual ResultCode HandleSyncRequest(Kernel::KServerSession& session,
70 Kernel::HLERequestContext& context) = 0;
70 71
71 /** 72 /**
72 * Signals that a client has just connected to this HLE handler and keeps the 73 * Signals that a client has just connected to this HLE handler and keeps the
@@ -126,17 +127,30 @@ public:
126 u32_le* src_cmdbuf); 127 u32_le* src_cmdbuf);
127 128
128 /// Writes data from this context back to the requesting process/thread. 129 /// Writes data from this context back to the requesting process/thread.
129 ResultCode WriteToOutgoingCommandBuffer(KThread& thread); 130 ResultCode WriteToOutgoingCommandBuffer(KThread& requesting_thread);
130 131
131 u32_le GetCommand() const { 132 u32_le GetHipcCommand() const {
132 return command; 133 return command;
133 } 134 }
134 135
136 u32_le GetTipcCommand() const {
137 return static_cast<u32_le>(command_header->type.Value()) -
138 static_cast<u32_le>(IPC::CommandType::TIPC_CommandRegion);
139 }
140
141 u32_le GetCommand() const {
142 return command_header->IsTipc() ? GetTipcCommand() : GetHipcCommand();
143 }
144
145 bool IsTipc() const {
146 return command_header->IsTipc();
147 }
148
135 IPC::CommandType GetCommandType() const { 149 IPC::CommandType GetCommandType() const {
136 return command_header->type; 150 return command_header->type;
137 } 151 }
138 152
139 unsigned GetDataPayloadOffset() const { 153 u32 GetDataPayloadOffset() const {
140 return data_payload_offset; 154 return data_payload_offset;
141 } 155 }
142 156
@@ -291,8 +305,10 @@ private:
291 std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; 305 std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors;
292 std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; 306 std::vector<IPC::BufferDescriptorC> buffer_c_desciptors;
293 307
294 unsigned data_payload_offset{}; 308 u32 data_payload_offset{};
295 unsigned buffer_c_offset{}; 309 u32 handles_offset{};
310 u32 domain_offset{};
311 u32 data_size{};
296 u32_le command{}; 312 u32_le command{};
297 313
298 std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; 314 std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h
index 765e46670..bc18582be 100644
--- a/src/core/hle/kernel/k_auto_object.h
+++ b/src/core/hle/kernel/k_auto_object.h
@@ -177,7 +177,7 @@ class KAutoObjectWithListContainer;
177 177
178class KAutoObjectWithList : public KAutoObject { 178class KAutoObjectWithList : public KAutoObject {
179public: 179public:
180 explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_), kernel(kernel_) {} 180 explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_) {}
181 181
182 static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) { 182 static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) {
183 const u64 lid = lhs.GetId(); 183 const u64 lid = lhs.GetId();
@@ -204,11 +204,7 @@ public:
204private: 204private:
205 friend class KAutoObjectWithListContainer; 205 friend class KAutoObjectWithListContainer;
206 206
207private:
208 Common::IntrusiveRedBlackTreeNode list_node; 207 Common::IntrusiveRedBlackTreeNode list_node;
209
210protected:
211 KernelCore& kernel;
212}; 208};
213 209
214template <typename T> 210template <typename T>
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp
index b6f1d713f..ad01cf67e 100644
--- a/src/core/hle/kernel/k_client_port.cpp
+++ b/src/core/hle/kernel/k_client_port.cpp
@@ -13,7 +13,7 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16KClientPort::KClientPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} 16KClientPort::KClientPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
17KClientPort::~KClientPort() = default; 17KClientPort::~KClientPort() = default;
18 18
19void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) { 19void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) {
@@ -58,9 +58,9 @@ bool KClientPort::IsSignaled() const {
58 58
59ResultCode KClientPort::CreateSession(KClientSession** out) { 59ResultCode KClientPort::CreateSession(KClientSession** out) {
60 // Reserve a new session from the resource limit. 60 // Reserve a new session from the resource limit.
61 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), 61 // KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
62 LimitableResource::Sessions); 62 // LimitableResource::Sessions);
63 R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); 63 // R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
64 64
65 // Update the session counts. 65 // Update the session counts.
66 { 66 {
@@ -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();
@@ -104,7 +104,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) {
104 session->Initialize(this, parent->GetName()); 104 session->Initialize(this, parent->GetName());
105 105
106 // Commit the session reservation. 106 // Commit the session reservation.
107 session_reservation.Commit(); 107 // session_reservation.Commit();
108 108
109 // Register the session. 109 // Register the session.
110 KSession::Register(kernel, session); 110 KSession::Register(kernel, session);
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index ec1d7e12e..d00ce3ddd 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -21,7 +21,7 @@ class KClientPort final : public KSynchronizationObject {
21 KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject); 21 KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject);
22 22
23public: 23public:
24 explicit KClientPort(KernelCore& kernel); 24 explicit KClientPort(KernelCore& kernel_);
25 virtual ~KClientPort() override; 25 virtual ~KClientPort() override;
26 26
27 void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_); 27 void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_);
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp
index 0618dc246..8ad1be762 100644
--- a/src/core/hle/kernel/k_client_session.cpp
+++ b/src/core/hle/kernel/k_client_session.cpp
@@ -12,7 +12,8 @@
12 12
13namespace Kernel { 13namespace Kernel {
14 14
15KClientSession::KClientSession(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} 15KClientSession::KClientSession(KernelCore& kernel_)
16 : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
16KClientSession::~KClientSession() = default; 17KClientSession::~KClientSession() = default;
17 18
18void KClientSession::Destroy() { 19void KClientSession::Destroy() {
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h
index 6476a588b..720a8c243 100644
--- a/src/core/hle/kernel/k_client_session.h
+++ b/src/core/hle/kernel/k_client_session.h
@@ -33,7 +33,7 @@ class KClientSession final
33 KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject); 33 KERNEL_AUTOOBJECT_TRAITS(KClientSession, KAutoObject);
34 34
35public: 35public:
36 explicit KClientSession(KernelCore& kernel); 36 explicit KClientSession(KernelCore& kernel_);
37 virtual ~KClientSession(); 37 virtual ~KClientSession();
38 38
39 void Initialize(KSession* parent_, std::string&& name_) { 39 void Initialize(KSession* parent_, std::string&& name_) {
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index f51cf3e7b..ce3bade60 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -254,8 +254,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
254 } 254 }
255 255
256 // Close threads in the list. 256 // Close threads in the list.
257 for (auto it = thread_list.begin(); it != thread_list.end(); 257 for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) {
258 it = thread_list.erase(kernel, it)) {
259 (*it).Close(); 258 (*it).Close();
260 } 259 }
261} 260}
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
index 986355b78..0720efece 100644
--- a/src/core/hle/kernel/k_event.cpp
+++ b/src/core/hle/kernel/k_event.cpp
@@ -8,8 +8,9 @@
8 8
9namespace Kernel { 9namespace Kernel {
10 10
11KEvent::KEvent(KernelCore& kernel) 11KEvent::KEvent(KernelCore& kernel_)
12 : KAutoObjectWithSlabHeapAndContainer{kernel}, readable_event{kernel}, writable_event{kernel} {} 12 : KAutoObjectWithSlabHeapAndContainer{kernel_}, readable_event{kernel_}, writable_event{
13 kernel_} {}
13 14
14KEvent::~KEvent() = default; 15KEvent::~KEvent() = default;
15 16
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
index 4ca869930..9a59ffb70 100644
--- a/src/core/hle/kernel/k_event.h
+++ b/src/core/hle/kernel/k_event.h
@@ -19,7 +19,7 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj
19 KERNEL_AUTOOBJECT_TRAITS(KEvent, KAutoObject); 19 KERNEL_AUTOOBJECT_TRAITS(KEvent, KAutoObject);
20 20
21public: 21public:
22 explicit KEvent(KernelCore& kernel); 22 explicit KEvent(KernelCore& kernel_);
23 virtual ~KEvent(); 23 virtual ~KEvent();
24 24
25 void Initialize(std::string&& name); 25 void Initialize(std::string&& name);
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
19class KLightConditionVariable { 19class KLightConditionVariable {
20public: 20public:
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 500f44685..6adfe1e34 100644
--- a/src/core/hle/kernel/k_linked_list.h
+++ b/src/core/hle/kernel/k_linked_list.h
@@ -124,7 +124,7 @@ public:
124 124
125 ~KLinkedList() { 125 ~KLinkedList() {
126 // Erase all elements. 126 // Erase all elements.
127 for (auto it = this->begin(); it != this->end(); it = this->erase(kernel, it)) { 127 for (auto it = begin(); it != end(); it = erase(it)) {
128 } 128 }
129 129
130 // Ensure we succeeded. 130 // Ensure we succeeded.
@@ -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) {
@@ -223,7 +223,7 @@ public:
223 this->erase(this->begin()); 223 this->erase(this->begin());
224 } 224 }
225 225
226 iterator erase(KernelCore& kernel, const iterator pos) { 226 iterator erase(const iterator pos) {
227 KLinkedListNode* freed_node = std::addressof(*pos.m_base_it); 227 KLinkedListNode* freed_node = std::addressof(*pos.m_base_it);
228 iterator ret = iterator(BaseList::erase(pos.m_base_it)); 228 iterator ret = iterator(BaseList::erase(pos.m_base_it));
229 KLinkedListNode::Free(kernel, freed_node); 229 KLinkedListNode::Free(kernel, freed_node);
diff --git a/src/core/hle/kernel/k_memory_block_manager.cpp b/src/core/hle/kernel/k_memory_block_manager.cpp
index 4a2d88008..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
8namespace Kernel { 8namespace Kernel {
9 9
10KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr) 10KMemoryBlockManager::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);
@@ -17,8 +17,8 @@ KMemoryBlockManager::KMemoryBlockManager(VAddr start_addr, VAddr end_addr)
17KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) { 17KMemoryBlockManager::iterator KMemoryBlockManager::FindIterator(VAddr addr) {
18 auto node{memory_block_tree.begin()}; 18 auto node{memory_block_tree.begin()};
19 while (node != end()) { 19 while (node != end()) {
20 const VAddr end_addr{node->GetNumPages() * PageSize + node->GetAddress()}; 20 const VAddr node_end_addr{node->GetNumPages() * PageSize + node->GetAddress()};
21 if (node->GetAddress() <= addr && end_addr - 1 >= addr) { 21 if (node->GetAddress() <= addr && node_end_addr - 1 >= addr) {
22 return node; 22 return node;
23 } 23 }
24 node = std::next(node); 24 node = std::next(node);
@@ -67,7 +67,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
67 KMemoryPermission prev_perm, KMemoryAttribute prev_attribute, 67 KMemoryPermission prev_perm, KMemoryAttribute prev_attribute,
68 KMemoryState state, KMemoryPermission perm, 68 KMemoryState state, KMemoryPermission perm,
69 KMemoryAttribute attribute) { 69 KMemoryAttribute attribute) {
70 const VAddr end_addr{addr + num_pages * PageSize}; 70 const VAddr update_end_addr{addr + num_pages * PageSize};
71 iterator node{memory_block_tree.begin()}; 71 iterator node{memory_block_tree.begin()};
72 72
73 prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped; 73 prev_attribute |= KMemoryAttribute::IpcAndDeviceMapped;
@@ -78,7 +78,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
78 const VAddr cur_addr{block->GetAddress()}; 78 const VAddr cur_addr{block->GetAddress()};
79 const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; 79 const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
80 80
81 if (addr < cur_end_addr && cur_addr < end_addr) { 81 if (addr < cur_end_addr && cur_addr < update_end_addr) {
82 if (!block->HasProperties(prev_state, prev_perm, prev_attribute)) { 82 if (!block->HasProperties(prev_state, prev_perm, prev_attribute)) {
83 node = next_node; 83 node = next_node;
84 continue; 84 continue;
@@ -89,8 +89,8 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
89 memory_block_tree.insert(node, block->Split(addr)); 89 memory_block_tree.insert(node, block->Split(addr));
90 } 90 }
91 91
92 if (end_addr < cur_end_addr) { 92 if (update_end_addr < cur_end_addr) {
93 new_node = memory_block_tree.insert(node, block->Split(end_addr)); 93 new_node = memory_block_tree.insert(node, block->Split(update_end_addr));
94 } 94 }
95 95
96 new_node->Update(state, perm, attribute); 96 new_node->Update(state, perm, attribute);
@@ -98,7 +98,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
98 MergeAdjacent(new_node, next_node); 98 MergeAdjacent(new_node, next_node);
99 } 99 }
100 100
101 if (cur_end_addr - 1 >= end_addr - 1) { 101 if (cur_end_addr - 1 >= update_end_addr - 1) {
102 break; 102 break;
103 } 103 }
104 104
@@ -108,7 +108,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
108 108
109void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state, 109void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState state,
110 KMemoryPermission perm, KMemoryAttribute attribute) { 110 KMemoryPermission perm, KMemoryAttribute attribute) {
111 const VAddr end_addr{addr + num_pages * PageSize}; 111 const VAddr update_end_addr{addr + num_pages * PageSize};
112 iterator node{memory_block_tree.begin()}; 112 iterator node{memory_block_tree.begin()};
113 113
114 while (node != memory_block_tree.end()) { 114 while (node != memory_block_tree.end()) {
@@ -117,15 +117,15 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
117 const VAddr cur_addr{block->GetAddress()}; 117 const VAddr cur_addr{block->GetAddress()};
118 const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; 118 const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
119 119
120 if (addr < cur_end_addr && cur_addr < end_addr) { 120 if (addr < cur_end_addr && cur_addr < update_end_addr) {
121 iterator new_node{node}; 121 iterator new_node{node};
122 122
123 if (addr > cur_addr) { 123 if (addr > cur_addr) {
124 memory_block_tree.insert(node, block->Split(addr)); 124 memory_block_tree.insert(node, block->Split(addr));
125 } 125 }
126 126
127 if (end_addr < cur_end_addr) { 127 if (update_end_addr < cur_end_addr) {
128 new_node = memory_block_tree.insert(node, block->Split(end_addr)); 128 new_node = memory_block_tree.insert(node, block->Split(update_end_addr));
129 } 129 }
130 130
131 new_node->Update(state, perm, attribute); 131 new_node->Update(state, perm, attribute);
@@ -133,7 +133,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
133 MergeAdjacent(new_node, next_node); 133 MergeAdjacent(new_node, next_node);
134 } 134 }
135 135
136 if (cur_end_addr - 1 >= end_addr - 1) { 136 if (cur_end_addr - 1 >= update_end_addr - 1) {
137 break; 137 break;
138 } 138 }
139 139
@@ -143,7 +143,7 @@ void KMemoryBlockManager::Update(VAddr addr, std::size_t num_pages, KMemoryState
143 143
144void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, 144void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func,
145 KMemoryPermission perm) { 145 KMemoryPermission perm) {
146 const VAddr end_addr{addr + num_pages * PageSize}; 146 const VAddr update_end_addr{addr + num_pages * PageSize};
147 iterator node{memory_block_tree.begin()}; 147 iterator node{memory_block_tree.begin()};
148 148
149 while (node != memory_block_tree.end()) { 149 while (node != memory_block_tree.end()) {
@@ -152,15 +152,15 @@ void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc
152 const VAddr cur_addr{block->GetAddress()}; 152 const VAddr cur_addr{block->GetAddress()};
153 const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr}; 153 const VAddr cur_end_addr{block->GetNumPages() * PageSize + cur_addr};
154 154
155 if (addr < cur_end_addr && cur_addr < end_addr) { 155 if (addr < cur_end_addr && cur_addr < update_end_addr) {
156 iterator new_node{node}; 156 iterator new_node{node};
157 157
158 if (addr > cur_addr) { 158 if (addr > cur_addr) {
159 memory_block_tree.insert(node, block->Split(addr)); 159 memory_block_tree.insert(node, block->Split(addr));
160 } 160 }
161 161
162 if (end_addr < cur_end_addr) { 162 if (update_end_addr < cur_end_addr) {
163 new_node = memory_block_tree.insert(node, block->Split(end_addr)); 163 new_node = memory_block_tree.insert(node, block->Split(update_end_addr));
164 } 164 }
165 165
166 lock_func(new_node, perm); 166 lock_func(new_node, perm);
@@ -168,7 +168,7 @@ void KMemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc
168 MergeAdjacent(new_node, next_node); 168 MergeAdjacent(new_node, next_node);
169 } 169 }
170 170
171 if (cur_end_addr - 1 >= end_addr - 1) { 171 if (cur_end_addr - 1 >= update_end_addr - 1) {
172 break; 172 break;
173 } 173 }
174 174
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
21public: 21public:
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_memory_region.h b/src/core/hle/kernel/k_memory_region.h
index a861c04ab..90ab8fd62 100644
--- a/src/core/hle/kernel/k_memory_region.h
+++ b/src/core/hle/kernel/k_memory_region.h
@@ -82,9 +82,9 @@ public:
82 type_id = type; 82 type_id = type;
83 } 83 }
84 84
85 constexpr bool Contains(u64 address) const { 85 constexpr bool Contains(u64 addr) const {
86 ASSERT(this->GetEndAddress() != 0); 86 ASSERT(this->GetEndAddress() != 0);
87 return this->GetAddress() <= address && address <= this->GetLastAddress(); 87 return this->GetAddress() <= addr && addr <= this->GetLastAddress();
88 } 88 }
89 89
90 constexpr bool IsDerivedFrom(u32 type) const { 90 constexpr bool IsDerivedFrom(u32 type) const {
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 {
17public: 17public:
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
61KPageTable::KPageTable(Core::System& system) : system{system} {} 61KPageTable::KPageTable(Core::System& system_) : system{system_} {}
62 62
63ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, 63ResultCode 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
25class KPageTable final : NonCopyable { 25class KPageTable final : NonCopyable {
26public: 26public:
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 734aa2a8c..feb2bb11f 100644
--- a/src/core/hle/kernel/k_port.cpp
+++ b/src/core/hle/kernel/k_port.cpp
@@ -9,8 +9,8 @@
9 9
10namespace Kernel { 10namespace Kernel {
11 11
12KPort::KPort(KernelCore& kernel) 12KPort::KPort(KernelCore& kernel_)
13 : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {} 13 : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {}
14 14
15KPort::~KPort() = default; 15KPort::~KPort() = default;
16 16
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h
index f1b2838d8..960f1f3a3 100644
--- a/src/core/hle/kernel/k_port.h
+++ b/src/core/hle/kernel/k_port.h
@@ -21,7 +21,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjec
21 KERNEL_AUTOOBJECT_TRAITS(KPort, KAutoObject); 21 KERNEL_AUTOOBJECT_TRAITS(KPort, KAutoObject);
22 22
23public: 23public:
24 explicit KPort(KernelCore& kernel); 24 explicit KPort(KernelCore& kernel_);
25 virtual ~KPort(); 25 virtual ~KPort();
26 26
27 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 27 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 174318180..bdcbaeeaa 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -118,11 +118,11 @@ private:
118 std::bitset<num_slot_entries> is_slot_used; 118 std::bitset<num_slot_entries> is_slot_used;
119}; 119};
120 120
121ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string name, 121ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name,
122 ProcessType type) { 122 ProcessType type) {
123 auto& kernel = system.Kernel(); 123 auto& kernel = system.Kernel();
124 124
125 process->name = std::move(name); 125 process->name = std::move(process_name);
126 126
127 process->resource_limit = kernel.GetSystemResourceLimit(); 127 process->resource_limit = kernel.GetSystemResourceLimit();
128 process->status = ProcessStatus::Created; 128 process->status = ProcessStatus::Created;
@@ -373,8 +373,8 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
373void KProcess::PrepareForTermination() { 373void KProcess::PrepareForTermination() {
374 ChangeStatus(ProcessStatus::Exiting); 374 ChangeStatus(ProcessStatus::Exiting);
375 375
376 const auto stop_threads = [this](const std::vector<KThread*>& thread_list) { 376 const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) {
377 for (auto& thread : thread_list) { 377 for (auto& thread : in_thread_list) {
378 if (thread->GetOwnerProcess() != this) 378 if (thread->GetOwnerProcess() != this)
379 continue; 379 continue;
380 380
@@ -491,10 +491,10 @@ bool KProcess::IsSignaled() const {
491 return is_signaled; 491 return is_signaled;
492} 492}
493 493
494KProcess::KProcess(KernelCore& kernel) 494KProcess::KProcess(KernelCore& kernel_)
495 : KAutoObjectWithSlabHeapAndContainer{kernel}, 495 : KAutoObjectWithSlabHeapAndContainer{kernel_},
496 page_table{std::make_unique<KPageTable>(kernel.System())}, handle_table{kernel}, 496 page_table{std::make_unique<KPageTable>(kernel_.System())}, handle_table{kernel_},
497 address_arbiter{kernel.System()}, condition_var{kernel.System()}, state_lock{kernel} {} 497 address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, state_lock{kernel_} {}
498 498
499KProcess::~KProcess() = default; 499KProcess::~KProcess() = default;
500 500
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 62ab26b05..123d71cd3 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -67,7 +67,7 @@ class KProcess final
67 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); 67 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
68 68
69public: 69public:
70 explicit KProcess(KernelCore& kernel); 70 explicit KProcess(KernelCore& kernel_);
71 ~KProcess() override; 71 ~KProcess() override;
72 72
73 enum : u64 { 73 enum : u64 {
@@ -90,7 +90,7 @@ public:
90 90
91 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; 91 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
92 92
93 static ResultCode Initialize(KProcess* process, Core::System& system, std::string name, 93 static ResultCode Initialize(KProcess* process, Core::System& system, std::string process_name,
94 ProcessType type); 94 ProcessType type);
95 95
96 /// Gets a reference to the process' page table. 96 /// Gets a reference to the process' page table.
diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp
index 8fef4bb00..0ea2d0275 100644
--- a/src/core/hle/kernel/k_readable_event.cpp
+++ b/src/core/hle/kernel/k_readable_event.cpp
@@ -12,7 +12,7 @@
12 12
13namespace Kernel { 13namespace Kernel {
14 14
15KReadableEvent::KReadableEvent(KernelCore& kernel) : KSynchronizationObject{kernel} {} 15KReadableEvent::KReadableEvent(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
16 16
17KReadableEvent::~KReadableEvent() = default; 17KReadableEvent::~KReadableEvent() = default;
18 18
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
index 1783ef0b8..33cd1dd3e 100644
--- a/src/core/hle/kernel/k_readable_event.h
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -18,7 +18,7 @@ class KReadableEvent : public KSynchronizationObject {
18 KERNEL_AUTOOBJECT_TRAITS(KReadableEvent, KSynchronizationObject); 18 KERNEL_AUTOOBJECT_TRAITS(KReadableEvent, KSynchronizationObject);
19 19
20public: 20public:
21 explicit KReadableEvent(KernelCore& kernel); 21 explicit KReadableEvent(KernelCore& kernel_);
22 ~KReadableEvent() override; 22 ~KReadableEvent() override;
23 23
24 void Initialize(KEvent* parent_, std::string&& name_) { 24 void Initialize(KEvent* parent_, std::string&& name_) {
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index ad5095bfd..bf20bf7d0 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -10,8 +10,8 @@
10namespace Kernel { 10namespace Kernel {
11constexpr s64 DefaultTimeout = 10000000000; // 10 seconds 11constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
12 12
13KResourceLimit::KResourceLimit(KernelCore& kernel) 13KResourceLimit::KResourceLimit(KernelCore& kernel_)
14 : KAutoObjectWithSlabHeapAndContainer{kernel}, lock{kernel}, cond_var{kernel} {} 14 : KAutoObjectWithSlabHeapAndContainer{kernel_}, lock{kernel_}, cond_var{kernel_} {}
15KResourceLimit::~KResourceLimit() = default; 15KResourceLimit::~KResourceLimit() = default;
16 16
17void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) { 17void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing_) {
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 66ebf32df..0debbbb51 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -36,7 +36,7 @@ class KResourceLimit final
36 KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject); 36 KERNEL_AUTOOBJECT_TRAITS(KResourceLimit, KAutoObject);
37 37
38public: 38public:
39 explicit KResourceLimit(KernelCore& kernel); 39 explicit KResourceLimit(KernelCore& kernel_);
40 virtual ~KResourceLimit(); 40 virtual ~KResourceLimit();
41 41
42 void Initialize(const Core::Timing::CoreTiming* core_timing_); 42 void Initialize(const Core::Timing::CoreTiming* core_timing_);
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 0115fe6d1..2f82fbcd6 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -259,7 +259,7 @@ void KScheduler::OnThreadAffinityMaskChanged(KernelCore& kernel, KThread* thread
259 } 259 }
260} 260}
261 261
262void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) { 262void KScheduler::RotateScheduledQueue(s32 cpu_core_id, s32 priority) {
263 ASSERT(system.GlobalSchedulerContext().IsLocked()); 263 ASSERT(system.GlobalSchedulerContext().IsLocked());
264 264
265 // Get a reference to the priority queue. 265 // Get a reference to the priority queue.
@@ -267,7 +267,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) {
267 auto& priority_queue = GetPriorityQueue(kernel); 267 auto& priority_queue = GetPriorityQueue(kernel);
268 268
269 // Rotate the front of the queue to the end. 269 // Rotate the front of the queue to the end.
270 KThread* top_thread = priority_queue.GetScheduledFront(core_id, priority); 270 KThread* top_thread = priority_queue.GetScheduledFront(cpu_core_id, priority);
271 KThread* next_thread = nullptr; 271 KThread* next_thread = nullptr;
272 if (top_thread != nullptr) { 272 if (top_thread != nullptr) {
273 next_thread = priority_queue.MoveToScheduledBack(top_thread); 273 next_thread = priority_queue.MoveToScheduledBack(top_thread);
@@ -279,7 +279,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) {
279 279
280 // While we have a suggested thread, try to migrate it! 280 // While we have a suggested thread, try to migrate it!
281 { 281 {
282 KThread* suggested = priority_queue.GetSuggestedFront(core_id, priority); 282 KThread* suggested = priority_queue.GetSuggestedFront(cpu_core_id, priority);
283 while (suggested != nullptr) { 283 while (suggested != nullptr) {
284 // Check if the suggested thread is the top thread on its core. 284 // Check if the suggested thread is the top thread on its core.
285 const s32 suggested_core = suggested->GetActiveCore(); 285 const s32 suggested_core = suggested->GetActiveCore();
@@ -300,7 +300,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) {
300 // to the front of the queue. 300 // to the front of the queue.
301 if (top_on_suggested_core == nullptr || 301 if (top_on_suggested_core == nullptr ||
302 top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) { 302 top_on_suggested_core->GetPriority() >= HighestCoreMigrationAllowedPriority) {
303 suggested->SetActiveCore(core_id); 303 suggested->SetActiveCore(cpu_core_id);
304 priority_queue.ChangeCore(suggested_core, suggested, true); 304 priority_queue.ChangeCore(suggested_core, suggested, true);
305 IncrementScheduledCount(suggested); 305 IncrementScheduledCount(suggested);
306 break; 306 break;
@@ -308,22 +308,22 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) {
308 } 308 }
309 309
310 // Get the next suggestion. 310 // Get the next suggestion.
311 suggested = priority_queue.GetSamePriorityNext(core_id, suggested); 311 suggested = priority_queue.GetSamePriorityNext(cpu_core_id, suggested);
312 } 312 }
313 } 313 }
314 314
315 // Now that we might have migrated a thread with the same priority, check if we can do better. 315 // Now that we might have migrated a thread with the same priority, check if we can do better.
316 316
317 { 317 {
318 KThread* best_thread = priority_queue.GetScheduledFront(core_id); 318 KThread* best_thread = priority_queue.GetScheduledFront(cpu_core_id);
319 if (best_thread == GetCurrentThread()) { 319 if (best_thread == GetCurrentThread()) {
320 best_thread = priority_queue.GetScheduledNext(core_id, best_thread); 320 best_thread = priority_queue.GetScheduledNext(cpu_core_id, best_thread);
321 } 321 }
322 322
323 // If the best thread we can choose has a priority the same or worse than ours, try to 323 // If the best thread we can choose has a priority the same or worse than ours, try to
324 // migrate a higher priority thread. 324 // migrate a higher priority thread.
325 if (best_thread != nullptr && best_thread->GetPriority() >= priority) { 325 if (best_thread != nullptr && best_thread->GetPriority() >= priority) {
326 KThread* suggested = priority_queue.GetSuggestedFront(core_id); 326 KThread* suggested = priority_queue.GetSuggestedFront(cpu_core_id);
327 while (suggested != nullptr) { 327 while (suggested != nullptr) {
328 // If the suggestion's priority is the same as ours, don't bother. 328 // If the suggestion's priority is the same as ours, don't bother.
329 if (suggested->GetPriority() >= best_thread->GetPriority()) { 329 if (suggested->GetPriority() >= best_thread->GetPriority()) {
@@ -342,7 +342,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) {
342 if (top_on_suggested_core == nullptr || 342 if (top_on_suggested_core == nullptr ||
343 top_on_suggested_core->GetPriority() >= 343 top_on_suggested_core->GetPriority() >=
344 HighestCoreMigrationAllowedPriority) { 344 HighestCoreMigrationAllowedPriority) {
345 suggested->SetActiveCore(core_id); 345 suggested->SetActiveCore(cpu_core_id);
346 priority_queue.ChangeCore(suggested_core, suggested, true); 346 priority_queue.ChangeCore(suggested_core, suggested, true);
347 IncrementScheduledCount(suggested); 347 IncrementScheduledCount(suggested);
348 break; 348 break;
@@ -350,7 +350,7 @@ void KScheduler::RotateScheduledQueue(s32 core_id, s32 priority) {
350 } 350 }
351 351
352 // Get the next suggestion. 352 // Get the next suggestion.
353 suggested = priority_queue.GetSuggestedNext(core_id, suggested); 353 suggested = priority_queue.GetSuggestedNext(cpu_core_id, suggested);
354 } 354 }
355 } 355 }
356 } 356 }
@@ -607,7 +607,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) {
607 } 607 }
608} 608}
609 609
610KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core_id(core_id) { 610KScheduler::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 b789a64a4..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
31class KScheduler final { 31class KScheduler final {
32public: 32public:
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)
@@ -141,7 +141,7 @@ private:
141 141
142 [[nodiscard]] static KSchedulerPriorityQueue& GetPriorityQueue(KernelCore& kernel); 142 [[nodiscard]] static KSchedulerPriorityQueue& GetPriorityQueue(KernelCore& kernel);
143 143
144 void RotateScheduledQueue(s32 core_id, s32 priority); 144 void RotateScheduledQueue(s32 cpu_core_id, s32 priority);
145 145
146 void Schedule() { 146 void Schedule() {
147 ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1); 147 ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1);
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
18class [[nodiscard]] KScopedSchedulerLockAndSleep { 18class [[nodiscard]] KScopedSchedulerLockAndSleep {
19public: 19public:
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.cpp b/src/core/hle/kernel/k_server_port.cpp
index 5e44c48e2..8cbde177a 100644
--- a/src/core/hle/kernel/k_server_port.cpp
+++ b/src/core/hle/kernel/k_server_port.cpp
@@ -14,7 +14,7 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17KServerPort::KServerPort(KernelCore& kernel) : KSynchronizationObject{kernel} {} 17KServerPort::KServerPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
18KServerPort::~KServerPort() = default; 18KServerPort::~KServerPort() = default;
19 19
20void KServerPort::Initialize(KPort* parent_, std::string&& name_) { 20void KServerPort::Initialize(KPort* parent_, std::string&& name_) {
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h
index 558c8ed4d..e76792253 100644
--- a/src/core/hle/kernel/k_server_port.h
+++ b/src/core/hle/kernel/k_server_port.h
@@ -29,7 +29,7 @@ private:
29 using SessionList = boost::intrusive::list<KServerSession>; 29 using SessionList = boost::intrusive::list<KServerSession>;
30 30
31public: 31public:
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>; 35 using HLEHandler = std::shared_ptr<SessionRequestHandler>;
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index c8acaa453..8850d9af5 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -23,7 +23,7 @@
23 23
24namespace Kernel { 24namespace Kernel {
25 25
26KServerSession::KServerSession(KernelCore& kernel) : KSynchronizationObject{kernel} {} 26KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
27 27
28KServerSession::~KServerSession() { 28KServerSession::~KServerSession() {
29 kernel.ReleaseServiceThread(service_thread); 29 kernel.ReleaseServiceThread(service_thread);
@@ -95,7 +95,7 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co
95 UNREACHABLE(); 95 UNREACHABLE();
96 return RESULT_SUCCESS; // Ignore error if asserts are off 96 return RESULT_SUCCESS; // Ignore error if asserts are off
97 } 97 }
98 return domain_request_handlers[object_id - 1]->HandleSyncRequest(context); 98 return domain_request_handlers[object_id - 1]->HandleSyncRequest(*this, context);
99 99
100 case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { 100 case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
101 LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); 101 LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
@@ -135,7 +135,7 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) {
135 // If there is no domain header, the regular session handler is used 135 // If there is no domain header, the regular session handler is used
136 } else if (hle_handler != nullptr) { 136 } else if (hle_handler != nullptr) {
137 // If this ServerSession has an associated HLE handler, forward the request to it. 137 // If this ServerSession has an associated HLE handler, forward the request to it.
138 result = hle_handler->HandleSyncRequest(context); 138 result = hle_handler->HandleSyncRequest(*this, context);
139 } 139 }
140 140
141 if (convert_to_domain) { 141 if (convert_to_domain) {
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index 77095bb85..597d76d38 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -40,7 +40,7 @@ class KServerSession final : public KSynchronizationObject,
40 friend class ServiceThread; 40 friend class ServiceThread;
41 41
42public: 42public:
43 explicit KServerSession(KernelCore& kernel); 43 explicit KServerSession(KernelCore& kernel_);
44 virtual ~KServerSession() override; 44 virtual ~KServerSession() override;
45 45
46 virtual void Destroy() override; 46 virtual void Destroy() override;
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp
index 7b0bc177d..b7ce27a0b 100644
--- a/src/core/hle/kernel/k_session.cpp
+++ b/src/core/hle/kernel/k_session.cpp
@@ -11,8 +11,8 @@
11 11
12namespace Kernel { 12namespace Kernel {
13 13
14KSession::KSession(KernelCore& kernel) 14KSession::KSession(KernelCore& kernel_)
15 : KAutoObjectWithSlabHeapAndContainer{kernel}, server{kernel}, client{kernel} {} 15 : KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {}
16KSession::~KSession() = default; 16KSession::~KSession() = default;
17 17
18void KSession::Initialize(KClientPort* port_, const std::string& name_) { 18void KSession::Initialize(KClientPort* port_, const std::string& name_) {
@@ -78,7 +78,7 @@ void KSession::OnClientClosed() {
78void KSession::PostDestroy(uintptr_t arg) { 78void KSession::PostDestroy(uintptr_t arg) {
79 // Release the session count resource the owner process holds. 79 // Release the session count resource the owner process holds.
80 KProcess* owner = reinterpret_cast<KProcess*>(arg); 80 KProcess* owner = reinterpret_cast<KProcess*>(arg);
81 owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); 81 // owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1);
82 owner->Close(); 82 owner->Close();
83} 83}
84 84
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
index 4321b7885..16901e19c 100644
--- a/src/core/hle/kernel/k_session.h
+++ b/src/core/hle/kernel/k_session.h
@@ -17,7 +17,7 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAut
17 KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject); 17 KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject);
18 18
19public: 19public:
20 explicit KSession(KernelCore& kernel); 20 explicit KSession(KernelCore& kernel_);
21 virtual ~KSession() override; 21 virtual ~KSession() override;
22 22
23 void Initialize(KClientPort* port_, const std::string& name_); 23 void Initialize(KClientPort* port_, const std::string& name_);
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp
index 1da57a4c3..7770b1868 100644
--- a/src/core/hle/kernel/k_shared_memory.cpp
+++ b/src/core/hle/kernel/k_shared_memory.cpp
@@ -12,14 +12,14 @@
12 12
13namespace Kernel { 13namespace Kernel {
14 14
15KSharedMemory::KSharedMemory(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} 15KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
16 16
17KSharedMemory::~KSharedMemory() { 17KSharedMemory::~KSharedMemory() {
18 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); 18 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size);
19} 19}
20 20
21ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_, 21ResultCode KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_,
22 KProcess* owner_process_, KPageLinkedList&& page_list_, 22 KPageLinkedList&& page_list_,
23 Svc::MemoryPermission owner_permission_, 23 Svc::MemoryPermission owner_permission_,
24 Svc::MemoryPermission user_permission_, 24 Svc::MemoryPermission user_permission_,
25 PAddr physical_address_, std::size_t size_, 25 PAddr physical_address_, std::size_t size_,
@@ -32,7 +32,7 @@ ResultCode KSharedMemory::Initialize(KernelCore& kernel_, Core::DeviceMemory& de
32 user_permission = user_permission_; 32 user_permission = user_permission_;
33 physical_address = physical_address_; 33 physical_address = physical_address_;
34 size = size_; 34 size = size_;
35 name = name_; 35 name = std::move(name_);
36 36
37 // Get the resource limit. 37 // Get the resource limit.
38 KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); 38 KResourceLimit* reslimit = kernel.GetSystemResourceLimit();
@@ -67,9 +67,9 @@ void KSharedMemory::Finalize() {
67 KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize(); 67 KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize();
68} 68}
69 69
70ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t size, 70ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size,
71 Svc::MemoryPermission permissions) { 71 Svc::MemoryPermission permissions) {
72 const u64 page_count{(size + PageSize - 1) / PageSize}; 72 const u64 page_count{(map_size + PageSize - 1) / PageSize};
73 73
74 if (page_list.GetNumPages() != page_count) { 74 if (page_list.GetNumPages() != page_count) {
75 UNIMPLEMENTED_MSG("Page count does not match"); 75 UNIMPLEMENTED_MSG("Page count does not match");
@@ -86,8 +86,8 @@ ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size
86 ConvertToKMemoryPermission(permissions)); 86 ConvertToKMemoryPermission(permissions));
87} 87}
88 88
89ResultCode KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t size) { 89ResultCode KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) {
90 const u64 page_count{(size + PageSize - 1) / PageSize}; 90 const u64 page_count{(unmap_size + PageSize - 1) / PageSize};
91 91
92 if (page_list.GetNumPages() != page_count) { 92 if (page_list.GetNumPages() != page_count) {
93 UNIMPLEMENTED_MSG("Page count does not match"); 93 UNIMPLEMENTED_MSG("Page count does not match");
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index 28939c93c..553a56327 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -24,12 +24,11 @@ class KSharedMemory final
24 KERNEL_AUTOOBJECT_TRAITS(KSharedMemory, KAutoObject); 24 KERNEL_AUTOOBJECT_TRAITS(KSharedMemory, KAutoObject);
25 25
26public: 26public:
27 explicit KSharedMemory(KernelCore& kernel); 27 explicit KSharedMemory(KernelCore& kernel_);
28 ~KSharedMemory() override; 28 ~KSharedMemory() override;
29 29
30 ResultCode Initialize(KernelCore& kernel_, Core::DeviceMemory& device_memory_, 30 ResultCode Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_,
31 KProcess* owner_process_, KPageLinkedList&& page_list_, 31 KPageLinkedList&& page_list_, Svc::MemoryPermission owner_permission_,
32 Svc::MemoryPermission owner_permission_,
33 Svc::MemoryPermission user_permission_, PAddr physical_address_, 32 Svc::MemoryPermission user_permission_, PAddr physical_address_,
34 std::size_t size_, std::string name_); 33 std::size_t size_, std::string name_);
35 34
@@ -37,19 +36,19 @@ public:
37 * Maps a shared memory block to an address in the target process' address space 36 * Maps a shared memory block to an address in the target process' address space
38 * @param target_process Process on which to map the memory block 37 * @param target_process Process on which to map the memory block
39 * @param address Address in system memory to map shared memory block to 38 * @param address Address in system memory to map shared memory block to
40 * @param size Size of the shared memory block to map 39 * @param map_size Size of the shared memory block to map
41 * @param permissions Memory block map permissions (specified by SVC field) 40 * @param permissions Memory block map permissions (specified by SVC field)
42 */ 41 */
43 ResultCode Map(KProcess& target_process, VAddr address, std::size_t size, 42 ResultCode Map(KProcess& target_process, VAddr address, std::size_t map_size,
44 Svc::MemoryPermission permissions); 43 Svc::MemoryPermission permissions);
45 44
46 /** 45 /**
47 * Unmaps a shared memory block from an address in the target process' address space 46 * Unmaps a shared memory block from an address in the target process' address space
48 * @param target_process Process on which to unmap the memory block 47 * @param target_process Process on which to unmap the memory block
49 * @param address Address in system memory to unmap shared memory block 48 * @param address Address in system memory to unmap shared memory block
50 * @param size Size of the shared memory block to unmap 49 * @param unmap_size Size of the shared memory block to unmap
51 */ 50 */
52 ResultCode Unmap(KProcess& target_process, VAddr address, std::size_t size); 51 ResultCode Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size);
53 52
54 /** 53 /**
55 * Gets a pointer to the shared memory block 54 * Gets a pointer to the shared memory block
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp
index 460b8a714..45380dea0 100644
--- a/src/core/hle/kernel/k_synchronization_object.cpp
+++ b/src/core/hle/kernel/k_synchronization_object.cpp
@@ -18,18 +18,18 @@ void KSynchronizationObject::Finalize() {
18 KAutoObject::Finalize(); 18 KAutoObject::Finalize();
19} 19}
20 20
21ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index, 21ResultCode KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
22 KSynchronizationObject** objects, const s32 num_objects, 22 KSynchronizationObject** objects, const s32 num_objects,
23 s64 timeout) { 23 s64 timeout) {
24 // Allocate space on stack for thread nodes. 24 // Allocate space on stack for thread nodes.
25 std::vector<ThreadListNode> thread_nodes(num_objects); 25 std::vector<ThreadListNode> thread_nodes(num_objects);
26 26
27 // Prepare for wait. 27 // Prepare for wait.
28 KThread* thread = kernel.CurrentScheduler()->GetCurrentThread(); 28 KThread* thread = kernel_ctx.CurrentScheduler()->GetCurrentThread();
29 29
30 { 30 {
31 // Setup the scheduling lock and sleep. 31 // Setup the scheduling lock and sleep.
32 KScopedSchedulerLockAndSleep slp{kernel, thread, timeout}; 32 KScopedSchedulerLockAndSleep slp{kernel_ctx, thread, timeout};
33 33
34 // Check if any of the objects are already signaled. 34 // Check if any of the objects are already signaled.
35 for (auto i = 0; i < num_objects; ++i) { 35 for (auto i = 0; i < num_objects; ++i) {
@@ -94,13 +94,13 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
94 thread->SetWaitObjectsForDebugging({}); 94 thread->SetWaitObjectsForDebugging({});
95 95
96 // Cancel the timer as needed. 96 // Cancel the timer as needed.
97 kernel.TimeManager().UnscheduleTimeEvent(thread); 97 kernel_ctx.TimeManager().UnscheduleTimeEvent(thread);
98 98
99 // Get the wait result. 99 // Get the wait result.
100 ResultCode wait_result{RESULT_SUCCESS}; 100 ResultCode wait_result{RESULT_SUCCESS};
101 s32 sync_index = -1; 101 s32 sync_index = -1;
102 { 102 {
103 KScopedSchedulerLock lock(kernel); 103 KScopedSchedulerLock lock(kernel_ctx);
104 KSynchronizationObject* synced_obj; 104 KSynchronizationObject* synced_obj;
105 wait_result = thread->GetWaitResult(std::addressof(synced_obj)); 105 wait_result = thread->GetWaitResult(std::addressof(synced_obj));
106 106
@@ -135,7 +135,8 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
135 return wait_result; 135 return wait_result;
136} 136}
137 137
138KSynchronizationObject::KSynchronizationObject(KernelCore& kernel) : KAutoObjectWithList{kernel} {} 138KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_)
139 : KAutoObjectWithList{kernel_} {}
139 140
140KSynchronizationObject::~KSynchronizationObject() = default; 141KSynchronizationObject::~KSynchronizationObject() = default;
141 142
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index ef6dfeeca..e3f08f256 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -60,8 +60,8 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
60 60
61namespace Kernel { 61namespace Kernel {
62 62
63KThread::KThread(KernelCore& kernel) 63KThread::KThread(KernelCore& kernel_)
64 : KAutoObjectWithSlabHeapAndContainer{kernel}, activity_pause_lock{kernel} {} 64 : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {}
65KThread::~KThread() = default; 65KThread::~KThread() = default;
66 66
67ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, 67ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio,
@@ -479,7 +479,7 @@ ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_m
479 return RESULT_SUCCESS; 479 return RESULT_SUCCESS;
480} 480}
481 481
482ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) { 482ResultCode KThread::SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask) {
483 ASSERT(parent != nullptr); 483 ASSERT(parent != nullptr);
484 ASSERT(v_affinity_mask != 0); 484 ASSERT(v_affinity_mask != 0);
485 KScopedLightLock lk{activity_pause_lock}; 485 KScopedLightLock lk{activity_pause_lock};
@@ -491,18 +491,18 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) {
491 ASSERT(num_core_migration_disables >= 0); 491 ASSERT(num_core_migration_disables >= 0);
492 492
493 // If the core id is no-update magic, preserve the ideal core id. 493 // If the core id is no-update magic, preserve the ideal core id.
494 if (core_id == Svc::IdealCoreNoUpdate) { 494 if (cpu_core_id == Svc::IdealCoreNoUpdate) {
495 core_id = virtual_ideal_core_id; 495 cpu_core_id = virtual_ideal_core_id;
496 R_UNLESS(((1ULL << core_id) & v_affinity_mask) != 0, ResultInvalidCombination); 496 R_UNLESS(((1ULL << cpu_core_id) & v_affinity_mask) != 0, ResultInvalidCombination);
497 } 497 }
498 498
499 // Set the virtual core/affinity mask. 499 // Set the virtual core/affinity mask.
500 virtual_ideal_core_id = core_id; 500 virtual_ideal_core_id = cpu_core_id;
501 virtual_affinity_mask = v_affinity_mask; 501 virtual_affinity_mask = v_affinity_mask;
502 502
503 // Translate the virtual core to a physical core. 503 // Translate the virtual core to a physical core.
504 if (core_id >= 0) { 504 if (cpu_core_id >= 0) {
505 core_id = Core::Hardware::VirtualToPhysicalCoreMap[core_id]; 505 cpu_core_id = Core::Hardware::VirtualToPhysicalCoreMap[cpu_core_id];
506 } 506 }
507 507
508 // Translate the virtual affinity mask to a physical one. 508 // Translate the virtual affinity mask to a physical one.
@@ -517,7 +517,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) {
517 const KAffinityMask old_mask = physical_affinity_mask; 517 const KAffinityMask old_mask = physical_affinity_mask;
518 518
519 // Set our new ideals. 519 // Set our new ideals.
520 physical_ideal_core_id = core_id; 520 physical_ideal_core_id = cpu_core_id;
521 physical_affinity_mask.SetAffinityMask(p_affinity_mask); 521 physical_affinity_mask.SetAffinityMask(p_affinity_mask);
522 522
523 if (physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) { 523 if (physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
@@ -535,7 +535,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) {
535 } 535 }
536 } else { 536 } else {
537 // Otherwise, we edit the original affinity for restoration later. 537 // Otherwise, we edit the original affinity for restoration later.
538 original_physical_ideal_core_id = core_id; 538 original_physical_ideal_core_id = cpu_core_id;
539 original_physical_affinity_mask.SetAffinityMask(p_affinity_mask); 539 original_physical_affinity_mask.SetAffinityMask(p_affinity_mask);
540 } 540 }
541 } 541 }
@@ -851,8 +851,8 @@ void KThread::RemoveWaiterImpl(KThread* thread) {
851 thread->SetLockOwner(nullptr); 851 thread->SetLockOwner(nullptr);
852} 852}
853 853
854void KThread::RestorePriority(KernelCore& kernel, KThread* thread) { 854void KThread::RestorePriority(KernelCore& kernel_ctx, KThread* thread) {
855 ASSERT(kernel.GlobalSchedulerContext().IsLocked()); 855 ASSERT(kernel_ctx.GlobalSchedulerContext().IsLocked());
856 856
857 while (true) { 857 while (true) {
858 // We want to inherit priority where possible. 858 // We want to inherit priority where possible.
@@ -868,7 +868,7 @@ void KThread::RestorePriority(KernelCore& kernel, KThread* thread) {
868 868
869 // Ensure we don't violate condition variable red black tree invariants. 869 // Ensure we don't violate condition variable red black tree invariants.
870 if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { 870 if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) {
871 BeforeUpdatePriority(kernel, cv_tree, thread); 871 BeforeUpdatePriority(kernel_ctx, cv_tree, thread);
872 } 872 }
873 873
874 // Change the priority. 874 // Change the priority.
@@ -877,11 +877,11 @@ void KThread::RestorePriority(KernelCore& kernel, KThread* thread) {
877 877
878 // Restore the condition variable, if relevant. 878 // Restore the condition variable, if relevant.
879 if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) { 879 if (auto* cv_tree = thread->GetConditionVariableTree(); cv_tree != nullptr) {
880 AfterUpdatePriority(kernel, cv_tree, thread); 880 AfterUpdatePriority(kernel_ctx, cv_tree, thread);
881 } 881 }
882 882
883 // Update the scheduler. 883 // Update the scheduler.
884 KScheduler::OnThreadPriorityChanged(kernel, thread, old_priority); 884 KScheduler::OnThreadPriorityChanged(kernel_ctx, thread, old_priority);
885 885
886 // Keep the lock owner up to date. 886 // Keep the lock owner up to date.
887 KThread* lock_owner = thread->GetLockOwner(); 887 KThread* lock_owner = thread->GetLockOwner();
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 4145ef56c..4abfc2b49 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -111,7 +111,7 @@ public:
111 static constexpr s32 DefaultThreadPriority = 44; 111 static constexpr s32 DefaultThreadPriority = 44;
112 static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1; 112 static constexpr s32 IdleThreadPriority = Svc::LowestThreadPriority + 1;
113 113
114 explicit KThread(KernelCore& kernel); 114 explicit KThread(KernelCore& kernel_);
115 ~KThread() override; 115 ~KThread() override;
116 116
117public: 117public:
@@ -318,7 +318,7 @@ public:
318 318
319 [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); 319 [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask);
320 320
321 [[nodiscard]] ResultCode SetCoreMask(s32 core_id, u64 v_affinity_mask); 321 [[nodiscard]] ResultCode SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask);
322 322
323 [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity); 323 [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity);
324 324
@@ -649,7 +649,7 @@ private:
649 std::function<void(void*)>&& init_func, 649 std::function<void(void*)>&& init_func,
650 void* init_func_parameter); 650 void* init_func_parameter);
651 651
652 static void RestorePriority(KernelCore& kernel, KThread* thread); 652 static void RestorePriority(KernelCore& kernel_ctx, KThread* thread);
653 653
654 // For core KThread implementation 654 // For core KThread implementation
655 ThreadContext32 thread_context_32{}; 655 ThreadContext32 thread_context_32{};
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
11class KThreadQueue { 11class KThreadQueue {
12public: 12public:
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.cpp b/src/core/hle/kernel/k_transfer_memory.cpp
index 201617d32..5bc33706d 100644
--- a/src/core/hle/kernel/k_transfer_memory.cpp
+++ b/src/core/hle/kernel/k_transfer_memory.cpp
@@ -9,8 +9,8 @@
9 9
10namespace Kernel { 10namespace Kernel {
11 11
12KTransferMemory::KTransferMemory(KernelCore& kernel) 12KTransferMemory::KTransferMemory(KernelCore& kernel_)
13 : KAutoObjectWithSlabHeapAndContainer{kernel} {} 13 : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
14 14
15KTransferMemory::~KTransferMemory() = default; 15KTransferMemory::~KTransferMemory() = default;
16 16
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h
index f56398b9c..c2d0f1eaf 100644
--- a/src/core/hle/kernel/k_transfer_memory.h
+++ b/src/core/hle/kernel/k_transfer_memory.h
@@ -26,7 +26,7 @@ class KTransferMemory final
26 KERNEL_AUTOOBJECT_TRAITS(KTransferMemory, KAutoObject); 26 KERNEL_AUTOOBJECT_TRAITS(KTransferMemory, KAutoObject);
27 27
28public: 28public:
29 explicit KTransferMemory(KernelCore& kernel); 29 explicit KTransferMemory(KernelCore& kernel_);
30 virtual ~KTransferMemory() override; 30 virtual ~KTransferMemory() override;
31 31
32 ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); 32 ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_);
@@ -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
58private: 58private:
diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp
index a430e0661..b7b83c151 100644
--- a/src/core/hle/kernel/k_writable_event.cpp
+++ b/src/core/hle/kernel/k_writable_event.cpp
@@ -8,7 +8,8 @@
8 8
9namespace Kernel { 9namespace Kernel {
10 10
11KWritableEvent::KWritableEvent(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel} {} 11KWritableEvent::KWritableEvent(KernelCore& kernel_)
12 : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
12 13
13KWritableEvent::~KWritableEvent() = default; 14KWritableEvent::~KWritableEvent() = default;
14 15
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
index 154d2382c..607b0eadb 100644
--- a/src/core/hle/kernel/k_writable_event.h
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -18,7 +18,7 @@ class KWritableEvent final
18 KERNEL_AUTOOBJECT_TRAITS(KWritableEvent, KAutoObject); 18 KERNEL_AUTOOBJECT_TRAITS(KWritableEvent, KAutoObject);
19 19
20public: 20public:
21 explicit KWritableEvent(KernelCore& kernel); 21 explicit KWritableEvent(KernelCore& kernel_);
22 ~KWritableEvent() override; 22 ~KWritableEvent() override;
23 23
24 virtual void Destroy() override; 24 virtual void Destroy() override;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 32bbf2d9b..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
49MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70)); 50MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
@@ -51,11 +52,11 @@ MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
51namespace Kernel { 52namespace Kernel {
52 53
53struct KernelCore::Impl { 54struct KernelCore::Impl {
54 explicit Impl(Core::System& system, KernelCore& kernel) 55 explicit Impl(Core::System& system_, KernelCore& kernel_)
55 : time_manager{system}, object_list_container{kernel}, system{system} {} 56 : time_manager{system_}, object_list_container{kernel_}, system{system_} {}
56 57
57 void SetMulticore(bool is_multicore) { 58 void SetMulticore(bool is_multi) {
58 this->is_multicore = is_multicore; 59 is_multicore = is_multi;
59 } 60 }
60 61
61 void Initialize(KernelCore& kernel) { 62 void Initialize(KernelCore& kernel) {
@@ -599,19 +600,19 @@ struct KernelCore::Impl {
599 irs_shared_mem = KSharedMemory::Create(system.Kernel()); 600 irs_shared_mem = KSharedMemory::Create(system.Kernel());
600 time_shared_mem = KSharedMemory::Create(system.Kernel()); 601 time_shared_mem = KSharedMemory::Create(system.Kernel());
601 602
602 hid_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 603 hid_shared_mem->Initialize(system.DeviceMemory(), nullptr,
603 {hid_phys_addr, hid_size / PageSize}, 604 {hid_phys_addr, hid_size / PageSize},
604 Svc::MemoryPermission::None, Svc::MemoryPermission::Read, 605 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
605 hid_phys_addr, hid_size, "HID:SharedMemory"); 606 hid_phys_addr, hid_size, "HID:SharedMemory");
606 font_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 607 font_shared_mem->Initialize(system.DeviceMemory(), nullptr,
607 {font_phys_addr, font_size / PageSize}, 608 {font_phys_addr, font_size / PageSize},
608 Svc::MemoryPermission::None, Svc::MemoryPermission::Read, 609 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
609 font_phys_addr, font_size, "Font:SharedMemory"); 610 font_phys_addr, font_size, "Font:SharedMemory");
610 irs_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 611 irs_shared_mem->Initialize(system.DeviceMemory(), nullptr,
611 {irs_phys_addr, irs_size / PageSize}, 612 {irs_phys_addr, irs_size / PageSize},
612 Svc::MemoryPermission::None, Svc::MemoryPermission::Read, 613 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
613 irs_phys_addr, irs_size, "IRS:SharedMemory"); 614 irs_phys_addr, irs_size, "IRS:SharedMemory");
614 time_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr, 615 time_shared_mem->Initialize(system.DeviceMemory(), nullptr,
615 {time_phys_addr, time_size / PageSize}, 616 {time_phys_addr, time_size / PageSize},
616 Svc::MemoryPermission::None, Svc::MemoryPermission::Read, 617 Svc::MemoryPermission::None, Svc::MemoryPermission::Read,
617 time_phys_addr, time_size, "Time:SharedMemory"); 618 time_phys_addr, time_size, "Time:SharedMemory");
@@ -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
847void KernelCore::AddNamedPort(std::string name, KClientPort* port) { 849void 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
852KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) { 853KClientPort* 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();
856KernelCore::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
861bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { 862bool 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;
27struct EventType; 27struct EventType;
28} // namespace Core::Timing 28} // namespace Core::Timing
29 29
30namespace Service::SM {
31class ServiceManager;
32}
33
30namespace Kernel { 34namespace Kernel {
31 35
32class KClientPort; 36class KClientPort;
@@ -51,6 +55,9 @@ class ServiceThread;
51class Synchronization; 55class Synchronization;
52class TimeManager; 56class TimeManager;
53 57
58using ServiceInterfaceFactory =
59 std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>;
60
54namespace Init { 61namespace Init {
55struct KSlabResourceCounts; 62struct 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
14namespace Kernel { 14namespace Kernel {
15 15
16PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, 16PhysicalCore::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
21PhysicalCore::~PhysicalCore() = default; 21PhysicalCore::~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
29class PhysicalCore { 29class PhysicalCore {
30public: 30public:
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/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h
index 0c5995db0..d0f7f084b 100644
--- a/src/core/hle/kernel/slab_helpers.h
+++ b/src/core/hle/kernel/slab_helpers.h
@@ -67,11 +67,11 @@ class KAutoObjectWithSlabHeapAndContainer : public Base {
67 67
68private: 68private:
69 static Derived* Allocate(KernelCore& kernel) { 69 static Derived* Allocate(KernelCore& kernel) {
70 return kernel.SlabHeap<Derived>().AllocateWithKernel(kernel); 70 return new Derived(kernel);
71 } 71 }
72 72
73 static void Free(KernelCore& kernel, Derived* obj) { 73 static void Free(KernelCore& kernel, Derived* obj) {
74 kernel.SlabHeap<Derived>().Free(obj); 74 delete obj;
75 } 75 }
76 76
77public: 77public:
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
834class StorageDataImpl final : public IStorageImpl { 834class StorageDataImpl final : public IStorageImpl {
835public: 835public:
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
16constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7; 16constexpr auto DEFAULT_PERFORMANCE_CONFIGURATION = PerformanceConfiguration::Config7;
17 17
18Controller::Controller(Core::Timing::CoreTiming& core_timing) 18Controller::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
24Controller::~Controller() = default; 24Controller::~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.
51class Controller { 51class Controller {
52public: 52public:
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
170class IAudioDevice final : public ServiceFramework<IAudioDevice> { 170class IAudioDevice final : public ServiceFramework<IAudioDevice> {
171public: 171public:
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
206private: 193private:
@@ -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 315AudRenU::AudRenU(Core::System& system_)
316 : ServiceFramework{system_, "audren:u"}, buffer_event{system.Kernel()} {
330 317
331AudRenU::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
345AudRenU::~AudRenU() = default; 334AudRenU::~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
668void AudRenU::OpenAudioRendererForManualExecution(Kernel::HLERequestContext& ctx) { 658void 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
690void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { 680void 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
9namespace Core { 10namespace 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
161class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> { 161class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
162public: 162public:
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
179class Boxcat::Client { 188class Boxcat::Client {
180public: 189public:
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
7namespace Service::HID { 7namespace Service::HID {
8 8
9ControllerBase::ControllerBase(Core::System& system) : system(system) {} 9ControllerBase::ControllerBase(Core::System& system_) : system(system_) {}
10ControllerBase::~ControllerBase() = default; 10ControllerBase::~ControllerBase() = default;
11 11
12void ControllerBase::ActivateController() { 12void 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;
18namespace Service::HID { 18namespace Service::HID {
19class ControllerBase { 19class ControllerBase {
20public: 20public:
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 bb77d8959..d311f754b 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -1,10 +1,9 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6#include "common/common_types.h"
7#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/math_util.h"
8#include "common/settings.h" 7#include "common/settings.h"
9#include "core/core_timing.h" 8#include "core/core_timing.h"
10#include "core/frontend/emu_window.h" 9#include "core/frontend/emu_window.h"
@@ -12,10 +11,19 @@
12 11
13namespace Service::HID { 12namespace Service::HID {
14constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00; 13constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
15constexpr f32 angle_threshold = 0.08f;
16constexpr f32 pinch_threshold = 100.0f;
17 14
18Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase{system_} {} 15// HW is around 700, value is set to 400 to make it easier to trigger with mouse
16constexpr f32 swipe_threshold = 400.0f; // Threshold in pixels/s
17constexpr f32 angle_threshold = 0.015f; // Threshold in radians
18constexpr f32 pinch_threshold = 0.5f; // Threshold in pixels
19constexpr f32 press_delay = 0.5f; // Time in seconds
20constexpr f32 double_tap_delay = 0.35f; // Time in seconds
21
22constexpr f32 Square(s32 num) {
23 return static_cast<f32>(num * num);
24}
25
26Controller_Gesture::Controller_Gesture(Core::System& system_) : ControllerBase(system_) {}
19Controller_Gesture::~Controller_Gesture() = default; 27Controller_Gesture::~Controller_Gesture() = default;
20 28
21void Controller_Gesture::OnInit() { 29void Controller_Gesture::OnInit() {
@@ -24,6 +32,8 @@ void Controller_Gesture::OnInit() {
24 keyboard_finger_id[id] = MAX_POINTS; 32 keyboard_finger_id[id] = MAX_POINTS;
25 udp_finger_id[id] = MAX_POINTS; 33 udp_finger_id[id] = MAX_POINTS;
26 } 34 }
35 shared_memory.header.entry_count = 0;
36 force_update = true;
27} 37}
28 38
29void Controller_Gesture::OnRelease() {} 39void Controller_Gesture::OnRelease() {}
@@ -38,17 +48,23 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
38 shared_memory.header.last_entry_index = 0; 48 shared_memory.header.last_entry_index = 0;
39 return; 49 return;
40 } 50 }
41 shared_memory.header.entry_count = 16;
42 51
43 const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index]; 52 ReadTouchInput();
44 shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17;
45 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
46 53
47 cur_entry.sampling_number = last_entry.sampling_number + 1; 54 GestureProperties gesture = GetGestureProperties();
48 cur_entry.sampling_number2 = cur_entry.sampling_number; 55 f32 time_difference = static_cast<f32>(shared_memory.header.timestamp - last_update_timestamp) /
56 (1000 * 1000 * 1000);
49 57
50 // TODO(german77): Implement all gesture types 58 // Only update if necesary
59 if (!ShouldUpdateGesture(gesture, time_difference)) {
60 return;
61 }
51 62
63 last_update_timestamp = shared_memory.header.timestamp;
64 UpdateGestureSharedMemory(data, size, gesture, time_difference);
65}
66
67void Controller_Gesture::ReadTouchInput() {
52 const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); 68 const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus();
53 const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); 69 const Input::TouchStatus& udp_status = touch_udp_device->GetStatus();
54 for (std::size_t id = 0; id < mouse_status.size(); ++id) { 70 for (std::size_t id = 0; id < mouse_status.size(); ++id) {
@@ -63,50 +79,71 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
63 UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); 79 UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]);
64 } 80 }
65 } 81 }
82}
66 83
67 TouchType type = TouchType::Idle; 84bool Controller_Gesture::ShouldUpdateGesture(const GestureProperties& gesture,
68 Attribute attributes{}; 85 f32 time_difference) {
69 GestureProperties gesture = GetGestureProperties(); 86 const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
70 if (last_gesture.active_points != gesture.active_points) { 87 if (force_update) {
71 ++last_gesture.detection_count; 88 force_update = false;
89 return true;
72 } 90 }
73 if (gesture.active_points > 0) {
74 if (last_gesture.active_points == 0) {
75 attributes.is_new_touch.Assign(true);
76 last_gesture.average_distance = gesture.average_distance;
77 last_gesture.angle = gesture.angle;
78 }
79 91
80 type = TouchType::Touch; 92 // Update if coordinates change
81 if (gesture.mid_point.x != last_entry.x || gesture.mid_point.y != last_entry.y) { 93 for (size_t id = 0; id < MAX_POINTS; id++) {
82 type = TouchType::Pan; 94 if (gesture.points[id].x != last_gesture.points[id].x ||
83 } 95 gesture.points[id].y != last_gesture.points[id].y) {
84 if (std::abs(gesture.average_distance - last_gesture.average_distance) > pinch_threshold) { 96 return true;
85 type = TouchType::Pinch;
86 }
87 if (std::abs(gesture.angle - last_gesture.angle) > angle_threshold) {
88 type = TouchType::Rotate;
89 } 97 }
98 }
99
100 // Update on press and hold event after 0.5 seconds
101 if (last_entry.type == TouchType::Touch && last_entry.point_count == 1 &&
102 time_difference > press_delay) {
103 return enable_press_and_tap;
104 }
105
106 return false;
107}
108
109void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,
110 GestureProperties& gesture,
111 f32 time_difference) {
112 TouchType type = TouchType::Idle;
113 Attribute attributes{};
114
115 const auto& last_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
116 shared_memory.header.last_entry_index = (shared_memory.header.last_entry_index + 1) % 17;
117 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
90 118
91 cur_entry.delta_x = gesture.mid_point.x - last_entry.x; 119 if (shared_memory.header.entry_count < 16) {
92 cur_entry.delta_y = gesture.mid_point.y - last_entry.y; 120 shared_memory.header.entry_count++;
93 // TODO: Find how velocities are calculated 121 }
94 cur_entry.vel_x = static_cast<float>(cur_entry.delta_x) * 150.1f;
95 cur_entry.vel_y = static_cast<float>(cur_entry.delta_y) * 150.1f;
96 122
97 // Slowdown the rate of change for less flapping 123 cur_entry.sampling_number = last_entry.sampling_number + 1;
98 last_gesture.average_distance = 124 cur_entry.sampling_number2 = cur_entry.sampling_number;
99 (last_gesture.average_distance * 0.9f) + (gesture.average_distance * 0.1f);
100 last_gesture.angle = (last_gesture.angle * 0.9f) + (gesture.angle * 0.1f);
101 125
126 // Reset values to default
127 cur_entry.delta_x = 0;
128 cur_entry.delta_y = 0;
129 cur_entry.vel_x = 0;
130 cur_entry.vel_y = 0;
131 cur_entry.direction = Direction::None;
132 cur_entry.rotation_angle = 0;
133 cur_entry.scale = 0;
134
135 if (gesture.active_points > 0) {
136 if (last_gesture.active_points == 0) {
137 NewGesture(gesture, type, attributes);
138 } else {
139 UpdateExistingGesture(gesture, type, time_difference);
140 }
102 } else { 141 } else {
103 cur_entry.delta_x = 0; 142 EndGesture(gesture, last_gesture, type, attributes, time_difference);
104 cur_entry.delta_y = 0;
105 cur_entry.vel_x = 0;
106 cur_entry.vel_y = 0;
107 } 143 }
108 last_gesture.active_points = gesture.active_points; 144
109 cur_entry.detection_count = last_gesture.detection_count; 145 // Apply attributes
146 cur_entry.detection_count = gesture.detection_count;
110 cur_entry.type = type; 147 cur_entry.type = type;
111 cur_entry.attributes = attributes; 148 cur_entry.attributes = attributes;
112 cur_entry.x = gesture.mid_point.x; 149 cur_entry.x = gesture.mid_point.x;
@@ -116,12 +153,195 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
116 cur_entry.points[id].x = gesture.points[id].x; 153 cur_entry.points[id].x = gesture.points[id].x;
117 cur_entry.points[id].y = gesture.points[id].y; 154 cur_entry.points[id].y = gesture.points[id].y;
118 } 155 }
119 cur_entry.rotation_angle = 0; 156 last_gesture = gesture;
120 cur_entry.scale = 0;
121 157
122 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory)); 158 std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(SharedMemory));
123} 159}
124 160
161void Controller_Gesture::NewGesture(GestureProperties& gesture, TouchType& type,
162 Attribute& attributes) {
163 const auto& last_entry =
164 shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
165 gesture.detection_count++;
166 type = TouchType::Touch;
167
168 // New touch after cancel is not considered new
169 if (last_entry.type != TouchType::Cancel) {
170 attributes.is_new_touch.Assign(1);
171 enable_press_and_tap = true;
172 }
173}
174
175void Controller_Gesture::UpdateExistingGesture(GestureProperties& gesture, TouchType& type,
176 f32 time_difference) {
177 const auto& last_entry =
178 shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
179
180 // Promote to pan type if touch moved
181 for (size_t id = 0; id < MAX_POINTS; id++) {
182 if (gesture.points[id].x != last_gesture.points[id].x ||
183 gesture.points[id].y != last_gesture.points[id].y) {
184 type = TouchType::Pan;
185 break;
186 }
187 }
188
189 // Number of fingers changed cancel the last event and clear data
190 if (gesture.active_points != last_gesture.active_points) {
191 type = TouchType::Cancel;
192 enable_press_and_tap = false;
193 gesture.active_points = 0;
194 gesture.mid_point = {};
195 for (size_t id = 0; id < MAX_POINTS; id++) {
196 gesture.points[id].x = 0;
197 gesture.points[id].y = 0;
198 }
199 return;
200 }
201
202 // Calculate extra parameters of panning
203 if (type == TouchType::Pan) {
204 UpdatePanEvent(gesture, last_gesture, type, time_difference);
205 return;
206 }
207
208 // Promote to press type
209 if (last_entry.type == TouchType::Touch) {
210 type = TouchType::Press;
211 }
212}
213
214void Controller_Gesture::EndGesture(GestureProperties& gesture,
215 GestureProperties& last_gesture_props, TouchType& type,
216 Attribute& attributes, f32 time_difference) {
217 const auto& last_entry =
218 shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
219 if (last_gesture_props.active_points != 0) {
220 switch (last_entry.type) {
221 case TouchType::Touch:
222 if (enable_press_and_tap) {
223 SetTapEvent(gesture, last_gesture_props, type, attributes);
224 return;
225 }
226 type = TouchType::Cancel;
227 force_update = true;
228 break;
229 case TouchType::Press:
230 case TouchType::Tap:
231 case TouchType::Swipe:
232 case TouchType::Pinch:
233 case TouchType::Rotate:
234 type = TouchType::Complete;
235 force_update = true;
236 break;
237 case TouchType::Pan:
238 EndPanEvent(gesture, last_gesture_props, type, time_difference);
239 break;
240 default:
241 break;
242 }
243 return;
244 }
245 if (last_entry.type == TouchType::Complete || last_entry.type == TouchType::Cancel) {
246 gesture.detection_count++;
247 }
248}
249
250void Controller_Gesture::SetTapEvent(GestureProperties& gesture,
251 GestureProperties& last_gesture_props, TouchType& type,
252 Attribute& attributes) {
253 type = TouchType::Tap;
254 gesture = last_gesture_props;
255 force_update = true;
256 f32 tap_time_difference =
257 static_cast<f32>(last_update_timestamp - last_tap_timestamp) / (1000 * 1000 * 1000);
258 last_tap_timestamp = last_update_timestamp;
259 if (tap_time_difference < double_tap_delay) {
260 attributes.is_double_tap.Assign(1);
261 }
262}
263
264void Controller_Gesture::UpdatePanEvent(GestureProperties& gesture,
265 GestureProperties& last_gesture_props, TouchType& type,
266 f32 time_difference) {
267 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
268 const auto& last_entry =
269 shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
270 cur_entry.delta_x = gesture.mid_point.x - last_entry.x;
271 cur_entry.delta_y = gesture.mid_point.y - last_entry.y;
272
273 cur_entry.vel_x = static_cast<f32>(cur_entry.delta_x) / time_difference;
274 cur_entry.vel_y = static_cast<f32>(cur_entry.delta_y) / time_difference;
275 last_pan_time_difference = time_difference;
276
277 // Promote to pinch type
278 if (std::abs(gesture.average_distance - last_gesture_props.average_distance) >
279 pinch_threshold) {
280 type = TouchType::Pinch;
281 cur_entry.scale = gesture.average_distance / last_gesture_props.average_distance;
282 }
283
284 const f32 angle_between_two_lines = std::atan((gesture.angle - last_gesture_props.angle) /
285 (1 + (gesture.angle * last_gesture_props.angle)));
286 // Promote to rotate type
287 if (std::abs(angle_between_two_lines) > angle_threshold) {
288 type = TouchType::Rotate;
289 cur_entry.scale = 0;
290 cur_entry.rotation_angle = angle_between_two_lines * 180.0f / Common::PI;
291 }
292}
293
294void Controller_Gesture::EndPanEvent(GestureProperties& gesture,
295 GestureProperties& last_gesture_props, TouchType& type,
296 f32 time_difference) {
297 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
298 const auto& last_entry =
299 shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
300 cur_entry.vel_x =
301 static_cast<f32>(last_entry.delta_x) / (last_pan_time_difference + time_difference);
302 cur_entry.vel_y =
303 static_cast<f32>(last_entry.delta_y) / (last_pan_time_difference + time_difference);
304 const f32 curr_vel =
305 std::sqrt((cur_entry.vel_x * cur_entry.vel_x) + (cur_entry.vel_y * cur_entry.vel_y));
306
307 // Set swipe event with parameters
308 if (curr_vel > swipe_threshold) {
309 SetSwipeEvent(gesture, last_gesture_props, type);
310 return;
311 }
312
313 // End panning without swipe
314 type = TouchType::Complete;
315 cur_entry.vel_x = 0;
316 cur_entry.vel_y = 0;
317 force_update = true;
318}
319
320void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,
321 GestureProperties& last_gesture_props, TouchType& type) {
322 auto& cur_entry = shared_memory.gesture_states[shared_memory.header.last_entry_index];
323 const auto& last_entry =
324 shared_memory.gesture_states[(shared_memory.header.last_entry_index + 16) % 17];
325 type = TouchType::Swipe;
326 gesture = last_gesture_props;
327 force_update = true;
328 cur_entry.delta_x = last_entry.delta_x;
329 cur_entry.delta_y = last_entry.delta_y;
330 if (std::abs(cur_entry.delta_x) > std::abs(cur_entry.delta_y)) {
331 if (cur_entry.delta_x > 0) {
332 cur_entry.direction = Direction::Right;
333 return;
334 }
335 cur_entry.direction = Direction::Left;
336 return;
337 }
338 if (cur_entry.delta_y > 0) {
339 cur_entry.direction = Direction::Down;
340 return;
341 }
342 cur_entry.direction = Direction::Up;
343}
344
125void Controller_Gesture::OnLoadInputDevices() { 345void Controller_Gesture::OnLoadInputDevices() {
126 touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window"); 346 touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window");
127 touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp"); 347 touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp");
@@ -183,23 +403,33 @@ Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties()
183 403
184 for (size_t id = 0; id < gesture.active_points; ++id) { 404 for (size_t id = 0; id < gesture.active_points; ++id) {
185 gesture.points[id].x = 405 gesture.points[id].x =
186 static_cast<int>(active_fingers[id].x * Layout::ScreenUndocked::Width); 406 static_cast<s32>(active_fingers[id].x * Layout::ScreenUndocked::Width);
187 gesture.points[id].y = 407 gesture.points[id].y =
188 static_cast<int>(active_fingers[id].y * Layout::ScreenUndocked::Height); 408 static_cast<s32>(active_fingers[id].y * Layout::ScreenUndocked::Height);
189 gesture.mid_point.x += static_cast<int>(gesture.points[id].x / gesture.active_points); 409
190 gesture.mid_point.y += static_cast<int>(gesture.points[id].y / gesture.active_points); 410 // Hack: There is no touch in docked but games still allow it
411 if (Settings::values.use_docked_mode.GetValue()) {
412 gesture.points[id].x =
413 static_cast<s32>(active_fingers[id].x * Layout::ScreenDocked::Width);
414 gesture.points[id].y =
415 static_cast<s32>(active_fingers[id].y * Layout::ScreenDocked::Height);
416 }
417
418 gesture.mid_point.x += static_cast<s32>(gesture.points[id].x / gesture.active_points);
419 gesture.mid_point.y += static_cast<s32>(gesture.points[id].y / gesture.active_points);
191 } 420 }
192 421
193 for (size_t id = 0; id < gesture.active_points; ++id) { 422 for (size_t id = 0; id < gesture.active_points; ++id) {
194 const double distance = 423 const f32 distance = std::sqrt(Square(gesture.mid_point.x - gesture.points[id].x) +
195 std::pow(static_cast<float>(gesture.mid_point.x - gesture.points[id].x), 2) + 424 Square(gesture.mid_point.y - gesture.points[id].y));
196 std::pow(static_cast<float>(gesture.mid_point.y - gesture.points[id].y), 2); 425 gesture.average_distance += distance / static_cast<f32>(gesture.active_points);
197 gesture.average_distance +=
198 static_cast<float>(distance) / static_cast<float>(gesture.active_points);
199 } 426 }
200 427
201 gesture.angle = std::atan2(static_cast<float>(gesture.mid_point.y - gesture.points[0].y), 428 gesture.angle = std::atan2(static_cast<f32>(gesture.mid_point.y - gesture.points[0].y),
202 static_cast<float>(gesture.mid_point.x - gesture.points[0].x)); 429 static_cast<f32>(gesture.mid_point.x - gesture.points[0].x));
430
431 gesture.detection_count = last_gesture.detection_count;
432
203 return gesture; 433 return gesture;
204} 434}
205 435
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index 7c357b977..f46e29411 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -1,4 +1,4 @@
1// Copyright 2018 yuzu emulator team 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
@@ -7,7 +7,6 @@
7#include <array> 7#include <array>
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/swap.h"
11#include "core/frontend/input.h" 10#include "core/frontend/input.h"
12#include "core/hle/service/hid/controllers/controller_base.h" 11#include "core/hle/service/hid/controllers/controller_base.h"
13 12
@@ -35,10 +34,10 @@ private:
35 34
36 enum class TouchType : u32 { 35 enum class TouchType : u32 {
37 Idle, // Nothing touching the screen 36 Idle, // Nothing touching the screen
38 Complete, // Unknown. End of touch? 37 Complete, // Set at the end of a touch event
39 Cancel, // Never triggered 38 Cancel, // Set when the number of fingers change
40 Touch, // Pressing without movement 39 Touch, // A finger just touched the screen
41 Press, // Never triggered 40 Press, // Set if last type is touch and the finger hasn't moved
42 Tap, // Fast press then release 41 Tap, // Fast press then release
43 Pan, // All points moving together across the screen 42 Pan, // All points moving together across the screen
44 Swipe, // Fast press movement and release of a single point 43 Swipe, // Fast press movement and release of a single point
@@ -58,8 +57,8 @@ private:
58 union { 57 union {
59 u32_le raw{}; 58 u32_le raw{};
60 59
61 BitField<0, 1, u32> is_new_touch; 60 BitField<4, 1, u32> is_new_touch;
62 BitField<1, 1, u32> is_double_tap; 61 BitField<8, 1, u32> is_double_tap;
63 }; 62 };
64 }; 63 };
65 static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size"); 64 static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size");
@@ -73,10 +72,9 @@ private:
73 struct GestureState { 72 struct GestureState {
74 s64_le sampling_number; 73 s64_le sampling_number;
75 s64_le sampling_number2; 74 s64_le sampling_number2;
76
77 s64_le detection_count; 75 s64_le detection_count;
78 TouchType type; 76 TouchType type;
79 Direction dir; 77 Direction direction;
80 s32_le x; 78 s32_le x;
81 s32_le y; 79 s32_le y;
82 s32_le delta_x; 80 s32_le delta_x;
@@ -84,8 +82,8 @@ private:
84 f32 vel_x; 82 f32 vel_x;
85 f32 vel_y; 83 f32 vel_y;
86 Attribute attributes; 84 Attribute attributes;
87 u32 scale; 85 f32 scale;
88 u32 rotation_angle; 86 f32 rotation_angle;
89 s32_le point_count; 87 s32_le point_count;
90 std::array<Points, 4> points; 88 std::array<Points, 4> points;
91 }; 89 };
@@ -109,17 +107,55 @@ private:
109 Points mid_point{}; 107 Points mid_point{};
110 s64_le detection_count{}; 108 s64_le detection_count{};
111 u64_le delta_time{}; 109 u64_le delta_time{};
112 float average_distance{}; 110 f32 average_distance{};
113 float angle{}; 111 f32 angle{};
114 }; 112 };
115 113
116 // Returns an unused finger id, if there is no fingers avaliable MAX_FINGERS will be returned 114 // Reads input from all available input engines
115 void ReadTouchInput();
116
117 // Returns true if gesture state needs to be updated
118 bool ShouldUpdateGesture(const GestureProperties& gesture, f32 time_difference);
119
120 // Updates the shared memory to the next state
121 void UpdateGestureSharedMemory(u8* data, std::size_t size, GestureProperties& gesture,
122 f32 time_difference);
123
124 // Initializes new gesture
125 void NewGesture(GestureProperties& gesture, TouchType& type, Attribute& attributes);
126
127 // Updates existing gesture state
128 void UpdateExistingGesture(GestureProperties& gesture, TouchType& type, f32 time_difference);
129
130 // Terminates exiting gesture
131 void EndGesture(GestureProperties& gesture, GestureProperties& last_gesture_props,
132 TouchType& type, Attribute& attributes, f32 time_difference);
133
134 // Set current event to a tap event
135 void SetTapEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
136 TouchType& type, Attribute& attributes);
137
138 // Calculates and set the extra parameters related to a pan event
139 void UpdatePanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
140 TouchType& type, f32 time_difference);
141
142 // Terminates the pan event
143 void EndPanEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
144 TouchType& type, f32 time_difference);
145
146 // Set current event to a swipe event
147 void SetSwipeEvent(GestureProperties& gesture, GestureProperties& last_gesture_props,
148 TouchType& type);
149
150 // Returns an unused finger id, if there is no fingers available std::nullopt is returned.
117 std::optional<size_t> GetUnusedFingerID() const; 151 std::optional<size_t> GetUnusedFingerID() const;
118 152
119 /** 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
120 * 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
121 * 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
122 * finger id */ 157 * finger id
158 */
123 size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, 159 size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input,
124 size_t finger_id); 160 size_t finger_id);
125 161
@@ -134,6 +170,11 @@ private:
134 std::array<size_t, MAX_FINGERS> keyboard_finger_id; 170 std::array<size_t, MAX_FINGERS> keyboard_finger_id;
135 std::array<size_t, MAX_FINGERS> udp_finger_id; 171 std::array<size_t, MAX_FINGERS> udp_finger_id;
136 std::array<Finger, MAX_POINTS> fingers; 172 std::array<Finger, MAX_POINTS> fingers;
137 GestureProperties last_gesture; 173 GestureProperties last_gesture{};
174 s64_le last_update_timestamp{};
175 s64_le last_tap_timestamp{};
176 f32 last_pan_time_difference{};
177 bool force_update{false};
178 bool enable_press_and_tap{false};
138}; 179};
139} // namespace Service::HID 180} // namespace Service::HID
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
91struct MiiInfoElement { 91struct 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
254class MiiDBModule final : public ServiceFramework<MiiDBModule> { 254class MiiDBModule final : public ServiceFramework<MiiDBModule> {
255public: 255public:
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.
22class nvdevice { 22class nvdevice {
23public: 23public:
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
9namespace Service::Nvidia { 9namespace Service::Nvidia {
10 10
11SyncpointManager::SyncpointManager(Tegra::GPU& gpu) : gpu{gpu} {} 11SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {}
12 12
13SyncpointManager::~SyncpointManager() = default; 13SyncpointManager::~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
19class SyncpointManager final { 19class SyncpointManager final {
20public: 20public:
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
14namespace Service::NVFlinger { 14namespace Service::NVFlinger {
15 15
16BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id) 16BufferQueue::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
64NVFlinger::NVFlinger(Core::System& system) : system(system) { 64NVFlinger::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
146void 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
149void NVFlinger::CloseLayer(u64 layer_id) { 153void NVFlinger::CloseLayer(u64 layer_id) {
@@ -154,9 +158,9 @@ void NVFlinger::CloseLayer(u64 layer_id) {
154 } 158 }
155} 159}
156 160
157std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const { 161std::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
239VI::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
235void NVFlinger::Compose() { 257void 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
46class NVFlinger final { 46class NVFlinger final {
47public: 47public:
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 @@
7namespace Service::PCTL { 7namespace Service::PCTL {
8 8
9PCTL::PCTL(Core::System& system_, std::shared_ptr<Module> module_, const char* name, 9PCTL::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 {
15class PCTL final : public Module::Interface { 15class PCTL final : public Module::Interface {
16public: 16public:
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
32void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, 32void 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..2c9b2ce6d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -111,7 +111,7 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
111 port_installed = true; 111 port_installed = true;
112} 112}
113 113
114void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) { 114Kernel::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);
@@ -119,9 +119,10 @@ void ServiceFrameworkBase::InstallAsNamedPort(Kernel::KernelCore& kernel) {
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().SetHleHandler(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
127void ServiceFrameworkBase::RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n) { 128void 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
136void 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
135void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext& ctx, 146void 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
169ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& context) { 180void 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
194ResultCode 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
22namespace Kernel { 22namespace Kernel {
23class HLERequestContext; 23class HLERequestContext;
24} 24class KClientPort;
25class KServerSession;
26} // namespace Kernel
25 27
26namespace Service { 28namespace 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
74protected: 83protected:
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
186private: 211private:
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..de530cbfb 100644
--- a/src/core/hle/service/sm/controller.cpp
+++ b/src/core/hle/service/sm/controller.cpp
@@ -26,15 +26,23 @@ 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 26 // 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 27 // and that we probably want to actually make an entirely new Session, but we still need to
28 // verify this on hardware. 28 // verify this on hardware.
29
29 LOG_DEBUG(Service, "called"); 30 LOG_DEBUG(Service, "called");
30 31
32 auto session = ctx.Session()->GetParent();
33
34 // Open a reference to the session to simulate a new one being created.
35 session->Open();
36 session->GetClientSession().Open();
37 session->GetServerSession().Open();
38
31 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; 39 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
32 rb.Push(RESULT_SUCCESS); 40 rb.Push(RESULT_SUCCESS);
33 rb.PushMoveObjects(ctx.Session()->GetParent()->GetClientSession()); 41 rb.PushMoveObjects(session->GetClientSession());
34} 42}
35 43
36void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { 44void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {
37 LOG_WARNING(Service, "(STUBBED) called, using CloneCurrentObject"); 45 LOG_DEBUG(Service, "called");
38 46
39 CloneCurrentObject(ctx); 47 CloneCurrentObject(ctx);
40} 48}
@@ -44,7 +52,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
44 52
45 IPC::ResponseBuilder rb{ctx, 3}; 53 IPC::ResponseBuilder rb{ctx, 3};
46 rb.Push(RESULT_SUCCESS); 54 rb.Push(RESULT_SUCCESS);
47 rb.Push<u16>(0x1000); 55 rb.Push<u16>(0x8000);
48} 56}
49 57
50// https://switchbrew.org/wiki/IPC_Marshalling 58// 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..8cc9aee8a 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
19namespace Service::SM { 20namespace Service::SM {
20 21
22constexpr ResultCode ERR_NOT_INITIALIZED(ErrorModule::SM, 2);
21constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); 23constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4);
22constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); 24constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6);
23constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); 25constexpr 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
44void ServiceManager::InstallInterfaces(std::shared_ptr<ServiceManager> self, Core::System& system) { 42Kernel::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
53ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name, 52ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name,
@@ -107,33 +106,68 @@ SM::~SM() = default;
107void SM::Initialize(Kernel::HLERequestContext& ctx) { 106void 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
114void SM::GetService(Kernel::HLERequestContext& ctx) { 115void 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
127void 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
134static 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}
118 144
119 std::string name(name_buf.begin(), end); 145ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ctx) {
146 if (!is_initialized) {
147 return ERR_NOT_INITIALIZED;
148 }
149
150 IPC::RequestParser rp{ctx};
151 std::string name(PopServiceName(rp));
120 152
121 auto result = service_manager->GetServicePort(name); 153 auto result = service_manager.GetServicePort(name);
122 if (result.Failed()) { 154 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); 155 LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw);
126 if (name.length() == 0) 156 return result.Code();
127 return; // LibNX Fix
128 UNIMPLEMENTED();
129 return;
130 } 157 }
131 158
132 auto* port = result.Unwrap(); 159 auto* port = result.Unwrap();
133 160
161 // Kernel::KScopedResourceReservation session_reservation(
162 // kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions);
163 // R_UNLESS(session_reservation.Succeeded(), Kernel::ResultLimitReached);
164
134 auto* session = Kernel::KSession::Create(kernel); 165 auto* session = Kernel::KSession::Create(kernel);
135 session->Initialize(&port->GetClientPort(), std::move(name)); 166 session->Initialize(&port->GetClientPort(), std::move(name));
136 167
168 // Commit the session reservation.
169 // session_reservation.Commit();
170
137 if (port->GetServerPort().GetHLEHandler()) { 171 if (port->GetServerPort().GetHLEHandler()) {
138 port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession()); 172 port->GetServerPort().GetHLEHandler()->ClientConnected(&session->GetServerSession());
139 } else { 173 } else {
@@ -141,18 +175,12 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
141 } 175 }
142 176
143 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); 177 LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
144 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; 178 return MakeResult(&session->GetClientSession());
145 rb.Push(RESULT_SUCCESS);
146 rb.PushMoveObjects(session->GetClientSession());
147} 179}
148 180
149void SM::RegisterService(Kernel::HLERequestContext& ctx) { 181void 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
179void SM::UnregisterService(Kernel::HLERequestContext& ctx) { 207void 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
192SM::SM(std::shared_ptr<ServiceManager> service_manager_, Core::System& system_) 217SM::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..60f0b3f8a 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
35class SM final : public ServiceFramework<SM> { 35class SM final : public ServiceFramework<SM> {
36public: 36public:
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
40private: 40private:
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
50class ServiceManager { 54class ServiceManager {
51public: 55public:
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();
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index dc2baca4a..3b072f6bc 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -10,6 +10,11 @@
10 10
11namespace Service::SSL { 11namespace Service::SSL {
12 12
13enum class CertificateFormat : u32 {
14 Pem = 1,
15 Der = 2,
16};
17
13class ISslConnection final : public ServiceFramework<ISslConnection> { 18class ISslConnection final : public ServiceFramework<ISslConnection> {
14public: 19public:
15 explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} { 20 explicit ISslConnection(Core::System& system_) : ServiceFramework{system_, "ISslConnection"} {
@@ -58,8 +63,8 @@ public:
58 {1, nullptr, "GetOption"}, 63 {1, nullptr, "GetOption"},
59 {2, &ISslContext::CreateConnection, "CreateConnection"}, 64 {2, &ISslContext::CreateConnection, "CreateConnection"},
60 {3, nullptr, "GetConnectionCount"}, 65 {3, nullptr, "GetConnectionCount"},
61 {4, nullptr, "ImportServerPki"}, 66 {4, &ISslContext::ImportServerPki, "ImportServerPki"},
62 {5, nullptr, "ImportClientPki"}, 67 {5, &ISslContext::ImportClientPki, "ImportClientPki"},
63 {6, nullptr, "RemoveServerPki"}, 68 {6, nullptr, "RemoveServerPki"},
64 {7, nullptr, "RemoveClientPki"}, 69 {7, nullptr, "RemoveClientPki"},
65 {8, nullptr, "RegisterInternalPki"}, 70 {8, nullptr, "RegisterInternalPki"},
@@ -94,6 +99,39 @@ private:
94 rb.Push(RESULT_SUCCESS); 99 rb.Push(RESULT_SUCCESS);
95 rb.PushIpcInterface<ISslConnection>(system); 100 rb.PushIpcInterface<ISslConnection>(system);
96 } 101 }
102
103 void ImportServerPki(Kernel::HLERequestContext& ctx) {
104 IPC::RequestParser rp{ctx};
105 const auto certificate_format = rp.PopEnum<CertificateFormat>();
106 const auto pkcs_12_certificates = ctx.ReadBuffer(0);
107
108 constexpr u64 server_id = 0;
109
110 LOG_WARNING(Service_SSL, "(STUBBED) called, certificate_format={}", certificate_format);
111
112 IPC::ResponseBuilder rb{ctx, 4};
113 rb.Push(RESULT_SUCCESS);
114 rb.Push(server_id);
115 }
116
117 void ImportClientPki(Kernel::HLERequestContext& ctx) {
118 const auto pkcs_12_certificate = ctx.ReadBuffer(0);
119 const auto ascii_password = [&ctx] {
120 if (ctx.CanReadBuffer(1)) {
121 return ctx.ReadBuffer(1);
122 }
123
124 return std::vector<u8>{};
125 }();
126
127 constexpr u64 client_id = 0;
128
129 LOG_WARNING(Service_SSL, "(STUBBED) called");
130
131 IPC::ResponseBuilder rb{ctx, 4};
132 rb.Push(RESULT_SUCCESS);
133 rb.Push(client_id);
134 }
97}; 135};
98 136
99class SSL final : public ServiceFramework<SSL> { 137class SSL final : public ServiceFramework<SSL> {
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
11class EphemeralNetworkSystemClockCore final : public SystemClockCore { 11class EphemeralNetworkSystemClockCore final : public SystemClockCore {
12public: 12public:
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
13class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback { 13class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback {
14public: 14public:
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
18protected: 18protected:
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
13class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback { 13class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback {
14public: 14public:
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
18protected: 18protected:
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
11class StandardLocalSystemClockCore final : public SystemClockCore { 11class StandardLocalSystemClockCore final : public SystemClockCore {
12public: 12public:
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
17class StandardNetworkSystemClockCore final : public SystemClockCore { 17class StandardNetworkSystemClockCore final : public SystemClockCore {
18public: 18public:
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 @@
11namespace Service::Time::Clock { 11namespace Service::Time::Clock {
12 12
13StandardUserSystemClockCore::StandardUserSystemClockCore( 13StandardUserSystemClockCore::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
37ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system, 37ResultCode 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
47ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext&) { 47ResultCode 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
24class StandardUserSystemClockCore final : public SystemClockCore { 24class StandardUserSystemClockCore final : public SystemClockCore {
25public: 25public:
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
9namespace Service::Time::Clock { 9namespace Service::Time::Clock {
10 10
11SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core) 11SystemClockCore::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
22class SystemClockCore { 22class SystemClockCore {
23public: 23public:
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
226TimeManager::TimeManager(Core::System& system) : system{system} {} 226TimeManager::TimeManager(Core::System& system_) : system{system_} {}
227 227
228TimeManager::~TimeManager() = default; 228TimeManager::~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
31class TimeManager final { 31class TimeManager final {
32public: 32public:
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
16static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000}; 16static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000};
17 17
18SharedMemory::SharedMemory(Core::System& system) : system(system) { 18SharedMemory::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
15class SharedMemory final { 15class SharedMemory final {
16public: 16public:
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
71TimeZoneContentManager::TimeZoneContentManager(Core::System& system) 71TimeZoneContentManager::TimeZoneContentManager(Core::System& system_)
72 : system{system}, location_name_cache{BuildLocationNameCache(system)} {} 72 : system{system_}, location_name_cache{BuildLocationNameCache(system)} {}
73 73
74void TimeZoneContentManager::Initialize(TimeManager& time_manager) { 74void 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
22class TimeZoneContentManager final { 22class TimeZoneContentManager final {
23public: 23public:
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
18namespace Service::VI { 18namespace Service::VI {
19 19
20Display::Display(u64 id, std::string name, Core::System& system) 20Display::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
98private: 98private:
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
7namespace Service::VI { 7namespace Service::VI {
8 8
9Layer::Layer(u64 id, NVFlinger::BufferQueue& queue) : id{id}, buffer_queue{queue} {} 9Layer::Layer(u64 id, NVFlinger::BufferQueue& queue) : layer_id{id}, buffer_queue{queue} {}
10 10
11Layer::~Layer() = default; 11Layer::~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
47private: 47private:
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
213class IGBPConnectRequestParcel : public Parcel { 213class IGBPConnectRequestParcel : public Parcel {
214public: 214public:
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
275class IGBPSetPreallocatedBufferRequestParcel : public Parcel { 275class IGBPSetPreallocatedBufferRequestParcel : public Parcel {
276public: 276public:
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
313class IGBPCancelBufferRequestParcel : public Parcel { 313class IGBPCancelBufferRequestParcel : public Parcel {
314public: 314public:
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
339class IGBPDequeueBufferRequestParcel : public Parcel { 339class IGBPDequeueBufferRequestParcel : public Parcel {
340public: 340public:
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
361class IGBPDequeueBufferResponseParcel : public Parcel { 361class IGBPDequeueBufferResponseParcel : public Parcel {
362public: 362public:
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
366protected: 366protected:
367 void SerializeData() override { 367 void SerializeData() override {
@@ -377,7 +377,7 @@ protected:
377 377
378class IGBPRequestBufferRequestParcel : public Parcel { 378class IGBPRequestBufferRequestParcel : public Parcel {
379public: 379public:
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
392class IGBPRequestBufferResponseParcel : public Parcel { 392class IGBPRequestBufferResponseParcel : public Parcel {
393public: 393public:
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
397protected: 397protected:
@@ -408,7 +408,7 @@ protected:
408 408
409class IGBPQueueBufferRequestParcel : public Parcel { 409class IGBPQueueBufferRequestParcel : public Parcel {
410public: 410public:
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
471class IGBPQueryRequestParcel : public Parcel { 471class IGBPQueryRequestParcel : public Parcel {
472public: 472public:
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
485class IGBPQueryResponseParcel : public Parcel { 485class IGBPQueryResponseParcel : public Parcel {
486public: 486public:
487 explicit IGBPQueryResponseParcel(u32 value) : value(value) {} 487 explicit IGBPQueryResponseParcel(u32 value_) : value{value_} {}
488 ~IGBPQueryResponseParcel() override = default; 488 ~IGBPQueryResponseParcel() override = default;
489 489
490protected: 490protected:
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 @@
22namespace Loader { 22namespace Loader {
23 23
24AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_, 24AppLoader_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
77AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( 76AppLoader_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
82FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) { 81FileType 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 {
24class AppLoader_DeconstructedRomDirectory final : public AppLoader { 24class AppLoader_DeconstructedRomDirectory final : public AppLoader {
25public: 25public:
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
197AppLoader::AppLoader(FileSys::VirtualFile file) : file(std::move(file)) {} 197AppLoader::AppLoader(FileSys::VirtualFile file_) : file(std::move(file_)) {}
198AppLoader::~AppLoader() = default; 198AppLoader::~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/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
40StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) 40StandardVmCallbacks::StandardVmCallbacks(System& system_, const CheatProcessMetadata& metadata_)
41 : metadata(metadata), system(system) {} 41 : metadata{metadata_}, system{system_} {}
42 42
43StandardVmCallbacks::~StandardVmCallbacks() = default; 43StandardVmCallbacks::~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
177CheatEngine::CheatEngine(Core::System& system, std::vector<CheatEntry> cheats, 177CheatEngine::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
184CheatEngine::~CheatEngine() { 184CheatEngine::~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
26class StandardVmCallbacks : public DmntCheatVm::Callbacks { 26class StandardVmCallbacks : public DmntCheatVm::Callbacks {
27public: 27public:
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
62class CheatEngine final { 62class CheatEngine final {
63public: 63public:
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
30namespace Core::Memory { 30namespace Core::Memory {
31 31
32DmntCheatVm::DmntCheatVm(std::unique_ptr<Callbacks> callbacks) : callbacks(std::move(callbacks)) {} 32DmntCheatVm::DmntCheatVm(std::unique_ptr<Callbacks> callbacks_)
33 : callbacks(std::move(callbacks_)) {}
33 34
34DmntCheatVm::~DmntCheatVm() = default; 35DmntCheatVm::~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
28namespace Core { 28namespace Core {
29 29
30PerfStats::PerfStats(u64 title_id) : title_id(title_id) {} 30PerfStats::PerfStats(u64 title_id_) : title_id(title_id_) {}
31 31
32PerfStats::~PerfStats() { 32PerfStats::~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
71void PerfStats::EndGameFrame() { 71void 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
77double PerfStats::GetMeanFrametime() const { 75double 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 {
15struct PerfStatsResults { 16struct 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 */
30class PerfStats { 31class PerfStats {
31public: 32public:
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
85class FrameLimiter { 88class 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
193namespace Core { 193namespace Core {
194 194
195Reporter::Reporter(System& system) : system(system) {} 195Reporter::Reporter(System& system_) : system(system_) {}
196 196
197Reporter::~Reporter() = default; 197Reporter::~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
31class Reporter { 31class Reporter {
32public: 32public:
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
42class NullState : public State { 45class NullState : public State {
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index f682a6db4..822d0b555 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
180std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { 236std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {
@@ -296,6 +352,12 @@ void SDLState::HandleGameControllerEvent(const SDL_Event& event) {
296 } 352 }
297 break; 353 break;
298 } 354 }
355 case SDL_CONTROLLERSENSORUPDATE: {
356 if (auto joystick = GetSDLJoystickBySDLID(event.csensor.which)) {
357 joystick->SetMotion(event.csensor);
358 }
359 break;
360 }
299 case SDL_JOYDEVICEREMOVED: 361 case SDL_JOYDEVICEREMOVED:
300 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); 362 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
301 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); 363 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
@@ -449,6 +511,18 @@ private:
449 std::shared_ptr<SDLJoystick> joystick; 511 std::shared_ptr<SDLJoystick> joystick;
450}; 512};
451 513
514class SDLMotion final : public Input::MotionDevice {
515public:
516 explicit SDLMotion(std::shared_ptr<SDLJoystick> joystick_) : joystick(std::move(joystick_)) {}
517
518 Input::MotionStatus GetStatus() const override {
519 return joystick->GetMotion().GetMotion();
520 }
521
522private:
523 std::shared_ptr<SDLJoystick> joystick;
524};
525
452class SDLDirectionMotion final : public Input::MotionDevice { 526class SDLDirectionMotion final : public Input::MotionDevice {
453public: 527public:
454 explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_) 528 explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
@@ -658,6 +732,10 @@ public:
658 732
659 auto joystick = state.GetSDLJoystickByGUID(guid, port); 733 auto joystick = state.GetSDLJoystickByGUID(guid, port);
660 734
735 if (params.Has("motion")) {
736 return std::make_unique<SDLMotion>(joystick);
737 }
738
661 if (params.Has("hat")) { 739 if (params.Has("hat")) {
662 const int hat = params.Get("hat", 0); 740 const int hat = params.Get("hat", 0);
663 const std::string direction_name = params.Get("direction", ""); 741 const std::string direction_name = params.Get("direction", "");
@@ -717,6 +795,17 @@ SDLState::SDLState() {
717 RegisterFactory<VibrationDevice>("sdl", vibration_factory); 795 RegisterFactory<VibrationDevice>("sdl", vibration_factory);
718 RegisterFactory<MotionDevice>("sdl", motion_factory); 796 RegisterFactory<MotionDevice>("sdl", motion_factory);
719 797
798 // Enable HIDAPI rumble. This prevents SDL from disabling motion on PS4 and PS5 controllers
799 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1");
800 SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
801
802 // Tell SDL2 to use the hidapi driver. This will allow joycons to be detected as a
803 // GameController and not a generic one
804 SDL_SetHint("SDL_JOYSTICK_HIDAPI_JOY_CONS", "1");
805
806 // Turn off Pro controller home led
807 SDL_SetHint("SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED", "0");
808
720 // If the frontend is going to manage the event loop, then we don't start one here 809 // If the frontend is going to manage the event loop, then we don't start one here
721 start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0; 810 start_thread = SDL_WasInit(SDL_INIT_JOYSTICK) == 0;
722 if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) { 811 if (start_thread && SDL_Init(SDL_INIT_JOYSTICK) < 0) {
@@ -853,6 +942,13 @@ Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s
853 return params; 942 return params;
854} 943}
855 944
945Common::ParamPackage BuildMotionParam(int port, std::string guid) {
946 Common::ParamPackage params({{"engine", "sdl"}, {"motion", "0"}});
947 params.Set("port", port);
948 params.Set("guid", std::move(guid));
949 return params;
950}
951
856Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { 952Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {
857 switch (event.type) { 953 switch (event.type) {
858 case SDL_JOYAXISMOTION: { 954 case SDL_JOYAXISMOTION: {
@@ -907,6 +1003,35 @@ Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Eve
907 } 1003 }
908 break; 1004 break;
909 } 1005 }
1006 case SDL_CONTROLLERSENSORUPDATE: {
1007 bool is_motion_shaking = false;
1008 constexpr float gyro_threshold = 5.0f;
1009 constexpr float accel_threshold = 11.0f;
1010 if (event.csensor.sensor == SDL_SENSOR_ACCEL) {
1011 const Common::Vec3f acceleration = {-event.csensor.data[0], event.csensor.data[2],
1012 -event.csensor.data[1]};
1013 if (acceleration.Length() > accel_threshold) {
1014 is_motion_shaking = true;
1015 }
1016 }
1017
1018 if (event.csensor.sensor == SDL_SENSOR_GYRO) {
1019 const Common::Vec3f gyroscope = {event.csensor.data[0], -event.csensor.data[2],
1020 event.csensor.data[1]};
1021 if (gyroscope.Length() > gyro_threshold) {
1022 is_motion_shaking = true;
1023 }
1024 }
1025
1026 if (!is_motion_shaking) {
1027 break;
1028 }
1029
1030 if (const auto joystick = state.GetSDLJoystickBySDLID(event.csensor.which)) {
1031 return BuildMotionParam(joystick->GetPort(), joystick->GetGUID());
1032 }
1033 break;
1034 }
910 } 1035 }
911 return {}; 1036 return {};
912} 1037}
@@ -1036,6 +1161,27 @@ AnalogMapping SDLState::GetAnalogMappingForDevice(const Common::ParamPackage& pa
1036 return mapping; 1161 return mapping;
1037} 1162}
1038 1163
1164MotionMapping SDLState::GetMotionMappingForDevice(const Common::ParamPackage& params) {
1165 if (!params.Has("guid") || !params.Has("port")) {
1166 return {};
1167 }
1168 const auto joystick = GetSDLJoystickByGUID(params.Get("guid", ""), params.Get("port", 0));
1169 auto* controller = joystick->GetSDLGameController();
1170 if (controller == nullptr) {
1171 return {};
1172 }
1173
1174 joystick->EnableMotion();
1175
1176 if (!joystick->HasGyro() && !joystick->HasAccel()) {
1177 return {};
1178 }
1179
1180 MotionMapping mapping = {};
1181 mapping.insert_or_assign(Settings::NativeMotion::MotionLeft,
1182 BuildMotionParam(joystick->GetPort(), joystick->GetGUID()));
1183 return mapping;
1184}
1039namespace Polling { 1185namespace Polling {
1040class SDLPoller : public InputCommon::Polling::DevicePoller { 1186class SDLPoller : public InputCommon::Polling::DevicePoller {
1041public: 1187public:
@@ -1149,6 +1295,7 @@ public:
1149 [[fallthrough]]; 1295 [[fallthrough]];
1150 case SDL_JOYBUTTONUP: 1296 case SDL_JOYBUTTONUP:
1151 case SDL_JOYHATMOTION: 1297 case SDL_JOYHATMOTION:
1298 case SDL_CONTROLLERSENSORUPDATE:
1152 return {SDLEventToMotionParamPackage(state, event)}; 1299 return {SDLEventToMotionParamPackage(state, event)};
1153 } 1300 }
1154 return std::nullopt; 1301 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
61private: 62private:
62 void InitJoystick(int joystick_index); 63 void InitJoystick(int joystick_index);
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
195void GPU::RendererFrameEndNotify() {
196 system.GetPerfStats().EndGameFrame();
197}
198
194void GPU::FlushCommands() { 199void 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_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
545void TextureCacheRuntime::BlitFramebuffer(Framebuffer* dst, Framebuffer* src, 545void 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;
28using VideoCommon::ImageViewId; 28using VideoCommon::ImageViewId;
29using VideoCommon::ImageViewType; 29using VideoCommon::ImageViewType;
30using VideoCommon::NUM_RT; 30using VideoCommon::NUM_RT;
31using VideoCommon::Offset2D; 31using VideoCommon::Region2D;
32using VideoCommon::RenderTargets; 32using VideoCommon::RenderTargets;
33 33
34struct ImageBufferMap { 34struct 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
292void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, 292void 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_,
353BlitImageHelper::~BlitImageHelper() = default; 353BlitImageHelper::~BlitImageHelper() = default;
354 354
355void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 355void 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
384void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer, 383void 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
14namespace Vulkan { 14namespace Vulkan {
15 15
16using VideoCommon::Offset2D; 16using VideoCommon::Region2D;
17 17
18class Device; 18class Device;
19class Framebuffer; 19class 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
604void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst, ImageView& src, 603void 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
17using VideoCommon::ImageId; 17using VideoCommon::ImageId;
18using VideoCommon::NUM_RT; 18using VideoCommon::NUM_RT;
19using VideoCommon::Offset2D; 19using VideoCommon::Region2D;
20using VideoCommon::RenderTargets; 20using VideoCommon::RenderTargets;
21using VideoCore::Surface::PixelFormat; 21using 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) {
615template <class P> 617template <class P>
616void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, 618void 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
666template <class P> 707template <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
67struct Region2D {
68 constexpr auto operator<=>(const Region2D&) const noexcept = default;
69
70 Offset2D start;
71 Offset2D end;
72};
73
67struct Extent2D { 74struct 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
11AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { 11AboutDialog::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
25AboutDialog::~AboutDialog() = default; 27AboutDialog::~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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;%1 | %2-%3 (%4)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> 73 <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;%1 (%2)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
74 </property> 74 </property>
75 </widget> 75 </widget>
76 </item> 76 </item>
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_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_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index f35c89e04..0cdaea8a4 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -46,6 +46,7 @@ ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::Configur
46 SetConfiguration(); 46 SetConfiguration();
47 47
48 // Force game list reload if any of the relevant settings are changed. 48 // Force game list reload if any of the relevant settings are changed.
49 connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate);
49 connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, 50 connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
50 &ConfigureUi::RequestGameListUpdate); 51 &ConfigureUi::RequestGameListUpdate);
51 connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, 52 connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
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
2752void GMainWindow::UpdateWindowTitle(const std::string& title_name, 2769void 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
81enum class ReinitializeKeyBehavior { 82enum class ReinitializeKeyBehavior {
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;