summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/audio_core/CMakeLists.txt3
-rw-r--r--src/audio_core/audio_renderer.cpp8
-rw-r--r--src/audio_core/audio_renderer.h8
-rw-r--r--src/audio_core/command_generator.cpp4
-rw-r--r--src/audio_core/common.h4
-rw-r--r--src/audio_core/effect_context.cpp4
-rw-r--r--src/audio_core/info_updater.cpp5
-rw-r--r--src/audio_core/info_updater.h4
-rw-r--r--src/audio_core/splitter_context.cpp2
-rw-r--r--src/audio_core/voice_context.cpp4
-rw-r--r--src/common/assert.cpp7
-rw-r--r--src/common/assert.h55
-rw-r--r--src/common/bounded_threadsafe_queue.h159
-rw-r--r--src/common/detached_tasks.cpp4
-rw-r--r--src/common/page_table.h3
-rw-r--r--src/common/param_package.cpp6
-rw-r--r--src/common/settings.cpp2
-rw-r--r--src/common/thread.cpp12
-rw-r--r--src/common/thread.h1
-rw-r--r--src/common/uint128.h5
-rw-r--r--src/common/x64/native_clock.cpp5
-rw-r--r--src/common/x64/native_clock.h6
-rw-r--r--src/core/CMakeLists.txt7
-rw-r--r--src/core/arm/arm_interface.cpp58
-rw-r--r--src/core/arm/arm_interface.h14
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp103
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp101
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h6
-rw-r--r--src/core/core.cpp24
-rw-r--r--src/core/core.h7
-rw-r--r--src/core/core_timing.cpp146
-rw-r--r--src/core/core_timing.h27
-rw-r--r--src/core/cpu_manager.cpp193
-rw-r--r--src/core/cpu_manager.h29
-rw-r--r--src/core/crypto/key_manager.cpp2
-rw-r--r--src/core/debugger/debugger.cpp154
-rw-r--r--src/core/debugger/debugger.h13
-rw-r--r--src/core/debugger/debugger_interface.h13
-rw-r--r--src/core/debugger/gdbstub.cpp142
-rw-r--r--src/core/debugger/gdbstub.h4
-rw-r--r--src/core/debugger/gdbstub_arch.cpp8
-rw-r--r--src/core/file_sys/content_archive.cpp2
-rw-r--r--src/core/file_sys/errors.h18
-rw-r--r--src/core/file_sys/nca_patch.cpp2
-rw-r--r--src/core/file_sys/registered_cache.cpp2
-rw-r--r--src/core/file_sys/vfs_real.cpp2
-rw-r--r--src/core/frontend/applets/controller.cpp2
-rw-r--r--src/core/frontend/applets/error.cpp6
-rw-r--r--src/core/frontend/applets/error.h12
-rw-r--r--src/core/hardware_properties.h3
-rw-r--r--src/core/hid/hid_core.cpp4
-rw-r--r--src/core/hle/ipc_helpers.h10
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp6
-rw-r--r--src/core/hle/kernel/hle_ipc.h15
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp2
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp17
-rw-r--r--src/core/hle/kernel/k_address_arbiter.h23
-rw-r--r--src/core/hle/kernel/k_address_space_info.cpp4
-rw-r--r--src/core/hle/kernel/k_auto_object.h11
-rw-r--r--src/core/hle/kernel/k_class_token.h1
-rw-r--r--src/core/hle/kernel/k_client_port.cpp4
-rw-r--r--src/core/hle/kernel/k_client_port.h4
-rw-r--r--src/core/hle/kernel/k_client_session.cpp4
-rw-r--r--src/core/hle/kernel/k_client_session.h6
-rw-r--r--src/core/hle/kernel/k_code_memory.cpp40
-rw-r--r--src/core/hle/kernel/k_code_memory.h14
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp18
-rw-r--r--src/core/hle/kernel/k_condition_variable.h6
-rw-r--r--src/core/hle/kernel/k_handle_table.cpp6
-rw-r--r--src/core/hle/kernel/k_handle_table.h8
-rw-r--r--src/core/hle/kernel/k_interrupt_manager.cpp5
-rw-r--r--src/core/hle/kernel/k_light_condition_variable.cpp3
-rw-r--r--src/core/hle/kernel/k_light_lock.cpp3
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp18
-rw-r--r--src/core/hle/kernel/k_memory_manager.h16
-rw-r--r--src/core/hle/kernel/k_page_group.h (renamed from src/core/hle/kernel/k_page_linked_list.h)10
-rw-r--r--src/core/hle/kernel/k_page_table.cpp297
-rw-r--r--src/core/hle/kernel/k_page_table.h172
-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.cpp165
-rw-r--r--src/core/hle/kernel/k_process.h75
-rw-r--r--src/core/hle/kernel/k_readable_event.cpp6
-rw-r--r--src/core/hle/kernel/k_readable_event.h6
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp2
-rw-r--r--src/core/hle/kernel/k_resource_limit.h4
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp27
-rw-r--r--src/core/hle/kernel/k_scheduler.h9
-rw-r--r--src/core/hle/kernel/k_server_session.cpp16
-rw-r--r--src/core/hle/kernel/k_server_session.h12
-rw-r--r--src/core/hle/kernel/k_shared_memory.cpp16
-rw-r--r--src/core/hle/kernel/k_shared_memory.h18
-rw-r--r--src/core/hle/kernel/k_synchronization_object.cpp13
-rw-r--r--src/core/hle/kernel/k_synchronization_object.h8
-rw-r--r--src/core/hle/kernel/k_thread.cpp87
-rw-r--r--src/core/hle/kernel/k_thread.h64
-rw-r--r--src/core/hle/kernel/k_thread_local_page.cpp4
-rw-r--r--src/core/hle/kernel/k_thread_local_page.h4
-rw-r--r--src/core/hle/kernel/k_thread_queue.cpp9
-rw-r--r--src/core/hle/kernel/k_thread_queue.h9
-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.cpp4
-rw-r--r--src/core/hle/kernel/k_writable_event.h4
-rw-r--r--src/core/hle/kernel/kernel.cpp70
-rw-r--r--src/core/hle/kernel/kernel.h14
-rw-r--r--src/core/hle/kernel/process_capability.cpp43
-rw-r--r--src/core/hle/kernel/process_capability.h38
-rw-r--r--src/core/hle/kernel/svc.cpp348
-rw-r--r--src/core/hle/kernel/svc_results.h58
-rw-r--r--src/core/hle/kernel/svc_wrap.h124
-rw-r--r--src/core/hle/result.h44
-rw-r--r--src/core/hle/service/acc/acc.cpp14
-rw-r--r--src/core/hle/service/acc/acc.h2
-rw-r--r--src/core/hle/service/acc/async_context.h2
-rw-r--r--src/core/hle/service/acc/errors.h4
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp12
-rw-r--r--src/core/hle/service/acc/profile_manager.h6
-rw-r--r--src/core/hle/service/am/am.cpp20
-rw-r--r--src/core/hle/service/am/am.h13
-rw-r--r--src/core/hle/service/am/applets/applet_controller.cpp8
-rw-r--r--src/core/hle/service/am/applets/applet_controller.h4
-rw-r--r--src/core/hle/service/am/applets/applet_error.cpp20
-rw-r--r--src/core/hle/service/am/applets/applet_error.h4
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.cpp14
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.h6
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.cpp4
-rw-r--r--src/core/hle/service/am/applets/applet_mii_edit.h2
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.cpp6
-rw-r--r--src/core/hle/service/am/applets/applet_profile_select.h4
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.cpp4
-rw-r--r--src/core/hle/service/am/applets/applet_software_keyboard.h4
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp6
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.h4
-rw-r--r--src/core/hle/service/am/applets/applets.h4
-rw-r--r--src/core/hle/service/audio/errors.h6
-rw-r--r--src/core/hle/service/bcat/backend/backend.cpp2
-rw-r--r--src/core/hle/service/bcat/backend/backend.h4
-rw-r--r--src/core/hle/service/bcat/bcat_module.cpp10
-rw-r--r--src/core/hle/service/es/es.cpp4
-rw-r--r--src/core/hle/service/fatal/fatal.cpp11
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp29
-rw-r--r--src/core/hle/service/filesystem/filesystem.h26
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp2
-rw-r--r--src/core/hle/service/friend/errors.h2
-rw-r--r--src/core/hle/service/glue/arp.cpp2
-rw-r--r--src/core/hle/service/glue/errors.h8
-rw-r--r--src/core/hle/service/glue/glue_manager.cpp6
-rw-r--r--src/core/hle/service/glue/glue_manager.h4
-rw-r--r--src/core/hle/service/glue/notif.cpp132
-rw-r--r--src/core/hle/service/glue/notif.h48
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp68
-rw-r--r--src/core/hle/service/hid/controllers/npad.h69
-rw-r--r--src/core/hle/service/hid/errors.h14
-rw-r--r--src/core/hle/service/hid/hid.cpp2
-rw-r--r--src/core/hle/service/hid/hidbus.h2
-rw-r--r--src/core/hle/service/hid/hidbus/hidbus_base.h2
-rw-r--r--src/core/hle/service/ldn/errors.h2
-rw-r--r--src/core/hle/service/ldr/ldr.cpp43
-rw-r--r--src/core/hle/service/mii/mii.cpp2
-rw-r--r--src/core/hle/service/mii/mii_manager.cpp6
-rw-r--r--src/core/hle/service/mii/mii_manager.h2
-rw-r--r--src/core/hle/service/nfp/nfp.cpp32
-rw-r--r--src/core/hle/service/nfp/nfp.h28
-rw-r--r--src/core/hle/service/ns/errors.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp4
-rw-r--r--src/core/hle/service/nvdrv/syncpoint_manager.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.cpp2
-rw-r--r--src/core/hle/service/pctl/pctl_module.cpp8
-rw-r--r--src/core/hle/service/pm/pm.cpp12
-rw-r--r--src/core/hle/service/service.cpp4
-rw-r--r--src/core/hle/service/service.h4
-rw-r--r--src/core/hle/service/set/set.cpp2
-rw-r--r--src/core/hle/service/set/set_sys.cpp2
-rw-r--r--src/core/hle/service/sm/sm.cpp18
-rw-r--r--src/core/hle/service/sm/sm.h6
-rw-r--r--src/core/hle/service/sm/sm_controller.cpp2
-rw-r--r--src/core/hle/service/spl/spl_results.h32
-rw-r--r--src/core/hle/service/time/clock_types.h8
-rw-r--r--src/core/hle/service/time/errors.h20
-rw-r--r--src/core/hle/service/time/local_system_clock_context_writer.h2
-rw-r--r--src/core/hle/service/time/network_system_clock_context_writer.h2
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.cpp26
-rw-r--r--src/core/hle/service/time/standard_user_system_clock_core.h10
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.cpp6
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.h4
-rw-r--r--src/core/hle/service/time/system_clock_core.cpp14
-rw-r--r--src/core/hle/service/time/system_clock_core.h14
-rw-r--r--src/core/hle/service/time/time.cpp25
-rw-r--r--src/core/hle/service/time/time.h2
-rw-r--r--src/core/hle/service/time/time_manager.cpp10
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp10
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.h6
-rw-r--r--src/core/hle/service/time/time_zone_manager.cpp48
-rw-r--r--src/core/hle/service/time/time_zone_manager.h20
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp15
-rw-r--r--src/core/hle/service/vi/vi.cpp8
-rw-r--r--src/core/loader/nso.cpp9
-rw-r--r--src/core/memory.cpp79
-rw-r--r--src/core/memory.h11
-rw-r--r--src/core/reporter.cpp8
-rw-r--r--src/core/reporter.h6
-rw-r--r--src/core/tools/freezer.cpp1
-rw-r--r--src/input_common/CMakeLists.txt1
-rw-r--r--src/input_common/drivers/sdl_driver.cpp56
-rw-r--r--src/input_common/drivers/sdl_driver.h15
-rw-r--r--src/shader_recompiler/CMakeLists.txt3
-rw-r--r--src/shader_recompiler/frontend/maxwell/control_flow.h2
-rw-r--r--src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp6
-rw-r--r--src/tests/core/core_timing.cpp4
-rw-r--r--src/video_core/CMakeLists.txt5
-rw-r--r--src/video_core/command_classes/codecs/codec.cpp2
-rw-r--r--src/video_core/command_classes/vic.cpp2
-rw-r--r--src/video_core/engines/maxwell_3d.h12
-rw-r--r--src/video_core/engines/maxwell_dma.cpp4
-rw-r--r--src/video_core/gpu_thread.cpp2
-rw-r--r--src/video_core/gpu_thread.h2
-rw-r--r--src/video_core/macro/macro.cpp2
-rw-r--r--src/video_core/macro/macro_interpreter.cpp1
-rw-r--r--src/video_core/macro/macro_jit_x64.cpp2
-rw-r--r--src/video_core/memory_manager.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_graphics_pipeline.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp38
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h12
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp4
-rw-r--r--src/video_core/renderer_opengl/util_shaders.cpp2
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp2
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h6
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp12
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h2
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h8
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp87
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h23
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h10
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp67
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.h28
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.h8
-rw-r--r--src/video_core/renderer_vulkan/vk_descriptor_pool.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_descriptor_pool.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.cpp21
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.h24
-rw-r--r--src/video_core/renderer_vulkan/vk_fsr.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_fsr.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h12
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h12
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.cpp16
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.h32
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h16
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.cpp38
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.h12
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp26
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h12
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp28
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h8
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.h10
-rw-r--r--src/video_core/shader_environment.cpp2
-rw-r--r--src/video_core/surface.cpp6
-rw-r--r--src/video_core/texture_cache/image_info.cpp2
-rw-r--r--src/video_core/texture_cache/image_view_info.cpp2
-rw-r--r--src/video_core/texture_cache/samples_helper.h4
-rw-r--r--src/video_core/texture_cache/texture_cache.h20
-rw-r--r--src/video_core/textures/decoders.cpp8
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp25
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp6
-rw-r--r--src/web_service/telemetry_json.cpp4
-rw-r--r--src/web_service/web_backend.cpp20
-rw-r--r--src/yuzu/applets/qt_controller.cpp2
-rw-r--r--src/yuzu/applets/qt_error.cpp6
-rw-r--r--src/yuzu/applets/qt_error.h6
-rw-r--r--src/yuzu/bootmanager.cpp13
-rw-r--r--src/yuzu/bootmanager.h12
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp7
-rw-r--r--src/yuzu/configuration/configure_dialog.h2
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp78
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp10
-rw-r--r--src/yuzu/configuration/configure_per_game.h4
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp4
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.h2
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp8
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.cpp4
-rw-r--r--src/yuzu/configuration/configure_touch_from_button.h2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp16
-rw-r--r--src/yuzu/debugger/wait_tree.h8
-rw-r--r--src/yuzu/game_list.cpp14
-rw-r--r--src/yuzu/game_list.h4
-rw-r--r--src/yuzu/game_list_p.h8
-rw-r--r--src/yuzu/game_list_worker.cpp12
-rw-r--r--src/yuzu/game_list_worker.h8
-rw-r--r--src/yuzu/main.cpp14
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu_cmd/config.cpp2
-rw-r--r--src/yuzu_cmd/default_ini.h5
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp10
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp4
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp4
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h2
-rw-r--r--src/yuzu_cmd/yuzu.cpp17
310 files changed, 3343 insertions, 2484 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9182dbfd4..39d038493 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -65,6 +65,10 @@ if (MSVC)
65 /we4305 # 'context': truncation from 'type1' to 'type2' 65 /we4305 # 'context': truncation from 'type1' to 'type2'
66 /we4388 # 'expression': signed/unsigned mismatch 66 /we4388 # 'expression': signed/unsigned mismatch
67 /we4389 # 'operator': signed/unsigned mismatch 67 /we4389 # 'operator': signed/unsigned mismatch
68 /we4456 # Declaration of 'identifier' hides previous local declaration
69 /we4457 # Declaration of 'identifier' hides function parameter
70 /we4458 # Declaration of 'identifier' hides class member
71 /we4459 # Declaration of 'identifier' hides global declaration
68 /we4505 # 'function': unreferenced local function has been removed 72 /we4505 # 'function': unreferenced local function has been removed
69 /we4547 # 'operator': operator before comma has no effect; expected operator with side-effect 73 /we4547 # 'operator': operator before comma has no effect; expected operator with side-effect
70 /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? 74 /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'?
@@ -92,6 +96,7 @@ else()
92 -Werror=missing-declarations 96 -Werror=missing-declarations
93 -Werror=missing-field-initializers 97 -Werror=missing-field-initializers
94 -Werror=reorder 98 -Werror=reorder
99 -Werror=shadow
95 -Werror=sign-compare 100 -Werror=sign-compare
96 -Werror=switch 101 -Werror=switch
97 -Werror=uninitialized 102 -Werror=uninitialized
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index e553b8203..89575a53e 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -49,9 +49,6 @@ if (NOT MSVC)
49 target_compile_options(audio_core PRIVATE 49 target_compile_options(audio_core PRIVATE
50 -Werror=conversion 50 -Werror=conversion
51 -Werror=ignored-qualifiers 51 -Werror=ignored-qualifiers
52 -Werror=shadow
53 -Werror=unused-parameter
54 -Werror=unused-variable
55 52
56 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 53 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
57 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> 54 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp
index e40ab16d2..2ee0a96ed 100644
--- a/src/audio_core/audio_renderer.cpp
+++ b/src/audio_core/audio_renderer.cpp
@@ -98,13 +98,13 @@ AudioRenderer::AudioRenderer(Core::Timing::CoreTiming& core_timing_, Core::Memor
98 98
99AudioRenderer::~AudioRenderer() = default; 99AudioRenderer::~AudioRenderer() = default;
100 100
101ResultCode AudioRenderer::Start() { 101Result AudioRenderer::Start() {
102 audio_out->StartStream(stream); 102 audio_out->StartStream(stream);
103 ReleaseAndQueueBuffers(); 103 ReleaseAndQueueBuffers();
104 return ResultSuccess; 104 return ResultSuccess;
105} 105}
106 106
107ResultCode AudioRenderer::Stop() { 107Result AudioRenderer::Stop() {
108 audio_out->StopStream(stream); 108 audio_out->StopStream(stream);
109 return ResultSuccess; 109 return ResultSuccess;
110} 110}
@@ -125,8 +125,8 @@ Stream::State AudioRenderer::GetStreamState() const {
125 return stream->GetState(); 125 return stream->GetState();
126} 126}
127 127
128ResultCode AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params, 128Result AudioRenderer::UpdateAudioRenderer(const std::vector<u8>& input_params,
129 std::vector<u8>& output_params) { 129 std::vector<u8>& output_params) {
130 std::scoped_lock lock{mutex}; 130 std::scoped_lock lock{mutex};
131 InfoUpdater info_updater{input_params, output_params, behavior_info}; 131 InfoUpdater info_updater{input_params, output_params, behavior_info};
132 132
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h
index 1f9f55ae2..a67ffd592 100644
--- a/src/audio_core/audio_renderer.h
+++ b/src/audio_core/audio_renderer.h
@@ -43,10 +43,10 @@ public:
43 Stream::ReleaseCallback&& release_callback, std::size_t instance_number); 43 Stream::ReleaseCallback&& release_callback, std::size_t instance_number);
44 ~AudioRenderer(); 44 ~AudioRenderer();
45 45
46 [[nodiscard]] ResultCode UpdateAudioRenderer(const std::vector<u8>& input_params, 46 [[nodiscard]] Result UpdateAudioRenderer(const std::vector<u8>& input_params,
47 std::vector<u8>& output_params); 47 std::vector<u8>& output_params);
48 [[nodiscard]] ResultCode Start(); 48 [[nodiscard]] Result Start();
49 [[nodiscard]] ResultCode Stop(); 49 [[nodiscard]] Result Stop();
50 void QueueMixedBuffer(Buffer::Tag tag); 50 void QueueMixedBuffer(Buffer::Tag tag);
51 void ReleaseAndQueueBuffers(); 51 void ReleaseAndQueueBuffers();
52 [[nodiscard]] u32 GetSampleRate() const; 52 [[nodiscard]] u32 GetSampleRate() const;
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp
index ff20ed00f..f97520820 100644
--- a/src/audio_core/command_generator.cpp
+++ b/src/audio_core/command_generator.cpp
@@ -429,7 +429,7 @@ void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, Vo
429 in_params.node_id); 429 in_params.node_id);
430 break; 430 break;
431 default: 431 default:
432 UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format); 432 ASSERT_MSG(false, "Unimplemented sample format={}", in_params.sample_format);
433 } 433 }
434 } 434 }
435} 435}
@@ -1312,7 +1312,7 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, std::s
1312 samples_to_read - samples_read, channel, temp_mix_offset); 1312 samples_to_read - samples_read, channel, temp_mix_offset);
1313 break; 1313 break;
1314 default: 1314 default:
1315 UNREACHABLE_MSG("Unimplemented sample format={}", in_params.sample_format); 1315 ASSERT_MSG(false, "Unimplemented sample format={}", in_params.sample_format);
1316 } 1316 }
1317 1317
1318 temp_mix_offset += samples_decoded; 1318 temp_mix_offset += samples_decoded;
diff --git a/src/audio_core/common.h b/src/audio_core/common.h
index 46ef83113..056a0ac70 100644
--- a/src/audio_core/common.h
+++ b/src/audio_core/common.h
@@ -10,8 +10,8 @@
10 10
11namespace AudioCommon { 11namespace AudioCommon {
12namespace Audren { 12namespace Audren {
13constexpr ResultCode ERR_INVALID_PARAMETERS{ErrorModule::Audio, 41}; 13constexpr Result ERR_INVALID_PARAMETERS{ErrorModule::Audio, 41};
14constexpr ResultCode ERR_SPLITTER_SORT_FAILED{ErrorModule::Audio, 43}; 14constexpr Result ERR_SPLITTER_SORT_FAILED{ErrorModule::Audio, 43};
15} // namespace Audren 15} // namespace Audren
16 16
17constexpr u8 BASE_REVISION = '0'; 17constexpr u8 BASE_REVISION = '0';
diff --git a/src/audio_core/effect_context.cpp b/src/audio_core/effect_context.cpp
index 51059580e..79bcd1192 100644
--- a/src/audio_core/effect_context.cpp
+++ b/src/audio_core/effect_context.cpp
@@ -50,7 +50,7 @@ EffectBase* EffectContext::RetargetEffect(std::size_t i, EffectType effect) {
50 effects[i] = std::make_unique<EffectBiquadFilter>(); 50 effects[i] = std::make_unique<EffectBiquadFilter>();
51 break; 51 break;
52 default: 52 default:
53 UNREACHABLE_MSG("Unimplemented effect {}", effect); 53 ASSERT_MSG(false, "Unimplemented effect {}", effect);
54 effects[i] = std::make_unique<EffectStubbed>(); 54 effects[i] = std::make_unique<EffectStubbed>();
55 } 55 }
56 return GetInfo(i); 56 return GetInfo(i);
@@ -104,7 +104,7 @@ void EffectI3dl2Reverb::Update(EffectInfo::InParams& in_params) {
104 auto& params = GetParams(); 104 auto& params = GetParams();
105 const auto* reverb_params = reinterpret_cast<I3dl2ReverbParams*>(in_params.raw.data()); 105 const auto* reverb_params = reinterpret_cast<I3dl2ReverbParams*>(in_params.raw.data());
106 if (!ValidChannelCountForEffect(reverb_params->max_channels)) { 106 if (!ValidChannelCountForEffect(reverb_params->max_channels)) {
107 UNREACHABLE_MSG("Invalid reverb max channel count {}", reverb_params->max_channels); 107 ASSERT_MSG(false, "Invalid reverb max channel count {}", reverb_params->max_channels);
108 return; 108 return;
109 } 109 }
110 110
diff --git a/src/audio_core/info_updater.cpp b/src/audio_core/info_updater.cpp
index 313a2eb6d..0065e6e53 100644
--- a/src/audio_core/info_updater.cpp
+++ b/src/audio_core/info_updater.cpp
@@ -285,9 +285,8 @@ bool InfoUpdater::UpdateSplitterInfo(SplitterContext& splitter_context) {
285 return true; 285 return true;
286} 286}
287 287
288ResultCode InfoUpdater::UpdateMixes(MixContext& mix_context, std::size_t mix_buffer_count, 288Result InfoUpdater::UpdateMixes(MixContext& mix_context, std::size_t mix_buffer_count,
289 SplitterContext& splitter_context, 289 SplitterContext& splitter_context, EffectContext& effect_context) {
290 EffectContext& effect_context) {
291 std::vector<MixInfo::InParams> mix_in_params; 290 std::vector<MixInfo::InParams> mix_in_params;
292 291
293 if (!behavior_info.IsMixInParameterDirtyOnlyUpdateSupported()) { 292 if (!behavior_info.IsMixInParameterDirtyOnlyUpdateSupported()) {
diff --git a/src/audio_core/info_updater.h b/src/audio_core/info_updater.h
index 6aab5beaf..17e66b036 100644
--- a/src/audio_core/info_updater.h
+++ b/src/audio_core/info_updater.h
@@ -32,8 +32,8 @@ public:
32 VAddr audio_codec_dsp_addr); 32 VAddr audio_codec_dsp_addr);
33 bool UpdateEffects(EffectContext& effect_context, bool is_active); 33 bool UpdateEffects(EffectContext& effect_context, bool is_active);
34 bool UpdateSplitterInfo(SplitterContext& splitter_context); 34 bool UpdateSplitterInfo(SplitterContext& splitter_context);
35 ResultCode UpdateMixes(MixContext& mix_context, std::size_t mix_buffer_count, 35 Result UpdateMixes(MixContext& mix_context, std::size_t mix_buffer_count,
36 SplitterContext& splitter_context, EffectContext& effect_context); 36 SplitterContext& splitter_context, EffectContext& effect_context);
37 bool UpdateSinks(SinkContext& sink_context); 37 bool UpdateSinks(SinkContext& sink_context);
38 bool UpdatePerformanceBuffer(); 38 bool UpdatePerformanceBuffer();
39 bool UpdateErrorInfo(BehaviorInfo& in_behavior_info); 39 bool UpdateErrorInfo(BehaviorInfo& in_behavior_info);
diff --git a/src/audio_core/splitter_context.cpp b/src/audio_core/splitter_context.cpp
index 1751d0212..10646dc05 100644
--- a/src/audio_core/splitter_context.cpp
+++ b/src/audio_core/splitter_context.cpp
@@ -483,7 +483,7 @@ bool NodeStates::DepthFirstSearch(EdgeMatrix& edge_matrix) {
483 // Add more work 483 // Add more work
484 index_stack.push(j); 484 index_stack.push(j);
485 } else if (node_state == NodeStates::State::InFound) { 485 } else if (node_state == NodeStates::State::InFound) {
486 UNREACHABLE_MSG("Node start marked as found"); 486 ASSERT_MSG(false, "Node start marked as found");
487 ResetState(); 487 ResetState();
488 return false; 488 return false;
489 } 489 }
diff --git a/src/audio_core/voice_context.cpp b/src/audio_core/voice_context.cpp
index c8e4a6caf..f58a5c754 100644
--- a/src/audio_core/voice_context.cpp
+++ b/src/audio_core/voice_context.cpp
@@ -114,7 +114,7 @@ void ServerVoiceInfo::UpdateParameters(const VoiceInfo::InParams& voice_in,
114 in_params.current_playstate = ServerPlayState::Play; 114 in_params.current_playstate = ServerPlayState::Play;
115 break; 115 break;
116 default: 116 default:
117 UNREACHABLE_MSG("Unknown playstate {}", voice_in.play_state); 117 ASSERT_MSG(false, "Unknown playstate {}", voice_in.play_state);
118 break; 118 break;
119 } 119 }
120 120
@@ -410,7 +410,7 @@ bool ServerVoiceInfo::UpdateParametersForCommandGeneration(
410 return in_params.should_depop; 410 return in_params.should_depop;
411 } 411 }
412 default: 412 default:
413 UNREACHABLE_MSG("Invalid playstate {}", in_params.current_playstate); 413 ASSERT_MSG(false, "Invalid playstate {}", in_params.current_playstate);
414 } 414 }
415 415
416 return false; 416 return false;
diff --git a/src/common/assert.cpp b/src/common/assert.cpp
index b44570528..6026b7dc2 100644
--- a/src/common/assert.cpp
+++ b/src/common/assert.cpp
@@ -6,8 +6,13 @@
6 6
7#include "common/settings.h" 7#include "common/settings.h"
8 8
9void assert_handle_failure() { 9void assert_fail_impl() {
10 if (Settings::values.use_debug_asserts) { 10 if (Settings::values.use_debug_asserts) {
11 Crash(); 11 Crash();
12 } 12 }
13} 13}
14
15[[noreturn]] void unreachable_impl() {
16 Crash();
17 throw std::runtime_error("Unreachable code");
18}
diff --git a/src/common/assert.h b/src/common/assert.h
index dbfd8abaf..8c927fcc0 100644
--- a/src/common/assert.h
+++ b/src/common/assert.h
@@ -9,44 +9,43 @@
9// Sometimes we want to try to continue even after hitting an assert. 9// Sometimes we want to try to continue even after hitting an assert.
10// However touching this file yields a global recompilation as this header is included almost 10// However touching this file yields a global recompilation as this header is included almost
11// everywhere. So let's just move the handling of the failed assert to a single cpp file. 11// everywhere. So let's just move the handling of the failed assert to a single cpp file.
12void assert_handle_failure();
13 12
14// For asserts we'd like to keep all the junk executed when an assert happens away from the 13void assert_fail_impl();
15// important code in the function. One way of doing this is to put all the relevant code inside a 14[[noreturn]] void unreachable_impl();
16// lambda and force the compiler to not inline it. Unfortunately, MSVC seems to have no syntax to 15
17// specify __declspec on lambda functions, so what we do instead is define a noinline wrapper 16#ifdef _MSC_VER
18// template that calls the lambda. This seems to generate an extra instruction at the call-site 17#define YUZU_NO_INLINE __declspec(noinline)
19// compared to the ideal implementation (which wouldn't support ASSERT_MSG parameters), but is good 18#else
20// enough for our purposes. 19#define YUZU_NO_INLINE __attribute__((noinline))
21template <typename Fn>
22#if defined(_MSC_VER)
23[[msvc::noinline]]
24#elif defined(__GNUC__)
25[[gnu::cold, gnu::noinline]]
26#endif 20#endif
27static void
28assert_noinline_call(const Fn& fn) {
29 fn();
30 assert_handle_failure();
31}
32 21
33#define ASSERT(_a_) \ 22#define ASSERT(_a_) \
34 do \ 23 ([&]() YUZU_NO_INLINE { \
35 if (!(_a_)) { \ 24 if (!(_a_)) [[unlikely]] { \
36 assert_noinline_call([] { LOG_CRITICAL(Debug, "Assertion Failed!"); }); \ 25 LOG_CRITICAL(Debug, "Assertion Failed!"); \
26 assert_fail_impl(); \
37 } \ 27 } \
38 while (0) 28 }())
39 29
40#define ASSERT_MSG(_a_, ...) \ 30#define ASSERT_MSG(_a_, ...) \
41 do \ 31 ([&]() YUZU_NO_INLINE { \
42 if (!(_a_)) { \ 32 if (!(_a_)) [[unlikely]] { \
43 assert_noinline_call([&] { LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); }); \ 33 LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \
34 assert_fail_impl(); \
44 } \ 35 } \
45 while (0) 36 }())
37
38#define UNREACHABLE() \
39 do { \
40 LOG_CRITICAL(Debug, "Unreachable code!"); \
41 unreachable_impl(); \
42 } while (0)
46 43
47#define UNREACHABLE() assert_noinline_call([] { LOG_CRITICAL(Debug, "Unreachable code!"); })
48#define UNREACHABLE_MSG(...) \ 44#define UNREACHABLE_MSG(...) \
49 assert_noinline_call([&] { LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); }) 45 do { \
46 LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); \
47 unreachable_impl(); \
48 } while (0)
50 49
51#ifdef _DEBUG 50#ifdef _DEBUG
52#define DEBUG_ASSERT(_a_) ASSERT(_a_) 51#define DEBUG_ASSERT(_a_) ASSERT(_a_)
diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h
index e83064c7f..7e465549b 100644
--- a/src/common/bounded_threadsafe_queue.h
+++ b/src/common/bounded_threadsafe_queue.h
@@ -1,10 +1,7 @@
1// SPDX-FileCopyrightText: Copyright (c) 2020 Erik Rigtorp <erik@rigtorp.se> 1// SPDX-FileCopyrightText: Copyright (c) 2020 Erik Rigtorp <erik@rigtorp.se>
2// SPDX-License-Identifier: MIT 2// SPDX-License-Identifier: MIT
3
3#pragma once 4#pragma once
4#ifdef _MSC_VER
5#pragma warning(push)
6#pragma warning(disable : 4324)
7#endif
8 5
9#include <atomic> 6#include <atomic>
10#include <bit> 7#include <bit>
@@ -12,105 +9,63 @@
12#include <memory> 9#include <memory>
13#include <mutex> 10#include <mutex>
14#include <new> 11#include <new>
15#include <stdexcept>
16#include <stop_token> 12#include <stop_token>
17#include <type_traits> 13#include <type_traits>
18#include <utility> 14#include <utility>
19 15
20namespace Common { 16namespace Common {
21namespace mpsc { 17
22#if defined(__cpp_lib_hardware_interference_size) 18#if defined(__cpp_lib_hardware_interference_size)
23constexpr size_t hardware_interference_size = std::hardware_destructive_interference_size; 19constexpr size_t hardware_interference_size = std::hardware_destructive_interference_size;
24#else 20#else
25constexpr size_t hardware_interference_size = 64; 21constexpr size_t hardware_interference_size = 64;
26#endif 22#endif
27 23
28template <typename T> 24#ifdef _MSC_VER
29using AlignedAllocator = std::allocator<T>; 25#pragma warning(push)
30 26#pragma warning(disable : 4324)
31template <typename T> 27#endif
32struct Slot {
33 ~Slot() noexcept {
34 if (turn.test()) {
35 destroy();
36 }
37 }
38
39 template <typename... Args>
40 void construct(Args&&... args) noexcept {
41 static_assert(std::is_nothrow_constructible_v<T, Args&&...>,
42 "T must be nothrow constructible with Args&&...");
43 std::construct_at(reinterpret_cast<T*>(&storage), std::forward<Args>(args)...);
44 }
45
46 void destroy() noexcept {
47 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible");
48 std::destroy_at(reinterpret_cast<T*>(&storage));
49 }
50
51 T&& move() noexcept {
52 return reinterpret_cast<T&&>(storage);
53 }
54
55 // Align to avoid false sharing between adjacent slots
56 alignas(hardware_interference_size) std::atomic_flag turn{};
57 struct aligned_store {
58 struct type {
59 alignas(T) unsigned char data[sizeof(T)];
60 };
61 };
62 typename aligned_store::type storage;
63};
64 28
65template <typename T, typename Allocator = AlignedAllocator<Slot<T>>> 29template <typename T, size_t capacity = 0x400>
66class Queue { 30class MPSCQueue {
67public: 31public:
68 explicit Queue(const size_t capacity, const Allocator& allocator = Allocator()) 32 explicit MPSCQueue() : allocator{std::allocator<Slot<T>>()} {
69 : allocator_(allocator) {
70 if (capacity < 1) {
71 throw std::invalid_argument("capacity < 1");
72 }
73 // Ensure that the queue length is an integer power of 2
74 // This is so that idx(i) can be a simple i & mask_ insted of i % capacity
75 // https://github.com/rigtorp/MPMCQueue/pull/36
76 if (!std::has_single_bit(capacity)) {
77 throw std::invalid_argument("capacity must be an integer power of 2");
78 }
79
80 mask_ = capacity - 1;
81
82 // Allocate one extra slot to prevent false sharing on the last slot 33 // Allocate one extra slot to prevent false sharing on the last slot
83 slots_ = allocator_.allocate(mask_ + 2); 34 slots = allocator.allocate(capacity + 1);
84 // Allocators are not required to honor alignment for over-aligned types 35 // Allocators are not required to honor alignment for over-aligned types
85 // (see http://eel.is/c++draft/allocator.requirements#10) so we verify 36 // (see http://eel.is/c++draft/allocator.requirements#10) so we verify
86 // alignment here 37 // alignment here
87 if (reinterpret_cast<uintptr_t>(slots_) % alignof(Slot<T>) != 0) { 38 if (reinterpret_cast<uintptr_t>(slots) % alignof(Slot<T>) != 0) {
88 allocator_.deallocate(slots_, mask_ + 2); 39 allocator.deallocate(slots, capacity + 1);
89 throw std::bad_alloc(); 40 throw std::bad_alloc();
90 } 41 }
91 for (size_t i = 0; i < mask_ + 1; ++i) { 42 for (size_t i = 0; i < capacity; ++i) {
92 std::construct_at(&slots_[i]); 43 std::construct_at(&slots[i]);
93 } 44 }
45 static_assert(std::has_single_bit(capacity), "capacity must be an integer power of 2");
94 static_assert(alignof(Slot<T>) == hardware_interference_size, 46 static_assert(alignof(Slot<T>) == hardware_interference_size,
95 "Slot must be aligned to cache line boundary to prevent false sharing"); 47 "Slot must be aligned to cache line boundary to prevent false sharing");
96 static_assert(sizeof(Slot<T>) % hardware_interference_size == 0, 48 static_assert(sizeof(Slot<T>) % hardware_interference_size == 0,
97 "Slot size must be a multiple of cache line size to prevent " 49 "Slot size must be a multiple of cache line size to prevent "
98 "false sharing between adjacent slots"); 50 "false sharing between adjacent slots");
99 static_assert(sizeof(Queue) % hardware_interference_size == 0, 51 static_assert(sizeof(MPSCQueue) % hardware_interference_size == 0,
100 "Queue size must be a multiple of cache line size to " 52 "Queue size must be a multiple of cache line size to "
101 "prevent false sharing between adjacent queues"); 53 "prevent false sharing between adjacent queues");
102 } 54 }
103 55
104 ~Queue() noexcept { 56 ~MPSCQueue() noexcept {
105 for (size_t i = 0; i < mask_ + 1; ++i) { 57 for (size_t i = 0; i < capacity; ++i) {
106 slots_[i].~Slot(); 58 std::destroy_at(&slots[i]);
107 } 59 }
108 allocator_.deallocate(slots_, mask_ + 2); 60 allocator.deallocate(slots, capacity + 1);
109 } 61 }
110 62
111 // non-copyable and non-movable 63 // The queue must be both non-copyable and non-movable
112 Queue(const Queue&) = delete; 64 MPSCQueue(const MPSCQueue&) = delete;
113 Queue& operator=(const Queue&) = delete; 65 MPSCQueue& operator=(const MPSCQueue&) = delete;
66
67 MPSCQueue(MPSCQueue&&) = delete;
68 MPSCQueue& operator=(MPSCQueue&&) = delete;
114 69
115 void Push(const T& v) noexcept { 70 void Push(const T& v) noexcept {
116 static_assert(std::is_nothrow_copy_constructible_v<T>, 71 static_assert(std::is_nothrow_copy_constructible_v<T>,
@@ -125,8 +80,8 @@ public:
125 80
126 void Pop(T& v, std::stop_token stop) noexcept { 81 void Pop(T& v, std::stop_token stop) noexcept {
127 auto const tail = tail_.fetch_add(1); 82 auto const tail = tail_.fetch_add(1);
128 auto& slot = slots_[idx(tail)]; 83 auto& slot = slots[idx(tail)];
129 if (false == slot.turn.test()) { 84 if (!slot.turn.test()) {
130 std::unique_lock lock{cv_mutex}; 85 std::unique_lock lock{cv_mutex};
131 cv.wait(lock, stop, [&slot] { return slot.turn.test(); }); 86 cv.wait(lock, stop, [&slot] { return slot.turn.test(); });
132 } 87 }
@@ -137,12 +92,46 @@ public:
137 } 92 }
138 93
139private: 94private:
95 template <typename U = T>
96 struct Slot {
97 ~Slot() noexcept {
98 if (turn.test()) {
99 destroy();
100 }
101 }
102
103 template <typename... Args>
104 void construct(Args&&... args) noexcept {
105 static_assert(std::is_nothrow_constructible_v<U, Args&&...>,
106 "T must be nothrow constructible with Args&&...");
107 std::construct_at(reinterpret_cast<U*>(&storage), std::forward<Args>(args)...);
108 }
109
110 void destroy() noexcept {
111 static_assert(std::is_nothrow_destructible_v<U>, "T must be nothrow destructible");
112 std::destroy_at(reinterpret_cast<U*>(&storage));
113 }
114
115 U&& move() noexcept {
116 return reinterpret_cast<U&&>(storage);
117 }
118
119 // Align to avoid false sharing between adjacent slots
120 alignas(hardware_interference_size) std::atomic_flag turn{};
121 struct aligned_store {
122 struct type {
123 alignas(U) unsigned char data[sizeof(U)];
124 };
125 };
126 typename aligned_store::type storage;
127 };
128
140 template <typename... Args> 129 template <typename... Args>
141 void emplace(Args&&... args) noexcept { 130 void emplace(Args&&... args) noexcept {
142 static_assert(std::is_nothrow_constructible_v<T, Args&&...>, 131 static_assert(std::is_nothrow_constructible_v<T, Args&&...>,
143 "T must be nothrow constructible with Args&&..."); 132 "T must be nothrow constructible with Args&&...");
144 auto const head = head_.fetch_add(1); 133 auto const head = head_.fetch_add(1);
145 auto& slot = slots_[idx(head)]; 134 auto& slot = slots[idx(head)];
146 slot.turn.wait(true); 135 slot.turn.wait(true);
147 slot.construct(std::forward<Args>(args)...); 136 slot.construct(std::forward<Args>(args)...);
148 slot.turn.test_and_set(); 137 slot.turn.test_and_set();
@@ -150,31 +139,29 @@ private:
150 } 139 }
151 140
152 constexpr size_t idx(size_t i) const noexcept { 141 constexpr size_t idx(size_t i) const noexcept {
153 return i & mask_; 142 return i & mask;
154 } 143 }
155 144
156 std::conditional_t<true, std::condition_variable_any, std::condition_variable> cv; 145 static constexpr size_t mask = capacity - 1;
157 std::mutex cv_mutex;
158 size_t mask_;
159 Slot<T>* slots_;
160 [[no_unique_address]] Allocator allocator_;
161 146
162 // Align to avoid false sharing between head_ and tail_ 147 // Align to avoid false sharing between head_ and tail_
163 alignas(hardware_interference_size) std::atomic<size_t> head_{0}; 148 alignas(hardware_interference_size) std::atomic<size_t> head_{0};
164 alignas(hardware_interference_size) std::atomic<size_t> tail_{0}; 149 alignas(hardware_interference_size) std::atomic<size_t> tail_{0};
165 150
151 std::mutex cv_mutex;
152 std::condition_variable_any cv;
153
154 Slot<T>* slots;
155 [[no_unique_address]] std::allocator<Slot<T>> allocator;
156
166 static_assert(std::is_nothrow_copy_assignable_v<T> || std::is_nothrow_move_assignable_v<T>, 157 static_assert(std::is_nothrow_copy_assignable_v<T> || std::is_nothrow_move_assignable_v<T>,
167 "T must be nothrow copy or move assignable"); 158 "T must be nothrow copy or move assignable");
168 159
169 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible"); 160 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible");
170}; 161};
171} // namespace mpsc
172
173template <typename T, typename Allocator = mpsc::AlignedAllocator<mpsc::Slot<T>>>
174using MPSCQueue = mpsc::Queue<T, Allocator>;
175
176} // namespace Common
177 162
178#ifdef _MSC_VER 163#ifdef _MSC_VER
179#pragma warning(pop) 164#pragma warning(pop)
180#endif 165#endif
166
167} // namespace Common
diff --git a/src/common/detached_tasks.cpp b/src/common/detached_tasks.cpp
index c1362631e..ec31d0b88 100644
--- a/src/common/detached_tasks.cpp
+++ b/src/common/detached_tasks.cpp
@@ -33,9 +33,9 @@ void DetachedTasks::AddTask(std::function<void()> task) {
33 ++instance->count; 33 ++instance->count;
34 std::thread([task{std::move(task)}]() { 34 std::thread([task{std::move(task)}]() {
35 task(); 35 task();
36 std::unique_lock lock{instance->mutex}; 36 std::unique_lock thread_lock{instance->mutex};
37 --instance->count; 37 --instance->count;
38 std::notify_all_at_thread_exit(instance->cv, std::move(lock)); 38 std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock));
39 }).detach(); 39 }).detach();
40} 40}
41 41
diff --git a/src/common/page_table.h b/src/common/page_table.h
index fcbd12a43..1ad3a9f8b 100644
--- a/src/common/page_table.h
+++ b/src/common/page_table.h
@@ -15,6 +15,9 @@ enum class PageType : u8 {
15 Unmapped, 15 Unmapped,
16 /// Page is mapped to regular memory. This is the only type you can get pointers to. 16 /// Page is mapped to regular memory. This is the only type you can get pointers to.
17 Memory, 17 Memory,
18 /// Page is mapped to regular memory, but inaccessible from CPU fastmem and must use
19 /// the callbacks.
20 DebugMemory,
18 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and 21 /// Page is mapped to regular memory, but also needs to check for rasterizer cache flushing and
19 /// invalidation 22 /// invalidation
20 RasterizerCachedMemory, 23 RasterizerCachedMemory,
diff --git a/src/common/param_package.cpp b/src/common/param_package.cpp
index bbf20f5eb..462502e34 100644
--- a/src/common/param_package.cpp
+++ b/src/common/param_package.cpp
@@ -76,7 +76,7 @@ std::string ParamPackage::Serialize() const {
76std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const { 76std::string ParamPackage::Get(const std::string& key, const std::string& default_value) const {
77 auto pair = data.find(key); 77 auto pair = data.find(key);
78 if (pair == data.end()) { 78 if (pair == data.end()) {
79 LOG_DEBUG(Common, "key '{}' not found", key); 79 LOG_TRACE(Common, "key '{}' not found", key);
80 return default_value; 80 return default_value;
81 } 81 }
82 82
@@ -86,7 +86,7 @@ std::string ParamPackage::Get(const std::string& key, const std::string& default
86int ParamPackage::Get(const std::string& key, int default_value) const { 86int ParamPackage::Get(const std::string& key, int default_value) const {
87 auto pair = data.find(key); 87 auto pair = data.find(key);
88 if (pair == data.end()) { 88 if (pair == data.end()) {
89 LOG_DEBUG(Common, "key '{}' not found", key); 89 LOG_TRACE(Common, "key '{}' not found", key);
90 return default_value; 90 return default_value;
91 } 91 }
92 92
@@ -101,7 +101,7 @@ int ParamPackage::Get(const std::string& key, int default_value) const {
101float ParamPackage::Get(const std::string& key, float default_value) const { 101float ParamPackage::Get(const std::string& key, float default_value) const {
102 auto pair = data.find(key); 102 auto pair = data.find(key);
103 if (pair == data.end()) { 103 if (pair == data.end()) {
104 LOG_DEBUG(Common, "key {} not found", key); 104 LOG_TRACE(Common, "key {} not found", key);
105 return default_value; 105 return default_value;
106 } 106 }
107 107
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 6ffab63af..751549583 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -147,7 +147,7 @@ void UpdateRescalingInfo() {
147 info.down_shift = 0; 147 info.down_shift = 0;
148 break; 148 break;
149 default: 149 default:
150 UNREACHABLE(); 150 ASSERT(false);
151 info.up_scale = 1; 151 info.up_scale = 1;
152 info.down_shift = 0; 152 info.down_shift = 0;
153 } 153 }
diff --git a/src/common/thread.cpp b/src/common/thread.cpp
index f932a7290..919e33af9 100644
--- a/src/common/thread.cpp
+++ b/src/common/thread.cpp
@@ -47,6 +47,9 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
47 case ThreadPriority::VeryHigh: 47 case ThreadPriority::VeryHigh:
48 windows_priority = THREAD_PRIORITY_HIGHEST; 48 windows_priority = THREAD_PRIORITY_HIGHEST;
49 break; 49 break;
50 case ThreadPriority::Critical:
51 windows_priority = THREAD_PRIORITY_TIME_CRITICAL;
52 break;
50 default: 53 default:
51 windows_priority = THREAD_PRIORITY_NORMAL; 54 windows_priority = THREAD_PRIORITY_NORMAL;
52 break; 55 break;
@@ -59,9 +62,10 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
59void SetCurrentThreadPriority(ThreadPriority new_priority) { 62void SetCurrentThreadPriority(ThreadPriority new_priority) {
60 pthread_t this_thread = pthread_self(); 63 pthread_t this_thread = pthread_self();
61 64
62 s32 max_prio = sched_get_priority_max(SCHED_OTHER); 65 const auto scheduling_type = SCHED_OTHER;
63 s32 min_prio = sched_get_priority_min(SCHED_OTHER); 66 s32 max_prio = sched_get_priority_max(scheduling_type);
64 u32 level = static_cast<u32>(new_priority) + 1; 67 s32 min_prio = sched_get_priority_min(scheduling_type);
68 u32 level = std::max(static_cast<u32>(new_priority) + 1, 4U);
65 69
66 struct sched_param params; 70 struct sched_param params;
67 if (max_prio > min_prio) { 71 if (max_prio > min_prio) {
@@ -70,7 +74,7 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
70 params.sched_priority = min_prio - ((min_prio - max_prio) * level) / 4; 74 params.sched_priority = min_prio - ((min_prio - max_prio) * level) / 4;
71 } 75 }
72 76
73 pthread_setschedparam(this_thread, SCHED_OTHER, &params); 77 pthread_setschedparam(this_thread, scheduling_type, &params);
74} 78}
75 79
76#endif 80#endif
diff --git a/src/common/thread.h b/src/common/thread.h
index a63122516..1552f58e0 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -92,6 +92,7 @@ enum class ThreadPriority : u32 {
92 Normal = 1, 92 Normal = 1,
93 High = 2, 93 High = 2,
94 VeryHigh = 3, 94 VeryHigh = 3,
95 Critical = 4,
95}; 96};
96 97
97void SetCurrentThreadPriority(ThreadPriority new_priority); 98void SetCurrentThreadPriority(ThreadPriority new_priority);
diff --git a/src/common/uint128.h b/src/common/uint128.h
index f890ffec2..199d0f55e 100644
--- a/src/common/uint128.h
+++ b/src/common/uint128.h
@@ -31,12 +31,17 @@ namespace Common {
31 return _udiv128(r[1], r[0], d, &remainder); 31 return _udiv128(r[1], r[0], d, &remainder);
32#endif 32#endif
33#else 33#else
34#ifdef __SIZEOF_INT128__
35 const auto product = static_cast<unsigned __int128>(a) * static_cast<unsigned __int128>(b);
36 return static_cast<u64>(product / d);
37#else
34 const u64 diva = a / d; 38 const u64 diva = a / d;
35 const u64 moda = a % d; 39 const u64 moda = a % d;
36 const u64 divb = b / d; 40 const u64 divb = b / d;
37 const u64 modb = b % d; 41 const u64 modb = b % d;
38 return diva * b + moda * divb + moda * modb / d; 42 return diva * b + moda * divb + moda * modb / d;
39#endif 43#endif
44#endif
40} 45}
41 46
42// This function multiplies 2 u64 values and produces a u128 value; 47// This function multiplies 2 u64 values and produces a u128 value;
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 1b7194503..6aaa8cdf9 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -75,8 +75,8 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
75} 75}
76 76
77u64 NativeClock::GetRTSC() { 77u64 NativeClock::GetRTSC() {
78 TimePoint new_time_point{};
79 TimePoint current_time_point{}; 78 TimePoint current_time_point{};
79 TimePoint new_time_point{};
80 80
81 current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); 81 current_time_point.pack = Common::AtomicLoad128(time_point.pack.data());
82 do { 82 do {
@@ -89,8 +89,7 @@ u64 NativeClock::GetRTSC() {
89 new_time_point.inner.accumulated_ticks = current_time_point.inner.accumulated_ticks + diff; 89 new_time_point.inner.accumulated_ticks = current_time_point.inner.accumulated_ticks + diff;
90 } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, 90 } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack,
91 current_time_point.pack, current_time_point.pack)); 91 current_time_point.pack, current_time_point.pack));
92 /// The clock cannot be more precise than the guest timer, remove the lower bits 92 return new_time_point.inner.accumulated_ticks;
93 return new_time_point.inner.accumulated_ticks & inaccuracy_mask;
94} 93}
95 94
96void NativeClock::Pause(bool is_paused) { 95void NativeClock::Pause(bool is_paused) {
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index 30d2ba2e9..38ae7a462 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -37,12 +37,8 @@ private:
37 } inner; 37 } inner;
38 }; 38 };
39 39
40 /// value used to reduce the native clocks accuracy as some apss rely on
41 /// undefined behavior where the level of accuracy in the clock shouldn't
42 /// be higher.
43 static constexpr u64 inaccuracy_mask = ~(UINT64_C(0x400) - 1);
44
45 TimePoint time_point; 40 TimePoint time_point;
41
46 // factors 42 // factors
47 u64 clock_rtsc_factor{}; 43 u64 clock_rtsc_factor{};
48 u64 cpu_rtsc_factor{}; 44 u64 cpu_rtsc_factor{};
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2bd720f08..d9357138f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -222,7 +222,7 @@ add_library(core STATIC
222 hle/kernel/k_page_buffer.h 222 hle/kernel/k_page_buffer.h
223 hle/kernel/k_page_heap.cpp 223 hle/kernel/k_page_heap.cpp
224 hle/kernel/k_page_heap.h 224 hle/kernel/k_page_heap.h
225 hle/kernel/k_page_linked_list.h 225 hle/kernel/k_page_group.h
226 hle/kernel/k_page_table.cpp 226 hle/kernel/k_page_table.cpp
227 hle/kernel/k_page_table.h 227 hle/kernel/k_page_table.h
228 hle/kernel/k_port.cpp 228 hle/kernel/k_port.cpp
@@ -743,16 +743,11 @@ if (MSVC)
743 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data 743 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
744 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch 744 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
745 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 745 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
746 /we4456 # Declaration of 'identifier' hides previous local declaration
747 /we4457 # Declaration of 'identifier' hides function parameter
748 /we4458 # Declaration of 'identifier' hides class member
749 /we4459 # Declaration of 'identifier' hides global declaration
750 ) 746 )
751else() 747else()
752 target_compile_options(core PRIVATE 748 target_compile_options(core PRIVATE
753 -Werror=conversion 749 -Werror=conversion
754 -Werror=ignored-qualifiers 750 -Werror=ignored-qualifiers
755 -Werror=shadow
756 751
757 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> 752 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess>
758 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 753 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 9b5a5ca57..0efc3732f 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -95,7 +95,7 @@ void ARM_Interface::Run() {
95 using Kernel::SuspendType; 95 using Kernel::SuspendType;
96 96
97 while (true) { 97 while (true) {
98 Kernel::KThread* current_thread{system.Kernel().CurrentScheduler()->GetCurrentThread()}; 98 Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())};
99 Dynarmic::HaltReason hr{}; 99 Dynarmic::HaltReason hr{};
100 100
101 // Notify the debugger and go to sleep if a step was performed 101 // Notify the debugger and go to sleep if a step was performed
@@ -107,6 +107,7 @@ void ARM_Interface::Run() {
107 } 107 }
108 108
109 // Otherwise, run the thread. 109 // Otherwise, run the thread.
110 system.EnterDynarmicProfile();
110 if (current_thread->GetStepState() == StepState::StepPending) { 111 if (current_thread->GetStepState() == StepState::StepPending) {
111 hr = StepJit(); 112 hr = StepJit();
112 113
@@ -116,14 +117,29 @@ void ARM_Interface::Run() {
116 } else { 117 } else {
117 hr = RunJit(); 118 hr = RunJit();
118 } 119 }
119 120 system.ExitDynarmicProfile();
120 // Notify the debugger and go to sleep if a breakpoint was hit. 121
121 if (Has(hr, breakpoint)) { 122 // Notify the debugger and go to sleep if a breakpoint was hit,
122 system.GetDebugger().NotifyThreadStopped(current_thread); 123 // or if the thread is unable to continue for any reason.
124 if (Has(hr, breakpoint) || Has(hr, no_execute)) {
125 RewindBreakpointInstruction();
126 if (system.DebuggerEnabled()) {
127 system.GetDebugger().NotifyThreadStopped(current_thread);
128 }
123 current_thread->RequestSuspend(Kernel::SuspendType::Debug); 129 current_thread->RequestSuspend(Kernel::SuspendType::Debug);
124 break; 130 break;
125 } 131 }
126 132
133 // Notify the debugger and go to sleep if a watchpoint was hit.
134 if (Has(hr, watchpoint)) {
135 RewindBreakpointInstruction();
136 if (system.DebuggerEnabled()) {
137 system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint());
138 }
139 current_thread->RequestSuspend(SuspendType::Debug);
140 break;
141 }
142
127 // Handle syscalls and scheduling (this may change the current thread) 143 // Handle syscalls and scheduling (this may change the current thread)
128 if (Has(hr, svc_call)) { 144 if (Has(hr, svc_call)) {
129 Kernel::Svc::Call(system, GetSvcNumber()); 145 Kernel::Svc::Call(system, GetSvcNumber());
@@ -134,4 +150,36 @@ void ARM_Interface::Run() {
134 } 150 }
135} 151}
136 152
153void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) {
154 watchpoints = &wp;
155}
156
157const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
158 VAddr addr, u64 size, Kernel::DebugWatchpointType access_type) const {
159 if (!watchpoints) {
160 return nullptr;
161 }
162
163 const VAddr start_address{addr};
164 const VAddr end_address{addr + size};
165
166 for (size_t i = 0; i < Core::Hardware::NUM_WATCHPOINTS; i++) {
167 const auto& watch{(*watchpoints)[i]};
168
169 if (end_address <= watch.start_address) {
170 continue;
171 }
172 if (start_address >= watch.end_address) {
173 continue;
174 }
175 if ((access_type & watch.type) == Kernel::DebugWatchpointType::None) {
176 continue;
177 }
178
179 return &watch;
180 }
181
182 return nullptr;
183}
184
137} // namespace Core 185} // namespace Core
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 66f6107e9..8a066ed91 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <span>
8#include <vector> 9#include <vector>
9 10
10#include <dynarmic/interface/halt_reason.h> 11#include <dynarmic/interface/halt_reason.h>
@@ -19,13 +20,16 @@ struct PageTable;
19 20
20namespace Kernel { 21namespace Kernel {
21enum class VMAPermission : u8; 22enum class VMAPermission : u8;
22} 23enum class DebugWatchpointType : u8;
24struct DebugWatchpoint;
25} // namespace Kernel
23 26
24namespace Core { 27namespace Core {
25class System; 28class System;
26class CPUInterruptHandler; 29class CPUInterruptHandler;
27 30
28using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>; 31using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>;
32using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>;
29 33
30/// Generic ARMv8 CPU interface 34/// Generic ARMv8 CPU interface
31class ARM_Interface { 35class ARM_Interface {
@@ -170,6 +174,7 @@ public:
170 virtual void SaveContext(ThreadContext64& ctx) = 0; 174 virtual void SaveContext(ThreadContext64& ctx) = 0;
171 virtual void LoadContext(const ThreadContext32& ctx) = 0; 175 virtual void LoadContext(const ThreadContext32& ctx) = 0;
172 virtual void LoadContext(const ThreadContext64& ctx) = 0; 176 virtual void LoadContext(const ThreadContext64& ctx) = 0;
177 void LoadWatchpointArray(const WatchpointArray& wp);
173 178
174 /// Clears the exclusive monitor's state. 179 /// Clears the exclusive monitor's state.
175 virtual void ClearExclusiveState() = 0; 180 virtual void ClearExclusiveState() = 0;
@@ -198,18 +203,25 @@ public:
198 static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; 203 static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2;
199 static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; 204 static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3;
200 static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; 205 static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4;
206 static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::UserDefined5;
207 static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6;
201 208
202protected: 209protected:
203 /// System context that this ARM interface is running under. 210 /// System context that this ARM interface is running under.
204 System& system; 211 System& system;
205 CPUInterrupts& interrupt_handlers; 212 CPUInterrupts& interrupt_handlers;
213 const WatchpointArray* watchpoints;
206 bool uses_wall_clock; 214 bool uses_wall_clock;
207 215
208 static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out); 216 static void SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out);
217 const Kernel::DebugWatchpoint* MatchingWatchpoint(
218 VAddr addr, u64 size, Kernel::DebugWatchpointType access_type) const;
209 219
210 virtual Dynarmic::HaltReason RunJit() = 0; 220 virtual Dynarmic::HaltReason RunJit() = 0;
211 virtual Dynarmic::HaltReason StepJit() = 0; 221 virtual Dynarmic::HaltReason StepJit() = 0;
212 virtual u32 GetSvcNumber() const = 0; 222 virtual u32 GetSvcNumber() const = 0;
223 virtual const Kernel::DebugWatchpoint* HaltedWatchpoint() const = 0;
224 virtual void RewindBreakpointInstruction() = 0;
213}; 225};
214 226
215} // namespace Core 227} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 7c82d0b96..10cf72a45 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -29,64 +29,94 @@ using namespace Common::Literals;
29class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { 29class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
30public: 30public:
31 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) 31 explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
32 : parent{parent_}, memory(parent.system.Memory()) {} 32 : parent{parent_},
33 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {}
33 34
34 u8 MemoryRead8(u32 vaddr) override { 35 u8 MemoryRead8(u32 vaddr) override {
36 CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
35 return memory.Read8(vaddr); 37 return memory.Read8(vaddr);
36 } 38 }
37 u16 MemoryRead16(u32 vaddr) override { 39 u16 MemoryRead16(u32 vaddr) override {
40 CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Read);
38 return memory.Read16(vaddr); 41 return memory.Read16(vaddr);
39 } 42 }
40 u32 MemoryRead32(u32 vaddr) override { 43 u32 MemoryRead32(u32 vaddr) override {
44 CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Read);
41 return memory.Read32(vaddr); 45 return memory.Read32(vaddr);
42 } 46 }
43 u64 MemoryRead64(u32 vaddr) override { 47 u64 MemoryRead64(u32 vaddr) override {
48 CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read);
44 return memory.Read64(vaddr); 49 return memory.Read64(vaddr);
45 } 50 }
51 std::optional<u32> MemoryReadCode(u32 vaddr) override {
52 if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
53 return std::nullopt;
54 }
55 return MemoryRead32(vaddr);
56 }
46 57
47 void MemoryWrite8(u32 vaddr, u8 value) override { 58 void MemoryWrite8(u32 vaddr, u8 value) override {
48 memory.Write8(vaddr, value); 59 if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) {
60 memory.Write8(vaddr, value);
61 }
49 } 62 }
50 void MemoryWrite16(u32 vaddr, u16 value) override { 63 void MemoryWrite16(u32 vaddr, u16 value) override {
51 memory.Write16(vaddr, value); 64 if (CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write)) {
65 memory.Write16(vaddr, value);
66 }
52 } 67 }
53 void MemoryWrite32(u32 vaddr, u32 value) override { 68 void MemoryWrite32(u32 vaddr, u32 value) override {
54 memory.Write32(vaddr, value); 69 if (CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write)) {
70 memory.Write32(vaddr, value);
71 }
55 } 72 }
56 void MemoryWrite64(u32 vaddr, u64 value) override { 73 void MemoryWrite64(u32 vaddr, u64 value) override {
57 memory.Write64(vaddr, value); 74 if (CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write)) {
75 memory.Write64(vaddr, value);
76 }
58 } 77 }
59 78
60 bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override { 79 bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override {
61 return memory.WriteExclusive8(vaddr, value, expected); 80 return CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write) &&
81 memory.WriteExclusive8(vaddr, value, expected);
62 } 82 }
63 bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override { 83 bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override {
64 return memory.WriteExclusive16(vaddr, value, expected); 84 return CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write) &&
85 memory.WriteExclusive16(vaddr, value, expected);
65 } 86 }
66 bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override { 87 bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override {
67 return memory.WriteExclusive32(vaddr, value, expected); 88 return CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write) &&
89 memory.WriteExclusive32(vaddr, value, expected);
68 } 90 }
69 bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override { 91 bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override {
70 return memory.WriteExclusive64(vaddr, value, expected); 92 return CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write) &&
93 memory.WriteExclusive64(vaddr, value, expected);
71 } 94 }
72 95
73 void InterpreterFallback(u32 pc, std::size_t num_instructions) override { 96 void InterpreterFallback(u32 pc, std::size_t num_instructions) override {
74 parent.LogBacktrace(); 97 parent.LogBacktrace();
75 UNIMPLEMENTED_MSG("This should never happen, pc = {:08X}, code = {:08X}", pc, 98 LOG_ERROR(Core_ARM,
76 MemoryReadCode(pc)); 99 "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
100 num_instructions, MemoryRead32(pc));
77 } 101 }
78 102
79 void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { 103 void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
80 if (parent.system.DebuggerEnabled()) { 104 switch (exception) {
81 parent.jit.load()->Regs()[15] = pc; 105 case Dynarmic::A32::Exception::NoExecuteFault:
82 parent.jit.load()->HaltExecution(ARM_Interface::breakpoint); 106 LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#08x}", pc);
107 ReturnException(pc, ARM_Interface::no_execute);
83 return; 108 return;
84 } 109 default:
110 if (debugger_enabled) {
111 ReturnException(pc, ARM_Interface::breakpoint);
112 return;
113 }
85 114
86 parent.LogBacktrace(); 115 parent.LogBacktrace();
87 LOG_CRITICAL(Core_ARM, 116 LOG_CRITICAL(Core_ARM,
88 "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", 117 "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})",
89 exception, pc, MemoryReadCode(pc), parent.IsInThumbMode()); 118 exception, pc, MemoryRead32(pc), parent.IsInThumbMode());
119 }
90 } 120 }
91 121
92 void CallSVC(u32 swi) override { 122 void CallSVC(u32 swi) override {
@@ -117,9 +147,31 @@ public:
117 return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0); 147 return std::max<s64>(parent.system.CoreTiming().GetDowncount(), 0);
118 } 148 }
119 149
150 bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
151 if (!debugger_enabled) {
152 return true;
153 }
154
155 const auto match{parent.MatchingWatchpoint(addr, size, type)};
156 if (match) {
157 parent.halted_watchpoint = match;
158 ReturnException(parent.jit.load()->Regs()[15], ARM_Interface::watchpoint);
159 return false;
160 }
161
162 return true;
163 }
164
165 void ReturnException(u32 pc, Dynarmic::HaltReason hr) {
166 parent.SaveContext(parent.breakpoint_context);
167 parent.breakpoint_context.cpu_registers[15] = pc;
168 parent.jit.load()->HaltExecution(hr);
169 }
170
120 ARM_Dynarmic_32& parent; 171 ARM_Dynarmic_32& parent;
121 Core::Memory::Memory& memory; 172 Core::Memory::Memory& memory;
122 std::size_t num_interpreted_instructions{}; 173 std::size_t num_interpreted_instructions{};
174 bool debugger_enabled{};
123 static constexpr u64 minimum_run_cycles = 1000U; 175 static constexpr u64 minimum_run_cycles = 1000U;
124}; 176};
125 177
@@ -154,6 +206,11 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
154 config.code_cache_size = 512_MiB; 206 config.code_cache_size = 512_MiB;
155 config.far_code_offset = 400_MiB; 207 config.far_code_offset = 400_MiB;
156 208
209 // Allow memory fault handling to work
210 if (system.DebuggerEnabled()) {
211 config.check_halt_on_memory_access = true;
212 }
213
157 // null_jit 214 // null_jit
158 if (!page_table) { 215 if (!page_table) {
159 // Don't waste too much memory on null_jit 216 // Don't waste too much memory on null_jit
@@ -248,6 +305,14 @@ u32 ARM_Dynarmic_32::GetSvcNumber() const {
248 return svc_swi; 305 return svc_swi;
249} 306}
250 307
308const Kernel::DebugWatchpoint* ARM_Dynarmic_32::HaltedWatchpoint() const {
309 return halted_watchpoint;
310}
311
312void ARM_Dynarmic_32::RewindBreakpointInstruction() {
313 LoadContext(breakpoint_context);
314}
315
251ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, 316ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_,
252 bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, 317 bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
253 std::size_t core_index_) 318 std::size_t core_index_)
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 5b1d60005..fcbe24f0c 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -72,6 +72,8 @@ protected:
72 Dynarmic::HaltReason RunJit() override; 72 Dynarmic::HaltReason RunJit() override;
73 Dynarmic::HaltReason StepJit() override; 73 Dynarmic::HaltReason StepJit() override;
74 u32 GetSvcNumber() const override; 74 u32 GetSvcNumber() const override;
75 const Kernel::DebugWatchpoint* HaltedWatchpoint() const override;
76 void RewindBreakpointInstruction() override;
75 77
76private: 78private:
77 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const; 79 std::shared_ptr<Dynarmic::A32::Jit> MakeJit(Common::PageTable* page_table) const;
@@ -98,6 +100,10 @@ private:
98 100
99 // SVC callback 101 // SVC callback
100 u32 svc_swi{}; 102 u32 svc_swi{};
103
104 // Watchpoint info
105 const Kernel::DebugWatchpoint* halted_watchpoint;
106 ThreadContext32 breakpoint_context;
101}; 107};
102 108
103} // namespace Core 109} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index d4c67eafd..92266aa9e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -29,62 +29,89 @@ using namespace Common::Literals;
29class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { 29class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
30public: 30public:
31 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) 31 explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
32 : parent{parent_}, memory(parent.system.Memory()) {} 32 : parent{parent_},
33 memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {}
33 34
34 u8 MemoryRead8(u64 vaddr) override { 35 u8 MemoryRead8(u64 vaddr) override {
36 CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
35 return memory.Read8(vaddr); 37 return memory.Read8(vaddr);
36 } 38 }
37 u16 MemoryRead16(u64 vaddr) override { 39 u16 MemoryRead16(u64 vaddr) override {
40 CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Read);
38 return memory.Read16(vaddr); 41 return memory.Read16(vaddr);
39 } 42 }
40 u32 MemoryRead32(u64 vaddr) override { 43 u32 MemoryRead32(u64 vaddr) override {
44 CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Read);
41 return memory.Read32(vaddr); 45 return memory.Read32(vaddr);
42 } 46 }
43 u64 MemoryRead64(u64 vaddr) override { 47 u64 MemoryRead64(u64 vaddr) override {
48 CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Read);
44 return memory.Read64(vaddr); 49 return memory.Read64(vaddr);
45 } 50 }
46 Vector MemoryRead128(u64 vaddr) override { 51 Vector MemoryRead128(u64 vaddr) override {
52 CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Read);
47 return {memory.Read64(vaddr), memory.Read64(vaddr + 8)}; 53 return {memory.Read64(vaddr), memory.Read64(vaddr + 8)};
48 } 54 }
55 std::optional<u32> MemoryReadCode(u64 vaddr) override {
56 if (!memory.IsValidVirtualAddressRange(vaddr, sizeof(u32))) {
57 return std::nullopt;
58 }
59 return MemoryRead32(vaddr);
60 }
49 61
50 void MemoryWrite8(u64 vaddr, u8 value) override { 62 void MemoryWrite8(u64 vaddr, u8 value) override {
51 memory.Write8(vaddr, value); 63 if (CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write)) {
64 memory.Write8(vaddr, value);
65 }
52 } 66 }
53 void MemoryWrite16(u64 vaddr, u16 value) override { 67 void MemoryWrite16(u64 vaddr, u16 value) override {
54 memory.Write16(vaddr, value); 68 if (CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write)) {
69 memory.Write16(vaddr, value);
70 }
55 } 71 }
56 void MemoryWrite32(u64 vaddr, u32 value) override { 72 void MemoryWrite32(u64 vaddr, u32 value) override {
57 memory.Write32(vaddr, value); 73 if (CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write)) {
74 memory.Write32(vaddr, value);
75 }
58 } 76 }
59 void MemoryWrite64(u64 vaddr, u64 value) override { 77 void MemoryWrite64(u64 vaddr, u64 value) override {
60 memory.Write64(vaddr, value); 78 if (CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write)) {
79 memory.Write64(vaddr, value);
80 }
61 } 81 }
62 void MemoryWrite128(u64 vaddr, Vector value) override { 82 void MemoryWrite128(u64 vaddr, Vector value) override {
63 memory.Write64(vaddr, value[0]); 83 if (CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Write)) {
64 memory.Write64(vaddr + 8, value[1]); 84 memory.Write64(vaddr, value[0]);
85 memory.Write64(vaddr + 8, value[1]);
86 }
65 } 87 }
66 88
67 bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override { 89 bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override {
68 return memory.WriteExclusive8(vaddr, value, expected); 90 return CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Write) &&
91 memory.WriteExclusive8(vaddr, value, expected);
69 } 92 }
70 bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override { 93 bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override {
71 return memory.WriteExclusive16(vaddr, value, expected); 94 return CheckMemoryAccess(vaddr, 2, Kernel::DebugWatchpointType::Write) &&
95 memory.WriteExclusive16(vaddr, value, expected);
72 } 96 }
73 bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override { 97 bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override {
74 return memory.WriteExclusive32(vaddr, value, expected); 98 return CheckMemoryAccess(vaddr, 4, Kernel::DebugWatchpointType::Write) &&
99 memory.WriteExclusive32(vaddr, value, expected);
75 } 100 }
76 bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override { 101 bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override {
77 return memory.WriteExclusive64(vaddr, value, expected); 102 return CheckMemoryAccess(vaddr, 8, Kernel::DebugWatchpointType::Write) &&
103 memory.WriteExclusive64(vaddr, value, expected);
78 } 104 }
79 bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override { 105 bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override {
80 return memory.WriteExclusive128(vaddr, value, expected); 106 return CheckMemoryAccess(vaddr, 16, Kernel::DebugWatchpointType::Write) &&
107 memory.WriteExclusive128(vaddr, value, expected);
81 } 108 }
82 109
83 void InterpreterFallback(u64 pc, std::size_t num_instructions) override { 110 void InterpreterFallback(u64 pc, std::size_t num_instructions) override {
84 parent.LogBacktrace(); 111 parent.LogBacktrace();
85 LOG_ERROR(Core_ARM, 112 LOG_ERROR(Core_ARM,
86 "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, 113 "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc,
87 num_instructions, MemoryReadCode(pc)); 114 num_instructions, MemoryRead32(pc));
88 } 115 }
89 116
90 void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, 117 void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op,
@@ -117,16 +144,19 @@ public:
117 case Dynarmic::A64::Exception::SendEventLocal: 144 case Dynarmic::A64::Exception::SendEventLocal:
118 case Dynarmic::A64::Exception::Yield: 145 case Dynarmic::A64::Exception::Yield:
119 return; 146 return;
147 case Dynarmic::A64::Exception::NoExecuteFault:
148 LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#016x}", pc);
149 ReturnException(pc, ARM_Interface::no_execute);
150 return;
120 default: 151 default:
121 if (parent.system.DebuggerEnabled()) { 152 if (debugger_enabled) {
122 parent.jit.load()->SetPC(pc); 153 ReturnException(pc, ARM_Interface::breakpoint);
123 parent.jit.load()->HaltExecution(ARM_Interface::breakpoint);
124 return; 154 return;
125 } 155 }
126 156
127 parent.LogBacktrace(); 157 parent.LogBacktrace();
128 ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", 158 LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
129 static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); 159 static_cast<std::size_t>(exception), pc, MemoryRead32(pc));
130 } 160 }
131 } 161 }
132 162
@@ -160,10 +190,32 @@ public:
160 return parent.system.CoreTiming().GetClockTicks(); 190 return parent.system.CoreTiming().GetClockTicks();
161 } 191 }
162 192
193 bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
194 if (!debugger_enabled) {
195 return true;
196 }
197
198 const auto match{parent.MatchingWatchpoint(addr, size, type)};
199 if (match) {
200 parent.halted_watchpoint = match;
201 ReturnException(parent.jit.load()->GetPC(), ARM_Interface::watchpoint);
202 return false;
203 }
204
205 return true;
206 }
207
208 void ReturnException(u64 pc, Dynarmic::HaltReason hr) {
209 parent.SaveContext(parent.breakpoint_context);
210 parent.breakpoint_context.pc = pc;
211 parent.jit.load()->HaltExecution(hr);
212 }
213
163 ARM_Dynarmic_64& parent; 214 ARM_Dynarmic_64& parent;
164 Core::Memory::Memory& memory; 215 Core::Memory::Memory& memory;
165 u64 tpidrro_el0 = 0; 216 u64 tpidrro_el0 = 0;
166 u64 tpidr_el0 = 0; 217 u64 tpidr_el0 = 0;
218 bool debugger_enabled{};
167 static constexpr u64 minimum_run_cycles = 1000U; 219 static constexpr u64 minimum_run_cycles = 1000U;
168}; 220};
169 221
@@ -214,6 +266,11 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
214 config.code_cache_size = 512_MiB; 266 config.code_cache_size = 512_MiB;
215 config.far_code_offset = 400_MiB; 267 config.far_code_offset = 400_MiB;
216 268
269 // Allow memory fault handling to work
270 if (system.DebuggerEnabled()) {
271 config.check_halt_on_memory_access = true;
272 }
273
217 // null_jit 274 // null_jit
218 if (!page_table) { 275 if (!page_table) {
219 // Don't waste too much memory on null_jit 276 // Don't waste too much memory on null_jit
@@ -308,6 +365,14 @@ u32 ARM_Dynarmic_64::GetSvcNumber() const {
308 return svc_swi; 365 return svc_swi;
309} 366}
310 367
368const Kernel::DebugWatchpoint* ARM_Dynarmic_64::HaltedWatchpoint() const {
369 return halted_watchpoint;
370}
371
372void ARM_Dynarmic_64::RewindBreakpointInstruction() {
373 LoadContext(breakpoint_context);
374}
375
311ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, 376ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_,
312 bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, 377 bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
313 std::size_t core_index_) 378 std::size_t core_index_)
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index abfbc3c3f..71dbaac5e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -66,6 +66,8 @@ protected:
66 Dynarmic::HaltReason RunJit() override; 66 Dynarmic::HaltReason RunJit() override;
67 Dynarmic::HaltReason StepJit() override; 67 Dynarmic::HaltReason StepJit() override;
68 u32 GetSvcNumber() const override; 68 u32 GetSvcNumber() const override;
69 const Kernel::DebugWatchpoint* HaltedWatchpoint() const override;
70 void RewindBreakpointInstruction() override;
69 71
70private: 72private:
71 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, 73 std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table,
@@ -91,6 +93,10 @@ private:
91 93
92 // SVC callback 94 // SVC callback
93 u32 svc_swi{}; 95 u32 svc_swi{};
96
97 // Breakpoint info
98 const Kernel::DebugWatchpoint* halted_watchpoint;
99 ThreadContext64 breakpoint_context;
94}; 100};
95 101
96} // namespace Core 102} // namespace Core
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 7d974ba65..7723d9782 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -138,7 +138,6 @@ struct System::Impl {
138 138
139 kernel.Suspend(false); 139 kernel.Suspend(false);
140 core_timing.SyncPause(false); 140 core_timing.SyncPause(false);
141 cpu_manager.Pause(false);
142 is_paused = false; 141 is_paused = false;
143 142
144 return status; 143 return status;
@@ -150,25 +149,22 @@ struct System::Impl {
150 149
151 core_timing.SyncPause(true); 150 core_timing.SyncPause(true);
152 kernel.Suspend(true); 151 kernel.Suspend(true);
153 cpu_manager.Pause(true);
154 is_paused = true; 152 is_paused = true;
155 153
156 return status; 154 return status;
157 } 155 }
158 156
159 std::unique_lock<std::mutex> StallCPU() { 157 std::unique_lock<std::mutex> StallProcesses() {
160 std::unique_lock<std::mutex> lk(suspend_guard); 158 std::unique_lock<std::mutex> lk(suspend_guard);
161 kernel.Suspend(true); 159 kernel.Suspend(true);
162 core_timing.SyncPause(true); 160 core_timing.SyncPause(true);
163 cpu_manager.Pause(true);
164 return lk; 161 return lk;
165 } 162 }
166 163
167 void UnstallCPU() { 164 void UnstallProcesses() {
168 if (!is_paused) { 165 if (!is_paused) {
169 core_timing.SyncPause(false); 166 core_timing.SyncPause(false);
170 kernel.Suspend(false); 167 kernel.Suspend(false);
171 cpu_manager.Pause(false);
172 } 168 }
173 } 169 }
174 170
@@ -334,6 +330,8 @@ struct System::Impl {
334 gpu_core->NotifyShutdown(); 330 gpu_core->NotifyShutdown();
335 } 331 }
336 332
333 kernel.ShutdownCores();
334 cpu_manager.Shutdown();
337 debugger.reset(); 335 debugger.reset();
338 services.reset(); 336 services.reset();
339 service_manager.reset(); 337 service_manager.reset();
@@ -493,12 +491,18 @@ void System::Shutdown() {
493 impl->Shutdown(); 491 impl->Shutdown();
494} 492}
495 493
496std::unique_lock<std::mutex> System::StallCPU() { 494void System::DetachDebugger() {
497 return impl->StallCPU(); 495 if (impl->debugger) {
496 impl->debugger->NotifyShutdown();
497 }
498}
499
500std::unique_lock<std::mutex> System::StallProcesses() {
501 return impl->StallProcesses();
498} 502}
499 503
500void System::UnstallCPU() { 504void System::UnstallProcesses() {
501 impl->UnstallCPU(); 505 impl->UnstallProcesses();
502} 506}
503 507
504void System::InitializeDebugger() { 508void System::InitializeDebugger() {
diff --git a/src/core/core.h b/src/core/core.h
index 94477206e..60efe4410 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -160,8 +160,11 @@ public:
160 /// Shutdown the emulated system. 160 /// Shutdown the emulated system.
161 void Shutdown(); 161 void Shutdown();
162 162
163 std::unique_lock<std::mutex> StallCPU(); 163 /// Forcibly detach the debugger if it is running.
164 void UnstallCPU(); 164 void DetachDebugger();
165
166 std::unique_lock<std::mutex> StallProcesses();
167 void UnstallProcesses();
165 168
166 /** 169 /**
167 * Initialize the debugger. 170 * Initialize the debugger.
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 29e7dba9b..140578069 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -6,7 +6,9 @@
6#include <string> 6#include <string>
7#include <tuple> 7#include <tuple>
8 8
9#include "common/logging/log.h"
9#include "common/microprofile.h" 10#include "common/microprofile.h"
11#include "common/thread.h"
10#include "core/core_timing.h" 12#include "core/core_timing.h"
11#include "core/core_timing_util.h" 13#include "core/core_timing_util.h"
12#include "core/hardware_properties.h" 14#include "core/hardware_properties.h"
@@ -41,11 +43,11 @@ CoreTiming::CoreTiming()
41 43
42CoreTiming::~CoreTiming() = default; 44CoreTiming::~CoreTiming() = default;
43 45
44void CoreTiming::ThreadEntry(CoreTiming& instance) { 46void CoreTiming::ThreadEntry(CoreTiming& instance, size_t id) {
45 constexpr char name[] = "yuzu:HostTiming"; 47 const std::string name = "yuzu:HostTiming_" + std::to_string(id);
46 MicroProfileOnThreadCreate(name); 48 MicroProfileOnThreadCreate(name.c_str());
47 Common::SetCurrentThreadName(name); 49 Common::SetCurrentThreadName(name.c_str());
48 Common::SetCurrentThreadPriority(Common::ThreadPriority::VeryHigh); 50 Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);
49 instance.on_thread_init(); 51 instance.on_thread_init();
50 instance.ThreadLoop(); 52 instance.ThreadLoop();
51 MicroProfileOnThreadExit(); 53 MicroProfileOnThreadExit();
@@ -59,68 +61,97 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
59 const auto empty_timed_callback = [](std::uintptr_t, std::chrono::nanoseconds) {}; 61 const auto empty_timed_callback = [](std::uintptr_t, std::chrono::nanoseconds) {};
60 ev_lost = CreateEvent("_lost_event", empty_timed_callback); 62 ev_lost = CreateEvent("_lost_event", empty_timed_callback);
61 if (is_multicore) { 63 if (is_multicore) {
62 timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); 64 const auto hardware_concurrency = std::thread::hardware_concurrency();
65 size_t id = 0;
66 worker_threads.emplace_back(ThreadEntry, std::ref(*this), id++);
67 if (hardware_concurrency > 8) {
68 worker_threads.emplace_back(ThreadEntry, std::ref(*this), id++);
69 }
63 } 70 }
64} 71}
65 72
66void CoreTiming::Shutdown() { 73void CoreTiming::Shutdown() {
67 paused = true; 74 is_paused = true;
68 shutting_down = true; 75 shutting_down = true;
69 pause_event.Set(); 76 std::atomic_thread_fence(std::memory_order_release);
70 event.Set(); 77
71 if (timer_thread) { 78 event_cv.notify_all();
72 timer_thread->join(); 79 wait_pause_cv.notify_all();
80 for (auto& thread : worker_threads) {
81 thread.join();
73 } 82 }
83 worker_threads.clear();
74 ClearPendingEvents(); 84 ClearPendingEvents();
75 timer_thread.reset();
76 has_started = false; 85 has_started = false;
77} 86}
78 87
79void CoreTiming::Pause(bool is_paused) { 88void CoreTiming::Pause(bool is_paused_) {
80 paused = is_paused; 89 std::unique_lock main_lock(event_mutex);
81 pause_event.Set(); 90 if (is_paused_ == paused_state.load(std::memory_order_relaxed)) {
91 return;
92 }
93 if (is_multicore) {
94 is_paused = is_paused_;
95 event_cv.notify_all();
96 if (!is_paused_) {
97 wait_pause_cv.notify_all();
98 }
99 }
100 paused_state.store(is_paused_, std::memory_order_relaxed);
82} 101}
83 102
84void CoreTiming::SyncPause(bool is_paused) { 103void CoreTiming::SyncPause(bool is_paused_) {
85 if (is_paused == paused && paused_set == paused) { 104 std::unique_lock main_lock(event_mutex);
105 if (is_paused_ == paused_state.load(std::memory_order_relaxed)) {
86 return; 106 return;
87 } 107 }
88 Pause(is_paused); 108
89 if (timer_thread) { 109 if (is_multicore) {
90 if (!is_paused) { 110 is_paused = is_paused_;
91 pause_event.Set(); 111 event_cv.notify_all();
112 if (!is_paused_) {
113 wait_pause_cv.notify_all();
114 }
115 }
116 paused_state.store(is_paused_, std::memory_order_relaxed);
117 if (is_multicore) {
118 if (is_paused_) {
119 wait_signal_cv.wait(main_lock, [this] { return pause_count == worker_threads.size(); });
120 } else {
121 wait_signal_cv.wait(main_lock, [this] { return pause_count == 0; });
92 } 122 }
93 event.Set();
94 while (paused_set != is_paused)
95 ;
96 } 123 }
97} 124}
98 125
99bool CoreTiming::IsRunning() const { 126bool CoreTiming::IsRunning() const {
100 return !paused_set; 127 return !paused_state.load(std::memory_order_acquire);
101} 128}
102 129
103bool CoreTiming::HasPendingEvents() const { 130bool CoreTiming::HasPendingEvents() const {
104 return !(wait_set && event_queue.empty()); 131 std::unique_lock main_lock(event_mutex);
132 return !event_queue.empty() || pending_events.load(std::memory_order_relaxed) != 0;
105} 133}
106 134
107void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, 135void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
108 const std::shared_ptr<EventType>& event_type, 136 const std::shared_ptr<EventType>& event_type,
109 std::uintptr_t user_data) { 137 std::uintptr_t user_data) {
110 {
111 std::scoped_lock scope{basic_lock};
112 const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count());
113 138
114 event_queue.emplace_back(Event{timeout, event_fifo_id++, user_data, event_type}); 139 std::unique_lock main_lock(event_mutex);
140 const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count());
141
142 event_queue.emplace_back(Event{timeout, event_fifo_id++, user_data, event_type});
143 pending_events.fetch_add(1, std::memory_order_relaxed);
115 144
116 std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); 145 std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
146
147 if (is_multicore) {
148 event_cv.notify_one();
117 } 149 }
118 event.Set();
119} 150}
120 151
121void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, 152void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
122 std::uintptr_t user_data) { 153 std::uintptr_t user_data) {
123 std::scoped_lock scope{basic_lock}; 154 std::unique_lock main_lock(event_mutex);
124 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { 155 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
125 return e.type.lock().get() == event_type.get() && e.user_data == user_data; 156 return e.type.lock().get() == event_type.get() && e.user_data == user_data;
126 }); 157 });
@@ -129,6 +160,7 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
129 if (itr != event_queue.end()) { 160 if (itr != event_queue.end()) {
130 event_queue.erase(itr, event_queue.end()); 161 event_queue.erase(itr, event_queue.end());
131 std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>()); 162 std::make_heap(event_queue.begin(), event_queue.end(), std::greater<>());
163 pending_events.fetch_sub(1, std::memory_order_relaxed);
132 } 164 }
133} 165}
134 166
@@ -168,11 +200,12 @@ u64 CoreTiming::GetClockTicks() const {
168} 200}
169 201
170void CoreTiming::ClearPendingEvents() { 202void CoreTiming::ClearPendingEvents() {
203 std::unique_lock main_lock(event_mutex);
171 event_queue.clear(); 204 event_queue.clear();
172} 205}
173 206
174void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { 207void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
175 std::scoped_lock lock{basic_lock}; 208 std::unique_lock main_lock(event_mutex);
176 209
177 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) { 210 const auto itr = std::remove_if(event_queue.begin(), event_queue.end(), [&](const Event& e) {
178 return e.type.lock().get() == event_type.get(); 211 return e.type.lock().get() == event_type.get();
@@ -186,21 +219,28 @@ void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
186} 219}
187 220
188std::optional<s64> CoreTiming::Advance() { 221std::optional<s64> CoreTiming::Advance() {
189 std::scoped_lock lock{advance_lock, basic_lock};
190 global_timer = GetGlobalTimeNs().count(); 222 global_timer = GetGlobalTimeNs().count();
191 223
224 std::unique_lock main_lock(event_mutex);
192 while (!event_queue.empty() && event_queue.front().time <= global_timer) { 225 while (!event_queue.empty() && event_queue.front().time <= global_timer) {
193 Event evt = std::move(event_queue.front()); 226 Event evt = std::move(event_queue.front());
194 std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>()); 227 std::pop_heap(event_queue.begin(), event_queue.end(), std::greater<>());
195 event_queue.pop_back(); 228 event_queue.pop_back();
196 basic_lock.unlock();
197 229
198 if (const auto event_type{evt.type.lock()}) { 230 if (const auto event_type{evt.type.lock()}) {
199 event_type->callback( 231 sequence_mutex.lock();
200 evt.user_data, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)}); 232 event_mutex.unlock();
233
234 event_type->guard.lock();
235 sequence_mutex.unlock();
236 const s64 delay = static_cast<s64>(GetGlobalTimeNs().count() - evt.time);
237 event_type->callback(evt.user_data, std::chrono::nanoseconds{delay});
238 event_type->guard.unlock();
239
240 event_mutex.lock();
241 pending_events.fetch_sub(1, std::memory_order_relaxed);
201 } 242 }
202 243
203 basic_lock.lock();
204 global_timer = GetGlobalTimeNs().count(); 244 global_timer = GetGlobalTimeNs().count();
205 } 245 }
206 246
@@ -213,26 +253,34 @@ std::optional<s64> CoreTiming::Advance() {
213} 253}
214 254
215void CoreTiming::ThreadLoop() { 255void CoreTiming::ThreadLoop() {
256 const auto predicate = [this] { return !event_queue.empty() || is_paused; };
216 has_started = true; 257 has_started = true;
217 while (!shutting_down) { 258 while (!shutting_down) {
218 while (!paused) { 259 while (!is_paused && !shutting_down) {
219 paused_set = false;
220 const auto next_time = Advance(); 260 const auto next_time = Advance();
221 if (next_time) { 261 if (next_time) {
222 if (*next_time > 0) { 262 if (*next_time > 0) {
223 std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); 263 std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time);
224 event.WaitFor(next_time_ns); 264 std::unique_lock main_lock(event_mutex);
265 event_cv.wait_for(main_lock, next_time_ns, predicate);
225 } 266 }
226 } else { 267 } else {
227 wait_set = true; 268 std::unique_lock main_lock(event_mutex);
228 event.Wait(); 269 event_cv.wait(main_lock, predicate);
229 } 270 }
230 wait_set = false;
231 } 271 }
232 paused_set = true; 272 std::unique_lock main_lock(event_mutex);
233 clock->Pause(true); 273 pause_count++;
234 pause_event.Wait(); 274 if (pause_count == worker_threads.size()) {
235 clock->Pause(false); 275 clock->Pause(true);
276 wait_signal_cv.notify_all();
277 }
278 wait_pause_cv.wait(main_lock, [this] { return !is_paused || shutting_down; });
279 pause_count--;
280 if (pause_count == 0) {
281 clock->Pause(false);
282 wait_signal_cv.notify_all();
283 }
236 } 284 }
237} 285}
238 286
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index d27773009..a86553e08 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -5,6 +5,7 @@
5 5
6#include <atomic> 6#include <atomic>
7#include <chrono> 7#include <chrono>
8#include <condition_variable>
8#include <functional> 9#include <functional>
9#include <memory> 10#include <memory>
10#include <mutex> 11#include <mutex>
@@ -14,7 +15,6 @@
14#include <vector> 15#include <vector>
15 16
16#include "common/common_types.h" 17#include "common/common_types.h"
17#include "common/thread.h"
18#include "common/wall_clock.h" 18#include "common/wall_clock.h"
19 19
20namespace Core::Timing { 20namespace Core::Timing {
@@ -32,6 +32,7 @@ struct EventType {
32 TimedCallback callback; 32 TimedCallback callback;
33 /// A pointer to the name of the event. 33 /// A pointer to the name of the event.
34 const std::string name; 34 const std::string name;
35 mutable std::mutex guard;
35}; 36};
36 37
37/** 38/**
@@ -131,7 +132,7 @@ private:
131 /// Clear all pending events. This should ONLY be done on exit. 132 /// Clear all pending events. This should ONLY be done on exit.
132 void ClearPendingEvents(); 133 void ClearPendingEvents();
133 134
134 static void ThreadEntry(CoreTiming& instance); 135 static void ThreadEntry(CoreTiming& instance, size_t id);
135 void ThreadLoop(); 136 void ThreadLoop();
136 137
137 std::unique_ptr<Common::WallClock> clock; 138 std::unique_ptr<Common::WallClock> clock;
@@ -144,21 +145,25 @@ private:
144 // accomodated by the standard adaptor class. 145 // accomodated by the standard adaptor class.
145 std::vector<Event> event_queue; 146 std::vector<Event> event_queue;
146 u64 event_fifo_id = 0; 147 u64 event_fifo_id = 0;
148 std::atomic<size_t> pending_events{};
147 149
148 std::shared_ptr<EventType> ev_lost; 150 std::shared_ptr<EventType> ev_lost;
149 Common::Event event{};
150 Common::Event pause_event{};
151 std::mutex basic_lock;
152 std::mutex advance_lock;
153 std::unique_ptr<std::thread> timer_thread;
154 std::atomic<bool> paused{};
155 std::atomic<bool> paused_set{};
156 std::atomic<bool> wait_set{};
157 std::atomic<bool> shutting_down{};
158 std::atomic<bool> has_started{}; 151 std::atomic<bool> has_started{};
159 std::function<void()> on_thread_init{}; 152 std::function<void()> on_thread_init{};
160 153
154 std::vector<std::thread> worker_threads;
155
156 std::condition_variable event_cv;
157 std::condition_variable wait_pause_cv;
158 std::condition_variable wait_signal_cv;
159 mutable std::mutex event_mutex;
160 mutable std::mutex sequence_mutex;
161
162 std::atomic<bool> paused_state{};
163 bool is_paused{};
164 bool shutting_down{};
161 bool is_multicore{}; 165 bool is_multicore{};
166 size_t pause_count{};
162 167
163 /// Cycle timing 168 /// Cycle timing
164 u64 ticks{}; 169 u64 ticks{};
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
index 09d9c5163..9fc78f033 100644
--- a/src/core/cpu_manager.cpp
+++ b/src/core/cpu_manager.cpp
@@ -21,23 +21,24 @@ CpuManager::~CpuManager() = default;
21 21
22void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, 22void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
23 std::size_t core) { 23 std::size_t core) {
24 cpu_manager.RunThread(stop_token, core); 24 cpu_manager.RunThread(core);
25} 25}
26 26
27void CpuManager::Initialize() { 27void CpuManager::Initialize() {
28 running_mode = true; 28 num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
29 if (is_multicore) { 29 gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1);
30 for (std::size_t core = 0; core < Core::Hardware::NUM_CPU_CORES; core++) { 30
31 core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); 31 for (std::size_t core = 0; core < num_cores; core++) {
32 } 32 core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
33 } else {
34 core_data[0].host_thread = std::jthread(ThreadStart, std::ref(*this), 0);
35 } 33 }
36} 34}
37 35
38void CpuManager::Shutdown() { 36void CpuManager::Shutdown() {
39 running_mode = false; 37 for (std::size_t core = 0; core < num_cores; core++) {
40 Pause(false); 38 if (core_data[core].host_thread.joinable()) {
39 core_data[core].host_thread.join();
40 }
41 }
41} 42}
42 43
43std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() { 44std::function<void(void*)> CpuManager::GetGuestThreadStartFunc() {
@@ -48,8 +49,8 @@ std::function<void(void*)> CpuManager::GetIdleThreadStartFunc() {
48 return IdleThreadFunction; 49 return IdleThreadFunction;
49} 50}
50 51
51std::function<void(void*)> CpuManager::GetSuspendThreadStartFunc() { 52std::function<void(void*)> CpuManager::GetShutdownThreadStartFunc() {
52 return SuspendThreadFunction; 53 return ShutdownThreadFunction;
53} 54}
54 55
55void CpuManager::GuestThreadFunction(void* cpu_manager_) { 56void CpuManager::GuestThreadFunction(void* cpu_manager_) {
@@ -79,17 +80,12 @@ void CpuManager::IdleThreadFunction(void* cpu_manager_) {
79 } 80 }
80} 81}
81 82
82void CpuManager::SuspendThreadFunction(void* cpu_manager_) { 83void CpuManager::ShutdownThreadFunction(void* cpu_manager) {
83 CpuManager* cpu_manager = static_cast<CpuManager*>(cpu_manager_); 84 static_cast<CpuManager*>(cpu_manager)->ShutdownThread();
84 if (cpu_manager->is_multicore) {
85 cpu_manager->MultiCoreRunSuspendThread();
86 } else {
87 cpu_manager->SingleCoreRunSuspendThread();
88 }
89} 85}
90 86
91void* CpuManager::GetStartFuncParamater() { 87void* CpuManager::GetStartFuncParameter() {
92 return static_cast<void*>(this); 88 return this;
93} 89}
94 90
95/////////////////////////////////////////////////////////////////////////////// 91///////////////////////////////////////////////////////////////////////////////
@@ -99,7 +95,7 @@ void* CpuManager::GetStartFuncParamater() {
99void CpuManager::MultiCoreRunGuestThread() { 95void CpuManager::MultiCoreRunGuestThread() {
100 auto& kernel = system.Kernel(); 96 auto& kernel = system.Kernel();
101 kernel.CurrentScheduler()->OnThreadStart(); 97 kernel.CurrentScheduler()->OnThreadStart();
102 auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); 98 auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread();
103 auto& host_context = thread->GetHostContext(); 99 auto& host_context = thread->GetHostContext();
104 host_context->SetRewindPoint(GuestRewindFunction, this); 100 host_context->SetRewindPoint(GuestRewindFunction, this);
105 MultiCoreRunGuestLoop(); 101 MultiCoreRunGuestLoop();
@@ -110,12 +106,10 @@ void CpuManager::MultiCoreRunGuestLoop() {
110 106
111 while (true) { 107 while (true) {
112 auto* physical_core = &kernel.CurrentPhysicalCore(); 108 auto* physical_core = &kernel.CurrentPhysicalCore();
113 system.EnterDynarmicProfile();
114 while (!physical_core->IsInterrupted()) { 109 while (!physical_core->IsInterrupted()) {
115 physical_core->Run(); 110 physical_core->Run();
116 physical_core = &kernel.CurrentPhysicalCore(); 111 physical_core = &kernel.CurrentPhysicalCore();
117 } 112 }
118 system.ExitDynarmicProfile();
119 { 113 {
120 Kernel::KScopedDisableDispatch dd(kernel); 114 Kernel::KScopedDisableDispatch dd(kernel);
121 physical_core->ArmInterface().ClearExclusiveState(); 115 physical_core->ArmInterface().ClearExclusiveState();
@@ -131,58 +125,6 @@ void CpuManager::MultiCoreRunIdleThread() {
131 } 125 }
132} 126}
133 127
134void CpuManager::MultiCoreRunSuspendThread() {
135 auto& kernel = system.Kernel();
136 kernel.CurrentScheduler()->OnThreadStart();
137 while (true) {
138 auto core = kernel.CurrentPhysicalCoreIndex();
139 auto& scheduler = *kernel.CurrentScheduler();
140 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
141 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
142 ASSERT(scheduler.ContextSwitchPending());
143 ASSERT(core == kernel.CurrentPhysicalCoreIndex());
144 scheduler.RescheduleCurrentCore();
145 }
146}
147
148void CpuManager::MultiCorePause(bool paused) {
149 if (!paused) {
150 bool all_not_barrier = false;
151 while (!all_not_barrier) {
152 all_not_barrier = true;
153 for (const auto& data : core_data) {
154 all_not_barrier &= !data.is_running.load() && data.initialized.load();
155 }
156 }
157 for (auto& data : core_data) {
158 data.enter_barrier->Set();
159 }
160 if (paused_state.load()) {
161 bool all_barrier = false;
162 while (!all_barrier) {
163 all_barrier = true;
164 for (const auto& data : core_data) {
165 all_barrier &= data.is_paused.load() && data.initialized.load();
166 }
167 }
168 for (auto& data : core_data) {
169 data.exit_barrier->Set();
170 }
171 }
172 } else {
173 /// Wait until all cores are paused.
174 bool all_barrier = false;
175 while (!all_barrier) {
176 all_barrier = true;
177 for (const auto& data : core_data) {
178 all_barrier &= data.is_paused.load() && data.initialized.load();
179 }
180 }
181 /// Don't release the barrier
182 }
183 paused_state = paused;
184}
185
186/////////////////////////////////////////////////////////////////////////////// 128///////////////////////////////////////////////////////////////////////////////
187/// SingleCore /// 129/// SingleCore ///
188/////////////////////////////////////////////////////////////////////////////// 130///////////////////////////////////////////////////////////////////////////////
@@ -190,7 +132,7 @@ void CpuManager::MultiCorePause(bool paused) {
190void CpuManager::SingleCoreRunGuestThread() { 132void CpuManager::SingleCoreRunGuestThread() {
191 auto& kernel = system.Kernel(); 133 auto& kernel = system.Kernel();
192 kernel.CurrentScheduler()->OnThreadStart(); 134 kernel.CurrentScheduler()->OnThreadStart();
193 auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); 135 auto* thread = kernel.CurrentScheduler()->GetSchedulerCurrentThread();
194 auto& host_context = thread->GetHostContext(); 136 auto& host_context = thread->GetHostContext();
195 host_context->SetRewindPoint(GuestRewindFunction, this); 137 host_context->SetRewindPoint(GuestRewindFunction, this);
196 SingleCoreRunGuestLoop(); 138 SingleCoreRunGuestLoop();
@@ -200,12 +142,10 @@ void CpuManager::SingleCoreRunGuestLoop() {
200 auto& kernel = system.Kernel(); 142 auto& kernel = system.Kernel();
201 while (true) { 143 while (true) {
202 auto* physical_core = &kernel.CurrentPhysicalCore(); 144 auto* physical_core = &kernel.CurrentPhysicalCore();
203 system.EnterDynarmicProfile();
204 if (!physical_core->IsInterrupted()) { 145 if (!physical_core->IsInterrupted()) {
205 physical_core->Run(); 146 physical_core->Run();
206 physical_core = &kernel.CurrentPhysicalCore(); 147 physical_core = &kernel.CurrentPhysicalCore();
207 } 148 }
208 system.ExitDynarmicProfile();
209 kernel.SetIsPhantomModeForSingleCore(true); 149 kernel.SetIsPhantomModeForSingleCore(true);
210 system.CoreTiming().Advance(); 150 system.CoreTiming().Advance();
211 kernel.SetIsPhantomModeForSingleCore(false); 151 kernel.SetIsPhantomModeForSingleCore(false);
@@ -228,25 +168,11 @@ void CpuManager::SingleCoreRunIdleThread() {
228 } 168 }
229} 169}
230 170
231void CpuManager::SingleCoreRunSuspendThread() {
232 auto& kernel = system.Kernel();
233 kernel.CurrentScheduler()->OnThreadStart();
234 while (true) {
235 auto core = kernel.GetCurrentHostThreadID();
236 auto& scheduler = *kernel.CurrentScheduler();
237 Kernel::KThread* current_thread = scheduler.GetCurrentThread();
238 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[0].host_context);
239 ASSERT(scheduler.ContextSwitchPending());
240 ASSERT(core == kernel.GetCurrentHostThreadID());
241 scheduler.RescheduleCurrentCore();
242 }
243}
244
245void CpuManager::PreemptSingleCore(bool from_running_enviroment) { 171void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
246 { 172 {
247 auto& kernel = system.Kernel(); 173 auto& kernel = system.Kernel();
248 auto& scheduler = kernel.Scheduler(current_core); 174 auto& scheduler = kernel.Scheduler(current_core);
249 Kernel::KThread* current_thread = scheduler.GetCurrentThread(); 175 Kernel::KThread* current_thread = scheduler.GetSchedulerCurrentThread();
250 if (idle_count >= 4 || from_running_enviroment) { 176 if (idle_count >= 4 || from_running_enviroment) {
251 if (!from_running_enviroment) { 177 if (!from_running_enviroment) {
252 system.CoreTiming().Idle(); 178 system.CoreTiming().Idle();
@@ -258,7 +184,7 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
258 } 184 }
259 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); 185 current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES);
260 system.CoreTiming().ResetTicks(); 186 system.CoreTiming().ResetTicks();
261 scheduler.Unload(scheduler.GetCurrentThread()); 187 scheduler.Unload(scheduler.GetSchedulerCurrentThread());
262 188
263 auto& next_scheduler = kernel.Scheduler(current_core); 189 auto& next_scheduler = kernel.Scheduler(current_core);
264 Common::Fiber::YieldTo(current_thread->GetHostContext(), *next_scheduler.ControlContext()); 190 Common::Fiber::YieldTo(current_thread->GetHostContext(), *next_scheduler.ControlContext());
@@ -267,47 +193,23 @@ void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
267 // May have changed scheduler 193 // May have changed scheduler
268 { 194 {
269 auto& scheduler = system.Kernel().Scheduler(current_core); 195 auto& scheduler = system.Kernel().Scheduler(current_core);
270 scheduler.Reload(scheduler.GetCurrentThread()); 196 scheduler.Reload(scheduler.GetSchedulerCurrentThread());
271 if (!scheduler.IsIdle()) { 197 if (!scheduler.IsIdle()) {
272 idle_count = 0; 198 idle_count = 0;
273 } 199 }
274 } 200 }
275} 201}
276 202
277void CpuManager::SingleCorePause(bool paused) { 203void CpuManager::ShutdownThread() {
278 if (!paused) { 204 auto& kernel = system.Kernel();
279 bool all_not_barrier = false; 205 auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0;
280 while (!all_not_barrier) { 206 auto* current_thread = kernel.GetCurrentEmuThread();
281 all_not_barrier = !core_data[0].is_running.load() && core_data[0].initialized.load();
282 }
283 core_data[0].enter_barrier->Set();
284 if (paused_state.load()) {
285 bool all_barrier = false;
286 while (!all_barrier) {
287 all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load();
288 }
289 core_data[0].exit_barrier->Set();
290 }
291 } else {
292 /// Wait until all cores are paused.
293 bool all_barrier = false;
294 while (!all_barrier) {
295 all_barrier = core_data[0].is_paused.load() && core_data[0].initialized.load();
296 }
297 /// Don't release the barrier
298 }
299 paused_state = paused;
300}
301 207
302void CpuManager::Pause(bool paused) { 208 Common::Fiber::YieldTo(current_thread->GetHostContext(), *core_data[core].host_context);
303 if (is_multicore) { 209 UNREACHABLE();
304 MultiCorePause(paused);
305 } else {
306 SingleCorePause(paused);
307 }
308} 210}
309 211
310void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) { 212void CpuManager::RunThread(std::size_t core) {
311 /// Initialization 213 /// Initialization
312 system.RegisterCoreThread(core); 214 system.RegisterCoreThread(core);
313 std::string name; 215 std::string name;
@@ -320,45 +222,24 @@ void CpuManager::RunThread(std::stop_token stop_token, std::size_t core) {
320 Common::SetCurrentThreadName(name.c_str()); 222 Common::SetCurrentThreadName(name.c_str());
321 Common::SetCurrentThreadPriority(Common::ThreadPriority::High); 223 Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
322 auto& data = core_data[core]; 224 auto& data = core_data[core];
323 data.enter_barrier = std::make_unique<Common::Event>();
324 data.exit_barrier = std::make_unique<Common::Event>();
325 data.host_context = Common::Fiber::ThreadToFiber(); 225 data.host_context = Common::Fiber::ThreadToFiber();
326 data.is_running = false;
327 data.initialized = true;
328 const bool sc_sync = !is_async_gpu && !is_multicore;
329 bool sc_sync_first_use = sc_sync;
330 226
331 // Cleanup 227 // Cleanup
332 SCOPE_EXIT({ 228 SCOPE_EXIT({
333 data.host_context->Exit(); 229 data.host_context->Exit();
334 data.enter_barrier.reset();
335 data.exit_barrier.reset();
336 data.initialized = false;
337 MicroProfileOnThreadExit(); 230 MicroProfileOnThreadExit();
338 }); 231 });
339 232
340 /// Running 233 // Running
341 while (running_mode) { 234 gpu_barrier->Sync();
342 data.is_running = false;
343 data.enter_barrier->Wait();
344 if (sc_sync_first_use) {
345 system.GPU().ObtainContext();
346 sc_sync_first_use = false;
347 }
348
349 // Emulation was stopped
350 if (stop_token.stop_requested()) {
351 return;
352 }
353 235
354 auto current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 236 if (!is_async_gpu && !is_multicore) {
355 data.is_running = true; 237 system.GPU().ObtainContext();
356 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
357 data.is_running = false;
358 data.is_paused = true;
359 data.exit_barrier->Wait();
360 data.is_paused = false;
361 } 238 }
239
240 auto* current_thread = system.Kernel().CurrentScheduler()->GetIdleThread();
241 Kernel::SetCurrentThread(system.Kernel(), current_thread);
242 Common::Fiber::YieldTo(data.host_context, *current_thread->GetHostContext());
362} 243}
363 244
364} // namespace Core 245} // namespace Core
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h
index aee352245..f0751fc58 100644
--- a/src/core/cpu_manager.h
+++ b/src/core/cpu_manager.h
@@ -43,15 +43,17 @@ public:
43 is_async_gpu = is_async; 43 is_async_gpu = is_async;
44 } 44 }
45 45
46 void OnGpuReady() {
47 gpu_barrier->Sync();
48 }
49
46 void Initialize(); 50 void Initialize();
47 void Shutdown(); 51 void Shutdown();
48 52
49 void Pause(bool paused);
50
51 static std::function<void(void*)> GetGuestThreadStartFunc(); 53 static std::function<void(void*)> GetGuestThreadStartFunc();
52 static std::function<void(void*)> GetIdleThreadStartFunc(); 54 static std::function<void(void*)> GetIdleThreadStartFunc();
53 static std::function<void(void*)> GetSuspendThreadStartFunc(); 55 static std::function<void(void*)> GetShutdownThreadStartFunc();
54 void* GetStartFuncParamater(); 56 void* GetStartFuncParameter();
55 57
56 void PreemptSingleCore(bool from_running_enviroment = true); 58 void PreemptSingleCore(bool from_running_enviroment = true);
57 59
@@ -63,43 +65,34 @@ private:
63 static void GuestThreadFunction(void* cpu_manager); 65 static void GuestThreadFunction(void* cpu_manager);
64 static void GuestRewindFunction(void* cpu_manager); 66 static void GuestRewindFunction(void* cpu_manager);
65 static void IdleThreadFunction(void* cpu_manager); 67 static void IdleThreadFunction(void* cpu_manager);
66 static void SuspendThreadFunction(void* cpu_manager); 68 static void ShutdownThreadFunction(void* cpu_manager);
67 69
68 void MultiCoreRunGuestThread(); 70 void MultiCoreRunGuestThread();
69 void MultiCoreRunGuestLoop(); 71 void MultiCoreRunGuestLoop();
70 void MultiCoreRunIdleThread(); 72 void MultiCoreRunIdleThread();
71 void MultiCoreRunSuspendThread();
72 void MultiCorePause(bool paused);
73 73
74 void SingleCoreRunGuestThread(); 74 void SingleCoreRunGuestThread();
75 void SingleCoreRunGuestLoop(); 75 void SingleCoreRunGuestLoop();
76 void SingleCoreRunIdleThread(); 76 void SingleCoreRunIdleThread();
77 void SingleCoreRunSuspendThread();
78 void SingleCorePause(bool paused);
79 77
80 static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core); 78 static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
81 79
82 void RunThread(std::stop_token stop_token, std::size_t core); 80 void ShutdownThread();
81 void RunThread(std::size_t core);
83 82
84 struct CoreData { 83 struct CoreData {
85 std::shared_ptr<Common::Fiber> host_context; 84 std::shared_ptr<Common::Fiber> host_context;
86 std::unique_ptr<Common::Event> enter_barrier;
87 std::unique_ptr<Common::Event> exit_barrier;
88 std::atomic<bool> is_running;
89 std::atomic<bool> is_paused;
90 std::atomic<bool> initialized;
91 std::jthread host_thread; 85 std::jthread host_thread;
92 }; 86 };
93 87
94 std::atomic<bool> running_mode{}; 88 std::unique_ptr<Common::Barrier> gpu_barrier{};
95 std::atomic<bool> paused_state{};
96
97 std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{}; 89 std::array<CoreData, Core::Hardware::NUM_CPU_CORES> core_data{};
98 90
99 bool is_async_gpu{}; 91 bool is_async_gpu{};
100 bool is_multicore{}; 92 bool is_multicore{};
101 std::atomic<std::size_t> current_core{}; 93 std::atomic<std::size_t> current_core{};
102 std::size_t idle_count{}; 94 std::size_t idle_count{};
95 std::size_t num_cores{};
103 static constexpr std::size_t max_cycle_runs = 5; 96 static constexpr std::size_t max_cycle_runs = 5;
104 97
105 System& system; 98 System& system;
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index e3c4f80eb..443323390 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -140,7 +140,6 @@ u64 GetSignatureTypeDataSize(SignatureType type) {
140 return 0x3C; 140 return 0x3C;
141 } 141 }
142 UNREACHABLE(); 142 UNREACHABLE();
143 return 0;
144} 143}
145 144
146u64 GetSignatureTypePaddingSize(SignatureType type) { 145u64 GetSignatureTypePaddingSize(SignatureType type) {
@@ -155,7 +154,6 @@ u64 GetSignatureTypePaddingSize(SignatureType type) {
155 return 0x40; 154 return 0x40;
156 } 155 }
157 UNREACHABLE(); 156 UNREACHABLE();
158 return 0;
159} 157}
160 158
161SignatureType Ticket::GetSignatureType() const { 159SignatureType Ticket::GetSignatureType() const {
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index 8d64990ed..ac64d2f9d 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -42,6 +42,18 @@ static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer) {
42 return received_data; 42 return received_data;
43} 43}
44 44
45enum class SignalType {
46 Stopped,
47 Watchpoint,
48 ShuttingDown,
49};
50
51struct SignalInfo {
52 SignalType type;
53 Kernel::KThread* thread;
54 const Kernel::DebugWatchpoint* watchpoint;
55};
56
45namespace Core { 57namespace Core {
46 58
47class DebuggerImpl : public DebuggerBackend { 59class DebuggerImpl : public DebuggerBackend {
@@ -56,17 +68,23 @@ public:
56 ShutdownServer(); 68 ShutdownServer();
57 } 69 }
58 70
59 bool NotifyThreadStopped(Kernel::KThread* thread) { 71 bool SignalDebugger(SignalInfo signal_info) {
60 std::scoped_lock lk{connection_lock}; 72 {
73 std::scoped_lock lk{connection_lock};
74
75 if (stopped) {
76 // Do not notify the debugger about another event.
77 // It should be ignored.
78 return false;
79 }
61 80
62 if (stopped) { 81 // Set up the state.
63 // Do not notify the debugger about another event. 82 stopped = true;
64 // It should be ignored. 83 info = signal_info;
65 return false;
66 } 84 }
67 stopped = true;
68 85
69 boost::asio::write(signal_pipe, boost::asio::buffer(&thread, sizeof(thread))); 86 // Write a single byte into the pipe to wake up the debug interface.
87 boost::asio::write(signal_pipe, boost::asio::buffer(&stopped, sizeof(stopped)));
70 return true; 88 return true;
71 } 89 }
72 90
@@ -96,7 +114,7 @@ private:
96 connection_thread = std::jthread([&, port](std::stop_token stop_token) { 114 connection_thread = std::jthread([&, port](std::stop_token stop_token) {
97 try { 115 try {
98 // Initialize the listening socket and accept a new client. 116 // Initialize the listening socket and accept a new client.
99 tcp::endpoint endpoint{boost::asio::ip::address_v4::loopback(), port}; 117 tcp::endpoint endpoint{boost::asio::ip::address_v4::any(), port};
100 tcp::acceptor acceptor{io_context, endpoint}; 118 tcp::acceptor acceptor{io_context, endpoint};
101 119
102 acceptor.async_accept(client_socket, [](const auto&) {}); 120 acceptor.async_accept(client_socket, [](const auto&) {});
@@ -124,12 +142,9 @@ private:
124 Common::SetCurrentThreadName("yuzu:Debugger"); 142 Common::SetCurrentThreadName("yuzu:Debugger");
125 143
126 // Set up the client signals for new data. 144 // Set up the client signals for new data.
127 AsyncReceiveInto(signal_pipe, active_thread, [&](auto d) { PipeData(d); }); 145 AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); });
128 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); }); 146 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); });
129 147
130 // Stop the emulated CPU.
131 AllCoreStop();
132
133 // Set the active thread. 148 // Set the active thread.
134 UpdateActiveThread(); 149 UpdateActiveThread();
135 150
@@ -142,9 +157,33 @@ private:
142 } 157 }
143 158
144 void PipeData(std::span<const u8> data) { 159 void PipeData(std::span<const u8> data) {
145 AllCoreStop(); 160 switch (info.type) {
146 UpdateActiveThread(); 161 case SignalType::Stopped:
147 frontend->Stopped(active_thread); 162 case SignalType::Watchpoint:
163 // Stop emulation.
164 PauseEmulation();
165
166 // Notify the client.
167 active_thread = info.thread;
168 UpdateActiveThread();
169
170 if (info.type == SignalType::Watchpoint) {
171 frontend->Watchpoint(active_thread, *info.watchpoint);
172 } else {
173 frontend->Stopped(active_thread);
174 }
175
176 break;
177 case SignalType::ShuttingDown:
178 frontend->ShuttingDown();
179
180 // Wait for emulation to shut down gracefully now.
181 signal_pipe.close();
182 client_socket.shutdown(boost::asio::socket_base::shutdown_both);
183 LOG_INFO(Debug_GDBStub, "Shut down server");
184
185 break;
186 }
148 } 187 }
149 188
150 void ClientData(std::span<const u8> data) { 189 void ClientData(std::span<const u8> data) {
@@ -156,32 +195,29 @@ private:
156 std::scoped_lock lk{connection_lock}; 195 std::scoped_lock lk{connection_lock};
157 stopped = true; 196 stopped = true;
158 } 197 }
159 AllCoreStop(); 198 PauseEmulation();
160 UpdateActiveThread(); 199 UpdateActiveThread();
161 frontend->Stopped(active_thread); 200 frontend->Stopped(active_thread);
162 break; 201 break;
163 } 202 }
164 case DebuggerAction::Continue: 203 case DebuggerAction::Continue:
165 active_thread->SetStepState(Kernel::StepState::NotStepping); 204 MarkResumed([&] { ResumeEmulation(); });
166 ResumeInactiveThreads();
167 AllCoreResume();
168 break; 205 break;
169 case DebuggerAction::StepThreadUnlocked: 206 case DebuggerAction::StepThreadUnlocked:
170 active_thread->SetStepState(Kernel::StepState::StepPending); 207 MarkResumed([&] {
171 ResumeInactiveThreads(); 208 active_thread->SetStepState(Kernel::StepState::StepPending);
172 AllCoreResume(); 209 active_thread->Resume(Kernel::SuspendType::Debug);
210 ResumeEmulation(active_thread);
211 });
173 break; 212 break;
174 case DebuggerAction::StepThreadLocked: 213 case DebuggerAction::StepThreadLocked: {
175 active_thread->SetStepState(Kernel::StepState::StepPending); 214 MarkResumed([&] {
176 SuspendInactiveThreads(); 215 active_thread->SetStepState(Kernel::StepState::StepPending);
177 AllCoreResume(); 216 active_thread->Resume(Kernel::SuspendType::Debug);
217 });
178 break; 218 break;
219 }
179 case DebuggerAction::ShutdownEmulation: { 220 case DebuggerAction::ShutdownEmulation: {
180 // Suspend all threads and release any locks held
181 active_thread->RequestSuspend(Kernel::SuspendType::Debug);
182 SuspendInactiveThreads();
183 AllCoreResume();
184
185 // Spawn another thread that will exit after shutdown, 221 // Spawn another thread that will exit after shutdown,
186 // to avoid a deadlock 222 // to avoid a deadlock
187 Core::System* system_ref{&system}; 223 Core::System* system_ref{&system};
@@ -193,33 +229,33 @@ private:
193 } 229 }
194 } 230 }
195 231
196 void AllCoreStop() { 232 void PauseEmulation() {
197 if (!suspend) { 233 // Put all threads to sleep on next scheduler round.
198 suspend = system.StallCPU(); 234 for (auto* thread : ThreadList()) {
235 thread->RequestSuspend(Kernel::SuspendType::Debug);
199 } 236 }
200 }
201 237
202 void AllCoreResume() { 238 // Signal an interrupt so that scheduler will fire.
203 stopped = false; 239 system.Kernel().InterruptAllPhysicalCores();
204 system.UnstallCPU();
205 suspend.reset();
206 } 240 }
207 241
208 void SuspendInactiveThreads() { 242 void ResumeEmulation(Kernel::KThread* except = nullptr) {
243 // Wake up all threads.
209 for (auto* thread : ThreadList()) { 244 for (auto* thread : ThreadList()) {
210 if (thread != active_thread) { 245 if (thread == except) {
211 thread->RequestSuspend(Kernel::SuspendType::Debug); 246 continue;
212 } 247 }
248
249 thread->SetStepState(Kernel::StepState::NotStepping);
250 thread->Resume(Kernel::SuspendType::Debug);
213 } 251 }
214 } 252 }
215 253
216 void ResumeInactiveThreads() { 254 template <typename Callback>
217 for (auto* thread : ThreadList()) { 255 void MarkResumed(Callback&& cb) {
218 if (thread != active_thread) { 256 std::scoped_lock lk{connection_lock};
219 thread->Resume(Kernel::SuspendType::Debug); 257 stopped = false;
220 thread->SetStepState(Kernel::StepState::NotStepping); 258 cb();
221 }
222 }
223 } 259 }
224 260
225 void UpdateActiveThread() { 261 void UpdateActiveThread() {
@@ -227,8 +263,6 @@ private:
227 if (std::find(threads.begin(), threads.end(), active_thread) == threads.end()) { 263 if (std::find(threads.begin(), threads.end(), active_thread) == threads.end()) {
228 active_thread = threads[0]; 264 active_thread = threads[0];
229 } 265 }
230 active_thread->Resume(Kernel::SuspendType::Debug);
231 active_thread->SetStepState(Kernel::StepState::NotStepping);
232 } 266 }
233 267
234 const std::vector<Kernel::KThread*>& ThreadList() { 268 const std::vector<Kernel::KThread*>& ThreadList() {
@@ -244,9 +278,10 @@ private:
244 boost::asio::io_context io_context; 278 boost::asio::io_context io_context;
245 boost::process::async_pipe signal_pipe; 279 boost::process::async_pipe signal_pipe;
246 boost::asio::ip::tcp::socket client_socket; 280 boost::asio::ip::tcp::socket client_socket;
247 std::optional<std::unique_lock<std::mutex>> suspend;
248 281
282 SignalInfo info;
249 Kernel::KThread* active_thread; 283 Kernel::KThread* active_thread;
284 bool pipe_data;
250 bool stopped; 285 bool stopped;
251 286
252 std::array<u8, 4096> client_data; 287 std::array<u8, 4096> client_data;
@@ -263,7 +298,18 @@ Debugger::Debugger(Core::System& system, u16 port) {
263Debugger::~Debugger() = default; 298Debugger::~Debugger() = default;
264 299
265bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) { 300bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) {
266 return impl && impl->NotifyThreadStopped(thread); 301 return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread, nullptr});
302}
303
304bool Debugger::NotifyThreadWatchpoint(Kernel::KThread* thread,
305 const Kernel::DebugWatchpoint& watch) {
306 return impl && impl->SignalDebugger(SignalInfo{SignalType::Watchpoint, thread, &watch});
307}
308
309void Debugger::NotifyShutdown() {
310 if (impl) {
311 impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr, nullptr});
312 }
267} 313}
268 314
269} // namespace Core 315} // namespace Core
diff --git a/src/core/debugger/debugger.h b/src/core/debugger/debugger.h
index ea36c6ab2..b2f503376 100644
--- a/src/core/debugger/debugger.h
+++ b/src/core/debugger/debugger.h
@@ -9,7 +9,8 @@
9 9
10namespace Kernel { 10namespace Kernel {
11class KThread; 11class KThread;
12} 12struct DebugWatchpoint;
13} // namespace Kernel
13 14
14namespace Core { 15namespace Core {
15class System; 16class System;
@@ -35,6 +36,16 @@ public:
35 */ 36 */
36 bool NotifyThreadStopped(Kernel::KThread* thread); 37 bool NotifyThreadStopped(Kernel::KThread* thread);
37 38
39 /**
40 * Notify the debugger that a shutdown is being performed now and disconnect.
41 */
42 void NotifyShutdown();
43
44 /*
45 * Notify the debugger that the given thread has stopped due to hitting a watchpoint.
46 */
47 bool NotifyThreadWatchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint& watch);
48
38private: 49private:
39 std::unique_ptr<DebuggerImpl> impl; 50 std::unique_ptr<DebuggerImpl> impl;
40}; 51};
diff --git a/src/core/debugger/debugger_interface.h b/src/core/debugger/debugger_interface.h
index 35ba0bc61..5b31edc43 100644
--- a/src/core/debugger/debugger_interface.h
+++ b/src/core/debugger/debugger_interface.h
@@ -11,7 +11,8 @@
11 11
12namespace Kernel { 12namespace Kernel {
13class KThread; 13class KThread;
14} 14struct DebugWatchpoint;
15} // namespace Kernel
15 16
16namespace Core { 17namespace Core {
17 18
@@ -67,6 +68,16 @@ public:
67 virtual void Stopped(Kernel::KThread* thread) = 0; 68 virtual void Stopped(Kernel::KThread* thread) = 0;
68 69
69 /** 70 /**
71 * Called when emulation is shutting down.
72 */
73 virtual void ShuttingDown() = 0;
74
75 /*
76 * Called when emulation has stopped on a watchpoint.
77 */
78 virtual void Watchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint& watch) = 0;
79
80 /**
70 * Called when new data is asynchronously received on the client socket. 81 * Called when new data is asynchronously received on the client socket.
71 * A list of actions to perform is returned. 82 * A list of actions to perform is returned.
72 */ 83 */
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index f52d78829..884229c77 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -106,10 +106,29 @@ GDBStub::~GDBStub() = default;
106 106
107void GDBStub::Connected() {} 107void GDBStub::Connected() {}
108 108
109void GDBStub::ShuttingDown() {}
110
109void GDBStub::Stopped(Kernel::KThread* thread) { 111void GDBStub::Stopped(Kernel::KThread* thread) {
110 SendReply(arch->ThreadStatus(thread, GDB_STUB_SIGTRAP)); 112 SendReply(arch->ThreadStatus(thread, GDB_STUB_SIGTRAP));
111} 113}
112 114
115void GDBStub::Watchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint& watch) {
116 const auto status{arch->ThreadStatus(thread, GDB_STUB_SIGTRAP)};
117
118 switch (watch.type) {
119 case Kernel::DebugWatchpointType::Read:
120 SendReply(fmt::format("{}rwatch:{:x};", status, watch.start_address));
121 break;
122 case Kernel::DebugWatchpointType::Write:
123 SendReply(fmt::format("{}watch:{:x};", status, watch.start_address));
124 break;
125 case Kernel::DebugWatchpointType::ReadOrWrite:
126 default:
127 SendReply(fmt::format("{}awatch:{:x};", status, watch.start_address));
128 break;
129 }
130}
131
113std::vector<DebuggerAction> GDBStub::ClientData(std::span<const u8> data) { 132std::vector<DebuggerAction> GDBStub::ClientData(std::span<const u8> data) {
114 std::vector<DebuggerAction> actions; 133 std::vector<DebuggerAction> actions;
115 current_command.insert(current_command.end(), data.begin(), data.end()); 134 current_command.insert(current_command.end(), data.begin(), data.end());
@@ -233,6 +252,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
233 const auto sep{std::find(command.begin(), command.end(), '=') - command.begin() + 1}; 252 const auto sep{std::find(command.begin(), command.end(), '=') - command.begin() + 1};
234 const size_t reg{static_cast<size_t>(strtoll(command.data(), nullptr, 16))}; 253 const size_t reg{static_cast<size_t>(strtoll(command.data(), nullptr, 16))};
235 arch->RegWrite(backend.GetActiveThread(), reg, std::string_view(command).substr(sep)); 254 arch->RegWrite(backend.GetActiveThread(), reg, std::string_view(command).substr(sep));
255 SendReply(GDB_STUB_REPLY_OK);
236 break; 256 break;
237 } 257 }
238 case 'm': { 258 case 'm': {
@@ -276,41 +296,121 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
276 case 'c': 296 case 'c':
277 actions.push_back(DebuggerAction::Continue); 297 actions.push_back(DebuggerAction::Continue);
278 break; 298 break;
279 case 'Z': { 299 case 'Z':
280 const auto addr_sep{std::find(command.begin(), command.end(), ',') - command.begin() + 1}; 300 HandleBreakpointInsert(command);
281 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 301 break;
302 case 'z':
303 HandleBreakpointRemove(command);
304 break;
305 default:
306 SendReply(GDB_STUB_REPLY_EMPTY);
307 break;
308 }
309}
282 310
283 if (system.Memory().IsValidVirtualAddress(addr)) { 311enum class BreakpointType {
284 replaced_instructions[addr] = system.Memory().Read32(addr); 312 Software = 0,
285 system.Memory().Write32(addr, arch->BreakpointInstruction()); 313 Hardware = 1,
286 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32)); 314 WriteWatch = 2,
315 ReadWatch = 3,
316 AccessWatch = 4,
317};
318
319void GDBStub::HandleBreakpointInsert(std::string_view command) {
320 const auto type{static_cast<BreakpointType>(strtoll(command.data(), nullptr, 16))};
321 const auto addr_sep{std::find(command.begin(), command.end(), ',') - command.begin() + 1};
322 const auto size_sep{std::find(command.begin() + addr_sep, command.end(), ',') -
323 command.begin() + 1};
324 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
325 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
326
327 if (!system.Memory().IsValidVirtualAddressRange(addr, size)) {
328 SendReply(GDB_STUB_REPLY_ERR);
329 return;
330 }
287 331
288 SendReply(GDB_STUB_REPLY_OK); 332 bool success{};
289 } else { 333
290 SendReply(GDB_STUB_REPLY_ERR); 334 switch (type) {
291 } 335 case BreakpointType::Software:
336 replaced_instructions[addr] = system.Memory().Read32(addr);
337 system.Memory().Write32(addr, arch->BreakpointInstruction());
338 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
339 success = true;
340 break;
341 case BreakpointType::WriteWatch:
342 success = system.CurrentProcess()->InsertWatchpoint(system, addr, size,
343 Kernel::DebugWatchpointType::Write);
344 break;
345 case BreakpointType::ReadWatch:
346 success = system.CurrentProcess()->InsertWatchpoint(system, addr, size,
347 Kernel::DebugWatchpointType::Read);
348 break;
349 case BreakpointType::AccessWatch:
350 success = system.CurrentProcess()->InsertWatchpoint(
351 system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
292 break; 352 break;
353 case BreakpointType::Hardware:
354 default:
355 SendReply(GDB_STUB_REPLY_EMPTY);
356 return;
357 }
358
359 if (success) {
360 SendReply(GDB_STUB_REPLY_OK);
361 } else {
362 SendReply(GDB_STUB_REPLY_ERR);
293 } 363 }
294 case 'z': { 364}
295 const auto addr_sep{std::find(command.begin(), command.end(), ',') - command.begin() + 1}; 365
296 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))}; 366void GDBStub::HandleBreakpointRemove(std::string_view command) {
367 const auto type{static_cast<BreakpointType>(strtoll(command.data(), nullptr, 16))};
368 const auto addr_sep{std::find(command.begin(), command.end(), ',') - command.begin() + 1};
369 const auto size_sep{std::find(command.begin() + addr_sep, command.end(), ',') -
370 command.begin() + 1};
371 const size_t addr{static_cast<size_t>(strtoll(command.data() + addr_sep, nullptr, 16))};
372 const size_t size{static_cast<size_t>(strtoll(command.data() + size_sep, nullptr, 16))};
373
374 if (!system.Memory().IsValidVirtualAddressRange(addr, size)) {
375 SendReply(GDB_STUB_REPLY_ERR);
376 return;
377 }
378
379 bool success{};
297 380
381 switch (type) {
382 case BreakpointType::Software: {
298 const auto orig_insn{replaced_instructions.find(addr)}; 383 const auto orig_insn{replaced_instructions.find(addr)};
299 if (system.Memory().IsValidVirtualAddress(addr) && 384 if (orig_insn != replaced_instructions.end()) {
300 orig_insn != replaced_instructions.end()) {
301 system.Memory().Write32(addr, orig_insn->second); 385 system.Memory().Write32(addr, orig_insn->second);
302 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32)); 386 system.InvalidateCpuInstructionCacheRange(addr, sizeof(u32));
303 replaced_instructions.erase(addr); 387 replaced_instructions.erase(addr);
304 388 success = true;
305 SendReply(GDB_STUB_REPLY_OK);
306 } else {
307 SendReply(GDB_STUB_REPLY_ERR);
308 } 389 }
309 break; 390 break;
310 } 391 }
392 case BreakpointType::WriteWatch:
393 success = system.CurrentProcess()->RemoveWatchpoint(system, addr, size,
394 Kernel::DebugWatchpointType::Write);
395 break;
396 case BreakpointType::ReadWatch:
397 success = system.CurrentProcess()->RemoveWatchpoint(system, addr, size,
398 Kernel::DebugWatchpointType::Read);
399 break;
400 case BreakpointType::AccessWatch:
401 success = system.CurrentProcess()->RemoveWatchpoint(
402 system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
403 break;
404 case BreakpointType::Hardware:
311 default: 405 default:
312 SendReply(GDB_STUB_REPLY_EMPTY); 406 SendReply(GDB_STUB_REPLY_EMPTY);
313 break; 407 return;
408 }
409
410 if (success) {
411 SendReply(GDB_STUB_REPLY_OK);
412 } else {
413 SendReply(GDB_STUB_REPLY_ERR);
314 } 414 }
315} 415}
316 416
diff --git a/src/core/debugger/gdbstub.h b/src/core/debugger/gdbstub.h
index 1bb638187..0b0f56e4b 100644
--- a/src/core/debugger/gdbstub.h
+++ b/src/core/debugger/gdbstub.h
@@ -23,6 +23,8 @@ public:
23 23
24 void Connected() override; 24 void Connected() override;
25 void Stopped(Kernel::KThread* thread) override; 25 void Stopped(Kernel::KThread* thread) override;
26 void ShuttingDown() override;
27 void Watchpoint(Kernel::KThread* thread, const Kernel::DebugWatchpoint& watch) override;
26 std::vector<DebuggerAction> ClientData(std::span<const u8> data) override; 28 std::vector<DebuggerAction> ClientData(std::span<const u8> data) override;
27 29
28private: 30private:
@@ -30,6 +32,8 @@ private:
30 void ExecuteCommand(std::string_view packet, std::vector<DebuggerAction>& actions); 32 void ExecuteCommand(std::string_view packet, std::vector<DebuggerAction>& actions);
31 void HandleVCont(std::string_view command, std::vector<DebuggerAction>& actions); 33 void HandleVCont(std::string_view command, std::vector<DebuggerAction>& actions);
32 void HandleQuery(std::string_view command); 34 void HandleQuery(std::string_view command);
35 void HandleBreakpointInsert(std::string_view command);
36 void HandleBreakpointRemove(std::string_view command);
33 std::vector<char>::const_iterator CommandEnd() const; 37 std::vector<char>::const_iterator CommandEnd() const;
34 std::optional<std::string> DetachCommand(); 38 std::optional<std::string> DetachCommand();
35 Kernel::KThread* GetThreadByID(u64 thread_id); 39 Kernel::KThread* GetThreadByID(u64 thread_id);
diff --git a/src/core/debugger/gdbstub_arch.cpp b/src/core/debugger/gdbstub_arch.cpp
index 750c353b9..4bef09bd7 100644
--- a/src/core/debugger/gdbstub_arch.cpp
+++ b/src/core/debugger/gdbstub_arch.cpp
@@ -191,8 +191,10 @@ std::string GDBStubA64::RegRead(const Kernel::KThread* thread, size_t id) const
191 const auto& gprs{context.cpu_registers}; 191 const auto& gprs{context.cpu_registers};
192 const auto& fprs{context.vector_registers}; 192 const auto& fprs{context.vector_registers};
193 193
194 if (id <= SP_REGISTER) { 194 if (id < SP_REGISTER) {
195 return ValueToHex(gprs[id]); 195 return ValueToHex(gprs[id]);
196 } else if (id == SP_REGISTER) {
197 return ValueToHex(context.sp);
196 } else if (id == PC_REGISTER) { 198 } else if (id == PC_REGISTER) {
197 return ValueToHex(context.pc); 199 return ValueToHex(context.pc);
198 } else if (id == PSTATE_REGISTER) { 200 } else if (id == PSTATE_REGISTER) {
@@ -215,8 +217,10 @@ void GDBStubA64::RegWrite(Kernel::KThread* thread, size_t id, std::string_view v
215 217
216 auto& context{thread->GetContext64()}; 218 auto& context{thread->GetContext64()};
217 219
218 if (id <= SP_REGISTER) { 220 if (id < SP_REGISTER) {
219 context.cpu_registers[id] = HexToValue<u64>(value); 221 context.cpu_registers[id] = HexToValue<u64>(value);
222 } else if (id == SP_REGISTER) {
223 context.sp = HexToValue<u64>(value);
220 } else if (id == PC_REGISTER) { 224 } else if (id == PC_REGISTER) {
221 context.pc = HexToValue<u64>(value); 225 context.pc = HexToValue<u64>(value);
222 } else if (id == PSTATE_REGISTER) { 226 } else if (id == PSTATE_REGISTER) {
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 93f784418..78e56bbbd 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -419,7 +419,7 @@ std::optional<Core::Crypto::Key128> NCA::GetKeyAreaKey(NCASectionCryptoType type
419 Core::Crypto::Mode::ECB); 419 Core::Crypto::Mode::ECB);
420 cipher.Transcode(key_area.data(), key_area.size(), key_area.data(), Core::Crypto::Op::Decrypt); 420 cipher.Transcode(key_area.data(), key_area.size(), key_area.data(), Core::Crypto::Op::Decrypt);
421 421
422 Core::Crypto::Key128 out; 422 Core::Crypto::Key128 out{};
423 if (type == NCASectionCryptoType::XTS) { 423 if (type == NCASectionCryptoType::XTS) {
424 std::copy(key_area.begin(), key_area.begin() + 0x10, out.begin()); 424 std::copy(key_area.begin(), key_area.begin() + 0x10, out.begin());
425 } else if (type == NCASectionCryptoType::CTR || type == NCASectionCryptoType::BKTR) { 425 } else if (type == NCASectionCryptoType::CTR || type == NCASectionCryptoType::BKTR) {
diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h
index 1a920b45d..ff15b3e23 100644
--- a/src/core/file_sys/errors.h
+++ b/src/core/file_sys/errors.h
@@ -8,14 +8,14 @@
8 8
9namespace FileSys { 9namespace FileSys {
10 10
11constexpr ResultCode ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1}; 11constexpr Result ERROR_PATH_NOT_FOUND{ErrorModule::FS, 1};
12constexpr ResultCode ERROR_PATH_ALREADY_EXISTS{ErrorModule::FS, 2}; 12constexpr Result ERROR_PATH_ALREADY_EXISTS{ErrorModule::FS, 2};
13constexpr ResultCode ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002}; 13constexpr Result ERROR_ENTITY_NOT_FOUND{ErrorModule::FS, 1002};
14constexpr ResultCode ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001}; 14constexpr Result ERROR_SD_CARD_NOT_FOUND{ErrorModule::FS, 2001};
15constexpr ResultCode ERROR_OUT_OF_BOUNDS{ErrorModule::FS, 3005}; 15constexpr Result ERROR_OUT_OF_BOUNDS{ErrorModule::FS, 3005};
16constexpr ResultCode ERROR_FAILED_MOUNT_ARCHIVE{ErrorModule::FS, 3223}; 16constexpr Result ERROR_FAILED_MOUNT_ARCHIVE{ErrorModule::FS, 3223};
17constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::FS, 6001}; 17constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::FS, 6001};
18constexpr ResultCode ERROR_INVALID_OFFSET{ErrorModule::FS, 6061}; 18constexpr Result ERROR_INVALID_OFFSET{ErrorModule::FS, 6061};
19constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::FS, 6062}; 19constexpr Result ERROR_INVALID_SIZE{ErrorModule::FS, 6062};
20 20
21} // namespace FileSys 21} // namespace FileSys
diff --git a/src/core/file_sys/nca_patch.cpp b/src/core/file_sys/nca_patch.cpp
index d4c0a974a..2735d053b 100644
--- a/src/core/file_sys/nca_patch.cpp
+++ b/src/core/file_sys/nca_patch.cpp
@@ -50,7 +50,7 @@ std::pair<std::size_t, std::size_t> SearchBucketEntry(u64 offset, const BlockTyp
50 low = mid + 1; 50 low = mid + 1;
51 } 51 }
52 } 52 }
53 UNREACHABLE_MSG("Offset could not be found in BKTR block."); 53 ASSERT_MSG(false, "Offset could not be found in BKTR block.");
54 return {0, 0}; 54 return {0, 0};
55} 55}
56} // Anonymous namespace 56} // Anonymous namespace
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 2eaac73ef..878d832c2 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -108,7 +108,7 @@ ContentRecordType GetCRTypeFromNCAType(NCAContentType type) {
108 // TODO(DarkLordZach): Peek at NCA contents to differentiate Manual and Legal. 108 // TODO(DarkLordZach): Peek at NCA contents to differentiate Manual and Legal.
109 return ContentRecordType::HtmlDocument; 109 return ContentRecordType::HtmlDocument;
110 default: 110 default:
111 UNREACHABLE_MSG("Invalid NCAContentType={:02X}", type); 111 ASSERT_MSG(false, "Invalid NCAContentType={:02X}", type);
112 return ContentRecordType{}; 112 return ContentRecordType{};
113 } 113 }
114} 114}
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index e42d7c9f6..cc0076238 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -144,7 +144,7 @@ VirtualFile RealVfsFilesystem::MoveFile(std::string_view old_path_, std::string_
144 LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", new_path); 144 LOG_ERROR(Service_FS, "Failed to open path {} in order to re-cache it", new_path);
145 } 145 }
146 } else { 146 } else {
147 UNREACHABLE(); 147 ASSERT(false);
148 return nullptr; 148 return nullptr;
149 } 149 }
150 150
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 0ff2a338e..6c230f619 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -65,7 +65,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
65 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); 65 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
66 controller->Connect(true); 66 controller->Connect(true);
67 } else { 67 } else {
68 UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); 68 ASSERT_MSG(false, "Unable to add a new controller based on the given parameters!");
69 } 69 }
70 } 70 }
71 71
diff --git a/src/core/frontend/applets/error.cpp b/src/core/frontend/applets/error.cpp
index f2ec4b10e..f8b961098 100644
--- a/src/core/frontend/applets/error.cpp
+++ b/src/core/frontend/applets/error.cpp
@@ -8,12 +8,12 @@ namespace Core::Frontend {
8 8
9ErrorApplet::~ErrorApplet() = default; 9ErrorApplet::~ErrorApplet() = default;
10 10
11void DefaultErrorApplet::ShowError(ResultCode error, std::function<void()> finished) const { 11void DefaultErrorApplet::ShowError(Result error, std::function<void()> finished) const {
12 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})", 12 LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
13 error.module.Value(), error.description.Value(), error.raw); 13 error.module.Value(), error.description.Value(), error.raw);
14} 14}
15 15
16void DefaultErrorApplet::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, 16void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
17 std::function<void()> finished) const { 17 std::function<void()> finished) const {
18 LOG_CRITICAL( 18 LOG_CRITICAL(
19 Service_Fatal, 19 Service_Fatal,
@@ -21,7 +21,7 @@ void DefaultErrorApplet::ShowErrorWithTimestamp(ResultCode error, std::chrono::s
21 error.module.Value(), error.description.Value(), error.raw, time.count()); 21 error.module.Value(), error.description.Value(), error.raw, time.count());
22} 22}
23 23
24void DefaultErrorApplet::ShowCustomErrorText(ResultCode error, std::string main_text, 24void DefaultErrorApplet::ShowCustomErrorText(Result error, std::string main_text,
25 std::string detail_text, 25 std::string detail_text,
26 std::function<void()> finished) const { 26 std::function<void()> finished) const {
27 LOG_CRITICAL(Service_Fatal, 27 LOG_CRITICAL(Service_Fatal,
diff --git a/src/core/frontend/applets/error.h b/src/core/frontend/applets/error.h
index 8a1134561..f378f8805 100644
--- a/src/core/frontend/applets/error.h
+++ b/src/core/frontend/applets/error.h
@@ -14,22 +14,22 @@ class ErrorApplet {
14public: 14public:
15 virtual ~ErrorApplet(); 15 virtual ~ErrorApplet();
16 16
17 virtual void ShowError(ResultCode error, std::function<void()> finished) const = 0; 17 virtual void ShowError(Result error, std::function<void()> finished) const = 0;
18 18
19 virtual void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, 19 virtual void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
20 std::function<void()> finished) const = 0; 20 std::function<void()> finished) const = 0;
21 21
22 virtual void ShowCustomErrorText(ResultCode error, std::string dialog_text, 22 virtual void ShowCustomErrorText(Result error, std::string dialog_text,
23 std::string fullscreen_text, 23 std::string fullscreen_text,
24 std::function<void()> finished) const = 0; 24 std::function<void()> finished) const = 0;
25}; 25};
26 26
27class DefaultErrorApplet final : public ErrorApplet { 27class DefaultErrorApplet final : public ErrorApplet {
28public: 28public:
29 void ShowError(ResultCode error, std::function<void()> finished) const override; 29 void ShowError(Result error, std::function<void()> finished) const override;
30 void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, 30 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
31 std::function<void()> finished) const override; 31 std::function<void()> finished) const override;
32 void ShowCustomErrorText(ResultCode error, std::string main_text, std::string detail_text, 32 void ShowCustomErrorText(Result error, std::string main_text, std::string detail_text,
33 std::function<void()> finished) const override; 33 std::function<void()> finished) const override;
34}; 34};
35 35
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h
index aac362c51..13cbdb734 100644
--- a/src/core/hardware_properties.h
+++ b/src/core/hardware_properties.h
@@ -25,6 +25,9 @@ constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{
25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 25 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
26}; 26};
27 27
28// Cortex-A57 supports 4 memory watchpoints
29constexpr u64 NUM_WATCHPOINTS = 4;
30
28} // namespace Hardware 31} // namespace Hardware
29 32
30} // namespace Core 33} // namespace Core
diff --git a/src/core/hid/hid_core.cpp b/src/core/hid/hid_core.cpp
index 7eed52593..7d6373414 100644
--- a/src/core/hid/hid_core.cpp
+++ b/src/core/hid/hid_core.cpp
@@ -48,7 +48,7 @@ EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type) {
48 return handheld.get(); 48 return handheld.get();
49 case NpadIdType::Invalid: 49 case NpadIdType::Invalid:
50 default: 50 default:
51 UNREACHABLE_MSG("Invalid NpadIdType={}", npad_id_type); 51 ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type);
52 return nullptr; 52 return nullptr;
53 } 53 }
54} 54}
@@ -77,7 +77,7 @@ const EmulatedController* HIDCore::GetEmulatedController(NpadIdType npad_id_type
77 return handheld.get(); 77 return handheld.get();
78 case NpadIdType::Invalid: 78 case NpadIdType::Invalid:
79 default: 79 default:
80 UNREACHABLE_MSG("Invalid NpadIdType={}", npad_id_type); 80 ASSERT_MSG(false, "Invalid NpadIdType={}", npad_id_type);
81 return nullptr; 81 return nullptr;
82 } 82 }
83} 83}
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 3c4e45fcd..004bb2005 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -19,7 +19,7 @@
19 19
20namespace IPC { 20namespace IPC {
21 21
22constexpr ResultCode ERR_REMOTE_PROCESS_DEAD{ErrorModule::HIPC, 301}; 22constexpr Result ERR_REMOTE_PROCESS_DEAD{ErrorModule::HIPC, 301};
23 23
24class RequestHelperBase { 24class RequestHelperBase {
25protected: 25protected:
@@ -176,7 +176,7 @@ public:
176 void PushImpl(float value); 176 void PushImpl(float value);
177 void PushImpl(double value); 177 void PushImpl(double value);
178 void PushImpl(bool value); 178 void PushImpl(bool value);
179 void PushImpl(ResultCode value); 179 void PushImpl(Result value);
180 180
181 template <typename T> 181 template <typename T>
182 void Push(T value) { 182 void Push(T value) {
@@ -251,7 +251,7 @@ void ResponseBuilder::PushRaw(const T& value) {
251 index += (sizeof(T) + 3) / 4; // round up to word length 251 index += (sizeof(T) + 3) / 4; // round up to word length
252} 252}
253 253
254inline void ResponseBuilder::PushImpl(ResultCode value) { 254inline void ResponseBuilder::PushImpl(Result value) {
255 // Result codes are actually 64-bit in the IPC buffer, but only the high part is discarded. 255 // Result codes are actually 64-bit in the IPC buffer, but only the high part is discarded.
256 Push(value.raw); 256 Push(value.raw);
257 Push<u32>(0); 257 Push<u32>(0);
@@ -481,8 +481,8 @@ inline bool RequestParser::Pop() {
481} 481}
482 482
483template <> 483template <>
484inline ResultCode RequestParser::Pop() { 484inline Result RequestParser::Pop() {
485 return ResultCode{Pop<u32>()}; 485 return Result{Pop<u32>()};
486} 486}
487 487
488template <typename T> 488template <typename T>
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 4650d25b0..45135a07f 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -188,8 +188,8 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
188 rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. 188 rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
189} 189}
190 190
191ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, 191Result HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table,
192 u32_le* src_cmdbuf) { 192 u32_le* src_cmdbuf) {
193 ParseCommandBuffer(handle_table, src_cmdbuf, true); 193 ParseCommandBuffer(handle_table, src_cmdbuf, true);
194 194
195 if (command_header->IsCloseCommand()) { 195 if (command_header->IsCloseCommand()) {
@@ -202,7 +202,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTab
202 return ResultSuccess; 202 return ResultSuccess;
203} 203}
204 204
205ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) { 205Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) {
206 auto current_offset = handles_offset; 206 auto current_offset = handles_offset;
207 auto& owner_process = *requesting_thread.GetOwnerProcess(); 207 auto& owner_process = *requesting_thread.GetOwnerProcess();
208 auto& handle_table = owner_process.GetHandleTable(); 208 auto& handle_table = owner_process.GetHandleTable();
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index a427cbc93..d3abeee85 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -18,7 +18,7 @@
18#include "core/hle/ipc.h" 18#include "core/hle/ipc.h"
19#include "core/hle/kernel/svc_common.h" 19#include "core/hle/kernel/svc_common.h"
20 20
21union ResultCode; 21union Result;
22 22
23namespace Core::Memory { 23namespace Core::Memory {
24class Memory; 24class Memory;
@@ -71,10 +71,10 @@ public:
71 * it should be used to differentiate which client (As in ClientSession) we're answering to. 71 * it should be used to differentiate which client (As in ClientSession) we're answering to.
72 * TODO(Subv): Use a wrapper structure to hold all the information relevant to 72 * TODO(Subv): Use a wrapper structure to hold all the information relevant to
73 * this request (ServerSession, Originator thread, Translated command buffer, etc). 73 * this request (ServerSession, Originator thread, Translated command buffer, etc).
74 * @returns ResultCode the result code of the translate operation. 74 * @returns Result the result code of the translate operation.
75 */ 75 */
76 virtual ResultCode HandleSyncRequest(Kernel::KServerSession& session, 76 virtual Result HandleSyncRequest(Kernel::KServerSession& session,
77 Kernel::HLERequestContext& context) = 0; 77 Kernel::HLERequestContext& context) = 0;
78 78
79 /** 79 /**
80 * Signals that a client has just connected to this HLE handler and keeps the 80 * Signals that a client has just connected to this HLE handler and keeps the
@@ -141,7 +141,7 @@ public:
141 if (index < DomainHandlerCount()) { 141 if (index < DomainHandlerCount()) {
142 domain_handlers[index] = nullptr; 142 domain_handlers[index] = nullptr;
143 } else { 143 } else {
144 UNREACHABLE_MSG("Unexpected handler index {}", index); 144 ASSERT_MSG(false, "Unexpected handler index {}", index);
145 } 145 }
146 } 146 }
147 147
@@ -212,11 +212,10 @@ public:
212 } 212 }
213 213
214 /// Populates this context with data from the requesting process/thread. 214 /// Populates this context with data from the requesting process/thread.
215 ResultCode PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, 215 Result PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf);
216 u32_le* src_cmdbuf);
217 216
218 /// Writes data from this context back to the requesting process/thread. 217 /// Writes data from this context back to the requesting process/thread.
219 ResultCode WriteToOutgoingCommandBuffer(KThread& requesting_thread); 218 Result WriteToOutgoingCommandBuffer(KThread& requesting_thread);
220 219
221 u32_le GetHipcCommand() const { 220 u32_le GetHipcCommand() const {
222 return command; 221 return command;
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index 34a8be052..9b6b284d0 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -244,7 +244,7 @@ void InitializeSlabHeaps(Core::System& system, KMemoryLayout& memory_layout) {
244 FOREACH_SLAB_TYPE(INITIALIZE_SLAB_HEAP) 244 FOREACH_SLAB_TYPE(INITIALIZE_SLAB_HEAP)
245 // If we somehow get an invalid type, abort. 245 // If we somehow get an invalid type, abort.
246 default: 246 default:
247 UNREACHABLE_MSG("Unknown slab type: {}", slab_types[i]); 247 ASSERT_MSG(false, "Unknown slab type: {}", slab_types[i]);
248 } 248 }
249 249
250 // If we've hit the end of a gap, free it. 250 // If we've hit the end of a gap, free it.
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index 04cf86d52..f85b11557 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -90,8 +90,7 @@ public:
90 explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel_, KAddressArbiter::ThreadTree* t) 90 explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel_, KAddressArbiter::ThreadTree* t)
91 : KThreadQueue(kernel_), m_tree(t) {} 91 : KThreadQueue(kernel_), m_tree(t) {}
92 92
93 void CancelWait(KThread* waiting_thread, ResultCode wait_result, 93 void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override {
94 bool cancel_timer_task) override {
95 // If the thread is waiting on an address arbiter, remove it from the tree. 94 // If the thread is waiting on an address arbiter, remove it from the tree.
96 if (waiting_thread->IsWaitingForAddressArbiter()) { 95 if (waiting_thread->IsWaitingForAddressArbiter()) {
97 m_tree->erase(m_tree->iterator_to(*waiting_thread)); 96 m_tree->erase(m_tree->iterator_to(*waiting_thread));
@@ -108,7 +107,7 @@ private:
108 107
109} // namespace 108} // namespace
110 109
111ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { 110Result KAddressArbiter::Signal(VAddr addr, s32 count) {
112 // Perform signaling. 111 // Perform signaling.
113 s32 num_waiters{}; 112 s32 num_waiters{};
114 { 113 {
@@ -131,7 +130,7 @@ ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) {
131 return ResultSuccess; 130 return ResultSuccess;
132} 131}
133 132
134ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 count) { 133Result KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 count) {
135 // Perform signaling. 134 // Perform signaling.
136 s32 num_waiters{}; 135 s32 num_waiters{};
137 { 136 {
@@ -164,7 +163,7 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
164 return ResultSuccess; 163 return ResultSuccess;
165} 164}
166 165
167ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 value, s32 count) { 166Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 value, s32 count) {
168 // Perform signaling. 167 // Perform signaling.
169 s32 num_waiters{}; 168 s32 num_waiters{};
170 { 169 {
@@ -232,9 +231,9 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
232 return ResultSuccess; 231 return ResultSuccess;
233} 232}
234 233
235ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { 234Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) {
236 // Prepare to wait. 235 // Prepare to wait.
237 KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); 236 KThread* cur_thread = GetCurrentThreadPointer(kernel);
238 ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); 237 ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree));
239 238
240 { 239 {
@@ -285,9 +284,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
285 return cur_thread->GetWaitResult(); 284 return cur_thread->GetWaitResult();
286} 285}
287 286
288ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { 287Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
289 // Prepare to wait. 288 // Prepare to wait.
290 KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); 289 KThread* cur_thread = GetCurrentThreadPointer(kernel);
291 ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); 290 ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree));
292 291
293 { 292 {
diff --git a/src/core/hle/kernel/k_address_arbiter.h b/src/core/hle/kernel/k_address_arbiter.h
index e46e0d848..e4085ae22 100644
--- a/src/core/hle/kernel/k_address_arbiter.h
+++ b/src/core/hle/kernel/k_address_arbiter.h
@@ -8,7 +8,7 @@
8#include "core/hle/kernel/k_condition_variable.h" 8#include "core/hle/kernel/k_condition_variable.h"
9#include "core/hle/kernel/svc_types.h" 9#include "core/hle/kernel/svc_types.h"
10 10
11union ResultCode; 11union Result;
12 12
13namespace Core { 13namespace Core {
14class System; 14class System;
@@ -25,8 +25,7 @@ public:
25 explicit KAddressArbiter(Core::System& system_); 25 explicit KAddressArbiter(Core::System& system_);
26 ~KAddressArbiter(); 26 ~KAddressArbiter();
27 27
28 [[nodiscard]] ResultCode SignalToAddress(VAddr addr, Svc::SignalType type, s32 value, 28 [[nodiscard]] Result SignalToAddress(VAddr addr, Svc::SignalType type, s32 value, s32 count) {
29 s32 count) {
30 switch (type) { 29 switch (type) {
31 case Svc::SignalType::Signal: 30 case Svc::SignalType::Signal:
32 return Signal(addr, count); 31 return Signal(addr, count);
@@ -35,12 +34,12 @@ public:
35 case Svc::SignalType::SignalAndModifyByWaitingCountIfEqual: 34 case Svc::SignalType::SignalAndModifyByWaitingCountIfEqual:
36 return SignalAndModifyByWaitingCountIfEqual(addr, value, count); 35 return SignalAndModifyByWaitingCountIfEqual(addr, value, count);
37 } 36 }
38 UNREACHABLE(); 37 ASSERT(false);
39 return ResultUnknown; 38 return ResultUnknown;
40 } 39 }
41 40
42 [[nodiscard]] ResultCode WaitForAddress(VAddr addr, Svc::ArbitrationType type, s32 value, 41 [[nodiscard]] Result WaitForAddress(VAddr addr, Svc::ArbitrationType type, s32 value,
43 s64 timeout) { 42 s64 timeout) {
44 switch (type) { 43 switch (type) {
45 case Svc::ArbitrationType::WaitIfLessThan: 44 case Svc::ArbitrationType::WaitIfLessThan:
46 return WaitIfLessThan(addr, value, false, timeout); 45 return WaitIfLessThan(addr, value, false, timeout);
@@ -49,16 +48,16 @@ public:
49 case Svc::ArbitrationType::WaitIfEqual: 48 case Svc::ArbitrationType::WaitIfEqual:
50 return WaitIfEqual(addr, value, timeout); 49 return WaitIfEqual(addr, value, timeout);
51 } 50 }
52 UNREACHABLE(); 51 ASSERT(false);
53 return ResultUnknown; 52 return ResultUnknown;
54 } 53 }
55 54
56private: 55private:
57 [[nodiscard]] ResultCode Signal(VAddr addr, s32 count); 56 [[nodiscard]] Result Signal(VAddr addr, s32 count);
58 [[nodiscard]] ResultCode SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 count); 57 [[nodiscard]] Result SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 count);
59 [[nodiscard]] ResultCode SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 value, s32 count); 58 [[nodiscard]] Result SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 value, s32 count);
60 [[nodiscard]] ResultCode WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout); 59 [[nodiscard]] Result WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout);
61 [[nodiscard]] ResultCode WaitIfEqual(VAddr addr, s32 value, s64 timeout); 60 [[nodiscard]] Result WaitIfEqual(VAddr addr, s32 value, s64 timeout);
62 61
63 ThreadTree thread_tree; 62 ThreadTree thread_tree;
64 63
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp
index bc37cadda..3e612a207 100644
--- a/src/core/hle/kernel/k_address_space_info.cpp
+++ b/src/core/hle/kernel/k_address_space_info.cpp
@@ -84,7 +84,7 @@ u64 KAddressSpaceInfo::GetAddressSpaceStart(std::size_t width, Type type) {
84 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index])); 84 ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index]));
85 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].address; 85 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].address;
86 } 86 }
87 UNREACHABLE(); 87 ASSERT(false);
88 return 0; 88 return 0;
89} 89}
90 90
@@ -101,7 +101,7 @@ std::size_t KAddressSpaceInfo::GetAddressSpaceSize(std::size_t width, Type type)
101 ASSERT(IsAllowed39BitType(type)); 101 ASSERT(IsAllowed39BitType(type));
102 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].size; 102 return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].size;
103 } 103 }
104 UNREACHABLE(); 104 ASSERT(false);
105 return 0; 105 return 0;
106} 106}
107 107
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h
index ea47fc600..2827763d5 100644
--- a/src/core/hle/kernel/k_auto_object.h
+++ b/src/core/hle/kernel/k_auto_object.h
@@ -18,7 +18,7 @@ namespace Kernel {
18class KernelCore; 18class KernelCore;
19class KProcess; 19class KProcess;
20 20
21#define KERNEL_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \ 21#define KERNEL_AUTOOBJECT_TRAITS_IMPL(CLASS, BASE_CLASS, ATTRIBUTE) \
22 \ 22 \
23private: \ 23private: \
24 friend class ::Kernel::KClassTokenGenerator; \ 24 friend class ::Kernel::KClassTokenGenerator; \
@@ -40,16 +40,19 @@ public:
40 static constexpr const char* GetStaticTypeName() { \ 40 static constexpr const char* GetStaticTypeName() { \
41 return TypeName; \ 41 return TypeName; \
42 } \ 42 } \
43 virtual TypeObj GetTypeObj() const { \ 43 virtual TypeObj GetTypeObj() ATTRIBUTE { \
44 return GetStaticTypeObj(); \ 44 return GetStaticTypeObj(); \
45 } \ 45 } \
46 virtual const char* GetTypeName() const { \ 46 virtual const char* GetTypeName() ATTRIBUTE { \
47 return GetStaticTypeName(); \ 47 return GetStaticTypeName(); \
48 } \ 48 } \
49 \ 49 \
50private: \ 50private: \
51 constexpr bool operator!=(const TypeObj& rhs) 51 constexpr bool operator!=(const TypeObj& rhs)
52 52
53#define KERNEL_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \
54 KERNEL_AUTOOBJECT_TRAITS_IMPL(CLASS, BASE_CLASS, const override)
55
53class KAutoObject { 56class KAutoObject {
54protected: 57protected:
55 class TypeObj { 58 class TypeObj {
@@ -82,7 +85,7 @@ protected:
82 }; 85 };
83 86
84private: 87private:
85 KERNEL_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject); 88 KERNEL_AUTOOBJECT_TRAITS_IMPL(KAutoObject, KAutoObject, const);
86 89
87public: 90public:
88 explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) { 91 explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) {
diff --git a/src/core/hle/kernel/k_class_token.h b/src/core/hle/kernel/k_class_token.h
index be9e3c357..c9001ae3d 100644
--- a/src/core/hle/kernel/k_class_token.h
+++ b/src/core/hle/kernel/k_class_token.h
@@ -49,6 +49,7 @@ private:
49 } 49 }
50 } 50 }
51 } 51 }
52 UNREACHABLE();
52 }(); 53 }();
53 54
54 template <typename T> 55 template <typename T>
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp
index ef168fe87..d63e77d15 100644
--- a/src/core/hle/kernel/k_client_port.cpp
+++ b/src/core/hle/kernel/k_client_port.cpp
@@ -59,8 +59,8 @@ bool KClientPort::IsSignaled() const {
59 return num_sessions < max_sessions; 59 return num_sessions < max_sessions;
60} 60}
61 61
62ResultCode KClientPort::CreateSession(KClientSession** out, 62Result KClientPort::CreateSession(KClientSession** out,
63 std::shared_ptr<SessionRequestManager> session_manager) { 63 std::shared_ptr<SessionRequestManager> session_manager) {
64 // Reserve a new session from the resource limit. 64 // Reserve a new session from the resource limit.
65 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), 65 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
66 LimitableResource::Sessions); 66 LimitableResource::Sessions);
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index 54bb05e20..ef8583efc 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -53,8 +53,8 @@ public:
53 void Destroy() override; 53 void Destroy() override;
54 bool IsSignaled() const override; 54 bool IsSignaled() const override;
55 55
56 ResultCode CreateSession(KClientSession** out, 56 Result CreateSession(KClientSession** out,
57 std::shared_ptr<SessionRequestManager> session_manager = nullptr); 57 std::shared_ptr<SessionRequestManager> session_manager = nullptr);
58 58
59private: 59private:
60 std::atomic<s32> num_sessions{}; 60 std::atomic<s32> num_sessions{};
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp
index 731af079c..b2a887b14 100644
--- a/src/core/hle/kernel/k_client_session.cpp
+++ b/src/core/hle/kernel/k_client_session.cpp
@@ -21,8 +21,8 @@ void KClientSession::Destroy() {
21 21
22void KClientSession::OnServerClosed() {} 22void KClientSession::OnServerClosed() {}
23 23
24ResultCode KClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, 24Result KClientSession::SendSyncRequest(KThread* thread, Core::Memory::Memory& memory,
25 Core::Timing::CoreTiming& core_timing) { 25 Core::Timing::CoreTiming& core_timing) {
26 // Signal the server session that new data is available 26 // Signal the server session that new data is available
27 return parent->GetServerSession().HandleSyncRequest(thread, memory, core_timing); 27 return parent->GetServerSession().HandleSyncRequest(thread, memory, core_timing);
28} 28}
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h
index 7a7ec8450..0c750d756 100644
--- a/src/core/hle/kernel/k_client_session.h
+++ b/src/core/hle/kernel/k_client_session.h
@@ -9,7 +9,7 @@
9#include "core/hle/kernel/slab_helpers.h" 9#include "core/hle/kernel/slab_helpers.h"
10#include "core/hle/result.h" 10#include "core/hle/result.h"
11 11
12union ResultCode; 12union Result;
13 13
14namespace Core::Memory { 14namespace Core::Memory {
15class Memory; 15class Memory;
@@ -46,8 +46,8 @@ public:
46 return parent; 46 return parent;
47 } 47 }
48 48
49 ResultCode SendSyncRequest(KThread* thread, Core::Memory::Memory& memory, 49 Result SendSyncRequest(KThread* thread, Core::Memory::Memory& memory,
50 Core::Timing::CoreTiming& core_timing); 50 Core::Timing::CoreTiming& core_timing);
51 51
52 void OnServerClosed(); 52 void OnServerClosed();
53 53
diff --git a/src/core/hle/kernel/k_code_memory.cpp b/src/core/hle/kernel/k_code_memory.cpp
index fd3cbfd94..da57ceb21 100644
--- a/src/core/hle/kernel/k_code_memory.cpp
+++ b/src/core/hle/kernel/k_code_memory.cpp
@@ -7,7 +7,7 @@
7#include "core/hle/kernel/k_code_memory.h" 7#include "core/hle/kernel/k_code_memory.h"
8#include "core/hle/kernel/k_light_lock.h" 8#include "core/hle/kernel/k_light_lock.h"
9#include "core/hle/kernel/k_memory_block.h" 9#include "core/hle/kernel/k_memory_block.h"
10#include "core/hle/kernel/k_page_linked_list.h" 10#include "core/hle/kernel/k_page_group.h"
11#include "core/hle/kernel/k_page_table.h" 11#include "core/hle/kernel/k_page_table.h"
12#include "core/hle/kernel/k_process.h" 12#include "core/hle/kernel/k_process.h"
13#include "core/hle/kernel/slab_helpers.h" 13#include "core/hle/kernel/slab_helpers.h"
@@ -19,7 +19,7 @@ namespace Kernel {
19KCodeMemory::KCodeMemory(KernelCore& kernel_) 19KCodeMemory::KCodeMemory(KernelCore& kernel_)
20 : KAutoObjectWithSlabHeapAndContainer{kernel_}, m_lock(kernel_) {} 20 : KAutoObjectWithSlabHeapAndContainer{kernel_}, m_lock(kernel_) {}
21 21
22ResultCode KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) { 22Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) {
23 // Set members. 23 // Set members.
24 m_owner = kernel.CurrentProcess(); 24 m_owner = kernel.CurrentProcess();
25 25
@@ -27,23 +27,18 @@ ResultCode KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr
27 auto& page_table = m_owner->PageTable(); 27 auto& page_table = m_owner->PageTable();
28 28
29 // Construct the page group. 29 // Construct the page group.
30 m_page_group = 30 m_page_group = {};
31 KPageLinkedList(page_table.GetPhysicalAddr(addr), Common::DivideUp(size, PageSize));
32 31
33 // Lock the memory. 32 // Lock the memory.
34 R_TRY(page_table.LockForCodeMemory(addr, size)) 33 R_TRY(page_table.LockForCodeMemory(&m_page_group, addr, size))
35 34
36 // Clear the memory. 35 // Clear the memory.
37 // 36 for (const auto& block : m_page_group.Nodes()) {
38 // FIXME: this ends up clobbering address ranges outside the scope of the mapping within 37 std::memset(device_memory.GetPointer(block.GetAddress()), 0xFF, block.GetSize());
39 // guest memory, and is not specifically required if the guest program is correctly 38 }
40 // written, so disable until this is further investigated.
41 //
42 // for (const auto& block : m_page_group.Nodes()) {
43 // std::memset(device_memory.GetPointer(block.GetAddress()), 0xFF, block.GetSize());
44 // }
45 39
46 // Set remaining tracking members. 40 // Set remaining tracking members.
41 m_owner->Open();
47 m_address = addr; 42 m_address = addr;
48 m_is_initialized = true; 43 m_is_initialized = true;
49 m_is_owner_mapped = false; 44 m_is_owner_mapped = false;
@@ -57,11 +52,17 @@ void KCodeMemory::Finalize() {
57 // Unlock. 52 // Unlock.
58 if (!m_is_mapped && !m_is_owner_mapped) { 53 if (!m_is_mapped && !m_is_owner_mapped) {
59 const size_t size = m_page_group.GetNumPages() * PageSize; 54 const size_t size = m_page_group.GetNumPages() * PageSize;
60 m_owner->PageTable().UnlockForCodeMemory(m_address, size); 55 m_owner->PageTable().UnlockForCodeMemory(m_address, size, m_page_group);
61 } 56 }
57
58 // Close the page group.
59 m_page_group = {};
60
61 // Close our reference to our owner.
62 m_owner->Close();
62} 63}
63 64
64ResultCode KCodeMemory::Map(VAddr address, size_t size) { 65Result KCodeMemory::Map(VAddr address, size_t size) {
65 // Validate the size. 66 // Validate the size.
66 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); 67 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
67 68
@@ -81,7 +82,7 @@ ResultCode KCodeMemory::Map(VAddr address, size_t size) {
81 return ResultSuccess; 82 return ResultSuccess;
82} 83}
83 84
84ResultCode KCodeMemory::Unmap(VAddr address, size_t size) { 85Result KCodeMemory::Unmap(VAddr address, size_t size) {
85 // Validate the size. 86 // Validate the size.
86 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); 87 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
87 88
@@ -98,7 +99,7 @@ ResultCode KCodeMemory::Unmap(VAddr address, size_t size) {
98 return ResultSuccess; 99 return ResultSuccess;
99} 100}
100 101
101ResultCode KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) { 102Result KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm) {
102 // Validate the size. 103 // Validate the size.
103 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); 104 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
104 105
@@ -118,7 +119,8 @@ ResultCode KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermis
118 k_perm = KMemoryPermission::UserReadExecute; 119 k_perm = KMemoryPermission::UserReadExecute;
119 break; 120 break;
120 default: 121 default:
121 break; 122 // Already validated by ControlCodeMemory svc
123 UNREACHABLE();
122 } 124 }
123 125
124 // Map the memory. 126 // Map the memory.
@@ -131,7 +133,7 @@ ResultCode KCodeMemory::MapToOwner(VAddr address, size_t size, Svc::MemoryPermis
131 return ResultSuccess; 133 return ResultSuccess;
132} 134}
133 135
134ResultCode KCodeMemory::UnmapFromOwner(VAddr address, size_t size) { 136Result KCodeMemory::UnmapFromOwner(VAddr address, size_t size) {
135 // Validate the size. 137 // Validate the size.
136 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize); 138 R_UNLESS(m_page_group.GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
137 139
diff --git a/src/core/hle/kernel/k_code_memory.h b/src/core/hle/kernel/k_code_memory.h
index ab06b6f29..2410f74a3 100644
--- a/src/core/hle/kernel/k_code_memory.h
+++ b/src/core/hle/kernel/k_code_memory.h
@@ -7,7 +7,7 @@
7#include "core/device_memory.h" 7#include "core/device_memory.h"
8#include "core/hle/kernel/k_auto_object.h" 8#include "core/hle/kernel/k_auto_object.h"
9#include "core/hle/kernel/k_light_lock.h" 9#include "core/hle/kernel/k_light_lock.h"
10#include "core/hle/kernel/k_page_linked_list.h" 10#include "core/hle/kernel/k_page_group.h"
11#include "core/hle/kernel/k_process.h" 11#include "core/hle/kernel/k_process.h"
12#include "core/hle/kernel/slab_helpers.h" 12#include "core/hle/kernel/slab_helpers.h"
13#include "core/hle/kernel/svc_types.h" 13#include "core/hle/kernel/svc_types.h"
@@ -29,13 +29,13 @@ class KCodeMemory final
29public: 29public:
30 explicit KCodeMemory(KernelCore& kernel_); 30 explicit KCodeMemory(KernelCore& kernel_);
31 31
32 ResultCode Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size); 32 Result Initialize(Core::DeviceMemory& device_memory, VAddr address, size_t size);
33 void Finalize(); 33 void Finalize();
34 34
35 ResultCode Map(VAddr address, size_t size); 35 Result Map(VAddr address, size_t size);
36 ResultCode Unmap(VAddr address, size_t size); 36 Result Unmap(VAddr address, size_t size);
37 ResultCode MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm); 37 Result MapToOwner(VAddr address, size_t size, Svc::MemoryPermission perm);
38 ResultCode UnmapFromOwner(VAddr address, size_t size); 38 Result UnmapFromOwner(VAddr address, size_t size);
39 39
40 bool IsInitialized() const { 40 bool IsInitialized() const {
41 return m_is_initialized; 41 return m_is_initialized;
@@ -53,7 +53,7 @@ public:
53 } 53 }
54 54
55private: 55private:
56 KPageLinkedList m_page_group{}; 56 KPageGroup m_page_group{};
57 KProcess* m_owner{}; 57 KProcess* m_owner{};
58 VAddr m_address{}; 58 VAddr m_address{};
59 KLightLock m_lock; 59 KLightLock m_lock;
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index 43bcd253d..124149697 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -61,8 +61,7 @@ public:
61 explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel_) 61 explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel_)
62 : KThreadQueue(kernel_) {} 62 : KThreadQueue(kernel_) {}
63 63
64 void CancelWait(KThread* waiting_thread, ResultCode wait_result, 64 void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override {
65 bool cancel_timer_task) override {
66 // Remove the thread as a waiter from its owner. 65 // Remove the thread as a waiter from its owner.
67 waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); 66 waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread);
68 67
@@ -80,8 +79,7 @@ public:
80 KernelCore& kernel_, KConditionVariable::ThreadTree* t) 79 KernelCore& kernel_, KConditionVariable::ThreadTree* t)
81 : KThreadQueue(kernel_), m_tree(t) {} 80 : KThreadQueue(kernel_), m_tree(t) {}
82 81
83 void CancelWait(KThread* waiting_thread, ResultCode wait_result, 82 void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override {
84 bool cancel_timer_task) override {
85 // Remove the thread as a waiter from its owner. 83 // Remove the thread as a waiter from its owner.
86 if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { 84 if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) {
87 owner->RemoveWaiter(waiting_thread); 85 owner->RemoveWaiter(waiting_thread);
@@ -105,8 +103,8 @@ KConditionVariable::KConditionVariable(Core::System& system_)
105 103
106KConditionVariable::~KConditionVariable() = default; 104KConditionVariable::~KConditionVariable() = default;
107 105
108ResultCode KConditionVariable::SignalToAddress(VAddr addr) { 106Result KConditionVariable::SignalToAddress(VAddr addr) {
109 KThread* owner_thread = kernel.CurrentScheduler()->GetCurrentThread(); 107 KThread* owner_thread = GetCurrentThreadPointer(kernel);
110 108
111 // Signal the address. 109 // Signal the address.
112 { 110 {
@@ -126,7 +124,7 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) {
126 } 124 }
127 125
128 // Write the value to userspace. 126 // Write the value to userspace.
129 ResultCode result{ResultSuccess}; 127 Result result{ResultSuccess};
130 if (WriteToUser(system, addr, std::addressof(next_value))) [[likely]] { 128 if (WriteToUser(system, addr, std::addressof(next_value))) [[likely]] {
131 result = ResultSuccess; 129 result = ResultSuccess;
132 } else { 130 } else {
@@ -146,8 +144,8 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) {
146 } 144 }
147} 145}
148 146
149ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) { 147Result KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) {
150 KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); 148 KThread* cur_thread = GetCurrentThreadPointer(kernel);
151 ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); 149 ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel);
152 150
153 // Wait for the address. 151 // Wait for the address.
@@ -261,7 +259,7 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
261 } 259 }
262} 260}
263 261
264ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { 262Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) {
265 // Prepare to wait. 263 // Prepare to wait.
266 KThread* cur_thread = GetCurrentThreadPointer(kernel); 264 KThread* cur_thread = GetCurrentThreadPointer(kernel);
267 ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue( 265 ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(
diff --git a/src/core/hle/kernel/k_condition_variable.h b/src/core/hle/kernel/k_condition_variable.h
index 7bc749d98..fad4ed011 100644
--- a/src/core/hle/kernel/k_condition_variable.h
+++ b/src/core/hle/kernel/k_condition_variable.h
@@ -25,12 +25,12 @@ public:
25 ~KConditionVariable(); 25 ~KConditionVariable();
26 26
27 // Arbitration 27 // Arbitration
28 [[nodiscard]] ResultCode SignalToAddress(VAddr addr); 28 [[nodiscard]] Result SignalToAddress(VAddr addr);
29 [[nodiscard]] ResultCode WaitForAddress(Handle handle, VAddr addr, u32 value); 29 [[nodiscard]] Result WaitForAddress(Handle handle, VAddr addr, u32 value);
30 30
31 // Condition variable 31 // Condition variable
32 void Signal(u64 cv_key, s32 count); 32 void Signal(u64 cv_key, s32 count);
33 [[nodiscard]] ResultCode Wait(VAddr addr, u64 key, u32 value, s64 timeout); 33 [[nodiscard]] Result Wait(VAddr addr, u64 key, u32 value, s64 timeout);
34 34
35private: 35private:
36 void SignalImpl(KThread* thread); 36 void SignalImpl(KThread* thread);
diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp
index c453927ad..e830ca46e 100644
--- a/src/core/hle/kernel/k_handle_table.cpp
+++ b/src/core/hle/kernel/k_handle_table.cpp
@@ -8,7 +8,7 @@ namespace Kernel {
8KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {} 8KHandleTable::KHandleTable(KernelCore& kernel_) : kernel{kernel_} {}
9KHandleTable::~KHandleTable() = default; 9KHandleTable::~KHandleTable() = default;
10 10
11ResultCode KHandleTable::Finalize() { 11Result KHandleTable::Finalize() {
12 // Get the table and clear our record of it. 12 // Get the table and clear our record of it.
13 u16 saved_table_size = 0; 13 u16 saved_table_size = 0;
14 { 14 {
@@ -62,7 +62,7 @@ bool KHandleTable::Remove(Handle handle) {
62 return true; 62 return true;
63} 63}
64 64
65ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj) { 65Result KHandleTable::Add(Handle* out_handle, KAutoObject* obj) {
66 KScopedDisableDispatch dd(kernel); 66 KScopedDisableDispatch dd(kernel);
67 KScopedSpinLock lk(m_lock); 67 KScopedSpinLock lk(m_lock);
68 68
@@ -85,7 +85,7 @@ ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj) {
85 return ResultSuccess; 85 return ResultSuccess;
86} 86}
87 87
88ResultCode KHandleTable::Reserve(Handle* out_handle) { 88Result KHandleTable::Reserve(Handle* out_handle) {
89 KScopedDisableDispatch dd(kernel); 89 KScopedDisableDispatch dd(kernel);
90 KScopedSpinLock lk(m_lock); 90 KScopedSpinLock lk(m_lock);
91 91
diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h
index befdb2ec9..0864a737c 100644
--- a/src/core/hle/kernel/k_handle_table.h
+++ b/src/core/hle/kernel/k_handle_table.h
@@ -30,7 +30,7 @@ public:
30 explicit KHandleTable(KernelCore& kernel_); 30 explicit KHandleTable(KernelCore& kernel_);
31 ~KHandleTable(); 31 ~KHandleTable();
32 32
33 ResultCode Initialize(s32 size) { 33 Result Initialize(s32 size) {
34 R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory); 34 R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory);
35 35
36 // Initialize all fields. 36 // Initialize all fields.
@@ -60,7 +60,7 @@ public:
60 return m_max_count; 60 return m_max_count;
61 } 61 }
62 62
63 ResultCode Finalize(); 63 Result Finalize();
64 bool Remove(Handle handle); 64 bool Remove(Handle handle);
65 65
66 template <typename T = KAutoObject> 66 template <typename T = KAutoObject>
@@ -100,10 +100,10 @@ public:
100 return this->template GetObjectWithoutPseudoHandle<T>(handle); 100 return this->template GetObjectWithoutPseudoHandle<T>(handle);
101 } 101 }
102 102
103 ResultCode Reserve(Handle* out_handle); 103 Result Reserve(Handle* out_handle);
104 void Unreserve(Handle handle); 104 void Unreserve(Handle handle);
105 105
106 ResultCode Add(Handle* out_handle, KAutoObject* obj); 106 Result Add(Handle* out_handle, KAutoObject* obj);
107 void Register(Handle handle, KAutoObject* obj); 107 void Register(Handle handle, KAutoObject* obj);
108 108
109 template <typename T> 109 template <typename T>
diff --git a/src/core/hle/kernel/k_interrupt_manager.cpp b/src/core/hle/kernel/k_interrupt_manager.cpp
index cf9ed80d0..d606a7f86 100644
--- a/src/core/hle/kernel/k_interrupt_manager.cpp
+++ b/src/core/hle/kernel/k_interrupt_manager.cpp
@@ -15,8 +15,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) {
15 return; 15 return;
16 } 16 }
17 17
18 auto& scheduler = kernel.Scheduler(core_id); 18 auto& current_thread = GetCurrentThread(kernel);
19 auto& current_thread = *scheduler.GetCurrentThread();
20 19
21 // If the user disable count is set, we may need to pin the current thread. 20 // If the user disable count is set, we may need to pin the current thread.
22 if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) { 21 if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) {
@@ -26,7 +25,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) {
26 process->PinCurrentThread(core_id); 25 process->PinCurrentThread(core_id);
27 26
28 // Set the interrupt flag for the thread. 27 // Set the interrupt flag for the thread.
29 scheduler.GetCurrentThread()->SetInterruptFlag(); 28 GetCurrentThread(kernel).SetInterruptFlag();
30 } 29 }
31} 30}
32 31
diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp
index a40f35f45..cade99cfd 100644
--- a/src/core/hle/kernel/k_light_condition_variable.cpp
+++ b/src/core/hle/kernel/k_light_condition_variable.cpp
@@ -17,8 +17,7 @@ public:
17 bool term) 17 bool term)
18 : KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {} 18 : KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {}
19 19
20 void CancelWait(KThread* waiting_thread, ResultCode wait_result, 20 void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override {
21 bool cancel_timer_task) override {
22 // Only process waits if we're allowed to. 21 // Only process waits if we're allowed to.
23 if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { 22 if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) {
24 return; 23 return;
diff --git a/src/core/hle/kernel/k_light_lock.cpp b/src/core/hle/kernel/k_light_lock.cpp
index 0225734b4..43185320d 100644
--- a/src/core/hle/kernel/k_light_lock.cpp
+++ b/src/core/hle/kernel/k_light_lock.cpp
@@ -15,8 +15,7 @@ class ThreadQueueImplForKLightLock final : public KThreadQueue {
15public: 15public:
16 explicit ThreadQueueImplForKLightLock(KernelCore& kernel_) : KThreadQueue(kernel_) {} 16 explicit ThreadQueueImplForKLightLock(KernelCore& kernel_) : KThreadQueue(kernel_) {}
17 17
18 void CancelWait(KThread* waiting_thread, ResultCode wait_result, 18 void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override {
19 bool cancel_timer_task) override {
20 // Remove the thread as a waiter from its owner. 19 // Remove the thread as a waiter from its owner.
21 if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { 20 if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) {
22 owner->RemoveWaiter(waiting_thread); 21 owner->RemoveWaiter(waiting_thread);
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index a55db3088..5b0a9963a 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -11,7 +11,7 @@
11#include "core/device_memory.h" 11#include "core/device_memory.h"
12#include "core/hle/kernel/initial_process.h" 12#include "core/hle/kernel/initial_process.h"
13#include "core/hle/kernel/k_memory_manager.h" 13#include "core/hle/kernel/k_memory_manager.h"
14#include "core/hle/kernel/k_page_linked_list.h" 14#include "core/hle/kernel/k_page_group.h"
15#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/svc_results.h" 16#include "core/hle/kernel/svc_results.h"
17 17
@@ -29,7 +29,7 @@ constexpr KMemoryManager::Pool GetPoolFromMemoryRegionType(u32 type) {
29 } else if ((type | KMemoryRegionType_DramSystemNonSecurePool) == type) { 29 } else if ((type | KMemoryRegionType_DramSystemNonSecurePool) == type) {
30 return KMemoryManager::Pool::SystemNonSecure; 30 return KMemoryManager::Pool::SystemNonSecure;
31 } else { 31 } else {
32 UNREACHABLE_MSG("InvalidMemoryRegionType for conversion to Pool"); 32 ASSERT_MSG(false, "InvalidMemoryRegionType for conversion to Pool");
33 return {}; 33 return {};
34 } 34 }
35} 35}
@@ -208,8 +208,8 @@ PAddr KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, size_t align_p
208 return allocated_block; 208 return allocated_block;
209} 209}
210 210
211ResultCode KMemoryManager::AllocatePageGroupImpl(KPageLinkedList* out, size_t num_pages, Pool pool, 211Result KMemoryManager::AllocatePageGroupImpl(KPageGroup* out, size_t num_pages, Pool pool,
212 Direction dir, bool random) { 212 Direction dir, bool random) {
213 // Choose a heap based on our page size request. 213 // Choose a heap based on our page size request.
214 const s32 heap_index = KPageHeap::GetBlockIndex(num_pages); 214 const s32 heap_index = KPageHeap::GetBlockIndex(num_pages);
215 R_UNLESS(0 <= heap_index, ResultOutOfMemory); 215 R_UNLESS(0 <= heap_index, ResultOutOfMemory);
@@ -257,7 +257,7 @@ ResultCode KMemoryManager::AllocatePageGroupImpl(KPageLinkedList* out, size_t nu
257 return ResultSuccess; 257 return ResultSuccess;
258} 258}
259 259
260ResultCode KMemoryManager::AllocateAndOpen(KPageLinkedList* out, size_t num_pages, u32 option) { 260Result KMemoryManager::AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 option) {
261 ASSERT(out != nullptr); 261 ASSERT(out != nullptr);
262 ASSERT(out->GetNumPages() == 0); 262 ASSERT(out->GetNumPages() == 0);
263 263
@@ -293,8 +293,8 @@ ResultCode KMemoryManager::AllocateAndOpen(KPageLinkedList* out, size_t num_page
293 return ResultSuccess; 293 return ResultSuccess;
294} 294}
295 295
296ResultCode KMemoryManager::AllocateAndOpenForProcess(KPageLinkedList* out, size_t num_pages, 296Result KMemoryManager::AllocateAndOpenForProcess(KPageGroup* out, size_t num_pages, u32 option,
297 u32 option, u64 process_id, u8 fill_pattern) { 297 u64 process_id, u8 fill_pattern) {
298 ASSERT(out != nullptr); 298 ASSERT(out != nullptr);
299 ASSERT(out->GetNumPages() == 0); 299 ASSERT(out->GetNumPages() == 0);
300 300
@@ -370,12 +370,12 @@ void KMemoryManager::Close(PAddr address, size_t num_pages) {
370 } 370 }
371} 371}
372 372
373void KMemoryManager::Close(const KPageLinkedList& pg) { 373void KMemoryManager::Close(const KPageGroup& pg) {
374 for (const auto& node : pg.Nodes()) { 374 for (const auto& node : pg.Nodes()) {
375 Close(node.GetAddress(), node.GetNumPages()); 375 Close(node.GetAddress(), node.GetNumPages());
376 } 376 }
377} 377}
378void KMemoryManager::Open(const KPageLinkedList& pg) { 378void KMemoryManager::Open(const KPageGroup& pg) {
379 for (const auto& node : pg.Nodes()) { 379 for (const auto& node : pg.Nodes()) {
380 Open(node.GetAddress(), node.GetNumPages()); 380 Open(node.GetAddress(), node.GetNumPages());
381 } 381 }
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h
index c7923cb82..dcb9b6348 100644
--- a/src/core/hle/kernel/k_memory_manager.h
+++ b/src/core/hle/kernel/k_memory_manager.h
@@ -19,7 +19,7 @@ class System;
19 19
20namespace Kernel { 20namespace Kernel {
21 21
22class KPageLinkedList; 22class KPageGroup;
23 23
24class KMemoryManager final { 24class KMemoryManager final {
25public: 25public:
@@ -65,17 +65,17 @@ public:
65 } 65 }
66 66
67 PAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option); 67 PAddr AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
68 ResultCode AllocateAndOpen(KPageLinkedList* out, size_t num_pages, u32 option); 68 Result AllocateAndOpen(KPageGroup* out, size_t num_pages, u32 option);
69 ResultCode AllocateAndOpenForProcess(KPageLinkedList* out, size_t num_pages, u32 option, 69 Result AllocateAndOpenForProcess(KPageGroup* out, size_t num_pages, u32 option, u64 process_id,
70 u64 process_id, u8 fill_pattern); 70 u8 fill_pattern);
71 71
72 static constexpr size_t MaxManagerCount = 10; 72 static constexpr size_t MaxManagerCount = 10;
73 73
74 void Close(PAddr address, size_t num_pages); 74 void Close(PAddr address, size_t num_pages);
75 void Close(const KPageLinkedList& pg); 75 void Close(const KPageGroup& pg);
76 76
77 void Open(PAddr address, size_t num_pages); 77 void Open(PAddr address, size_t num_pages);
78 void Open(const KPageLinkedList& pg); 78 void Open(const KPageGroup& pg);
79 79
80public: 80public:
81 static size_t CalculateManagementOverheadSize(size_t region_size) { 81 static size_t CalculateManagementOverheadSize(size_t region_size) {
@@ -262,8 +262,8 @@ private:
262 } 262 }
263 } 263 }
264 264
265 ResultCode AllocatePageGroupImpl(KPageLinkedList* out, size_t num_pages, Pool pool, 265 Result AllocatePageGroupImpl(KPageGroup* out, size_t num_pages, Pool pool, Direction dir,
266 Direction dir, bool random); 266 bool random);
267 267
268private: 268private:
269 Core::System& system; 269 Core::System& system;
diff --git a/src/core/hle/kernel/k_page_linked_list.h b/src/core/hle/kernel/k_page_group.h
index 1f79c8330..968753992 100644
--- a/src/core/hle/kernel/k_page_linked_list.h
+++ b/src/core/hle/kernel/k_page_group.h
@@ -12,7 +12,7 @@
12 12
13namespace Kernel { 13namespace Kernel {
14 14
15class KPageLinkedList final { 15class KPageGroup final {
16public: 16public:
17 class Node final { 17 class Node final {
18 public: 18 public:
@@ -36,8 +36,8 @@ public:
36 }; 36 };
37 37
38public: 38public:
39 KPageLinkedList() = default; 39 KPageGroup() = default;
40 KPageLinkedList(u64 address, u64 num_pages) { 40 KPageGroup(u64 address, u64 num_pages) {
41 ASSERT(AddBlock(address, num_pages).IsSuccess()); 41 ASSERT(AddBlock(address, num_pages).IsSuccess());
42 } 42 }
43 43
@@ -57,7 +57,7 @@ public:
57 return num_pages; 57 return num_pages;
58 } 58 }
59 59
60 bool IsEqual(KPageLinkedList& other) const { 60 bool IsEqual(KPageGroup& other) const {
61 auto this_node = nodes.begin(); 61 auto this_node = nodes.begin();
62 auto other_node = other.nodes.begin(); 62 auto other_node = other.nodes.begin();
63 while (this_node != nodes.end() && other_node != other.nodes.end()) { 63 while (this_node != nodes.end() && other_node != other.nodes.end()) {
@@ -72,7 +72,7 @@ public:
72 return this_node == nodes.end() && other_node == other.nodes.end(); 72 return this_node == nodes.end() && other_node == other.nodes.end();
73 } 73 }
74 74
75 ResultCode AddBlock(u64 address, u64 num_pages) { 75 Result AddBlock(u64 address, u64 num_pages) {
76 if (!num_pages) { 76 if (!num_pages) {
77 return ResultSuccess; 77 return ResultSuccess;
78 } 78 }
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index b38ef333b..d975de844 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -9,7 +9,7 @@
9#include "core/hle/kernel/k_address_space_info.h" 9#include "core/hle/kernel/k_address_space_info.h"
10#include "core/hle/kernel/k_memory_block.h" 10#include "core/hle/kernel/k_memory_block.h"
11#include "core/hle/kernel/k_memory_block_manager.h" 11#include "core/hle/kernel/k_memory_block_manager.h"
12#include "core/hle/kernel/k_page_linked_list.h" 12#include "core/hle/kernel/k_page_group.h"
13#include "core/hle/kernel/k_page_table.h" 13#include "core/hle/kernel/k_page_table.h"
14#include "core/hle/kernel/k_process.h" 14#include "core/hle/kernel/k_process.h"
15#include "core/hle/kernel/k_resource_limit.h" 15#include "core/hle/kernel/k_resource_limit.h"
@@ -35,7 +35,7 @@ constexpr std::size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceT
35 case FileSys::ProgramAddressSpaceType::Is39Bit: 35 case FileSys::ProgramAddressSpaceType::Is39Bit:
36 return 39; 36 return 39;
37 default: 37 default:
38 UNREACHABLE(); 38 ASSERT(false);
39 return {}; 39 return {};
40 } 40 }
41} 41}
@@ -47,9 +47,9 @@ KPageTable::KPageTable(Core::System& system_)
47 47
48KPageTable::~KPageTable() = default; 48KPageTable::~KPageTable() = default;
49 49
50ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, 50Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
51 bool enable_aslr, VAddr code_addr, 51 VAddr code_addr, std::size_t code_size,
52 std::size_t code_size, KMemoryManager::Pool pool) { 52 KMemoryManager::Pool pool) {
53 53
54 const auto GetSpaceStart = [this](KAddressSpaceInfo::Type type) { 54 const auto GetSpaceStart = [this](KAddressSpaceInfo::Type type) {
55 return KAddressSpaceInfo::GetAddressSpaceStart(address_space_width, type); 55 return KAddressSpaceInfo::GetAddressSpaceStart(address_space_width, type);
@@ -65,7 +65,6 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_
65 std::size_t alias_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Alias)}; 65 std::size_t alias_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Alias)};
66 std::size_t heap_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Heap)}; 66 std::size_t heap_region_size{GetSpaceSize(KAddressSpaceInfo::Type::Heap)};
67 67
68 ASSERT(start <= code_addr);
69 ASSERT(code_addr < code_addr + code_size); 68 ASSERT(code_addr < code_addr + code_size);
70 ASSERT(code_addr + code_size - 1 <= end - 1); 69 ASSERT(code_addr + code_size - 1 <= end - 1);
71 70
@@ -128,7 +127,7 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_
128 const std::size_t needed_size{ 127 const std::size_t needed_size{
129 (alias_region_size + heap_region_size + stack_region_size + kernel_map_region_size)}; 128 (alias_region_size + heap_region_size + stack_region_size + kernel_map_region_size)};
130 if (alloc_size < needed_size) { 129 if (alloc_size < needed_size) {
131 UNREACHABLE(); 130 ASSERT(false);
132 return ResultOutOfMemory; 131 return ResultOutOfMemory;
133 } 132 }
134 133
@@ -258,8 +257,8 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_
258 return InitializeMemoryLayout(start, end); 257 return InitializeMemoryLayout(start, end);
259} 258}
260 259
261ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemoryState state, 260Result KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemoryState state,
262 KMemoryPermission perm) { 261 KMemoryPermission perm) {
263 const u64 size{num_pages * PageSize}; 262 const u64 size{num_pages * PageSize};
264 263
265 // Validate the mapping request. 264 // Validate the mapping request.
@@ -272,7 +271,7 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
272 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, KMemoryState::Free, 271 R_TRY(this->CheckMemoryState(addr, size, KMemoryState::All, KMemoryState::Free,
273 KMemoryPermission::None, KMemoryPermission::None, 272 KMemoryPermission::None, KMemoryPermission::None,
274 KMemoryAttribute::None, KMemoryAttribute::None)); 273 KMemoryAttribute::None, KMemoryAttribute::None));
275 KPageLinkedList pg; 274 KPageGroup pg;
276 R_TRY(system.Kernel().MemoryManager().AllocateAndOpen( 275 R_TRY(system.Kernel().MemoryManager().AllocateAndOpen(
277 &pg, num_pages, 276 &pg, num_pages,
278 KMemoryManager::EncodeOption(KMemoryManager::Pool::Application, allocation_option))); 277 KMemoryManager::EncodeOption(KMemoryManager::Pool::Application, allocation_option)));
@@ -284,7 +283,7 @@ ResultCode KPageTable::MapProcessCode(VAddr addr, std::size_t num_pages, KMemory
284 return ResultSuccess; 283 return ResultSuccess;
285} 284}
286 285
287ResultCode KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size) { 286Result KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size) {
288 // Validate the mapping request. 287 // Validate the mapping request.
289 R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode), 288 R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode),
290 ResultInvalidMemoryRegion); 289 ResultInvalidMemoryRegion);
@@ -314,7 +313,7 @@ ResultCode KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, std::
314 const std::size_t num_pages = size / PageSize; 313 const std::size_t num_pages = size / PageSize;
315 314
316 // Create page groups for the memory being mapped. 315 // Create page groups for the memory being mapped.
317 KPageLinkedList pg; 316 KPageGroup pg;
318 AddRegionToPages(src_address, num_pages, pg); 317 AddRegionToPages(src_address, num_pages, pg);
319 318
320 // Reprotect the source as kernel-read/not mapped. 319 // Reprotect the source as kernel-read/not mapped.
@@ -345,8 +344,8 @@ ResultCode KPageTable::MapCodeMemory(VAddr dst_address, VAddr src_address, std::
345 return ResultSuccess; 344 return ResultSuccess;
346} 345}
347 346
348ResultCode KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size, 347Result KPageTable::UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size,
349 ICacheInvalidationStrategy icache_invalidation_strategy) { 348 ICacheInvalidationStrategy icache_invalidation_strategy) {
350 // Validate the mapping request. 349 // Validate the mapping request.
351 R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode), 350 R_UNLESS(this->CanContain(dst_address, size, KMemoryState::AliasCode),
352 ResultInvalidMemoryRegion); 351 ResultInvalidMemoryRegion);
@@ -490,7 +489,7 @@ VAddr KPageTable::FindFreeArea(VAddr region_start, std::size_t region_num_pages,
490 return address; 489 return address;
491} 490}
492 491
493ResultCode KPageTable::MakePageGroup(KPageLinkedList& pg, VAddr addr, size_t num_pages) { 492Result KPageTable::MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages) {
494 ASSERT(this->IsLockedByCurrentThread()); 493 ASSERT(this->IsLockedByCurrentThread());
495 494
496 const size_t size = num_pages * PageSize; 495 const size_t size = num_pages * PageSize;
@@ -542,8 +541,97 @@ ResultCode KPageTable::MakePageGroup(KPageLinkedList& pg, VAddr addr, size_t num
542 return ResultSuccess; 541 return ResultSuccess;
543} 542}
544 543
545ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, 544bool KPageTable::IsValidPageGroup(const KPageGroup& pg_ll, VAddr addr, size_t num_pages) {
546 KPageTable& src_page_table, VAddr src_addr) { 545 ASSERT(this->IsLockedByCurrentThread());
546
547 const size_t size = num_pages * PageSize;
548 const auto& pg = pg_ll.Nodes();
549 const auto& memory_layout = system.Kernel().MemoryLayout();
550
551 // Empty groups are necessarily invalid.
552 if (pg.empty()) {
553 return false;
554 }
555
556 // We're going to validate that the group we'd expect is the group we see.
557 auto cur_it = pg.begin();
558 PAddr cur_block_address = cur_it->GetAddress();
559 size_t cur_block_pages = cur_it->GetNumPages();
560
561 auto UpdateCurrentIterator = [&]() {
562 if (cur_block_pages == 0) {
563 if ((++cur_it) == pg.end()) {
564 return false;
565 }
566
567 cur_block_address = cur_it->GetAddress();
568 cur_block_pages = cur_it->GetNumPages();
569 }
570 return true;
571 };
572
573 // Begin traversal.
574 Common::PageTable::TraversalContext context;
575 Common::PageTable::TraversalEntry next_entry;
576 if (!page_table_impl.BeginTraversal(next_entry, context, addr)) {
577 return false;
578 }
579
580 // Prepare tracking variables.
581 PAddr cur_addr = next_entry.phys_addr;
582 size_t cur_size = next_entry.block_size - (cur_addr & (next_entry.block_size - 1));
583 size_t tot_size = cur_size;
584
585 // Iterate, comparing expected to actual.
586 while (tot_size < size) {
587 if (!page_table_impl.ContinueTraversal(next_entry, context)) {
588 return false;
589 }
590
591 if (next_entry.phys_addr != (cur_addr + cur_size)) {
592 const size_t cur_pages = cur_size / PageSize;
593
594 if (!IsHeapPhysicalAddress(memory_layout, cur_addr)) {
595 return false;
596 }
597
598 if (!UpdateCurrentIterator()) {
599 return false;
600 }
601
602 if (cur_block_address != cur_addr || cur_block_pages < cur_pages) {
603 return false;
604 }
605
606 cur_block_address += cur_size;
607 cur_block_pages -= cur_pages;
608 cur_addr = next_entry.phys_addr;
609 cur_size = next_entry.block_size;
610 } else {
611 cur_size += next_entry.block_size;
612 }
613
614 tot_size += next_entry.block_size;
615 }
616
617 // Ensure we compare the right amount for the last block.
618 if (tot_size > size) {
619 cur_size -= (tot_size - size);
620 }
621
622 if (!IsHeapPhysicalAddress(memory_layout, cur_addr)) {
623 return false;
624 }
625
626 if (!UpdateCurrentIterator()) {
627 return false;
628 }
629
630 return cur_block_address == cur_addr && cur_block_pages == (cur_size / PageSize);
631}
632
633Result KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table,
634 VAddr src_addr) {
547 KScopedLightLock lk(general_lock); 635 KScopedLightLock lk(general_lock);
548 636
549 const std::size_t num_pages{size / PageSize}; 637 const std::size_t num_pages{size / PageSize};
@@ -572,7 +660,7 @@ ResultCode KPageTable::UnmapProcessMemory(VAddr dst_addr, std::size_t size,
572 return ResultSuccess; 660 return ResultSuccess;
573} 661}
574 662
575ResultCode KPageTable::MapPhysicalMemory(VAddr address, std::size_t size) { 663Result KPageTable::MapPhysicalMemory(VAddr address, std::size_t size) {
576 // Lock the physical memory lock. 664 // Lock the physical memory lock.
577 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock); 665 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
578 666
@@ -633,7 +721,7 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr address, std::size_t size) {
633 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); 721 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
634 722
635 // Allocate pages for the new memory. 723 // Allocate pages for the new memory.
636 KPageLinkedList pg; 724 KPageGroup pg;
637 R_TRY(system.Kernel().MemoryManager().AllocateAndOpenForProcess( 725 R_TRY(system.Kernel().MemoryManager().AllocateAndOpenForProcess(
638 &pg, (size - mapped_size) / PageSize, 726 &pg, (size - mapped_size) / PageSize,
639 KMemoryManager::EncodeOption(memory_pool, allocation_option), 0, 0)); 727 KMemoryManager::EncodeOption(memory_pool, allocation_option), 0, 0));
@@ -815,7 +903,7 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr address, std::size_t size) {
815 } 903 }
816} 904}
817 905
818ResultCode KPageTable::UnmapPhysicalMemory(VAddr address, std::size_t size) { 906Result KPageTable::UnmapPhysicalMemory(VAddr address, std::size_t size) {
819 // Lock the physical memory lock. 907 // Lock the physical memory lock.
820 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock); 908 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
821 909
@@ -884,7 +972,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr address, std::size_t size) {
884 } 972 }
885 973
886 // Make a page group for the unmap region. 974 // Make a page group for the unmap region.
887 KPageLinkedList pg; 975 KPageGroup pg;
888 { 976 {
889 auto& impl = this->PageTableImpl(); 977 auto& impl = this->PageTableImpl();
890 978
@@ -1046,7 +1134,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr address, std::size_t size) {
1046 return ResultSuccess; 1134 return ResultSuccess;
1047} 1135}
1048 1136
1049ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 1137Result KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
1050 KScopedLightLock lk(general_lock); 1138 KScopedLightLock lk(general_lock);
1051 1139
1052 KMemoryState src_state{}; 1140 KMemoryState src_state{};
@@ -1059,7 +1147,7 @@ ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t siz
1059 return ResultInvalidCurrentMemory; 1147 return ResultInvalidCurrentMemory;
1060 } 1148 }
1061 1149
1062 KPageLinkedList page_linked_list; 1150 KPageGroup page_linked_list;
1063 const std::size_t num_pages{size / PageSize}; 1151 const std::size_t num_pages{size / PageSize};
1064 1152
1065 AddRegionToPages(src_addr, num_pages, page_linked_list); 1153 AddRegionToPages(src_addr, num_pages, page_linked_list);
@@ -1085,7 +1173,7 @@ ResultCode KPageTable::MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t siz
1085 return ResultSuccess; 1173 return ResultSuccess;
1086} 1174}
1087 1175
1088ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) { 1176Result KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size) {
1089 KScopedLightLock lk(general_lock); 1177 KScopedLightLock lk(general_lock);
1090 1178
1091 KMemoryState src_state{}; 1179 KMemoryState src_state{};
@@ -1100,8 +1188,8 @@ ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t s
1100 KMemoryPermission::None, KMemoryAttribute::Mask, 1188 KMemoryPermission::None, KMemoryAttribute::Mask,
1101 KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); 1189 KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
1102 1190
1103 KPageLinkedList src_pages; 1191 KPageGroup src_pages;
1104 KPageLinkedList dst_pages; 1192 KPageGroup dst_pages;
1105 const std::size_t num_pages{size / PageSize}; 1193 const std::size_t num_pages{size / PageSize};
1106 1194
1107 AddRegionToPages(src_addr, num_pages, src_pages); 1195 AddRegionToPages(src_addr, num_pages, src_pages);
@@ -1127,8 +1215,8 @@ ResultCode KPageTable::UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t s
1127 return ResultSuccess; 1215 return ResultSuccess;
1128} 1216}
1129 1217
1130ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_list, 1218Result KPageTable::MapPages(VAddr addr, const KPageGroup& page_linked_list,
1131 KMemoryPermission perm) { 1219 KMemoryPermission perm) {
1132 ASSERT(this->IsLockedByCurrentThread()); 1220 ASSERT(this->IsLockedByCurrentThread());
1133 1221
1134 VAddr cur_addr{addr}; 1222 VAddr cur_addr{addr};
@@ -1151,8 +1239,8 @@ ResultCode KPageTable::MapPages(VAddr addr, const KPageLinkedList& page_linked_l
1151 return ResultSuccess; 1239 return ResultSuccess;
1152} 1240}
1153 1241
1154ResultCode KPageTable::MapPages(VAddr address, KPageLinkedList& page_linked_list, 1242Result KPageTable::MapPages(VAddr address, KPageGroup& page_linked_list, KMemoryState state,
1155 KMemoryState state, KMemoryPermission perm) { 1243 KMemoryPermission perm) {
1156 // Check that the map is in range. 1244 // Check that the map is in range.
1157 const std::size_t num_pages{page_linked_list.GetNumPages()}; 1245 const std::size_t num_pages{page_linked_list.GetNumPages()};
1158 const std::size_t size{num_pages * PageSize}; 1246 const std::size_t size{num_pages * PageSize};
@@ -1175,10 +1263,10 @@ ResultCode KPageTable::MapPages(VAddr address, KPageLinkedList& page_linked_list
1175 return ResultSuccess; 1263 return ResultSuccess;
1176} 1264}
1177 1265
1178ResultCode KPageTable::MapPages(VAddr* out_addr, std::size_t num_pages, std::size_t alignment, 1266Result KPageTable::MapPages(VAddr* out_addr, std::size_t num_pages, std::size_t alignment,
1179 PAddr phys_addr, bool is_pa_valid, VAddr region_start, 1267 PAddr phys_addr, bool is_pa_valid, VAddr region_start,
1180 std::size_t region_num_pages, KMemoryState state, 1268 std::size_t region_num_pages, KMemoryState state,
1181 KMemoryPermission perm) { 1269 KMemoryPermission perm) {
1182 ASSERT(Common::IsAligned(alignment, PageSize) && alignment >= PageSize); 1270 ASSERT(Common::IsAligned(alignment, PageSize) && alignment >= PageSize);
1183 1271
1184 // Ensure this is a valid map request. 1272 // Ensure this is a valid map request.
@@ -1215,7 +1303,7 @@ ResultCode KPageTable::MapPages(VAddr* out_addr, std::size_t num_pages, std::siz
1215 return ResultSuccess; 1303 return ResultSuccess;
1216} 1304}
1217 1305
1218ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list) { 1306Result KPageTable::UnmapPages(VAddr addr, const KPageGroup& page_linked_list) {
1219 ASSERT(this->IsLockedByCurrentThread()); 1307 ASSERT(this->IsLockedByCurrentThread());
1220 1308
1221 VAddr cur_addr{addr}; 1309 VAddr cur_addr{addr};
@@ -1233,8 +1321,7 @@ ResultCode KPageTable::UnmapPages(VAddr addr, const KPageLinkedList& page_linked
1233 return ResultSuccess; 1321 return ResultSuccess;
1234} 1322}
1235 1323
1236ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, 1324Result KPageTable::UnmapPages(VAddr addr, KPageGroup& page_linked_list, KMemoryState state) {
1237 KMemoryState state) {
1238 // Check that the unmap is in range. 1325 // Check that the unmap is in range.
1239 const std::size_t num_pages{page_linked_list.GetNumPages()}; 1326 const std::size_t num_pages{page_linked_list.GetNumPages()};
1240 const std::size_t size{num_pages * PageSize}; 1327 const std::size_t size{num_pages * PageSize};
@@ -1257,7 +1344,7 @@ ResultCode KPageTable::UnmapPages(VAddr addr, KPageLinkedList& page_linked_list,
1257 return ResultSuccess; 1344 return ResultSuccess;
1258} 1345}
1259 1346
1260ResultCode KPageTable::UnmapPages(VAddr address, std::size_t num_pages, KMemoryState state) { 1347Result KPageTable::UnmapPages(VAddr address, std::size_t num_pages, KMemoryState state) {
1261 // Check that the unmap is in range. 1348 // Check that the unmap is in range.
1262 const std::size_t size = num_pages * PageSize; 1349 const std::size_t size = num_pages * PageSize;
1263 R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory); 1350 R_UNLESS(this->Contains(address, size), ResultInvalidCurrentMemory);
@@ -1281,10 +1368,10 @@ ResultCode KPageTable::UnmapPages(VAddr address, std::size_t num_pages, KMemoryS
1281 return ResultSuccess; 1368 return ResultSuccess;
1282} 1369}
1283 1370
1284ResultCode KPageTable::MakeAndOpenPageGroup(KPageLinkedList* out, VAddr address, size_t num_pages, 1371Result KPageTable::MakeAndOpenPageGroup(KPageGroup* out, VAddr address, size_t num_pages,
1285 KMemoryState state_mask, KMemoryState state, 1372 KMemoryState state_mask, KMemoryState state,
1286 KMemoryPermission perm_mask, KMemoryPermission perm, 1373 KMemoryPermission perm_mask, KMemoryPermission perm,
1287 KMemoryAttribute attr_mask, KMemoryAttribute attr) { 1374 KMemoryAttribute attr_mask, KMemoryAttribute attr) {
1288 // Ensure that the page group isn't null. 1375 // Ensure that the page group isn't null.
1289 ASSERT(out != nullptr); 1376 ASSERT(out != nullptr);
1290 1377
@@ -1306,8 +1393,8 @@ ResultCode KPageTable::MakeAndOpenPageGroup(KPageLinkedList* out, VAddr address,
1306 return ResultSuccess; 1393 return ResultSuccess;
1307} 1394}
1308 1395
1309ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size, 1396Result KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size,
1310 Svc::MemoryPermission svc_perm) { 1397 Svc::MemoryPermission svc_perm) {
1311 const size_t num_pages = size / PageSize; 1398 const size_t num_pages = size / PageSize;
1312 1399
1313 // Lock the table. 1400 // Lock the table.
@@ -1341,7 +1428,7 @@ ResultCode KPageTable::SetProcessMemoryPermission(VAddr addr, std::size_t size,
1341 new_state = KMemoryState::AliasCodeData; 1428 new_state = KMemoryState::AliasCodeData;
1342 break; 1429 break;
1343 default: 1430 default:
1344 UNREACHABLE(); 1431 ASSERT(false);
1345 } 1432 }
1346 } 1433 }
1347 1434
@@ -1379,7 +1466,7 @@ KMemoryInfo KPageTable::QueryInfo(VAddr addr) {
1379 return QueryInfoImpl(addr); 1466 return QueryInfoImpl(addr);
1380} 1467}
1381 1468
1382ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) { 1469Result KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm) {
1383 KScopedLightLock lk(general_lock); 1470 KScopedLightLock lk(general_lock);
1384 1471
1385 KMemoryState state{}; 1472 KMemoryState state{};
@@ -1397,7 +1484,7 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo
1397 return ResultSuccess; 1484 return ResultSuccess;
1398} 1485}
1399 1486
1400ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) { 1487Result KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
1401 KScopedLightLock lk(general_lock); 1488 KScopedLightLock lk(general_lock);
1402 1489
1403 KMemoryState state{}; 1490 KMemoryState state{};
@@ -1412,8 +1499,8 @@ ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
1412 return ResultSuccess; 1499 return ResultSuccess;
1413} 1500}
1414 1501
1415ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size, 1502Result KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
1416 Svc::MemoryPermission svc_perm) { 1503 Svc::MemoryPermission svc_perm) {
1417 const size_t num_pages = size / PageSize; 1504 const size_t num_pages = size / PageSize;
1418 1505
1419 // Lock the table. 1506 // Lock the table.
@@ -1440,7 +1527,7 @@ ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
1440 return ResultSuccess; 1527 return ResultSuccess;
1441} 1528}
1442 1529
1443ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask, u32 attr) { 1530Result KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask, u32 attr) {
1444 const size_t num_pages = size / PageSize; 1531 const size_t num_pages = size / PageSize;
1445 ASSERT((static_cast<KMemoryAttribute>(mask) | KMemoryAttribute::SetMask) == 1532 ASSERT((static_cast<KMemoryAttribute>(mask) | KMemoryAttribute::SetMask) ==
1446 KMemoryAttribute::SetMask); 1533 KMemoryAttribute::SetMask);
@@ -1475,7 +1562,7 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask
1475 return ResultSuccess; 1562 return ResultSuccess;
1476} 1563}
1477 1564
1478ResultCode KPageTable::SetMaxHeapSize(std::size_t size) { 1565Result KPageTable::SetMaxHeapSize(std::size_t size) {
1479 // Lock the table. 1566 // Lock the table.
1480 KScopedLightLock lk(general_lock); 1567 KScopedLightLock lk(general_lock);
1481 1568
@@ -1487,7 +1574,7 @@ ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
1487 return ResultSuccess; 1574 return ResultSuccess;
1488} 1575}
1489 1576
1490ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) { 1577Result KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
1491 // Lock the physical memory mutex. 1578 // Lock the physical memory mutex.
1492 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock); 1579 KScopedLightLock map_phys_mem_lk(map_physical_memory_lock);
1493 1580
@@ -1554,7 +1641,7 @@ ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
1554 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); 1641 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
1555 1642
1556 // Allocate pages for the heap extension. 1643 // Allocate pages for the heap extension.
1557 KPageLinkedList pg; 1644 KPageGroup pg;
1558 R_TRY(system.Kernel().MemoryManager().AllocateAndOpen( 1645 R_TRY(system.Kernel().MemoryManager().AllocateAndOpen(
1559 &pg, allocation_size / PageSize, 1646 &pg, allocation_size / PageSize,
1560 KMemoryManager::EncodeOption(memory_pool, allocation_option))); 1647 KMemoryManager::EncodeOption(memory_pool, allocation_option)));
@@ -1629,7 +1716,7 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
1629 if (is_map_only) { 1716 if (is_map_only) {
1630 R_TRY(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr)); 1717 R_TRY(Operate(addr, needed_num_pages, perm, OperationType::Map, map_addr));
1631 } else { 1718 } else {
1632 KPageLinkedList page_group; 1719 KPageGroup page_group;
1633 R_TRY(system.Kernel().MemoryManager().AllocateAndOpenForProcess( 1720 R_TRY(system.Kernel().MemoryManager().AllocateAndOpenForProcess(
1634 &page_group, needed_num_pages, 1721 &page_group, needed_num_pages,
1635 KMemoryManager::EncodeOption(memory_pool, allocation_option), 0, 0)); 1722 KMemoryManager::EncodeOption(memory_pool, allocation_option), 0, 0));
@@ -1641,11 +1728,11 @@ ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages,
1641 return addr; 1728 return addr;
1642} 1729}
1643 1730
1644ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) { 1731Result KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1645 KScopedLightLock lk(general_lock); 1732 KScopedLightLock lk(general_lock);
1646 1733
1647 KMemoryPermission perm{}; 1734 KMemoryPermission perm{};
1648 if (const ResultCode result{CheckMemoryState( 1735 if (const Result result{CheckMemoryState(
1649 nullptr, &perm, nullptr, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute, 1736 nullptr, &perm, nullptr, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute,
1650 KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, 1737 KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None,
1651 KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None, 1738 KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None,
@@ -1664,11 +1751,11 @@ ResultCode KPageTable::LockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1664 return ResultSuccess; 1751 return ResultSuccess;
1665} 1752}
1666 1753
1667ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) { 1754Result KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size) {
1668 KScopedLightLock lk(general_lock); 1755 KScopedLightLock lk(general_lock);
1669 1756
1670 KMemoryPermission perm{}; 1757 KMemoryPermission perm{};
1671 if (const ResultCode result{CheckMemoryState( 1758 if (const Result result{CheckMemoryState(
1672 nullptr, &perm, nullptr, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute, 1759 nullptr, &perm, nullptr, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute,
1673 KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, 1760 KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None,
1674 KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None, 1761 KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None,
@@ -1687,25 +1774,24 @@ ResultCode KPageTable::UnlockForDeviceAddressSpace(VAddr addr, std::size_t size)
1687 return ResultSuccess; 1774 return ResultSuccess;
1688} 1775}
1689 1776
1690ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) { 1777Result KPageTable::LockForCodeMemory(KPageGroup* out, VAddr addr, std::size_t size) {
1691 return this->LockMemoryAndOpen( 1778 return this->LockMemoryAndOpen(
1692 nullptr, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, 1779 out, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, KMemoryState::FlagCanCodeMemory,
1693 KMemoryState::FlagCanCodeMemory, KMemoryPermission::All, KMemoryPermission::UserReadWrite, 1780 KMemoryPermission::All, KMemoryPermission::UserReadWrite, KMemoryAttribute::All,
1694 KMemoryAttribute::All, KMemoryAttribute::None, 1781 KMemoryAttribute::None,
1695 static_cast<KMemoryPermission>(KMemoryPermission::NotMapped | 1782 static_cast<KMemoryPermission>(KMemoryPermission::NotMapped |
1696 KMemoryPermission::KernelReadWrite), 1783 KMemoryPermission::KernelReadWrite),
1697 KMemoryAttribute::Locked); 1784 KMemoryAttribute::Locked);
1698} 1785}
1699 1786
1700ResultCode KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size) { 1787Result KPageTable::UnlockForCodeMemory(VAddr addr, std::size_t size, const KPageGroup& pg) {
1701 return this->UnlockMemory(addr, size, KMemoryState::FlagCanCodeMemory, 1788 return this->UnlockMemory(
1702 KMemoryState::FlagCanCodeMemory, KMemoryPermission::None, 1789 addr, size, KMemoryState::FlagCanCodeMemory, KMemoryState::FlagCanCodeMemory,
1703 KMemoryPermission::None, KMemoryAttribute::All, 1790 KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::All,
1704 KMemoryAttribute::Locked, KMemoryPermission::UserReadWrite, 1791 KMemoryAttribute::Locked, KMemoryPermission::UserReadWrite, KMemoryAttribute::Locked, &pg);
1705 KMemoryAttribute::Locked, nullptr);
1706} 1792}
1707 1793
1708ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) { 1794Result KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
1709 block_manager = std::make_unique<KMemoryBlockManager>(start, end); 1795 block_manager = std::make_unique<KMemoryBlockManager>(start, end);
1710 1796
1711 return ResultSuccess; 1797 return ResultSuccess;
@@ -1730,13 +1816,11 @@ bool KPageTable::IsRegionContiguous(VAddr addr, u64 size) const {
1730} 1816}
1731 1817
1732void KPageTable::AddRegionToPages(VAddr start, std::size_t num_pages, 1818void KPageTable::AddRegionToPages(VAddr start, std::size_t num_pages,
1733 KPageLinkedList& page_linked_list) { 1819 KPageGroup& page_linked_list) {
1734 VAddr addr{start}; 1820 VAddr addr{start};
1735 while (addr < start + (num_pages * PageSize)) { 1821 while (addr < start + (num_pages * PageSize)) {
1736 const PAddr paddr{GetPhysicalAddr(addr)}; 1822 const PAddr paddr{GetPhysicalAddr(addr)};
1737 if (!paddr) { 1823 ASSERT(paddr != 0);
1738 UNREACHABLE();
1739 }
1740 page_linked_list.AddBlock(paddr, 1); 1824 page_linked_list.AddBlock(paddr, 1);
1741 addr += PageSize; 1825 addr += PageSize;
1742 } 1826 }
@@ -1751,8 +1835,8 @@ VAddr KPageTable::AllocateVirtualMemory(VAddr start, std::size_t region_num_page
1751 IsKernel() ? 1 : 4); 1835 IsKernel() ? 1 : 4);
1752} 1836}
1753 1837
1754ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageLinkedList& page_group, 1838Result KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageGroup& page_group,
1755 OperationType operation) { 1839 OperationType operation) {
1756 ASSERT(this->IsLockedByCurrentThread()); 1840 ASSERT(this->IsLockedByCurrentThread());
1757 1841
1758 ASSERT(Common::IsAligned(addr, PageSize)); 1842 ASSERT(Common::IsAligned(addr, PageSize));
@@ -1767,7 +1851,7 @@ ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageLin
1767 system.Memory().MapMemoryRegion(page_table_impl, addr, size, node.GetAddress()); 1851 system.Memory().MapMemoryRegion(page_table_impl, addr, size, node.GetAddress());
1768 break; 1852 break;
1769 default: 1853 default:
1770 UNREACHABLE(); 1854 ASSERT(false);
1771 } 1855 }
1772 1856
1773 addr += size; 1857 addr += size;
@@ -1776,8 +1860,8 @@ ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, const KPageLin
1776 return ResultSuccess; 1860 return ResultSuccess;
1777} 1861}
1778 1862
1779ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm, 1863Result KPageTable::Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm,
1780 OperationType operation, PAddr map_addr) { 1864 OperationType operation, PAddr map_addr) {
1781 ASSERT(this->IsLockedByCurrentThread()); 1865 ASSERT(this->IsLockedByCurrentThread());
1782 1866
1783 ASSERT(num_pages > 0); 1867 ASSERT(num_pages > 0);
@@ -1798,7 +1882,7 @@ ResultCode KPageTable::Operate(VAddr addr, std::size_t num_pages, KMemoryPermiss
1798 case OperationType::ChangePermissionsAndRefresh: 1882 case OperationType::ChangePermissionsAndRefresh:
1799 break; 1883 break;
1800 default: 1884 default:
1801 UNREACHABLE(); 1885 ASSERT(false);
1802 } 1886 }
1803 return ResultSuccess; 1887 return ResultSuccess;
1804} 1888}
@@ -1835,7 +1919,6 @@ VAddr KPageTable::GetRegionAddress(KMemoryState state) const {
1835 return code_region_start; 1919 return code_region_start;
1836 default: 1920 default:
1837 UNREACHABLE(); 1921 UNREACHABLE();
1838 return {};
1839 } 1922 }
1840} 1923}
1841 1924
@@ -1871,7 +1954,6 @@ std::size_t KPageTable::GetRegionSize(KMemoryState state) const {
1871 return code_region_end - code_region_start; 1954 return code_region_end - code_region_start;
1872 default: 1955 default:
1873 UNREACHABLE(); 1956 UNREACHABLE();
1874 return {};
1875 } 1957 }
1876} 1958}
1877 1959
@@ -1921,10 +2003,10 @@ bool KPageTable::CanContain(VAddr addr, std::size_t size, KMemoryState state) co
1921 } 2003 }
1922} 2004}
1923 2005
1924ResultCode KPageTable::CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, 2006Result KPageTable::CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask,
1925 KMemoryState state, KMemoryPermission perm_mask, 2007 KMemoryState state, KMemoryPermission perm_mask,
1926 KMemoryPermission perm, KMemoryAttribute attr_mask, 2008 KMemoryPermission perm, KMemoryAttribute attr_mask,
1927 KMemoryAttribute attr) const { 2009 KMemoryAttribute attr) const {
1928 // Validate the states match expectation. 2010 // Validate the states match expectation.
1929 R_UNLESS((info.state & state_mask) == state, ResultInvalidCurrentMemory); 2011 R_UNLESS((info.state & state_mask) == state, ResultInvalidCurrentMemory);
1930 R_UNLESS((info.perm & perm_mask) == perm, ResultInvalidCurrentMemory); 2012 R_UNLESS((info.perm & perm_mask) == perm, ResultInvalidCurrentMemory);
@@ -1933,12 +2015,11 @@ ResultCode KPageTable::CheckMemoryState(const KMemoryInfo& info, KMemoryState st
1933 return ResultSuccess; 2015 return ResultSuccess;
1934} 2016}
1935 2017
1936ResultCode KPageTable::CheckMemoryStateContiguous(std::size_t* out_blocks_needed, VAddr addr, 2018Result KPageTable::CheckMemoryStateContiguous(std::size_t* out_blocks_needed, VAddr addr,
1937 std::size_t size, KMemoryState state_mask, 2019 std::size_t size, KMemoryState state_mask,
1938 KMemoryState state, KMemoryPermission perm_mask, 2020 KMemoryState state, KMemoryPermission perm_mask,
1939 KMemoryPermission perm, 2021 KMemoryPermission perm, KMemoryAttribute attr_mask,
1940 KMemoryAttribute attr_mask, 2022 KMemoryAttribute attr) const {
1941 KMemoryAttribute attr) const {
1942 ASSERT(this->IsLockedByCurrentThread()); 2023 ASSERT(this->IsLockedByCurrentThread());
1943 2024
1944 // Get information about the first block. 2025 // Get information about the first block.
@@ -1976,12 +2057,12 @@ ResultCode KPageTable::CheckMemoryStateContiguous(std::size_t* out_blocks_needed
1976 return ResultSuccess; 2057 return ResultSuccess;
1977} 2058}
1978 2059
1979ResultCode KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, 2060Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm,
1980 KMemoryAttribute* out_attr, std::size_t* out_blocks_needed, 2061 KMemoryAttribute* out_attr, std::size_t* out_blocks_needed,
1981 VAddr addr, std::size_t size, KMemoryState state_mask, 2062 VAddr addr, std::size_t size, KMemoryState state_mask,
1982 KMemoryState state, KMemoryPermission perm_mask, 2063 KMemoryState state, KMemoryPermission perm_mask,
1983 KMemoryPermission perm, KMemoryAttribute attr_mask, 2064 KMemoryPermission perm, KMemoryAttribute attr_mask,
1984 KMemoryAttribute attr, KMemoryAttribute ignore_attr) const { 2065 KMemoryAttribute attr, KMemoryAttribute ignore_attr) const {
1985 ASSERT(this->IsLockedByCurrentThread()); 2066 ASSERT(this->IsLockedByCurrentThread());
1986 2067
1987 // Get information about the first block. 2068 // Get information about the first block.
@@ -2038,11 +2119,11 @@ ResultCode KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermissi
2038 return ResultSuccess; 2119 return ResultSuccess;
2039} 2120}
2040 2121
2041ResultCode KPageTable::LockMemoryAndOpen(KPageLinkedList* out_pg, PAddr* out_paddr, VAddr addr, 2122Result KPageTable::LockMemoryAndOpen(KPageGroup* out_pg, PAddr* out_paddr, VAddr addr, size_t size,
2042 size_t size, KMemoryState state_mask, KMemoryState state, 2123 KMemoryState state_mask, KMemoryState state,
2043 KMemoryPermission perm_mask, KMemoryPermission perm, 2124 KMemoryPermission perm_mask, KMemoryPermission perm,
2044 KMemoryAttribute attr_mask, KMemoryAttribute attr, 2125 KMemoryAttribute attr_mask, KMemoryAttribute attr,
2045 KMemoryPermission new_perm, KMemoryAttribute lock_attr) { 2126 KMemoryPermission new_perm, KMemoryAttribute lock_attr) {
2046 // Validate basic preconditions. 2127 // Validate basic preconditions.
2047 ASSERT((lock_attr & attr) == KMemoryAttribute::None); 2128 ASSERT((lock_attr & attr) == KMemoryAttribute::None);
2048 ASSERT((lock_attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) == 2129 ASSERT((lock_attr & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)) ==
@@ -2096,11 +2177,11 @@ ResultCode KPageTable::LockMemoryAndOpen(KPageLinkedList* out_pg, PAddr* out_pad
2096 return ResultSuccess; 2177 return ResultSuccess;
2097} 2178}
2098 2179
2099ResultCode KPageTable::UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask, 2180Result KPageTable::UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask,
2100 KMemoryState state, KMemoryPermission perm_mask, 2181 KMemoryState state, KMemoryPermission perm_mask,
2101 KMemoryPermission perm, KMemoryAttribute attr_mask, 2182 KMemoryPermission perm, KMemoryAttribute attr_mask,
2102 KMemoryAttribute attr, KMemoryPermission new_perm, 2183 KMemoryAttribute attr, KMemoryPermission new_perm,
2103 KMemoryAttribute lock_attr, const KPageLinkedList* pg) { 2184 KMemoryAttribute lock_attr, const KPageGroup* pg) {
2104 // Validate basic preconditions. 2185 // Validate basic preconditions.
2105 ASSERT((attr_mask & lock_attr) == lock_attr); 2186 ASSERT((attr_mask & lock_attr) == lock_attr);
2106 ASSERT((attr & lock_attr) == lock_attr); 2187 ASSERT((attr & lock_attr) == lock_attr);
@@ -2125,7 +2206,7 @@ ResultCode KPageTable::UnlockMemory(VAddr addr, size_t size, KMemoryState state_
2125 2206
2126 // Check the page group. 2207 // Check the page group.
2127 if (pg != nullptr) { 2208 if (pg != nullptr) {
2128 UNIMPLEMENTED_MSG("PageGroup support is unimplemented!"); 2209 R_UNLESS(this->IsValidPageGroup(*pg, addr, num_pages), ResultInvalidMemoryRegion);
2129 } 2210 }
2130 2211
2131 // Decide on new perm and attr. 2212 // Decide on new perm and attr.
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 52a93ce86..25774f232 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -33,51 +33,49 @@ public:
33 explicit KPageTable(Core::System& system_); 33 explicit KPageTable(Core::System& system_);
34 ~KPageTable(); 34 ~KPageTable();
35 35
36 ResultCode InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, 36 Result InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr,
37 VAddr code_addr, std::size_t code_size, 37 VAddr code_addr, std::size_t code_size, KMemoryManager::Pool pool);
38 KMemoryManager::Pool pool); 38 Result MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state,
39 ResultCode MapProcessCode(VAddr addr, std::size_t pages_count, KMemoryState state, 39 KMemoryPermission perm);
40 KMemoryPermission perm); 40 Result MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size);
41 ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size); 41 Result UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size,
42 ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, std::size_t size, 42 ICacheInvalidationStrategy icache_invalidation_strategy);
43 ICacheInvalidationStrategy icache_invalidation_strategy); 43 Result UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table,
44 ResultCode UnmapProcessMemory(VAddr dst_addr, std::size_t size, KPageTable& src_page_table, 44 VAddr src_addr);
45 VAddr src_addr); 45 Result MapPhysicalMemory(VAddr addr, std::size_t size);
46 ResultCode MapPhysicalMemory(VAddr addr, std::size_t size); 46 Result UnmapPhysicalMemory(VAddr addr, std::size_t size);
47 ResultCode UnmapPhysicalMemory(VAddr addr, std::size_t size); 47 Result MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
48 ResultCode MapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); 48 Result UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size);
49 ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, std::size_t size); 49 Result MapPages(VAddr addr, KPageGroup& page_linked_list, KMemoryState state,
50 ResultCode MapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state, 50 KMemoryPermission perm);
51 KMemoryPermission perm); 51 Result MapPages(VAddr* out_addr, std::size_t num_pages, std::size_t alignment, PAddr phys_addr,
52 ResultCode MapPages(VAddr* out_addr, std::size_t num_pages, std::size_t alignment, 52 KMemoryState state, KMemoryPermission perm) {
53 PAddr phys_addr, KMemoryState state, KMemoryPermission perm) {
54 return this->MapPages(out_addr, num_pages, alignment, phys_addr, true, 53 return this->MapPages(out_addr, num_pages, alignment, phys_addr, true,
55 this->GetRegionAddress(state), this->GetRegionSize(state) / PageSize, 54 this->GetRegionAddress(state), this->GetRegionSize(state) / PageSize,
56 state, perm); 55 state, perm);
57 } 56 }
58 ResultCode UnmapPages(VAddr addr, KPageLinkedList& page_linked_list, KMemoryState state); 57 Result UnmapPages(VAddr addr, KPageGroup& page_linked_list, KMemoryState state);
59 ResultCode UnmapPages(VAddr address, std::size_t num_pages, KMemoryState state); 58 Result UnmapPages(VAddr address, std::size_t num_pages, KMemoryState state);
60 ResultCode SetProcessMemoryPermission(VAddr addr, std::size_t size, 59 Result SetProcessMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission svc_perm);
61 Svc::MemoryPermission svc_perm);
62 KMemoryInfo QueryInfo(VAddr addr); 60 KMemoryInfo QueryInfo(VAddr addr);
63 ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); 61 Result ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm);
64 ResultCode ResetTransferMemory(VAddr addr, std::size_t size); 62 Result ResetTransferMemory(VAddr addr, std::size_t size);
65 ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm); 63 Result SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm);
66 ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask, u32 attr); 64 Result SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask, u32 attr);
67 ResultCode SetMaxHeapSize(std::size_t size); 65 Result SetMaxHeapSize(std::size_t size);
68 ResultCode SetHeapSize(VAddr* out, std::size_t size); 66 Result SetHeapSize(VAddr* out, std::size_t size);
69 ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, 67 ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
70 bool is_map_only, VAddr region_start, 68 bool is_map_only, VAddr region_start,
71 std::size_t region_num_pages, KMemoryState state, 69 std::size_t region_num_pages, KMemoryState state,
72 KMemoryPermission perm, PAddr map_addr = 0); 70 KMemoryPermission perm, PAddr map_addr = 0);
73 ResultCode LockForDeviceAddressSpace(VAddr addr, std::size_t size); 71 Result LockForDeviceAddressSpace(VAddr addr, std::size_t size);
74 ResultCode UnlockForDeviceAddressSpace(VAddr addr, std::size_t size); 72 Result UnlockForDeviceAddressSpace(VAddr addr, std::size_t size);
75 ResultCode LockForCodeMemory(VAddr addr, std::size_t size); 73 Result LockForCodeMemory(KPageGroup* out, VAddr addr, std::size_t size);
76 ResultCode UnlockForCodeMemory(VAddr addr, std::size_t size); 74 Result UnlockForCodeMemory(VAddr addr, std::size_t size, const KPageGroup& pg);
77 ResultCode MakeAndOpenPageGroup(KPageLinkedList* out, VAddr address, size_t num_pages, 75 Result MakeAndOpenPageGroup(KPageGroup* out, VAddr address, size_t num_pages,
78 KMemoryState state_mask, KMemoryState state, 76 KMemoryState state_mask, KMemoryState state,
79 KMemoryPermission perm_mask, KMemoryPermission perm, 77 KMemoryPermission perm_mask, KMemoryPermission perm,
80 KMemoryAttribute attr_mask, KMemoryAttribute attr); 78 KMemoryAttribute attr_mask, KMemoryAttribute attr);
81 79
82 Common::PageTable& PageTableImpl() { 80 Common::PageTable& PageTableImpl() {
83 return page_table_impl; 81 return page_table_impl;
@@ -102,82 +100,78 @@ private:
102 KMemoryAttribute::IpcLocked | 100 KMemoryAttribute::IpcLocked |
103 KMemoryAttribute::DeviceShared; 101 KMemoryAttribute::DeviceShared;
104 102
105 ResultCode InitializeMemoryLayout(VAddr start, VAddr end); 103 Result InitializeMemoryLayout(VAddr start, VAddr end);
106 ResultCode MapPages(VAddr addr, const KPageLinkedList& page_linked_list, 104 Result MapPages(VAddr addr, const KPageGroup& page_linked_list, KMemoryPermission perm);
107 KMemoryPermission perm); 105 Result MapPages(VAddr* out_addr, std::size_t num_pages, std::size_t alignment, PAddr phys_addr,
108 ResultCode MapPages(VAddr* out_addr, std::size_t num_pages, std::size_t alignment, 106 bool is_pa_valid, VAddr region_start, std::size_t region_num_pages,
109 PAddr phys_addr, bool is_pa_valid, VAddr region_start, 107 KMemoryState state, KMemoryPermission perm);
110 std::size_t region_num_pages, KMemoryState state, KMemoryPermission perm); 108 Result UnmapPages(VAddr addr, const KPageGroup& page_linked_list);
111 ResultCode UnmapPages(VAddr addr, const KPageLinkedList& page_linked_list);
112 bool IsRegionMapped(VAddr address, u64 size); 109 bool IsRegionMapped(VAddr address, u64 size);
113 bool IsRegionContiguous(VAddr addr, u64 size) const; 110 bool IsRegionContiguous(VAddr addr, u64 size) const;
114 void AddRegionToPages(VAddr start, std::size_t num_pages, KPageLinkedList& page_linked_list); 111 void AddRegionToPages(VAddr start, std::size_t num_pages, KPageGroup& page_linked_list);
115 KMemoryInfo QueryInfoImpl(VAddr addr); 112 KMemoryInfo QueryInfoImpl(VAddr addr);
116 VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages, 113 VAddr AllocateVirtualMemory(VAddr start, std::size_t region_num_pages, u64 needed_num_pages,
117 std::size_t align); 114 std::size_t align);
118 ResultCode Operate(VAddr addr, std::size_t num_pages, const KPageLinkedList& page_group, 115 Result Operate(VAddr addr, std::size_t num_pages, const KPageGroup& page_group,
119 OperationType operation); 116 OperationType operation);
120 ResultCode Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm, 117 Result Operate(VAddr addr, std::size_t num_pages, KMemoryPermission perm,
121 OperationType operation, PAddr map_addr = 0); 118 OperationType operation, PAddr map_addr = 0);
122 VAddr GetRegionAddress(KMemoryState state) const; 119 VAddr GetRegionAddress(KMemoryState state) const;
123 std::size_t GetRegionSize(KMemoryState state) const; 120 std::size_t GetRegionSize(KMemoryState state) const;
124 121
125 VAddr FindFreeArea(VAddr region_start, std::size_t region_num_pages, std::size_t num_pages, 122 VAddr FindFreeArea(VAddr region_start, std::size_t region_num_pages, std::size_t num_pages,
126 std::size_t alignment, std::size_t offset, std::size_t guard_pages); 123 std::size_t alignment, std::size_t offset, std::size_t guard_pages);
127 124
128 ResultCode CheckMemoryStateContiguous(std::size_t* out_blocks_needed, VAddr addr, 125 Result CheckMemoryStateContiguous(std::size_t* out_blocks_needed, VAddr addr, std::size_t size,
129 std::size_t size, KMemoryState state_mask, 126 KMemoryState state_mask, KMemoryState state,
130 KMemoryState state, KMemoryPermission perm_mask, 127 KMemoryPermission perm_mask, KMemoryPermission perm,
131 KMemoryPermission perm, KMemoryAttribute attr_mask, 128 KMemoryAttribute attr_mask, KMemoryAttribute attr) const;
132 KMemoryAttribute attr) const; 129 Result CheckMemoryStateContiguous(VAddr addr, std::size_t size, KMemoryState state_mask,
133 ResultCode CheckMemoryStateContiguous(VAddr addr, std::size_t size, KMemoryState state_mask, 130 KMemoryState state, KMemoryPermission perm_mask,
134 KMemoryState state, KMemoryPermission perm_mask, 131 KMemoryPermission perm, KMemoryAttribute attr_mask,
135 KMemoryPermission perm, KMemoryAttribute attr_mask, 132 KMemoryAttribute attr) const {
136 KMemoryAttribute attr) const {
137 return this->CheckMemoryStateContiguous(nullptr, addr, size, state_mask, state, perm_mask, 133 return this->CheckMemoryStateContiguous(nullptr, addr, size, state_mask, state, perm_mask,
138 perm, attr_mask, attr); 134 perm, attr_mask, attr);
139 } 135 }
140 136
141 ResultCode CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, 137 Result CheckMemoryState(const KMemoryInfo& info, KMemoryState state_mask, KMemoryState state,
142 KMemoryState state, KMemoryPermission perm_mask, 138 KMemoryPermission perm_mask, KMemoryPermission perm,
143 KMemoryPermission perm, KMemoryAttribute attr_mask, 139 KMemoryAttribute attr_mask, KMemoryAttribute attr) const;
144 KMemoryAttribute attr) const; 140 Result CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm,
145 ResultCode CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, 141 KMemoryAttribute* out_attr, std::size_t* out_blocks_needed, VAddr addr,
146 KMemoryAttribute* out_attr, std::size_t* out_blocks_needed, 142 std::size_t size, KMemoryState state_mask, KMemoryState state,
147 VAddr addr, std::size_t size, KMemoryState state_mask, 143 KMemoryPermission perm_mask, KMemoryPermission perm,
148 KMemoryState state, KMemoryPermission perm_mask, 144 KMemoryAttribute attr_mask, KMemoryAttribute attr,
149 KMemoryPermission perm, KMemoryAttribute attr_mask, 145 KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const;
150 KMemoryAttribute attr, 146 Result CheckMemoryState(std::size_t* out_blocks_needed, VAddr addr, std::size_t size,
151 KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const; 147 KMemoryState state_mask, KMemoryState state,
152 ResultCode CheckMemoryState(std::size_t* out_blocks_needed, VAddr addr, std::size_t size, 148 KMemoryPermission perm_mask, KMemoryPermission perm,
153 KMemoryState state_mask, KMemoryState state, 149 KMemoryAttribute attr_mask, KMemoryAttribute attr,
154 KMemoryPermission perm_mask, KMemoryPermission perm, 150 KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const {
155 KMemoryAttribute attr_mask, KMemoryAttribute attr,
156 KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const {
157 return CheckMemoryState(nullptr, nullptr, nullptr, out_blocks_needed, addr, size, 151 return CheckMemoryState(nullptr, nullptr, nullptr, out_blocks_needed, addr, size,
158 state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr); 152 state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr);
159 } 153 }
160 ResultCode CheckMemoryState(VAddr addr, std::size_t size, KMemoryState state_mask, 154 Result CheckMemoryState(VAddr addr, std::size_t size, KMemoryState state_mask,
161 KMemoryState state, KMemoryPermission perm_mask, 155 KMemoryState state, KMemoryPermission perm_mask, KMemoryPermission perm,
162 KMemoryPermission perm, KMemoryAttribute attr_mask, 156 KMemoryAttribute attr_mask, KMemoryAttribute attr,
163 KMemoryAttribute attr, 157 KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const {
164 KMemoryAttribute ignore_attr = DefaultMemoryIgnoreAttr) const {
165 return this->CheckMemoryState(nullptr, addr, size, state_mask, state, perm_mask, perm, 158 return this->CheckMemoryState(nullptr, addr, size, state_mask, state, perm_mask, perm,
166 attr_mask, attr, ignore_attr); 159 attr_mask, attr, ignore_attr);
167 } 160 }
168 161
169 ResultCode LockMemoryAndOpen(KPageLinkedList* out_pg, PAddr* out_paddr, VAddr addr, size_t size, 162 Result LockMemoryAndOpen(KPageGroup* out_pg, PAddr* out_paddr, VAddr addr, size_t size,
170 KMemoryState state_mask, KMemoryState state, 163 KMemoryState state_mask, KMemoryState state,
171 KMemoryPermission perm_mask, KMemoryPermission perm, 164 KMemoryPermission perm_mask, KMemoryPermission perm,
172 KMemoryAttribute attr_mask, KMemoryAttribute attr, 165 KMemoryAttribute attr_mask, KMemoryAttribute attr,
173 KMemoryPermission new_perm, KMemoryAttribute lock_attr); 166 KMemoryPermission new_perm, KMemoryAttribute lock_attr);
174 ResultCode UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask, KMemoryState state, 167 Result UnlockMemory(VAddr addr, size_t size, KMemoryState state_mask, KMemoryState state,
175 KMemoryPermission perm_mask, KMemoryPermission perm, 168 KMemoryPermission perm_mask, KMemoryPermission perm,
176 KMemoryAttribute attr_mask, KMemoryAttribute attr, 169 KMemoryAttribute attr_mask, KMemoryAttribute attr,
177 KMemoryPermission new_perm, KMemoryAttribute lock_attr, 170 KMemoryPermission new_perm, KMemoryAttribute lock_attr,
178 const KPageLinkedList* pg); 171 const KPageGroup* pg);
179 172
180 ResultCode MakePageGroup(KPageLinkedList& pg, VAddr addr, size_t num_pages); 173 Result MakePageGroup(KPageGroup& pg, VAddr addr, size_t num_pages);
174 bool IsValidPageGroup(const KPageGroup& pg, VAddr addr, size_t num_pages);
181 175
182 bool IsLockedByCurrentThread() const { 176 bool IsLockedByCurrentThread() const {
183 return general_lock.IsLockedByCurrentThread(); 177 return general_lock.IsLockedByCurrentThread();
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp
index a31861cdb..7a5a9dc2a 100644
--- a/src/core/hle/kernel/k_port.cpp
+++ b/src/core/hle/kernel/k_port.cpp
@@ -50,7 +50,7 @@ bool KPort::IsServerClosed() const {
50 return state == State::ServerClosed; 50 return state == State::ServerClosed;
51} 51}
52 52
53ResultCode KPort::EnqueueSession(KServerSession* session) { 53Result KPort::EnqueueSession(KServerSession* session) {
54 KScopedSchedulerLock sl{kernel}; 54 KScopedSchedulerLock sl{kernel};
55 55
56 R_UNLESS(state == State::Normal, ResultPortClosed); 56 R_UNLESS(state == State::Normal, ResultPortClosed);
@@ -60,7 +60,7 @@ ResultCode KPort::EnqueueSession(KServerSession* session) {
60 if (auto session_ptr = server.GetSessionRequestHandler().lock()) { 60 if (auto session_ptr = server.GetSessionRequestHandler().lock()) {
61 session_ptr->ClientConnected(server.AcceptSession()); 61 session_ptr->ClientConnected(server.AcceptSession());
62 } else { 62 } else {
63 UNREACHABLE(); 63 ASSERT(false);
64 } 64 }
65 65
66 return ResultSuccess; 66 return ResultSuccess;
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h
index 1bfecf8c3..0cfc16dab 100644
--- a/src/core/hle/kernel/k_port.h
+++ b/src/core/hle/kernel/k_port.h
@@ -34,7 +34,7 @@ public:
34 34
35 bool IsServerClosed() const; 35 bool IsServerClosed() const;
36 36
37 ResultCode EnqueueSession(KServerSession* session); 37 Result EnqueueSession(KServerSession* session);
38 38
39 KClientPort& GetClientPort() { 39 KClientPort& GetClientPort() {
40 return client; 40 return client;
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index dcfeacccd..183c693e3 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -57,23 +57,18 @@ void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority
57 thread->GetContext64().cpu_registers[0] = 0; 57 thread->GetContext64().cpu_registers[0] = 0;
58 thread->GetContext32().cpu_registers[1] = thread_handle; 58 thread->GetContext32().cpu_registers[1] = thread_handle;
59 thread->GetContext64().cpu_registers[1] = thread_handle; 59 thread->GetContext64().cpu_registers[1] = thread_handle;
60 thread->DisableDispatch();
61 60
62 auto& kernel = system.Kernel(); 61 if (system.DebuggerEnabled()) {
63 // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires 62 thread->RequestSuspend(SuspendType::Debug);
64 {
65 KScopedSchedulerLock lock{kernel};
66 thread->SetState(ThreadState::Runnable);
67
68 if (system.DebuggerEnabled()) {
69 thread->RequestSuspend(SuspendType::Debug);
70 }
71 } 63 }
64
65 // Run our thread.
66 void(thread->Run());
72} 67}
73} // Anonymous namespace 68} // Anonymous namespace
74 69
75ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name, 70Result KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name,
76 ProcessType type, KResourceLimit* res_limit) { 71 ProcessType type, KResourceLimit* res_limit) {
77 auto& kernel = system.Kernel(); 72 auto& kernel = system.Kernel();
78 73
79 process->name = std::move(process_name); 74 process->name = std::move(process_name);
@@ -181,7 +176,8 @@ void KProcess::PinCurrentThread(s32 core_id) {
181 ASSERT(kernel.GlobalSchedulerContext().IsLocked()); 176 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
182 177
183 // Get the current thread. 178 // Get the current thread.
184 KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread(); 179 KThread* cur_thread =
180 kernel.Scheduler(static_cast<std::size_t>(core_id)).GetSchedulerCurrentThread();
185 181
186 // If the thread isn't terminated, pin it. 182 // If the thread isn't terminated, pin it.
187 if (!cur_thread->IsTerminationRequested()) { 183 if (!cur_thread->IsTerminationRequested()) {
@@ -198,7 +194,8 @@ void KProcess::UnpinCurrentThread(s32 core_id) {
198 ASSERT(kernel.GlobalSchedulerContext().IsLocked()); 194 ASSERT(kernel.GlobalSchedulerContext().IsLocked());
199 195
200 // Get the current thread. 196 // Get the current thread.
201 KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread(); 197 KThread* cur_thread =
198 kernel.Scheduler(static_cast<std::size_t>(core_id)).GetSchedulerCurrentThread();
202 199
203 // Unpin it. 200 // Unpin it.
204 cur_thread->Unpin(); 201 cur_thread->Unpin();
@@ -222,8 +219,8 @@ void KProcess::UnpinThread(KThread* thread) {
222 KScheduler::SetSchedulerUpdateNeeded(kernel); 219 KScheduler::SetSchedulerUpdateNeeded(kernel);
223} 220}
224 221
225ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address, 222Result KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address,
226 [[maybe_unused]] size_t size) { 223 [[maybe_unused]] size_t size) {
227 // Lock ourselves, to prevent concurrent access. 224 // Lock ourselves, to prevent concurrent access.
228 KScopedLightLock lk(state_lock); 225 KScopedLightLock lk(state_lock);
229 226
@@ -275,15 +272,19 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a
275 shmem->Close(); 272 shmem->Close();
276} 273}
277 274
278void KProcess::RegisterThread(const KThread* thread) { 275void KProcess::RegisterThread(KThread* thread) {
276 KScopedLightLock lk{list_lock};
277
279 thread_list.push_back(thread); 278 thread_list.push_back(thread);
280} 279}
281 280
282void KProcess::UnregisterThread(const KThread* thread) { 281void KProcess::UnregisterThread(KThread* thread) {
282 KScopedLightLock lk{list_lock};
283
283 thread_list.remove(thread); 284 thread_list.remove(thread);
284} 285}
285 286
286ResultCode KProcess::Reset() { 287Result KProcess::Reset() {
287 // Lock the process and the scheduler. 288 // Lock the process and the scheduler.
288 KScopedLightLock lk(state_lock); 289 KScopedLightLock lk(state_lock);
289 KScopedSchedulerLock sl{kernel}; 290 KScopedSchedulerLock sl{kernel};
@@ -297,8 +298,51 @@ ResultCode KProcess::Reset() {
297 return ResultSuccess; 298 return ResultSuccess;
298} 299}
299 300
300ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, 301Result KProcess::SetActivity(ProcessActivity activity) {
301 std::size_t code_size) { 302 // Lock ourselves and the scheduler.
303 KScopedLightLock lk{state_lock};
304 KScopedLightLock list_lk{list_lock};
305 KScopedSchedulerLock sl{kernel};
306
307 // Validate our state.
308 R_UNLESS(status != ProcessStatus::Exiting, ResultInvalidState);
309 R_UNLESS(status != ProcessStatus::Exited, ResultInvalidState);
310
311 // Either pause or resume.
312 if (activity == ProcessActivity::Paused) {
313 // Verify that we're not suspended.
314 if (is_suspended) {
315 return ResultInvalidState;
316 }
317
318 // Suspend all threads.
319 for (auto* thread : GetThreadList()) {
320 thread->RequestSuspend(SuspendType::Process);
321 }
322
323 // Set ourselves as suspended.
324 SetSuspended(true);
325 } else {
326 ASSERT(activity == ProcessActivity::Runnable);
327
328 // Verify that we're suspended.
329 if (!is_suspended) {
330 return ResultInvalidState;
331 }
332
333 // Resume all threads.
334 for (auto* thread : GetThreadList()) {
335 thread->Resume(SuspendType::Process);
336 }
337
338 // Set ourselves as resumed.
339 SetSuspended(false);
340 }
341
342 return ResultSuccess;
343}
344
345Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size) {
302 program_id = metadata.GetTitleID(); 346 program_id = metadata.GetTitleID();
303 ideal_core = metadata.GetMainThreadCore(); 347 ideal_core = metadata.GetMainThreadCore();
304 is_64bit_process = metadata.Is64BitProgram(); 348 is_64bit_process = metadata.Is64BitProgram();
@@ -313,24 +357,24 @@ ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
313 return ResultLimitReached; 357 return ResultLimitReached;
314 } 358 }
315 // Initialize proces address space 359 // Initialize proces address space
316 if (const ResultCode result{ 360 if (const Result result{page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false,
317 page_table->InitializeForProcess(metadata.GetAddressSpaceType(), false, 0x8000000, 361 0x8000000, code_size,
318 code_size, KMemoryManager::Pool::Application)}; 362 KMemoryManager::Pool::Application)};
319 result.IsError()) { 363 result.IsError()) {
320 return result; 364 return result;
321 } 365 }
322 366
323 // Map process code region 367 // Map process code region
324 if (const ResultCode result{page_table->MapProcessCode(page_table->GetCodeRegionStart(), 368 if (const Result result{page_table->MapProcessCode(page_table->GetCodeRegionStart(),
325 code_size / PageSize, KMemoryState::Code, 369 code_size / PageSize, KMemoryState::Code,
326 KMemoryPermission::None)}; 370 KMemoryPermission::None)};
327 result.IsError()) { 371 result.IsError()) {
328 return result; 372 return result;
329 } 373 }
330 374
331 // Initialize process capabilities 375 // Initialize process capabilities
332 const auto& caps{metadata.GetKernelCapabilities()}; 376 const auto& caps{metadata.GetKernelCapabilities()};
333 if (const ResultCode result{ 377 if (const Result result{
334 capabilities.InitializeForUserProcess(caps.data(), caps.size(), *page_table)}; 378 capabilities.InitializeForUserProcess(caps.data(), caps.size(), *page_table)};
335 result.IsError()) { 379 result.IsError()) {
336 return result; 380 return result;
@@ -350,7 +394,7 @@ ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
350 break; 394 break;
351 395
352 default: 396 default:
353 UNREACHABLE(); 397 ASSERT(false);
354 } 398 }
355 399
356 // Create TLS region 400 // Create TLS region
@@ -377,11 +421,11 @@ void KProcess::PrepareForTermination() {
377 ChangeStatus(ProcessStatus::Exiting); 421 ChangeStatus(ProcessStatus::Exiting);
378 422
379 const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) { 423 const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) {
380 for (auto& thread : in_thread_list) { 424 for (auto* thread : in_thread_list) {
381 if (thread->GetOwnerProcess() != this) 425 if (thread->GetOwnerProcess() != this)
382 continue; 426 continue;
383 427
384 if (thread == kernel.CurrentScheduler()->GetCurrentThread()) 428 if (thread == GetCurrentThreadPointer(kernel))
385 continue; 429 continue;
386 430
387 // TODO(Subv): When are the other running/ready threads terminated? 431 // TODO(Subv): When are the other running/ready threads terminated?
@@ -437,7 +481,7 @@ void KProcess::Finalize() {
437 KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize(); 481 KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize();
438} 482}
439 483
440ResultCode KProcess::CreateThreadLocalRegion(VAddr* out) { 484Result KProcess::CreateThreadLocalRegion(VAddr* out) {
441 KThreadLocalPage* tlp = nullptr; 485 KThreadLocalPage* tlp = nullptr;
442 VAddr tlr = 0; 486 VAddr tlr = 0;
443 487
@@ -488,7 +532,7 @@ ResultCode KProcess::CreateThreadLocalRegion(VAddr* out) {
488 return ResultSuccess; 532 return ResultSuccess;
489} 533}
490 534
491ResultCode KProcess::DeleteThreadLocalRegion(VAddr addr) { 535Result KProcess::DeleteThreadLocalRegion(VAddr addr) {
492 KThreadLocalPage* page_to_free = nullptr; 536 KThreadLocalPage* page_to_free = nullptr;
493 537
494 // Release the region. 538 // Release the region.
@@ -536,6 +580,52 @@ ResultCode KProcess::DeleteThreadLocalRegion(VAddr addr) {
536 return ResultSuccess; 580 return ResultSuccess;
537} 581}
538 582
583bool KProcess::InsertWatchpoint(Core::System& system, VAddr addr, u64 size,
584 DebugWatchpointType type) {
585 const auto watch{std::find_if(watchpoints.begin(), watchpoints.end(), [&](const auto& wp) {
586 return wp.type == DebugWatchpointType::None;
587 })};
588
589 if (watch == watchpoints.end()) {
590 return false;
591 }
592
593 watch->start_address = addr;
594 watch->end_address = addr + size;
595 watch->type = type;
596
597 for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) {
598 debug_page_refcounts[page]++;
599 system.Memory().MarkRegionDebug(page, PageSize, true);
600 }
601
602 return true;
603}
604
605bool KProcess::RemoveWatchpoint(Core::System& system, VAddr addr, u64 size,
606 DebugWatchpointType type) {
607 const auto watch{std::find_if(watchpoints.begin(), watchpoints.end(), [&](const auto& wp) {
608 return wp.start_address == addr && wp.end_address == addr + size && wp.type == type;
609 })};
610
611 if (watch == watchpoints.end()) {
612 return false;
613 }
614
615 watch->start_address = 0;
616 watch->end_address = 0;
617 watch->type = DebugWatchpointType::None;
618
619 for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) {
620 debug_page_refcounts[page]--;
621 if (!debug_page_refcounts[page]) {
622 system.Memory().MarkRegionDebug(page, PageSize, false);
623 }
624 }
625
626 return true;
627}
628
539void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { 629void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) {
540 const auto ReprotectSegment = [&](const CodeSet::Segment& segment, 630 const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
541 Svc::MemoryPermission permission) { 631 Svc::MemoryPermission permission) {
@@ -556,9 +646,10 @@ bool KProcess::IsSignaled() const {
556} 646}
557 647
558KProcess::KProcess(KernelCore& kernel_) 648KProcess::KProcess(KernelCore& kernel_)
559 : KAutoObjectWithSlabHeapAndContainer{kernel_}, 649 : KAutoObjectWithSlabHeapAndContainer{kernel_}, page_table{std::make_unique<KPageTable>(
560 page_table{std::make_unique<KPageTable>(kernel_.System())}, handle_table{kernel_}, 650 kernel_.System())},
561 address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, state_lock{kernel_} {} 651 handle_table{kernel_}, address_arbiter{kernel_.System()}, condition_var{kernel_.System()},
652 state_lock{kernel_}, list_lock{kernel_} {}
562 653
563KProcess::~KProcess() = default; 654KProcess::~KProcess() = default;
564 655
@@ -572,7 +663,7 @@ void KProcess::ChangeStatus(ProcessStatus new_status) {
572 NotifyAvailable(); 663 NotifyAvailable();
573} 664}
574 665
575ResultCode KProcess::AllocateMainThreadStack(std::size_t stack_size) { 666Result KProcess::AllocateMainThreadStack(std::size_t stack_size) {
576 ASSERT(stack_size); 667 ASSERT(stack_size);
577 668
578 // The kernel always ensures that the given stack size is page aligned. 669 // The kernel always ensures that the given stack size is page aligned.
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 9f171e3da..5e3e22ad8 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -7,6 +7,7 @@
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <list> 9#include <list>
10#include <map>
10#include <string> 11#include <string>
11#include "common/common_types.h" 12#include "common/common_types.h"
12#include "core/hle/kernel/k_address_arbiter.h" 13#include "core/hle/kernel/k_address_arbiter.h"
@@ -63,6 +64,25 @@ enum class ProcessStatus {
63 DebugBreak, 64 DebugBreak,
64}; 65};
65 66
67enum class ProcessActivity : u32 {
68 Runnable,
69 Paused,
70};
71
72enum class DebugWatchpointType : u8 {
73 None = 0,
74 Read = 1 << 0,
75 Write = 1 << 1,
76 ReadOrWrite = Read | Write,
77};
78DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType);
79
80struct DebugWatchpoint {
81 VAddr start_address;
82 VAddr end_address;
83 DebugWatchpointType type;
84};
85
66class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { 86class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> {
67 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); 87 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
68 88
@@ -90,8 +110,8 @@ public:
90 110
91 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; 111 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
92 112
93 static ResultCode Initialize(KProcess* process, Core::System& system, std::string process_name, 113 static Result Initialize(KProcess* process, Core::System& system, std::string process_name,
94 ProcessType type, KResourceLimit* res_limit); 114 ProcessType type, KResourceLimit* res_limit);
95 115
96 /// Gets a reference to the process' page table. 116 /// Gets a reference to the process' page table.
97 KPageTable& PageTable() { 117 KPageTable& PageTable() {
@@ -113,11 +133,11 @@ public:
113 return handle_table; 133 return handle_table;
114 } 134 }
115 135
116 ResultCode SignalToAddress(VAddr address) { 136 Result SignalToAddress(VAddr address) {
117 return condition_var.SignalToAddress(address); 137 return condition_var.SignalToAddress(address);
118 } 138 }
119 139
120 ResultCode WaitForAddress(Handle handle, VAddr address, u32 tag) { 140 Result WaitForAddress(Handle handle, VAddr address, u32 tag) {
121 return condition_var.WaitForAddress(handle, address, tag); 141 return condition_var.WaitForAddress(handle, address, tag);
122 } 142 }
123 143
@@ -125,17 +145,16 @@ public:
125 return condition_var.Signal(cv_key, count); 145 return condition_var.Signal(cv_key, count);
126 } 146 }
127 147
128 ResultCode WaitConditionVariable(VAddr address, u64 cv_key, u32 tag, s64 ns) { 148 Result WaitConditionVariable(VAddr address, u64 cv_key, u32 tag, s64 ns) {
129 return condition_var.Wait(address, cv_key, tag, ns); 149 return condition_var.Wait(address, cv_key, tag, ns);
130 } 150 }
131 151
132 ResultCode SignalAddressArbiter(VAddr address, Svc::SignalType signal_type, s32 value, 152 Result SignalAddressArbiter(VAddr address, Svc::SignalType signal_type, s32 value, s32 count) {
133 s32 count) {
134 return address_arbiter.SignalToAddress(address, signal_type, value, count); 153 return address_arbiter.SignalToAddress(address, signal_type, value, count);
135 } 154 }
136 155
137 ResultCode WaitAddressArbiter(VAddr address, Svc::ArbitrationType arb_type, s32 value, 156 Result WaitAddressArbiter(VAddr address, Svc::ArbitrationType arb_type, s32 value,
138 s64 timeout) { 157 s64 timeout) {
139 return address_arbiter.WaitForAddress(address, arb_type, value, timeout); 158 return address_arbiter.WaitForAddress(address, arb_type, value, timeout);
140 } 159 }
141 160
@@ -282,17 +301,17 @@ public:
282 u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const; 301 u64 GetTotalPhysicalMemoryUsedWithoutSystemResource() const;
283 302
284 /// Gets the list of all threads created with this process as their owner. 303 /// Gets the list of all threads created with this process as their owner.
285 const std::list<const KThread*>& GetThreadList() const { 304 std::list<KThread*>& GetThreadList() {
286 return thread_list; 305 return thread_list;
287 } 306 }
288 307
289 /// Registers a thread as being created under this process, 308 /// Registers a thread as being created under this process,
290 /// adding it to this process' thread list. 309 /// adding it to this process' thread list.
291 void RegisterThread(const KThread* thread); 310 void RegisterThread(KThread* thread);
292 311
293 /// Unregisters a thread from this process, removing it 312 /// Unregisters a thread from this process, removing it
294 /// from this process' thread list. 313 /// from this process' thread list.
295 void UnregisterThread(const KThread* thread); 314 void UnregisterThread(KThread* thread);
296 315
297 /// Clears the signaled state of the process if and only if it's signaled. 316 /// Clears the signaled state of the process if and only if it's signaled.
298 /// 317 ///
@@ -302,7 +321,7 @@ public:
302 /// @pre The process must be in a signaled state. If this is called on a 321 /// @pre The process must be in a signaled state. If this is called on a
303 /// process instance that is not signaled, ERR_INVALID_STATE will be 322 /// process instance that is not signaled, ERR_INVALID_STATE will be
304 /// returned. 323 /// returned.
305 ResultCode Reset(); 324 Result Reset();
306 325
307 /** 326 /**
308 * Loads process-specifics configuration info with metadata provided 327 * Loads process-specifics configuration info with metadata provided
@@ -313,7 +332,7 @@ public:
313 * @returns ResultSuccess if all relevant metadata was able to be 332 * @returns ResultSuccess if all relevant metadata was able to be
314 * loaded and parsed. Otherwise, an error code is returned. 333 * loaded and parsed. Otherwise, an error code is returned.
315 */ 334 */
316 ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size); 335 Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size);
317 336
318 /** 337 /**
319 * Starts the main application thread for this process. 338 * Starts the main application thread for this process.
@@ -347,6 +366,8 @@ public:
347 366
348 void DoWorkerTaskImpl(); 367 void DoWorkerTaskImpl();
349 368
369 Result SetActivity(ProcessActivity activity);
370
350 void PinCurrentThread(s32 core_id); 371 void PinCurrentThread(s32 core_id);
351 void UnpinCurrentThread(s32 core_id); 372 void UnpinCurrentThread(s32 core_id);
352 void UnpinThread(KThread* thread); 373 void UnpinThread(KThread* thread);
@@ -355,17 +376,30 @@ public:
355 return state_lock; 376 return state_lock;
356 } 377 }
357 378
358 ResultCode AddSharedMemory(KSharedMemory* shmem, VAddr address, size_t size); 379 Result AddSharedMemory(KSharedMemory* shmem, VAddr address, size_t size);
359 void RemoveSharedMemory(KSharedMemory* shmem, VAddr address, size_t size); 380 void RemoveSharedMemory(KSharedMemory* shmem, VAddr address, size_t size);
360 381
361 /////////////////////////////////////////////////////////////////////////////////////////////// 382 ///////////////////////////////////////////////////////////////////////////////////////////////
362 // Thread-local storage management 383 // Thread-local storage management
363 384
364 // Marks the next available region as used and returns the address of the slot. 385 // Marks the next available region as used and returns the address of the slot.
365 [[nodiscard]] ResultCode CreateThreadLocalRegion(VAddr* out); 386 [[nodiscard]] Result CreateThreadLocalRegion(VAddr* out);
366 387
367 // Frees a used TLS slot identified by the given address 388 // Frees a used TLS slot identified by the given address
368 ResultCode DeleteThreadLocalRegion(VAddr addr); 389 Result DeleteThreadLocalRegion(VAddr addr);
390
391 ///////////////////////////////////////////////////////////////////////////////////////////////
392 // Debug watchpoint management
393
394 // Attempts to insert a watchpoint into a free slot. Returns false if none are available.
395 bool InsertWatchpoint(Core::System& system, VAddr addr, u64 size, DebugWatchpointType type);
396
397 // Attempts to remove the watchpoint specified by the given parameters.
398 bool RemoveWatchpoint(Core::System& system, VAddr addr, u64 size, DebugWatchpointType type);
399
400 const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const {
401 return watchpoints;
402 }
369 403
370private: 404private:
371 void PinThread(s32 core_id, KThread* thread) { 405 void PinThread(s32 core_id, KThread* thread) {
@@ -388,7 +422,7 @@ private:
388 void ChangeStatus(ProcessStatus new_status); 422 void ChangeStatus(ProcessStatus new_status);
389 423
390 /// Allocates the main thread stack for the process, given the stack size in bytes. 424 /// Allocates the main thread stack for the process, given the stack size in bytes.
391 ResultCode AllocateMainThreadStack(std::size_t stack_size); 425 Result AllocateMainThreadStack(std::size_t stack_size);
392 426
393 /// Memory manager for this process 427 /// Memory manager for this process
394 std::unique_ptr<KPageTable> page_table; 428 std::unique_ptr<KPageTable> page_table;
@@ -442,7 +476,7 @@ private:
442 std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{}; 476 std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{};
443 477
444 /// List of threads that are running with this process as their owner. 478 /// List of threads that are running with this process as their owner.
445 std::list<const KThread*> thread_list; 479 std::list<KThread*> thread_list;
446 480
447 /// List of shared memory that are running with this process as their owner. 481 /// List of shared memory that are running with this process as their owner.
448 std::list<KSharedMemoryInfo*> shared_memory_list; 482 std::list<KSharedMemoryInfo*> shared_memory_list;
@@ -471,10 +505,13 @@ private:
471 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> running_threads{}; 505 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> running_threads{};
472 std::array<u64, Core::Hardware::NUM_CPU_CORES> running_thread_idle_counts{}; 506 std::array<u64, Core::Hardware::NUM_CPU_CORES> running_thread_idle_counts{};
473 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> pinned_threads{}; 507 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> pinned_threads{};
508 std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> watchpoints{};
509 std::map<VAddr, u64> debug_page_refcounts;
474 510
475 KThread* exception_thread{}; 511 KThread* exception_thread{};
476 512
477 KLightLock state_lock; 513 KLightLock state_lock;
514 KLightLock list_lock;
478 515
479 using TLPTree = 516 using TLPTree =
480 Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>; 517 Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
diff --git a/src/core/hle/kernel/k_readable_event.cpp b/src/core/hle/kernel/k_readable_event.cpp
index dddba554d..94c5464fe 100644
--- a/src/core/hle/kernel/k_readable_event.cpp
+++ b/src/core/hle/kernel/k_readable_event.cpp
@@ -27,7 +27,7 @@ void KReadableEvent::Destroy() {
27 } 27 }
28} 28}
29 29
30ResultCode KReadableEvent::Signal() { 30Result KReadableEvent::Signal() {
31 KScopedSchedulerLock lk{kernel}; 31 KScopedSchedulerLock lk{kernel};
32 32
33 if (!is_signaled) { 33 if (!is_signaled) {
@@ -38,13 +38,13 @@ ResultCode KReadableEvent::Signal() {
38 return ResultSuccess; 38 return ResultSuccess;
39} 39}
40 40
41ResultCode KReadableEvent::Clear() { 41Result KReadableEvent::Clear() {
42 Reset(); 42 Reset();
43 43
44 return ResultSuccess; 44 return ResultSuccess;
45} 45}
46 46
47ResultCode KReadableEvent::Reset() { 47Result KReadableEvent::Reset() {
48 KScopedSchedulerLock lk{kernel}; 48 KScopedSchedulerLock lk{kernel};
49 49
50 if (!is_signaled) { 50 if (!is_signaled) {
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
index 5065c7cc0..18dcad289 100644
--- a/src/core/hle/kernel/k_readable_event.h
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -33,9 +33,9 @@ public:
33 bool IsSignaled() const override; 33 bool IsSignaled() const override;
34 void Destroy() override; 34 void Destroy() override;
35 35
36 ResultCode Signal(); 36 Result Signal();
37 ResultCode Clear(); 37 Result Clear();
38 ResultCode Reset(); 38 Result Reset();
39 39
40private: 40private:
41 bool is_signaled{}; 41 bool is_signaled{};
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index 3e0ecffdb..010dcf99e 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -73,7 +73,7 @@ s64 KResourceLimit::GetFreeValue(LimitableResource which) const {
73 return value; 73 return value;
74} 74}
75 75
76ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { 76Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
77 const auto index = static_cast<std::size_t>(which); 77 const auto index = static_cast<std::size_t>(which);
78 KScopedLightLock lk(lock); 78 KScopedLightLock lk(lock);
79 R_UNLESS(current_values[index] <= value, ResultInvalidState); 79 R_UNLESS(current_values[index] <= value, ResultInvalidState);
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 43bf74b8d..65c98c979 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -8,7 +8,7 @@
8#include "core/hle/kernel/k_light_condition_variable.h" 8#include "core/hle/kernel/k_light_condition_variable.h"
9#include "core/hle/kernel/k_light_lock.h" 9#include "core/hle/kernel/k_light_lock.h"
10 10
11union ResultCode; 11union Result;
12 12
13namespace Core::Timing { 13namespace Core::Timing {
14class CoreTiming; 14class CoreTiming;
@@ -46,7 +46,7 @@ public:
46 s64 GetPeakValue(LimitableResource which) const; 46 s64 GetPeakValue(LimitableResource which) const;
47 s64 GetFreeValue(LimitableResource which) const; 47 s64 GetFreeValue(LimitableResource which) const;
48 48
49 ResultCode SetLimitValue(LimitableResource which, s64 value); 49 Result SetLimitValue(LimitableResource which, s64 value);
50 50
51 bool Reserve(LimitableResource which, s64 value); 51 bool Reserve(LimitableResource which, s64 value);
52 bool Reserve(LimitableResource which, s64 value, s64 timeout); 52 bool Reserve(LimitableResource which, s64 value, s64 timeout);
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 2d4e8637b..d586b3f5c 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -317,7 +317,7 @@ void KScheduler::RotateScheduledQueue(s32 cpu_core_id, s32 priority) {
317 317
318 { 318 {
319 KThread* best_thread = priority_queue.GetScheduledFront(cpu_core_id); 319 KThread* best_thread = priority_queue.GetScheduledFront(cpu_core_id);
320 if (best_thread == GetCurrentThread()) { 320 if (best_thread == GetCurrentThreadPointer(kernel)) {
321 best_thread = priority_queue.GetScheduledNext(cpu_core_id, best_thread); 321 best_thread = priority_queue.GetScheduledNext(cpu_core_id, best_thread);
322 } 322 }
323 323
@@ -424,7 +424,7 @@ void KScheduler::YieldWithoutCoreMigration(KernelCore& kernel) {
424 ASSERT(kernel.CurrentProcess() != nullptr); 424 ASSERT(kernel.CurrentProcess() != nullptr);
425 425
426 // Get the current thread and process. 426 // Get the current thread and process.
427 KThread& cur_thread = Kernel::GetCurrentThread(kernel); 427 KThread& cur_thread = GetCurrentThread(kernel);
428 KProcess& cur_process = *kernel.CurrentProcess(); 428 KProcess& cur_process = *kernel.CurrentProcess();
429 429
430 // If the thread's yield count matches, there's nothing for us to do. 430 // If the thread's yield count matches, there's nothing for us to do.
@@ -463,7 +463,7 @@ void KScheduler::YieldWithCoreMigration(KernelCore& kernel) {
463 ASSERT(kernel.CurrentProcess() != nullptr); 463 ASSERT(kernel.CurrentProcess() != nullptr);
464 464
465 // Get the current thread and process. 465 // Get the current thread and process.
466 KThread& cur_thread = Kernel::GetCurrentThread(kernel); 466 KThread& cur_thread = GetCurrentThread(kernel);
467 KProcess& cur_process = *kernel.CurrentProcess(); 467 KProcess& cur_process = *kernel.CurrentProcess();
468 468
469 // If the thread's yield count matches, there's nothing for us to do. 469 // If the thread's yield count matches, there's nothing for us to do.
@@ -551,7 +551,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) {
551 ASSERT(kernel.CurrentProcess() != nullptr); 551 ASSERT(kernel.CurrentProcess() != nullptr);
552 552
553 // Get the current thread and process. 553 // Get the current thread and process.
554 KThread& cur_thread = Kernel::GetCurrentThread(kernel); 554 KThread& cur_thread = GetCurrentThread(kernel);
555 KProcess& cur_process = *kernel.CurrentProcess(); 555 KProcess& cur_process = *kernel.CurrentProcess();
556 556
557 // If the thread's yield count matches, there's nothing for us to do. 557 // If the thread's yield count matches, there's nothing for us to do.
@@ -642,7 +642,7 @@ KScheduler::~KScheduler() {
642 ASSERT(!idle_thread); 642 ASSERT(!idle_thread);
643} 643}
644 644
645KThread* KScheduler::GetCurrentThread() const { 645KThread* KScheduler::GetSchedulerCurrentThread() const {
646 if (auto result = current_thread.load(); result) { 646 if (auto result = current_thread.load(); result) {
647 return result; 647 return result;
648 } 648 }
@@ -654,7 +654,7 @@ u64 KScheduler::GetLastContextSwitchTicks() const {
654} 654}
655 655
656void KScheduler::RescheduleCurrentCore() { 656void KScheduler::RescheduleCurrentCore() {
657 ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1); 657 ASSERT(GetCurrentThread(system.Kernel()).GetDisableDispatchCount() == 1);
658 658
659 auto& phys_core = system.Kernel().PhysicalCore(core_id); 659 auto& phys_core = system.Kernel().PhysicalCore(core_id);
660 if (phys_core.IsInterrupted()) { 660 if (phys_core.IsInterrupted()) {
@@ -665,7 +665,7 @@ void KScheduler::RescheduleCurrentCore() {
665 if (state.needs_scheduling.load()) { 665 if (state.needs_scheduling.load()) {
666 Schedule(); 666 Schedule();
667 } else { 667 } else {
668 GetCurrentThread()->EnableDispatch(); 668 GetCurrentThread(system.Kernel()).EnableDispatch();
669 guard.Unlock(); 669 guard.Unlock();
670 } 670 }
671} 671}
@@ -710,6 +710,7 @@ void KScheduler::Reload(KThread* thread) {
710 Core::ARM_Interface& cpu_core = system.ArmInterface(core_id); 710 Core::ARM_Interface& cpu_core = system.ArmInterface(core_id);
711 cpu_core.LoadContext(thread->GetContext32()); 711 cpu_core.LoadContext(thread->GetContext32());
712 cpu_core.LoadContext(thread->GetContext64()); 712 cpu_core.LoadContext(thread->GetContext64());
713 cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints());
713 cpu_core.SetTlsAddress(thread->GetTLSAddress()); 714 cpu_core.SetTlsAddress(thread->GetTLSAddress());
714 cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0()); 715 cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0());
715 cpu_core.ClearExclusiveState(); 716 cpu_core.ClearExclusiveState();
@@ -717,13 +718,18 @@ void KScheduler::Reload(KThread* thread) {
717 718
718void KScheduler::SwitchContextStep2() { 719void KScheduler::SwitchContextStep2() {
719 // Load context of new thread 720 // Load context of new thread
720 Reload(GetCurrentThread()); 721 Reload(GetCurrentThreadPointer(system.Kernel()));
721 722
722 RescheduleCurrentCore(); 723 RescheduleCurrentCore();
723} 724}
724 725
726void KScheduler::Schedule() {
727 ASSERT(GetCurrentThread(system.Kernel()).GetDisableDispatchCount() == 1);
728 this->ScheduleImpl();
729}
730
725void KScheduler::ScheduleImpl() { 731void KScheduler::ScheduleImpl() {
726 KThread* previous_thread = GetCurrentThread(); 732 KThread* previous_thread = GetCurrentThreadPointer(system.Kernel());
727 KThread* next_thread = state.highest_priority_thread; 733 KThread* next_thread = state.highest_priority_thread;
728 734
729 state.needs_scheduling.store(false); 735 state.needs_scheduling.store(false);
@@ -761,6 +767,7 @@ void KScheduler::ScheduleImpl() {
761 old_context = &previous_thread->GetHostContext(); 767 old_context = &previous_thread->GetHostContext();
762 768
763 // Set the new thread. 769 // Set the new thread.
770 SetCurrentThread(system.Kernel(), next_thread);
764 current_thread.store(next_thread); 771 current_thread.store(next_thread);
765 772
766 guard.Unlock(); 773 guard.Unlock();
@@ -804,6 +811,7 @@ void KScheduler::SwitchToCurrent() {
804 } 811 }
805 } 812 }
806 auto thread = next_thread ? next_thread : idle_thread; 813 auto thread = next_thread ? next_thread : idle_thread;
814 SetCurrentThread(system.Kernel(), thread);
807 Common::Fiber::YieldTo(switch_fiber, *thread->GetHostContext()); 815 Common::Fiber::YieldTo(switch_fiber, *thread->GetHostContext());
808 } while (!is_switch_pending()); 816 } while (!is_switch_pending());
809 } 817 }
@@ -829,6 +837,7 @@ void KScheduler::Initialize() {
829 idle_thread = KThread::Create(system.Kernel()); 837 idle_thread = KThread::Create(system.Kernel());
830 ASSERT(KThread::InitializeIdleThread(system, idle_thread, core_id).IsSuccess()); 838 ASSERT(KThread::InitializeIdleThread(system, idle_thread, core_id).IsSuccess());
831 idle_thread->SetName(fmt::format("IdleThread:{}", core_id)); 839 idle_thread->SetName(fmt::format("IdleThread:{}", core_id));
840 idle_thread->EnableDispatch();
832} 841}
833 842
834KScopedSchedulerLock::KScopedSchedulerLock(KernelCore& kernel) 843KScopedSchedulerLock::KScopedSchedulerLock(KernelCore& kernel)
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index 729e006f2..cc3da33f5 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -48,7 +48,7 @@ public:
48 void Reload(KThread* thread); 48 void Reload(KThread* thread);
49 49
50 /// Gets the current running thread 50 /// Gets the current running thread
51 [[nodiscard]] KThread* GetCurrentThread() const; 51 [[nodiscard]] KThread* GetSchedulerCurrentThread() const;
52 52
53 /// Gets the idle thread 53 /// Gets the idle thread
54 [[nodiscard]] KThread* GetIdleThread() const { 54 [[nodiscard]] KThread* GetIdleThread() const {
@@ -57,7 +57,7 @@ public:
57 57
58 /// Returns true if the scheduler is idle 58 /// Returns true if the scheduler is idle
59 [[nodiscard]] bool IsIdle() const { 59 [[nodiscard]] bool IsIdle() const {
60 return GetCurrentThread() == idle_thread; 60 return GetSchedulerCurrentThread() == idle_thread;
61 } 61 }
62 62
63 /// Gets the timestamp for the last context switch in ticks. 63 /// Gets the timestamp for the last context switch in ticks.
@@ -149,10 +149,7 @@ private:
149 149
150 void RotateScheduledQueue(s32 cpu_core_id, s32 priority); 150 void RotateScheduledQueue(s32 cpu_core_id, s32 priority);
151 151
152 void Schedule() { 152 void Schedule();
153 ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1);
154 this->ScheduleImpl();
155 }
156 153
157 /// Switches the CPU's active thread context to that of the specified thread 154 /// Switches the CPU's active thread context to that of the specified thread
158 void ScheduleImpl(); 155 void ScheduleImpl();
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 7e39f6d50..802c646a6 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -79,7 +79,7 @@ std::size_t KServerSession::NumDomainRequestHandlers() const {
79 return manager->DomainHandlerCount(); 79 return manager->DomainHandlerCount();
80} 80}
81 81
82ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) { 82Result KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
83 if (!context.HasDomainMessageHeader()) { 83 if (!context.HasDomainMessageHeader()) {
84 return ResultSuccess; 84 return ResultSuccess;
85 } 85 }
@@ -97,13 +97,13 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co
97 "object_id {} is too big! This probably means a recent service call " 97 "object_id {} is too big! This probably means a recent service call "
98 "to {} needed to return a new interface!", 98 "to {} needed to return a new interface!",
99 object_id, name); 99 object_id, name);
100 UNREACHABLE(); 100 ASSERT(false);
101 return ResultSuccess; // Ignore error if asserts are off 101 return ResultSuccess; // Ignore error if asserts are off
102 } 102 }
103 if (auto strong_ptr = manager->DomainHandler(object_id - 1).lock()) { 103 if (auto strong_ptr = manager->DomainHandler(object_id - 1).lock()) {
104 return strong_ptr->HandleSyncRequest(*this, context); 104 return strong_ptr->HandleSyncRequest(*this, context);
105 } else { 105 } else {
106 UNREACHABLE(); 106 ASSERT(false);
107 return ResultSuccess; 107 return ResultSuccess;
108 } 108 }
109 109
@@ -123,7 +123,7 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co
123 return ResultSuccess; 123 return ResultSuccess;
124} 124}
125 125
126ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) { 126Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) {
127 u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))}; 127 u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))};
128 auto context = std::make_shared<HLERequestContext>(kernel, memory, this, thread); 128 auto context = std::make_shared<HLERequestContext>(kernel, memory, this, thread);
129 129
@@ -143,8 +143,8 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor
143 return ResultSuccess; 143 return ResultSuccess;
144} 144}
145 145
146ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { 146Result KServerSession::CompleteSyncRequest(HLERequestContext& context) {
147 ResultCode result = ResultSuccess; 147 Result result = ResultSuccess;
148 148
149 // If the session has been converted to a domain, handle the domain request 149 // If the session has been converted to a domain, handle the domain request
150 if (manager->HasSessionRequestHandler(context)) { 150 if (manager->HasSessionRequestHandler(context)) {
@@ -173,8 +173,8 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) {
173 return result; 173 return result;
174} 174}
175 175
176ResultCode KServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, 176Result KServerSession::HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory,
177 Core::Timing::CoreTiming& core_timing) { 177 Core::Timing::CoreTiming& core_timing) {
178 return QueueSyncRequest(thread, memory); 178 return QueueSyncRequest(thread, memory);
179} 179}
180 180
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index b628a843f..6d0821945 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -73,10 +73,10 @@ public:
73 * @param memory Memory context to handle the sync request under. 73 * @param memory Memory context to handle the sync request under.
74 * @param core_timing Core timing context to schedule the request event under. 74 * @param core_timing Core timing context to schedule the request event under.
75 * 75 *
76 * @returns ResultCode from the operation. 76 * @returns Result from the operation.
77 */ 77 */
78 ResultCode HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory, 78 Result HandleSyncRequest(KThread* thread, Core::Memory::Memory& memory,
79 Core::Timing::CoreTiming& core_timing); 79 Core::Timing::CoreTiming& core_timing);
80 80
81 /// Adds a new domain request handler to the collection of request handlers within 81 /// Adds a new domain request handler to the collection of request handlers within
82 /// this ServerSession instance. 82 /// this ServerSession instance.
@@ -103,14 +103,14 @@ public:
103 103
104private: 104private:
105 /// Queues a sync request from the emulated application. 105 /// Queues a sync request from the emulated application.
106 ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory); 106 Result QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory);
107 107
108 /// Completes a sync request from the emulated application. 108 /// Completes a sync request from the emulated application.
109 ResultCode CompleteSyncRequest(HLERequestContext& context); 109 Result CompleteSyncRequest(HLERequestContext& context);
110 110
111 /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an 111 /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an
112 /// object handle. 112 /// object handle.
113 ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context); 113 Result HandleDomainSyncRequest(Kernel::HLERequestContext& context);
114 114
115 /// This session's HLE request handlers 115 /// This session's HLE request handlers
116 std::shared_ptr<SessionRequestManager> manager; 116 std::shared_ptr<SessionRequestManager> manager;
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp
index 51d7538ca..b77735736 100644
--- a/src/core/hle/kernel/k_shared_memory.cpp
+++ b/src/core/hle/kernel/k_shared_memory.cpp
@@ -18,12 +18,10 @@ KSharedMemory::~KSharedMemory() {
18 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); 18 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size);
19} 19}
20 20
21ResultCode KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, 21Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_,
22 KPageLinkedList&& page_list_, 22 KPageGroup&& page_list_, Svc::MemoryPermission owner_permission_,
23 Svc::MemoryPermission owner_permission_, 23 Svc::MemoryPermission user_permission_, PAddr physical_address_,
24 Svc::MemoryPermission user_permission_, 24 std::size_t size_, std::string name_) {
25 PAddr physical_address_, std::size_t size_,
26 std::string name_) {
27 // Set members. 25 // Set members.
28 owner_process = owner_process_; 26 owner_process = owner_process_;
29 device_memory = &device_memory_; 27 device_memory = &device_memory_;
@@ -67,8 +65,8 @@ void KSharedMemory::Finalize() {
67 KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize(); 65 KAutoObjectWithSlabHeapAndContainer<KSharedMemory, KAutoObjectWithList>::Finalize();
68} 66}
69 67
70ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size, 68Result KSharedMemory::Map(KProcess& target_process, VAddr address, std::size_t map_size,
71 Svc::MemoryPermission permissions) { 69 Svc::MemoryPermission permissions) {
72 const u64 page_count{(map_size + PageSize - 1) / PageSize}; 70 const u64 page_count{(map_size + PageSize - 1) / PageSize};
73 71
74 if (page_list.GetNumPages() != page_count) { 72 if (page_list.GetNumPages() != page_count) {
@@ -86,7 +84,7 @@ ResultCode KSharedMemory::Map(KProcess& target_process, VAddr address, std::size
86 ConvertToKMemoryPermission(permissions)); 84 ConvertToKMemoryPermission(permissions));
87} 85}
88 86
89ResultCode KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) { 87Result KSharedMemory::Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size) {
90 const u64 page_count{(unmap_size + PageSize - 1) / PageSize}; 88 const u64 page_count{(unmap_size + PageSize - 1) / PageSize};
91 89
92 if (page_list.GetNumPages() != page_count) { 90 if (page_list.GetNumPages() != page_count) {
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index 81de36136..2c1db0e70 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -9,7 +9,7 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/device_memory.h" 10#include "core/device_memory.h"
11#include "core/hle/kernel/k_memory_block.h" 11#include "core/hle/kernel/k_memory_block.h"
12#include "core/hle/kernel/k_page_linked_list.h" 12#include "core/hle/kernel/k_page_group.h"
13#include "core/hle/kernel/k_process.h" 13#include "core/hle/kernel/k_process.h"
14#include "core/hle/kernel/slab_helpers.h" 14#include "core/hle/kernel/slab_helpers.h"
15#include "core/hle/result.h" 15#include "core/hle/result.h"
@@ -26,10 +26,10 @@ public:
26 explicit KSharedMemory(KernelCore& kernel_); 26 explicit KSharedMemory(KernelCore& kernel_);
27 ~KSharedMemory() override; 27 ~KSharedMemory() override;
28 28
29 ResultCode Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, 29 Result Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_,
30 KPageLinkedList&& page_list_, Svc::MemoryPermission owner_permission_, 30 KPageGroup&& page_list_, Svc::MemoryPermission owner_permission_,
31 Svc::MemoryPermission user_permission_, PAddr physical_address_, 31 Svc::MemoryPermission user_permission_, PAddr physical_address_,
32 std::size_t size_, std::string name_); 32 std::size_t size_, std::string name_);
33 33
34 /** 34 /**
35 * Maps a shared memory block to an address in the target process' address space 35 * Maps a shared memory block to an address in the target process' address space
@@ -38,8 +38,8 @@ public:
38 * @param map_size Size of the shared memory block to map 38 * @param map_size Size of the shared memory block to map
39 * @param permissions Memory block map permissions (specified by SVC field) 39 * @param permissions Memory block map permissions (specified by SVC field)
40 */ 40 */
41 ResultCode Map(KProcess& target_process, VAddr address, std::size_t map_size, 41 Result Map(KProcess& target_process, VAddr address, std::size_t map_size,
42 Svc::MemoryPermission permissions); 42 Svc::MemoryPermission permissions);
43 43
44 /** 44 /**
45 * Unmaps a shared memory block from an address in the target process' address space 45 * Unmaps a shared memory block from an address in the target process' address space
@@ -47,7 +47,7 @@ public:
47 * @param address Address in system memory to unmap shared memory block 47 * @param address Address in system memory to unmap shared memory block
48 * @param unmap_size Size of the shared memory block to unmap 48 * @param unmap_size Size of the shared memory block to unmap
49 */ 49 */
50 ResultCode Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size); 50 Result Unmap(KProcess& target_process, VAddr address, std::size_t unmap_size);
51 51
52 /** 52 /**
53 * Gets a pointer to the shared memory block 53 * Gets a pointer to the shared memory block
@@ -77,7 +77,7 @@ public:
77private: 77private:
78 Core::DeviceMemory* device_memory; 78 Core::DeviceMemory* device_memory;
79 KProcess* owner_process{}; 79 KProcess* owner_process{};
80 KPageLinkedList page_list; 80 KPageGroup page_list;
81 Svc::MemoryPermission owner_permission{}; 81 Svc::MemoryPermission owner_permission{};
82 Svc::MemoryPermission user_permission{}; 82 Svc::MemoryPermission user_permission{};
83 PAddr physical_address{}; 83 PAddr physical_address{};
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp
index 8554144d5..802dca046 100644
--- a/src/core/hle/kernel/k_synchronization_object.cpp
+++ b/src/core/hle/kernel/k_synchronization_object.cpp
@@ -22,7 +22,7 @@ public:
22 : KThreadQueueWithoutEndWait(kernel_), m_objects(o), m_nodes(n), m_count(c) {} 22 : KThreadQueueWithoutEndWait(kernel_), m_objects(o), m_nodes(n), m_count(c) {}
23 23
24 void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, 24 void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object,
25 ResultCode wait_result) override { 25 Result wait_result) override {
26 // Determine the sync index, and unlink all nodes. 26 // Determine the sync index, and unlink all nodes.
27 s32 sync_index = -1; 27 s32 sync_index = -1;
28 for (auto i = 0; i < m_count; ++i) { 28 for (auto i = 0; i < m_count; ++i) {
@@ -45,8 +45,7 @@ public:
45 KThreadQueue::EndWait(waiting_thread, wait_result); 45 KThreadQueue::EndWait(waiting_thread, wait_result);
46 } 46 }
47 47
48 void CancelWait(KThread* waiting_thread, ResultCode wait_result, 48 void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override {
49 bool cancel_timer_task) override {
50 // Remove all nodes from our list. 49 // Remove all nodes from our list.
51 for (auto i = 0; i < m_count; ++i) { 50 for (auto i = 0; i < m_count; ++i) {
52 m_objects[i]->UnlinkNode(std::addressof(m_nodes[i])); 51 m_objects[i]->UnlinkNode(std::addressof(m_nodes[i]));
@@ -72,9 +71,9 @@ void KSynchronizationObject::Finalize() {
72 KAutoObject::Finalize(); 71 KAutoObject::Finalize();
73} 72}
74 73
75ResultCode KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, 74Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
76 KSynchronizationObject** objects, const s32 num_objects, 75 KSynchronizationObject** objects, const s32 num_objects,
77 s64 timeout) { 76 s64 timeout) {
78 // Allocate space on stack for thread nodes. 77 // Allocate space on stack for thread nodes.
79 std::vector<ThreadListNode> thread_nodes(num_objects); 78 std::vector<ThreadListNode> thread_nodes(num_objects);
80 79
@@ -148,7 +147,7 @@ KSynchronizationObject::KSynchronizationObject(KernelCore& kernel_)
148 147
149KSynchronizationObject::~KSynchronizationObject() = default; 148KSynchronizationObject::~KSynchronizationObject() = default;
150 149
151void KSynchronizationObject::NotifyAvailable(ResultCode result) { 150void KSynchronizationObject::NotifyAvailable(Result result) {
152 KScopedSchedulerLock sl(kernel); 151 KScopedSchedulerLock sl(kernel);
153 152
154 // If we're not signaled, we've nothing to notify. 153 // If we're not signaled, we've nothing to notify.
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index d7540d6c7..8d8122ab7 100644
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -24,9 +24,9 @@ public:
24 KThread* thread{}; 24 KThread* thread{};
25 }; 25 };
26 26
27 [[nodiscard]] static ResultCode Wait(KernelCore& kernel, s32* out_index, 27 [[nodiscard]] static Result Wait(KernelCore& kernel, s32* out_index,
28 KSynchronizationObject** objects, const s32 num_objects, 28 KSynchronizationObject** objects, const s32 num_objects,
29 s64 timeout); 29 s64 timeout);
30 30
31 void Finalize() override; 31 void Finalize() override;
32 32
@@ -72,7 +72,7 @@ protected:
72 72
73 virtual void OnFinalizeSynchronizationObject() {} 73 virtual void OnFinalizeSynchronizationObject() {}
74 74
75 void NotifyAvailable(ResultCode result); 75 void NotifyAvailable(Result result);
76 void NotifyAvailable() { 76 void NotifyAvailable() {
77 return this->NotifyAvailable(ResultSuccess); 77 return this->NotifyAvailable(ResultSuccess);
78 } 78 }
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 940334f59..8d7faa662 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -80,8 +80,7 @@ public:
80 explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel_, KThread::WaiterList* wl) 80 explicit ThreadQueueImplForKThreadSetProperty(KernelCore& kernel_, KThread::WaiterList* wl)
81 : KThreadQueue(kernel_), m_wait_list(wl) {} 81 : KThreadQueue(kernel_), m_wait_list(wl) {}
82 82
83 void CancelWait(KThread* waiting_thread, ResultCode wait_result, 83 void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override {
84 bool cancel_timer_task) override {
85 // Remove the thread from the wait list. 84 // Remove the thread from the wait list.
86 m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); 85 m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread));
87 86
@@ -99,8 +98,8 @@ KThread::KThread(KernelCore& kernel_)
99 : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {} 98 : KAutoObjectWithSlabHeapAndContainer{kernel_}, activity_pause_lock{kernel_} {}
100KThread::~KThread() = default; 99KThread::~KThread() = default;
101 100
102ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio, 101Result KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, s32 prio,
103 s32 virt_core, KProcess* owner, ThreadType type) { 102 s32 virt_core, KProcess* owner, ThreadType type) {
104 // Assert parameters are valid. 103 // Assert parameters are valid.
105 ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) || 104 ASSERT((type == ThreadType::Main) || (type == ThreadType::Dummy) ||
106 (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority)); 105 (Svc::HighestThreadPriority <= prio && prio <= Svc::LowestThreadPriority));
@@ -133,7 +132,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
133 UNIMPLEMENTED(); 132 UNIMPLEMENTED();
134 break; 133 break;
135 default: 134 default:
136 UNREACHABLE_MSG("KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type)); 135 ASSERT_MSG(false, "KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type));
137 break; 136 break;
138 } 137 }
139 thread_type = type; 138 thread_type = type;
@@ -225,7 +224,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
225 // Setup the stack parameters. 224 // Setup the stack parameters.
226 StackParameters& sp = GetStackParameters(); 225 StackParameters& sp = GetStackParameters();
227 sp.cur_thread = this; 226 sp.cur_thread = this;
228 sp.disable_count = 0; 227 sp.disable_count = 1;
229 SetInExceptionHandler(); 228 SetInExceptionHandler();
230 229
231 // Set thread ID. 230 // Set thread ID.
@@ -245,10 +244,10 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
245 return ResultSuccess; 244 return ResultSuccess;
246} 245}
247 246
248ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg, 247Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_t arg,
249 VAddr user_stack_top, s32 prio, s32 core, KProcess* owner, 248 VAddr user_stack_top, s32 prio, s32 core, KProcess* owner,
250 ThreadType type, std::function<void(void*)>&& init_func, 249 ThreadType type, std::function<void(void*)>&& init_func,
251 void* init_func_parameter) { 250 void* init_func_parameter) {
252 // Initialize the thread. 251 // Initialize the thread.
253 R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type)); 252 R_TRY(thread->Initialize(func, arg, user_stack_top, prio, core, owner, type));
254 253
@@ -260,31 +259,30 @@ ResultCode KThread::InitializeThread(KThread* thread, KThreadFunction func, uint
260 return ResultSuccess; 259 return ResultSuccess;
261} 260}
262 261
263ResultCode KThread::InitializeDummyThread(KThread* thread) { 262Result KThread::InitializeDummyThread(KThread* thread) {
264 return thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy); 263 return thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy);
265} 264}
266 265
267ResultCode KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { 266Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) {
268 return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, 267 return InitializeThread(thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main,
269 Core::CpuManager::GetIdleThreadStartFunc(), 268 Core::CpuManager::GetIdleThreadStartFunc(),
270 system.GetCpuManager().GetStartFuncParamater()); 269 system.GetCpuManager().GetStartFuncParameter());
271} 270}
272 271
273ResultCode KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, 272Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread,
274 KThreadFunction func, uintptr_t arg, 273 KThreadFunction func, uintptr_t arg, s32 virt_core) {
275 s32 virt_core) {
276 return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, 274 return InitializeThread(thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority,
277 Core::CpuManager::GetSuspendThreadStartFunc(), 275 Core::CpuManager::GetShutdownThreadStartFunc(),
278 system.GetCpuManager().GetStartFuncParamater()); 276 system.GetCpuManager().GetStartFuncParameter());
279} 277}
280 278
281ResultCode KThread::InitializeUserThread(Core::System& system, KThread* thread, 279Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func,
282 KThreadFunction func, uintptr_t arg, VAddr user_stack_top, 280 uintptr_t arg, VAddr user_stack_top, s32 prio, s32 virt_core,
283 s32 prio, s32 virt_core, KProcess* owner) { 281 KProcess* owner) {
284 system.Kernel().GlobalSchedulerContext().AddThread(thread); 282 system.Kernel().GlobalSchedulerContext().AddThread(thread);
285 return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, 283 return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner,
286 ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(), 284 ThreadType::User, Core::CpuManager::GetGuestThreadStartFunc(),
287 system.GetCpuManager().GetStartFuncParamater()); 285 system.GetCpuManager().GetStartFuncParameter());
288} 286}
289 287
290void KThread::PostDestroy(uintptr_t arg) { 288void KThread::PostDestroy(uintptr_t arg) {
@@ -382,7 +380,7 @@ void KThread::FinishTermination() {
382 for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) { 380 for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
383 KThread* core_thread{}; 381 KThread* core_thread{};
384 do { 382 do {
385 core_thread = kernel.Scheduler(i).GetCurrentThread(); 383 core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread();
386 } while (core_thread == this); 384 } while (core_thread == this);
387 } 385 }
388 } 386 }
@@ -523,7 +521,7 @@ void KThread::ClearInterruptFlag() {
523 memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0); 521 memory.Write16(tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
524} 522}
525 523
526ResultCode KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { 524Result KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
527 KScopedSchedulerLock sl{kernel}; 525 KScopedSchedulerLock sl{kernel};
528 526
529 // Get the virtual mask. 527 // Get the virtual mask.
@@ -533,7 +531,7 @@ ResultCode KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
533 return ResultSuccess; 531 return ResultSuccess;
534} 532}
535 533
536ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { 534Result KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
537 KScopedSchedulerLock sl{kernel}; 535 KScopedSchedulerLock sl{kernel};
538 ASSERT(num_core_migration_disables >= 0); 536 ASSERT(num_core_migration_disables >= 0);
539 537
@@ -549,7 +547,7 @@ ResultCode KThread::GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_m
549 return ResultSuccess; 547 return ResultSuccess;
550} 548}
551 549
552ResultCode KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) { 550Result KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) {
553 ASSERT(parent != nullptr); 551 ASSERT(parent != nullptr);
554 ASSERT(v_affinity_mask != 0); 552 ASSERT(v_affinity_mask != 0);
555 KScopedLightLock lk(activity_pause_lock); 553 KScopedLightLock lk(activity_pause_lock);
@@ -631,7 +629,7 @@ ResultCode KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) {
631 s32 thread_core; 629 s32 thread_core;
632 for (thread_core = 0; thread_core < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); 630 for (thread_core = 0; thread_core < static_cast<s32>(Core::Hardware::NUM_CPU_CORES);
633 ++thread_core) { 631 ++thread_core) {
634 if (kernel.Scheduler(thread_core).GetCurrentThread() == this) { 632 if (kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) {
635 thread_is_current = true; 633 thread_is_current = true;
636 break; 634 break;
637 } 635 }
@@ -748,7 +746,20 @@ void KThread::Continue() {
748 KScheduler::OnThreadStateChanged(kernel, this, old_state); 746 KScheduler::OnThreadStateChanged(kernel, this, old_state);
749} 747}
750 748
751ResultCode KThread::SetActivity(Svc::ThreadActivity activity) { 749void KThread::WaitUntilSuspended() {
750 // Make sure we have a suspend requested.
751 ASSERT(IsSuspendRequested());
752
753 // Loop until the thread is not executing on any core.
754 for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
755 KThread* core_thread{};
756 do {
757 core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread();
758 } while (core_thread == this);
759 }
760}
761
762Result KThread::SetActivity(Svc::ThreadActivity activity) {
752 // Lock ourselves. 763 // Lock ourselves.
753 KScopedLightLock lk(activity_pause_lock); 764 KScopedLightLock lk(activity_pause_lock);
754 765
@@ -809,7 +820,7 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
809 // Check if the thread is currently running. 820 // Check if the thread is currently running.
810 // If it is, we'll need to retry. 821 // If it is, we'll need to retry.
811 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { 822 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
812 if (kernel.Scheduler(i).GetCurrentThread() == this) { 823 if (kernel.Scheduler(i).GetSchedulerCurrentThread() == this) {
813 thread_is_current = true; 824 thread_is_current = true;
814 break; 825 break;
815 } 826 }
@@ -821,7 +832,7 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
821 return ResultSuccess; 832 return ResultSuccess;
822} 833}
823 834
824ResultCode KThread::GetThreadContext3(std::vector<u8>& out) { 835Result KThread::GetThreadContext3(std::vector<u8>& out) {
825 // Lock ourselves. 836 // Lock ourselves.
826 KScopedLightLock lk{activity_pause_lock}; 837 KScopedLightLock lk{activity_pause_lock};
827 838
@@ -986,7 +997,7 @@ KThread* KThread::RemoveWaiterByKey(s32* out_num_waiters, VAddr key) {
986 return next_lock_owner; 997 return next_lock_owner;
987} 998}
988 999
989ResultCode KThread::Run() { 1000Result KThread::Run() {
990 while (true) { 1001 while (true) {
991 KScopedSchedulerLock lk{kernel}; 1002 KScopedSchedulerLock lk{kernel};
992 1003
@@ -1014,8 +1025,6 @@ ResultCode KThread::Run() {
1014 // Set our state and finish. 1025 // Set our state and finish.
1015 SetState(ThreadState::Runnable); 1026 SetState(ThreadState::Runnable);
1016 1027
1017 DisableDispatch();
1018
1019 return ResultSuccess; 1028 return ResultSuccess;
1020 } 1029 }
1021} 1030}
@@ -1049,7 +1058,7 @@ void KThread::Exit() {
1049 } 1058 }
1050} 1059}
1051 1060
1052ResultCode KThread::Sleep(s64 timeout) { 1061Result KThread::Sleep(s64 timeout) {
1053 ASSERT(!kernel.GlobalSchedulerContext().IsLocked()); 1062 ASSERT(!kernel.GlobalSchedulerContext().IsLocked());
1054 ASSERT(this == GetCurrentThreadPointer(kernel)); 1063 ASSERT(this == GetCurrentThreadPointer(kernel));
1055 ASSERT(timeout > 0); 1064 ASSERT(timeout > 0);
@@ -1105,7 +1114,7 @@ void KThread::BeginWait(KThreadQueue* queue) {
1105 wait_queue = queue; 1114 wait_queue = queue;
1106} 1115}
1107 1116
1108void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_) { 1117void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result_) {
1109 // Lock the scheduler. 1118 // Lock the scheduler.
1110 KScopedSchedulerLock sl(kernel); 1119 KScopedSchedulerLock sl(kernel);
1111 1120
@@ -1115,7 +1124,7 @@ void KThread::NotifyAvailable(KSynchronizationObject* signaled_object, ResultCod
1115 } 1124 }
1116} 1125}
1117 1126
1118void KThread::EndWait(ResultCode wait_result_) { 1127void KThread::EndWait(Result wait_result_) {
1119 // Lock the scheduler. 1128 // Lock the scheduler.
1120 KScopedSchedulerLock sl(kernel); 1129 KScopedSchedulerLock sl(kernel);
1121 1130
@@ -1134,7 +1143,7 @@ void KThread::EndWait(ResultCode wait_result_) {
1134 } 1143 }
1135} 1144}
1136 1145
1137void KThread::CancelWait(ResultCode wait_result_, bool cancel_timer_task) { 1146void KThread::CancelWait(Result wait_result_, bool cancel_timer_task) {
1138 // Lock the scheduler. 1147 // Lock the scheduler.
1139 KScopedSchedulerLock sl(kernel); 1148 KScopedSchedulerLock sl(kernel);
1140 1149
@@ -1164,6 +1173,10 @@ std::shared_ptr<Common::Fiber>& KThread::GetHostContext() {
1164 return host_context; 1173 return host_context;
1165} 1174}
1166 1175
1176void SetCurrentThread(KernelCore& kernel, KThread* thread) {
1177 kernel.SetCurrentEmuThread(thread);
1178}
1179
1167KThread* GetCurrentThreadPointer(KernelCore& kernel) { 1180KThread* GetCurrentThreadPointer(KernelCore& kernel) {
1168 return kernel.GetCurrentEmuThread(); 1181 return kernel.GetCurrentEmuThread();
1169} 1182}
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index f4d83f99a..94c4cd1c8 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -106,6 +106,7 @@ enum class StepState : u32 {
106 StepPerformed, ///< Thread has stepped, waiting to be scheduled again 106 StepPerformed, ///< Thread has stepped, waiting to be scheduled again
107}; 107};
108 108
109void SetCurrentThread(KernelCore& kernel, KThread* thread);
109[[nodiscard]] KThread* GetCurrentThreadPointer(KernelCore& kernel); 110[[nodiscard]] KThread* GetCurrentThreadPointer(KernelCore& kernel);
110[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); 111[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
111[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); 112[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
@@ -175,7 +176,7 @@ public:
175 176
176 void SetBasePriority(s32 value); 177 void SetBasePriority(s32 value);
177 178
178 [[nodiscard]] ResultCode Run(); 179 [[nodiscard]] Result Run();
179 180
180 void Exit(); 181 void Exit();
181 182
@@ -207,6 +208,8 @@ public:
207 208
208 void Continue(); 209 void Continue();
209 210
211 void WaitUntilSuspended();
212
210 constexpr void SetSyncedIndex(s32 index) { 213 constexpr void SetSyncedIndex(s32 index) {
211 synced_index = index; 214 synced_index = index;
212 } 215 }
@@ -215,11 +218,11 @@ public:
215 return synced_index; 218 return synced_index;
216 } 219 }
217 220
218 constexpr void SetWaitResult(ResultCode wait_res) { 221 constexpr void SetWaitResult(Result wait_res) {
219 wait_result = wait_res; 222 wait_result = wait_res;
220 } 223 }
221 224
222 [[nodiscard]] constexpr ResultCode GetWaitResult() const { 225 [[nodiscard]] constexpr Result GetWaitResult() const {
223 return wait_result; 226 return wait_result;
224 } 227 }
225 228
@@ -342,15 +345,15 @@ public:
342 return physical_affinity_mask; 345 return physical_affinity_mask;
343 } 346 }
344 347
345 [[nodiscard]] ResultCode GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask); 348 [[nodiscard]] Result GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask);
346 349
347 [[nodiscard]] ResultCode GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask); 350 [[nodiscard]] Result GetPhysicalCoreMask(s32* out_ideal_core, u64* out_affinity_mask);
348 351
349 [[nodiscard]] ResultCode SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask); 352 [[nodiscard]] Result SetCoreMask(s32 cpu_core_id, u64 v_affinity_mask);
350 353
351 [[nodiscard]] ResultCode SetActivity(Svc::ThreadActivity activity); 354 [[nodiscard]] Result SetActivity(Svc::ThreadActivity activity);
352 355
353 [[nodiscard]] ResultCode Sleep(s64 timeout); 356 [[nodiscard]] Result Sleep(s64 timeout);
354 357
355 [[nodiscard]] s64 GetYieldScheduleCount() const { 358 [[nodiscard]] s64 GetYieldScheduleCount() const {
356 return schedule_count; 359 return schedule_count;
@@ -408,20 +411,19 @@ public:
408 411
409 static void PostDestroy(uintptr_t arg); 412 static void PostDestroy(uintptr_t arg);
410 413
411 [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); 414 [[nodiscard]] static Result InitializeDummyThread(KThread* thread);
412 415
413 [[nodiscard]] static ResultCode InitializeIdleThread(Core::System& system, KThread* thread, 416 [[nodiscard]] static Result InitializeIdleThread(Core::System& system, KThread* thread,
414 s32 virt_core); 417 s32 virt_core);
415 418
416 [[nodiscard]] static ResultCode InitializeHighPriorityThread(Core::System& system, 419 [[nodiscard]] static Result InitializeHighPriorityThread(Core::System& system, KThread* thread,
417 KThread* thread, 420 KThreadFunction func, uintptr_t arg,
418 KThreadFunction func, 421 s32 virt_core);
419 uintptr_t arg, s32 virt_core);
420 422
421 [[nodiscard]] static ResultCode InitializeUserThread(Core::System& system, KThread* thread, 423 [[nodiscard]] static Result InitializeUserThread(Core::System& system, KThread* thread,
422 KThreadFunction func, uintptr_t arg, 424 KThreadFunction func, uintptr_t arg,
423 VAddr user_stack_top, s32 prio, 425 VAddr user_stack_top, s32 prio, s32 virt_core,
424 s32 virt_core, KProcess* owner); 426 KProcess* owner);
425 427
426public: 428public:
427 struct StackParameters { 429 struct StackParameters {
@@ -607,7 +609,7 @@ public:
607 609
608 void RemoveWaiter(KThread* thread); 610 void RemoveWaiter(KThread* thread);
609 611
610 [[nodiscard]] ResultCode GetThreadContext3(std::vector<u8>& out); 612 [[nodiscard]] Result GetThreadContext3(std::vector<u8>& out);
611 613
612 [[nodiscard]] KThread* RemoveWaiterByKey(s32* out_num_waiters, VAddr key); 614 [[nodiscard]] KThread* RemoveWaiterByKey(s32* out_num_waiters, VAddr key);
613 615
@@ -633,9 +635,9 @@ public:
633 } 635 }
634 636
635 void BeginWait(KThreadQueue* queue); 637 void BeginWait(KThreadQueue* queue);
636 void NotifyAvailable(KSynchronizationObject* signaled_object, ResultCode wait_result_); 638 void NotifyAvailable(KSynchronizationObject* signaled_object, Result wait_result_);
637 void EndWait(ResultCode wait_result_); 639 void EndWait(Result wait_result_);
638 void CancelWait(ResultCode wait_result_, bool cancel_timer_task); 640 void CancelWait(Result wait_result_, bool cancel_timer_task);
639 641
640 [[nodiscard]] bool HasWaiters() const { 642 [[nodiscard]] bool HasWaiters() const {
641 return !waiter_list.empty(); 643 return !waiter_list.empty();
@@ -721,14 +723,14 @@ private:
721 723
722 void FinishTermination(); 724 void FinishTermination();
723 725
724 [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, 726 [[nodiscard]] Result Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top,
725 s32 prio, s32 virt_core, KProcess* owner, ThreadType type); 727 s32 prio, s32 virt_core, KProcess* owner, ThreadType type);
726 728
727 [[nodiscard]] static ResultCode InitializeThread(KThread* thread, KThreadFunction func, 729 [[nodiscard]] static Result InitializeThread(KThread* thread, KThreadFunction func,
728 uintptr_t arg, VAddr user_stack_top, s32 prio, 730 uintptr_t arg, VAddr user_stack_top, s32 prio,
729 s32 core, KProcess* owner, ThreadType type, 731 s32 core, KProcess* owner, ThreadType type,
730 std::function<void(void*)>&& init_func, 732 std::function<void(void*)>&& init_func,
731 void* init_func_parameter); 733 void* init_func_parameter);
732 734
733 static void RestorePriority(KernelCore& kernel_ctx, KThread* thread); 735 static void RestorePriority(KernelCore& kernel_ctx, KThread* thread);
734 736
@@ -765,7 +767,7 @@ private:
765 u32 suspend_request_flags{}; 767 u32 suspend_request_flags{};
766 u32 suspend_allowed_flags{}; 768 u32 suspend_allowed_flags{};
767 s32 synced_index{}; 769 s32 synced_index{};
768 ResultCode wait_result{ResultSuccess}; 770 Result wait_result{ResultSuccess};
769 s32 base_priority{}; 771 s32 base_priority{};
770 s32 physical_ideal_core_id{}; 772 s32 physical_ideal_core_id{};
771 s32 virtual_ideal_core_id{}; 773 s32 virtual_ideal_core_id{};
diff --git a/src/core/hle/kernel/k_thread_local_page.cpp b/src/core/hle/kernel/k_thread_local_page.cpp
index fbdc40b3a..563560114 100644
--- a/src/core/hle/kernel/k_thread_local_page.cpp
+++ b/src/core/hle/kernel/k_thread_local_page.cpp
@@ -13,7 +13,7 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16ResultCode KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) { 16Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
17 // Set that this process owns us. 17 // Set that this process owns us.
18 m_owner = process; 18 m_owner = process;
19 m_kernel = &kernel; 19 m_kernel = &kernel;
@@ -35,7 +35,7 @@ ResultCode KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
35 return ResultSuccess; 35 return ResultSuccess;
36} 36}
37 37
38ResultCode KThreadLocalPage::Finalize() { 38Result KThreadLocalPage::Finalize() {
39 // Get the physical address of the page. 39 // Get the physical address of the page.
40 const PAddr phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr); 40 const PAddr phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr);
41 ASSERT(phys_addr); 41 ASSERT(phys_addr);
diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h
index a4fe43ee5..0a7f22680 100644
--- a/src/core/hle/kernel/k_thread_local_page.h
+++ b/src/core/hle/kernel/k_thread_local_page.h
@@ -34,8 +34,8 @@ public:
34 return m_virt_addr; 34 return m_virt_addr;
35 } 35 }
36 36
37 ResultCode Initialize(KernelCore& kernel, KProcess* process); 37 Result Initialize(KernelCore& kernel, KProcess* process);
38 ResultCode Finalize(); 38 Result Finalize();
39 39
40 VAddr Reserve(); 40 VAddr Reserve();
41 void Release(VAddr addr); 41 void Release(VAddr addr);
diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp
index 1c338904a..9f4e081ba 100644
--- a/src/core/hle/kernel/k_thread_queue.cpp
+++ b/src/core/hle/kernel/k_thread_queue.cpp
@@ -9,9 +9,9 @@ namespace Kernel {
9 9
10void KThreadQueue::NotifyAvailable([[maybe_unused]] KThread* waiting_thread, 10void KThreadQueue::NotifyAvailable([[maybe_unused]] KThread* waiting_thread,
11 [[maybe_unused]] KSynchronizationObject* signaled_object, 11 [[maybe_unused]] KSynchronizationObject* signaled_object,
12 [[maybe_unused]] ResultCode wait_result) {} 12 [[maybe_unused]] Result wait_result) {}
13 13
14void KThreadQueue::EndWait(KThread* waiting_thread, ResultCode wait_result) { 14void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) {
15 // Set the thread's wait result. 15 // Set the thread's wait result.
16 waiting_thread->SetWaitResult(wait_result); 16 waiting_thread->SetWaitResult(wait_result);
17 17
@@ -25,8 +25,7 @@ void KThreadQueue::EndWait(KThread* waiting_thread, ResultCode wait_result) {
25 kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); 25 kernel.TimeManager().UnscheduleTimeEvent(waiting_thread);
26} 26}
27 27
28void KThreadQueue::CancelWait(KThread* waiting_thread, ResultCode wait_result, 28void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) {
29 bool cancel_timer_task) {
30 // Set the thread's wait result. 29 // Set the thread's wait result.
31 waiting_thread->SetWaitResult(wait_result); 30 waiting_thread->SetWaitResult(wait_result);
32 31
@@ -43,6 +42,6 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, ResultCode wait_result,
43} 42}
44 43
45void KThreadQueueWithoutEndWait::EndWait([[maybe_unused]] KThread* waiting_thread, 44void KThreadQueueWithoutEndWait::EndWait([[maybe_unused]] KThread* waiting_thread,
46 [[maybe_unused]] ResultCode wait_result) {} 45 [[maybe_unused]] Result wait_result) {}
47 46
48} // namespace Kernel 47} // namespace Kernel
diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h
index 4a7dbdd47..8d76ece81 100644
--- a/src/core/hle/kernel/k_thread_queue.h
+++ b/src/core/hle/kernel/k_thread_queue.h
@@ -14,10 +14,9 @@ public:
14 virtual ~KThreadQueue() = default; 14 virtual ~KThreadQueue() = default;
15 15
16 virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, 16 virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object,
17 ResultCode wait_result); 17 Result wait_result);
18 virtual void EndWait(KThread* waiting_thread, ResultCode wait_result); 18 virtual void EndWait(KThread* waiting_thread, Result wait_result);
19 virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, 19 virtual void CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task);
20 bool cancel_timer_task);
21 20
22private: 21private:
23 KernelCore& kernel; 22 KernelCore& kernel;
@@ -28,7 +27,7 @@ class KThreadQueueWithoutEndWait : public KThreadQueue {
28public: 27public:
29 explicit KThreadQueueWithoutEndWait(KernelCore& kernel_) : KThreadQueue(kernel_) {} 28 explicit KThreadQueueWithoutEndWait(KernelCore& kernel_) : KThreadQueue(kernel_) {}
30 29
31 void EndWait(KThread* waiting_thread, ResultCode wait_result) override final; 30 void EndWait(KThread* waiting_thread, Result wait_result) override final;
32}; 31};
33 32
34} // namespace Kernel 33} // namespace Kernel
diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp
index 1ed4b0f6f..b0320eb73 100644
--- a/src/core/hle/kernel/k_transfer_memory.cpp
+++ b/src/core/hle/kernel/k_transfer_memory.cpp
@@ -13,8 +13,8 @@ KTransferMemory::KTransferMemory(KernelCore& kernel_)
13 13
14KTransferMemory::~KTransferMemory() = default; 14KTransferMemory::~KTransferMemory() = default;
15 15
16ResultCode KTransferMemory::Initialize(VAddr address_, std::size_t size_, 16Result KTransferMemory::Initialize(VAddr address_, std::size_t size_,
17 Svc::MemoryPermission owner_perm_) { 17 Svc::MemoryPermission owner_perm_) {
18 // Set members. 18 // Set members.
19 owner = kernel.CurrentProcess(); 19 owner = kernel.CurrentProcess();
20 20
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h
index 9ad80ba30..85d508ee7 100644
--- a/src/core/hle/kernel/k_transfer_memory.h
+++ b/src/core/hle/kernel/k_transfer_memory.h
@@ -7,7 +7,7 @@
7#include "core/hle/kernel/svc_types.h" 7#include "core/hle/kernel/svc_types.h"
8#include "core/hle/result.h" 8#include "core/hle/result.h"
9 9
10union ResultCode; 10union Result;
11 11
12namespace Core::Memory { 12namespace Core::Memory {
13class Memory; 13class Memory;
@@ -26,7 +26,7 @@ public:
26 explicit KTransferMemory(KernelCore& kernel_); 26 explicit KTransferMemory(KernelCore& kernel_);
27 ~KTransferMemory() override; 27 ~KTransferMemory() override;
28 28
29 ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); 29 Result Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_);
30 30
31 void Finalize() override; 31 void Finalize() override;
32 32
diff --git a/src/core/hle/kernel/k_writable_event.cpp b/src/core/hle/kernel/k_writable_event.cpp
index 26c8489ad..ff88c5acd 100644
--- a/src/core/hle/kernel/k_writable_event.cpp
+++ b/src/core/hle/kernel/k_writable_event.cpp
@@ -18,11 +18,11 @@ void KWritableEvent::Initialize(KEvent* parent_event_, std::string&& name_) {
18 parent->GetReadableEvent().Open(); 18 parent->GetReadableEvent().Open();
19} 19}
20 20
21ResultCode KWritableEvent::Signal() { 21Result KWritableEvent::Signal() {
22 return parent->GetReadableEvent().Signal(); 22 return parent->GetReadableEvent().Signal();
23} 23}
24 24
25ResultCode KWritableEvent::Clear() { 25Result KWritableEvent::Clear() {
26 return parent->GetReadableEvent().Clear(); 26 return parent->GetReadableEvent().Clear();
27} 27}
28 28
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
index e289e80c4..3fd0c7d0a 100644
--- a/src/core/hle/kernel/k_writable_event.h
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -25,8 +25,8 @@ public:
25 static void PostDestroy([[maybe_unused]] uintptr_t arg) {} 25 static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
26 26
27 void Initialize(KEvent* parent_, std::string&& name_); 27 void Initialize(KEvent* parent_, std::string&& name_);
28 ResultCode Signal(); 28 Result Signal();
29 ResultCode Clear(); 29 Result Clear();
30 30
31 KEvent* GetParent() const { 31 KEvent* GetParent() const {
32 return parent; 32 return parent;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 92f6d8c49..0009193be 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -76,7 +76,7 @@ struct KernelCore::Impl {
76 InitializeMemoryLayout(); 76 InitializeMemoryLayout();
77 Init::InitializeKPageBufferSlabHeap(system); 77 Init::InitializeKPageBufferSlabHeap(system);
78 InitializeSchedulers(); 78 InitializeSchedulers();
79 InitializeSuspendThreads(); 79 InitializeShutdownThreads();
80 InitializePreemption(kernel); 80 InitializePreemption(kernel);
81 81
82 RegisterHostThread(); 82 RegisterHostThread();
@@ -143,9 +143,9 @@ struct KernelCore::Impl {
143 CleanupObject(system_resource_limit); 143 CleanupObject(system_resource_limit);
144 144
145 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 145 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
146 if (suspend_threads[core_id]) { 146 if (shutdown_threads[core_id]) {
147 suspend_threads[core_id]->Close(); 147 shutdown_threads[core_id]->Close();
148 suspend_threads[core_id] = nullptr; 148 shutdown_threads[core_id] = nullptr;
149 } 149 }
150 150
151 schedulers[core_id]->Finalize(); 151 schedulers[core_id]->Finalize();
@@ -212,7 +212,9 @@ struct KernelCore::Impl {
212 system_resource_limit = KResourceLimit::Create(system.Kernel()); 212 system_resource_limit = KResourceLimit::Create(system.Kernel());
213 system_resource_limit->Initialize(&core_timing); 213 system_resource_limit->Initialize(&core_timing);
214 214
215 const auto [total_size, kernel_size] = memory_layout->GetTotalAndKernelMemorySizes(); 215 const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()};
216 const auto total_size{sizes.first};
217 const auto kernel_size{sizes.second};
216 218
217 // If setting the default system values fails, then something seriously wrong has occurred. 219 // If setting the default system values fails, then something seriously wrong has occurred.
218 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size) 220 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size)
@@ -245,13 +247,13 @@ struct KernelCore::Impl {
245 system.CoreTiming().ScheduleEvent(time_interval, preemption_event); 247 system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
246 } 248 }
247 249
248 void InitializeSuspendThreads() { 250 void InitializeShutdownThreads() {
249 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 251 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
250 suspend_threads[core_id] = KThread::Create(system.Kernel()); 252 shutdown_threads[core_id] = KThread::Create(system.Kernel());
251 ASSERT(KThread::InitializeHighPriorityThread(system, suspend_threads[core_id], {}, {}, 253 ASSERT(KThread::InitializeHighPriorityThread(system, shutdown_threads[core_id], {}, {},
252 core_id) 254 core_id)
253 .IsSuccess()); 255 .IsSuccess());
254 suspend_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id)); 256 shutdown_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id));
255 } 257 }
256 } 258 }
257 259
@@ -329,6 +331,8 @@ struct KernelCore::Impl {
329 return is_shutting_down.load(std::memory_order_relaxed); 331 return is_shutting_down.load(std::memory_order_relaxed);
330 } 332 }
331 333
334 static inline thread_local KThread* current_thread{nullptr};
335
332 KThread* GetCurrentEmuThread() { 336 KThread* GetCurrentEmuThread() {
333 // If we are shutting down the kernel, none of this is relevant anymore. 337 // If we are shutting down the kernel, none of this is relevant anymore.
334 if (IsShuttingDown()) { 338 if (IsShuttingDown()) {
@@ -339,7 +343,12 @@ struct KernelCore::Impl {
339 if (thread_id >= Core::Hardware::NUM_CPU_CORES) { 343 if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
340 return GetHostDummyThread(); 344 return GetHostDummyThread();
341 } 345 }
342 return schedulers[thread_id]->GetCurrentThread(); 346
347 return current_thread;
348 }
349
350 void SetCurrentEmuThread(KThread* thread) {
351 current_thread = thread;
343 } 352 }
344 353
345 void DeriveInitialMemoryLayout() { 354 void DeriveInitialMemoryLayout() {
@@ -766,7 +775,7 @@ struct KernelCore::Impl {
766 std::weak_ptr<ServiceThread> default_service_thread; 775 std::weak_ptr<ServiceThread> default_service_thread;
767 Common::ThreadWorker service_threads_manager; 776 Common::ThreadWorker service_threads_manager;
768 777
769 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; 778 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
770 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; 779 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
771 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 780 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
772 781
@@ -917,6 +926,12 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
917 return *impl->global_object_list_container; 926 return *impl->global_object_list_container;
918} 927}
919 928
929void KernelCore::InterruptAllPhysicalCores() {
930 for (auto& physical_core : impl->cores) {
931 physical_core.Interrupt();
932 }
933}
934
920void KernelCore::InvalidateAllInstructionCaches() { 935void KernelCore::InvalidateAllInstructionCaches() {
921 for (auto& physical_core : impl->cores) { 936 for (auto& physical_core : impl->cores) {
922 physical_core.ArmInterface().ClearInstructionCache(); 937 physical_core.ArmInterface().ClearInstructionCache();
@@ -1016,6 +1031,10 @@ KThread* KernelCore::GetCurrentEmuThread() const {
1016 return impl->GetCurrentEmuThread(); 1031 return impl->GetCurrentEmuThread();
1017} 1032}
1018 1033
1034void KernelCore::SetCurrentEmuThread(KThread* thread) {
1035 impl->SetCurrentEmuThread(thread);
1036}
1037
1019KMemoryManager& KernelCore::MemoryManager() { 1038KMemoryManager& KernelCore::MemoryManager() {
1020 return *impl->memory_manager; 1039 return *impl->memory_manager;
1021} 1040}
@@ -1064,22 +1083,29 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
1064 return *impl->hidbus_shared_mem; 1083 return *impl->hidbus_shared_mem;
1065} 1084}
1066 1085
1067void KernelCore::Suspend(bool in_suspention) { 1086void KernelCore::Suspend(bool suspended) {
1068 const bool should_suspend = exception_exited || in_suspention; 1087 const bool should_suspend{exception_exited || suspended};
1069 { 1088 const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
1070 KScopedSchedulerLock lock(*this); 1089
1071 const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; 1090 for (auto* process : GetProcessList()) {
1072 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 1091 process->SetActivity(activity);
1073 impl->suspend_threads[core_id]->SetState(state); 1092
1074 impl->suspend_threads[core_id]->SetWaitReasonForDebugging( 1093 if (should_suspend) {
1075 ThreadWaitReasonForDebugging::Suspended); 1094 // Wait for execution to stop
1076 if (!should_suspend) { 1095 for (auto* thread : process->GetThreadList()) {
1077 impl->suspend_threads[core_id]->DisableDispatch(); 1096 thread->WaitUntilSuspended();
1078 } 1097 }
1079 } 1098 }
1080 } 1099 }
1081} 1100}
1082 1101
1102void KernelCore::ShutdownCores() {
1103 for (auto* thread : impl->shutdown_threads) {
1104 void(thread->Run());
1105 }
1106 InterruptAllPhysicalCores();
1107}
1108
1083bool KernelCore::IsMulticore() const { 1109bool KernelCore::IsMulticore() const {
1084 return impl->is_multicore; 1110 return impl->is_multicore;
1085} 1111}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 926e14c6f..aa0ebaa02 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -184,6 +184,8 @@ public:
184 184
185 const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; 185 const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const;
186 186
187 void InterruptAllPhysicalCores();
188
187 void InvalidateAllInstructionCaches(); 189 void InvalidateAllInstructionCaches();
188 190
189 void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); 191 void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
@@ -224,6 +226,9 @@ public:
224 /// Gets the current host_thread/guest_thread pointer. 226 /// Gets the current host_thread/guest_thread pointer.
225 KThread* GetCurrentEmuThread() const; 227 KThread* GetCurrentEmuThread() const;
226 228
229 /// Sets the current guest_thread pointer.
230 void SetCurrentEmuThread(KThread* thread);
231
227 /// Gets the current host_thread handle. 232 /// Gets the current host_thread handle.
228 u32 GetCurrentHostThreadID() const; 233 u32 GetCurrentHostThreadID() const;
229 234
@@ -269,12 +274,15 @@ public:
269 /// Gets the shared memory object for HIDBus services. 274 /// Gets the shared memory object for HIDBus services.
270 const Kernel::KSharedMemory& GetHidBusSharedMem() const; 275 const Kernel::KSharedMemory& GetHidBusSharedMem() const;
271 276
272 /// Suspend/unsuspend the OS. 277 /// Suspend/unsuspend all processes.
273 void Suspend(bool in_suspention); 278 void Suspend(bool suspend);
274 279
275 /// Exceptional exit the OS. 280 /// Exceptional exit all processes.
276 void ExceptionalExit(); 281 void ExceptionalExit();
277 282
283 /// Notify emulated CPU cores to shut down.
284 void ShutdownCores();
285
278 bool IsMulticore() const; 286 bool IsMulticore() const;
279 287
280 bool IsShuttingDown() const; 288 bool IsShuttingDown() const;
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp
index 54872626e..773319ad8 100644
--- a/src/core/hle/kernel/process_capability.cpp
+++ b/src/core/hle/kernel/process_capability.cpp
@@ -68,9 +68,9 @@ u32 GetFlagBitOffset(CapabilityType type) {
68 68
69} // Anonymous namespace 69} // Anonymous namespace
70 70
71ResultCode ProcessCapabilities::InitializeForKernelProcess(const u32* capabilities, 71Result ProcessCapabilities::InitializeForKernelProcess(const u32* capabilities,
72 std::size_t num_capabilities, 72 std::size_t num_capabilities,
73 KPageTable& page_table) { 73 KPageTable& page_table) {
74 Clear(); 74 Clear();
75 75
76 // Allow all cores and priorities. 76 // Allow all cores and priorities.
@@ -81,9 +81,9 @@ ResultCode ProcessCapabilities::InitializeForKernelProcess(const u32* capabiliti
81 return ParseCapabilities(capabilities, num_capabilities, page_table); 81 return ParseCapabilities(capabilities, num_capabilities, page_table);
82} 82}
83 83
84ResultCode ProcessCapabilities::InitializeForUserProcess(const u32* capabilities, 84Result ProcessCapabilities::InitializeForUserProcess(const u32* capabilities,
85 std::size_t num_capabilities, 85 std::size_t num_capabilities,
86 KPageTable& page_table) { 86 KPageTable& page_table) {
87 Clear(); 87 Clear();
88 88
89 return ParseCapabilities(capabilities, num_capabilities, page_table); 89 return ParseCapabilities(capabilities, num_capabilities, page_table);
@@ -107,9 +107,8 @@ void ProcessCapabilities::InitializeForMetadatalessProcess() {
107 can_force_debug = true; 107 can_force_debug = true;
108} 108}
109 109
110ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, 110Result ProcessCapabilities::ParseCapabilities(const u32* capabilities, std::size_t num_capabilities,
111 std::size_t num_capabilities, 111 KPageTable& page_table) {
112 KPageTable& page_table) {
113 u32 set_flags = 0; 112 u32 set_flags = 0;
114 u32 set_svc_bits = 0; 113 u32 set_svc_bits = 0;
115 114
@@ -155,8 +154,8 @@ ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities,
155 return ResultSuccess; 154 return ResultSuccess;
156} 155}
157 156
158ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, 157Result ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag,
159 u32 flag, KPageTable& page_table) { 158 KPageTable& page_table) {
160 const auto type = GetCapabilityType(flag); 159 const auto type = GetCapabilityType(flag);
161 160
162 if (type == CapabilityType::Unset) { 161 if (type == CapabilityType::Unset) {
@@ -224,7 +223,7 @@ void ProcessCapabilities::Clear() {
224 can_force_debug = false; 223 can_force_debug = false;
225} 224}
226 225
227ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) { 226Result ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) {
228 if (priority_mask != 0 || core_mask != 0) { 227 if (priority_mask != 0 || core_mask != 0) {
229 LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}", 228 LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}",
230 priority_mask, core_mask); 229 priority_mask, core_mask);
@@ -266,7 +265,7 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) {
266 return ResultSuccess; 265 return ResultSuccess;
267} 266}
268 267
269ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) { 268Result ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) {
270 const u32 index = flags >> 29; 269 const u32 index = flags >> 29;
271 const u32 svc_bit = 1U << index; 270 const u32 svc_bit = 1U << index;
272 271
@@ -290,23 +289,23 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags)
290 return ResultSuccess; 289 return ResultSuccess;
291} 290}
292 291
293ResultCode ProcessCapabilities::HandleMapPhysicalFlags(u32 flags, u32 size_flags, 292Result ProcessCapabilities::HandleMapPhysicalFlags(u32 flags, u32 size_flags,
294 KPageTable& page_table) { 293 KPageTable& page_table) {
295 // TODO(Lioncache): Implement once the memory manager can handle this. 294 // TODO(Lioncache): Implement once the memory manager can handle this.
296 return ResultSuccess; 295 return ResultSuccess;
297} 296}
298 297
299ResultCode ProcessCapabilities::HandleMapIOFlags(u32 flags, KPageTable& page_table) { 298Result ProcessCapabilities::HandleMapIOFlags(u32 flags, KPageTable& page_table) {
300 // TODO(Lioncache): Implement once the memory manager can handle this. 299 // TODO(Lioncache): Implement once the memory manager can handle this.
301 return ResultSuccess; 300 return ResultSuccess;
302} 301}
303 302
304ResultCode ProcessCapabilities::HandleMapRegionFlags(u32 flags, KPageTable& page_table) { 303Result ProcessCapabilities::HandleMapRegionFlags(u32 flags, KPageTable& page_table) {
305 // TODO(Lioncache): Implement once the memory manager can handle this. 304 // TODO(Lioncache): Implement once the memory manager can handle this.
306 return ResultSuccess; 305 return ResultSuccess;
307} 306}
308 307
309ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) { 308Result ProcessCapabilities::HandleInterruptFlags(u32 flags) {
310 constexpr u32 interrupt_ignore_value = 0x3FF; 309 constexpr u32 interrupt_ignore_value = 0x3FF;
311 const u32 interrupt0 = (flags >> 12) & 0x3FF; 310 const u32 interrupt0 = (flags >> 12) & 0x3FF;
312 const u32 interrupt1 = (flags >> 22) & 0x3FF; 311 const u32 interrupt1 = (flags >> 22) & 0x3FF;
@@ -333,7 +332,7 @@ ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) {
333 return ResultSuccess; 332 return ResultSuccess;
334} 333}
335 334
336ResultCode ProcessCapabilities::HandleProgramTypeFlags(u32 flags) { 335Result ProcessCapabilities::HandleProgramTypeFlags(u32 flags) {
337 const u32 reserved = flags >> 17; 336 const u32 reserved = flags >> 17;
338 if (reserved != 0) { 337 if (reserved != 0) {
339 LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); 338 LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
@@ -344,7 +343,7 @@ ResultCode ProcessCapabilities::HandleProgramTypeFlags(u32 flags) {
344 return ResultSuccess; 343 return ResultSuccess;
345} 344}
346 345
347ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) { 346Result ProcessCapabilities::HandleKernelVersionFlags(u32 flags) {
348 // Yes, the internal member variable is checked in the actual kernel here. 347 // Yes, the internal member variable is checked in the actual kernel here.
349 // This might look odd for options that are only allowed to be initialized 348 // This might look odd for options that are only allowed to be initialized
350 // just once, however the kernel has a separate initialization function for 349 // just once, however the kernel has a separate initialization function for
@@ -364,7 +363,7 @@ ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) {
364 return ResultSuccess; 363 return ResultSuccess;
365} 364}
366 365
367ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) { 366Result ProcessCapabilities::HandleHandleTableFlags(u32 flags) {
368 const u32 reserved = flags >> 26; 367 const u32 reserved = flags >> 26;
369 if (reserved != 0) { 368 if (reserved != 0) {
370 LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); 369 LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
@@ -375,7 +374,7 @@ ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) {
375 return ResultSuccess; 374 return ResultSuccess;
376} 375}
377 376
378ResultCode ProcessCapabilities::HandleDebugFlags(u32 flags) { 377Result ProcessCapabilities::HandleDebugFlags(u32 flags) {
379 const u32 reserved = flags >> 19; 378 const u32 reserved = flags >> 19;
380 if (reserved != 0) { 379 if (reserved != 0) {
381 LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); 380 LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
diff --git a/src/core/hle/kernel/process_capability.h b/src/core/hle/kernel/process_capability.h
index 7f3a2339d..ff05dc5ff 100644
--- a/src/core/hle/kernel/process_capability.h
+++ b/src/core/hle/kernel/process_capability.h
@@ -7,7 +7,7 @@
7 7
8#include "common/common_types.h" 8#include "common/common_types.h"
9 9
10union ResultCode; 10union Result;
11 11
12namespace Kernel { 12namespace Kernel {
13 13
@@ -86,8 +86,8 @@ public:
86 /// @returns ResultSuccess if this capabilities instance was able to be initialized, 86 /// @returns ResultSuccess if this capabilities instance was able to be initialized,
87 /// otherwise, an error code upon failure. 87 /// otherwise, an error code upon failure.
88 /// 88 ///
89 ResultCode InitializeForKernelProcess(const u32* capabilities, std::size_t num_capabilities, 89 Result InitializeForKernelProcess(const u32* capabilities, std::size_t num_capabilities,
90 KPageTable& page_table); 90 KPageTable& page_table);
91 91
92 /// Initializes this process capabilities instance for a userland process. 92 /// Initializes this process capabilities instance for a userland process.
93 /// 93 ///
@@ -99,8 +99,8 @@ public:
99 /// @returns ResultSuccess if this capabilities instance was able to be initialized, 99 /// @returns ResultSuccess if this capabilities instance was able to be initialized,
100 /// otherwise, an error code upon failure. 100 /// otherwise, an error code upon failure.
101 /// 101 ///
102 ResultCode InitializeForUserProcess(const u32* capabilities, std::size_t num_capabilities, 102 Result InitializeForUserProcess(const u32* capabilities, std::size_t num_capabilities,
103 KPageTable& page_table); 103 KPageTable& page_table);
104 104
105 /// Initializes this process capabilities instance for a process that does not 105 /// Initializes this process capabilities instance for a process that does not
106 /// have any metadata to parse. 106 /// have any metadata to parse.
@@ -185,8 +185,8 @@ private:
185 /// 185 ///
186 /// @return ResultSuccess if no errors occur, otherwise an error code. 186 /// @return ResultSuccess if no errors occur, otherwise an error code.
187 /// 187 ///
188 ResultCode ParseCapabilities(const u32* capabilities, std::size_t num_capabilities, 188 Result ParseCapabilities(const u32* capabilities, std::size_t num_capabilities,
189 KPageTable& page_table); 189 KPageTable& page_table);
190 190
191 /// Attempts to parse a capability descriptor that is only represented by a 191 /// Attempts to parse a capability descriptor that is only represented by a
192 /// single flag set. 192 /// single flag set.
@@ -200,8 +200,8 @@ private:
200 /// 200 ///
201 /// @return ResultSuccess if no errors occurred, otherwise an error code. 201 /// @return ResultSuccess if no errors occurred, otherwise an error code.
202 /// 202 ///
203 ResultCode ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag, 203 Result ParseSingleFlagCapability(u32& set_flags, u32& set_svc_bits, u32 flag,
204 KPageTable& page_table); 204 KPageTable& page_table);
205 205
206 /// Clears the internal state of this process capability instance. Necessary, 206 /// Clears the internal state of this process capability instance. Necessary,
207 /// to have a sane starting point due to us allowing running executables without 207 /// to have a sane starting point due to us allowing running executables without
@@ -219,34 +219,34 @@ private:
219 void Clear(); 219 void Clear();
220 220
221 /// Handles flags related to the priority and core number capability flags. 221 /// Handles flags related to the priority and core number capability flags.
222 ResultCode HandlePriorityCoreNumFlags(u32 flags); 222 Result HandlePriorityCoreNumFlags(u32 flags);
223 223
224 /// Handles flags related to determining the allowable SVC mask. 224 /// Handles flags related to determining the allowable SVC mask.
225 ResultCode HandleSyscallFlags(u32& set_svc_bits, u32 flags); 225 Result HandleSyscallFlags(u32& set_svc_bits, u32 flags);
226 226
227 /// Handles flags related to mapping physical memory pages. 227 /// Handles flags related to mapping physical memory pages.
228 ResultCode HandleMapPhysicalFlags(u32 flags, u32 size_flags, KPageTable& page_table); 228 Result HandleMapPhysicalFlags(u32 flags, u32 size_flags, KPageTable& page_table);
229 229
230 /// Handles flags related to mapping IO pages. 230 /// Handles flags related to mapping IO pages.
231 ResultCode HandleMapIOFlags(u32 flags, KPageTable& page_table); 231 Result HandleMapIOFlags(u32 flags, KPageTable& page_table);
232 232
233 /// Handles flags related to mapping physical memory regions. 233 /// Handles flags related to mapping physical memory regions.
234 ResultCode HandleMapRegionFlags(u32 flags, KPageTable& page_table); 234 Result HandleMapRegionFlags(u32 flags, KPageTable& page_table);
235 235
236 /// Handles flags related to the interrupt capability flags. 236 /// Handles flags related to the interrupt capability flags.
237 ResultCode HandleInterruptFlags(u32 flags); 237 Result HandleInterruptFlags(u32 flags);
238 238
239 /// Handles flags related to the program type. 239 /// Handles flags related to the program type.
240 ResultCode HandleProgramTypeFlags(u32 flags); 240 Result HandleProgramTypeFlags(u32 flags);
241 241
242 /// Handles flags related to the handle table size. 242 /// Handles flags related to the handle table size.
243 ResultCode HandleHandleTableFlags(u32 flags); 243 Result HandleHandleTableFlags(u32 flags);
244 244
245 /// Handles flags related to the kernel version capability flags. 245 /// Handles flags related to the kernel version capability flags.
246 ResultCode HandleKernelVersionFlags(u32 flags); 246 Result HandleKernelVersionFlags(u32 flags);
247 247
248 /// Handles flags related to debug-specific capabilities. 248 /// Handles flags related to debug-specific capabilities.
249 ResultCode HandleDebugFlags(u32 flags); 249 Result HandleDebugFlags(u32 flags);
250 250
251 SyscallCapabilities svc_capabilities; 251 SyscallCapabilities svc_capabilities;
252 InterruptCapabilities interrupt_capabilities; 252 InterruptCapabilities interrupt_capabilities;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 66e0ce2d0..8655506b0 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -15,6 +15,7 @@
15#include "common/scope_exit.h" 15#include "common/scope_exit.h"
16#include "core/core.h" 16#include "core/core.h"
17#include "core/core_timing.h" 17#include "core/core_timing.h"
18#include "core/debugger/debugger.h"
18#include "core/hle/kernel/k_client_port.h" 19#include "core/hle/kernel/k_client_port.h"
19#include "core/hle/kernel/k_client_session.h" 20#include "core/hle/kernel/k_client_session.h"
20#include "core/hle/kernel/k_code_memory.h" 21#include "core/hle/kernel/k_code_memory.h"
@@ -57,8 +58,8 @@ constexpr bool IsValidAddressRange(VAddr address, u64 size) {
57// Helper function that performs the common sanity checks for svcMapMemory 58// Helper function that performs the common sanity checks for svcMapMemory
58// and svcUnmapMemory. This is doable, as both functions perform their sanitizing 59// and svcUnmapMemory. This is doable, as both functions perform their sanitizing
59// in the same order. 60// in the same order.
60ResultCode MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, VAddr src_addr, 61Result MapUnmapMemorySanityChecks(const KPageTable& manager, VAddr dst_addr, VAddr src_addr,
61 u64 size) { 62 u64 size) {
62 if (!Common::Is4KBAligned(dst_addr)) { 63 if (!Common::Is4KBAligned(dst_addr)) {
63 LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr); 64 LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
64 return ResultInvalidAddress; 65 return ResultInvalidAddress;
@@ -134,7 +135,7 @@ enum class ResourceLimitValueType {
134} // Anonymous namespace 135} // Anonymous namespace
135 136
136/// Set the process heap to a given Size. It can both extend and shrink the heap. 137/// Set the process heap to a given Size. It can both extend and shrink the heap.
137static ResultCode SetHeapSize(Core::System& system, VAddr* out_address, u64 size) { 138static Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
138 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size); 139 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size);
139 140
140 // Validate size. 141 // Validate size.
@@ -147,9 +148,9 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* out_address, u64 size
147 return ResultSuccess; 148 return ResultSuccess;
148} 149}
149 150
150static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size) { 151static Result SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size) {
151 VAddr temp_heap_addr{}; 152 VAddr temp_heap_addr{};
152 const ResultCode result{SetHeapSize(system, &temp_heap_addr, heap_size)}; 153 const Result result{SetHeapSize(system, &temp_heap_addr, heap_size)};
153 *heap_addr = static_cast<u32>(temp_heap_addr); 154 *heap_addr = static_cast<u32>(temp_heap_addr);
154 return result; 155 return result;
155} 156}
@@ -165,8 +166,8 @@ constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
165 } 166 }
166} 167}
167 168
168static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size, 169static Result SetMemoryPermission(Core::System& system, VAddr address, u64 size,
169 MemoryPermission perm) { 170 MemoryPermission perm) {
170 LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size=0x{:X}, perm=0x{:08X", address, size, 171 LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size=0x{:X}, perm=0x{:08X", address, size,
171 perm); 172 perm);
172 173
@@ -187,8 +188,8 @@ static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 s
187 return page_table.SetMemoryPermission(address, size, perm); 188 return page_table.SetMemoryPermission(address, size, perm);
188} 189}
189 190
190static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, 191static Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
191 u32 attr) { 192 u32 attr) {
192 LOG_DEBUG(Kernel_SVC, 193 LOG_DEBUG(Kernel_SVC,
193 "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, 194 "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
194 size, mask, attr); 195 size, mask, attr);
@@ -212,19 +213,19 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si
212 return page_table.SetMemoryAttribute(address, size, mask, attr); 213 return page_table.SetMemoryAttribute(address, size, mask, attr);
213} 214}
214 215
215static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, 216static Result SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask,
216 u32 attr) { 217 u32 attr) {
217 return SetMemoryAttribute(system, address, size, mask, attr); 218 return SetMemoryAttribute(system, address, size, mask, attr);
218} 219}
219 220
220/// Maps a memory range into a different range. 221/// Maps a memory range into a different range.
221static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { 222static Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
222 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 223 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
223 src_addr, size); 224 src_addr, size);
224 225
225 auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; 226 auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
226 227
227 if (const ResultCode result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)}; 228 if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
228 result.IsError()) { 229 result.IsError()) {
229 return result; 230 return result;
230 } 231 }
@@ -232,18 +233,18 @@ static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr
232 return page_table.MapMemory(dst_addr, src_addr, size); 233 return page_table.MapMemory(dst_addr, src_addr, size);
233} 234}
234 235
235static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { 236static Result MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) {
236 return MapMemory(system, dst_addr, src_addr, size); 237 return MapMemory(system, dst_addr, src_addr, size);
237} 238}
238 239
239/// Unmaps a region that was previously mapped with svcMapMemory 240/// Unmaps a region that was previously mapped with svcMapMemory
240static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { 241static Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
241 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 242 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
242 src_addr, size); 243 src_addr, size);
243 244
244 auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; 245 auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
245 246
246 if (const ResultCode result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)}; 247 if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
247 result.IsError()) { 248 result.IsError()) {
248 return result; 249 return result;
249 } 250 }
@@ -251,12 +252,12 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad
251 return page_table.UnmapMemory(dst_addr, src_addr, size); 252 return page_table.UnmapMemory(dst_addr, src_addr, size);
252} 253}
253 254
254static ResultCode UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) { 255static Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) {
255 return UnmapMemory(system, dst_addr, src_addr, size); 256 return UnmapMemory(system, dst_addr, src_addr, size);
256} 257}
257 258
258/// Connect to an OS service given the port name, returns the handle to the port to out 259/// Connect to an OS service given the port name, returns the handle to the port to out
259static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) { 260static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {
260 auto& memory = system.Memory(); 261 auto& memory = system.Memory();
261 if (!memory.IsValidVirtualAddress(port_name_address)) { 262 if (!memory.IsValidVirtualAddress(port_name_address)) {
262 LOG_ERROR(Kernel_SVC, 263 LOG_ERROR(Kernel_SVC,
@@ -306,14 +307,14 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out, VAddr po
306 return ResultSuccess; 307 return ResultSuccess;
307} 308}
308 309
309static ResultCode ConnectToNamedPort32(Core::System& system, Handle* out_handle, 310static Result ConnectToNamedPort32(Core::System& system, Handle* out_handle,
310 u32 port_name_address) { 311 u32 port_name_address) {
311 312
312 return ConnectToNamedPort(system, out_handle, port_name_address); 313 return ConnectToNamedPort(system, out_handle, port_name_address);
313} 314}
314 315
315/// Makes a blocking IPC call to an OS service. 316/// Makes a blocking IPC call to an OS service.
316static ResultCode SendSyncRequest(Core::System& system, Handle handle) { 317static Result SendSyncRequest(Core::System& system, Handle handle) {
317 auto& kernel = system.Kernel(); 318 auto& kernel = system.Kernel();
318 319
319 // Create the wait queue. 320 // Create the wait queue.
@@ -326,7 +327,6 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
326 327
327 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); 328 LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
328 329
329 auto thread = kernel.CurrentScheduler()->GetCurrentThread();
330 { 330 {
331 KScopedSchedulerLock lock(kernel); 331 KScopedSchedulerLock lock(kernel);
332 332
@@ -336,15 +336,15 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
336 session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), system.CoreTiming()); 336 session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), system.CoreTiming());
337 } 337 }
338 338
339 return thread->GetWaitResult(); 339 return GetCurrentThread(kernel).GetWaitResult();
340} 340}
341 341
342static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { 342static Result SendSyncRequest32(Core::System& system, Handle handle) {
343 return SendSyncRequest(system, handle); 343 return SendSyncRequest(system, handle);
344} 344}
345 345
346/// Get the ID for the specified thread. 346/// Get the ID for the specified thread.
347static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { 347static Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
348 // Get the thread from its handle. 348 // Get the thread from its handle.
349 KScopedAutoObject thread = 349 KScopedAutoObject thread =
350 system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); 350 system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
@@ -355,10 +355,10 @@ static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle t
355 return ResultSuccess; 355 return ResultSuccess;
356} 356}
357 357
358static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low, 358static Result GetThreadId32(Core::System& system, u32* out_thread_id_low, u32* out_thread_id_high,
359 u32* out_thread_id_high, Handle thread_handle) { 359 Handle thread_handle) {
360 u64 out_thread_id{}; 360 u64 out_thread_id{};
361 const ResultCode result{GetThreadId(system, &out_thread_id, thread_handle)}; 361 const Result result{GetThreadId(system, &out_thread_id, thread_handle)};
362 362
363 *out_thread_id_low = static_cast<u32>(out_thread_id >> 32); 363 *out_thread_id_low = static_cast<u32>(out_thread_id >> 32);
364 *out_thread_id_high = static_cast<u32>(out_thread_id & std::numeric_limits<u32>::max()); 364 *out_thread_id_high = static_cast<u32>(out_thread_id & std::numeric_limits<u32>::max());
@@ -367,7 +367,7 @@ static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low,
367} 367}
368 368
369/// Gets the ID of the specified process or a specified thread's owning process. 369/// Gets the ID of the specified process or a specified thread's owning process.
370static ResultCode GetProcessId(Core::System& system, u64* out_process_id, Handle handle) { 370static Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
371 LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); 371 LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
372 372
373 // Get the object from the handle table. 373 // Get the object from the handle table.
@@ -398,8 +398,8 @@ static ResultCode GetProcessId(Core::System& system, u64* out_process_id, Handle
398 return ResultSuccess; 398 return ResultSuccess;
399} 399}
400 400
401static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low, 401static Result GetProcessId32(Core::System& system, u32* out_process_id_low,
402 u32* out_process_id_high, Handle handle) { 402 u32* out_process_id_high, Handle handle) {
403 u64 out_process_id{}; 403 u64 out_process_id{};
404 const auto result = GetProcessId(system, &out_process_id, handle); 404 const auto result = GetProcessId(system, &out_process_id, handle);
405 *out_process_id_low = static_cast<u32>(out_process_id); 405 *out_process_id_low = static_cast<u32>(out_process_id);
@@ -408,8 +408,8 @@ static ResultCode GetProcessId32(Core::System& system, u32* out_process_id_low,
408} 408}
409 409
410/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 410/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
411static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, 411static Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address,
412 s32 num_handles, s64 nano_seconds) { 412 s32 num_handles, s64 nano_seconds) {
413 LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}", 413 LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}",
414 handles_address, num_handles, nano_seconds); 414 handles_address, num_handles, nano_seconds);
415 415
@@ -444,14 +444,14 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha
444 nano_seconds); 444 nano_seconds);
445} 445}
446 446
447static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address, 447static Result WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address,
448 s32 num_handles, u32 timeout_high, s32* index) { 448 s32 num_handles, u32 timeout_high, s32* index) {
449 const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)}; 449 const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)};
450 return WaitSynchronization(system, index, handles_address, num_handles, nano_seconds); 450 return WaitSynchronization(system, index, handles_address, num_handles, nano_seconds);
451} 451}
452 452
453/// Resumes a thread waiting on WaitSynchronization 453/// Resumes a thread waiting on WaitSynchronization
454static ResultCode CancelSynchronization(Core::System& system, Handle handle) { 454static Result CancelSynchronization(Core::System& system, Handle handle) {
455 LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle); 455 LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle);
456 456
457 // Get the thread from its handle. 457 // Get the thread from its handle.
@@ -464,13 +464,12 @@ static ResultCode CancelSynchronization(Core::System& system, Handle handle) {
464 return ResultSuccess; 464 return ResultSuccess;
465} 465}
466 466
467static ResultCode CancelSynchronization32(Core::System& system, Handle handle) { 467static Result CancelSynchronization32(Core::System& system, Handle handle) {
468 return CancelSynchronization(system, handle); 468 return CancelSynchronization(system, handle);
469} 469}
470 470
471/// Attempts to locks a mutex 471/// Attempts to locks a mutex
472static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address, 472static Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address, u32 tag) {
473 u32 tag) {
474 LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address=0x{:X}, tag=0x{:08X}", 473 LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address=0x{:X}, tag=0x{:08X}",
475 thread_handle, address, tag); 474 thread_handle, address, tag);
476 475
@@ -488,13 +487,12 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd
488 return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag); 487 return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
489} 488}
490 489
491static ResultCode ArbitrateLock32(Core::System& system, Handle thread_handle, u32 address, 490static Result ArbitrateLock32(Core::System& system, Handle thread_handle, u32 address, u32 tag) {
492 u32 tag) {
493 return ArbitrateLock(system, thread_handle, address, tag); 491 return ArbitrateLock(system, thread_handle, address, tag);
494} 492}
495 493
496/// Unlock a mutex 494/// Unlock a mutex
497static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) { 495static Result ArbitrateUnlock(Core::System& system, VAddr address) {
498 LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); 496 LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
499 497
500 // Validate the input address. 498 // Validate the input address.
@@ -512,7 +510,7 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) {
512 return system.Kernel().CurrentProcess()->SignalToAddress(address); 510 return system.Kernel().CurrentProcess()->SignalToAddress(address);
513} 511}
514 512
515static ResultCode ArbitrateUnlock32(Core::System& system, u32 address) { 513static Result ArbitrateUnlock32(Core::System& system, u32 address) {
516 return ArbitrateUnlock(system, address); 514 return ArbitrateUnlock(system, address);
517} 515}
518 516
@@ -623,10 +621,16 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
623 621
624 handle_debug_buffer(info1, info2); 622 handle_debug_buffer(info1, info2);
625 623
626 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 624 auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
627 const auto thread_processor_id = current_thread->GetActiveCore(); 625 const auto thread_processor_id = current_thread->GetActiveCore();
628 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); 626 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
629 } 627 }
628
629 if (system.DebuggerEnabled()) {
630 auto* thread = system.Kernel().GetCurrentEmuThread();
631 system.GetDebugger().NotifyThreadStopped(thread);
632 thread->RequestSuspend(Kernel::SuspendType::Debug);
633 }
630} 634}
631 635
632static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) { 636static void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) {
@@ -649,8 +653,8 @@ static void OutputDebugString32(Core::System& system, u32 address, u32 len) {
649} 653}
650 654
651/// Gets system/memory information for the current process 655/// Gets system/memory information for the current process
652static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, 656static Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle,
653 u64 info_sub_id) { 657 u64 info_sub_id) {
654 LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, 658 LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
655 info_sub_id, handle); 659 info_sub_id, handle);
656 660
@@ -685,6 +689,9 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
685 // 6.0.0+ 689 // 6.0.0+
686 TotalPhysicalMemoryAvailableWithoutSystemResource = 21, 690 TotalPhysicalMemoryAvailableWithoutSystemResource = 21,
687 TotalPhysicalMemoryUsedWithoutSystemResource = 22, 691 TotalPhysicalMemoryUsedWithoutSystemResource = 22,
692
693 // Homebrew only
694 MesosphereCurrentProcess = 65001,
688 }; 695 };
689 696
690 const auto info_id_type = static_cast<GetInfoType>(info_id); 697 const auto info_id_type = static_cast<GetInfoType>(info_id);
@@ -877,7 +884,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
877 884
878 const auto& core_timing = system.CoreTiming(); 885 const auto& core_timing = system.CoreTiming();
879 const auto& scheduler = *system.Kernel().CurrentScheduler(); 886 const auto& scheduler = *system.Kernel().CurrentScheduler();
880 const auto* const current_thread = scheduler.GetCurrentThread(); 887 const auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
881 const bool same_thread = current_thread == thread.GetPointerUnsafe(); 888 const bool same_thread = current_thread == thread.GetPointerUnsafe();
882 889
883 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); 890 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
@@ -907,18 +914,39 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
907 *result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime(); 914 *result = system.Kernel().CurrentScheduler()->GetIdleThread()->GetCpuTime();
908 return ResultSuccess; 915 return ResultSuccess;
909 } 916 }
917 case GetInfoType::MesosphereCurrentProcess: {
918 // Verify the input handle is invalid.
919 R_UNLESS(handle == InvalidHandle, ResultInvalidHandle);
920
921 // Verify the sub-type is valid.
922 R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
923
924 // Get the handle table.
925 KProcess* current_process = system.Kernel().CurrentProcess();
926 KHandleTable& handle_table = current_process->GetHandleTable();
927
928 // Get a new handle for the current process.
929 Handle tmp;
930 R_TRY(handle_table.Add(&tmp, current_process));
931
932 // Set the output.
933 *result = tmp;
934
935 // We succeeded.
936 return ResultSuccess;
937 }
910 default: 938 default:
911 LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id); 939 LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
912 return ResultInvalidEnumValue; 940 return ResultInvalidEnumValue;
913 } 941 }
914} 942}
915 943
916static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low, 944static Result GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low,
917 u32 info_id, u32 handle, u32 sub_id_high) { 945 u32 info_id, u32 handle, u32 sub_id_high) {
918 const u64 sub_id{u64{sub_id_low} | (u64{sub_id_high} << 32)}; 946 const u64 sub_id{u64{sub_id_low} | (u64{sub_id_high} << 32)};
919 u64 res_value{}; 947 u64 res_value{};
920 948
921 const ResultCode result{GetInfo(system, &res_value, info_id, handle, sub_id)}; 949 const Result result{GetInfo(system, &res_value, info_id, handle, sub_id)};
922 *result_high = static_cast<u32>(res_value >> 32); 950 *result_high = static_cast<u32>(res_value >> 32);
923 *result_low = static_cast<u32>(res_value & std::numeric_limits<u32>::max()); 951 *result_low = static_cast<u32>(res_value & std::numeric_limits<u32>::max());
924 952
@@ -926,7 +954,7 @@ static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_h
926} 954}
927 955
928/// Maps memory at a desired address 956/// Maps memory at a desired address
929static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { 957static Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
930 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); 958 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
931 959
932 if (!Common::Is4KBAligned(addr)) { 960 if (!Common::Is4KBAligned(addr)) {
@@ -974,12 +1002,12 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size)
974 return page_table.MapPhysicalMemory(addr, size); 1002 return page_table.MapPhysicalMemory(addr, size);
975} 1003}
976 1004
977static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { 1005static Result MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) {
978 return MapPhysicalMemory(system, addr, size); 1006 return MapPhysicalMemory(system, addr, size);
979} 1007}
980 1008
981/// Unmaps memory previously mapped via MapPhysicalMemory 1009/// Unmaps memory previously mapped via MapPhysicalMemory
982static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { 1010static Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
983 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); 1011 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
984 1012
985 if (!Common::Is4KBAligned(addr)) { 1013 if (!Common::Is4KBAligned(addr)) {
@@ -1027,13 +1055,13 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size
1027 return page_table.UnmapPhysicalMemory(addr, size); 1055 return page_table.UnmapPhysicalMemory(addr, size);
1028} 1056}
1029 1057
1030static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) { 1058static Result UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) {
1031 return UnmapPhysicalMemory(system, addr, size); 1059 return UnmapPhysicalMemory(system, addr, size);
1032} 1060}
1033 1061
1034/// Sets the thread activity 1062/// Sets the thread activity
1035static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, 1063static Result SetThreadActivity(Core::System& system, Handle thread_handle,
1036 ThreadActivity thread_activity) { 1064 ThreadActivity thread_activity) {
1037 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, 1065 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
1038 thread_activity); 1066 thread_activity);
1039 1067
@@ -1058,13 +1086,13 @@ static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
1058 return ResultSuccess; 1086 return ResultSuccess;
1059} 1087}
1060 1088
1061static ResultCode SetThreadActivity32(Core::System& system, Handle thread_handle, 1089static Result SetThreadActivity32(Core::System& system, Handle thread_handle,
1062 Svc::ThreadActivity thread_activity) { 1090 Svc::ThreadActivity thread_activity) {
1063 return SetThreadActivity(system, thread_handle, thread_activity); 1091 return SetThreadActivity(system, thread_handle, thread_activity);
1064} 1092}
1065 1093
1066/// Gets the thread context 1094/// Gets the thread context
1067static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle) { 1095static Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle) {
1068 LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, 1096 LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
1069 thread_handle); 1097 thread_handle);
1070 1098
@@ -1096,7 +1124,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
1096 if (thread->GetRawState() != ThreadState::Runnable) { 1124 if (thread->GetRawState() != ThreadState::Runnable) {
1097 bool current = false; 1125 bool current = false;
1098 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) { 1126 for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
1099 if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) { 1127 if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetSchedulerCurrentThread()) {
1100 current = true; 1128 current = true;
1101 break; 1129 break;
1102 } 1130 }
@@ -1121,12 +1149,12 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
1121 return ResultSuccess; 1149 return ResultSuccess;
1122} 1150}
1123 1151
1124static ResultCode GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle) { 1152static Result GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle) {
1125 return GetThreadContext(system, out_context, thread_handle); 1153 return GetThreadContext(system, out_context, thread_handle);
1126} 1154}
1127 1155
1128/// Gets the priority for the specified thread 1156/// Gets the priority for the specified thread
1129static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Handle handle) { 1157static Result GetThreadPriority(Core::System& system, u32* out_priority, Handle handle) {
1130 LOG_TRACE(Kernel_SVC, "called"); 1158 LOG_TRACE(Kernel_SVC, "called");
1131 1159
1132 // Get the thread from its handle. 1160 // Get the thread from its handle.
@@ -1139,12 +1167,12 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han
1139 return ResultSuccess; 1167 return ResultSuccess;
1140} 1168}
1141 1169
1142static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle) { 1170static Result GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle) {
1143 return GetThreadPriority(system, out_priority, handle); 1171 return GetThreadPriority(system, out_priority, handle);
1144} 1172}
1145 1173
1146/// Sets the priority for the specified thread 1174/// Sets the priority for the specified thread
1147static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) { 1175static Result SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) {
1148 // Get the current process. 1176 // Get the current process.
1149 KProcess& process = *system.Kernel().CurrentProcess(); 1177 KProcess& process = *system.Kernel().CurrentProcess();
1150 1178
@@ -1162,7 +1190,7 @@ static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle,
1162 return ResultSuccess; 1190 return ResultSuccess;
1163} 1191}
1164 1192
1165static ResultCode SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) { 1193static Result SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) {
1166 return SetThreadPriority(system, thread_handle, priority); 1194 return SetThreadPriority(system, thread_handle, priority);
1167} 1195}
1168 1196
@@ -1222,8 +1250,8 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(Svc::MemoryPermission p
1222 1250
1223} // Anonymous namespace 1251} // Anonymous namespace
1224 1252
1225static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, 1253static Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size,
1226 u64 size, Svc::MemoryPermission map_perm) { 1254 Svc::MemoryPermission map_perm) {
1227 LOG_TRACE(Kernel_SVC, 1255 LOG_TRACE(Kernel_SVC,
1228 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", 1256 "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
1229 shmem_handle, address, size, map_perm); 1257 shmem_handle, address, size, map_perm);
@@ -1263,13 +1291,13 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shmem_handle, VAd
1263 return ResultSuccess; 1291 return ResultSuccess;
1264} 1292}
1265 1293
1266static ResultCode MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, 1294static Result MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size,
1267 u32 size, Svc::MemoryPermission map_perm) { 1295 Svc::MemoryPermission map_perm) {
1268 return MapSharedMemory(system, shmem_handle, address, size, map_perm); 1296 return MapSharedMemory(system, shmem_handle, address, size, map_perm);
1269} 1297}
1270 1298
1271static ResultCode UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, 1299static Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
1272 u64 size) { 1300 u64 size) {
1273 // Validate the address/size. 1301 // Validate the address/size.
1274 R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); 1302 R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
1275 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); 1303 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
@@ -1296,13 +1324,13 @@ static ResultCode UnmapSharedMemory(Core::System& system, Handle shmem_handle, V
1296 return ResultSuccess; 1324 return ResultSuccess;
1297} 1325}
1298 1326
1299static ResultCode UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, 1327static Result UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address,
1300 u32 size) { 1328 u32 size) {
1301 return UnmapSharedMemory(system, shmem_handle, address, size); 1329 return UnmapSharedMemory(system, shmem_handle, address, size);
1302} 1330}
1303 1331
1304static ResultCode SetProcessMemoryPermission(Core::System& system, Handle process_handle, 1332static Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, VAddr address,
1305 VAddr address, u64 size, Svc::MemoryPermission perm) { 1333 u64 size, Svc::MemoryPermission perm) {
1306 LOG_TRACE(Kernel_SVC, 1334 LOG_TRACE(Kernel_SVC,
1307 "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}", 1335 "called, process_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
1308 process_handle, address, size, perm); 1336 process_handle, address, size, perm);
@@ -1331,8 +1359,8 @@ static ResultCode SetProcessMemoryPermission(Core::System& system, Handle proces
1331 return page_table.SetProcessMemoryPermission(address, size, perm); 1359 return page_table.SetProcessMemoryPermission(address, size, perm);
1332} 1360}
1333 1361
1334static ResultCode MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, 1362static Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
1335 VAddr src_address, u64 size) { 1363 VAddr src_address, u64 size) {
1336 LOG_TRACE(Kernel_SVC, 1364 LOG_TRACE(Kernel_SVC,
1337 "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", 1365 "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
1338 dst_address, process_handle, src_address, size); 1366 dst_address, process_handle, src_address, size);
@@ -1361,7 +1389,7 @@ static ResultCode MapProcessMemory(Core::System& system, VAddr dst_address, Hand
1361 ResultInvalidMemoryRegion); 1389 ResultInvalidMemoryRegion);
1362 1390
1363 // Create a new page group. 1391 // Create a new page group.
1364 KPageLinkedList pg; 1392 KPageGroup pg;
1365 R_TRY(src_pt.MakeAndOpenPageGroup( 1393 R_TRY(src_pt.MakeAndOpenPageGroup(
1366 std::addressof(pg), src_address, size / PageSize, KMemoryState::FlagCanMapProcess, 1394 std::addressof(pg), src_address, size / PageSize, KMemoryState::FlagCanMapProcess,
1367 KMemoryState::FlagCanMapProcess, KMemoryPermission::None, KMemoryPermission::None, 1395 KMemoryState::FlagCanMapProcess, KMemoryPermission::None, KMemoryPermission::None,
@@ -1374,8 +1402,8 @@ static ResultCode MapProcessMemory(Core::System& system, VAddr dst_address, Hand
1374 return ResultSuccess; 1402 return ResultSuccess;
1375} 1403}
1376 1404
1377static ResultCode UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle, 1405static Result UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
1378 VAddr src_address, u64 size) { 1406 VAddr src_address, u64 size) {
1379 LOG_TRACE(Kernel_SVC, 1407 LOG_TRACE(Kernel_SVC,
1380 "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}", 1408 "called, dst_address=0x{:X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
1381 dst_address, process_handle, src_address, size); 1409 dst_address, process_handle, src_address, size);
@@ -1409,7 +1437,7 @@ static ResultCode UnmapProcessMemory(Core::System& system, VAddr dst_address, Ha
1409 return ResultSuccess; 1437 return ResultSuccess;
1410} 1438}
1411 1439
1412static ResultCode CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) { 1440static Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) {
1413 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size); 1441 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size);
1414 1442
1415 // Get kernel instance. 1443 // Get kernel instance.
@@ -1444,12 +1472,12 @@ static ResultCode CreateCodeMemory(Core::System& system, Handle* out, VAddr addr
1444 return ResultSuccess; 1472 return ResultSuccess;
1445} 1473}
1446 1474
1447static ResultCode CreateCodeMemory32(Core::System& system, Handle* out, u32 address, u32 size) { 1475static Result CreateCodeMemory32(Core::System& system, Handle* out, u32 address, u32 size) {
1448 return CreateCodeMemory(system, out, address, size); 1476 return CreateCodeMemory(system, out, address, size);
1449} 1477}
1450 1478
1451static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation, 1479static Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation,
1452 VAddr address, size_t size, Svc::MemoryPermission perm) { 1480 VAddr address, size_t size, Svc::MemoryPermission perm) {
1453 1481
1454 LOG_TRACE(Kernel_SVC, 1482 LOG_TRACE(Kernel_SVC,
1455 "called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, " 1483 "called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, "
@@ -1527,15 +1555,13 @@ static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_han
1527 return ResultSuccess; 1555 return ResultSuccess;
1528} 1556}
1529 1557
1530static ResultCode ControlCodeMemory32(Core::System& system, Handle code_memory_handle, 1558static Result ControlCodeMemory32(Core::System& system, Handle code_memory_handle, u32 operation,
1531 u32 operation, u64 address, u64 size, 1559 u64 address, u64 size, Svc::MemoryPermission perm) {
1532 Svc::MemoryPermission perm) {
1533 return ControlCodeMemory(system, code_memory_handle, operation, address, size, perm); 1560 return ControlCodeMemory(system, code_memory_handle, operation, address, size, perm);
1534} 1561}
1535 1562
1536static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, 1563static Result QueryProcessMemory(Core::System& system, VAddr memory_info_address,
1537 VAddr page_info_address, Handle process_handle, 1564 VAddr page_info_address, Handle process_handle, VAddr address) {
1538 VAddr address) {
1539 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); 1565 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
1540 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1566 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1541 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); 1567 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
@@ -1563,8 +1589,8 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add
1563 return ResultSuccess; 1589 return ResultSuccess;
1564} 1590}
1565 1591
1566static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address, 1592static Result QueryMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
1567 VAddr page_info_address, VAddr query_address) { 1593 VAddr query_address) {
1568 LOG_TRACE(Kernel_SVC, 1594 LOG_TRACE(Kernel_SVC,
1569 "called, memory_info_address=0x{:016X}, page_info_address=0x{:016X}, " 1595 "called, memory_info_address=0x{:016X}, page_info_address=0x{:016X}, "
1570 "query_address=0x{:016X}", 1596 "query_address=0x{:016X}",
@@ -1574,13 +1600,13 @@ static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address,
1574 query_address); 1600 query_address);
1575} 1601}
1576 1602
1577static ResultCode QueryMemory32(Core::System& system, u32 memory_info_address, 1603static Result QueryMemory32(Core::System& system, u32 memory_info_address, u32 page_info_address,
1578 u32 page_info_address, u32 query_address) { 1604 u32 query_address) {
1579 return QueryMemory(system, memory_info_address, page_info_address, query_address); 1605 return QueryMemory(system, memory_info_address, page_info_address, query_address);
1580} 1606}
1581 1607
1582static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address, 1608static Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
1583 u64 src_address, u64 size) { 1609 u64 src_address, u64 size) {
1584 LOG_DEBUG(Kernel_SVC, 1610 LOG_DEBUG(Kernel_SVC,
1585 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, " 1611 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
1586 "src_address=0x{:016X}, size=0x{:016X}", 1612 "src_address=0x{:016X}, size=0x{:016X}",
@@ -1647,8 +1673,8 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
1647 return page_table.MapCodeMemory(dst_address, src_address, size); 1673 return page_table.MapCodeMemory(dst_address, src_address, size);
1648} 1674}
1649 1675
1650static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, 1676static Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
1651 u64 dst_address, u64 src_address, u64 size) { 1677 u64 src_address, u64 size) {
1652 LOG_DEBUG(Kernel_SVC, 1678 LOG_DEBUG(Kernel_SVC,
1653 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, " 1679 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
1654 "size=0x{:016X}", 1680 "size=0x{:016X}",
@@ -1719,11 +1745,12 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
1719/// Exits the current process 1745/// Exits the current process
1720static void ExitProcess(Core::System& system) { 1746static void ExitProcess(Core::System& system) {
1721 auto* current_process = system.Kernel().CurrentProcess(); 1747 auto* current_process = system.Kernel().CurrentProcess();
1722 UNIMPLEMENTED();
1723 1748
1724 LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID()); 1749 LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID());
1725 ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running, 1750 ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running,
1726 "Process has already exited"); 1751 "Process has already exited");
1752
1753 system.Exit();
1727} 1754}
1728 1755
1729static void ExitProcess32(Core::System& system) { 1756static void ExitProcess32(Core::System& system) {
@@ -1739,8 +1766,8 @@ constexpr bool IsValidVirtualCoreId(int32_t core_id) {
1739} // Anonymous namespace 1766} // Anonymous namespace
1740 1767
1741/// Creates a new thread 1768/// Creates a new thread
1742static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, 1769static Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
1743 VAddr stack_bottom, u32 priority, s32 core_id) { 1770 VAddr stack_bottom, u32 priority, s32 core_id) {
1744 LOG_DEBUG(Kernel_SVC, 1771 LOG_DEBUG(Kernel_SVC,
1745 "called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, " 1772 "called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, "
1746 "priority=0x{:08X}, core_id=0x{:08X}", 1773 "priority=0x{:08X}, core_id=0x{:08X}",
@@ -1811,13 +1838,13 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1811 return ResultSuccess; 1838 return ResultSuccess;
1812} 1839}
1813 1840
1814static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 priority, 1841static Result CreateThread32(Core::System& system, Handle* out_handle, u32 priority,
1815 u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { 1842 u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) {
1816 return CreateThread(system, out_handle, entry_point, arg, stack_top, priority, processor_id); 1843 return CreateThread(system, out_handle, entry_point, arg, stack_top, priority, processor_id);
1817} 1844}
1818 1845
1819/// Starts the thread for the provided handle 1846/// Starts the thread for the provided handle
1820static ResultCode StartThread(Core::System& system, Handle thread_handle) { 1847static Result StartThread(Core::System& system, Handle thread_handle) {
1821 LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); 1848 LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
1822 1849
1823 // Get the thread from its handle. 1850 // Get the thread from its handle.
@@ -1835,7 +1862,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
1835 return ResultSuccess; 1862 return ResultSuccess;
1836} 1863}
1837 1864
1838static ResultCode StartThread32(Core::System& system, Handle thread_handle) { 1865static Result StartThread32(Core::System& system, Handle thread_handle) {
1839 return StartThread(system, thread_handle); 1866 return StartThread(system, thread_handle);
1840} 1867}
1841 1868
@@ -1843,7 +1870,7 @@ static ResultCode StartThread32(Core::System& system, Handle thread_handle) {
1843static void ExitThread(Core::System& system) { 1870static void ExitThread(Core::System& system) {
1844 LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); 1871 LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
1845 1872
1846 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 1873 auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
1847 system.GlobalSchedulerContext().RemoveThread(current_thread); 1874 system.GlobalSchedulerContext().RemoveThread(current_thread);
1848 current_thread->Exit(); 1875 current_thread->Exit();
1849 system.Kernel().UnregisterInUseObject(current_thread); 1876 system.Kernel().UnregisterInUseObject(current_thread);
@@ -1876,7 +1903,7 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
1876 KScheduler::YieldToAnyThread(kernel); 1903 KScheduler::YieldToAnyThread(kernel);
1877 } else { 1904 } else {
1878 // Nintendo does nothing at all if an otherwise invalid value is passed. 1905 // Nintendo does nothing at all if an otherwise invalid value is passed.
1879 UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); 1906 ASSERT_MSG(false, "Unimplemented sleep yield type '{:016X}'!", nanoseconds);
1880 } 1907 }
1881} 1908}
1882 1909
@@ -1886,8 +1913,8 @@ static void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanosec
1886} 1913}
1887 1914
1888/// Wait process wide key atomic 1915/// Wait process wide key atomic
1889static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_key, 1916static Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_key, u32 tag,
1890 u32 tag, s64 timeout_ns) { 1917 s64 timeout_ns) {
1891 LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag=0x{:08X}, timeout_ns={}", address, 1918 LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag=0x{:08X}, timeout_ns={}", address,
1892 cv_key, tag, timeout_ns); 1919 cv_key, tag, timeout_ns);
1893 1920
@@ -1922,8 +1949,8 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address,
1922 address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout); 1949 address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout);
1923} 1950}
1924 1951
1925static ResultCode WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag, 1952static Result WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag,
1926 u32 timeout_ns_low, u32 timeout_ns_high) { 1953 u32 timeout_ns_low, u32 timeout_ns_high) {
1927 const auto timeout_ns = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32)); 1954 const auto timeout_ns = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
1928 return WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns); 1955 return WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns);
1929} 1956}
@@ -1968,8 +1995,8 @@ constexpr bool IsValidArbitrationType(Svc::ArbitrationType type) {
1968} // namespace 1995} // namespace
1969 1996
1970// Wait for an address (via Address Arbiter) 1997// Wait for an address (via Address Arbiter)
1971static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::ArbitrationType arb_type, 1998static Result WaitForAddress(Core::System& system, VAddr address, Svc::ArbitrationType arb_type,
1972 s32 value, s64 timeout_ns) { 1999 s32 value, s64 timeout_ns) {
1973 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}", 2000 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}",
1974 address, arb_type, value, timeout_ns); 2001 address, arb_type, value, timeout_ns);
1975 2002
@@ -2006,15 +2033,15 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit
2006 return system.Kernel().CurrentProcess()->WaitAddressArbiter(address, arb_type, value, timeout); 2033 return system.Kernel().CurrentProcess()->WaitAddressArbiter(address, arb_type, value, timeout);
2007} 2034}
2008 2035
2009static ResultCode WaitForAddress32(Core::System& system, u32 address, Svc::ArbitrationType arb_type, 2036static Result WaitForAddress32(Core::System& system, u32 address, Svc::ArbitrationType arb_type,
2010 s32 value, u32 timeout_ns_low, u32 timeout_ns_high) { 2037 s32 value, u32 timeout_ns_low, u32 timeout_ns_high) {
2011 const auto timeout = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32)); 2038 const auto timeout = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
2012 return WaitForAddress(system, address, arb_type, value, timeout); 2039 return WaitForAddress(system, address, arb_type, value, timeout);
2013} 2040}
2014 2041
2015// Signals to an address (via Address Arbiter) 2042// Signals to an address (via Address Arbiter)
2016static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::SignalType signal_type, 2043static Result SignalToAddress(Core::System& system, VAddr address, Svc::SignalType signal_type,
2017 s32 value, s32 count) { 2044 s32 value, s32 count) {
2018 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}", 2045 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}",
2019 address, signal_type, value, count); 2046 address, signal_type, value, count);
2020 2047
@@ -2055,8 +2082,8 @@ static void SynchronizePreemptionState(Core::System& system) {
2055 } 2082 }
2056} 2083}
2057 2084
2058static ResultCode SignalToAddress32(Core::System& system, u32 address, Svc::SignalType signal_type, 2085static Result SignalToAddress32(Core::System& system, u32 address, Svc::SignalType signal_type,
2059 s32 value, s32 count) { 2086 s32 value, s32 count) {
2060 return SignalToAddress(system, address, signal_type, value, count); 2087 return SignalToAddress(system, address, signal_type, value, count);
2061} 2088}
2062 2089
@@ -2094,7 +2121,7 @@ static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high)
2094} 2121}
2095 2122
2096/// Close a handle 2123/// Close a handle
2097static ResultCode CloseHandle(Core::System& system, Handle handle) { 2124static Result CloseHandle(Core::System& system, Handle handle) {
2098 LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); 2125 LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
2099 2126
2100 // Remove the handle. 2127 // Remove the handle.
@@ -2104,12 +2131,12 @@ static ResultCode CloseHandle(Core::System& system, Handle handle) {
2104 return ResultSuccess; 2131 return ResultSuccess;
2105} 2132}
2106 2133
2107static ResultCode CloseHandle32(Core::System& system, Handle handle) { 2134static Result CloseHandle32(Core::System& system, Handle handle) {
2108 return CloseHandle(system, handle); 2135 return CloseHandle(system, handle);
2109} 2136}
2110 2137
2111/// Clears the signaled state of an event or process. 2138/// Clears the signaled state of an event or process.
2112static ResultCode ResetSignal(Core::System& system, Handle handle) { 2139static Result ResetSignal(Core::System& system, Handle handle) {
2113 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); 2140 LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
2114 2141
2115 // Get the current handle table. 2142 // Get the current handle table.
@@ -2136,7 +2163,7 @@ static ResultCode ResetSignal(Core::System& system, Handle handle) {
2136 return ResultInvalidHandle; 2163 return ResultInvalidHandle;
2137} 2164}
2138 2165
2139static ResultCode ResetSignal32(Core::System& system, Handle handle) { 2166static Result ResetSignal32(Core::System& system, Handle handle) {
2140 return ResetSignal(system, handle); 2167 return ResetSignal(system, handle);
2141} 2168}
2142 2169
@@ -2156,8 +2183,8 @@ constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) {
2156} // Anonymous namespace 2183} // Anonymous namespace
2157 2184
2158/// Creates a TransferMemory object 2185/// Creates a TransferMemory object
2159static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, 2186static Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size,
2160 MemoryPermission map_perm) { 2187 MemoryPermission map_perm) {
2161 auto& kernel = system.Kernel(); 2188 auto& kernel = system.Kernel();
2162 2189
2163 // Validate the size. 2190 // Validate the size.
@@ -2203,13 +2230,13 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr
2203 return ResultSuccess; 2230 return ResultSuccess;
2204} 2231}
2205 2232
2206static ResultCode CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size, 2233static Result CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size,
2207 MemoryPermission map_perm) { 2234 MemoryPermission map_perm) {
2208 return CreateTransferMemory(system, out, address, size, map_perm); 2235 return CreateTransferMemory(system, out, address, size, map_perm);
2209} 2236}
2210 2237
2211static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, 2238static Result GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
2212 u64* out_affinity_mask) { 2239 u64* out_affinity_mask) {
2213 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); 2240 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
2214 2241
2215 // Get the thread from its handle. 2242 // Get the thread from its handle.
@@ -2223,8 +2250,8 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
2223 return ResultSuccess; 2250 return ResultSuccess;
2224} 2251}
2225 2252
2226static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id, 2253static Result GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
2227 u32* out_affinity_mask_low, u32* out_affinity_mask_high) { 2254 u32* out_affinity_mask_low, u32* out_affinity_mask_high) {
2228 u64 out_affinity_mask{}; 2255 u64 out_affinity_mask{};
2229 const auto result = GetThreadCoreMask(system, thread_handle, out_core_id, &out_affinity_mask); 2256 const auto result = GetThreadCoreMask(system, thread_handle, out_core_id, &out_affinity_mask);
2230 *out_affinity_mask_high = static_cast<u32>(out_affinity_mask >> 32); 2257 *out_affinity_mask_high = static_cast<u32>(out_affinity_mask >> 32);
@@ -2232,8 +2259,8 @@ static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle
2232 return result; 2259 return result;
2233} 2260}
2234 2261
2235static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, 2262static Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
2236 u64 affinity_mask) { 2263 u64 affinity_mask) {
2237 // Determine the core id/affinity mask. 2264 // Determine the core id/affinity mask.
2238 if (core_id == IdealCoreUseProcessValue) { 2265 if (core_id == IdealCoreUseProcessValue) {
2239 core_id = system.Kernel().CurrentProcess()->GetIdealCoreId(); 2266 core_id = system.Kernel().CurrentProcess()->GetIdealCoreId();
@@ -2264,13 +2291,13 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
2264 return ResultSuccess; 2291 return ResultSuccess;
2265} 2292}
2266 2293
2267static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id, 2294static Result SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
2268 u32 affinity_mask_low, u32 affinity_mask_high) { 2295 u32 affinity_mask_low, u32 affinity_mask_high) {
2269 const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32); 2296 const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32);
2270 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask); 2297 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
2271} 2298}
2272 2299
2273static ResultCode SignalEvent(Core::System& system, Handle event_handle) { 2300static Result SignalEvent(Core::System& system, Handle event_handle) {
2274 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); 2301 LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
2275 2302
2276 // Get the current handle table. 2303 // Get the current handle table.
@@ -2283,11 +2310,11 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
2283 return writable_event->Signal(); 2310 return writable_event->Signal();
2284} 2311}
2285 2312
2286static ResultCode SignalEvent32(Core::System& system, Handle event_handle) { 2313static Result SignalEvent32(Core::System& system, Handle event_handle) {
2287 return SignalEvent(system, event_handle); 2314 return SignalEvent(system, event_handle);
2288} 2315}
2289 2316
2290static ResultCode ClearEvent(Core::System& system, Handle event_handle) { 2317static Result ClearEvent(Core::System& system, Handle event_handle) {
2291 LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle); 2318 LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
2292 2319
2293 // Get the current handle table. 2320 // Get the current handle table.
@@ -2314,11 +2341,11 @@ static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
2314 return ResultInvalidHandle; 2341 return ResultInvalidHandle;
2315} 2342}
2316 2343
2317static ResultCode ClearEvent32(Core::System& system, Handle event_handle) { 2344static Result ClearEvent32(Core::System& system, Handle event_handle) {
2318 return ClearEvent(system, event_handle); 2345 return ClearEvent(system, event_handle);
2319} 2346}
2320 2347
2321static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) { 2348static Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
2322 LOG_DEBUG(Kernel_SVC, "called"); 2349 LOG_DEBUG(Kernel_SVC, "called");
2323 2350
2324 // Get the kernel reference and handle table. 2351 // Get the kernel reference and handle table.
@@ -2363,11 +2390,11 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
2363 return ResultSuccess; 2390 return ResultSuccess;
2364} 2391}
2365 2392
2366static ResultCode CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) { 2393static Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
2367 return CreateEvent(system, out_write, out_read); 2394 return CreateEvent(system, out_write, out_read);
2368} 2395}
2369 2396
2370static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { 2397static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
2371 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); 2398 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);
2372 2399
2373 // This function currently only allows retrieving a process' status. 2400 // This function currently only allows retrieving a process' status.
@@ -2393,7 +2420,7 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_
2393 return ResultSuccess; 2420 return ResultSuccess;
2394} 2421}
2395 2422
2396static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle) { 2423static Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
2397 LOG_DEBUG(Kernel_SVC, "called"); 2424 LOG_DEBUG(Kernel_SVC, "called");
2398 2425
2399 // Create a new resource limit. 2426 // Create a new resource limit.
@@ -2416,9 +2443,8 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
2416 return ResultSuccess; 2443 return ResultSuccess;
2417} 2444}
2418 2445
2419static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value, 2446static Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
2420 Handle resource_limit_handle, 2447 Handle resource_limit_handle, LimitableResource which) {
2421 LimitableResource which) {
2422 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, 2448 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
2423 which); 2449 which);
2424 2450
@@ -2437,9 +2463,8 @@ static ResultCode GetResourceLimitLimitValue(Core::System& system, u64* out_limi
2437 return ResultSuccess; 2463 return ResultSuccess;
2438} 2464}
2439 2465
2440static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value, 2466static Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value,
2441 Handle resource_limit_handle, 2467 Handle resource_limit_handle, LimitableResource which) {
2442 LimitableResource which) {
2443 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle, 2468 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
2444 which); 2469 which);
2445 2470
@@ -2458,8 +2483,8 @@ static ResultCode GetResourceLimitCurrentValue(Core::System& system, u64* out_cu
2458 return ResultSuccess; 2483 return ResultSuccess;
2459} 2484}
2460 2485
2461static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle, 2486static Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle,
2462 LimitableResource which, u64 limit_value) { 2487 LimitableResource which, u64 limit_value) {
2463 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}", 2488 LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}",
2464 resource_limit_handle, which, limit_value); 2489 resource_limit_handle, which, limit_value);
2465 2490
@@ -2478,8 +2503,8 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
2478 return ResultSuccess; 2503 return ResultSuccess;
2479} 2504}
2480 2505
2481static ResultCode GetProcessList(Core::System& system, u32* out_num_processes, 2506static Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_process_ids,
2482 VAddr out_process_ids, u32 out_process_ids_size) { 2507 u32 out_process_ids_size) {
2483 LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}", 2508 LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}",
2484 out_process_ids, out_process_ids_size); 2509 out_process_ids, out_process_ids_size);
2485 2510
@@ -2515,8 +2540,8 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
2515 return ResultSuccess; 2540 return ResultSuccess;
2516} 2541}
2517 2542
2518static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids, 2543static Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
2519 u32 out_thread_ids_size, Handle debug_handle) { 2544 u32 out_thread_ids_size, Handle debug_handle) {
2520 // TODO: Handle this case when debug events are supported. 2545 // TODO: Handle this case when debug events are supported.
2521 UNIMPLEMENTED_IF(debug_handle != InvalidHandle); 2546 UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
2522 2547
@@ -2530,7 +2555,7 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd
2530 return ResultOutOfRange; 2555 return ResultOutOfRange;
2531 } 2556 }
2532 2557
2533 const auto* const current_process = system.Kernel().CurrentProcess(); 2558 auto* const current_process = system.Kernel().CurrentProcess();
2534 const auto total_copy_size = out_thread_ids_size * sizeof(u64); 2559 const auto total_copy_size = out_thread_ids_size * sizeof(u64);
2535 2560
2536 if (out_thread_ids_size > 0 && 2561 if (out_thread_ids_size > 0 &&
@@ -2555,9 +2580,9 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd
2555 return ResultSuccess; 2580 return ResultSuccess;
2556} 2581}
2557 2582
2558static ResultCode FlushProcessDataCache32([[maybe_unused]] Core::System& system, 2583static Result FlushProcessDataCache32([[maybe_unused]] Core::System& system,
2559 [[maybe_unused]] Handle handle, 2584 [[maybe_unused]] Handle handle, [[maybe_unused]] u32 address,
2560 [[maybe_unused]] u32 address, [[maybe_unused]] u32 size) { 2585 [[maybe_unused]] u32 size) {
2561 // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a no-op, 2586 // Note(Blinkhawk): For emulation purposes of the data cache this is mostly a no-op,
2562 // as all emulation is done in the same cache level in host architecture, thus data cache 2587 // as all emulation is done in the same cache level in host architecture, thus data cache
2563 // does not need flushing. 2588 // does not need flushing.
@@ -2982,11 +3007,10 @@ static const FunctionDef* GetSVCInfo64(u32 func_num) {
2982} 3007}
2983 3008
2984void Call(Core::System& system, u32 immediate) { 3009void Call(Core::System& system, u32 immediate) {
2985 system.ExitDynarmicProfile();
2986 auto& kernel = system.Kernel(); 3010 auto& kernel = system.Kernel();
2987 kernel.EnterSVCProfile(); 3011 kernel.EnterSVCProfile();
2988 3012
2989 auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); 3013 auto* thread = GetCurrentThreadPointer(kernel);
2990 thread->SetIsCallingSvc(); 3014 thread->SetIsCallingSvc();
2991 3015
2992 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) 3016 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
@@ -3007,8 +3031,6 @@ void Call(Core::System& system, u32 immediate) {
3007 auto* host_context = thread->GetHostContext().get(); 3031 auto* host_context = thread->GetHostContext().get();
3008 host_context->Rewind(); 3032 host_context->Rewind();
3009 } 3033 }
3010
3011 system.EnterDynarmicProfile();
3012} 3034}
3013 3035
3014} // namespace Kernel::Svc 3036} // namespace Kernel::Svc
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h
index fab12d070..f27cade33 100644
--- a/src/core/hle/kernel/svc_results.h
+++ b/src/core/hle/kernel/svc_results.h
@@ -9,34 +9,34 @@ namespace Kernel {
9 9
10// Confirmed Switch kernel error codes 10// Confirmed Switch kernel error codes
11 11
12constexpr ResultCode ResultOutOfSessions{ErrorModule::Kernel, 7}; 12constexpr Result ResultOutOfSessions{ErrorModule::Kernel, 7};
13constexpr ResultCode ResultInvalidArgument{ErrorModule::Kernel, 14}; 13constexpr Result ResultInvalidArgument{ErrorModule::Kernel, 14};
14constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57}; 14constexpr Result ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
15constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; 15constexpr Result ResultTerminationRequested{ErrorModule::Kernel, 59};
16constexpr ResultCode ResultInvalidSize{ErrorModule::Kernel, 101}; 16constexpr Result ResultInvalidSize{ErrorModule::Kernel, 101};
17constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; 17constexpr Result ResultInvalidAddress{ErrorModule::Kernel, 102};
18constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103}; 18constexpr Result ResultOutOfResource{ErrorModule::Kernel, 103};
19constexpr ResultCode ResultOutOfMemory{ErrorModule::Kernel, 104}; 19constexpr Result ResultOutOfMemory{ErrorModule::Kernel, 104};
20constexpr ResultCode ResultOutOfHandles{ErrorModule::Kernel, 105}; 20constexpr Result ResultOutOfHandles{ErrorModule::Kernel, 105};
21constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; 21constexpr Result ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
22constexpr ResultCode ResultInvalidNewMemoryPermission{ErrorModule::Kernel, 108}; 22constexpr Result ResultInvalidNewMemoryPermission{ErrorModule::Kernel, 108};
23constexpr ResultCode ResultInvalidMemoryRegion{ErrorModule::Kernel, 110}; 23constexpr Result ResultInvalidMemoryRegion{ErrorModule::Kernel, 110};
24constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; 24constexpr Result ResultInvalidPriority{ErrorModule::Kernel, 112};
25constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; 25constexpr Result ResultInvalidCoreId{ErrorModule::Kernel, 113};
26constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114}; 26constexpr Result ResultInvalidHandle{ErrorModule::Kernel, 114};
27constexpr ResultCode ResultInvalidPointer{ErrorModule::Kernel, 115}; 27constexpr Result ResultInvalidPointer{ErrorModule::Kernel, 115};
28constexpr ResultCode ResultInvalidCombination{ErrorModule::Kernel, 116}; 28constexpr Result ResultInvalidCombination{ErrorModule::Kernel, 116};
29constexpr ResultCode ResultTimedOut{ErrorModule::Kernel, 117}; 29constexpr Result ResultTimedOut{ErrorModule::Kernel, 117};
30constexpr ResultCode ResultCancelled{ErrorModule::Kernel, 118}; 30constexpr Result ResultCancelled{ErrorModule::Kernel, 118};
31constexpr ResultCode ResultOutOfRange{ErrorModule::Kernel, 119}; 31constexpr Result ResultOutOfRange{ErrorModule::Kernel, 119};
32constexpr ResultCode ResultInvalidEnumValue{ErrorModule::Kernel, 120}; 32constexpr Result ResultInvalidEnumValue{ErrorModule::Kernel, 120};
33constexpr ResultCode ResultNotFound{ErrorModule::Kernel, 121}; 33constexpr Result ResultNotFound{ErrorModule::Kernel, 121};
34constexpr ResultCode ResultBusy{ErrorModule::Kernel, 122}; 34constexpr Result ResultBusy{ErrorModule::Kernel, 122};
35constexpr ResultCode ResultSessionClosed{ErrorModule::Kernel, 123}; 35constexpr Result ResultSessionClosed{ErrorModule::Kernel, 123};
36constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125}; 36constexpr Result ResultInvalidState{ErrorModule::Kernel, 125};
37constexpr ResultCode ResultReservedUsed{ErrorModule::Kernel, 126}; 37constexpr Result ResultReservedUsed{ErrorModule::Kernel, 126};
38constexpr ResultCode ResultPortClosed{ErrorModule::Kernel, 131}; 38constexpr Result ResultPortClosed{ErrorModule::Kernel, 131};
39constexpr ResultCode ResultLimitReached{ErrorModule::Kernel, 132}; 39constexpr Result ResultLimitReached{ErrorModule::Kernel, 132};
40constexpr ResultCode ResultInvalidId{ErrorModule::Kernel, 519}; 40constexpr Result ResultInvalidId{ErrorModule::Kernel, 519};
41 41
42} // namespace Kernel 42} // namespace Kernel
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 2271bb80c..4bc49087e 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -33,24 +33,24 @@ static inline void FuncReturn32(Core::System& system, u32 result) {
33} 33}
34 34
35//////////////////////////////////////////////////////////////////////////////////////////////////// 35////////////////////////////////////////////////////////////////////////////////////////////////////
36// Function wrappers that return type ResultCode 36// Function wrappers that return type Result
37 37
38template <ResultCode func(Core::System&, u64)> 38template <Result func(Core::System&, u64)>
39void SvcWrap64(Core::System& system) { 39void SvcWrap64(Core::System& system) {
40 FuncReturn(system, func(system, Param(system, 0)).raw); 40 FuncReturn(system, func(system, Param(system, 0)).raw);
41} 41}
42 42
43template <ResultCode func(Core::System&, u64, u64)> 43template <Result func(Core::System&, u64, u64)>
44void SvcWrap64(Core::System& system) { 44void SvcWrap64(Core::System& system) {
45 FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw); 45 FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw);
46} 46}
47 47
48template <ResultCode func(Core::System&, u32)> 48template <Result func(Core::System&, u32)>
49void SvcWrap64(Core::System& system) { 49void SvcWrap64(Core::System& system) {
50 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw); 50 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
51} 51}
52 52
53template <ResultCode func(Core::System&, u32, u32)> 53template <Result func(Core::System&, u32, u32)>
54void SvcWrap64(Core::System& system) { 54void SvcWrap64(Core::System& system) {
55 FuncReturn( 55 FuncReturn(
56 system, 56 system,
@@ -58,14 +58,14 @@ void SvcWrap64(Core::System& system) {
58} 58}
59 59
60// Used by SetThreadActivity 60// Used by SetThreadActivity
61template <ResultCode func(Core::System&, Handle, Svc::ThreadActivity)> 61template <Result func(Core::System&, Handle, Svc::ThreadActivity)>
62void SvcWrap64(Core::System& system) { 62void SvcWrap64(Core::System& system) {
63 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), 63 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
64 static_cast<Svc::ThreadActivity>(Param(system, 1))) 64 static_cast<Svc::ThreadActivity>(Param(system, 1)))
65 .raw); 65 .raw);
66} 66}
67 67
68template <ResultCode func(Core::System&, u32, u64, u64, u64)> 68template <Result func(Core::System&, u32, u64, u64, u64)>
69void SvcWrap64(Core::System& system) { 69void SvcWrap64(Core::System& system) {
70 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), 70 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
71 Param(system, 2), Param(system, 3)) 71 Param(system, 2), Param(system, 3))
@@ -73,7 +73,7 @@ void SvcWrap64(Core::System& system) {
73} 73}
74 74
75// Used by MapProcessMemory and UnmapProcessMemory 75// Used by MapProcessMemory and UnmapProcessMemory
76template <ResultCode func(Core::System&, u64, u32, u64, u64)> 76template <Result func(Core::System&, u64, u32, u64, u64)>
77void SvcWrap64(Core::System& system) { 77void SvcWrap64(Core::System& system) {
78 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)), 78 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
79 Param(system, 2), Param(system, 3)) 79 Param(system, 2), Param(system, 3))
@@ -81,7 +81,7 @@ void SvcWrap64(Core::System& system) {
81} 81}
82 82
83// Used by ControlCodeMemory 83// Used by ControlCodeMemory
84template <ResultCode func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)> 84template <Result func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)>
85void SvcWrap64(Core::System& system) { 85void SvcWrap64(Core::System& system) {
86 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), 86 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
87 static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3), 87 static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3),
@@ -89,7 +89,7 @@ void SvcWrap64(Core::System& system) {
89 .raw); 89 .raw);
90} 90}
91 91
92template <ResultCode func(Core::System&, u32*)> 92template <Result func(Core::System&, u32*)>
93void SvcWrap64(Core::System& system) { 93void SvcWrap64(Core::System& system) {
94 u32 param = 0; 94 u32 param = 0;
95 const u32 retval = func(system, &param).raw; 95 const u32 retval = func(system, &param).raw;
@@ -97,7 +97,7 @@ void SvcWrap64(Core::System& system) {
97 FuncReturn(system, retval); 97 FuncReturn(system, retval);
98} 98}
99 99
100template <ResultCode func(Core::System&, u32*, u32)> 100template <Result func(Core::System&, u32*, u32)>
101void SvcWrap64(Core::System& system) { 101void SvcWrap64(Core::System& system) {
102 u32 param_1 = 0; 102 u32 param_1 = 0;
103 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw; 103 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
@@ -105,7 +105,7 @@ void SvcWrap64(Core::System& system) {
105 FuncReturn(system, retval); 105 FuncReturn(system, retval);
106} 106}
107 107
108template <ResultCode func(Core::System&, u32*, u32*)> 108template <Result func(Core::System&, u32*, u32*)>
109void SvcWrap64(Core::System& system) { 109void SvcWrap64(Core::System& system) {
110 u32 param_1 = 0; 110 u32 param_1 = 0;
111 u32 param_2 = 0; 111 u32 param_2 = 0;
@@ -118,7 +118,7 @@ void SvcWrap64(Core::System& system) {
118 FuncReturn(system, retval); 118 FuncReturn(system, retval);
119} 119}
120 120
121template <ResultCode func(Core::System&, u32*, u64)> 121template <Result func(Core::System&, u32*, u64)>
122void SvcWrap64(Core::System& system) { 122void SvcWrap64(Core::System& system) {
123 u32 param_1 = 0; 123 u32 param_1 = 0;
124 const u32 retval = func(system, &param_1, Param(system, 1)).raw; 124 const u32 retval = func(system, &param_1, Param(system, 1)).raw;
@@ -126,7 +126,7 @@ void SvcWrap64(Core::System& system) {
126 FuncReturn(system, retval); 126 FuncReturn(system, retval);
127} 127}
128 128
129template <ResultCode func(Core::System&, u32*, u64, u32)> 129template <Result func(Core::System&, u32*, u64, u32)>
130void SvcWrap64(Core::System& system) { 130void SvcWrap64(Core::System& system) {
131 u32 param_1 = 0; 131 u32 param_1 = 0;
132 const u32 retval = 132 const u32 retval =
@@ -136,7 +136,7 @@ void SvcWrap64(Core::System& system) {
136 FuncReturn(system, retval); 136 FuncReturn(system, retval);
137} 137}
138 138
139template <ResultCode func(Core::System&, u64*, u32)> 139template <Result func(Core::System&, u64*, u32)>
140void SvcWrap64(Core::System& system) { 140void SvcWrap64(Core::System& system) {
141 u64 param_1 = 0; 141 u64 param_1 = 0;
142 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw; 142 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
@@ -145,12 +145,12 @@ void SvcWrap64(Core::System& system) {
145 FuncReturn(system, retval); 145 FuncReturn(system, retval);
146} 146}
147 147
148template <ResultCode func(Core::System&, u64, u32)> 148template <Result func(Core::System&, u64, u32)>
149void SvcWrap64(Core::System& system) { 149void SvcWrap64(Core::System& system) {
150 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw); 150 FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);
151} 151}
152 152
153template <ResultCode func(Core::System&, u64*, u64)> 153template <Result func(Core::System&, u64*, u64)>
154void SvcWrap64(Core::System& system) { 154void SvcWrap64(Core::System& system) {
155 u64 param_1 = 0; 155 u64 param_1 = 0;
156 const u32 retval = func(system, &param_1, Param(system, 1)).raw; 156 const u32 retval = func(system, &param_1, Param(system, 1)).raw;
@@ -159,7 +159,7 @@ void SvcWrap64(Core::System& system) {
159 FuncReturn(system, retval); 159 FuncReturn(system, retval);
160} 160}
161 161
162template <ResultCode func(Core::System&, u64*, u32, u32)> 162template <Result func(Core::System&, u64*, u32, u32)>
163void SvcWrap64(Core::System& system) { 163void SvcWrap64(Core::System& system) {
164 u64 param_1 = 0; 164 u64 param_1 = 0;
165 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)), 165 const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)),
@@ -171,7 +171,7 @@ void SvcWrap64(Core::System& system) {
171} 171}
172 172
173// Used by GetResourceLimitLimitValue. 173// Used by GetResourceLimitLimitValue.
174template <ResultCode func(Core::System&, u64*, Handle, LimitableResource)> 174template <Result func(Core::System&, u64*, Handle, LimitableResource)>
175void SvcWrap64(Core::System& system) { 175void SvcWrap64(Core::System& system) {
176 u64 param_1 = 0; 176 u64 param_1 = 0;
177 const u32 retval = func(system, &param_1, static_cast<Handle>(Param(system, 1)), 177 const u32 retval = func(system, &param_1, static_cast<Handle>(Param(system, 1)),
@@ -182,13 +182,13 @@ void SvcWrap64(Core::System& system) {
182 FuncReturn(system, retval); 182 FuncReturn(system, retval);
183} 183}
184 184
185template <ResultCode func(Core::System&, u32, u64)> 185template <Result func(Core::System&, u32, u64)>
186void SvcWrap64(Core::System& system) { 186void SvcWrap64(Core::System& system) {
187 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw); 187 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);
188} 188}
189 189
190// Used by SetResourceLimitLimitValue 190// Used by SetResourceLimitLimitValue
191template <ResultCode func(Core::System&, Handle, LimitableResource, u64)> 191template <Result func(Core::System&, Handle, LimitableResource, u64)>
192void SvcWrap64(Core::System& system) { 192void SvcWrap64(Core::System& system) {
193 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), 193 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
194 static_cast<LimitableResource>(Param(system, 1)), Param(system, 2)) 194 static_cast<LimitableResource>(Param(system, 1)), Param(system, 2))
@@ -196,7 +196,7 @@ void SvcWrap64(Core::System& system) {
196} 196}
197 197
198// Used by SetThreadCoreMask 198// Used by SetThreadCoreMask
199template <ResultCode func(Core::System&, Handle, s32, u64)> 199template <Result func(Core::System&, Handle, s32, u64)>
200void SvcWrap64(Core::System& system) { 200void SvcWrap64(Core::System& system) {
201 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), 201 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
202 static_cast<s32>(Param(system, 1)), Param(system, 2)) 202 static_cast<s32>(Param(system, 1)), Param(system, 2))
@@ -204,44 +204,44 @@ void SvcWrap64(Core::System& system) {
204} 204}
205 205
206// Used by GetThreadCoreMask 206// Used by GetThreadCoreMask
207template <ResultCode func(Core::System&, Handle, s32*, u64*)> 207template <Result func(Core::System&, Handle, s32*, u64*)>
208void SvcWrap64(Core::System& system) { 208void SvcWrap64(Core::System& system) {
209 s32 param_1 = 0; 209 s32 param_1 = 0;
210 u64 param_2 = 0; 210 u64 param_2 = 0;
211 const ResultCode retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2); 211 const Result retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2);
212 212
213 system.CurrentArmInterface().SetReg(1, param_1); 213 system.CurrentArmInterface().SetReg(1, param_1);
214 system.CurrentArmInterface().SetReg(2, param_2); 214 system.CurrentArmInterface().SetReg(2, param_2);
215 FuncReturn(system, retval.raw); 215 FuncReturn(system, retval.raw);
216} 216}
217 217
218template <ResultCode func(Core::System&, u64, u64, u32, u32)> 218template <Result func(Core::System&, u64, u64, u32, u32)>
219void SvcWrap64(Core::System& system) { 219void SvcWrap64(Core::System& system) {
220 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), 220 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
221 static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3))) 221 static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
222 .raw); 222 .raw);
223} 223}
224 224
225template <ResultCode func(Core::System&, u64, u64, u32, u64)> 225template <Result func(Core::System&, u64, u64, u32, u64)>
226void SvcWrap64(Core::System& system) { 226void SvcWrap64(Core::System& system) {
227 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), 227 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
228 static_cast<u32>(Param(system, 2)), Param(system, 3)) 228 static_cast<u32>(Param(system, 2)), Param(system, 3))
229 .raw); 229 .raw);
230} 230}
231 231
232template <ResultCode func(Core::System&, u32, u64, u32)> 232template <Result func(Core::System&, u32, u64, u32)>
233void SvcWrap64(Core::System& system) { 233void SvcWrap64(Core::System& system) {
234 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), 234 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
235 static_cast<u32>(Param(system, 2))) 235 static_cast<u32>(Param(system, 2)))
236 .raw); 236 .raw);
237} 237}
238 238
239template <ResultCode func(Core::System&, u64, u64, u64)> 239template <Result func(Core::System&, u64, u64, u64)>
240void SvcWrap64(Core::System& system) { 240void SvcWrap64(Core::System& system) {
241 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw); 241 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw);
242} 242}
243 243
244template <ResultCode func(Core::System&, u64, u64, u32)> 244template <Result func(Core::System&, u64, u64, u32)>
245void SvcWrap64(Core::System& system) { 245void SvcWrap64(Core::System& system) {
246 FuncReturn( 246 FuncReturn(
247 system, 247 system,
@@ -249,7 +249,7 @@ void SvcWrap64(Core::System& system) {
249} 249}
250 250
251// Used by SetMemoryPermission 251// Used by SetMemoryPermission
252template <ResultCode func(Core::System&, u64, u64, Svc::MemoryPermission)> 252template <Result func(Core::System&, u64, u64, Svc::MemoryPermission)>
253void SvcWrap64(Core::System& system) { 253void SvcWrap64(Core::System& system) {
254 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), 254 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
255 static_cast<Svc::MemoryPermission>(Param(system, 2))) 255 static_cast<Svc::MemoryPermission>(Param(system, 2)))
@@ -257,14 +257,14 @@ void SvcWrap64(Core::System& system) {
257} 257}
258 258
259// Used by MapSharedMemory 259// Used by MapSharedMemory
260template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)> 260template <Result func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
261void SvcWrap64(Core::System& system) { 261void SvcWrap64(Core::System& system) {
262 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), Param(system, 1), 262 FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), Param(system, 1),
263 Param(system, 2), static_cast<Svc::MemoryPermission>(Param(system, 3))) 263 Param(system, 2), static_cast<Svc::MemoryPermission>(Param(system, 3)))
264 .raw); 264 .raw);
265} 265}
266 266
267template <ResultCode func(Core::System&, u32, u64, u64)> 267template <Result func(Core::System&, u32, u64, u64)>
268void SvcWrap64(Core::System& system) { 268void SvcWrap64(Core::System& system) {
269 FuncReturn( 269 FuncReturn(
270 system, 270 system,
@@ -272,7 +272,7 @@ void SvcWrap64(Core::System& system) {
272} 272}
273 273
274// Used by WaitSynchronization 274// Used by WaitSynchronization
275template <ResultCode func(Core::System&, s32*, u64, s32, s64)> 275template <Result func(Core::System&, s32*, u64, s32, s64)>
276void SvcWrap64(Core::System& system) { 276void SvcWrap64(Core::System& system) {
277 s32 param_1 = 0; 277 s32 param_1 = 0;
278 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<s32>(Param(system, 2)), 278 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<s32>(Param(system, 2)),
@@ -283,7 +283,7 @@ void SvcWrap64(Core::System& system) {
283 FuncReturn(system, retval); 283 FuncReturn(system, retval);
284} 284}
285 285
286template <ResultCode func(Core::System&, u64, u64, u32, s64)> 286template <Result func(Core::System&, u64, u64, u32, s64)>
287void SvcWrap64(Core::System& system) { 287void SvcWrap64(Core::System& system) {
288 FuncReturn(system, func(system, Param(system, 0), Param(system, 1), 288 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
289 static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3))) 289 static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
@@ -291,7 +291,7 @@ void SvcWrap64(Core::System& system) {
291} 291}
292 292
293// Used by GetInfo 293// Used by GetInfo
294template <ResultCode func(Core::System&, u64*, u64, Handle, u64)> 294template <Result func(Core::System&, u64*, u64, Handle, u64)>
295void SvcWrap64(Core::System& system) { 295void SvcWrap64(Core::System& system) {
296 u64 param_1 = 0; 296 u64 param_1 = 0;
297 const u32 retval = func(system, &param_1, Param(system, 1), 297 const u32 retval = func(system, &param_1, Param(system, 1),
@@ -302,7 +302,7 @@ void SvcWrap64(Core::System& system) {
302 FuncReturn(system, retval); 302 FuncReturn(system, retval);
303} 303}
304 304
305template <ResultCode func(Core::System&, u32*, u64, u64, u64, u32, s32)> 305template <Result func(Core::System&, u32*, u64, u64, u64, u32, s32)>
306void SvcWrap64(Core::System& system) { 306void SvcWrap64(Core::System& system) {
307 u32 param_1 = 0; 307 u32 param_1 = 0;
308 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3), 308 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3),
@@ -314,7 +314,7 @@ void SvcWrap64(Core::System& system) {
314} 314}
315 315
316// Used by CreateTransferMemory 316// Used by CreateTransferMemory
317template <ResultCode func(Core::System&, Handle*, u64, u64, Svc::MemoryPermission)> 317template <Result func(Core::System&, Handle*, u64, u64, Svc::MemoryPermission)>
318void SvcWrap64(Core::System& system) { 318void SvcWrap64(Core::System& system) {
319 u32 param_1 = 0; 319 u32 param_1 = 0;
320 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), 320 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2),
@@ -326,7 +326,7 @@ void SvcWrap64(Core::System& system) {
326} 326}
327 327
328// Used by CreateCodeMemory 328// Used by CreateCodeMemory
329template <ResultCode func(Core::System&, Handle*, u64, u64)> 329template <Result func(Core::System&, Handle*, u64, u64)>
330void SvcWrap64(Core::System& system) { 330void SvcWrap64(Core::System& system) {
331 u32 param_1 = 0; 331 u32 param_1 = 0;
332 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2)).raw; 332 const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2)).raw;
@@ -335,7 +335,7 @@ void SvcWrap64(Core::System& system) {
335 FuncReturn(system, retval); 335 FuncReturn(system, retval);
336} 336}
337 337
338template <ResultCode func(Core::System&, Handle*, u64, u32, u32)> 338template <Result func(Core::System&, Handle*, u64, u32, u32)>
339void SvcWrap64(Core::System& system) { 339void SvcWrap64(Core::System& system) {
340 u32 param_1 = 0; 340 u32 param_1 = 0;
341 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)), 341 const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
@@ -347,7 +347,7 @@ void SvcWrap64(Core::System& system) {
347} 347}
348 348
349// Used by WaitForAddress 349// Used by WaitForAddress
350template <ResultCode func(Core::System&, u64, Svc::ArbitrationType, s32, s64)> 350template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)>
351void SvcWrap64(Core::System& system) { 351void SvcWrap64(Core::System& system) {
352 FuncReturn(system, 352 FuncReturn(system,
353 func(system, Param(system, 0), static_cast<Svc::ArbitrationType>(Param(system, 1)), 353 func(system, Param(system, 0), static_cast<Svc::ArbitrationType>(Param(system, 1)),
@@ -356,7 +356,7 @@ void SvcWrap64(Core::System& system) {
356} 356}
357 357
358// Used by SignalToAddress 358// Used by SignalToAddress
359template <ResultCode func(Core::System&, u64, Svc::SignalType, s32, s32)> 359template <Result func(Core::System&, u64, Svc::SignalType, s32, s32)>
360void SvcWrap64(Core::System& system) { 360void SvcWrap64(Core::System& system) {
361 FuncReturn(system, 361 FuncReturn(system,
362 func(system, Param(system, 0), static_cast<Svc::SignalType>(Param(system, 1)), 362 func(system, Param(system, 0), static_cast<Svc::SignalType>(Param(system, 1)),
@@ -425,7 +425,7 @@ void SvcWrap64(Core::System& system) {
425} 425}
426 426
427// Used by QueryMemory32, ArbitrateLock32 427// Used by QueryMemory32, ArbitrateLock32
428template <ResultCode func(Core::System&, u32, u32, u32)> 428template <Result func(Core::System&, u32, u32, u32)>
429void SvcWrap32(Core::System& system) { 429void SvcWrap32(Core::System& system) {
430 FuncReturn32(system, 430 FuncReturn32(system,
431 func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw); 431 func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw);
@@ -456,7 +456,7 @@ void SvcWrap32(Core::System& system) {
456} 456}
457 457
458// Used by CreateThread32 458// Used by CreateThread32
459template <ResultCode func(Core::System&, Handle*, u32, u32, u32, u32, s32)> 459template <Result func(Core::System&, Handle*, u32, u32, u32, u32, s32)>
460void SvcWrap32(Core::System& system) { 460void SvcWrap32(Core::System& system) {
461 Handle param_1 = 0; 461 Handle param_1 = 0;
462 462
@@ -469,7 +469,7 @@ void SvcWrap32(Core::System& system) {
469} 469}
470 470
471// Used by GetInfo32 471// Used by GetInfo32
472template <ResultCode func(Core::System&, u32*, u32*, u32, u32, u32, u32)> 472template <Result func(Core::System&, u32*, u32*, u32, u32, u32, u32)>
473void SvcWrap32(Core::System& system) { 473void SvcWrap32(Core::System& system) {
474 u32 param_1 = 0; 474 u32 param_1 = 0;
475 u32 param_2 = 0; 475 u32 param_2 = 0;
@@ -484,7 +484,7 @@ void SvcWrap32(Core::System& system) {
484} 484}
485 485
486// Used by GetThreadPriority32, ConnectToNamedPort32 486// Used by GetThreadPriority32, ConnectToNamedPort32
487template <ResultCode func(Core::System&, u32*, u32)> 487template <Result func(Core::System&, u32*, u32)>
488void SvcWrap32(Core::System& system) { 488void SvcWrap32(Core::System& system) {
489 u32 param_1 = 0; 489 u32 param_1 = 0;
490 const u32 retval = func(system, &param_1, Param32(system, 1)).raw; 490 const u32 retval = func(system, &param_1, Param32(system, 1)).raw;
@@ -493,7 +493,7 @@ void SvcWrap32(Core::System& system) {
493} 493}
494 494
495// Used by GetThreadId32 495// Used by GetThreadId32
496template <ResultCode func(Core::System&, u32*, u32*, u32)> 496template <Result func(Core::System&, u32*, u32*, u32)>
497void SvcWrap32(Core::System& system) { 497void SvcWrap32(Core::System& system) {
498 u32 param_1 = 0; 498 u32 param_1 = 0;
499 u32 param_2 = 0; 499 u32 param_2 = 0;
@@ -516,7 +516,7 @@ void SvcWrap32(Core::System& system) {
516} 516}
517 517
518// Used by CreateEvent32 518// Used by CreateEvent32
519template <ResultCode func(Core::System&, Handle*, Handle*)> 519template <Result func(Core::System&, Handle*, Handle*)>
520void SvcWrap32(Core::System& system) { 520void SvcWrap32(Core::System& system) {
521 Handle param_1 = 0; 521 Handle param_1 = 0;
522 Handle param_2 = 0; 522 Handle param_2 = 0;
@@ -528,7 +528,7 @@ void SvcWrap32(Core::System& system) {
528} 528}
529 529
530// Used by GetThreadId32 530// Used by GetThreadId32
531template <ResultCode func(Core::System&, Handle, u32*, u32*, u32*)> 531template <Result func(Core::System&, Handle, u32*, u32*, u32*)>
532void SvcWrap32(Core::System& system) { 532void SvcWrap32(Core::System& system) {
533 u32 param_1 = 0; 533 u32 param_1 = 0;
534 u32 param_2 = 0; 534 u32 param_2 = 0;
@@ -542,7 +542,7 @@ void SvcWrap32(Core::System& system) {
542} 542}
543 543
544// Used by GetThreadCoreMask32 544// Used by GetThreadCoreMask32
545template <ResultCode func(Core::System&, Handle, s32*, u32*, u32*)> 545template <Result func(Core::System&, Handle, s32*, u32*, u32*)>
546void SvcWrap32(Core::System& system) { 546void SvcWrap32(Core::System& system) {
547 s32 param_1 = 0; 547 s32 param_1 = 0;
548 u32 param_2 = 0; 548 u32 param_2 = 0;
@@ -562,7 +562,7 @@ void SvcWrap32(Core::System& system) {
562} 562}
563 563
564// Used by SetThreadActivity32 564// Used by SetThreadActivity32
565template <ResultCode func(Core::System&, Handle, Svc::ThreadActivity)> 565template <Result func(Core::System&, Handle, Svc::ThreadActivity)>
566void SvcWrap32(Core::System& system) { 566void SvcWrap32(Core::System& system) {
567 const u32 retval = func(system, static_cast<Handle>(Param(system, 0)), 567 const u32 retval = func(system, static_cast<Handle>(Param(system, 0)),
568 static_cast<Svc::ThreadActivity>(Param(system, 1))) 568 static_cast<Svc::ThreadActivity>(Param(system, 1)))
@@ -571,7 +571,7 @@ void SvcWrap32(Core::System& system) {
571} 571}
572 572
573// Used by SetThreadPriority32 573// Used by SetThreadPriority32
574template <ResultCode func(Core::System&, Handle, u32)> 574template <Result func(Core::System&, Handle, u32)>
575void SvcWrap32(Core::System& system) { 575void SvcWrap32(Core::System& system) {
576 const u32 retval = 576 const u32 retval =
577 func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw; 577 func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw;
@@ -579,7 +579,7 @@ void SvcWrap32(Core::System& system) {
579} 579}
580 580
581// Used by SetMemoryAttribute32 581// Used by SetMemoryAttribute32
582template <ResultCode func(Core::System&, Handle, u32, u32, u32)> 582template <Result func(Core::System&, Handle, u32, u32, u32)>
583void SvcWrap32(Core::System& system) { 583void SvcWrap32(Core::System& system) {
584 const u32 retval = 584 const u32 retval =
585 func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1)), 585 func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1)),
@@ -589,7 +589,7 @@ void SvcWrap32(Core::System& system) {
589} 589}
590 590
591// Used by MapSharedMemory32 591// Used by MapSharedMemory32
592template <ResultCode func(Core::System&, Handle, u32, u32, Svc::MemoryPermission)> 592template <Result func(Core::System&, Handle, u32, u32, Svc::MemoryPermission)>
593void SvcWrap32(Core::System& system) { 593void SvcWrap32(Core::System& system) {
594 const u32 retval = func(system, static_cast<Handle>(Param(system, 0)), 594 const u32 retval = func(system, static_cast<Handle>(Param(system, 0)),
595 static_cast<u32>(Param(system, 1)), static_cast<u32>(Param(system, 2)), 595 static_cast<u32>(Param(system, 1)), static_cast<u32>(Param(system, 2)),
@@ -599,7 +599,7 @@ void SvcWrap32(Core::System& system) {
599} 599}
600 600
601// Used by SetThreadCoreMask32 601// Used by SetThreadCoreMask32
602template <ResultCode func(Core::System&, Handle, s32, u32, u32)> 602template <Result func(Core::System&, Handle, s32, u32, u32)>
603void SvcWrap32(Core::System& system) { 603void SvcWrap32(Core::System& system) {
604 const u32 retval = 604 const u32 retval =
605 func(system, static_cast<Handle>(Param(system, 0)), static_cast<s32>(Param(system, 1)), 605 func(system, static_cast<Handle>(Param(system, 0)), static_cast<s32>(Param(system, 1)),
@@ -609,7 +609,7 @@ void SvcWrap32(Core::System& system) {
609} 609}
610 610
611// Used by WaitProcessWideKeyAtomic32 611// Used by WaitProcessWideKeyAtomic32
612template <ResultCode func(Core::System&, u32, u32, Handle, u32, u32)> 612template <Result func(Core::System&, u32, u32, Handle, u32, u32)>
613void SvcWrap32(Core::System& system) { 613void SvcWrap32(Core::System& system) {
614 const u32 retval = 614 const u32 retval =
615 func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1)), 615 func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1)),
@@ -620,7 +620,7 @@ void SvcWrap32(Core::System& system) {
620} 620}
621 621
622// Used by WaitForAddress32 622// Used by WaitForAddress32
623template <ResultCode func(Core::System&, u32, Svc::ArbitrationType, s32, u32, u32)> 623template <Result func(Core::System&, u32, Svc::ArbitrationType, s32, u32, u32)>
624void SvcWrap32(Core::System& system) { 624void SvcWrap32(Core::System& system) {
625 const u32 retval = func(system, static_cast<u32>(Param(system, 0)), 625 const u32 retval = func(system, static_cast<u32>(Param(system, 0)),
626 static_cast<Svc::ArbitrationType>(Param(system, 1)), 626 static_cast<Svc::ArbitrationType>(Param(system, 1)),
@@ -631,7 +631,7 @@ void SvcWrap32(Core::System& system) {
631} 631}
632 632
633// Used by SignalToAddress32 633// Used by SignalToAddress32
634template <ResultCode func(Core::System&, u32, Svc::SignalType, s32, s32)> 634template <Result func(Core::System&, u32, Svc::SignalType, s32, s32)>
635void SvcWrap32(Core::System& system) { 635void SvcWrap32(Core::System& system) {
636 const u32 retval = func(system, static_cast<u32>(Param(system, 0)), 636 const u32 retval = func(system, static_cast<u32>(Param(system, 0)),
637 static_cast<Svc::SignalType>(Param(system, 1)), 637 static_cast<Svc::SignalType>(Param(system, 1)),
@@ -641,13 +641,13 @@ void SvcWrap32(Core::System& system) {
641} 641}
642 642
643// Used by SendSyncRequest32, ArbitrateUnlock32 643// Used by SendSyncRequest32, ArbitrateUnlock32
644template <ResultCode func(Core::System&, u32)> 644template <Result func(Core::System&, u32)>
645void SvcWrap32(Core::System& system) { 645void SvcWrap32(Core::System& system) {
646 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw); 646 FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
647} 647}
648 648
649// Used by CreateTransferMemory32 649// Used by CreateTransferMemory32
650template <ResultCode func(Core::System&, Handle*, u32, u32, Svc::MemoryPermission)> 650template <Result func(Core::System&, Handle*, u32, u32, Svc::MemoryPermission)>
651void SvcWrap32(Core::System& system) { 651void SvcWrap32(Core::System& system) {
652 Handle handle = 0; 652 Handle handle = 0;
653 const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2), 653 const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2),
@@ -658,7 +658,7 @@ void SvcWrap32(Core::System& system) {
658} 658}
659 659
660// Used by WaitSynchronization32 660// Used by WaitSynchronization32
661template <ResultCode func(Core::System&, u32, u32, s32, u32, s32*)> 661template <Result func(Core::System&, u32, u32, s32, u32, s32*)>
662void SvcWrap32(Core::System& system) { 662void SvcWrap32(Core::System& system) {
663 s32 param_1 = 0; 663 s32 param_1 = 0;
664 const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2), 664 const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2),
@@ -669,7 +669,7 @@ void SvcWrap32(Core::System& system) {
669} 669}
670 670
671// Used by CreateCodeMemory32 671// Used by CreateCodeMemory32
672template <ResultCode func(Core::System&, Handle*, u32, u32)> 672template <Result func(Core::System&, Handle*, u32, u32)>
673void SvcWrap32(Core::System& system) { 673void SvcWrap32(Core::System& system) {
674 Handle handle = 0; 674 Handle handle = 0;
675 675
@@ -680,7 +680,7 @@ void SvcWrap32(Core::System& system) {
680} 680}
681 681
682// Used by ControlCodeMemory32 682// Used by ControlCodeMemory32
683template <ResultCode func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)> 683template <Result func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)>
684void SvcWrap32(Core::System& system) { 684void SvcWrap32(Core::System& system) {
685 const u32 retval = 685 const u32 retval =
686 func(system, Param32(system, 0), Param32(system, 1), Param(system, 2), Param(system, 4), 686 func(system, Param32(system, 0), Param32(system, 1), Param(system, 2), Param(system, 4),
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 569dd9f38..aa9e5b89d 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -112,15 +112,15 @@ enum class ErrorModule : u32 {
112}; 112};
113 113
114/// Encapsulates a Horizon OS error code, allowing it to be separated into its constituent fields. 114/// Encapsulates a Horizon OS error code, allowing it to be separated into its constituent fields.
115union ResultCode { 115union Result {
116 u32 raw; 116 u32 raw;
117 117
118 BitField<0, 9, ErrorModule> module; 118 BitField<0, 9, ErrorModule> module;
119 BitField<9, 13, u32> description; 119 BitField<9, 13, u32> description;
120 120
121 constexpr explicit ResultCode(u32 raw_) : raw(raw_) {} 121 constexpr explicit Result(u32 raw_) : raw(raw_) {}
122 122
123 constexpr ResultCode(ErrorModule module_, u32 description_) 123 constexpr Result(ErrorModule module_, u32 description_)
124 : raw(module.FormatValue(module_) | description.FormatValue(description_)) {} 124 : raw(module.FormatValue(module_) | description.FormatValue(description_)) {}
125 125
126 [[nodiscard]] constexpr bool IsSuccess() const { 126 [[nodiscard]] constexpr bool IsSuccess() const {
@@ -132,18 +132,18 @@ union ResultCode {
132 } 132 }
133}; 133};
134 134
135[[nodiscard]] constexpr bool operator==(const ResultCode& a, const ResultCode& b) { 135[[nodiscard]] constexpr bool operator==(const Result& a, const Result& b) {
136 return a.raw == b.raw; 136 return a.raw == b.raw;
137} 137}
138 138
139[[nodiscard]] constexpr bool operator!=(const ResultCode& a, const ResultCode& b) { 139[[nodiscard]] constexpr bool operator!=(const Result& a, const Result& b) {
140 return !operator==(a, b); 140 return !operator==(a, b);
141} 141}
142 142
143// Convenience functions for creating some common kinds of errors: 143// Convenience functions for creating some common kinds of errors:
144 144
145/// The default success `ResultCode`. 145/// The default success `Result`.
146constexpr ResultCode ResultSuccess(0); 146constexpr Result ResultSuccess(0);
147 147
148/** 148/**
149 * Placeholder result code used for unknown error codes. 149 * Placeholder result code used for unknown error codes.
@@ -151,24 +151,24 @@ constexpr ResultCode ResultSuccess(0);
151 * @note This should only be used when a particular error code 151 * @note This should only be used when a particular error code
152 * is not known yet. 152 * is not known yet.
153 */ 153 */
154constexpr ResultCode ResultUnknown(UINT32_MAX); 154constexpr Result ResultUnknown(UINT32_MAX);
155 155
156/** 156/**
157 * A ResultRange defines an inclusive range of error descriptions within an error module. 157 * A ResultRange defines an inclusive range of error descriptions within an error module.
158 * This can be used to check whether the description of a given ResultCode falls within the range. 158 * This can be used to check whether the description of a given Result falls within the range.
159 * The conversion function returns a ResultCode with its description set to description_start. 159 * The conversion function returns a Result with its description set to description_start.
160 * 160 *
161 * An example of how it could be used: 161 * An example of how it could be used:
162 * \code 162 * \code
163 * constexpr ResultRange ResultCommonError{ErrorModule::Common, 0, 9999}; 163 * constexpr ResultRange ResultCommonError{ErrorModule::Common, 0, 9999};
164 * 164 *
165 * ResultCode Example(int value) { 165 * Result Example(int value) {
166 * const ResultCode result = OtherExample(value); 166 * const Result result = OtherExample(value);
167 * 167 *
168 * // This will only evaluate to true if result.module is ErrorModule::Common and 168 * // This will only evaluate to true if result.module is ErrorModule::Common and
169 * // result.description is in between 0 and 9999 inclusive. 169 * // result.description is in between 0 and 9999 inclusive.
170 * if (ResultCommonError.Includes(result)) { 170 * if (ResultCommonError.Includes(result)) {
171 * // This returns ResultCode{ErrorModule::Common, 0}; 171 * // This returns Result{ErrorModule::Common, 0};
172 * return ResultCommonError; 172 * return ResultCommonError;
173 * } 173 * }
174 * 174 *
@@ -181,22 +181,22 @@ public:
181 consteval ResultRange(ErrorModule module, u32 description_start, u32 description_end_) 181 consteval ResultRange(ErrorModule module, u32 description_start, u32 description_end_)
182 : code{module, description_start}, description_end{description_end_} {} 182 : code{module, description_start}, description_end{description_end_} {}
183 183
184 [[nodiscard]] constexpr operator ResultCode() const { 184 [[nodiscard]] constexpr operator Result() const {
185 return code; 185 return code;
186 } 186 }
187 187
188 [[nodiscard]] constexpr bool Includes(ResultCode other) const { 188 [[nodiscard]] constexpr bool Includes(Result other) const {
189 return code.module == other.module && code.description <= other.description && 189 return code.module == other.module && code.description <= other.description &&
190 other.description <= description_end; 190 other.description <= description_end;
191 } 191 }
192 192
193private: 193private:
194 ResultCode code; 194 Result code;
195 u32 description_end; 195 u32 description_end;
196}; 196};
197 197
198/** 198/**
199 * This is an optional value type. It holds a `ResultCode` and, if that code is ResultSuccess, it 199 * This is an optional value type. It holds a `Result` and, if that code is ResultSuccess, it
200 * also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying 200 * also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying
201 * to access the inner value with operator* is undefined behavior and will assert with Unwrap(). 201 * to access the inner value with operator* is undefined behavior and will assert with Unwrap().
202 * Users of this class must be cognizant to check the status of the ResultVal with operator bool(), 202 * Users of this class must be cognizant to check the status of the ResultVal with operator bool(),
@@ -207,7 +207,7 @@ private:
207 * ResultVal<int> Frobnicate(float strength) { 207 * ResultVal<int> Frobnicate(float strength) {
208 * if (strength < 0.f || strength > 1.0f) { 208 * if (strength < 0.f || strength > 1.0f) {
209 * // Can't frobnicate too weakly or too strongly 209 * // Can't frobnicate too weakly or too strongly
210 * return ResultCode{ErrorModule::Common, 1}; 210 * return Result{ErrorModule::Common, 1};
211 * } else { 211 * } else {
212 * // Frobnicated! Give caller a cookie 212 * // Frobnicated! Give caller a cookie
213 * return 42; 213 * return 42;
@@ -230,7 +230,7 @@ class ResultVal {
230public: 230public:
231 constexpr ResultVal() : expected{} {} 231 constexpr ResultVal() : expected{} {}
232 232
233 constexpr ResultVal(ResultCode code) : expected{Common::Unexpected(code)} {} 233 constexpr ResultVal(Result code) : expected{Common::Unexpected(code)} {}
234 234
235 constexpr ResultVal(ResultRange range) : expected{Common::Unexpected(range)} {} 235 constexpr ResultVal(ResultRange range) : expected{Common::Unexpected(range)} {}
236 236
@@ -252,7 +252,7 @@ public:
252 return expected.has_value(); 252 return expected.has_value();
253 } 253 }
254 254
255 [[nodiscard]] constexpr ResultCode Code() const { 255 [[nodiscard]] constexpr Result Code() const {
256 return expected.has_value() ? ResultSuccess : expected.error(); 256 return expected.has_value() ? ResultSuccess : expected.error();
257 } 257 }
258 258
@@ -320,7 +320,7 @@ public:
320 320
321private: 321private:
322 // TODO (Morph): Replace this with C++23 std::expected. 322 // TODO (Morph): Replace this with C++23 std::expected.
323 Common::Expected<T, ResultCode> expected; 323 Common::Expected<T, Result> expected;
324}; 324};
325 325
326/** 326/**
@@ -337,7 +337,7 @@ private:
337 target = std::move(*CONCAT2(check_result_L, __LINE__)) 337 target = std::move(*CONCAT2(check_result_L, __LINE__))
338 338
339/** 339/**
340 * Analogous to CASCADE_RESULT, but for a bare ResultCode. The code will be propagated if 340 * Analogous to CASCADE_RESULT, but for a bare Result. The code will be propagated if
341 * non-success, or discarded otherwise. 341 * non-success, or discarded otherwise.
342 */ 342 */
343#define CASCADE_CODE(source) \ 343#define CASCADE_CODE(source) \
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 88b74cbb0..b726ac27a 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -28,11 +28,11 @@
28 28
29namespace Service::Account { 29namespace Service::Account {
30 30
31constexpr ResultCode ERR_INVALID_USER_ID{ErrorModule::Account, 20}; 31constexpr Result ERR_INVALID_USER_ID{ErrorModule::Account, 20};
32constexpr ResultCode ERR_INVALID_APPLICATION_ID{ErrorModule::Account, 22}; 32constexpr Result ERR_INVALID_APPLICATION_ID{ErrorModule::Account, 22};
33constexpr ResultCode ERR_INVALID_BUFFER{ErrorModule::Account, 30}; 33constexpr Result ERR_INVALID_BUFFER{ErrorModule::Account, 30};
34constexpr ResultCode ERR_INVALID_BUFFER_SIZE{ErrorModule::Account, 31}; 34constexpr Result ERR_INVALID_BUFFER_SIZE{ErrorModule::Account, 31};
35constexpr ResultCode ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100}; 35constexpr Result ERR_FAILED_SAVE_DATA{ErrorModule::Account, 100};
36 36
37// Thumbnails are hard coded to be at least this size 37// Thumbnails are hard coded to be at least this size
38constexpr std::size_t THUMBNAIL_SIZE = 0x24000; 38constexpr std::size_t THUMBNAIL_SIZE = 0x24000;
@@ -505,7 +505,7 @@ protected:
505 505
506 void Cancel() override {} 506 void Cancel() override {}
507 507
508 ResultCode GetResult() const override { 508 Result GetResult() const override {
509 return ResultSuccess; 509 return ResultSuccess;
510 } 510 }
511}; 511};
@@ -747,7 +747,7 @@ void Module::Interface::InitializeApplicationInfoRestricted(Kernel::HLERequestCo
747 rb.Push(InitializeApplicationInfoBase()); 747 rb.Push(InitializeApplicationInfoBase());
748} 748}
749 749
750ResultCode Module::Interface::InitializeApplicationInfoBase() { 750Result Module::Interface::InitializeApplicationInfoBase() {
751 if (application_info) { 751 if (application_info) {
752 LOG_ERROR(Service_ACC, "Application already initialized"); 752 LOG_ERROR(Service_ACC, "Application already initialized");
753 return ERR_ACCOUNTINFO_ALREADY_INITIALIZED; 753 return ERR_ACCOUNTINFO_ALREADY_INITIALIZED;
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index fff447fc3..1621e7c0a 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -41,7 +41,7 @@ public:
41 void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx); 41 void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx);
42 42
43 private: 43 private:
44 ResultCode InitializeApplicationInfoBase(); 44 Result InitializeApplicationInfoBase();
45 void StoreSaveDataThumbnail(Kernel::HLERequestContext& ctx, const Common::UUID& uuid, 45 void StoreSaveDataThumbnail(Kernel::HLERequestContext& ctx, const Common::UUID& uuid,
46 const u64 tid); 46 const u64 tid);
47 47
diff --git a/src/core/hle/service/acc/async_context.h b/src/core/hle/service/acc/async_context.h
index e4929f7f0..26332d241 100644
--- a/src/core/hle/service/acc/async_context.h
+++ b/src/core/hle/service/acc/async_context.h
@@ -26,7 +26,7 @@ public:
26protected: 26protected:
27 virtual bool IsComplete() const = 0; 27 virtual bool IsComplete() const = 0;
28 virtual void Cancel() = 0; 28 virtual void Cancel() = 0;
29 virtual ResultCode GetResult() const = 0; 29 virtual Result GetResult() const = 0;
30 30
31 void MarkComplete(); 31 void MarkComplete();
32 32
diff --git a/src/core/hle/service/acc/errors.h b/src/core/hle/service/acc/errors.h
index eafb75713..e9c16b951 100644
--- a/src/core/hle/service/acc/errors.h
+++ b/src/core/hle/service/acc/errors.h
@@ -7,7 +7,7 @@
7 7
8namespace Service::Account { 8namespace Service::Account {
9 9
10constexpr ResultCode ERR_ACCOUNTINFO_BAD_APPLICATION{ErrorModule::Account, 22}; 10constexpr Result ERR_ACCOUNTINFO_BAD_APPLICATION{ErrorModule::Account, 22};
11constexpr ResultCode ERR_ACCOUNTINFO_ALREADY_INITIALIZED{ErrorModule::Account, 41}; 11constexpr Result ERR_ACCOUNTINFO_ALREADY_INITIALIZED{ErrorModule::Account, 41};
12 12
13} // namespace Service::Account 13} // namespace Service::Account
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 0ef298180..8118ead33 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -33,9 +33,9 @@ struct ProfileDataRaw {
33static_assert(sizeof(ProfileDataRaw) == 0x650, "ProfileDataRaw has incorrect size."); 33static_assert(sizeof(ProfileDataRaw) == 0x650, "ProfileDataRaw has incorrect size.");
34 34
35// TODO(ogniK): Get actual error codes 35// TODO(ogniK): Get actual error codes
36constexpr ResultCode ERROR_TOO_MANY_USERS(ErrorModule::Account, u32(-1)); 36constexpr Result ERROR_TOO_MANY_USERS(ErrorModule::Account, u32(-1));
37constexpr ResultCode ERROR_USER_ALREADY_EXISTS(ErrorModule::Account, u32(-2)); 37constexpr Result ERROR_USER_ALREADY_EXISTS(ErrorModule::Account, u32(-2));
38constexpr ResultCode ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20); 38constexpr Result ERROR_ARGUMENT_IS_NULL(ErrorModule::Account, 20);
39 39
40constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "system/save/8000000000000010/su/avators"; 40constexpr char ACC_SAVE_AVATORS_BASE_PATH[] = "system/save/8000000000000010/su/avators";
41 41
@@ -87,7 +87,7 @@ bool ProfileManager::RemoveProfileAtIndex(std::size_t index) {
87} 87}
88 88
89/// Helper function to register a user to the system 89/// Helper function to register a user to the system
90ResultCode ProfileManager::AddUser(const ProfileInfo& user) { 90Result ProfileManager::AddUser(const ProfileInfo& user) {
91 if (!AddToProfiles(user)) { 91 if (!AddToProfiles(user)) {
92 return ERROR_TOO_MANY_USERS; 92 return ERROR_TOO_MANY_USERS;
93 } 93 }
@@ -96,7 +96,7 @@ ResultCode ProfileManager::AddUser(const ProfileInfo& user) {
96 96
97/// Create a new user on the system. If the uuid of the user already exists, the user is not 97/// Create a new user on the system. If the uuid of the user already exists, the user is not
98/// created. 98/// created.
99ResultCode ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& username) { 99Result ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& username) {
100 if (user_count == MAX_USERS) { 100 if (user_count == MAX_USERS) {
101 return ERROR_TOO_MANY_USERS; 101 return ERROR_TOO_MANY_USERS;
102 } 102 }
@@ -123,7 +123,7 @@ ResultCode ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& usern
123/// Creates a new user on the system. This function allows a much simpler method of registration 123/// Creates a new user on the system. This function allows a much simpler method of registration
124/// specifically by allowing an std::string for the username. This is required specifically since 124/// specifically by allowing an std::string for the username. This is required specifically since
125/// we're loading a string straight from the config 125/// we're loading a string straight from the config
126ResultCode ProfileManager::CreateNewUser(UUID uuid, const std::string& username) { 126Result ProfileManager::CreateNewUser(UUID uuid, const std::string& username) {
127 ProfileUsername username_output{}; 127 ProfileUsername username_output{};
128 128
129 if (username.size() > username_output.size()) { 129 if (username.size() > username_output.size()) {
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 955dbd3d6..9940957f1 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -64,9 +64,9 @@ public:
64 ProfileManager(); 64 ProfileManager();
65 ~ProfileManager(); 65 ~ProfileManager();
66 66
67 ResultCode AddUser(const ProfileInfo& user); 67 Result AddUser(const ProfileInfo& user);
68 ResultCode CreateNewUser(Common::UUID uuid, const ProfileUsername& username); 68 Result CreateNewUser(Common::UUID uuid, const ProfileUsername& username);
69 ResultCode CreateNewUser(Common::UUID uuid, const std::string& username); 69 Result CreateNewUser(Common::UUID uuid, const std::string& username);
70 std::optional<Common::UUID> GetUser(std::size_t index) const; 70 std::optional<Common::UUID> GetUser(std::size_t index) const;
71 std::optional<std::size_t> GetUserIndex(const Common::UUID& uuid) const; 71 std::optional<std::size_t> GetUserIndex(const Common::UUID& uuid) const;
72 std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const; 72 std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const;
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 4657bdabc..d35644e73 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -40,9 +40,9 @@
40 40
41namespace Service::AM { 41namespace Service::AM {
42 42
43constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 2}; 43constexpr Result ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 2};
44constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 3}; 44constexpr Result ERR_NO_MESSAGES{ErrorModule::AM, 3};
45constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 503}; 45constexpr Result ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 503};
46 46
47enum class LaunchParameterKind : u32 { 47enum class LaunchParameterKind : u32 {
48 ApplicationSpecific = 1, 48 ApplicationSpecific = 1,
@@ -365,7 +365,7 @@ void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) {
365 // Entry and exit of fatal sections must be balanced. 365 // Entry and exit of fatal sections must be balanced.
366 if (num_fatal_sections_entered == 0) { 366 if (num_fatal_sections_entered == 0) {
367 IPC::ResponseBuilder rb{ctx, 2}; 367 IPC::ResponseBuilder rb{ctx, 2};
368 rb.Push(ResultCode{ErrorModule::AM, 512}); 368 rb.Push(Result{ErrorModule::AM, 512});
369 return; 369 return;
370 } 370 }
371 371
@@ -686,7 +686,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
686 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"}, 686 {66, &ICommonStateGetter::SetCpuBoostMode, "SetCpuBoostMode"},
687 {67, nullptr, "CancelCpuBoostMode"}, 687 {67, nullptr, "CancelCpuBoostMode"},
688 {68, nullptr, "GetBuiltInDisplayType"}, 688 {68, nullptr, "GetBuiltInDisplayType"},
689 {80, nullptr, "PerformSystemButtonPressingIfInFocus"}, 689 {80, &ICommonStateGetter::PerformSystemButtonPressingIfInFocus, "PerformSystemButtonPressingIfInFocus"},
690 {90, nullptr, "SetPerformanceConfigurationChangedNotification"}, 690 {90, nullptr, "SetPerformanceConfigurationChangedNotification"},
691 {91, nullptr, "GetCurrentPerformanceConfiguration"}, 691 {91, nullptr, "GetCurrentPerformanceConfiguration"},
692 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"}, 692 {100, nullptr, "SetHandlingHomeButtonShortPressedEnabled"},
@@ -826,6 +826,16 @@ void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) {
826 apm_sys->SetCpuBoostMode(ctx); 826 apm_sys->SetCpuBoostMode(ctx);
827} 827}
828 828
829void ICommonStateGetter::PerformSystemButtonPressingIfInFocus(Kernel::HLERequestContext& ctx) {
830 IPC::RequestParser rp{ctx};
831 const auto system_button{rp.PopEnum<SystemButtonType>()};
832
833 LOG_WARNING(Service_AM, "(STUBBED) called, system_button={}", system_button);
834
835 IPC::ResponseBuilder rb{ctx, 2};
836 rb.Push(ResultSuccess);
837}
838
829void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled( 839void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
830 Kernel::HLERequestContext& ctx) { 840 Kernel::HLERequestContext& ctx) {
831 LOG_WARNING(Service_AM, "(STUBBED) called"); 841 LOG_WARNING(Service_AM, "(STUBBED) called");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 06f13aa09..988ead215 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -220,6 +220,18 @@ private:
220 Docked = 1, 220 Docked = 1,
221 }; 221 };
222 222
223 // This is nn::am::service::SystemButtonType
224 enum class SystemButtonType {
225 None,
226 HomeButtonShortPressing,
227 HomeButtonLongPressing,
228 PowerButtonShortPressing,
229 PowerButtonLongPressing,
230 ShutdownSystem,
231 CaptureButtonShortPressing,
232 CaptureButtonLongPressing,
233 };
234
223 void GetEventHandle(Kernel::HLERequestContext& ctx); 235 void GetEventHandle(Kernel::HLERequestContext& ctx);
224 void ReceiveMessage(Kernel::HLERequestContext& ctx); 236 void ReceiveMessage(Kernel::HLERequestContext& ctx);
225 void GetCurrentFocusState(Kernel::HLERequestContext& ctx); 237 void GetCurrentFocusState(Kernel::HLERequestContext& ctx);
@@ -234,6 +246,7 @@ private:
234 void EndVrModeEx(Kernel::HLERequestContext& ctx); 246 void EndVrModeEx(Kernel::HLERequestContext& ctx);
235 void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); 247 void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
236 void SetCpuBoostMode(Kernel::HLERequestContext& ctx); 248 void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
249 void PerformSystemButtonPressingIfInFocus(Kernel::HLERequestContext& ctx);
237 void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(Kernel::HLERequestContext& ctx); 250 void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(Kernel::HLERequestContext& ctx);
238 251
239 std::shared_ptr<AppletMessageQueue> msg_queue; 252 std::shared_ptr<AppletMessageQueue> msg_queue;
diff --git a/src/core/hle/service/am/applets/applet_controller.cpp b/src/core/hle/service/am/applets/applet_controller.cpp
index 655f2e936..b418031de 100644
--- a/src/core/hle/service/am/applets/applet_controller.cpp
+++ b/src/core/hle/service/am/applets/applet_controller.cpp
@@ -20,9 +20,9 @@
20namespace Service::AM::Applets { 20namespace Service::AM::Applets {
21 21
22// This error code (0x183ACA) is thrown when the applet fails to initialize. 22// This error code (0x183ACA) is thrown when the applet fails to initialize.
23[[maybe_unused]] constexpr ResultCode ERR_CONTROLLER_APPLET_3101{ErrorModule::HID, 3101}; 23[[maybe_unused]] constexpr Result ERR_CONTROLLER_APPLET_3101{ErrorModule::HID, 3101};
24// This error code (0x183CCA) is thrown when the u32 result in ControllerSupportResultInfo is 2. 24// This error code (0x183CCA) is thrown when the u32 result in ControllerSupportResultInfo is 2.
25[[maybe_unused]] constexpr ResultCode ERR_CONTROLLER_APPLET_3102{ErrorModule::HID, 3102}; 25[[maybe_unused]] constexpr Result ERR_CONTROLLER_APPLET_3102{ErrorModule::HID, 3102};
26 26
27static Core::Frontend::ControllerParameters ConvertToFrontendParameters( 27static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
28 ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text, 28 ControllerSupportArgPrivate private_arg, ControllerSupportArgHeader header, bool enable_text,
@@ -173,12 +173,12 @@ bool Controller::TransactionComplete() const {
173 return complete; 173 return complete;
174} 174}
175 175
176ResultCode Controller::GetStatus() const { 176Result Controller::GetStatus() const {
177 return status; 177 return status;
178} 178}
179 179
180void Controller::ExecuteInteractive() { 180void Controller::ExecuteInteractive() {
181 UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet."); 181 ASSERT_MSG(false, "Attempted to call interactive execution on non-interactive applet.");
182} 182}
183 183
184void Controller::Execute() { 184void Controller::Execute() {
diff --git a/src/core/hle/service/am/applets/applet_controller.h b/src/core/hle/service/am/applets/applet_controller.h
index e1a34853d..1f9adec65 100644
--- a/src/core/hle/service/am/applets/applet_controller.h
+++ b/src/core/hle/service/am/applets/applet_controller.h
@@ -126,7 +126,7 @@ public:
126 void Initialize() override; 126 void Initialize() override;
127 127
128 bool TransactionComplete() const override; 128 bool TransactionComplete() const override;
129 ResultCode GetStatus() const override; 129 Result GetStatus() const override;
130 void ExecuteInteractive() override; 130 void ExecuteInteractive() override;
131 void Execute() override; 131 void Execute() override;
132 132
@@ -143,7 +143,7 @@ private:
143 ControllerUpdateFirmwareArg controller_update_arg; 143 ControllerUpdateFirmwareArg controller_update_arg;
144 ControllerKeyRemappingArg controller_key_remapping_arg; 144 ControllerKeyRemappingArg controller_key_remapping_arg;
145 bool complete{false}; 145 bool complete{false};
146 ResultCode status{ResultSuccess}; 146 Result status{ResultSuccess};
147 bool is_single_mode{false}; 147 bool is_single_mode{false};
148 std::vector<u8> out_data; 148 std::vector<u8> out_data;
149}; 149};
diff --git a/src/core/hle/service/am/applets/applet_error.cpp b/src/core/hle/service/am/applets/applet_error.cpp
index 911b2c229..fcf34bf7e 100644
--- a/src/core/hle/service/am/applets/applet_error.cpp
+++ b/src/core/hle/service/am/applets/applet_error.cpp
@@ -25,15 +25,15 @@ struct ErrorCode {
25 }; 25 };
26 } 26 }
27 27
28 static constexpr ErrorCode FromResultCode(ResultCode result) { 28 static constexpr ErrorCode FromResult(Result result) {
29 return { 29 return {
30 .error_category{2000 + static_cast<u32>(result.module.Value())}, 30 .error_category{2000 + static_cast<u32>(result.module.Value())},
31 .error_number{result.description.Value()}, 31 .error_number{result.description.Value()},
32 }; 32 };
33 } 33 }
34 34
35 constexpr ResultCode ToResultCode() const { 35 constexpr Result ToResult() const {
36 return ResultCode{static_cast<ErrorModule>(error_category - 2000), error_number}; 36 return Result{static_cast<ErrorModule>(error_category - 2000), error_number};
37 } 37 }
38}; 38};
39static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size."); 39static_assert(sizeof(ErrorCode) == 0x8, "ErrorCode has incorrect size.");
@@ -97,8 +97,8 @@ void CopyArgumentData(const std::vector<u8>& data, T& variable) {
97 std::memcpy(&variable, data.data(), sizeof(T)); 97 std::memcpy(&variable, data.data(), sizeof(T));
98} 98}
99 99
100ResultCode Decode64BitError(u64 error) { 100Result Decode64BitError(u64 error) {
101 return ErrorCode::FromU64(error).ToResultCode(); 101 return ErrorCode::FromU64(error).ToResult();
102} 102}
103 103
104} // Anonymous namespace 104} // Anonymous namespace
@@ -127,16 +127,16 @@ void Error::Initialize() {
127 if (args->error.use_64bit_error_code) { 127 if (args->error.use_64bit_error_code) {
128 error_code = Decode64BitError(args->error.error_code_64); 128 error_code = Decode64BitError(args->error.error_code_64);
129 } else { 129 } else {
130 error_code = ResultCode(args->error.error_code_32); 130 error_code = Result(args->error.error_code_32);
131 } 131 }
132 break; 132 break;
133 case ErrorAppletMode::ShowSystemError: 133 case ErrorAppletMode::ShowSystemError:
134 CopyArgumentData(data, args->system_error); 134 CopyArgumentData(data, args->system_error);
135 error_code = ResultCode(Decode64BitError(args->system_error.error_code_64)); 135 error_code = Result(Decode64BitError(args->system_error.error_code_64));
136 break; 136 break;
137 case ErrorAppletMode::ShowApplicationError: 137 case ErrorAppletMode::ShowApplicationError:
138 CopyArgumentData(data, args->application_error); 138 CopyArgumentData(data, args->application_error);
139 error_code = ResultCode(args->application_error.error_code); 139 error_code = Result(args->application_error.error_code);
140 break; 140 break;
141 case ErrorAppletMode::ShowErrorRecord: 141 case ErrorAppletMode::ShowErrorRecord:
142 CopyArgumentData(data, args->error_record); 142 CopyArgumentData(data, args->error_record);
@@ -151,12 +151,12 @@ bool Error::TransactionComplete() const {
151 return complete; 151 return complete;
152} 152}
153 153
154ResultCode Error::GetStatus() const { 154Result Error::GetStatus() const {
155 return ResultSuccess; 155 return ResultSuccess;
156} 156}
157 157
158void Error::ExecuteInteractive() { 158void Error::ExecuteInteractive() {
159 UNREACHABLE_MSG("Unexpected interactive applet data!"); 159 ASSERT_MSG(false, "Unexpected interactive applet data!");
160} 160}
161 161
162void Error::Execute() { 162void Error::Execute() {
diff --git a/src/core/hle/service/am/applets/applet_error.h b/src/core/hle/service/am/applets/applet_error.h
index 43487f647..d78d6f1d1 100644
--- a/src/core/hle/service/am/applets/applet_error.h
+++ b/src/core/hle/service/am/applets/applet_error.h
@@ -31,7 +31,7 @@ public:
31 void Initialize() override; 31 void Initialize() override;
32 32
33 bool TransactionComplete() const override; 33 bool TransactionComplete() const override;
34 ResultCode GetStatus() const override; 34 Result GetStatus() const override;
35 void ExecuteInteractive() override; 35 void ExecuteInteractive() override;
36 void Execute() override; 36 void Execute() override;
37 37
@@ -41,7 +41,7 @@ private:
41 union ErrorArguments; 41 union ErrorArguments;
42 42
43 const Core::Frontend::ErrorApplet& frontend; 43 const Core::Frontend::ErrorApplet& frontend;
44 ResultCode error_code = ResultSuccess; 44 Result error_code = ResultSuccess;
45 ErrorAppletMode mode = ErrorAppletMode::ShowError; 45 ErrorAppletMode mode = ErrorAppletMode::ShowError;
46 std::unique_ptr<ErrorArguments> args; 46 std::unique_ptr<ErrorArguments> args;
47 47
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp
index 3fe1a390a..c34ef08b3 100644
--- a/src/core/hle/service/am/applets/applet_general_backend.cpp
+++ b/src/core/hle/service/am/applets/applet_general_backend.cpp
@@ -13,7 +13,7 @@
13 13
14namespace Service::AM::Applets { 14namespace Service::AM::Applets {
15 15
16constexpr ResultCode ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; 16constexpr Result ERROR_INVALID_PIN{ErrorModule::PCTL, 221};
17 17
18static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) { 18static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) {
19 std::shared_ptr<IStorage> storage = broker.PopNormalDataToApplet(); 19 std::shared_ptr<IStorage> storage = broker.PopNormalDataToApplet();
@@ -71,12 +71,12 @@ bool Auth::TransactionComplete() const {
71 return complete; 71 return complete;
72} 72}
73 73
74ResultCode Auth::GetStatus() const { 74Result Auth::GetStatus() const {
75 return successful ? ResultSuccess : ERROR_INVALID_PIN; 75 return successful ? ResultSuccess : ERROR_INVALID_PIN;
76} 76}
77 77
78void Auth::ExecuteInteractive() { 78void Auth::ExecuteInteractive() {
79 UNREACHABLE_MSG("Unexpected interactive applet data."); 79 ASSERT_MSG(false, "Unexpected interactive applet data.");
80} 80}
81 81
82void Auth::Execute() { 82void Auth::Execute() {
@@ -136,7 +136,7 @@ void Auth::AuthFinished(bool is_successful) {
136 successful = is_successful; 136 successful = is_successful;
137 137
138 struct Return { 138 struct Return {
139 ResultCode result_code; 139 Result result_code;
140 }; 140 };
141 static_assert(sizeof(Return) == 0x4, "Return (AuthApplet) has incorrect size."); 141 static_assert(sizeof(Return) == 0x4, "Return (AuthApplet) has incorrect size.");
142 142
@@ -170,12 +170,12 @@ bool PhotoViewer::TransactionComplete() const {
170 return complete; 170 return complete;
171} 171}
172 172
173ResultCode PhotoViewer::GetStatus() const { 173Result PhotoViewer::GetStatus() const {
174 return ResultSuccess; 174 return ResultSuccess;
175} 175}
176 176
177void PhotoViewer::ExecuteInteractive() { 177void PhotoViewer::ExecuteInteractive() {
178 UNREACHABLE_MSG("Unexpected interactive applet data."); 178 ASSERT_MSG(false, "Unexpected interactive applet data.");
179} 179}
180 180
181void PhotoViewer::Execute() { 181void PhotoViewer::Execute() {
@@ -223,7 +223,7 @@ bool StubApplet::TransactionComplete() const {
223 return true; 223 return true;
224} 224}
225 225
226ResultCode StubApplet::GetStatus() const { 226Result StubApplet::GetStatus() const {
227 LOG_WARNING(Service_AM, "called (STUBBED)"); 227 LOG_WARNING(Service_AM, "called (STUBBED)");
228 return ResultSuccess; 228 return ResultSuccess;
229} 229}
diff --git a/src/core/hle/service/am/applets/applet_general_backend.h b/src/core/hle/service/am/applets/applet_general_backend.h
index e647d0f41..a9f2535a2 100644
--- a/src/core/hle/service/am/applets/applet_general_backend.h
+++ b/src/core/hle/service/am/applets/applet_general_backend.h
@@ -25,7 +25,7 @@ public:
25 25
26 void Initialize() override; 26 void Initialize() override;
27 bool TransactionComplete() const override; 27 bool TransactionComplete() const override;
28 ResultCode GetStatus() const override; 28 Result GetStatus() const override;
29 void ExecuteInteractive() override; 29 void ExecuteInteractive() override;
30 void Execute() override; 30 void Execute() override;
31 31
@@ -56,7 +56,7 @@ public:
56 56
57 void Initialize() override; 57 void Initialize() override;
58 bool TransactionComplete() const override; 58 bool TransactionComplete() const override;
59 ResultCode GetStatus() const override; 59 Result GetStatus() const override;
60 void ExecuteInteractive() override; 60 void ExecuteInteractive() override;
61 void Execute() override; 61 void Execute() override;
62 62
@@ -77,7 +77,7 @@ public:
77 void Initialize() override; 77 void Initialize() override;
78 78
79 bool TransactionComplete() const override; 79 bool TransactionComplete() const override;
80 ResultCode GetStatus() const override; 80 Result GetStatus() const override;
81 void ExecuteInteractive() override; 81 void ExecuteInteractive() override;
82 void Execute() override; 82 void Execute() override;
83 83
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.cpp b/src/core/hle/service/am/applets/applet_mii_edit.cpp
index 3acde1630..ae80ef506 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.cpp
+++ b/src/core/hle/service/am/applets/applet_mii_edit.cpp
@@ -62,12 +62,12 @@ bool MiiEdit::TransactionComplete() const {
62 return is_complete; 62 return is_complete;
63} 63}
64 64
65ResultCode MiiEdit::GetStatus() const { 65Result MiiEdit::GetStatus() const {
66 return ResultSuccess; 66 return ResultSuccess;
67} 67}
68 68
69void MiiEdit::ExecuteInteractive() { 69void MiiEdit::ExecuteInteractive() {
70 UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet."); 70 ASSERT_MSG(false, "Attempted to call interactive execution on non-interactive applet.");
71} 71}
72 72
73void MiiEdit::Execute() { 73void MiiEdit::Execute() {
diff --git a/src/core/hle/service/am/applets/applet_mii_edit.h b/src/core/hle/service/am/applets/applet_mii_edit.h
index 900754e57..d18dd3cf5 100644
--- a/src/core/hle/service/am/applets/applet_mii_edit.h
+++ b/src/core/hle/service/am/applets/applet_mii_edit.h
@@ -22,7 +22,7 @@ public:
22 void Initialize() override; 22 void Initialize() override;
23 23
24 bool TransactionComplete() const override; 24 bool TransactionComplete() const override;
25 ResultCode GetStatus() const override; 25 Result GetStatus() const override;
26 void ExecuteInteractive() override; 26 void ExecuteInteractive() override;
27 void Execute() override; 27 void Execute() override;
28 28
diff --git a/src/core/hle/service/am/applets/applet_profile_select.cpp b/src/core/hle/service/am/applets/applet_profile_select.cpp
index fd16f2e49..c738db028 100644
--- a/src/core/hle/service/am/applets/applet_profile_select.cpp
+++ b/src/core/hle/service/am/applets/applet_profile_select.cpp
@@ -12,7 +12,7 @@
12 12
13namespace Service::AM::Applets { 13namespace Service::AM::Applets {
14 14
15constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1}; 15constexpr Result ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
16 16
17ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_, 17ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
18 const Core::Frontend::ProfileSelectApplet& frontend_) 18 const Core::Frontend::ProfileSelectApplet& frontend_)
@@ -39,12 +39,12 @@ bool ProfileSelect::TransactionComplete() const {
39 return complete; 39 return complete;
40} 40}
41 41
42ResultCode ProfileSelect::GetStatus() const { 42Result ProfileSelect::GetStatus() const {
43 return status; 43 return status;
44} 44}
45 45
46void ProfileSelect::ExecuteInteractive() { 46void ProfileSelect::ExecuteInteractive() {
47 UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet."); 47 ASSERT_MSG(false, "Attempted to call interactive execution on non-interactive applet.");
48} 48}
49 49
50void ProfileSelect::Execute() { 50void ProfileSelect::Execute() {
diff --git a/src/core/hle/service/am/applets/applet_profile_select.h b/src/core/hle/service/am/applets/applet_profile_select.h
index 3a6e50eaa..b77f1d205 100644
--- a/src/core/hle/service/am/applets/applet_profile_select.h
+++ b/src/core/hle/service/am/applets/applet_profile_select.h
@@ -39,7 +39,7 @@ public:
39 void Initialize() override; 39 void Initialize() override;
40 40
41 bool TransactionComplete() const override; 41 bool TransactionComplete() const override;
42 ResultCode GetStatus() const override; 42 Result GetStatus() const override;
43 void ExecuteInteractive() override; 43 void ExecuteInteractive() override;
44 void Execute() override; 44 void Execute() override;
45 45
@@ -50,7 +50,7 @@ private:
50 50
51 UserSelectionConfig config; 51 UserSelectionConfig config;
52 bool complete = false; 52 bool complete = false;
53 ResultCode status = ResultSuccess; 53 Result status = ResultSuccess;
54 std::vector<u8> final_data; 54 std::vector<u8> final_data;
55 Core::System& system; 55 Core::System& system;
56}; 56};
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.cpp b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
index 7c21365e4..faa092957 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.cpp
@@ -71,7 +71,7 @@ void SoftwareKeyboard::Initialize() {
71 InitializeBackground(applet_mode); 71 InitializeBackground(applet_mode);
72 break; 72 break;
73 default: 73 default:
74 UNREACHABLE_MSG("Invalid LibraryAppletMode={}", applet_mode); 74 ASSERT_MSG(false, "Invalid LibraryAppletMode={}", applet_mode);
75 break; 75 break;
76 } 76 }
77} 77}
@@ -80,7 +80,7 @@ bool SoftwareKeyboard::TransactionComplete() const {
80 return complete; 80 return complete;
81} 81}
82 82
83ResultCode SoftwareKeyboard::GetStatus() const { 83Result SoftwareKeyboard::GetStatus() const {
84 return status; 84 return status;
85} 85}
86 86
diff --git a/src/core/hle/service/am/applets/applet_software_keyboard.h b/src/core/hle/service/am/applets/applet_software_keyboard.h
index c36806a72..b01b31c98 100644
--- a/src/core/hle/service/am/applets/applet_software_keyboard.h
+++ b/src/core/hle/service/am/applets/applet_software_keyboard.h
@@ -28,7 +28,7 @@ public:
28 void Initialize() override; 28 void Initialize() override;
29 29
30 bool TransactionComplete() const override; 30 bool TransactionComplete() const override;
31 ResultCode GetStatus() const override; 31 Result GetStatus() const override;
32 void ExecuteInteractive() override; 32 void ExecuteInteractive() override;
33 void Execute() override; 33 void Execute() override;
34 34
@@ -180,7 +180,7 @@ private:
180 bool is_background{false}; 180 bool is_background{false};
181 181
182 bool complete{false}; 182 bool complete{false};
183 ResultCode status{ResultSuccess}; 183 Result status{ResultSuccess};
184}; 184};
185 185
186} // namespace Service::AM::Applets 186} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 2aa4a00ad..4b804b78c 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -279,7 +279,7 @@ void WebBrowser::Initialize() {
279 InitializeLobby(); 279 InitializeLobby();
280 break; 280 break;
281 default: 281 default:
282 UNREACHABLE_MSG("Invalid ShimKind={}", web_arg_header.shim_kind); 282 ASSERT_MSG(false, "Invalid ShimKind={}", web_arg_header.shim_kind);
283 break; 283 break;
284 } 284 }
285} 285}
@@ -288,7 +288,7 @@ bool WebBrowser::TransactionComplete() const {
288 return complete; 288 return complete;
289} 289}
290 290
291ResultCode WebBrowser::GetStatus() const { 291Result WebBrowser::GetStatus() const {
292 return status; 292 return status;
293} 293}
294 294
@@ -320,7 +320,7 @@ void WebBrowser::Execute() {
320 ExecuteLobby(); 320 ExecuteLobby();
321 break; 321 break;
322 default: 322 default:
323 UNREACHABLE_MSG("Invalid ShimKind={}", web_arg_header.shim_kind); 323 ASSERT_MSG(false, "Invalid ShimKind={}", web_arg_header.shim_kind);
324 WebBrowserExit(WebExitReason::EndButtonPressed); 324 WebBrowserExit(WebExitReason::EndButtonPressed);
325 break; 325 break;
326 } 326 }
diff --git a/src/core/hle/service/am/applets/applet_web_browser.h b/src/core/hle/service/am/applets/applet_web_browser.h
index 6b602769b..fd727fac8 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.h
+++ b/src/core/hle/service/am/applets/applet_web_browser.h
@@ -32,7 +32,7 @@ public:
32 void Initialize() override; 32 void Initialize() override;
33 33
34 bool TransactionComplete() const override; 34 bool TransactionComplete() const override;
35 ResultCode GetStatus() const override; 35 Result GetStatus() const override;
36 void ExecuteInteractive() override; 36 void ExecuteInteractive() override;
37 void Execute() override; 37 void Execute() override;
38 38
@@ -66,7 +66,7 @@ private:
66 const Core::Frontend::WebBrowserApplet& frontend; 66 const Core::Frontend::WebBrowserApplet& frontend;
67 67
68 bool complete{false}; 68 bool complete{false};
69 ResultCode status{ResultSuccess}; 69 Result status{ResultSuccess};
70 70
71 WebAppletVersion web_applet_version{}; 71 WebAppletVersion web_applet_version{};
72 WebArgHeader web_arg_header{}; 72 WebArgHeader web_arg_header{};
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 2861fed0e..e78a57657 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -9,7 +9,7 @@
9#include "common/swap.h" 9#include "common/swap.h"
10#include "core/hle/service/kernel_helpers.h" 10#include "core/hle/service/kernel_helpers.h"
11 11
12union ResultCode; 12union Result;
13 13
14namespace Core { 14namespace Core {
15class System; 15class System;
@@ -138,7 +138,7 @@ public:
138 virtual void Initialize(); 138 virtual void Initialize();
139 139
140 virtual bool TransactionComplete() const = 0; 140 virtual bool TransactionComplete() const = 0;
141 virtual ResultCode GetStatus() const = 0; 141 virtual Result GetStatus() const = 0;
142 virtual void ExecuteInteractive() = 0; 142 virtual void ExecuteInteractive() = 0;
143 virtual void Execute() = 0; 143 virtual void Execute() = 0;
144 144
diff --git a/src/core/hle/service/audio/errors.h b/src/core/hle/service/audio/errors.h
index 542fec899..ac6c514af 100644
--- a/src/core/hle/service/audio/errors.h
+++ b/src/core/hle/service/audio/errors.h
@@ -7,8 +7,8 @@
7 7
8namespace Service::Audio { 8namespace Service::Audio {
9 9
10constexpr ResultCode ERR_OPERATION_FAILED{ErrorModule::Audio, 2}; 10constexpr Result ERR_OPERATION_FAILED{ErrorModule::Audio, 2};
11constexpr ResultCode ERR_BUFFER_COUNT_EXCEEDED{ErrorModule::Audio, 8}; 11constexpr Result ERR_BUFFER_COUNT_EXCEEDED{ErrorModule::Audio, 8};
12constexpr ResultCode ERR_NOT_SUPPORTED{ErrorModule::Audio, 513}; 12constexpr Result ERR_NOT_SUPPORTED{ErrorModule::Audio, 513};
13 13
14} // namespace Service::Audio 14} // namespace Service::Audio
diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp
index 7e6d16230..cd0b405ff 100644
--- a/src/core/hle/service/bcat/backend/backend.cpp
+++ b/src/core/hle/service/bcat/backend/backend.cpp
@@ -74,7 +74,7 @@ void ProgressServiceBackend::CommitDirectory(std::string_view dir_name) {
74 SignalUpdate(); 74 SignalUpdate();
75} 75}
76 76
77void ProgressServiceBackend::FinishDownload(ResultCode result) { 77void ProgressServiceBackend::FinishDownload(Result result) {
78 impl.total_downloaded_bytes = impl.total_bytes; 78 impl.total_downloaded_bytes = impl.total_bytes;
79 impl.status = DeliveryCacheProgressImpl::Status::Done; 79 impl.status = DeliveryCacheProgressImpl::Status::Done;
80 impl.result = result; 80 impl.result = result;
diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h
index 7e8026c75..205ed0702 100644
--- a/src/core/hle/service/bcat/backend/backend.h
+++ b/src/core/hle/service/bcat/backend/backend.h
@@ -49,7 +49,7 @@ struct DeliveryCacheProgressImpl {
49 }; 49 };
50 50
51 Status status; 51 Status status;
52 ResultCode result = ResultSuccess; 52 Result result = ResultSuccess;
53 DirectoryName current_directory; 53 DirectoryName current_directory;
54 FileName current_file; 54 FileName current_file;
55 s64 current_downloaded_bytes; ///< Bytes downloaded on current file. 55 s64 current_downloaded_bytes; ///< Bytes downloaded on current file.
@@ -90,7 +90,7 @@ public:
90 void CommitDirectory(std::string_view dir_name); 90 void CommitDirectory(std::string_view dir_name);
91 91
92 // Notifies the application that the operation completed with result code result. 92 // Notifies the application that the operation completed with result code result.
93 void FinishDownload(ResultCode result); 93 void FinishDownload(Result result);
94 94
95private: 95private:
96 explicit ProgressServiceBackend(Core::System& system, std::string_view event_name); 96 explicit ProgressServiceBackend(Core::System& system, std::string_view event_name);
diff --git a/src/core/hle/service/bcat/bcat_module.cpp b/src/core/hle/service/bcat/bcat_module.cpp
index 076fd79e7..d928e37fb 100644
--- a/src/core/hle/service/bcat/bcat_module.cpp
+++ b/src/core/hle/service/bcat/bcat_module.cpp
@@ -18,15 +18,15 @@
18 18
19namespace Service::BCAT { 19namespace Service::BCAT {
20 20
21constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::BCAT, 1}; 21constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::BCAT, 1};
22constexpr ResultCode ERROR_FAILED_OPEN_ENTITY{ErrorModule::BCAT, 2}; 22constexpr Result ERROR_FAILED_OPEN_ENTITY{ErrorModule::BCAT, 2};
23constexpr ResultCode ERROR_ENTITY_ALREADY_OPEN{ErrorModule::BCAT, 6}; 23constexpr Result ERROR_ENTITY_ALREADY_OPEN{ErrorModule::BCAT, 6};
24constexpr ResultCode ERROR_NO_OPEN_ENTITY{ErrorModule::BCAT, 7}; 24constexpr Result ERROR_NO_OPEN_ENTITY{ErrorModule::BCAT, 7};
25 25
26// The command to clear the delivery cache just calls fs IFileSystem DeleteFile on all of the files 26// The command to clear the delivery cache just calls fs IFileSystem DeleteFile on all of the files
27// and if any of them have a non-zero result it just forwards that result. This is the FS error code 27// and if any of them have a non-zero result it just forwards that result. This is the FS error code
28// for permission denied, which is the closest approximation of this scenario. 28// for permission denied, which is the closest approximation of this scenario.
29constexpr ResultCode ERROR_FAILED_CLEAR_CACHE{ErrorModule::FS, 6400}; 29constexpr Result ERROR_FAILED_CLEAR_CACHE{ErrorModule::FS, 6400};
30 30
31using BCATDigest = std::array<u8, 0x10>; 31using BCATDigest = std::array<u8, 0x10>;
32 32
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp
index cbe9d5f7c..ff9b0427c 100644
--- a/src/core/hle/service/es/es.cpp
+++ b/src/core/hle/service/es/es.cpp
@@ -8,8 +8,8 @@
8 8
9namespace Service::ES { 9namespace Service::ES {
10 10
11constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::ETicket, 2}; 11constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::ETicket, 2};
12constexpr ResultCode ERROR_INVALID_RIGHTS_ID{ErrorModule::ETicket, 3}; 12constexpr Result ERROR_INVALID_RIGHTS_ID{ErrorModule::ETicket, 3};
13 13
14class ETicket final : public ServiceFramework<ETicket> { 14class ETicket final : public ServiceFramework<ETicket> {
15public: 15public:
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index a99c90479..27675615b 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -62,8 +62,7 @@ enum class FatalType : u32 {
62 ErrorScreen = 2, 62 ErrorScreen = 2,
63}; 63};
64 64
65static void GenerateErrorReport(Core::System& system, ResultCode error_code, 65static void GenerateErrorReport(Core::System& system, Result error_code, const FatalInfo& info) {
66 const FatalInfo& info) {
67 const auto title_id = system.GetCurrentProcessProgramID(); 66 const auto title_id = system.GetCurrentProcessProgramID();
68 std::string crash_report = fmt::format( 67 std::string crash_report = fmt::format(
69 "Yuzu {}-{} crash report\n" 68 "Yuzu {}-{} crash report\n"
@@ -106,7 +105,7 @@ static void GenerateErrorReport(Core::System& system, ResultCode error_code,
106 info.backtrace_size, info.ArchAsString(), info.unk10); 105 info.backtrace_size, info.ArchAsString(), info.unk10);
107} 106}
108 107
109static void ThrowFatalError(Core::System& system, ResultCode error_code, FatalType fatal_type, 108static void ThrowFatalError(Core::System& system, Result error_code, FatalType fatal_type,
110 const FatalInfo& info) { 109 const FatalInfo& info) {
111 LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code 0x{:X}", fatal_type, 110 LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code 0x{:X}", fatal_type,
112 error_code.raw); 111 error_code.raw);
@@ -129,7 +128,7 @@ static void ThrowFatalError(Core::System& system, ResultCode error_code, FatalTy
129void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) { 128void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) {
130 LOG_ERROR(Service_Fatal, "called"); 129 LOG_ERROR(Service_Fatal, "called");
131 IPC::RequestParser rp{ctx}; 130 IPC::RequestParser rp{ctx};
132 const auto error_code = rp.Pop<ResultCode>(); 131 const auto error_code = rp.Pop<Result>();
133 132
134 ThrowFatalError(system, error_code, FatalType::ErrorScreen, {}); 133 ThrowFatalError(system, error_code, FatalType::ErrorScreen, {});
135 IPC::ResponseBuilder rb{ctx, 2}; 134 IPC::ResponseBuilder rb{ctx, 2};
@@ -139,7 +138,7 @@ void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) {
139void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) { 138void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {
140 LOG_ERROR(Service_Fatal, "called"); 139 LOG_ERROR(Service_Fatal, "called");
141 IPC::RequestParser rp(ctx); 140 IPC::RequestParser rp(ctx);
142 const auto error_code = rp.Pop<ResultCode>(); 141 const auto error_code = rp.Pop<Result>();
143 const auto fatal_type = rp.PopEnum<FatalType>(); 142 const auto fatal_type = rp.PopEnum<FatalType>();
144 143
145 ThrowFatalError(system, error_code, fatal_type, 144 ThrowFatalError(system, error_code, fatal_type,
@@ -151,7 +150,7 @@ void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {
151void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) { 150void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) {
152 LOG_ERROR(Service_Fatal, "called"); 151 LOG_ERROR(Service_Fatal, "called");
153 IPC::RequestParser rp(ctx); 152 IPC::RequestParser rp(ctx);
154 const auto error_code = rp.Pop<ResultCode>(); 153 const auto error_code = rp.Pop<Result>();
155 const auto fatal_type = rp.PopEnum<FatalType>(); 154 const auto fatal_type = rp.PopEnum<FatalType>();
156 const auto fatal_info = ctx.ReadBuffer(); 155 const auto fatal_info = ctx.ReadBuffer();
157 FatalInfo info{}; 156 FatalInfo info{};
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index f8e7519ca..11c604a0f 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -49,7 +49,7 @@ std::string VfsDirectoryServiceWrapper::GetName() const {
49 return backing->GetName(); 49 return backing->GetName();
50} 50}
51 51
52ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const { 52Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size) const {
53 std::string path(Common::FS::SanitizePath(path_)); 53 std::string path(Common::FS::SanitizePath(path_));
54 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); 54 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
55 if (dir == nullptr) { 55 if (dir == nullptr) {
@@ -73,7 +73,7 @@ ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64
73 return ResultSuccess; 73 return ResultSuccess;
74} 74}
75 75
76ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const { 76Result VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const {
77 std::string path(Common::FS::SanitizePath(path_)); 77 std::string path(Common::FS::SanitizePath(path_));
78 if (path.empty()) { 78 if (path.empty()) {
79 // TODO(DarkLordZach): Why do games call this and what should it do? Works as is but... 79 // TODO(DarkLordZach): Why do games call this and what should it do? Works as is but...
@@ -92,7 +92,7 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons
92 return ResultSuccess; 92 return ResultSuccess;
93} 93}
94 94
95ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const { 95Result VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const {
96 std::string path(Common::FS::SanitizePath(path_)); 96 std::string path(Common::FS::SanitizePath(path_));
97 97
98 // NOTE: This is inaccurate behavior. CreateDirectory is not recursive. 98 // NOTE: This is inaccurate behavior. CreateDirectory is not recursive.
@@ -116,7 +116,7 @@ ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_)
116 return ResultSuccess; 116 return ResultSuccess;
117} 117}
118 118
119ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) const { 119Result VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_) const {
120 std::string path(Common::FS::SanitizePath(path_)); 120 std::string path(Common::FS::SanitizePath(path_));
121 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); 121 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
122 if (!dir->DeleteSubdirectory(Common::FS::GetFilename(path))) { 122 if (!dir->DeleteSubdirectory(Common::FS::GetFilename(path))) {
@@ -126,7 +126,7 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectory(const std::string& path_)
126 return ResultSuccess; 126 return ResultSuccess;
127} 127}
128 128
129ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path_) const { 129Result VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::string& path_) const {
130 std::string path(Common::FS::SanitizePath(path_)); 130 std::string path(Common::FS::SanitizePath(path_));
131 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); 131 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
132 if (!dir->DeleteSubdirectoryRecursive(Common::FS::GetFilename(path))) { 132 if (!dir->DeleteSubdirectoryRecursive(Common::FS::GetFilename(path))) {
@@ -136,7 +136,7 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::str
136 return ResultSuccess; 136 return ResultSuccess;
137} 137}
138 138
139ResultCode VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::string& path) const { 139Result VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::string& path) const {
140 const std::string sanitized_path(Common::FS::SanitizePath(path)); 140 const std::string sanitized_path(Common::FS::SanitizePath(path));
141 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(sanitized_path)); 141 auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(sanitized_path));
142 142
@@ -148,8 +148,8 @@ ResultCode VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::stri
148 return ResultSuccess; 148 return ResultSuccess;
149} 149}
150 150
151ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, 151Result VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_,
152 const std::string& dest_path_) const { 152 const std::string& dest_path_) const {
153 std::string src_path(Common::FS::SanitizePath(src_path_)); 153 std::string src_path(Common::FS::SanitizePath(src_path_));
154 std::string dest_path(Common::FS::SanitizePath(dest_path_)); 154 std::string dest_path(Common::FS::SanitizePath(dest_path_));
155 auto src = backing->GetFileRelative(src_path); 155 auto src = backing->GetFileRelative(src_path);
@@ -183,8 +183,8 @@ ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_,
183 return ResultSuccess; 183 return ResultSuccess;
184} 184}
185 185
186ResultCode VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_, 186Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,
187 const std::string& dest_path_) const { 187 const std::string& dest_path_) const {
188 std::string src_path(Common::FS::SanitizePath(src_path_)); 188 std::string src_path(Common::FS::SanitizePath(src_path_));
189 std::string dest_path(Common::FS::SanitizePath(dest_path_)); 189 std::string dest_path(Common::FS::SanitizePath(dest_path_));
190 auto src = GetDirectoryRelativeWrapped(backing, src_path); 190 auto src = GetDirectoryRelativeWrapped(backing, src_path);
@@ -273,28 +273,27 @@ FileSystemController::FileSystemController(Core::System& system_) : system{syste
273 273
274FileSystemController::~FileSystemController() = default; 274FileSystemController::~FileSystemController() = default;
275 275
276ResultCode FileSystemController::RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory) { 276Result FileSystemController::RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory) {
277 romfs_factory = std::move(factory); 277 romfs_factory = std::move(factory);
278 LOG_DEBUG(Service_FS, "Registered RomFS"); 278 LOG_DEBUG(Service_FS, "Registered RomFS");
279 return ResultSuccess; 279 return ResultSuccess;
280} 280}
281 281
282ResultCode FileSystemController::RegisterSaveData( 282Result FileSystemController::RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory) {
283 std::unique_ptr<FileSys::SaveDataFactory>&& factory) {
284 ASSERT_MSG(save_data_factory == nullptr, "Tried to register a second save data"); 283 ASSERT_MSG(save_data_factory == nullptr, "Tried to register a second save data");
285 save_data_factory = std::move(factory); 284 save_data_factory = std::move(factory);
286 LOG_DEBUG(Service_FS, "Registered save data"); 285 LOG_DEBUG(Service_FS, "Registered save data");
287 return ResultSuccess; 286 return ResultSuccess;
288} 287}
289 288
290ResultCode FileSystemController::RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory) { 289Result FileSystemController::RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory) {
291 ASSERT_MSG(sdmc_factory == nullptr, "Tried to register a second SDMC"); 290 ASSERT_MSG(sdmc_factory == nullptr, "Tried to register a second SDMC");
292 sdmc_factory = std::move(factory); 291 sdmc_factory = std::move(factory);
293 LOG_DEBUG(Service_FS, "Registered SDMC"); 292 LOG_DEBUG(Service_FS, "Registered SDMC");
294 return ResultSuccess; 293 return ResultSuccess;
295} 294}
296 295
297ResultCode FileSystemController::RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) { 296Result FileSystemController::RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) {
298 ASSERT_MSG(bis_factory == nullptr, "Tried to register a second BIS"); 297 ASSERT_MSG(bis_factory == nullptr, "Tried to register a second BIS");
299 bis_factory = std::move(factory); 298 bis_factory = std::move(factory);
300 LOG_DEBUG(Service_FS, "Registered BIS"); 299 LOG_DEBUG(Service_FS, "Registered BIS");
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 8dd2652fe..5b27de9fa 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -58,10 +58,10 @@ public:
58 explicit FileSystemController(Core::System& system_); 58 explicit FileSystemController(Core::System& system_);
59 ~FileSystemController(); 59 ~FileSystemController();
60 60
61 ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory); 61 Result RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory);
62 ResultCode RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory); 62 Result RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory);
63 ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory); 63 Result RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory);
64 ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); 64 Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
65 65
66 void SetPackedUpdate(FileSys::VirtualFile update_raw); 66 void SetPackedUpdate(FileSys::VirtualFile update_raw);
67 ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const; 67 ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const;
@@ -141,7 +141,7 @@ private:
141 141
142void InstallInterfaces(Core::System& system); 142void InstallInterfaces(Core::System& system);
143 143
144// A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of 144// A class that wraps a VfsDirectory with methods that return ResultVal and Result instead of
145// pointers and booleans. This makes using a VfsDirectory with switch services much easier and 145// pointers and booleans. This makes using a VfsDirectory with switch services much easier and
146// avoids repetitive code. 146// avoids repetitive code.
147class VfsDirectoryServiceWrapper { 147class VfsDirectoryServiceWrapper {
@@ -160,35 +160,35 @@ public:
160 * @param size The size of the new file, filled with zeroes 160 * @param size The size of the new file, filled with zeroes
161 * @return Result of the operation 161 * @return Result of the operation
162 */ 162 */
163 ResultCode CreateFile(const std::string& path, u64 size) const; 163 Result CreateFile(const std::string& path, u64 size) const;
164 164
165 /** 165 /**
166 * Delete a file specified by its path 166 * Delete a file specified by its path
167 * @param path Path relative to the archive 167 * @param path Path relative to the archive
168 * @return Result of the operation 168 * @return Result of the operation
169 */ 169 */
170 ResultCode DeleteFile(const std::string& path) const; 170 Result DeleteFile(const std::string& path) const;
171 171
172 /** 172 /**
173 * Create a directory specified by its path 173 * Create a directory specified by its path
174 * @param path Path relative to the archive 174 * @param path Path relative to the archive
175 * @return Result of the operation 175 * @return Result of the operation
176 */ 176 */
177 ResultCode CreateDirectory(const std::string& path) const; 177 Result CreateDirectory(const std::string& path) const;
178 178
179 /** 179 /**
180 * Delete a directory specified by its path 180 * Delete a directory specified by its path
181 * @param path Path relative to the archive 181 * @param path Path relative to the archive
182 * @return Result of the operation 182 * @return Result of the operation
183 */ 183 */
184 ResultCode DeleteDirectory(const std::string& path) const; 184 Result DeleteDirectory(const std::string& path) const;
185 185
186 /** 186 /**
187 * Delete a directory specified by its path and anything under it 187 * Delete a directory specified by its path and anything under it
188 * @param path Path relative to the archive 188 * @param path Path relative to the archive
189 * @return Result of the operation 189 * @return Result of the operation
190 */ 190 */
191 ResultCode DeleteDirectoryRecursively(const std::string& path) const; 191 Result DeleteDirectoryRecursively(const std::string& path) const;
192 192
193 /** 193 /**
194 * Cleans the specified directory. This is similar to DeleteDirectoryRecursively, 194 * Cleans the specified directory. This is similar to DeleteDirectoryRecursively,
@@ -200,7 +200,7 @@ public:
200 * 200 *
201 * @return Result of the operation. 201 * @return Result of the operation.
202 */ 202 */
203 ResultCode CleanDirectoryRecursively(const std::string& path) const; 203 Result CleanDirectoryRecursively(const std::string& path) const;
204 204
205 /** 205 /**
206 * Rename a File specified by its path 206 * Rename a File specified by its path
@@ -208,7 +208,7 @@ public:
208 * @param dest_path Destination path relative to the archive 208 * @param dest_path Destination path relative to the archive
209 * @return Result of the operation 209 * @return Result of the operation
210 */ 210 */
211 ResultCode RenameFile(const std::string& src_path, const std::string& dest_path) const; 211 Result RenameFile(const std::string& src_path, const std::string& dest_path) const;
212 212
213 /** 213 /**
214 * Rename a Directory specified by its path 214 * Rename a Directory specified by its path
@@ -216,7 +216,7 @@ public:
216 * @param dest_path Destination path relative to the archive 216 * @param dest_path Destination path relative to the archive
217 * @return Result of the operation 217 * @return Result of the operation
218 */ 218 */
219 ResultCode RenameDirectory(const std::string& src_path, const std::string& dest_path) const; 219 Result RenameDirectory(const std::string& src_path, const std::string& dest_path) const;
220 220
221 /** 221 /**
222 * Open a file specified by its path, using the specified mode 222 * Open a file specified by its path, using the specified mode
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index ddfcba0f1..fae6e5aff 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -899,7 +899,7 @@ void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
899 case FileSys::SaveDataSpaceId::TemporaryStorage: 899 case FileSys::SaveDataSpaceId::TemporaryStorage:
900 case FileSys::SaveDataSpaceId::ProperSystem: 900 case FileSys::SaveDataSpaceId::ProperSystem:
901 case FileSys::SaveDataSpaceId::SafeMode: 901 case FileSys::SaveDataSpaceId::SafeMode:
902 UNREACHABLE(); 902 ASSERT(false);
903 } 903 }
904 904
905 auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()), 905 auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()),
diff --git a/src/core/hle/service/friend/errors.h b/src/core/hle/service/friend/errors.h
index bc9fe0aca..ff525d865 100644
--- a/src/core/hle/service/friend/errors.h
+++ b/src/core/hle/service/friend/errors.h
@@ -7,5 +7,5 @@
7 7
8namespace Service::Friend { 8namespace Service::Friend {
9 9
10constexpr ResultCode ERR_NO_NOTIFICATIONS{ErrorModule::Account, 15}; 10constexpr Result ERR_NO_NOTIFICATIONS{ErrorModule::Account, 15};
11} 11}
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index fec7787ab..49b6d45fe 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -153,7 +153,7 @@ class IRegistrar final : public ServiceFramework<IRegistrar> {
153 friend class ARP_W; 153 friend class ARP_W;
154 154
155public: 155public:
156 using IssuerFn = std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)>; 156 using IssuerFn = std::function<Result(u64, ApplicationLaunchProperty, std::vector<u8>)>;
157 157
158 explicit IRegistrar(Core::System& system_, IssuerFn&& issuer) 158 explicit IRegistrar(Core::System& system_, IssuerFn&& issuer)
159 : ServiceFramework{system_, "IRegistrar"}, issue_process_id{std::move(issuer)} { 159 : ServiceFramework{system_, "IRegistrar"}, issue_process_id{std::move(issuer)} {
diff --git a/src/core/hle/service/glue/errors.h b/src/core/hle/service/glue/errors.h
index aefbe1f3e..d4ce7f44e 100644
--- a/src/core/hle/service/glue/errors.h
+++ b/src/core/hle/service/glue/errors.h
@@ -7,9 +7,9 @@
7 7
8namespace Service::Glue { 8namespace Service::Glue {
9 9
10constexpr ResultCode ERR_INVALID_RESOURCE{ErrorModule::ARP, 30}; 10constexpr Result ERR_INVALID_RESOURCE{ErrorModule::ARP, 30};
11constexpr ResultCode ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 31}; 11constexpr Result ERR_INVALID_PROCESS_ID{ErrorModule::ARP, 31};
12constexpr ResultCode ERR_INVALID_ACCESS{ErrorModule::ARP, 42}; 12constexpr Result ERR_INVALID_ACCESS{ErrorModule::ARP, 42};
13constexpr ResultCode ERR_NOT_REGISTERED{ErrorModule::ARP, 102}; 13constexpr Result ERR_NOT_REGISTERED{ErrorModule::ARP, 102};
14 14
15} // namespace Service::Glue 15} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/glue_manager.cpp b/src/core/hle/service/glue/glue_manager.cpp
index f1655b33e..8a654cdca 100644
--- a/src/core/hle/service/glue/glue_manager.cpp
+++ b/src/core/hle/service/glue/glue_manager.cpp
@@ -41,8 +41,8 @@ ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
41 return iter->second.control; 41 return iter->second.control;
42} 42}
43 43
44ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, 44Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
45 std::vector<u8> control) { 45 std::vector<u8> control) {
46 if (title_id == 0) { 46 if (title_id == 0) {
47 return ERR_INVALID_PROCESS_ID; 47 return ERR_INVALID_PROCESS_ID;
48 } 48 }
@@ -56,7 +56,7 @@ ResultCode ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,
56 return ResultSuccess; 56 return ResultSuccess;
57} 57}
58 58
59ResultCode ARPManager::Unregister(u64 title_id) { 59Result ARPManager::Unregister(u64 title_id) {
60 if (title_id == 0) { 60 if (title_id == 0) {
61 return ERR_INVALID_PROCESS_ID; 61 return ERR_INVALID_PROCESS_ID;
62 } 62 }
diff --git a/src/core/hle/service/glue/glue_manager.h b/src/core/hle/service/glue/glue_manager.h
index 6246fd2ff..cd0b092ac 100644
--- a/src/core/hle/service/glue/glue_manager.h
+++ b/src/core/hle/service/glue/glue_manager.h
@@ -42,12 +42,12 @@ public:
42 // Adds a new entry to the internal database with the provided parameters, returning 42 // Adds a new entry to the internal database with the provided parameters, returning
43 // ERR_INVALID_ACCESS if attempting to re-register a title ID without an intermediate Unregister 43 // ERR_INVALID_ACCESS if attempting to re-register a title ID without an intermediate Unregister
44 // step, and ERR_INVALID_PROCESS_ID if the title ID is 0. 44 // step, and ERR_INVALID_PROCESS_ID if the title ID is 0.
45 ResultCode Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control); 45 Result Register(u64 title_id, ApplicationLaunchProperty launch, std::vector<u8> control);
46 46
47 // Removes the registration for the provided title ID from the database, returning 47 // Removes the registration for the provided title ID from the database, returning
48 // ERR_NOT_REGISTERED if it doesn't exist in the database and ERR_INVALID_PROCESS_ID if the 48 // ERR_NOT_REGISTERED if it doesn't exist in the database and ERR_INVALID_PROCESS_ID if the
49 // title ID is 0. 49 // title ID is 0.
50 ResultCode Unregister(u64 title_id); 50 Result Unregister(u64 title_id);
51 51
52 // Removes all entries from the database, always succeeds. Should only be used when resetting 52 // Removes all entries from the database, always succeeds. Should only be used when resetting
53 // system state. 53 // system state.
diff --git a/src/core/hle/service/glue/notif.cpp b/src/core/hle/service/glue/notif.cpp
index b971846e7..3ace2dabd 100644
--- a/src/core/hle/service/glue/notif.cpp
+++ b/src/core/hle/service/glue/notif.cpp
@@ -1,6 +1,11 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <algorithm>
5#include <cstring>
6
7#include "common/assert.h"
8#include "common/logging/log.h"
4#include "core/hle/ipc_helpers.h" 9#include "core/hle/ipc_helpers.h"
5#include "core/hle/service/glue/notif.h" 10#include "core/hle/service/glue/notif.h"
6 11
@@ -9,11 +14,11 @@ namespace Service::Glue {
9NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} { 14NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} {
10 // clang-format off 15 // clang-format off
11 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
12 {500, nullptr, "RegisterAlarmSetting"}, 17 {500, &NOTIF_A::RegisterAlarmSetting, "RegisterAlarmSetting"},
13 {510, nullptr, "UpdateAlarmSetting"}, 18 {510, &NOTIF_A::UpdateAlarmSetting, "UpdateAlarmSetting"},
14 {520, &NOTIF_A::ListAlarmSettings, "ListAlarmSettings"}, 19 {520, &NOTIF_A::ListAlarmSettings, "ListAlarmSettings"},
15 {530, nullptr, "LoadApplicationParameter"}, 20 {530, &NOTIF_A::LoadApplicationParameter, "LoadApplicationParameter"},
16 {540, nullptr, "DeleteAlarmSetting"}, 21 {540, &NOTIF_A::DeleteAlarmSetting, "DeleteAlarmSetting"},
17 {1000, &NOTIF_A::Initialize, "Initialize"}, 22 {1000, &NOTIF_A::Initialize, "Initialize"},
18 }; 23 };
19 // clang-format on 24 // clang-format on
@@ -23,21 +28,132 @@ NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} {
23 28
24NOTIF_A::~NOTIF_A() = default; 29NOTIF_A::~NOTIF_A() = default;
25 30
31void NOTIF_A::RegisterAlarmSetting(Kernel::HLERequestContext& ctx) {
32 const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0);
33 const auto application_parameter_size = ctx.GetReadBufferSize(1);
34
35 ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting),
36 "alarm_setting_buffer_size is not 0x40 bytes");
37 ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter),
38 "application_parameter_size is bigger than 0x400 bytes");
39
40 AlarmSetting new_alarm{};
41 memcpy(&new_alarm, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting));
42
43 // TODO: Count alarms per game id
44 if (alarms.size() >= max_alarms) {
45 LOG_ERROR(Service_NOTIF, "Alarm limit reached");
46 IPC::ResponseBuilder rb{ctx, 2};
47 rb.Push(ResultUnknown);
48 return;
49 }
50
51 new_alarm.alarm_setting_id = last_alarm_setting_id++;
52 alarms.push_back(new_alarm);
53
54 // TODO: Save application parameter data
55
56 LOG_WARNING(Service_NOTIF,
57 "(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}",
58 application_parameter_size, new_alarm.alarm_setting_id, new_alarm.kind,
59 new_alarm.muted);
60
61 IPC::ResponseBuilder rb{ctx, 2};
62 rb.Push(ResultSuccess);
63 rb.Push(new_alarm.alarm_setting_id);
64}
65
66void NOTIF_A::UpdateAlarmSetting(Kernel::HLERequestContext& ctx) {
67 const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0);
68 const auto application_parameter_size = ctx.GetReadBufferSize(1);
69
70 ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting),
71 "alarm_setting_buffer_size is not 0x40 bytes");
72 ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter),
73 "application_parameter_size is bigger than 0x400 bytes");
74
75 AlarmSetting alarm_setting{};
76 memcpy(&alarm_setting, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting));
77
78 const auto alarm_it = GetAlarmFromId(alarm_setting.alarm_setting_id);
79 if (alarm_it != alarms.end()) {
80 LOG_DEBUG(Service_NOTIF, "Alarm updated");
81 *alarm_it = alarm_setting;
82 // TODO: Save application parameter data
83 }
84
85 LOG_WARNING(Service_NOTIF,
86 "(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}",
87 application_parameter_size, alarm_setting.alarm_setting_id, alarm_setting.kind,
88 alarm_setting.muted);
89
90 IPC::ResponseBuilder rb{ctx, 2};
91 rb.Push(ResultSuccess);
92}
93
26void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) { 94void NOTIF_A::ListAlarmSettings(Kernel::HLERequestContext& ctx) {
27 // Returns an array of AlarmSetting 95 LOG_INFO(Service_NOTIF, "called, alarm_count={}", alarms.size());
28 constexpr s32 alarm_count = 0;
29 96
30 LOG_WARNING(Service_NOTIF, "(STUBBED) called"); 97 // TODO: Only return alarms of this game id
98 ctx.WriteBuffer(alarms);
31 99
32 IPC::ResponseBuilder rb{ctx, 3}; 100 IPC::ResponseBuilder rb{ctx, 3};
33 rb.Push(ResultSuccess); 101 rb.Push(ResultSuccess);
34 rb.Push(alarm_count); 102 rb.Push(static_cast<u32>(alarms.size()));
103}
104
105void NOTIF_A::LoadApplicationParameter(Kernel::HLERequestContext& ctx) {
106 IPC::RequestParser rp{ctx};
107 const auto alarm_setting_id{rp.Pop<AlarmSettingId>()};
108
109 const auto alarm_it = GetAlarmFromId(alarm_setting_id);
110 if (alarm_it == alarms.end()) {
111 LOG_ERROR(Service_NOTIF, "Invalid alarm setting id={}", alarm_setting_id);
112 IPC::ResponseBuilder rb{ctx, 2};
113 rb.Push(ResultUnknown);
114 return;
115 }
116
117 // TODO: Read application parameter related to this setting id
118 ApplicationParameter application_parameter{};
119
120 LOG_WARNING(Service_NOTIF, "(STUBBED) called, alarm_setting_id={}", alarm_setting_id);
121
122 ctx.WriteBuffer(application_parameter);
123
124 IPC::ResponseBuilder rb{ctx, 2};
125 rb.Push(ResultSuccess);
126 rb.Push(static_cast<u32>(application_parameter.size()));
127}
128
129void NOTIF_A::DeleteAlarmSetting(Kernel::HLERequestContext& ctx) {
130 IPC::RequestParser rp{ctx};
131 const auto alarm_setting_id{rp.Pop<AlarmSettingId>()};
132
133 std::erase_if(alarms, [alarm_setting_id](const AlarmSetting& alarm) {
134 return alarm.alarm_setting_id == alarm_setting_id;
135 });
136
137 LOG_INFO(Service_NOTIF, "called, alarm_setting_id={}", alarm_setting_id);
138
139 IPC::ResponseBuilder rb{ctx, 2};
140 rb.Push(ResultSuccess);
35} 141}
36 142
37void NOTIF_A::Initialize(Kernel::HLERequestContext& ctx) { 143void NOTIF_A::Initialize(Kernel::HLERequestContext& ctx) {
144 // TODO: Load previous alarms from config
145
38 LOG_WARNING(Service_NOTIF, "(STUBBED) called"); 146 LOG_WARNING(Service_NOTIF, "(STUBBED) called");
39 IPC::ResponseBuilder rb{ctx, 2}; 147 IPC::ResponseBuilder rb{ctx, 2};
40 rb.Push(ResultSuccess); 148 rb.Push(ResultSuccess);
41} 149}
42 150
151std::vector<NOTIF_A::AlarmSetting>::iterator NOTIF_A::GetAlarmFromId(
152 AlarmSettingId alarm_setting_id) {
153 return std::find_if(alarms.begin(), alarms.end(),
154 [alarm_setting_id](const AlarmSetting& alarm) {
155 return alarm.alarm_setting_id == alarm_setting_id;
156 });
157}
158
43} // namespace Service::Glue 159} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/notif.h b/src/core/hle/service/glue/notif.h
index 7310d7f72..4467e1f35 100644
--- a/src/core/hle/service/glue/notif.h
+++ b/src/core/hle/service/glue/notif.h
@@ -3,6 +3,10 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <array>
7#include <vector>
8
9#include "common/uuid.h"
6#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
7 11
8namespace Core { 12namespace Core {
@@ -17,8 +21,52 @@ public:
17 ~NOTIF_A() override; 21 ~NOTIF_A() override;
18 22
19private: 23private:
24 static constexpr std::size_t max_alarms = 8;
25
26 // This is nn::notification::AlarmSettingId
27 using AlarmSettingId = u16;
28 static_assert(sizeof(AlarmSettingId) == 0x2, "AlarmSettingId is an invalid size");
29
30 using ApplicationParameter = std::array<u8, 0x400>;
31 static_assert(sizeof(ApplicationParameter) == 0x400, "ApplicationParameter is an invalid size");
32
33 struct DailyAlarmSetting {
34 s8 hour;
35 s8 minute;
36 };
37 static_assert(sizeof(DailyAlarmSetting) == 0x2, "DailyAlarmSetting is an invalid size");
38
39 struct WeeklyScheduleAlarmSetting {
40 INSERT_PADDING_BYTES(0xA);
41 std::array<DailyAlarmSetting, 0x7> day_of_week;
42 };
43 static_assert(sizeof(WeeklyScheduleAlarmSetting) == 0x18,
44 "WeeklyScheduleAlarmSetting is an invalid size");
45
46 // This is nn::notification::AlarmSetting
47 struct AlarmSetting {
48 AlarmSettingId alarm_setting_id;
49 u8 kind;
50 u8 muted;
51 INSERT_PADDING_BYTES(0x4);
52 Common::UUID account_id;
53 u64 application_id;
54 INSERT_PADDING_BYTES(0x8);
55 WeeklyScheduleAlarmSetting schedule;
56 };
57 static_assert(sizeof(AlarmSetting) == 0x40, "AlarmSetting is an invalid size");
58
59 void RegisterAlarmSetting(Kernel::HLERequestContext& ctx);
60 void UpdateAlarmSetting(Kernel::HLERequestContext& ctx);
20 void ListAlarmSettings(Kernel::HLERequestContext& ctx); 61 void ListAlarmSettings(Kernel::HLERequestContext& ctx);
62 void LoadApplicationParameter(Kernel::HLERequestContext& ctx);
63 void DeleteAlarmSetting(Kernel::HLERequestContext& ctx);
21 void Initialize(Kernel::HLERequestContext& ctx); 64 void Initialize(Kernel::HLERequestContext& ctx);
65
66 std::vector<AlarmSetting>::iterator GetAlarmFromId(AlarmSettingId alarm_setting_id);
67
68 std::vector<AlarmSetting> alarms{};
69 AlarmSettingId last_alarm_setting_id{};
22}; 70};
23 71
24} // namespace Service::Glue 72} // namespace Service::Glue
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 1e04ee3f2..c08b0a5dc 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -56,7 +56,7 @@ bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle
56 return npad_id && npad_type && device_index; 56 return npad_id && npad_type && device_index;
57} 57}
58 58
59ResultCode Controller_NPad::VerifyValidSixAxisSensorHandle( 59Result Controller_NPad::VerifyValidSixAxisSensorHandle(
60 const Core::HID::SixAxisSensorHandle& device_handle) { 60 const Core::HID::SixAxisSensorHandle& device_handle) {
61 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)); 61 const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
62 if (!npad_id) { 62 if (!npad_id) {
@@ -160,7 +160,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
160 shared_memory->system_properties.raw = 0; 160 shared_memory->system_properties.raw = 0;
161 switch (controller_type) { 161 switch (controller_type) {
162 case Core::HID::NpadStyleIndex::None: 162 case Core::HID::NpadStyleIndex::None:
163 UNREACHABLE(); 163 ASSERT(false);
164 break; 164 break;
165 case Core::HID::NpadStyleIndex::ProController: 165 case Core::HID::NpadStyleIndex::ProController:
166 shared_memory->style_tag.fullkey.Assign(1); 166 shared_memory->style_tag.fullkey.Assign(1);
@@ -422,7 +422,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
422 libnx_state.connection_status.is_connected.Assign(1); 422 libnx_state.connection_status.is_connected.Assign(1);
423 switch (controller_type) { 423 switch (controller_type) {
424 case Core::HID::NpadStyleIndex::None: 424 case Core::HID::NpadStyleIndex::None:
425 UNREACHABLE(); 425 ASSERT(false);
426 break; 426 break;
427 case Core::HID::NpadStyleIndex::ProController: 427 case Core::HID::NpadStyleIndex::ProController:
428 case Core::HID::NpadStyleIndex::NES: 428 case Core::HID::NpadStyleIndex::NES:
@@ -597,7 +597,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
597 597
598 switch (controller_type) { 598 switch (controller_type) {
599 case Core::HID::NpadStyleIndex::None: 599 case Core::HID::NpadStyleIndex::None:
600 UNREACHABLE(); 600 ASSERT(false);
601 break; 601 break;
602 case Core::HID::NpadStyleIndex::ProController: 602 case Core::HID::NpadStyleIndex::ProController:
603 case Core::HID::NpadStyleIndex::Pokeball: 603 case Core::HID::NpadStyleIndex::Pokeball:
@@ -720,9 +720,9 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
720 return communication_mode; 720 return communication_mode;
721} 721}
722 722
723ResultCode Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, 723Result Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
724 NpadJoyDeviceType npad_device_type, 724 NpadJoyDeviceType npad_device_type,
725 NpadJoyAssignmentMode assignment_mode) { 725 NpadJoyAssignmentMode assignment_mode) {
726 if (!IsNpadIdValid(npad_id)) { 726 if (!IsNpadIdValid(npad_id)) {
727 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 727 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
728 return InvalidNpadId; 728 return InvalidNpadId;
@@ -856,7 +856,7 @@ void Controller_NPad::VibrateController(
856 } 856 }
857 857
858 if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) { 858 if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
859 UNREACHABLE_MSG("DeviceIndex should never be None!"); 859 ASSERT_MSG(false, "DeviceIndex should never be None!");
860 return; 860 return;
861 } 861 }
862 862
@@ -984,7 +984,7 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
984 InitNewlyAddedController(npad_id); 984 InitNewlyAddedController(npad_id);
985} 985}
986 986
987ResultCode Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) { 987Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
988 if (!IsNpadIdValid(npad_id)) { 988 if (!IsNpadIdValid(npad_id)) {
989 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 989 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
990 return InvalidNpadId; 990 return InvalidNpadId;
@@ -1032,7 +1032,7 @@ ResultCode Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1032 WriteEmptyEntry(shared_memory); 1032 WriteEmptyEntry(shared_memory);
1033 return ResultSuccess; 1033 return ResultSuccess;
1034} 1034}
1035ResultCode Controller_NPad::SetGyroscopeZeroDriftMode( 1035Result Controller_NPad::SetGyroscopeZeroDriftMode(
1036 const Core::HID::SixAxisSensorHandle& sixaxis_handle, GyroscopeZeroDriftMode drift_mode) { 1036 const Core::HID::SixAxisSensorHandle& sixaxis_handle, GyroscopeZeroDriftMode drift_mode) {
1037 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1037 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1038 if (is_valid.IsError()) { 1038 if (is_valid.IsError()) {
@@ -1046,7 +1046,7 @@ ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(
1046 return ResultSuccess; 1046 return ResultSuccess;
1047} 1047}
1048 1048
1049ResultCode Controller_NPad::GetGyroscopeZeroDriftMode( 1049Result Controller_NPad::GetGyroscopeZeroDriftMode(
1050 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 1050 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1051 GyroscopeZeroDriftMode& drift_mode) const { 1051 GyroscopeZeroDriftMode& drift_mode) const {
1052 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1052 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
@@ -1061,8 +1061,8 @@ ResultCode Controller_NPad::GetGyroscopeZeroDriftMode(
1061 return ResultSuccess; 1061 return ResultSuccess;
1062} 1062}
1063 1063
1064ResultCode Controller_NPad::IsSixAxisSensorAtRest( 1064Result Controller_NPad::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1065 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_at_rest) const { 1065 bool& is_at_rest) const {
1066 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1066 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1067 if (is_valid.IsError()) { 1067 if (is_valid.IsError()) {
1068 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); 1068 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
@@ -1074,7 +1074,7 @@ ResultCode Controller_NPad::IsSixAxisSensorAtRest(
1074 return ResultSuccess; 1074 return ResultSuccess;
1075} 1075}
1076 1076
1077ResultCode Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor( 1077Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1078 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const { 1078 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
1079 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1079 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1080 if (is_valid.IsError()) { 1080 if (is_valid.IsError()) {
@@ -1087,7 +1087,7 @@ ResultCode Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
1087 return ResultSuccess; 1087 return ResultSuccess;
1088} 1088}
1089 1089
1090ResultCode Controller_NPad::EnableSixAxisSensorUnalteredPassthrough( 1090Result Controller_NPad::EnableSixAxisSensorUnalteredPassthrough(
1091 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) { 1091 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
1092 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1092 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1093 if (is_valid.IsError()) { 1093 if (is_valid.IsError()) {
@@ -1100,7 +1100,7 @@ ResultCode Controller_NPad::EnableSixAxisSensorUnalteredPassthrough(
1100 return ResultSuccess; 1100 return ResultSuccess;
1101} 1101}
1102 1102
1103ResultCode Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled( 1103Result Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
1104 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const { 1104 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
1105 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1105 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1106 if (is_valid.IsError()) { 1106 if (is_valid.IsError()) {
@@ -1113,7 +1113,7 @@ ResultCode Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
1113 return ResultSuccess; 1113 return ResultSuccess;
1114} 1114}
1115 1115
1116ResultCode Controller_NPad::LoadSixAxisSensorCalibrationParameter( 1116Result Controller_NPad::LoadSixAxisSensorCalibrationParameter(
1117 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 1117 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1118 Core::HID::SixAxisSensorCalibrationParameter& calibration) const { 1118 Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
1119 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1119 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
@@ -1128,7 +1128,7 @@ ResultCode Controller_NPad::LoadSixAxisSensorCalibrationParameter(
1128 return ResultSuccess; 1128 return ResultSuccess;
1129} 1129}
1130 1130
1131ResultCode Controller_NPad::GetSixAxisSensorIcInformation( 1131Result Controller_NPad::GetSixAxisSensorIcInformation(
1132 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 1132 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1133 Core::HID::SixAxisSensorIcInformation& ic_information) const { 1133 Core::HID::SixAxisSensorIcInformation& ic_information) const {
1134 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1134 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
@@ -1143,7 +1143,7 @@ ResultCode Controller_NPad::GetSixAxisSensorIcInformation(
1143 return ResultSuccess; 1143 return ResultSuccess;
1144} 1144}
1145 1145
1146ResultCode Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned( 1146Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1147 const Core::HID::SixAxisSensorHandle& sixaxis_handle) { 1147 const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
1148 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1148 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1149 if (is_valid.IsError()) { 1149 if (is_valid.IsError()) {
@@ -1157,8 +1157,8 @@ ResultCode Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
1157 return ResultSuccess; 1157 return ResultSuccess;
1158} 1158}
1159 1159
1160ResultCode Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 1160Result Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1161 bool sixaxis_status) { 1161 bool sixaxis_status) {
1162 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1162 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1163 if (is_valid.IsError()) { 1163 if (is_valid.IsError()) {
1164 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw); 1164 LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
@@ -1170,7 +1170,7 @@ ResultCode Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHand
1170 return ResultSuccess; 1170 return ResultSuccess;
1171} 1171}
1172 1172
1173ResultCode Controller_NPad::IsSixAxisSensorFusionEnabled( 1173Result Controller_NPad::IsSixAxisSensorFusionEnabled(
1174 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const { 1174 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const {
1175 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1175 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1176 if (is_valid.IsError()) { 1176 if (is_valid.IsError()) {
@@ -1183,7 +1183,7 @@ ResultCode Controller_NPad::IsSixAxisSensorFusionEnabled(
1183 1183
1184 return ResultSuccess; 1184 return ResultSuccess;
1185} 1185}
1186ResultCode Controller_NPad::SetSixAxisFusionEnabled( 1186Result Controller_NPad::SetSixAxisFusionEnabled(
1187 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) { 1187 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
1188 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1188 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
1189 if (is_valid.IsError()) { 1189 if (is_valid.IsError()) {
@@ -1197,7 +1197,7 @@ ResultCode Controller_NPad::SetSixAxisFusionEnabled(
1197 return ResultSuccess; 1197 return ResultSuccess;
1198} 1198}
1199 1199
1200ResultCode Controller_NPad::SetSixAxisFusionParameters( 1200Result Controller_NPad::SetSixAxisFusionParameters(
1201 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 1201 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1202 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) { 1202 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
1203 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1203 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
@@ -1217,7 +1217,7 @@ ResultCode Controller_NPad::SetSixAxisFusionParameters(
1217 return ResultSuccess; 1217 return ResultSuccess;
1218} 1218}
1219 1219
1220ResultCode Controller_NPad::GetSixAxisFusionParameters( 1220Result Controller_NPad::GetSixAxisFusionParameters(
1221 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 1221 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
1222 Core::HID::SixAxisSensorFusionParameters& parameters) const { 1222 Core::HID::SixAxisSensorFusionParameters& parameters) const {
1223 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle); 1223 const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
@@ -1232,8 +1232,8 @@ ResultCode Controller_NPad::GetSixAxisFusionParameters(
1232 return ResultSuccess; 1232 return ResultSuccess;
1233} 1233}
1234 1234
1235ResultCode Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, 1235Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
1236 Core::HID::NpadIdType npad_id_2) { 1236 Core::HID::NpadIdType npad_id_2) {
1237 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1237 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1238 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1238 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1239 npad_id_2); 1239 npad_id_2);
@@ -1304,8 +1304,8 @@ void Controller_NPad::StopLRAssignmentMode() {
1304 is_in_lr_assignment_mode = false; 1304 is_in_lr_assignment_mode = false;
1305} 1305}
1306 1306
1307ResultCode Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, 1307Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1308 Core::HID::NpadIdType npad_id_2) { 1308 Core::HID::NpadIdType npad_id_2) {
1309 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { 1309 if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
1310 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, 1310 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
1311 npad_id_2); 1311 npad_id_2);
@@ -1336,8 +1336,8 @@ ResultCode Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
1336 return ResultSuccess; 1336 return ResultSuccess;
1337} 1337}
1338 1338
1339ResultCode Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id, 1339Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
1340 Core::HID::LedPattern& pattern) const { 1340 Core::HID::LedPattern& pattern) const {
1341 if (!IsNpadIdValid(npad_id)) { 1341 if (!IsNpadIdValid(npad_id)) {
1342 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1342 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1343 return InvalidNpadId; 1343 return InvalidNpadId;
@@ -1347,8 +1347,8 @@ ResultCode Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
1347 return ResultSuccess; 1347 return ResultSuccess;
1348} 1348}
1349 1349
1350ResultCode Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled( 1350Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
1351 Core::HID::NpadIdType npad_id, bool& is_valid) const { 1351 bool& is_valid) const {
1352 if (!IsNpadIdValid(npad_id)) { 1352 if (!IsNpadIdValid(npad_id)) {
1353 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1353 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
1354 return InvalidNpadId; 1354 return InvalidNpadId;
@@ -1358,7 +1358,7 @@ ResultCode Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
1358 return ResultSuccess; 1358 return ResultSuccess;
1359} 1359}
1360 1360
1361ResultCode Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled( 1361Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
1362 bool is_protection_enabled, Core::HID::NpadIdType npad_id) { 1362 bool is_protection_enabled, Core::HID::NpadIdType npad_id) {
1363 if (!IsNpadIdValid(npad_id)) { 1363 if (!IsNpadIdValid(npad_id)) {
1364 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id); 1364 LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 0b662b7f8..8b54724ed 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -29,7 +29,7 @@ namespace Service::KernelHelpers {
29class ServiceContext; 29class ServiceContext;
30} // namespace Service::KernelHelpers 30} // namespace Service::KernelHelpers
31 31
32union ResultCode; 32union Result;
33 33
34namespace Service::HID { 34namespace Service::HID {
35 35
@@ -107,8 +107,8 @@ public:
107 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_); 107 void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
108 NpadCommunicationMode GetNpadCommunicationMode() const; 108 NpadCommunicationMode GetNpadCommunicationMode() const;
109 109
110 ResultCode SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type, 110 Result SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
111 NpadJoyAssignmentMode assignment_mode); 111 NpadJoyAssignmentMode assignment_mode);
112 112
113 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index, 113 bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
114 const Core::HID::VibrationValue& vibration_value); 114 const Core::HID::VibrationValue& vibration_value);
@@ -141,56 +141,55 @@ public:
141 void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id, 141 void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id,
142 bool connected); 142 bool connected);
143 143
144 ResultCode DisconnectNpad(Core::HID::NpadIdType npad_id); 144 Result DisconnectNpad(Core::HID::NpadIdType npad_id);
145 145
146 ResultCode SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 146 Result SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
147 GyroscopeZeroDriftMode drift_mode); 147 GyroscopeZeroDriftMode drift_mode);
148 ResultCode GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 148 Result GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
149 GyroscopeZeroDriftMode& drift_mode) const; 149 GyroscopeZeroDriftMode& drift_mode) const;
150 ResultCode IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 150 Result IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
151 bool& is_at_rest) const; 151 bool& is_at_rest) const;
152 ResultCode IsFirmwareUpdateAvailableForSixAxisSensor( 152 Result IsFirmwareUpdateAvailableForSixAxisSensor(
153 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const; 153 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const;
154 ResultCode EnableSixAxisSensorUnalteredPassthrough( 154 Result EnableSixAxisSensorUnalteredPassthrough(
155 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled); 155 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
156 ResultCode IsSixAxisSensorUnalteredPassthroughEnabled( 156 Result IsSixAxisSensorUnalteredPassthroughEnabled(
157 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const; 157 const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
158 ResultCode LoadSixAxisSensorCalibrationParameter( 158 Result LoadSixAxisSensorCalibrationParameter(
159 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 159 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
160 Core::HID::SixAxisSensorCalibrationParameter& calibration) const; 160 Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
161 ResultCode GetSixAxisSensorIcInformation( 161 Result GetSixAxisSensorIcInformation(
162 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 162 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
163 Core::HID::SixAxisSensorIcInformation& ic_information) const; 163 Core::HID::SixAxisSensorIcInformation& ic_information) const;
164 ResultCode ResetIsSixAxisSensorDeviceNewlyAssigned( 164 Result ResetIsSixAxisSensorDeviceNewlyAssigned(
165 const Core::HID::SixAxisSensorHandle& sixaxis_handle); 165 const Core::HID::SixAxisSensorHandle& sixaxis_handle);
166 ResultCode SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 166 Result SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
167 bool sixaxis_status); 167 bool sixaxis_status);
168 ResultCode IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 168 Result IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
169 bool& is_fusion_enabled) const; 169 bool& is_fusion_enabled) const;
170 ResultCode SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle, 170 Result SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
171 bool is_fusion_enabled); 171 bool is_fusion_enabled);
172 ResultCode SetSixAxisFusionParameters( 172 Result SetSixAxisFusionParameters(
173 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 173 const Core::HID::SixAxisSensorHandle& sixaxis_handle,
174 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters); 174 Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
175 ResultCode GetSixAxisFusionParameters( 175 Result GetSixAxisFusionParameters(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
176 const Core::HID::SixAxisSensorHandle& sixaxis_handle, 176 Core::HID::SixAxisSensorFusionParameters& parameters) const;
177 Core::HID::SixAxisSensorFusionParameters& parameters) const; 177 Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
178 ResultCode GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const; 178 Result IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
179 ResultCode IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id, 179 bool& is_enabled) const;
180 bool& is_enabled) const; 180 Result SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
181 ResultCode SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, 181 Core::HID::NpadIdType npad_id);
182 Core::HID::NpadIdType npad_id);
183 void SetAnalogStickUseCenterClamp(bool use_center_clamp); 182 void SetAnalogStickUseCenterClamp(bool use_center_clamp);
184 void ClearAllConnectedControllers(); 183 void ClearAllConnectedControllers();
185 void DisconnectAllConnectedControllers(); 184 void DisconnectAllConnectedControllers();
186 void ConnectAllDisconnectedControllers(); 185 void ConnectAllDisconnectedControllers();
187 void ClearAllControllers(); 186 void ClearAllControllers();
188 187
189 ResultCode MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, 188 Result MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
190 Core::HID::NpadIdType npad_id_2); 189 Core::HID::NpadIdType npad_id_2);
191 void StartLRAssignmentMode(); 190 void StartLRAssignmentMode();
192 void StopLRAssignmentMode(); 191 void StopLRAssignmentMode();
193 ResultCode SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); 192 Result SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);
194 193
195 // Logical OR for all buttons presses on all controllers 194 // Logical OR for all buttons presses on all controllers
196 // Specifically for cheat engine and other features. 195 // Specifically for cheat engine and other features.
@@ -198,7 +197,7 @@ public:
198 197
199 static bool IsNpadIdValid(Core::HID::NpadIdType npad_id); 198 static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
200 static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle); 199 static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
201 static ResultCode VerifyValidSixAxisSensorHandle( 200 static Result VerifyValidSixAxisSensorHandle(
202 const Core::HID::SixAxisSensorHandle& device_handle); 201 const Core::HID::SixAxisSensorHandle& device_handle);
203 202
204private: 203private:
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h
index 6c8ad04af..615c23b84 100644
--- a/src/core/hle/service/hid/errors.h
+++ b/src/core/hle/service/hid/errors.h
@@ -7,12 +7,12 @@
7 7
8namespace Service::HID { 8namespace Service::HID {
9 9
10constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100}; 10constexpr Result NpadInvalidHandle{ErrorModule::HID, 100};
11constexpr ResultCode NpadDeviceIndexOutOfRange{ErrorModule::HID, 107}; 11constexpr Result NpadDeviceIndexOutOfRange{ErrorModule::HID, 107};
12constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423}; 12constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423};
13constexpr ResultCode NpadIsDualJoycon{ErrorModule::HID, 601}; 13constexpr Result NpadIsDualJoycon{ErrorModule::HID, 601};
14constexpr ResultCode NpadIsSameType{ErrorModule::HID, 602}; 14constexpr Result NpadIsSameType{ErrorModule::HID, 602};
15constexpr ResultCode InvalidNpadId{ErrorModule::HID, 709}; 15constexpr Result InvalidNpadId{ErrorModule::HID, 709};
16constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710}; 16constexpr Result NpadNotConnected{ErrorModule::HID, 710};
17 17
18} // namespace Service::HID 18} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 8a496c38c..dc5d0366d 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1441,7 +1441,7 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
1441 break; 1441 break;
1442 case Core::HID::DeviceIndex::None: 1442 case Core::HID::DeviceIndex::None:
1443 default: 1443 default:
1444 UNREACHABLE_MSG("DeviceIndex should never be None!"); 1444 ASSERT_MSG(false, "DeviceIndex should never be None!");
1445 vibration_device_info.position = Core::HID::VibrationDevicePosition::None; 1445 vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
1446 break; 1446 break;
1447 } 1447 }
diff --git a/src/core/hle/service/hid/hidbus.h b/src/core/hle/service/hid/hidbus.h
index 6b3015a0f..8c687f678 100644
--- a/src/core/hle/service/hid/hidbus.h
+++ b/src/core/hle/service/hid/hidbus.h
@@ -71,7 +71,7 @@ private:
71 struct HidbusStatusManagerEntry { 71 struct HidbusStatusManagerEntry {
72 u8 is_connected{}; 72 u8 is_connected{};
73 INSERT_PADDING_BYTES(0x3); 73 INSERT_PADDING_BYTES(0x3);
74 ResultCode is_connected_result{0}; 74 Result is_connected_result{0};
75 u8 is_enabled{}; 75 u8 is_enabled{};
76 u8 is_in_focus{}; 76 u8 is_in_focus{};
77 u8 is_polling_mode{}; 77 u8 is_polling_mode{};
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h
index 01c52051b..d3960f506 100644
--- a/src/core/hle/service/hid/hidbus/hidbus_base.h
+++ b/src/core/hle/service/hid/hidbus/hidbus_base.h
@@ -26,7 +26,7 @@ enum class JoyPollingMode : u32 {
26}; 26};
27 27
28struct DataAccessorHeader { 28struct DataAccessorHeader {
29 ResultCode result{ResultUnknown}; 29 Result result{ResultUnknown};
30 INSERT_PADDING_WORDS(0x1); 30 INSERT_PADDING_WORDS(0x1);
31 std::array<u8, 0x18> unused{}; 31 std::array<u8, 0x18> unused{};
32 u64 latest_entry{}; 32 u64 latest_entry{};
diff --git a/src/core/hle/service/ldn/errors.h b/src/core/hle/service/ldn/errors.h
index fb86b9402..972a74806 100644
--- a/src/core/hle/service/ldn/errors.h
+++ b/src/core/hle/service/ldn/errors.h
@@ -7,6 +7,6 @@
7 7
8namespace Service::LDN { 8namespace Service::LDN {
9 9
10constexpr ResultCode ERROR_DISABLED{ErrorModule::LDN, 22}; 10constexpr Result ERROR_DISABLED{ErrorModule::LDN, 22};
11 11
12} // namespace Service::LDN 12} // namespace Service::LDN
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index fa72fcba9..becd6d1b9 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -20,20 +20,20 @@
20 20
21namespace Service::LDR { 21namespace Service::LDR {
22 22
23constexpr ResultCode ERROR_INSUFFICIENT_ADDRESS_SPACE{ErrorModule::RO, 2}; 23constexpr Result ERROR_INSUFFICIENT_ADDRESS_SPACE{ErrorModule::RO, 2};
24 24
25[[maybe_unused]] constexpr ResultCode ERROR_INVALID_MEMORY_STATE{ErrorModule::Loader, 51}; 25[[maybe_unused]] constexpr Result ERROR_INVALID_MEMORY_STATE{ErrorModule::Loader, 51};
26constexpr ResultCode ERROR_INVALID_NRO{ErrorModule::Loader, 52}; 26constexpr Result ERROR_INVALID_NRO{ErrorModule::Loader, 52};
27constexpr ResultCode ERROR_INVALID_NRR{ErrorModule::Loader, 53}; 27constexpr Result ERROR_INVALID_NRR{ErrorModule::Loader, 53};
28constexpr ResultCode ERROR_MISSING_NRR_HASH{ErrorModule::Loader, 54}; 28constexpr Result ERROR_MISSING_NRR_HASH{ErrorModule::Loader, 54};
29constexpr ResultCode ERROR_MAXIMUM_NRO{ErrorModule::Loader, 55}; 29constexpr Result ERROR_MAXIMUM_NRO{ErrorModule::Loader, 55};
30constexpr ResultCode ERROR_MAXIMUM_NRR{ErrorModule::Loader, 56}; 30constexpr Result ERROR_MAXIMUM_NRR{ErrorModule::Loader, 56};
31constexpr ResultCode ERROR_ALREADY_LOADED{ErrorModule::Loader, 57}; 31constexpr Result ERROR_ALREADY_LOADED{ErrorModule::Loader, 57};
32constexpr ResultCode ERROR_INVALID_ALIGNMENT{ErrorModule::Loader, 81}; 32constexpr Result ERROR_INVALID_ALIGNMENT{ErrorModule::Loader, 81};
33constexpr ResultCode ERROR_INVALID_SIZE{ErrorModule::Loader, 82}; 33constexpr Result ERROR_INVALID_SIZE{ErrorModule::Loader, 82};
34constexpr ResultCode ERROR_INVALID_NRO_ADDRESS{ErrorModule::Loader, 84}; 34constexpr Result ERROR_INVALID_NRO_ADDRESS{ErrorModule::Loader, 84};
35[[maybe_unused]] constexpr ResultCode ERROR_INVALID_NRR_ADDRESS{ErrorModule::Loader, 85}; 35[[maybe_unused]] constexpr Result ERROR_INVALID_NRR_ADDRESS{ErrorModule::Loader, 85};
36constexpr ResultCode ERROR_NOT_INITIALIZED{ErrorModule::Loader, 87}; 36constexpr Result ERROR_NOT_INITIALIZED{ErrorModule::Loader, 87};
37 37
38constexpr std::size_t MAXIMUM_LOADED_RO{0x40}; 38constexpr std::size_t MAXIMUM_LOADED_RO{0x40};
39constexpr std::size_t MAXIMUM_MAP_RETRIES{0x200}; 39constexpr std::size_t MAXIMUM_MAP_RETRIES{0x200};
@@ -307,7 +307,7 @@ public:
307 return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize()); 307 return (start + size + padding_size) <= (end_info.GetAddress() + end_info.GetSize());
308 } 308 }
309 309
310 ResultCode GetAvailableMapRegion(Kernel::KPageTable& page_table, u64 size, VAddr& out_addr) { 310 Result GetAvailableMapRegion(Kernel::KPageTable& page_table, u64 size, VAddr& out_addr) {
311 size = Common::AlignUp(size, Kernel::PageSize); 311 size = Common::AlignUp(size, Kernel::PageSize);
312 size += page_table.GetNumGuardPages() * Kernel::PageSize * 4; 312 size += page_table.GetNumGuardPages() * Kernel::PageSize * 4;
313 313
@@ -347,7 +347,7 @@ public:
347 } 347 }
348 348
349 if (!succeeded) { 349 if (!succeeded) {
350 UNREACHABLE_MSG("Out of address space!"); 350 ASSERT_MSG(false, "Out of address space!");
351 return Kernel::ResultOutOfMemory; 351 return Kernel::ResultOutOfMemory;
352 } 352 }
353 353
@@ -364,7 +364,7 @@ public:
364 for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { 364 for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
365 R_TRY(GetAvailableMapRegion(page_table, size, addr)); 365 R_TRY(GetAvailableMapRegion(page_table, size, addr));
366 366
367 const ResultCode result{page_table.MapCodeMemory(addr, base_addr, size)}; 367 const Result result{page_table.MapCodeMemory(addr, base_addr, size)};
368 if (result == Kernel::ResultInvalidCurrentMemory) { 368 if (result == Kernel::ResultInvalidCurrentMemory) {
369 continue; 369 continue;
370 } 370 }
@@ -397,8 +397,7 @@ public:
397 Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange); 397 Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange);
398 }); 398 });
399 399
400 const ResultCode result{ 400 const Result result{page_table.MapCodeMemory(addr + nro_size, bss_addr, bss_size)};
401 page_table.MapCodeMemory(addr + nro_size, bss_addr, bss_size)};
402 401
403 if (result == Kernel::ResultInvalidCurrentMemory) { 402 if (result == Kernel::ResultInvalidCurrentMemory) {
404 continue; 403 continue;
@@ -419,8 +418,8 @@ public:
419 return ERROR_INSUFFICIENT_ADDRESS_SPACE; 418 return ERROR_INSUFFICIENT_ADDRESS_SPACE;
420 } 419 }
421 420
422 ResultCode LoadNro(Kernel::KProcess* process, const NROHeader& nro_header, VAddr nro_addr, 421 Result LoadNro(Kernel::KProcess* process, const NROHeader& nro_header, VAddr nro_addr,
423 VAddr start) const { 422 VAddr start) const {
424 const VAddr text_start{start + nro_header.segment_headers[TEXT_INDEX].memory_offset}; 423 const VAddr text_start{start + nro_header.segment_headers[TEXT_INDEX].memory_offset};
425 const VAddr ro_start{start + nro_header.segment_headers[RO_INDEX].memory_offset}; 424 const VAddr ro_start{start + nro_header.segment_headers[RO_INDEX].memory_offset};
426 const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset}; 425 const VAddr data_start{start + nro_header.segment_headers[DATA_INDEX].memory_offset};
@@ -569,7 +568,7 @@ public:
569 rb.Push(*map_result); 568 rb.Push(*map_result);
570 } 569 }
571 570
572 ResultCode UnmapNro(const NROInfo& info) { 571 Result UnmapNro(const NROInfo& info) {
573 // Each region must be unmapped separately to validate memory state 572 // Each region must be unmapped separately to validate memory state
574 auto& page_table{system.CurrentProcess()->PageTable()}; 573 auto& page_table{system.CurrentProcess()->PageTable()};
575 574
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
index 41755bf0b..efb569993 100644
--- a/src/core/hle/service/mii/mii.cpp
+++ b/src/core/hle/service/mii/mii.cpp
@@ -12,7 +12,7 @@
12 12
13namespace Service::Mii { 13namespace Service::Mii {
14 14
15constexpr ResultCode ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1}; 15constexpr Result ERROR_INVALID_ARGUMENT{ErrorModule::Mii, 1};
16 16
17class IDatabaseService final : public ServiceFramework<IDatabaseService> { 17class IDatabaseService final : public ServiceFramework<IDatabaseService> {
18public: 18public:
diff --git a/src/core/hle/service/mii/mii_manager.cpp b/src/core/hle/service/mii/mii_manager.cpp
index 4964539f9..544c92a00 100644
--- a/src/core/hle/service/mii/mii_manager.cpp
+++ b/src/core/hle/service/mii/mii_manager.cpp
@@ -16,7 +16,7 @@ namespace Service::Mii {
16 16
17namespace { 17namespace {
18 18
19constexpr ResultCode ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4}; 19constexpr Result ERROR_CANNOT_FIND_ENTRY{ErrorModule::Mii, 4};
20 20
21constexpr std::size_t BaseMiiCount{2}; 21constexpr std::size_t BaseMiiCount{2};
22constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()}; 22constexpr std::size_t DefaultMiiCount{RawData::DefaultMii.size()};
@@ -290,7 +290,7 @@ MiiStoreData BuildRandomStoreData(Age age, Gender gender, Race race, const Commo
290 u8 glasses_type{}; 290 u8 glasses_type{};
291 while (glasses_type_start < glasses_type_info.values[glasses_type]) { 291 while (glasses_type_start < glasses_type_info.values[glasses_type]) {
292 if (++glasses_type >= glasses_type_info.values_count) { 292 if (++glasses_type >= glasses_type_info.values_count) {
293 UNREACHABLE(); 293 ASSERT(false);
294 break; 294 break;
295 } 295 }
296 } 296 }
@@ -441,7 +441,7 @@ ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_
441 return result; 441 return result;
442} 442}
443 443
444ResultCode MiiManager::GetIndex([[maybe_unused]] const MiiInfo& info, u32& index) { 444Result MiiManager::GetIndex([[maybe_unused]] const MiiInfo& info, u32& index) {
445 constexpr u32 INVALID_INDEX{0xFFFFFFFF}; 445 constexpr u32 INVALID_INDEX{0xFFFFFFFF};
446 446
447 index = INVALID_INDEX; 447 index = INVALID_INDEX;
diff --git a/src/core/hle/service/mii/mii_manager.h b/src/core/hle/service/mii/mii_manager.h
index db217b9a5..6a286bd96 100644
--- a/src/core/hle/service/mii/mii_manager.h
+++ b/src/core/hle/service/mii/mii_manager.h
@@ -23,7 +23,7 @@ public:
23 MiiInfo BuildRandom(Age age, Gender gender, Race race); 23 MiiInfo BuildRandom(Age age, Gender gender, Race race);
24 MiiInfo BuildDefault(std::size_t index); 24 MiiInfo BuildDefault(std::size_t index);
25 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag); 25 ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag);
26 ResultCode GetIndex(const MiiInfo& info, u32& index); 26 Result GetIndex(const MiiInfo& info, u32& index);
27 27
28private: 28private:
29 const Common::UUID user_id{}; 29 const Common::UUID user_id{};
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 74891da57..6c5b41dd1 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -17,10 +17,10 @@
17 17
18namespace Service::NFP { 18namespace Service::NFP {
19namespace ErrCodes { 19namespace ErrCodes {
20constexpr ResultCode DeviceNotFound(ErrorModule::NFP, 64); 20constexpr Result DeviceNotFound(ErrorModule::NFP, 64);
21constexpr ResultCode WrongDeviceState(ErrorModule::NFP, 73); 21constexpr Result WrongDeviceState(ErrorModule::NFP, 73);
22constexpr ResultCode ApplicationAreaIsNotInitialized(ErrorModule::NFP, 128); 22constexpr Result ApplicationAreaIsNotInitialized(ErrorModule::NFP, 128);
23constexpr ResultCode ApplicationAreaExist(ErrorModule::NFP, 168); 23constexpr Result ApplicationAreaExist(ErrorModule::NFP, 168);
24} // namespace ErrCodes 24} // namespace ErrCodes
25 25
26constexpr u32 ApplicationAreaSize = 0xD8; 26constexpr u32 ApplicationAreaSize = 0xD8;
@@ -585,7 +585,7 @@ void Module::Interface::Finalize() {
585 application_area_data.clear(); 585 application_area_data.clear();
586} 586}
587 587
588ResultCode Module::Interface::StartDetection(s32 protocol_) { 588Result Module::Interface::StartDetection(s32 protocol_) {
589 auto npad_device = system.HIDCore().GetEmulatedController(npad_id); 589 auto npad_device = system.HIDCore().GetEmulatedController(npad_id);
590 590
591 // TODO(german77): Add callback for when nfc data is available 591 // TODO(german77): Add callback for when nfc data is available
@@ -601,7 +601,7 @@ ResultCode Module::Interface::StartDetection(s32 protocol_) {
601 return ErrCodes::WrongDeviceState; 601 return ErrCodes::WrongDeviceState;
602} 602}
603 603
604ResultCode Module::Interface::StopDetection() { 604Result Module::Interface::StopDetection() {
605 auto npad_device = system.HIDCore().GetEmulatedController(npad_id); 605 auto npad_device = system.HIDCore().GetEmulatedController(npad_id);
606 npad_device->SetPollingMode(Common::Input::PollingMode::Active); 606 npad_device->SetPollingMode(Common::Input::PollingMode::Active);
607 607
@@ -618,7 +618,7 @@ ResultCode Module::Interface::StopDetection() {
618 return ErrCodes::WrongDeviceState; 618 return ErrCodes::WrongDeviceState;
619} 619}
620 620
621ResultCode Module::Interface::Mount() { 621Result Module::Interface::Mount() {
622 if (device_state == DeviceState::TagFound) { 622 if (device_state == DeviceState::TagFound) {
623 device_state = DeviceState::TagMounted; 623 device_state = DeviceState::TagMounted;
624 return ResultSuccess; 624 return ResultSuccess;
@@ -628,7 +628,7 @@ ResultCode Module::Interface::Mount() {
628 return ErrCodes::WrongDeviceState; 628 return ErrCodes::WrongDeviceState;
629} 629}
630 630
631ResultCode Module::Interface::Unmount() { 631Result Module::Interface::Unmount() {
632 if (device_state == DeviceState::TagMounted) { 632 if (device_state == DeviceState::TagMounted) {
633 is_application_area_initialized = false; 633 is_application_area_initialized = false;
634 application_area_id = 0; 634 application_area_id = 0;
@@ -641,7 +641,7 @@ ResultCode Module::Interface::Unmount() {
641 return ErrCodes::WrongDeviceState; 641 return ErrCodes::WrongDeviceState;
642} 642}
643 643
644ResultCode Module::Interface::GetTagInfo(TagInfo& tag_info) const { 644Result Module::Interface::GetTagInfo(TagInfo& tag_info) const {
645 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) { 645 if (device_state == DeviceState::TagFound || device_state == DeviceState::TagMounted) {
646 tag_info = { 646 tag_info = {
647 .uuid = tag_data.uuid, 647 .uuid = tag_data.uuid,
@@ -656,7 +656,7 @@ ResultCode Module::Interface::GetTagInfo(TagInfo& tag_info) const {
656 return ErrCodes::WrongDeviceState; 656 return ErrCodes::WrongDeviceState;
657} 657}
658 658
659ResultCode Module::Interface::GetCommonInfo(CommonInfo& common_info) const { 659Result Module::Interface::GetCommonInfo(CommonInfo& common_info) const {
660 if (device_state != DeviceState::TagMounted) { 660 if (device_state != DeviceState::TagMounted) {
661 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 661 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
662 return ErrCodes::WrongDeviceState; 662 return ErrCodes::WrongDeviceState;
@@ -674,7 +674,7 @@ ResultCode Module::Interface::GetCommonInfo(CommonInfo& common_info) const {
674 return ResultSuccess; 674 return ResultSuccess;
675} 675}
676 676
677ResultCode Module::Interface::GetModelInfo(ModelInfo& model_info) const { 677Result Module::Interface::GetModelInfo(ModelInfo& model_info) const {
678 if (device_state != DeviceState::TagMounted) { 678 if (device_state != DeviceState::TagMounted) {
679 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 679 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
680 return ErrCodes::WrongDeviceState; 680 return ErrCodes::WrongDeviceState;
@@ -684,7 +684,7 @@ ResultCode Module::Interface::GetModelInfo(ModelInfo& model_info) const {
684 return ResultSuccess; 684 return ResultSuccess;
685} 685}
686 686
687ResultCode Module::Interface::GetRegisterInfo(RegisterInfo& register_info) const { 687Result Module::Interface::GetRegisterInfo(RegisterInfo& register_info) const {
688 if (device_state != DeviceState::TagMounted) { 688 if (device_state != DeviceState::TagMounted) {
689 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 689 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
690 return ErrCodes::WrongDeviceState; 690 return ErrCodes::WrongDeviceState;
@@ -704,7 +704,7 @@ ResultCode Module::Interface::GetRegisterInfo(RegisterInfo& register_info) const
704 return ResultSuccess; 704 return ResultSuccess;
705} 705}
706 706
707ResultCode Module::Interface::OpenApplicationArea(u32 access_id) { 707Result Module::Interface::OpenApplicationArea(u32 access_id) {
708 if (device_state != DeviceState::TagMounted) { 708 if (device_state != DeviceState::TagMounted) {
709 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 709 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
710 return ErrCodes::WrongDeviceState; 710 return ErrCodes::WrongDeviceState;
@@ -721,7 +721,7 @@ ResultCode Module::Interface::OpenApplicationArea(u32 access_id) {
721 return ResultSuccess; 721 return ResultSuccess;
722} 722}
723 723
724ResultCode Module::Interface::GetApplicationArea(std::vector<u8>& data) const { 724Result Module::Interface::GetApplicationArea(std::vector<u8>& data) const {
725 if (device_state != DeviceState::TagMounted) { 725 if (device_state != DeviceState::TagMounted) {
726 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 726 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
727 return ErrCodes::WrongDeviceState; 727 return ErrCodes::WrongDeviceState;
@@ -736,7 +736,7 @@ ResultCode Module::Interface::GetApplicationArea(std::vector<u8>& data) const {
736 return ResultSuccess; 736 return ResultSuccess;
737} 737}
738 738
739ResultCode Module::Interface::SetApplicationArea(const std::vector<u8>& data) { 739Result Module::Interface::SetApplicationArea(const std::vector<u8>& data) {
740 if (device_state != DeviceState::TagMounted) { 740 if (device_state != DeviceState::TagMounted) {
741 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 741 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
742 return ErrCodes::WrongDeviceState; 742 return ErrCodes::WrongDeviceState;
@@ -750,7 +750,7 @@ ResultCode Module::Interface::SetApplicationArea(const std::vector<u8>& data) {
750 return ResultSuccess; 750 return ResultSuccess;
751} 751}
752 752
753ResultCode Module::Interface::CreateApplicationArea(u32 access_id, const std::vector<u8>& data) { 753Result Module::Interface::CreateApplicationArea(u32 access_id, const std::vector<u8>& data) {
754 if (device_state != DeviceState::TagMounted) { 754 if (device_state != DeviceState::TagMounted) {
755 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state); 755 LOG_ERROR(Service_NFP, "Wrong device state {}", device_state);
756 return ErrCodes::WrongDeviceState; 756 return ErrCodes::WrongDeviceState;
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index d307c6a35..0fc808781 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -178,20 +178,20 @@ public:
178 void Initialize(); 178 void Initialize();
179 void Finalize(); 179 void Finalize();
180 180
181 ResultCode StartDetection(s32 protocol_); 181 Result StartDetection(s32 protocol_);
182 ResultCode StopDetection(); 182 Result StopDetection();
183 ResultCode Mount(); 183 Result Mount();
184 ResultCode Unmount(); 184 Result Unmount();
185 185
186 ResultCode GetTagInfo(TagInfo& tag_info) const; 186 Result GetTagInfo(TagInfo& tag_info) const;
187 ResultCode GetCommonInfo(CommonInfo& common_info) const; 187 Result GetCommonInfo(CommonInfo& common_info) const;
188 ResultCode GetModelInfo(ModelInfo& model_info) const; 188 Result GetModelInfo(ModelInfo& model_info) const;
189 ResultCode GetRegisterInfo(RegisterInfo& register_info) const; 189 Result GetRegisterInfo(RegisterInfo& register_info) const;
190 190
191 ResultCode OpenApplicationArea(u32 access_id); 191 Result OpenApplicationArea(u32 access_id);
192 ResultCode GetApplicationArea(std::vector<u8>& data) const; 192 Result GetApplicationArea(std::vector<u8>& data) const;
193 ResultCode SetApplicationArea(const std::vector<u8>& data); 193 Result SetApplicationArea(const std::vector<u8>& data);
194 ResultCode CreateApplicationArea(u32 access_id, const std::vector<u8>& data); 194 Result CreateApplicationArea(u32 access_id, const std::vector<u8>& data);
195 195
196 u64 GetHandle() const; 196 u64 GetHandle() const;
197 DeviceState GetCurrentState() const; 197 DeviceState GetCurrentState() const;
diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/errors.h
index 3c50c66e0..8a7621798 100644
--- a/src/core/hle/service/ns/errors.h
+++ b/src/core/hle/service/ns/errors.h
@@ -7,5 +7,5 @@
7 7
8namespace Service::NS { 8namespace Service::NS {
9 9
10constexpr ResultCode ERR_APPLICATION_LANGUAGE_NOT_FOUND{ErrorModule::NS, 300}; 10constexpr Result ERR_APPLICATION_LANGUAGE_NOT_FOUND{ErrorModule::NS, 300};
11} \ No newline at end of file 11} \ No newline at end of file
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 705fefc83..527531f29 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -150,9 +150,9 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
150 event.event->GetWritableEvent().Clear(); 150 event.event->GetWritableEvent().Clear();
151 if (events_interface.failed[event_id]) { 151 if (events_interface.failed[event_id]) {
152 { 152 {
153 auto lk = system.StallCPU(); 153 auto lk = system.StallProcesses();
154 gpu.WaitFence(params.syncpt_id, target_value); 154 gpu.WaitFence(params.syncpt_id, target_value);
155 system.UnstallCPU(); 155 system.UnstallProcesses();
156 } 156 }
157 std::memcpy(output.data(), &params, sizeof(params)); 157 std::memcpy(output.data(), &params, sizeof(params));
158 events_interface.failed[event_id] = false; 158 events_interface.failed[event_id] = false;
diff --git a/src/core/hle/service/nvdrv/syncpoint_manager.cpp b/src/core/hle/service/nvdrv/syncpoint_manager.cpp
index f77f0df27..a6fa943e8 100644
--- a/src/core/hle/service/nvdrv/syncpoint_manager.cpp
+++ b/src/core/hle/service/nvdrv/syncpoint_manager.cpp
@@ -23,7 +23,7 @@ u32 SyncpointManager::AllocateSyncpoint() {
23 return syncpoint_id; 23 return syncpoint_id;
24 } 24 }
25 } 25 }
26 UNREACHABLE_MSG("No more available syncpoints!"); 26 ASSERT_MSG(false, "No more available syncpoints!");
27 return {}; 27 return {};
28} 28}
29 29
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
index fe95d1b73..337431488 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
@@ -659,7 +659,7 @@ Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) {
659 value = core->consumer_usage_bit; 659 value = core->consumer_usage_bit;
660 break; 660 break;
661 default: 661 default:
662 UNREACHABLE(); 662 ASSERT(false);
663 return Status::BadValue; 663 return Status::BadValue;
664 } 664 }
665 665
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp
index 8d5729003..2a123b42d 100644
--- a/src/core/hle/service/pctl/pctl_module.cpp
+++ b/src/core/hle/service/pctl/pctl_module.cpp
@@ -13,10 +13,10 @@ namespace Service::PCTL {
13 13
14namespace Error { 14namespace Error {
15 15
16constexpr ResultCode ResultNoFreeCommunication{ErrorModule::PCTL, 101}; 16constexpr Result ResultNoFreeCommunication{ErrorModule::PCTL, 101};
17constexpr ResultCode ResultStereoVisionRestricted{ErrorModule::PCTL, 104}; 17constexpr Result ResultStereoVisionRestricted{ErrorModule::PCTL, 104};
18constexpr ResultCode ResultNoCapability{ErrorModule::PCTL, 131}; 18constexpr Result ResultNoCapability{ErrorModule::PCTL, 131};
19constexpr ResultCode ResultNoRestrictionEnabled{ErrorModule::PCTL, 181}; 19constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
20 20
21} // namespace Error 21} // namespace Error
22 22
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp
index a8e2a5cbd..b10e86c8f 100644
--- a/src/core/hle/service/pm/pm.cpp
+++ b/src/core/hle/service/pm/pm.cpp
@@ -12,12 +12,12 @@ namespace Service::PM {
12 12
13namespace { 13namespace {
14 14
15constexpr ResultCode ResultProcessNotFound{ErrorModule::PM, 1}; 15constexpr Result ResultProcessNotFound{ErrorModule::PM, 1};
16[[maybe_unused]] constexpr ResultCode ResultAlreadyStarted{ErrorModule::PM, 2}; 16[[maybe_unused]] constexpr Result ResultAlreadyStarted{ErrorModule::PM, 2};
17[[maybe_unused]] constexpr ResultCode ResultNotTerminated{ErrorModule::PM, 3}; 17[[maybe_unused]] constexpr Result ResultNotTerminated{ErrorModule::PM, 3};
18[[maybe_unused]] constexpr ResultCode ResultDebugHookInUse{ErrorModule::PM, 4}; 18[[maybe_unused]] constexpr Result ResultDebugHookInUse{ErrorModule::PM, 4};
19[[maybe_unused]] constexpr ResultCode ResultApplicationRunning{ErrorModule::PM, 5}; 19[[maybe_unused]] constexpr Result ResultApplicationRunning{ErrorModule::PM, 5};
20[[maybe_unused]] constexpr ResultCode ResultInvalidSize{ErrorModule::PM, 6}; 20[[maybe_unused]] constexpr Result ResultInvalidSize{ErrorModule::PM, 6};
21 21
22constexpr u64 NO_PROCESS_FOUND_PID{0}; 22constexpr u64 NO_PROCESS_FOUND_PID{0};
23 23
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 574272b0c..318009e4f 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -190,8 +190,8 @@ void ServiceFrameworkBase::InvokeRequestTipc(Kernel::HLERequestContext& ctx) {
190 handler_invoker(this, info->handler_callback, ctx); 190 handler_invoker(this, info->handler_callback, ctx);
191} 191}
192 192
193ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, 193Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session,
194 Kernel::HLERequestContext& ctx) { 194 Kernel::HLERequestContext& ctx) {
195 const auto guard = LockService(); 195 const auto guard = LockService();
196 196
197 switch (ctx.GetCommandType()) { 197 switch (ctx.GetCommandType()) {
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index f23e0cd64..5bf197c51 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -79,8 +79,8 @@ public:
79 Kernel::KClientPort& CreatePort(); 79 Kernel::KClientPort& CreatePort();
80 80
81 /// Handles a synchronization request for the service. 81 /// Handles a synchronization request for the service.
82 ResultCode HandleSyncRequest(Kernel::KServerSession& session, 82 Result HandleSyncRequest(Kernel::KServerSession& session,
83 Kernel::HLERequestContext& context) override; 83 Kernel::HLERequestContext& context) override;
84 84
85protected: 85protected:
86 /// Member-function pointer type of SyncRequest handlers. 86 /// Member-function pointer type of SyncRequest handlers.
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index 2839cffcf..f761c2da4 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -74,7 +74,7 @@ constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_la
74constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF; 74constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF;
75constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40; 75constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40;
76 76
77constexpr ResultCode ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625}; 77constexpr Result ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625};
78 78
79void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t num_language_codes) { 79void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t num_language_codes) {
80 IPC::ResponseBuilder rb{ctx, 3}; 80 IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index 87c6f7f85..2a0b812c1 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -32,7 +32,7 @@ void GetFirmwareVersionImpl(Kernel::HLERequestContext& ctx, GetFirmwareVersionTy
32 // consistence (currently reports as 5.1.0-0.0) 32 // consistence (currently reports as 5.1.0-0.0)
33 const auto archive = FileSys::SystemArchive::SystemVersion(); 33 const auto archive = FileSys::SystemArchive::SystemVersion();
34 34
35 const auto early_exit_failure = [&ctx](std::string_view desc, ResultCode code) { 35 const auto early_exit_failure = [&ctx](std::string_view desc, Result code) {
36 LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).", 36 LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).",
37 desc); 37 desc);
38 IPC::ResponseBuilder rb{ctx, 2}; 38 IPC::ResponseBuilder rb{ctx, 2};
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 925608875..246c94623 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -17,10 +17,10 @@
17 17
18namespace Service::SM { 18namespace Service::SM {
19 19
20constexpr ResultCode ERR_NOT_INITIALIZED(ErrorModule::SM, 2); 20constexpr Result ERR_NOT_INITIALIZED(ErrorModule::SM, 2);
21constexpr ResultCode ERR_ALREADY_REGISTERED(ErrorModule::SM, 4); 21constexpr Result ERR_ALREADY_REGISTERED(ErrorModule::SM, 4);
22constexpr ResultCode ERR_INVALID_NAME(ErrorModule::SM, 6); 22constexpr Result ERR_INVALID_NAME(ErrorModule::SM, 6);
23constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7); 23constexpr Result ERR_SERVICE_NOT_REGISTERED(ErrorModule::SM, 7);
24 24
25ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {} 25ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {}
26ServiceManager::~ServiceManager() = default; 26ServiceManager::~ServiceManager() = default;
@@ -29,7 +29,7 @@ void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
29 controller_interface->InvokeRequest(context); 29 controller_interface->InvokeRequest(context);
30} 30}
31 31
32static ResultCode ValidateServiceName(const std::string& name) { 32static Result ValidateServiceName(const std::string& name) {
33 if (name.empty() || name.size() > 8) { 33 if (name.empty() || name.size() > 8) {
34 LOG_ERROR(Service_SM, "Invalid service name! service={}", name); 34 LOG_ERROR(Service_SM, "Invalid service name! service={}", name);
35 return ERR_INVALID_NAME; 35 return ERR_INVALID_NAME;
@@ -43,8 +43,8 @@ Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core
43 return self.sm_interface->CreatePort(); 43 return self.sm_interface->CreatePort();
44} 44}
45 45
46ResultCode ServiceManager::RegisterService(std::string name, u32 max_sessions, 46Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
47 Kernel::SessionRequestHandlerPtr handler) { 47 Kernel::SessionRequestHandlerPtr handler) {
48 48
49 CASCADE_CODE(ValidateServiceName(name)); 49 CASCADE_CODE(ValidateServiceName(name));
50 50
@@ -58,7 +58,7 @@ ResultCode ServiceManager::RegisterService(std::string name, u32 max_sessions,
58 return ResultSuccess; 58 return ResultSuccess;
59} 59}
60 60
61ResultCode ServiceManager::UnregisterService(const std::string& name) { 61Result ServiceManager::UnregisterService(const std::string& name) {
62 CASCADE_CODE(ValidateServiceName(name)); 62 CASCADE_CODE(ValidateServiceName(name));
63 63
64 const auto iter = registered_services.find(name); 64 const auto iter = registered_services.find(name);
@@ -94,7 +94,7 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name
94 * Inputs: 94 * Inputs:
95 * 0: 0x00000000 95 * 0: 0x00000000
96 * Outputs: 96 * Outputs:
97 * 0: ResultCode 97 * 0: Result
98 */ 98 */
99void SM::Initialize(Kernel::HLERequestContext& ctx) { 99void SM::Initialize(Kernel::HLERequestContext& ctx) {
100 LOG_DEBUG(Service_SM, "called"); 100 LOG_DEBUG(Service_SM, "called");
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 43d445e97..878decc6f 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -55,9 +55,9 @@ public:
55 explicit ServiceManager(Kernel::KernelCore& kernel_); 55 explicit ServiceManager(Kernel::KernelCore& kernel_);
56 ~ServiceManager(); 56 ~ServiceManager();
57 57
58 ResultCode RegisterService(std::string name, u32 max_sessions, 58 Result RegisterService(std::string name, u32 max_sessions,
59 Kernel::SessionRequestHandlerPtr handler); 59 Kernel::SessionRequestHandlerPtr handler);
60 ResultCode UnregisterService(const std::string& name); 60 Result UnregisterService(const std::string& name);
61 ResultVal<Kernel::KPort*> GetServicePort(const std::string& name); 61 ResultVal<Kernel::KPort*> GetServicePort(const std::string& name);
62 62
63 template <Common::DerivedFrom<Kernel::SessionRequestHandler> T> 63 template <Common::DerivedFrom<Kernel::SessionRequestHandler> T>
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index a4ed4193e..2a4bd64ab 100644
--- a/src/core/hle/service/sm/sm_controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -33,7 +33,7 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
33 33
34 // Create a session. 34 // Create a session.
35 Kernel::KClientSession* session{}; 35 Kernel::KClientSession* session{};
36 const ResultCode result = parent_port.CreateSession(std::addressof(session), session_manager); 36 const Result result = parent_port.CreateSession(std::addressof(session), session_manager);
37 if (result.IsError()) { 37 if (result.IsError()) {
38 LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw); 38 LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw);
39 IPC::ResponseBuilder rb{ctx, 2}; 39 IPC::ResponseBuilder rb{ctx, 2};
diff --git a/src/core/hle/service/spl/spl_results.h b/src/core/hle/service/spl/spl_results.h
index 17ef655a9..dd7ba11f3 100644
--- a/src/core/hle/service/spl/spl_results.h
+++ b/src/core/hle/service/spl/spl_results.h
@@ -8,23 +8,23 @@
8namespace Service::SPL { 8namespace Service::SPL {
9 9
10// Description 0 - 99 10// Description 0 - 99
11constexpr ResultCode ResultSecureMonitorError{ErrorModule::SPL, 0}; 11constexpr Result ResultSecureMonitorError{ErrorModule::SPL, 0};
12constexpr ResultCode ResultSecureMonitorNotImplemented{ErrorModule::SPL, 1}; 12constexpr Result ResultSecureMonitorNotImplemented{ErrorModule::SPL, 1};
13constexpr ResultCode ResultSecureMonitorInvalidArgument{ErrorModule::SPL, 2}; 13constexpr Result ResultSecureMonitorInvalidArgument{ErrorModule::SPL, 2};
14constexpr ResultCode ResultSecureMonitorBusy{ErrorModule::SPL, 3}; 14constexpr Result ResultSecureMonitorBusy{ErrorModule::SPL, 3};
15constexpr ResultCode ResultSecureMonitorNoAsyncOperation{ErrorModule::SPL, 4}; 15constexpr Result ResultSecureMonitorNoAsyncOperation{ErrorModule::SPL, 4};
16constexpr ResultCode ResultSecureMonitorInvalidAsyncOperation{ErrorModule::SPL, 5}; 16constexpr Result ResultSecureMonitorInvalidAsyncOperation{ErrorModule::SPL, 5};
17constexpr ResultCode ResultSecureMonitorNotPermitted{ErrorModule::SPL, 6}; 17constexpr Result ResultSecureMonitorNotPermitted{ErrorModule::SPL, 6};
18constexpr ResultCode ResultSecureMonitorNotInitialized{ErrorModule::SPL, 7}; 18constexpr Result ResultSecureMonitorNotInitialized{ErrorModule::SPL, 7};
19 19
20constexpr ResultCode ResultInvalidSize{ErrorModule::SPL, 100}; 20constexpr Result ResultInvalidSize{ErrorModule::SPL, 100};
21constexpr ResultCode ResultUnknownSecureMonitorError{ErrorModule::SPL, 101}; 21constexpr Result ResultUnknownSecureMonitorError{ErrorModule::SPL, 101};
22constexpr ResultCode ResultDecryptionFailed{ErrorModule::SPL, 102}; 22constexpr Result ResultDecryptionFailed{ErrorModule::SPL, 102};
23 23
24constexpr ResultCode ResultOutOfKeySlots{ErrorModule::SPL, 104}; 24constexpr Result ResultOutOfKeySlots{ErrorModule::SPL, 104};
25constexpr ResultCode ResultInvalidKeySlot{ErrorModule::SPL, 105}; 25constexpr Result ResultInvalidKeySlot{ErrorModule::SPL, 105};
26constexpr ResultCode ResultBootReasonAlreadySet{ErrorModule::SPL, 106}; 26constexpr Result ResultBootReasonAlreadySet{ErrorModule::SPL, 106};
27constexpr ResultCode ResultBootReasonNotSet{ErrorModule::SPL, 107}; 27constexpr Result ResultBootReasonNotSet{ErrorModule::SPL, 107};
28constexpr ResultCode ResultInvalidArgument{ErrorModule::SPL, 108}; 28constexpr Result ResultInvalidArgument{ErrorModule::SPL, 108};
29 29
30} // namespace Service::SPL 30} // namespace Service::SPL
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
index d0af06d94..ef070f32f 100644
--- a/src/core/hle/service/time/clock_types.h
+++ b/src/core/hle/service/time/clock_types.h
@@ -22,7 +22,7 @@ struct SteadyClockTimePoint {
22 s64 time_point; 22 s64 time_point;
23 Common::UUID clock_source_id; 23 Common::UUID clock_source_id;
24 24
25 ResultCode GetSpanBetween(SteadyClockTimePoint other, s64& span) const { 25 Result GetSpanBetween(SteadyClockTimePoint other, s64& span) const {
26 span = 0; 26 span = 0;
27 27
28 if (clock_source_id != other.clock_source_id) { 28 if (clock_source_id != other.clock_source_id) {
@@ -92,9 +92,9 @@ struct ClockSnapshot {
92 TimeType type; 92 TimeType type;
93 INSERT_PADDING_BYTES_NOINIT(0x2); 93 INSERT_PADDING_BYTES_NOINIT(0x2);
94 94
95 static ResultCode GetCurrentTime(s64& current_time, 95 static Result GetCurrentTime(s64& current_time,
96 const SteadyClockTimePoint& steady_clock_time_point, 96 const SteadyClockTimePoint& steady_clock_time_point,
97 const SystemClockContext& context) { 97 const SystemClockContext& context) {
98 if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) { 98 if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) {
99 current_time = 0; 99 current_time = 0;
100 return ERROR_TIME_MISMATCH; 100 return ERROR_TIME_MISMATCH;
diff --git a/src/core/hle/service/time/errors.h b/src/core/hle/service/time/errors.h
index 592921f6b..6655d30e1 100644
--- a/src/core/hle/service/time/errors.h
+++ b/src/core/hle/service/time/errors.h
@@ -7,15 +7,15 @@
7 7
8namespace Service::Time { 8namespace Service::Time {
9 9
10constexpr ResultCode ERROR_PERMISSION_DENIED{ErrorModule::Time, 1}; 10constexpr Result ERROR_PERMISSION_DENIED{ErrorModule::Time, 1};
11constexpr ResultCode ERROR_TIME_MISMATCH{ErrorModule::Time, 102}; 11constexpr Result ERROR_TIME_MISMATCH{ErrorModule::Time, 102};
12constexpr ResultCode ERROR_UNINITIALIZED_CLOCK{ErrorModule::Time, 103}; 12constexpr Result ERROR_UNINITIALIZED_CLOCK{ErrorModule::Time, 103};
13constexpr ResultCode ERROR_TIME_NOT_FOUND{ErrorModule::Time, 200}; 13constexpr Result ERROR_TIME_NOT_FOUND{ErrorModule::Time, 200};
14constexpr ResultCode ERROR_OVERFLOW{ErrorModule::Time, 201}; 14constexpr Result ERROR_OVERFLOW{ErrorModule::Time, 201};
15constexpr ResultCode ERROR_LOCATION_NAME_TOO_LONG{ErrorModule::Time, 801}; 15constexpr Result ERROR_LOCATION_NAME_TOO_LONG{ErrorModule::Time, 801};
16constexpr ResultCode ERROR_OUT_OF_RANGE{ErrorModule::Time, 902}; 16constexpr Result ERROR_OUT_OF_RANGE{ErrorModule::Time, 902};
17constexpr ResultCode ERROR_TIME_ZONE_CONVERSION_FAILED{ErrorModule::Time, 903}; 17constexpr Result ERROR_TIME_ZONE_CONVERSION_FAILED{ErrorModule::Time, 903};
18constexpr ResultCode ERROR_TIME_ZONE_NOT_FOUND{ErrorModule::Time, 989}; 18constexpr Result ERROR_TIME_ZONE_NOT_FOUND{ErrorModule::Time, 989};
19constexpr ResultCode ERROR_NOT_IMPLEMENTED{ErrorModule::Time, 990}; 19constexpr Result ERROR_NOT_IMPLEMENTED{ErrorModule::Time, 990};
20 20
21} // namespace Service::Time 21} // namespace Service::Time
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 0977806b3..1639ef2b9 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
@@ -14,7 +14,7 @@ public:
14 : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {} 14 : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {}
15 15
16protected: 16protected:
17 ResultCode Update() override { 17 Result Update() override {
18 shared_memory.UpdateLocalSystemClockContext(context); 18 shared_memory.UpdateLocalSystemClockContext(context);
19 return ResultSuccess; 19 return ResultSuccess;
20 } 20 }
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 975089af8..655e4c06d 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
@@ -15,7 +15,7 @@ public:
15 : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {} 15 : SystemClockContextUpdateCallback{}, shared_memory{shared_memory_} {}
16 16
17protected: 17protected:
18 ResultCode Update() override { 18 Result Update() override {
19 shared_memory.UpdateNetworkSystemClockContext(context); 19 shared_memory.UpdateNetworkSystemClockContext(context);
20 return ResultSuccess; 20 return ResultSuccess;
21 } 21 }
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 f0cc9a155..b033757ed 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
@@ -27,9 +27,9 @@ StandardUserSystemClockCore::~StandardUserSystemClockCore() {
27 service_context.CloseEvent(auto_correction_event); 27 service_context.CloseEvent(auto_correction_event);
28} 28}
29 29
30ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system, 30Result StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
31 bool value) { 31 bool value) {
32 if (const ResultCode result{ApplyAutomaticCorrection(system, value)}; result != ResultSuccess) { 32 if (const Result result{ApplyAutomaticCorrection(system, value)}; result != ResultSuccess) {
33 return result; 33 return result;
34 } 34 }
35 35
@@ -38,27 +38,27 @@ ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::Syst
38 return ResultSuccess; 38 return ResultSuccess;
39} 39}
40 40
41ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system, 41Result StandardUserSystemClockCore::GetClockContext(Core::System& system,
42 SystemClockContext& ctx) const { 42 SystemClockContext& ctx) const {
43 if (const ResultCode result{ApplyAutomaticCorrection(system, false)}; result != ResultSuccess) { 43 if (const Result result{ApplyAutomaticCorrection(system, false)}; result != ResultSuccess) {
44 return result; 44 return result;
45 } 45 }
46 46
47 return local_system_clock_core.GetClockContext(system, ctx); 47 return local_system_clock_core.GetClockContext(system, ctx);
48} 48}
49 49
50ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext&) { 50Result StandardUserSystemClockCore::Flush(const SystemClockContext&) {
51 UNREACHABLE(); 51 UNIMPLEMENTED();
52 return ERROR_NOT_IMPLEMENTED; 52 return ERROR_NOT_IMPLEMENTED;
53} 53}
54 54
55ResultCode StandardUserSystemClockCore::SetClockContext(const SystemClockContext&) { 55Result StandardUserSystemClockCore::SetClockContext(const SystemClockContext&) {
56 UNREACHABLE(); 56 UNIMPLEMENTED();
57 return ERROR_NOT_IMPLEMENTED; 57 return ERROR_NOT_IMPLEMENTED;
58} 58}
59 59
60ResultCode StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& system, 60Result StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& system,
61 bool value) const { 61 bool value) const {
62 if (auto_correction_enabled == value) { 62 if (auto_correction_enabled == value) {
63 return ResultSuccess; 63 return ResultSuccess;
64 } 64 }
@@ -68,7 +68,7 @@ ResultCode StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& s
68 } 68 }
69 69
70 SystemClockContext ctx{}; 70 SystemClockContext ctx{};
71 if (const ResultCode result{network_system_clock_core.GetClockContext(system, ctx)}; 71 if (const Result result{network_system_clock_core.GetClockContext(system, ctx)};
72 result != ResultSuccess) { 72 result != ResultSuccess) {
73 return result; 73 return result;
74 } 74 }
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 22df23b29..ee6e29487 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
@@ -28,9 +28,9 @@ public:
28 28
29 ~StandardUserSystemClockCore() override; 29 ~StandardUserSystemClockCore() override;
30 30
31 ResultCode SetAutomaticCorrectionEnabled(Core::System& system, bool value); 31 Result SetAutomaticCorrectionEnabled(Core::System& system, bool value);
32 32
33 ResultCode GetClockContext(Core::System& system, SystemClockContext& ctx) const override; 33 Result GetClockContext(Core::System& system, SystemClockContext& ctx) const override;
34 34
35 bool IsAutomaticCorrectionEnabled() const { 35 bool IsAutomaticCorrectionEnabled() const {
36 return auto_correction_enabled; 36 return auto_correction_enabled;
@@ -41,11 +41,11 @@ public:
41 } 41 }
42 42
43protected: 43protected:
44 ResultCode Flush(const SystemClockContext&) override; 44 Result Flush(const SystemClockContext&) override;
45 45
46 ResultCode SetClockContext(const SystemClockContext&) override; 46 Result SetClockContext(const SystemClockContext&) override;
47 47
48 ResultCode ApplyAutomaticCorrection(Core::System& system, bool value) const; 48 Result ApplyAutomaticCorrection(Core::System& system, bool value) const;
49 49
50 const SteadyClockTimePoint& GetAutomaticCorrectionUpdatedTime() const { 50 const SteadyClockTimePoint& GetAutomaticCorrectionUpdatedTime() const {
51 return auto_correction_time; 51 return auto_correction_time;
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.cpp b/src/core/hle/service/time/system_clock_context_update_callback.cpp
index 37c140c6f..a649bed3a 100644
--- a/src/core/hle/service/time/system_clock_context_update_callback.cpp
+++ b/src/core/hle/service/time/system_clock_context_update_callback.cpp
@@ -30,8 +30,8 @@ void SystemClockContextUpdateCallback::BroadcastOperationEvent() {
30 } 30 }
31} 31}
32 32
33ResultCode SystemClockContextUpdateCallback::Update(const SystemClockContext& value) { 33Result SystemClockContextUpdateCallback::Update(const SystemClockContext& value) {
34 ResultCode result{ResultSuccess}; 34 Result result{ResultSuccess};
35 35
36 if (NeedUpdate(value)) { 36 if (NeedUpdate(value)) {
37 context = value; 37 context = value;
@@ -47,7 +47,7 @@ ResultCode SystemClockContextUpdateCallback::Update(const SystemClockContext& va
47 return result; 47 return result;
48} 48}
49 49
50ResultCode SystemClockContextUpdateCallback::Update() { 50Result SystemClockContextUpdateCallback::Update() {
51 return ResultSuccess; 51 return ResultSuccess;
52} 52}
53 53
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.h b/src/core/hle/service/time/system_clock_context_update_callback.h
index bee90e329..9c6caf196 100644
--- a/src/core/hle/service/time/system_clock_context_update_callback.h
+++ b/src/core/hle/service/time/system_clock_context_update_callback.h
@@ -28,10 +28,10 @@ public:
28 28
29 void BroadcastOperationEvent(); 29 void BroadcastOperationEvent();
30 30
31 ResultCode Update(const SystemClockContext& value); 31 Result Update(const SystemClockContext& value);
32 32
33protected: 33protected:
34 virtual ResultCode Update(); 34 virtual Result Update();
35 35
36 SystemClockContext context{}; 36 SystemClockContext context{};
37 37
diff --git a/src/core/hle/service/time/system_clock_core.cpp b/src/core/hle/service/time/system_clock_core.cpp
index cb132239c..da078241f 100644
--- a/src/core/hle/service/time/system_clock_core.cpp
+++ b/src/core/hle/service/time/system_clock_core.cpp
@@ -14,13 +14,13 @@ SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core_)
14 14
15SystemClockCore::~SystemClockCore() = default; 15SystemClockCore::~SystemClockCore() = default;
16 16
17ResultCode SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time) const { 17Result SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time) const {
18 posix_time = 0; 18 posix_time = 0;
19 19
20 const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)}; 20 const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
21 21
22 SystemClockContext clock_context{}; 22 SystemClockContext clock_context{};
23 if (const ResultCode result{GetClockContext(system, clock_context)}; result != ResultSuccess) { 23 if (const Result result{GetClockContext(system, clock_context)}; result != ResultSuccess) {
24 return result; 24 return result;
25 } 25 }
26 26
@@ -33,26 +33,26 @@ ResultCode SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time
33 return ResultSuccess; 33 return ResultSuccess;
34} 34}
35 35
36ResultCode SystemClockCore::SetCurrentTime(Core::System& system, s64 posix_time) { 36Result SystemClockCore::SetCurrentTime(Core::System& system, s64 posix_time) {
37 const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)}; 37 const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
38 const SystemClockContext clock_context{posix_time - current_time_point.time_point, 38 const SystemClockContext clock_context{posix_time - current_time_point.time_point,
39 current_time_point}; 39 current_time_point};
40 40
41 if (const ResultCode result{SetClockContext(clock_context)}; result != ResultSuccess) { 41 if (const Result result{SetClockContext(clock_context)}; result != ResultSuccess) {
42 return result; 42 return result;
43 } 43 }
44 return Flush(clock_context); 44 return Flush(clock_context);
45} 45}
46 46
47ResultCode SystemClockCore::Flush(const SystemClockContext& clock_context) { 47Result SystemClockCore::Flush(const SystemClockContext& clock_context) {
48 if (!system_clock_context_update_callback) { 48 if (!system_clock_context_update_callback) {
49 return ResultSuccess; 49 return ResultSuccess;
50 } 50 }
51 return system_clock_context_update_callback->Update(clock_context); 51 return system_clock_context_update_callback->Update(clock_context);
52} 52}
53 53
54ResultCode SystemClockCore::SetSystemClockContext(const SystemClockContext& clock_context) { 54Result SystemClockCore::SetSystemClockContext(const SystemClockContext& clock_context) {
55 if (const ResultCode result{SetClockContext(clock_context)}; result != ResultSuccess) { 55 if (const Result result{SetClockContext(clock_context)}; result != ResultSuccess) {
56 return result; 56 return result;
57 } 57 }
58 return Flush(clock_context); 58 return Flush(clock_context);
diff --git a/src/core/hle/service/time/system_clock_core.h b/src/core/hle/service/time/system_clock_core.h
index 76d82f976..8cb34126f 100644
--- a/src/core/hle/service/time/system_clock_core.h
+++ b/src/core/hle/service/time/system_clock_core.h
@@ -29,28 +29,28 @@ public:
29 return steady_clock_core; 29 return steady_clock_core;
30 } 30 }
31 31
32 ResultCode GetCurrentTime(Core::System& system, s64& posix_time) const; 32 Result GetCurrentTime(Core::System& system, s64& posix_time) const;
33 33
34 ResultCode SetCurrentTime(Core::System& system, s64 posix_time); 34 Result SetCurrentTime(Core::System& system, s64 posix_time);
35 35
36 virtual ResultCode GetClockContext([[maybe_unused]] Core::System& system, 36 virtual Result GetClockContext([[maybe_unused]] Core::System& system,
37 SystemClockContext& value) const { 37 SystemClockContext& value) const {
38 value = context; 38 value = context;
39 return ResultSuccess; 39 return ResultSuccess;
40 } 40 }
41 41
42 virtual ResultCode SetClockContext(const SystemClockContext& value) { 42 virtual Result SetClockContext(const SystemClockContext& value) {
43 context = value; 43 context = value;
44 return ResultSuccess; 44 return ResultSuccess;
45 } 45 }
46 46
47 virtual ResultCode Flush(const SystemClockContext& clock_context); 47 virtual Result Flush(const SystemClockContext& clock_context);
48 48
49 void SetUpdateCallbackInstance(std::shared_ptr<SystemClockContextUpdateCallback> callback) { 49 void SetUpdateCallbackInstance(std::shared_ptr<SystemClockContextUpdateCallback> callback) {
50 system_clock_context_update_callback = std::move(callback); 50 system_clock_context_update_callback = std::move(callback);
51 } 51 }
52 52
53 ResultCode SetSystemClockContext(const SystemClockContext& context); 53 Result SetSystemClockContext(const SystemClockContext& context);
54 54
55 bool IsInitialized() const { 55 bool IsInitialized() const {
56 return is_initialized; 56 return is_initialized;
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 095fa021c..f77cdbb43 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -43,8 +43,7 @@ private:
43 } 43 }
44 44
45 s64 posix_time{}; 45 s64 posix_time{};
46 if (const ResultCode result{clock_core.GetCurrentTime(system, posix_time)}; 46 if (const Result result{clock_core.GetCurrentTime(system, posix_time)}; result.IsError()) {
47 result.IsError()) {
48 IPC::ResponseBuilder rb{ctx, 2}; 47 IPC::ResponseBuilder rb{ctx, 2};
49 rb.Push(result); 48 rb.Push(result);
50 return; 49 return;
@@ -65,7 +64,7 @@ private:
65 } 64 }
66 65
67 Clock::SystemClockContext system_clock_context{}; 66 Clock::SystemClockContext system_clock_context{};
68 if (const ResultCode result{clock_core.GetClockContext(system, system_clock_context)}; 67 if (const Result result{clock_core.GetClockContext(system, system_clock_context)};
69 result.IsError()) { 68 result.IsError()) {
70 IPC::ResponseBuilder rb{ctx, 2}; 69 IPC::ResponseBuilder rb{ctx, 2};
71 rb.Push(result); 70 rb.Push(result);
@@ -116,7 +115,7 @@ private:
116 Clock::SteadyClockCore& clock_core; 115 Clock::SteadyClockCore& clock_core;
117}; 116};
118 117
119ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( 118Result Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
120 Kernel::KThread* thread, Clock::SystemClockContext user_context, 119 Kernel::KThread* thread, Clock::SystemClockContext user_context,
121 Clock::SystemClockContext network_context, Clock::TimeType type, 120 Clock::SystemClockContext network_context, Clock::TimeType type,
122 Clock::ClockSnapshot& clock_snapshot) { 121 Clock::ClockSnapshot& clock_snapshot) {
@@ -129,7 +128,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
129 time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); 128 time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled();
130 clock_snapshot.type = type; 129 clock_snapshot.type = type;
131 130
132 if (const ResultCode result{ 131 if (const Result result{
133 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName( 132 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName(
134 clock_snapshot.location_name)}; 133 clock_snapshot.location_name)};
135 result != ResultSuccess) { 134 result != ResultSuccess) {
@@ -138,7 +137,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
138 137
139 clock_snapshot.user_context = user_context; 138 clock_snapshot.user_context = user_context;
140 139
141 if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime( 140 if (const Result result{Clock::ClockSnapshot::GetCurrentTime(
142 clock_snapshot.user_time, clock_snapshot.steady_clock_time_point, 141 clock_snapshot.user_time, clock_snapshot.steady_clock_time_point,
143 clock_snapshot.user_context)}; 142 clock_snapshot.user_context)};
144 result != ResultSuccess) { 143 result != ResultSuccess) {
@@ -146,7 +145,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
146 } 145 }
147 146
148 TimeZone::CalendarInfo userCalendarInfo{}; 147 TimeZone::CalendarInfo userCalendarInfo{};
149 if (const ResultCode result{ 148 if (const Result result{
150 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules( 149 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
151 clock_snapshot.user_time, userCalendarInfo)}; 150 clock_snapshot.user_time, userCalendarInfo)};
152 result != ResultSuccess) { 151 result != ResultSuccess) {
@@ -165,7 +164,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
165 } 164 }
166 165
167 TimeZone::CalendarInfo networkCalendarInfo{}; 166 TimeZone::CalendarInfo networkCalendarInfo{};
168 if (const ResultCode result{ 167 if (const Result result{
169 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules( 168 time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
170 clock_snapshot.network_time, networkCalendarInfo)}; 169 clock_snapshot.network_time, networkCalendarInfo)};
171 result != ResultSuccess) { 170 result != ResultSuccess) {
@@ -262,7 +261,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
262 LOG_DEBUG(Service_Time, "called, type={}", type); 261 LOG_DEBUG(Service_Time, "called, type={}", type);
263 262
264 Clock::SystemClockContext user_context{}; 263 Clock::SystemClockContext user_context{};
265 if (const ResultCode result{ 264 if (const Result result{
266 system.GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(system, 265 system.GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(system,
267 user_context)}; 266 user_context)};
268 result.IsError()) { 267 result.IsError()) {
@@ -272,7 +271,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
272 } 271 }
273 272
274 Clock::SystemClockContext network_context{}; 273 Clock::SystemClockContext network_context{};
275 if (const ResultCode result{ 274 if (const Result result{
276 system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( 275 system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
277 system, network_context)}; 276 system, network_context)};
278 result.IsError()) { 277 result.IsError()) {
@@ -282,7 +281,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
282 } 281 }
283 282
284 Clock::ClockSnapshot clock_snapshot{}; 283 Clock::ClockSnapshot clock_snapshot{};
285 if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal( 284 if (const Result result{GetClockSnapshotFromSystemClockContextInternal(
286 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)}; 285 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
287 result.IsError()) { 286 result.IsError()) {
288 IPC::ResponseBuilder rb{ctx, 2}; 287 IPC::ResponseBuilder rb{ctx, 2};
@@ -308,7 +307,7 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
308 LOG_DEBUG(Service_Time, "called, type={}", type); 307 LOG_DEBUG(Service_Time, "called, type={}", type);
309 308
310 Clock::ClockSnapshot clock_snapshot{}; 309 Clock::ClockSnapshot clock_snapshot{};
311 if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal( 310 if (const Result result{GetClockSnapshotFromSystemClockContextInternal(
312 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)}; 311 &ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
313 result != ResultSuccess) { 312 result != ResultSuccess) {
314 IPC::ResponseBuilder rb{ctx, 2}; 313 IPC::ResponseBuilder rb{ctx, 2};
@@ -365,7 +364,7 @@ void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) {
365 Clock::TimeSpanType time_span_type{}; 364 Clock::TimeSpanType time_span_type{};
366 s64 span{}; 365 s64 span{};
367 366
368 if (const ResultCode result{snapshot_a.steady_clock_time_point.GetSpanBetween( 367 if (const Result result{snapshot_a.steady_clock_time_point.GetSpanBetween(
369 snapshot_b.steady_clock_time_point, span)}; 368 snapshot_b.steady_clock_time_point, span)};
370 result != ResultSuccess) { 369 result != ResultSuccess) {
371 if (snapshot_a.network_time && snapshot_b.network_time) { 370 if (snapshot_a.network_time && snapshot_b.network_time) {
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 017f20a23..76a46cfc7 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -36,7 +36,7 @@ public:
36 void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); 36 void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
37 37
38 private: 38 private:
39 ResultCode GetClockSnapshotFromSystemClockContextInternal( 39 Result GetClockSnapshotFromSystemClockContextInternal(
40 Kernel::KThread* thread, Clock::SystemClockContext user_context, 40 Kernel::KThread* thread, Clock::SystemClockContext user_context,
41 Clock::SystemClockContext network_context, Clock::TimeType type, 41 Clock::SystemClockContext network_context, Clock::TimeType type,
42 Clock::ClockSnapshot& cloc_snapshot); 42 Clock::ClockSnapshot& cloc_snapshot);
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index acc038dbf..28667710e 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -111,7 +111,7 @@ struct TimeManager::Impl final {
111 FileSys::VirtualFile& vfs_file) { 111 FileSys::VirtualFile& vfs_file) {
112 if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( 112 if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
113 location_name, vfs_file) != ResultSuccess) { 113 location_name, vfs_file) != ResultSuccess) {
114 UNREACHABLE(); 114 ASSERT(false);
115 return; 115 return;
116 } 116 }
117 117
@@ -155,7 +155,7 @@ struct TimeManager::Impl final {
155 } else { 155 } else {
156 if (standard_local_system_clock_core.SetCurrentTime(system_, posix_time) != 156 if (standard_local_system_clock_core.SetCurrentTime(system_, posix_time) !=
157 ResultSuccess) { 157 ResultSuccess) {
158 UNREACHABLE(); 158 ASSERT(false);
159 return; 159 return;
160 } 160 }
161 } 161 }
@@ -170,7 +170,7 @@ struct TimeManager::Impl final {
170 170
171 if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != 171 if (standard_network_system_clock_core.SetSystemClockContext(clock_context) !=
172 ResultSuccess) { 172 ResultSuccess) {
173 UNREACHABLE(); 173 ASSERT(false);
174 return; 174 return;
175 } 175 }
176 176
@@ -183,7 +183,7 @@ struct TimeManager::Impl final {
183 Clock::SteadyClockTimePoint steady_clock_time_point) { 183 Clock::SteadyClockTimePoint steady_clock_time_point) {
184 if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( 184 if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled(
185 system_, is_automatic_correction_enabled) != ResultSuccess) { 185 system_, is_automatic_correction_enabled) != ResultSuccess) {
186 UNREACHABLE(); 186 ASSERT(false);
187 return; 187 return;
188 } 188 }
189 189
@@ -203,7 +203,7 @@ struct TimeManager::Impl final {
203 if (GetStandardLocalSystemClockCore() 203 if (GetStandardLocalSystemClockCore()
204 .SetCurrentTime(system_, timespan.ToSeconds()) 204 .SetCurrentTime(system_, timespan.ToSeconds())
205 .IsError()) { 205 .IsError()) {
206 UNREACHABLE(); 206 ASSERT(false);
207 return; 207 return;
208 } 208 }
209 } 209 }
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 80818eb70..afbfe9715 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -90,10 +90,10 @@ void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
90 } 90 }
91} 91}
92 92
93ResultCode TimeZoneContentManager::LoadTimeZoneRule(TimeZoneRule& rules, 93Result TimeZoneContentManager::LoadTimeZoneRule(TimeZoneRule& rules,
94 const std::string& location_name) const { 94 const std::string& location_name) const {
95 FileSys::VirtualFile vfs_file; 95 FileSys::VirtualFile vfs_file;
96 if (const ResultCode result{GetTimeZoneInfoFile(location_name, vfs_file)}; 96 if (const Result result{GetTimeZoneInfoFile(location_name, vfs_file)};
97 result != ResultSuccess) { 97 result != ResultSuccess) {
98 return result; 98 return result;
99 } 99 }
@@ -106,8 +106,8 @@ bool TimeZoneContentManager::IsLocationNameValid(const std::string& location_nam
106 location_name_cache.end(); 106 location_name_cache.end();
107} 107}
108 108
109ResultCode TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_name, 109Result TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_name,
110 FileSys::VirtualFile& vfs_file) const { 110 FileSys::VirtualFile& vfs_file) const {
111 if (!IsLocationNameValid(location_name)) { 111 if (!IsLocationNameValid(location_name)) {
112 return ERROR_TIME_NOT_FOUND; 112 return ERROR_TIME_NOT_FOUND;
113 } 113 }
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 c6c94bcc0..3d94b6428 100644
--- a/src/core/hle/service/time/time_zone_content_manager.h
+++ b/src/core/hle/service/time/time_zone_content_manager.h
@@ -32,12 +32,12 @@ public:
32 return time_zone_manager; 32 return time_zone_manager;
33 } 33 }
34 34
35 ResultCode LoadTimeZoneRule(TimeZoneRule& rules, const std::string& location_name) const; 35 Result LoadTimeZoneRule(TimeZoneRule& rules, const std::string& location_name) const;
36 36
37private: 37private:
38 bool IsLocationNameValid(const std::string& location_name) const; 38 bool IsLocationNameValid(const std::string& location_name) const;
39 ResultCode GetTimeZoneInfoFile(const std::string& location_name, 39 Result GetTimeZoneInfoFile(const std::string& location_name,
40 FileSys::VirtualFile& vfs_file) const; 40 FileSys::VirtualFile& vfs_file) const;
41 41
42 Core::System& system; 42 Core::System& system;
43 TimeZoneManager time_zone_manager; 43 TimeZoneManager time_zone_manager;
diff --git a/src/core/hle/service/time/time_zone_manager.cpp b/src/core/hle/service/time/time_zone_manager.cpp
index eeec34436..2aa675df9 100644
--- a/src/core/hle/service/time/time_zone_manager.cpp
+++ b/src/core/hle/service/time/time_zone_manager.cpp
@@ -279,7 +279,7 @@ static constexpr int TransitionTime(int year, Rule rule, int offset) {
279 break; 279 break;
280 } 280 }
281 default: 281 default:
282 UNREACHABLE(); 282 ASSERT(false);
283 } 283 }
284 return value + rule.transition_time + offset; 284 return value + rule.transition_time + offset;
285} 285}
@@ -666,8 +666,8 @@ static bool ParseTimeZoneBinary(TimeZoneRule& time_zone_rule, FileSys::VirtualFi
666 return true; 666 return true;
667} 667}
668 668
669static ResultCode CreateCalendarTime(s64 time, int gmt_offset, CalendarTimeInternal& calendar_time, 669static Result CreateCalendarTime(s64 time, int gmt_offset, CalendarTimeInternal& calendar_time,
670 CalendarAdditionalInfo& calendar_additional_info) { 670 CalendarAdditionalInfo& calendar_additional_info) {
671 s64 year{epoch_year}; 671 s64 year{epoch_year};
672 s64 time_days{time / seconds_per_day}; 672 s64 time_days{time / seconds_per_day};
673 s64 remaining_seconds{time % seconds_per_day}; 673 s64 remaining_seconds{time % seconds_per_day};
@@ -741,9 +741,9 @@ static ResultCode CreateCalendarTime(s64 time, int gmt_offset, CalendarTimeInter
741 return ResultSuccess; 741 return ResultSuccess;
742} 742}
743 743
744static ResultCode ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time, 744static Result ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
745 CalendarTimeInternal& calendar_time, 745 CalendarTimeInternal& calendar_time,
746 CalendarAdditionalInfo& calendar_additional_info) { 746 CalendarAdditionalInfo& calendar_additional_info) {
747 if ((rules.go_ahead && time < rules.ats[0]) || 747 if ((rules.go_ahead && time < rules.ats[0]) ||
748 (rules.go_back && time > rules.ats[rules.time_count - 1])) { 748 (rules.go_back && time > rules.ats[rules.time_count - 1])) {
749 s64 seconds{}; 749 s64 seconds{};
@@ -766,7 +766,7 @@ static ResultCode ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
766 if (new_time < rules.ats[0] && new_time > rules.ats[rules.time_count - 1]) { 766 if (new_time < rules.ats[0] && new_time > rules.ats[rules.time_count - 1]) {
767 return ERROR_TIME_NOT_FOUND; 767 return ERROR_TIME_NOT_FOUND;
768 } 768 }
769 if (const ResultCode result{ 769 if (const Result result{
770 ToCalendarTimeInternal(rules, new_time, calendar_time, calendar_additional_info)}; 770 ToCalendarTimeInternal(rules, new_time, calendar_time, calendar_additional_info)};
771 result != ResultSuccess) { 771 result != ResultSuccess) {
772 return result; 772 return result;
@@ -797,8 +797,8 @@ static ResultCode ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
797 tti_index = rules.types[low - 1]; 797 tti_index = rules.types[low - 1];
798 } 798 }
799 799
800 if (const ResultCode result{CreateCalendarTime(time, rules.ttis[tti_index].gmt_offset, 800 if (const Result result{CreateCalendarTime(time, rules.ttis[tti_index].gmt_offset,
801 calendar_time, calendar_additional_info)}; 801 calendar_time, calendar_additional_info)};
802 result != ResultSuccess) { 802 result != ResultSuccess) {
803 return result; 803 return result;
804 } 804 }
@@ -811,9 +811,9 @@ static ResultCode ToCalendarTimeInternal(const TimeZoneRule& rules, s64 time,
811 return ResultSuccess; 811 return ResultSuccess;
812} 812}
813 813
814static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) { 814static Result ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) {
815 CalendarTimeInternal calendar_time{}; 815 CalendarTimeInternal calendar_time{};
816 const ResultCode result{ 816 const Result result{
817 ToCalendarTimeInternal(rules, time, calendar_time, calendar.additional_info)}; 817 ToCalendarTimeInternal(rules, time, calendar_time, calendar.additional_info)};
818 calendar.time.year = static_cast<s16>(calendar_time.year); 818 calendar.time.year = static_cast<s16>(calendar_time.year);
819 819
@@ -830,13 +830,13 @@ static ResultCode ToCalendarTimeImpl(const TimeZoneRule& rules, s64 time, Calend
830TimeZoneManager::TimeZoneManager() = default; 830TimeZoneManager::TimeZoneManager() = default;
831TimeZoneManager::~TimeZoneManager() = default; 831TimeZoneManager::~TimeZoneManager() = default;
832 832
833ResultCode TimeZoneManager::ToCalendarTime(const TimeZoneRule& rules, s64 time, 833Result TimeZoneManager::ToCalendarTime(const TimeZoneRule& rules, s64 time,
834 CalendarInfo& calendar) const { 834 CalendarInfo& calendar) const {
835 return ToCalendarTimeImpl(rules, time, calendar); 835 return ToCalendarTimeImpl(rules, time, calendar);
836} 836}
837 837
838ResultCode TimeZoneManager::SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name, 838Result TimeZoneManager::SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name,
839 FileSys::VirtualFile& vfs_file) { 839 FileSys::VirtualFile& vfs_file) {
840 TimeZoneRule rule{}; 840 TimeZoneRule rule{};
841 if (ParseTimeZoneBinary(rule, vfs_file)) { 841 if (ParseTimeZoneBinary(rule, vfs_file)) {
842 device_location_name = location_name; 842 device_location_name = location_name;
@@ -846,12 +846,12 @@ ResultCode TimeZoneManager::SetDeviceLocationNameWithTimeZoneRule(const std::str
846 return ERROR_TIME_ZONE_CONVERSION_FAILED; 846 return ERROR_TIME_ZONE_CONVERSION_FAILED;
847} 847}
848 848
849ResultCode TimeZoneManager::SetUpdatedTime(const Clock::SteadyClockTimePoint& value) { 849Result TimeZoneManager::SetUpdatedTime(const Clock::SteadyClockTimePoint& value) {
850 time_zone_update_time_point = value; 850 time_zone_update_time_point = value;
851 return ResultSuccess; 851 return ResultSuccess;
852} 852}
853 853
854ResultCode TimeZoneManager::ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const { 854Result TimeZoneManager::ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const {
855 if (is_initialized) { 855 if (is_initialized) {
856 return ToCalendarTime(time_zone_rule, time, calendar); 856 return ToCalendarTime(time_zone_rule, time, calendar);
857 } else { 857 } else {
@@ -859,16 +859,16 @@ ResultCode TimeZoneManager::ToCalendarTimeWithMyRules(s64 time, CalendarInfo& ca
859 } 859 }
860} 860}
861 861
862ResultCode TimeZoneManager::ParseTimeZoneRuleBinary(TimeZoneRule& rules, 862Result TimeZoneManager::ParseTimeZoneRuleBinary(TimeZoneRule& rules,
863 FileSys::VirtualFile& vfs_file) const { 863 FileSys::VirtualFile& vfs_file) const {
864 if (!ParseTimeZoneBinary(rules, vfs_file)) { 864 if (!ParseTimeZoneBinary(rules, vfs_file)) {
865 return ERROR_TIME_ZONE_CONVERSION_FAILED; 865 return ERROR_TIME_ZONE_CONVERSION_FAILED;
866 } 866 }
867 return ResultSuccess; 867 return ResultSuccess;
868} 868}
869 869
870ResultCode TimeZoneManager::ToPosixTime(const TimeZoneRule& rules, 870Result TimeZoneManager::ToPosixTime(const TimeZoneRule& rules, const CalendarTime& calendar_time,
871 const CalendarTime& calendar_time, s64& posix_time) const { 871 s64& posix_time) const {
872 posix_time = 0; 872 posix_time = 0;
873 873
874 CalendarTimeInternal internal_time{ 874 CalendarTimeInternal internal_time{
@@ -1020,8 +1020,8 @@ ResultCode TimeZoneManager::ToPosixTime(const TimeZoneRule& rules,
1020 return ResultSuccess; 1020 return ResultSuccess;
1021} 1021}
1022 1022
1023ResultCode TimeZoneManager::ToPosixTimeWithMyRule(const CalendarTime& calendar_time, 1023Result TimeZoneManager::ToPosixTimeWithMyRule(const CalendarTime& calendar_time,
1024 s64& posix_time) const { 1024 s64& posix_time) const {
1025 if (is_initialized) { 1025 if (is_initialized) {
1026 return ToPosixTime(time_zone_rule, calendar_time, posix_time); 1026 return ToPosixTime(time_zone_rule, calendar_time, posix_time);
1027 } 1027 }
@@ -1029,7 +1029,7 @@ ResultCode TimeZoneManager::ToPosixTimeWithMyRule(const CalendarTime& calendar_t
1029 return ERROR_UNINITIALIZED_CLOCK; 1029 return ERROR_UNINITIALIZED_CLOCK;
1030} 1030}
1031 1031
1032ResultCode TimeZoneManager::GetDeviceLocationName(LocationName& value) const { 1032Result TimeZoneManager::GetDeviceLocationName(LocationName& value) const {
1033 if (!is_initialized) { 1033 if (!is_initialized) {
1034 return ERROR_UNINITIALIZED_CLOCK; 1034 return ERROR_UNINITIALIZED_CLOCK;
1035 } 1035 }
diff --git a/src/core/hle/service/time/time_zone_manager.h b/src/core/hle/service/time/time_zone_manager.h
index 8c1b19f81..5ebd4035e 100644
--- a/src/core/hle/service/time/time_zone_manager.h
+++ b/src/core/hle/service/time/time_zone_manager.h
@@ -29,16 +29,16 @@ public:
29 is_initialized = true; 29 is_initialized = true;
30 } 30 }
31 31
32 ResultCode SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name, 32 Result SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name,
33 FileSys::VirtualFile& vfs_file); 33 FileSys::VirtualFile& vfs_file);
34 ResultCode SetUpdatedTime(const Clock::SteadyClockTimePoint& value); 34 Result SetUpdatedTime(const Clock::SteadyClockTimePoint& value);
35 ResultCode GetDeviceLocationName(TimeZone::LocationName& value) const; 35 Result GetDeviceLocationName(TimeZone::LocationName& value) const;
36 ResultCode ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const; 36 Result ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const;
37 ResultCode ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const; 37 Result ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const;
38 ResultCode ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const; 38 Result ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const;
39 ResultCode ToPosixTime(const TimeZoneRule& rules, const CalendarTime& calendar_time, 39 Result ToPosixTime(const TimeZoneRule& rules, const CalendarTime& calendar_time,
40 s64& posix_time) const; 40 s64& posix_time) const;
41 ResultCode ToPosixTimeWithMyRule(const CalendarTime& calendar_time, s64& posix_time) const; 41 Result ToPosixTimeWithMyRule(const CalendarTime& calendar_time, s64& posix_time) const;
42 42
43private: 43private:
44 bool is_initialized{}; 44 bool is_initialized{};
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index cbf0ef6fa..961040bfc 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -32,7 +32,7 @@ void ITimeZoneService::GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
32 LOG_DEBUG(Service_Time, "called"); 32 LOG_DEBUG(Service_Time, "called");
33 33
34 TimeZone::LocationName location_name{}; 34 TimeZone::LocationName location_name{};
35 if (const ResultCode result{ 35 if (const Result result{
36 time_zone_content_manager.GetTimeZoneManager().GetDeviceLocationName(location_name)}; 36 time_zone_content_manager.GetTimeZoneManager().GetDeviceLocationName(location_name)};
37 result != ResultSuccess) { 37 result != ResultSuccess) {
38 IPC::ResponseBuilder rb{ctx, 2}; 38 IPC::ResponseBuilder rb{ctx, 2};
@@ -61,7 +61,7 @@ void ITimeZoneService::LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
61 LOG_DEBUG(Service_Time, "called, location_name={}", location_name); 61 LOG_DEBUG(Service_Time, "called, location_name={}", location_name);
62 62
63 TimeZone::TimeZoneRule time_zone_rule{}; 63 TimeZone::TimeZoneRule time_zone_rule{};
64 if (const ResultCode result{ 64 if (const Result result{
65 time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)}; 65 time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)};
66 result != ResultSuccess) { 66 result != ResultSuccess) {
67 IPC::ResponseBuilder rb{ctx, 2}; 67 IPC::ResponseBuilder rb{ctx, 2};
@@ -88,7 +88,7 @@ void ITimeZoneService::ToCalendarTime(Kernel::HLERequestContext& ctx) {
88 std::memcpy(&time_zone_rule, buffer.data(), buffer.size()); 88 std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
89 89
90 TimeZone::CalendarInfo calendar_info{}; 90 TimeZone::CalendarInfo calendar_info{};
91 if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToCalendarTime( 91 if (const Result result{time_zone_content_manager.GetTimeZoneManager().ToCalendarTime(
92 time_zone_rule, posix_time, calendar_info)}; 92 time_zone_rule, posix_time, calendar_info)};
93 result != ResultSuccess) { 93 result != ResultSuccess) {
94 IPC::ResponseBuilder rb{ctx, 2}; 94 IPC::ResponseBuilder rb{ctx, 2};
@@ -108,7 +108,7 @@ void ITimeZoneService::ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx)
108 LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time); 108 LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time);
109 109
110 TimeZone::CalendarInfo calendar_info{}; 110 TimeZone::CalendarInfo calendar_info{};
111 if (const ResultCode result{ 111 if (const Result result{
112 time_zone_content_manager.GetTimeZoneManager().ToCalendarTimeWithMyRules( 112 time_zone_content_manager.GetTimeZoneManager().ToCalendarTimeWithMyRules(
113 posix_time, calendar_info)}; 113 posix_time, calendar_info)};
114 result != ResultSuccess) { 114 result != ResultSuccess) {
@@ -131,7 +131,7 @@ void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) {
131 std::memcpy(&time_zone_rule, ctx.ReadBuffer().data(), sizeof(TimeZone::TimeZoneRule)); 131 std::memcpy(&time_zone_rule, ctx.ReadBuffer().data(), sizeof(TimeZone::TimeZoneRule));
132 132
133 s64 posix_time{}; 133 s64 posix_time{};
134 if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToPosixTime( 134 if (const Result result{time_zone_content_manager.GetTimeZoneManager().ToPosixTime(
135 time_zone_rule, calendar_time, posix_time)}; 135 time_zone_rule, calendar_time, posix_time)};
136 result != ResultSuccess) { 136 result != ResultSuccess) {
137 IPC::ResponseBuilder rb{ctx, 2}; 137 IPC::ResponseBuilder rb{ctx, 2};
@@ -154,9 +154,8 @@ void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
154 const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()}; 154 const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()};
155 155
156 s64 posix_time{}; 156 s64 posix_time{};
157 if (const ResultCode result{ 157 if (const Result result{time_zone_content_manager.GetTimeZoneManager().ToPosixTimeWithMyRule(
158 time_zone_content_manager.GetTimeZoneManager().ToPosixTimeWithMyRule(calendar_time, 158 calendar_time, posix_time)};
159 posix_time)};
160 result != ResultSuccess) { 159 result != ResultSuccess) {
161 IPC::ResponseBuilder rb{ctx, 2}; 160 IPC::ResponseBuilder rb{ctx, 2};
162 rb.Push(result); 161 rb.Push(result);
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index a7b53d7dc..546879648 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -34,10 +34,10 @@
34 34
35namespace Service::VI { 35namespace Service::VI {
36 36
37constexpr ResultCode ERR_OPERATION_FAILED{ErrorModule::VI, 1}; 37constexpr Result ERR_OPERATION_FAILED{ErrorModule::VI, 1};
38constexpr ResultCode ERR_PERMISSION_DENIED{ErrorModule::VI, 5}; 38constexpr Result ERR_PERMISSION_DENIED{ErrorModule::VI, 5};
39constexpr ResultCode ERR_UNSUPPORTED{ErrorModule::VI, 6}; 39constexpr Result ERR_UNSUPPORTED{ErrorModule::VI, 6};
40constexpr ResultCode ERR_NOT_FOUND{ErrorModule::VI, 7}; 40constexpr Result ERR_NOT_FOUND{ErrorModule::VI, 7};
41 41
42struct DisplayInfo { 42struct DisplayInfo {
43 /// The name of this particular display. 43 /// The name of this particular display.
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 8a938aa83..8dd956fc6 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -128,11 +128,10 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
128 128
129 // Apply patches if necessary 129 // Apply patches if necessary
130 if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) { 130 if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
131 std::vector<u8> pi_header; 131 std::vector<u8> pi_header(sizeof(NSOHeader) + program_image.size());
132 pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header), 132 std::memcpy(pi_header.data(), &nso_header, sizeof(NSOHeader));
133 reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader)); 133 std::memcpy(pi_header.data() + sizeof(NSOHeader), program_image.data(),
134 pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.data(), 134 program_image.size());
135 program_image.data() + program_image.size());
136 135
137 pi_header = pm->PatchNSO(pi_header, nso_file.GetName()); 136 pi_header = pm->PatchNSO(pi_header, nso_file.GetName());
138 137
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 7534de01e..584808d50 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -67,6 +67,16 @@ struct Memory::Impl {
67 return system.DeviceMemory().GetPointer(paddr) + vaddr; 67 return system.DeviceMemory().GetPointer(paddr) + vaddr;
68 } 68 }
69 69
70 [[nodiscard]] u8* GetPointerFromDebugMemory(VAddr vaddr) const {
71 const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]};
72
73 if (paddr == 0) {
74 return {};
75 }
76
77 return system.DeviceMemory().GetPointer(paddr) + vaddr;
78 }
79
70 u8 Read8(const VAddr addr) { 80 u8 Read8(const VAddr addr) {
71 return Read<u8>(addr); 81 return Read<u8>(addr);
72 } 82 }
@@ -187,6 +197,12 @@ struct Memory::Impl {
187 on_memory(copy_amount, mem_ptr); 197 on_memory(copy_amount, mem_ptr);
188 break; 198 break;
189 } 199 }
200 case Common::PageType::DebugMemory: {
201 DEBUG_ASSERT(pointer);
202 u8* const mem_ptr{GetPointerFromDebugMemory(current_vaddr)};
203 on_memory(copy_amount, mem_ptr);
204 break;
205 }
190 case Common::PageType::RasterizerCachedMemory: { 206 case Common::PageType::RasterizerCachedMemory: {
191 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; 207 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
192 on_rasterizer(current_vaddr, copy_amount, host_ptr); 208 on_rasterizer(current_vaddr, copy_amount, host_ptr);
@@ -316,6 +332,58 @@ struct Memory::Impl {
316 }); 332 });
317 } 333 }
318 334
335 void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) {
336 if (vaddr == 0) {
337 return;
338 }
339
340 // Iterate over a contiguous CPU address space, marking/unmarking the region.
341 // The region is at a granularity of CPU pages.
342
343 const u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1;
344 for (u64 i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
345 const Common::PageType page_type{
346 current_page_table->pointers[vaddr >> PAGE_BITS].Type()};
347 if (debug) {
348 // Switch page type to debug if now debug
349 switch (page_type) {
350 case Common::PageType::Unmapped:
351 ASSERT_MSG(false, "Attempted to mark unmapped pages as debug");
352 break;
353 case Common::PageType::RasterizerCachedMemory:
354 case Common::PageType::DebugMemory:
355 // Page is already marked.
356 break;
357 case Common::PageType::Memory:
358 current_page_table->pointers[vaddr >> PAGE_BITS].Store(
359 nullptr, Common::PageType::DebugMemory);
360 break;
361 default:
362 UNREACHABLE();
363 }
364 } else {
365 // Switch page type to non-debug if now non-debug
366 switch (page_type) {
367 case Common::PageType::Unmapped:
368 ASSERT_MSG(false, "Attempted to mark unmapped pages as non-debug");
369 break;
370 case Common::PageType::RasterizerCachedMemory:
371 case Common::PageType::Memory:
372 // Don't mess with already non-debug or rasterizer memory.
373 break;
374 case Common::PageType::DebugMemory: {
375 u8* const pointer{GetPointerFromDebugMemory(vaddr & ~PAGE_MASK)};
376 current_page_table->pointers[vaddr >> PAGE_BITS].Store(
377 pointer - (vaddr & ~PAGE_MASK), Common::PageType::Memory);
378 break;
379 }
380 default:
381 UNREACHABLE();
382 }
383 }
384 }
385 }
386
319 void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { 387 void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) {
320 if (vaddr == 0) { 388 if (vaddr == 0) {
321 return; 389 return;
@@ -342,6 +410,7 @@ struct Memory::Impl {
342 // It is not necessary for a process to have this region mapped into its address 410 // It is not necessary for a process to have this region mapped into its address
343 // space, for example, a system module need not have a VRAM mapping. 411 // space, for example, a system module need not have a VRAM mapping.
344 break; 412 break;
413 case Common::PageType::DebugMemory:
345 case Common::PageType::Memory: 414 case Common::PageType::Memory:
346 current_page_table->pointers[vaddr >> PAGE_BITS].Store( 415 current_page_table->pointers[vaddr >> PAGE_BITS].Store(
347 nullptr, Common::PageType::RasterizerCachedMemory); 416 nullptr, Common::PageType::RasterizerCachedMemory);
@@ -360,6 +429,7 @@ struct Memory::Impl {
360 // It is not necessary for a process to have this region mapped into its address 429 // It is not necessary for a process to have this region mapped into its address
361 // space, for example, a system module need not have a VRAM mapping. 430 // space, for example, a system module need not have a VRAM mapping.
362 break; 431 break;
432 case Common::PageType::DebugMemory:
363 case Common::PageType::Memory: 433 case Common::PageType::Memory:
364 // There can be more than one GPU region mapped per CPU region, so it's common 434 // There can be more than one GPU region mapped per CPU region, so it's common
365 // that this area is already unmarked as cached. 435 // that this area is already unmarked as cached.
@@ -460,6 +530,8 @@ struct Memory::Impl {
460 case Common::PageType::Memory: 530 case Common::PageType::Memory:
461 ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr); 531 ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
462 return nullptr; 532 return nullptr;
533 case Common::PageType::DebugMemory:
534 return GetPointerFromDebugMemory(vaddr);
463 case Common::PageType::RasterizerCachedMemory: { 535 case Common::PageType::RasterizerCachedMemory: {
464 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)}; 536 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
465 on_rasterizer(); 537 on_rasterizer();
@@ -591,7 +663,8 @@ bool Memory::IsValidVirtualAddress(const VAddr vaddr) const {
591 return false; 663 return false;
592 } 664 }
593 const auto [pointer, type] = page_table.pointers[page].PointerType(); 665 const auto [pointer, type] = page_table.pointers[page].PointerType();
594 return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory; 666 return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory ||
667 type == Common::PageType::DebugMemory;
595} 668}
596 669
597bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const { 670bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const {
@@ -707,4 +780,8 @@ void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) {
707 impl->RasterizerMarkRegionCached(vaddr, size, cached); 780 impl->RasterizerMarkRegionCached(vaddr, size, cached);
708} 781}
709 782
783void Memory::MarkRegionDebug(VAddr vaddr, u64 size, bool debug) {
784 impl->MarkRegionDebug(vaddr, size, debug);
785}
786
710} // namespace Core::Memory 787} // namespace Core::Memory
diff --git a/src/core/memory.h b/src/core/memory.h
index 58cc27b29..f22c0a2d8 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -446,6 +446,17 @@ public:
446 */ 446 */
447 void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached); 447 void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached);
448 448
449 /**
450 * Marks each page within the specified address range as debug or non-debug.
451 * Debug addresses are not accessible from fastmem pointers.
452 *
453 * @param vaddr The virtual address indicating the start of the address range.
454 * @param size The size of the address range in bytes.
455 * @param debug Whether or not any pages within the address range should be
456 * marked as debug or non-debug.
457 */
458 void MarkRegionDebug(VAddr vaddr, u64 size, bool debug);
459
449private: 460private:
450 Core::System& system; 461 Core::System& system;
451 462
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index fa2729f54..6e21296f6 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -63,7 +63,7 @@ json GetYuzuVersionData() {
63 }; 63 };
64} 64}
65 65
66json GetReportCommonData(u64 title_id, ResultCode result, const std::string& timestamp, 66json GetReportCommonData(u64 title_id, Result result, const std::string& timestamp,
67 std::optional<u128> user_id = {}) { 67 std::optional<u128> user_id = {}) {
68 auto out = json{ 68 auto out = json{
69 {"title_id", fmt::format("{:016X}", title_id)}, 69 {"title_id", fmt::format("{:016X}", title_id)},
@@ -198,8 +198,8 @@ Reporter::Reporter(System& system_) : system(system_) {
198 198
199Reporter::~Reporter() = default; 199Reporter::~Reporter() = default;
200 200
201void Reporter::SaveCrashReport(u64 title_id, ResultCode result, u64 set_flags, u64 entry_point, 201void Reporter::SaveCrashReport(u64 title_id, Result result, u64 set_flags, u64 entry_point, u64 sp,
202 u64 sp, u64 pc, u64 pstate, u64 afsr0, u64 afsr1, u64 esr, u64 far, 202 u64 pc, u64 pstate, u64 afsr0, u64 afsr1, u64 esr, u64 far,
203 const std::array<u64, 31>& registers, 203 const std::array<u64, 31>& registers,
204 const std::array<u64, 32>& backtrace, u32 backtrace_size, 204 const std::array<u64, 32>& backtrace, u32 backtrace_size,
205 const std::string& arch, u32 unk10) const { 205 const std::string& arch, u32 unk10) const {
@@ -338,7 +338,7 @@ void Reporter::SavePlayReport(PlayReportType type, u64 title_id, std::vector<std
338 SaveToFile(std::move(out), GetPath("play_report", title_id, timestamp)); 338 SaveToFile(std::move(out), GetPath("play_report", title_id, timestamp));
339} 339}
340 340
341void Reporter::SaveErrorReport(u64 title_id, ResultCode result, 341void Reporter::SaveErrorReport(u64 title_id, Result result,
342 std::optional<std::string> custom_text_main, 342 std::optional<std::string> custom_text_main,
343 std::optional<std::string> custom_text_detail) const { 343 std::optional<std::string> custom_text_detail) const {
344 if (!IsReportingEnabled()) { 344 if (!IsReportingEnabled()) {
diff --git a/src/core/reporter.h b/src/core/reporter.h
index a5386bc83..68755cbde 100644
--- a/src/core/reporter.h
+++ b/src/core/reporter.h
@@ -9,7 +9,7 @@
9#include <vector> 9#include <vector>
10#include "common/common_types.h" 10#include "common/common_types.h"
11 11
12union ResultCode; 12union Result;
13 13
14namespace Kernel { 14namespace Kernel {
15class HLERequestContext; 15class HLERequestContext;
@@ -29,7 +29,7 @@ public:
29 ~Reporter(); 29 ~Reporter();
30 30
31 // Used by fatal services 31 // Used by fatal services
32 void SaveCrashReport(u64 title_id, ResultCode result, u64 set_flags, u64 entry_point, u64 sp, 32 void SaveCrashReport(u64 title_id, Result result, u64 set_flags, u64 entry_point, u64 sp,
33 u64 pc, u64 pstate, u64 afsr0, u64 afsr1, u64 esr, u64 far, 33 u64 pc, u64 pstate, u64 afsr0, u64 afsr1, u64 esr, u64 far,
34 const std::array<u64, 31>& registers, const std::array<u64, 32>& backtrace, 34 const std::array<u64, 31>& registers, const std::array<u64, 32>& backtrace,
35 u32 backtrace_size, const std::string& arch, u32 unk10) const; 35 u32 backtrace_size, const std::string& arch, u32 unk10) const;
@@ -60,7 +60,7 @@ public:
60 std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const; 60 std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const;
61 61
62 // Used by error applet 62 // Used by error applet
63 void SaveErrorReport(u64 title_id, ResultCode result, 63 void SaveErrorReport(u64 title_id, Result result,
64 std::optional<std::string> custom_text_main = {}, 64 std::optional<std::string> custom_text_main = {},
65 std::optional<std::string> custom_text_detail = {}) const; 65 std::optional<std::string> custom_text_detail = {}) const;
66 66
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp
index 7a0b73eca..5cc99fbe4 100644
--- a/src/core/tools/freezer.cpp
+++ b/src/core/tools/freezer.cpp
@@ -25,7 +25,6 @@ u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) {
25 return memory.Read64(addr); 25 return memory.Read64(addr);
26 default: 26 default:
27 UNREACHABLE(); 27 UNREACHABLE();
28 return 0;
29 } 28 }
30} 29}
31 30
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index d4fa69a77..48e799cf5 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -44,7 +44,6 @@ else()
44 -Werror 44 -Werror
45 -Werror=conversion 45 -Werror=conversion
46 -Werror=ignored-qualifiers 46 -Werror=ignored-qualifiers
47 -Werror=shadow
48 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 47 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
49 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> 48 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
50 -Werror=unused-variable 49 -Werror=unused-variable
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 1a14ef10b..446c027d3 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -13,11 +13,11 @@
13namespace InputCommon { 13namespace InputCommon {
14 14
15namespace { 15namespace {
16std::string GetGUID(SDL_Joystick* joystick) { 16Common::UUID GetGUID(SDL_Joystick* joystick) {
17 const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); 17 const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
18 char guid_str[33]; 18 std::array<u8, 16> data{};
19 SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str)); 19 std::memcpy(data.data(), guid.data, sizeof(data));
20 return guid_str; 20 return Common::UUID{data};
21} 21}
22} // Anonymous namespace 22} // Anonymous namespace
23 23
@@ -31,9 +31,9 @@ static int SDLEventWatcher(void* user_data, SDL_Event* event) {
31 31
32class SDLJoystick { 32class SDLJoystick {
33public: 33public:
34 SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, 34 SDLJoystick(Common::UUID guid_, int port_, SDL_Joystick* joystick,
35 SDL_GameController* game_controller) 35 SDL_GameController* game_controller)
36 : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose}, 36 : guid{guid_}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose},
37 sdl_controller{game_controller, &SDL_GameControllerClose} { 37 sdl_controller{game_controller, &SDL_GameControllerClose} {
38 EnableMotion(); 38 EnableMotion();
39 } 39 }
@@ -120,7 +120,7 @@ public:
120 */ 120 */
121 const PadIdentifier GetPadIdentifier() const { 121 const PadIdentifier GetPadIdentifier() const {
122 return { 122 return {
123 .guid = Common::UUID{guid}, 123 .guid = guid,
124 .port = static_cast<std::size_t>(port), 124 .port = static_cast<std::size_t>(port),
125 .pad = 0, 125 .pad = 0,
126 }; 126 };
@@ -129,7 +129,7 @@ public:
129 /** 129 /**
130 * The guid of the joystick 130 * The guid of the joystick
131 */ 131 */
132 const std::string& GetGUID() const { 132 const Common::UUID& GetGUID() const {
133 return guid; 133 return guid;
134 } 134 }
135 135
@@ -228,7 +228,7 @@ public:
228 } 228 }
229 229
230private: 230private:
231 std::string guid; 231 Common::UUID guid;
232 int port; 232 int port;
233 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; 233 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
234 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; 234 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
@@ -240,7 +240,7 @@ private:
240 BasicMotion motion; 240 BasicMotion motion;
241}; 241};
242 242
243std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) { 243std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const Common::UUID& guid, int port) {
244 std::scoped_lock lock{joystick_map_mutex}; 244 std::scoped_lock lock{joystick_map_mutex};
245 const auto it = joystick_map.find(guid); 245 const auto it = joystick_map.find(guid);
246 246
@@ -259,9 +259,13 @@ std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string&
259 return joystick_map[guid].emplace_back(std::move(joystick)); 259 return joystick_map[guid].emplace_back(std::move(joystick));
260} 260}
261 261
262std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickByGUID(const std::string& guid, int port) {
263 return GetSDLJoystickByGUID(Common::UUID{guid}, port);
264}
265
262std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) { 266std::shared_ptr<SDLJoystick> SDLDriver::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
263 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id); 267 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
264 const std::string guid = GetGUID(sdl_joystick); 268 const auto guid = GetGUID(sdl_joystick);
265 269
266 std::scoped_lock lock{joystick_map_mutex}; 270 std::scoped_lock lock{joystick_map_mutex};
267 const auto map_it = joystick_map.find(guid); 271 const auto map_it = joystick_map.find(guid);
@@ -295,7 +299,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
295 return; 299 return;
296 } 300 }
297 301
298 const std::string guid = GetGUID(sdl_joystick); 302 const auto guid = GetGUID(sdl_joystick);
299 303
300 std::scoped_lock lock{joystick_map_mutex}; 304 std::scoped_lock lock{joystick_map_mutex};
301 if (joystick_map.find(guid) == joystick_map.end()) { 305 if (joystick_map.find(guid) == joystick_map.end()) {
@@ -324,7 +328,7 @@ void SDLDriver::InitJoystick(int joystick_index) {
324} 328}
325 329
326void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) { 330void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) {
327 const std::string guid = GetGUID(sdl_joystick); 331 const auto guid = GetGUID(sdl_joystick);
328 332
329 std::scoped_lock lock{joystick_map_mutex}; 333 std::scoped_lock lock{joystick_map_mutex};
330 // This call to guid is safe since the joystick is guaranteed to be in the map 334 // This call to guid is safe since the joystick is guaranteed to be in the map
@@ -470,7 +474,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
470 devices.emplace_back(Common::ParamPackage{ 474 devices.emplace_back(Common::ParamPackage{
471 {"engine", GetEngineName()}, 475 {"engine", GetEngineName()},
472 {"display", std::move(name)}, 476 {"display", std::move(name)},
473 {"guid", joystick->GetGUID()}, 477 {"guid", joystick->GetGUID().RawString()},
474 {"port", std::to_string(joystick->GetPort())}, 478 {"port", std::to_string(joystick->GetPort())},
475 }); 479 });
476 if (joystick->IsJoyconLeft()) { 480 if (joystick->IsJoyconLeft()) {
@@ -493,8 +497,8 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
493 devices.emplace_back(Common::ParamPackage{ 497 devices.emplace_back(Common::ParamPackage{
494 {"engine", GetEngineName()}, 498 {"engine", GetEngineName()},
495 {"display", std::move(name)}, 499 {"display", std::move(name)},
496 {"guid", joystick->GetGUID()}, 500 {"guid", joystick->GetGUID().RawString()},
497 {"guid2", joystick2->GetGUID()}, 501 {"guid2", joystick2->GetGUID().RawString()},
498 {"port", std::to_string(joystick->GetPort())}, 502 {"port", std::to_string(joystick->GetPort())},
499 }); 503 });
500 } 504 }
@@ -557,50 +561,50 @@ void SDLDriver::SendVibrations() {
557 } 561 }
558} 562}
559 563
560Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, std::string guid, 564Common::ParamPackage SDLDriver::BuildAnalogParamPackageForButton(int port, const Common::UUID& guid,
561 s32 axis, float value) const { 565 s32 axis, float value) const {
562 Common::ParamPackage params{}; 566 Common::ParamPackage params{};
563 params.Set("engine", GetEngineName()); 567 params.Set("engine", GetEngineName());
564 params.Set("port", port); 568 params.Set("port", port);
565 params.Set("guid", std::move(guid)); 569 params.Set("guid", guid.RawString());
566 params.Set("axis", axis); 570 params.Set("axis", axis);
567 params.Set("threshold", "0.5"); 571 params.Set("threshold", "0.5");
568 params.Set("invert", value < 0 ? "-" : "+"); 572 params.Set("invert", value < 0 ? "-" : "+");
569 return params; 573 return params;
570} 574}
571 575
572Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, std::string guid, 576Common::ParamPackage SDLDriver::BuildButtonParamPackageForButton(int port, const Common::UUID& guid,
573 s32 button) const { 577 s32 button) const {
574 Common::ParamPackage params{}; 578 Common::ParamPackage params{};
575 params.Set("engine", GetEngineName()); 579 params.Set("engine", GetEngineName());
576 params.Set("port", port); 580 params.Set("port", port);
577 params.Set("guid", std::move(guid)); 581 params.Set("guid", guid.RawString());
578 params.Set("button", button); 582 params.Set("button", button);
579 return params; 583 return params;
580} 584}
581 585
582Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, std::string guid, s32 hat, 586Common::ParamPackage SDLDriver::BuildHatParamPackageForButton(int port, const Common::UUID& guid,
583 u8 value) const { 587 s32 hat, u8 value) const {
584 Common::ParamPackage params{}; 588 Common::ParamPackage params{};
585 params.Set("engine", GetEngineName()); 589 params.Set("engine", GetEngineName());
586 params.Set("port", port); 590 params.Set("port", port);
587 params.Set("guid", std::move(guid)); 591 params.Set("guid", guid.RawString());
588 params.Set("hat", hat); 592 params.Set("hat", hat);
589 params.Set("direction", GetHatButtonName(value)); 593 params.Set("direction", GetHatButtonName(value));
590 return params; 594 return params;
591} 595}
592 596
593Common::ParamPackage SDLDriver::BuildMotionParam(int port, std::string guid) const { 597Common::ParamPackage SDLDriver::BuildMotionParam(int port, const Common::UUID& guid) const {
594 Common::ParamPackage params{}; 598 Common::ParamPackage params{};
595 params.Set("engine", GetEngineName()); 599 params.Set("engine", GetEngineName());
596 params.Set("motion", 0); 600 params.Set("motion", 0);
597 params.Set("port", port); 601 params.Set("port", port);
598 params.Set("guid", std::move(guid)); 602 params.Set("guid", guid.RawString());
599 return params; 603 return params;
600} 604}
601 605
602Common::ParamPackage SDLDriver::BuildParamPackageForBinding( 606Common::ParamPackage SDLDriver::BuildParamPackageForBinding(
603 int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const { 607 int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const {
604 switch (binding.bindType) { 608 switch (binding.bindType) {
605 case SDL_CONTROLLER_BINDTYPE_NONE: 609 case SDL_CONTROLLER_BINDTYPE_NONE:
606 break; 610 break;
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index c82632506..0846fbb50 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -47,6 +47,7 @@ public:
47 * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so 47 * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so
48 * tie it to a SDLJoystick with the same guid and that port 48 * tie it to a SDLJoystick with the same guid and that port
49 */ 49 */
50 std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const Common::UUID& guid, int port);
50 std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port); 51 std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port);
51 52
52 std::vector<Common::ParamPackage> GetInputDevices() const override; 53 std::vector<Common::ParamPackage> GetInputDevices() const override;
@@ -79,18 +80,18 @@ private:
79 /// Takes all vibrations from the queue and sends the command to the controller 80 /// Takes all vibrations from the queue and sends the command to the controller
80 void SendVibrations(); 81 void SendVibrations();
81 82
82 Common::ParamPackage BuildAnalogParamPackageForButton(int port, std::string guid, s32 axis, 83 Common::ParamPackage BuildAnalogParamPackageForButton(int port, const Common::UUID& guid,
83 float value = 0.1f) const; 84 s32 axis, float value = 0.1f) const;
84 Common::ParamPackage BuildButtonParamPackageForButton(int port, std::string guid, 85 Common::ParamPackage BuildButtonParamPackageForButton(int port, const Common::UUID& guid,
85 s32 button) const; 86 s32 button) const;
86 87
87 Common::ParamPackage BuildHatParamPackageForButton(int port, std::string guid, s32 hat, 88 Common::ParamPackage BuildHatParamPackageForButton(int port, const Common::UUID& guid, s32 hat,
88 u8 value) const; 89 u8 value) const;
89 90
90 Common::ParamPackage BuildMotionParam(int port, std::string guid) const; 91 Common::ParamPackage BuildMotionParam(int port, const Common::UUID& guid) const;
91 92
92 Common::ParamPackage BuildParamPackageForBinding( 93 Common::ParamPackage BuildParamPackageForBinding(
93 int port, const std::string& guid, const SDL_GameControllerButtonBind& binding) const; 94 int port, const Common::UUID& guid, const SDL_GameControllerButtonBind& binding) const;
94 95
95 Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, 96 Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x,
96 int axis_y, float offset_x, 97 int axis_y, float offset_x,
@@ -120,7 +121,7 @@ private:
120 Common::SPSCQueue<VibrationRequest> vibration_queue; 121 Common::SPSCQueue<VibrationRequest> vibration_queue;
121 122
122 /// Map of GUID of a list of corresponding virtual Joysticks 123 /// Map of GUID of a list of corresponding virtual Joysticks
123 std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map; 124 std::unordered_map<Common::UUID, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
124 std::mutex joystick_map_mutex; 125 std::mutex joystick_map_mutex;
125 126
126 bool start_thread = false; 127 bool start_thread = false;
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index 4c76ce1ea..ae1dbe619 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -253,9 +253,6 @@ else()
253 -Werror 253 -Werror
254 -Werror=conversion 254 -Werror=conversion
255 -Werror=ignored-qualifiers 255 -Werror=ignored-qualifiers
256 -Werror=implicit-fallthrough
257 -Werror=shadow
258 -Werror=sign-compare
259 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter> 256 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
260 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable> 257 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
261 -Werror=unused-variable 258 -Werror=unused-variable
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.h b/src/shader_recompiler/frontend/maxwell/control_flow.h
index 2487b9b0b..1ce45b3a5 100644
--- a/src/shader_recompiler/frontend/maxwell/control_flow.h
+++ b/src/shader_recompiler/frontend/maxwell/control_flow.h
@@ -58,7 +58,7 @@ public:
58 [[nodiscard]] Stack Remove(Token token) const; 58 [[nodiscard]] Stack Remove(Token token) const;
59 59
60private: 60private:
61 boost::container::small_vector<StackEntry, 3> entries; 61 std::vector<StackEntry> entries;
62}; 62};
63 63
64struct IndirectBranch { 64struct IndirectBranch {
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
index 3dc7c9a11..578bc8c1b 100644
--- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp
@@ -975,13 +975,7 @@ private:
975 Environment& env; 975 Environment& env;
976 IR::AbstractSyntaxList& syntax_list; 976 IR::AbstractSyntaxList& syntax_list;
977 bool uses_demote_to_helper{}; 977 bool uses_demote_to_helper{};
978
979// TODO: C++20 Remove this when all compilers support constexpr std::vector
980#if __cpp_lib_constexpr_vector >= 201907
981 static constexpr Flow::Block dummy_flow_block;
982#else
983 const Flow::Block dummy_flow_block; 978 const Flow::Block dummy_flow_block;
984#endif
985}; 979};
986} // Anonymous namespace 980} // Anonymous namespace
987 981
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp
index 8358d36b5..e687416a8 100644
--- a/src/tests/core/core_timing.cpp
+++ b/src/tests/core/core_timing.cpp
@@ -8,6 +8,7 @@
8#include <chrono> 8#include <chrono>
9#include <cstdlib> 9#include <cstdlib>
10#include <memory> 10#include <memory>
11#include <mutex>
11#include <string> 12#include <string>
12 13
13#include "core/core.h" 14#include "core/core.h"
@@ -21,13 +22,14 @@ std::array<s64, 5> delays{};
21 22
22std::bitset<CB_IDS.size()> callbacks_ran_flags; 23std::bitset<CB_IDS.size()> callbacks_ran_flags;
23u64 expected_callback = 0; 24u64 expected_callback = 0;
25std::mutex control_mutex;
24 26
25template <unsigned int IDX> 27template <unsigned int IDX>
26void HostCallbackTemplate(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) { 28void HostCallbackTemplate(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
29 std::unique_lock<std::mutex> lk(control_mutex);
27 static_assert(IDX < CB_IDS.size(), "IDX out of range"); 30 static_assert(IDX < CB_IDS.size(), "IDX out of range");
28 callbacks_ran_flags.set(IDX); 31 callbacks_ran_flags.set(IDX);
29 REQUIRE(CB_IDS[IDX] == user_data); 32 REQUIRE(CB_IDS[IDX] == user_data);
30 REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
31 delays[IDX] = ns_late.count(); 33 delays[IDX] = ns_late.count();
32 ++expected_callback; 34 ++expected_callback;
33} 35}
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 256695804..14de7bc89 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -258,10 +258,6 @@ if (MSVC)
258 target_compile_options(video_core PRIVATE 258 target_compile_options(video_core PRIVATE
259 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data 259 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
260 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data 260 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
261 /we4456 # Declaration of 'identifier' hides previous local declaration
262 /we4457 # Declaration of 'identifier' hides function parameter
263 /we4458 # Declaration of 'identifier' hides class member
264 /we4459 # Declaration of 'identifier' hides global declaration
265 ) 261 )
266else() 262else()
267 target_compile_options(video_core PRIVATE 263 target_compile_options(video_core PRIVATE
@@ -269,7 +265,6 @@ else()
269 -Wno-error=sign-conversion 265 -Wno-error=sign-conversion
270 -Werror=pessimizing-move 266 -Werror=pessimizing-move
271 -Werror=redundant-move 267 -Werror=redundant-move
272 -Werror=shadow
273 -Werror=type-limits 268 -Werror=type-limits
274 269
275 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> 270 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess>
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp
index 83b2e0fc4..a5eb97b7f 100644
--- a/src/video_core/command_classes/codecs/codec.cpp
+++ b/src/video_core/command_classes/codecs/codec.cpp
@@ -224,7 +224,7 @@ void Codec::Decode() {
224 vp9_hidden_frame = vp9_decoder->WasFrameHidden(); 224 vp9_hidden_frame = vp9_decoder->WasFrameHidden();
225 return vp9_decoder->GetFrameBytes(); 225 return vp9_decoder->GetFrameBytes();
226 default: 226 default:
227 UNREACHABLE(); 227 ASSERT(false);
228 return std::vector<u8>{}; 228 return std::vector<u8>{};
229 } 229 }
230 }(); 230 }();
diff --git a/src/video_core/command_classes/vic.cpp b/src/video_core/command_classes/vic.cpp
index bef321b6e..7c17df353 100644
--- a/src/video_core/command_classes/vic.cpp
+++ b/src/video_core/command_classes/vic.cpp
@@ -228,7 +228,7 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
228 break; 228 break;
229 } 229 }
230 default: 230 default:
231 UNREACHABLE(); 231 ASSERT(false);
232 break; 232 break;
233 } 233 }
234 gpu.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), 234 gpu.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(),
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 434ba0877..5f9eb208c 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -202,7 +202,7 @@ public:
202 case Size::Size_11_11_10: 202 case Size::Size_11_11_10:
203 return 3; 203 return 3;
204 default: 204 default:
205 UNREACHABLE(); 205 ASSERT(false);
206 return 1; 206 return 1;
207 } 207 }
208 } 208 }
@@ -238,7 +238,7 @@ public:
238 case Size::Size_11_11_10: 238 case Size::Size_11_11_10:
239 return 4; 239 return 4;
240 default: 240 default:
241 UNREACHABLE(); 241 ASSERT(false);
242 return 1; 242 return 1;
243 } 243 }
244 } 244 }
@@ -274,7 +274,7 @@ public:
274 case Size::Size_11_11_10: 274 case Size::Size_11_11_10:
275 return "11_11_10"; 275 return "11_11_10";
276 default: 276 default:
277 UNREACHABLE(); 277 ASSERT(false);
278 return {}; 278 return {};
279 } 279 }
280 } 280 }
@@ -296,7 +296,7 @@ public:
296 case Type::Float: 296 case Type::Float:
297 return "FLOAT"; 297 return "FLOAT";
298 } 298 }
299 UNREACHABLE(); 299 ASSERT(false);
300 return {}; 300 return {};
301 } 301 }
302 302
@@ -336,7 +336,7 @@ public:
336 case 3: 336 case 3:
337 return {x3, y3}; 337 return {x3, y3};
338 default: 338 default:
339 UNREACHABLE(); 339 ASSERT(false);
340 return {0, 0}; 340 return {0, 0};
341 } 341 }
342 } 342 }
@@ -1193,7 +1193,7 @@ public:
1193 case IndexFormat::UnsignedInt: 1193 case IndexFormat::UnsignedInt:
1194 return 4; 1194 return 4;
1195 } 1195 }
1196 UNREACHABLE(); 1196 ASSERT(false);
1197 return 1; 1197 return 1;
1198 } 1198 }
1199 1199
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp
index a7302f7c1..0efe58282 100644
--- a/src/video_core/engines/maxwell_dma.cpp
+++ b/src/video_core/engines/maxwell_dma.cpp
@@ -62,7 +62,7 @@ void MaxwellDMA::Launch() {
62 62
63 if (!is_src_pitch && !is_dst_pitch) { 63 if (!is_src_pitch && !is_dst_pitch) {
64 // If both the source and the destination are in block layout, assert. 64 // If both the source and the destination are in block layout, assert.
65 UNREACHABLE_MSG("Tiled->Tiled DMA transfers are not yet implemented"); 65 UNIMPLEMENTED_MSG("Tiled->Tiled DMA transfers are not yet implemented");
66 return; 66 return;
67 } 67 }
68 68
@@ -260,7 +260,7 @@ void MaxwellDMA::ReleaseSemaphore() {
260 memory_manager.Write<u64>(address + 8, system.GPU().GetTicks()); 260 memory_manager.Write<u64>(address + 8, system.GPU().GetTicks());
261 break; 261 break;
262 default: 262 default:
263 UNREACHABLE_MSG("Unknown semaphore type: {}", static_cast<u32>(type.Value())); 263 ASSERT_MSG(false, "Unknown semaphore type: {}", static_cast<u32>(type.Value()));
264 } 264 }
265} 265}
266 266
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 8479dc6d2..b0ce9f000 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -50,7 +50,7 @@ static void RunThread(std::stop_token stop_token, Core::System& system,
50 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) { 50 } else if (const auto* invalidate = std::get_if<InvalidateRegionCommand>(&next.data)) {
51 rasterizer->OnCPUWrite(invalidate->addr, invalidate->size); 51 rasterizer->OnCPUWrite(invalidate->addr, invalidate->size);
52 } else { 52 } else {
53 UNREACHABLE(); 53 ASSERT(false);
54 } 54 }
55 state.signaled_fence.store(next.fence); 55 state.signaled_fence.store(next.fence);
56 if (next.block) { 56 if (next.block) {
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index ad9fd5eff..be0ac2214 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -98,7 +98,7 @@ struct CommandDataContainer {
98struct SynchState final { 98struct SynchState final {
99 using CommandQueue = Common::MPSCQueue<CommandDataContainer>; 99 using CommandQueue = Common::MPSCQueue<CommandDataContainer>;
100 std::mutex write_lock; 100 std::mutex write_lock;
101 CommandQueue queue{512}; // size must be 2^n 101 CommandQueue queue;
102 u64 last_fence{}; 102 u64 last_fence{};
103 std::atomic<u64> signaled_fence{}; 103 std::atomic<u64> signaled_fence{};
104 std::condition_variable_any cv; 104 std::condition_variable_any cv;
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp
index e7279efcd..43f8b5904 100644
--- a/src/video_core/macro/macro.cpp
+++ b/src/video_core/macro/macro.cpp
@@ -71,7 +71,7 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) {
71 } 71 }
72 } 72 }
73 if (!mid_method.has_value()) { 73 if (!mid_method.has_value()) {
74 UNREACHABLE_MSG("Macro 0x{0:x} was not uploaded", method); 74 ASSERT_MSG(false, "Macro 0x{0:x} was not uploaded", method);
75 return; 75 return;
76 } 76 }
77 } 77 }
diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp
index 87d2e8721..f670b1bca 100644
--- a/src/video_core/macro/macro_interpreter.cpp
+++ b/src/video_core/macro/macro_interpreter.cpp
@@ -308,7 +308,6 @@ bool MacroInterpreterImpl::EvaluateBranchCondition(Macro::BranchCondition cond,
308 return value != 0; 308 return value != 0;
309 } 309 }
310 UNREACHABLE(); 310 UNREACHABLE();
311 return true;
312} 311}
313 312
314Macro::Opcode MacroInterpreterImpl::GetOpcode() const { 313Macro::Opcode MacroInterpreterImpl::GetOpcode() const {
diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp
index dc5376501..aca25d902 100644
--- a/src/video_core/macro/macro_jit_x64.cpp
+++ b/src/video_core/macro/macro_jit_x64.cpp
@@ -411,7 +411,7 @@ void MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) {
411 411
412 Xbyak::Label end; 412 Xbyak::Label end;
413 auto value = Compile_GetRegister(opcode.src_a, eax); 413 auto value = Compile_GetRegister(opcode.src_a, eax);
414 test(value, value); 414 cmp(value, 0); // test(value, value);
415 if (optimizer.has_delayed_pc) { 415 if (optimizer.has_delayed_pc) {
416 switch (opcode.branch_condition) { 416 switch (opcode.branch_condition) {
417 case Macro::BranchCondition::Zero: 417 case Macro::BranchCondition::Zero:
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index c8d99fdb5..d373be0ba 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -67,7 +67,7 @@ void MemoryManager::Unmap(GPUVAddr gpu_addr, std::size_t size) {
67 ASSERT(it->first == gpu_addr); 67 ASSERT(it->first == gpu_addr);
68 map_ranges.erase(it); 68 map_ranges.erase(it);
69 } else { 69 } else {
70 UNREACHABLE_MSG("Unmapping non-existent GPU address=0x{:x}", gpu_addr); 70 ASSERT_MSG(false, "Unmapping non-existent GPU address=0x{:x}", gpu_addr);
71 } 71 }
72 const auto submapped_ranges = GetSubmappedRange(gpu_addr, size); 72 const auto submapped_ranges = GetSubmappedRange(gpu_addr, size);
73 73
@@ -206,7 +206,7 @@ T MemoryManager::Read(GPUVAddr addr) const {
206 return value; 206 return value;
207 } 207 }
208 208
209 UNREACHABLE(); 209 ASSERT(false);
210 210
211 return {}; 211 return {};
212} 212}
@@ -219,7 +219,7 @@ void MemoryManager::Write(GPUVAddr addr, T data) {
219 return; 219 return;
220 } 220 }
221 221
222 UNREACHABLE(); 222 ASSERT(false);
223} 223}
224 224
225template u8 MemoryManager::Read<u8>(GPUVAddr addr) const; 225template u8 MemoryManager::Read<u8>(GPUVAddr addr) const;
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 35f42f2f8..67eae369d 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -48,7 +48,7 @@ GLenum Stage(size_t stage_index) {
48 case 4: 48 case 4:
49 return GL_FRAGMENT_SHADER; 49 return GL_FRAGMENT_SHADER;
50 } 50 }
51 UNREACHABLE_MSG("{}", stage_index); 51 ASSERT_MSG(false, "{}", stage_index);
52 return GL_NONE; 52 return GL_NONE;
53} 53}
54 54
@@ -65,7 +65,7 @@ GLenum AssemblyStage(size_t stage_index) {
65 case 4: 65 case 4:
66 return GL_FRAGMENT_PROGRAM_NV; 66 return GL_FRAGMENT_PROGRAM_NV;
67 } 67 }
68 UNREACHABLE_MSG("{}", stage_index); 68 ASSERT_MSG(false, "{}", stage_index);
69 return GL_NONE; 69 return GL_NONE;
70} 70}
71 71
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index cd48fef26..07d4b7cf0 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -85,7 +85,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
85 case Maxwell::TessellationPrimitive::Quads: 85 case Maxwell::TessellationPrimitive::Quads:
86 return Shader::TessPrimitive::Quads; 86 return Shader::TessPrimitive::Quads;
87 } 87 }
88 UNREACHABLE(); 88 ASSERT(false);
89 return Shader::TessPrimitive::Triangles; 89 return Shader::TessPrimitive::Triangles;
90 }(); 90 }();
91 info.tess_spacing = [&] { 91 info.tess_spacing = [&] {
@@ -97,7 +97,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
97 case Maxwell::TessellationSpacing::FractionalEven: 97 case Maxwell::TessellationSpacing::FractionalEven:
98 return Shader::TessSpacing::FractionalEven; 98 return Shader::TessSpacing::FractionalEven;
99 } 99 }
100 UNREACHABLE(); 100 ASSERT(false);
101 return Shader::TessSpacing::Equal; 101 return Shader::TessSpacing::Equal;
102 }(); 102 }();
103 break; 103 break;
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 29ff736fb..8c0fffc67 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -83,7 +83,7 @@ GLenum ImageTarget(const VideoCommon::ImageInfo& info) {
83 case ImageType::Buffer: 83 case ImageType::Buffer:
84 return GL_TEXTURE_BUFFER; 84 return GL_TEXTURE_BUFFER;
85 } 85 }
86 UNREACHABLE_MSG("Invalid image type={}", info.type); 86 ASSERT_MSG(false, "Invalid image type={}", info.type);
87 return GL_NONE; 87 return GL_NONE;
88} 88}
89 89
@@ -107,7 +107,7 @@ GLenum ImageTarget(Shader::TextureType type, int num_samples = 1) {
107 case Shader::TextureType::Buffer: 107 case Shader::TextureType::Buffer:
108 return GL_TEXTURE_BUFFER; 108 return GL_TEXTURE_BUFFER;
109 } 109 }
110 UNREACHABLE_MSG("Invalid image view type={}", type); 110 ASSERT_MSG(false, "Invalid image view type={}", type);
111 return GL_NONE; 111 return GL_NONE;
112} 112}
113 113
@@ -119,7 +119,7 @@ GLenum TextureMode(PixelFormat format, bool is_first) {
119 case PixelFormat::S8_UINT_D24_UNORM: 119 case PixelFormat::S8_UINT_D24_UNORM:
120 return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; 120 return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
121 default: 121 default:
122 UNREACHABLE(); 122 ASSERT(false);
123 return GL_DEPTH_COMPONENT; 123 return GL_DEPTH_COMPONENT;
124 } 124 }
125} 125}
@@ -140,7 +140,7 @@ GLint Swizzle(SwizzleSource source) {
140 case SwizzleSource::OneFloat: 140 case SwizzleSource::OneFloat:
141 return GL_ONE; 141 return GL_ONE;
142 } 142 }
143 UNREACHABLE_MSG("Invalid swizzle source={}", source); 143 ASSERT_MSG(false, "Invalid swizzle source={}", source);
144 return GL_NONE; 144 return GL_NONE;
145} 145}
146 146
@@ -197,7 +197,7 @@ GLint ConvertA5B5G5R1_UNORM(SwizzleSource source) {
197 case SwizzleSource::OneFloat: 197 case SwizzleSource::OneFloat:
198 return GL_ONE; 198 return GL_ONE;
199 } 199 }
200 UNREACHABLE_MSG("Invalid swizzle source={}", source); 200 ASSERT_MSG(false, "Invalid swizzle source={}", source);
201 return GL_NONE; 201 return GL_NONE;
202} 202}
203 203
@@ -381,10 +381,10 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
381 glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, depth); 381 glTextureStorage3D(handle, gl_num_levels, gl_internal_format, width, height, depth);
382 break; 382 break;
383 case GL_TEXTURE_BUFFER: 383 case GL_TEXTURE_BUFFER:
384 UNREACHABLE(); 384 ASSERT(false);
385 break; 385 break;
386 default: 386 default:
387 UNREACHABLE_MSG("Invalid target=0x{:x}", target); 387 ASSERT_MSG(false, "Invalid target=0x{:x}", target);
388 break; 388 break;
389 } 389 }
390 return texture; 390 return texture;
@@ -420,7 +420,7 @@ OGLTexture MakeImage(const VideoCommon::ImageInfo& info, GLenum gl_internal_form
420 case Shader::ImageFormat::R32G32B32A32_UINT: 420 case Shader::ImageFormat::R32G32B32A32_UINT:
421 return GL_RGBA32UI; 421 return GL_RGBA32UI;
422 } 422 }
423 UNREACHABLE_MSG("Invalid image format={}", format); 423 ASSERT_MSG(false, "Invalid image format={}", format);
424 return GL_R32UI; 424 return GL_R32UI;
425} 425}
426 426
@@ -579,7 +579,7 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src,
579 } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) { 579 } else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) {
580 format_conversion_pass.ConvertImage(dst, src, copies); 580 format_conversion_pass.ConvertImage(dst, src, copies);
581 } else { 581 } else {
582 UNREACHABLE(); 582 ASSERT(false);
583 } 583 }
584} 584}
585 585
@@ -620,7 +620,7 @@ void TextureCacheRuntime::AccelerateImageUpload(Image& image, const ImageBufferM
620 case ImageType::Linear: 620 case ImageType::Linear:
621 return util_shaders.PitchUpload(image, map, swizzles); 621 return util_shaders.PitchUpload(image, map, swizzles);
622 default: 622 default:
623 UNREACHABLE(); 623 ASSERT(false);
624 break; 624 break;
625 } 625 }
626} 626}
@@ -639,7 +639,7 @@ FormatProperties TextureCacheRuntime::FormatInfo(ImageType type, GLenum internal
639 case ImageType::e3D: 639 case ImageType::e3D:
640 return format_properties[2].at(internal_format); 640 return format_properties[2].at(internal_format);
641 default: 641 default:
642 UNREACHABLE(); 642 ASSERT(false);
643 return FormatProperties{}; 643 return FormatProperties{};
644 } 644 }
645} 645}
@@ -888,7 +888,7 @@ void Image::CopyBufferToImage(const VideoCommon::BufferImageCopy& copy, size_t b
888 } 888 }
889 break; 889 break;
890 default: 890 default:
891 UNREACHABLE(); 891 ASSERT(false);
892 } 892 }
893} 893}
894 894
@@ -924,7 +924,7 @@ void Image::CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t b
924 depth = copy.image_extent.depth; 924 depth = copy.image_extent.depth;
925 break; 925 break;
926 default: 926 default:
927 UNREACHABLE(); 927 ASSERT(false);
928 } 928 }
929 // Compressed formats don't have a pixel format or type 929 // Compressed formats don't have a pixel format or type
930 const bool is_compressed = gl_format == GL_NONE; 930 const bool is_compressed = gl_format == GL_NONE;
@@ -950,7 +950,7 @@ void Image::Scale(bool up_scale) {
950 case SurfaceType::DepthStencil: 950 case SurfaceType::DepthStencil:
951 return GL_DEPTH_STENCIL_ATTACHMENT; 951 return GL_DEPTH_STENCIL_ATTACHMENT;
952 default: 952 default:
953 UNREACHABLE(); 953 ASSERT(false);
954 return GL_COLOR_ATTACHMENT0; 954 return GL_COLOR_ATTACHMENT0;
955 } 955 }
956 }(); 956 }();
@@ -965,7 +965,7 @@ void Image::Scale(bool up_scale) {
965 case SurfaceType::DepthStencil: 965 case SurfaceType::DepthStencil:
966 return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; 966 return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
967 default: 967 default:
968 UNREACHABLE(); 968 ASSERT(false);
969 return GL_COLOR_BUFFER_BIT; 969 return GL_COLOR_BUFFER_BIT;
970 } 970 }
971 }(); 971 }();
@@ -980,7 +980,7 @@ void Image::Scale(bool up_scale) {
980 case SurfaceType::DepthStencil: 980 case SurfaceType::DepthStencil:
981 return 3; 981 return 3;
982 default: 982 default:
983 UNREACHABLE(); 983 ASSERT(false);
984 return 0; 984 return 0;
985 } 985 }
986 }(); 986 }();
@@ -1045,7 +1045,7 @@ bool Image::ScaleUp(bool ignore) {
1045 return false; 1045 return false;
1046 } 1046 }
1047 if (info.type == ImageType::Linear) { 1047 if (info.type == ImageType::Linear) {
1048 UNREACHABLE(); 1048 ASSERT(false);
1049 return false; 1049 return false;
1050 } 1050 }
1051 flags |= ImageFlagBits::Rescaled; 1051 flags |= ImageFlagBits::Rescaled;
@@ -1139,7 +1139,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
1139 UNIMPLEMENTED(); 1139 UNIMPLEMENTED();
1140 break; 1140 break;
1141 case ImageViewType::Buffer: 1141 case ImageViewType::Buffer:
1142 UNREACHABLE(); 1142 ASSERT(false);
1143 break; 1143 break;
1144 } 1144 }
1145 switch (info.type) { 1145 switch (info.type) {
@@ -1319,7 +1319,7 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM
1319 buffer_bits |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; 1319 buffer_bits |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
1320 break; 1320 break;
1321 default: 1321 default:
1322 UNREACHABLE(); 1322 ASSERT(false);
1323 buffer_bits |= GL_DEPTH_BUFFER_BIT; 1323 buffer_bits |= GL_DEPTH_BUFFER_BIT;
1324 break; 1324 break;
1325 } 1325 }
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index c2a6da5a7..644b60d73 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -206,7 +206,7 @@ inline GLenum IndexFormat(Maxwell::IndexFormat index_format) {
206 case Maxwell::IndexFormat::UnsignedInt: 206 case Maxwell::IndexFormat::UnsignedInt:
207 return GL_UNSIGNED_INT; 207 return GL_UNSIGNED_INT;
208 } 208 }
209 UNREACHABLE_MSG("Invalid index_format={}", index_format); 209 ASSERT_MSG(false, "Invalid index_format={}", index_format);
210 return {}; 210 return {};
211} 211}
212 212
@@ -243,7 +243,7 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
243 case Maxwell::PrimitiveTopology::Patches: 243 case Maxwell::PrimitiveTopology::Patches:
244 return GL_PATCHES; 244 return GL_PATCHES;
245 } 245 }
246 UNREACHABLE_MSG("Invalid topology={}", topology); 246 ASSERT_MSG(false, "Invalid topology={}", topology);
247 return GL_POINTS; 247 return GL_POINTS;
248} 248}
249 249
@@ -271,8 +271,8 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode,
271 } 271 }
272 break; 272 break;
273 } 273 }
274 UNREACHABLE_MSG("Invalid texture filter mode={} and mipmap filter mode={}", filter_mode, 274 ASSERT_MSG(false, "Invalid texture filter mode={} and mipmap filter mode={}", filter_mode,
275 mipmap_filter_mode); 275 mipmap_filter_mode);
276 return GL_NEAREST; 276 return GL_NEAREST;
277} 277}
278 278
@@ -550,7 +550,7 @@ inline GLenum PolygonMode(Maxwell::PolygonMode polygon_mode) {
550 case Maxwell::PolygonMode::Fill: 550 case Maxwell::PolygonMode::Fill:
551 return GL_FILL; 551 return GL_FILL;
552 } 552 }
553 UNREACHABLE_MSG("Invalid polygon mode={}", polygon_mode); 553 ASSERT_MSG(false, "Invalid polygon mode={}", polygon_mode);
554 return GL_FILL; 554 return GL_FILL;
555} 555}
556 556
@@ -563,7 +563,7 @@ inline GLenum ReductionFilter(Tegra::Texture::SamplerReduction filter) {
563 case Tegra::Texture::SamplerReduction::Max: 563 case Tegra::Texture::SamplerReduction::Max:
564 return GL_MAX; 564 return GL_MAX;
565 } 565 }
566 UNREACHABLE_MSG("Invalid reduction filter={}", static_cast<int>(filter)); 566 ASSERT_MSG(false, "Invalid reduction filter={}", static_cast<int>(filter));
567 return GL_WEIGHTED_AVERAGE_ARB; 567 return GL_WEIGHTED_AVERAGE_ARB;
568} 568}
569 569
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 3a3c213bb..9a9243544 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -79,7 +79,7 @@ const char* GetSource(GLenum source) {
79 case GL_DEBUG_SOURCE_OTHER: 79 case GL_DEBUG_SOURCE_OTHER:
80 return "OTHER"; 80 return "OTHER";
81 default: 81 default:
82 UNREACHABLE(); 82 ASSERT(false);
83 return "Unknown source"; 83 return "Unknown source";
84 } 84 }
85} 85}
@@ -101,7 +101,7 @@ const char* GetType(GLenum type) {
101 case GL_DEBUG_TYPE_MARKER: 101 case GL_DEBUG_TYPE_MARKER:
102 return "MARKER"; 102 return "MARKER";
103 default: 103 default:
104 UNREACHABLE(); 104 ASSERT(false);
105 return "Unknown type"; 105 return "Unknown type";
106 } 106 }
107} 107}
diff --git a/src/video_core/renderer_opengl/util_shaders.cpp b/src/video_core/renderer_opengl/util_shaders.cpp
index 837825737..404def62e 100644
--- a/src/video_core/renderer_opengl/util_shaders.cpp
+++ b/src/video_core/renderer_opengl/util_shaders.cpp
@@ -282,7 +282,7 @@ GLenum StoreFormat(u32 bytes_per_block) {
282 case 16: 282 case 16:
283 return GL_RGBA32UI; 283 return GL_RGBA32UI;
284 } 284 }
285 UNREACHABLE(); 285 ASSERT(false);
286 return GL_R8UI; 286 return GL_R8UI;
287} 287}
288 288
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index 5d35366f7..3f2b139e0 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -349,7 +349,7 @@ VkExtent2D GetConversionExtent(const ImageView& src_image_view) {
349} 349}
350} // Anonymous namespace 350} // Anonymous namespace
351 351
352BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, 352BlitImageHelper::BlitImageHelper(const Device& device_, Scheduler& scheduler_,
353 StateTracker& state_tracker_, DescriptorPool& descriptor_pool) 353 StateTracker& state_tracker_, DescriptorPool& descriptor_pool)
354 : device{device_}, scheduler{scheduler_}, state_tracker{state_tracker_}, 354 : device{device_}, scheduler{scheduler_}, state_tracker{state_tracker_},
355 one_texture_set_layout(device.GetLogical().CreateDescriptorSetLayout( 355 one_texture_set_layout(device.GetLogical().CreateDescriptorSetLayout(
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index 21e9d7d69..5df679fb4 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -16,7 +16,7 @@ class Device;
16class Framebuffer; 16class Framebuffer;
17class ImageView; 17class ImageView;
18class StateTracker; 18class StateTracker;
19class VKScheduler; 19class Scheduler;
20 20
21struct BlitImagePipelineKey { 21struct BlitImagePipelineKey {
22 constexpr auto operator<=>(const BlitImagePipelineKey&) const noexcept = default; 22 constexpr auto operator<=>(const BlitImagePipelineKey&) const noexcept = default;
@@ -27,7 +27,7 @@ struct BlitImagePipelineKey {
27 27
28class BlitImageHelper { 28class BlitImageHelper {
29public: 29public:
30 explicit BlitImageHelper(const Device& device, VKScheduler& scheduler, 30 explicit BlitImageHelper(const Device& device, Scheduler& scheduler,
31 StateTracker& state_tracker, DescriptorPool& descriptor_pool); 31 StateTracker& state_tracker, DescriptorPool& descriptor_pool);
32 ~BlitImageHelper(); 32 ~BlitImageHelper();
33 33
@@ -82,7 +82,7 @@ private:
82 vk::ShaderModule& module); 82 vk::ShaderModule& module);
83 83
84 const Device& device; 84 const Device& device;
85 VKScheduler& scheduler; 85 Scheduler& scheduler;
86 StateTracker& state_tracker; 86 StateTracker& state_tracker;
87 87
88 vk::DescriptorSetLayout one_texture_set_layout; 88 vk::DescriptorSetLayout one_texture_set_layout;
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index ea360f339..193cbe15e 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -25,7 +25,7 @@ VkFilter Filter(Tegra::Texture::TextureFilter filter) {
25 case Tegra::Texture::TextureFilter::Linear: 25 case Tegra::Texture::TextureFilter::Linear:
26 return VK_FILTER_LINEAR; 26 return VK_FILTER_LINEAR;
27 } 27 }
28 UNREACHABLE_MSG("Invalid sampler filter={}", filter); 28 ASSERT_MSG(false, "Invalid sampler filter={}", filter);
29 return {}; 29 return {};
30} 30}
31 31
@@ -42,7 +42,7 @@ VkSamplerMipmapMode MipmapMode(Tegra::Texture::TextureMipmapFilter mipmap_filter
42 case Tegra::Texture::TextureMipmapFilter::Linear: 42 case Tegra::Texture::TextureMipmapFilter::Linear:
43 return VK_SAMPLER_MIPMAP_MODE_LINEAR; 43 return VK_SAMPLER_MIPMAP_MODE_LINEAR;
44 } 44 }
45 UNREACHABLE_MSG("Invalid sampler mipmap mode={}", mipmap_filter); 45 ASSERT_MSG(false, "Invalid sampler mipmap mode={}", mipmap_filter);
46 return {}; 46 return {};
47} 47}
48 48
@@ -70,7 +70,7 @@ VkSamplerAddressMode WrapMode(const Device& device, Tegra::Texture::WrapMode wra
70 case Tegra::Texture::TextureFilter::Linear: 70 case Tegra::Texture::TextureFilter::Linear:
71 return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 71 return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER;
72 } 72 }
73 UNREACHABLE(); 73 ASSERT(false);
74 return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 74 return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
75 case Tegra::Texture::WrapMode::MirrorOnceClampToEdge: 75 case Tegra::Texture::WrapMode::MirrorOnceClampToEdge:
76 return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; 76 return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE;
@@ -744,7 +744,7 @@ VkViewportCoordinateSwizzleNV ViewportSwizzle(Maxwell::ViewportSwizzle swizzle)
744 case Maxwell::ViewportSwizzle::NegativeW: 744 case Maxwell::ViewportSwizzle::NegativeW:
745 return VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV; 745 return VK_VIEWPORT_COORDINATE_SWIZZLE_NEGATIVE_W_NV;
746 } 746 }
747 UNREACHABLE_MSG("Invalid swizzle={}", swizzle); 747 ASSERT_MSG(false, "Invalid swizzle={}", swizzle);
748 return {}; 748 return {};
749} 749}
750 750
@@ -757,7 +757,7 @@ VkSamplerReductionMode SamplerReduction(Tegra::Texture::SamplerReduction reducti
757 case Tegra::Texture::SamplerReduction::Max: 757 case Tegra::Texture::SamplerReduction::Max:
758 return VK_SAMPLER_REDUCTION_MODE_MAX_EXT; 758 return VK_SAMPLER_REDUCTION_MODE_MAX_EXT;
759 } 759 }
760 UNREACHABLE_MSG("Invalid sampler mode={}", static_cast<int>(reduction)); 760 ASSERT_MSG(false, "Invalid sampler mode={}", static_cast<int>(reduction));
761 return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT; 761 return VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT;
762} 762}
763 763
@@ -780,7 +780,7 @@ VkSampleCountFlagBits MsaaMode(Tegra::Texture::MsaaMode msaa_mode) {
780 case Tegra::Texture::MsaaMode::Msaa4x4: 780 case Tegra::Texture::MsaaMode::Msaa4x4:
781 return VK_SAMPLE_COUNT_16_BIT; 781 return VK_SAMPLE_COUNT_16_BIT;
782 default: 782 default:
783 UNREACHABLE_MSG("Invalid msaa_mode={}", static_cast<int>(msaa_mode)); 783 ASSERT_MSG(false, "Invalid msaa_mode={}", static_cast<int>(msaa_mode));
784 return VK_SAMPLE_COUNT_1_BIT; 784 return VK_SAMPLE_COUNT_1_BIT;
785 } 785 }
786} 786}
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index 9d676612c..b24f3424a 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -168,7 +168,7 @@ private:
168}; 168};
169 169
170inline void PushImageDescriptors(TextureCache& texture_cache, 170inline void PushImageDescriptors(TextureCache& texture_cache,
171 VKUpdateDescriptorQueue& update_descriptor_queue, 171 UpdateDescriptorQueue& update_descriptor_queue,
172 const Shader::Info& info, RescalingPushConstant& rescaling, 172 const Shader::Info& info, RescalingPushConstant& rescaling,
173 const VkSampler*& samplers, 173 const VkSampler*& samplers,
174 const VideoCommon::ImageViewInOut*& views) { 174 const VideoCommon::ImageViewInOut*& views) {
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 8a8cb347c..e7bfecb20 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -65,14 +65,14 @@ private:
65 vk::DebugUtilsMessenger debug_callback; 65 vk::DebugUtilsMessenger debug_callback;
66 vk::SurfaceKHR surface; 66 vk::SurfaceKHR surface;
67 67
68 VKScreenInfo screen_info; 68 ScreenInfo screen_info;
69 69
70 Device device; 70 Device device;
71 MemoryAllocator memory_allocator; 71 MemoryAllocator memory_allocator;
72 StateTracker state_tracker; 72 StateTracker state_tracker;
73 VKScheduler scheduler; 73 Scheduler scheduler;
74 VKSwapchain swapchain; 74 Swapchain swapchain;
75 VKBlitScreen blit_screen; 75 BlitScreen blit_screen;
76 RasterizerVulkan rasterizer; 76 RasterizerVulkan rasterizer;
77}; 77};
78 78
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 289bfd7b6..1ec8392e1 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -108,7 +108,7 @@ VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
108 108
109} // Anonymous namespace 109} // Anonymous namespace
110 110
111struct VKBlitScreen::BufferData { 111struct BlitScreen::BufferData {
112 struct { 112 struct {
113 std::array<f32, 4 * 4> modelview_matrix; 113 std::array<f32, 4 * 4> modelview_matrix;
114 } uniform; 114 } uniform;
@@ -118,10 +118,9 @@ struct VKBlitScreen::BufferData {
118 // Unaligned image data goes here 118 // Unaligned image data goes here
119}; 119};
120 120
121VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_, 121BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWindow& render_window_,
122 Core::Frontend::EmuWindow& render_window_, const Device& device_, 122 const Device& device_, MemoryAllocator& memory_allocator_,
123 MemoryAllocator& memory_allocator_, VKSwapchain& swapchain_, 123 Swapchain& swapchain_, Scheduler& scheduler_, const ScreenInfo& screen_info_)
124 VKScheduler& scheduler_, const VKScreenInfo& screen_info_)
125 : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_}, 124 : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_},
126 memory_allocator{memory_allocator_}, swapchain{swapchain_}, scheduler{scheduler_}, 125 memory_allocator{memory_allocator_}, swapchain{swapchain_}, scheduler{scheduler_},
127 image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { 126 image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
@@ -131,16 +130,16 @@ VKBlitScreen::VKBlitScreen(Core::Memory::Memory& cpu_memory_,
131 CreateDynamicResources(); 130 CreateDynamicResources();
132} 131}
133 132
134VKBlitScreen::~VKBlitScreen() = default; 133BlitScreen::~BlitScreen() = default;
135 134
136void VKBlitScreen::Recreate() { 135void BlitScreen::Recreate() {
137 CreateDynamicResources(); 136 CreateDynamicResources();
138} 137}
139 138
140VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer, 139VkSemaphore BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
141 const VkFramebuffer& host_framebuffer, 140 const VkFramebuffer& host_framebuffer,
142 const Layout::FramebufferLayout layout, VkExtent2D render_area, 141 const Layout::FramebufferLayout layout, VkExtent2D render_area,
143 bool use_accelerated) { 142 bool use_accelerated) {
144 RefreshResources(framebuffer); 143 RefreshResources(framebuffer);
145 144
146 // Finish any pending renderpass 145 // Finish any pending renderpass
@@ -419,20 +418,20 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
419 return *semaphores[image_index]; 418 return *semaphores[image_index];
420} 419}
421 420
422VkSemaphore VKBlitScreen::DrawToSwapchain(const Tegra::FramebufferConfig& framebuffer, 421VkSemaphore BlitScreen::DrawToSwapchain(const Tegra::FramebufferConfig& framebuffer,
423 bool use_accelerated) { 422 bool use_accelerated) {
424 const std::size_t image_index = swapchain.GetImageIndex(); 423 const std::size_t image_index = swapchain.GetImageIndex();
425 const VkExtent2D render_area = swapchain.GetSize(); 424 const VkExtent2D render_area = swapchain.GetSize();
426 const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); 425 const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
427 return Draw(framebuffer, *framebuffers[image_index], layout, render_area, use_accelerated); 426 return Draw(framebuffer, *framebuffers[image_index], layout, render_area, use_accelerated);
428} 427}
429 428
430vk::Framebuffer VKBlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent) { 429vk::Framebuffer BlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent) {
431 return CreateFramebuffer(image_view, extent, renderpass); 430 return CreateFramebuffer(image_view, extent, renderpass);
432} 431}
433 432
434vk::Framebuffer VKBlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent, 433vk::Framebuffer BlitScreen::CreateFramebuffer(const VkImageView& image_view, VkExtent2D extent,
435 vk::RenderPass& rd) { 434 vk::RenderPass& rd) {
436 return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{ 435 return device.GetLogical().CreateFramebuffer(VkFramebufferCreateInfo{
437 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 436 .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
438 .pNext = nullptr, 437 .pNext = nullptr,
@@ -446,7 +445,7 @@ vk::Framebuffer VKBlitScreen::CreateFramebuffer(const VkImageView& image_view, V
446 }); 445 });
447} 446}
448 447
449void VKBlitScreen::CreateStaticResources() { 448void BlitScreen::CreateStaticResources() {
450 CreateShaders(); 449 CreateShaders();
451 CreateSemaphores(); 450 CreateSemaphores();
452 CreateDescriptorPool(); 451 CreateDescriptorPool();
@@ -456,7 +455,7 @@ void VKBlitScreen::CreateStaticResources() {
456 CreateSampler(); 455 CreateSampler();
457} 456}
458 457
459void VKBlitScreen::CreateDynamicResources() { 458void BlitScreen::CreateDynamicResources() {
460 CreateRenderPass(); 459 CreateRenderPass();
461 CreateFramebuffers(); 460 CreateFramebuffers();
462 CreateGraphicsPipeline(); 461 CreateGraphicsPipeline();
@@ -466,7 +465,7 @@ void VKBlitScreen::CreateDynamicResources() {
466 } 465 }
467} 466}
468 467
469void VKBlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) { 468void BlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer) {
470 if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { 469 if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
471 if (!fsr) { 470 if (!fsr) {
472 CreateFSR(); 471 CreateFSR();
@@ -486,7 +485,7 @@ void VKBlitScreen::RefreshResources(const Tegra::FramebufferConfig& framebuffer)
486 CreateRawImages(framebuffer); 485 CreateRawImages(framebuffer);
487} 486}
488 487
489void VKBlitScreen::CreateShaders() { 488void BlitScreen::CreateShaders() {
490 vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV); 489 vertex_shader = BuildShader(device, VULKAN_PRESENT_VERT_SPV);
491 fxaa_vertex_shader = BuildShader(device, FXAA_VERT_SPV); 490 fxaa_vertex_shader = BuildShader(device, FXAA_VERT_SPV);
492 fxaa_fragment_shader = BuildShader(device, FXAA_FRAG_SPV); 491 fxaa_fragment_shader = BuildShader(device, FXAA_FRAG_SPV);
@@ -500,12 +499,12 @@ void VKBlitScreen::CreateShaders() {
500 } 499 }
501} 500}
502 501
503void VKBlitScreen::CreateSemaphores() { 502void BlitScreen::CreateSemaphores() {
504 semaphores.resize(image_count); 503 semaphores.resize(image_count);
505 std::ranges::generate(semaphores, [this] { return device.GetLogical().CreateSemaphore(); }); 504 std::ranges::generate(semaphores, [this] { return device.GetLogical().CreateSemaphore(); });
506} 505}
507 506
508void VKBlitScreen::CreateDescriptorPool() { 507void BlitScreen::CreateDescriptorPool() {
509 const std::array<VkDescriptorPoolSize, 2> pool_sizes{{ 508 const std::array<VkDescriptorPoolSize, 2> pool_sizes{{
510 { 509 {
511 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 510 .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
@@ -545,11 +544,11 @@ void VKBlitScreen::CreateDescriptorPool() {
545 aa_descriptor_pool = device.GetLogical().CreateDescriptorPool(ci_aa); 544 aa_descriptor_pool = device.GetLogical().CreateDescriptorPool(ci_aa);
546} 545}
547 546
548void VKBlitScreen::CreateRenderPass() { 547void BlitScreen::CreateRenderPass() {
549 renderpass = CreateRenderPassImpl(swapchain.GetImageViewFormat()); 548 renderpass = CreateRenderPassImpl(swapchain.GetImageViewFormat());
550} 549}
551 550
552vk::RenderPass VKBlitScreen::CreateRenderPassImpl(VkFormat format, bool is_present) { 551vk::RenderPass BlitScreen::CreateRenderPassImpl(VkFormat format, bool is_present) {
553 const VkAttachmentDescription color_attachment{ 552 const VkAttachmentDescription color_attachment{
554 .flags = 0, 553 .flags = 0,
555 .format = format, 554 .format = format,
@@ -605,7 +604,7 @@ vk::RenderPass VKBlitScreen::CreateRenderPassImpl(VkFormat format, bool is_prese
605 return device.GetLogical().CreateRenderPass(renderpass_ci); 604 return device.GetLogical().CreateRenderPass(renderpass_ci);
606} 605}
607 606
608void VKBlitScreen::CreateDescriptorSetLayout() { 607void BlitScreen::CreateDescriptorSetLayout() {
609 const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{{ 608 const std::array<VkDescriptorSetLayoutBinding, 2> layout_bindings{{
610 { 609 {
611 .binding = 0, 610 .binding = 0,
@@ -660,7 +659,7 @@ void VKBlitScreen::CreateDescriptorSetLayout() {
660 aa_descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci_aa); 659 aa_descriptor_set_layout = device.GetLogical().CreateDescriptorSetLayout(ci_aa);
661} 660}
662 661
663void VKBlitScreen::CreateDescriptorSets() { 662void BlitScreen::CreateDescriptorSets() {
664 const std::vector layouts(image_count, *descriptor_set_layout); 663 const std::vector layouts(image_count, *descriptor_set_layout);
665 const std::vector layouts_aa(image_count, *aa_descriptor_set_layout); 664 const std::vector layouts_aa(image_count, *aa_descriptor_set_layout);
666 665
@@ -684,7 +683,7 @@ void VKBlitScreen::CreateDescriptorSets() {
684 aa_descriptor_sets = aa_descriptor_pool.Allocate(ai_aa); 683 aa_descriptor_sets = aa_descriptor_pool.Allocate(ai_aa);
685} 684}
686 685
687void VKBlitScreen::CreatePipelineLayout() { 686void BlitScreen::CreatePipelineLayout() {
688 const VkPipelineLayoutCreateInfo ci{ 687 const VkPipelineLayoutCreateInfo ci{
689 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 688 .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
690 .pNext = nullptr, 689 .pNext = nullptr,
@@ -707,7 +706,7 @@ void VKBlitScreen::CreatePipelineLayout() {
707 aa_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci_aa); 706 aa_pipeline_layout = device.GetLogical().CreatePipelineLayout(ci_aa);
708} 707}
709 708
710void VKBlitScreen::CreateGraphicsPipeline() { 709void BlitScreen::CreateGraphicsPipeline() {
711 const std::array<VkPipelineShaderStageCreateInfo, 2> bilinear_shader_stages{{ 710 const std::array<VkPipelineShaderStageCreateInfo, 2> bilinear_shader_stages{{
712 { 711 {
713 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 712 .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
@@ -980,7 +979,7 @@ void VKBlitScreen::CreateGraphicsPipeline() {
980 scaleforce_pipeline = device.GetLogical().CreateGraphicsPipeline(scaleforce_pipeline_ci); 979 scaleforce_pipeline = device.GetLogical().CreateGraphicsPipeline(scaleforce_pipeline_ci);
981} 980}
982 981
983void VKBlitScreen::CreateSampler() { 982void BlitScreen::CreateSampler() {
984 const VkSamplerCreateInfo ci{ 983 const VkSamplerCreateInfo ci{
985 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, 984 .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
986 .pNext = nullptr, 985 .pNext = nullptr,
@@ -1027,7 +1026,7 @@ void VKBlitScreen::CreateSampler() {
1027 nn_sampler = device.GetLogical().CreateSampler(ci_nn); 1026 nn_sampler = device.GetLogical().CreateSampler(ci_nn);
1028} 1027}
1029 1028
1030void VKBlitScreen::CreateFramebuffers() { 1029void BlitScreen::CreateFramebuffers() {
1031 const VkExtent2D size{swapchain.GetSize()}; 1030 const VkExtent2D size{swapchain.GetSize()};
1032 framebuffers.resize(image_count); 1031 framebuffers.resize(image_count);
1033 1032
@@ -1037,7 +1036,7 @@ void VKBlitScreen::CreateFramebuffers() {
1037 } 1036 }
1038} 1037}
1039 1038
1040void VKBlitScreen::ReleaseRawImages() { 1039void BlitScreen::ReleaseRawImages() {
1041 for (const u64 tick : resource_ticks) { 1040 for (const u64 tick : resource_ticks) {
1042 scheduler.Wait(tick); 1041 scheduler.Wait(tick);
1043 } 1042 }
@@ -1052,7 +1051,7 @@ void VKBlitScreen::ReleaseRawImages() {
1052 buffer_commit = MemoryCommit{}; 1051 buffer_commit = MemoryCommit{};
1053} 1052}
1054 1053
1055void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) { 1054void BlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
1056 const VkBufferCreateInfo ci{ 1055 const VkBufferCreateInfo ci{
1057 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 1056 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1058 .pNext = nullptr, 1057 .pNext = nullptr,
@@ -1069,7 +1068,7 @@ void VKBlitScreen::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuff
1069 buffer_commit = memory_allocator.Commit(buffer, MemoryUsage::Upload); 1068 buffer_commit = memory_allocator.Commit(buffer, MemoryUsage::Upload);
1070} 1069}
1071 1070
1072void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) { 1071void BlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer) {
1073 raw_images.resize(image_count); 1072 raw_images.resize(image_count);
1074 raw_image_views.resize(image_count); 1073 raw_image_views.resize(image_count);
1075 raw_buffer_commits.resize(image_count); 1074 raw_buffer_commits.resize(image_count);
@@ -1294,8 +1293,8 @@ void VKBlitScreen::CreateRawImages(const Tegra::FramebufferConfig& framebuffer)
1294 aa_pipeline = device.GetLogical().CreateGraphicsPipeline(fxaa_pipeline_ci); 1293 aa_pipeline = device.GetLogical().CreateGraphicsPipeline(fxaa_pipeline_ci);
1295} 1294}
1296 1295
1297void VKBlitScreen::UpdateAADescriptorSet(std::size_t image_index, VkImageView image_view, 1296void BlitScreen::UpdateAADescriptorSet(std::size_t image_index, VkImageView image_view,
1298 bool nn) const { 1297 bool nn) const {
1299 const VkDescriptorImageInfo image_info{ 1298 const VkDescriptorImageInfo image_info{
1300 .sampler = nn ? *nn_sampler : *sampler, 1299 .sampler = nn ? *nn_sampler : *sampler,
1301 .imageView = image_view, 1300 .imageView = image_view,
@@ -1331,8 +1330,8 @@ void VKBlitScreen::UpdateAADescriptorSet(std::size_t image_index, VkImageView im
1331 device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, sampler_write_2}, {}); 1330 device.GetLogical().UpdateDescriptorSets(std::array{sampler_write, sampler_write_2}, {});
1332} 1331}
1333 1332
1334void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view, 1333void BlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView image_view,
1335 bool nn) const { 1334 bool nn) const {
1336 const VkDescriptorBufferInfo buffer_info{ 1335 const VkDescriptorBufferInfo buffer_info{
1337 .buffer = *buffer, 1336 .buffer = *buffer,
1338 .offset = offsetof(BufferData, uniform), 1337 .offset = offsetof(BufferData, uniform),
@@ -1374,13 +1373,13 @@ void VKBlitScreen::UpdateDescriptorSet(std::size_t image_index, VkImageView imag
1374 device.GetLogical().UpdateDescriptorSets(std::array{ubo_write, sampler_write}, {}); 1373 device.GetLogical().UpdateDescriptorSets(std::array{ubo_write, sampler_write}, {});
1375} 1374}
1376 1375
1377void VKBlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const { 1376void BlitScreen::SetUniformData(BufferData& data, const Layout::FramebufferLayout layout) const {
1378 data.uniform.modelview_matrix = 1377 data.uniform.modelview_matrix =
1379 MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height)); 1378 MakeOrthographicMatrix(static_cast<f32>(layout.width), static_cast<f32>(layout.height));
1380} 1379}
1381 1380
1382void VKBlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer, 1381void BlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfig& framebuffer,
1383 const Layout::FramebufferLayout layout) const { 1382 const Layout::FramebufferLayout layout) const {
1384 const auto& framebuffer_transform_flags = framebuffer.transform_flags; 1383 const auto& framebuffer_transform_flags = framebuffer.transform_flags;
1385 const auto& framebuffer_crop_rect = framebuffer.crop_rect; 1384 const auto& framebuffer_crop_rect = framebuffer.crop_rect;
1386 1385
@@ -1432,7 +1431,7 @@ void VKBlitScreen::SetVertexData(BufferData& data, const Tegra::FramebufferConfi
1432 data.vertices[3] = ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v); 1431 data.vertices[3] = ScreenRectVertex(x + w, y + h, texcoords.bottom * scale_u, right * scale_v);
1433} 1432}
1434 1433
1435void VKBlitScreen::CreateFSR() { 1434void BlitScreen::CreateFSR() {
1436 const auto& layout = render_window.GetFramebufferLayout(); 1435 const auto& layout = render_window.GetFramebufferLayout();
1437 const VkExtent2D fsr_size{ 1436 const VkExtent2D fsr_size{
1438 .width = layout.screen.GetWidth(), 1437 .width = layout.screen.GetWidth(),
@@ -1441,12 +1440,12 @@ void VKBlitScreen::CreateFSR() {
1441 fsr = std::make_unique<FSR>(device, memory_allocator, image_count, fsr_size); 1440 fsr = std::make_unique<FSR>(device, memory_allocator, image_count, fsr_size);
1442} 1441}
1443 1442
1444u64 VKBlitScreen::CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const { 1443u64 BlitScreen::CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const {
1445 return sizeof(BufferData) + GetSizeInBytes(framebuffer) * image_count; 1444 return sizeof(BufferData) + GetSizeInBytes(framebuffer) * image_count;
1446} 1445}
1447 1446
1448u64 VKBlitScreen::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer, 1447u64 BlitScreen::GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer,
1449 std::size_t image_index) const { 1448 std::size_t image_index) const {
1450 constexpr auto first_image_offset = static_cast<u64>(sizeof(BufferData)); 1449 constexpr auto first_image_offset = static_cast<u64>(sizeof(BufferData));
1451 return first_image_offset + GetSizeInBytes(framebuffer) * image_index; 1450 return first_image_offset + GetSizeInBytes(framebuffer) * image_index;
1452} 1451}
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
index 1b4260f36..b8c67bef0 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.h
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -35,23 +35,22 @@ struct ScreenInfo;
35class Device; 35class Device;
36class FSR; 36class FSR;
37class RasterizerVulkan; 37class RasterizerVulkan;
38class VKScheduler; 38class Scheduler;
39class VKSwapchain; 39class Swapchain;
40 40
41struct VKScreenInfo { 41struct ScreenInfo {
42 VkImageView image_view{}; 42 VkImageView image_view{};
43 u32 width{}; 43 u32 width{};
44 u32 height{}; 44 u32 height{};
45 bool is_srgb{}; 45 bool is_srgb{};
46}; 46};
47 47
48class VKBlitScreen { 48class BlitScreen {
49public: 49public:
50 explicit VKBlitScreen(Core::Memory::Memory& cpu_memory, 50 explicit BlitScreen(Core::Memory::Memory& cpu_memory, Core::Frontend::EmuWindow& render_window,
51 Core::Frontend::EmuWindow& render_window, const Device& device, 51 const Device& device, MemoryAllocator& memory_manager, Swapchain& swapchain,
52 MemoryAllocator& memory_manager, VKSwapchain& swapchain, 52 Scheduler& scheduler, const ScreenInfo& screen_info);
53 VKScheduler& scheduler, const VKScreenInfo& screen_info); 53 ~BlitScreen();
54 ~VKBlitScreen();
55 54
56 void Recreate(); 55 void Recreate();
57 56
@@ -108,10 +107,10 @@ private:
108 Core::Frontend::EmuWindow& render_window; 107 Core::Frontend::EmuWindow& render_window;
109 const Device& device; 108 const Device& device;
110 MemoryAllocator& memory_allocator; 109 MemoryAllocator& memory_allocator;
111 VKSwapchain& swapchain; 110 Swapchain& swapchain;
112 VKScheduler& scheduler; 111 Scheduler& scheduler;
113 const std::size_t image_count; 112 const std::size_t image_count;
114 const VKScreenInfo& screen_info; 113 const ScreenInfo& screen_info;
115 114
116 vk::ShaderModule vertex_shader; 115 vk::ShaderModule vertex_shader;
117 vk::ShaderModule fxaa_vertex_shader; 116 vk::ShaderModule fxaa_vertex_shader;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 0aeb37538..558b8db56 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -46,7 +46,7 @@ size_t BytesPerIndex(VkIndexType index_type) {
46 case VK_INDEX_TYPE_UINT32: 46 case VK_INDEX_TYPE_UINT32:
47 return 4; 47 return 4;
48 default: 48 default:
49 UNREACHABLE_MSG("Invalid index type={}", index_type); 49 ASSERT_MSG(false, "Invalid index type={}", index_type);
50 return 1; 50 return 1;
51 } 51 }
52} 52}
@@ -124,8 +124,8 @@ VkBufferView Buffer::View(u32 offset, u32 size, VideoCore::Surface::PixelFormat
124} 124}
125 125
126BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_, 126BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_,
127 VKScheduler& scheduler_, StagingBufferPool& staging_pool_, 127 Scheduler& scheduler_, StagingBufferPool& staging_pool_,
128 VKUpdateDescriptorQueue& update_descriptor_queue_, 128 UpdateDescriptorQueue& update_descriptor_queue_,
129 DescriptorPool& descriptor_pool) 129 DescriptorPool& descriptor_pool)
130 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, 130 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
131 staging_pool{staging_pool_}, update_descriptor_queue{update_descriptor_queue_}, 131 staging_pool{staging_pool_}, update_descriptor_queue{update_descriptor_queue_},
@@ -366,7 +366,7 @@ void BufferCacheRuntime::ReserveQuadArrayLUT(u32 num_indices, bool wait_for_idle
366 std::memcpy(staging_data, MakeQuadIndices<u32>(quad, first).data(), quad_size); 366 std::memcpy(staging_data, MakeQuadIndices<u32>(quad, first).data(), quad_size);
367 break; 367 break;
368 default: 368 default:
369 UNREACHABLE(); 369 ASSERT(false);
370 break; 370 break;
371 } 371 }
372 staging_data += quad_size; 372 staging_data += quad_size;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 6fa618f18..a15c8b39b 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -16,7 +16,7 @@ namespace Vulkan {
16 16
17class Device; 17class Device;
18class DescriptorPool; 18class DescriptorPool;
19class VKScheduler; 19class Scheduler;
20 20
21class BufferCacheRuntime; 21class BufferCacheRuntime;
22 22
@@ -58,8 +58,8 @@ class BufferCacheRuntime {
58 58
59public: 59public:
60 explicit BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_manager_, 60 explicit BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_manager_,
61 VKScheduler& scheduler_, StagingBufferPool& staging_pool_, 61 Scheduler& scheduler_, StagingBufferPool& staging_pool_,
62 VKUpdateDescriptorQueue& update_descriptor_queue_, 62 UpdateDescriptorQueue& update_descriptor_queue_,
63 DescriptorPool& descriptor_pool); 63 DescriptorPool& descriptor_pool);
64 64
65 void Finish(); 65 void Finish();
@@ -124,9 +124,9 @@ private:
124 124
125 const Device& device; 125 const Device& device;
126 MemoryAllocator& memory_allocator; 126 MemoryAllocator& memory_allocator;
127 VKScheduler& scheduler; 127 Scheduler& scheduler;
128 StagingBufferPool& staging_pool; 128 StagingBufferPool& staging_pool;
129 VKUpdateDescriptorQueue& update_descriptor_queue; 129 UpdateDescriptorQueue& update_descriptor_queue;
130 130
131 vk::Buffer quad_array_lut; 131 vk::Buffer quad_array_lut;
132 MemoryCommit quad_array_lut_commit; 132 MemoryCommit quad_array_lut_commit;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 29481a102..f17a5ccd6 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -200,9 +200,9 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
200 200
201ComputePass::~ComputePass() = default; 201ComputePass::~ComputePass() = default;
202 202
203Uint8Pass::Uint8Pass(const Device& device_, VKScheduler& scheduler_, 203Uint8Pass::Uint8Pass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool,
204 DescriptorPool& descriptor_pool, StagingBufferPool& staging_buffer_pool_, 204 StagingBufferPool& staging_buffer_pool_,
205 VKUpdateDescriptorQueue& update_descriptor_queue_) 205 UpdateDescriptorQueue& update_descriptor_queue_)
206 : ComputePass(device_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, 206 : ComputePass(device_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
207 INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {}, 207 INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {},
208 VULKAN_UINT8_COMP_SPV), 208 VULKAN_UINT8_COMP_SPV),
@@ -241,10 +241,10 @@ std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer
241 return {staging.buffer, staging.offset}; 241 return {staging.buffer, staging.offset};
242} 242}
243 243
244QuadIndexedPass::QuadIndexedPass(const Device& device_, VKScheduler& scheduler_, 244QuadIndexedPass::QuadIndexedPass(const Device& device_, Scheduler& scheduler_,
245 DescriptorPool& descriptor_pool_, 245 DescriptorPool& descriptor_pool_,
246 StagingBufferPool& staging_buffer_pool_, 246 StagingBufferPool& staging_buffer_pool_,
247 VKUpdateDescriptorQueue& update_descriptor_queue_) 247 UpdateDescriptorQueue& update_descriptor_queue_)
248 : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS, 248 : ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
249 INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, 249 INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
250 COMPUTE_PUSH_CONSTANT_RANGE<sizeof(u32) * 2>, VULKAN_QUAD_INDEXED_COMP_SPV), 250 COMPUTE_PUSH_CONSTANT_RANGE<sizeof(u32) * 2>, VULKAN_QUAD_INDEXED_COMP_SPV),
@@ -265,7 +265,7 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
265 case Tegra::Engines::Maxwell3D::Regs::IndexFormat::UnsignedInt: 265 case Tegra::Engines::Maxwell3D::Regs::IndexFormat::UnsignedInt:
266 return 2; 266 return 2;
267 } 267 }
268 UNREACHABLE(); 268 ASSERT(false);
269 return 2; 269 return 2;
270 }(); 270 }();
271 const u32 input_size = num_vertices << index_shift; 271 const u32 input_size = num_vertices << index_shift;
@@ -303,10 +303,10 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
303 return {staging.buffer, staging.offset}; 303 return {staging.buffer, staging.offset};
304} 304}
305 305
306ASTCDecoderPass::ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, 306ASTCDecoderPass::ASTCDecoderPass(const Device& device_, Scheduler& scheduler_,
307 DescriptorPool& descriptor_pool_, 307 DescriptorPool& descriptor_pool_,
308 StagingBufferPool& staging_buffer_pool_, 308 StagingBufferPool& staging_buffer_pool_,
309 VKUpdateDescriptorQueue& update_descriptor_queue_, 309 UpdateDescriptorQueue& update_descriptor_queue_,
310 MemoryAllocator& memory_allocator_) 310 MemoryAllocator& memory_allocator_)
311 : ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS, 311 : ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
312 ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO, 312 ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
@@ -328,31 +328,32 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
328 const VkImageAspectFlags aspect_mask = image.AspectMask(); 328 const VkImageAspectFlags aspect_mask = image.AspectMask();
329 const VkImage vk_image = image.Handle(); 329 const VkImage vk_image = image.Handle();
330 const bool is_initialized = image.ExchangeInitialization(); 330 const bool is_initialized = image.ExchangeInitialization();
331 scheduler.Record( 331 scheduler.Record([vk_pipeline, vk_image, aspect_mask,
332 [vk_pipeline, vk_image, aspect_mask, is_initialized](vk::CommandBuffer cmdbuf) { 332 is_initialized](vk::CommandBuffer cmdbuf) {
333 const VkImageMemoryBarrier image_barrier{ 333 const VkImageMemoryBarrier image_barrier{
334 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 334 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
335 .pNext = nullptr, 335 .pNext = nullptr,
336 .srcAccessMask = is_initialized ? VK_ACCESS_SHADER_WRITE_BIT : VkAccessFlags{}, 336 .srcAccessMask = static_cast<VkAccessFlags>(is_initialized ? VK_ACCESS_SHADER_WRITE_BIT
337 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, 337 : VK_ACCESS_NONE),
338 .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, 338 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
339 .newLayout = VK_IMAGE_LAYOUT_GENERAL, 339 .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
340 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 340 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
341 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, 341 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
342 .image = vk_image, 342 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
343 .subresourceRange{ 343 .image = vk_image,
344 .aspectMask = aspect_mask, 344 .subresourceRange{
345 .baseMipLevel = 0, 345 .aspectMask = aspect_mask,
346 .levelCount = VK_REMAINING_MIP_LEVELS, 346 .baseMipLevel = 0,
347 .baseArrayLayer = 0, 347 .levelCount = VK_REMAINING_MIP_LEVELS,
348 .layerCount = VK_REMAINING_ARRAY_LAYERS, 348 .baseArrayLayer = 0,
349 }, 349 .layerCount = VK_REMAINING_ARRAY_LAYERS,
350 }; 350 },
351 cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT 351 };
352 : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 352 cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
353 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier); 353 : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
354 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline); 354 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
355 }); 355 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
356 });
356 for (const VideoCommon::SwizzleParameters& swizzle : swizzles) { 357 for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
357 const size_t input_offset = swizzle.buffer_offset + map.offset; 358 const size_t input_offset = swizzle.buffer_offset + map.offset;
358 const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 8U); 359 const u32 num_dispatches_x = Common::DivCeil(swizzle.num_tiles.width, 8U);
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h
index 1c6aa0805..dcc691a8e 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.h
@@ -20,8 +20,8 @@ namespace Vulkan {
20 20
21class Device; 21class Device;
22class StagingBufferPool; 22class StagingBufferPool;
23class VKScheduler; 23class Scheduler;
24class VKUpdateDescriptorQueue; 24class UpdateDescriptorQueue;
25class Image; 25class Image;
26struct StagingBufferRef; 26struct StagingBufferRef;
27 27
@@ -48,9 +48,9 @@ private:
48 48
49class Uint8Pass final : public ComputePass { 49class Uint8Pass final : public ComputePass {
50public: 50public:
51 explicit Uint8Pass(const Device& device_, VKScheduler& scheduler_, 51 explicit Uint8Pass(const Device& device_, Scheduler& scheduler_,
52 DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_, 52 DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_,
53 VKUpdateDescriptorQueue& update_descriptor_queue_); 53 UpdateDescriptorQueue& update_descriptor_queue_);
54 ~Uint8Pass(); 54 ~Uint8Pass();
55 55
56 /// Assemble uint8 indices into an uint16 index buffer 56 /// Assemble uint8 indices into an uint16 index buffer
@@ -59,17 +59,17 @@ public:
59 u32 src_offset); 59 u32 src_offset);
60 60
61private: 61private:
62 VKScheduler& scheduler; 62 Scheduler& scheduler;
63 StagingBufferPool& staging_buffer_pool; 63 StagingBufferPool& staging_buffer_pool;
64 VKUpdateDescriptorQueue& update_descriptor_queue; 64 UpdateDescriptorQueue& update_descriptor_queue;
65}; 65};
66 66
67class QuadIndexedPass final : public ComputePass { 67class QuadIndexedPass final : public ComputePass {
68public: 68public:
69 explicit QuadIndexedPass(const Device& device_, VKScheduler& scheduler_, 69 explicit QuadIndexedPass(const Device& device_, Scheduler& scheduler_,
70 DescriptorPool& descriptor_pool_, 70 DescriptorPool& descriptor_pool_,
71 StagingBufferPool& staging_buffer_pool_, 71 StagingBufferPool& staging_buffer_pool_,
72 VKUpdateDescriptorQueue& update_descriptor_queue_); 72 UpdateDescriptorQueue& update_descriptor_queue_);
73 ~QuadIndexedPass(); 73 ~QuadIndexedPass();
74 74
75 std::pair<VkBuffer, VkDeviceSize> Assemble( 75 std::pair<VkBuffer, VkDeviceSize> Assemble(
@@ -77,17 +77,17 @@ public:
77 u32 base_vertex, VkBuffer src_buffer, u32 src_offset); 77 u32 base_vertex, VkBuffer src_buffer, u32 src_offset);
78 78
79private: 79private:
80 VKScheduler& scheduler; 80 Scheduler& scheduler;
81 StagingBufferPool& staging_buffer_pool; 81 StagingBufferPool& staging_buffer_pool;
82 VKUpdateDescriptorQueue& update_descriptor_queue; 82 UpdateDescriptorQueue& update_descriptor_queue;
83}; 83};
84 84
85class ASTCDecoderPass final : public ComputePass { 85class ASTCDecoderPass final : public ComputePass {
86public: 86public:
87 explicit ASTCDecoderPass(const Device& device_, VKScheduler& scheduler_, 87 explicit ASTCDecoderPass(const Device& device_, Scheduler& scheduler_,
88 DescriptorPool& descriptor_pool_, 88 DescriptorPool& descriptor_pool_,
89 StagingBufferPool& staging_buffer_pool_, 89 StagingBufferPool& staging_buffer_pool_,
90 VKUpdateDescriptorQueue& update_descriptor_queue_, 90 UpdateDescriptorQueue& update_descriptor_queue_,
91 MemoryAllocator& memory_allocator_); 91 MemoryAllocator& memory_allocator_);
92 ~ASTCDecoderPass(); 92 ~ASTCDecoderPass();
93 93
@@ -95,9 +95,9 @@ public:
95 std::span<const VideoCommon::SwizzleParameters> swizzles); 95 std::span<const VideoCommon::SwizzleParameters> swizzles);
96 96
97private: 97private:
98 VKScheduler& scheduler; 98 Scheduler& scheduler;
99 StagingBufferPool& staging_buffer_pool; 99 StagingBufferPool& staging_buffer_pool;
100 VKUpdateDescriptorQueue& update_descriptor_queue; 100 UpdateDescriptorQueue& update_descriptor_queue;
101 MemoryAllocator& memory_allocator; 101 MemoryAllocator& memory_allocator;
102}; 102};
103 103
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 6c497b5d4..6447210e2 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -25,7 +25,7 @@ using Shader::Backend::SPIRV::RESCALING_LAYOUT_WORDS_OFFSET;
25using Tegra::Texture::TexturePair; 25using Tegra::Texture::TexturePair;
26 26
27ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool, 27ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descriptor_pool,
28 VKUpdateDescriptorQueue& update_descriptor_queue_, 28 UpdateDescriptorQueue& update_descriptor_queue_,
29 Common::ThreadWorker* thread_worker, 29 Common::ThreadWorker* thread_worker,
30 PipelineStatistics* pipeline_statistics, 30 PipelineStatistics* pipeline_statistics,
31 VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_, 31 VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_,
@@ -91,7 +91,7 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript
91} 91}
92 92
93void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute, 93void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
94 Tegra::MemoryManager& gpu_memory, VKScheduler& scheduler, 94 Tegra::MemoryManager& gpu_memory, Scheduler& scheduler,
95 BufferCache& buffer_cache, TextureCache& texture_cache) { 95 BufferCache& buffer_cache, TextureCache& texture_cache) {
96 update_descriptor_queue.Acquire(); 96 update_descriptor_queue.Acquire();
97 97
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index d4c0e2015..9879735fe 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -24,12 +24,12 @@ namespace Vulkan {
24 24
25class Device; 25class Device;
26class PipelineStatistics; 26class PipelineStatistics;
27class VKScheduler; 27class Scheduler;
28 28
29class ComputePipeline { 29class ComputePipeline {
30public: 30public:
31 explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool, 31 explicit ComputePipeline(const Device& device, DescriptorPool& descriptor_pool,
32 VKUpdateDescriptorQueue& update_descriptor_queue, 32 UpdateDescriptorQueue& update_descriptor_queue,
33 Common::ThreadWorker* thread_worker, 33 Common::ThreadWorker* thread_worker,
34 PipelineStatistics* pipeline_statistics, 34 PipelineStatistics* pipeline_statistics,
35 VideoCore::ShaderNotify* shader_notify, const Shader::Info& info, 35 VideoCore::ShaderNotify* shader_notify, const Shader::Info& info,
@@ -42,11 +42,11 @@ public:
42 ComputePipeline(const ComputePipeline&) = delete; 42 ComputePipeline(const ComputePipeline&) = delete;
43 43
44 void Configure(Tegra::Engines::KeplerCompute& kepler_compute, Tegra::MemoryManager& gpu_memory, 44 void Configure(Tegra::Engines::KeplerCompute& kepler_compute, Tegra::MemoryManager& gpu_memory,
45 VKScheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache); 45 Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache);
46 46
47private: 47private:
48 const Device& device; 48 const Device& device;
49 VKUpdateDescriptorQueue& update_descriptor_queue; 49 UpdateDescriptorQueue& update_descriptor_queue;
50 Shader::Info info; 50 Shader::Info info;
51 51
52 VideoCommon::ComputeUniformBufferSizes uniform_buffer_sizes{}; 52 VideoCommon::ComputeUniformBufferSizes uniform_buffer_sizes{};
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
index 7073a874b..c7196b64e 100644
--- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
@@ -121,7 +121,7 @@ vk::DescriptorSets DescriptorAllocator::AllocateDescriptors(size_t count) {
121 throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY); 121 throw vk::Exception(VK_ERROR_OUT_OF_POOL_MEMORY);
122} 122}
123 123
124DescriptorPool::DescriptorPool(const Device& device_, VKScheduler& scheduler) 124DescriptorPool::DescriptorPool(const Device& device_, Scheduler& scheduler)
125 : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()} {} 125 : device{device_}, master_semaphore{scheduler.GetMasterSemaphore()} {}
126 126
127DescriptorPool::~DescriptorPool() = default; 127DescriptorPool::~DescriptorPool() = default;
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.h b/src/video_core/renderer_vulkan/vk_descriptor_pool.h
index 30895f259..bd6696b07 100644
--- a/src/video_core/renderer_vulkan/vk_descriptor_pool.h
+++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.h
@@ -14,7 +14,7 @@
14namespace Vulkan { 14namespace Vulkan {
15 15
16class Device; 16class Device;
17class VKScheduler; 17class Scheduler;
18 18
19struct DescriptorBank; 19struct DescriptorBank;
20 20
@@ -62,7 +62,7 @@ private:
62 62
63class DescriptorPool { 63class DescriptorPool {
64public: 64public:
65 explicit DescriptorPool(const Device& device, VKScheduler& scheduler); 65 explicit DescriptorPool(const Device& device, Scheduler& scheduler);
66 ~DescriptorPool(); 66 ~DescriptorPool();
67 67
68 DescriptorPool& operator=(const DescriptorPool&) = delete; 68 DescriptorPool& operator=(const DescriptorPool&) = delete;
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.cpp b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
index 96335f22c..c249b34d4 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
@@ -11,10 +11,10 @@
11 11
12namespace Vulkan { 12namespace Vulkan {
13 13
14InnerFence::InnerFence(VKScheduler& scheduler_, u32 payload_, bool is_stubbed_) 14InnerFence::InnerFence(Scheduler& scheduler_, u32 payload_, bool is_stubbed_)
15 : FenceBase{payload_, is_stubbed_}, scheduler{scheduler_} {} 15 : FenceBase{payload_, is_stubbed_}, scheduler{scheduler_} {}
16 16
17InnerFence::InnerFence(VKScheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_) 17InnerFence::InnerFence(Scheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_)
18 : FenceBase{address_, payload_, is_stubbed_}, scheduler{scheduler_} {} 18 : FenceBase{address_, payload_, is_stubbed_}, scheduler{scheduler_} {}
19 19
20InnerFence::~InnerFence() = default; 20InnerFence::~InnerFence() = default;
@@ -42,30 +42,29 @@ void InnerFence::Wait() {
42 scheduler.Wait(wait_tick); 42 scheduler.Wait(wait_tick);
43} 43}
44 44
45VKFenceManager::VKFenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_, 45FenceManager::FenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_,
46 TextureCache& texture_cache_, BufferCache& buffer_cache_, 46 TextureCache& texture_cache_, BufferCache& buffer_cache_,
47 VKQueryCache& query_cache_, const Device& device_, 47 QueryCache& query_cache_, const Device& device_, Scheduler& scheduler_)
48 VKScheduler& scheduler_)
49 : GenericFenceManager{rasterizer_, gpu_, texture_cache_, buffer_cache_, query_cache_}, 48 : GenericFenceManager{rasterizer_, gpu_, texture_cache_, buffer_cache_, query_cache_},
50 scheduler{scheduler_} {} 49 scheduler{scheduler_} {}
51 50
52Fence VKFenceManager::CreateFence(u32 value, bool is_stubbed) { 51Fence FenceManager::CreateFence(u32 value, bool is_stubbed) {
53 return std::make_shared<InnerFence>(scheduler, value, is_stubbed); 52 return std::make_shared<InnerFence>(scheduler, value, is_stubbed);
54} 53}
55 54
56Fence VKFenceManager::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) { 55Fence FenceManager::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) {
57 return std::make_shared<InnerFence>(scheduler, addr, value, is_stubbed); 56 return std::make_shared<InnerFence>(scheduler, addr, value, is_stubbed);
58} 57}
59 58
60void VKFenceManager::QueueFence(Fence& fence) { 59void FenceManager::QueueFence(Fence& fence) {
61 fence->Queue(); 60 fence->Queue();
62} 61}
63 62
64bool VKFenceManager::IsFenceSignaled(Fence& fence) const { 63bool FenceManager::IsFenceSignaled(Fence& fence) const {
65 return fence->IsSignaled(); 64 return fence->IsSignaled();
66} 65}
67 66
68void VKFenceManager::WaitFence(Fence& fence) { 67void FenceManager::WaitFence(Fence& fence) {
69 fence->Wait(); 68 fence->Wait();
70} 69}
71 70
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.h b/src/video_core/renderer_vulkan/vk_fence_manager.h
index 04eb575ce..7c0bbd80a 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.h
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.h
@@ -20,13 +20,13 @@ class RasterizerInterface;
20namespace Vulkan { 20namespace Vulkan {
21 21
22class Device; 22class Device;
23class VKQueryCache; 23class QueryCache;
24class VKScheduler; 24class Scheduler;
25 25
26class InnerFence : public VideoCommon::FenceBase { 26class InnerFence : public VideoCommon::FenceBase {
27public: 27public:
28 explicit InnerFence(VKScheduler& scheduler_, u32 payload_, bool is_stubbed_); 28 explicit InnerFence(Scheduler& scheduler_, u32 payload_, bool is_stubbed_);
29 explicit InnerFence(VKScheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_); 29 explicit InnerFence(Scheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_);
30 ~InnerFence(); 30 ~InnerFence();
31 31
32 void Queue(); 32 void Queue();
@@ -36,20 +36,18 @@ public:
36 void Wait(); 36 void Wait();
37 37
38private: 38private:
39 VKScheduler& scheduler; 39 Scheduler& scheduler;
40 u64 wait_tick = 0; 40 u64 wait_tick = 0;
41}; 41};
42using Fence = std::shared_ptr<InnerFence>; 42using Fence = std::shared_ptr<InnerFence>;
43 43
44using GenericFenceManager = 44using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCache, BufferCache, QueryCache>;
45 VideoCommon::FenceManager<Fence, TextureCache, BufferCache, VKQueryCache>;
46 45
47class VKFenceManager final : public GenericFenceManager { 46class FenceManager final : public GenericFenceManager {
48public: 47public:
49 explicit VKFenceManager(VideoCore::RasterizerInterface& rasterizer, Tegra::GPU& gpu, 48 explicit FenceManager(VideoCore::RasterizerInterface& rasterizer, Tegra::GPU& gpu,
50 TextureCache& texture_cache, BufferCache& buffer_cache, 49 TextureCache& texture_cache, BufferCache& buffer_cache,
51 VKQueryCache& query_cache, const Device& device, 50 QueryCache& query_cache, const Device& device, Scheduler& scheduler);
52 VKScheduler& scheduler);
53 51
54protected: 52protected:
55 Fence CreateFence(u32 value, bool is_stubbed) override; 53 Fence CreateFence(u32 value, bool is_stubbed) override;
@@ -59,7 +57,7 @@ protected:
59 void WaitFence(Fence& fence) override; 57 void WaitFence(Fence& fence) override;
60 58
61private: 59private:
62 VKScheduler& scheduler; 60 Scheduler& scheduler;
63}; 61};
64 62
65} // namespace Vulkan 63} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_fsr.cpp b/src/video_core/renderer_vulkan/vk_fsr.cpp
index b563bd51d..dd450169e 100644
--- a/src/video_core/renderer_vulkan/vk_fsr.cpp
+++ b/src/video_core/renderer_vulkan/vk_fsr.cpp
@@ -172,7 +172,7 @@ FSR::FSR(const Device& device_, MemoryAllocator& memory_allocator_, size_t image
172 CreatePipeline(); 172 CreatePipeline();
173} 173}
174 174
175VkImageView FSR::Draw(VKScheduler& scheduler, size_t image_index, VkImageView image_view, 175VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view,
176 VkExtent2D input_image_extent, const Common::Rectangle<int>& crop_rect) { 176 VkExtent2D input_image_extent, const Common::Rectangle<int>& crop_rect) {
177 177
178 UpdateDescriptorSet(image_index, image_view); 178 UpdateDescriptorSet(image_index, image_view);
diff --git a/src/video_core/renderer_vulkan/vk_fsr.h b/src/video_core/renderer_vulkan/vk_fsr.h
index 836592cb3..5d872861f 100644
--- a/src/video_core/renderer_vulkan/vk_fsr.h
+++ b/src/video_core/renderer_vulkan/vk_fsr.h
@@ -10,13 +10,13 @@
10namespace Vulkan { 10namespace Vulkan {
11 11
12class Device; 12class Device;
13class VKScheduler; 13class Scheduler;
14 14
15class FSR { 15class FSR {
16public: 16public:
17 explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count, 17 explicit FSR(const Device& device, MemoryAllocator& memory_allocator, size_t image_count,
18 VkExtent2D output_size); 18 VkExtent2D output_size);
19 VkImageView Draw(VKScheduler& scheduler, size_t image_index, VkImageView image_view, 19 VkImageView Draw(Scheduler& scheduler, size_t image_index, VkImageView image_view,
20 VkExtent2D input_image_extent, const Common::Rectangle<int>& crop_rect); 20 VkExtent2D input_image_extent, const Common::Rectangle<int>& crop_rect);
21 21
22private: 22private:
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 0179679c8..682f05335 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -215,10 +215,10 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m
215} // Anonymous namespace 215} // Anonymous namespace
216 216
217GraphicsPipeline::GraphicsPipeline( 217GraphicsPipeline::GraphicsPipeline(
218 Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, 218 Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, Scheduler& scheduler_,
219 VKScheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_, 219 BufferCache& buffer_cache_, TextureCache& texture_cache_,
220 VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool, 220 VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool,
221 VKUpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread, 221 UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread,
222 PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache, 222 PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
223 const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages, 223 const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages,
224 const std::array<const Shader::Info*, NUM_STAGES>& infos) 224 const std::array<const Shader::Info*, NUM_STAGES>& infos)
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index b3bcb0a2d..e8949a9ab 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -62,8 +62,8 @@ class Device;
62class PipelineStatistics; 62class PipelineStatistics;
63class RenderPassCache; 63class RenderPassCache;
64class RescalingPushConstant; 64class RescalingPushConstant;
65class VKScheduler; 65class Scheduler;
66class VKUpdateDescriptorQueue; 66class UpdateDescriptorQueue;
67 67
68class GraphicsPipeline { 68class GraphicsPipeline {
69 static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; 69 static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
@@ -71,9 +71,9 @@ class GraphicsPipeline {
71public: 71public:
72 explicit GraphicsPipeline( 72 explicit GraphicsPipeline(
73 Tegra::Engines::Maxwell3D& maxwell3d, Tegra::MemoryManager& gpu_memory, 73 Tegra::Engines::Maxwell3D& maxwell3d, Tegra::MemoryManager& gpu_memory,
74 VKScheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache, 74 Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache,
75 VideoCore::ShaderNotify* shader_notify, const Device& device, 75 VideoCore::ShaderNotify* shader_notify, const Device& device,
76 DescriptorPool& descriptor_pool, VKUpdateDescriptorQueue& update_descriptor_queue, 76 DescriptorPool& descriptor_pool, UpdateDescriptorQueue& update_descriptor_queue,
77 Common::ThreadWorker* worker_thread, PipelineStatistics* pipeline_statistics, 77 Common::ThreadWorker* worker_thread, PipelineStatistics* pipeline_statistics,
78 RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key, 78 RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key,
79 std::array<vk::ShaderModule, NUM_STAGES> stages, 79 std::array<vk::ShaderModule, NUM_STAGES> stages,
@@ -125,8 +125,8 @@ private:
125 const Device& device; 125 const Device& device;
126 TextureCache& texture_cache; 126 TextureCache& texture_cache;
127 BufferCache& buffer_cache; 127 BufferCache& buffer_cache;
128 VKScheduler& scheduler; 128 Scheduler& scheduler;
129 VKUpdateDescriptorQueue& update_descriptor_queue; 129 UpdateDescriptorQueue& update_descriptor_queue;
130 130
131 void (*configure_func)(GraphicsPipeline*, bool){}; 131 void (*configure_func)(GraphicsPipeline*, bool){};
132 132
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 5196bdcf2..09e035799 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -174,7 +174,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
174 case Maxwell::TessellationPrimitive::Quads: 174 case Maxwell::TessellationPrimitive::Quads:
175 return Shader::TessPrimitive::Quads; 175 return Shader::TessPrimitive::Quads;
176 } 176 }
177 UNREACHABLE(); 177 ASSERT(false);
178 return Shader::TessPrimitive::Triangles; 178 return Shader::TessPrimitive::Triangles;
179 }(); 179 }();
180 info.tess_spacing = [&] { 180 info.tess_spacing = [&] {
@@ -187,7 +187,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
187 case Maxwell::TessellationSpacing::FractionalEven: 187 case Maxwell::TessellationSpacing::FractionalEven:
188 return Shader::TessSpacing::FractionalEven; 188 return Shader::TessSpacing::FractionalEven;
189 } 189 }
190 UNREACHABLE(); 190 ASSERT(false);
191 return Shader::TessSpacing::Equal; 191 return Shader::TessSpacing::Equal;
192 }(); 192 }();
193 break; 193 break;
@@ -262,8 +262,8 @@ bool GraphicsPipelineCacheKey::operator==(const GraphicsPipelineCacheKey& rhs) c
262PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxwell3D& maxwell3d_, 262PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::Engines::Maxwell3D& maxwell3d_,
263 Tegra::Engines::KeplerCompute& kepler_compute_, 263 Tegra::Engines::KeplerCompute& kepler_compute_,
264 Tegra::MemoryManager& gpu_memory_, const Device& device_, 264 Tegra::MemoryManager& gpu_memory_, const Device& device_,
265 VKScheduler& scheduler_, DescriptorPool& descriptor_pool_, 265 Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
266 VKUpdateDescriptorQueue& update_descriptor_queue_, 266 UpdateDescriptorQueue& update_descriptor_queue_,
267 RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, 267 RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_,
268 TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) 268 TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_)
269 : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_}, 269 : VideoCommon::ShaderCache{rasterizer_, gpu_memory_, maxwell3d_, kepler_compute_},
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index 5d3a9e496..127957dbf 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -81,8 +81,8 @@ class Device;
81class PipelineStatistics; 81class PipelineStatistics;
82class RasterizerVulkan; 82class RasterizerVulkan;
83class RenderPassCache; 83class RenderPassCache;
84class VKScheduler; 84class Scheduler;
85class VKUpdateDescriptorQueue; 85class UpdateDescriptorQueue;
86 86
87using VideoCommon::ShaderInfo; 87using VideoCommon::ShaderInfo;
88 88
@@ -103,8 +103,8 @@ public:
103 explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::Engines::Maxwell3D& maxwell3d, 103 explicit PipelineCache(RasterizerVulkan& rasterizer, Tegra::Engines::Maxwell3D& maxwell3d,
104 Tegra::Engines::KeplerCompute& kepler_compute, 104 Tegra::Engines::KeplerCompute& kepler_compute,
105 Tegra::MemoryManager& gpu_memory, const Device& device, 105 Tegra::MemoryManager& gpu_memory, const Device& device,
106 VKScheduler& scheduler, DescriptorPool& descriptor_pool, 106 Scheduler& scheduler, DescriptorPool& descriptor_pool,
107 VKUpdateDescriptorQueue& update_descriptor_queue, 107 UpdateDescriptorQueue& update_descriptor_queue,
108 RenderPassCache& render_pass_cache, BufferCache& buffer_cache, 108 RenderPassCache& render_pass_cache, BufferCache& buffer_cache,
109 TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); 109 TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_);
110 ~PipelineCache(); 110 ~PipelineCache();
@@ -138,9 +138,9 @@ private:
138 bool build_in_parallel); 138 bool build_in_parallel);
139 139
140 const Device& device; 140 const Device& device;
141 VKScheduler& scheduler; 141 Scheduler& scheduler;
142 DescriptorPool& descriptor_pool; 142 DescriptorPool& descriptor_pool;
143 VKUpdateDescriptorQueue& update_descriptor_queue; 143 UpdateDescriptorQueue& update_descriptor_queue;
144 RenderPassCache& render_pass_cache; 144 RenderPassCache& render_pass_cache;
145 BufferCache& buffer_cache; 145 BufferCache& buffer_cache;
146 TextureCache& texture_cache; 146 TextureCache& texture_cache;
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp
index ea989d3bc..2b859c6b8 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp
@@ -26,7 +26,7 @@ constexpr VkQueryType GetTarget(QueryType type) {
26 26
27} // Anonymous namespace 27} // Anonymous namespace
28 28
29QueryPool::QueryPool(const Device& device_, VKScheduler& scheduler, QueryType type_) 29QueryPool::QueryPool(const Device& device_, Scheduler& scheduler, QueryType type_)
30 : ResourcePool{scheduler.GetMasterSemaphore(), GROW_STEP}, device{device_}, type{type_} {} 30 : ResourcePool{scheduler.GetMasterSemaphore(), GROW_STEP}, device{device_}, type{type_} {}
31 31
32QueryPool::~QueryPool() = default; 32QueryPool::~QueryPool() = default;
@@ -65,15 +65,15 @@ void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) {
65 usage[pool_index * GROW_STEP + static_cast<std::ptrdiff_t>(query.second)] = false; 65 usage[pool_index * GROW_STEP + static_cast<std::ptrdiff_t>(query.second)] = false;
66} 66}
67 67
68VKQueryCache::VKQueryCache(VideoCore::RasterizerInterface& rasterizer_, 68QueryCache::QueryCache(VideoCore::RasterizerInterface& rasterizer_,
69 Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, 69 Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_,
70 const Device& device_, VKScheduler& scheduler_) 70 const Device& device_, Scheduler& scheduler_)
71 : QueryCacheBase{rasterizer_, maxwell3d_, gpu_memory_}, device{device_}, scheduler{scheduler_}, 71 : QueryCacheBase{rasterizer_, maxwell3d_, gpu_memory_}, device{device_}, scheduler{scheduler_},
72 query_pools{ 72 query_pools{
73 QueryPool{device_, scheduler_, QueryType::SamplesPassed}, 73 QueryPool{device_, scheduler_, QueryType::SamplesPassed},
74 } {} 74 } {}
75 75
76VKQueryCache::~VKQueryCache() { 76QueryCache::~QueryCache() {
77 // TODO(Rodrigo): This is a hack to destroy all HostCounter instances before the base class 77 // TODO(Rodrigo): This is a hack to destroy all HostCounter instances before the base class
78 // destructor is called. The query cache should be redesigned to have a proper ownership model 78 // destructor is called. The query cache should be redesigned to have a proper ownership model
79 // instead of using shared pointers. 79 // instead of using shared pointers.
@@ -84,15 +84,15 @@ VKQueryCache::~VKQueryCache() {
84 } 84 }
85} 85}
86 86
87std::pair<VkQueryPool, u32> VKQueryCache::AllocateQuery(QueryType type) { 87std::pair<VkQueryPool, u32> QueryCache::AllocateQuery(QueryType type) {
88 return query_pools[static_cast<std::size_t>(type)].Commit(); 88 return query_pools[static_cast<std::size_t>(type)].Commit();
89} 89}
90 90
91void VKQueryCache::Reserve(QueryType type, std::pair<VkQueryPool, u32> query) { 91void QueryCache::Reserve(QueryType type, std::pair<VkQueryPool, u32> query) {
92 query_pools[static_cast<std::size_t>(type)].Reserve(query); 92 query_pools[static_cast<std::size_t>(type)].Reserve(query);
93} 93}
94 94
95HostCounter::HostCounter(VKQueryCache& cache_, std::shared_ptr<HostCounter> dependency_, 95HostCounter::HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> dependency_,
96 QueryType type_) 96 QueryType type_)
97 : HostCounterBase{std::move(dependency_)}, cache{cache_}, type{type_}, 97 : HostCounterBase{std::move(dependency_)}, cache{cache_}, type{type_},
98 query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} { 98 query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} {
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.h b/src/video_core/renderer_vulkan/vk_query_cache.h
index fc176d907..b0d86c4f8 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.h
+++ b/src/video_core/renderer_vulkan/vk_query_cache.h
@@ -22,14 +22,14 @@ namespace Vulkan {
22class CachedQuery; 22class CachedQuery;
23class Device; 23class Device;
24class HostCounter; 24class HostCounter;
25class VKQueryCache; 25class QueryCache;
26class VKScheduler; 26class Scheduler;
27 27
28using CounterStream = VideoCommon::CounterStreamBase<VKQueryCache, HostCounter>; 28using CounterStream = VideoCommon::CounterStreamBase<QueryCache, HostCounter>;
29 29
30class QueryPool final : public ResourcePool { 30class QueryPool final : public ResourcePool {
31public: 31public:
32 explicit QueryPool(const Device& device, VKScheduler& scheduler, VideoCore::QueryType type); 32 explicit QueryPool(const Device& device, Scheduler& scheduler, VideoCore::QueryType type);
33 ~QueryPool() override; 33 ~QueryPool() override;
34 34
35 std::pair<VkQueryPool, u32> Commit(); 35 std::pair<VkQueryPool, u32> Commit();
@@ -49,13 +49,13 @@ private:
49 std::vector<bool> usage; 49 std::vector<bool> usage;
50}; 50};
51 51
52class VKQueryCache final 52class QueryCache final
53 : public VideoCommon::QueryCacheBase<VKQueryCache, CachedQuery, CounterStream, HostCounter> { 53 : public VideoCommon::QueryCacheBase<QueryCache, CachedQuery, CounterStream, HostCounter> {
54public: 54public:
55 explicit VKQueryCache(VideoCore::RasterizerInterface& rasterizer_, 55 explicit QueryCache(VideoCore::RasterizerInterface& rasterizer_,
56 Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, 56 Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_,
57 const Device& device_, VKScheduler& scheduler_); 57 const Device& device_, Scheduler& scheduler_);
58 ~VKQueryCache(); 58 ~QueryCache();
59 59
60 std::pair<VkQueryPool, u32> AllocateQuery(VideoCore::QueryType type); 60 std::pair<VkQueryPool, u32> AllocateQuery(VideoCore::QueryType type);
61 61
@@ -65,19 +65,19 @@ public:
65 return device; 65 return device;
66 } 66 }
67 67
68 VKScheduler& GetScheduler() const noexcept { 68 Scheduler& GetScheduler() const noexcept {
69 return scheduler; 69 return scheduler;
70 } 70 }
71 71
72private: 72private:
73 const Device& device; 73 const Device& device;
74 VKScheduler& scheduler; 74 Scheduler& scheduler;
75 std::array<QueryPool, VideoCore::NumQueryTypes> query_pools; 75 std::array<QueryPool, VideoCore::NumQueryTypes> query_pools;
76}; 76};
77 77
78class HostCounter final : public VideoCommon::HostCounterBase<VKQueryCache, HostCounter> { 78class HostCounter final : public VideoCommon::HostCounterBase<QueryCache, HostCounter> {
79public: 79public:
80 explicit HostCounter(VKQueryCache& cache_, std::shared_ptr<HostCounter> dependency_, 80 explicit HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> dependency_,
81 VideoCore::QueryType type_); 81 VideoCore::QueryType type_);
82 ~HostCounter(); 82 ~HostCounter();
83 83
@@ -86,7 +86,7 @@ public:
86private: 86private:
87 u64 BlockingQuery() const override; 87 u64 BlockingQuery() const override;
88 88
89 VKQueryCache& cache; 89 QueryCache& cache;
90 const VideoCore::QueryType type; 90 const VideoCore::QueryType type;
91 const std::pair<VkQueryPool, u32> query; 91 const std::pair<VkQueryPool, u32> query;
92 const u64 tick; 92 const u64 tick;
@@ -94,7 +94,7 @@ private:
94 94
95class CachedQuery : public VideoCommon::CachedQueryBase<HostCounter> { 95class CachedQuery : public VideoCommon::CachedQueryBase<HostCounter> {
96public: 96public:
97 explicit CachedQuery(VKQueryCache&, VideoCore::QueryType, VAddr cpu_addr_, u8* host_ptr_) 97 explicit CachedQuery(QueryCache&, VideoCore::QueryType, VAddr cpu_addr_, u8* host_ptr_)
98 : CachedQueryBase{cpu_addr_, host_ptr_} {} 98 : CachedQueryBase{cpu_addr_, host_ptr_} {}
99}; 99};
100 100
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index ce6c853c1..10f9fe7fe 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -142,9 +142,9 @@ DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_instan
142 142
143RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 143RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
144 Tegra::MemoryManager& gpu_memory_, 144 Tegra::MemoryManager& gpu_memory_,
145 Core::Memory::Memory& cpu_memory_, VKScreenInfo& screen_info_, 145 Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_,
146 const Device& device_, MemoryAllocator& memory_allocator_, 146 const Device& device_, MemoryAllocator& memory_allocator_,
147 StateTracker& state_tracker_, VKScheduler& scheduler_) 147 StateTracker& state_tracker_, Scheduler& scheduler_)
148 : RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, 148 : RasterizerAccelerated{cpu_memory_}, gpu{gpu_},
149 gpu_memory{gpu_memory_}, maxwell3d{gpu.Maxwell3D()}, kepler_compute{gpu.KeplerCompute()}, 149 gpu_memory{gpu_memory_}, maxwell3d{gpu.Maxwell3D()}, kepler_compute{gpu.KeplerCompute()},
150 screen_info{screen_info_}, device{device_}, memory_allocator{memory_allocator_}, 150 screen_info{screen_info_}, device{device_}, memory_allocator{memory_allocator_},
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 97eeedd9e..0370ea39b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -38,7 +38,7 @@ class Maxwell3D;
38 38
39namespace Vulkan { 39namespace Vulkan {
40 40
41struct VKScreenInfo; 41struct ScreenInfo;
42 42
43class StateTracker; 43class StateTracker;
44 44
@@ -58,9 +58,9 @@ class RasterizerVulkan final : public VideoCore::RasterizerAccelerated {
58public: 58public:
59 explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 59 explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
60 Tegra::MemoryManager& gpu_memory_, Core::Memory::Memory& cpu_memory_, 60 Tegra::MemoryManager& gpu_memory_, Core::Memory::Memory& cpu_memory_,
61 VKScreenInfo& screen_info_, const Device& device_, 61 ScreenInfo& screen_info_, const Device& device_,
62 MemoryAllocator& memory_allocator_, StateTracker& state_tracker_, 62 MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
63 VKScheduler& scheduler_); 63 Scheduler& scheduler_);
64 ~RasterizerVulkan() override; 64 ~RasterizerVulkan() override;
65 65
66 void Draw(bool is_indexed, bool is_instanced) override; 66 void Draw(bool is_indexed, bool is_instanced) override;
@@ -138,15 +138,15 @@ private:
138 Tegra::Engines::Maxwell3D& maxwell3d; 138 Tegra::Engines::Maxwell3D& maxwell3d;
139 Tegra::Engines::KeplerCompute& kepler_compute; 139 Tegra::Engines::KeplerCompute& kepler_compute;
140 140
141 VKScreenInfo& screen_info; 141 ScreenInfo& screen_info;
142 const Device& device; 142 const Device& device;
143 MemoryAllocator& memory_allocator; 143 MemoryAllocator& memory_allocator;
144 StateTracker& state_tracker; 144 StateTracker& state_tracker;
145 VKScheduler& scheduler; 145 Scheduler& scheduler;
146 146
147 StagingBufferPool staging_pool; 147 StagingBufferPool staging_pool;
148 DescriptorPool descriptor_pool; 148 DescriptorPool descriptor_pool;
149 VKUpdateDescriptorQueue update_descriptor_queue; 149 UpdateDescriptorQueue update_descriptor_queue;
150 BlitImageHelper blit_image; 150 BlitImageHelper blit_image;
151 ASTCDecoderPass astc_decoder_pass; 151 ASTCDecoderPass astc_decoder_pass;
152 RenderPassCache render_pass_cache; 152 RenderPassCache render_pass_cache;
@@ -156,9 +156,9 @@ private:
156 BufferCacheRuntime buffer_cache_runtime; 156 BufferCacheRuntime buffer_cache_runtime;
157 BufferCache buffer_cache; 157 BufferCache buffer_cache;
158 PipelineCache pipeline_cache; 158 PipelineCache pipeline_cache;
159 VKQueryCache query_cache; 159 QueryCache query_cache;
160 AccelerateDMA accelerate_dma; 160 AccelerateDMA accelerate_dma;
161 VKFenceManager fence_manager; 161 FenceManager fence_manager;
162 162
163 vk::Event wfi_event; 163 vk::Event wfi_event;
164 164
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp
index a7261cf97..a331ff37e 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.cpp
+++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp
@@ -21,7 +21,7 @@ namespace Vulkan {
21 21
22MICROPROFILE_DECLARE(Vulkan_WaitForWorker); 22MICROPROFILE_DECLARE(Vulkan_WaitForWorker);
23 23
24void VKScheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf) { 24void Scheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf) {
25 auto command = first; 25 auto command = first;
26 while (command != nullptr) { 26 while (command != nullptr) {
27 auto next = command->GetNext(); 27 auto next = command->GetNext();
@@ -35,7 +35,7 @@ void VKScheduler::CommandChunk::ExecuteAll(vk::CommandBuffer cmdbuf) {
35 last = nullptr; 35 last = nullptr;
36} 36}
37 37
38VKScheduler::VKScheduler(const Device& device_, StateTracker& state_tracker_) 38Scheduler::Scheduler(const Device& device_, StateTracker& state_tracker_)
39 : device{device_}, state_tracker{state_tracker_}, 39 : device{device_}, state_tracker{state_tracker_},
40 master_semaphore{std::make_unique<MasterSemaphore>(device)}, 40 master_semaphore{std::make_unique<MasterSemaphore>(device)},
41 command_pool{std::make_unique<CommandPool>(*master_semaphore, device)} { 41 command_pool{std::make_unique<CommandPool>(*master_semaphore, device)} {
@@ -44,14 +44,14 @@ VKScheduler::VKScheduler(const Device& device_, StateTracker& state_tracker_)
44 worker_thread = std::jthread([this](std::stop_token token) { WorkerThread(token); }); 44 worker_thread = std::jthread([this](std::stop_token token) { WorkerThread(token); });
45} 45}
46 46
47VKScheduler::~VKScheduler() = default; 47Scheduler::~Scheduler() = default;
48 48
49void VKScheduler::Flush(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) { 49void Scheduler::Flush(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) {
50 SubmitExecution(signal_semaphore, wait_semaphore); 50 SubmitExecution(signal_semaphore, wait_semaphore);
51 AllocateNewContext(); 51 AllocateNewContext();
52} 52}
53 53
54void VKScheduler::Finish(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) { 54void Scheduler::Finish(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) {
55 const u64 presubmit_tick = CurrentTick(); 55 const u64 presubmit_tick = CurrentTick();
56 SubmitExecution(signal_semaphore, wait_semaphore); 56 SubmitExecution(signal_semaphore, wait_semaphore);
57 WaitWorker(); 57 WaitWorker();
@@ -59,7 +59,7 @@ void VKScheduler::Finish(VkSemaphore signal_semaphore, VkSemaphore wait_semaphor
59 AllocateNewContext(); 59 AllocateNewContext();
60} 60}
61 61
62void VKScheduler::WaitWorker() { 62void Scheduler::WaitWorker() {
63 MICROPROFILE_SCOPE(Vulkan_WaitForWorker); 63 MICROPROFILE_SCOPE(Vulkan_WaitForWorker);
64 DispatchWork(); 64 DispatchWork();
65 65
@@ -67,7 +67,7 @@ void VKScheduler::WaitWorker() {
67 wait_cv.wait(lock, [this] { return work_queue.empty(); }); 67 wait_cv.wait(lock, [this] { return work_queue.empty(); });
68} 68}
69 69
70void VKScheduler::DispatchWork() { 70void Scheduler::DispatchWork() {
71 if (chunk->Empty()) { 71 if (chunk->Empty()) {
72 return; 72 return;
73 } 73 }
@@ -79,7 +79,7 @@ void VKScheduler::DispatchWork() {
79 AcquireNewChunk(); 79 AcquireNewChunk();
80} 80}
81 81
82void VKScheduler::RequestRenderpass(const Framebuffer* framebuffer) { 82void Scheduler::RequestRenderpass(const Framebuffer* framebuffer) {
83 const VkRenderPass renderpass = framebuffer->RenderPass(); 83 const VkRenderPass renderpass = framebuffer->RenderPass();
84 const VkFramebuffer framebuffer_handle = framebuffer->Handle(); 84 const VkFramebuffer framebuffer_handle = framebuffer->Handle();
85 const VkExtent2D render_area = framebuffer->RenderArea(); 85 const VkExtent2D render_area = framebuffer->RenderArea();
@@ -114,11 +114,11 @@ void VKScheduler::RequestRenderpass(const Framebuffer* framebuffer) {
114 renderpass_image_ranges = framebuffer->ImageRanges(); 114 renderpass_image_ranges = framebuffer->ImageRanges();
115} 115}
116 116
117void VKScheduler::RequestOutsideRenderPassOperationContext() { 117void Scheduler::RequestOutsideRenderPassOperationContext() {
118 EndRenderPass(); 118 EndRenderPass();
119} 119}
120 120
121bool VKScheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) { 121bool Scheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
122 if (state.graphics_pipeline == pipeline) { 122 if (state.graphics_pipeline == pipeline) {
123 return false; 123 return false;
124 } 124 }
@@ -126,7 +126,7 @@ bool VKScheduler::UpdateGraphicsPipeline(GraphicsPipeline* pipeline) {
126 return true; 126 return true;
127} 127}
128 128
129bool VKScheduler::UpdateRescaling(bool is_rescaling) { 129bool Scheduler::UpdateRescaling(bool is_rescaling) {
130 if (state.rescaling_defined && is_rescaling == state.is_rescaling) { 130 if (state.rescaling_defined && is_rescaling == state.is_rescaling) {
131 return false; 131 return false;
132 } 132 }
@@ -135,7 +135,7 @@ bool VKScheduler::UpdateRescaling(bool is_rescaling) {
135 return true; 135 return true;
136} 136}
137 137
138void VKScheduler::WorkerThread(std::stop_token stop_token) { 138void Scheduler::WorkerThread(std::stop_token stop_token) {
139 Common::SetCurrentThreadName("yuzu:VulkanWorker"); 139 Common::SetCurrentThreadName("yuzu:VulkanWorker");
140 do { 140 do {
141 std::unique_ptr<CommandChunk> work; 141 std::unique_ptr<CommandChunk> work;
@@ -161,7 +161,7 @@ void VKScheduler::WorkerThread(std::stop_token stop_token) {
161 } while (!stop_token.stop_requested()); 161 } while (!stop_token.stop_requested());
162} 162}
163 163
164void VKScheduler::AllocateWorkerCommandBuffer() { 164void Scheduler::AllocateWorkerCommandBuffer() {
165 current_cmdbuf = vk::CommandBuffer(command_pool->Commit(), device.GetDispatchLoader()); 165 current_cmdbuf = vk::CommandBuffer(command_pool->Commit(), device.GetDispatchLoader());
166 current_cmdbuf.Begin({ 166 current_cmdbuf.Begin({
167 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 167 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@@ -171,7 +171,7 @@ void VKScheduler::AllocateWorkerCommandBuffer() {
171 }); 171 });
172} 172}
173 173
174void VKScheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) { 174void Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_semaphore) {
175 EndPendingOperations(); 175 EndPendingOperations();
176 InvalidateState(); 176 InvalidateState();
177 177
@@ -225,25 +225,25 @@ void VKScheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait
225 DispatchWork(); 225 DispatchWork();
226} 226}
227 227
228void VKScheduler::AllocateNewContext() { 228void Scheduler::AllocateNewContext() {
229 // Enable counters once again. These are disabled when a command buffer is finished. 229 // Enable counters once again. These are disabled when a command buffer is finished.
230 if (query_cache) { 230 if (query_cache) {
231 query_cache->UpdateCounters(); 231 query_cache->UpdateCounters();
232 } 232 }
233} 233}
234 234
235void VKScheduler::InvalidateState() { 235void Scheduler::InvalidateState() {
236 state.graphics_pipeline = nullptr; 236 state.graphics_pipeline = nullptr;
237 state.rescaling_defined = false; 237 state.rescaling_defined = false;
238 state_tracker.InvalidateCommandBufferState(); 238 state_tracker.InvalidateCommandBufferState();
239} 239}
240 240
241void VKScheduler::EndPendingOperations() { 241void Scheduler::EndPendingOperations() {
242 query_cache->DisableStreams(); 242 query_cache->DisableStreams();
243 EndRenderPass(); 243 EndRenderPass();
244} 244}
245 245
246void VKScheduler::EndRenderPass() { 246void Scheduler::EndRenderPass() {
247 if (!state.renderpass) { 247 if (!state.renderpass) {
248 return; 248 return;
249 } 249 }
@@ -280,7 +280,7 @@ void VKScheduler::EndRenderPass() {
280 num_renderpass_images = 0; 280 num_renderpass_images = 0;
281} 281}
282 282
283void VKScheduler::AcquireNewChunk() { 283void Scheduler::AcquireNewChunk() {
284 std::scoped_lock lock{reserve_mutex}; 284 std::scoped_lock lock{reserve_mutex};
285 if (chunk_reserve.empty()) { 285 if (chunk_reserve.empty()) {
286 chunk = std::make_unique<CommandChunk>(); 286 chunk = std::make_unique<CommandChunk>();
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h
index 7a2200474..c04aad08f 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.h
+++ b/src/video_core/renderer_vulkan/vk_scheduler.h
@@ -22,14 +22,14 @@ class Device;
22class Framebuffer; 22class Framebuffer;
23class GraphicsPipeline; 23class GraphicsPipeline;
24class StateTracker; 24class StateTracker;
25class VKQueryCache; 25class QueryCache;
26 26
27/// The scheduler abstracts command buffer and fence management with an interface that's able to do 27/// The scheduler abstracts command buffer and fence management with an interface that's able to do
28/// OpenGL-like operations on Vulkan command buffers. 28/// OpenGL-like operations on Vulkan command buffers.
29class VKScheduler { 29class Scheduler {
30public: 30public:
31 explicit VKScheduler(const Device& device, StateTracker& state_tracker); 31 explicit Scheduler(const Device& device, StateTracker& state_tracker);
32 ~VKScheduler(); 32 ~Scheduler();
33 33
34 /// Sends the current execution context to the GPU. 34 /// Sends the current execution context to the GPU.
35 void Flush(VkSemaphore signal_semaphore = nullptr, VkSemaphore wait_semaphore = nullptr); 35 void Flush(VkSemaphore signal_semaphore = nullptr, VkSemaphore wait_semaphore = nullptr);
@@ -61,7 +61,7 @@ public:
61 void InvalidateState(); 61 void InvalidateState();
62 62
63 /// Assigns the query cache. 63 /// Assigns the query cache.
64 void SetQueryCache(VKQueryCache& query_cache_) { 64 void SetQueryCache(QueryCache& query_cache_) {
65 query_cache = &query_cache_; 65 query_cache = &query_cache_;
66 } 66 }
67 67
@@ -212,7 +212,7 @@ private:
212 std::unique_ptr<MasterSemaphore> master_semaphore; 212 std::unique_ptr<MasterSemaphore> master_semaphore;
213 std::unique_ptr<CommandPool> command_pool; 213 std::unique_ptr<CommandPool> command_pool;
214 214
215 VKQueryCache* query_cache = nullptr; 215 QueryCache* query_cache = nullptr;
216 216
217 vk::CommandBuffer current_cmdbuf; 217 vk::CommandBuffer current_cmdbuf;
218 218
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index 31ce2f815..06f68d09a 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -85,7 +85,7 @@ size_t Region(size_t iterator) noexcept {
85} // Anonymous namespace 85} // Anonymous namespace
86 86
87StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, 87StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
88 VKScheduler& scheduler_) 88 Scheduler& scheduler_)
89 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} { 89 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} {
90 const vk::Device& dev = device.GetLogical(); 90 const vk::Device& dev = device.GetLogical();
91 stream_buffer = dev.CreateBuffer(VkBufferCreateInfo{ 91 stream_buffer = dev.CreateBuffer(VkBufferCreateInfo{
@@ -263,7 +263,7 @@ StagingBufferPool::StagingBuffersCache& StagingBufferPool::GetCache(MemoryUsage
263 case MemoryUsage::Download: 263 case MemoryUsage::Download:
264 return download_cache; 264 return download_cache;
265 default: 265 default:
266 UNREACHABLE_MSG("Invalid memory usage={}", usage); 266 ASSERT_MSG(false, "Invalid memory usage={}", usage);
267 return upload_cache; 267 return upload_cache;
268 } 268 }
269} 269}
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
index d4d7efa68..91dc84da8 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
@@ -14,7 +14,7 @@
14namespace Vulkan { 14namespace Vulkan {
15 15
16class Device; 16class Device;
17class VKScheduler; 17class Scheduler;
18 18
19struct StagingBufferRef { 19struct StagingBufferRef {
20 VkBuffer buffer; 20 VkBuffer buffer;
@@ -27,7 +27,7 @@ public:
27 static constexpr size_t NUM_SYNCS = 16; 27 static constexpr size_t NUM_SYNCS = 16;
28 28
29 explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator, 29 explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator,
30 VKScheduler& scheduler); 30 Scheduler& scheduler);
31 ~StagingBufferPool(); 31 ~StagingBufferPool();
32 32
33 StagingBufferRef Request(size_t size, MemoryUsage usage); 33 StagingBufferRef Request(size_t size, MemoryUsage usage);
@@ -82,7 +82,7 @@ private:
82 82
83 const Device& device; 83 const Device& device;
84 MemoryAllocator& memory_allocator; 84 MemoryAllocator& memory_allocator;
85 VKScheduler& scheduler; 85 Scheduler& scheduler;
86 86
87 vk::Buffer stream_buffer; 87 vk::Buffer stream_buffer;
88 vk::DeviceMemory stream_memory; 88 vk::DeviceMemory stream_memory;
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 7da81551a..a0c26a72a 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -64,15 +64,15 @@ VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 wi
64 64
65} // Anonymous namespace 65} // Anonymous namespace
66 66
67VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKScheduler& scheduler_, 67Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_, u32 width,
68 u32 width, u32 height, bool srgb) 68 u32 height, bool srgb)
69 : surface{surface_}, device{device_}, scheduler{scheduler_} { 69 : surface{surface_}, device{device_}, scheduler{scheduler_} {
70 Create(width, height, srgb); 70 Create(width, height, srgb);
71} 71}
72 72
73VKSwapchain::~VKSwapchain() = default; 73Swapchain::~Swapchain() = default;
74 74
75void VKSwapchain::Create(u32 width, u32 height, bool srgb) { 75void Swapchain::Create(u32 width, u32 height, bool srgb) {
76 is_outdated = false; 76 is_outdated = false;
77 is_suboptimal = false; 77 is_suboptimal = false;
78 78
@@ -93,7 +93,7 @@ void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
93 resource_ticks.resize(image_count); 93 resource_ticks.resize(image_count);
94} 94}
95 95
96void VKSwapchain::AcquireNextImage() { 96void Swapchain::AcquireNextImage() {
97 const VkResult result = device.GetLogical().AcquireNextImageKHR( 97 const VkResult result = device.GetLogical().AcquireNextImageKHR(
98 *swapchain, std::numeric_limits<u64>::max(), *present_semaphores[frame_index], 98 *swapchain, std::numeric_limits<u64>::max(), *present_semaphores[frame_index],
99 VK_NULL_HANDLE, &image_index); 99 VK_NULL_HANDLE, &image_index);
@@ -114,7 +114,7 @@ void VKSwapchain::AcquireNextImage() {
114 resource_ticks[image_index] = scheduler.CurrentTick(); 114 resource_ticks[image_index] = scheduler.CurrentTick();
115} 115}
116 116
117void VKSwapchain::Present(VkSemaphore render_semaphore) { 117void Swapchain::Present(VkSemaphore render_semaphore) {
118 const auto present_queue{device.GetPresentQueue()}; 118 const auto present_queue{device.GetPresentQueue()};
119 const VkPresentInfoKHR present_info{ 119 const VkPresentInfoKHR present_info{
120 .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 120 .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
@@ -145,8 +145,8 @@ void VKSwapchain::Present(VkSemaphore render_semaphore) {
145 } 145 }
146} 146}
147 147
148void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, 148void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height,
149 u32 height, bool srgb) { 149 bool srgb) {
150 const auto physical_device{device.GetPhysical()}; 150 const auto physical_device{device.GetPhysical()};
151 const auto formats{physical_device.GetSurfaceFormatsKHR(surface)}; 151 const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
152 const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)}; 152 const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)};
@@ -212,13 +212,13 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
212 image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM; 212 image_view_format = srgb ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8A8_UNORM;
213} 213}
214 214
215void VKSwapchain::CreateSemaphores() { 215void Swapchain::CreateSemaphores() {
216 present_semaphores.resize(image_count); 216 present_semaphores.resize(image_count);
217 std::ranges::generate(present_semaphores, 217 std::ranges::generate(present_semaphores,
218 [this] { return device.GetLogical().CreateSemaphore(); }); 218 [this] { return device.GetLogical().CreateSemaphore(); });
219} 219}
220 220
221void VKSwapchain::CreateImageViews() { 221void Swapchain::CreateImageViews() {
222 VkImageViewCreateInfo ci{ 222 VkImageViewCreateInfo ci{
223 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 223 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
224 .pNext = nullptr, 224 .pNext = nullptr,
@@ -250,7 +250,7 @@ void VKSwapchain::CreateImageViews() {
250 } 250 }
251} 251}
252 252
253void VKSwapchain::Destroy() { 253void Swapchain::Destroy() {
254 frame_index = 0; 254 frame_index = 0;
255 present_semaphores.clear(); 255 present_semaphores.clear();
256 framebuffers.clear(); 256 framebuffers.clear();
@@ -258,11 +258,11 @@ void VKSwapchain::Destroy() {
258 swapchain.reset(); 258 swapchain.reset();
259} 259}
260 260
261bool VKSwapchain::HasFpsUnlockChanged() const { 261bool Swapchain::HasFpsUnlockChanged() const {
262 return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue(); 262 return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue();
263} 263}
264 264
265bool VKSwapchain::NeedsPresentModeUpdate() const { 265bool Swapchain::NeedsPresentModeUpdate() const {
266 // Mailbox present mode is the ideal for all scenarios. If it is not available, 266 // Mailbox present mode is the ideal for all scenarios. If it is not available,
267 // A different present mode is needed to support unlocked FPS above the monitor's refresh rate. 267 // A different present mode is needed to support unlocked FPS above the monitor's refresh rate.
268 return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged(); 268 return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged();
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index 6d9d8fec9..111b3902d 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -15,13 +15,13 @@ struct FramebufferLayout;
15namespace Vulkan { 15namespace Vulkan {
16 16
17class Device; 17class Device;
18class VKScheduler; 18class Scheduler;
19 19
20class VKSwapchain { 20class Swapchain {
21public: 21public:
22 explicit VKSwapchain(VkSurfaceKHR surface, const Device& device, VKScheduler& scheduler, 22 explicit Swapchain(VkSurfaceKHR surface, const Device& device, Scheduler& scheduler, u32 width,
23 u32 width, u32 height, bool srgb); 23 u32 height, bool srgb);
24 ~VKSwapchain(); 24 ~Swapchain();
25 25
26 /// Creates (or recreates) the swapchain with a given size. 26 /// Creates (or recreates) the swapchain with a given size.
27 void Create(u32 width, u32 height, bool srgb); 27 void Create(u32 width, u32 height, bool srgb);
@@ -94,7 +94,7 @@ private:
94 94
95 const VkSurfaceKHR surface; 95 const VkSurfaceKHR surface;
96 const Device& device; 96 const Device& device;
97 VKScheduler& scheduler; 97 Scheduler& scheduler;
98 98
99 vk::SwapchainKHR swapchain; 99 vk::SwapchainKHR swapchain;
100 100
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 353594293..ba6d81420 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -70,7 +70,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
70 case ImageType::Buffer: 70 case ImageType::Buffer:
71 break; 71 break;
72 } 72 }
73 UNREACHABLE_MSG("Invalid image type={}", type); 73 ASSERT_MSG(false, "Invalid image type={}", type);
74 return {}; 74 return {};
75} 75}
76 76
@@ -87,7 +87,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
87 case 16: 87 case 16:
88 return VK_SAMPLE_COUNT_16_BIT; 88 return VK_SAMPLE_COUNT_16_BIT;
89 default: 89 default:
90 UNREACHABLE_MSG("Invalid number of samples={}", num_samples); 90 ASSERT_MSG(false, "Invalid number of samples={}", num_samples);
91 return VK_SAMPLE_COUNT_1_BIT; 91 return VK_SAMPLE_COUNT_1_BIT;
92 } 92 }
93} 93}
@@ -107,7 +107,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
107 usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 107 usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
108 break; 108 break;
109 default: 109 default:
110 UNREACHABLE_MSG("Invalid surface type"); 110 ASSERT_MSG(false, "Invalid surface type");
111 } 111 }
112 } 112 }
113 if (info.storage) { 113 if (info.storage) {
@@ -179,7 +179,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
179 case VideoCore::Surface::SurfaceType::DepthStencil: 179 case VideoCore::Surface::SurfaceType::DepthStencil:
180 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 180 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
181 default: 181 default:
182 UNREACHABLE_MSG("Invalid surface type"); 182 ASSERT_MSG(false, "Invalid surface type");
183 return VkImageAspectFlags{}; 183 return VkImageAspectFlags{};
184 } 184 }
185} 185}
@@ -221,7 +221,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
221 case SwizzleSource::OneInt: 221 case SwizzleSource::OneInt:
222 return VK_COMPONENT_SWIZZLE_ONE; 222 return VK_COMPONENT_SWIZZLE_ONE;
223 } 223 }
224 UNREACHABLE_MSG("Invalid swizzle={}", swizzle); 224 ASSERT_MSG(false, "Invalid swizzle={}", swizzle);
225 return VK_COMPONENT_SWIZZLE_ZERO; 225 return VK_COMPONENT_SWIZZLE_ZERO;
226} 226}
227 227
@@ -242,10 +242,10 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
242 case Shader::TextureType::ColorArrayCube: 242 case Shader::TextureType::ColorArrayCube:
243 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; 243 return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
244 case Shader::TextureType::Buffer: 244 case Shader::TextureType::Buffer:
245 UNREACHABLE_MSG("Texture buffers can't be image views"); 245 ASSERT_MSG(false, "Texture buffers can't be image views");
246 return VK_IMAGE_VIEW_TYPE_1D; 246 return VK_IMAGE_VIEW_TYPE_1D;
247 } 247 }
248 UNREACHABLE_MSG("Invalid image view type={}", type); 248 ASSERT_MSG(false, "Invalid image view type={}", type);
249 return VK_IMAGE_VIEW_TYPE_2D; 249 return VK_IMAGE_VIEW_TYPE_2D;
250} 250}
251 251
@@ -269,10 +269,10 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
269 UNIMPLEMENTED_MSG("Rect image view"); 269 UNIMPLEMENTED_MSG("Rect image view");
270 return VK_IMAGE_VIEW_TYPE_2D; 270 return VK_IMAGE_VIEW_TYPE_2D;
271 case VideoCommon::ImageViewType::Buffer: 271 case VideoCommon::ImageViewType::Buffer:
272 UNREACHABLE_MSG("Texture buffers can't be image views"); 272 ASSERT_MSG(false, "Texture buffers can't be image views");
273 return VK_IMAGE_VIEW_TYPE_1D; 273 return VK_IMAGE_VIEW_TYPE_1D;
274 } 274 }
275 UNREACHABLE_MSG("Invalid image view type={}", type); 275 ASSERT_MSG(false, "Invalid image view type={}", type);
276 return VK_IMAGE_VIEW_TYPE_2D; 276 return VK_IMAGE_VIEW_TYPE_2D;
277} 277}
278 278
@@ -644,11 +644,11 @@ struct RangedBarrierRange {
644 case Shader::ImageFormat::R32G32B32A32_UINT: 644 case Shader::ImageFormat::R32G32B32A32_UINT:
645 return VK_FORMAT_R32G32B32A32_UINT; 645 return VK_FORMAT_R32G32B32A32_UINT;
646 } 646 }
647 UNREACHABLE_MSG("Invalid image format={}", format); 647 ASSERT_MSG(false, "Invalid image format={}", format);
648 return VK_FORMAT_R32_UINT; 648 return VK_FORMAT_R32_UINT;
649} 649}
650 650
651void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info, 651void BlitScale(Scheduler& scheduler, VkImage src_image, VkImage dst_image, const ImageInfo& info,
652 VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution, 652 VkImageAspectFlags aspect_mask, const Settings::ResolutionScalingInfo& resolution,
653 bool up_scaling = true) { 653 bool up_scaling = true) {
654 const bool is_2d = info.type == ImageType::e2D; 654 const bool is_2d = info.type == ImageType::e2D;
@@ -788,7 +788,7 @@ void BlitScale(VKScheduler& scheduler, VkImage src_image, VkImage dst_image, con
788} 788}
789} // Anonymous namespace 789} // Anonymous namespace
790 790
791TextureCacheRuntime::TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_, 791TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& scheduler_,
792 MemoryAllocator& memory_allocator_, 792 MemoryAllocator& memory_allocator_,
793 StagingBufferPool& staging_buffer_pool_, 793 StagingBufferPool& staging_buffer_pool_,
794 BlitImageHelper& blit_image_helper_, 794 BlitImageHelper& blit_image_helper_,
@@ -1596,7 +1596,7 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
1596 UNIMPLEMENTED(); 1596 UNIMPLEMENTED();
1597 break; 1597 break;
1598 case VideoCommon::ImageViewType::Buffer: 1598 case VideoCommon::ImageViewType::Buffer:
1599 UNREACHABLE(); 1599 ASSERT(false);
1600 break; 1600 break;
1601 } 1601 }
1602} 1602}
@@ -1822,7 +1822,7 @@ void TextureCacheRuntime::AccelerateImageUpload(
1822 if (IsPixelFormatASTC(image.info.format)) { 1822 if (IsPixelFormatASTC(image.info.format)) {
1823 return astc_decoder_pass.Assemble(image, map, swizzles); 1823 return astc_decoder_pass.Assemble(image, map, swizzles);
1824 } 1824 }
1825 UNREACHABLE(); 1825 ASSERT(false);
1826} 1826}
1827 1827
1828} // namespace Vulkan 1828} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 356dcc703..69f06ee7b 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -33,11 +33,11 @@ class ImageView;
33class Framebuffer; 33class Framebuffer;
34class RenderPassCache; 34class RenderPassCache;
35class StagingBufferPool; 35class StagingBufferPool;
36class VKScheduler; 36class Scheduler;
37 37
38class TextureCacheRuntime { 38class TextureCacheRuntime {
39public: 39public:
40 explicit TextureCacheRuntime(const Device& device_, VKScheduler& scheduler_, 40 explicit TextureCacheRuntime(const Device& device_, Scheduler& scheduler_,
41 MemoryAllocator& memory_allocator_, 41 MemoryAllocator& memory_allocator_,
42 StagingBufferPool& staging_buffer_pool_, 42 StagingBufferPool& staging_buffer_pool_,
43 BlitImageHelper& blit_image_helper_, 43 BlitImageHelper& blit_image_helper_,
@@ -93,7 +93,7 @@ public:
93 [[nodiscard]] VkBuffer GetTemporaryBuffer(size_t needed_size); 93 [[nodiscard]] VkBuffer GetTemporaryBuffer(size_t needed_size);
94 94
95 const Device& device; 95 const Device& device;
96 VKScheduler& scheduler; 96 Scheduler& scheduler;
97 MemoryAllocator& memory_allocator; 97 MemoryAllocator& memory_allocator;
98 StagingBufferPool& staging_buffer_pool; 98 StagingBufferPool& staging_buffer_pool;
99 BlitImageHelper& blit_image_helper; 99 BlitImageHelper& blit_image_helper;
@@ -154,7 +154,7 @@ private:
154 154
155 bool NeedsScaleHelper() const; 155 bool NeedsScaleHelper() const;
156 156
157 VKScheduler* scheduler{}; 157 Scheduler* scheduler{};
158 TextureCacheRuntime* runtime{}; 158 TextureCacheRuntime* runtime{};
159 159
160 vk::Image original_image; 160 vk::Image original_image;
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
index d29540fec..4d4a6753b 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp
@@ -12,18 +12,18 @@
12 12
13namespace Vulkan { 13namespace Vulkan {
14 14
15VKUpdateDescriptorQueue::VKUpdateDescriptorQueue(const Device& device_, VKScheduler& scheduler_) 15UpdateDescriptorQueue::UpdateDescriptorQueue(const Device& device_, Scheduler& scheduler_)
16 : device{device_}, scheduler{scheduler_} { 16 : device{device_}, scheduler{scheduler_} {
17 payload_cursor = payload.data(); 17 payload_cursor = payload.data();
18} 18}
19 19
20VKUpdateDescriptorQueue::~VKUpdateDescriptorQueue() = default; 20UpdateDescriptorQueue::~UpdateDescriptorQueue() = default;
21 21
22void VKUpdateDescriptorQueue::TickFrame() { 22void UpdateDescriptorQueue::TickFrame() {
23 payload_cursor = payload.data(); 23 payload_cursor = payload.data();
24} 24}
25 25
26void VKUpdateDescriptorQueue::Acquire() { 26void UpdateDescriptorQueue::Acquire() {
27 // Minimum number of entries required. 27 // Minimum number of entries required.
28 // This is the maximum number of entries a single draw call migth use. 28 // This is the maximum number of entries a single draw call migth use.
29 static constexpr size_t MIN_ENTRIES = 0x400; 29 static constexpr size_t MIN_ENTRIES = 0x400;
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h
index d8a56b153..625bcc809 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.h
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h
@@ -10,7 +10,7 @@
10namespace Vulkan { 10namespace Vulkan {
11 11
12class Device; 12class Device;
13class VKScheduler; 13class Scheduler;
14 14
15struct DescriptorUpdateEntry { 15struct DescriptorUpdateEntry {
16 struct Empty {}; 16 struct Empty {};
@@ -28,10 +28,10 @@ struct DescriptorUpdateEntry {
28 }; 28 };
29}; 29};
30 30
31class VKUpdateDescriptorQueue final { 31class UpdateDescriptorQueue final {
32public: 32public:
33 explicit VKUpdateDescriptorQueue(const Device& device_, VKScheduler& scheduler_); 33 explicit UpdateDescriptorQueue(const Device& device_, Scheduler& scheduler_);
34 ~VKUpdateDescriptorQueue(); 34 ~UpdateDescriptorQueue();
35 35
36 void TickFrame(); 36 void TickFrame();
37 37
@@ -71,7 +71,7 @@ public:
71 71
72private: 72private:
73 const Device& device; 73 const Device& device;
74 VKScheduler& scheduler; 74 Scheduler& scheduler;
75 75
76 DescriptorUpdateEntry* payload_cursor = nullptr; 76 DescriptorUpdateEntry* payload_cursor = nullptr;
77 const DescriptorUpdateEntry* upload_start = nullptr; 77 const DescriptorUpdateEntry* upload_start = nullptr;
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index d469964f6..c4e923bbf 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -280,7 +280,7 @@ GraphicsEnvironment::GraphicsEnvironment(Tegra::Engines::Maxwell3D& maxwell3d_,
280 stage_index = 4; 280 stage_index = 4;
281 break; 281 break;
282 default: 282 default:
283 UNREACHABLE_MSG("Invalid program={}", program); 283 ASSERT_MSG(false, "Invalid program={}", program);
284 break; 284 break;
285 } 285 }
286 const u64 local_size{sph.LocalMemorySize()}; 286 const u64 local_size{sph.LocalMemorySize()};
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index 5f428d35d..69c1b1e6d 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -29,7 +29,7 @@ SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_t
29 return SurfaceTarget::Texture2DArray; 29 return SurfaceTarget::Texture2DArray;
30 default: 30 default:
31 LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", texture_type); 31 LOG_CRITICAL(HW_GPU, "Unimplemented texture_type={}", texture_type);
32 UNREACHABLE(); 32 ASSERT(false);
33 return SurfaceTarget::Texture2D; 33 return SurfaceTarget::Texture2D;
34 } 34 }
35} 35}
@@ -48,7 +48,7 @@ bool SurfaceTargetIsLayered(SurfaceTarget target) {
48 return true; 48 return true;
49 default: 49 default:
50 LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", target); 50 LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", target);
51 UNREACHABLE(); 51 ASSERT(false);
52 return false; 52 return false;
53 } 53 }
54} 54}
@@ -67,7 +67,7 @@ bool SurfaceTargetIsArray(SurfaceTarget target) {
67 return true; 67 return true;
68 default: 68 default:
69 LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", target); 69 LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", target);
70 UNREACHABLE(); 70 ASSERT(false);
71 return false; 71 return false;
72 } 72 }
73} 73}
diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp
index 802939f6c..6c073ee57 100644
--- a/src/video_core/texture_cache/image_info.cpp
+++ b/src/video_core/texture_cache/image_info.cpp
@@ -94,7 +94,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept {
94 resources.layers = 1; 94 resources.layers = 1;
95 break; 95 break;
96 default: 96 default:
97 UNREACHABLE_MSG("Invalid texture_type={}", static_cast<int>(config.texture_type.Value())); 97 ASSERT_MSG(false, "Invalid texture_type={}", static_cast<int>(config.texture_type.Value()));
98 break; 98 break;
99 } 99 }
100 if (type != ImageType::Linear) { 100 if (type != ImageType::Linear) {
diff --git a/src/video_core/texture_cache/image_view_info.cpp b/src/video_core/texture_cache/image_view_info.cpp
index 0cee5e45f..f47885147 100644
--- a/src/video_core/texture_cache/image_view_info.cpp
+++ b/src/video_core/texture_cache/image_view_info.cpp
@@ -71,7 +71,7 @@ ImageViewInfo::ImageViewInfo(const TICEntry& config, s32 base_layer) noexcept
71 range.extent.layers = config.Depth() * 6; 71 range.extent.layers = config.Depth() * 6;
72 break; 72 break;
73 default: 73 default:
74 UNREACHABLE_MSG("Invalid texture_type={}", static_cast<int>(config.texture_type.Value())); 74 ASSERT_MSG(false, "Invalid texture_type={}", static_cast<int>(config.texture_type.Value()));
75 break; 75 break;
76 } 76 }
77} 77}
diff --git a/src/video_core/texture_cache/samples_helper.h b/src/video_core/texture_cache/samples_helper.h
index 91fec60bd..d552bccf0 100644
--- a/src/video_core/texture_cache/samples_helper.h
+++ b/src/video_core/texture_cache/samples_helper.h
@@ -23,7 +23,7 @@ namespace VideoCommon {
23 case 16: 23 case 16:
24 return {2, 2}; 24 return {2, 2};
25 } 25 }
26 UNREACHABLE_MSG("Invalid number of samples={}", num_samples); 26 ASSERT_MSG(false, "Invalid number of samples={}", num_samples);
27 return {1, 1}; 27 return {1, 1};
28} 28}
29 29
@@ -47,7 +47,7 @@ namespace VideoCommon {
47 case MsaaMode::Msaa4x4: 47 case MsaaMode::Msaa4x4:
48 return 16; 48 return 16;
49 } 49 }
50 UNREACHABLE_MSG("Invalid MSAA mode={}", static_cast<int>(msaa_mode)); 50 ASSERT_MSG(false, "Invalid MSAA mode={}", static_cast<int>(msaa_mode));
51 return 1; 51 return 1;
52} 52}
53 53
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 6622d7818..cf3ca06a6 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1485,14 +1485,14 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
1485 std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>>& selected_page_table) { 1485 std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>>& selected_page_table) {
1486 const auto page_it = selected_page_table.find(page); 1486 const auto page_it = selected_page_table.find(page);
1487 if (page_it == selected_page_table.end()) { 1487 if (page_it == selected_page_table.end()) {
1488 UNREACHABLE_MSG("Unregistering unregistered page=0x{:x}", page << PAGE_BITS); 1488 ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << PAGE_BITS);
1489 return; 1489 return;
1490 } 1490 }
1491 std::vector<ImageId>& image_ids = page_it->second; 1491 std::vector<ImageId>& image_ids = page_it->second;
1492 const auto vector_it = std::ranges::find(image_ids, image_id); 1492 const auto vector_it = std::ranges::find(image_ids, image_id);
1493 if (vector_it == image_ids.end()) { 1493 if (vector_it == image_ids.end()) {
1494 UNREACHABLE_MSG("Unregistering unregistered image in page=0x{:x}", 1494 ASSERT_MSG(false, "Unregistering unregistered image in page=0x{:x}",
1495 page << PAGE_BITS); 1495 page << PAGE_BITS);
1496 return; 1496 return;
1497 } 1497 }
1498 image_ids.erase(vector_it); 1498 image_ids.erase(vector_it);
@@ -1504,14 +1504,14 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
1504 ForEachCPUPage(image.cpu_addr, image.guest_size_bytes, [this, map_id](u64 page) { 1504 ForEachCPUPage(image.cpu_addr, image.guest_size_bytes, [this, map_id](u64 page) {
1505 const auto page_it = page_table.find(page); 1505 const auto page_it = page_table.find(page);
1506 if (page_it == page_table.end()) { 1506 if (page_it == page_table.end()) {
1507 UNREACHABLE_MSG("Unregistering unregistered page=0x{:x}", page << PAGE_BITS); 1507 ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << PAGE_BITS);
1508 return; 1508 return;
1509 } 1509 }
1510 std::vector<ImageMapId>& image_map_ids = page_it->second; 1510 std::vector<ImageMapId>& image_map_ids = page_it->second;
1511 const auto vector_it = std::ranges::find(image_map_ids, map_id); 1511 const auto vector_it = std::ranges::find(image_map_ids, map_id);
1512 if (vector_it == image_map_ids.end()) { 1512 if (vector_it == image_map_ids.end()) {
1513 UNREACHABLE_MSG("Unregistering unregistered image in page=0x{:x}", 1513 ASSERT_MSG(false, "Unregistering unregistered image in page=0x{:x}",
1514 page << PAGE_BITS); 1514 page << PAGE_BITS);
1515 return; 1515 return;
1516 } 1516 }
1517 image_map_ids.erase(vector_it); 1517 image_map_ids.erase(vector_it);
@@ -1532,7 +1532,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
1532 ForEachCPUPage(cpu_addr, size, [this, image_id](u64 page) { 1532 ForEachCPUPage(cpu_addr, size, [this, image_id](u64 page) {
1533 const auto page_it = page_table.find(page); 1533 const auto page_it = page_table.find(page);
1534 if (page_it == page_table.end()) { 1534 if (page_it == page_table.end()) {
1535 UNREACHABLE_MSG("Unregistering unregistered page=0x{:x}", page << PAGE_BITS); 1535 ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << PAGE_BITS);
1536 return; 1536 return;
1537 } 1537 }
1538 std::vector<ImageMapId>& image_map_ids = page_it->second; 1538 std::vector<ImageMapId>& image_map_ids = page_it->second;
@@ -1616,15 +1616,15 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {
1616 const GPUVAddr gpu_addr = image.gpu_addr; 1616 const GPUVAddr gpu_addr = image.gpu_addr;
1617 const auto alloc_it = image_allocs_table.find(gpu_addr); 1617 const auto alloc_it = image_allocs_table.find(gpu_addr);
1618 if (alloc_it == image_allocs_table.end()) { 1618 if (alloc_it == image_allocs_table.end()) {
1619 UNREACHABLE_MSG("Trying to delete an image alloc that does not exist in address 0x{:x}", 1619 ASSERT_MSG(false, "Trying to delete an image alloc that does not exist in address 0x{:x}",
1620 gpu_addr); 1620 gpu_addr);
1621 return; 1621 return;
1622 } 1622 }
1623 const ImageAllocId alloc_id = alloc_it->second; 1623 const ImageAllocId alloc_id = alloc_it->second;
1624 std::vector<ImageId>& alloc_images = slot_image_allocs[alloc_id].images; 1624 std::vector<ImageId>& alloc_images = slot_image_allocs[alloc_id].images;
1625 const auto alloc_image_it = std::ranges::find(alloc_images, image_id); 1625 const auto alloc_image_it = std::ranges::find(alloc_images, image_id);
1626 if (alloc_image_it == alloc_images.end()) { 1626 if (alloc_image_it == alloc_images.end()) {
1627 UNREACHABLE_MSG("Trying to delete an image that does not exist"); 1627 ASSERT_MSG(false, "Trying to delete an image that does not exist");
1628 return; 1628 return;
1629 } 1629 }
1630 ASSERT_MSG(False(image.flags & ImageFlagBits::Tracked), "Image was not untracked"); 1630 ASSERT_MSG(False(image.flags & ImageFlagBits::Tracked), "Image was not untracked");
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index c81343850..9b6b8527b 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -87,7 +87,7 @@ void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixe
87 BPP_CASE(16) 87 BPP_CASE(16)
88#undef BPP_CASE 88#undef BPP_CASE
89 default: 89 default:
90 UNREACHABLE_MSG("Invalid bytes_per_pixel={}", bytes_per_pixel); 90 ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel);
91 } 91 }
92} 92}
93 93
@@ -209,7 +209,7 @@ void SwizzleSubrect(u32 subrect_width, u32 subrect_height, u32 source_pitch, u32
209 BPP_CASE(16) 209 BPP_CASE(16)
210#undef BPP_CASE 210#undef BPP_CASE
211 default: 211 default:
212 UNREACHABLE_MSG("Invalid bytes_per_pixel={}", bytes_per_pixel); 212 ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel);
213 } 213 }
214} 214}
215 215
@@ -230,7 +230,7 @@ void UnswizzleSubrect(u32 line_length_in, u32 line_count, u32 pitch, u32 width,
230 BPP_CASE(16) 230 BPP_CASE(16)
231#undef BPP_CASE 231#undef BPP_CASE
232 default: 232 default:
233 UNREACHABLE_MSG("Invalid bytes_per_pixel={}", bytes_per_pixel); 233 ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel);
234 } 234 }
235} 235}
236 236
@@ -253,7 +253,7 @@ void SwizzleSliceToVoxel(u32 line_length_in, u32 line_count, u32 pitch, u32 widt
253 BPP_CASE(16) 253 BPP_CASE(16)
254#undef BPP_CASE 254#undef BPP_CASE
255 default: 255 default:
256 UNREACHABLE_MSG("Invalid bytes_per_pixel={}", bytes_per_pixel); 256 ASSERT_MSG(false, "Invalid bytes_per_pixel={}", bytes_per_pixel);
257 } 257 }
258} 258}
259 259
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index b3a77e07f..743ac09f6 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -669,17 +669,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
669 const bool is_amd = 669 const bool is_amd =
670 driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE; 670 driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE;
671 if (is_amd) { 671 if (is_amd) {
672 // TODO(lat9nq): Add an upper bound when AMD fixes their VK_KHR_push_descriptor
673 const bool has_broken_push_descriptor = VK_VERSION_MAJOR(properties.driverVersion) == 2 &&
674 VK_VERSION_MINOR(properties.driverVersion) == 0 &&
675 VK_VERSION_PATCH(properties.driverVersion) >= 226;
676 if (khr_push_descriptor && has_broken_push_descriptor) {
677 LOG_WARNING(
678 Render_Vulkan,
679 "Disabling AMD driver 2.0.226 and later from broken VK_KHR_push_descriptor");
680 khr_push_descriptor = false;
681 }
682
683 // AMD drivers need a higher amount of Sets per Pool in certain circunstances like in XC2. 672 // AMD drivers need a higher amount of Sets per Pool in certain circunstances like in XC2.
684 sets_per_pool = 96; 673 sets_per_pool = 96;
685 // Disable VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT on AMD GCN4 and lower as it is broken. 674 // Disable VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT on AMD GCN4 and lower as it is broken.
@@ -738,9 +727,10 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags
738 // The wanted format is not supported by hardware, search for alternatives 727 // The wanted format is not supported by hardware, search for alternatives
739 const VkFormat* alternatives = GetFormatAlternatives(wanted_format); 728 const VkFormat* alternatives = GetFormatAlternatives(wanted_format);
740 if (alternatives == nullptr) { 729 if (alternatives == nullptr) {
741 UNREACHABLE_MSG("Format={} with usage={} and type={} has no defined alternatives and host " 730 ASSERT_MSG(false,
742 "hardware does not support it", 731 "Format={} with usage={} and type={} has no defined alternatives and host "
743 wanted_format, wanted_usage, format_type); 732 "hardware does not support it",
733 wanted_format, wanted_usage, format_type);
744 return wanted_format; 734 return wanted_format;
745 } 735 }
746 736
@@ -756,9 +746,10 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags
756 } 746 }
757 747
758 // No alternatives found, panic 748 // No alternatives found, panic
759 UNREACHABLE_MSG("Format={} with usage={} and type={} is not supported by the host hardware and " 749 ASSERT_MSG(false,
760 "doesn't support any of the alternatives", 750 "Format={} with usage={} and type={} is not supported by the host hardware and "
761 wanted_format, wanted_usage, format_type); 751 "doesn't support any of the alternatives",
752 wanted_format, wanted_usage, format_type);
762 return wanted_format; 753 return wanted_format;
763} 754}
764 755
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index caae6dfdc..6442898bd 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -49,7 +49,7 @@ struct Range {
49 return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | 49 return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
50 VK_MEMORY_PROPERTY_HOST_CACHED_BIT; 50 VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
51 } 51 }
52 UNREACHABLE_MSG("Invalid memory usage={}", usage); 52 ASSERT_MSG(false, "Invalid memory usage={}", usage);
53 return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 53 return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
54} 54}
55 55
@@ -325,7 +325,7 @@ VkMemoryPropertyFlags MemoryAllocator::MemoryPropertyFlags(u32 type_mask,
325 // Remove device local, if it's not supported by the requested resource 325 // Remove device local, if it's not supported by the requested resource
326 return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 326 return MemoryPropertyFlags(type_mask, flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
327 } 327 }
328 UNREACHABLE_MSG("No compatible memory types found"); 328 ASSERT_MSG(false, "No compatible memory types found");
329 return 0; 329 return 0;
330} 330}
331 331
@@ -349,7 +349,7 @@ bool IsHostVisible(MemoryUsage usage) noexcept {
349 case MemoryUsage::Download: 349 case MemoryUsage::Download:
350 return true; 350 return true;
351 } 351 }
352 UNREACHABLE_MSG("Invalid memory usage={}", usage); 352 ASSERT_MSG(false, "Invalid memory usage={}", usage);
353 return false; 353 return false;
354} 354}
355 355
diff --git a/src/web_service/telemetry_json.cpp b/src/web_service/telemetry_json.cpp
index 6215c914f..46faddb61 100644
--- a/src/web_service/telemetry_json.cpp
+++ b/src/web_service/telemetry_json.cpp
@@ -13,8 +13,8 @@ namespace WebService {
13namespace Telemetry = Common::Telemetry; 13namespace Telemetry = Common::Telemetry;
14 14
15struct TelemetryJson::Impl { 15struct TelemetryJson::Impl {
16 Impl(std::string host, std::string username, std::string token) 16 Impl(std::string host_, std::string username_, std::string token_)
17 : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} {} 17 : host{std::move(host_)}, username{std::move(username_)}, token{std::move(token_)} {}
18 18
19 nlohmann::json& TopSection() { 19 nlohmann::json& TopSection() {
20 return sections[static_cast<u8>(Telemetry::FieldType::None)]; 20 return sections[static_cast<u8>(Telemetry::FieldType::None)];
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index 58b0c2f10..dce9772fe 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -30,10 +30,10 @@ constexpr std::array<const char, 1> API_VERSION{'1'};
30constexpr std::size_t TIMEOUT_SECONDS = 30; 30constexpr std::size_t TIMEOUT_SECONDS = 30;
31 31
32struct Client::Impl { 32struct Client::Impl {
33 Impl(std::string host, std::string username, std::string token) 33 Impl(std::string host_, std::string username_, std::string token_)
34 : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} { 34 : host{std::move(host_)}, username{std::move(username_)}, token{std::move(token_)} {
35 std::scoped_lock lock{jwt_cache.mutex}; 35 std::scoped_lock lock{jwt_cache.mutex};
36 if (this->username == jwt_cache.username && this->token == jwt_cache.token) { 36 if (username == jwt_cache.username && token == jwt_cache.token) {
37 jwt = jwt_cache.jwt; 37 jwt = jwt_cache.jwt;
38 } 38 }
39 } 39 }
@@ -69,8 +69,8 @@ struct Client::Impl {
69 */ 69 */
70 WebResult GenericRequest(const std::string& method, const std::string& path, 70 WebResult GenericRequest(const std::string& method, const std::string& path,
71 const std::string& data, const std::string& accept, 71 const std::string& data, const std::string& accept,
72 const std::string& jwt = "", const std::string& username = "", 72 const std::string& jwt_ = "", const std::string& username_ = "",
73 const std::string& token = "") { 73 const std::string& token_ = "") {
74 if (cli == nullptr) { 74 if (cli == nullptr) {
75 cli = std::make_unique<httplib::Client>(host.c_str()); 75 cli = std::make_unique<httplib::Client>(host.c_str());
76 } 76 }
@@ -85,14 +85,14 @@ struct Client::Impl {
85 cli->set_write_timeout(TIMEOUT_SECONDS); 85 cli->set_write_timeout(TIMEOUT_SECONDS);
86 86
87 httplib::Headers params; 87 httplib::Headers params;
88 if (!jwt.empty()) { 88 if (!jwt_.empty()) {
89 params = { 89 params = {
90 {std::string("Authorization"), fmt::format("Bearer {}", jwt)}, 90 {std::string("Authorization"), fmt::format("Bearer {}", jwt_)},
91 }; 91 };
92 } else if (!username.empty()) { 92 } else if (!username_.empty()) {
93 params = { 93 params = {
94 {std::string("x-username"), username}, 94 {std::string("x-username"), username_},
95 {std::string("x-token"), token}, 95 {std::string("x-token"), token_},
96 }; 96 };
97 } 97 }
98 98
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index c924cb0cb..8be311fcb 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -631,7 +631,7 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
631 switch (max_supported_players) { 631 switch (max_supported_players) {
632 case 0: 632 case 0:
633 default: 633 default:
634 UNREACHABLE(); 634 ASSERT(false);
635 return; 635 return;
636 case 1: 636 case 1:
637 ui->widgetSpacer->hide(); 637 ui->widgetSpacer->hide();
diff --git a/src/yuzu/applets/qt_error.cpp b/src/yuzu/applets/qt_error.cpp
index 5bd8d85bb..367d5352d 100644
--- a/src/yuzu/applets/qt_error.cpp
+++ b/src/yuzu/applets/qt_error.cpp
@@ -14,7 +14,7 @@ QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) {
14 14
15QtErrorDisplay::~QtErrorDisplay() = default; 15QtErrorDisplay::~QtErrorDisplay() = default;
16 16
17void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const { 17void QtErrorDisplay::ShowError(Result error, std::function<void()> finished) const {
18 callback = std::move(finished); 18 callback = std::move(finished);
19 emit MainWindowDisplayError( 19 emit MainWindowDisplayError(
20 tr("Error Code: %1-%2 (0x%3)") 20 tr("Error Code: %1-%2 (0x%3)")
@@ -24,7 +24,7 @@ void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished)
24 tr("An error has occurred.\nPlease try again or contact the developer of the software.")); 24 tr("An error has occurred.\nPlease try again or contact the developer of the software."));
25} 25}
26 26
27void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, 27void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
28 std::function<void()> finished) const { 28 std::function<void()> finished) const {
29 callback = std::move(finished); 29 callback = std::move(finished);
30 30
@@ -40,7 +40,7 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon
40 .arg(date_time.toString(QStringLiteral("h:mm:ss A")))); 40 .arg(date_time.toString(QStringLiteral("h:mm:ss A"))));
41} 41}
42 42
43void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_text, 43void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text,
44 std::string fullscreen_text, 44 std::string fullscreen_text,
45 std::function<void()> finished) const { 45 std::function<void()> finished) const {
46 callback = std::move(finished); 46 callback = std::move(finished);
diff --git a/src/yuzu/applets/qt_error.h b/src/yuzu/applets/qt_error.h
index 2d045b4fc..eb4107c7e 100644
--- a/src/yuzu/applets/qt_error.h
+++ b/src/yuzu/applets/qt_error.h
@@ -16,10 +16,10 @@ public:
16 explicit QtErrorDisplay(GMainWindow& parent); 16 explicit QtErrorDisplay(GMainWindow& parent);
17 ~QtErrorDisplay() override; 17 ~QtErrorDisplay() override;
18 18
19 void ShowError(ResultCode error, std::function<void()> finished) const override; 19 void ShowError(Result error, std::function<void()> finished) const override;
20 void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time, 20 void ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
21 std::function<void()> finished) const override; 21 std::function<void()> finished) const override;
22 void ShowCustomErrorText(ResultCode error, std::string dialog_text, std::string fullscreen_text, 22 void ShowCustomErrorText(Result error, std::string dialog_text, std::string fullscreen_text,
23 std::function<void()> finished) const override; 23 std::function<void()> finished) const override;
24 24
25signals: 25signals:
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index bde465485..01acda22b 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -29,6 +29,7 @@
29#include "common/scm_rev.h" 29#include "common/scm_rev.h"
30#include "common/settings.h" 30#include "common/settings.h"
31#include "core/core.h" 31#include "core/core.h"
32#include "core/cpu_manager.h"
32#include "core/frontend/framebuffer_layout.h" 33#include "core/frontend/framebuffer_layout.h"
33#include "input_common/drivers/keyboard.h" 34#include "input_common/drivers/keyboard.h"
34#include "input_common/drivers/mouse.h" 35#include "input_common/drivers/mouse.h"
@@ -73,6 +74,8 @@ void EmuThread::run() {
73 74
74 gpu.ReleaseContext(); 75 gpu.ReleaseContext();
75 76
77 system.GetCpuManager().OnGpuReady();
78
76 // Holds whether the cpu was running during the last iteration, 79 // Holds whether the cpu was running during the last iteration,
77 // so that the DebugModeLeft signal can be emitted before the 80 // so that the DebugModeLeft signal can be emitted before the
78 // next execution step 81 // next execution step
@@ -127,7 +130,7 @@ void EmuThread::run() {
127class OpenGLSharedContext : public Core::Frontend::GraphicsContext { 130class OpenGLSharedContext : public Core::Frontend::GraphicsContext {
128public: 131public:
129 /// Create the original context that should be shared from 132 /// Create the original context that should be shared from
130 explicit OpenGLSharedContext(QSurface* surface) : surface(surface) { 133 explicit OpenGLSharedContext(QSurface* surface_) : surface{surface_} {
131 QSurfaceFormat format; 134 QSurfaceFormat format;
132 format.setVersion(4, 6); 135 format.setVersion(4, 6);
133 format.setProfile(QSurfaceFormat::CompatibilityProfile); 136 format.setProfile(QSurfaceFormat::CompatibilityProfile);
@@ -364,9 +367,9 @@ void GRenderWindow::RestoreGeometry() {
364 QWidget::restoreGeometry(geometry); 367 QWidget::restoreGeometry(geometry);
365} 368}
366 369
367void GRenderWindow::restoreGeometry(const QByteArray& geometry) { 370void GRenderWindow::restoreGeometry(const QByteArray& geometry_) {
368 // Make sure users of this class don't need to deal with backing up the geometry themselves 371 // Make sure users of this class don't need to deal with backing up the geometry themselves
369 QWidget::restoreGeometry(geometry); 372 QWidget::restoreGeometry(geometry_);
370 BackupGeometry(); 373 BackupGeometry();
371} 374}
372 375
@@ -1014,8 +1017,8 @@ QStringList GRenderWindow::GetUnsupportedGLExtensions() const {
1014 return unsupported_ext; 1017 return unsupported_ext;
1015} 1018}
1016 1019
1017void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) { 1020void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread_) {
1018 this->emu_thread = emu_thread; 1021 emu_thread = emu_thread_;
1019} 1022}
1020 1023
1021void GRenderWindow::OnEmulationStopping() { 1024void GRenderWindow::OnEmulationStopping() {
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index d01538039..81fe52c0e 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -56,12 +56,12 @@ public:
56 56
57 /** 57 /**
58 * Sets whether the emulation thread is running or not 58 * Sets whether the emulation thread is running or not
59 * @param running Boolean value, set the emulation thread to running if true 59 * @param running_ Boolean value, set the emulation thread to running if true
60 * @note This function is thread-safe 60 * @note This function is thread-safe
61 */ 61 */
62 void SetRunning(bool running) { 62 void SetRunning(bool running_) {
63 std::unique_lock lock{running_mutex}; 63 std::unique_lock lock{running_mutex};
64 this->running = running; 64 running = running_;
65 lock.unlock(); 65 lock.unlock();
66 running_cv.notify_all(); 66 running_cv.notify_all();
67 if (!running) { 67 if (!running) {
@@ -138,8 +138,8 @@ public:
138 138
139 void BackupGeometry(); 139 void BackupGeometry();
140 void RestoreGeometry(); 140 void RestoreGeometry();
141 void restoreGeometry(const QByteArray& geometry); // overridden 141 void restoreGeometry(const QByteArray& geometry_); // overridden
142 QByteArray saveGeometry(); // overridden 142 QByteArray saveGeometry(); // overridden
143 143
144 qreal windowPixelRatio() const; 144 qreal windowPixelRatio() const;
145 145
@@ -189,7 +189,7 @@ public:
189 void Exit(); 189 void Exit();
190 190
191public slots: 191public slots:
192 void OnEmulationStarting(EmuThread* emu_thread); 192 void OnEmulationStarting(EmuThread* emu_thread_);
193 void OnEmulationStopping(); 193 void OnEmulationStopping();
194 void OnFramebufferSizeChanged(); 194 void OnFramebufferSizeChanged();
195 195
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index b415a1cc4..e99657bd6 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -27,12 +27,11 @@
27#include "yuzu/hotkeys.h" 27#include "yuzu/hotkeys.h"
28#include "yuzu/uisettings.h" 28#include "yuzu/uisettings.h"
29 29
30ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, 30ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
31 InputCommon::InputSubsystem* input_subsystem, 31 InputCommon::InputSubsystem* input_subsystem,
32 Core::System& system_) 32 Core::System& system_)
33 : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, 33 : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
34 registry(registry), system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, 34 system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, this)},
35 this)},
36 cpu_tab{std::make_unique<ConfigureCpu>(system_, this)}, 35 cpu_tab{std::make_unique<ConfigureCpu>(system_, this)},
37 debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)}, 36 debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},
38 filesystem_tab{std::make_unique<ConfigureFilesystem>(this)}, 37 filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 32ddfd4e0..12cf25daf 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -40,7 +40,7 @@ class ConfigureDialog : public QDialog {
40 Q_OBJECT 40 Q_OBJECT
41 41
42public: 42public:
43 explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, 43 explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
44 InputCommon::InputSubsystem* input_subsystem, Core::System& system_); 44 InputCommon::InputSubsystem* input_subsystem, Core::System& system_);
45 ~ConfigureDialog() override; 45 ~ConfigureDialog() override;
46 46
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 1c05dd0f3..f3be9a374 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -264,15 +264,16 @@ QString ConfigureInputPlayer::AnalogToText(const Common::ParamPackage& param,
264 return QObject::tr("[unknown]"); 264 return QObject::tr("[unknown]");
265} 265}
266 266
267ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, 267ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index_,
268 QWidget* bottom_row, 268 QWidget* bottom_row_,
269 InputCommon::InputSubsystem* input_subsystem_, 269 InputCommon::InputSubsystem* input_subsystem_,
270 InputProfiles* profiles_, Core::HID::HIDCore& hid_core_, 270 InputProfiles* profiles_, Core::HID::HIDCore& hid_core_,
271 bool is_powered_on_, bool debug) 271 bool is_powered_on_, bool debug_)
272 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), 272 : QWidget(parent),
273 debug(debug), is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, 273 ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index{player_index_}, debug{debug_},
274 profiles(profiles_), timeout_timer(std::make_unique<QTimer>()), 274 is_powered_on{is_powered_on_}, input_subsystem{input_subsystem_}, profiles(profiles_),
275 poll_timer(std::make_unique<QTimer>()), bottom_row(bottom_row), hid_core{hid_core_} { 275 timeout_timer(std::make_unique<QTimer>()),
276 poll_timer(std::make_unique<QTimer>()), bottom_row{bottom_row_}, hid_core{hid_core_} {
276 if (player_index == 0) { 277 if (player_index == 0) {
277 auto* emulated_controller_p1 = 278 auto* emulated_controller_p1 =
278 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); 279 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
@@ -696,39 +697,38 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
696 UpdateControllerEnabledButtons(); 697 UpdateControllerEnabledButtons();
697 UpdateControllerButtonNames(); 698 UpdateControllerButtonNames();
698 UpdateMotionButtons(); 699 UpdateMotionButtons();
699 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), 700 connect(ui->comboControllerType, qOverload<int>(&QComboBox::currentIndexChanged), [this](int) {
700 [this, player_index](int) { 701 UpdateControllerAvailableButtons();
701 UpdateControllerAvailableButtons(); 702 UpdateControllerEnabledButtons();
702 UpdateControllerEnabledButtons(); 703 UpdateControllerButtonNames();
703 UpdateControllerButtonNames(); 704 UpdateMotionButtons();
704 UpdateMotionButtons(); 705 const Core::HID::NpadStyleIndex type =
705 const Core::HID::NpadStyleIndex type = 706 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex());
706 GetControllerTypeFromIndex(ui->comboControllerType->currentIndex()); 707
707 708 if (player_index == 0) {
708 if (player_index == 0) { 709 auto* emulated_controller_p1 =
709 auto* emulated_controller_p1 = 710 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
710 hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1); 711 auto* emulated_controller_handheld =
711 auto* emulated_controller_handheld = 712 hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
712 hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); 713 bool is_connected = emulated_controller->IsConnected(true);
713 bool is_connected = emulated_controller->IsConnected(true); 714
714 715 emulated_controller_p1->SetNpadStyleIndex(type);
715 emulated_controller_p1->SetNpadStyleIndex(type); 716 emulated_controller_handheld->SetNpadStyleIndex(type);
716 emulated_controller_handheld->SetNpadStyleIndex(type); 717 if (is_connected) {
717 if (is_connected) { 718 if (type == Core::HID::NpadStyleIndex::Handheld) {
718 if (type == Core::HID::NpadStyleIndex::Handheld) { 719 emulated_controller_p1->Disconnect();
719 emulated_controller_p1->Disconnect(); 720 emulated_controller_handheld->Connect(true);
720 emulated_controller_handheld->Connect(true); 721 emulated_controller = emulated_controller_handheld;
721 emulated_controller = emulated_controller_handheld; 722 } else {
722 } else { 723 emulated_controller_handheld->Disconnect();
723 emulated_controller_handheld->Disconnect(); 724 emulated_controller_p1->Connect(true);
724 emulated_controller_p1->Connect(true); 725 emulated_controller = emulated_controller_p1;
725 emulated_controller = emulated_controller_p1;
726 }
727 }
728 ui->controllerFrame->SetController(emulated_controller);
729 } 726 }
730 emulated_controller->SetNpadStyleIndex(type); 727 }
731 }); 728 ui->controllerFrame->SetController(emulated_controller);
729 }
730 emulated_controller->SetNpadStyleIndex(type);
731 });
732 732
733 connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this, 733 connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,
734 &ConfigureInputPlayer::UpdateMappingWithDefaults); 734 &ConfigureInputPlayer::UpdateMappingWithDefaults);
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 54b3fe150..af8343b2e 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -35,10 +35,10 @@
35#include "yuzu/uisettings.h" 35#include "yuzu/uisettings.h"
36#include "yuzu/util/util.h" 36#include "yuzu/util/util.h"
37 37
38ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id, const std::string& file_name, 38ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
39 Core::System& system_) 39 Core::System& system_)
40 : QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()), 40 : QDialog(parent),
41 title_id(title_id), system{system_} { 41 ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_} {
42 const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name)); 42 const auto file_path = std::filesystem::path(Common::FS::ToU8String(file_name));
43 const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()) 43 const auto config_file_name = title_id == 0 ? Common::FS::PathToUTF8String(file_path.filename())
44 : fmt::format("{:016X}", title_id); 44 : fmt::format("{:016X}", title_id);
@@ -116,8 +116,8 @@ void ConfigurePerGame::HandleApplyButtonClicked() {
116 ApplyConfiguration(); 116 ApplyConfiguration();
117} 117}
118 118
119void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file) { 119void ConfigurePerGame::LoadFromFile(FileSys::VirtualFile file_) {
120 this->file = std::move(file); 120 file = std::move(file_);
121 LoadConfiguration(); 121 LoadConfiguration();
122} 122}
123 123
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index e6dc05546..17a98a0f3 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -39,14 +39,14 @@ class ConfigurePerGame : public QDialog {
39 39
40public: 40public:
41 // Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263 41 // Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263
42 explicit ConfigurePerGame(QWidget* parent, u64 title_id, const std::string& file_name, 42 explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
43 Core::System& system_); 43 Core::System& system_);
44 ~ConfigurePerGame() override; 44 ~ConfigurePerGame() override;
45 45
46 /// Save all button configurations to settings file 46 /// Save all button configurations to settings file
47 void ApplyConfiguration(); 47 void ApplyConfiguration();
48 48
49 void LoadFromFile(FileSys::VirtualFile file); 49 void LoadFromFile(FileSys::VirtualFile file_);
50 50
51private: 51private:
52 void changeEvent(QEvent* event) override; 52 void changeEvent(QEvent* event) override;
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 7893a85bb..4906997ab 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -89,8 +89,8 @@ void ConfigurePerGameAddons::ApplyConfiguration() {
89 Settings::values.disabled_addons[title_id] = disabled_addons; 89 Settings::values.disabled_addons[title_id] = disabled_addons;
90} 90}
91 91
92void ConfigurePerGameAddons::LoadFromFile(FileSys::VirtualFile file) { 92void ConfigurePerGameAddons::LoadFromFile(FileSys::VirtualFile file_) {
93 this->file = std::move(file); 93 file = std::move(file_);
94 LoadConfiguration(); 94 LoadConfiguration();
95} 95}
96 96
diff --git a/src/yuzu/configuration/configure_per_game_addons.h b/src/yuzu/configuration/configure_per_game_addons.h
index 24b017494..14690fba8 100644
--- a/src/yuzu/configuration/configure_per_game_addons.h
+++ b/src/yuzu/configuration/configure_per_game_addons.h
@@ -35,7 +35,7 @@ public:
35 /// Save all button configurations to settings file 35 /// Save all button configurations to settings file
36 void ApplyConfiguration(); 36 void ApplyConfiguration();
37 37
38 void LoadFromFile(FileSys::VirtualFile file); 38 void LoadFromFile(FileSys::VirtualFile file_);
39 39
40 void SetTitleId(u64 id); 40 void SetTitleId(u64 id);
41 41
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp
index 4fcc22b7a..688c2dd38 100644
--- a/src/yuzu/configuration/configure_ringcon.cpp
+++ b/src/yuzu/configuration/configure_ringcon.cpp
@@ -165,10 +165,10 @@ ConfigureRingController::ConfigureRingController(QWidget* parent,
165 const std::string invert_str = invert_value ? "+" : "-"; 165 const std::string invert_str = invert_value ? "+" : "-";
166 param.Set("invert_x", invert_str); 166 param.Set("invert_x", invert_str);
167 emulated_device->SetRingParam(param); 167 emulated_device->SetRingParam(param);
168 for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; 168 for (int sub_button_id2 = 0; sub_button_id2 < ANALOG_SUB_BUTTONS_NUM;
169 ++sub_button_id) { 169 ++sub_button_id2) {
170 analog_map_buttons[sub_button_id]->setText( 170 analog_map_buttons[sub_button_id2]->setText(
171 AnalogToText(param, analog_sub_buttons[sub_button_id])); 171 AnalogToText(param, analog_sub_buttons[sub_button_id2]));
172 } 172 }
173 }); 173 });
174 context_menu.exec( 174 context_menu.exec(
diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp
index c17da6fd1..06cc452c3 100644
--- a/src/yuzu/configuration/configure_touch_from_button.cpp
+++ b/src/yuzu/configuration/configure_touch_from_button.cpp
@@ -68,10 +68,10 @@ static QString ButtonToText(const Common::ParamPackage& param) {
68} 68}
69 69
70ConfigureTouchFromButton::ConfigureTouchFromButton( 70ConfigureTouchFromButton::ConfigureTouchFromButton(
71 QWidget* parent, const std::vector<Settings::TouchFromButtonMap>& touch_maps, 71 QWidget* parent, const std::vector<Settings::TouchFromButtonMap>& touch_maps_,
72 InputCommon::InputSubsystem* input_subsystem_, const int default_index) 72 InputCommon::InputSubsystem* input_subsystem_, const int default_index)
73 : QDialog(parent), ui(std::make_unique<Ui::ConfigureTouchFromButton>()), 73 : QDialog(parent), ui(std::make_unique<Ui::ConfigureTouchFromButton>()),
74 touch_maps(touch_maps), input_subsystem{input_subsystem_}, selected_index(default_index), 74 touch_maps{touch_maps_}, input_subsystem{input_subsystem_}, selected_index{default_index},
75 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) { 75 timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
76 ui->setupUi(this); 76 ui->setupUi(this);
77 binding_list_model = new QStandardItemModel(0, 3, this); 77 binding_list_model = new QStandardItemModel(0, 3, this);
diff --git a/src/yuzu/configuration/configure_touch_from_button.h b/src/yuzu/configuration/configure_touch_from_button.h
index e1400481a..b8c55db66 100644
--- a/src/yuzu/configuration/configure_touch_from_button.h
+++ b/src/yuzu/configuration/configure_touch_from_button.h
@@ -37,7 +37,7 @@ class ConfigureTouchFromButton : public QDialog {
37 37
38public: 38public:
39 explicit ConfigureTouchFromButton(QWidget* parent, 39 explicit ConfigureTouchFromButton(QWidget* parent,
40 const std::vector<Settings::TouchFromButtonMap>& touch_maps, 40 const std::vector<Settings::TouchFromButtonMap>& touch_maps_,
41 InputCommon::InputSubsystem* input_subsystem_, 41 InputCommon::InputSubsystem* input_subsystem_,
42 int default_index = 0); 42 int default_index = 0);
43 ~ConfigureTouchFromButton() override; 43 ~ConfigureTouchFromButton() override;
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 8f486a131..0ea31cd33 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -113,9 +113,9 @@ QString WaitTreeText::GetText() const {
113 return text; 113 return text;
114} 114}
115 115
116WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table, 116WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address_, const Kernel::KHandleTable& handle_table,
117 Core::System& system_) 117 Core::System& system_)
118 : mutex_address(mutex_address), system{system_} { 118 : mutex_address{mutex_address_}, system{system_} {
119 mutex_value = system.Memory().Read32(mutex_address); 119 mutex_value = system.Memory().Read32(mutex_address);
120 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); 120 owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask);
121 owner = handle_table.GetObject<Kernel::KThread>(owner_handle).GetPointerUnsafe(); 121 owner = handle_table.GetObject<Kernel::KThread>(owner_handle).GetPointerUnsafe();
@@ -140,8 +140,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() cons
140 return list; 140 return list;
141} 141}
142 142
143WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread, Core::System& system_) 143WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_)
144 : thread(thread), system{system_} {} 144 : thread{thread_}, system{system_} {}
145WaitTreeCallstack::~WaitTreeCallstack() = default; 145WaitTreeCallstack::~WaitTreeCallstack() = default;
146 146
147QString WaitTreeCallstack::GetText() const { 147QString WaitTreeCallstack::GetText() const {
@@ -171,8 +171,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
171} 171}
172 172
173WaitTreeSynchronizationObject::WaitTreeSynchronizationObject( 173WaitTreeSynchronizationObject::WaitTreeSynchronizationObject(
174 const Kernel::KSynchronizationObject& o, Core::System& system_) 174 const Kernel::KSynchronizationObject& object_, Core::System& system_)
175 : object(o), system{system_} {} 175 : object{object_}, system{system_} {}
176WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default; 176WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default;
177 177
178WaitTreeExpandableItem::WaitTreeExpandableItem() = default; 178WaitTreeExpandableItem::WaitTreeExpandableItem() = default;
@@ -380,8 +380,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
380 return list; 380 return list;
381} 381}
382 382
383WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object, Core::System& system_) 383WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_)
384 : WaitTreeSynchronizationObject(object, system_) {} 384 : WaitTreeSynchronizationObject(object_, system_) {}
385WaitTreeEvent::~WaitTreeEvent() = default; 385WaitTreeEvent::~WaitTreeEvent() = default;
386 386
387WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_) 387WaitTreeThreadList::WaitTreeThreadList(std::vector<Kernel::KThread*>&& list, Core::System& system_)
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 4a36dfc48..f21b9f467 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -78,7 +78,7 @@ public:
78class WaitTreeMutexInfo : public WaitTreeExpandableItem { 78class WaitTreeMutexInfo : public WaitTreeExpandableItem {
79 Q_OBJECT 79 Q_OBJECT
80public: 80public:
81 explicit WaitTreeMutexInfo(VAddr mutex_address, const Kernel::KHandleTable& handle_table, 81 explicit WaitTreeMutexInfo(VAddr mutex_address_, const Kernel::KHandleTable& handle_table,
82 Core::System& system_); 82 Core::System& system_);
83 ~WaitTreeMutexInfo() override; 83 ~WaitTreeMutexInfo() override;
84 84
@@ -97,7 +97,7 @@ private:
97class WaitTreeCallstack : public WaitTreeExpandableItem { 97class WaitTreeCallstack : public WaitTreeExpandableItem {
98 Q_OBJECT 98 Q_OBJECT
99public: 99public:
100 explicit WaitTreeCallstack(const Kernel::KThread& thread, Core::System& system_); 100 explicit WaitTreeCallstack(const Kernel::KThread& thread_, Core::System& system_);
101 ~WaitTreeCallstack() override; 101 ~WaitTreeCallstack() override;
102 102
103 QString GetText() const override; 103 QString GetText() const override;
@@ -112,7 +112,7 @@ private:
112class WaitTreeSynchronizationObject : public WaitTreeExpandableItem { 112class WaitTreeSynchronizationObject : public WaitTreeExpandableItem {
113 Q_OBJECT 113 Q_OBJECT
114public: 114public:
115 explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object, 115 explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object_,
116 Core::System& system_); 116 Core::System& system_);
117 ~WaitTreeSynchronizationObject() override; 117 ~WaitTreeSynchronizationObject() override;
118 118
@@ -162,7 +162,7 @@ private:
162class WaitTreeEvent : public WaitTreeSynchronizationObject { 162class WaitTreeEvent : public WaitTreeSynchronizationObject {
163 Q_OBJECT 163 Q_OBJECT
164public: 164public:
165 explicit WaitTreeEvent(const Kernel::KReadableEvent& object, Core::System& system_); 165 explicit WaitTreeEvent(const Kernel::KReadableEvent& object_, Core::System& system_);
166 ~WaitTreeEvent() override; 166 ~WaitTreeEvent() override;
167}; 167};
168 168
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 6321afc83..05d309827 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -28,8 +28,8 @@
28#include "yuzu/uisettings.h" 28#include "yuzu/uisettings.h"
29#include "yuzu/util/controller_navigation.h" 29#include "yuzu/util/controller_navigation.h"
30 30
31GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist, QObject* parent) 31GameListSearchField::KeyReleaseEater::KeyReleaseEater(GameList* gamelist_, QObject* parent)
32 : QObject(parent), gamelist{gamelist} {} 32 : QObject(parent), gamelist{gamelist_} {}
33 33
34// EventFilter in order to process systemkeys while editing the searchfield 34// EventFilter in order to process systemkeys while editing the searchfield
35bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) { 35bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* event) {
@@ -80,9 +80,9 @@ bool GameListSearchField::KeyReleaseEater::eventFilter(QObject* obj, QEvent* eve
80 return QObject::eventFilter(obj, event); 80 return QObject::eventFilter(obj, event);
81} 81}
82 82
83void GameListSearchField::setFilterResult(int visible, int total) { 83void GameListSearchField::setFilterResult(int visible_, int total_) {
84 this->visible = visible; 84 visible = visible_;
85 this->total = total; 85 total = total_;
86 86
87 label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible)); 87 label_filter_result->setText(tr("%1 of %n result(s)", "", total).arg(visible));
88} 88}
@@ -309,9 +309,9 @@ void GameList::OnFilterCloseClicked() {
309 main_window->filterBarSetChecked(false); 309 main_window->filterBarSetChecked(false);
310} 310}
311 311
312GameList::GameList(FileSys::VirtualFilesystem vfs, FileSys::ManualContentProvider* provider, 312GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvider* provider_,
313 Core::System& system_, GMainWindow* parent) 313 Core::System& system_, GMainWindow* parent)
314 : QWidget{parent}, vfs(std::move(vfs)), provider(provider), system{system_} { 314 : QWidget{parent}, vfs{std::move(vfs_)}, provider{provider_}, system{system_} {
315 watcher = new QFileSystemWatcher(this); 315 watcher = new QFileSystemWatcher(this);
316 connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory); 316 connect(watcher, &QFileSystemWatcher::directoryChanged, this, &GameList::RefreshGameDirectory);
317 317
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 464da98ad..bc36d015a 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -67,8 +67,8 @@ public:
67 COLUMN_COUNT, // Number of columns 67 COLUMN_COUNT, // Number of columns
68 }; 68 };
69 69
70 explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs, 70 explicit GameList(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
71 FileSys::ManualContentProvider* provider, Core::System& system_, 71 FileSys::ManualContentProvider* provider_, Core::System& system_,
72 GMainWindow* parent = nullptr); 72 GMainWindow* parent = nullptr);
73 ~GameList() override; 73 ~GameList() override;
74 74
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index f2a986ed8..cd7d63536 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -225,8 +225,8 @@ public:
225 static constexpr int GameDirRole = Qt::UserRole + 2; 225 static constexpr int GameDirRole = Qt::UserRole + 2;
226 226
227 explicit GameListDir(UISettings::GameDir& directory, 227 explicit GameListDir(UISettings::GameDir& directory,
228 GameListItemType dir_type = GameListItemType::CustomDir) 228 GameListItemType dir_type_ = GameListItemType::CustomDir)
229 : dir_type{dir_type} { 229 : dir_type{dir_type_} {
230 setData(type(), TypeRole); 230 setData(type(), TypeRole);
231 231
232 UISettings::GameDir* game_dir = &directory; 232 UISettings::GameDir* game_dir = &directory;
@@ -348,7 +348,7 @@ public:
348 explicit GameListSearchField(GameList* parent = nullptr); 348 explicit GameListSearchField(GameList* parent = nullptr);
349 349
350 QString filterText() const; 350 QString filterText() const;
351 void setFilterResult(int visible, int total); 351 void setFilterResult(int visible_, int total_);
352 352
353 void clear(); 353 void clear();
354 void setFocus(); 354 void setFocus();
@@ -356,7 +356,7 @@ public:
356private: 356private:
357 class KeyReleaseEater : public QObject { 357 class KeyReleaseEater : public QObject {
358 public: 358 public:
359 explicit KeyReleaseEater(GameList* gamelist, QObject* parent = nullptr); 359 explicit KeyReleaseEater(GameList* gamelist_, QObject* parent = nullptr);
360 360
361 private: 361 private:
362 GameList* gamelist = nullptr; 362 GameList* gamelist = nullptr;
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index ca1899b5c..63326968b 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -223,12 +223,12 @@ QList<QStandardItem*> MakeGameListEntry(const std::string& path, const std::stri
223} 223}
224} // Anonymous namespace 224} // Anonymous namespace
225 225
226GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs, 226GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_,
227 FileSys::ManualContentProvider* provider, 227 FileSys::ManualContentProvider* provider_,
228 QVector<UISettings::GameDir>& game_dirs, 228 QVector<UISettings::GameDir>& game_dirs_,
229 const CompatibilityList& compatibility_list, Core::System& system_) 229 const CompatibilityList& compatibility_list_, Core::System& system_)
230 : vfs(std::move(vfs)), provider(provider), game_dirs(game_dirs), 230 : vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_},
231 compatibility_list(compatibility_list), system{system_} {} 231 compatibility_list{compatibility_list_}, system{system_} {}
232 232
233GameListWorker::~GameListWorker() = default; 233GameListWorker::~GameListWorker() = default;
234 234
diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h
index 622d241fb..24a4e92c3 100644
--- a/src/yuzu/game_list_worker.h
+++ b/src/yuzu/game_list_worker.h
@@ -33,10 +33,10 @@ class GameListWorker : public QObject, public QRunnable {
33 Q_OBJECT 33 Q_OBJECT
34 34
35public: 35public:
36 explicit GameListWorker(std::shared_ptr<FileSys::VfsFilesystem> vfs, 36 explicit GameListWorker(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
37 FileSys::ManualContentProvider* provider, 37 FileSys::ManualContentProvider* provider_,
38 QVector<UISettings::GameDir>& game_dirs, 38 QVector<UISettings::GameDir>& game_dirs_,
39 const CompatibilityList& compatibility_list, Core::System& system_); 39 const CompatibilityList& compatibility_list_, Core::System& system_);
40 ~GameListWorker() override; 40 ~GameListWorker() override;
41 41
42 /// Starts the processing of directory tree information. 42 /// Starts the processing of directory tree information.
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 27f23bcb0..b460020b1 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -934,8 +934,7 @@ void GMainWindow::InitializeWidgets() {
934 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan); 934 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan);
935 } else { 935 } else {
936 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); 936 Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL);
937 const auto filter = Settings::values.scaling_filter.GetValue(); 937 if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) {
938 if (filter == Settings::ScalingFilter::Fsr) {
939 Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor); 938 Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor);
940 UpdateFilterText(); 939 UpdateFilterText();
941 } 940 }
@@ -1442,7 +1441,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
1442 } 1441 }
1443 return false; 1442 return false;
1444 } 1443 }
1445 game_path = filename; 1444 current_game_path = filename;
1446 1445
1447 system->TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt"); 1446 system->TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt");
1448 return true; 1447 return true;
@@ -1508,7 +1507,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1508 1507
1509 // Register an ExecuteProgram callback such that Core can execute a sub-program 1508 // Register an ExecuteProgram callback such that Core can execute a sub-program
1510 system->RegisterExecuteProgramCallback( 1509 system->RegisterExecuteProgramCallback(
1511 [this](std::size_t program_index) { render_window->ExecuteProgram(program_index); }); 1510 [this](std::size_t program_index_) { render_window->ExecuteProgram(program_index_); });
1512 1511
1513 // Register an Exit callback such that Core can exit the currently running application. 1512 // Register an Exit callback such that Core can exit the currently running application.
1514 system->RegisterExitCallback([this]() { render_window->Exit(); }); 1513 system->RegisterExitCallback([this]() { render_window->Exit(); });
@@ -1591,6 +1590,7 @@ void GMainWindow::ShutdownGame() {
1591 1590
1592 AllowOSSleep(); 1591 AllowOSSleep();
1593 1592
1593 system->DetachDebugger();
1594 discord_rpc->Pause(); 1594 discord_rpc->Pause();
1595 emu_thread->RequestStop(); 1595 emu_thread->RequestStop();
1596 1596
@@ -1640,7 +1640,7 @@ void GMainWindow::ShutdownGame() {
1640 emu_frametime_label->setVisible(false); 1640 emu_frametime_label->setVisible(false);
1641 renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan); 1641 renderer_status_button->setEnabled(!UISettings::values.has_broken_vulkan);
1642 1642
1643 game_path.clear(); 1643 current_game_path.clear();
1644 1644
1645 // When closing the game, destroy the GLWindow to clear the context after the game is closed 1645 // When closing the game, destroy the GLWindow to clear the context after the game is closed
1646 render_window->ReleaseRenderTarget(); 1646 render_window->ReleaseRenderTarget();
@@ -2559,7 +2559,7 @@ void GMainWindow::OnRestartGame() {
2559 return; 2559 return;
2560 } 2560 }
2561 // Make a copy since BootGame edits game_path 2561 // Make a copy since BootGame edits game_path
2562 BootGame(QString(game_path)); 2562 BootGame(QString(current_game_path));
2563} 2563}
2564 2564
2565void GMainWindow::OnPauseGame() { 2565void GMainWindow::OnPauseGame() {
@@ -2988,7 +2988,7 @@ void GMainWindow::OnToggleAdaptingFilter() {
2988 2988
2989void GMainWindow::OnConfigurePerGame() { 2989void GMainWindow::OnConfigurePerGame() {
2990 const u64 title_id = system->GetCurrentProcessProgramID(); 2990 const u64 title_id = system->GetCurrentProcessProgramID();
2991 OpenPerGameConfiguration(title_id, game_path.toStdString()); 2991 OpenPerGameConfiguration(title_id, current_game_path.toStdString());
2992} 2992}
2993 2993
2994void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) { 2994void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file_name) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 600647015..8cf224c9c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -369,7 +369,7 @@ private:
369 bool emulation_running = false; 369 bool emulation_running = false;
370 std::unique_ptr<EmuThread> emu_thread; 370 std::unique_ptr<EmuThread> emu_thread;
371 // The path to the game currently running 371 // The path to the game currently running
372 QString game_path; 372 QString current_game_path;
373 373
374 bool auto_paused = false; 374 bool auto_paused = false;
375 bool auto_muted = false; 375 bool auto_muted = false;
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index fc16f0f0c..fc4744fb0 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -344,6 +344,8 @@ void Config::ReadValues() {
344 ReadSetting("Debugging", Settings::values.use_debug_asserts); 344 ReadSetting("Debugging", Settings::values.use_debug_asserts);
345 ReadSetting("Debugging", Settings::values.use_auto_stub); 345 ReadSetting("Debugging", Settings::values.use_auto_stub);
346 ReadSetting("Debugging", Settings::values.disable_macro_jit); 346 ReadSetting("Debugging", Settings::values.disable_macro_jit);
347 ReadSetting("Debugging", Settings::values.use_gdbstub);
348 ReadSetting("Debugging", Settings::values.gdbstub_port);
347 349
348 const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); 350 const auto title_list = sdl2_config->Get("AddOns", "title_ids", "");
349 std::stringstream ss(title_list); 351 std::stringstream ss(title_list);
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 39063e32b..a3b8432f5 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -437,6 +437,11 @@ disable_macro_jit=false
437# Presents guest frames as they become available. Experimental. 437# Presents guest frames as they become available. Experimental.
438# false: Disabled (default), true: Enabled 438# false: Disabled (default), true: Enabled
439disable_fps_limit=false 439disable_fps_limit=false
440# Determines whether to enable the GDB stub and wait for the debugger to attach before running.
441# false: Disabled (default), true: Enabled
442use_gdbstub=false
443# The port to use for the GDB server, if it is enabled.
444gdbstub_port=6543
440 445
441[WebService] 446[WebService]
442# Whether or not to enable telemetry 447# Whether or not to enable telemetry
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 71c413e64..8e38724db 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -162,7 +162,15 @@ void EmuWindow_SDL2::WaitEvent() {
162 SDL_Event event; 162 SDL_Event event;
163 163
164 if (!SDL_WaitEvent(&event)) { 164 if (!SDL_WaitEvent(&event)) {
165 LOG_CRITICAL(Frontend, "SDL_WaitEvent failed: {}", SDL_GetError()); 165 const char* error = SDL_GetError();
166 if (!error || strcmp(error, "") == 0) {
167 // https://github.com/libsdl-org/SDL/issues/5780
168 // Sometimes SDL will return without actually having hit an error condition;
169 // just ignore it in this case.
170 return;
171 }
172
173 LOG_CRITICAL(Frontend, "SDL_WaitEvent failed: {}", error);
166 exit(1); 174 exit(1);
167 } 175 }
168 176
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
index 9746585f5..58b885465 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h
@@ -20,7 +20,7 @@ enum class MouseButton;
20 20
21class EmuWindow_SDL2 : public Core::Frontend::EmuWindow { 21class EmuWindow_SDL2 : public Core::Frontend::EmuWindow {
22public: 22public:
23 explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem, Core::System& system_); 23 explicit EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_);
24 ~EmuWindow_SDL2(); 24 ~EmuWindow_SDL2();
25 25
26 /// Whether the window is still open, and a close request hasn't yet been sent 26 /// Whether the window is still open, and a close request hasn't yet been sent
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index 8075c9082..9b660c13c 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -73,9 +73,9 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
73 return unsupported_ext.empty(); 73 return unsupported_ext.empty();
74} 74}
75 75
76EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, 76EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_,
77 Core::System& system_, bool fullscreen) 77 Core::System& system_, bool fullscreen)
78 : EmuWindow_SDL2{input_subsystem, system_} { 78 : EmuWindow_SDL2{input_subsystem_, system_} {
79 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 79 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
80 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); 80 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
81 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); 81 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
index d159166fd..39346e704 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.h
@@ -17,7 +17,7 @@ class InputSubsystem;
17 17
18class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 { 18class EmuWindow_SDL2_GL final : public EmuWindow_SDL2 {
19public: 19public:
20 explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, Core::System& system_, 20 explicit EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_,
21 bool fullscreen); 21 bool fullscreen);
22 ~EmuWindow_SDL2_GL(); 22 ~EmuWindow_SDL2_GL();
23 23
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index d5fe35aa0..65455c86e 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -21,9 +21,9 @@
21#include <SDL.h> 21#include <SDL.h>
22#include <SDL_syswm.h> 22#include <SDL_syswm.h>
23 23
24EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, 24EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_,
25 Core::System& system_, bool fullscreen) 25 Core::System& system_, bool fullscreen)
26 : EmuWindow_SDL2{input_subsystem, system_} { 26 : EmuWindow_SDL2{input_subsystem_, system_} {
27 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, 27 const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name,
28 Common::g_scm_branch, Common::g_scm_desc); 28 Common::g_scm_branch, Common::g_scm_desc);
29 render_window = 29 render_window =
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
index d92e3aaab..e39ad754d 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h
@@ -18,7 +18,7 @@ class InputSubsystem;
18 18
19class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 { 19class EmuWindow_SDL2_VK final : public EmuWindow_SDL2 {
20public: 20public:
21 explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem, Core::System& system, 21 explicit EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsystem_, Core::System& system,
22 bool fullscreen); 22 bool fullscreen);
23 ~EmuWindow_SDL2_VK() override; 23 ~EmuWindow_SDL2_VK() override;
24 24
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index ab12dd15d..cb301e78b 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -21,6 +21,7 @@
21#include "common/string_util.h" 21#include "common/string_util.h"
22#include "common/telemetry.h" 22#include "common/telemetry.h"
23#include "core/core.h" 23#include "core/core.h"
24#include "core/cpu_manager.h"
24#include "core/crypto/key_manager.h" 25#include "core/crypto/key_manager.h"
25#include "core/file_sys/registered_cache.h" 26#include "core/file_sys/registered_cache.h"
26#include "core/file_sys/vfs_real.h" 27#include "core/file_sys/vfs_real.h"
@@ -138,6 +139,12 @@ int main(int argc, char** argv) {
138 139
139 Config config{config_path}; 140 Config config{config_path};
140 141
142 // apply the log_filter setting
143 // the logger was initialized before and doesn't pick up the filter on its own
144 Common::Log::Filter filter;
145 filter.ParseFilterString(Settings::values.log_filter.GetValue());
146 Common::Log::SetGlobalFilter(filter);
147
141 if (!program_args.empty()) { 148 if (!program_args.empty()) {
142 Settings::values.program_args = program_args; 149 Settings::values.program_args = program_args;
143 } 150 }
@@ -210,6 +217,7 @@ int main(int argc, char** argv) {
210 217
211 // Core is loaded, start the GPU (makes the GPU contexts current to this thread) 218 // Core is loaded, start the GPU (makes the GPU contexts current to this thread)
212 system.GPU().Start(); 219 system.GPU().Start();
220 system.GetCpuManager().OnGpuReady();
213 221
214 if (Settings::values.use_disk_shader_cache.GetValue()) { 222 if (Settings::values.use_disk_shader_cache.GetValue()) {
215 system.Renderer().ReadRasterizer()->LoadDiskResources( 223 system.Renderer().ReadRasterizer()->LoadDiskResources(
@@ -217,10 +225,19 @@ int main(int argc, char** argv) {
217 [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); 225 [](VideoCore::LoadCallbackStage, size_t value, size_t total) {});
218 } 226 }
219 227
228 system.RegisterExitCallback([&] {
229 // Just exit right away.
230 exit(0);
231 });
232
220 void(system.Run()); 233 void(system.Run());
234 if (system.DebuggerEnabled()) {
235 system.InitializeDebugger();
236 }
221 while (emu_window->IsOpen()) { 237 while (emu_window->IsOpen()) {
222 emu_window->WaitEvent(); 238 emu_window->WaitEvent();
223 } 239 }
240 system.DetachDebugger();
224 void(system.Pause()); 241 void(system.Pause());
225 system.Shutdown(); 242 system.Shutdown();
226 243