summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--dist/icons/controller/applet_pro_controller_dark_disabled.pngbin4477 -> 2712 bytes
-rw-r--r--dist/icons/controller/applet_pro_controller_disabled.pngbin4173 -> 2630 bytes
-rw-r--r--dist/icons/controller/applet_pro_controller_midnight_disabled.pngbin4459 -> 2774 bytes
-rw-r--r--dist/icons/overlay/button_A.pngbin3494 -> 1647 bytes
-rw-r--r--dist/icons/overlay/button_B.pngbin3375 -> 1534 bytes
-rw-r--r--dist/icons/overlay/button_X.pngbin3968 -> 1748 bytes
-rw-r--r--dist/icons/overlay/button_Y.pngbin3337 -> 1504 bytes
-rw-r--r--dist/icons/overlay/button_press_stick.pngbin5225 -> 2477 bytes
-rw-r--r--dist/icons/overlay/controller_dual_joycon.pngbin7312 -> 3475 bytes
-rw-r--r--dist/icons/overlay/controller_dual_joycon_dark.pngbin5889 -> 3107 bytes
-rw-r--r--dist/icons/overlay/controller_handheld.pngbin4645 -> 2250 bytes
-rw-r--r--dist/icons/overlay/controller_handheld_dark.pngbin3745 -> 2000 bytes
-rw-r--r--dist/icons/overlay/controller_pro.pngbin9493 -> 4531 bytes
-rw-r--r--dist/icons/overlay/controller_pro_dark.pngbin7488 -> 4531 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left.pngbin7489 -> 3605 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_dark.pngbin6768 -> 3447 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_left_y_dark.pngbin2639 -> 1035 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_right.pngbin7497 -> 3603 bytes
-rw-r--r--dist/icons/overlay/controller_single_joycon_right_dark.pngbin6729 -> 3406 bytes
-rw-r--r--dist/icons/overlay/osk_button_backspace.pngbin2919 -> 1272 bytes
-rw-r--r--dist/icons/overlay/osk_button_backspace_dark.pngbin2958 -> 1262 bytes
-rw-r--r--dist/languages/uk.ts7321
-rw-r--r--dist/qt_themes/colorful/icons/48x48/bad_folder.pngbin15494 -> 528 bytes
-rw-r--r--dist/qt_themes/default/icons/256x256/plus_folder.pngbin3521 -> 1948 bytes
-rw-r--r--dist/qt_themes/default/icons/256x256/yuzu.pngbin6751 -> 4425 bytes
-rw-r--r--dist/qt_themes/qdarkstyle/icons/256x256/plus_folder.pngbin3931 -> 1924 bytes
-rw-r--r--src/CMakeLists.txt33
-rw-r--r--src/audio_core/CMakeLists.txt11
-rw-r--r--src/audio_core/in/audio_in_system.cpp2
-rw-r--r--src/audio_core/in/audio_in_system.h2
-rw-r--r--src/audio_core/out/audio_out_system.cpp4
-rw-r--r--src/audio_core/out/audio_out_system.h4
-rw-r--r--src/audio_core/renderer/behavior/info_updater.cpp2
-rw-r--r--src/audio_core/renderer/command/effect/biquad_filter.cpp2
-rw-r--r--src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp2
-rw-r--r--src/audio_core/renderer/system.cpp85
-rw-r--r--src/audio_core/renderer/system.h16
-rw-r--r--src/audio_core/renderer/voice/voice_context.cpp4
-rw-r--r--src/common/CMakeLists.txt7
-rw-r--r--src/common/bit_field.h15
-rw-r--r--src/common/bounded_threadsafe_queue.h9
-rw-r--r--src/common/concepts.h24
-rw-r--r--src/common/fixed_point.h187
-rw-r--r--src/common/fs/file.h12
-rw-r--r--src/common/input.h5
-rw-r--r--src/core/CMakeLists.txt10
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp2
-rw-r--r--src/core/core.cpp10
-rw-r--r--src/core/file_sys/card_image.cpp4
-rw-r--r--src/core/file_sys/control_metadata.cpp43
-rw-r--r--src/core/file_sys/control_metadata.h6
-rw-r--r--src/core/file_sys/program_metadata.cpp2
-rw-r--r--src/core/hid/emulated_controller.cpp68
-rw-r--r--src/core/hid/emulated_controller.h5
-rw-r--r--src/core/hle/ipc_helpers.h15
-rw-r--r--src/core/hle/kernel/global_scheduler_context.cpp22
-rw-r--r--src/core/hle/kernel/global_scheduler_context.h8
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp110
-rw-r--r--src/core/hle/kernel/hle_ipc.h11
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp2
-rw-r--r--src/core/hle/kernel/k_client_session.cpp15
-rw-r--r--src/core/hle/kernel/k_linked_list.h1
-rw-r--r--src/core/hle/kernel/k_page_buffer.h1
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp26
-rw-r--r--src/core/hle/kernel/k_server_session.cpp232
-rw-r--r--src/core/hle/kernel/k_server_session.h41
-rw-r--r--src/core/hle/kernel/k_session_request.cpp61
-rw-r--r--src/core/hle/kernel/k_session_request.h306
-rw-r--r--src/core/hle/kernel/k_shared_memory_info.h3
-rw-r--r--src/core/hle/kernel/k_thread.cpp40
-rw-r--r--src/core/hle/kernel/k_thread.h8
-rw-r--r--src/core/hle/kernel/k_thread_local_page.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp12
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/slab_helpers.h2
-rw-r--r--src/core/hle/kernel/svc.cpp4
-rw-r--r--src/core/hle/service/acc/acc.cpp34
-rw-r--r--src/core/hle/service/acc/acc.h1
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp2
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp25
-rw-r--r--src/core/hle/service/acc/profile_manager.h3
-rw-r--r--src/core/hle/service/am/am.cpp13
-rw-r--r--src/core/hle/service/am/am.h1
-rw-r--r--src/core/hle/service/am/applets/applets.h2
-rw-r--r--src/core/hle/service/audio/audctl.cpp16
-rw-r--r--src/core/hle/service/audio/audin_u.cpp2
-rw-r--r--src/core/hle/service/audio/audout_u.cpp2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp26
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp29
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.cpp8
-rw-r--r--src/core/hle/service/nfp/amiibo_crypto.h3
-rw-r--r--src/core/hle/service/nfp/nfp_device.cpp9
-rw-r--r--src/core/hle/service/nfp/nfp_device.h1
-rw-r--r--src/core/hle/service/nfp/nfp_types.h5
-rw-r--r--src/core/hle/service/nfp/nfp_user.cpp3
-rw-r--r--src/core/hle/service/nfp/nfp_user.h8
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp5
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.h1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp10
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h6
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue_producer.cpp7
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp25
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h7
-rw-r--r--src/core/hle/service/service.cpp4
-rw-r--r--src/core/hle/service/service.h2
-rw-r--r--src/core/hle/service/sm/sm.cpp8
-rw-r--r--src/core/hle/service/sm/sm_controller.cpp38
-rw-r--r--src/core/hle/service/vi/display/vi_display.h6
-rw-r--r--src/core/hle/service/vi/vi.cpp8
-rw-r--r--src/core/memory.cpp37
-rw-r--r--src/input_common/CMakeLists.txt9
-rw-r--r--src/input_common/drivers/gc_adapter.cpp6
-rw-r--r--src/input_common/drivers/gc_adapter.h4
-rw-r--r--src/input_common/drivers/sdl_driver.cpp68
-rw-r--r--src/input_common/drivers/sdl_driver.h4
-rw-r--r--src/input_common/input_engine.h7
-rw-r--r--src/input_common/input_poller.cpp24
-rw-r--r--src/shader_recompiler/CMakeLists.txt14
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp4
-rw-r--r--src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp4
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp5
-rw-r--r--src/shader_recompiler/frontend/ir/value.h4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.cpp47
-rw-r--r--src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp98
-rw-r--r--src/shader_recompiler/runtime_info.h2
-rw-r--r--src/shader_recompiler/shader_info.h3
-rw-r--r--src/tests/video_core/buffer_base.cpp2
-rw-r--r--src/video_core/CMakeLists.txt8
-rw-r--r--src/video_core/engines/maxwell_3d.cpp285
-rw-r--r--src/video_core/engines/maxwell_3d.h48
-rw-r--r--src/video_core/engines/puller.cpp5
-rw-r--r--src/video_core/macro/macro_hle.cpp47
-rw-r--r--src/video_core/macro/macro_interpreter.cpp2
-rw-r--r--src/video_core/macro/macro_jit_x64.cpp2
-rw-r--r--src/video_core/memory_manager.cpp4
-rw-r--r--src/video_core/rasterizer_interface.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp17
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp47
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_scheduler.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp12
-rw-r--r--src/video_core/texture_cache/format_lookup_table.cpp2
-rw-r--r--src/video_core/texture_cache/texture_cache.h8
-rw-r--r--src/video_core/textures/astc.cpp4
-rw-r--r--src/video_core/textures/decoders.cpp2
-rw-r--r--src/yuzu/applets/qt_controller.ui2
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_ui.cpp3
-rw-r--r--src/yuzu/configuration/configure_ui.ui7
-rw-r--r--src/yuzu/game_list.cpp2
-rw-r--r--src/yuzu/main.ui1
-rw-r--r--src/yuzu/multiplayer/state.cpp2
-rw-r--r--src/yuzu/startup_checks.cpp17
-rw-r--r--src/yuzu/uisettings.h3
160 files changed, 8954 insertions, 1087 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 957df54f5..b625743ea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -541,9 +541,9 @@ add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
541# Adjustments for MSVC + Ninja 541# Adjustments for MSVC + Ninja
542if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja") 542if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
543 add_compile_options( 543 add_compile_options(
544 /wd4711 # function 'function' selected for automatic inline expansion
545 /wd4464 # relative include path contains '..' 544 /wd4464 # relative include path contains '..'
546 /wd4820 # 'identifier1': '4' bytes padding added after data member 'identifier2' 545 /wd4711 # function 'function' selected for automatic inline expansion
546 /wd4820 # 'bytes' bytes padding added after construct 'member_name'
547 ) 547 )
548endif() 548endif()
549 549
diff --git a/dist/icons/controller/applet_pro_controller_dark_disabled.png b/dist/icons/controller/applet_pro_controller_dark_disabled.png
index 416e1e2fb..d45f91db5 100644
--- a/dist/icons/controller/applet_pro_controller_dark_disabled.png
+++ b/dist/icons/controller/applet_pro_controller_dark_disabled.png
Binary files differ
diff --git a/dist/icons/controller/applet_pro_controller_disabled.png b/dist/icons/controller/applet_pro_controller_disabled.png
index 72a549ea9..8c6bcd308 100644
--- a/dist/icons/controller/applet_pro_controller_disabled.png
+++ b/dist/icons/controller/applet_pro_controller_disabled.png
Binary files differ
diff --git a/dist/icons/controller/applet_pro_controller_midnight_disabled.png b/dist/icons/controller/applet_pro_controller_midnight_disabled.png
index 2907f3be4..d27dbfc66 100644
--- a/dist/icons/controller/applet_pro_controller_midnight_disabled.png
+++ b/dist/icons/controller/applet_pro_controller_midnight_disabled.png
Binary files differ
diff --git a/dist/icons/overlay/button_A.png b/dist/icons/overlay/button_A.png
index fd90f8b42..aafafecff 100644
--- a/dist/icons/overlay/button_A.png
+++ b/dist/icons/overlay/button_A.png
Binary files differ
diff --git a/dist/icons/overlay/button_B.png b/dist/icons/overlay/button_B.png
index e8927addc..4a19d8176 100644
--- a/dist/icons/overlay/button_B.png
+++ b/dist/icons/overlay/button_B.png
Binary files differ
diff --git a/dist/icons/overlay/button_X.png b/dist/icons/overlay/button_X.png
index fe70fb685..f50a53974 100644
--- a/dist/icons/overlay/button_X.png
+++ b/dist/icons/overlay/button_X.png
Binary files differ
diff --git a/dist/icons/overlay/button_Y.png b/dist/icons/overlay/button_Y.png
index ca0de569d..435ec30d5 100644
--- a/dist/icons/overlay/button_Y.png
+++ b/dist/icons/overlay/button_Y.png
Binary files differ
diff --git a/dist/icons/overlay/button_press_stick.png b/dist/icons/overlay/button_press_stick.png
index 6d0254d50..13bbff9ef 100644
--- a/dist/icons/overlay/button_press_stick.png
+++ b/dist/icons/overlay/button_press_stick.png
Binary files differ
diff --git a/dist/icons/overlay/controller_dual_joycon.png b/dist/icons/overlay/controller_dual_joycon.png
index 8e8b5ad41..286b8d8aa 100644
--- a/dist/icons/overlay/controller_dual_joycon.png
+++ b/dist/icons/overlay/controller_dual_joycon.png
Binary files differ
diff --git a/dist/icons/overlay/controller_dual_joycon_dark.png b/dist/icons/overlay/controller_dual_joycon_dark.png
index 63e03eb4e..3fba54618 100644
--- a/dist/icons/overlay/controller_dual_joycon_dark.png
+++ b/dist/icons/overlay/controller_dual_joycon_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_handheld.png b/dist/icons/overlay/controller_handheld.png
index deb375011..38c38c0da 100644
--- a/dist/icons/overlay/controller_handheld.png
+++ b/dist/icons/overlay/controller_handheld.png
Binary files differ
diff --git a/dist/icons/overlay/controller_handheld_dark.png b/dist/icons/overlay/controller_handheld_dark.png
index 1f5317aa0..2b73b812e 100644
--- a/dist/icons/overlay/controller_handheld_dark.png
+++ b/dist/icons/overlay/controller_handheld_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_pro.png b/dist/icons/overlay/controller_pro.png
index 67cf86d5c..78273fe57 100644
--- a/dist/icons/overlay/controller_pro.png
+++ b/dist/icons/overlay/controller_pro.png
Binary files differ
diff --git a/dist/icons/overlay/controller_pro_dark.png b/dist/icons/overlay/controller_pro_dark.png
index 7be655b96..8d261f1f7 100644
--- a/dist/icons/overlay/controller_pro_dark.png
+++ b/dist/icons/overlay/controller_pro_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left.png b/dist/icons/overlay/controller_single_joycon_left.png
index 340ddc71b..34f0a424e 100644
--- a/dist/icons/overlay/controller_single_joycon_left.png
+++ b/dist/icons/overlay/controller_single_joycon_left.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_dark.png b/dist/icons/overlay/controller_single_joycon_left_dark.png
index 24ed2c44c..740647a2b 100644
--- a/dist/icons/overlay/controller_single_joycon_left_dark.png
+++ b/dist/icons/overlay/controller_single_joycon_left_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_left_y_dark.png b/dist/icons/overlay/controller_single_joycon_left_y_dark.png
index fdf177c12..725bec62d 100644
--- a/dist/icons/overlay/controller_single_joycon_left_y_dark.png
+++ b/dist/icons/overlay/controller_single_joycon_left_y_dark.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_right.png b/dist/icons/overlay/controller_single_joycon_right.png
index 5b8fc0eff..65e7686ca 100644
--- a/dist/icons/overlay/controller_single_joycon_right.png
+++ b/dist/icons/overlay/controller_single_joycon_right.png
Binary files differ
diff --git a/dist/icons/overlay/controller_single_joycon_right_dark.png b/dist/icons/overlay/controller_single_joycon_right_dark.png
index afa80e6ef..81cb94a1d 100644
--- a/dist/icons/overlay/controller_single_joycon_right_dark.png
+++ b/dist/icons/overlay/controller_single_joycon_right_dark.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_backspace.png b/dist/icons/overlay/osk_button_backspace.png
index 4ad284720..b7dc33228 100644
--- a/dist/icons/overlay/osk_button_backspace.png
+++ b/dist/icons/overlay/osk_button_backspace.png
Binary files differ
diff --git a/dist/icons/overlay/osk_button_backspace_dark.png b/dist/icons/overlay/osk_button_backspace_dark.png
index 19ac8847e..542038bef 100644
--- a/dist/icons/overlay/osk_button_backspace_dark.png
+++ b/dist/icons/overlay/osk_button_backspace_dark.png
Binary files differ
diff --git a/dist/languages/uk.ts b/dist/languages/uk.ts
new file mode 100644
index 000000000..66a3ac96e
--- /dev/null
+++ b/dist/languages/uk.ts
@@ -0,0 +1,7321 @@
1<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="uk" sourcelanguage="en_US">
2<context>
3 <name>AboutDialog</name>
4 <message>
5 <location filename="../../src/yuzu/aboutdialog.ui" line="14"/>
6 <source>About yuzu</source>
7 <translation>Про yuzu</translation>
8 </message>
9 <message>
10 <location filename="../../src/yuzu/aboutdialog.ui" line="72"/>
11 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:28pt;&quot;&gt;yuzu&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
12 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:28pt;&quot;&gt;yuzu&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
13 </message>
14 <message>
15 <location filename="../../src/yuzu/aboutdialog.ui" line="85"/>
16 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;%1 (%2)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
17 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;%1 (%2)&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
18 </message>
19 <message>
20 <location filename="../../src/yuzu/aboutdialog.ui" line="98"/>
21 <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
22&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
23p, li { white-space: pre-wrap; }
24&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
25&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'MS Shell Dlg 2'; font-size:12pt;&quot;&gt;yuzu is an experimental open-source emulator for the Nintendo Switch licensed under GPLv3.0+.&lt;/span&gt;&lt;/p&gt;
26&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
27&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:12pt;&quot;&gt;This software should not be used to play games you have not legally obtained.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
28 <translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
29&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
30p, li { white-space: pre-wrap; }
31&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;Ubuntu&apos;; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
32&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:12pt;&quot;&gt;yuzu є експериментальним емулятором Nintendo Switch з відкритим кодом ліцензований під GPLv3.0+.&lt;/span&gt;&lt;/p&gt;
33&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:&apos;MS Shell Dlg 2&apos;; font-size:8pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
34&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:12pt;&quot;&gt;Це програмне забезпечення не слід використовувати для ігор, які ви отримали незаконним шляхом.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
35 </message>
36 <message>
37 <location filename="../../src/yuzu/aboutdialog.ui" line="130"/>
38 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://yuzu-emu.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Website&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Source Code&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/graphs/contributors&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Contributors&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/blob/master/LICENSE.txt&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;License&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
39 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://yuzu-emu.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Веб-сайт&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Вихідний код&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/graphs/contributors&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Вкладники&lt;/span&gt;&lt;/a&gt; | &lt;a href=&quot;https://github.com/yuzu-emu/yuzu/blob/master/LICENSE.txt&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;Ліцензія&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
40 </message>
41 <message>
42 <location filename="../../src/yuzu/aboutdialog.ui" line="146"/>
43 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:7pt;&quot;&gt;&amp;quot;Nintendo Switch&amp;quot; is a trademark of Nintendo. yuzu is not affiliated with Nintendo in any way.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
44 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:7pt;&quot;&gt;&amp;quot;Nintendo Switch&amp;quot; є торговою маркою Nintendo. yuzu не пов&apos;язаний з Nintendo у будь-якому вигляді.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
45 </message>
46</context>
47<context>
48 <name>CalibrationConfigurationDialog</name>
49 <message>
50 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="23"/>
51 <source>Communicating with the server...</source>
52 <translation>Зв&apos;язок із сервером...</translation>
53 </message>
54 <message>
55 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="24"/>
56 <source>Cancel</source>
57 <translation>Скасувати</translation>
58 </message>
59 <message>
60 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="43"/>
61 <source>Touch the top left corner &lt;br&gt;of your touchpad.</source>
62 <translation>Торкніться верхнього лівого кута &lt;br&gt; вашого тачпаду.</translation>
63 </message>
64 <message>
65 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="46"/>
66 <source>Now touch the bottom right corner &lt;br&gt;of your touchpad.</source>
67 <translation>Тепер торкніться правого нижнього кута &lt;br&gt; вашого тачпаду.</translation>
68 </message>
69 <message>
70 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="49"/>
71 <source>Configuration completed!</source>
72 <translation>Налаштування завершено!</translation>
73 </message>
74 <message>
75 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="57"/>
76 <source>OK</source>
77 <translation>ОК</translation>
78 </message>
79</context>
80<context>
81 <name>ChatRoom</name>
82 <message>
83 <location filename="../../src/yuzu/multiplayer/chat_room.ui" line="14"/>
84 <source>Room Window</source>
85 <translation>Вікно кімнати</translation>
86 </message>
87 <message>
88 <location filename="../../src/yuzu/multiplayer/chat_room.ui" line="40"/>
89 <source>Send Chat Message</source>
90 <translation>Надіслати повідомлення в чат</translation>
91 </message>
92 <message>
93 <location filename="../../src/yuzu/multiplayer/chat_room.ui" line="47"/>
94 <source>Send Message</source>
95 <translation>Надіслати повідомлення</translation>
96 </message>
97 <message>
98 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="181"/>
99 <source>Members</source>
100 <translation>Члени</translation>
101 </message>
102 <message>
103 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="318"/>
104 <source>%1 has joined</source>
105 <translation>%1 приєднався</translation>
106 </message>
107 <message>
108 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="321"/>
109 <source>%1 has left</source>
110 <translation>%1 вийшов</translation>
111 </message>
112 <message>
113 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="324"/>
114 <source>%1 has been kicked</source>
115 <translation>%1 вигнано</translation>
116 </message>
117 <message>
118 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="327"/>
119 <source>%1 has been banned</source>
120 <translation>%1 заблоковано</translation>
121 </message>
122 <message>
123 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="330"/>
124 <source>%1 has been unbanned</source>
125 <translation>%1 розблоковано</translation>
126 </message>
127 <message>
128 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="446"/>
129 <source>View Profile</source>
130 <translation>Переглянути профіль</translation>
131 </message>
132 <message>
133 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="459"/>
134 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="469"/>
135 <source>Block Player</source>
136 <translation>Заблокувати гравця</translation>
137 </message>
138 <message>
139 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="470"/>
140 <source>When you block a player, you will no longer receive chat messages from them.&lt;br&gt;&lt;br&gt;Are you sure you would like to block %1?</source>
141 <translation>Коли ви блокуєте гравця, ви більше не отримуватиме від нього повідомлення у чаті. &lt;br&gt;&lt;br&gt;Ви впевнені що бажаєте заблокувати %1?</translation>
142 </message>
143 <message>
144 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="483"/>
145 <source>Kick</source>
146 <translation>Вигнати</translation>
147 </message>
148 <message>
149 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="484"/>
150 <source>Ban</source>
151 <translation>Заблокувати</translation>
152 </message>
153 <message>
154 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="488"/>
155 <source>Kick Player</source>
156 <translation>Вигнати гравця</translation>
157 </message>
158 <message>
159 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="489"/>
160 <source>Are you sure you would like to &lt;b&gt;kick&lt;/b&gt; %1?</source>
161 <translation>Ви впевнені що бажаєте &lt;b&gt;вигнати&lt;/b&gt; %1?</translation>
162 </message>
163 <message>
164 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="497"/>
165 <source>Ban Player</source>
166 <translation>Заблокувати гравця</translation>
167 </message>
168 <message>
169 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="498"/>
170 <source>Are you sure you would like to &lt;b&gt;kick and ban&lt;/b&gt; %1?
171
172This would ban both their forum username and their IP address.</source>
173 <translation>Ви впевнені що бажаєте &lt;b&gt;вигнати і заблокувати&lt;/b&gt; %1?
174
175Ця дія заблокує ім&apos;я користувача на форумі та IP-адресу.</translation>
176 </message>
177</context>
178<context>
179 <name>ClientRoom</name>
180 <message>
181 <location filename="../../src/yuzu/multiplayer/client_room.ui" line="14"/>
182 <source>Room Window</source>
183 <translation>Вікно кімнати</translation>
184 </message>
185 <message>
186 <location filename="../../src/yuzu/multiplayer/client_room.ui" line="27"/>
187 <source>Room Description</source>
188 <translation>Опис кімнати</translation>
189 </message>
190 <message>
191 <location filename="../../src/yuzu/multiplayer/client_room.ui" line="47"/>
192 <source>Moderation...</source>
193 <translation>Модерація...</translation>
194 </message>
195 <message>
196 <location filename="../../src/yuzu/multiplayer/client_room.ui" line="57"/>
197 <source>Leave Room</source>
198 <translation>Залишити кімнату</translation>
199 </message>
200</context>
201<context>
202 <name>ClientRoomWindow</name>
203 <message>
204 <location filename="../../src/yuzu/multiplayer/client_room.cpp" line="78"/>
205 <source>Connected</source>
206 <translation>З&apos;єднано</translation>
207 </message>
208 <message>
209 <location filename="../../src/yuzu/multiplayer/client_room.cpp" line="87"/>
210 <source>Disconnected</source>
211 <translation>Роз&apos;єднано</translation>
212 </message>
213 <message>
214 <location filename="../../src/yuzu/multiplayer/client_room.cpp" line="100"/>
215 <source>%1 - %2 (%3/%4 members) - connected</source>
216 <translation>%1 - %2 (%3/%4 члени) - з&apos;єднано</translation>
217 </message>
218</context>
219<context>
220 <name>CompatDB</name>
221 <message>
222 <location filename="../../src/yuzu/compatdb.ui" line="20"/>
223 <source>Report Compatibility</source>
224 <translation>Повідомити про сумісність</translation>
225 </message>
226 <message>
227 <location filename="../../src/yuzu/compatdb.ui" line="27"/>
228 <location filename="../../src/yuzu/compatdb.ui" line="63"/>
229 <source>Report Game Compatibility</source>
230 <translation>Повідомити про сумісність гри</translation>
231 </message>
232 <message>
233 <location filename="../../src/yuzu/compatdb.ui" line="36"/>
234 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Should you choose to submit a test case to the &lt;/span&gt;&lt;a href=&quot;https://yuzu-emu.org/game/&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;yuzu Compatibility List&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;, The following information will be collected and displayed on the site:&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Hardware Information (CPU / GPU / Operating System)&lt;/li&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Which version of yuzu you are running&lt;/li&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The connected yuzu account&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</source>
235 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Якщо ви бажаєте надіслати звіт до &lt;/span&gt;&lt;a href=&quot;https://yuzu-emu.org/game/&quot;&gt;&lt;span style=&quot; font-size:10pt; text-decoration: underline; color:#0000ff;&quot;&gt;списку сумісності yuzu&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;, наступна інформація буде зібрана та відображена на сайті:&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Інформація про залізо (ЦП / ГП / Операційна система)&lt;/li&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Версія yuzu&lt;/li&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Підключений акаунт yuzu&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</translation>
236 </message>
237 <message>
238 <location filename="../../src/yuzu/compatdb.ui" line="72"/>
239 <source>Perfect</source>
240 <translation>Ідеально</translation>
241 </message>
242 <message>
243 <location filename="../../src/yuzu/compatdb.ui" line="79"/>
244 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions flawlessly with no audio or graphical glitches.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
245 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Гра працює ідеально, без звукових чи графічних артефактів.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
246 </message>
247 <message>
248 <location filename="../../src/yuzu/compatdb.ui" line="89"/>
249 <source>Great</source>
250 <translation>Чудово</translation>
251 </message>
252 <message>
253 <location filename="../../src/yuzu/compatdb.ui" line="96"/>
254 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions with minor graphical or audio glitches and is playable from start to finish. May require some workarounds.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
255 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Гра працює з невеликими графічними або звуковими артефактами та може бути пройдена від початку до кінця. Можуть знадобитися обхідні шляхи.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
256 </message>
257 <message>
258 <location filename="../../src/yuzu/compatdb.ui" line="106"/>
259 <source>Okay</source>
260 <translation>Добре</translation>
261 </message>
262 <message>
263 <location filename="../../src/yuzu/compatdb.ui" line="113"/>
264 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions with major graphical or audio glitches, but game is playable from start to finish with workarounds.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
265 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Гра працює зі суттєвими графічними або звуковими артефактами, але з обхідними шляхами може бути пройдена.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
266 </message>
267 <message>
268 <location filename="../../src/yuzu/compatdb.ui" line="123"/>
269 <source>Bad</source>
270 <translation>Погано</translation>
271 </message>
272 <message>
273 <location filename="../../src/yuzu/compatdb.ui" line="130"/>
274 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches even with workarounds.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
275 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Гра працює, але з суттєвими графічними чи звуковими артефактами. У деяких місцях неможливо пройти навіть із обхідними шляхами.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
276 </message>
277 <message>
278 <location filename="../../src/yuzu/compatdb.ui" line="140"/>
279 <source>Intro/Menu</source>
280 <translation>Вступ/Меню</translation>
281 </message>
282 <message>
283 <location filename="../../src/yuzu/compatdb.ui" line="147"/>
284 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start Screen.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
285 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;У гру неможливо грати через серйозні графічні або звукові артефакти. Неможливо просунутися далі за стартове меню.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
286 </message>
287 <message>
288 <location filename="../../src/yuzu/compatdb.ui" line="157"/>
289 <source>Won&apos;t Boot</source>
290 <translation>Не запускається</translation>
291 </message>
292 <message>
293 <location filename="../../src/yuzu/compatdb.ui" line="170"/>
294 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The game crashes when attempting to startup.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
295 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Гра вилітає при спробі запуску.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
296 </message>
297 <message>
298 <location filename="../../src/yuzu/compatdb.ui" line="182"/>
299 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Independent of speed or performance, how well does this game play from start to finish on this version of yuzu?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
300 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Незалежно від швидкості або продуктивності, наскільки добре ця гра працює від початку до кінця у поточній версії yuzu?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
301 </message>
302 <message>
303 <location filename="../../src/yuzu/compatdb.ui" line="206"/>
304 <source>Thank you for your submission!</source>
305 <translation>Дякуємо за ваш звіт!</translation>
306 </message>
307 <message>
308 <location filename="../../src/yuzu/compatdb.cpp" line="58"/>
309 <source>Submitting</source>
310 <translation>Надсилання</translation>
311 </message>
312 <message>
313 <location filename="../../src/yuzu/compatdb.cpp" line="71"/>
314 <source>Communication error</source>
315 <translation>Помилка з&apos;єднання</translation>
316 </message>
317 <message>
318 <location filename="../../src/yuzu/compatdb.cpp" line="72"/>
319 <source>An error occurred while sending the Testcase</source>
320 <translation>Сталася помилка під час надсилання звіту</translation>
321 </message>
322 <message>
323 <location filename="../../src/yuzu/compatdb.cpp" line="74"/>
324 <source>Next</source>
325 <translation>Далі</translation>
326 </message>
327</context>
328<context>
329 <name>ConfigureAudio</name>
330 <message>
331 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="14"/>
332 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="20"/>
333 <source>Audio</source>
334 <translation>Аудіо</translation>
335 </message>
336 <message>
337 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="28"/>
338 <source>Output Engine:</source>
339 <translation>Рушій виводу:</translation>
340 </message>
341 <message>
342 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="42"/>
343 <source>Output Device</source>
344 <translation>Пристрій виводу</translation>
345 </message>
346 <message>
347 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="56"/>
348 <source>Input Device</source>
349 <translation>Пристрій вводу</translation>
350 </message>
351 <message>
352 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="84"/>
353 <source>Use global volume</source>
354 <translation>Використовувати загальну гучність</translation>
355 </message>
356 <message>
357 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="89"/>
358 <source>Set volume:</source>
359 <translation>Встановити гучність:</translation>
360 </message>
361 <message>
362 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="97"/>
363 <source>Volume:</source>
364 <translation>Гучність</translation>
365 </message>
366 <message>
367 <location filename="../../src/yuzu/configuration/configure_audio.ui" line="142"/>
368 <source>0 %</source>
369 <translation>0 %</translation>
370 </message>
371 <message>
372 <location filename="../../src/yuzu/configuration/configure_audio.cpp" line="108"/>
373 <source>%1%</source>
374 <comment>Volume percentage (e.g. 50%)</comment>
375 <translation>%1%</translation>
376 </message>
377</context>
378<context>
379 <name>ConfigureCamera</name>
380 <message>
381 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="14"/>
382 <source>Configure Infrared Camera</source>
383 <translation>Налаштування інфрачервоної камери</translation>
384 </message>
385 <message>
386 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="26"/>
387 <source>Select where the image of the emulated camera comes from. It may be a virtual camera or a real camera.</source>
388 <translation>Виберіть, звідки береться зображення емульованої камери. Це може бути віртуальна або реальна камера.</translation>
389 </message>
390 <message>
391 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="52"/>
392 <source>Camera Image Source:</source>
393 <translation>Джерело зображення камери:</translation>
394 </message>
395 <message>
396 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="71"/>
397 <source>Input device:</source>
398 <translation>Пристрій вводу:</translation>
399 </message>
400 <message>
401 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="96"/>
402 <source>Preview</source>
403 <translation>Попередній перегляд</translation>
404 </message>
405 <message>
406 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="108"/>
407 <source>Resolution: 320*240</source>
408 <translation>Роздільна здатність: 320*240</translation>
409 </message>
410 <message>
411 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="115"/>
412 <source>Click to preview</source>
413 <translation>Натисніть для попереднього перегляду</translation>
414 </message>
415 <message>
416 <location filename="../../src/yuzu/configuration/configure_camera.ui" line="140"/>
417 <source>Restore Defaults</source>
418 <translation>Значення за замовчуванням</translation>
419 </message>
420 <message>
421 <location filename="../../src/yuzu/configuration/configure_camera.cpp" line="135"/>
422 <source>Auto</source>
423 <translation>Авто</translation>
424 </message>
425</context>
426<context>
427 <name>ConfigureCpu</name>
428 <message>
429 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="14"/>
430 <source>Form</source>
431 <translation>Форма</translation>
432 </message>
433 <message>
434 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="17"/>
435 <source>CPU</source>
436 <translation>ЦП</translation>
437 </message>
438 <message>
439 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="25"/>
440 <source>General</source>
441 <translation>Загальні</translation>
442 </message>
443 <message>
444 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="34"/>
445 <source>Accuracy:</source>
446 <translation>Точність:</translation>
447 </message>
448 <message>
449 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="42"/>
450 <source>Auto</source>
451 <translation>Авто</translation>
452 </message>
453 <message>
454 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="47"/>
455 <source>Accurate</source>
456 <translation>Точно</translation>
457 </message>
458 <message>
459 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="52"/>
460 <source>Unsafe</source>
461 <translation>Небезпечно</translation>
462 </message>
463 <message>
464 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="57"/>
465 <source>Paranoid (disables most optimizations)</source>
466 <translation>Параноїк (відключає більшість оптимізацій)</translation>
467 </message>
468 <message>
469 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="68"/>
470 <source>We recommend setting accuracy to &quot;Auto&quot;.</source>
471 <translation>Ми рекомендуємо встановити точність на &quot;Авто&quot;.</translation>
472 </message>
473 <message>
474 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="85"/>
475 <source>Unsafe CPU Optimization Settings</source>
476 <translation>Небезпечні налаштування оптимізації ЦП</translation>
477 </message>
478 <message>
479 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="91"/>
480 <source>These settings reduce accuracy for speed.</source>
481 <translation>Ці налаштування зменшують точність заради швидкості. </translation>
482 </message>
483 <message>
484 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="101"/>
485 <source>
486 &lt;div&gt;This option improves speed by reducing accuracy of fused-multiply-add instructions on CPUs without native FMA support.&lt;/div&gt;
487 </source>
488 <translation type="unfinished"/>
489 </message>
490 <message>
491 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="106"/>
492 <source>Unfuse FMA (improve performance on CPUs without FMA)</source>
493 <translation>Не використовувати FMA (покращує продуктивність на ЦП без FMA)</translation>
494 </message>
495 <message>
496 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="113"/>
497 <source>
498 &lt;div&gt;This option improves the speed of some approximate floating-point functions by using less accurate native approximations.&lt;/div&gt;
499 </source>
500 <translation type="unfinished"/>
501 </message>
502 <message>
503 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="118"/>
504 <source>Faster FRSQRTE and FRECPE</source>
505 <translation>Прискорені FRSQRTE та FRECPE</translation>
506 </message>
507 <message>
508 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="125"/>
509 <source>
510 &lt;div&gt;This option improves the speed of 32 bits ASIMD floating-point functions by running with incorrect rounding modes.&lt;/div&gt;
511 </source>
512 <translation type="unfinished"/>
513 </message>
514 <message>
515 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="130"/>
516 <source>Faster ASIMD instructions (32 bits only)</source>
517 <translation>Швидші інструкції ASIMD (лише 32 біт)</translation>
518 </message>
519 <message>
520 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="137"/>
521 <source>
522 &lt;div&gt;This option improves speed by removing NaN checking. Please note this also reduces accuracy of certain floating-point instructions.&lt;/div&gt;
523 </source>
524 <translation type="unfinished"/>
525 </message>
526 <message>
527 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="142"/>
528 <source>Inaccurate NaN handling</source>
529 <translation>Неправильна обробка NaN</translation>
530 </message>
531 <message>
532 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="149"/>
533 <source>
534 &lt;div&gt;This option improves speed by eliminating a safety check before every memory read/write in guest. Disabling it may allow a game to read/write the emulator's memory.&lt;/div&gt;
535 </source>
536 <translation type="unfinished"/>
537 </message>
538 <message>
539 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="154"/>
540 <source>Disable address space checks</source>
541 <translation type="unfinished"/>
542 </message>
543 <message>
544 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="161"/>
545 <source>
546 &lt;div&gt;This option improves speed by relying only on the semantics of cmpxchg to ensure safety of exclusive access instructions. Please note this may result in deadlocks and other race conditions.&lt;/div&gt;
547 </source>
548 <translation type="unfinished"/>
549 </message>
550 <message>
551 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="166"/>
552 <source>Ignore global monitor</source>
553 <translation type="unfinished"/>
554 </message>
555 <message>
556 <location filename="../../src/yuzu/configuration/configure_cpu.ui" line="191"/>
557 <source>CPU settings are available only when game is not running.</source>
558 <translation>Налаштування ЦП недоступні, поки запущена гра.</translation>
559 </message>
560</context>
561<context>
562 <name>ConfigureCpuDebug</name>
563 <message>
564 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="14"/>
565 <source>Form</source>
566 <translation>Форма</translation>
567 </message>
568 <message>
569 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="17"/>
570 <source>CPU</source>
571 <translation>ЦП</translation>
572 </message>
573 <message>
574 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="25"/>
575 <source>Toggle CPU Optimizations</source>
576 <translation>Увімкнути оптимізації ЦП</translation>
577 </message>
578 <message>
579 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="31"/>
580 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;For debugging only.&lt;/span&gt;&lt;br/&gt;If you&apos;re not sure what these do, keep all of these enabled. &lt;br/&gt;These settings, when disabled, only take effect when CPU Debugging is enabled. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
581 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Тільки для налагодження.&lt;/span&gt;&lt;br/&gt;Якщо ви не впевнені в тому, що вони роблять, залиште всі ці параметри увімкненими. &lt;br/&gt;Коли їх вимкнено, ці параметри набувають чинності лише за увімкненого налагодження ЦП. &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
582 </message>
583 <message>
584 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="41"/>
585 <source>
586 &lt;div style=&quot;white-space: nowrap&quot;&gt;This optimization speeds up memory accesses by the guest program.&lt;/div&gt;
587 &lt;div style=&quot;white-space: nowrap&quot;&gt;Enabling it inlines accesses to PageTable::pointers into emitted code.&lt;/div&gt;
588 &lt;div style=&quot;white-space: nowrap&quot;&gt;Disabling this forces all memory accesses to go through the Memory::Read/Memory::Write functions.&lt;/div&gt;
589 </source>
590 <translation type="unfinished"/>
591 </message>
592 <message>
593 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="48"/>
594 <source>Enable inline page tables</source>
595 <translation type="unfinished"/>
596 </message>
597 <message>
598 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="55"/>
599 <source>
600 &lt;div&gt;This optimization avoids dispatcher lookups by allowing emitted basic blocks to jump directly to other basic blocks if the destination PC is static.&lt;/div&gt;
601 </source>
602 <translation type="unfinished"/>
603 </message>
604 <message>
605 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="60"/>
606 <source>Enable block linking</source>
607 <translation type="unfinished"/>
608 </message>
609 <message>
610 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="67"/>
611 <source>
612 &lt;div&gt;This optimization avoids dispatcher lookups by keeping track potential return addresses of BL instructions. This approximates what happens with a return stack buffer on a real CPU.&lt;/div&gt;
613 </source>
614 <translation type="unfinished"/>
615 </message>
616 <message>
617 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="72"/>
618 <source>Enable return stack buffer</source>
619 <translation type="unfinished"/>
620 </message>
621 <message>
622 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="79"/>
623 <source>
624 &lt;div&gt;Enable a two-tiered dispatch system. A faster dispatcher written in assembly has a small MRU cache of jump destinations is used first. If that fails, dispatch falls back to the slower C++ dispatcher.&lt;/div&gt;
625 </source>
626 <translation type="unfinished"/>
627 </message>
628 <message>
629 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="84"/>
630 <source>Enable fast dispatcher</source>
631 <translation type="unfinished"/>
632 </message>
633 <message>
634 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="91"/>
635 <source>
636 &lt;div&gt;Enables an IR optimization that reduces unnecessary accesses to the CPU context structure.&lt;/div&gt;
637 </source>
638 <translation type="unfinished"/>
639 </message>
640 <message>
641 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="96"/>
642 <source>Enable context elimination</source>
643 <translation type="unfinished"/>
644 </message>
645 <message>
646 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="103"/>
647 <source>
648 &lt;div&gt;Enables IR optimizations that involve constant propagation.&lt;/div&gt;
649 </source>
650 <translation type="unfinished"/>
651 </message>
652 <message>
653 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="108"/>
654 <source>Enable constant propagation</source>
655 <translation type="unfinished"/>
656 </message>
657 <message>
658 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="115"/>
659 <source>
660 &lt;div&gt;Enables miscellaneous IR optimizations.&lt;/div&gt;
661 </source>
662 <translation type="unfinished"/>
663 </message>
664 <message>
665 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="120"/>
666 <source>Enable miscellaneous optimizations</source>
667 <translation>Увімкнути різні оптимізації</translation>
668 </message>
669 <message>
670 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="127"/>
671 <source>
672 &lt;div style=&quot;white-space: nowrap&quot;&gt;When enabled, a misalignment is only triggered when an access crosses a page boundary.&lt;/div&gt;
673 &lt;div style=&quot;white-space: nowrap&quot;&gt;When disabled, a misalignment is triggered on all misaligned accesses.&lt;/div&gt;
674 </source>
675 <translation type="unfinished"/>
676 </message>
677 <message>
678 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="133"/>
679 <source>Enable misalignment check reduction</source>
680 <translation type="unfinished"/>
681 </message>
682 <message>
683 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="140"/>
684 <source>
685 &lt;div style=&quot;white-space: nowrap&quot;&gt;This optimization speeds up memory accesses by the guest program.&lt;/div&gt;
686 &lt;div style=&quot;white-space: nowrap&quot;&gt;Enabling it causes guest memory reads/writes to be done directly into memory and make use of Host's MMU.&lt;/div&gt;
687 &lt;div style=&quot;white-space: nowrap&quot;&gt;Disabling this forces all memory accesses to use Software MMU Emulation.&lt;/div&gt;
688 </source>
689 <translation type="unfinished"/>
690 </message>
691 <message>
692 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="147"/>
693 <source>Enable Host MMU Emulation (general memory instructions)</source>
694 <translation type="unfinished"/>
695 </message>
696 <message>
697 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="154"/>
698 <source>
699 &lt;div style=&quot;white-space: nowrap&quot;&gt;This optimization speeds up exclusive memory accesses by the guest program.&lt;/div&gt;
700 &lt;div style=&quot;white-space: nowrap&quot;&gt;Enabling it causes guest exclusive memory reads/writes to be done directly into memory and make use of Host's MMU.&lt;/div&gt;
701 &lt;div style=&quot;white-space: nowrap&quot;&gt;Disabling this forces all exclusive memory accesses to use Software MMU Emulation.&lt;/div&gt;
702 </source>
703 <translation type="unfinished"/>
704 </message>
705 <message>
706 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="161"/>
707 <source>Enable Host MMU Emulation (exclusive memory instructions)</source>
708 <translation type="unfinished"/>
709 </message>
710 <message>
711 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="168"/>
712 <source>
713 &lt;div style=&quot;white-space: nowrap&quot;&gt;This optimization speeds up exclusive memory accesses by the guest program.&lt;/div&gt;
714 &lt;div style=&quot;white-space: nowrap&quot;&gt;Enabling it reduces the overhead of fastmem failure of exclusive memory accesses.&lt;/div&gt;
715 </source>
716 <translation type="unfinished"/>
717 </message>
718 <message>
719 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="174"/>
720 <source>Enable recompilation of exclusive memory instructions</source>
721 <translation type="unfinished"/>
722 </message>
723 <message>
724 <location filename="../../src/yuzu/configuration/configure_cpu_debug.ui" line="199"/>
725 <source>CPU settings are available only when game is not running.</source>
726 <translation>Налаштування ЦП доступні тільки тоді, коли гру не запущено.</translation>
727 </message>
728</context>
729<context>
730 <name>ConfigureDebug</name>
731 <message>
732 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="15"/>
733 <source>Debugger</source>
734 <translation>Налагоджувач</translation>
735 </message>
736 <message>
737 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="23"/>
738 <source>Enable GDB Stub</source>
739 <translation type="unfinished"/>
740 </message>
741 <message>
742 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="43"/>
743 <source>Port:</source>
744 <translation>Порт:</translation>
745 </message>
746 <message>
747 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="67"/>
748 <source>Logging</source>
749 <translation>Журналювання</translation>
750 </message>
751 <message>
752 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="75"/>
753 <source>Global Log Filter</source>
754 <translation>Глобальний фільтр журналів</translation>
755 </message>
756 <message>
757 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="87"/>
758 <source>Show Log in Console</source>
759 <translation>Показувати журнал у консолі</translation>
760 </message>
761 <message>
762 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="94"/>
763 <source>Open Log Location</source>
764 <translation>Відкрити папку для журналів</translation>
765 </message>
766 <message>
767 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="104"/>
768 <source>When checked, the max size of the log increases from 100 MB to 1 GB</source>
769 <translation>Якщо увімкнено, максимальний розмір журналу збільшується зі 100 МБ до 1 ГБ</translation>
770 </message>
771 <message>
772 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="107"/>
773 <source>Enable Extended Logging**</source>
774 <translation>Увімкнути розширене ведення журналу**</translation>
775 </message>
776 <message>
777 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="117"/>
778 <source>Homebrew</source>
779 <translation>Homebrew</translation>
780 </message>
781 <message>
782 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="125"/>
783 <source>Arguments String</source>
784 <translation>Рядок аргументів</translation>
785 </message>
786 <message>
787 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="140"/>
788 <source>Graphics</source>
789 <translation>Графіка</translation>
790 </message>
791 <message>
792 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="149"/>
793 <source>When checked, the graphics API enters a slower debugging mode</source>
794 <translation>Якщо увімкнено, графічний API переходить у повільніший режим налагодження</translation>
795 </message>
796 <message>
797 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="152"/>
798 <source>Enable Graphics Debugging</source>
799 <translation>Увімкнути налагодження графіки</translation>
800 </message>
801 <message>
802 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="159"/>
803 <source>When checked, it enables Nsight Aftermath crash dumps</source>
804 <translation type="unfinished"/>
805 </message>
806 <message>
807 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="162"/>
808 <source>Enable Nsight Aftermath</source>
809 <translation type="unfinished"/>
810 </message>
811 <message>
812 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="172"/>
813 <source>When checked, it will dump all the original assembler shaders from the disk shader cache or game as found</source>
814 <translation>Якщо ввімкнено, буде дампити всі оригінальні шейдери асемблера з кешу шейдерів на диску або гри як знайдені</translation>
815 </message>
816 <message>
817 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="175"/>
818 <source>Dump Game Shaders</source>
819 <translation>Дамп ігрових шейдерів</translation>
820 </message>
821 <message>
822 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="185"/>
823 <source>When checked, it will dump all the macro programs of the GPU</source>
824 <translation type="unfinished"/>
825 </message>
826 <message>
827 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="188"/>
828 <source>Dump Maxwell Macros</source>
829 <translation type="unfinished"/>
830 </message>
831 <message>
832 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="198"/>
833 <source>When checked, it disables the macro Just In Time compiler. Enabling this makes games run slower</source>
834 <translation type="unfinished"/>
835 </message>
836 <message>
837 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="201"/>
838 <source>Disable Macro JIT</source>
839 <translation type="unfinished"/>
840 </message>
841 <message>
842 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="208"/>
843 <source>When checked, yuzu will log statistics about the compiled pipeline cache</source>
844 <translation>Якщо увімкнено, yuzu записуватиме статистику про скомпільований кеш конвеєра</translation>
845 </message>
846 <message>
847 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="211"/>
848 <source>Enable Shader Feedback</source>
849 <translation>Увімкнути зворотний зв&apos;язок про шейдери</translation>
850 </message>
851 <message>
852 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="218"/>
853 <source>When checked, it executes shaders without loop logic changes</source>
854 <translation type="unfinished"/>
855 </message>
856 <message>
857 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="221"/>
858 <source>Disable Loop safety checks</source>
859 <translation type="unfinished"/>
860 </message>
861 <message>
862 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="231"/>
863 <source>Debugging</source>
864 <translation>Налагодження</translation>
865 </message>
866 <message>
867 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="237"/>
868 <source>Enable Verbose Reporting Services**</source>
869 <translation type="unfinished"/>
870 </message>
871 <message>
872 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="244"/>
873 <source>Enable FS Access Log</source>
874 <translation type="unfinished"/>
875 </message>
876 <message>
877 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="251"/>
878 <source>Enable this to output the latest generated audio command list to the console. Only affects games using the audio renderer.</source>
879 <translation type="unfinished"/>
880 </message>
881 <message>
882 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="254"/>
883 <source>Dump Audio Commands To Console**</source>
884 <translation type="unfinished"/>
885 </message>
886 <message>
887 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="261"/>
888 <source>Create Minidump After Crash</source>
889 <translation type="unfinished"/>
890 </message>
891 <message>
892 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="271"/>
893 <source>Advanced</source>
894 <translation>Розширені</translation>
895 </message>
896 <message>
897 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="277"/>
898 <source>Kiosk (Quest) Mode</source>
899 <translation>Режим кіоску (Квест)</translation>
900 </message>
901 <message>
902 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="284"/>
903 <source>Enable CPU Debugging</source>
904 <translation>Увімкнути налагодження ЦП</translation>
905 </message>
906 <message>
907 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="291"/>
908 <source>Enable Debug Asserts</source>
909 <translation type="unfinished"/>
910 </message>
911 <message>
912 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="298"/>
913 <source>Enable Auto-Stub**</source>
914 <translation type="unfinished"/>
915 </message>
916 <message>
917 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="305"/>
918 <source>Enable All Controller Types</source>
919 <translation>Увімкнути всі типи контролерів</translation>
920 </message>
921 <message>
922 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="312"/>
923 <source>Disable Web Applet</source>
924 <translation>Вимкнути веб-аплет</translation>
925 </message>
926 <message>
927 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="319"/>
928 <source>Enables yuzu to check for a working Vulkan environment when the program starts up. Disable this if this is causing issues with external programs seeing yuzu.</source>
929 <translation>Дозволяє yuzu перевіряти наявність робочого середовища Vulkan під час запуску програми. Вимкніть цю опцію, якщо це викликає проблеми з тим, що зовнішні програми бачать yuzu.</translation>
930 </message>
931 <message>
932 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="322"/>
933 <source>Perform Startup Vulkan Check</source>
934 <translation>Виконувати перевірку Vulkan під час запуску</translation>
935 </message>
936 <message>
937 <location filename="../../src/yuzu/configuration/configure_debug.ui" line="337"/>
938 <source>**This will be reset automatically when yuzu closes.</source>
939 <translation>**Це буде автоматично скинуто після закриття yuzu.</translation>
940 </message>
941 <message>
942 <location filename="../../src/yuzu/configuration/configure_debug.cpp" line="35"/>
943 <source>Restart Required</source>
944 <translation>Потрібен перезапуск</translation>
945 </message>
946 <message>
947 <location filename="../../src/yuzu/configuration/configure_debug.cpp" line="36"/>
948 <source>yuzu is required to restart in order to apply this setting.</source>
949 <translation>yuzu потрібно перезапустити, щоб застосувати це налаштування.</translation>
950 </message>
951 <message>
952 <location filename="../../src/yuzu/configuration/configure_debug.cpp" line="86"/>
953 <source>Web applet not compiled</source>
954 <translation>Веб-аплет не скомпільовано</translation>
955 </message>
956 <message>
957 <location filename="../../src/yuzu/configuration/configure_debug.cpp" line="93"/>
958 <source>MiniDump creation not compiled</source>
959 <translation type="unfinished"/>
960 </message>
961</context>
962<context>
963 <name>ConfigureDebugController</name>
964 <message>
965 <location filename="../../src/yuzu/configuration/configure_debug_controller.ui" line="14"/>
966 <source>Configure Debug Controller</source>
967 <translation>Налаштування налагоджувального контролера</translation>
968 </message>
969 <message>
970 <location filename="../../src/yuzu/configuration/configure_debug_controller.ui" line="40"/>
971 <source>Clear</source>
972 <translation>Очистити</translation>
973 </message>
974 <message>
975 <location filename="../../src/yuzu/configuration/configure_debug_controller.ui" line="47"/>
976 <source>Defaults</source>
977 <translation>За замовчуванням</translation>
978 </message>
979</context>
980<context>
981 <name>ConfigureDebugTab</name>
982 <message>
983 <location filename="../../src/yuzu/configuration/configure_debug_tab.ui" line="14"/>
984 <source>Form</source>
985 <translation>Форма</translation>
986 </message>
987 <message>
988 <location filename="../../src/yuzu/configuration/configure_debug_tab.ui" line="17"/>
989 <location filename="../../src/yuzu/configuration/configure_debug_tab.cpp" line="16"/>
990 <source>Debug</source>
991 <translation>Налагодження</translation>
992 </message>
993 <message>
994 <location filename="../../src/yuzu/configuration/configure_debug_tab.cpp" line="17"/>
995 <source>CPU</source>
996 <translation>ЦП</translation>
997 </message>
998</context>
999<context>
1000 <name>ConfigureDialog</name>
1001 <message>
1002 <location filename="../../src/yuzu/configuration/configure.ui" line="20"/>
1003 <source>yuzu Configuration</source>
1004 <translation>Налаштування yuzu</translation>
1005 </message>
1006 <message>
1007 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="52"/>
1008 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="156"/>
1009 <source>Audio</source>
1010 <translation>Аудіо</translation>
1011 </message>
1012 <message>
1013 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="53"/>
1014 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="154"/>
1015 <source>CPU</source>
1016 <translation>ЦП</translation>
1017 </message>
1018 <message>
1019 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="54"/>
1020 <source>Debug</source>
1021 <translation>Налагодження</translation>
1022 </message>
1023 <message>
1024 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="55"/>
1025 <source>Filesystem</source>
1026 <translation>Файлова система</translation>
1027 </message>
1028 <message>
1029 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="56"/>
1030 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="150"/>
1031 <source>General</source>
1032 <translation>Загальні</translation>
1033 </message>
1034 <message>
1035 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="57"/>
1036 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="155"/>
1037 <source>Graphics</source>
1038 <translation>Графіка</translation>
1039 </message>
1040 <message>
1041 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="58"/>
1042 <source>GraphicsAdvanced</source>
1043 <translation>ГрафікаРозширені</translation>
1044 </message>
1045 <message>
1046 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="59"/>
1047 <source>Hotkeys</source>
1048 <translation>Гарячі клавіші</translation>
1049 </message>
1050 <message>
1051 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="60"/>
1052 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="157"/>
1053 <source>Controls</source>
1054 <translation>Керування</translation>
1055 </message>
1056 <message>
1057 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="61"/>
1058 <source>Profiles</source>
1059 <translation>Профілі</translation>
1060 </message>
1061 <message>
1062 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="62"/>
1063 <source>Network</source>
1064 <translation>Мережа</translation>
1065 </message>
1066 <message>
1067 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="63"/>
1068 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="152"/>
1069 <source>System</source>
1070 <translation>Система</translation>
1071 </message>
1072 <message>
1073 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="64"/>
1074 <source>Game List</source>
1075 <translation>Список ігор</translation>
1076 </message>
1077 <message>
1078 <location filename="../../src/yuzu/configuration/configure_dialog.cpp" line="65"/>
1079 <source>Web</source>
1080 <translation>Мережа</translation>
1081 </message>
1082</context>
1083<context>
1084 <name>ConfigureFilesystem</name>
1085 <message>
1086 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="14"/>
1087 <source>Form</source>
1088 <translation>Форма</translation>
1089 </message>
1090 <message>
1091 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="17"/>
1092 <source>Filesystem</source>
1093 <translation>Файлова система</translation>
1094 </message>
1095 <message>
1096 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="25"/>
1097 <source>Storage Directories</source>
1098 <translation>Каталоги зберігання</translation>
1099 </message>
1100 <message>
1101 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="31"/>
1102 <source>NAND</source>
1103 <translation>NAND</translation>
1104 </message>
1105 <message>
1106 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="38"/>
1107 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="58"/>
1108 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="114"/>
1109 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="136"/>
1110 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="143"/>
1111 <source>...</source>
1112 <translation>...</translation>
1113 </message>
1114 <message>
1115 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="51"/>
1116 <source>SD Card</source>
1117 <translation>SD карта</translation>
1118 </message>
1119 <message>
1120 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="84"/>
1121 <source>Gamecard</source>
1122 <translation>Картридж</translation>
1123 </message>
1124 <message>
1125 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="90"/>
1126 <source>Path</source>
1127 <translation>Шлях</translation>
1128 </message>
1129 <message>
1130 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="100"/>
1131 <source>Inserted</source>
1132 <translation>Вставлений</translation>
1133 </message>
1134 <message>
1135 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="107"/>
1136 <source>Current Game</source>
1137 <translation>Поточна гра</translation>
1138 </message>
1139 <message>
1140 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="124"/>
1141 <source>Patch Manager</source>
1142 <translation>Керування патчами</translation>
1143 </message>
1144 <message>
1145 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="152"/>
1146 <source>Dump Decompressed NSOs</source>
1147 <translation>Дамп розпакованих NSO</translation>
1148 </message>
1149 <message>
1150 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="159"/>
1151 <source>Dump ExeFS</source>
1152 <translation>Дамп ExeFS</translation>
1153 </message>
1154 <message>
1155 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="168"/>
1156 <source>Mod Load Root</source>
1157 <translation>Папка з модами</translation>
1158 </message>
1159 <message>
1160 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="175"/>
1161 <source>Dump Root</source>
1162 <translation>Корінь дампу</translation>
1163 </message>
1164 <message>
1165 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="201"/>
1166 <source>Caching</source>
1167 <translation>Кешування</translation>
1168 </message>
1169 <message>
1170 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="209"/>
1171 <source>Cache Game List Metadata</source>
1172 <translation>Кешувати метадані списку ігор</translation>
1173 </message>
1174 <message>
1175 <location filename="../../src/yuzu/configuration/configure_filesystem.ui" line="216"/>
1176 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="131"/>
1177 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="135"/>
1178 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="140"/>
1179 <source>Reset Metadata Cache</source>
1180 <translation>Скинути кеш метаданих</translation>
1181 </message>
1182 <message>
1183 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="93"/>
1184 <source>Select Emulated NAND Directory...</source>
1185 <translation>Виберіть папку для емульованого NAND...</translation>
1186 </message>
1187 <message>
1188 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="96"/>
1189 <source>Select Emulated SD Directory...</source>
1190 <translation>Виберіть папку для емульованого SD...</translation>
1191 </message>
1192 <message>
1193 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="99"/>
1194 <source>Select Gamecard Path...</source>
1195 <translation>Оберіть папку для картриджів...</translation>
1196 </message>
1197 <message>
1198 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="102"/>
1199 <source>Select Dump Directory...</source>
1200 <translation>Оберіть папку для дампів...</translation>
1201 </message>
1202 <message>
1203 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="105"/>
1204 <source>Select Mod Load Directory...</source>
1205 <translation>Оберіть папку для модів...</translation>
1206 </message>
1207 <message>
1208 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="132"/>
1209 <source>The metadata cache is already empty.</source>
1210 <translation>Кеш метаданих вже порожній.</translation>
1211 </message>
1212 <message>
1213 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="136"/>
1214 <source>The operation completed successfully.</source>
1215 <translation>Операція завершилася успішно.</translation>
1216 </message>
1217 <message>
1218 <location filename="../../src/yuzu/configuration/configure_filesystem.cpp" line="141"/>
1219 <source>The metadata cache couldn&apos;t be deleted. It might be in use or non-existent.</source>
1220 <translation>Кеш метаданих не можна видалити. Можливо, він використовується або відсутній.</translation>
1221 </message>
1222</context>
1223<context>
1224 <name>ConfigureGeneral</name>
1225 <message>
1226 <location filename="../../src/yuzu/configuration/configure_general.ui" line="14"/>
1227 <source>Form</source>
1228 <translation>Форма</translation>
1229 </message>
1230 <message>
1231 <location filename="../../src/yuzu/configuration/configure_general.ui" line="17"/>
1232 <location filename="../../src/yuzu/configuration/configure_general.ui" line="25"/>
1233 <source>General</source>
1234 <translation>Загальні</translation>
1235 </message>
1236 <message>
1237 <location filename="../../src/yuzu/configuration/configure_general.ui" line="35"/>
1238 <source>Limit Speed Percent</source>
1239 <translation>Обмеження відсотка швидкості</translation>
1240 </message>
1241 <message>
1242 <location filename="../../src/yuzu/configuration/configure_general.ui" line="42"/>
1243 <source>%</source>
1244 <translation>%</translation>
1245 </message>
1246 <message>
1247 <location filename="../../src/yuzu/configuration/configure_general.ui" line="60"/>
1248 <source>Multicore CPU Emulation</source>
1249 <translation>Багатоядерна емуляція ЦП</translation>
1250 </message>
1251 <message>
1252 <location filename="../../src/yuzu/configuration/configure_general.ui" line="67"/>
1253 <source>Extended memory layout (6GB DRAM)</source>
1254 <translation>Розширене компонування пам&apos;яті (6 ГБ DRAM)</translation>
1255 </message>
1256 <message>
1257 <location filename="../../src/yuzu/configuration/configure_general.ui" line="74"/>
1258 <source>Confirm exit while emulation is running</source>
1259 <translation>Підтверджувати вихід під час емуляції</translation>
1260 </message>
1261 <message>
1262 <location filename="../../src/yuzu/configuration/configure_general.ui" line="81"/>
1263 <source>Prompt for user on game boot</source>
1264 <translation>Запитувати користувача під час запуску гри</translation>
1265 </message>
1266 <message>
1267 <location filename="../../src/yuzu/configuration/configure_general.ui" line="88"/>
1268 <source>Pause emulation when in background</source>
1269 <translation>Призупиняти емуляцію у фоновому режимі</translation>
1270 </message>
1271 <message>
1272 <location filename="../../src/yuzu/configuration/configure_general.ui" line="95"/>
1273 <source>Mute audio when in background</source>
1274 <translation>Приглушити звук у фоновому режимі</translation>
1275 </message>
1276 <message>
1277 <location filename="../../src/yuzu/configuration/configure_general.ui" line="102"/>
1278 <source>Hide mouse on inactivity</source>
1279 <translation>Приховування миші при бездіяльності</translation>
1280 </message>
1281 <message>
1282 <location filename="../../src/yuzu/configuration/configure_general.ui" line="144"/>
1283 <source>Reset All Settings</source>
1284 <translation>Скинути всі налаштування</translation>
1285 </message>
1286 <message>
1287 <location filename="../../src/yuzu/configuration/configure_general.cpp" line="68"/>
1288 <source>yuzu</source>
1289 <translation>yuzu</translation>
1290 </message>
1291 <message>
1292 <location filename="../../src/yuzu/configuration/configure_general.cpp" line="69"/>
1293 <source>This reset all settings and remove all per-game configurations. This will not delete game directories, profiles, or input profiles. Proceed?</source>
1294 <translation>Це скине всі налаштування і видалить усі конфігурації під окремі ігри. При цьому не будуть видалені шляхи до ігор, профілів або профілів вводу. Продовжити?</translation>
1295 </message>
1296</context>
1297<context>
1298 <name>ConfigureGraphics</name>
1299 <message>
1300 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="14"/>
1301 <source>Form</source>
1302 <translation>Форма</translation>
1303 </message>
1304 <message>
1305 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="17"/>
1306 <source>Graphics</source>
1307 <translation>Графіка</translation>
1308 </message>
1309 <message>
1310 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="25"/>
1311 <source>API Settings</source>
1312 <translation>Налаштування API</translation>
1313 </message>
1314 <message>
1315 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="64"/>
1316 <source>Shader Backend:</source>
1317 <translation>Бекенд шейдерів:</translation>
1318 </message>
1319 <message>
1320 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="92"/>
1321 <source>Device:</source>
1322 <translation>Пристрій:</translation>
1323 </message>
1324 <message>
1325 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="120"/>
1326 <source>API:</source>
1327 <translation>API:</translation>
1328 </message>
1329 <message>
1330 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="156"/>
1331 <source>Graphics Settings</source>
1332 <translation>Налаштування графіки</translation>
1333 </message>
1334 <message>
1335 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="162"/>
1336 <source>Use disk pipeline cache</source>
1337 <translation>Використовувати кеш конвеєра на диску</translation>
1338 </message>
1339 <message>
1340 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="169"/>
1341 <source>Use asynchronous GPU emulation</source>
1342 <translation>Використовувати асинхронну емуляцію ГП</translation>
1343 </message>
1344 <message>
1345 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="176"/>
1346 <source>Accelerate ASTC texture decoding</source>
1347 <translation>Прискорення декодування текстур ASTC</translation>
1348 </message>
1349 <message>
1350 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="198"/>
1351 <source>NVDEC emulation:</source>
1352 <translation>Емуляція NVDEC:</translation>
1353 </message>
1354 <message>
1355 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="206"/>
1356 <source>No Video Output</source>
1357 <translation>Відсутність відеовиходу</translation>
1358 </message>
1359 <message>
1360 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="211"/>
1361 <source>CPU Video Decoding</source>
1362 <translation>Декодування відео на ЦП</translation>
1363 </message>
1364 <message>
1365 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="216"/>
1366 <source>GPU Video Decoding (Default)</source>
1367 <translation>Декодування відео на ГП (за замовчуванням)</translation>
1368 </message>
1369 <message>
1370 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="242"/>
1371 <source>Fullscreen Mode:</source>
1372 <translation>Повноекранний режим:</translation>
1373 </message>
1374 <message>
1375 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="250"/>
1376 <source>Borderless Windowed</source>
1377 <translation>Вікно без рамок</translation>
1378 </message>
1379 <message>
1380 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="255"/>
1381 <source>Exclusive Fullscreen</source>
1382 <translation>Ексклюзивний повноекранний</translation>
1383 </message>
1384 <message>
1385 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="281"/>
1386 <source>Aspect Ratio:</source>
1387 <translation>Співвідношення сторін:</translation>
1388 </message>
1389 <message>
1390 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="289"/>
1391 <source>Default (16:9)</source>
1392 <translation>За замовчуванням (16:9)</translation>
1393 </message>
1394 <message>
1395 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="294"/>
1396 <source>Force 4:3</source>
1397 <translation>Змусити 4:3</translation>
1398 </message>
1399 <message>
1400 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="299"/>
1401 <source>Force 21:9</source>
1402 <translation>Змусити 21:9</translation>
1403 </message>
1404 <message>
1405 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="304"/>
1406 <source>Force 16:10</source>
1407 <translation>Змусити 16:10</translation>
1408 </message>
1409 <message>
1410 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="309"/>
1411 <source>Stretch to Window</source>
1412 <translation>Розтягнути до вікна</translation>
1413 </message>
1414 <message>
1415 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="335"/>
1416 <source>Resolution:</source>
1417 <translation>Роздільна здатність:</translation>
1418 </message>
1419 <message>
1420 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="343"/>
1421 <source>0.5X (360p/540p) [EXPERIMENTAL]</source>
1422 <translation>0.5X (360p/540p) [ЕКСПЕРИМЕНТАЛЬНЕ]</translation>
1423 </message>
1424 <message>
1425 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="348"/>
1426 <source>0.75X (540p/810p) [EXPERIMENTAL]</source>
1427 <translation>0.75X (540p/810p) [ЕКСПЕРИМЕНТАЛЬНЕ]</translation>
1428 </message>
1429 <message>
1430 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="353"/>
1431 <source>1X (720p/1080p)</source>
1432 <translation>1X (720p/1080p)</translation>
1433 </message>
1434 <message>
1435 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="358"/>
1436 <source>2X (1440p/2160p)</source>
1437 <translation>2X (1440p/2160p)</translation>
1438 </message>
1439 <message>
1440 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="363"/>
1441 <source>3X (2160p/3240p)</source>
1442 <translation>3X (2160p/3240p)</translation>
1443 </message>
1444 <message>
1445 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="368"/>
1446 <source>4X (2880p/4320p)</source>
1447 <translation>4X (2880p/4320p)</translation>
1448 </message>
1449 <message>
1450 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="373"/>
1451 <source>5X (3600p/5400p)</source>
1452 <translation>5X (3600p/5400p)</translation>
1453 </message>
1454 <message>
1455 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="378"/>
1456 <source>6X (4320p/6480p)</source>
1457 <translation>6X (4320p/6480p)</translation>
1458 </message>
1459 <message>
1460 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="404"/>
1461 <source>Window Adapting Filter:</source>
1462 <translation>Фільтр адаптації вікна:</translation>
1463 </message>
1464 <message>
1465 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="412"/>
1466 <source>Nearest Neighbor</source>
1467 <translation>Найближчий сусід</translation>
1468 </message>
1469 <message>
1470 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="417"/>
1471 <source>Bilinear</source>
1472 <translation>Білінійне</translation>
1473 </message>
1474 <message>
1475 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="422"/>
1476 <source>Bicubic</source>
1477 <translation>Бікубічне</translation>
1478 </message>
1479 <message>
1480 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="427"/>
1481 <source>Gaussian</source>
1482 <translation>Гауса</translation>
1483 </message>
1484 <message>
1485 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="432"/>
1486 <source>ScaleForce</source>
1487 <translation>ScaleForce</translation>
1488 </message>
1489 <message>
1490 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="437"/>
1491 <source>AMD FidelityFX™️ Super Resolution (Vulkan Only)</source>
1492 <translation>AMD FidelityFX™️ Super Resolution (Лише для Vulkan)</translation>
1493 </message>
1494 <message>
1495 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="463"/>
1496 <source>Anti-Aliasing Method:</source>
1497 <translation>Метод згладжування:</translation>
1498 </message>
1499 <message>
1500 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="471"/>
1501 <source>None</source>
1502 <translation>Вимкнено</translation>
1503 </message>
1504 <message>
1505 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="476"/>
1506 <source>FXAA</source>
1507 <translation>FXAA</translation>
1508 </message>
1509 <message>
1510 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="511"/>
1511 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="521"/>
1512 <source>Use global background color</source>
1513 <translation>Використовувати глобальний фоновий колір</translation>
1514 </message>
1515 <message>
1516 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="526"/>
1517 <source>Set background color:</source>
1518 <translation>Встановити фоновий колір:</translation>
1519 </message>
1520 <message>
1521 <location filename="../../src/yuzu/configuration/configure_graphics.ui" line="534"/>
1522 <source>Background Color:</source>
1523 <translation>Фоновий колір:</translation>
1524 </message>
1525 <message>
1526 <location filename="../../src/yuzu/configuration/configure_graphics.cpp" line="33"/>
1527 <source>GLASM (Assembly Shaders, NVIDIA Only)</source>
1528 <translation>GLASM (асемблерні шейдери, лише для NVIDIA)</translation>
1529 </message>
1530</context>
1531<context>
1532 <name>ConfigureGraphicsAdvanced</name>
1533 <message>
1534 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="14"/>
1535 <source>Form</source>
1536 <translation>Форма</translation>
1537 </message>
1538 <message>
1539 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="17"/>
1540 <source>Advanced</source>
1541 <translation>Розширені</translation>
1542 </message>
1543 <message>
1544 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="25"/>
1545 <source>Advanced Graphics Settings</source>
1546 <translation>Розширені налаштування графіки</translation>
1547 </message>
1548 <message>
1549 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="46"/>
1550 <source>Accuracy Level:</source>
1551 <translation>Рівень точності:</translation>
1552 </message>
1553 <message>
1554 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="75"/>
1555 <source>VSync prevents the screen from tearing, but some graphics cards have lower performance with VSync enabled. Keep it enabled if you don&apos;t notice a performance difference.</source>
1556 <translation>Вертикальна синхронізація запобігає розривам екрана, але деякі відеокарти мають нижчу продуктивність при вертикальній синхронізації. Залишайте увімкненим, якщо ви не помічаєте різниці в продуктивності.</translation>
1557 </message>
1558 <message>
1559 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="78"/>
1560 <source>Use VSync</source>
1561 <translation>Використувати вертикальну сінхронізацію</translation>
1562 </message>
1563 <message>
1564 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="85"/>
1565 <source>Enables asynchronous shader compilation, which may reduce shader stutter. This feature is experimental.</source>
1566 <translation>Вмикає асинхронну компіляцію шейдерів, що зменшить зависання через шейдери. Функція є експериментальною.</translation>
1567 </message>
1568 <message>
1569 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="88"/>
1570 <source>Use asynchronous shader building (Hack)</source>
1571 <translation>Використовувати асинхронну побудову шейдерів (хак)</translation>
1572 </message>
1573 <message>
1574 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="95"/>
1575 <source>Enables Fast GPU Time. This option will force most games to run at their highest native resolution.</source>
1576 <translation>Вмикає функцію Fast GPU Time. Цей параметр змусить більшість ігор працювати в максимальній рідній роздільній здатності.</translation>
1577 </message>
1578 <message>
1579 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="98"/>
1580 <source>Use Fast GPU Time (Hack)</source>
1581 <translation>Увімкнути Fast GPU Time (Хак)</translation>
1582 </message>
1583 <message>
1584 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="105"/>
1585 <source>Enables pessimistic buffer flushes. This option will force unmodified buffers to be flushed, which can cost performance.</source>
1586 <translation>Вмикає песимістичне очищення буферів. Ця опція змушує промивати немодифіковані буфери, що може знизити продуктивність.</translation>
1587 </message>
1588 <message>
1589 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="108"/>
1590 <source>Use pessimistic buffer flushes (Hack)</source>
1591 <translation>Використовувати песимістичне очищення буферів (Хак)</translation>
1592 </message>
1593 <message>
1594 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="130"/>
1595 <source>Anisotropic Filtering:</source>
1596 <translation>Анізотропна фільтрація:</translation>
1597 </message>
1598 <message>
1599 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="138"/>
1600 <source>Automatic</source>
1601 <translation>Автоматично</translation>
1602 </message>
1603 <message>
1604 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="143"/>
1605 <source>Default</source>
1606 <translation>За замовчуванням</translation>
1607 </message>
1608 <message>
1609 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="148"/>
1610 <source>2x</source>
1611 <translation>2x</translation>
1612 </message>
1613 <message>
1614 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="153"/>
1615 <source>4x</source>
1616 <translation>4x</translation>
1617 </message>
1618 <message>
1619 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="158"/>
1620 <source>8x</source>
1621 <translation>8x</translation>
1622 </message>
1623 <message>
1624 <location filename="../../src/yuzu/configuration/configure_graphics_advanced.ui" line="163"/>
1625 <source>16x</source>
1626 <translation>16x</translation>
1627 </message>
1628</context>
1629<context>
1630 <name>ConfigureHotkeys</name>
1631 <message>
1632 <location filename="../../src/yuzu/configuration/configure_hotkeys.ui" line="14"/>
1633 <source>Hotkey Settings</source>
1634 <translation>Налаштування гарячих клавіш</translation>
1635 </message>
1636 <message>
1637 <location filename="../../src/yuzu/configuration/configure_hotkeys.ui" line="17"/>
1638 <source>Hotkeys</source>
1639 <translation>Гарячі клавіші</translation>
1640 </message>
1641 <message>
1642 <location filename="../../src/yuzu/configuration/configure_hotkeys.ui" line="25"/>
1643 <source>Double-click on a binding to change it.</source>
1644 <translation>Натисніть двічі на прив&apos;язці, щоб змінити її.</translation>
1645 </message>
1646 <message>
1647 <location filename="../../src/yuzu/configuration/configure_hotkeys.ui" line="45"/>
1648 <source>Clear All</source>
1649 <translation>Очистити все</translation>
1650 </message>
1651 <message>
1652 <location filename="../../src/yuzu/configuration/configure_hotkeys.ui" line="52"/>
1653 <source>Restore Defaults</source>
1654 <translation>Відновити значення за замовчуванням.</translation>
1655 </message>
1656 <message>
1657 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="98"/>
1658 <source>Action</source>
1659 <translation>Дія</translation>
1660 </message>
1661 <message>
1662 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="98"/>
1663 <source>Hotkey</source>
1664 <translation>Гаряча клавіша</translation>
1665 </message>
1666 <message>
1667 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="98"/>
1668 <source>Controller Hotkey</source>
1669 <translation>Гаряча клавіша контролера</translation>
1670 </message>
1671 <message>
1672 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="138"/>
1673 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="164"/>
1674 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="379"/>
1675 <source>Conflicting Key Sequence</source>
1676 <translation>Конфліктуюча комбінація клавіш</translation>
1677 </message>
1678 <message>
1679 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="139"/>
1680 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="165"/>
1681 <source>The entered key sequence is already assigned to: %1</source>
1682 <translation>Введена комбінація вже призначена до: %1</translation>
1683 </message>
1684 <message>
1685 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="158"/>
1686 <source>Home+%1</source>
1687 <translation>Home+%1</translation>
1688 </message>
1689 <message>
1690 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="172"/>
1691 <source>[waiting]</source>
1692 <translation>[очікування]</translation>
1693 </message>
1694 <message>
1695 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="242"/>
1696 <source>Invalid</source>
1697 <translation>Неприпустимо</translation>
1698 </message>
1699 <message>
1700 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="343"/>
1701 <source>Restore Default</source>
1702 <translation>Відновити значення за замовчуванням</translation>
1703 </message>
1704 <message>
1705 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="344"/>
1706 <source>Clear</source>
1707 <translation>Очистити</translation>
1708 </message>
1709 <message>
1710 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="365"/>
1711 <source>Conflicting Button Sequence</source>
1712 <translation>Конфліктуюче поєднання кнопок</translation>
1713 </message>
1714 <message>
1715 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="366"/>
1716 <source>The default button sequence is already assigned to: %1</source>
1717 <translation>Типова комбінація кнопок вже призначена до: %1</translation>
1718 </message>
1719 <message>
1720 <location filename="../../src/yuzu/configuration/configure_hotkeys.cpp" line="380"/>
1721 <source>The default key sequence is already assigned to: %1</source>
1722 <translation>Типова комбінація клавіш вже призначена до: %1</translation>
1723 </message>
1724</context>
1725<context>
1726 <name>ConfigureInput</name>
1727 <message>
1728 <location filename="../../src/yuzu/configuration/configure_input.ui" line="14"/>
1729 <source>ConfigureInput</source>
1730 <translation>НалаштуванняВводу</translation>
1731 </message>
1732 <message>
1733 <location filename="../../src/yuzu/configuration/configure_input.ui" line="39"/>
1734 <location filename="../../src/yuzu/configuration/configure_input.ui" line="42"/>
1735 <source>Player 1</source>
1736 <translation>Гравець 1</translation>
1737 </message>
1738 <message>
1739 <location filename="../../src/yuzu/configuration/configure_input.ui" line="47"/>
1740 <location filename="../../src/yuzu/configuration/configure_input.ui" line="50"/>
1741 <source>Player 2</source>
1742 <translation>Гравець 2</translation>
1743 </message>
1744 <message>
1745 <location filename="../../src/yuzu/configuration/configure_input.ui" line="55"/>
1746 <location filename="../../src/yuzu/configuration/configure_input.ui" line="58"/>
1747 <source>Player 3</source>
1748 <translation>Гравець 3</translation>
1749 </message>
1750 <message>
1751 <location filename="../../src/yuzu/configuration/configure_input.ui" line="63"/>
1752 <location filename="../../src/yuzu/configuration/configure_input.ui" line="66"/>
1753 <source>Player 4</source>
1754 <translation>Гравець 4</translation>
1755 </message>
1756 <message>
1757 <location filename="../../src/yuzu/configuration/configure_input.ui" line="71"/>
1758 <location filename="../../src/yuzu/configuration/configure_input.ui" line="74"/>
1759 <source>Player 5</source>
1760 <translation>Гравець 5</translation>
1761 </message>
1762 <message>
1763 <location filename="../../src/yuzu/configuration/configure_input.ui" line="79"/>
1764 <location filename="../../src/yuzu/configuration/configure_input.ui" line="82"/>
1765 <source>Player 6</source>
1766 <translation>Гравець 6</translation>
1767 </message>
1768 <message>
1769 <location filename="../../src/yuzu/configuration/configure_input.ui" line="87"/>
1770 <location filename="../../src/yuzu/configuration/configure_input.ui" line="90"/>
1771 <source>Player 7</source>
1772 <translation>Гравець 7</translation>
1773 </message>
1774 <message>
1775 <location filename="../../src/yuzu/configuration/configure_input.ui" line="95"/>
1776 <location filename="../../src/yuzu/configuration/configure_input.ui" line="98"/>
1777 <source>Player 8</source>
1778 <translation>Гравець 8</translation>
1779 </message>
1780 <message>
1781 <location filename="../../src/yuzu/configuration/configure_input.ui" line="103"/>
1782 <location filename="../../src/yuzu/configuration/configure_input.ui" line="106"/>
1783 <source>Advanced</source>
1784 <translation>Розширені</translation>
1785 </message>
1786 <message>
1787 <location filename="../../src/yuzu/configuration/configure_input.ui" line="138"/>
1788 <source>Console Mode</source>
1789 <translation>Режим консолі</translation>
1790 </message>
1791 <message>
1792 <location filename="../../src/yuzu/configuration/configure_input.ui" line="159"/>
1793 <source>Docked</source>
1794 <translation>У док-станції</translation>
1795 </message>
1796 <message>
1797 <location filename="../../src/yuzu/configuration/configure_input.ui" line="169"/>
1798 <source>Handheld</source>
1799 <translation>Портативний</translation>
1800 </message>
1801 <message>
1802 <location filename="../../src/yuzu/configuration/configure_input.ui" line="179"/>
1803 <source>Vibration</source>
1804 <translation>Вібрація</translation>
1805 </message>
1806 <message>
1807 <location filename="../../src/yuzu/configuration/configure_input.ui" line="215"/>
1808 <location filename="../../src/yuzu/configuration/configure_input.ui" line="261"/>
1809 <source>Configure</source>
1810 <translation>Налаштувати</translation>
1811 </message>
1812 <message>
1813 <location filename="../../src/yuzu/configuration/configure_input.ui" line="225"/>
1814 <source>Motion</source>
1815 <translation>Рух</translation>
1816 </message>
1817 <message>
1818 <location filename="../../src/yuzu/configuration/configure_input.ui" line="296"/>
1819 <source>Controllers</source>
1820 <translation>Контролери</translation>
1821 </message>
1822 <message>
1823 <location filename="../../src/yuzu/configuration/configure_input.ui" line="324"/>
1824 <source>1</source>
1825 <translation>1</translation>
1826 </message>
1827 <message>
1828 <location filename="../../src/yuzu/configuration/configure_input.ui" line="365"/>
1829 <source>2</source>
1830 <translation>2</translation>
1831 </message>
1832 <message>
1833 <location filename="../../src/yuzu/configuration/configure_input.ui" line="375"/>
1834 <source>3</source>
1835 <translation>3</translation>
1836 </message>
1837 <message>
1838 <location filename="../../src/yuzu/configuration/configure_input.ui" line="385"/>
1839 <source>4</source>
1840 <translation>4</translation>
1841 </message>
1842 <message>
1843 <location filename="../../src/yuzu/configuration/configure_input.ui" line="395"/>
1844 <source>5</source>
1845 <translation>5</translation>
1846 </message>
1847 <message>
1848 <location filename="../../src/yuzu/configuration/configure_input.ui" line="405"/>
1849 <source>6</source>
1850 <translation>6</translation>
1851 </message>
1852 <message>
1853 <location filename="../../src/yuzu/configuration/configure_input.ui" line="415"/>
1854 <source>7</source>
1855 <translation>7</translation>
1856 </message>
1857 <message>
1858 <location filename="../../src/yuzu/configuration/configure_input.ui" line="425"/>
1859 <source>8</source>
1860 <translation>8</translation>
1861 </message>
1862 <message>
1863 <location filename="../../src/yuzu/configuration/configure_input.ui" line="435"/>
1864 <source>Connected</source>
1865 <translation>З&apos;єднано</translation>
1866 </message>
1867 <message>
1868 <location filename="../../src/yuzu/configuration/configure_input.ui" line="494"/>
1869 <source>Defaults</source>
1870 <translation>За замовчуванням</translation>
1871 </message>
1872 <message>
1873 <location filename="../../src/yuzu/configuration/configure_input.ui" line="537"/>
1874 <source>Clear</source>
1875 <translation>Очистити</translation>
1876 </message>
1877</context>
1878<context>
1879 <name>ConfigureInputAdvanced</name>
1880 <message>
1881 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="14"/>
1882 <source>Configure Input</source>
1883 <translation>Налаштування вводу</translation>
1884 </message>
1885 <message>
1886 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="74"/>
1887 <source>Joycon Colors</source>
1888 <translation>Кольори Joy-Con&apos;ів</translation>
1889 </message>
1890 <message>
1891 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="125"/>
1892 <source>Player 1</source>
1893 <translation>Гравець 1</translation>
1894 </message>
1895 <message>
1896 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="164"/>
1897 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="450"/>
1898 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="754"/>
1899 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1040"/>
1900 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1365"/>
1901 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1651"/>
1902 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1955"/>
1903 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2241"/>
1904 <source>L Body</source>
1905 <translation>Лівий контролер</translation>
1906 </message>
1907 <message>
1908 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="219"/>
1909 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="505"/>
1910 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="809"/>
1911 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1095"/>
1912 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1420"/>
1913 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1706"/>
1914 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2010"/>
1915 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2296"/>
1916 <source>L Button</source>
1917 <translation>Кнопка L</translation>
1918 </message>
1919 <message>
1920 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="295"/>
1921 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="581"/>
1922 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="885"/>
1923 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1171"/>
1924 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1496"/>
1925 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1782"/>
1926 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2086"/>
1927 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2372"/>
1928 <source>R Body</source>
1929 <translation>Правий контролер</translation>
1930 </message>
1931 <message>
1932 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="350"/>
1933 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="636"/>
1934 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="940"/>
1935 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1226"/>
1936 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1551"/>
1937 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1837"/>
1938 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2141"/>
1939 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2427"/>
1940 <source>R Button</source>
1941 <translation>Кнопка R</translation>
1942 </message>
1943 <message>
1944 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="411"/>
1945 <source>Player 2</source>
1946 <translation>Гравець 2</translation>
1947 </message>
1948 <message>
1949 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="715"/>
1950 <source>Player 3</source>
1951 <translation>Гравець 3</translation>
1952 </message>
1953 <message>
1954 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1001"/>
1955 <source>Player 4</source>
1956 <translation>Гравець 4</translation>
1957 </message>
1958 <message>
1959 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1326"/>
1960 <source>Player 5</source>
1961 <translation>Гравець 5</translation>
1962 </message>
1963 <message>
1964 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1612"/>
1965 <source>Player 6</source>
1966 <translation>Гравець 6</translation>
1967 </message>
1968 <message>
1969 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="1916"/>
1970 <source>Player 7</source>
1971 <translation>Гравець 7</translation>
1972 </message>
1973 <message>
1974 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2202"/>
1975 <source>Player 8</source>
1976 <translation>Гравець 8</translation>
1977 </message>
1978 <message>
1979 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2533"/>
1980 <source>Emulated Devices</source>
1981 <translation>Емульовані пристрої</translation>
1982 </message>
1983 <message>
1984 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2545"/>
1985 <source>Keyboard</source>
1986 <translation>Клавіатура</translation>
1987 </message>
1988 <message>
1989 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2558"/>
1990 <source>Mouse</source>
1991 <translation>Миша</translation>
1992 </message>
1993 <message>
1994 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2565"/>
1995 <source>Touchscreen</source>
1996 <translation>Сенсорний екран</translation>
1997 </message>
1998 <message>
1999 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2588"/>
2000 <source>Advanced</source>
2001 <translation>Розширені</translation>
2002 </message>
2003 <message>
2004 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2595"/>
2005 <source>Debug Controller</source>
2006 <translation>Налагоджувальний контролер</translation>
2007 </message>
2008 <message>
2009 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2602"/>
2010 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2616"/>
2011 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2630"/>
2012 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2743"/>
2013 <source>Configure</source>
2014 <translation>Налаштувати</translation>
2015 </message>
2016 <message>
2017 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2609"/>
2018 <source>Ring Controller</source>
2019 <translation>Контролер Ring</translation>
2020 </message>
2021 <message>
2022 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2623"/>
2023 <source>Infrared Camera</source>
2024 <translation>Інфрачервона камера</translation>
2025 </message>
2026 <message>
2027 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2640"/>
2028 <source>Other</source>
2029 <translation>Інше</translation>
2030 </message>
2031 <message>
2032 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2652"/>
2033 <source>Emulate Analog with Keyboard Input</source>
2034 <translation>Емуляція аналогового вводу з клавіатури</translation>
2035 </message>
2036 <message>
2037 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2659"/>
2038 <source>Requires restarting yuzu</source>
2039 <translation>Потребує перезапуску yuzu</translation>
2040 </message>
2041 <message>
2042 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2668"/>
2043 <source>Enable XInput 8 player support (disables web applet)</source>
2044 <translation>Увімкнути підтримку 8-ми гравців на XInput (відключає веб-аплет)</translation>
2045 </message>
2046 <message>
2047 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2681"/>
2048 <source>Enable UDP controllers (not needed for motion)</source>
2049 <translation>Увімкнути UDP контролери (не обов&apos;язково для руху)</translation>
2050 </message>
2051 <message>
2052 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2694"/>
2053 <source>Controller navigation</source>
2054 <translation>Навігація контролера</translation>
2055 </message>
2056 <message>
2057 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2707"/>
2058 <source>Enable mouse panning</source>
2059 <translation>Увімкнути панорамування миші</translation>
2060 </message>
2061 <message>
2062 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2714"/>
2063 <source>Mouse sensitivity</source>
2064 <translation>Чутливість миші</translation>
2065 </message>
2066 <message>
2067 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2720"/>
2068 <source>%</source>
2069 <translation>%</translation>
2070 </message>
2071 <message>
2072 <location filename="../../src/yuzu/configuration/configure_input_advanced.ui" line="2736"/>
2073 <source>Motion / Touch</source>
2074 <translation>Рух і сенсор</translation>
2075 </message>
2076</context>
2077<context>
2078 <name>ConfigureInputPlayer</name>
2079 <message>
2080 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="14"/>
2081 <source>Configure Input</source>
2082 <translation>Налаштування вводу</translation>
2083 </message>
2084 <message>
2085 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="63"/>
2086 <source>Connect Controller</source>
2087 <translation>Підключити контролер</translation>
2088 </message>
2089 <message>
2090 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="100"/>
2091 <source>Input Device</source>
2092 <translation>Пристрій вводу</translation>
2093 </message>
2094 <message>
2095 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="156"/>
2096 <source>Profile</source>
2097 <translation>Профіль</translation>
2098 </message>
2099 <message>
2100 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="196"/>
2101 <source>Save</source>
2102 <translation>Зберегти</translation>
2103 </message>
2104 <message>
2105 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="212"/>
2106 <source>New</source>
2107 <translation>Новий</translation>
2108 </message>
2109 <message>
2110 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="228"/>
2111 <source>Delete</source>
2112 <translation>Видалити</translation>
2113 </message>
2114 <message>
2115 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="291"/>
2116 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1291"/>
2117 <source>Left Stick</source>
2118 <translation>Лівий міні-джойстик</translation>
2119 </message>
2120 <message>
2121 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="349"/>
2122 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="391"/>
2123 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="925"/>
2124 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="964"/>
2125 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2583"/>
2126 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2622"/>
2127 <source>Up</source>
2128 <translation>Вгору</translation>
2129 </message>
2130 <message>
2131 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="422"/>
2132 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="461"/>
2133 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="995"/>
2134 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1034"/>
2135 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2069"/>
2136 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2653"/>
2137 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2692"/>
2138 <source>Left</source>
2139 <translation>Вліво</translation>
2140 </message>
2141 <message>
2142 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="471"/>
2143 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="510"/>
2144 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1044"/>
2145 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1083"/>
2146 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2118"/>
2147 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2702"/>
2148 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2741"/>
2149 <source>Right</source>
2150 <translation>Вправо</translation>
2151 </message>
2152 <message>
2153 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="553"/>
2154 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="592"/>
2155 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1126"/>
2156 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1165"/>
2157 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2784"/>
2158 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2823"/>
2159 <source>Down</source>
2160 <translation>Вниз</translation>
2161 </message>
2162 <message>
2163 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="623"/>
2164 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="662"/>
2165 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2854"/>
2166 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2893"/>
2167 <source>Pressed</source>
2168 <translation>Натиснення</translation>
2169 </message>
2170 <message>
2171 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="672"/>
2172 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="711"/>
2173 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2903"/>
2174 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2942"/>
2175 <source>Modifier</source>
2176 <translation>Модифікатор</translation>
2177 </message>
2178 <message>
2179 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="721"/>
2180 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2952"/>
2181 <source>Range</source>
2182 <translation>Діапазон</translation>
2183 </message>
2184 <message>
2185 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="754"/>
2186 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2985"/>
2187 <source>%</source>
2188 <translation>%</translation>
2189 </message>
2190 <message>
2191 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="797"/>
2192 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="3025"/>
2193 <source>Deadzone: 0%</source>
2194 <translation>Мертва зона: 0%</translation>
2195 </message>
2196 <message>
2197 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="821"/>
2198 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="3049"/>
2199 <source>Modifier Range: 0%</source>
2200 <translation>Діапазон модифікатора: 0%</translation>
2201 </message>
2202 <message>
2203 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="867"/>
2204 <source>D-Pad</source>
2205 <translation>Кнопки напрямків</translation>
2206 </message>
2207 <message>
2208 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1251"/>
2209 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1290"/>
2210 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1296"/>
2211 <source>L</source>
2212 <translation>L</translation>
2213 </message>
2214 <message>
2215 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1306"/>
2216 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1345"/>
2217 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1288"/>
2218 <source>ZL</source>
2219 <translation>ZL</translation>
2220 </message>
2221 <message>
2222 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1426"/>
2223 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1465"/>
2224 <source>Minus</source>
2225 <translation>Мінус</translation>
2226 </message>
2227 <message>
2228 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1475"/>
2229 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1514"/>
2230 <source>Capture</source>
2231 <translation>Захоплення</translation>
2232 </message>
2233 <message>
2234 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1545"/>
2235 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1584"/>
2236 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1287"/>
2237 <source>Plus</source>
2238 <translation>Плюс</translation>
2239 </message>
2240 <message>
2241 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1594"/>
2242 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1633"/>
2243 <source>Home</source>
2244 <translation>Home</translation>
2245 </message>
2246 <message>
2247 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1698"/>
2248 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1737"/>
2249 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1290"/>
2250 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1297"/>
2251 <source>R</source>
2252 <translation>R</translation>
2253 </message>
2254 <message>
2255 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1753"/>
2256 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1792"/>
2257 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1289"/>
2258 <source>ZR</source>
2259 <translation>ZR</translation>
2260 </message>
2261 <message>
2262 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1873"/>
2263 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1912"/>
2264 <source>SL</source>
2265 <translation>SL</translation>
2266 </message>
2267 <message>
2268 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1922"/>
2269 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="1961"/>
2270 <source>SR</source>
2271 <translation>SR</translation>
2272 </message>
2273 <message>
2274 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2030"/>
2275 <source>Motion 1</source>
2276 <translation>Рух 1</translation>
2277 </message>
2278 <message>
2279 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2079"/>
2280 <source>Motion 2</source>
2281 <translation>Рух 2</translation>
2282 </message>
2283 <message>
2284 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2170"/>
2285 <source>Face Buttons</source>
2286 <translation>Кнопки A/B/X/Y</translation>
2287 </message>
2288 <message>
2289 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2228"/>
2290 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2267"/>
2291 <source>X</source>
2292 <translation>X</translation>
2293 </message>
2294 <message>
2295 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2298"/>
2296 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2337"/>
2297 <source>Y</source>
2298 <translation>Y</translation>
2299 </message>
2300 <message>
2301 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2347"/>
2302 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2386"/>
2303 <source>A</source>
2304 <translation>A</translation>
2305 </message>
2306 <message>
2307 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2429"/>
2308 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2468"/>
2309 <source>B</source>
2310 <translation>B</translation>
2311 </message>
2312 <message>
2313 <location filename="../../src/yuzu/configuration/configure_input_player.ui" line="2516"/>
2314 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1292"/>
2315 <source>Right Stick</source>
2316 <translation>Правий міні-джойстик</translation>
2317 </message>
2318 <message>
2319 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="361"/>
2320 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="434"/>
2321 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="529"/>
2322 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="624"/>
2323 <source>Clear</source>
2324 <translation>Очистити</translation>
2325 </message>
2326 <message>
2327 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="363"/>
2328 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="436"/>
2329 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="533"/>
2330 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="552"/>
2331 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="626"/>
2332 <source>[not set]</source>
2333 <translation>[не задано]</translation>
2334 </message>
2335 <message>
2336 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="366"/>
2337 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="638"/>
2338 <source>Invert button</source>
2339 <translation>Інвертувати кнопку</translation>
2340 </message>
2341 <message>
2342 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="372"/>
2343 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="629"/>
2344 <source>Toggle button</source>
2345 <translation>Переключити кнопку</translation>
2346 </message>
2347 <message>
2348 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="380"/>
2349 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="580"/>
2350 <source>Invert axis</source>
2351 <translation>Інвертувати осі</translation>
2352 </message>
2353 <message>
2354 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="386"/>
2355 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="390"/>
2356 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="443"/>
2357 <source>Set threshold</source>
2358 <translation>Встановити поріг</translation>
2359 </message>
2360 <message>
2361 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="390"/>
2362 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="443"/>
2363 <source>Choose a value between 0% and 100%</source>
2364 <translation>Оберіть значення між 0% і 100%</translation>
2365 </message>
2366 <message>
2367 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="402"/>
2368 <source>Toggle axis</source>
2369 <translation>Переключити осі</translation>
2370 </message>
2371 <message>
2372 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="439"/>
2373 <source>Set gyro threshold</source>
2374 <translation>Встановити поріг гіроскопа</translation>
2375 </message>
2376 <message>
2377 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="485"/>
2378 <source>Map Analog Stick</source>
2379 <translation>Задати аналоговий міні-джойстик</translation>
2380 </message>
2381 <message>
2382 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="486"/>
2383 <source>After pressing OK, first move your joystick horizontally, and then vertically.
2384To invert the axes, first move your joystick vertically, and then horizontally.</source>
2385 <translation>Після натискання на ОК, рухайте ваш міні-джойстик горизонтально, а потім вертикально.
2386Щоб інвертувати осі, спочатку рухайте ваш міні-джойстик вертикально, а потім горизонтально.</translation>
2387 </message>
2388 <message>
2389 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="554"/>
2390 <source>Center axis</source>
2391 <translation>Центрувати осі</translation>
2392 </message>
2393 <message>
2394 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="662"/>
2395 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1016"/>
2396 <source>Deadzone: %1%</source>
2397 <translation>Мертва зона: %1%</translation>
2398 </message>
2399 <message>
2400 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="671"/>
2401 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1021"/>
2402 <source>Modifier Range: %1%</source>
2403 <translation>Діапазон модифікатора: %1%</translation>
2404 </message>
2405 <message>
2406 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="697"/>
2407 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1046"/>
2408 <source>Pro Controller</source>
2409 <translation>Контролер Pro</translation>
2410 </message>
2411 <message>
2412 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1050"/>
2413 <source>Dual Joycons</source>
2414 <translation>Подвійні Joy-Con&apos;и</translation>
2415 </message>
2416 <message>
2417 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1054"/>
2418 <source>Left Joycon</source>
2419 <translation>Лівий Joy-Con</translation>
2420 </message>
2421 <message>
2422 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1058"/>
2423 <source>Right Joycon</source>
2424 <translation>Правий Joy-Con</translation>
2425 </message>
2426 <message>
2427 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1062"/>
2428 <source>Handheld</source>
2429 <translation>Портативний</translation>
2430 </message>
2431 <message>
2432 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1066"/>
2433 <source>GameCube Controller</source>
2434 <translation>Контролер GameCube</translation>
2435 </message>
2436 <message>
2437 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1075"/>
2438 <source>Poke Ball Plus</source>
2439 <translation>Poke Ball Plus</translation>
2440 </message>
2441 <message>
2442 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1079"/>
2443 <source>NES Controller</source>
2444 <translation>Контролер NES</translation>
2445 </message>
2446 <message>
2447 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1083"/>
2448 <source>SNES Controller</source>
2449 <translation>Контролер SNES</translation>
2450 </message>
2451 <message>
2452 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1087"/>
2453 <source>N64 Controller</source>
2454 <translation>Контролер N64</translation>
2455 </message>
2456 <message>
2457 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1091"/>
2458 <source>Sega Genesis</source>
2459 <translation>Sega Genesis</translation>
2460 </message>
2461 <message>
2462 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1295"/>
2463 <source>Start / Pause</source>
2464 <translation>Старт / Пауза</translation>
2465 </message>
2466 <message>
2467 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1298"/>
2468 <source>Z</source>
2469 <translation>Z</translation>
2470 </message>
2471 <message>
2472 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1299"/>
2473 <source>Control Stick</source>
2474 <translation>Міні-джойстик керування</translation>
2475 </message>
2476 <message>
2477 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1300"/>
2478 <source>C-Stick</source>
2479 <translation>C-Джойстик</translation>
2480 </message>
2481 <message>
2482 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1401"/>
2483 <source>Shake!</source>
2484 <translation>Потрусіть!</translation>
2485 </message>
2486 <message>
2487 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1403"/>
2488 <source>[waiting]</source>
2489 <translation>[очікування]</translation>
2490 </message>
2491 <message>
2492 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1485"/>
2493 <source>New Profile</source>
2494 <translation>Новий профіль</translation>
2495 </message>
2496 <message>
2497 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1485"/>
2498 <source>Enter a profile name:</source>
2499 <translation>Введіть ім&apos;я профілю:</translation>
2500 </message>
2501 <message>
2502 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1493"/>
2503 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1501"/>
2504 <source>Create Input Profile</source>
2505 <translation>Створити профіль контролю</translation>
2506 </message>
2507 <message>
2508 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1494"/>
2509 <source>The given profile name is not valid!</source>
2510 <translation>Задане ім&apos;я профілю недійсне!</translation>
2511 </message>
2512 <message>
2513 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1502"/>
2514 <source>Failed to create the input profile &quot;%1&quot;</source>
2515 <translation>Не вдалося створити профіль контролю &quot;%1&quot;</translation>
2516 </message>
2517 <message>
2518 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1522"/>
2519 <source>Delete Input Profile</source>
2520 <translation>Видалити профіль контролю</translation>
2521 </message>
2522 <message>
2523 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1523"/>
2524 <source>Failed to delete the input profile &quot;%1&quot;</source>
2525 <translation>Не вдалося видалити профіль контролю &quot;%1&quot;</translation>
2526 </message>
2527 <message>
2528 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1545"/>
2529 <source>Load Input Profile</source>
2530 <translation>Завантажити профіль контролю</translation>
2531 </message>
2532 <message>
2533 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1546"/>
2534 <source>Failed to load the input profile &quot;%1&quot;</source>
2535 <translation>Не вдалося завантажити профіль контролю &quot;%1&quot;</translation>
2536 </message>
2537 <message>
2538 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1565"/>
2539 <source>Save Input Profile</source>
2540 <translation>Зберегти профіль контролю</translation>
2541 </message>
2542 <message>
2543 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="1566"/>
2544 <source>Failed to save the input profile &quot;%1&quot;</source>
2545 <translation>Не вдалося зберегти профіль контролю &quot;%1&quot;</translation>
2546 </message>
2547</context>
2548<context>
2549 <name>ConfigureInputProfileDialog</name>
2550 <message>
2551 <location filename="../../src/yuzu/configuration/configure_input_profile_dialog.ui" line="14"/>
2552 <source>Create Input Profile</source>
2553 <translation>Створити профіль контролю</translation>
2554 </message>
2555 <message>
2556 <location filename="../../src/yuzu/configuration/configure_input_profile_dialog.ui" line="40"/>
2557 <source>Clear</source>
2558 <translation>Очистити</translation>
2559 </message>
2560 <message>
2561 <location filename="../../src/yuzu/configuration/configure_input_profile_dialog.ui" line="47"/>
2562 <source>Defaults</source>
2563 <translation>За замовчуванням</translation>
2564 </message>
2565</context>
2566<context>
2567 <name>ConfigureMotionTouch</name>
2568 <message>
2569 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="6"/>
2570 <source>Configure Motion / Touch</source>
2571 <translation>Налаштування руху та сенсора</translation>
2572 </message>
2573 <message>
2574 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="15"/>
2575 <source>Touch</source>
2576 <translation>Сенсор</translation>
2577 </message>
2578 <message>
2579 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="23"/>
2580 <source>UDP Calibration:</source>
2581 <translation>Калібрація UDP:</translation>
2582 </message>
2583 <message>
2584 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="30"/>
2585 <source>(100, 50) - (1800, 850)</source>
2586 <translation>(100, 50) - (1800, 850)</translation>
2587 </message>
2588 <message>
2589 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="46"/>
2590 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="73"/>
2591 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="243"/>
2592 <source>Configure</source>
2593 <translation>Налаштувати</translation>
2594 </message>
2595 <message>
2596 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="57"/>
2597 <source>Touch from button profile:</source>
2598 <translation>Торкніться з профілю кнопки:</translation>
2599 </message>
2600 <message>
2601 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="85"/>
2602 <source>CemuhookUDP Config</source>
2603 <translation>Налаштування CemuhookUDP</translation>
2604 </message>
2605 <message>
2606 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="91"/>
2607 <source>You may use any Cemuhook compatible UDP input source to provide motion and touch input.</source>
2608 <translation>Ви можете використовувати будь-яке сумісне з Cemuhook джерело UDP сигналу для руху і сенсора.</translation>
2609 </message>
2610 <message>
2611 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="134"/>
2612 <source>Server:</source>
2613 <translation>Сервер:</translation>
2614 </message>
2615 <message>
2616 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="161"/>
2617 <source>Port:</source>
2618 <translation>Порт:</translation>
2619 </message>
2620 <message>
2621 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="188"/>
2622 <source>Learn More</source>
2623 <translation>Дізнатися більше</translation>
2624 </message>
2625 <message>
2626 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="201"/>
2627 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="266"/>
2628 <source>Test</source>
2629 <translation>Тест</translation>
2630 </message>
2631 <message>
2632 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="214"/>
2633 <source>Add Server</source>
2634 <translation>Додати сервер</translation>
2635 </message>
2636 <message>
2637 <location filename="../../src/yuzu/configuration/configure_motion_touch.ui" line="247"/>
2638 <source>Remove Server</source>
2639 <translation>Видалити сервер</translation>
2640 </message>
2641 <message>
2642 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="87"/>
2643 <source>&lt;a href=&apos;https://yuzu-emu.org/wiki/using-a-controller-or-android-phone-for-motion-or-touch-input&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn More&lt;/span&gt;&lt;/a&gt;</source>
2644 <translation>&lt;a href=&apos;https://yuzu-emu.org/wiki/using-a-controller-or-android-phone-for-motion-or-touch-input&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Дізнатися більше&lt;/span&gt;&lt;/a&gt;</translation>
2645 </message>
2646 <message>
2647 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="169"/>
2648 <source>%1:%2</source>
2649 <translation>%1:%2</translation>
2650 </message>
2651 <message>
2652 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="174"/>
2653 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="178"/>
2654 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="182"/>
2655 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="188"/>
2656 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="194"/>
2657 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="288"/>
2658 <source>yuzu</source>
2659 <translation>yuzu</translation>
2660 </message>
2661 <message>
2662 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="174"/>
2663 <source>Port number has invalid characters</source>
2664 <translation>Номер порту містить неприпустимі символи</translation>
2665 </message>
2666 <message>
2667 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="178"/>
2668 <source>Port has to be in range 0 and 65353</source>
2669 <translation>Порт повинен бути в районі від 0 до 65353</translation>
2670 </message>
2671 <message>
2672 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="182"/>
2673 <source>IP address is not valid</source>
2674 <translation>IP-адреса недійсна</translation>
2675 </message>
2676 <message>
2677 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="188"/>
2678 <source>This UDP server already exists</source>
2679 <translation>Цей UDP сервер уже існує</translation>
2680 </message>
2681 <message>
2682 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="194"/>
2683 <source>Unable to add more than 8 servers</source>
2684 <translation>Неможливо додати більше 8 серверів</translation>
2685 </message>
2686 <message>
2687 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="210"/>
2688 <source>Testing</source>
2689 <translation>Тестування</translation>
2690 </message>
2691 <message>
2692 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="226"/>
2693 <source>Configuring</source>
2694 <translation>Налаштування</translation>
2695 </message>
2696 <message>
2697 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="257"/>
2698 <source>Test Successful</source>
2699 <translation>Тест успішний</translation>
2700 </message>
2701 <message>
2702 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="258"/>
2703 <source>Successfully received data from the server.</source>
2704 <translation>Успішно отримано інформацію із сервера</translation>
2705 </message>
2706 <message>
2707 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="260"/>
2708 <source>Test Failed</source>
2709 <translation>Тест провалено</translation>
2710 </message>
2711 <message>
2712 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="261"/>
2713 <source>Could not receive valid data from the server.&lt;br&gt;Please verify that the server is set up correctly and the address and port are correct.</source>
2714 <translation>Не вдалося отримати дійсні дані з сервера.&lt;br&gt;Переконайтеся, що сервер правильно налаштований, а також перевірте адресу та порт.</translation>
2715 </message>
2716 <message>
2717 <location filename="../../src/yuzu/configuration/configure_motion_touch.cpp" line="289"/>
2718 <source>UDP Test or calibration configuration is in progress.&lt;br&gt;Please wait for them to finish.</source>
2719 <translation>Тест UDP або калібрація в процесі.&lt;br&gt;Будь ласка, зачекайте завершення.</translation>
2720 </message>
2721</context>
2722<context>
2723 <name>ConfigureNetwork</name>
2724 <message>
2725 <location filename="../../src/yuzu/configuration/configure_network.ui" line="14"/>
2726 <source>Form</source>
2727 <translation>Форма</translation>
2728 </message>
2729 <message>
2730 <location filename="../../src/yuzu/configuration/configure_network.ui" line="17"/>
2731 <source>Network</source>
2732 <translation>Мережа</translation>
2733 </message>
2734 <message>
2735 <location filename="../../src/yuzu/configuration/configure_network.ui" line="25"/>
2736 <source>General</source>
2737 <translation>Загальні</translation>
2738 </message>
2739 <message>
2740 <location filename="../../src/yuzu/configuration/configure_network.ui" line="34"/>
2741 <source>Network Interface</source>
2742 <translation>Інтерфейс мережі</translation>
2743 </message>
2744 <message>
2745 <location filename="../../src/yuzu/configuration/configure_network.cpp" line="15"/>
2746 <source>None</source>
2747 <translation>Нічого</translation>
2748 </message>
2749</context>
2750<context>
2751 <name>ConfigurePerGame</name>
2752 <message>
2753 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="12"/>
2754 <source>Dialog</source>
2755 <translation>Діалог</translation>
2756 </message>
2757 <message>
2758 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="26"/>
2759 <source>Info</source>
2760 <translation>Інформація</translation>
2761 </message>
2762 <message>
2763 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="85"/>
2764 <source>Name</source>
2765 <translation>Назва</translation>
2766 </message>
2767 <message>
2768 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="92"/>
2769 <source>Title ID</source>
2770 <translation>Ідентифікатор гри</translation>
2771 </message>
2772 <message>
2773 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="129"/>
2774 <source>Filename</source>
2775 <translation>Ім&apos;я файлу</translation>
2776 </message>
2777 <message>
2778 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="156"/>
2779 <source>Format</source>
2780 <translation>Формат</translation>
2781 </message>
2782 <message>
2783 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="163"/>
2784 <source>Version</source>
2785 <translation>Версія</translation>
2786 </message>
2787 <message>
2788 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="170"/>
2789 <source>Size</source>
2790 <translation>Розмір</translation>
2791 </message>
2792 <message>
2793 <location filename="../../src/yuzu/configuration/configure_per_game.ui" line="177"/>
2794 <source>Developer</source>
2795 <translation>Розробник</translation>
2796 </message>
2797 <message>
2798 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="57"/>
2799 <source>Add-Ons</source>
2800 <translation>Доповнення</translation>
2801 </message>
2802 <message>
2803 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="58"/>
2804 <source>General</source>
2805 <translation>Загальні</translation>
2806 </message>
2807 <message>
2808 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="59"/>
2809 <source>System</source>
2810 <translation>Система</translation>
2811 </message>
2812 <message>
2813 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="60"/>
2814 <source>CPU</source>
2815 <translation>ЦП</translation>
2816 </message>
2817 <message>
2818 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="61"/>
2819 <source>Graphics</source>
2820 <translation>Графіка</translation>
2821 </message>
2822 <message>
2823 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="62"/>
2824 <source>Adv. Graphics</source>
2825 <translation>Розш. Графіка</translation>
2826 </message>
2827 <message>
2828 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="63"/>
2829 <source>Audio</source>
2830 <translation>Аудіо</translation>
2831 </message>
2832 <message>
2833 <location filename="../../src/yuzu/configuration/configure_per_game.cpp" line="66"/>
2834 <source>Properties</source>
2835 <translation>Властивості</translation>
2836 </message>
2837 <message>
2838 <location filename="../../src/yuzu/configuration/configuration_shared.cpp" line="91"/>
2839 <source>Use global configuration (%1)</source>
2840 <translation>Використовувати глобальне налаштування (%1)</translation>
2841 </message>
2842</context>
2843<context>
2844 <name>ConfigurePerGameAddons</name>
2845 <message>
2846 <location filename="../../src/yuzu/configuration/configure_per_game_addons.ui" line="14"/>
2847 <source>Form</source>
2848 <translation>Форма</translation>
2849 </message>
2850 <message>
2851 <location filename="../../src/yuzu/configuration/configure_per_game_addons.ui" line="17"/>
2852 <source>Add-Ons</source>
2853 <translation>Доповнення</translation>
2854 </message>
2855 <message>
2856 <location filename="../../src/yuzu/configuration/configure_per_game_addons.cpp" line="46"/>
2857 <source>Patch Name</source>
2858 <translation>Назва патчу</translation>
2859 </message>
2860 <message>
2861 <location filename="../../src/yuzu/configuration/configure_per_game_addons.cpp" line="47"/>
2862 <source>Version</source>
2863 <translation>Версія</translation>
2864 </message>
2865</context>
2866<context>
2867 <name>ConfigureProfileManager</name>
2868 <message>
2869 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="14"/>
2870 <source>Form</source>
2871 <translation>Форма</translation>
2872 </message>
2873 <message>
2874 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="17"/>
2875 <source>Profiles</source>
2876 <translation>Профілі</translation>
2877 </message>
2878 <message>
2879 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="25"/>
2880 <source>Profile Manager</source>
2881 <translation>Керування профілями</translation>
2882 </message>
2883 <message>
2884 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="42"/>
2885 <source>Current User</source>
2886 <translation>Поточний користувач</translation>
2887 </message>
2888 <message>
2889 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="80"/>
2890 <source>Username</source>
2891 <translation>Ім&apos;я користувача</translation>
2892 </message>
2893 <message>
2894 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="110"/>
2895 <source>Set Image</source>
2896 <translation>Обрати зображення</translation>
2897 </message>
2898 <message>
2899 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="130"/>
2900 <source>Add</source>
2901 <translation>Додати</translation>
2902 </message>
2903 <message>
2904 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="140"/>
2905 <source>Rename</source>
2906 <translation>Перейменувати</translation>
2907 </message>
2908 <message>
2909 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="150"/>
2910 <source>Remove</source>
2911 <translation>Видалити</translation>
2912 </message>
2913 <message>
2914 <location filename="../../src/yuzu/configuration/configure_profile_manager.ui" line="162"/>
2915 <source>Profile management is available only when game is not running.</source>
2916 <translation>Керування профілями недоступне, поки запущена гра.</translation>
2917 </message>
2918 <message>
2919 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="52"/>
2920 <source>%1
2921%2</source>
2922 <comment>%1 is the profile username, %2 is the formatted UUID (e.g. 00112233-4455-6677-8899-AABBCCDDEEFF))</comment>
2923 <translation>%1
2924%2</translation>
2925 </message>
2926 <message>
2927 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="70"/>
2928 <source>Enter Username</source>
2929 <translation>Введіть ім&apos;я користувача</translation>
2930 </message>
2931 <message>
2932 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="133"/>
2933 <source>Users</source>
2934 <translation>Користувачі</translation>
2935 </message>
2936 <message>
2937 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="195"/>
2938 <source>Enter a username for the new user:</source>
2939 <translation>Введіть ім&apos;я користувача для нового профілю:</translation>
2940 </message>
2941 <message>
2942 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="215"/>
2943 <source>Enter a new username:</source>
2944 <translation>Введіть нове ім&apos;я користувача:</translation>
2945 </message>
2946 <message>
2947 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="240"/>
2948 <source>Confirm Delete</source>
2949 <translation>Підтвердити видалення</translation>
2950 </message>
2951 <message>
2952 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="241"/>
2953 <source>You are about to delete user with name &quot;%1&quot;. Are you sure?</source>
2954 <translation>Ви збираєтеся видалити користувача &quot;%1&quot;. Ви впевнені?</translation>
2955 </message>
2956 <message>
2957 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="268"/>
2958 <source>Select User Image</source>
2959 <translation>Оберіть зображення користувача</translation>
2960 </message>
2961 <message>
2962 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="269"/>
2963 <source>JPEG Images (*.jpg *.jpeg)</source>
2964 <translation>Зображення JPEG (*.jpg *.jpeg)</translation>
2965 </message>
2966 <message>
2967 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="278"/>
2968 <source>Error deleting image</source>
2969 <translation>Помилка під час видалення зображення</translation>
2970 </message>
2971 <message>
2972 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="279"/>
2973 <source>Error occurred attempting to overwrite previous image at: %1.</source>
2974 <translation>Помилка під час спроби перезапису попереднього зображення в: %1.</translation>
2975 </message>
2976 <message>
2977 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="287"/>
2978 <source>Error deleting file</source>
2979 <translation>Помилка під час видалення файлу</translation>
2980 </message>
2981 <message>
2982 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="288"/>
2983 <source>Unable to delete existing file: %1.</source>
2984 <translation>Не вдалося видалити наявний файл: %1.</translation>
2985 </message>
2986 <message>
2987 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="295"/>
2988 <source>Error creating user image directory</source>
2989 <translation>Помилка під час створення папки користувацьких зображень</translation>
2990 </message>
2991 <message>
2992 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="296"/>
2993 <source>Unable to create directory %1 for storing user images.</source>
2994 <translation>Не вийшло створити папку %1 для зберігання зображень користувача.</translation>
2995 </message>
2996 <message>
2997 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="301"/>
2998 <source>Error copying user image</source>
2999 <translation>Помилка під час копіювання зображення користувача</translation>
3000 </message>
3001 <message>
3002 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="302"/>
3003 <source>Unable to copy image from %1 to %2</source>
3004 <translation>Не вийшло скопіювати зображення з %1 у %2</translation>
3005 </message>
3006 <message>
3007 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="311"/>
3008 <source>Error resizing user image</source>
3009 <translation>Помилка під час зміни розміру зображення користувача</translation>
3010 </message>
3011 <message>
3012 <location filename="../../src/yuzu/configuration/configure_profile_manager.cpp" line="312"/>
3013 <source>Unable to resize image</source>
3014 <translation>Неможливо змінити розмір зображення</translation>
3015 </message>
3016</context>
3017<context>
3018 <name>ConfigureRingController</name>
3019 <message>
3020 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="14"/>
3021 <source>Configure Ring Controller</source>
3022 <translation>Налаштування контролера Ring</translation>
3023 </message>
3024 <message>
3025 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="26"/>
3026 <source>If you want to use this controller configure player 1 as right controller and player 2 as dual joycon before starting the game to allow this controller to be detected properly.</source>
3027 <translation>Якщо ви хочете використовувати цей контролер, налаштуйте гравця 1 як правий контролер, а гравця 2 як подвійний Joy-Соп перед початком гри, щоб цей контролер був виявлений правильно.</translation>
3028 </message>
3029 <message>
3030 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="52"/>
3031 <source>Ring Sensor Parameters</source>
3032 <translation>Параметри сенсора Ring</translation>
3033 </message>
3034 <message>
3035 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="84"/>
3036 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="123"/>
3037 <source>Pull</source>
3038 <translation>Потягнути</translation>
3039 </message>
3040 <message>
3041 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="133"/>
3042 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="172"/>
3043 <source>Push</source>
3044 <translation>Натиснути</translation>
3045 </message>
3046 <message>
3047 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="206"/>
3048 <source>Deadzone: 0%</source>
3049 <translation>Мертва зона: 0%</translation>
3050 </message>
3051 <message>
3052 <location filename="../../src/yuzu/configuration/configure_ringcon.ui" line="248"/>
3053 <source>Restore Defaults</source>
3054 <translation>За замовчуванням</translation>
3055 </message>
3056 <message>
3057 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="159"/>
3058 <source>Clear</source>
3059 <translation>Очистити</translation>
3060 </message>
3061 <message>
3062 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="161"/>
3063 <source>[not set]</source>
3064 <translation>[не задано]</translation>
3065 </message>
3066 <message>
3067 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="163"/>
3068 <source>Invert axis</source>
3069 <translation>Інвертувати осі</translation>
3070 </message>
3071 <message>
3072 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="182"/>
3073 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="238"/>
3074 <source>Deadzone: %1%</source>
3075 <translation>Мертва зона: %1%</translation>
3076 </message>
3077 <message>
3078 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="262"/>
3079 <source>[waiting]</source>
3080 <translation>[очікування]</translation>
3081 </message>
3082</context>
3083<context>
3084 <name>ConfigureSystem</name>
3085 <message>
3086 <location filename="../../src/yuzu/configuration/configure_system.ui" line="14"/>
3087 <source>Form</source>
3088 <translation>Форма</translation>
3089 </message>
3090 <message>
3091 <location filename="../../src/yuzu/configuration/configure_system.ui" line="17"/>
3092 <source>System</source>
3093 <translation>Система</translation>
3094 </message>
3095 <message>
3096 <location filename="../../src/yuzu/configuration/configure_system.ui" line="25"/>
3097 <source>System Settings</source>
3098 <translation>Налаштування системи</translation>
3099 </message>
3100 <message>
3101 <location filename="../../src/yuzu/configuration/configure_system.ui" line="33"/>
3102 <source>Region:</source>
3103 <translation>Регіон:</translation>
3104 </message>
3105 <message>
3106 <location filename="../../src/yuzu/configuration/configure_system.ui" line="41"/>
3107 <source>Auto</source>
3108 <translation>Авто</translation>
3109 </message>
3110 <message>
3111 <location filename="../../src/yuzu/configuration/configure_system.ui" line="46"/>
3112 <source>Default</source>
3113 <translation>За замовчуванням</translation>
3114 </message>
3115 <message>
3116 <location filename="../../src/yuzu/configuration/configure_system.ui" line="51"/>
3117 <source>CET</source>
3118 <translation>CET</translation>
3119 </message>
3120 <message>
3121 <location filename="../../src/yuzu/configuration/configure_system.ui" line="56"/>
3122 <source>CST6CDT</source>
3123 <translation>CST6CDT</translation>
3124 </message>
3125 <message>
3126 <location filename="../../src/yuzu/configuration/configure_system.ui" line="61"/>
3127 <source>Cuba</source>
3128 <translation>Куба</translation>
3129 </message>
3130 <message>
3131 <location filename="../../src/yuzu/configuration/configure_system.ui" line="66"/>
3132 <source>EET</source>
3133 <translation>EET</translation>
3134 </message>
3135 <message>
3136 <location filename="../../src/yuzu/configuration/configure_system.ui" line="71"/>
3137 <source>Egypt</source>
3138 <translation>Єгипет</translation>
3139 </message>
3140 <message>
3141 <location filename="../../src/yuzu/configuration/configure_system.ui" line="76"/>
3142 <source>Eire</source>
3143 <translation>Ейре</translation>
3144 </message>
3145 <message>
3146 <location filename="../../src/yuzu/configuration/configure_system.ui" line="81"/>
3147 <source>EST</source>
3148 <translation>EST</translation>
3149 </message>
3150 <message>
3151 <location filename="../../src/yuzu/configuration/configure_system.ui" line="86"/>
3152 <source>EST5EDT</source>
3153 <translation>EST5EDT</translation>
3154 </message>
3155 <message>
3156 <location filename="../../src/yuzu/configuration/configure_system.ui" line="91"/>
3157 <source>GB</source>
3158 <translation>GB</translation>
3159 </message>
3160 <message>
3161 <location filename="../../src/yuzu/configuration/configure_system.ui" line="96"/>
3162 <source>GB-Eire</source>
3163 <translation>GB-Ейре</translation>
3164 </message>
3165 <message>
3166 <location filename="../../src/yuzu/configuration/configure_system.ui" line="101"/>
3167 <source>GMT</source>
3168 <translation>GMT</translation>
3169 </message>
3170 <message>
3171 <location filename="../../src/yuzu/configuration/configure_system.ui" line="106"/>
3172 <source>GMT+0</source>
3173 <translation>GMT+0</translation>
3174 </message>
3175 <message>
3176 <location filename="../../src/yuzu/configuration/configure_system.ui" line="111"/>
3177 <source>GMT-0</source>
3178 <translation>GMT-0</translation>
3179 </message>
3180 <message>
3181 <location filename="../../src/yuzu/configuration/configure_system.ui" line="116"/>
3182 <source>GMT0</source>
3183 <translation>GMT0</translation>
3184 </message>
3185 <message>
3186 <location filename="../../src/yuzu/configuration/configure_system.ui" line="121"/>
3187 <source>Greenwich</source>
3188 <translation>Гринвіч</translation>
3189 </message>
3190 <message>
3191 <location filename="../../src/yuzu/configuration/configure_system.ui" line="126"/>
3192 <source>Hongkong</source>
3193 <translation>Гонконг</translation>
3194 </message>
3195 <message>
3196 <location filename="../../src/yuzu/configuration/configure_system.ui" line="131"/>
3197 <source>HST</source>
3198 <translation>HST</translation>
3199 </message>
3200 <message>
3201 <location filename="../../src/yuzu/configuration/configure_system.ui" line="136"/>
3202 <source>Iceland</source>
3203 <translation>Ісландія</translation>
3204 </message>
3205 <message>
3206 <location filename="../../src/yuzu/configuration/configure_system.ui" line="141"/>
3207 <source>Iran</source>
3208 <translation>Іран</translation>
3209 </message>
3210 <message>
3211 <location filename="../../src/yuzu/configuration/configure_system.ui" line="146"/>
3212 <source>Israel</source>
3213 <translation>Ізраїль</translation>
3214 </message>
3215 <message>
3216 <location filename="../../src/yuzu/configuration/configure_system.ui" line="151"/>
3217 <source>Jamaica</source>
3218 <translation>Ямайка</translation>
3219 </message>
3220 <message>
3221 <location filename="../../src/yuzu/configuration/configure_system.ui" line="156"/>
3222 <location filename="../../src/yuzu/configuration/configure_system.ui" line="275"/>
3223 <source>Japan</source>
3224 <translation>Японія</translation>
3225 </message>
3226 <message>
3227 <location filename="../../src/yuzu/configuration/configure_system.ui" line="161"/>
3228 <source>Kwajalein</source>
3229 <translation>Кваджалейн</translation>
3230 </message>
3231 <message>
3232 <location filename="../../src/yuzu/configuration/configure_system.ui" line="166"/>
3233 <source>Libya</source>
3234 <translation>Лівія</translation>
3235 </message>
3236 <message>
3237 <location filename="../../src/yuzu/configuration/configure_system.ui" line="171"/>
3238 <source>MET</source>
3239 <translation>MET</translation>
3240 </message>
3241 <message>
3242 <location filename="../../src/yuzu/configuration/configure_system.ui" line="176"/>
3243 <source>MST</source>
3244 <translation>MST</translation>
3245 </message>
3246 <message>
3247 <location filename="../../src/yuzu/configuration/configure_system.ui" line="181"/>
3248 <source>MST7MDT</source>
3249 <translation>MST7MDT</translation>
3250 </message>
3251 <message>
3252 <location filename="../../src/yuzu/configuration/configure_system.ui" line="186"/>
3253 <source>Navajo</source>
3254 <translation>Навахо</translation>
3255 </message>
3256 <message>
3257 <location filename="../../src/yuzu/configuration/configure_system.ui" line="191"/>
3258 <source>NZ</source>
3259 <translation>NZ</translation>
3260 </message>
3261 <message>
3262 <location filename="../../src/yuzu/configuration/configure_system.ui" line="196"/>
3263 <source>NZ-CHAT</source>
3264 <translation>NZ-CHAT</translation>
3265 </message>
3266 <message>
3267 <location filename="../../src/yuzu/configuration/configure_system.ui" line="201"/>
3268 <source>Poland</source>
3269 <translation>Польща</translation>
3270 </message>
3271 <message>
3272 <location filename="../../src/yuzu/configuration/configure_system.ui" line="206"/>
3273 <source>Portugal</source>
3274 <translation>Португалія</translation>
3275 </message>
3276 <message>
3277 <location filename="../../src/yuzu/configuration/configure_system.ui" line="211"/>
3278 <source>PRC</source>
3279 <translation>PRC</translation>
3280 </message>
3281 <message>
3282 <location filename="../../src/yuzu/configuration/configure_system.ui" line="216"/>
3283 <source>PST8PDT</source>
3284 <translation>PST8PDT</translation>
3285 </message>
3286 <message>
3287 <location filename="../../src/yuzu/configuration/configure_system.ui" line="221"/>
3288 <source>ROC</source>
3289 <translation>ROC</translation>
3290 </message>
3291 <message>
3292 <location filename="../../src/yuzu/configuration/configure_system.ui" line="226"/>
3293 <source>ROK</source>
3294 <translation>ROK</translation>
3295 </message>
3296 <message>
3297 <location filename="../../src/yuzu/configuration/configure_system.ui" line="231"/>
3298 <source>Singapore</source>
3299 <translation>Сінгапур</translation>
3300 </message>
3301 <message>
3302 <location filename="../../src/yuzu/configuration/configure_system.ui" line="236"/>
3303 <source>Turkey</source>
3304 <translation>Туреччина</translation>
3305 </message>
3306 <message>
3307 <location filename="../../src/yuzu/configuration/configure_system.ui" line="241"/>
3308 <source>UCT</source>
3309 <translation>UCT</translation>
3310 </message>
3311 <message>
3312 <location filename="../../src/yuzu/configuration/configure_system.ui" line="246"/>
3313 <source>Universal</source>
3314 <translation>Універсальний</translation>
3315 </message>
3316 <message>
3317 <location filename="../../src/yuzu/configuration/configure_system.ui" line="251"/>
3318 <source>UTC</source>
3319 <translation>UTC</translation>
3320 </message>
3321 <message>
3322 <location filename="../../src/yuzu/configuration/configure_system.ui" line="256"/>
3323 <source>W-SU</source>
3324 <translation>W-SU</translation>
3325 </message>
3326 <message>
3327 <location filename="../../src/yuzu/configuration/configure_system.ui" line="261"/>
3328 <source>WET</source>
3329 <translation>WET</translation>
3330 </message>
3331 <message>
3332 <location filename="../../src/yuzu/configuration/configure_system.ui" line="266"/>
3333 <source>Zulu</source>
3334 <translation>Зулуси</translation>
3335 </message>
3336 <message>
3337 <location filename="../../src/yuzu/configuration/configure_system.ui" line="280"/>
3338 <source>USA</source>
3339 <translation>США</translation>
3340 </message>
3341 <message>
3342 <location filename="../../src/yuzu/configuration/configure_system.ui" line="285"/>
3343 <source>Europe</source>
3344 <translation>Європа</translation>
3345 </message>
3346 <message>
3347 <location filename="../../src/yuzu/configuration/configure_system.ui" line="290"/>
3348 <source>Australia</source>
3349 <translation>Австралія</translation>
3350 </message>
3351 <message>
3352 <location filename="../../src/yuzu/configuration/configure_system.ui" line="295"/>
3353 <source>China</source>
3354 <translation>Китай</translation>
3355 </message>
3356 <message>
3357 <location filename="../../src/yuzu/configuration/configure_system.ui" line="300"/>
3358 <source>Korea</source>
3359 <translation>Корея</translation>
3360 </message>
3361 <message>
3362 <location filename="../../src/yuzu/configuration/configure_system.ui" line="305"/>
3363 <source>Taiwan</source>
3364 <translation>Тайвань</translation>
3365 </message>
3366 <message>
3367 <location filename="../../src/yuzu/configuration/configure_system.ui" line="313"/>
3368 <source>Time Zone:</source>
3369 <translation>Часовий пояс:</translation>
3370 </message>
3371 <message>
3372 <location filename="../../src/yuzu/configuration/configure_system.ui" line="320"/>
3373 <source>Note: this can be overridden when region setting is auto-select</source>
3374 <translation>Примітка: може бути перезаписано якщо регіон вибирається автоматично</translation>
3375 </message>
3376 <message>
3377 <location filename="../../src/yuzu/configuration/configure_system.ui" line="324"/>
3378 <source>Japanese (日本語)</source>
3379 <translation>Японська (日本語)</translation>
3380 </message>
3381 <message>
3382 <location filename="../../src/yuzu/configuration/configure_system.ui" line="329"/>
3383 <source>English</source>
3384 <translation>Англійська (English)</translation>
3385 </message>
3386 <message>
3387 <location filename="../../src/yuzu/configuration/configure_system.ui" line="334"/>
3388 <source>French (français)</source>
3389 <translation>Французька (français)</translation>
3390 </message>
3391 <message>
3392 <location filename="../../src/yuzu/configuration/configure_system.ui" line="339"/>
3393 <source>German (Deutsch)</source>
3394 <translation>Німецька (Deutsch)</translation>
3395 </message>
3396 <message>
3397 <location filename="../../src/yuzu/configuration/configure_system.ui" line="344"/>
3398 <source>Italian (italiano)</source>
3399 <translation>Італійська (italiano)</translation>
3400 </message>
3401 <message>
3402 <location filename="../../src/yuzu/configuration/configure_system.ui" line="349"/>
3403 <source>Spanish (español)</source>
3404 <translation>Іспанська (español)</translation>
3405 </message>
3406 <message>
3407 <location filename="../../src/yuzu/configuration/configure_system.ui" line="354"/>
3408 <source>Chinese</source>
3409 <translation>Китайська</translation>
3410 </message>
3411 <message>
3412 <location filename="../../src/yuzu/configuration/configure_system.ui" line="359"/>
3413 <source>Korean (한국어)</source>
3414 <translation>Корейська (한국어)</translation>
3415 </message>
3416 <message>
3417 <location filename="../../src/yuzu/configuration/configure_system.ui" line="364"/>
3418 <source>Dutch (Nederlands)</source>
3419 <translation>Голландська (Nederlands)</translation>
3420 </message>
3421 <message>
3422 <location filename="../../src/yuzu/configuration/configure_system.ui" line="369"/>
3423 <source>Portuguese (português)</source>
3424 <translation>Португальська (português)</translation>
3425 </message>
3426 <message>
3427 <location filename="../../src/yuzu/configuration/configure_system.ui" line="374"/>
3428 <source>Russian (Русский)</source>
3429 <translation>Російська (Русский)</translation>
3430 </message>
3431 <message>
3432 <location filename="../../src/yuzu/configuration/configure_system.ui" line="379"/>
3433 <source>Taiwanese</source>
3434 <translation>Тайванська</translation>
3435 </message>
3436 <message>
3437 <location filename="../../src/yuzu/configuration/configure_system.ui" line="384"/>
3438 <source>British English</source>
3439 <translation>Британська Англійська</translation>
3440 </message>
3441 <message>
3442 <location filename="../../src/yuzu/configuration/configure_system.ui" line="389"/>
3443 <source>Canadian French</source>
3444 <translation>Канадська Французька</translation>
3445 </message>
3446 <message>
3447 <location filename="../../src/yuzu/configuration/configure_system.ui" line="394"/>
3448 <source>Latin American Spanish</source>
3449 <translation>Латиноамериканська Іспанська</translation>
3450 </message>
3451 <message>
3452 <location filename="../../src/yuzu/configuration/configure_system.ui" line="399"/>
3453 <source>Simplified Chinese</source>
3454 <translation>Спрощена Китайська</translation>
3455 </message>
3456 <message>
3457 <location filename="../../src/yuzu/configuration/configure_system.ui" line="404"/>
3458 <source>Traditional Chinese (正體中文)</source>
3459 <translation>Традиційна Китайська (正體中文)</translation>
3460 </message>
3461 <message>
3462 <location filename="../../src/yuzu/configuration/configure_system.ui" line="409"/>
3463 <source>Brazilian Portuguese (português do Brasil)</source>
3464 <translation>Бразильська Португальська (português do Brasil)</translation>
3465 </message>
3466 <message>
3467 <location filename="../../src/yuzu/configuration/configure_system.ui" line="417"/>
3468 <source>Custom RTC</source>
3469 <translation>Користувацький RTC</translation>
3470 </message>
3471 <message>
3472 <location filename="../../src/yuzu/configuration/configure_system.ui" line="424"/>
3473 <source>Language</source>
3474 <translation>Мова</translation>
3475 </message>
3476 <message>
3477 <location filename="../../src/yuzu/configuration/configure_system.ui" line="431"/>
3478 <source>RNG Seed</source>
3479 <translation>Сід RNG</translation>
3480 </message>
3481 <message>
3482 <location filename="../../src/yuzu/configuration/configure_system.ui" line="439"/>
3483 <source>Mono</source>
3484 <translation>Моно</translation>
3485 </message>
3486 <message>
3487 <location filename="../../src/yuzu/configuration/configure_system.ui" line="444"/>
3488 <source>Stereo</source>
3489 <translation>Стерео</translation>
3490 </message>
3491 <message>
3492 <location filename="../../src/yuzu/configuration/configure_system.ui" line="449"/>
3493 <source>Surround</source>
3494 <translation>Об&apos;ємний звук</translation>
3495 </message>
3496 <message>
3497 <location filename="../../src/yuzu/configuration/configure_system.ui" line="457"/>
3498 <source>Console ID:</source>
3499 <translation>Ідентифікатор консолі:</translation>
3500 </message>
3501 <message>
3502 <location filename="../../src/yuzu/configuration/configure_system.ui" line="464"/>
3503 <source>Sound output mode</source>
3504 <translation>Режим виводу звуку</translation>
3505 </message>
3506 <message>
3507 <location filename="../../src/yuzu/configuration/configure_system.ui" line="512"/>
3508 <source>Regenerate</source>
3509 <translation>Перегенерувати</translation>
3510 </message>
3511 <message>
3512 <location filename="../../src/yuzu/configuration/configure_system.ui" line="537"/>
3513 <source>System settings are available only when game is not running.</source>
3514 <translation>Налаштування системи доступні тільки тоді, коли гру не запущено.</translation>
3515 </message>
3516 <message>
3517 <location filename="../../src/yuzu/configuration/configure_system.cpp" line="161"/>
3518 <source>This will replace your current virtual Switch with a new one. Your current virtual Switch will not be recoverable. This might have unexpected effects in games. This might fail, if you use an outdated config savegame. Continue?</source>
3519 <translation>Це замінить ваш поточний віртуальний Switch новим. Ваш поточний віртуальний Switch буде безповоротно втрачено. Це може мати несподівані наслідки в іграх. Може не спрацювати, якщо ви використовуєте застарілу конфігурацію збережених ігор. Продовжити?</translation>
3520 </message>
3521 <message>
3522 <location filename="../../src/yuzu/configuration/configure_system.cpp" line="165"/>
3523 <source>Warning</source>
3524 <translation>Увага</translation>
3525 </message>
3526 <message>
3527 <location filename="../../src/yuzu/configuration/configure_system.cpp" line="173"/>
3528 <source>Console ID: 0x%1</source>
3529 <translation>Ідентифікатор консолі: 0x%1</translation>
3530 </message>
3531</context>
3532<context>
3533 <name>ConfigureTas</name>
3534 <message>
3535 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="11"/>
3536 <source>TAS</source>
3537 <translation>TAS</translation>
3538 </message>
3539 <message>
3540 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="17"/>
3541 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Reads controller input from scripts in the same format as TAS-nx scripts.&lt;br/&gt;For a more detailed explanation, please consult the &lt;a href=&quot;https://yuzu-emu.org/help/feature/tas/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;help page&lt;/span&gt;&lt;/a&gt; on the yuzu website.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
3542 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Зчитує вхідні дані контролера зі скриптів у тому ж форматі, що і скрипти TAS-nx.&lt;br/&gt;Для більш детального пояснення зверніться до &lt;a href=&quot;https://yuzu-emu.org/help/feature/tas/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#039be5;&quot;&gt;сторінки допомоги&lt;/span&gt;&lt;/a&gt; на сайті yuzu.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
3543 </message>
3544 <message>
3545 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="27"/>
3546 <source>To check which hotkeys control the playback/recording, please refer to the Hotkey settings (Configure -&gt; General -&gt; Hotkeys).</source>
3547 <translation>Щоб перевірити, які гарячі клавіші керують відтворенням/записом, зверніться до налаштувань гарячих клавіш (Налаштування - Загальні -&gt; Гарячі клавіші).</translation>
3548 </message>
3549 <message>
3550 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="37"/>
3551 <source>WARNING: This is an experimental feature.&lt;br/&gt;It will not play back scripts frame perfectly with the current, imperfect syncing method.</source>
3552 <translation>ПОПЕРЕДЖЕННЯ: Це експериментальна функція.&lt;br/&gt;Вона не буде ідеально відтворювати кадри сценаріїв за поточного недосконалого методу синхронізації.</translation>
3553 </message>
3554 <message>
3555 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="54"/>
3556 <source>Settings</source>
3557 <translation>Налаштування</translation>
3558 </message>
3559 <message>
3560 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="60"/>
3561 <source>Enable TAS features</source>
3562 <translation>Увімкнути функції TAS</translation>
3563 </message>
3564 <message>
3565 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="67"/>
3566 <source>Loop script</source>
3567 <translation>Зациклити скрипт</translation>
3568 </message>
3569 <message>
3570 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="77"/>
3571 <source>Pause execution during loads</source>
3572 <translation>Призупинити виконання під час завантаження</translation>
3573 </message>
3574 <message>
3575 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="91"/>
3576 <source>Script Directory</source>
3577 <translation>Папка для скриптів</translation>
3578 </message>
3579 <message>
3580 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="97"/>
3581 <source>Path</source>
3582 <translation>Шлях</translation>
3583 </message>
3584 <message>
3585 <location filename="../../src/yuzu/configuration/configure_tas.ui" line="104"/>
3586 <source>...</source>
3587 <translation>...</translation>
3588 </message>
3589</context>
3590<context>
3591 <name>ConfigureTasDialog</name>
3592 <message>
3593 <location filename="../../src/yuzu/configuration/configure_tas.cpp" line="19"/>
3594 <source>TAS Configuration</source>
3595 <translation>Налаштування TAS</translation>
3596 </message>
3597 <message>
3598 <location filename="../../src/yuzu/configuration/configure_tas.cpp" line="50"/>
3599 <source>Select TAS Load Directory...</source>
3600 <translation>Обрати папку завантаження TAS...</translation>
3601 </message>
3602</context>
3603<context>
3604 <name>ConfigureTouchFromButton</name>
3605 <message>
3606 <location filename="../../src/yuzu/configuration/configure_touch_from_button.ui" line="14"/>
3607 <source>Configure Touchscreen Mappings</source>
3608 <translation>Налаштування відображення сенсорного екрана</translation>
3609 </message>
3610 <message>
3611 <location filename="../../src/yuzu/configuration/configure_touch_from_button.ui" line="22"/>
3612 <source>Mapping:</source>
3613 <translation>Прив&apos;язки:</translation>
3614 </message>
3615 <message>
3616 <location filename="../../src/yuzu/configuration/configure_touch_from_button.ui" line="48"/>
3617 <source>New</source>
3618 <translation>Новий</translation>
3619 </message>
3620 <message>
3621 <location filename="../../src/yuzu/configuration/configure_touch_from_button.ui" line="61"/>
3622 <source>Delete</source>
3623 <translation>Видалити</translation>
3624 </message>
3625 <message>
3626 <location filename="../../src/yuzu/configuration/configure_touch_from_button.ui" line="74"/>
3627 <source>Rename</source>
3628 <translation>Перейменувати</translation>
3629 </message>
3630 <message>
3631 <location filename="../../src/yuzu/configuration/configure_touch_from_button.ui" line="92"/>
3632 <source>Click the bottom area to add a point, then press a button to bind.
3633Drag points to change position, or double-click table cells to edit values.</source>
3634 <translation>Натисніть на нижній області, щоб додати точку, після чого натисніть кнопку для прив&apos;язки.
3635Перетягніть точки, щоб змінити позицію, або натисніть двічі на комірки таблиці для зміни значень.</translation>
3636 </message>
3637 <message>
3638 <location filename="../../src/yuzu/configuration/configure_touch_from_button.ui" line="116"/>
3639 <source>Delete Point</source>
3640 <translation>Видалити точку</translation>
3641 </message>
3642 <message>
3643 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="78"/>
3644 <source>Button</source>
3645 <translation>Кнопка</translation>
3646 </message>
3647 <message>
3648 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="78"/>
3649 <source>X</source>
3650 <comment>X axis</comment>
3651 <translation>X</translation>
3652 </message>
3653 <message>
3654 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="78"/>
3655 <source>Y</source>
3656 <comment>Y axis</comment>
3657 <translation>Y</translation>
3658 </message>
3659 <message>
3660 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="195"/>
3661 <source>New Profile</source>
3662 <translation>Новий профіль</translation>
3663 </message>
3664 <message>
3665 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="195"/>
3666 <source>Enter the name for the new profile.</source>
3667 <translation>Введіть ім&apos;я вашого нового профілю.</translation>
3668 </message>
3669 <message>
3670 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="206"/>
3671 <source>Delete Profile</source>
3672 <translation>Видалити профіль</translation>
3673 </message>
3674 <message>
3675 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="206"/>
3676 <source>Delete profile %1?</source>
3677 <translation>Видалити профіль %1?</translation>
3678 </message>
3679 <message>
3680 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="219"/>
3681 <source>Rename Profile</source>
3682 <translation>Перейменувати профіль</translation>
3683 </message>
3684 <message>
3685 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="219"/>
3686 <source>New name:</source>
3687 <translation>Нова назва:</translation>
3688 </message>
3689 <message>
3690 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="231"/>
3691 <source>[press key]</source>
3692 <translation>[натисніть клавішу]</translation>
3693 </message>
3694</context>
3695<context>
3696 <name>ConfigureTouchscreenAdvanced</name>
3697 <message>
3698 <location filename="../../src/yuzu/configuration/configure_touchscreen_advanced.ui" line="14"/>
3699 <source>Configure Touchscreen</source>
3700 <translation>Налаштування сенсорного екрана</translation>
3701 </message>
3702 <message>
3703 <location filename="../../src/yuzu/configuration/configure_touchscreen_advanced.ui" line="26"/>
3704 <source>Warning: The settings in this page affect the inner workings of yuzu&apos;s emulated touchscreen. Changing them may result in undesirable behavior, such as the touchscreen partially or not working. You should only use this page if you know what you are doing.</source>
3705 <translation>Увага: Налаштування на цій сторінці впливають на внутрішню роботу емульованого сенсорного екрана yuzu. Їх зміна може призвести до небажаної поведінки, як часткова або повна непрацездатність сенсорного екрана. Використовуйте цю сторінку лише якщо ви знаєте, що робите.</translation>
3706 </message>
3707 <message>
3708 <location filename="../../src/yuzu/configuration/configure_touchscreen_advanced.ui" line="52"/>
3709 <source>Touch Parameters</source>
3710 <translation>Параметри сенсора</translation>
3711 </message>
3712 <message>
3713 <location filename="../../src/yuzu/configuration/configure_touchscreen_advanced.ui" line="71"/>
3714 <source>Touch Diameter Y</source>
3715 <translation>Діаметр сенсора Y</translation>
3716 </message>
3717 <message>
3718 <location filename="../../src/yuzu/configuration/configure_touchscreen_advanced.ui" line="91"/>
3719 <source>Touch Diameter X</source>
3720 <translation>Діаметр сенсора X</translation>
3721 </message>
3722 <message>
3723 <location filename="../../src/yuzu/configuration/configure_touchscreen_advanced.ui" line="98"/>
3724 <source>Rotational Angle</source>
3725 <translation>Кут повороту</translation>
3726 </message>
3727 <message>
3728 <location filename="../../src/yuzu/configuration/configure_touchscreen_advanced.ui" line="132"/>
3729 <source>Restore Defaults</source>
3730 <translation>За замовчуванням</translation>
3731 </message>
3732</context>
3733<context>
3734 <name>ConfigureUI</name>
3735 <message>
3736 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="20"/>
3737 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="28"/>
3738 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="40"/>
3739 <source>None</source>
3740 <translation>Нічого</translation>
3741 </message>
3742 <message>
3743 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="21"/>
3744 <source>Small (32x32)</source>
3745 <translation>Маленький (32х32)</translation>
3746 </message>
3747 <message>
3748 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="22"/>
3749 <source>Standard (64x64)</source>
3750 <translation>Стандартний (64х64)</translation>
3751 </message>
3752 <message>
3753 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="23"/>
3754 <source>Large (128x128)</source>
3755 <translation>Великий (128х128)</translation>
3756 </message>
3757 <message>
3758 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="24"/>
3759 <source>Full Size (256x256)</source>
3760 <translation>Повнорозмірний (256х256)</translation>
3761 </message>
3762 <message>
3763 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="29"/>
3764 <source>Small (24x24)</source>
3765 <translation>Маленький (24х24)</translation>
3766 </message>
3767 <message>
3768 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="30"/>
3769 <source>Standard (48x48)</source>
3770 <translation>Стандартний (48х48)</translation>
3771 </message>
3772 <message>
3773 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="31"/>
3774 <source>Large (72x72)</source>
3775 <translation>Великий (72х72)</translation>
3776 </message>
3777 <message>
3778 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="36"/>
3779 <source>Filename</source>
3780 <translation>Ім&apos;я файлу</translation>
3781 </message>
3782 <message>
3783 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="37"/>
3784 <source>Filetype</source>
3785 <translation>Тип файлу</translation>
3786 </message>
3787 <message>
3788 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="38"/>
3789 <source>Title ID</source>
3790 <translation>Ідентифікатор гри</translation>
3791 </message>
3792 <message>
3793 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="39"/>
3794 <source>Title Name</source>
3795 <translation>Назва гри</translation>
3796 </message>
3797</context>
3798<context>
3799 <name>ConfigureUi</name>
3800 <message>
3801 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="14"/>
3802 <source>Form</source>
3803 <translation>Форма</translation>
3804 </message>
3805 <message>
3806 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="17"/>
3807 <source>UI</source>
3808 <translation>Інтерфейс</translation>
3809 </message>
3810 <message>
3811 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="23"/>
3812 <source>General</source>
3813 <translation>Загальні</translation>
3814 </message>
3815 <message>
3816 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="31"/>
3817 <source>Note: Changing language will apply your configuration.</source>
3818 <translation>Примітка: Зміна мови призведе до застосування налаштувань.</translation>
3819 </message>
3820 <message>
3821 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="43"/>
3822 <source>Interface language:</source>
3823 <translation>Мова інтерфейсу:</translation>
3824 </message>
3825 <message>
3826 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="57"/>
3827 <source>Theme:</source>
3828 <translation>Тема:</translation>
3829 </message>
3830 <message>
3831 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="74"/>
3832 <source>Game List</source>
3833 <translation>Список ігор</translation>
3834 </message>
3835 <message>
3836 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="82"/>
3837 <source>Show Compatibility List</source>
3838 <translation>Показати список сумісності</translation>
3839 </message>
3840 <message>
3841 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="89"/>
3842 <source>Show Add-Ons Column</source>
3843 <translation>Показувати стовпець доповнень</translation>
3844 </message>
3845 <message>
3846 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="98"/>
3847 <source>Game Icon Size:</source>
3848 <translation>Розмір іконки гри:</translation>
3849 </message>
3850 <message>
3851 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="112"/>
3852 <source>Folder Icon Size:</source>
3853 <translation>Розмір іконки папки:</translation>
3854 </message>
3855 <message>
3856 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="126"/>
3857 <source>Row 1 Text:</source>
3858 <translation>Текст 1-го рядку:</translation>
3859 </message>
3860 <message>
3861 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="140"/>
3862 <source>Row 2 Text:</source>
3863 <translation>Текст 2-го рядку:</translation>
3864 </message>
3865 <message>
3866 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="157"/>
3867 <source>Screenshots</source>
3868 <translation>Знімки екрану</translation>
3869 </message>
3870 <message>
3871 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="165"/>
3872 <source>Ask Where To Save Screenshots (Windows Only)</source>
3873 <translation>Запитувати куди зберігати знімки екрану (Тільки для Windows)</translation>
3874 </message>
3875 <message>
3876 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="174"/>
3877 <source>Screenshots Path: </source>
3878 <translation>Папка для знімків екрану:</translation>
3879 </message>
3880 <message>
3881 <location filename="../../src/yuzu/configuration/configure_ui.ui" line="184"/>
3882 <source>...</source>
3883 <translation>...</translation>
3884 </message>
3885 <message>
3886 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="94"/>
3887 <source>Select Screenshots Path...</source>
3888 <translation>Виберіть папку для знімків екрану...</translation>
3889 </message>
3890 <message>
3891 <location filename="../../src/yuzu/configuration/configure_ui.cpp" line="219"/>
3892 <source>&lt;System&gt;</source>
3893 <translation>&lt;System&gt;</translation>
3894 </message>
3895</context>
3896<context>
3897 <name>ConfigureVibration</name>
3898 <message>
3899 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="14"/>
3900 <source>Configure Vibration</source>
3901 <translation>Налаштування вібрації</translation>
3902 </message>
3903 <message>
3904 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="23"/>
3905 <source>Press any controller button to vibrate the controller.</source>
3906 <translation>Натисніть будь-яку кнопку контролера, щоб викликати вібрацію.</translation>
3907 </message>
3908 <message>
3909 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="30"/>
3910 <source>Vibration</source>
3911 <translation>Вібрація</translation>
3912 </message>
3913 <message>
3914 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="63"/>
3915 <source>Player 1</source>
3916 <translation>Гравець 1</translation>
3917 </message>
3918 <message>
3919 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="96"/>
3920 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="148"/>
3921 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="200"/>
3922 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="252"/>
3923 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="322"/>
3924 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="374"/>
3925 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="426"/>
3926 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="478"/>
3927 <source>%</source>
3928 <translation>%</translation>
3929 </message>
3930 <message>
3931 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="115"/>
3932 <source>Player 2</source>
3933 <translation>Гравець 2</translation>
3934 </message>
3935 <message>
3936 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="167"/>
3937 <source>Player 3</source>
3938 <translation>Гравець 3</translation>
3939 </message>
3940 <message>
3941 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="219"/>
3942 <source>Player 4</source>
3943 <translation>Гравець 4</translation>
3944 </message>
3945 <message>
3946 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="289"/>
3947 <source>Player 5</source>
3948 <translation>Гравець 5</translation>
3949 </message>
3950 <message>
3951 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="341"/>
3952 <source>Player 6</source>
3953 <translation>Гравець 6</translation>
3954 </message>
3955 <message>
3956 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="393"/>
3957 <source>Player 7</source>
3958 <translation>Гравець 7</translation>
3959 </message>
3960 <message>
3961 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="445"/>
3962 <source>Player 8</source>
3963 <translation>Гравець 8</translation>
3964 </message>
3965 <message>
3966 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="503"/>
3967 <source>Settings</source>
3968 <translation>Налаштування</translation>
3969 </message>
3970 <message>
3971 <location filename="../../src/yuzu/configuration/configure_vibration.ui" line="509"/>
3972 <source>Enable Accurate Vibration</source>
3973 <translation>Увімкнути точну вібрацію</translation>
3974 </message>
3975</context>
3976<context>
3977 <name>ConfigureWeb</name>
3978 <message>
3979 <location filename="../../src/yuzu/configuration/configure_web.ui" line="14"/>
3980 <source>Form</source>
3981 <translation>Форма</translation>
3982 </message>
3983 <message>
3984 <location filename="../../src/yuzu/configuration/configure_web.ui" line="17"/>
3985 <source>Web</source>
3986 <translation>Мережа</translation>
3987 </message>
3988 <message>
3989 <location filename="../../src/yuzu/configuration/configure_web.ui" line="25"/>
3990 <source>yuzu Web Service</source>
3991 <translation>Веб-сервіс yuzu</translation>
3992 </message>
3993 <message>
3994 <location filename="../../src/yuzu/configuration/configure_web.ui" line="31"/>
3995 <source>By providing your username and token, you agree to allow yuzu to collect additional usage data, which may include user identifying information.</source>
3996 <translation>Надаючи своє ім&apos;я користувача і токен, ви погоджуєтеся дозволити yuzu збирати додаткові дані про використання, які можуть включати інформацію, що ідентифікує користувача.</translation>
3997 </message>
3998 <message>
3999 <location filename="../../src/yuzu/configuration/configure_web.ui" line="49"/>
4000 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="159"/>
4001 <source>Verify</source>
4002 <translation>Підтвердити</translation>
4003 </message>
4004 <message>
4005 <location filename="../../src/yuzu/configuration/configure_web.ui" line="56"/>
4006 <source>Sign up</source>
4007 <translation>Реєстрація</translation>
4008 </message>
4009 <message>
4010 <location filename="../../src/yuzu/configuration/configure_web.ui" line="66"/>
4011 <source>Token: </source>
4012 <translation>Токен:</translation>
4013 </message>
4014 <message>
4015 <location filename="../../src/yuzu/configuration/configure_web.ui" line="76"/>
4016 <source>Username: </source>
4017 <translation>Ім&apos;я користувача:</translation>
4018 </message>
4019 <message>
4020 <location filename="../../src/yuzu/configuration/configure_web.ui" line="93"/>
4021 <source>What is my token?</source>
4022 <translation>Що таке токен і де його знайти?</translation>
4023 </message>
4024 <message>
4025 <location filename="../../src/yuzu/configuration/configure_web.ui" line="118"/>
4026 <source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
4027 <translation>Налаштування веб-служби можуть бути змінені тільки в тому випадку, коли не хоститься публічна кімната.</translation>
4028 </message>
4029 <message>
4030 <location filename="../../src/yuzu/configuration/configure_web.ui" line="128"/>
4031 <source>Telemetry</source>
4032 <translation>Телеметрія</translation>
4033 </message>
4034 <message>
4035 <location filename="../../src/yuzu/configuration/configure_web.ui" line="134"/>
4036 <source>Share anonymous usage data with the yuzu team</source>
4037 <translation>Ділитися анонімною інформацією про використання з командою yuzu</translation>
4038 </message>
4039 <message>
4040 <location filename="../../src/yuzu/configuration/configure_web.ui" line="141"/>
4041 <source>Learn more</source>
4042 <translation>Дізнатися більше</translation>
4043 </message>
4044 <message>
4045 <location filename="../../src/yuzu/configuration/configure_web.ui" line="150"/>
4046 <source>Telemetry ID:</source>
4047 <translation>Ідентифікатор телеметрії:</translation>
4048 </message>
4049 <message>
4050 <location filename="../../src/yuzu/configuration/configure_web.ui" line="166"/>
4051 <source>Regenerate</source>
4052 <translation>Перегенерувати</translation>
4053 </message>
4054 <message>
4055 <location filename="../../src/yuzu/configuration/configure_web.ui" line="180"/>
4056 <source>Discord Presence</source>
4057 <translation>Discord Presence</translation>
4058 </message>
4059 <message>
4060 <location filename="../../src/yuzu/configuration/configure_web.ui" line="186"/>
4061 <source>Show Current Game in your Discord Status</source>
4062 <translation>Показувати поточну гру у вашому статусі Discord</translation>
4063 </message>
4064 <message>
4065 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="68"/>
4066 <source>&lt;a href=&apos;https://yuzu-emu.org/help/feature/telemetry/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
4067 <translation>&lt;a href=&apos;https://yuzu-emu.org/help/feature/telemetry/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Дізнатися більше&lt;/span&gt;&lt;/a&gt;</translation>
4068 </message>
4069 <message>
4070 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="72"/>
4071 <source>&lt;a href=&apos;https://profile.yuzu-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
4072 <translation>&lt;a href=&apos;https://profile.yuzu-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Реєстрація&lt;/span&gt;&lt;/a&gt;</translation>
4073 </message>
4074 <message>
4075 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="76"/>
4076 <source>&lt;a href=&apos;https://yuzu-emu.org/wiki/yuzu-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
4077 <translation>&lt;a href=&apos;https://yuzu-emu.org/wiki/yuzu-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Що таке токен і де його знайти?&lt;/span&gt;&lt;/a&gt;</translation>
4078 </message>
4079 <message>
4080 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="80"/>
4081 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="125"/>
4082 <source>Telemetry ID: 0x%1</source>
4083 <translation>Ідентифікатор телеметрії: 0x%1</translation>
4084 </message>
4085 <message>
4086 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="91"/>
4087 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="170"/>
4088 <source>Unspecified</source>
4089 <translation>Відсутній</translation>
4090 </message>
4091 <message>
4092 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="117"/>
4093 <source>Token not verified</source>
4094 <translation>Токен не підтверджено</translation>
4095 </message>
4096 <message>
4097 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="118"/>
4098 <source>Token was not verified. The change to your token has not been saved.</source>
4099 <translation>Токен не було підтверджено. Зміну вашого токена не було збережено.</translation>
4100 </message>
4101 <message>
4102 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="141"/>
4103 <source>Unverified, please click Verify before saving configuration</source>
4104 <comment>Tooltip</comment>
4105 <translation>Не підтверджено, будь ласка, натисніть кнопку Підтвердити, перш ніж зберігати конфігурацію.</translation>
4106 </message>
4107 <message>
4108 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="147"/>
4109 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="149"/>
4110 <source>Verifying...</source>
4111 <translation>Підтверждення...</translation>
4112 </message>
4113 <message>
4114 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="164"/>
4115 <source>Verified</source>
4116 <comment>Tooltip</comment>
4117 <translation>Підтверджено</translation>
4118 </message>
4119 <message>
4120 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="169"/>
4121 <source>Verification failed</source>
4122 <comment>Tooltip</comment>
4123 <translation>Підтверждення не було успішним</translation>
4124 </message>
4125 <message>
4126 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="171"/>
4127 <source>Verification failed</source>
4128 <translation>Підтверждення не було успішним</translation>
4129 </message>
4130 <message>
4131 <location filename="../../src/yuzu/configuration/configure_web.cpp" line="172"/>
4132 <source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
4133 <translation>Підтверждення не було успішним. Переконайтеся, що ви правильно ввели свій токен і що ваше інтернет-з&apos;єднання працює.</translation>
4134 </message>
4135</context>
4136<context>
4137 <name>ControllerDialog</name>
4138 <message>
4139 <location filename="../../src/yuzu/debugger/controller.cpp" line="20"/>
4140 <source>Controller P1</source>
4141 <translation>Контролер P1</translation>
4142 </message>
4143 <message>
4144 <location filename="../../src/yuzu/debugger/controller.cpp" line="59"/>
4145 <source>&amp;Controller P1</source>
4146 <translation>[&amp;C] Контролер P1</translation>
4147 </message>
4148</context>
4149<context>
4150 <name>DirectConnect</name>
4151 <message>
4152 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="14"/>
4153 <source>Direct Connect</source>
4154 <translation>Пряме підключення</translation>
4155 </message>
4156 <message>
4157 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="33"/>
4158 <source>IP Address</source>
4159 <translation>IP-адреса</translation>
4160 </message>
4161 <message>
4162 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="56"/>
4163 <source>IP</source>
4164 <translation>IP</translation>
4165 </message>
4166 <message>
4167 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="63"/>
4168 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;IPv4 address of the host&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
4169 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;IPv4 адреса хоста&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
4170 </message>
4171 <message>
4172 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="73"/>
4173 <source>Port</source>
4174 <translation>Порт</translation>
4175 </message>
4176 <message>
4177 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="80"/>
4178 <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Port number the host is listening on&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
4179 <translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Номер порту, який прослуховується хостом&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
4180 </message>
4181 <message>
4182 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="100"/>
4183 <source>Nickname</source>
4184 <translation>Псевдонім</translation>
4185 </message>
4186 <message>
4187 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="114"/>
4188 <source>Password</source>
4189 <translation>Пароль</translation>
4190 </message>
4191 <message>
4192 <location filename="../../src/yuzu/multiplayer/direct_connect.ui" line="156"/>
4193 <source>Connect</source>
4194 <translation>Підключитися</translation>
4195 </message>
4196</context>
4197<context>
4198 <name>DirectConnectWindow</name>
4199 <message>
4200 <location filename="../../src/yuzu/multiplayer/direct_connect.cpp" line="127"/>
4201 <source>Connecting</source>
4202 <translation>Підключення</translation>
4203 </message>
4204 <message>
4205 <location filename="../../src/yuzu/multiplayer/direct_connect.cpp" line="132"/>
4206 <source>Connect</source>
4207 <translation>Підключитися</translation>
4208 </message>
4209</context>
4210<context>
4211 <name>GMainWindow</name>
4212 <message>
4213 <location filename="../../src/yuzu/main.cpp" line="188"/>
4214 <source>&lt;a href=&apos;https://yuzu-emu.org/help/feature/telemetry/&apos;&gt;Anonymous data is collected&lt;/a&gt; to help improve yuzu. &lt;br/&gt;&lt;br/&gt;Would you like to share your usage data with us?</source>
4215 <translation>&lt;a href=&apos;https://yuzu-emu.org/help/feature/telemetry/&apos;&gt;Анонімні дані збираються для того,&lt;/a&gt; щоб допомогти поліпшити роботу yuzu. &lt;br/&gt;&lt;br/&gt;Хотіли б ви ділитися даними про використання з нами?</translation>
4216 </message>
4217 <message>
4218 <location filename="../../src/yuzu/main.cpp" line="191"/>
4219 <source>Telemetry</source>
4220 <translation>Телеметрія</translation>
4221 </message>
4222 <message>
4223 <location filename="../../src/yuzu/main.cpp" line="405"/>
4224 <source>Broken Vulkan Installation Detected</source>
4225 <translation>Виявлено пошкоджену інсталяцію Vulkan</translation>
4226 </message>
4227 <message>
4228 <location filename="../../src/yuzu/main.cpp" line="406"/>
4229 <source>Vulkan initialization failed during boot.&lt;br&gt;&lt;br&gt;Click &lt;a href=&apos;https://yuzu-emu.org/wiki/faq/#yuzu-starts-with-the-error-broken-vulkan-installation-detected&apos;&gt;here for instructions to fix the issue&lt;/a&gt;.</source>
4230 <translation>Не вдалося виконати ініціалізацію Vulkan під час завантаження.&lt;br&gt;&lt;br&gt;Натисніть &lt;a href=&apos;https://yuzu-emu.org/wiki/faq/#yuzu-starts-with-the-error-broken-vulkan-installation-detected&apos;&gt;тут для отримання інструкцій щодо усунення проблеми&lt;/a&gt;.</translation>
4231 </message>
4232 <message>
4233 <location filename="../../src/yuzu/main.cpp" line="734"/>
4234 <source>Loading Web Applet...</source>
4235 <translation>Завантаження веб-аплета...</translation>
4236 </message>
4237 <message>
4238 <location filename="../../src/yuzu/main.cpp" line="781"/>
4239 <location filename="../../src/yuzu/main.cpp" line="784"/>
4240 <source>Disable Web Applet</source>
4241 <translation>Вимкнути веб-аплет</translation>
4242 </message>
4243 <message>
4244 <location filename="../../src/yuzu/main.cpp" line="785"/>
4245 <source>Disabling the web applet can lead to undefined behavior and should only be used with Super Mario 3D All-Stars. Are you sure you want to disable the web applet?
4246(This can be re-enabled in the Debug settings.)</source>
4247 <translation>Вимкнення веб-апплета може призвести до несподіваної поведінки, і його слід вимикати лише заради Super Mario 3D All-Stars. Ви впевнені, що хочете вимкнути веб-апплет?
4248(Його можна знову ввімкнути в налаштуваннях налагодження.)</translation>
4249 </message>
4250 <message>
4251 <location filename="../../src/yuzu/main.cpp" line="892"/>
4252 <source>The amount of shaders currently being built</source>
4253 <translation>Кількість створюваних шейдерів на цей момент</translation>
4254 </message>
4255 <message>
4256 <location filename="../../src/yuzu/main.cpp" line="894"/>
4257 <source>The current selected resolution scaling multiplier.</source>
4258 <translation>Поточний обраний множник масштабування роздільної здатності.</translation>
4259 </message>
4260 <message>
4261 <location filename="../../src/yuzu/main.cpp" line="897"/>
4262 <source>Current emulation speed. Values higher or lower than 100% indicate emulation is running faster or slower than a Switch.</source>
4263 <translation>Поточна швидкість емуляції. Значення вище або нижче 100% вказують на те, що емуляція йде швидше або повільніше, ніж на Switch.</translation>
4264 </message>
4265 <message>
4266 <location filename="../../src/yuzu/main.cpp" line="900"/>
4267 <source>How many frames per second the game is currently displaying. This will vary from game to game and scene to scene.</source>
4268 <translation>Кількість кадрів на секунду в цей момент. Значення буде змінюватися між іграми та сценами.</translation>
4269 </message>
4270 <message>
4271 <location filename="../../src/yuzu/main.cpp" line="904"/>
4272 <source>Time taken to emulate a Switch frame, not counting framelimiting or v-sync. For full-speed emulation this should be at most 16.67 ms.</source>
4273 <translation>Час, який потрібен для емуляції 1 кадру Switch, не беручи до уваги обмеження FPS або вертикальну синхронізацію. Для емуляції в повній швидкості значення має бути не більше 16,67 мс.</translation>
4274 </message>
4275 <message>
4276 <location filename="../../src/yuzu/main.cpp" line="983"/>
4277 <source>VULKAN</source>
4278 <translation>VULKAN</translation>
4279 </message>
4280 <message>
4281 <location filename="../../src/yuzu/main.cpp" line="983"/>
4282 <source>OPENGL</source>
4283 <translation>OPENGL</translation>
4284 </message>
4285 <message>
4286 <location filename="../../src/yuzu/main.cpp" line="1045"/>
4287 <source>&amp;Clear Recent Files</source>
4288 <translation>[&amp;C] Очистити нещодавні файли</translation>
4289 </message>
4290 <message>
4291 <location filename="../../src/yuzu/main.cpp" line="1353"/>
4292 <source>&amp;Continue</source>
4293 <translation>[&amp;C] Продовжити</translation>
4294 </message>
4295 <message>
4296 <location filename="../../src/yuzu/main.cpp" line="1355"/>
4297 <source>&amp;Pause</source>
4298 <translation>[&amp;P] Пауза</translation>
4299 </message>
4300 <message>
4301 <location filename="../../src/yuzu/main.cpp" line="1435"/>
4302 <source>yuzu is running a game</source>
4303 <extracomment>TRANSLATORS: This string is shown to the user to explain why yuzu needs to prevent the computer from sleeping</extracomment>
4304 <translation>В yuzu запущено гру</translation>
4305 </message>
4306 <message>
4307 <location filename="../../src/yuzu/main.cpp" line="1566"/>
4308 <source>Warning Outdated Game Format</source>
4309 <translation>Попередження застарілий формат гри</translation>
4310 </message>
4311 <message>
4312 <location filename="../../src/yuzu/main.cpp" line="1567"/>
4313 <source>You are using the deconstructed ROM directory format for this game, which is an outdated format that has been superseded by others such as NCA, NAX, XCI, or NSP. Deconstructed ROM directories lack icons, metadata, and update support.&lt;br&gt;&lt;br&gt;For an explanation of the various Switch formats yuzu supports, &lt;a href=&apos;https://yuzu-emu.org/wiki/overview-of-switch-game-formats&apos;&gt;check out our wiki&lt;/a&gt;. This message will not be shown again.</source>
4314 <translation>Для цієї гри ви використовуєте розархівований формат ROM&apos;а, який є застарілим і був замінений іншими, такими як NCA, NAX, XCI або NSP. У розархівованих каталогах ROM&apos;а відсутні іконки, метадані та підтримка оновлень. &lt;br&gt;&lt;br&gt;Для отримання інформації про різні формати Switch, підтримувані yuzu, &lt;a href=&apos;https://yuzu-emu.org/wiki/overview-of-switch-game-formats&apos;&gt;перегляньте нашу вікі&lt;/a&gt;. Це повідомлення більше не буде відображатися.</translation>
4315 </message>
4316 <message>
4317 <location filename="../../src/yuzu/main.cpp" line="1579"/>
4318 <location filename="../../src/yuzu/main.cpp" line="1613"/>
4319 <source>Error while loading ROM!</source>
4320 <translation>Помилка під час завантаження ROM!</translation>
4321 </message>
4322 <message>
4323 <location filename="../../src/yuzu/main.cpp" line="1580"/>
4324 <source>The ROM format is not supported.</source>
4325 <translation>Формат ROM&apos;а не підтримується.</translation>
4326 </message>
4327 <message>
4328 <location filename="../../src/yuzu/main.cpp" line="1584"/>
4329 <source>An error occurred initializing the video core.</source>
4330 <translation>Сталася помилка під час ініціалізації відеоядра.</translation>
4331 </message>
4332 <message>
4333 <location filename="../../src/yuzu/main.cpp" line="1585"/>
4334 <source>yuzu has encountered an error while running the video core. This is usually caused by outdated GPU drivers, including integrated ones. Please see the log for more details. For more information on accessing the log, please see the following page: &lt;a href=&apos;https://yuzu-emu.org/help/reference/log-files/&apos;&gt;How to Upload the Log File&lt;/a&gt;. </source>
4335 <translation>yuzu зіткнувся з помилкою під час запуску відеоядра. Зазвичай це спричинено застарілими драйверами ГП, включно з інтегрованими. Перевірте журнал для отримання більш детальної інформації. Додаткову інформацію про доступ до журналу дивіться на наступній сторінці: &lt;a href=&apos;https://yuzu-emu.org/help/reference/log-files/&apos;&gt;Як завантажити файл журналу&lt;/a&gt;. </translation>
4336 </message>
4337 <message>
4338 <location filename="../../src/yuzu/main.cpp" line="1600"/>
4339 <source>Error while loading ROM! %1</source>
4340 <comment>%1 signifies a numeric error code.</comment>
4341 <translation>Помилка під час завантаження ROM&apos;а! %1</translation>
4342 </message>
4343 <message>
4344 <location filename="../../src/yuzu/main.cpp" line="1603"/>
4345 <source>%1&lt;br&gt;Please follow &lt;a href=&apos;https://yuzu-emu.org/help/quickstart/&apos;&gt;the yuzu quickstart guide&lt;/a&gt; to redump your files.&lt;br&gt;You can refer to the yuzu wiki&lt;/a&gt; or the yuzu Discord&lt;/a&gt; for help.</source>
4346 <comment>%1 signifies an error string.</comment>
4347 <translation>%1&lt;br&gt;Будь ласка, дотримуйтесь &lt;a href=&apos;https://yuzu-emu.org/help/quickstart/&apos;&gt;короткого керівництва користувача yuzu&lt;/a&gt; щоб пере-дампити ваші файли&lt;br&gt;Ви можете звернутися до вікі yuzu&lt;/a&gt; або Discord yuzu&lt;/a&gt; для допомоги</translation>
4348 </message>
4349 <message>
4350 <location filename="../../src/yuzu/main.cpp" line="1614"/>
4351 <source>An unknown error occurred. Please see the log for more details.</source>
4352 <translation>Сталася невідома помилка. Будь ласка, перевірте журнал для подробиць.</translation>
4353 </message>
4354 <message>
4355 <location filename="../../src/yuzu/main.cpp" line="1746"/>
4356 <source>(64-bit)</source>
4357 <translation>(64-бітний)</translation>
4358 </message>
4359 <message>
4360 <location filename="../../src/yuzu/main.cpp" line="1746"/>
4361 <source>(32-bit)</source>
4362 <translation>(32-бітний)</translation>
4363 </message>
4364 <message>
4365 <location filename="../../src/yuzu/main.cpp" line="1747"/>
4366 <source>%1 %2</source>
4367 <comment>%1 is the title name. %2 indicates if the title is 64-bit or 32-bit</comment>
4368 <translation>%1 %2</translation>
4369 </message>
4370 <message>
4371 <location filename="../../src/yuzu/main.cpp" line="1897"/>
4372 <source>Save Data</source>
4373 <translation>Збереження</translation>
4374 </message>
4375 <message>
4376 <location filename="../../src/yuzu/main.cpp" line="1947"/>
4377 <source>Mod Data</source>
4378 <translation>Дані модів</translation>
4379 </message>
4380 <message>
4381 <location filename="../../src/yuzu/main.cpp" line="1959"/>
4382 <source>Error Opening %1 Folder</source>
4383 <translation>Помилка під час відкриття папки %1</translation>
4384 </message>
4385 <message>
4386 <location filename="../../src/yuzu/main.cpp" line="1960"/>
4387 <location filename="../../src/yuzu/main.cpp" line="2366"/>
4388 <source>Folder does not exist!</source>
4389 <translation>Папка не існує!</translation>
4390 </message>
4391 <message>
4392 <location filename="../../src/yuzu/main.cpp" line="1972"/>
4393 <source>Error Opening Transferable Shader Cache</source>
4394 <translation>Помилка під час відкриття переносного кешу шейдерів</translation>
4395 </message>
4396 <message>
4397 <location filename="../../src/yuzu/main.cpp" line="1973"/>
4398 <source>Failed to create the shader cache directory for this title.</source>
4399 <translation>Не вдалося створити папку кешу шейдерів для цієї гри.</translation>
4400 </message>
4401 <message>
4402 <location filename="../../src/yuzu/main.cpp" line="2025"/>
4403 <source>Contents</source>
4404 <translation>Зміст</translation>
4405 </message>
4406 <message>
4407 <location filename="../../src/yuzu/main.cpp" line="2027"/>
4408 <source>Update</source>
4409 <translation>Оновлення</translation>
4410 </message>
4411 <message>
4412 <location filename="../../src/yuzu/main.cpp" line="2029"/>
4413 <source>DLC</source>
4414 <translation>DLC</translation>
4415 </message>
4416 <message>
4417 <location filename="../../src/yuzu/main.cpp" line="2036"/>
4418 <source>Remove Entry</source>
4419 <translation>Видалити запис</translation>
4420 </message>
4421 <message>
4422 <location filename="../../src/yuzu/main.cpp" line="2036"/>
4423 <source>Remove Installed Game %1?</source>
4424 <translation>Видалити встановлену гру %1?</translation>
4425 </message>
4426 <message>
4427 <location filename="../../src/yuzu/main.cpp" line="2066"/>
4428 <location filename="../../src/yuzu/main.cpp" line="2082"/>
4429 <location filename="../../src/yuzu/main.cpp" line="2113"/>
4430 <location filename="../../src/yuzu/main.cpp" line="2174"/>
4431 <location filename="../../src/yuzu/main.cpp" line="2192"/>
4432 <location filename="../../src/yuzu/main.cpp" line="2215"/>
4433 <source>Successfully Removed</source>
4434 <translation>Успішно видалено</translation>
4435 </message>
4436 <message>
4437 <location filename="../../src/yuzu/main.cpp" line="2067"/>
4438 <source>Successfully removed the installed base game.</source>
4439 <translation>Встановлену гру успішно видалено.</translation>
4440 </message>
4441 <message>
4442 <location filename="../../src/yuzu/main.cpp" line="2070"/>
4443 <location filename="../../src/yuzu/main.cpp" line="2085"/>
4444 <location filename="../../src/yuzu/main.cpp" line="2108"/>
4445 <source>Error Removing %1</source>
4446 <translation>Помилка під час видалення %1</translation>
4447 </message>
4448 <message>
4449 <location filename="../../src/yuzu/main.cpp" line="2071"/>
4450 <source>The base game is not installed in the NAND and cannot be removed.</source>
4451 <translation>Гру не встановлено в NAND і не може буде видалено.</translation>
4452 </message>
4453 <message>
4454 <location filename="../../src/yuzu/main.cpp" line="2083"/>
4455 <source>Successfully removed the installed update.</source>
4456 <translation>Встановлене оновлення успішно видалено.</translation>
4457 </message>
4458 <message>
4459 <location filename="../../src/yuzu/main.cpp" line="2086"/>
4460 <source>There is no update installed for this title.</source>
4461 <translation>Для цієї гри не було встановлено оновлення.</translation>
4462 </message>
4463 <message>
4464 <location filename="../../src/yuzu/main.cpp" line="2109"/>
4465 <source>There are no DLC installed for this title.</source>
4466 <translation>Для цієї гри не було встановлено DLC.</translation>
4467 </message>
4468 <message>
4469 <location filename="../../src/yuzu/main.cpp" line="2114"/>
4470 <source>Successfully removed %1 installed DLC.</source>
4471 <translation>Встановлений DLC %1 було успішно видалено</translation>
4472 </message>
4473 <message>
4474 <location filename="../../src/yuzu/main.cpp" line="2122"/>
4475 <source>Delete OpenGL Transferable Shader Cache?</source>
4476 <translation>Видалити переносний кеш шейдерів OpenGL?</translation>
4477 </message>
4478 <message>
4479 <location filename="../../src/yuzu/main.cpp" line="2124"/>
4480 <source>Delete Vulkan Transferable Shader Cache?</source>
4481 <translation>Видалити переносний кеш шейдерів Vulakn?</translation>
4482 </message>
4483 <message>
4484 <location filename="../../src/yuzu/main.cpp" line="2126"/>
4485 <source>Delete All Transferable Shader Caches?</source>
4486 <translation>Видалити весь переносний кеш шейдерів?</translation>
4487 </message>
4488 <message>
4489 <location filename="../../src/yuzu/main.cpp" line="2128"/>
4490 <source>Remove Custom Game Configuration?</source>
4491 <translation>Видалити користувацьке налаштування гри?</translation>
4492 </message>
4493 <message>
4494 <location filename="../../src/yuzu/main.cpp" line="2134"/>
4495 <source>Remove File</source>
4496 <translation>Видалити файл</translation>
4497 </message>
4498 <message>
4499 <location filename="../../src/yuzu/main.cpp" line="2169"/>
4500 <location filename="../../src/yuzu/main.cpp" line="2177"/>
4501 <source>Error Removing Transferable Shader Cache</source>
4502 <translation>Помилка під час видалення переносного кешу шейдерів</translation>
4503 </message>
4504 <message>
4505 <location filename="../../src/yuzu/main.cpp" line="2170"/>
4506 <location filename="../../src/yuzu/main.cpp" line="2188"/>
4507 <source>A shader cache for this title does not exist.</source>
4508 <translation>Кеш шейдерів для цієї гри не існує.</translation>
4509 </message>
4510 <message>
4511 <location filename="../../src/yuzu/main.cpp" line="2175"/>
4512 <source>Successfully removed the transferable shader cache.</source>
4513 <translation>Переносний кеш шейдерів успішно видалено.</translation>
4514 </message>
4515 <message>
4516 <location filename="../../src/yuzu/main.cpp" line="2178"/>
4517 <source>Failed to remove the transferable shader cache.</source>
4518 <translation>Не вдалося видалити переносний кеш шейдерів.</translation>
4519 </message>
4520 <message>
4521 <location filename="../../src/yuzu/main.cpp" line="2187"/>
4522 <location filename="../../src/yuzu/main.cpp" line="2195"/>
4523 <source>Error Removing Transferable Shader Caches</source>
4524 <translation>Помилка під час видалення переносного кешу шейдерів</translation>
4525 </message>
4526 <message>
4527 <location filename="../../src/yuzu/main.cpp" line="2193"/>
4528 <source>Successfully removed the transferable shader caches.</source>
4529 <translation>Переносний кеш шейдерів успішно видалено.</translation>
4530 </message>
4531 <message>
4532 <location filename="../../src/yuzu/main.cpp" line="2196"/>
4533 <source>Failed to remove the transferable shader cache directory.</source>
4534 <translation>Помилка під час видалення папки переносного кешу шейдерів.</translation>
4535 </message>
4536 <message>
4537 <location filename="../../src/yuzu/main.cpp" line="2209"/>
4538 <location filename="../../src/yuzu/main.cpp" line="2218"/>
4539 <source>Error Removing Custom Configuration</source>
4540 <translation>Помилка під час видалення користувацького налаштування</translation>
4541 </message>
4542 <message>
4543 <location filename="../../src/yuzu/main.cpp" line="2210"/>
4544 <source>A custom configuration for this title does not exist.</source>
4545 <translation>Користувацьких налаштувань для цієї гри не існує.</translation>
4546 </message>
4547 <message>
4548 <location filename="../../src/yuzu/main.cpp" line="2216"/>
4549 <source>Successfully removed the custom game configuration.</source>
4550 <translation>Користувацьке налаштування гри успішно видалено.</translation>
4551 </message>
4552 <message>
4553 <location filename="../../src/yuzu/main.cpp" line="2219"/>
4554 <source>Failed to remove the custom game configuration.</source>
4555 <translation>Не вдалося видалити користувацьке налаштування гри.</translation>
4556 </message>
4557 <message>
4558 <location filename="../../src/yuzu/main.cpp" line="2226"/>
4559 <location filename="../../src/yuzu/main.cpp" line="2305"/>
4560 <source>RomFS Extraction Failed!</source>
4561 <translation>Не вдалося вилучити RomFS!</translation>
4562 </message>
4563 <message>
4564 <location filename="../../src/yuzu/main.cpp" line="2227"/>
4565 <source>There was an error copying the RomFS files or the user cancelled the operation.</source>
4566 <translation>Сталася помилка під час копіювання файлів RomFS або користувач скасував операцію.</translation>
4567 </message>
4568 <message>
4569 <location filename="../../src/yuzu/main.cpp" line="2285"/>
4570 <source>Full</source>
4571 <translation>Повний</translation>
4572 </message>
4573 <message>
4574 <location filename="../../src/yuzu/main.cpp" line="2285"/>
4575 <source>Skeleton</source>
4576 <translation>Скелет</translation>
4577 </message>
4578 <message>
4579 <location filename="../../src/yuzu/main.cpp" line="2287"/>
4580 <source>Select RomFS Dump Mode</source>
4581 <translation>Виберіть режим дампа RomFS</translation>
4582 </message>
4583 <message>
4584 <location filename="../../src/yuzu/main.cpp" line="2288"/>
4585 <source>Please select the how you would like the RomFS dumped.&lt;br&gt;Full will copy all of the files into the new directory while &lt;br&gt;skeleton will only create the directory structure.</source>
4586 <translation>Будь ласка, виберіть, як ви хочете виконати дамп RomFS &lt;br&gt;Повний скопіює всі файли в нову папку, тоді як &lt;br&gt;скелет створить лише структуру папок.</translation>
4587 </message>
4588 <message>
4589 <location filename="../../src/yuzu/main.cpp" line="2306"/>
4590 <source>There is not enough free space at %1 to extract the RomFS. Please free up space or select a different dump directory at Emulation &gt; Configure &gt; System &gt; Filesystem &gt; Dump Root</source>
4591 <translation>В %1 недостатньо вільного місця для вилучення RomFS. Будь ласка, звільніть місце або виберіть іншу папку для дампа в Емуляція &gt; Налаштування &gt; Система &gt; Файлова система &gt; Корінь дампа</translation>
4592 </message>
4593 <message>
4594 <location filename="../../src/yuzu/main.cpp" line="2313"/>
4595 <source>Extracting RomFS...</source>
4596 <translation>Вилучення RomFS...</translation>
4597 </message>
4598 <message>
4599 <location filename="../../src/yuzu/main.cpp" line="2313"/>
4600 <location filename="../../src/yuzu/main.cpp" line="2499"/>
4601 <source>Cancel</source>
4602 <translation>Скасувати</translation>
4603 </message>
4604 <message>
4605 <location filename="../../src/yuzu/main.cpp" line="2320"/>
4606 <source>RomFS Extraction Succeeded!</source>
4607 <translation>Вилучення RomFS пройшло успішно!</translation>
4608 </message>
4609 <message>
4610 <location filename="../../src/yuzu/main.cpp" line="2321"/>
4611 <source>The operation completed successfully.</source>
4612 <translation>Операція завершилася успішно.</translation>
4613 </message>
4614 <message>
4615 <location filename="../../src/yuzu/main.cpp" line="2365"/>
4616 <source>Error Opening %1</source>
4617 <translation>Помилка відкриття %1</translation>
4618 </message>
4619 <message>
4620 <location filename="../../src/yuzu/main.cpp" line="2374"/>
4621 <source>Select Directory</source>
4622 <translation>Обрати папку</translation>
4623 </message>
4624 <message>
4625 <location filename="../../src/yuzu/main.cpp" line="2401"/>
4626 <source>Properties</source>
4627 <translation>Властивості</translation>
4628 </message>
4629 <message>
4630 <location filename="../../src/yuzu/main.cpp" line="2402"/>
4631 <source>The game properties could not be loaded.</source>
4632 <translation>Не вдалося завантажити властивості гри.</translation>
4633 </message>
4634 <message>
4635 <location filename="../../src/yuzu/main.cpp" line="2419"/>
4636 <source>Switch Executable (%1);;All Files (*.*)</source>
4637 <comment>%1 is an identifier for the Switch executable file extensions.</comment>
4638 <translation>Виконуваний файл Switch (%1);;Усі файли (*.*)</translation>
4639 </message>
4640 <message>
4641 <location filename="../../src/yuzu/main.cpp" line="2423"/>
4642 <source>Load File</source>
4643 <translation>Завантажити файл</translation>
4644 </message>
4645 <message>
4646 <location filename="../../src/yuzu/main.cpp" line="2436"/>
4647 <source>Open Extracted ROM Directory</source>
4648 <translation>Відкрити папку вилученого ROM&apos;а</translation>
4649 </message>
4650 <message>
4651 <location filename="../../src/yuzu/main.cpp" line="2447"/>
4652 <source>Invalid Directory Selected</source>
4653 <translation>Вибрано неприпустиму папку</translation>
4654 </message>
4655 <message>
4656 <location filename="../../src/yuzu/main.cpp" line="2448"/>
4657 <source>The directory you have selected does not contain a &apos;main&apos; file.</source>
4658 <translation>Папка, яку ви вибрали, не містить файлу &apos;main&apos;.</translation>
4659 </message>
4660 <message>
4661 <location filename="../../src/yuzu/main.cpp" line="2458"/>
4662 <source>Installable Switch File (*.nca *.nsp *.xci);;Nintendo Content Archive (*.nca);;Nintendo Submission Package (*.nsp);;NX Cartridge Image (*.xci)</source>
4663 <translation>Встановлюваний файл Switch (*.nca, *.nsp, *.xci);;Архів контенту Nintendo (*.nca);;Пакет подачі Nintendo (*.nsp);;Образ картриджа NX (*.xci)</translation>
4664 </message>
4665 <message>
4666 <location filename="../../src/yuzu/main.cpp" line="2463"/>
4667 <source>Install Files</source>
4668 <translation>Встановити файли</translation>
4669 </message>
4670 <message numerus="yes">
4671 <location filename="../../src/yuzu/main.cpp" line="2507"/>
4672 <source>%n file(s) remaining</source>
4673 <translation><numerusform>Залишився %n файл</numerusform><numerusform>Залишилося %n файл(ів)</numerusform><numerusform>Залишилося %n файл(ів)</numerusform><numerusform>Залишилося %n файл(ів)</numerusform></translation>
4674 </message>
4675 <message>
4676 <location filename="../../src/yuzu/main.cpp" line="2509"/>
4677 <source>Installing file &quot;%1&quot;...</source>
4678 <translation>Встановлення файлу &quot;%1&quot;...</translation>
4679 </message>
4680 <message>
4681 <location filename="../../src/yuzu/main.cpp" line="2555"/>
4682 <location filename="../../src/yuzu/main.cpp" line="2569"/>
4683 <source>Install Results</source>
4684 <translation>Результати встановлення</translation>
4685 </message>
4686 <message>
4687 <location filename="../../src/yuzu/main.cpp" line="2556"/>
4688 <source>To avoid possible conflicts, we discourage users from installing base games to the NAND.
4689Please, only use this feature to install updates and DLC.</source>
4690 <translation>Щоб уникнути можливих конфліктів, ми не рекомендуємо користувачам встановлювати ігри в NAND.
4691Будь ласка, використовуйте цю функцію тільки для встановлення оновлень і завантажуваного контенту.</translation>
4692 </message>
4693 <message numerus="yes">
4694 <location filename="../../src/yuzu/main.cpp" line="2562"/>
4695 <source>%n file(s) were newly installed
4696</source>
4697 <translation><numerusform>%n файл було нещодавно встановлено
4698</numerusform><numerusform>%n файл(ів) було нещодавно встановлено
4699</numerusform><numerusform>%n файл(ів) було нещодавно встановлено
4700</numerusform><numerusform>%n файл(ів) було нещодавно встановлено
4701</numerusform></translation>
4702 </message>
4703 <message numerus="yes">
4704 <location filename="../../src/yuzu/main.cpp" line="2565"/>
4705 <source>%n file(s) were overwritten
4706</source>
4707 <translation><numerusform>%n файл було перезаписано
4708</numerusform><numerusform>%n файл(ів) було перезаписано
4709</numerusform><numerusform>%n файл(ів) було перезаписано
4710</numerusform><numerusform>%n файл(ів) було перезаписано
4711</numerusform></translation>
4712 </message>
4713 <message numerus="yes">
4714 <location filename="../../src/yuzu/main.cpp" line="2567"/>
4715 <source>%n file(s) failed to install
4716</source>
4717 <translation><numerusform>%n файл не вдалося встановити
4718</numerusform><numerusform>%n файл(ів) не вдалося встановити
4719</numerusform><numerusform>%n файл(ів) не вдалося встановити
4720</numerusform><numerusform>%n файл(ів) не вдалося встановити
4721</numerusform></translation>
4722 </message>
4723 <message>
4724 <location filename="../../src/yuzu/main.cpp" line="2668"/>
4725 <source>System Application</source>
4726 <translation>Системний додаток</translation>
4727 </message>
4728 <message>
4729 <location filename="../../src/yuzu/main.cpp" line="2669"/>
4730 <source>System Archive</source>
4731 <translation>Системний архів</translation>
4732 </message>
4733 <message>
4734 <location filename="../../src/yuzu/main.cpp" line="2670"/>
4735 <source>System Application Update</source>
4736 <translation>Оновлення системного додатку</translation>
4737 </message>
4738 <message>
4739 <location filename="../../src/yuzu/main.cpp" line="2671"/>
4740 <source>Firmware Package (Type A)</source>
4741 <translation>Пакет прошивки (Тип А)</translation>
4742 </message>
4743 <message>
4744 <location filename="../../src/yuzu/main.cpp" line="2672"/>
4745 <source>Firmware Package (Type B)</source>
4746 <translation>Пакет прошивки (Тип Б)</translation>
4747 </message>
4748 <message>
4749 <location filename="../../src/yuzu/main.cpp" line="2673"/>
4750 <source>Game</source>
4751 <translation>Гра</translation>
4752 </message>
4753 <message>
4754 <location filename="../../src/yuzu/main.cpp" line="2674"/>
4755 <source>Game Update</source>
4756 <translation>Оновлення гри</translation>
4757 </message>
4758 <message>
4759 <location filename="../../src/yuzu/main.cpp" line="2675"/>
4760 <source>Game DLC</source>
4761 <translation>DLC до гри</translation>
4762 </message>
4763 <message>
4764 <location filename="../../src/yuzu/main.cpp" line="2676"/>
4765 <source>Delta Title</source>
4766 <translation>Дельта-титул</translation>
4767 </message>
4768 <message>
4769 <location filename="../../src/yuzu/main.cpp" line="2679"/>
4770 <source>Select NCA Install Type...</source>
4771 <translation>Виберіть тип установки NCA...</translation>
4772 </message>
4773 <message>
4774 <location filename="../../src/yuzu/main.cpp" line="2680"/>
4775 <source>Please select the type of title you would like to install this NCA as:
4776(In most instances, the default &apos;Game&apos; is fine.)</source>
4777 <translation>Будь ласка, виберіть тип додатку, який ви хочете встановити для цього NCA:
4778(У більшості випадків, підходить стандартний вибір &quot;Гра&quot;.)</translation>
4779 </message>
4780 <message>
4781 <location filename="../../src/yuzu/main.cpp" line="2686"/>
4782 <source>Failed to Install</source>
4783 <translation>Помилка встановлення</translation>
4784 </message>
4785 <message>
4786 <location filename="../../src/yuzu/main.cpp" line="2687"/>
4787 <source>The title type you selected for the NCA is invalid.</source>
4788 <translation>Тип додатку, який ви вибрали для NCA, недійсний.</translation>
4789 </message>
4790 <message>
4791 <location filename="../../src/yuzu/main.cpp" line="2722"/>
4792 <source>File not found</source>
4793 <translation>Файл не знайдено</translation>
4794 </message>
4795 <message>
4796 <location filename="../../src/yuzu/main.cpp" line="2723"/>
4797 <source>File &quot;%1&quot; not found</source>
4798 <translation>Файл &quot;%1&quot; не знайдено</translation>
4799 </message>
4800 <message>
4801 <location filename="../../src/yuzu/main.cpp" line="2798"/>
4802 <source>OK</source>
4803 <translation>ОК</translation>
4804 </message>
4805 <message>
4806 <location filename="../../src/yuzu/main.cpp" line="2812"/>
4807 <source>Missing yuzu Account</source>
4808 <translation>Відсутній обліковий запис yuzu</translation>
4809 </message>
4810 <message>
4811 <location filename="../../src/yuzu/main.cpp" line="2813"/>
4812 <source>In order to submit a game compatibility test case, you must link your yuzu account.&lt;br&gt;&lt;br/&gt;To link your yuzu account, go to Emulation &amp;gt; Configuration &amp;gt; Web.</source>
4813 <translation>Щоб надіслати звіт про сумісність гри, необхідно прив&apos;язати свій обліковий запис yuzu. &lt;br&gt;&lt;br/&gt;Щоб прив&apos;язати свій обліковий запис yuzu, перейдіть у розділ Емуляція &amp;gt; Параметри &amp;gt; Мережа.</translation>
4814 </message>
4815 <message>
4816 <location filename="../../src/yuzu/main.cpp" line="2823"/>
4817 <source>Error opening URL</source>
4818 <translation>Помилка під час відкриття URL</translation>
4819 </message>
4820 <message>
4821 <location filename="../../src/yuzu/main.cpp" line="2824"/>
4822 <source>Unable to open the URL &quot;%1&quot;.</source>
4823 <translation>Не вдалося відкрити URL: &quot;%1&quot;.</translation>
4824 </message>
4825 <message>
4826 <location filename="../../src/yuzu/main.cpp" line="3120"/>
4827 <source>TAS Recording</source>
4828 <translation>Запис TAS</translation>
4829 </message>
4830 <message>
4831 <location filename="../../src/yuzu/main.cpp" line="3121"/>
4832 <source>Overwrite file of player 1?</source>
4833 <translation>Перезаписати файл гравця 1?</translation>
4834 </message>
4835 <message>
4836 <location filename="../../src/yuzu/main.cpp" line="3147"/>
4837 <source>Invalid config detected</source>
4838 <translation>Виявлено неприпустиму конфігурацію</translation>
4839 </message>
4840 <message>
4841 <location filename="../../src/yuzu/main.cpp" line="3148"/>
4842 <source>Handheld controller can&apos;t be used on docked mode. Pro controller will be selected.</source>
4843 <translation>Портативний контролер не може бути використаний у режимі док-станції. Буде обрано контролер Pro.</translation>
4844 </message>
4845 <message>
4846 <location filename="../../src/yuzu/main.cpp" line="3243"/>
4847 <location filename="../../src/yuzu/main.cpp" line="3271"/>
4848 <source>Amiibo</source>
4849 <translation>Amiibo</translation>
4850 </message>
4851 <message>
4852 <location filename="../../src/yuzu/main.cpp" line="3243"/>
4853 <location filename="../../src/yuzu/main.cpp" line="3271"/>
4854 <source>The current amiibo has been removed</source>
4855 <translation>Поточний amiibo було прибрано</translation>
4856 </message>
4857 <message>
4858 <location filename="../../src/yuzu/main.cpp" line="3248"/>
4859 <source>Error</source>
4860 <translation>Помилка</translation>
4861 </message>
4862 <message>
4863 <location filename="../../src/yuzu/main.cpp" line="3248"/>
4864 <location filename="../../src/yuzu/main.cpp" line="3283"/>
4865 <source>The current game is not looking for amiibos</source>
4866 <translation>Поточна гра не шукає amiibo</translation>
4867 </message>
4868 <message>
4869 <location filename="../../src/yuzu/main.cpp" line="3254"/>
4870 <source>Amiibo File (%1);; All Files (*.*)</source>
4871 <translation>Файл Amiibo (%1);; Всі Файли (*.*)</translation>
4872 </message>
4873 <message>
4874 <location filename="../../src/yuzu/main.cpp" line="3255"/>
4875 <source>Load Amiibo</source>
4876 <translation>Завантажити Amiibo</translation>
4877 </message>
4878 <message>
4879 <location filename="../../src/yuzu/main.cpp" line="3267"/>
4880 <source>Error loading Amiibo data</source>
4881 <translation>Помилка під час завантаження даних Amiibo</translation>
4882 </message>
4883 <message>
4884 <location filename="../../src/yuzu/main.cpp" line="3277"/>
4885 <source>The selected file is not a valid amiibo</source>
4886 <translation>Обраний файл не є допустимим amiibo</translation>
4887 </message>
4888 <message>
4889 <location filename="../../src/yuzu/main.cpp" line="3280"/>
4890 <source>The selected file is already on use</source>
4891 <translation>Обраний файл уже використовується</translation>
4892 </message>
4893 <message>
4894 <location filename="../../src/yuzu/main.cpp" line="3286"/>
4895 <source>An unknown error occurred</source>
4896 <translation>Виникла невідома помилка</translation>
4897 </message>
4898 <message>
4899 <location filename="../../src/yuzu/main.cpp" line="3338"/>
4900 <source>Capture Screenshot</source>
4901 <translation>Зробити знімок екрану</translation>
4902 </message>
4903 <message>
4904 <location filename="../../src/yuzu/main.cpp" line="3339"/>
4905 <source>PNG Image (*.png)</source>
4906 <translation>Зображення PNG (*.png)</translation>
4907 </message>
4908 <message>
4909 <location filename="../../src/yuzu/main.cpp" line="3405"/>
4910 <source>TAS state: Running %1/%2</source>
4911 <translation>Стан TAS: Виконується %1/%2</translation>
4912 </message>
4913 <message>
4914 <location filename="../../src/yuzu/main.cpp" line="3407"/>
4915 <source>TAS state: Recording %1</source>
4916 <translation>Стан TAS: Записується %1</translation>
4917 </message>
4918 <message>
4919 <location filename="../../src/yuzu/main.cpp" line="3409"/>
4920 <source>TAS state: Idle %1/%2</source>
4921 <translation>Стан TAS: Простий %1/%2</translation>
4922 </message>
4923 <message>
4924 <location filename="../../src/yuzu/main.cpp" line="3411"/>
4925 <source>TAS State: Invalid</source>
4926 <translation>Стан TAS: Неприпустимий</translation>
4927 </message>
4928 <message>
4929 <location filename="../../src/yuzu/main.cpp" line="3425"/>
4930 <source>&amp;Stop Running</source>
4931 <translation>[&amp;S] Зупинка</translation>
4932 </message>
4933 <message>
4934 <location filename="../../src/yuzu/main.cpp" line="3425"/>
4935 <source>&amp;Start</source>
4936 <translation>[&amp;S] Почати</translation>
4937 </message>
4938 <message>
4939 <location filename="../../src/yuzu/main.cpp" line="3426"/>
4940 <source>Stop R&amp;ecording</source>
4941 <translation>[&amp;E] Закінчити запис</translation>
4942 </message>
4943 <message>
4944 <location filename="../../src/yuzu/main.cpp" line="3426"/>
4945 <source>R&amp;ecord</source>
4946 <translation>[&amp;E] Запис</translation>
4947 </message>
4948 <message numerus="yes">
4949 <location filename="../../src/yuzu/main.cpp" line="3450"/>
4950 <source>Building: %n shader(s)</source>
4951 <translation><numerusform>Побудова: %n шейдер</numerusform><numerusform>Побудова: %n шейдер(ів)</numerusform><numerusform>Побудова: %n шейдер(ів)</numerusform><numerusform>Побудова: %n шейдер(ів)</numerusform></translation>
4952 </message>
4953 <message>
4954 <location filename="../../src/yuzu/main.cpp" line="3459"/>
4955 <source>Scale: %1x</source>
4956 <comment>%1 is the resolution scaling factor</comment>
4957 <translation>Масштаб: %1x</translation>
4958 </message>
4959 <message>
4960 <location filename="../../src/yuzu/main.cpp" line="3462"/>
4961 <source>Speed: %1% / %2%</source>
4962 <translation>Швидкість: %1% / %2%</translation>
4963 </message>
4964 <message>
4965 <location filename="../../src/yuzu/main.cpp" line="3466"/>
4966 <source>Speed: %1%</source>
4967 <translation>Швидкість: %1%</translation>
4968 </message>
4969 <message>
4970 <location filename="../../src/yuzu/main.cpp" line="3470"/>
4971 <source>Game: %1 FPS (Unlocked)</source>
4972 <translation>Гра: %1 FPS (Необмежено)</translation>
4973 </message>
4974 <message>
4975 <location filename="../../src/yuzu/main.cpp" line="3473"/>
4976 <source>Game: %1 FPS</source>
4977 <translation>Гра: %1 FPS</translation>
4978 </message>
4979 <message>
4980 <location filename="../../src/yuzu/main.cpp" line="3475"/>
4981 <source>Frame: %1 ms</source>
4982 <translation>Кадр: %1 мс</translation>
4983 </message>
4984 <message>
4985 <location filename="../../src/yuzu/main.cpp" line="3486"/>
4986 <source>GPU NORMAL</source>
4987 <translation>ГП НОРМАЛЬНО</translation>
4988 </message>
4989 <message>
4990 <location filename="../../src/yuzu/main.cpp" line="3491"/>
4991 <source>GPU HIGH</source>
4992 <translation>ГП ВИСОКО</translation>
4993 </message>
4994 <message>
4995 <location filename="../../src/yuzu/main.cpp" line="3496"/>
4996 <source>GPU EXTREME</source>
4997 <translation>ГП ЕКСТРИМ</translation>
4998 </message>
4999 <message>
5000 <location filename="../../src/yuzu/main.cpp" line="3501"/>
5001 <source>GPU ERROR</source>
5002 <translation>ГП ПОМИЛКА</translation>
5003 </message>
5004 <message>
5005 <location filename="../../src/yuzu/main.cpp" line="3510"/>
5006 <source>DOCKED</source>
5007 <translation>В ДОК-СТАНЦІЇ</translation>
5008 </message>
5009 <message>
5010 <location filename="../../src/yuzu/main.cpp" line="3510"/>
5011 <source>HANDHELD</source>
5012 <translation>ПОРТАТИВНИЙ</translation>
5013 </message>
5014 <message>
5015 <location filename="../../src/yuzu/main.cpp" line="3517"/>
5016 <source>NEAREST</source>
5017 <translation>НАЙБЛИЖЧІЙ</translation>
5018 </message>
5019 <message>
5020 <location filename="../../src/yuzu/main.cpp" line="3520"/>
5021 <location filename="../../src/yuzu/main.cpp" line="3535"/>
5022 <source>BILINEAR</source>
5023 <translation>БІЛІНІЙНИЙ</translation>
5024 </message>
5025 <message>
5026 <location filename="../../src/yuzu/main.cpp" line="3523"/>
5027 <source>BICUBIC</source>
5028 <translation>БІКУБІЧНИЙ</translation>
5029 </message>
5030 <message>
5031 <location filename="../../src/yuzu/main.cpp" line="3526"/>
5032 <source>GAUSSIAN</source>
5033 <translation>ГАУС</translation>
5034 </message>
5035 <message>
5036 <location filename="../../src/yuzu/main.cpp" line="3529"/>
5037 <source>SCALEFORCE</source>
5038 <translation>SCALEFORCE</translation>
5039 </message>
5040 <message>
5041 <location filename="../../src/yuzu/main.cpp" line="3532"/>
5042 <source>FSR</source>
5043 <translation>FSR</translation>
5044 </message>
5045 <message>
5046 <location filename="../../src/yuzu/main.cpp" line="3544"/>
5047 <location filename="../../src/yuzu/main.cpp" line="3550"/>
5048 <source>NO AA</source>
5049 <translation>БЕЗ ЗГЛАДЖУВАННЯ</translation>
5050 </message>
5051 <message>
5052 <location filename="../../src/yuzu/main.cpp" line="3547"/>
5053 <source>FXAA</source>
5054 <translation>FXAA</translation>
5055 </message>
5056 <message>
5057 <location filename="../../src/yuzu/main.cpp" line="3624"/>
5058 <source>The game you are trying to load requires additional files from your Switch to be dumped before playing.&lt;br/&gt;&lt;br/&gt;For more information on dumping these files, please see the following wiki page: &lt;a href=&apos;https://yuzu-emu.org/wiki/dumping-system-archives-and-the-shared-fonts-from-a-switch-console/&apos;&gt;Dumping System Archives and the Shared Fonts from a Switch Console&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;Would you like to quit back to the game list? Continuing emulation may result in crashes, corrupted save data, or other bugs.</source>
5059 <translation>Гра, яку ви намагаєтеся завантажити, вимагає, щоб додаткові файли були здамплені з вашого Switch перед початком гри. &lt;br/&gt;&lt;br/&gt;Для отримання додаткової інформації про дамп цих файлів див. наступну вікі: &lt;a href=&apos;https://yuzu-emu.org/wiki/dumping-system-archives-and-the-shared-fonts-from-a-switch-console/&apos;&gt;Дамп системних архівів і загальних шрифтів з консолі&lt;/a&gt;. &lt;br/&gt;&lt;br/&gt;Хочете повернутися до списку ігор? Продовження емуляції може призвести до збоїв, пошкодження збережених даних або інших помилок.</translation>
5060 </message>
5061 <message>
5062 <location filename="../../src/yuzu/main.cpp" line="3639"/>
5063 <source>yuzu was unable to locate a Switch system archive. %1</source>
5064 <translation>yuzu не вдалося знайти системний архів Switch. %1</translation>
5065 </message>
5066 <message>
5067 <location filename="../../src/yuzu/main.cpp" line="3641"/>
5068 <source>yuzu was unable to locate a Switch system archive: %1. %2</source>
5069 <translation>yuzu не вдалося знайти системний архів Switch: %1. %2</translation>
5070 </message>
5071 <message>
5072 <location filename="../../src/yuzu/main.cpp" line="3645"/>
5073 <source>System Archive Not Found</source>
5074 <translation>Системний архів не знайдено</translation>
5075 </message>
5076 <message>
5077 <location filename="../../src/yuzu/main.cpp" line="3647"/>
5078 <source>System Archive Missing</source>
5079 <translation>Відсутній системний архів</translation>
5080 </message>
5081 <message>
5082 <location filename="../../src/yuzu/main.cpp" line="3653"/>
5083 <source>yuzu was unable to locate the Switch shared fonts. %1</source>
5084 <translation>yuzu не вдалося знайти загальні шрифти Switch. %1</translation>
5085 </message>
5086 <message>
5087 <location filename="../../src/yuzu/main.cpp" line="3654"/>
5088 <source>Shared Fonts Not Found</source>
5089 <translation>Загальні шрифти не знайдено</translation>
5090 </message>
5091 <message>
5092 <location filename="../../src/yuzu/main.cpp" line="3656"/>
5093 <source>Shared Font Missing</source>
5094 <translation>Загальні шрифти відсутні</translation>
5095 </message>
5096 <message>
5097 <location filename="../../src/yuzu/main.cpp" line="3662"/>
5098 <source>Fatal Error</source>
5099 <translation>Фатальна помилка</translation>
5100 </message>
5101 <message>
5102 <location filename="../../src/yuzu/main.cpp" line="3663"/>
5103 <source>yuzu has encountered a fatal error, please see the log for more details. For more information on accessing the log, please see the following page: &lt;a href=&apos;https://community.citra-emu.org/t/how-to-upload-the-log-file/296&apos;&gt;How to Upload the Log File&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;Would you like to quit back to the game list? Continuing emulation may result in crashes, corrupted save data, or other bugs.</source>
5104 <translation>yuzu зіткнувся з фатальною помилкою, перевірте журнал для отримання більш детальної інформації. Для отримання додаткової інформації про доступ до журналу відкрийте наступну сторінку: &lt;a href=&apos;https://community.citra-emu.org/t/how-to-upload-the-log-file/296&apos;&gt;Як завантажити файл журналу&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;Ви хочете повернутися до списку ігор? Продовження емуляції може призвести до збоїв, пошкодження збережень або інших помилок.</translation>
5105 </message>
5106 <message>
5107 <location filename="../../src/yuzu/main.cpp" line="3672"/>
5108 <source>Fatal Error encountered</source>
5109 <translation>Сталася фатальна помилка</translation>
5110 </message>
5111 <message>
5112 <location filename="../../src/yuzu/main.cpp" line="3695"/>
5113 <source>Confirm Key Rederivation</source>
5114 <translation>Підтвердіть перерахунок ключа</translation>
5115 </message>
5116 <message>
5117 <location filename="../../src/yuzu/main.cpp" line="3696"/>
5118 <source>You are about to force rederive all of your keys.
5119If you do not know what this means or what you are doing,
5120this is a potentially destructive action.
5121Please make sure this is what you want
5122and optionally make backups.
5123
5124This will delete your autogenerated key files and re-run the key derivation module.</source>
5125 <translation>Ви збираєтеся примусово перерахувати всі ваші ключі.
5126Якщо ви не знаєте, що це означає або що ви робите,
5127це потенційно руйнівна дія.
5128Будь ласка, переконайтеся, що це те, що ви хочете
5129і, по бажанню, зробіть резервні копії.
5130
5131Це видалить ваші автоматично згенеровані файли ключів і повторно запустить модуль розрахунку ключів.</translation>
5132 </message>
5133 <message>
5134 <location filename="../../src/yuzu/main.cpp" line="3728"/>
5135 <source>Missing fuses</source>
5136 <translation>Відсутні запобіжники</translation>
5137 </message>
5138 <message>
5139 <location filename="../../src/yuzu/main.cpp" line="3731"/>
5140 <source> - Missing BOOT0</source>
5141 <translation>- Відсутній BOOT0</translation>
5142 </message>
5143 <message>
5144 <location filename="../../src/yuzu/main.cpp" line="3734"/>
5145 <source> - Missing BCPKG2-1-Normal-Main</source>
5146 <translation>- Відсутній BCPKG2-1-Normal-Main</translation>
5147 </message>
5148 <message>
5149 <location filename="../../src/yuzu/main.cpp" line="3737"/>
5150 <source> - Missing PRODINFO</source>
5151 <translation> - Відсутній PRODINFO</translation>
5152 </message>
5153 <message>
5154 <location filename="../../src/yuzu/main.cpp" line="3741"/>
5155 <source>Derivation Components Missing</source>
5156 <translation>Компоненти розрахунку відсутні</translation>
5157 </message>
5158 <message>
5159 <location filename="../../src/yuzu/main.cpp" line="3742"/>
5160 <source>Encryption keys are missing. &lt;br&gt;Please follow &lt;a href=&apos;https://yuzu-emu.org/help/quickstart/&apos;&gt;the yuzu quickstart guide&lt;/a&gt; to get all your keys, firmware and games.&lt;br&gt;&lt;br&gt;&lt;small&gt;(%1)&lt;/small&gt;</source>
5161 <translation>Ключі шифрування відсутні.&lt;br&gt;Будь ласка, дотримуйтесь &lt;a href=&apos;https://yuzu-emu.org/help/quickstart/&apos;&gt;короткого керівництва користувача yuzu&lt;/a&gt;, щоб отримати всі ваші ключі, прошивку та ігри&lt;br&gt;&lt;br&gt;&lt;small&gt;(%1)&lt;/small&gt;</translation>
5162 </message>
5163 <message>
5164 <location filename="../../src/yuzu/main.cpp" line="3751"/>
5165 <source>Deriving keys...
5166This may take up to a minute depending
5167on your system&apos;s performance.</source>
5168 <translation>Отримання ключів...
5169Це може зайняти до хвилини залежно від
5170від продуктивності вашої системи.</translation>
5171 </message>
5172 <message>
5173 <location filename="../../src/yuzu/main.cpp" line="3753"/>
5174 <source>Deriving Keys</source>
5175 <translation>Отримання ключів</translation>
5176 </message>
5177 <message>
5178 <location filename="../../src/yuzu/main.cpp" line="3798"/>
5179 <source>Select RomFS Dump Target</source>
5180 <translation>Оберіть ціль для дампа RomFS</translation>
5181 </message>
5182 <message>
5183 <location filename="../../src/yuzu/main.cpp" line="3799"/>
5184 <source>Please select which RomFS you would like to dump.</source>
5185 <translation>Будь ласка, виберіть, який RomFS ви хочете здампити.</translation>
5186 </message>
5187 <message>
5188 <location filename="../../src/yuzu/main.cpp" line="3814"/>
5189 <source>Are you sure you want to close yuzu?</source>
5190 <translation>Ви впевнені, що хочете закрити yuzu?</translation>
5191 </message>
5192 <message>
5193 <location filename="../../src/yuzu/main.cpp" line="3815"/>
5194 <location filename="../../src/yuzu/main.cpp" line="3913"/>
5195 <location filename="../../src/yuzu/main.cpp" line="3926"/>
5196 <source>yuzu</source>
5197 <translation>yuzu</translation>
5198 </message>
5199 <message>
5200 <location filename="../../src/yuzu/main.cpp" line="3914"/>
5201 <source>Are you sure you want to stop the emulation? Any unsaved progress will be lost.</source>
5202 <translation>Ви впевнені, що хочете зупинити емуляцію? Будь-який незбережений прогрес буде втрачено.</translation>
5203 </message>
5204 <message>
5205 <location filename="../../src/yuzu/main.cpp" line="3923"/>
5206 <source>The currently running application has requested yuzu to not exit.
5207
5208Would you like to bypass this and exit anyway?</source>
5209 <translation>Запущений на даний момент додаток просить yuzu не завершувати роботу.
5210
5211Чи хочете ви обійти це і вийти в будь-якому випадку?</translation>
5212 </message>
5213</context>
5214<context>
5215 <name>GRenderWindow</name>
5216 <message>
5217 <location filename="../../src/yuzu/bootmanager.cpp" line="1047"/>
5218 <source>OpenGL not available!</source>
5219 <translation>OpenGL недоступний!</translation>
5220 </message>
5221 <message>
5222 <location filename="../../src/yuzu/bootmanager.cpp" line="1048"/>
5223 <source>yuzu has not been compiled with OpenGL support.</source>
5224 <translation>yuzu не було зібрано з підтримкою OpenGL.</translation>
5225 </message>
5226 <message>
5227 <location filename="../../src/yuzu/bootmanager.cpp" line="1067"/>
5228 <location filename="../../src/yuzu/bootmanager.cpp" line="1087"/>
5229 <source>Error while initializing OpenGL!</source>
5230 <translation>Помилка під час ініціалізації OpenGL!</translation>
5231 </message>
5232 <message>
5233 <location filename="../../src/yuzu/bootmanager.cpp" line="1068"/>
5234 <source>Your GPU may not support OpenGL, or you do not have the latest graphics driver.</source>
5235 <translation>Ваш ГП може не підтримувати OpenGL, або у вас встановлено застарілий графічний драйвер.</translation>
5236 </message>
5237 <message>
5238 <location filename="../../src/yuzu/bootmanager.cpp" line="1077"/>
5239 <source>Error while initializing OpenGL 4.6!</source>
5240 <translation>Помилка під час ініціалізації OpenGL 4.6!</translation>
5241 </message>
5242 <message>
5243 <location filename="../../src/yuzu/bootmanager.cpp" line="1078"/>
5244 <source>Your GPU may not support OpenGL 4.6, or you do not have the latest graphics driver.&lt;br&gt;&lt;br&gt;GL Renderer:&lt;br&gt;%1</source>
5245 <translation>Ваш ГП може не підтримувати OpenGL 4.6, або у вас встановлено застарілий графічний драйвер.&lt;br&gt;&lt;br&gt;Рендерер GL:&lt;br&gt;%1</translation>
5246 </message>
5247 <message>
5248 <location filename="../../src/yuzu/bootmanager.cpp" line="1088"/>
5249 <source>Your GPU may not support one or more required OpenGL extensions. Please ensure you have the latest graphics driver.&lt;br&gt;&lt;br&gt;GL Renderer:&lt;br&gt;%1&lt;br&gt;&lt;br&gt;Unsupported extensions:&lt;br&gt;%2</source>
5250 <translation>Ваш ГП може не підтримувати одне або кілька необхідних розширень OpenGL. Будь ласка, переконайтеся в тому, що у вас встановлено останній графічний драйвер.&lt;br&gt;&lt;br&gt;Рендерер GL:&lt;br&gt;%1&lt;br&gt;&lt;br&gt;Розширення, що не підтримуються:&lt;br&gt;%2</translation>
5251 </message>
5252</context>
5253<context>
5254 <name>GameList</name>
5255 <message>
5256 <location filename="../../src/yuzu/game_list.cpp" line="532"/>
5257 <source>Favorite</source>
5258 <translation>Улюблені</translation>
5259 </message>
5260 <message>
5261 <location filename="../../src/yuzu/game_list.cpp" line="534"/>
5262 <source>Start Game</source>
5263 <translation>Запустити гру</translation>
5264 </message>
5265 <message>
5266 <location filename="../../src/yuzu/game_list.cpp" line="536"/>
5267 <source>Start Game without Custom Configuration</source>
5268 <translation>Запустити гру без користувацького налаштування</translation>
5269 </message>
5270 <message>
5271 <location filename="../../src/yuzu/game_list.cpp" line="538"/>
5272 <source>Open Save Data Location</source>
5273 <translation>Відкрити папку для збережень</translation>
5274 </message>
5275 <message>
5276 <location filename="../../src/yuzu/game_list.cpp" line="539"/>
5277 <source>Open Mod Data Location</source>
5278 <translation>Відкрити папку для модів</translation>
5279 </message>
5280 <message>
5281 <location filename="../../src/yuzu/game_list.cpp" line="541"/>
5282 <source>Open Transferable Pipeline Cache</source>
5283 <translation>Відкрити переносний кеш конвеєра</translation>
5284 </message>
5285 <message>
5286 <location filename="../../src/yuzu/game_list.cpp" line="543"/>
5287 <source>Remove</source>
5288 <translation>Видалити</translation>
5289 </message>
5290 <message>
5291 <location filename="../../src/yuzu/game_list.cpp" line="544"/>
5292 <source>Remove Installed Update</source>
5293 <translation>Видалити встановлене оновлення</translation>
5294 </message>
5295 <message>
5296 <location filename="../../src/yuzu/game_list.cpp" line="545"/>
5297 <source>Remove All Installed DLC</source>
5298 <translation>Видалити усі DLC</translation>
5299 </message>
5300 <message>
5301 <location filename="../../src/yuzu/game_list.cpp" line="546"/>
5302 <source>Remove Custom Configuration</source>
5303 <translation>Видалити користувацьке налаштування</translation>
5304 </message>
5305 <message>
5306 <location filename="../../src/yuzu/game_list.cpp" line="547"/>
5307 <source>Remove OpenGL Pipeline Cache</source>
5308 <translation>Видалити кеш конвеєра OpenGL</translation>
5309 </message>
5310 <message>
5311 <location filename="../../src/yuzu/game_list.cpp" line="548"/>
5312 <source>Remove Vulkan Pipeline Cache</source>
5313 <translation>Видалити кеш конвеєра Vulkan</translation>
5314 </message>
5315 <message>
5316 <location filename="../../src/yuzu/game_list.cpp" line="550"/>
5317 <source>Remove All Pipeline Caches</source>
5318 <translation>Видалити весь кеш конвеєра </translation>
5319 </message>
5320 <message>
5321 <location filename="../../src/yuzu/game_list.cpp" line="551"/>
5322 <source>Remove All Installed Contents</source>
5323 <translation>Видалити весь встановлений вміст</translation>
5324 </message>
5325 <message>
5326 <location filename="../../src/yuzu/game_list.cpp" line="552"/>
5327 <location filename="../../src/yuzu/game_list.cpp" line="553"/>
5328 <source>Dump RomFS</source>
5329 <translation>Дамп RomFS</translation>
5330 </message>
5331 <message>
5332 <location filename="../../src/yuzu/game_list.cpp" line="554"/>
5333 <source>Dump RomFS to SDMC</source>
5334 <translation>Здампити RomFS у SDMC</translation>
5335 </message>
5336 <message>
5337 <location filename="../../src/yuzu/game_list.cpp" line="555"/>
5338 <source>Copy Title ID to Clipboard</source>
5339 <translation>Скопіювати ідентифікатор додатку в буфер обміну</translation>
5340 </message>
5341 <message>
5342 <location filename="../../src/yuzu/game_list.cpp" line="556"/>
5343 <source>Navigate to GameDB entry</source>
5344 <translation>Перейти до сторінки GameDB</translation>
5345 </message>
5346 <message>
5347 <location filename="../../src/yuzu/game_list.cpp" line="558"/>
5348 <source>Properties</source>
5349 <translation>Властивості</translation>
5350 </message>
5351 <message>
5352 <location filename="../../src/yuzu/game_list.cpp" line="630"/>
5353 <source>Scan Subfolders</source>
5354 <translation>Сканувати підпапки</translation>
5355 </message>
5356 <message>
5357 <location filename="../../src/yuzu/game_list.cpp" line="631"/>
5358 <source>Remove Game Directory</source>
5359 <translation>Видалити директорію гри</translation>
5360 </message>
5361 <message>
5362 <location filename="../../src/yuzu/game_list.cpp" line="650"/>
5363 <source>▲ Move Up</source>
5364 <translation>▲ Перемістити вверх</translation>
5365 </message>
5366 <message>
5367 <location filename="../../src/yuzu/game_list.cpp" line="651"/>
5368 <source>▼ Move Down</source>
5369 <translation>▼ Перемістити вниз</translation>
5370 </message>
5371 <message>
5372 <location filename="../../src/yuzu/game_list.cpp" line="652"/>
5373 <source>Open Directory Location</source>
5374 <translation>Відкрити розташування папки</translation>
5375 </message>
5376 <message>
5377 <location filename="../../src/yuzu/game_list.cpp" line="697"/>
5378 <source>Clear</source>
5379 <translation>Очистити</translation>
5380 </message>
5381 <message>
5382 <location filename="../../src/yuzu/game_list.cpp" line="761"/>
5383 <source>Name</source>
5384 <translation>Назва</translation>
5385 </message>
5386 <message>
5387 <location filename="../../src/yuzu/game_list.cpp" line="762"/>
5388 <source>Compatibility</source>
5389 <translation>Сумісність</translation>
5390 </message>
5391 <message>
5392 <location filename="../../src/yuzu/game_list.cpp" line="763"/>
5393 <source>Add-ons</source>
5394 <translation>Доповнення</translation>
5395 </message>
5396 <message>
5397 <location filename="../../src/yuzu/game_list.cpp" line="764"/>
5398 <source>File type</source>
5399 <translation>Тип файлу</translation>
5400 </message>
5401 <message>
5402 <location filename="../../src/yuzu/game_list.cpp" line="765"/>
5403 <source>Size</source>
5404 <translation>Розмір</translation>
5405 </message>
5406</context>
5407<context>
5408 <name>GameListItemCompat</name>
5409 <message>
5410 <location filename="../../src/yuzu/game_list_p.h" line="149"/>
5411 <source>Perfect</source>
5412 <translation>Ідеально</translation>
5413 </message>
5414 <message>
5415 <location filename="../../src/yuzu/game_list_p.h" line="149"/>
5416 <source>Game functions flawless with no audio or graphical glitches, all tested functionality works as intended without
5417any workarounds needed.</source>
5418 <translation>Гра працює бездоганно, без звукових або графічних артефактів, усі протестовані функції працюють без обхідних шляхів.</translation>
5419 </message>
5420 <message>
5421 <location filename="../../src/yuzu/game_list_p.h" line="150"/>
5422 <source>Great</source>
5423 <translation>Чудово</translation>
5424 </message>
5425 <message>
5426 <location filename="../../src/yuzu/game_list_p.h" line="150"/>
5427 <source>Game functions with minor graphical or audio glitches and is playable from start to finish. May require some
5428workarounds.</source>
5429 <translation>Гра працює з невеликими графічними або звуковими артефактами і може бути пройдена від
5430 початку до кінця. Можуть знадобитися обхідні шляхи.</translation>
5431 </message>
5432 <message>
5433 <location filename="../../src/yuzu/game_list_p.h" line="151"/>
5434 <source>Okay</source>
5435 <translation>Добре</translation>
5436 </message>
5437 <message>
5438 <location filename="../../src/yuzu/game_list_p.h" line="151"/>
5439 <source>Game functions with major graphical or audio glitches, but game is playable from start to finish with
5440workarounds.</source>
5441 <translation>Гра працює з істотними графічними або звуковими артефактами, але може бути пройдена
5442з використанням обхідних шляхів.</translation>
5443 </message>
5444 <message>
5445 <location filename="../../src/yuzu/game_list_p.h" line="152"/>
5446 <source>Bad</source>
5447 <translation>Погано</translation>
5448 </message>
5449 <message>
5450 <location filename="../../src/yuzu/game_list_p.h" line="152"/>
5451 <source>Game functions, but with major graphical or audio glitches. Unable to progress in specific areas due to glitches
5452even with workarounds.</source>
5453 <translation>Гра працює, але з істотними графічними або звуковими артефактами.
5454У деяких частинах неможливо просунутися навіть з обхідними шляхами.</translation>
5455 </message>
5456 <message>
5457 <location filename="../../src/yuzu/game_list_p.h" line="153"/>
5458 <source>Intro/Menu</source>
5459 <translation>Вступ/Меню</translation>
5460 </message>
5461 <message>
5462 <location filename="../../src/yuzu/game_list_p.h" line="153"/>
5463 <source>Game is completely unplayable due to major graphical or audio glitches. Unable to progress past the Start
5464Screen.</source>
5465 <translation>У гру неможливо грати через графічні або звукові артефакти.
5466Неможливо просунутися далі стартового екрана.</translation>
5467 </message>
5468 <message>
5469 <location filename="../../src/yuzu/game_list_p.h" line="154"/>
5470 <source>Won&apos;t Boot</source>
5471 <translation>Не запускається</translation>
5472 </message>
5473 <message>
5474 <location filename="../../src/yuzu/game_list_p.h" line="154"/>
5475 <source>The game crashes when attempting to startup.</source>
5476 <translation>Гра вилітає під час запуску.</translation>
5477 </message>
5478 <message>
5479 <location filename="../../src/yuzu/game_list_p.h" line="155"/>
5480 <source>Not Tested</source>
5481 <translation>Не перевірено</translation>
5482 </message>
5483 <message>
5484 <location filename="../../src/yuzu/game_list_p.h" line="155"/>
5485 <source>The game has not yet been tested.</source>
5486 <translation>Гру ще не перевіряли на сумісність.</translation>
5487 </message>
5488</context>
5489<context>
5490 <name>GameListPlaceholder</name>
5491 <message>
5492 <location filename="../../src/yuzu/game_list.cpp" line="935"/>
5493 <source>Double-click to add a new folder to the game list</source>
5494 <translation>Натисніть двічі, щоб додати нову папку до списку ігор</translation>
5495 </message>
5496</context>
5497<context>
5498 <name>GameListSearchField</name>
5499 <message numerus="yes">
5500 <location filename="../../src/yuzu/game_list.cpp" line="86"/>
5501 <source>%1 of %n result(s)</source>
5502 <translation><numerusform>%1 із %n результат(ів)</numerusform><numerusform>%1 із %n результат(ів)</numerusform><numerusform>%1 із %n результат(ів)</numerusform><numerusform>%1 із %n результат(ів)</numerusform></translation>
5503 </message>
5504 <message>
5505 <location filename="../../src/yuzu/game_list.cpp" line="777"/>
5506 <source>Filter:</source>
5507 <translation>Пошук:</translation>
5508 </message>
5509 <message>
5510 <location filename="../../src/yuzu/game_list.cpp" line="778"/>
5511 <source>Enter pattern to filter</source>
5512 <translation>Введіть текст для пошуку</translation>
5513 </message>
5514</context>
5515<context>
5516 <name>HostRoom</name>
5517 <message>
5518 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="14"/>
5519 <source>Create Room</source>
5520 <translation>Створити кімнату</translation>
5521 </message>
5522 <message>
5523 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="37"/>
5524 <source>Room Name</source>
5525 <translation>Назва кімнати</translation>
5526 </message>
5527 <message>
5528 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="51"/>
5529 <source>Preferred Game</source>
5530 <translation>Переважна гра</translation>
5531 </message>
5532 <message>
5533 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="61"/>
5534 <source>Max Players</source>
5535 <translation>Максимальна кількість гравців</translation>
5536 </message>
5537 <message>
5538 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="91"/>
5539 <source>Username</source>
5540 <translation>Ім&apos;я користувача</translation>
5541 </message>
5542 <message>
5543 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="101"/>
5544 <source>(Leave blank for open game)</source>
5545 <translation>(Залиште порожнім для відкритої гри)</translation>
5546 </message>
5547 <message>
5548 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="118"/>
5549 <source>Password</source>
5550 <translation>Пароль</translation>
5551 </message>
5552 <message>
5553 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="125"/>
5554 <source>Port</source>
5555 <translation>Порт</translation>
5556 </message>
5557 <message>
5558 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="139"/>
5559 <source>Room Description</source>
5560 <translation>Опис кімнати</translation>
5561 </message>
5562 <message>
5563 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="153"/>
5564 <source>Load Previous Ban List</source>
5565 <translation>Завантажити попередній список заблокованих</translation>
5566 </message>
5567 <message>
5568 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="184"/>
5569 <source>Public</source>
5570 <translation>Публічна</translation>
5571 </message>
5572 <message>
5573 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="189"/>
5574 <source>Unlisted</source>
5575 <translation>Прихована</translation>
5576 </message>
5577 <message>
5578 <location filename="../../src/yuzu/multiplayer/host_room.ui" line="197"/>
5579 <source>Host Room</source>
5580 <translation>Створити кімнату</translation>
5581 </message>
5582</context>
5583<context>
5584 <name>HostRoomWindow</name>
5585 <message>
5586 <location filename="../../src/yuzu/multiplayer/host_room.cpp" line="182"/>
5587 <source>Error</source>
5588 <translation>Помилка</translation>
5589 </message>
5590 <message>
5591 <location filename="../../src/yuzu/multiplayer/host_room.cpp" line="183"/>
5592 <source>Failed to announce the room to the public lobby. In order to host a room publicly, you must have a valid yuzu account configured in Emulation -&gt; Configure -&gt; Web. If you do not want to publish a room in the public lobby, then select Unlisted instead.
5593Debug Message: </source>
5594 <translation>Не вдалося оголосити кімнату в публічному фойє. Щоб хостити публічну кімнату, у вас має бути діючий обліковий запис yuzu, налаштований в Емуляція -&gt; Налаштування -&gt; Мережа. Якщо ви не хочете оголошувати кімнату в публічному лобі, виберіть замість цього прихований тип.
5595Повідомлення налагодження:</translation>
5596 </message>
5597</context>
5598<context>
5599 <name>Hotkeys</name>
5600 <message>
5601 <location filename="../../src/yuzu/configuration/config.cpp" line="73"/>
5602 <source>Audio Mute/Unmute</source>
5603 <translation>Увімкнення/вимкнення звуку</translation>
5604 </message>
5605 <message>
5606 <location filename="../../src/yuzu/configuration/config.cpp" line="73"/>
5607 <location filename="../../src/yuzu/configuration/config.cpp" line="74"/>
5608 <location filename="../../src/yuzu/configuration/config.cpp" line="75"/>
5609 <location filename="../../src/yuzu/configuration/config.cpp" line="76"/>
5610 <location filename="../../src/yuzu/configuration/config.cpp" line="77"/>
5611 <location filename="../../src/yuzu/configuration/config.cpp" line="78"/>
5612 <location filename="../../src/yuzu/configuration/config.cpp" line="79"/>
5613 <location filename="../../src/yuzu/configuration/config.cpp" line="80"/>
5614 <location filename="../../src/yuzu/configuration/config.cpp" line="81"/>
5615 <location filename="../../src/yuzu/configuration/config.cpp" line="82"/>
5616 <location filename="../../src/yuzu/configuration/config.cpp" line="83"/>
5617 <location filename="../../src/yuzu/configuration/config.cpp" line="84"/>
5618 <location filename="../../src/yuzu/configuration/config.cpp" line="85"/>
5619 <location filename="../../src/yuzu/configuration/config.cpp" line="86"/>
5620 <location filename="../../src/yuzu/configuration/config.cpp" line="87"/>
5621 <location filename="../../src/yuzu/configuration/config.cpp" line="88"/>
5622 <location filename="../../src/yuzu/configuration/config.cpp" line="89"/>
5623 <location filename="../../src/yuzu/configuration/config.cpp" line="90"/>
5624 <location filename="../../src/yuzu/configuration/config.cpp" line="91"/>
5625 <location filename="../../src/yuzu/configuration/config.cpp" line="92"/>
5626 <location filename="../../src/yuzu/configuration/config.cpp" line="93"/>
5627 <location filename="../../src/yuzu/configuration/config.cpp" line="94"/>
5628 <source>Main Window</source>
5629 <translation>Основне вікно</translation>
5630 </message>
5631 <message>
5632 <location filename="../../src/yuzu/configuration/config.cpp" line="74"/>
5633 <source>Audio Volume Down</source>
5634 <translation>Зменшити гучність звуку</translation>
5635 </message>
5636 <message>
5637 <location filename="../../src/yuzu/configuration/config.cpp" line="75"/>
5638 <source>Audio Volume Up</source>
5639 <translation>Підвищити гучність звуку</translation>
5640 </message>
5641 <message>
5642 <location filename="../../src/yuzu/configuration/config.cpp" line="76"/>
5643 <source>Capture Screenshot</source>
5644 <translation>Зробити знімок екрану</translation>
5645 </message>
5646 <message>
5647 <location filename="../../src/yuzu/configuration/config.cpp" line="77"/>
5648 <source>Change Adapting Filter</source>
5649 <translation>Змінити адаптуючий фільтр</translation>
5650 </message>
5651 <message>
5652 <location filename="../../src/yuzu/configuration/config.cpp" line="78"/>
5653 <source>Change Docked Mode</source>
5654 <translation>Змінити режим консолі</translation>
5655 </message>
5656 <message>
5657 <location filename="../../src/yuzu/configuration/config.cpp" line="79"/>
5658 <source>Change GPU Accuracy</source>
5659 <translation>Змінити точність ГП</translation>
5660 </message>
5661 <message>
5662 <location filename="../../src/yuzu/configuration/config.cpp" line="80"/>
5663 <source>Continue/Pause Emulation</source>
5664 <translation>Продовження/Пауза емуляції</translation>
5665 </message>
5666 <message>
5667 <location filename="../../src/yuzu/configuration/config.cpp" line="81"/>
5668 <source>Exit Fullscreen</source>
5669 <translation>Вийти з повноекранного режиму</translation>
5670 </message>
5671 <message>
5672 <location filename="../../src/yuzu/configuration/config.cpp" line="82"/>
5673 <source>Exit yuzu</source>
5674 <translation>Вийти з yuzu</translation>
5675 </message>
5676 <message>
5677 <location filename="../../src/yuzu/configuration/config.cpp" line="83"/>
5678 <source>Fullscreen</source>
5679 <translation>Повний екран</translation>
5680 </message>
5681 <message>
5682 <location filename="../../src/yuzu/configuration/config.cpp" line="84"/>
5683 <source>Load File</source>
5684 <translation>Завантажити файл</translation>
5685 </message>
5686 <message>
5687 <location filename="../../src/yuzu/configuration/config.cpp" line="85"/>
5688 <source>Load/Remove Amiibo</source>
5689 <translation>Завантажити/видалити Amiibo</translation>
5690 </message>
5691 <message>
5692 <location filename="../../src/yuzu/configuration/config.cpp" line="86"/>
5693 <source>Restart Emulation</source>
5694 <translation>Перезапустити емуляцію</translation>
5695 </message>
5696 <message>
5697 <location filename="../../src/yuzu/configuration/config.cpp" line="87"/>
5698 <source>Stop Emulation</source>
5699 <translation>Зупинити емуляцію</translation>
5700 </message>
5701 <message>
5702 <location filename="../../src/yuzu/configuration/config.cpp" line="88"/>
5703 <source>TAS Record</source>
5704 <translation>Запис TAS</translation>
5705 </message>
5706 <message>
5707 <location filename="../../src/yuzu/configuration/config.cpp" line="89"/>
5708 <source>TAS Reset</source>
5709 <translation>Скидання TAS</translation>
5710 </message>
5711 <message>
5712 <location filename="../../src/yuzu/configuration/config.cpp" line="90"/>
5713 <source>TAS Start/Stop</source>
5714 <translation>Старт/Стоп TAS</translation>
5715 </message>
5716 <message>
5717 <location filename="../../src/yuzu/configuration/config.cpp" line="91"/>
5718 <source>Toggle Filter Bar</source>
5719 <translation>Переключити панель пошуку</translation>
5720 </message>
5721 <message>
5722 <location filename="../../src/yuzu/configuration/config.cpp" line="92"/>
5723 <source>Toggle Framerate Limit</source>
5724 <translation>Переключити обмеження частоти кадрів</translation>
5725 </message>
5726 <message>
5727 <location filename="../../src/yuzu/configuration/config.cpp" line="93"/>
5728 <source>Toggle Mouse Panning</source>
5729 <translation>Переключити панорамування миші</translation>
5730 </message>
5731 <message>
5732 <location filename="../../src/yuzu/configuration/config.cpp" line="94"/>
5733 <source>Toggle Status Bar</source>
5734 <translation>Переключити панель стану</translation>
5735 </message>
5736</context>
5737<context>
5738 <name>InstallDialog</name>
5739 <message>
5740 <location filename="../../src/yuzu/install_dialog.cpp" line="29"/>
5741 <source>Please confirm these are the files you wish to install.</source>
5742 <translation>Будь ласка, переконайтеся, що це ті файли, які ви хочете встановити.</translation>
5743 </message>
5744 <message>
5745 <location filename="../../src/yuzu/install_dialog.cpp" line="32"/>
5746 <source>Installing an Update or DLC will overwrite the previously installed one.</source>
5747 <translation>Встановлення оновлення або завантажуваного контенту перезапише раніше встановлене.</translation>
5748 </message>
5749 <message>
5750 <location filename="../../src/yuzu/install_dialog.cpp" line="36"/>
5751 <source>Install</source>
5752 <translation>Встановити</translation>
5753 </message>
5754 <message>
5755 <location filename="../../src/yuzu/install_dialog.cpp" line="50"/>
5756 <source>Install Files to NAND</source>
5757 <translation>Встановити файли в NAND</translation>
5758 </message>
5759</context>
5760<context>
5761 <name>LimitableInputDialog</name>
5762 <message>
5763 <location filename="../../src/yuzu/util/limitable_input_dialog.cpp" line="61"/>
5764 <source>The text can't contain any of the following characters:
5765%1</source>
5766 <translation>У тексті неприпустимі такі символи:
5767%1</translation>
5768 </message>
5769</context>
5770<context>
5771 <name>LoadingScreen</name>
5772 <message>
5773 <location filename="../../src/yuzu/loading_screen.ui" line="84"/>
5774 <source>Loading Shaders 387 / 1628</source>
5775 <translation>Завантаження шейдерів 387 / 1628</translation>
5776 </message>
5777 <message>
5778 <location filename="../../src/yuzu/loading_screen.ui" line="121"/>
5779 <source>Loading Shaders %v out of %m</source>
5780 <translation>Завантаження шейдерів %v із %m</translation>
5781 </message>
5782 <message>
5783 <location filename="../../src/yuzu/loading_screen.ui" line="135"/>
5784 <source>Estimated Time 5m 4s</source>
5785 <translation>Залишилося приблизно 5м 4с</translation>
5786 </message>
5787 <message>
5788 <location filename="../../src/yuzu/loading_screen.cpp" line="83"/>
5789 <source>Loading...</source>
5790 <translation>Завантаження...</translation>
5791 </message>
5792 <message>
5793 <location filename="../../src/yuzu/loading_screen.cpp" line="84"/>
5794 <source>Loading Shaders %1 / %2</source>
5795 <translation>Завантаження шейдерів %1 / %2</translation>
5796 </message>
5797 <message>
5798 <location filename="../../src/yuzu/loading_screen.cpp" line="85"/>
5799 <source>Launching...</source>
5800 <translation>Запуск...</translation>
5801 </message>
5802 <message>
5803 <location filename="../../src/yuzu/loading_screen.cpp" line="170"/>
5804 <source>Estimated Time %1</source>
5805 <translation>Залишилося приблизно %1</translation>
5806 </message>
5807</context>
5808<context>
5809 <name>Lobby</name>
5810 <message>
5811 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="14"/>
5812 <source>Public Room Browser</source>
5813 <translation>Браузер публічних кімнат</translation>
5814 </message>
5815 <message>
5816 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="32"/>
5817 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="39"/>
5818 <source>Nickname</source>
5819 <translation>Псевдонім</translation>
5820 </message>
5821 <message>
5822 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="59"/>
5823 <source>Filters</source>
5824 <translation>Фільтри</translation>
5825 </message>
5826 <message>
5827 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="66"/>
5828 <source>Search</source>
5829 <translation>Пошук</translation>
5830 </message>
5831 <message>
5832 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="76"/>
5833 <source>Games I Own</source>
5834 <translation>Ігри, якими я володію</translation>
5835 </message>
5836 <message>
5837 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="83"/>
5838 <source>Hide Full Rooms</source>
5839 <translation>Приховати повні кімнати</translation>
5840 </message>
5841 <message>
5842 <location filename="../../src/yuzu/multiplayer/lobby.ui" line="103"/>
5843 <source>Refresh Lobby</source>
5844 <translation>Оновити фойє</translation>
5845 </message>
5846 <message>
5847 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="112"/>
5848 <source>Password Required to Join</source>
5849 <translation>Для входу необхідний пароль</translation>
5850 </message>
5851 <message>
5852 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="112"/>
5853 <source>Password:</source>
5854 <translation>Пароль:</translation>
5855 </message>
5856 <message>
5857 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="215"/>
5858 <source>Players</source>
5859 <translation>Гравці</translation>
5860 </message>
5861 <message>
5862 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="216"/>
5863 <source>Room Name</source>
5864 <translation>Назва кімнати</translation>
5865 </message>
5866 <message>
5867 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="217"/>
5868 <source>Preferred Game</source>
5869 <translation>Переважна гра</translation>
5870 </message>
5871 <message>
5872 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="218"/>
5873 <source>Host</source>
5874 <translation>Хост</translation>
5875 </message>
5876 <message>
5877 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="225"/>
5878 <source>Refreshing</source>
5879 <translation>Оновлення</translation>
5880 </message>
5881 <message>
5882 <location filename="../../src/yuzu/multiplayer/lobby.cpp" line="282"/>
5883 <source>Refresh List</source>
5884 <translation>Оновити список</translation>
5885 </message>
5886</context>
5887<context>
5888 <name>MainWindow</name>
5889 <message>
5890 <location filename="../../src/yuzu/main.ui" line="14"/>
5891 <source>yuzu</source>
5892 <translation>yuzu</translation>
5893 </message>
5894 <message>
5895 <location filename="../../src/yuzu/main.ui" line="44"/>
5896 <source>&amp;File</source>
5897 <translation>[&amp;F] Файл</translation>
5898 </message>
5899 <message>
5900 <location filename="../../src/yuzu/main.ui" line="48"/>
5901 <source>&amp;Recent Files</source>
5902 <translation>[&amp;R] Нещодавні файли</translation>
5903 </message>
5904 <message>
5905 <location filename="../../src/yuzu/main.ui" line="67"/>
5906 <source>&amp;Emulation</source>
5907 <translation>[&amp;E] Емуляція</translation>
5908 </message>
5909 <message>
5910 <location filename="../../src/yuzu/main.ui" line="78"/>
5911 <source>&amp;View</source>
5912 <translation>[&amp;V] Вигляд</translation>
5913 </message>
5914 <message>
5915 <location filename="../../src/yuzu/main.ui" line="82"/>
5916 <source>&amp;Reset Window Size</source>
5917 <translation>[&amp;R] Скинути розмір вікна</translation>
5918 </message>
5919 <message>
5920 <location filename="../../src/yuzu/main.ui" line="87"/>
5921 <source>&amp;Debugging</source>
5922 <translation>[&amp;D] Налагодження</translation>
5923 </message>
5924 <message>
5925 <location filename="../../src/yuzu/main.ui" line="92"/>
5926 <source>Reset Window Size to &amp;720p</source>
5927 <translation>Скинути розмір вікна до &amp;720p</translation>
5928 </message>
5929 <message>
5930 <location filename="../../src/yuzu/main.ui" line="95"/>
5931 <source>Reset Window Size to 720p</source>
5932 <translation>Скинути розмір вікна до 720p</translation>
5933 </message>
5934 <message>
5935 <location filename="../../src/yuzu/main.ui" line="100"/>
5936 <source>Reset Window Size to &amp;900p</source>
5937 <translation>Скинути розмір вікна до &amp;900p</translation>
5938 </message>
5939 <message>
5940 <location filename="../../src/yuzu/main.ui" line="103"/>
5941 <source>Reset Window Size to 900p</source>
5942 <translation>Скинути розмір вікна до 900p</translation>
5943 </message>
5944 <message>
5945 <location filename="../../src/yuzu/main.ui" line="108"/>
5946 <source>Reset Window Size to &amp;1080p</source>
5947 <translation>Скинути розмір вікна до &amp;1080p</translation>
5948 </message>
5949 <message>
5950 <location filename="../../src/yuzu/main.ui" line="111"/>
5951 <source>Reset Window Size to 1080p</source>
5952 <translation>Скинути розмір вікна до 1080p</translation>
5953 </message>
5954 <message>
5955 <location filename="../../src/yuzu/main.ui" line="128"/>
5956 <source>&amp;Multiplayer</source>
5957 <translation>[&amp;M] Мультиплеєр</translation>
5958 </message>
5959 <message>
5960 <location filename="../../src/yuzu/main.ui" line="139"/>
5961 <source>&amp;Tools</source>
5962 <translation>[&amp;T] Інструменти</translation>
5963 </message>
5964 <message>
5965 <location filename="../../src/yuzu/main.ui" line="143"/>
5966 <source>&amp;TAS</source>
5967 <translation>[&amp;T] TAS</translation>
5968 </message>
5969 <message>
5970 <location filename="../../src/yuzu/main.ui" line="158"/>
5971 <source>&amp;Help</source>
5972 <translation>[&amp;H] Допомога</translation>
5973 </message>
5974 <message>
5975 <location filename="../../src/yuzu/main.ui" line="179"/>
5976 <source>&amp;Install Files to NAND...</source>
5977 <translation>[&amp;I] Встановити файли в NAND...</translation>
5978 </message>
5979 <message>
5980 <location filename="../../src/yuzu/main.ui" line="184"/>
5981 <source>L&amp;oad File...</source>
5982 <translation>[&amp;O] Завантажити файл...</translation>
5983 </message>
5984 <message>
5985 <location filename="../../src/yuzu/main.ui" line="189"/>
5986 <source>Load &amp;Folder...</source>
5987 <translation>[&amp;F] Завантажити папку...</translation>
5988 </message>
5989 <message>
5990 <location filename="../../src/yuzu/main.ui" line="194"/>
5991 <source>E&amp;xit</source>
5992 <translation>[&amp;X] Вихід</translation>
5993 </message>
5994 <message>
5995 <location filename="../../src/yuzu/main.ui" line="202"/>
5996 <source>&amp;Pause</source>
5997 <translation>[&amp;P] Пауза</translation>
5998 </message>
5999 <message>
6000 <location filename="../../src/yuzu/main.ui" line="210"/>
6001 <source>&amp;Stop</source>
6002 <translation>[&amp;S] Стоп</translation>
6003 </message>
6004 <message>
6005 <location filename="../../src/yuzu/main.ui" line="215"/>
6006 <source>&amp;Reinitialize keys...</source>
6007 <translation>[&amp;R] Переініціалізувати ключі...</translation>
6008 </message>
6009 <message>
6010 <location filename="../../src/yuzu/main.ui" line="220"/>
6011 <source>&amp;About yuzu</source>
6012 <translation>[&amp;A] Про yuzu</translation>
6013 </message>
6014 <message>
6015 <location filename="../../src/yuzu/main.ui" line="228"/>
6016 <source>Single &amp;Window Mode</source>
6017 <translation>[&amp;W] Режим одного вікна</translation>
6018 </message>
6019 <message>
6020 <location filename="../../src/yuzu/main.ui" line="233"/>
6021 <source>Con&amp;figure...</source>
6022 <translation>[&amp;F] Налаштування...</translation>
6023 </message>
6024 <message>
6025 <location filename="../../src/yuzu/main.ui" line="241"/>
6026 <source>Display D&amp;ock Widget Headers</source>
6027 <translation>[&amp;O] Відображати заголовки віджетів дока</translation>
6028 </message>
6029 <message>
6030 <location filename="../../src/yuzu/main.ui" line="249"/>
6031 <source>Show &amp;Filter Bar</source>
6032 <translation>[&amp;F] Показати панель пошуку</translation>
6033 </message>
6034 <message>
6035 <location filename="../../src/yuzu/main.ui" line="257"/>
6036 <source>Show &amp;Status Bar</source>
6037 <translation>[&amp;S] Показати панель статусу</translation>
6038 </message>
6039 <message>
6040 <location filename="../../src/yuzu/main.ui" line="260"/>
6041 <source>Show Status Bar</source>
6042 <translation>Показати панель статусу</translation>
6043 </message>
6044 <message>
6045 <location filename="../../src/yuzu/main.ui" line="268"/>
6046 <source>&amp;Browse Public Game Lobby</source>
6047 <translation>[&amp;B] Переглянути публічні ігрові фойє</translation>
6048 </message>
6049 <message>
6050 <location filename="../../src/yuzu/main.ui" line="276"/>
6051 <source>&amp;Create Room</source>
6052 <translation>[&amp;C] Створити кімнату</translation>
6053 </message>
6054 <message>
6055 <location filename="../../src/yuzu/main.ui" line="284"/>
6056 <source>&amp;Leave Room</source>
6057 <translation>[&amp;L] Залишити кімнату</translation>
6058 </message>
6059 <message>
6060 <location filename="../../src/yuzu/main.ui" line="289"/>
6061 <source>&amp;Direct Connect to Room</source>
6062 <translation>[&amp;D] Пряме під&apos;єднання до кімнати</translation>
6063 </message>
6064 <message>
6065 <location filename="../../src/yuzu/main.ui" line="297"/>
6066 <source>&amp;Show Current Room</source>
6067 <translation>[&amp;S] Показати поточну кімнату</translation>
6068 </message>
6069 <message>
6070 <location filename="../../src/yuzu/main.ui" line="305"/>
6071 <source>F&amp;ullscreen</source>
6072 <translation>[&amp;U] Повноекранний</translation>
6073 </message>
6074 <message>
6075 <location filename="../../src/yuzu/main.ui" line="313"/>
6076 <source>&amp;Restart</source>
6077 <translation>[&amp;R] Перезапустити</translation>
6078 </message>
6079 <message>
6080 <location filename="../../src/yuzu/main.ui" line="321"/>
6081 <source>Load/Remove &amp;Amiibo...</source>
6082 <translation>[&amp;A] Завантажити/Видалити Amiibo...</translation>
6083 </message>
6084 <message>
6085 <location filename="../../src/yuzu/main.ui" line="329"/>
6086 <source>&amp;Report Compatibility</source>
6087 <translation>[&amp;R] Повідомити про сумісність</translation>
6088 </message>
6089 <message>
6090 <location filename="../../src/yuzu/main.ui" line="337"/>
6091 <source>Open &amp;Mods Page</source>
6092 <translation>[&amp;M] Відкрити сторінку модів</translation>
6093 </message>
6094 <message>
6095 <location filename="../../src/yuzu/main.ui" line="342"/>
6096 <source>Open &amp;Quickstart Guide</source>
6097 <translation>[&amp;Q] Відкрити посібник користувача</translation>
6098 </message>
6099 <message>
6100 <location filename="../../src/yuzu/main.ui" line="347"/>
6101 <source>&amp;FAQ</source>
6102 <translation>[&amp;F] ЧАП</translation>
6103 </message>
6104 <message>
6105 <location filename="../../src/yuzu/main.ui" line="352"/>
6106 <source>Open &amp;yuzu Folder</source>
6107 <translation>[&amp;Y] Відкрити папку yuzu</translation>
6108 </message>
6109 <message>
6110 <location filename="../../src/yuzu/main.ui" line="360"/>
6111 <source>&amp;Capture Screenshot</source>
6112 <translation>[&amp;C] Зробити знімок екрану</translation>
6113 </message>
6114 <message>
6115 <location filename="../../src/yuzu/main.ui" line="365"/>
6116 <source>&amp;Configure TAS...</source>
6117 <translation>[&amp;C] Налаштування TAS...</translation>
6118 </message>
6119 <message>
6120 <location filename="../../src/yuzu/main.ui" line="373"/>
6121 <source>Configure C&amp;urrent Game...</source>
6122 <translation>[&amp;U] Налаштувати поточну гру...</translation>
6123 </message>
6124 <message>
6125 <location filename="../../src/yuzu/main.ui" line="381"/>
6126 <source>&amp;Start</source>
6127 <translation>[&amp;S] Почати</translation>
6128 </message>
6129 <message>
6130 <location filename="../../src/yuzu/main.ui" line="389"/>
6131 <source>&amp;Reset</source>
6132 <translation>[&amp;S] Скинути</translation>
6133 </message>
6134 <message>
6135 <location filename="../../src/yuzu/main.ui" line="397"/>
6136 <source>R&amp;ecord</source>
6137 <translation>[&amp;E] Запис</translation>
6138 </message>
6139</context>
6140<context>
6141 <name>MicroProfileDialog</name>
6142 <message>
6143 <location filename="../../src/yuzu/debugger/profiler.cpp" line="50"/>
6144 <source>&amp;MicroProfile</source>
6145 <translation>[&amp;M] MicroProfile</translation>
6146 </message>
6147</context>
6148<context>
6149 <name>ModerationDialog</name>
6150 <message>
6151 <location filename="../../src/yuzu/multiplayer/moderation_dialog.ui" line="6"/>
6152 <source>Moderation</source>
6153 <translation>Модерація</translation>
6154 </message>
6155 <message>
6156 <location filename="../../src/yuzu/multiplayer/moderation_dialog.ui" line="20"/>
6157 <source>Ban List</source>
6158 <translation>Список заблокованих</translation>
6159 </message>
6160 <message>
6161 <location filename="../../src/yuzu/multiplayer/moderation_dialog.ui" line="41"/>
6162 <location filename="../../src/yuzu/multiplayer/moderation_dialog.cpp" line="73"/>
6163 <source>Refreshing</source>
6164 <translation>Оновлення</translation>
6165 </message>
6166 <message>
6167 <location filename="../../src/yuzu/multiplayer/moderation_dialog.ui" line="51"/>
6168 <source>Unban</source>
6169 <translation>Розблокувати</translation>
6170 </message>
6171 <message>
6172 <location filename="../../src/yuzu/multiplayer/moderation_dialog.cpp" line="40"/>
6173 <source>Subject</source>
6174 <translation>Суб&apos;єкт</translation>
6175 </message>
6176 <message>
6177 <location filename="../../src/yuzu/multiplayer/moderation_dialog.cpp" line="41"/>
6178 <source>Type</source>
6179 <translation>Тип</translation>
6180 </message>
6181 <message>
6182 <location filename="../../src/yuzu/multiplayer/moderation_dialog.cpp" line="83"/>
6183 <source>Forum Username</source>
6184 <translation>Ім&apos;я користувача на форумі</translation>
6185 </message>
6186 <message>
6187 <location filename="../../src/yuzu/multiplayer/moderation_dialog.cpp" line="88"/>
6188 <source>IP Address</source>
6189 <translation>IP-адреса</translation>
6190 </message>
6191 <message>
6192 <location filename="../../src/yuzu/multiplayer/moderation_dialog.cpp" line="95"/>
6193 <source>Refresh</source>
6194 <translation>Оновити</translation>
6195 </message>
6196</context>
6197<context>
6198 <name>MultiplayerState</name>
6199 <message>
6200 <location filename="../../src/yuzu/multiplayer/state.cpp" line="90"/>
6201 <source>Current connection status</source>
6202 <translation>Поточний стан з&apos;єднання</translation>
6203 </message>
6204 <message>
6205 <location filename="../../src/yuzu/multiplayer/state.cpp" line="117"/>
6206 <source>Not Connected. Click here to find a room!</source>
6207 <translation>Не з&apos;єднано. Натисніть тут, щоб знайти кімнату!</translation>
6208 </message>
6209 <message>
6210 <location filename="../../src/yuzu/multiplayer/state.cpp" line="123"/>
6211 <source>Not Connected</source>
6212 <translation>Не з&apos;єднано</translation>
6213 </message>
6214 <message>
6215 <location filename="../../src/yuzu/multiplayer/state.cpp" line="129"/>
6216 <source>Connected</source>
6217 <translation>З&apos;єднано</translation>
6218 </message>
6219 <message>
6220 <location filename="../../src/yuzu/multiplayer/state.cpp" line="136"/>
6221 <source>New Messages Received</source>
6222 <translation>Отримано нові повідомлення</translation>
6223 </message>
6224 <message>
6225 <location filename="../../src/yuzu/multiplayer/state.cpp" line="207"/>
6226 <source>Error</source>
6227 <translation>Помилка</translation>
6228 </message>
6229 <message>
6230 <location filename="../../src/yuzu/multiplayer/state.cpp" line="208"/>
6231 <source>Failed to update the room information. Please check your Internet connection and try hosting the room again.
6232Debug Message: </source>
6233 <translation>Не вдалося оновити інформацію про кімнату. Будь ласка, перевірте підключення до Інтернету та спробуйте знову зайти в кімнату.
6234Повідомлення налагодження:</translation>
6235 </message>
6236</context>
6237<context>
6238 <name>NetworkMessage</name>
6239 <message>
6240 <location filename="../../src/yuzu/multiplayer/message.cpp" line="11"/>
6241 <source>Username is not valid. Must be 4 to 20 alphanumeric characters.</source>
6242 <translation>Ім&apos;я користувача неприпустиме. Має бути від 4 до 20 буквено-цифрових символів.</translation>
6243 </message>
6244 <message>
6245 <location filename="../../src/yuzu/multiplayer/message.cpp" line="13"/>
6246 <source>Room name is not valid. Must be 4 to 20 alphanumeric characters.</source>
6247 <translation>Назва кімнати неприпустима. Має бути від 4 до 20 буквено-цифрових символів.</translation>
6248 </message>
6249 <message>
6250 <location filename="../../src/yuzu/multiplayer/message.cpp" line="15"/>
6251 <source>Username is already in use or not valid. Please choose another.</source>
6252 <translation>Ім&apos;я користувача вже використовується або недійсне. Будь ласка, виберіть інше.</translation>
6253 </message>
6254 <message>
6255 <location filename="../../src/yuzu/multiplayer/message.cpp" line="17"/>
6256 <source>IP is not a valid IPv4 address.</source>
6257 <translation>IP-адреса не є дійсною адресою IPv4.</translation>
6258 </message>
6259 <message>
6260 <location filename="../../src/yuzu/multiplayer/message.cpp" line="19"/>
6261 <source>Port must be a number between 0 to 65535.</source>
6262 <translation>Порт повинен бути числом від 0 до 65535.</translation>
6263 </message>
6264 <message>
6265 <location filename="../../src/yuzu/multiplayer/message.cpp" line="20"/>
6266 <source>You must choose a Preferred Game to host a room. If you do not have any games in your game list yet, add a game folder by clicking on the plus icon in the game list.</source>
6267 <translation>Ви повинні вибрати бажану гру, щоб хостити кімнату. Якщо у вашому списку ігор ще немає жодної гри, додайте папку з грою, натиснувши на значок плюса у списку ігор.</translation>
6268 </message>
6269 <message>
6270 <location filename="../../src/yuzu/multiplayer/message.cpp" line="24"/>
6271 <source>Unable to find an internet connection. Check your internet settings.</source>
6272 <translation>Неможливо знайти підключення до Інтернету. Перевірте налаштування інтернету.</translation>
6273 </message>
6274 <message>
6275 <location filename="../../src/yuzu/multiplayer/message.cpp" line="26"/>
6276 <source>Unable to connect to the host. Verify that the connection settings are correct. If you still cannot connect, contact the room host and verify that the host is properly configured with the external port forwarded.</source>
6277 <translation>Неможливо підключитися до хоста. Перевірте правильність налаштувань підключення. Якщо під&apos;єднання, як і раніше, неможливе, зв&apos;яжіться з хостом кімнати та переконайтеся, що хост правильно налаштований із прокинутим зовнішнім портом.</translation>
6278 </message>
6279 <message>
6280 <location filename="../../src/yuzu/multiplayer/message.cpp" line="30"/>
6281 <source>Unable to connect to the room because it is already full.</source>
6282 <translation>Неможливо підключитися до кімнати, оскільки вона вже заповнена.</translation>
6283 </message>
6284 <message>
6285 <location filename="../../src/yuzu/multiplayer/message.cpp" line="32"/>
6286 <source>Creating a room failed. Please retry. Restarting yuzu might be necessary.</source>
6287 <translation>Створення кімнати не вдалося. Будь ласка, повторіть спробу. Можливо, потрібно перезапустити yuzu.</translation>
6288 </message>
6289 <message>
6290 <location filename="../../src/yuzu/multiplayer/message.cpp" line="34"/>
6291 <source>The host of the room has banned you. Speak with the host to unban you or try a different room.</source>
6292 <translation>Хост кімнати заблокував вас. Поговоріть із хостом, щоб він розблокував вас, або спробуйте іншу кімнату.</translation>
6293 </message>
6294 <message>
6295 <location filename="../../src/yuzu/multiplayer/message.cpp" line="37"/>
6296 <source>Version mismatch! Please update to the latest version of yuzu. If the problem persists, contact the room host and ask them to update the server.</source>
6297 <translation>Невідповідність версій! Будь ласка, оновіть yuzu до останньої версії. Якщо проблема не зникне, зверніться до хосту кімнати і попросіть його оновити сервер.</translation>
6298 </message>
6299 <message>
6300 <location filename="../../src/yuzu/multiplayer/message.cpp" line="39"/>
6301 <source>Incorrect password.</source>
6302 <translation>Невірний пароль.</translation>
6303 </message>
6304 <message>
6305 <location filename="../../src/yuzu/multiplayer/message.cpp" line="40"/>
6306 <source>An unknown error occurred. If this error continues to occur, please open an issue</source>
6307 <translation>Сталася невідома помилка. Якщо ця помилка продовжує виникати, будь ласка, відкрийте проблему</translation>
6308 </message>
6309 <message>
6310 <location filename="../../src/yuzu/multiplayer/message.cpp" line="43"/>
6311 <source>Connection to room lost. Try to reconnect.</source>
6312 <translation>З&apos;єднання з кімнатою втрачено. Спробуйте підключитися знову.</translation>
6313 </message>
6314 <message>
6315 <location filename="../../src/yuzu/multiplayer/message.cpp" line="45"/>
6316 <source>You have been kicked by the room host.</source>
6317 <translation>Вас вигнав хост кімнати.</translation>
6318 </message>
6319 <message>
6320 <location filename="../../src/yuzu/multiplayer/message.cpp" line="47"/>
6321 <source>IP address is already in use. Please choose another.</source>
6322 <translation>IP-адреса вже використовується. Будь ласка, виберіть іншу.</translation>
6323 </message>
6324 <message>
6325 <location filename="../../src/yuzu/multiplayer/message.cpp" line="49"/>
6326 <source>You do not have enough permission to perform this action.</source>
6327 <translation>У вас немає достатніх дозволів для виконання цієї дії.</translation>
6328 </message>
6329 <message>
6330 <location filename="../../src/yuzu/multiplayer/message.cpp" line="50"/>
6331 <source>The user you are trying to kick/ban could not be found.
6332They may have left the room.</source>
6333 <translation>Користувача, якого ви намагаєтеся вигнати/заблокувати, не знайдено.
6334Можливо, вони покинули кімнату.</translation>
6335 </message>
6336 <message>
6337 <location filename="../../src/yuzu/multiplayer/message.cpp" line="52"/>
6338 <source>No valid network interface is selected.
6339Please go to Configure -&gt; System -&gt; Network and make a selection.</source>
6340 <translation>Не вибрано припустимий інтерфейс мережі.
6341Будь ласка, перейдіть у Налаштування -&gt; Система -&gt; Мережа та зробіть вибір.</translation>
6342 </message>
6343 <message>
6344 <location filename="../../src/yuzu/multiplayer/message.cpp" line="68"/>
6345 <source>Game already running</source>
6346 <translation>Гру вже запущено</translation>
6347 </message>
6348 <message>
6349 <location filename="../../src/yuzu/multiplayer/message.cpp" line="69"/>
6350 <source>Joining a room when the game is already running is discouraged and can cause the room feature not to work correctly.
6351Proceed anyway?</source>
6352 <translation>Приєднуватися до кімнати, коли гру вже запущено, не рекомендується, це може призвести до неправильної роботи функції кімнати.
6353Все одно продовжити?</translation>
6354 </message>
6355 <message>
6356 <location filename="../../src/yuzu/multiplayer/message.cpp" line="75"/>
6357 <source>Leave Room</source>
6358 <translation>Залишити кімнату</translation>
6359 </message>
6360 <message>
6361 <location filename="../../src/yuzu/multiplayer/message.cpp" line="76"/>
6362 <source>You are about to close the room. Any network connections will be closed.</source>
6363 <translation>Ви збираєтеся закрити кімнату. Усі мережеві підключення буде закрито.</translation>
6364 </message>
6365 <message>
6366 <location filename="../../src/yuzu/multiplayer/message.cpp" line="81"/>
6367 <source>Disconnect</source>
6368 <translation>Від&apos;єднатися</translation>
6369 </message>
6370 <message>
6371 <location filename="../../src/yuzu/multiplayer/message.cpp" line="82"/>
6372 <source>You are about to leave the room. Any network connections will be closed.</source>
6373 <translation>Ви збираєтеся покинути кімнату. Усі мережеві підключення буде закрито.</translation>
6374 </message>
6375</context>
6376<context>
6377 <name>NetworkMessage::ErrorManager</name>
6378 <message>
6379 <location filename="../../src/yuzu/multiplayer/message.cpp" line="63"/>
6380 <source>Error</source>
6381 <translation>Помилка</translation>
6382 </message>
6383</context>
6384<context>
6385 <name>OverlayDialog</name>
6386 <message>
6387 <location filename="../../src/yuzu/util/overlay_dialog.ui" line="14"/>
6388 <source>Dialog</source>
6389 <translation>Діалог</translation>
6390 </message>
6391 <message>
6392 <location filename="../../src/yuzu/util/overlay_dialog.ui" line="134"/>
6393 <location filename="../../src/yuzu/util/overlay_dialog.ui" line="353"/>
6394 <source>Cancel</source>
6395 <translation>Скасувати</translation>
6396 </message>
6397 <message>
6398 <location filename="../../src/yuzu/util/overlay_dialog.ui" line="152"/>
6399 <location filename="../../src/yuzu/util/overlay_dialog.ui" line="371"/>
6400 <source>OK</source>
6401 <translation>ОК</translation>
6402 </message>
6403 <message>
6404 <location filename="../../src/yuzu/util/overlay_dialog.ui" line="313"/>
6405 <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
6406&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
6407p, li { white-space: pre-wrap; }
6408&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:400; font-style:normal;&quot;&gt;
6409&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
6410 <translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
6411&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
6412p, li { white-space: pre-wrap; }
6413&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:18pt; font-weight:400; font-style:normal;&quot;&gt;
6414&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
6415 </message>
6416</context>
6417<context>
6418 <name>PlayerControlPreview</name>
6419 <message>
6420 <location filename="../../src/yuzu/configuration/configure_input_player_widget.cpp" line="1575"/>
6421 <source>START/PAUSE</source>
6422 <translation>СТАРТ/ПАУЗА</translation>
6423 </message>
6424</context>
6425<context>
6426 <name>QObject</name>
6427 <message>
6428 <location filename="../../src/yuzu/multiplayer/lobby_p.h" line="236"/>
6429 <source>%1 is not playing a game</source>
6430 <translation>%1 не грає у гру</translation>
6431 </message>
6432 <message>
6433 <location filename="../../src/yuzu/multiplayer/lobby_p.h" line="238"/>
6434 <source>%1 is playing %2</source>
6435 <translation>%1 грає в %2</translation>
6436 </message>
6437 <message>
6438 <location filename="../../src/yuzu/multiplayer/chat_room.cpp" line="142"/>
6439 <source>Not playing a game</source>
6440 <translation>Не грає в гру</translation>
6441 </message>
6442 <message>
6443 <location filename="../../src/yuzu/game_list_p.h" line="242"/>
6444 <source>Installed SD Titles</source>
6445 <translation>Встановлені SD ігри</translation>
6446 </message>
6447 <message>
6448 <location filename="../../src/yuzu/game_list_p.h" line="250"/>
6449 <source>Installed NAND Titles</source>
6450 <translation>Встановлені NAND ігри</translation>
6451 </message>
6452 <message>
6453 <location filename="../../src/yuzu/game_list_p.h" line="258"/>
6454 <source>System Titles</source>
6455 <translation>Системні ігри</translation>
6456 </message>
6457 <message>
6458 <location filename="../../src/yuzu/game_list_p.h" line="301"/>
6459 <source>Add New Game Directory</source>
6460 <translation>Додати нову папку з іграми</translation>
6461 </message>
6462 <message>
6463 <location filename="../../src/yuzu/game_list_p.h" line="324"/>
6464 <source>Favorites</source>
6465 <translation>Улюблені</translation>
6466 </message>
6467 <message>
6468 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="21"/>
6469 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="30"/>
6470 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="41"/>
6471 <source>Shift</source>
6472 <translation>Shift</translation>
6473 </message>
6474 <message>
6475 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="23"/>
6476 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="32"/>
6477 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="43"/>
6478 <source>Ctrl</source>
6479 <translation>Ctrl</translation>
6480 </message>
6481 <message>
6482 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="25"/>
6483 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="34"/>
6484 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="45"/>
6485 <source>Alt</source>
6486 <translation>Alt</translation>
6487 </message>
6488 <message>
6489 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="35"/>
6490 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="318"/>
6491 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="384"/>
6492 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="159"/>
6493 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="226"/>
6494 <source>[not set]</source>
6495 <translation>[не задано]</translation>
6496 </message>
6497 <message>
6498 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="47"/>
6499 <source>Hat %1 %2</source>
6500 <translation>Напр. %1 %2</translation>
6501 </message>
6502 <message>
6503 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="54"/>
6504 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="407"/>
6505 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="411"/>
6506 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="415"/>
6507 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="419"/>
6508 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="249"/>
6509 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="253"/>
6510 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="257"/>
6511 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="261"/>
6512 <source>Axis %1%2</source>
6513 <translation>Ось %1%2</translation>
6514 </message>
6515 <message>
6516 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="60"/>
6517 <source>Button %1</source>
6518 <translation>Кнопка %1</translation>
6519 </message>
6520 <message>
6521 <location filename="../../src/yuzu/configuration/configure_touch_from_button.cpp" line="66"/>
6522 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="378"/>
6523 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="392"/>
6524 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="422"/>
6525 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="220"/>
6526 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="234"/>
6527 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="264"/>
6528 <source>[unknown]</source>
6529 <translation>[невідомо]</translation>
6530 </message>
6531 <message>
6532 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="45"/>
6533 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="56"/>
6534 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="124"/>
6535 <source>Left</source>
6536 <translation>Вліво</translation>
6537 </message>
6538 <message>
6539 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="47"/>
6540 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="58"/>
6541 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="127"/>
6542 <source>Right</source>
6543 <translation>Вправо</translation>
6544 </message>
6545 <message>
6546 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="49"/>
6547 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="60"/>
6548 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="133"/>
6549 <source>Down</source>
6550 <translation>Вниз</translation>
6551 </message>
6552 <message>
6553 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="51"/>
6554 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="62"/>
6555 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="130"/>
6556 <source>Up</source>
6557 <translation>Вгору</translation>
6558 </message>
6559 <message>
6560 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="53"/>
6561 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="64"/>
6562 <source>Z</source>
6563 <translation>Z</translation>
6564 </message>
6565 <message>
6566 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="55"/>
6567 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="66"/>
6568 <source>R</source>
6569 <translation>R</translation>
6570 </message>
6571 <message>
6572 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="57"/>
6573 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="68"/>
6574 <source>L</source>
6575 <translation>L</translation>
6576 </message>
6577 <message>
6578 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="59"/>
6579 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="70"/>
6580 <source>A</source>
6581 <translation>A</translation>
6582 </message>
6583 <message>
6584 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="61"/>
6585 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="72"/>
6586 <source>B</source>
6587 <translation>B</translation>
6588 </message>
6589 <message>
6590 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="63"/>
6591 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="74"/>
6592 <source>X</source>
6593 <translation>X</translation>
6594 </message>
6595 <message>
6596 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="65"/>
6597 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="76"/>
6598 <source>Y</source>
6599 <translation>Y</translation>
6600 </message>
6601 <message>
6602 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="67"/>
6603 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="78"/>
6604 <source>Start</source>
6605 <translation>Start</translation>
6606 </message>
6607 <message>
6608 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="69"/>
6609 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="80"/>
6610 <source>L1</source>
6611 <translation>L1</translation>
6612 </message>
6613 <message>
6614 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="71"/>
6615 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="82"/>
6616 <source>L2</source>
6617 <translation>L2</translation>
6618 </message>
6619 <message>
6620 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="73"/>
6621 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="84"/>
6622 <source>L3</source>
6623 <translation>L3</translation>
6624 </message>
6625 <message>
6626 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="75"/>
6627 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="86"/>
6628 <source>R1</source>
6629 <translation>R1</translation>
6630 </message>
6631 <message>
6632 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="77"/>
6633 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="88"/>
6634 <source>R2</source>
6635 <translation>R2</translation>
6636 </message>
6637 <message>
6638 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="79"/>
6639 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="90"/>
6640 <source>R3</source>
6641 <translation>R3</translation>
6642 </message>
6643 <message>
6644 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="81"/>
6645 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="92"/>
6646 <source>Circle</source>
6647 <translation>Кружечок</translation>
6648 </message>
6649 <message>
6650 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="83"/>
6651 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="94"/>
6652 <source>Cross</source>
6653 <translation>Хрестик</translation>
6654 </message>
6655 <message>
6656 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="85"/>
6657 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="96"/>
6658 <source>Square</source>
6659 <translation>Квадратик</translation>
6660 </message>
6661 <message>
6662 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="87"/>
6663 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="98"/>
6664 <source>Triangle</source>
6665 <translation>Трикутничок</translation>
6666 </message>
6667 <message>
6668 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="89"/>
6669 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="100"/>
6670 <source>Share</source>
6671 <translation>Share</translation>
6672 </message>
6673 <message>
6674 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="91"/>
6675 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="102"/>
6676 <source>Options</source>
6677 <translation>Options</translation>
6678 </message>
6679 <message>
6680 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="93"/>
6681 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="118"/>
6682 <source>[undefined]</source>
6683 <translation>[невизначено]</translation>
6684 </message>
6685 <message>
6686 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="328"/>
6687 <source>%1%2</source>
6688 <translation>%1%2</translation>
6689 </message>
6690 <message>
6691 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="332"/>
6692 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="174"/>
6693 <source>[invalid]</source>
6694 <translation>[неприпустимо]</translation>
6695 </message>
6696 <message>
6697 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="342"/>
6698 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="366"/>
6699 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="184"/>
6700 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="208"/>
6701 <source>%1%2Hat %3</source>
6702 <translation>%1%2Напр. %3</translation>
6703 </message>
6704 <message>
6705 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="346"/>
6706 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="369"/>
6707 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="372"/>
6708 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="188"/>
6709 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="211"/>
6710 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="214"/>
6711 <source>%1%2Axis %3</source>
6712 <translation>%1%2Ось %3</translation>
6713 </message>
6714 <message>
6715 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="352"/>
6716 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="194"/>
6717 <source>%1%2Axis %3,%4,%5</source>
6718 <translation>%1%2Ось %3,%4,%5</translation>
6719 </message>
6720 <message>
6721 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="356"/>
6722 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="198"/>
6723 <source>%1%2Motion %3</source>
6724 <translation>%1%2Рух %3</translation>
6725 </message>
6726 <message>
6727 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="360"/>
6728 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="375"/>
6729 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="202"/>
6730 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="217"/>
6731 <source>%1%2Button %3</source>
6732 <translation>%1%2Кнопка %3</translation>
6733 </message>
6734 <message>
6735 <location filename="../../src/yuzu/configuration/configure_ringcon.cpp" line="402"/>
6736 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="244"/>
6737 <source>[unused]</source>
6738 <translation>[не використаний]</translation>
6739 </message>
6740 <message>
6741 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="104"/>
6742 <source>Home</source>
6743 <translation>Home</translation>
6744 </message>
6745 <message>
6746 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="106"/>
6747 <source>Touch</source>
6748 <translation>Сенсор</translation>
6749 </message>
6750 <message>
6751 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="108"/>
6752 <source>Wheel</source>
6753 <comment>Indicates the mouse wheel</comment>
6754 <translation>Коліщатко</translation>
6755 </message>
6756 <message>
6757 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="110"/>
6758 <source>Backward</source>
6759 <translation>Назад</translation>
6760 </message>
6761 <message>
6762 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="112"/>
6763 <source>Forward</source>
6764 <translation>Вперед</translation>
6765 </message>
6766 <message>
6767 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="114"/>
6768 <source>Task</source>
6769 <translation>Задача</translation>
6770 </message>
6771 <message>
6772 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="116"/>
6773 <source>Extra</source>
6774 <translation>Додаткова</translation>
6775 </message>
6776 <message>
6777 <location filename="../../src/yuzu/configuration/configure_input_player.cpp" line="170"/>
6778 <source>%1%2%3</source>
6779 <translation>%1%2%3</translation>
6780 </message>
6781</context>
6782<context>
6783 <name>QtControllerSelectorDialog</name>
6784 <message>
6785 <location filename="../../src/yuzu/applets/qt_controller.ui" line="14"/>
6786 <source>Controller Applet</source>
6787 <translation>Аплет контролера</translation>
6788 </message>
6789 <message>
6790 <location filename="../../src/yuzu/applets/qt_controller.ui" line="129"/>
6791 <source>Supported Controller Types:</source>
6792 <translation>Підтримувані типи контролерів:</translation>
6793 </message>
6794 <message>
6795 <location filename="../../src/yuzu/applets/qt_controller.ui" line="282"/>
6796 <source>Players:</source>
6797 <translation>Гравці:</translation>
6798 </message>
6799 <message>
6800 <location filename="../../src/yuzu/applets/qt_controller.ui" line="300"/>
6801 <source>1 - 8</source>
6802 <translation>1 - 8</translation>
6803 </message>
6804 <message>
6805 <location filename="../../src/yuzu/applets/qt_controller.ui" line="418"/>
6806 <source>P4</source>
6807 <translation>P4</translation>
6808 </message>
6809 <message>
6810 <location filename="../../src/yuzu/applets/qt_controller.ui" line="514"/>
6811 <location filename="../../src/yuzu/applets/qt_controller.ui" line="711"/>
6812 <location filename="../../src/yuzu/applets/qt_controller.ui" line="912"/>
6813 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1222"/>
6814 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1459"/>
6815 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1656"/>
6816 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1857"/>
6817 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2054"/>
6818 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="414"/>
6819 <source>Pro Controller</source>
6820 <translation>Контролер Pro</translation>
6821 </message>
6822 <message>
6823 <location filename="../../src/yuzu/applets/qt_controller.ui" line="519"/>
6824 <location filename="../../src/yuzu/applets/qt_controller.ui" line="716"/>
6825 <location filename="../../src/yuzu/applets/qt_controller.ui" line="917"/>
6826 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1227"/>
6827 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1464"/>
6828 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1661"/>
6829 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1862"/>
6830 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2059"/>
6831 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="418"/>
6832 <source>Dual Joycons</source>
6833 <translation>Подвійні Joy-Con&apos;и</translation>
6834 </message>
6835 <message>
6836 <location filename="../../src/yuzu/applets/qt_controller.ui" line="524"/>
6837 <location filename="../../src/yuzu/applets/qt_controller.ui" line="721"/>
6838 <location filename="../../src/yuzu/applets/qt_controller.ui" line="922"/>
6839 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1232"/>
6840 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1469"/>
6841 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1666"/>
6842 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1867"/>
6843 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2064"/>
6844 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="422"/>
6845 <source>Left Joycon</source>
6846 <translation>Лівий Joy-Con</translation>
6847 </message>
6848 <message>
6849 <location filename="../../src/yuzu/applets/qt_controller.ui" line="529"/>
6850 <location filename="../../src/yuzu/applets/qt_controller.ui" line="726"/>
6851 <location filename="../../src/yuzu/applets/qt_controller.ui" line="927"/>
6852 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1237"/>
6853 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1474"/>
6854 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1671"/>
6855 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1872"/>
6856 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2069"/>
6857 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="426"/>
6858 <source>Right Joycon</source>
6859 <translation>Правий Joy-Con</translation>
6860 </message>
6861 <message>
6862 <location filename="../../src/yuzu/applets/qt_controller.ui" line="538"/>
6863 <location filename="../../src/yuzu/applets/qt_controller.ui" line="735"/>
6864 <location filename="../../src/yuzu/applets/qt_controller.ui" line="941"/>
6865 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1246"/>
6866 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1483"/>
6867 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1680"/>
6868 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1881"/>
6869 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2078"/>
6870 <source>Use Current Config</source>
6871 <translation>Використовувати поточну конфігурацію</translation>
6872 </message>
6873 <message>
6874 <location filename="../../src/yuzu/applets/qt_controller.ui" line="615"/>
6875 <source>P2</source>
6876 <translation>P2</translation>
6877 </message>
6878 <message>
6879 <location filename="../../src/yuzu/applets/qt_controller.ui" line="812"/>
6880 <source>P1</source>
6881 <translation>P1</translation>
6882 </message>
6883 <message>
6884 <location filename="../../src/yuzu/applets/qt_controller.ui" line="932"/>
6885 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2303"/>
6886 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="430"/>
6887 <source>Handheld</source>
6888 <translation>Портативний</translation>
6889 </message>
6890 <message>
6891 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1126"/>
6892 <source>P3</source>
6893 <translation>P3</translation>
6894 </message>
6895 <message>
6896 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1363"/>
6897 <source>P7</source>
6898 <translation>P7</translation>
6899 </message>
6900 <message>
6901 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1560"/>
6902 <source>P8</source>
6903 <translation>P8</translation>
6904 </message>
6905 <message>
6906 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1757"/>
6907 <source>P5</source>
6908 <translation>P5</translation>
6909 </message>
6910 <message>
6911 <location filename="../../src/yuzu/applets/qt_controller.ui" line="1958"/>
6912 <source>P6</source>
6913 <translation>P6</translation>
6914 </message>
6915 <message>
6916 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2272"/>
6917 <source>Console Mode</source>
6918 <translation>Режим консолі</translation>
6919 </message>
6920 <message>
6921 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2293"/>
6922 <source>Docked</source>
6923 <translation>У док-станції</translation>
6924 </message>
6925 <message>
6926 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2313"/>
6927 <source>Vibration</source>
6928 <translation>Вібрація</translation>
6929 </message>
6930 <message>
6931 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2349"/>
6932 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2395"/>
6933 <source>Configure</source>
6934 <translation>Налаштувати</translation>
6935 </message>
6936 <message>
6937 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2359"/>
6938 <source>Motion</source>
6939 <translation>Рух</translation>
6940 </message>
6941 <message>
6942 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2405"/>
6943 <source>Profiles</source>
6944 <translation>Профілі</translation>
6945 </message>
6946 <message>
6947 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2432"/>
6948 <source>Create</source>
6949 <translation>Створити</translation>
6950 </message>
6951 <message>
6952 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2467"/>
6953 <source>Controllers</source>
6954 <translation>Контролери</translation>
6955 </message>
6956 <message>
6957 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2481"/>
6958 <source>1</source>
6959 <translation>1</translation>
6960 </message>
6961 <message>
6962 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2508"/>
6963 <source>2</source>
6964 <translation>2</translation>
6965 </message>
6966 <message>
6967 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2518"/>
6968 <source>4</source>
6969 <translation>4</translation>
6970 </message>
6971 <message>
6972 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2528"/>
6973 <source>3</source>
6974 <translation>3</translation>
6975 </message>
6976 <message>
6977 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2538"/>
6978 <source>Connected</source>
6979 <translation>З&apos;єднано</translation>
6980 </message>
6981 <message>
6982 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2552"/>
6983 <source>5</source>
6984 <translation>5</translation>
6985 </message>
6986 <message>
6987 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2569"/>
6988 <source>7</source>
6989 <translation>7</translation>
6990 </message>
6991 <message>
6992 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2586"/>
6993 <source>6</source>
6994 <translation>6</translation>
6995 </message>
6996 <message>
6997 <location filename="../../src/yuzu/applets/qt_controller.ui" line="2596"/>
6998 <source>8</source>
6999 <translation>8</translation>
7000 </message>
7001 <message>
7002 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="434"/>
7003 <source>GameCube Controller</source>
7004 <translation>Контролер GameCube</translation>
7005 </message>
7006 <message>
7007 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="443"/>
7008 <source>Poke Ball Plus</source>
7009 <translation>Poke Ball Plus</translation>
7010 </message>
7011 <message>
7012 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="447"/>
7013 <source>NES Controller</source>
7014 <translation>Контролер NES</translation>
7015 </message>
7016 <message>
7017 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="451"/>
7018 <source>SNES Controller</source>
7019 <translation>Контролер SNES</translation>
7020 </message>
7021 <message>
7022 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="455"/>
7023 <source>N64 Controller</source>
7024 <translation>Контролер N64</translation>
7025 </message>
7026 <message>
7027 <location filename="../../src/yuzu/applets/qt_controller.cpp" line="459"/>
7028 <source>Sega Genesis</source>
7029 <translation>Sega Genesis</translation>
7030 </message>
7031</context>
7032<context>
7033 <name>QtErrorDisplay</name>
7034 <message>
7035 <location filename="../../src/yuzu/applets/qt_error.cpp" line="20"/>
7036 <location filename="../../src/yuzu/applets/qt_error.cpp" line="33"/>
7037 <location filename="../../src/yuzu/applets/qt_error.cpp" line="48"/>
7038 <source>Error Code: %1-%2 (0x%3)</source>
7039 <translation>Код помилки: %1-%2 (0x%3)</translation>
7040 </message>
7041 <message>
7042 <location filename="../../src/yuzu/applets/qt_error.cpp" line="24"/>
7043 <source>An error has occurred.
7044Please try again or contact the developer of the software.</source>
7045 <translation>Сталася помилка.
7046Будь ласка, спробуйте ще раз або зв&apos;яжіться з розробником ПЗ.</translation>
7047 </message>
7048 <message>
7049 <location filename="../../src/yuzu/applets/qt_error.cpp" line="37"/>
7050 <source>An error occurred on %1 at %2.
7051Please try again or contact the developer of the software.</source>
7052 <translation>Сталася помилка на %1 у %2.
7053Будь ласка, спробуйте ще раз або зв&apos;яжіться з розробником ПЗ.</translation>
7054 </message>
7055 <message>
7056 <location filename="../../src/yuzu/applets/qt_error.cpp" line="52"/>
7057 <source>An error has occurred.
7058
7059%1
7060
7061%2</source>
7062 <translation>Сталася помилка.
7063
7064%1
7065
7066%2</translation>
7067 </message>
7068</context>
7069<context>
7070 <name>QtProfileSelectionDialog</name>
7071 <message>
7072 <location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="23"/>
7073 <source>%1
7074%2</source>
7075 <comment>%1 is the profile username, %2 is the formatted UUID (e.g. 00112233-4455-6677-8899-AABBCCDDEEFF))</comment>
7076 <translation>%1
7077%2</translation>
7078 </message>
7079 <message>
7080 <location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="53"/>
7081 <source>Select a user:</source>
7082 <translation>Оберить користувача</translation>
7083 </message>
7084 <message>
7085 <location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="83"/>
7086 <source>Users</source>
7087 <translation>Користувачі</translation>
7088 </message>
7089 <message>
7090 <location filename="../../src/yuzu/applets/qt_profile_select.cpp" line="123"/>
7091 <source>Profile Selector</source>
7092 <translation>Вибір профілю</translation>
7093 </message>
7094</context>
7095<context>
7096 <name>QtSoftwareKeyboardDialog</name>
7097 <message>
7098 <location filename="../../src/yuzu/applets/qt_software_keyboard.ui" line="14"/>
7099 <source>Software Keyboard</source>
7100 <translation>Віртуальна клавіатура</translation>
7101 </message>
7102 <message>
7103 <location filename="../../src/yuzu/applets/qt_software_keyboard.ui" line="199"/>
7104 <source>Enter Text</source>
7105 <translation>Введіть текст</translation>
7106 </message>
7107 <message>
7108 <location filename="../../src/yuzu/applets/qt_software_keyboard.ui" line="479"/>
7109 <source>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
7110&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
7111p, li { white-space: pre-wrap; }
7112&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:26pt; font-weight:400; font-style:normal;&quot;&gt;
7113&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
7114 <translation>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
7115&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
7116p, li { white-space: pre-wrap; }
7117&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:&apos;MS Shell Dlg 2&apos;; font-size:26pt; font-weight:400; font-style:normal;&quot;&gt;
7118&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
7119 </message>
7120 <message>
7121 <location filename="../../src/yuzu/applets/qt_software_keyboard.cpp" line="403"/>
7122 <location filename="../../src/yuzu/applets/qt_software_keyboard.cpp" line="413"/>
7123 <source>OK</source>
7124 <translation>ОК</translation>
7125 </message>
7126 <message>
7127 <location filename="../../src/yuzu/applets/qt_software_keyboard.cpp" line="413"/>
7128 <source>Cancel</source>
7129 <translation>Скасувати</translation>
7130 </message>
7131</context>
7132<context>
7133 <name>SequenceDialog</name>
7134 <message>
7135 <location filename="../../src/yuzu/util/sequence_dialog/sequence_dialog.cpp" line="10"/>
7136 <source>Enter a hotkey</source>
7137 <translation>Введіть комбінацію</translation>
7138 </message>
7139</context>
7140<context>
7141 <name>WaitTreeCallstack</name>
7142 <message>
7143 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="147"/>
7144 <source>Call stack</source>
7145 <translation>Стек викликів</translation>
7146 </message>
7147</context>
7148<context>
7149 <name>WaitTreeMutexInfo</name>
7150 <message>
7151 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="126"/>
7152 <source>waiting for mutex 0x%1</source>
7153 <translation type="unfinished"/>
7154 </message>
7155 <message>
7156 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="133"/>
7157 <source>has waiters: %1</source>
7158 <translation type="unfinished"/>
7159 </message>
7160 <message>
7161 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="135"/>
7162 <source>owner handle: 0x%1</source>
7163 <translation type="unfinished"/>
7164 </message>
7165</context>
7166<context>
7167 <name>WaitTreeObjectList</name>
7168 <message>
7169 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="228"/>
7170 <source>waiting for all objects</source>
7171 <translation type="unfinished"/>
7172 </message>
7173 <message>
7174 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="229"/>
7175 <source>waiting for one of the following objects</source>
7176 <translation type="unfinished"/>
7177 </message>
7178</context>
7179<context>
7180 <name>WaitTreeSynchronizationObject</name>
7181 <message>
7182 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="185"/>
7183 <source>[%1] %2 %3</source>
7184 <translation>[%1] %2 %3</translation>
7185 </message>
7186 <message>
7187 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="212"/>
7188 <source>waited by no thread</source>
7189 <translation type="unfinished"/>
7190 </message>
7191</context>
7192<context>
7193 <name>WaitTreeThread</name>
7194 <message>
7195 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="250"/>
7196 <source>runnable</source>
7197 <translation type="unfinished"/>
7198 </message>
7199 <message>
7200 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="252"/>
7201 <source>paused</source>
7202 <translation type="unfinished"/>
7203 </message>
7204 <message>
7205 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="258"/>
7206 <source>sleeping</source>
7207 <translation type="unfinished"/>
7208 </message>
7209 <message>
7210 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="261"/>
7211 <source>waiting for IPC reply</source>
7212 <translation type="unfinished"/>
7213 </message>
7214 <message>
7215 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="264"/>
7216 <source>waiting for objects</source>
7217 <translation type="unfinished"/>
7218 </message>
7219 <message>
7220 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="267"/>
7221 <source>waiting for condition variable</source>
7222 <translation type="unfinished"/>
7223 </message>
7224 <message>
7225 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="270"/>
7226 <source>waiting for address arbiter</source>
7227 <translation type="unfinished"/>
7228 </message>
7229 <message>
7230 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="273"/>
7231 <source>waiting for suspend resume</source>
7232 <translation type="unfinished"/>
7233 </message>
7234 <message>
7235 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="276"/>
7236 <source>waiting</source>
7237 <translation type="unfinished"/>
7238 </message>
7239 <message>
7240 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="281"/>
7241 <source>initialized</source>
7242 <translation type="unfinished"/>
7243 </message>
7244 <message>
7245 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="284"/>
7246 <source>terminated</source>
7247 <translation type="unfinished"/>
7248 </message>
7249 <message>
7250 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="287"/>
7251 <source>unknown</source>
7252 <translation type="unfinished"/>
7253 </message>
7254 <message>
7255 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="292"/>
7256 <source> PC = 0x%1 LR = 0x%2</source>
7257 <translation> PC = 0x%1 LR = 0x%2</translation>
7258 </message>
7259 <message>
7260 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="342"/>
7261 <source>ideal</source>
7262 <translation type="unfinished"/>
7263 </message>
7264 <message>
7265 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="345"/>
7266 <source>core %1</source>
7267 <translation type="unfinished"/>
7268 </message>
7269 <message>
7270 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="349"/>
7271 <source>processor = %1</source>
7272 <translation type="unfinished"/>
7273 </message>
7274 <message>
7275 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="351"/>
7276 <source>ideal core = %1</source>
7277 <translation type="unfinished"/>
7278 </message>
7279 <message>
7280 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="353"/>
7281 <source>affinity mask = %1</source>
7282 <translation type="unfinished"/>
7283 </message>
7284 <message>
7285 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="354"/>
7286 <source>thread id = %1</source>
7287 <translation type="unfinished"/>
7288 </message>
7289 <message>
7290 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="355"/>
7291 <source>priority = %1(current) / %2(normal)</source>
7292 <translation type="unfinished"/>
7293 </message>
7294 <message>
7295 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="359"/>
7296 <source>last running ticks = %1</source>
7297 <translation type="unfinished"/>
7298 </message>
7299 <message>
7300 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="367"/>
7301 <source>not waiting for mutex</source>
7302 <translation type="unfinished"/>
7303 </message>
7304</context>
7305<context>
7306 <name>WaitTreeThreadList</name>
7307 <message>
7308 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="391"/>
7309 <source>waited by thread</source>
7310 <translation type="unfinished"/>
7311 </message>
7312</context>
7313<context>
7314 <name>WaitTreeWidget</name>
7315 <message>
7316 <location filename="../../src/yuzu/debugger/wait_tree.cpp" line="465"/>
7317 <source>&amp;Wait Tree</source>
7318 <translation>[&amp;W] Дерево очікування</translation>
7319 </message>
7320</context>
7321</TS> \ No newline at end of file
diff --git a/dist/qt_themes/colorful/icons/48x48/bad_folder.png b/dist/qt_themes/colorful/icons/48x48/bad_folder.png
index a7ab7a1f6..34069c6b2 100644
--- a/dist/qt_themes/colorful/icons/48x48/bad_folder.png
+++ b/dist/qt_themes/colorful/icons/48x48/bad_folder.png
Binary files differ
diff --git a/dist/qt_themes/default/icons/256x256/plus_folder.png b/dist/qt_themes/default/icons/256x256/plus_folder.png
index 3a49669a3..f44c80c3a 100644
--- a/dist/qt_themes/default/icons/256x256/plus_folder.png
+++ b/dist/qt_themes/default/icons/256x256/plus_folder.png
Binary files differ
diff --git a/dist/qt_themes/default/icons/256x256/yuzu.png b/dist/qt_themes/default/icons/256x256/yuzu.png
index bd5cf533f..238adeb89 100644
--- a/dist/qt_themes/default/icons/256x256/yuzu.png
+++ b/dist/qt_themes/default/icons/256x256/yuzu.png
Binary files differ
diff --git a/dist/qt_themes/qdarkstyle/icons/256x256/plus_folder.png b/dist/qt_themes/qdarkstyle/icons/256x256/plus_folder.png
index 002101114..14c90fea5 100644
--- a/dist/qt_themes/qdarkstyle/icons/256x256/plus_folder.png
+++ b/dist/qt_themes/qdarkstyle/icons/256x256/plus_folder.png
Binary files differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3575a3cb3..0ac3d254e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -58,13 +58,11 @@ if (MSVC)
58 58
59 # Warnings 59 # Warnings
60 /W3 60 /W3
61 /we4018 # 'expression': signed/unsigned mismatch 61 /WX
62
62 /we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled 63 /we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled
63 /we4101 # 'identifier': unreferenced local variable
64 /we4189 # 'identifier': local variable is initialized but not referenced 64 /we4189 # 'identifier': local variable is initialized but not referenced
65 /we4265 # 'class': class has virtual functions, but destructor is not virtual 65 /we4265 # 'class': class has virtual functions, but destructor is not virtual
66 /we4267 # 'var': conversion from 'size_t' to 'type', possible loss of data
67 /we4305 # 'context': truncation from 'type1' to 'type2'
68 /we4388 # 'expression': signed/unsigned mismatch 66 /we4388 # 'expression': signed/unsigned mismatch
69 /we4389 # 'operator': signed/unsigned mismatch 67 /we4389 # 'operator': signed/unsigned mismatch
70 /we4456 # Declaration of 'identifier' hides previous local declaration 68 /we4456 # Declaration of 'identifier' hides previous local declaration
@@ -75,10 +73,13 @@ if (MSVC)
75 /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
76 /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'?
77 /we4555 # Expression has no effect; expected expression with side-effect 75 /we4555 # Expression has no effect; expected expression with side-effect
78 /we4715 # 'function': not all control paths return a value 76 /we4826 # Conversion from 'type1' to 'type2' is sign-extended. This may cause unexpected runtime behavior.
79 /we4834 # Discarding return value of function with 'nodiscard' attribute
80 /we5038 # data member 'member1' will be initialized after data member 'member2' 77 /we5038 # data member 'member1' will be initialized after data member 'member2'
78 /we5233 # explicit lambda capture 'identifier' is not used
81 /we5245 # 'function': unreferenced function with internal linkage has been removed 79 /we5245 # 'function': unreferenced function with internal linkage has been removed
80
81 /wd4100 # 'identifier': unreferenced formal parameter
82 /wd4324 # 'struct_name': structure was padded due to __declspec(align())
82 ) 83 )
83 84
84 if (USE_CCACHE) 85 if (USE_CCACHE)
@@ -99,24 +100,18 @@ if (MSVC)
99 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) 100 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE)
100else() 101else()
101 add_compile_options( 102 add_compile_options(
102 -Wall 103 -Werror=all
103 -Werror=array-bounds 104 -Werror=extra
104 -Werror=implicit-fallthrough
105 -Werror=missing-declarations 105 -Werror=missing-declarations
106 -Werror=missing-field-initializers
107 -Werror=reorder
108 -Werror=shadow 106 -Werror=shadow
109 -Werror=sign-compare 107 -Werror=unused
110 -Werror=switch 108
111 -Werror=uninitialized
112 -Werror=unused-function
113 -Werror=unused-result
114 -Werror=unused-variable
115 -Wextra
116 -Wmissing-declarations
117 -Wno-attributes 109 -Wno-attributes
118 -Wno-invalid-offsetof 110 -Wno-invalid-offsetof
119 -Wno-unused-parameter 111 -Wno-unused-parameter
112
113 $<$<CXX_COMPILER_ID:Clang>:-Wno-braced-scalar-init>
114 $<$<CXX_COMPILER_ID:Clang>:-Wno-unused-private-field>
120 ) 115 )
121 116
122 if (ARCHITECTURE_x86_64) 117 if (ARCHITECTURE_x86_64)
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index 144f1bab2..0a1f3bf18 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -206,20 +206,11 @@ if (MSVC)
206 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data 206 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
207 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch 207 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
208 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 208 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
209 /we4456 # Declaration of 'identifier' hides previous local declaration 209 /we4800 # Implicit conversion from 'type' to bool. Possible information loss
210 /we4457 # Declaration of 'identifier' hides function parameter
211 /we4458 # Declaration of 'identifier' hides class member
212 /we4459 # Declaration of 'identifier' hides global declaration
213 ) 210 )
214else() 211else()
215 target_compile_options(audio_core PRIVATE 212 target_compile_options(audio_core PRIVATE
216 -Werror=conversion 213 -Werror=conversion
217 -Werror=ignored-qualifiers
218 -Werror=shadow
219 -Werror=unused-variable
220
221 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
222 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
223 214
224 -Wno-sign-conversion 215 -Wno-sign-conversion
225 ) 216 )
diff --git a/src/audio_core/in/audio_in_system.cpp b/src/audio_core/in/audio_in_system.cpp
index 6b7e6715c..4324cafd8 100644
--- a/src/audio_core/in/audio_in_system.cpp
+++ b/src/audio_core/in/audio_in_system.cpp
@@ -56,7 +56,7 @@ Result System::IsConfigValid(const std::string_view device_name,
56 return ResultSuccess; 56 return ResultSuccess;
57} 57}
58 58
59Result System::Initialize(std::string& device_name, const AudioInParameter& in_params, 59Result System::Initialize(std::string device_name, const AudioInParameter& in_params,
60 const u32 handle_, const u64 applet_resource_user_id_) { 60 const u32 handle_, const u64 applet_resource_user_id_) {
61 auto result{IsConfigValid(device_name, in_params)}; 61 auto result{IsConfigValid(device_name, in_params)};
62 if (result.IsError()) { 62 if (result.IsError()) {
diff --git a/src/audio_core/in/audio_in_system.h b/src/audio_core/in/audio_in_system.h
index b9dc0e60f..1c5154638 100644
--- a/src/audio_core/in/audio_in_system.h
+++ b/src/audio_core/in/audio_in_system.h
@@ -97,7 +97,7 @@ public:
97 * @param applet_resource_user_id - Unused. 97 * @param applet_resource_user_id - Unused.
98 * @return Result code. 98 * @return Result code.
99 */ 99 */
100 Result Initialize(std::string& device_name, const AudioInParameter& in_params, u32 handle, 100 Result Initialize(std::string device_name, const AudioInParameter& in_params, u32 handle,
101 u64 applet_resource_user_id); 101 u64 applet_resource_user_id);
102 102
103 /** 103 /**
diff --git a/src/audio_core/out/audio_out_system.cpp b/src/audio_core/out/audio_out_system.cpp
index 48a801923..a66208ed9 100644
--- a/src/audio_core/out/audio_out_system.cpp
+++ b/src/audio_core/out/audio_out_system.cpp
@@ -49,8 +49,8 @@ Result System::IsConfigValid(std::string_view device_name,
49 return Service::Audio::ERR_INVALID_CHANNEL_COUNT; 49 return Service::Audio::ERR_INVALID_CHANNEL_COUNT;
50} 50}
51 51
52Result System::Initialize(std::string& device_name, const AudioOutParameter& in_params, u32 handle_, 52Result System::Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle_,
53 u64& applet_resource_user_id_) { 53 u64 applet_resource_user_id_) {
54 auto result = IsConfigValid(device_name, in_params); 54 auto result = IsConfigValid(device_name, in_params);
55 if (result.IsError()) { 55 if (result.IsError()) {
56 return result; 56 return result;
diff --git a/src/audio_core/out/audio_out_system.h b/src/audio_core/out/audio_out_system.h
index 0817b2f37..b95cb91be 100644
--- a/src/audio_core/out/audio_out_system.h
+++ b/src/audio_core/out/audio_out_system.h
@@ -88,8 +88,8 @@ public:
88 * @param applet_resource_user_id - Unused. 88 * @param applet_resource_user_id - Unused.
89 * @return Result code. 89 * @return Result code.
90 */ 90 */
91 Result Initialize(std::string& device_name, const AudioOutParameter& in_params, u32 handle, 91 Result Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle,
92 u64& applet_resource_user_id); 92 u64 applet_resource_user_id);
93 93
94 /** 94 /**
95 * Start this system. 95 * Start this system.
diff --git a/src/audio_core/renderer/behavior/info_updater.cpp b/src/audio_core/renderer/behavior/info_updater.cpp
index c0a307b89..574cf0982 100644
--- a/src/audio_core/renderer/behavior/info_updater.cpp
+++ b/src/audio_core/renderer/behavior/info_updater.cpp
@@ -91,7 +91,7 @@ Result InfoUpdater::UpdateVoices(VoiceContext& voice_context,
91 voice_info.Initialize(); 91 voice_info.Initialize();
92 92
93 for (u32 channel = 0; channel < in_param.channel_count; channel++) { 93 for (u32 channel = 0; channel < in_param.channel_count; channel++) {
94 std::memset(voice_states[channel], 0, sizeof(VoiceState)); 94 *voice_states[channel] = {};
95 } 95 }
96 } 96 }
97 97
diff --git a/src/audio_core/renderer/command/effect/biquad_filter.cpp b/src/audio_core/renderer/command/effect/biquad_filter.cpp
index 1baae74fd..edb30ce72 100644
--- a/src/audio_core/renderer/command/effect/biquad_filter.cpp
+++ b/src/audio_core/renderer/command/effect/biquad_filter.cpp
@@ -94,7 +94,7 @@ void BiquadFilterCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor
94void BiquadFilterCommand::Process(const ADSP::CommandListProcessor& processor) { 94void BiquadFilterCommand::Process(const ADSP::CommandListProcessor& processor) {
95 auto state_{reinterpret_cast<VoiceState::BiquadFilterState*>(state)}; 95 auto state_{reinterpret_cast<VoiceState::BiquadFilterState*>(state)};
96 if (needs_init) { 96 if (needs_init) {
97 std::memset(state_, 0, sizeof(VoiceState::BiquadFilterState)); 97 *state_ = {};
98 } 98 }
99 99
100 auto input_buffer{ 100 auto input_buffer{
diff --git a/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp b/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp
index b3c3ba4ba..48a7cba8a 100644
--- a/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp
+++ b/src/audio_core/renderer/command/effect/multi_tap_biquad_filter.cpp
@@ -30,7 +30,7 @@ void MultiTapBiquadFilterCommand::Process(const ADSP::CommandListProcessor& proc
30 for (u32 i = 0; i < filter_tap_count; i++) { 30 for (u32 i = 0; i < filter_tap_count; i++) {
31 auto state{reinterpret_cast<VoiceState::BiquadFilterState*>(states[i])}; 31 auto state{reinterpret_cast<VoiceState::BiquadFilterState*>(states[i])};
32 if (needs_init[i]) { 32 if (needs_init[i]) {
33 std::memset(state, 0, sizeof(VoiceState::BiquadFilterState)); 33 *state = {};
34 } 34 }
35 35
36 ApplyBiquadFilterFloat(output_buffer, input_buffer, biquads[i].b, biquads[i].a, *state, 36 ApplyBiquadFilterFloat(output_buffer, input_buffer, biquads[i].b, biquads[i].a, *state,
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp
index bde794cd1..4fac30c7c 100644
--- a/src/audio_core/renderer/system.cpp
+++ b/src/audio_core/renderer/system.cpp
@@ -98,9 +98,8 @@ System::System(Core::System& core_, Kernel::KEvent* adsp_rendered_event_)
98 : core{core_}, adsp{core.AudioCore().GetADSP()}, adsp_rendered_event{adsp_rendered_event_} {} 98 : core{core_}, adsp{core.AudioCore().GetADSP()}, adsp_rendered_event{adsp_rendered_event_} {}
99 99
100Result System::Initialize(const AudioRendererParameterInternal& params, 100Result System::Initialize(const AudioRendererParameterInternal& params,
101 Kernel::KTransferMemory* transfer_memory, const u64 transfer_memory_size, 101 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
102 const u32 process_handle_, const u64 applet_resource_user_id_, 102 u32 process_handle_, u64 applet_resource_user_id_, s32 session_id_) {
103 const s32 session_id_) {
104 if (!CheckValidRevision(params.revision)) { 103 if (!CheckValidRevision(params.revision)) {
105 return Service::Audio::ERR_INVALID_REVISION; 104 return Service::Audio::ERR_INVALID_REVISION;
106 } 105 }
@@ -354,6 +353,8 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
354 353
355 render_time_limit_percent = 100; 354 render_time_limit_percent = 100;
356 drop_voice = params.voice_drop_enabled && params.execution_mode == ExecutionMode::Auto; 355 drop_voice = params.voice_drop_enabled && params.execution_mode == ExecutionMode::Auto;
356 drop_voice_param = 1.0f;
357 num_voices_dropped = 0;
357 358
358 allocator.Align(0x40); 359 allocator.Align(0x40);
359 command_workbuffer_size = allocator.GetRemainingSize(); 360 command_workbuffer_size = allocator.GetRemainingSize();
@@ -547,7 +548,7 @@ u32 System::GetRenderingTimeLimit() const {
547 return render_time_limit_percent; 548 return render_time_limit_percent;
548} 549}
549 550
550void System::SetRenderingTimeLimit(const u32 limit) { 551void System::SetRenderingTimeLimit(u32 limit) {
551 render_time_limit_percent = limit; 552 render_time_limit_percent = limit;
552} 553}
553 554
@@ -635,7 +636,7 @@ void System::SendCommandToDsp() {
635} 636}
636 637
637u64 System::GenerateCommand(std::span<u8> in_command_buffer, 638u64 System::GenerateCommand(std::span<u8> in_command_buffer,
638 [[maybe_unused]] const u64 command_buffer_size_) { 639 [[maybe_unused]] u64 command_buffer_size_) {
639 PoolMapper::ClearUseState(memory_pool_workbuffer, memory_pool_count); 640 PoolMapper::ClearUseState(memory_pool_workbuffer, memory_pool_count);
640 const auto start_time{core.CoreTiming().GetClockTicks()}; 641 const auto start_time{core.CoreTiming().GetClockTicks()};
641 642
@@ -693,7 +694,8 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer,
693 694
694 voice_context.SortInfo(); 695 voice_context.SortInfo();
695 696
696 const auto start_estimated_time{command_buffer.estimated_process_time}; 697 const auto start_estimated_time{drop_voice_param *
698 static_cast<f32>(command_buffer.estimated_process_time)};
697 699
698 command_generator.GenerateVoiceCommands(); 700 command_generator.GenerateVoiceCommands();
699 command_generator.GenerateSubMixCommands(); 701 command_generator.GenerateSubMixCommands();
@@ -712,11 +714,16 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer,
712 render_context.behavior->IsAudioRendererProcessingTimeLimit70PercentSupported(); 714 render_context.behavior->IsAudioRendererProcessingTimeLimit70PercentSupported();
713 time_limit_percent = 70.0f; 715 time_limit_percent = 70.0f;
714 } 716 }
717
718 const auto end_estimated_time{drop_voice_param *
719 static_cast<f32>(command_buffer.estimated_process_time)};
720 const auto estimated_time{start_estimated_time - end_estimated_time};
721
715 const auto time_limit{static_cast<u32>( 722 const auto time_limit{static_cast<u32>(
716 static_cast<f32>(start_estimated_time - command_buffer.estimated_process_time) + 723 estimated_time + (((time_limit_percent / 100.0f) * 2'880'000.0) *
717 (((time_limit_percent / 100.0f) * 2'880'000.0) * 724 (static_cast<f32>(render_time_limit_percent) / 100.0f)))};
718 (static_cast<f32>(render_time_limit_percent) / 100.0f)))}; 725 num_voices_dropped =
719 num_voices_dropped = DropVoices(command_buffer, start_estimated_time, time_limit); 726 DropVoices(command_buffer, static_cast<u32>(start_estimated_time), time_limit);
720 } 727 }
721 728
722 command_list_header->buffer_size = command_buffer.size; 729 command_list_header->buffer_size = command_buffer.size;
@@ -737,24 +744,33 @@ u64 System::GenerateCommand(std::span<u8> in_command_buffer,
737 return command_buffer.size; 744 return command_buffer.size;
738} 745}
739 746
740u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_process_time, 747f32 System::GetVoiceDropParameter() const {
741 const u32 time_limit) { 748 return drop_voice_param;
749}
750
751void System::SetVoiceDropParameter(f32 voice_drop_) {
752 drop_voice_param = voice_drop_;
753}
754
755u32 System::DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time, u32 time_limit) {
742 u32 i{0}; 756 u32 i{0};
743 auto command_list{command_buffer.command_list.data() + sizeof(CommandListHeader)}; 757 auto command_list{command_buffer.command_list.data() + sizeof(CommandListHeader)};
744 ICommand* cmd{}; 758 ICommand* cmd{nullptr};
745 759
746 for (; i < command_buffer.count; i++) { 760 // Find a first valid voice to drop
761 while (i < command_buffer.count) {
747 cmd = reinterpret_cast<ICommand*>(command_list); 762 cmd = reinterpret_cast<ICommand*>(command_list);
748 if (cmd->type != CommandId::Performance && 763 if (cmd->type == CommandId::Performance ||
749 cmd->type != CommandId::DataSourcePcmInt16Version1 && 764 cmd->type == CommandId::DataSourcePcmInt16Version1 ||
750 cmd->type != CommandId::DataSourcePcmInt16Version2 && 765 cmd->type == CommandId::DataSourcePcmInt16Version2 ||
751 cmd->type != CommandId::DataSourcePcmFloatVersion1 && 766 cmd->type == CommandId::DataSourcePcmFloatVersion1 ||
752 cmd->type != CommandId::DataSourcePcmFloatVersion2 && 767 cmd->type == CommandId::DataSourcePcmFloatVersion2 ||
753 cmd->type != CommandId::DataSourceAdpcmVersion1 && 768 cmd->type == CommandId::DataSourceAdpcmVersion1 ||
754 cmd->type != CommandId::DataSourceAdpcmVersion2) { 769 cmd->type == CommandId::DataSourceAdpcmVersion2) {
755 break; 770 break;
756 } 771 }
757 command_list += cmd->size; 772 command_list += cmd->size;
773 i++;
758 } 774 }
759 775
760 if (cmd == nullptr || command_buffer.count == 0 || i >= command_buffer.count) { 776 if (cmd == nullptr || command_buffer.count == 0 || i >= command_buffer.count) {
@@ -767,6 +783,7 @@ u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_proces
767 const auto node_id_type{cmd->node_id >> 28}; 783 const auto node_id_type{cmd->node_id >> 28};
768 const auto node_id_base{cmd->node_id & 0xFFF}; 784 const auto node_id_base{cmd->node_id & 0xFFF};
769 785
786 // If the new estimated process time falls below the limit, we're done dropping.
770 if (estimated_process_time <= time_limit) { 787 if (estimated_process_time <= time_limit) {
771 break; 788 break;
772 } 789 }
@@ -775,6 +792,7 @@ u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_proces
775 break; 792 break;
776 } 793 }
777 794
795 // Don't drop voices marked with the highest priority.
778 auto& voice_info{voice_context.GetInfo(node_id_base)}; 796 auto& voice_info{voice_context.GetInfo(node_id_base)};
779 if (voice_info.priority == HighestVoicePriority) { 797 if (voice_info.priority == HighestVoicePriority) {
780 break; 798 break;
@@ -783,18 +801,23 @@ u32 System::DropVoices(CommandBuffer& command_buffer, const u32 estimated_proces
783 voices_dropped++; 801 voices_dropped++;
784 voice_info.voice_dropped = true; 802 voice_info.voice_dropped = true;
785 803
786 if (i < command_buffer.count) { 804 // First iteration should drop the voice, and then iterate through all of the commands tied
787 while (cmd->node_id == node_id) { 805 // to the voice. We don't need reverb on a voice which we've just removed, for example.
788 if (cmd->type == CommandId::DepopPrepare) { 806 // Depops can't be removed otherwise we'll introduce audio popping, and we don't
789 cmd->enabled = true; 807 // remove perf commands. Lower the estimated time for each command dropped.
790 } else if (cmd->type == CommandId::Performance || !cmd->enabled) { 808 while (i < command_buffer.count && cmd->node_id == node_id) {
791 cmd->enabled = false; 809 if (cmd->type == CommandId::DepopPrepare) {
792 } 810 cmd->enabled = true;
793 i++; 811 } else if (cmd->enabled && cmd->type != CommandId::Performance) {
794 command_list += cmd->size; 812 cmd->enabled = false;
795 cmd = reinterpret_cast<ICommand*>(command_list); 813 estimated_process_time -= static_cast<u32>(
814 drop_voice_param * static_cast<f32>(cmd->estimated_process_time));
796 } 815 }
816 command_list += cmd->size;
817 cmd = reinterpret_cast<ICommand*>(command_list);
818 i++;
797 } 819 }
820 i++;
798 } 821 }
799 return voices_dropped; 822 return voices_dropped;
800} 823}
diff --git a/src/audio_core/renderer/system.h b/src/audio_core/renderer/system.h
index bcbe65b07..429196e41 100644
--- a/src/audio_core/renderer/system.h
+++ b/src/audio_core/renderer/system.h
@@ -196,6 +196,20 @@ public:
196 */ 196 */
197 u32 DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time, u32 time_limit); 197 u32 DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time, u32 time_limit);
198 198
199 /**
200 * Get the current voice drop parameter.
201 *
202 * @return The current voice drop.
203 */
204 f32 GetVoiceDropParameter() const;
205
206 /**
207 * Set the voice drop parameter.
208 *
209 * @param The new voice drop.
210 */
211 void SetVoiceDropParameter(f32 voice_drop);
212
199private: 213private:
200 /// Core system 214 /// Core system
201 Core::System& core; 215 Core::System& core;
@@ -301,6 +315,8 @@ private:
301 u32 num_voices_dropped{}; 315 u32 num_voices_dropped{};
302 /// Tick that rendering started 316 /// Tick that rendering started
303 u64 render_start_tick{}; 317 u64 render_start_tick{};
318 /// Parameter to control the threshold for dropping voices if the audio graph gets too large
319 f32 drop_voice_param{1.0f};
304}; 320};
305 321
306} // namespace AudioRenderer 322} // namespace AudioRenderer
diff --git a/src/audio_core/renderer/voice/voice_context.cpp b/src/audio_core/renderer/voice/voice_context.cpp
index eafb51b01..a501a677d 100644
--- a/src/audio_core/renderer/voice/voice_context.cpp
+++ b/src/audio_core/renderer/voice/voice_context.cpp
@@ -74,8 +74,8 @@ void VoiceContext::SortInfo() {
74 } 74 }
75 75
76 std::ranges::sort(sorted_voice_info, [](const VoiceInfo* a, const VoiceInfo* b) { 76 std::ranges::sort(sorted_voice_info, [](const VoiceInfo* a, const VoiceInfo* b) {
77 return a->priority != b->priority ? a->priority < b->priority 77 return a->priority != b->priority ? a->priority > b->priority
78 : a->sort_order < b->sort_order; 78 : a->sort_order > b->sort_order;
79 }); 79 });
80} 80}
81 81
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 46cf75fde..c0555f840 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -156,12 +156,13 @@ if (MSVC)
156 ) 156 )
157 target_compile_options(common PRIVATE 157 target_compile_options(common PRIVATE
158 /W4 158 /W4
159 /WX 159
160 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
161 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
162 /we4800 # Implicit conversion from 'type' to bool. Possible information loss
160 ) 163 )
161else() 164else()
162 target_compile_options(common PRIVATE 165 target_compile_options(common PRIVATE
163 -Werror
164
165 $<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation> 166 $<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>
166 ) 167 )
167endif() 168endif()
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 7e1df62b1..e4e58ea45 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -141,10 +141,6 @@ public:
141 constexpr BitField(BitField&&) noexcept = default; 141 constexpr BitField(BitField&&) noexcept = default;
142 constexpr BitField& operator=(BitField&&) noexcept = default; 142 constexpr BitField& operator=(BitField&&) noexcept = default;
143 143
144 [[nodiscard]] constexpr operator T() const {
145 return Value();
146 }
147
148 constexpr void Assign(const T& value) { 144 constexpr void Assign(const T& value) {
149#ifdef _MSC_VER 145#ifdef _MSC_VER
150 storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value)); 146 storage = static_cast<StorageType>((storage & ~mask) | FormatValue(value));
@@ -162,6 +158,17 @@ public:
162 return ExtractValue(storage); 158 return ExtractValue(storage);
163 } 159 }
164 160
161 template <typename ConvertedToType>
162 [[nodiscard]] constexpr ConvertedToType As() const {
163 static_assert(!std::is_same_v<T, ConvertedToType>,
164 "Unnecessary cast. Use Value() instead.");
165 return static_cast<ConvertedToType>(Value());
166 }
167
168 [[nodiscard]] constexpr operator T() const {
169 return Value();
170 }
171
165 [[nodiscard]] constexpr explicit operator bool() const { 172 [[nodiscard]] constexpr explicit operator bool() const {
166 return Value() != 0; 173 return Value() != 0;
167 } 174 }
diff --git a/src/common/bounded_threadsafe_queue.h b/src/common/bounded_threadsafe_queue.h
index 7e465549b..21217801e 100644
--- a/src/common/bounded_threadsafe_queue.h
+++ b/src/common/bounded_threadsafe_queue.h
@@ -21,11 +21,6 @@ constexpr size_t hardware_interference_size = std::hardware_destructive_interfer
21constexpr size_t hardware_interference_size = 64; 21constexpr size_t hardware_interference_size = 64;
22#endif 22#endif
23 23
24#ifdef _MSC_VER
25#pragma warning(push)
26#pragma warning(disable : 4324)
27#endif
28
29template <typename T, size_t capacity = 0x400> 24template <typename T, size_t capacity = 0x400>
30class MPSCQueue { 25class MPSCQueue {
31public: 26public:
@@ -160,8 +155,4 @@ private:
160 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible"); 155 static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible");
161}; 156};
162 157
163#ifdef _MSC_VER
164#pragma warning(pop)
165#endif
166
167} // namespace Common 158} // namespace Common
diff --git a/src/common/concepts.h b/src/common/concepts.h
index a97555f6a..a9acff3e7 100644
--- a/src/common/concepts.h
+++ b/src/common/concepts.h
@@ -3,24 +3,14 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <iterator>
6#include <type_traits> 7#include <type_traits>
7 8
8namespace Common { 9namespace Common {
9 10
10// Check if type is like an STL container 11// Check if type satisfies the ContiguousContainer named requirement.
11template <typename T> 12template <typename T>
12concept IsSTLContainer = requires(T t) { 13concept IsContiguousContainer = std::contiguous_iterator<typename T::iterator>;
13 typename T::value_type;
14 typename T::iterator;
15 typename T::const_iterator;
16 // TODO(ogniK): Replace below is std::same_as<void> when MSVC supports it.
17 t.begin();
18 t.end();
19 t.cbegin();
20 t.cend();
21 t.data();
22 t.size();
23};
24 14
25// TODO: Replace with std::derived_from when the <concepts> header 15// TODO: Replace with std::derived_from when the <concepts> header
26// is available on all supported platforms. 16// is available on all supported platforms.
@@ -34,4 +24,12 @@ concept DerivedFrom = requires {
34template <typename From, typename To> 24template <typename From, typename To>
35concept ConvertibleTo = std::is_convertible_v<From, To>; 25concept ConvertibleTo = std::is_convertible_v<From, To>;
36 26
27// No equivalents in the stdlib
28
29template <typename T>
30concept IsArithmetic = std::is_arithmetic_v<T>;
31
32template <typename T>
33concept IsIntegral = std::is_integral_v<T>;
34
37} // namespace Common 35} // namespace Common
diff --git a/src/common/fixed_point.h b/src/common/fixed_point.h
index 6eb6afe2f..f899b0d54 100644
--- a/src/common/fixed_point.h
+++ b/src/common/fixed_point.h
@@ -12,6 +12,8 @@
12#include <ostream> 12#include <ostream>
13#include <type_traits> 13#include <type_traits>
14 14
15#include <common/concepts.h>
16
15namespace Common { 17namespace Common {
16 18
17template <size_t I, size_t F> 19template <size_t I, size_t F>
@@ -50,8 +52,8 @@ struct type_from_size<64> {
50 static constexpr size_t size = 64; 52 static constexpr size_t size = 64;
51 53
52 using value_type = int64_t; 54 using value_type = int64_t;
53 using unsigned_type = std::make_unsigned<value_type>::type; 55 using unsigned_type = std::make_unsigned_t<value_type>;
54 using signed_type = std::make_signed<value_type>::type; 56 using signed_type = std::make_signed_t<value_type>;
55 using next_size = type_from_size<128>; 57 using next_size = type_from_size<128>;
56}; 58};
57 59
@@ -61,8 +63,8 @@ struct type_from_size<32> {
61 static constexpr size_t size = 32; 63 static constexpr size_t size = 32;
62 64
63 using value_type = int32_t; 65 using value_type = int32_t;
64 using unsigned_type = std::make_unsigned<value_type>::type; 66 using unsigned_type = std::make_unsigned_t<value_type>;
65 using signed_type = std::make_signed<value_type>::type; 67 using signed_type = std::make_signed_t<value_type>;
66 using next_size = type_from_size<64>; 68 using next_size = type_from_size<64>;
67}; 69};
68 70
@@ -72,8 +74,8 @@ struct type_from_size<16> {
72 static constexpr size_t size = 16; 74 static constexpr size_t size = 16;
73 75
74 using value_type = int16_t; 76 using value_type = int16_t;
75 using unsigned_type = std::make_unsigned<value_type>::type; 77 using unsigned_type = std::make_unsigned_t<value_type>;
76 using signed_type = std::make_signed<value_type>::type; 78 using signed_type = std::make_signed_t<value_type>;
77 using next_size = type_from_size<32>; 79 using next_size = type_from_size<32>;
78}; 80};
79 81
@@ -83,8 +85,8 @@ struct type_from_size<8> {
83 static constexpr size_t size = 8; 85 static constexpr size_t size = 8;
84 86
85 using value_type = int8_t; 87 using value_type = int8_t;
86 using unsigned_type = std::make_unsigned<value_type>::type; 88 using unsigned_type = std::make_unsigned_t<value_type>;
87 using signed_type = std::make_signed<value_type>::type; 89 using signed_type = std::make_signed_t<value_type>;
88 using next_size = type_from_size<16>; 90 using next_size = type_from_size<16>;
89}; 91};
90 92
@@ -101,7 +103,7 @@ struct divide_by_zero : std::exception {};
101template <size_t I, size_t F> 103template <size_t I, size_t F>
102constexpr FixedPoint<I, F> divide( 104constexpr FixedPoint<I, F> divide(
103 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, 105 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder,
104 typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 106 std::enable_if_t<type_from_size<I + F>::next_size::is_specialized>* = nullptr) {
105 107
106 using next_type = typename FixedPoint<I, F>::next_type; 108 using next_type = typename FixedPoint<I, F>::next_type;
107 using base_type = typename FixedPoint<I, F>::base_type; 109 using base_type = typename FixedPoint<I, F>::base_type;
@@ -121,7 +123,7 @@ constexpr FixedPoint<I, F> divide(
121template <size_t I, size_t F> 123template <size_t I, size_t F>
122constexpr FixedPoint<I, F> divide( 124constexpr FixedPoint<I, F> divide(
123 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder, 125 FixedPoint<I, F> numerator, FixedPoint<I, F> denominator, FixedPoint<I, F>& remainder,
124 typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 126 std::enable_if_t<!type_from_size<I + F>::next_size::is_specialized>* = nullptr) {
125 127
126 using unsigned_type = typename FixedPoint<I, F>::unsigned_type; 128 using unsigned_type = typename FixedPoint<I, F>::unsigned_type;
127 129
@@ -191,7 +193,7 @@ constexpr FixedPoint<I, F> divide(
191template <size_t I, size_t F> 193template <size_t I, size_t F>
192constexpr FixedPoint<I, F> multiply( 194constexpr FixedPoint<I, F> multiply(
193 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, 195 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs,
194 typename std::enable_if<type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 196 std::enable_if_t<type_from_size<I + F>::next_size::is_specialized>* = nullptr) {
195 197
196 using next_type = typename FixedPoint<I, F>::next_type; 198 using next_type = typename FixedPoint<I, F>::next_type;
197 using base_type = typename FixedPoint<I, F>::base_type; 199 using base_type = typename FixedPoint<I, F>::base_type;
@@ -210,7 +212,7 @@ constexpr FixedPoint<I, F> multiply(
210template <size_t I, size_t F> 212template <size_t I, size_t F>
211constexpr FixedPoint<I, F> multiply( 213constexpr FixedPoint<I, F> multiply(
212 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs, 214 FixedPoint<I, F> lhs, FixedPoint<I, F> rhs,
213 typename std::enable_if<!type_from_size<I + F>::next_size::is_specialized>::type* = nullptr) { 215 std::enable_if_t<!type_from_size<I + F>::next_size::is_specialized>* = nullptr) {
214 216
215 using base_type = typename FixedPoint<I, F>::base_type; 217 using base_type = typename FixedPoint<I, F>::base_type;
216 218
@@ -265,15 +267,16 @@ public:
265 static constexpr base_type one = base_type(1) << fractional_bits; 267 static constexpr base_type one = base_type(1) << fractional_bits;
266 268
267public: // constructors 269public: // constructors
268 FixedPoint() = default; 270 constexpr FixedPoint() = default;
269 FixedPoint(const FixedPoint&) = default; 271
270 FixedPoint(FixedPoint&&) = default; 272 constexpr FixedPoint(const FixedPoint&) = default;
271 FixedPoint& operator=(const FixedPoint&) = default; 273 constexpr FixedPoint& operator=(const FixedPoint&) = default;
272 274
273 template <class Number> 275 constexpr FixedPoint(FixedPoint&&) noexcept = default;
274 constexpr FixedPoint( 276 constexpr FixedPoint& operator=(FixedPoint&&) noexcept = default;
275 Number n, typename std::enable_if<std::is_arithmetic<Number>::value>::type* = nullptr) 277
276 : data_(static_cast<base_type>(n * one)) {} 278 template <IsArithmetic Number>
279 constexpr FixedPoint(Number n) : data_(static_cast<base_type>(n * one)) {}
277 280
278public: // conversion 281public: // conversion
279 template <size_t I2, size_t F2> 282 template <size_t I2, size_t F2>
@@ -301,36 +304,14 @@ public:
301 } 304 }
302 305
303public: // comparison operators 306public: // comparison operators
304 constexpr bool operator==(FixedPoint rhs) const { 307 friend constexpr auto operator<=>(FixedPoint lhs, FixedPoint rhs) = default;
305 return data_ == rhs.data_;
306 }
307
308 constexpr bool operator!=(FixedPoint rhs) const {
309 return data_ != rhs.data_;
310 }
311
312 constexpr bool operator<(FixedPoint rhs) const {
313 return data_ < rhs.data_;
314 }
315
316 constexpr bool operator>(FixedPoint rhs) const {
317 return data_ > rhs.data_;
318 }
319
320 constexpr bool operator<=(FixedPoint rhs) const {
321 return data_ <= rhs.data_;
322 }
323
324 constexpr bool operator>=(FixedPoint rhs) const {
325 return data_ >= rhs.data_;
326 }
327 308
328public: // unary operators 309public: // unary operators
329 constexpr bool operator!() const { 310 [[nodiscard]] constexpr bool operator!() const {
330 return !data_; 311 return !data_;
331 } 312 }
332 313
333 constexpr FixedPoint operator~() const { 314 [[nodiscard]] constexpr FixedPoint operator~() const {
334 // NOTE(eteran): this will often appear to "just negate" the value 315 // NOTE(eteran): this will often appear to "just negate" the value
335 // that is not an error, it is because -x == (~x+1) 316 // that is not an error, it is because -x == (~x+1)
336 // and that "+1" is adding an infinitesimally small fraction to the 317 // and that "+1" is adding an infinitesimally small fraction to the
@@ -338,11 +319,11 @@ public: // unary operators
338 return FixedPoint::from_base(~data_); 319 return FixedPoint::from_base(~data_);
339 } 320 }
340 321
341 constexpr FixedPoint operator-() const { 322 [[nodiscard]] constexpr FixedPoint operator-() const {
342 return FixedPoint::from_base(-data_); 323 return FixedPoint::from_base(-data_);
343 } 324 }
344 325
345 constexpr FixedPoint operator+() const { 326 [[nodiscard]] constexpr FixedPoint operator+() const {
346 return FixedPoint::from_base(+data_); 327 return FixedPoint::from_base(+data_);
347 } 328 }
348 329
@@ -411,15 +392,13 @@ public: // binary math operators, effects underlying bit pattern since these
411 return *this; 392 return *this;
412 } 393 }
413 394
414 template <class Integer, 395 template <IsIntegral Integer>
415 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
416 constexpr FixedPoint& operator>>=(Integer n) { 396 constexpr FixedPoint& operator>>=(Integer n) {
417 data_ >>= n; 397 data_ >>= n;
418 return *this; 398 return *this;
419 } 399 }
420 400
421 template <class Integer, 401 template <IsIntegral Integer>
422 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
423 constexpr FixedPoint& operator<<=(Integer n) { 402 constexpr FixedPoint& operator<<=(Integer n) {
424 data_ <<= n; 403 data_ <<= n;
425 return *this; 404 return *this;
@@ -430,42 +409,42 @@ public: // conversion to basic types
430 data_ += (data_ & fractional_mask) >> 1; 409 data_ += (data_ & fractional_mask) >> 1;
431 } 410 }
432 411
433 constexpr int to_int() { 412 [[nodiscard]] constexpr int to_int() {
434 round_up(); 413 round_up();
435 return static_cast<int>((data_ & integer_mask) >> fractional_bits); 414 return static_cast<int>((data_ & integer_mask) >> fractional_bits);
436 } 415 }
437 416
438 constexpr unsigned int to_uint() const { 417 [[nodiscard]] constexpr unsigned int to_uint() {
439 round_up(); 418 round_up();
440 return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); 419 return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits);
441 } 420 }
442 421
443 constexpr int64_t to_long() { 422 [[nodiscard]] constexpr int64_t to_long() {
444 round_up(); 423 round_up();
445 return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); 424 return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits);
446 } 425 }
447 426
448 constexpr int to_int_floor() const { 427 [[nodiscard]] constexpr int to_int_floor() const {
449 return static_cast<int>((data_ & integer_mask) >> fractional_bits); 428 return static_cast<int>((data_ & integer_mask) >> fractional_bits);
450 } 429 }
451 430
452 constexpr int64_t to_long_floor() { 431 [[nodiscard]] constexpr int64_t to_long_floor() const {
453 return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits); 432 return static_cast<int64_t>((data_ & integer_mask) >> fractional_bits);
454 } 433 }
455 434
456 constexpr unsigned int to_uint_floor() const { 435 [[nodiscard]] constexpr unsigned int to_uint_floor() const {
457 return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits); 436 return static_cast<unsigned int>((data_ & integer_mask) >> fractional_bits);
458 } 437 }
459 438
460 constexpr float to_float() const { 439 [[nodiscard]] constexpr float to_float() const {
461 return static_cast<float>(data_) / FixedPoint::one; 440 return static_cast<float>(data_) / FixedPoint::one;
462 } 441 }
463 442
464 constexpr double to_double() const { 443 [[nodiscard]] constexpr double to_double() const {
465 return static_cast<double>(data_) / FixedPoint::one; 444 return static_cast<double>(data_) / FixedPoint::one;
466 } 445 }
467 446
468 constexpr base_type to_raw() const { 447 [[nodiscard]] constexpr base_type to_raw() const {
469 return data_; 448 return data_;
470 } 449 }
471 450
@@ -473,27 +452,27 @@ public: // conversion to basic types
473 data_ &= fractional_mask; 452 data_ &= fractional_mask;
474 } 453 }
475 454
476 constexpr base_type get_frac() const { 455 [[nodiscard]] constexpr base_type get_frac() const {
477 return data_ & fractional_mask; 456 return data_ & fractional_mask;
478 } 457 }
479 458
480public: 459public:
481 constexpr void swap(FixedPoint& rhs) { 460 constexpr void swap(FixedPoint& rhs) noexcept {
482 using std::swap; 461 using std::swap;
483 swap(data_, rhs.data_); 462 swap(data_, rhs.data_);
484 } 463 }
485 464
486public: 465public:
487 base_type data_; 466 base_type data_{};
488}; 467};
489 468
490// if we have the same fractional portion, but differing integer portions, we trivially upgrade the 469// if we have the same fractional portion, but differing integer portions, we trivially upgrade the
491// smaller type 470// smaller type
492template <size_t I1, size_t I2, size_t F> 471template <size_t I1, size_t I2, size_t F>
493constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator+( 472constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator+(
494 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 473 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
495 474
496 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 475 using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>;
497 476
498 const T l = T::from_base(lhs.to_raw()); 477 const T l = T::from_base(lhs.to_raw());
499 const T r = T::from_base(rhs.to_raw()); 478 const T r = T::from_base(rhs.to_raw());
@@ -501,10 +480,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2,
501} 480}
502 481
503template <size_t I1, size_t I2, size_t F> 482template <size_t I1, size_t I2, size_t F>
504constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator-( 483constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator-(
505 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 484 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
506 485
507 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 486 using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>;
508 487
509 const T l = T::from_base(lhs.to_raw()); 488 const T l = T::from_base(lhs.to_raw());
510 const T r = T::from_base(rhs.to_raw()); 489 const T r = T::from_base(rhs.to_raw());
@@ -512,10 +491,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2,
512} 491}
513 492
514template <size_t I1, size_t I2, size_t F> 493template <size_t I1, size_t I2, size_t F>
515constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator*( 494constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator*(
516 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 495 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
517 496
518 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 497 using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>;
519 498
520 const T l = T::from_base(lhs.to_raw()); 499 const T l = T::from_base(lhs.to_raw());
521 const T r = T::from_base(rhs.to_raw()); 500 const T r = T::from_base(rhs.to_raw());
@@ -523,10 +502,10 @@ constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2,
523} 502}
524 503
525template <size_t I1, size_t I2, size_t F> 504template <size_t I1, size_t I2, size_t F>
526constexpr typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type operator/( 505constexpr std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>> operator/(
527 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) { 506 FixedPoint<I1, F> lhs, FixedPoint<I2, F> rhs) {
528 507
529 using T = typename std::conditional<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>::type; 508 using T = std::conditional_t<I1 >= I2, FixedPoint<I1, F>, FixedPoint<I2, F>>;
530 509
531 const T l = T::from_base(lhs.to_raw()); 510 const T l = T::from_base(lhs.to_raw());
532 const T r = T::from_base(rhs.to_raw()); 511 const T r = T::from_base(rhs.to_raw());
@@ -561,54 +540,46 @@ constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, FixedPoint<I, F> rhs)
561 return lhs; 540 return lhs;
562} 541}
563 542
564template <size_t I, size_t F, class Number, 543template <size_t I, size_t F, IsArithmetic Number>
565 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
566constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) { 544constexpr FixedPoint<I, F> operator+(FixedPoint<I, F> lhs, Number rhs) {
567 lhs += FixedPoint<I, F>(rhs); 545 lhs += FixedPoint<I, F>(rhs);
568 return lhs; 546 return lhs;
569} 547}
570template <size_t I, size_t F, class Number, 548template <size_t I, size_t F, IsArithmetic Number>
571 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
572constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) { 549constexpr FixedPoint<I, F> operator-(FixedPoint<I, F> lhs, Number rhs) {
573 lhs -= FixedPoint<I, F>(rhs); 550 lhs -= FixedPoint<I, F>(rhs);
574 return lhs; 551 return lhs;
575} 552}
576template <size_t I, size_t F, class Number, 553template <size_t I, size_t F, IsArithmetic Number>
577 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
578constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) { 554constexpr FixedPoint<I, F> operator*(FixedPoint<I, F> lhs, Number rhs) {
579 lhs *= FixedPoint<I, F>(rhs); 555 lhs *= FixedPoint<I, F>(rhs);
580 return lhs; 556 return lhs;
581} 557}
582template <size_t I, size_t F, class Number, 558template <size_t I, size_t F, IsArithmetic Number>
583 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
584constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) { 559constexpr FixedPoint<I, F> operator/(FixedPoint<I, F> lhs, Number rhs) {
585 lhs /= FixedPoint<I, F>(rhs); 560 lhs /= FixedPoint<I, F>(rhs);
586 return lhs; 561 return lhs;
587} 562}
588 563
589template <size_t I, size_t F, class Number, 564template <size_t I, size_t F, IsArithmetic Number>
590 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
591constexpr FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) { 565constexpr FixedPoint<I, F> operator+(Number lhs, FixedPoint<I, F> rhs) {
592 FixedPoint<I, F> tmp(lhs); 566 FixedPoint<I, F> tmp(lhs);
593 tmp += rhs; 567 tmp += rhs;
594 return tmp; 568 return tmp;
595} 569}
596template <size_t I, size_t F, class Number, 570template <size_t I, size_t F, IsArithmetic Number>
597 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
598constexpr FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) { 571constexpr FixedPoint<I, F> operator-(Number lhs, FixedPoint<I, F> rhs) {
599 FixedPoint<I, F> tmp(lhs); 572 FixedPoint<I, F> tmp(lhs);
600 tmp -= rhs; 573 tmp -= rhs;
601 return tmp; 574 return tmp;
602} 575}
603template <size_t I, size_t F, class Number, 576template <size_t I, size_t F, IsArithmetic Number>
604 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
605constexpr FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) { 577constexpr FixedPoint<I, F> operator*(Number lhs, FixedPoint<I, F> rhs) {
606 FixedPoint<I, F> tmp(lhs); 578 FixedPoint<I, F> tmp(lhs);
607 tmp *= rhs; 579 tmp *= rhs;
608 return tmp; 580 return tmp;
609} 581}
610template <size_t I, size_t F, class Number, 582template <size_t I, size_t F, IsArithmetic Number>
611 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
612constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) { 583constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) {
613 FixedPoint<I, F> tmp(lhs); 584 FixedPoint<I, F> tmp(lhs);
614 tmp /= rhs; 585 tmp /= rhs;
@@ -616,78 +587,64 @@ constexpr FixedPoint<I, F> operator/(Number lhs, FixedPoint<I, F> rhs) {
616} 587}
617 588
618// shift operators 589// shift operators
619template <size_t I, size_t F, class Integer, 590template <size_t I, size_t F, IsIntegral Integer>
620 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
621constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) { 591constexpr FixedPoint<I, F> operator<<(FixedPoint<I, F> lhs, Integer rhs) {
622 lhs <<= rhs; 592 lhs <<= rhs;
623 return lhs; 593 return lhs;
624} 594}
625template <size_t I, size_t F, class Integer, 595template <size_t I, size_t F, IsIntegral Integer>
626 class = typename std::enable_if<std::is_integral<Integer>::value>::type>
627constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) { 596constexpr FixedPoint<I, F> operator>>(FixedPoint<I, F> lhs, Integer rhs) {
628 lhs >>= rhs; 597 lhs >>= rhs;
629 return lhs; 598 return lhs;
630} 599}
631 600
632// comparison operators 601// comparison operators
633template <size_t I, size_t F, class Number, 602template <size_t I, size_t F, IsArithmetic Number>
634 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
635constexpr bool operator>(FixedPoint<I, F> lhs, Number rhs) { 603constexpr bool operator>(FixedPoint<I, F> lhs, Number rhs) {
636 return lhs > FixedPoint<I, F>(rhs); 604 return lhs > FixedPoint<I, F>(rhs);
637} 605}
638template <size_t I, size_t F, class Number, 606template <size_t I, size_t F, IsArithmetic Number>
639 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
640constexpr bool operator<(FixedPoint<I, F> lhs, Number rhs) { 607constexpr bool operator<(FixedPoint<I, F> lhs, Number rhs) {
641 return lhs < FixedPoint<I, F>(rhs); 608 return lhs < FixedPoint<I, F>(rhs);
642} 609}
643template <size_t I, size_t F, class Number, 610template <size_t I, size_t F, IsArithmetic Number>
644 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
645constexpr bool operator>=(FixedPoint<I, F> lhs, Number rhs) { 611constexpr bool operator>=(FixedPoint<I, F> lhs, Number rhs) {
646 return lhs >= FixedPoint<I, F>(rhs); 612 return lhs >= FixedPoint<I, F>(rhs);
647} 613}
648template <size_t I, size_t F, class Number, 614template <size_t I, size_t F, IsArithmetic Number>
649 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
650constexpr bool operator<=(FixedPoint<I, F> lhs, Number rhs) { 615constexpr bool operator<=(FixedPoint<I, F> lhs, Number rhs) {
651 return lhs <= FixedPoint<I, F>(rhs); 616 return lhs <= FixedPoint<I, F>(rhs);
652} 617}
653template <size_t I, size_t F, class Number, 618template <size_t I, size_t F, IsArithmetic Number>
654 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
655constexpr bool operator==(FixedPoint<I, F> lhs, Number rhs) { 619constexpr bool operator==(FixedPoint<I, F> lhs, Number rhs) {
656 return lhs == FixedPoint<I, F>(rhs); 620 return lhs == FixedPoint<I, F>(rhs);
657} 621}
658template <size_t I, size_t F, class Number, 622template <size_t I, size_t F, IsArithmetic Number>
659 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
660constexpr bool operator!=(FixedPoint<I, F> lhs, Number rhs) { 623constexpr bool operator!=(FixedPoint<I, F> lhs, Number rhs) {
661 return lhs != FixedPoint<I, F>(rhs); 624 return lhs != FixedPoint<I, F>(rhs);
662} 625}
663 626
664template <size_t I, size_t F, class Number, 627template <size_t I, size_t F, IsArithmetic Number>
665 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
666constexpr bool operator>(Number lhs, FixedPoint<I, F> rhs) { 628constexpr bool operator>(Number lhs, FixedPoint<I, F> rhs) {
667 return FixedPoint<I, F>(lhs) > rhs; 629 return FixedPoint<I, F>(lhs) > rhs;
668} 630}
669template <size_t I, size_t F, class Number, 631template <size_t I, size_t F, IsArithmetic Number>
670 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
671constexpr bool operator<(Number lhs, FixedPoint<I, F> rhs) { 632constexpr bool operator<(Number lhs, FixedPoint<I, F> rhs) {
672 return FixedPoint<I, F>(lhs) < rhs; 633 return FixedPoint<I, F>(lhs) < rhs;
673} 634}
674template <size_t I, size_t F, class Number, 635template <size_t I, size_t F, IsArithmetic Number>
675 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
676constexpr bool operator>=(Number lhs, FixedPoint<I, F> rhs) { 636constexpr bool operator>=(Number lhs, FixedPoint<I, F> rhs) {
677 return FixedPoint<I, F>(lhs) >= rhs; 637 return FixedPoint<I, F>(lhs) >= rhs;
678} 638}
679template <size_t I, size_t F, class Number, 639template <size_t I, size_t F, IsArithmetic Number>
680 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
681constexpr bool operator<=(Number lhs, FixedPoint<I, F> rhs) { 640constexpr bool operator<=(Number lhs, FixedPoint<I, F> rhs) {
682 return FixedPoint<I, F>(lhs) <= rhs; 641 return FixedPoint<I, F>(lhs) <= rhs;
683} 642}
684template <size_t I, size_t F, class Number, 643template <size_t I, size_t F, IsArithmetic Number>
685 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
686constexpr bool operator==(Number lhs, FixedPoint<I, F> rhs) { 644constexpr bool operator==(Number lhs, FixedPoint<I, F> rhs) {
687 return FixedPoint<I, F>(lhs) == rhs; 645 return FixedPoint<I, F>(lhs) == rhs;
688} 646}
689template <size_t I, size_t F, class Number, 647template <size_t I, size_t F, IsArithmetic Number>
690 class = typename std::enable_if<std::is_arithmetic<Number>::value>::type>
691constexpr bool operator!=(Number lhs, FixedPoint<I, F> rhs) { 648constexpr bool operator!=(Number lhs, FixedPoint<I, F> rhs) {
692 return FixedPoint<I, F>(lhs) != rhs; 649 return FixedPoint<I, F>(lhs) != rhs;
693} 650}
diff --git a/src/common/fs/file.h b/src/common/fs/file.h
index 69b53384c..167c4d826 100644
--- a/src/common/fs/file.h
+++ b/src/common/fs/file.h
@@ -209,8 +209,8 @@ public:
209 209
210 /** 210 /**
211 * Helper function which deduces the value type of a contiguous STL container used in ReadSpan. 211 * Helper function which deduces the value type of a contiguous STL container used in ReadSpan.
212 * If T is not a contiguous STL container as defined by the concept IsSTLContainer, this calls 212 * If T is not a contiguous container as defined by the concept IsContiguousContainer, this
213 * ReadObject and T must be a trivially copyable object. 213 * calls ReadObject and T must be a trivially copyable object.
214 * 214 *
215 * See ReadSpan for more details if T is a contiguous container. 215 * See ReadSpan for more details if T is a contiguous container.
216 * See ReadObject for more details if T is a trivially copyable object. 216 * See ReadObject for more details if T is a trivially copyable object.
@@ -223,7 +223,7 @@ public:
223 */ 223 */
224 template <typename T> 224 template <typename T>
225 [[nodiscard]] size_t Read(T& data) const { 225 [[nodiscard]] size_t Read(T& data) const {
226 if constexpr (IsSTLContainer<T>) { 226 if constexpr (IsContiguousContainer<T>) {
227 using ContiguousType = typename T::value_type; 227 using ContiguousType = typename T::value_type;
228 static_assert(std::is_trivially_copyable_v<ContiguousType>, 228 static_assert(std::is_trivially_copyable_v<ContiguousType>,
229 "Data type must be trivially copyable."); 229 "Data type must be trivially copyable.");
@@ -235,8 +235,8 @@ public:
235 235
236 /** 236 /**
237 * Helper function which deduces the value type of a contiguous STL container used in WriteSpan. 237 * Helper function which deduces the value type of a contiguous STL container used in WriteSpan.
238 * If T is not a contiguous STL container as defined by the concept IsSTLContainer, this calls 238 * If T is not a contiguous STL container as defined by the concept IsContiguousContainer, this
239 * WriteObject and T must be a trivially copyable object. 239 * calls WriteObject and T must be a trivially copyable object.
240 * 240 *
241 * See WriteSpan for more details if T is a contiguous container. 241 * See WriteSpan for more details if T is a contiguous container.
242 * See WriteObject for more details if T is a trivially copyable object. 242 * See WriteObject for more details if T is a trivially copyable object.
@@ -249,7 +249,7 @@ public:
249 */ 249 */
250 template <typename T> 250 template <typename T>
251 [[nodiscard]] size_t Write(const T& data) const { 251 [[nodiscard]] size_t Write(const T& data) const {
252 if constexpr (IsSTLContainer<T>) { 252 if constexpr (IsContiguousContainer<T>) {
253 using ContiguousType = typename T::value_type; 253 using ContiguousType = typename T::value_type;
254 static_assert(std::is_trivially_copyable_v<ContiguousType>, 254 static_assert(std::is_trivially_copyable_v<ContiguousType>,
255 "Data type must be trivially copyable."); 255 "Data type must be trivially copyable.");
diff --git a/src/common/input.h b/src/common/input.h
index b533f3844..cb30b7254 100644
--- a/src/common/input.h
+++ b/src/common/input.h
@@ -100,7 +100,6 @@ enum class CameraError {
100enum class VibrationAmplificationType { 100enum class VibrationAmplificationType {
101 Linear, 101 Linear,
102 Exponential, 102 Exponential,
103 Test,
104}; 103};
105 104
106// Analog properties for calibration 105// Analog properties for calibration
@@ -325,6 +324,10 @@ public:
325 return VibrationError::NotSupported; 324 return VibrationError::NotSupported;
326 } 325 }
327 326
327 virtual bool IsVibrationEnabled() {
328 return false;
329 }
330
328 virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) { 331 virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) {
329 return PollingError::NotSupported; 332 return PollingError::NotSupported;
330 } 333 }
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e7fe675cb..113e663b5 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -243,6 +243,8 @@ add_library(core STATIC
243 hle/kernel/k_server_session.h 243 hle/kernel/k_server_session.h
244 hle/kernel/k_session.cpp 244 hle/kernel/k_session.cpp
245 hle/kernel/k_session.h 245 hle/kernel/k_session.h
246 hle/kernel/k_session_request.cpp
247 hle/kernel/k_session_request.h
246 hle/kernel/k_shared_memory.cpp 248 hle/kernel/k_shared_memory.cpp
247 hle/kernel/k_shared_memory.h 249 hle/kernel/k_shared_memory.h
248 hle/kernel/k_shared_memory_info.h 250 hle/kernel/k_shared_memory_info.h
@@ -772,19 +774,15 @@ if (MSVC)
772 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data 774 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
773 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch 775 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
774 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 776 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
777 /we4800 # Implicit conversion from 'type' to bool. Possible information loss
775 ) 778 )
776else() 779else()
777 target_compile_options(core PRIVATE 780 target_compile_options(core PRIVATE
778 -Werror=conversion 781 -Werror=conversion
779 -Werror=ignored-qualifiers
780 782
781 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> 783 -Wno-sign-conversion
782 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
783 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
784 784
785 $<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation> 785 $<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>
786
787 -Wno-sign-conversion
788 ) 786 )
789endif() 787endif()
790 788
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index d1e70f19d..287ba102e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -450,7 +450,7 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::S
450 // Frame records are two words long: 450 // Frame records are two words long:
451 // fp+0 : pointer to previous frame record 451 // fp+0 : pointer to previous frame record
452 // fp+4 : value of lr for frame 452 // fp+4 : value of lr for frame
453 while (true) { 453 for (size_t i = 0; i < 256; i++) {
454 out.push_back({"", 0, lr, 0, ""}); 454 out.push_back({"", 0, lr, 0, ""});
455 if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { 455 if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) {
456 break; 456 break;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 22b5d5656..afb7fb3a0 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -517,7 +517,7 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::S
517 // Frame records are two words long: 517 // Frame records are two words long:
518 // fp+0 : pointer to previous frame record 518 // fp+0 : pointer to previous frame record
519 // fp+8 : value of lr for frame 519 // fp+8 : value of lr for frame
520 while (true) { 520 for (size_t i = 0; i < 256; i++) {
521 out.push_back({"", 0, lr, 0, ""}); 521 out.push_back({"", 0, lr, 0, ""});
522 if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { 522 if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) {
523 break; 523 break;
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 7fb8bc019..d8934be52 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -137,6 +137,7 @@ struct System::Impl {
137 device_memory = std::make_unique<Core::DeviceMemory>(); 137 device_memory = std::make_unique<Core::DeviceMemory>();
138 138
139 is_multicore = Settings::values.use_multi_core.GetValue(); 139 is_multicore = Settings::values.use_multi_core.GetValue();
140 extended_memory_layout = Settings::values.use_extended_memory_layout.GetValue();
140 141
141 core_timing.SetMulticore(is_multicore); 142 core_timing.SetMulticore(is_multicore);
142 core_timing.Initialize([&system]() { system.RegisterHostThread(); }); 143 core_timing.Initialize([&system]() { system.RegisterHostThread(); });
@@ -166,13 +167,18 @@ struct System::Impl {
166 } 167 }
167 168
168 void ReinitializeIfNecessary(System& system) { 169 void ReinitializeIfNecessary(System& system) {
169 if (is_multicore == Settings::values.use_multi_core.GetValue()) { 170 const bool must_reinitialize =
171 is_multicore != Settings::values.use_multi_core.GetValue() ||
172 extended_memory_layout != Settings::values.use_extended_memory_layout.GetValue();
173
174 if (!must_reinitialize) {
170 return; 175 return;
171 } 176 }
172 177
173 LOG_DEBUG(Kernel, "Re-initializing"); 178 LOG_DEBUG(Kernel, "Re-initializing");
174 179
175 is_multicore = Settings::values.use_multi_core.GetValue(); 180 is_multicore = Settings::values.use_multi_core.GetValue();
181 extended_memory_layout = Settings::values.use_extended_memory_layout.GetValue();
176 182
177 Initialize(system); 183 Initialize(system);
178 } 184 }
@@ -384,6 +390,7 @@ struct System::Impl {
384 kernel.ShutdownCores(); 390 kernel.ShutdownCores();
385 cpu_manager.Shutdown(); 391 cpu_manager.Shutdown();
386 debugger.reset(); 392 debugger.reset();
393 services->KillNVNFlinger();
387 kernel.CloseServices(); 394 kernel.CloseServices();
388 services.reset(); 395 services.reset();
389 service_manager.reset(); 396 service_manager.reset();
@@ -520,6 +527,7 @@ struct System::Impl {
520 527
521 bool is_multicore{}; 528 bool is_multicore{};
522 bool is_async_gpu{}; 529 bool is_async_gpu{};
530 bool extended_memory_layout{};
523 531
524 ExecuteProgramCallback execute_program_callback; 532 ExecuteProgramCallback execute_program_callback;
525 ExitCallback exit_callback; 533 ExitCallback exit_callback;
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index f23d9373b..5d02865f4 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -232,8 +232,8 @@ const std::vector<std::shared_ptr<NCA>>& XCI::GetNCAs() const {
232 232
233std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const { 233std::shared_ptr<NCA> XCI::GetNCAByType(NCAContentType type) const {
234 const auto program_id = secure_partition->GetProgramTitleID(); 234 const auto program_id = secure_partition->GetProgramTitleID();
235 const auto iter = std::find_if( 235 const auto iter =
236 ncas.begin(), ncas.end(), [this, type, program_id](const std::shared_ptr<NCA>& nca) { 236 std::find_if(ncas.begin(), ncas.end(), [type, program_id](const std::shared_ptr<NCA>& nca) {
237 return nca->GetType() == type && nca->GetTitleId() == program_id; 237 return nca->GetType() == type && nca->GetTitleId() == program_id;
238 }); 238 });
239 return iter == ncas.end() ? nullptr : *iter; 239 return iter == ncas.end() ? nullptr : *iter;
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
index be25da2f6..50f44f598 100644
--- a/src/core/file_sys/control_metadata.cpp
+++ b/src/core/file_sys/control_metadata.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 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 "common/settings.h"
4#include "common/string_util.h" 5#include "common/string_util.h"
5#include "common/swap.h" 6#include "common/swap.h"
6#include "core/file_sys/control_metadata.h" 7#include "core/file_sys/control_metadata.h"
@@ -37,6 +38,27 @@ std::string LanguageEntry::GetDeveloperName() const {
37 developer_name.size()); 38 developer_name.size());
38} 39}
39 40
41constexpr std::array<Language, 18> language_to_codes = {{
42 Language::Japanese,
43 Language::AmericanEnglish,
44 Language::French,
45 Language::German,
46 Language::Italian,
47 Language::Spanish,
48 Language::Chinese,
49 Language::Korean,
50 Language::Dutch,
51 Language::Portuguese,
52 Language::Russian,
53 Language::Taiwanese,
54 Language::BritishEnglish,
55 Language::CanadianFrench,
56 Language::LatinAmericanSpanish,
57 Language::Chinese,
58 Language::Taiwanese,
59 Language::BrazilianPortuguese,
60}};
61
40NACP::NACP() = default; 62NACP::NACP() = default;
41 63
42NACP::NACP(VirtualFile file) { 64NACP::NACP(VirtualFile file) {
@@ -45,9 +67,13 @@ NACP::NACP(VirtualFile file) {
45 67
46NACP::~NACP() = default; 68NACP::~NACP() = default;
47 69
48const LanguageEntry& NACP::GetLanguageEntry(Language language) const { 70const LanguageEntry& NACP::GetLanguageEntry() const {
49 if (language != Language::Default) { 71 Language language = language_to_codes[Settings::values.language_index.GetValue()];
50 return raw.language_entries.at(static_cast<u8>(language)); 72
73 {
74 const auto& language_entry = raw.language_entries.at(static_cast<u8>(language));
75 if (!language_entry.GetApplicationName().empty())
76 return language_entry;
51 } 77 }
52 78
53 for (const auto& language_entry : raw.language_entries) { 79 for (const auto& language_entry : raw.language_entries) {
@@ -55,16 +81,15 @@ const LanguageEntry& NACP::GetLanguageEntry(Language language) const {
55 return language_entry; 81 return language_entry;
56 } 82 }
57 83
58 // Fallback to English 84 return raw.language_entries.at(static_cast<u8>(Language::AmericanEnglish));
59 return GetLanguageEntry(Language::AmericanEnglish);
60} 85}
61 86
62std::string NACP::GetApplicationName(Language language) const { 87std::string NACP::GetApplicationName() const {
63 return GetLanguageEntry(language).GetApplicationName(); 88 return GetLanguageEntry().GetApplicationName();
64} 89}
65 90
66std::string NACP::GetDeveloperName(Language language) const { 91std::string NACP::GetDeveloperName() const {
67 return GetLanguageEntry(language).GetDeveloperName(); 92 return GetLanguageEntry().GetDeveloperName();
68} 93}
69 94
70u64 NACP::GetTitleId() const { 95u64 NACP::GetTitleId() const {
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
index 75295519c..6a81873b1 100644
--- a/src/core/file_sys/control_metadata.h
+++ b/src/core/file_sys/control_metadata.h
@@ -101,9 +101,9 @@ public:
101 explicit NACP(VirtualFile file); 101 explicit NACP(VirtualFile file);
102 ~NACP(); 102 ~NACP();
103 103
104 const LanguageEntry& GetLanguageEntry(Language language = Language::Default) const; 104 const LanguageEntry& GetLanguageEntry() const;
105 std::string GetApplicationName(Language language = Language::Default) const; 105 std::string GetApplicationName() const;
106 std::string GetDeveloperName(Language language = Language::Default) const; 106 std::string GetDeveloperName() const;
107 u64 GetTitleId() const; 107 u64 GetTitleId() const;
108 u64 GetDLCBaseTitleId() const; 108 u64 GetDLCBaseTitleId() const;
109 std::string GetVersionString() const; 109 std::string GetVersionString() const;
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index 08d489eab..f00479bd3 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -127,7 +127,7 @@ void ProgramMetadata::LoadManual(bool is_64_bit, ProgramAddressSpaceType address
127} 127}
128 128
129bool ProgramMetadata::Is64BitProgram() const { 129bool ProgramMetadata::Is64BitProgram() const {
130 return npdm_header.has_64_bit_instructions; 130 return npdm_header.has_64_bit_instructions.As<bool>();
131} 131}
132 132
133ProgramAddressSpaceType ProgramMetadata::GetAddressSpaceType() const { 133ProgramAddressSpaceType ProgramMetadata::GetAddressSpaceType() const {
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 025f1c78e..ec1364452 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -970,14 +970,7 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
970 Common::Input::VibrationError::None; 970 Common::Input::VibrationError::None;
971} 971}
972 972
973bool EmulatedController::TestVibration(std::size_t device_index) { 973bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
974 if (device_index >= output_devices.size()) {
975 return false;
976 }
977 if (!output_devices[device_index]) {
978 return false;
979 }
980
981 const auto player_index = NpadIdTypeToIndex(npad_id_type); 974 const auto player_index = NpadIdTypeToIndex(npad_id_type);
982 const auto& player = Settings::values.players.GetValue()[player_index]; 975 const auto& player = Settings::values.players.GetValue()[player_index];
983 976
@@ -985,31 +978,15 @@ bool EmulatedController::TestVibration(std::size_t device_index) {
985 return false; 978 return false;
986 } 979 }
987 980
988 const Common::Input::VibrationStatus test_vibration = { 981 if (device_index >= output_devices.size()) {
989 .low_amplitude = 0.001f, 982 return false;
990 .low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency, 983 }
991 .high_amplitude = 0.001f,
992 .high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency,
993 .type = Common::Input::VibrationAmplificationType::Test,
994 };
995
996 const Common::Input::VibrationStatus zero_vibration = {
997 .low_amplitude = DEFAULT_VIBRATION_VALUE.low_amplitude,
998 .low_frequency = DEFAULT_VIBRATION_VALUE.low_frequency,
999 .high_amplitude = DEFAULT_VIBRATION_VALUE.high_amplitude,
1000 .high_frequency = DEFAULT_VIBRATION_VALUE.high_frequency,
1001 .type = Common::Input::VibrationAmplificationType::Test,
1002 };
1003
1004 // Send a slight vibration to test for rumble support
1005 output_devices[device_index]->SetVibration(test_vibration);
1006 984
1007 // Wait for about 15ms to ensure the controller is ready for the stop command 985 if (!output_devices[device_index]) {
1008 std::this_thread::sleep_for(std::chrono::milliseconds(15)); 986 return false;
987 }
1009 988
1010 // Stop any vibration and return the result 989 return output_devices[device_index]->IsVibrationEnabled();
1011 return output_devices[device_index]->SetVibration(zero_vibration) ==
1012 Common::Input::VibrationError::None;
1013} 990}
1014 991
1015bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) { 992bool EmulatedController::SetPollingMode(Common::Input::PollingMode polling_mode) {
@@ -1048,6 +1025,7 @@ bool EmulatedController::HasNfc() const {
1048 case NpadStyleIndex::JoyconRight: 1025 case NpadStyleIndex::JoyconRight:
1049 case NpadStyleIndex::JoyconDual: 1026 case NpadStyleIndex::JoyconDual:
1050 case NpadStyleIndex::ProController: 1027 case NpadStyleIndex::ProController:
1028 case NpadStyleIndex::Handheld:
1051 break; 1029 break;
1052 default: 1030 default:
1053 return false; 1031 return false;
@@ -1158,27 +1136,27 @@ bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
1158 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type; 1136 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
1159 switch (type) { 1137 switch (type) {
1160 case NpadStyleIndex::ProController: 1138 case NpadStyleIndex::ProController:
1161 return supported_style_tag.fullkey; 1139 return supported_style_tag.fullkey.As<bool>();
1162 case NpadStyleIndex::Handheld: 1140 case NpadStyleIndex::Handheld:
1163 return supported_style_tag.handheld; 1141 return supported_style_tag.handheld.As<bool>();
1164 case NpadStyleIndex::JoyconDual: 1142 case NpadStyleIndex::JoyconDual:
1165 return supported_style_tag.joycon_dual; 1143 return supported_style_tag.joycon_dual.As<bool>();
1166 case NpadStyleIndex::JoyconLeft: 1144 case NpadStyleIndex::JoyconLeft:
1167 return supported_style_tag.joycon_left; 1145 return supported_style_tag.joycon_left.As<bool>();
1168 case NpadStyleIndex::JoyconRight: 1146 case NpadStyleIndex::JoyconRight:
1169 return supported_style_tag.joycon_right; 1147 return supported_style_tag.joycon_right.As<bool>();
1170 case NpadStyleIndex::GameCube: 1148 case NpadStyleIndex::GameCube:
1171 return supported_style_tag.gamecube; 1149 return supported_style_tag.gamecube.As<bool>();
1172 case NpadStyleIndex::Pokeball: 1150 case NpadStyleIndex::Pokeball:
1173 return supported_style_tag.palma; 1151 return supported_style_tag.palma.As<bool>();
1174 case NpadStyleIndex::NES: 1152 case NpadStyleIndex::NES:
1175 return supported_style_tag.lark; 1153 return supported_style_tag.lark.As<bool>();
1176 case NpadStyleIndex::SNES: 1154 case NpadStyleIndex::SNES:
1177 return supported_style_tag.lucia; 1155 return supported_style_tag.lucia.As<bool>();
1178 case NpadStyleIndex::N64: 1156 case NpadStyleIndex::N64:
1179 return supported_style_tag.lagoon; 1157 return supported_style_tag.lagoon.As<bool>();
1180 case NpadStyleIndex::SegaGenesis: 1158 case NpadStyleIndex::SegaGenesis:
1181 return supported_style_tag.lager; 1159 return supported_style_tag.lager.As<bool>();
1182 default: 1160 default:
1183 return false; 1161 return false;
1184 } 1162 }
@@ -1234,12 +1212,6 @@ bool EmulatedController::IsConnected(bool get_temporary_value) const {
1234 return is_connected; 1212 return is_connected;
1235} 1213}
1236 1214
1237bool EmulatedController::IsVibrationEnabled() const {
1238 const auto player_index = NpadIdTypeToIndex(npad_id_type);
1239 const auto& player = Settings::values.players.GetValue()[player_index];
1240 return player.vibration_enabled;
1241}
1242
1243NpadIdType EmulatedController::GetNpadIdType() const { 1215NpadIdType EmulatedController::GetNpadIdType() const {
1244 std::scoped_lock lock{mutex}; 1216 std::scoped_lock lock{mutex};
1245 return npad_id_type; 1217 return npad_id_type;
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index 319226bf8..d004ca56a 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -206,9 +206,6 @@ public:
206 */ 206 */
207 bool IsConnected(bool get_temporary_value = false) const; 207 bool IsConnected(bool get_temporary_value = false) const;
208 208
209 /// Returns true if vibration is enabled
210 bool IsVibrationEnabled() const;
211
212 /// Removes all callbacks created from input devices 209 /// Removes all callbacks created from input devices
213 void UnloadInput(); 210 void UnloadInput();
214 211
@@ -339,7 +336,7 @@ public:
339 * Sends a small vibration to the output device 336 * Sends a small vibration to the output device
340 * @return true if SetVibration was successfull 337 * @return true if SetVibration was successfull
341 */ 338 */
342 bool TestVibration(std::size_t device_index); 339 bool IsVibrationEnabled(std::size_t device_index);
343 340
344 /** 341 /**
345 * Sets the desired data to be polled from a controller 342 * Sets the desired data to be polled from a controller
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 0cc26a211..18fde8bd6 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -86,13 +86,13 @@ public:
86 u32 num_domain_objects{}; 86 u32 num_domain_objects{};
87 const bool always_move_handles{ 87 const bool always_move_handles{
88 (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0}; 88 (static_cast<u32>(flags) & static_cast<u32>(Flags::AlwaysMoveHandles)) != 0};
89 if (!ctx.Session()->IsDomain() || always_move_handles) { 89 if (!ctx.Session()->GetSessionRequestManager()->IsDomain() || always_move_handles) {
90 num_handles_to_move = num_objects_to_move; 90 num_handles_to_move = num_objects_to_move;
91 } else { 91 } else {
92 num_domain_objects = num_objects_to_move; 92 num_domain_objects = num_objects_to_move;
93 } 93 }
94 94
95 if (ctx.Session()->IsDomain()) { 95 if (ctx.Session()->GetSessionRequestManager()->IsDomain()) {
96 raw_data_size += 96 raw_data_size +=
97 static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects); 97 static_cast<u32>(sizeof(DomainMessageHeader) / sizeof(u32) + num_domain_objects);
98 ctx.write_size += num_domain_objects; 98 ctx.write_size += num_domain_objects;
@@ -125,7 +125,8 @@ public:
125 if (!ctx.IsTipc()) { 125 if (!ctx.IsTipc()) {
126 AlignWithPadding(); 126 AlignWithPadding();
127 127
128 if (ctx.Session()->IsDomain() && ctx.HasDomainMessageHeader()) { 128 if (ctx.Session()->GetSessionRequestManager()->IsDomain() &&
129 ctx.HasDomainMessageHeader()) {
129 IPC::DomainMessageHeader domain_header{}; 130 IPC::DomainMessageHeader domain_header{};
130 domain_header.num_objects = num_domain_objects; 131 domain_header.num_objects = num_domain_objects;
131 PushRaw(domain_header); 132 PushRaw(domain_header);
@@ -145,7 +146,7 @@ public:
145 146
146 template <class T> 147 template <class T>
147 void PushIpcInterface(std::shared_ptr<T> iface) { 148 void PushIpcInterface(std::shared_ptr<T> iface) {
148 if (context->Session()->IsDomain()) { 149 if (context->Session()->GetSessionRequestManager()->IsDomain()) {
149 context->AddDomainObject(std::move(iface)); 150 context->AddDomainObject(std::move(iface));
150 } else { 151 } else {
151 kernel.CurrentProcess()->GetResourceLimit()->Reserve( 152 kernel.CurrentProcess()->GetResourceLimit()->Reserve(
@@ -386,7 +387,7 @@ public:
386 387
387 template <class T> 388 template <class T>
388 std::weak_ptr<T> PopIpcInterface() { 389 std::weak_ptr<T> PopIpcInterface() {
389 ASSERT(context->Session()->IsDomain()); 390 ASSERT(context->Session()->GetSessionRequestManager()->IsDomain());
390 ASSERT(context->GetDomainMessageHeader().input_object_count > 0); 391 ASSERT(context->GetDomainMessageHeader().input_object_count > 0);
391 return context->GetDomainHandler<T>(Pop<u32>() - 1); 392 return context->GetDomainHandler<T>(Pop<u32>() - 1);
392 } 393 }
@@ -405,7 +406,7 @@ inline s32 RequestParser::Pop() {
405} 406}
406 407
407// Ignore the -Wclass-memaccess warning on memcpy for non-trivially default constructible objects. 408// Ignore the -Wclass-memaccess warning on memcpy for non-trivially default constructible objects.
408#if defined(__GNUC__) 409#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
409#pragma GCC diagnostic push 410#pragma GCC diagnostic push
410#pragma GCC diagnostic ignored "-Wclass-memaccess" 411#pragma GCC diagnostic ignored "-Wclass-memaccess"
411#endif 412#endif
@@ -416,7 +417,7 @@ void RequestParser::PopRaw(T& value) {
416 std::memcpy(&value, cmdbuf + index, sizeof(T)); 417 std::memcpy(&value, cmdbuf + index, sizeof(T));
417 index += (sizeof(T) + 3) / 4; // round up to word length 418 index += (sizeof(T) + 3) / 4; // round up to word length
418} 419}
419#if defined(__GNUC__) 420#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
420#pragma GCC diagnostic pop 421#pragma GCC diagnostic pop
421#endif 422#endif
422 423
diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp
index 65576b8c4..fd911a3a5 100644
--- a/src/core/hle/kernel/global_scheduler_context.cpp
+++ b/src/core/hle/kernel/global_scheduler_context.cpp
@@ -49,4 +49,26 @@ bool GlobalSchedulerContext::IsLocked() const {
49 return scheduler_lock.IsLockedByCurrentThread(); 49 return scheduler_lock.IsLockedByCurrentThread();
50} 50}
51 51
52void GlobalSchedulerContext::RegisterDummyThreadForWakeup(KThread* thread) {
53 ASSERT(IsLocked());
54
55 woken_dummy_threads.insert(thread);
56}
57
58void GlobalSchedulerContext::UnregisterDummyThreadForWakeup(KThread* thread) {
59 ASSERT(IsLocked());
60
61 woken_dummy_threads.erase(thread);
62}
63
64void GlobalSchedulerContext::WakeupWaitingDummyThreads() {
65 ASSERT(IsLocked());
66
67 for (auto* thread : woken_dummy_threads) {
68 thread->DummyThreadEndWait();
69 }
70
71 woken_dummy_threads.clear();
72}
73
52} // namespace Kernel 74} // namespace Kernel
diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h
index 67bb9852d..220ed6192 100644
--- a/src/core/hle/kernel/global_scheduler_context.h
+++ b/src/core/hle/kernel/global_scheduler_context.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <atomic> 6#include <atomic>
7#include <set>
7#include <vector> 8#include <vector>
8 9
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -58,6 +59,10 @@ public:
58 /// Returns true if the global scheduler lock is acquired 59 /// Returns true if the global scheduler lock is acquired
59 bool IsLocked() const; 60 bool IsLocked() const;
60 61
62 void UnregisterDummyThreadForWakeup(KThread* thread);
63 void RegisterDummyThreadForWakeup(KThread* thread);
64 void WakeupWaitingDummyThreads();
65
61 [[nodiscard]] LockType& SchedulerLock() { 66 [[nodiscard]] LockType& SchedulerLock() {
62 return scheduler_lock; 67 return scheduler_lock;
63 } 68 }
@@ -76,6 +81,9 @@ private:
76 KSchedulerPriorityQueue priority_queue; 81 KSchedulerPriorityQueue priority_queue;
77 LockType scheduler_lock; 82 LockType scheduler_lock;
78 83
84 /// Lists dummy threads pending wakeup on lock release
85 std::set<KThread*> woken_dummy_threads;
86
79 /// Lists all thread ids that aren't deleted/etc. 87 /// Lists all thread ids that aren't deleted/etc.
80 std::vector<KThread*> thread_list; 88 std::vector<KThread*> thread_list;
81 std::mutex global_list_guard; 89 std::mutex global_list_guard;
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 5b3feec66..e4f43a053 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -19,6 +19,7 @@
19#include "core/hle/kernel/k_server_session.h" 19#include "core/hle/kernel/k_server_session.h"
20#include "core/hle/kernel/k_thread.h" 20#include "core/hle/kernel/k_thread.h"
21#include "core/hle/kernel/kernel.h" 21#include "core/hle/kernel/kernel.h"
22#include "core/hle/kernel/service_thread.h"
22#include "core/memory.h" 23#include "core/memory.h"
23 24
24namespace Kernel { 25namespace Kernel {
@@ -56,16 +57,103 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co
56 } 57 }
57} 58}
58 59
60Result SessionRequestManager::CompleteSyncRequest(KServerSession* server_session,
61 HLERequestContext& context) {
62 Result result = ResultSuccess;
63
64 // If the session has been converted to a domain, handle the domain request
65 if (this->HasSessionRequestHandler(context)) {
66 if (IsDomain() && context.HasDomainMessageHeader()) {
67 result = HandleDomainSyncRequest(server_session, context);
68 // If there is no domain header, the regular session handler is used
69 } else if (this->HasSessionHandler()) {
70 // If this manager has an associated HLE handler, forward the request to it.
71 result = this->SessionHandler().HandleSyncRequest(*server_session, context);
72 }
73 } else {
74 ASSERT_MSG(false, "Session handler is invalid, stubbing response!");
75 IPC::ResponseBuilder rb(context, 2);
76 rb.Push(ResultSuccess);
77 }
78
79 if (convert_to_domain) {
80 ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance.");
81 this->ConvertToDomain();
82 convert_to_domain = false;
83 }
84
85 return result;
86}
87
88Result SessionRequestManager::HandleDomainSyncRequest(KServerSession* server_session,
89 HLERequestContext& context) {
90 if (!context.HasDomainMessageHeader()) {
91 return ResultSuccess;
92 }
93
94 // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
95 context.SetSessionRequestManager(server_session->GetSessionRequestManager());
96
97 // If there is a DomainMessageHeader, then this is CommandType "Request"
98 const auto& domain_message_header = context.GetDomainMessageHeader();
99 const u32 object_id{domain_message_header.object_id};
100 switch (domain_message_header.command) {
101 case IPC::DomainMessageHeader::CommandType::SendMessage:
102 if (object_id > this->DomainHandlerCount()) {
103 LOG_CRITICAL(IPC,
104 "object_id {} is too big! This probably means a recent service call "
105 "needed to return a new interface!",
106 object_id);
107 ASSERT(false);
108 return ResultSuccess; // Ignore error if asserts are off
109 }
110 if (auto strong_ptr = this->DomainHandler(object_id - 1).lock()) {
111 return strong_ptr->HandleSyncRequest(*server_session, context);
112 } else {
113 ASSERT(false);
114 return ResultSuccess;
115 }
116
117 case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
118 LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
119
120 this->CloseDomainHandler(object_id - 1);
121
122 IPC::ResponseBuilder rb{context, 2};
123 rb.Push(ResultSuccess);
124 return ResultSuccess;
125 }
126 }
127
128 LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value());
129 ASSERT(false);
130 return ResultSuccess;
131}
132
133Result SessionRequestManager::QueueSyncRequest(KSession* parent,
134 std::shared_ptr<HLERequestContext>&& context) {
135 // Ensure we have a session request handler
136 if (this->HasSessionRequestHandler(*context)) {
137 if (auto strong_ptr = this->GetServiceThread().lock()) {
138 strong_ptr->QueueSyncRequest(*parent, std::move(context));
139 } else {
140 ASSERT_MSG(false, "strong_ptr is nullptr!");
141 }
142 } else {
143 ASSERT_MSG(false, "handler is invalid!");
144 }
145
146 return ResultSuccess;
147}
148
59void SessionRequestHandler::ClientConnected(KServerSession* session) { 149void SessionRequestHandler::ClientConnected(KServerSession* session) {
60 session->ClientConnected(shared_from_this()); 150 session->GetSessionRequestManager()->SetSessionHandler(shared_from_this());
61 151
62 // Ensure our server session is tracked globally. 152 // Ensure our server session is tracked globally.
63 kernel.RegisterServerObject(session); 153 kernel.RegisterServerObject(session);
64} 154}
65 155
66void SessionRequestHandler::ClientDisconnected(KServerSession* session) { 156void SessionRequestHandler::ClientDisconnected(KServerSession* session) {}
67 session->ClientDisconnected();
68}
69 157
70HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, 158HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_,
71 KServerSession* server_session_, KThread* thread_) 159 KServerSession* server_session_, KThread* thread_)
@@ -126,7 +214,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
126 // Padding to align to 16 bytes 214 // Padding to align to 16 bytes
127 rp.AlignWithPadding(); 215 rp.AlignWithPadding();
128 216
129 if (Session()->IsDomain() && 217 if (Session()->GetSessionRequestManager()->IsDomain() &&
130 ((command_header->type == IPC::CommandType::Request || 218 ((command_header->type == IPC::CommandType::Request ||
131 command_header->type == IPC::CommandType::RequestWithContext) || 219 command_header->type == IPC::CommandType::RequestWithContext) ||
132 !incoming)) { 220 !incoming)) {
@@ -135,7 +223,7 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
135 if (incoming || domain_message_header) { 223 if (incoming || domain_message_header) {
136 domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); 224 domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>();
137 } else { 225 } else {
138 if (Session()->IsDomain()) { 226 if (Session()->GetSessionRequestManager()->IsDomain()) {
139 LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); 227 LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!");
140 } 228 }
141 } 229 }
@@ -228,12 +316,12 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_threa
228 // Write the domain objects to the command buffer, these go after the raw untranslated data. 316 // Write the domain objects to the command buffer, these go after the raw untranslated data.
229 // TODO(Subv): This completely ignores C buffers. 317 // TODO(Subv): This completely ignores C buffers.
230 318
231 if (Session()->IsDomain()) { 319 if (server_session->GetSessionRequestManager()->IsDomain()) {
232 current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); 320 current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size());
233 for (const auto& object : outgoing_domain_objects) { 321 for (auto& object : outgoing_domain_objects) {
234 server_session->AppendDomainHandler(object); 322 server_session->GetSessionRequestManager()->AppendDomainHandler(std::move(object));
235 cmd_buf[current_offset++] = 323 cmd_buf[current_offset++] = static_cast<u32_le>(
236 static_cast<u32_le>(server_session->NumDomainRequestHandlers()); 324 server_session->GetSessionRequestManager()->DomainHandlerCount());
237 } 325 }
238 } 326 }
239 327
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index e258e2cdf..1083638a9 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -121,6 +121,10 @@ public:
121 is_domain = true; 121 is_domain = true;
122 } 122 }
123 123
124 void ConvertToDomainOnRequestEnd() {
125 convert_to_domain = true;
126 }
127
124 std::size_t DomainHandlerCount() const { 128 std::size_t DomainHandlerCount() const {
125 return domain_handlers.size(); 129 return domain_handlers.size();
126 } 130 }
@@ -164,7 +168,12 @@ public:
164 168
165 bool HasSessionRequestHandler(const HLERequestContext& context) const; 169 bool HasSessionRequestHandler(const HLERequestContext& context) const;
166 170
171 Result HandleDomainSyncRequest(KServerSession* server_session, HLERequestContext& context);
172 Result CompleteSyncRequest(KServerSession* server_session, HLERequestContext& context);
173 Result QueueSyncRequest(KSession* parent, std::shared_ptr<HLERequestContext>&& context);
174
167private: 175private:
176 bool convert_to_domain{};
168 bool is_domain{}; 177 bool is_domain{};
169 SessionRequestHandlerPtr session_handler; 178 SessionRequestHandlerPtr session_handler;
170 std::vector<SessionRequestHandlerPtr> domain_handlers; 179 std::vector<SessionRequestHandlerPtr> domain_handlers;
@@ -295,7 +304,7 @@ public:
295 */ 304 */
296 template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>> 305 template <typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>>
297 std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const { 306 std::size_t WriteBuffer(const T& data, std::size_t buffer_index = 0) const {
298 if constexpr (Common::IsSTLContainer<T>) { 307 if constexpr (Common::IsContiguousContainer<T>) {
299 using ContiguousType = typename T::value_type; 308 using ContiguousType = typename T::value_type;
300 static_assert(std::is_trivially_copyable_v<ContiguousType>, 309 static_assert(std::is_trivially_copyable_v<ContiguousType>,
301 "Container to WriteBuffer must contain trivially copyable objects"); 310 "Container to WriteBuffer must contain trivially copyable objects");
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index c84d36c8c..477e4e407 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -18,6 +18,7 @@
18#include "core/hle/kernel/k_process.h" 18#include "core/hle/kernel/k_process.h"
19#include "core/hle/kernel/k_resource_limit.h" 19#include "core/hle/kernel/k_resource_limit.h"
20#include "core/hle/kernel/k_session.h" 20#include "core/hle/kernel/k_session.h"
21#include "core/hle/kernel/k_session_request.h"
21#include "core/hle/kernel/k_shared_memory.h" 22#include "core/hle/kernel/k_shared_memory.h"
22#include "core/hle/kernel/k_shared_memory_info.h" 23#include "core/hle/kernel/k_shared_memory_info.h"
23#include "core/hle/kernel/k_system_control.h" 24#include "core/hle/kernel/k_system_control.h"
@@ -34,6 +35,7 @@ namespace Kernel::Init {
34 HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \ 35 HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__) \
35 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \ 36 HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__) \
36 HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \ 37 HANDLER(KPort, (SLAB_COUNT(KPort)), ##__VA_ARGS__) \
38 HANDLER(KSessionRequest, (SLAB_COUNT(KSession) * 2), ##__VA_ARGS__) \
37 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \ 39 HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__) \
38 HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ 40 HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \
39 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ 41 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \
diff --git a/src/core/hle/kernel/k_client_session.cpp b/src/core/hle/kernel/k_client_session.cpp
index 8892c5b7c..b4197a8d5 100644
--- a/src/core/hle/kernel/k_client_session.cpp
+++ b/src/core/hle/kernel/k_client_session.cpp
@@ -1,6 +1,7 @@
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 "common/scope_exit.h"
4#include "core/hle/kernel/hle_ipc.h" 5#include "core/hle/kernel/hle_ipc.h"
5#include "core/hle/kernel/k_client_session.h" 6#include "core/hle/kernel/k_client_session.h"
6#include "core/hle/kernel/k_server_session.h" 7#include "core/hle/kernel/k_server_session.h"
@@ -10,6 +11,8 @@
10 11
11namespace Kernel { 12namespace Kernel {
12 13
14static constexpr u32 MessageBufferSize = 0x100;
15
13KClientSession::KClientSession(KernelCore& kernel_) 16KClientSession::KClientSession(KernelCore& kernel_)
14 : KAutoObjectWithSlabHeapAndContainer{kernel_} {} 17 : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
15KClientSession::~KClientSession() = default; 18KClientSession::~KClientSession() = default;
@@ -22,8 +25,16 @@ void KClientSession::Destroy() {
22void KClientSession::OnServerClosed() {} 25void KClientSession::OnServerClosed() {}
23 26
24Result KClientSession::SendSyncRequest() { 27Result KClientSession::SendSyncRequest() {
25 // Signal the server session that new data is available 28 // Create a session request.
26 return parent->GetServerSession().OnRequest(); 29 KSessionRequest* request = KSessionRequest::Create(kernel);
30 R_UNLESS(request != nullptr, ResultOutOfResource);
31 SCOPE_EXIT({ request->Close(); });
32
33 // Initialize the request.
34 request->Initialize(nullptr, GetCurrentThread(kernel).GetTLSAddress(), MessageBufferSize);
35
36 // Send the request.
37 return parent->GetServerSession().OnRequest(request);
27} 38}
28 39
29} // namespace Kernel 40} // namespace Kernel
diff --git a/src/core/hle/kernel/k_linked_list.h b/src/core/hle/kernel/k_linked_list.h
index 78859ced3..29ebd16b7 100644
--- a/src/core/hle/kernel/k_linked_list.h
+++ b/src/core/hle/kernel/k_linked_list.h
@@ -16,6 +16,7 @@ class KLinkedListNode : public boost::intrusive::list_base_hook<>,
16 public KSlabAllocated<KLinkedListNode> { 16 public KSlabAllocated<KLinkedListNode> {
17 17
18public: 18public:
19 explicit KLinkedListNode(KernelCore&) {}
19 KLinkedListNode() = default; 20 KLinkedListNode() = default;
20 21
21 void Initialize(void* it) { 22 void Initialize(void* it) {
diff --git a/src/core/hle/kernel/k_page_buffer.h b/src/core/hle/kernel/k_page_buffer.h
index 7e50dc1d1..aef06e213 100644
--- a/src/core/hle/kernel/k_page_buffer.h
+++ b/src/core/hle/kernel/k_page_buffer.h
@@ -13,6 +13,7 @@ namespace Kernel {
13 13
14class KPageBuffer final : public KSlabAllocated<KPageBuffer> { 14class KPageBuffer final : public KSlabAllocated<KPageBuffer> {
15public: 15public:
16 explicit KPageBuffer(KernelCore&) {}
16 KPageBuffer() = default; 17 KPageBuffer() = default;
17 18
18 static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr); 19 static KPageBuffer* FromPhysicalAddress(Core::System& system, PAddr phys_addr);
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index c34ce7a17..b1cabbca0 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -81,8 +81,8 @@ void KScheduler::RescheduleCurrentHLEThread(KernelCore& kernel) {
81 // HACK: we cannot schedule from this thread, it is not a core thread 81 // HACK: we cannot schedule from this thread, it is not a core thread
82 ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); 82 ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1);
83 83
84 // Special case to ensure dummy threads that are waiting block 84 // Ensure dummy threads that are waiting block.
85 GetCurrentThread(kernel).IfDummyThreadTryWait(); 85 GetCurrentThread(kernel).DummyThreadBeginWait();
86 86
87 ASSERT(GetCurrentThread(kernel).GetState() != ThreadState::Waiting); 87 ASSERT(GetCurrentThread(kernel).GetState() != ThreadState::Waiting);
88 GetCurrentThread(kernel).EnableDispatch(); 88 GetCurrentThread(kernel).EnableDispatch();
@@ -314,6 +314,16 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) {
314 idle_cores &= ~(1ULL << core_id); 314 idle_cores &= ~(1ULL << core_id);
315 } 315 }
316 316
317 // HACK: any waiting dummy threads can wake up now.
318 kernel.GlobalSchedulerContext().WakeupWaitingDummyThreads();
319
320 // HACK: if we are a dummy thread, and we need to go sleep, indicate
321 // that for when the lock is released.
322 KThread* const cur_thread = GetCurrentThreadPointer(kernel);
323 if (cur_thread->IsDummyThread() && cur_thread->GetState() != ThreadState::Runnable) {
324 cur_thread->RequestDummyThreadWait();
325 }
326
317 return cores_needing_scheduling; 327 return cores_needing_scheduling;
318} 328}
319 329
@@ -531,11 +541,23 @@ void KScheduler::OnThreadStateChanged(KernelCore& kernel, KThread* thread, Threa
531 GetPriorityQueue(kernel).Remove(thread); 541 GetPriorityQueue(kernel).Remove(thread);
532 IncrementScheduledCount(thread); 542 IncrementScheduledCount(thread);
533 SetSchedulerUpdateNeeded(kernel); 543 SetSchedulerUpdateNeeded(kernel);
544
545 if (thread->IsDummyThread()) {
546 // HACK: if this is a dummy thread, it should no longer wake up when the
547 // scheduler lock is released.
548 kernel.GlobalSchedulerContext().UnregisterDummyThreadForWakeup(thread);
549 }
534 } else if (cur_state == ThreadState::Runnable) { 550 } else if (cur_state == ThreadState::Runnable) {
535 // If we're now runnable, then we weren't previously, and we should add. 551 // If we're now runnable, then we weren't previously, and we should add.
536 GetPriorityQueue(kernel).PushBack(thread); 552 GetPriorityQueue(kernel).PushBack(thread);
537 IncrementScheduledCount(thread); 553 IncrementScheduledCount(thread);
538 SetSchedulerUpdateNeeded(kernel); 554 SetSchedulerUpdateNeeded(kernel);
555
556 if (thread->IsDummyThread()) {
557 // HACK: if this is a dummy thread, it should wake up when the scheduler
558 // lock is released.
559 kernel.GlobalSchedulerContext().RegisterDummyThreadForWakeup(thread);
560 }
539 } 561 }
540} 562}
541 563
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 4252c9adb..faf03fcc8 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -22,15 +22,12 @@
22#include "core/hle/kernel/k_thread.h" 22#include "core/hle/kernel/k_thread.h"
23#include "core/hle/kernel/k_thread_queue.h" 23#include "core/hle/kernel/k_thread_queue.h"
24#include "core/hle/kernel/kernel.h" 24#include "core/hle/kernel/kernel.h"
25#include "core/hle/kernel/service_thread.h"
26#include "core/memory.h" 25#include "core/memory.h"
27 26
28namespace Kernel { 27namespace Kernel {
29 28
30using ThreadQueueImplForKServerSessionRequest = KThreadQueue; 29using ThreadQueueImplForKServerSessionRequest = KThreadQueue;
31 30
32static constexpr u32 MessageBufferSize = 0x100;
33
34KServerSession::KServerSession(KernelCore& kernel_) 31KServerSession::KServerSession(KernelCore& kernel_)
35 : KSynchronizationObject{kernel_}, m_lock{kernel_} {} 32 : KSynchronizationObject{kernel_}, m_lock{kernel_} {}
36 33
@@ -73,59 +70,7 @@ bool KServerSession::IsSignaled() const {
73 } 70 }
74 71
75 // Otherwise, we're signaled if we have a request and aren't handling one. 72 // Otherwise, we're signaled if we have a request and aren't handling one.
76 return !m_thread_request_list.empty() && m_current_thread_request == nullptr; 73 return !m_request_list.empty() && m_current_request == nullptr;
77}
78
79void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) {
80 manager->AppendDomainHandler(std::move(handler));
81}
82
83std::size_t KServerSession::NumDomainRequestHandlers() const {
84 return manager->DomainHandlerCount();
85}
86
87Result KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
88 if (!context.HasDomainMessageHeader()) {
89 return ResultSuccess;
90 }
91
92 // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
93 context.SetSessionRequestManager(manager);
94
95 // If there is a DomainMessageHeader, then this is CommandType "Request"
96 const auto& domain_message_header = context.GetDomainMessageHeader();
97 const u32 object_id{domain_message_header.object_id};
98 switch (domain_message_header.command) {
99 case IPC::DomainMessageHeader::CommandType::SendMessage:
100 if (object_id > manager->DomainHandlerCount()) {
101 LOG_CRITICAL(IPC,
102 "object_id {} is too big! This probably means a recent service call "
103 "to {} needed to return a new interface!",
104 object_id, name);
105 ASSERT(false);
106 return ResultSuccess; // Ignore error if asserts are off
107 }
108 if (auto strong_ptr = manager->DomainHandler(object_id - 1).lock()) {
109 return strong_ptr->HandleSyncRequest(*this, context);
110 } else {
111 ASSERT(false);
112 return ResultSuccess;
113 }
114
115 case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
116 LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
117
118 manager->CloseDomainHandler(object_id - 1);
119
120 IPC::ResponseBuilder rb{context, 2};
121 rb.Push(ResultSuccess);
122 return ResultSuccess;
123 }
124 }
125
126 LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value());
127 ASSERT(false);
128 return ResultSuccess;
129} 74}
130 75
131Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) { 76Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory) {
@@ -134,43 +79,11 @@ Result KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memory& m
134 79
135 context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); 80 context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
136 81
137 // Ensure we have a session request handler 82 return manager->QueueSyncRequest(parent, std::move(context));
138 if (manager->HasSessionRequestHandler(*context)) {
139 if (auto strong_ptr = manager->GetServiceThread().lock()) {
140 strong_ptr->QueueSyncRequest(*parent, std::move(context));
141 } else {
142 ASSERT_MSG(false, "strong_ptr is nullptr!");
143 }
144 } else {
145 ASSERT_MSG(false, "handler is invalid!");
146 }
147
148 return ResultSuccess;
149} 83}
150 84
151Result KServerSession::CompleteSyncRequest(HLERequestContext& context) { 85Result KServerSession::CompleteSyncRequest(HLERequestContext& context) {
152 Result result = ResultSuccess; 86 Result result = manager->CompleteSyncRequest(this, context);
153
154 // If the session has been converted to a domain, handle the domain request
155 if (manager->HasSessionRequestHandler(context)) {
156 if (IsDomain() && context.HasDomainMessageHeader()) {
157 result = HandleDomainSyncRequest(context);
158 // If there is no domain header, the regular session handler is used
159 } else if (manager->HasSessionHandler()) {
160 // If this ServerSession has an associated HLE handler, forward the request to it.
161 result = manager->SessionHandler().HandleSyncRequest(*this, context);
162 }
163 } else {
164 ASSERT_MSG(false, "Session handler is invalid, stubbing response!");
165 IPC::ResponseBuilder rb(context, 2);
166 rb.Push(ResultSuccess);
167 }
168
169 if (convert_to_domain) {
170 ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance.");
171 manager->ConvertToDomain();
172 convert_to_domain = false;
173 }
174 87
175 // The calling thread is waiting for this request to complete, so wake it up. 88 // The calling thread is waiting for this request to complete, so wake it up.
176 context.GetThread().EndWait(result); 89 context.GetThread().EndWait(result);
@@ -178,7 +91,7 @@ Result KServerSession::CompleteSyncRequest(HLERequestContext& context) {
178 return result; 91 return result;
179} 92}
180 93
181Result KServerSession::OnRequest() { 94Result KServerSession::OnRequest(KSessionRequest* request) {
182 // Create the wait queue. 95 // Create the wait queue.
183 ThreadQueueImplForKServerSessionRequest wait_queue{kernel}; 96 ThreadQueueImplForKServerSessionRequest wait_queue{kernel};
184 97
@@ -198,14 +111,13 @@ Result KServerSession::OnRequest() {
198 this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory); 111 this->QueueSyncRequest(GetCurrentThreadPointer(kernel), memory);
199 } else { 112 } else {
200 // Non-HLE request. 113 // Non-HLE request.
201 auto* thread{GetCurrentThreadPointer(kernel)};
202 114
203 // Get whether we're empty. 115 // Get whether we're empty.
204 const bool was_empty = m_thread_request_list.empty(); 116 const bool was_empty = m_request_list.empty();
205 117
206 // Add the thread to the list. 118 // Add the request to the list.
207 thread->Open(); 119 request->Open();
208 m_thread_request_list.push_back(thread); 120 m_request_list.push_back(*request);
209 121
210 // If we were empty, signal. 122 // If we were empty, signal.
211 if (was_empty) { 123 if (was_empty) {
@@ -213,6 +125,9 @@ Result KServerSession::OnRequest() {
213 } 125 }
214 } 126 }
215 127
128 // If we have a request event, this is asynchronous, and we don't need to wait.
129 R_SUCCEED_IF(request->GetEvent() != nullptr);
130
216 // This is a synchronous request, so we should wait for our request to complete. 131 // This is a synchronous request, so we should wait for our request to complete.
217 GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); 132 GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
218 GetCurrentThread(kernel).BeginWait(&wait_queue); 133 GetCurrentThread(kernel).BeginWait(&wait_queue);
@@ -223,32 +138,32 @@ Result KServerSession::OnRequest() {
223 138
224Result KServerSession::SendReply() { 139Result KServerSession::SendReply() {
225 // Lock the session. 140 // Lock the session.
226 KScopedLightLock lk(m_lock); 141 KScopedLightLock lk{m_lock};
227 142
228 // Get the request. 143 // Get the request.
229 KThread* client_thread; 144 KSessionRequest* request;
230 { 145 {
231 KScopedSchedulerLock sl{kernel}; 146 KScopedSchedulerLock sl{kernel};
232 147
233 // Get the current request. 148 // Get the current request.
234 client_thread = m_current_thread_request; 149 request = m_current_request;
235 R_UNLESS(client_thread != nullptr, ResultInvalidState); 150 R_UNLESS(request != nullptr, ResultInvalidState);
236 151
237 // Clear the current request, since we're processing it. 152 // Clear the current request, since we're processing it.
238 m_current_thread_request = nullptr; 153 m_current_request = nullptr;
239 if (!m_thread_request_list.empty()) { 154 if (!m_request_list.empty()) {
240 this->NotifyAvailable(); 155 this->NotifyAvailable();
241 } 156 }
242 } 157 }
243 158
244 // Close reference to the request once we're done processing it. 159 // Close reference to the request once we're done processing it.
245 SCOPE_EXIT({ client_thread->Close(); }); 160 SCOPE_EXIT({ request->Close(); });
246 161
247 // Extract relevant information from the request. 162 // Extract relevant information from the request.
248 // const uintptr_t client_message = request->GetAddress(); 163 const uintptr_t client_message = request->GetAddress();
249 // const size_t client_buffer_size = request->GetSize(); 164 const size_t client_buffer_size = request->GetSize();
250 // KThread *client_thread = request->GetThread(); 165 KThread* client_thread = request->GetThread();
251 // KEvent *event = request->GetEvent(); 166 KEvent* event = request->GetEvent();
252 167
253 // Check whether we're closed. 168 // Check whether we're closed.
254 const bool closed = (client_thread == nullptr || parent->IsClientClosed()); 169 const bool closed = (client_thread == nullptr || parent->IsClientClosed());
@@ -261,8 +176,8 @@ Result KServerSession::SendReply() {
261 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); 176 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
262 177
263 auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); 178 auto* src_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress());
264 auto* dst_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); 179 auto* dst_msg_buffer = memory.GetPointer(client_message);
265 std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); 180 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
266 } else { 181 } else {
267 result = ResultSessionClosed; 182 result = ResultSessionClosed;
268 } 183 }
@@ -278,11 +193,30 @@ Result KServerSession::SendReply() {
278 193
279 // If there's a client thread, update it. 194 // If there's a client thread, update it.
280 if (client_thread != nullptr) { 195 if (client_thread != nullptr) {
281 // End the client thread's wait. 196 if (event != nullptr) {
282 KScopedSchedulerLock sl{kernel}; 197 // // Get the client process/page table.
198 // KProcess *client_process = client_thread->GetOwnerProcess();
199 // KPageTable *client_page_table = &client_process->PageTable();
200
201 // // If we need to, reply with an async error.
202 // if (R_FAILED(client_result)) {
203 // ReplyAsyncError(client_process, client_message, client_buffer_size,
204 // client_result);
205 // }
206
207 // // Unlock the client buffer.
208 // // NOTE: Nintendo does not check the result of this.
209 // client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size);
210
211 // Signal the event.
212 event->Signal();
213 } else {
214 // End the client thread's wait.
215 KScopedSchedulerLock sl{kernel};
283 216
284 if (!client_thread->IsTerminationRequested()) { 217 if (!client_thread->IsTerminationRequested()) {
285 client_thread->EndWait(client_result); 218 client_thread->EndWait(client_result);
219 }
286 } 220 }
287 } 221 }
288 222
@@ -291,10 +225,10 @@ Result KServerSession::SendReply() {
291 225
292Result KServerSession::ReceiveRequest() { 226Result KServerSession::ReceiveRequest() {
293 // Lock the session. 227 // Lock the session.
294 KScopedLightLock lk(m_lock); 228 KScopedLightLock lk{m_lock};
295 229
296 // Get the request and client thread. 230 // Get the request and client thread.
297 // KSessionRequest *request; 231 KSessionRequest* request;
298 KThread* client_thread; 232 KThread* client_thread;
299 233
300 { 234 {
@@ -304,35 +238,41 @@ Result KServerSession::ReceiveRequest() {
304 R_UNLESS(!parent->IsClientClosed(), ResultSessionClosed); 238 R_UNLESS(!parent->IsClientClosed(), ResultSessionClosed);
305 239
306 // Ensure we aren't already servicing a request. 240 // Ensure we aren't already servicing a request.
307 R_UNLESS(m_current_thread_request == nullptr, ResultNotFound); 241 R_UNLESS(m_current_request == nullptr, ResultNotFound);
308 242
309 // Ensure we have a request to service. 243 // Ensure we have a request to service.
310 R_UNLESS(!m_thread_request_list.empty(), ResultNotFound); 244 R_UNLESS(!m_request_list.empty(), ResultNotFound);
311 245
312 // Pop the first request from the list. 246 // Pop the first request from the list.
313 client_thread = m_thread_request_list.front(); 247 request = &m_request_list.front();
314 m_thread_request_list.pop_front(); 248 m_request_list.pop_front();
315 249
316 // Get the thread for the request. 250 // Get the thread for the request.
251 client_thread = request->GetThread();
317 R_UNLESS(client_thread != nullptr, ResultSessionClosed); 252 R_UNLESS(client_thread != nullptr, ResultSessionClosed);
318 253
319 // Open the client thread. 254 // Open the client thread.
320 client_thread->Open(); 255 client_thread->Open();
321 } 256 }
322 257
323 // SCOPE_EXIT({ client_thread->Close(); }); 258 SCOPE_EXIT({ client_thread->Close(); });
324 259
325 // Set the request as our current. 260 // Set the request as our current.
326 m_current_thread_request = client_thread; 261 m_current_request = request;
262
263 // Get the client address.
264 uintptr_t client_message = request->GetAddress();
265 size_t client_buffer_size = request->GetSize();
266 // bool recv_list_broken = false;
327 267
328 // Receive the message. 268 // Receive the message.
329 Core::Memory::Memory& memory{kernel.System().Memory()}; 269 Core::Memory::Memory& memory{kernel.System().Memory()};
330 KThread* server_thread{GetCurrentThreadPointer(kernel)}; 270 KThread* server_thread{GetCurrentThreadPointer(kernel)};
331 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess()); 271 UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
332 272
333 auto* src_msg_buffer = memory.GetPointer(client_thread->GetTLSAddress()); 273 auto* src_msg_buffer = memory.GetPointer(client_message);
334 auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress()); 274 auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTLSAddress());
335 std::memcpy(dst_msg_buffer, src_msg_buffer, MessageBufferSize); 275 std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
336 276
337 // We succeeded. 277 // We succeeded.
338 return ResultSuccess; 278 return ResultSuccess;
@@ -344,35 +284,34 @@ void KServerSession::CleanupRequests() {
344 // Clean up any pending requests. 284 // Clean up any pending requests.
345 while (true) { 285 while (true) {
346 // Get the next request. 286 // Get the next request.
347 // KSessionRequest *request = nullptr; 287 KSessionRequest* request = nullptr;
348 KThread* client_thread = nullptr;
349 { 288 {
350 KScopedSchedulerLock sl{kernel}; 289 KScopedSchedulerLock sl{kernel};
351 290
352 if (m_current_thread_request) { 291 if (m_current_request) {
353 // Choose the current request if we have one. 292 // Choose the current request if we have one.
354 client_thread = m_current_thread_request; 293 request = m_current_request;
355 m_current_thread_request = nullptr; 294 m_current_request = nullptr;
356 } else if (!m_thread_request_list.empty()) { 295 } else if (!m_request_list.empty()) {
357 // Pop the request from the front of the list. 296 // Pop the request from the front of the list.
358 client_thread = m_thread_request_list.front(); 297 request = &m_request_list.front();
359 m_thread_request_list.pop_front(); 298 m_request_list.pop_front();
360 } 299 }
361 } 300 }
362 301
363 // If there's no request, we're done. 302 // If there's no request, we're done.
364 if (client_thread == nullptr) { 303 if (request == nullptr) {
365 break; 304 break;
366 } 305 }
367 306
368 // Close a reference to the request once it's cleaned up. 307 // Close a reference to the request once it's cleaned up.
369 SCOPE_EXIT({ client_thread->Close(); }); 308 SCOPE_EXIT({ request->Close(); });
370 309
371 // Extract relevant information from the request. 310 // Extract relevant information from the request.
372 // const uintptr_t client_message = request->GetAddress(); 311 // const uintptr_t client_message = request->GetAddress();
373 // const size_t client_buffer_size = request->GetSize(); 312 // const size_t client_buffer_size = request->GetSize();
374 // KThread *client_thread = request->GetThread(); 313 KThread* client_thread = request->GetThread();
375 // KEvent *event = request->GetEvent(); 314 KEvent* event = request->GetEvent();
376 315
377 // KProcess *server_process = request->GetServerProcess(); 316 // KProcess *server_process = request->GetServerProcess();
378 // KProcess *client_process = (client_thread != nullptr) ? 317 // KProcess *client_process = (client_thread != nullptr) ?
@@ -385,11 +324,24 @@ void KServerSession::CleanupRequests() {
385 324
386 // If there's a client thread, update it. 325 // If there's a client thread, update it.
387 if (client_thread != nullptr) { 326 if (client_thread != nullptr) {
388 // End the client thread's wait. 327 if (event != nullptr) {
389 KScopedSchedulerLock sl{kernel}; 328 // // We need to reply async.
390 329 // ReplyAsyncError(client_process, client_message, client_buffer_size,
391 if (!client_thread->IsTerminationRequested()) { 330 // (R_SUCCEEDED(result) ? ResultSessionClosed : result));
392 client_thread->EndWait(ResultSessionClosed); 331
332 // // Unlock the client buffer.
333 // NOTE: Nintendo does not check the result of this.
334 // client_page_table->UnlockForIpcUserBuffer(client_message, client_buffer_size);
335
336 // Signal the event.
337 event->Signal();
338 } else {
339 // End the client thread's wait.
340 KScopedSchedulerLock sl{kernel};
341
342 if (!client_thread->IsTerminationRequested()) {
343 client_thread->EndWait(ResultSessionClosed);
344 }
393 } 345 }
394 } 346 }
395 } 347 }
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index 748d52826..188aef4af 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -12,6 +12,7 @@
12 12
13#include "core/hle/kernel/hle_ipc.h" 13#include "core/hle/kernel/hle_ipc.h"
14#include "core/hle/kernel/k_light_lock.h" 14#include "core/hle/kernel/k_light_lock.h"
15#include "core/hle/kernel/k_session_request.h"
15#include "core/hle/kernel/k_synchronization_object.h" 16#include "core/hle/kernel/k_synchronization_object.h"
16#include "core/hle/result.h" 17#include "core/hle/result.h"
17 18
@@ -57,44 +58,15 @@ public:
57 } 58 }
58 59
59 bool IsSignaled() const override; 60 bool IsSignaled() const override;
60
61 void OnClientClosed(); 61 void OnClientClosed();
62 62
63 void ClientConnected(SessionRequestHandlerPtr handler) {
64 if (manager) {
65 manager->SetSessionHandler(std::move(handler));
66 }
67 }
68
69 void ClientDisconnected() {
70 manager = nullptr;
71 }
72
73 /// Adds a new domain request handler to the collection of request handlers within
74 /// this ServerSession instance.
75 void AppendDomainHandler(SessionRequestHandlerPtr handler);
76
77 /// Retrieves the total number of domain request handlers that have been
78 /// appended to this ServerSession instance.
79 std::size_t NumDomainRequestHandlers() const;
80
81 /// Returns true if the session has been converted to a domain, otherwise False
82 bool IsDomain() const {
83 return manager && manager->IsDomain();
84 }
85
86 /// Converts the session to a domain at the end of the current command
87 void ConvertToDomain() {
88 convert_to_domain = true;
89 }
90
91 /// Gets the session request manager, which forwards requests to the underlying service 63 /// Gets the session request manager, which forwards requests to the underlying service
92 std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() { 64 std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() {
93 return manager; 65 return manager;
94 } 66 }
95 67
96 /// TODO: flesh these out to match the real kernel 68 /// TODO: flesh these out to match the real kernel
97 Result OnRequest(); 69 Result OnRequest(KSessionRequest* request);
98 Result SendReply(); 70 Result SendReply();
99 Result ReceiveRequest(); 71 Result ReceiveRequest();
100 72
@@ -108,10 +80,6 @@ private:
108 /// Completes a sync request from the emulated application. 80 /// Completes a sync request from the emulated application.
109 Result CompleteSyncRequest(HLERequestContext& context); 81 Result CompleteSyncRequest(HLERequestContext& context);
110 82
111 /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an
112 /// object handle.
113 Result HandleDomainSyncRequest(Kernel::HLERequestContext& context);
114
115 /// This session's HLE request handlers; if nullptr, this is not an HLE server 83 /// This session's HLE request handlers; if nullptr, this is not an HLE server
116 std::shared_ptr<SessionRequestManager> manager; 84 std::shared_ptr<SessionRequestManager> manager;
117 85
@@ -122,9 +90,8 @@ private:
122 KSession* parent{}; 90 KSession* parent{};
123 91
124 /// List of threads which are pending a reply. 92 /// List of threads which are pending a reply.
125 /// FIXME: KSessionRequest 93 boost::intrusive::list<KSessionRequest> m_request_list;
126 std::list<KThread*> m_thread_request_list; 94 KSessionRequest* m_current_request{};
127 KThread* m_current_thread_request{};
128 95
129 KLightLock m_lock; 96 KLightLock m_lock;
130}; 97};
diff --git a/src/core/hle/kernel/k_session_request.cpp b/src/core/hle/kernel/k_session_request.cpp
new file mode 100644
index 000000000..520da6aa7
--- /dev/null
+++ b/src/core/hle/kernel/k_session_request.cpp
@@ -0,0 +1,61 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/hle/kernel/k_page_buffer.h"
5#include "core/hle/kernel/k_session_request.h"
6
7namespace Kernel {
8
9Result KSessionRequest::SessionMappings::PushMap(VAddr client, VAddr server, size_t size,
10 KMemoryState state, size_t index) {
11 // At most 15 buffers of each type (4-bit descriptor counts).
12 ASSERT(index < ((1ul << 4) - 1) * 3);
13
14 // Get the mapping.
15 Mapping* mapping;
16 if (index < NumStaticMappings) {
17 mapping = &m_static_mappings[index];
18 } else {
19 // Allocate a page for the extra mappings.
20 if (m_mappings == nullptr) {
21 KPageBuffer* page_buffer = KPageBuffer::Allocate(kernel);
22 R_UNLESS(page_buffer != nullptr, ResultOutOfMemory);
23
24 m_mappings = reinterpret_cast<Mapping*>(page_buffer);
25 }
26
27 mapping = &m_mappings[index - NumStaticMappings];
28 }
29
30 // Set the mapping.
31 mapping->Set(client, server, size, state);
32
33 return ResultSuccess;
34}
35
36Result KSessionRequest::SessionMappings::PushSend(VAddr client, VAddr server, size_t size,
37 KMemoryState state) {
38 ASSERT(m_num_recv == 0);
39 ASSERT(m_num_exch == 0);
40 return this->PushMap(client, server, size, state, m_num_send++);
41}
42
43Result KSessionRequest::SessionMappings::PushReceive(VAddr client, VAddr server, size_t size,
44 KMemoryState state) {
45 ASSERT(m_num_exch == 0);
46 return this->PushMap(client, server, size, state, m_num_send + m_num_recv++);
47}
48
49Result KSessionRequest::SessionMappings::PushExchange(VAddr client, VAddr server, size_t size,
50 KMemoryState state) {
51 return this->PushMap(client, server, size, state, m_num_send + m_num_recv + m_num_exch++);
52}
53
54void KSessionRequest::SessionMappings::Finalize() {
55 if (m_mappings) {
56 KPageBuffer::Free(kernel, reinterpret_cast<KPageBuffer*>(m_mappings));
57 m_mappings = nullptr;
58 }
59}
60
61} // namespace Kernel
diff --git a/src/core/hle/kernel/k_session_request.h b/src/core/hle/kernel/k_session_request.h
new file mode 100644
index 000000000..e5558bc2c
--- /dev/null
+++ b/src/core/hle/kernel/k_session_request.h
@@ -0,0 +1,306 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7
8#include "core/hle/kernel/k_auto_object.h"
9#include "core/hle/kernel/k_event.h"
10#include "core/hle/kernel/k_memory_block.h"
11#include "core/hle/kernel/k_process.h"
12#include "core/hle/kernel/k_thread.h"
13#include "core/hle/kernel/slab_helpers.h"
14
15namespace Kernel {
16
17class KSessionRequest final : public KSlabAllocated<KSessionRequest>,
18 public KAutoObject,
19 public boost::intrusive::list_base_hook<> {
20 KERNEL_AUTOOBJECT_TRAITS(KSessionRequest, KAutoObject);
21
22public:
23 class SessionMappings {
24 private:
25 static constexpr size_t NumStaticMappings = 8;
26
27 class Mapping {
28 public:
29 constexpr void Set(VAddr c, VAddr s, size_t sz, KMemoryState st) {
30 m_client_address = c;
31 m_server_address = s;
32 m_size = sz;
33 m_state = st;
34 }
35
36 constexpr VAddr GetClientAddress() const {
37 return m_client_address;
38 }
39 constexpr VAddr GetServerAddress() const {
40 return m_server_address;
41 }
42 constexpr size_t GetSize() const {
43 return m_size;
44 }
45 constexpr KMemoryState GetMemoryState() const {
46 return m_state;
47 }
48
49 private:
50 VAddr m_client_address;
51 VAddr m_server_address;
52 size_t m_size;
53 KMemoryState m_state;
54 };
55
56 public:
57 explicit SessionMappings(KernelCore& kernel_) : kernel(kernel_) {}
58
59 void Initialize() {}
60 void Finalize();
61
62 size_t GetSendCount() const {
63 return m_num_send;
64 }
65 size_t GetReceiveCount() const {
66 return m_num_recv;
67 }
68 size_t GetExchangeCount() const {
69 return m_num_exch;
70 }
71
72 Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state);
73 Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state);
74 Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state);
75
76 VAddr GetSendClientAddress(size_t i) const {
77 return GetSendMapping(i).GetClientAddress();
78 }
79 VAddr GetSendServerAddress(size_t i) const {
80 return GetSendMapping(i).GetServerAddress();
81 }
82 size_t GetSendSize(size_t i) const {
83 return GetSendMapping(i).GetSize();
84 }
85 KMemoryState GetSendMemoryState(size_t i) const {
86 return GetSendMapping(i).GetMemoryState();
87 }
88
89 VAddr GetReceiveClientAddress(size_t i) const {
90 return GetReceiveMapping(i).GetClientAddress();
91 }
92 VAddr GetReceiveServerAddress(size_t i) const {
93 return GetReceiveMapping(i).GetServerAddress();
94 }
95 size_t GetReceiveSize(size_t i) const {
96 return GetReceiveMapping(i).GetSize();
97 }
98 KMemoryState GetReceiveMemoryState(size_t i) const {
99 return GetReceiveMapping(i).GetMemoryState();
100 }
101
102 VAddr GetExchangeClientAddress(size_t i) const {
103 return GetExchangeMapping(i).GetClientAddress();
104 }
105 VAddr GetExchangeServerAddress(size_t i) const {
106 return GetExchangeMapping(i).GetServerAddress();
107 }
108 size_t GetExchangeSize(size_t i) const {
109 return GetExchangeMapping(i).GetSize();
110 }
111 KMemoryState GetExchangeMemoryState(size_t i) const {
112 return GetExchangeMapping(i).GetMemoryState();
113 }
114
115 private:
116 Result PushMap(VAddr client, VAddr server, size_t size, KMemoryState state, size_t index);
117
118 const Mapping& GetSendMapping(size_t i) const {
119 ASSERT(i < m_num_send);
120
121 const size_t index = i;
122 if (index < NumStaticMappings) {
123 return m_static_mappings[index];
124 } else {
125 return m_mappings[index - NumStaticMappings];
126 }
127 }
128
129 const Mapping& GetReceiveMapping(size_t i) const {
130 ASSERT(i < m_num_recv);
131
132 const size_t index = m_num_send + i;
133 if (index < NumStaticMappings) {
134 return m_static_mappings[index];
135 } else {
136 return m_mappings[index - NumStaticMappings];
137 }
138 }
139
140 const Mapping& GetExchangeMapping(size_t i) const {
141 ASSERT(i < m_num_exch);
142
143 const size_t index = m_num_send + m_num_recv + i;
144 if (index < NumStaticMappings) {
145 return m_static_mappings[index];
146 } else {
147 return m_mappings[index - NumStaticMappings];
148 }
149 }
150
151 private:
152 KernelCore& kernel;
153 std::array<Mapping, NumStaticMappings> m_static_mappings;
154 Mapping* m_mappings{};
155 u8 m_num_send{};
156 u8 m_num_recv{};
157 u8 m_num_exch{};
158 };
159
160public:
161 explicit KSessionRequest(KernelCore& kernel_) : KAutoObject(kernel_), m_mappings(kernel_) {}
162
163 static KSessionRequest* Create(KernelCore& kernel) {
164 KSessionRequest* req = KSessionRequest::Allocate(kernel);
165 if (req != nullptr) [[likely]] {
166 KAutoObject::Create(req);
167 }
168 return req;
169 }
170
171 void Destroy() override {
172 this->Finalize();
173 KSessionRequest::Free(kernel, this);
174 }
175
176 void Initialize(KEvent* event, uintptr_t address, size_t size) {
177 m_mappings.Initialize();
178
179 m_thread = GetCurrentThreadPointer(kernel);
180 m_event = event;
181 m_address = address;
182 m_size = size;
183
184 m_thread->Open();
185 if (m_event != nullptr) {
186 m_event->Open();
187 }
188 }
189
190 static void PostDestroy(uintptr_t arg) {}
191
192 KThread* GetThread() const {
193 return m_thread;
194 }
195 KEvent* GetEvent() const {
196 return m_event;
197 }
198 uintptr_t GetAddress() const {
199 return m_address;
200 }
201 size_t GetSize() const {
202 return m_size;
203 }
204 KProcess* GetServerProcess() const {
205 return m_server;
206 }
207
208 void SetServerProcess(KProcess* process) {
209 m_server = process;
210 m_server->Open();
211 }
212
213 void ClearThread() {
214 m_thread = nullptr;
215 }
216 void ClearEvent() {
217 m_event = nullptr;
218 }
219
220 size_t GetSendCount() const {
221 return m_mappings.GetSendCount();
222 }
223 size_t GetReceiveCount() const {
224 return m_mappings.GetReceiveCount();
225 }
226 size_t GetExchangeCount() const {
227 return m_mappings.GetExchangeCount();
228 }
229
230 Result PushSend(VAddr client, VAddr server, size_t size, KMemoryState state) {
231 return m_mappings.PushSend(client, server, size, state);
232 }
233
234 Result PushReceive(VAddr client, VAddr server, size_t size, KMemoryState state) {
235 return m_mappings.PushReceive(client, server, size, state);
236 }
237
238 Result PushExchange(VAddr client, VAddr server, size_t size, KMemoryState state) {
239 return m_mappings.PushExchange(client, server, size, state);
240 }
241
242 VAddr GetSendClientAddress(size_t i) const {
243 return m_mappings.GetSendClientAddress(i);
244 }
245 VAddr GetSendServerAddress(size_t i) const {
246 return m_mappings.GetSendServerAddress(i);
247 }
248 size_t GetSendSize(size_t i) const {
249 return m_mappings.GetSendSize(i);
250 }
251 KMemoryState GetSendMemoryState(size_t i) const {
252 return m_mappings.GetSendMemoryState(i);
253 }
254
255 VAddr GetReceiveClientAddress(size_t i) const {
256 return m_mappings.GetReceiveClientAddress(i);
257 }
258 VAddr GetReceiveServerAddress(size_t i) const {
259 return m_mappings.GetReceiveServerAddress(i);
260 }
261 size_t GetReceiveSize(size_t i) const {
262 return m_mappings.GetReceiveSize(i);
263 }
264 KMemoryState GetReceiveMemoryState(size_t i) const {
265 return m_mappings.GetReceiveMemoryState(i);
266 }
267
268 VAddr GetExchangeClientAddress(size_t i) const {
269 return m_mappings.GetExchangeClientAddress(i);
270 }
271 VAddr GetExchangeServerAddress(size_t i) const {
272 return m_mappings.GetExchangeServerAddress(i);
273 }
274 size_t GetExchangeSize(size_t i) const {
275 return m_mappings.GetExchangeSize(i);
276 }
277 KMemoryState GetExchangeMemoryState(size_t i) const {
278 return m_mappings.GetExchangeMemoryState(i);
279 }
280
281private:
282 // NOTE: This is public and virtual in Nintendo's kernel.
283 void Finalize() override {
284 m_mappings.Finalize();
285
286 if (m_thread) {
287 m_thread->Close();
288 }
289 if (m_event) {
290 m_event->Close();
291 }
292 if (m_server) {
293 m_server->Close();
294 }
295 }
296
297private:
298 SessionMappings m_mappings;
299 KThread* m_thread{};
300 KProcess* m_server{};
301 KEvent* m_event{};
302 uintptr_t m_address{};
303 size_t m_size{};
304};
305
306} // namespace Kernel
diff --git a/src/core/hle/kernel/k_shared_memory_info.h b/src/core/hle/kernel/k_shared_memory_info.h
index e43db8515..2bb6b6d08 100644
--- a/src/core/hle/kernel/k_shared_memory_info.h
+++ b/src/core/hle/kernel/k_shared_memory_info.h
@@ -15,7 +15,8 @@ class KSharedMemoryInfo final : public KSlabAllocated<KSharedMemoryInfo>,
15 public boost::intrusive::list_base_hook<> { 15 public boost::intrusive::list_base_hook<> {
16 16
17public: 17public:
18 explicit KSharedMemoryInfo() = default; 18 explicit KSharedMemoryInfo(KernelCore&) {}
19 KSharedMemoryInfo() = default;
19 20
20 constexpr void Initialize(KSharedMemory* shmem) { 21 constexpr void Initialize(KSharedMemory* shmem) {
21 shared_memory = shmem; 22 shared_memory = shmem;
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index b7bfcdce3..cc88d08f0 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -148,7 +148,9 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack
148 physical_affinity_mask.SetAffinity(phys_core, true); 148 physical_affinity_mask.SetAffinity(phys_core, true);
149 149
150 // Set the thread state. 150 // Set the thread state.
151 thread_state = (type == ThreadType::Main) ? ThreadState::Runnable : ThreadState::Initialized; 151 thread_state = (type == ThreadType::Main || type == ThreadType::Dummy)
152 ? ThreadState::Runnable
153 : ThreadState::Initialized;
152 154
153 // Set TLS address. 155 // Set TLS address.
154 tls_address = 0; 156 tls_address = 0;
@@ -1174,30 +1176,31 @@ Result KThread::Sleep(s64 timeout) {
1174 R_SUCCEED(); 1176 R_SUCCEED();
1175} 1177}
1176 1178
1177void KThread::IfDummyThreadTryWait() { 1179void KThread::RequestDummyThreadWait() {
1178 if (!IsDummyThread()) { 1180 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel));
1179 return; 1181 ASSERT(this->IsDummyThread());
1180 } 1182
1183 // We will block when the scheduler lock is released.
1184 dummy_thread_runnable.store(false);
1185}
1181 1186
1182 if (GetState() != ThreadState::Waiting) { 1187void KThread::DummyThreadBeginWait() {
1188 if (!this->IsDummyThread() || kernel.IsPhantomModeForSingleCore()) {
1189 // Occurs in single core mode.
1183 return; 1190 return;
1184 } 1191 }
1185 1192
1186 ASSERT(!kernel.IsPhantomModeForSingleCore()); 1193 // Block until runnable is no longer false.
1187 1194 dummy_thread_runnable.wait(false);
1188 // Block until we are no longer waiting.
1189 std::unique_lock lk(dummy_wait_lock);
1190 dummy_wait_cv.wait(
1191 lk, [&] { return GetState() != ThreadState::Waiting || kernel.IsShuttingDown(); });
1192} 1195}
1193 1196
1194void KThread::IfDummyThreadEndWait() { 1197void KThread::DummyThreadEndWait() {
1195 if (!IsDummyThread()) { 1198 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel));
1196 return; 1199 ASSERT(this->IsDummyThread());
1197 }
1198 1200
1199 // Wake up the waiting thread. 1201 // Wake up the waiting thread.
1200 dummy_wait_cv.notify_one(); 1202 dummy_thread_runnable.store(true);
1203 dummy_thread_runnable.notify_one();
1201} 1204}
1202 1205
1203void KThread::BeginWait(KThreadQueue* queue) { 1206void KThread::BeginWait(KThreadQueue* queue) {
@@ -1231,9 +1234,6 @@ void KThread::EndWait(Result wait_result_) {
1231 } 1234 }
1232 1235
1233 wait_queue->EndWait(this, wait_result_); 1236 wait_queue->EndWait(this, wait_result_);
1234
1235 // Special case for dummy threads to wakeup if necessary.
1236 IfDummyThreadEndWait();
1237 } 1237 }
1238} 1238}
1239 1239
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index e2a27d603..30aa10c9a 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -643,8 +643,9 @@ public:
643 // therefore will not block on guest kernel synchronization primitives. These methods handle 643 // therefore will not block on guest kernel synchronization primitives. These methods handle
644 // blocking as needed. 644 // blocking as needed.
645 645
646 void IfDummyThreadTryWait(); 646 void RequestDummyThreadWait();
647 void IfDummyThreadEndWait(); 647 void DummyThreadBeginWait();
648 void DummyThreadEndWait();
648 649
649 [[nodiscard]] uintptr_t GetArgument() const { 650 [[nodiscard]] uintptr_t GetArgument() const {
650 return argument; 651 return argument;
@@ -777,8 +778,7 @@ private:
777 bool is_single_core{}; 778 bool is_single_core{};
778 ThreadType thread_type{}; 779 ThreadType thread_type{};
779 StepState step_state{}; 780 StepState step_state{};
780 std::mutex dummy_wait_lock; 781 std::atomic<bool> dummy_thread_runnable{true};
781 std::condition_variable dummy_wait_cv;
782 782
783 // For debugging 783 // For debugging
784 std::vector<KSynchronizationObject*> wait_objects_for_debugging; 784 std::vector<KSynchronizationObject*> wait_objects_for_debugging;
diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h
index 0a7f22680..5d466ace7 100644
--- a/src/core/hle/kernel/k_thread_local_page.h
+++ b/src/core/hle/kernel/k_thread_local_page.h
@@ -26,7 +26,7 @@ public:
26 static_assert(RegionsPerPage > 0); 26 static_assert(RegionsPerPage > 0);
27 27
28public: 28public:
29 constexpr explicit KThreadLocalPage(VAddr addr = {}) : m_virt_addr(addr) { 29 constexpr explicit KThreadLocalPage(KernelCore&, VAddr addr = {}) : m_virt_addr(addr) {
30 m_is_region_free.fill(true); 30 m_is_region_free.fill(true);
31 } 31 }
32 32
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index eed2dc9f3..fdc774e30 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -48,8 +48,8 @@ namespace Kernel {
48 48
49struct KernelCore::Impl { 49struct KernelCore::Impl {
50 explicit Impl(Core::System& system_, KernelCore& kernel_) 50 explicit Impl(Core::System& system_, KernelCore& kernel_)
51 : time_manager{system_}, 51 : time_manager{system_}, service_threads_manager{1, "ServiceThreadsManager"},
52 service_threads_manager{1, "ServiceThreadsManager"}, system{system_} {} 52 service_thread_barrier{2}, system{system_} {}
53 53
54 void SetMulticore(bool is_multi) { 54 void SetMulticore(bool is_multi) {
55 is_multicore = is_multi; 55 is_multicore = is_multi;
@@ -737,7 +737,12 @@ struct KernelCore::Impl {
737 } 737 }
738 738
739 void ClearServiceThreads() { 739 void ClearServiceThreads() {
740 service_threads_manager.QueueWork([this]() { service_threads.clear(); }); 740 service_threads_manager.QueueWork([this] {
741 service_threads.clear();
742 default_service_thread.reset();
743 service_thread_barrier.Sync();
744 });
745 service_thread_barrier.Sync();
741 } 746 }
742 747
743 std::mutex server_objects_lock; 748 std::mutex server_objects_lock;
@@ -802,6 +807,7 @@ struct KernelCore::Impl {
802 std::unordered_set<std::shared_ptr<ServiceThread>> service_threads; 807 std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
803 std::weak_ptr<ServiceThread> default_service_thread; 808 std::weak_ptr<ServiceThread> default_service_thread;
804 Common::ThreadWorker service_threads_manager; 809 Common::ThreadWorker service_threads_manager;
810 Common::Barrier service_thread_barrier;
805 811
806 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; 812 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
807 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 813 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 6eded9539..266be2bc4 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -47,6 +47,7 @@ class KResourceLimit;
47class KScheduler; 47class KScheduler;
48class KServerSession; 48class KServerSession;
49class KSession; 49class KSession;
50class KSessionRequest;
50class KSharedMemory; 51class KSharedMemory;
51class KSharedMemoryInfo; 52class KSharedMemoryInfo;
52class KThread; 53class KThread;
@@ -360,6 +361,8 @@ public:
360 return slab_heap_container->page_buffer; 361 return slab_heap_container->page_buffer;
361 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { 362 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
362 return slab_heap_container->thread_local_page; 363 return slab_heap_container->thread_local_page;
364 } else if constexpr (std::is_same_v<T, KSessionRequest>) {
365 return slab_heap_container->session_request;
363 } 366 }
364 } 367 }
365 368
@@ -422,6 +425,7 @@ private:
422 KSlabHeap<KCodeMemory> code_memory; 425 KSlabHeap<KCodeMemory> code_memory;
423 KSlabHeap<KPageBuffer> page_buffer; 426 KSlabHeap<KPageBuffer> page_buffer;
424 KSlabHeap<KThreadLocalPage> thread_local_page; 427 KSlabHeap<KThreadLocalPage> thread_local_page;
428 KSlabHeap<KSessionRequest> session_request;
425 }; 429 };
426 430
427 std::unique_ptr<SlabHeapContainer> slab_heap_container; 431 std::unique_ptr<SlabHeapContainer> slab_heap_container;
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h
index 299a981a8..06b51e919 100644
--- a/src/core/hle/kernel/slab_helpers.h
+++ b/src/core/hle/kernel/slab_helpers.h
@@ -24,7 +24,7 @@ public:
24 } 24 }
25 25
26 static Derived* Allocate(KernelCore& kernel) { 26 static Derived* Allocate(KernelCore& kernel) {
27 return kernel.SlabHeap<Derived>().Allocate(); 27 return kernel.SlabHeap<Derived>().Allocate(kernel);
28 } 28 }
29 29
30 static void Free(KernelCore& kernel, Derived* obj) { 30 static void Free(KernelCore& kernel, Derived* obj) {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b07ae3f02..4aca5b27d 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -751,8 +751,8 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
751 } 751 }
752 752
753 system.GetReporter().SaveSvcBreakReport( 753 system.GetReporter().SaveSvcBreakReport(
754 static_cast<u32>(break_reason.break_type.Value()), break_reason.signal_debugger, info1, 754 static_cast<u32>(break_reason.break_type.Value()), break_reason.signal_debugger.As<bool>(),
755 info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); 755 info1, info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt);
756 756
757 if (!break_reason.signal_debugger) { 757 if (!break_reason.signal_debugger) {
758 LOG_CRITICAL( 758 LOG_CRITICAL(
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index bb838e285..85a3f0802 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -512,10 +512,11 @@ protected:
512 512
513class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { 513class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
514public: 514public:
515 explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_) 515 explicit IManagerForApplication(Core::System& system_,
516 const std::shared_ptr<ProfileManager>& profile_manager_)
516 : ServiceFramework{system_, "IManagerForApplication"}, 517 : ServiceFramework{system_, "IManagerForApplication"},
517 ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)}, 518 ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)},
518 user_id{user_id_} { 519 profile_manager{profile_manager_} {
519 // clang-format off 520 // clang-format off
520 static const FunctionInfo functions[] = { 521 static const FunctionInfo functions[] = {
521 {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, 522 {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
@@ -545,7 +546,7 @@ private:
545 546
546 IPC::ResponseBuilder rb{ctx, 4}; 547 IPC::ResponseBuilder rb{ctx, 4};
547 rb.Push(ResultSuccess); 548 rb.Push(ResultSuccess);
548 rb.PushRaw<u64>(user_id.Hash()); 549 rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash());
549 } 550 }
550 551
551 void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) { 552 void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) {
@@ -575,17 +576,20 @@ private:
575 576
576 IPC::ResponseBuilder rb{ctx, 4}; 577 IPC::ResponseBuilder rb{ctx, 4};
577 rb.Push(ResultSuccess); 578 rb.Push(ResultSuccess);
578 rb.PushRaw<u64>(user_id.Hash()); 579 rb.PushRaw<u64>(profile_manager->GetLastOpenedUser().Hash());
579 } 580 }
580 581
581 void StoreOpenContext(Kernel::HLERequestContext& ctx) { 582 void StoreOpenContext(Kernel::HLERequestContext& ctx) {
582 LOG_WARNING(Service_ACC, "(STUBBED) called"); 583 LOG_DEBUG(Service_ACC, "called");
584
585 profile_manager->StoreOpenedUsers();
586
583 IPC::ResponseBuilder rb{ctx, 2}; 587 IPC::ResponseBuilder rb{ctx, 2};
584 rb.Push(ResultSuccess); 588 rb.Push(ResultSuccess);
585 } 589 }
586 590
587 std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{}; 591 std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{};
588 Common::UUID user_id{}; 592 std::shared_ptr<ProfileManager> profile_manager;
589}; 593};
590 594
591// 6.0.0+ 595// 6.0.0+
@@ -790,7 +794,7 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo
790 LOG_DEBUG(Service_ACC, "called"); 794 LOG_DEBUG(Service_ACC, "called");
791 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 795 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
792 rb.Push(ResultSuccess); 796 rb.Push(ResultSuccess);
793 rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser()); 797 rb.PushIpcInterface<IManagerForApplication>(system, profile_manager);
794} 798}
795 799
796void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) { 800void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) {
@@ -849,22 +853,10 @@ void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) {
849 rb.Push(ResultSuccess); 853 rb.Push(ResultSuccess);
850} 854}
851 855
852void Module::Interface::LoadOpenContext(Kernel::HLERequestContext& ctx) {
853 LOG_WARNING(Service_ACC, "(STUBBED) called");
854
855 // This is similar to GetBaasAccountManagerForApplication
856 // This command is used concurrently with ListOpenContextStoredUsers
857 // TODO: Find the differences between this and GetBaasAccountManagerForApplication
858 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
859 rb.Push(ResultSuccess);
860 rb.PushIpcInterface<IManagerForApplication>(system, profile_manager->GetLastOpenedUser());
861}
862
863void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) { 856void Module::Interface::ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx) {
864 LOG_WARNING(Service_ACC, "(STUBBED) called"); 857 LOG_DEBUG(Service_ACC, "called");
865 858
866 // TODO(ogniK): Handle open contexts 859 ctx.WriteBuffer(profile_manager->GetStoredOpenedUsers());
867 ctx.WriteBuffer(profile_manager->GetOpenUsers());
868 IPC::ResponseBuilder rb{ctx, 2}; 860 IPC::ResponseBuilder rb{ctx, 2};
869 rb.Push(ResultSuccess); 861 rb.Push(ResultSuccess);
870} 862}
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 1621e7c0a..9411b0b92 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -35,7 +35,6 @@ public:
35 void InitializeApplicationInfoV2(Kernel::HLERequestContext& ctx); 35 void InitializeApplicationInfoV2(Kernel::HLERequestContext& ctx);
36 void GetProfileEditor(Kernel::HLERequestContext& ctx); 36 void GetProfileEditor(Kernel::HLERequestContext& ctx);
37 void ListQualifiedUsers(Kernel::HLERequestContext& ctx); 37 void ListQualifiedUsers(Kernel::HLERequestContext& ctx);
38 void LoadOpenContext(Kernel::HLERequestContext& ctx);
39 void ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx); 38 void ListOpenContextStoredUsers(Kernel::HLERequestContext& ctx);
40 void StoreSaveDataThumbnailApplication(Kernel::HLERequestContext& ctx); 39 void StoreSaveDataThumbnailApplication(Kernel::HLERequestContext& ctx);
41 void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx); 40 void StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 65023b8c2..54844bfe7 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -28,7 +28,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager>
28 {110, &ACC_U0::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"}, 28 {110, &ACC_U0::StoreSaveDataThumbnailApplication, "StoreSaveDataThumbnail"},
29 {111, nullptr, "ClearSaveDataThumbnail"}, 29 {111, nullptr, "ClearSaveDataThumbnail"},
30 {120, nullptr, "CreateGuestLoginRequest"}, 30 {120, nullptr, "CreateGuestLoginRequest"},
31 {130, &ACC_U0::LoadOpenContext, "LoadOpenContext"}, // 5.0.0+ 31 {130, nullptr, "LoadOpenContext"}, // 5.0.0+
32 {131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+ 32 {131, &ACC_U0::ListOpenContextStoredUsers, "ListOpenContextStoredUsers"}, // 6.0.0+
33 {140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+ 33 {140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
34 {141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ 34 {141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index a58da4d5f..481e0d141 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -261,6 +261,31 @@ UUID ProfileManager::GetLastOpenedUser() const {
261 return last_opened_user; 261 return last_opened_user;
262} 262}
263 263
264/// Gets the list of stored opened users.
265UserIDArray ProfileManager::GetStoredOpenedUsers() const {
266 UserIDArray output{};
267 std::ranges::transform(stored_opened_profiles, output.begin(), [](const ProfileInfo& p) {
268 if (p.is_open)
269 return p.user_uuid;
270 return Common::InvalidUUID;
271 });
272 std::stable_partition(output.begin(), output.end(),
273 [](const UUID& uuid) { return uuid.IsValid(); });
274 return output;
275}
276
277/// Captures the opened users, which can be queried across process launches with
278/// ListOpenContextStoredUsers.
279void ProfileManager::StoreOpenedUsers() {
280 size_t profile_index{};
281 stored_opened_profiles = {};
282 std::for_each(profiles.begin(), profiles.end(), [&](const auto& profile) {
283 if (profile.is_open) {
284 stored_opened_profiles[profile_index++] = profile;
285 }
286 });
287}
288
264/// Return the users profile base and the unknown arbitary data. 289/// Return the users profile base and the unknown arbitary data.
265bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile, 290bool ProfileManager::GetProfileBaseAndData(std::optional<std::size_t> index, ProfileBase& profile,
266 UserData& data) const { 291 UserData& data) const {
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 135f7d0d5..993a5a57a 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -86,6 +86,8 @@ public:
86 UserIDArray GetOpenUsers() const; 86 UserIDArray GetOpenUsers() const;
87 UserIDArray GetAllUsers() const; 87 UserIDArray GetAllUsers() const;
88 Common::UUID GetLastOpenedUser() const; 88 Common::UUID GetLastOpenedUser() const;
89 UserIDArray GetStoredOpenedUsers() const;
90 void StoreOpenedUsers();
89 91
90 bool CanSystemRegisterUser() const; 92 bool CanSystemRegisterUser() const;
91 93
@@ -101,6 +103,7 @@ private:
101 bool RemoveProfileAtIndex(std::size_t index); 103 bool RemoveProfileAtIndex(std::size_t index);
102 104
103 std::array<ProfileInfo, MAX_USERS> profiles{}; 105 std::array<ProfileInfo, MAX_USERS> profiles{};
106 std::array<ProfileInfo, MAX_USERS> stored_opened_profiles{};
104 std::size_t user_count{}; 107 std::size_t user_count{};
105 Common::UUID last_opened_user{}; 108 Common::UUID last_opened_user{};
106}; 109};
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index e55233054..8ea7fd760 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -299,7 +299,7 @@ ISelfController::ISelfController(Core::System& system_, NVFlinger::NVFlinger& nv
299 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"}, 299 {100, &ISelfController::SetAlbumImageTakenNotificationEnabled, "SetAlbumImageTakenNotificationEnabled"},
300 {110, nullptr, "SetApplicationAlbumUserData"}, 300 {110, nullptr, "SetApplicationAlbumUserData"},
301 {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"}, 301 {120, &ISelfController::SaveCurrentScreenshot, "SaveCurrentScreenshot"},
302 {130, nullptr, "SetRecordVolumeMuted"}, 302 {130, &ISelfController::SetRecordVolumeMuted, "SetRecordVolumeMuted"},
303 {1000, nullptr, "GetDebugStorageChannel"}, 303 {1000, nullptr, "GetDebugStorageChannel"},
304 }; 304 };
305 // clang-format on 305 // clang-format on
@@ -597,6 +597,17 @@ void ISelfController::SaveCurrentScreenshot(Kernel::HLERequestContext& ctx) {
597 rb.Push(ResultSuccess); 597 rb.Push(ResultSuccess);
598} 598}
599 599
600void ISelfController::SetRecordVolumeMuted(Kernel::HLERequestContext& ctx) {
601 IPC::RequestParser rp{ctx};
602
603 const auto is_record_volume_muted = rp.Pop<bool>();
604
605 LOG_WARNING(Service_AM, "(STUBBED) called. is_record_volume_muted={}", is_record_volume_muted);
606
607 IPC::ResponseBuilder rb{ctx, 2};
608 rb.Push(ResultSuccess);
609}
610
600AppletMessageQueue::AppletMessageQueue(Core::System& system) 611AppletMessageQueue::AppletMessageQueue(Core::System& system)
601 : service_context{system, "AppletMessageQueue"} { 612 : service_context{system, "AppletMessageQueue"} {
602 on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived"); 613 on_new_message = service_context.CreateEvent("AMMessageQueue:OnMessageReceived");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index bb75c6281..a0fbfcfc5 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -182,6 +182,7 @@ private:
182 void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); 182 void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx);
183 void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx); 183 void SetAlbumImageTakenNotificationEnabled(Kernel::HLERequestContext& ctx);
184 void SaveCurrentScreenshot(Kernel::HLERequestContext& ctx); 184 void SaveCurrentScreenshot(Kernel::HLERequestContext& ctx);
185 void SetRecordVolumeMuted(Kernel::HLERequestContext& ctx);
185 186
186 enum class ScreenshotPermission : u32 { 187 enum class ScreenshotPermission : u32 {
187 Inherit = 0, 188 Inherit = 0,
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index e78a57657..12c6a5b1a 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -164,7 +164,7 @@ protected:
164 u32_le size; 164 u32_le size;
165 u32_le library_version; 165 u32_le library_version;
166 u32_le theme_color; 166 u32_le theme_color;
167 u8 play_startup_sound; 167 bool play_startup_sound;
168 u64_le system_tick; 168 u64_le system_tick;
169 }; 169 };
170 static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size."); 170 static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
index 4a2ae5f88..5abf22ba4 100644
--- a/src/core/hle/service/audio/audctl.cpp
+++ b/src/core/hle/service/audio/audctl.cpp
@@ -45,9 +45,25 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
45 {32, nullptr, "GetActiveOutputTarget"}, 45 {32, nullptr, "GetActiveOutputTarget"},
46 {33, nullptr, "GetTargetDeviceInfo"}, 46 {33, nullptr, "GetTargetDeviceInfo"},
47 {34, nullptr, "AcquireTargetNotification"}, 47 {34, nullptr, "AcquireTargetNotification"},
48 {35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
49 {36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
50 {37, nullptr, "SetHearingProtectionSafeguardEnabled"},
51 {38, nullptr, "IsHearingProtectionSafeguardEnabled"},
52 {39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
53 {40, nullptr, "GetSystemInformationForDebug"},
54 {41, nullptr, "SetVolumeButtonLongPressTime"},
55 {42, nullptr, "SetNativeVolumeForDebug"},
48 {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"}, 56 {10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
49 {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"}, 57 {10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
50 {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"}, 58 {10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
59 {10100, nullptr, "GetAudioVolumeDataForPlayReport"},
60 {10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"},
61 {10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
62 {10103, nullptr, "GetAudioOutputTargetForPlayReport"},
63 {10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
64 {10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
65 {10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
66 {50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
51 }; 67 };
52 // clang-format on 68 // clang-format on
53 69
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 48a9a73a0..608925dfc 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -17,7 +17,7 @@ using namespace AudioCore::AudioIn;
17class IAudioIn final : public ServiceFramework<IAudioIn> { 17class IAudioIn final : public ServiceFramework<IAudioIn> {
18public: 18public:
19 explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id, 19 explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
20 std::string& device_name, const AudioInParameter& in_params, u32 handle, 20 const std::string& device_name, const AudioInParameter& in_params, u32 handle,
21 u64 applet_resource_user_id) 21 u64 applet_resource_user_id)
22 : ServiceFramework{system_, "IAudioIn"}, 22 : ServiceFramework{system_, "IAudioIn"},
23 service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")}, 23 service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")},
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 49c092301..122290c6a 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -24,7 +24,7 @@ using namespace AudioCore::AudioOut;
24class IAudioOut final : public ServiceFramework<IAudioOut> { 24class IAudioOut final : public ServiceFramework<IAudioOut> {
25public: 25public:
26 explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, 26 explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager,
27 size_t session_id, std::string& device_name, 27 size_t session_id, const std::string& device_name,
28 const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) 28 const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id)
29 : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew}, 29 : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew},
30 service_context{system_, "IAudioOut"}, event{service_context.CreateEvent( 30 service_context{system_, "IAudioOut"}, event{service_context.CreateEvent(
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 60c30cd5b..13423dca6 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -52,6 +52,8 @@ public:
52 {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, 52 {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
53 {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"}, 53 {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
54 {11, nullptr, "ExecuteAudioRendererRendering"}, 54 {11, nullptr, "ExecuteAudioRendererRendering"},
55 {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
56 {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
55 }; 57 };
56 // clang-format on 58 // clang-format on
57 RegisterHandlers(functions); 59 RegisterHandlers(functions);
@@ -205,6 +207,30 @@ private:
205 LOG_DEBUG(Service_Audio, "called"); 207 LOG_DEBUG(Service_Audio, "called");
206 } 208 }
207 209
210 void SetVoiceDropParameter(Kernel::HLERequestContext& ctx) {
211 LOG_DEBUG(Service_Audio, "called");
212
213 IPC::RequestParser rp{ctx};
214 auto voice_drop_param{rp.Pop<f32>()};
215
216 auto& system_ = impl->GetSystem();
217 system_.SetVoiceDropParameter(voice_drop_param);
218
219 IPC::ResponseBuilder rb{ctx, 2};
220 rb.Push(ResultSuccess);
221 }
222
223 void GetVoiceDropParameter(Kernel::HLERequestContext& ctx) {
224 LOG_DEBUG(Service_Audio, "called");
225
226 auto& system_ = impl->GetSystem();
227 auto voice_drop_param{system_.GetVoiceDropParameter()};
228
229 IPC::ResponseBuilder rb{ctx, 3};
230 rb.Push(ResultSuccess);
231 rb.Push(voice_drop_param);
232 }
233
208 KernelHelpers::ServiceContext service_context; 234 KernelHelpers::ServiceContext service_context;
209 Kernel::KEvent* rendered_event; 235 Kernel::KEvent* rendered_event;
210 Manager& manager; 236 Manager& manager;
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 98e4f2af7..2f871de31 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -745,8 +745,9 @@ void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
745} 745}
746 746
747void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) { 747void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
748 ASSERT(max_length < supported_npad_id_types.size()); 748 const auto copy_amount = supported_npad_id_types.size() * sizeof(u32);
749 std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size()); 749 ASSERT(max_length <= copy_amount);
750 std::memcpy(data, supported_npad_id_types.data(), copy_amount);
750} 751}
751 752
752std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const { 753std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
@@ -867,7 +868,7 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
867 return false; 868 return false;
868 } 869 }
869 870
870 if (!controller.device->IsVibrationEnabled()) { 871 if (!controller.device->IsVibrationEnabled(device_index)) {
871 if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f || 872 if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
872 controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) { 873 controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
873 // Send an empty vibration to stop any vibrations. 874 // Send an empty vibration to stop any vibrations.
@@ -1000,7 +1001,7 @@ void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npa
1000 } 1001 }
1001 1002
1002 controller.vibration[device_index].device_mounted = 1003 controller.vibration[device_index].device_mounted =
1003 controller.device->TestVibration(device_index); 1004 controller.device->IsVibrationEnabled(device_index);
1004} 1005}
1005 1006
1006void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) { 1007void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
@@ -1501,25 +1502,25 @@ bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller
1501 Core::HID::NpadStyleTag style = GetSupportedStyleSet(); 1502 Core::HID::NpadStyleTag style = GetSupportedStyleSet();
1502 switch (controller) { 1503 switch (controller) {
1503 case Core::HID::NpadStyleIndex::ProController: 1504 case Core::HID::NpadStyleIndex::ProController:
1504 return style.fullkey; 1505 return style.fullkey.As<bool>();
1505 case Core::HID::NpadStyleIndex::JoyconDual: 1506 case Core::HID::NpadStyleIndex::JoyconDual:
1506 return style.joycon_dual; 1507 return style.joycon_dual.As<bool>();
1507 case Core::HID::NpadStyleIndex::JoyconLeft: 1508 case Core::HID::NpadStyleIndex::JoyconLeft:
1508 return style.joycon_left; 1509 return style.joycon_left.As<bool>();
1509 case Core::HID::NpadStyleIndex::JoyconRight: 1510 case Core::HID::NpadStyleIndex::JoyconRight:
1510 return style.joycon_right; 1511 return style.joycon_right.As<bool>();
1511 case Core::HID::NpadStyleIndex::GameCube: 1512 case Core::HID::NpadStyleIndex::GameCube:
1512 return style.gamecube; 1513 return style.gamecube.As<bool>();
1513 case Core::HID::NpadStyleIndex::Pokeball: 1514 case Core::HID::NpadStyleIndex::Pokeball:
1514 return style.palma; 1515 return style.palma.As<bool>();
1515 case Core::HID::NpadStyleIndex::NES: 1516 case Core::HID::NpadStyleIndex::NES:
1516 return style.lark; 1517 return style.lark.As<bool>();
1517 case Core::HID::NpadStyleIndex::SNES: 1518 case Core::HID::NpadStyleIndex::SNES:
1518 return style.lucia; 1519 return style.lucia.As<bool>();
1519 case Core::HID::NpadStyleIndex::N64: 1520 case Core::HID::NpadStyleIndex::N64:
1520 return style.lagoon; 1521 return style.lagoon.As<bool>();
1521 case Core::HID::NpadStyleIndex::SegaGenesis: 1522 case Core::HID::NpadStyleIndex::SegaGenesis:
1522 return style.lager; 1523 return style.lager.As<bool>();
1523 default: 1524 default:
1524 return false; 1525 return false;
1525 } 1526 }
diff --git a/src/core/hle/service/nfp/amiibo_crypto.cpp b/src/core/hle/service/nfp/amiibo_crypto.cpp
index c32a6816b..167e29572 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfp/amiibo_crypto.cpp
@@ -9,6 +9,7 @@
9#include <mbedtls/hmac_drbg.h> 9#include <mbedtls/hmac_drbg.h>
10 10
11#include "common/fs/file.h" 11#include "common/fs/file.h"
12#include "common/fs/fs.h"
12#include "common/fs/path_util.h" 13#include "common/fs/path_util.h"
13#include "common/logging/log.h" 14#include "common/logging/log.h"
14#include "core/hle/service/mii/mii_manager.h" 15#include "core/hle/service/mii/mii_manager.h"
@@ -279,7 +280,7 @@ bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info) {
279 Common::FS::FileType::BinaryFile}; 280 Common::FS::FileType::BinaryFile};
280 281
281 if (!keys_file.IsOpen()) { 282 if (!keys_file.IsOpen()) {
282 LOG_ERROR(Service_NFP, "No keys detected"); 283 LOG_ERROR(Service_NFP, "Failed to open key file");
283 return false; 284 return false;
284 } 285 }
285 286
@@ -295,6 +296,11 @@ bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info) {
295 return true; 296 return true;
296} 297}
297 298
299bool IsKeyAvailable() {
300 const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
301 return Common::FS::Exists(yuzu_keys_dir / "key_retail.bin");
302}
303
298bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data) { 304bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data) {
299 InternalKey locked_secret{}; 305 InternalKey locked_secret{};
300 InternalKey unfixed_info{}; 306 InternalKey unfixed_info{};
diff --git a/src/core/hle/service/nfp/amiibo_crypto.h b/src/core/hle/service/nfp/amiibo_crypto.h
index 0175ced91..1fa61174e 100644
--- a/src/core/hle/service/nfp/amiibo_crypto.h
+++ b/src/core/hle/service/nfp/amiibo_crypto.h
@@ -91,6 +91,9 @@ void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& ou
91/// Loads both amiibo keys from key_retail.bin 91/// Loads both amiibo keys from key_retail.bin
92bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info); 92bool LoadKeys(InternalKey& locked_secret, InternalKey& unfixed_info);
93 93
94/// Returns true if key_retail.bin exist
95bool IsKeyAvailable();
96
94/// Decodes encripted amiibo data returns true if output is valid 97/// Decodes encripted amiibo data returns true if output is valid
95bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data); 98bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& tag_data);
96 99
diff --git a/src/core/hle/service/nfp/nfp_device.cpp b/src/core/hle/service/nfp/nfp_device.cpp
index 76f8a267a..b19672560 100644
--- a/src/core/hle/service/nfp/nfp_device.cpp
+++ b/src/core/hle/service/nfp/nfp_device.cpp
@@ -17,6 +17,7 @@
17#include "core/hle/ipc_helpers.h" 17#include "core/hle/ipc_helpers.h"
18#include "core/hle/kernel/k_event.h" 18#include "core/hle/kernel/k_event.h"
19#include "core/hle/service/mii/mii_manager.h" 19#include "core/hle/service/mii/mii_manager.h"
20#include "core/hle/service/mii/types.h"
20#include "core/hle/service/nfp/amiibo_crypto.h" 21#include "core/hle/service/nfp/amiibo_crypto.h"
21#include "core/hle/service/nfp/nfp.h" 22#include "core/hle/service/nfp/nfp.h"
22#include "core/hle/service/nfp/nfp_device.h" 23#include "core/hle/service/nfp/nfp_device.h"
@@ -233,6 +234,14 @@ Result NfpDevice::Mount(MountTarget mount_target_) {
233 return NotAnAmiibo; 234 return NotAnAmiibo;
234 } 235 }
235 236
237 // Mark amiibos as read only when keys are missing
238 if (!AmiiboCrypto::IsKeyAvailable()) {
239 LOG_ERROR(Service_NFP, "No keys detected");
240 device_state = DeviceState::TagMounted;
241 mount_target = MountTarget::Rom;
242 return ResultSuccess;
243 }
244
236 if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) { 245 if (!AmiiboCrypto::DecodeAmiibo(encrypted_tag_data, tag_data)) {
237 LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state); 246 LOG_ERROR(Service_NFP, "Can't decode amiibo {}", device_state);
238 return CorruptedData; 247 return CorruptedData;
diff --git a/src/core/hle/service/nfp/nfp_device.h b/src/core/hle/service/nfp/nfp_device.h
index a5b72cf19..76d0e9ae4 100644
--- a/src/core/hle/service/nfp/nfp_device.h
+++ b/src/core/hle/service/nfp/nfp_device.h
@@ -8,7 +8,6 @@
8 8
9#include "common/common_funcs.h" 9#include "common/common_funcs.h"
10#include "core/hle/service/kernel_helpers.h" 10#include "core/hle/service/kernel_helpers.h"
11#include "core/hle/service/mii/types.h"
12#include "core/hle/service/nfp/nfp_types.h" 11#include "core/hle/service/nfp/nfp_types.h"
13#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
14 13
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h
index c09f9ddb6..63d5917cb 100644
--- a/src/core/hle/service/nfp/nfp_types.h
+++ b/src/core/hle/service/nfp/nfp_types.h
@@ -17,11 +17,6 @@ enum class ServiceType : u32 {
17 System, 17 System,
18}; 18};
19 19
20enum class State : u32 {
21 NonInitialized,
22 Initialized,
23};
24
25enum class DeviceState : u32 { 20enum class DeviceState : u32 {
26 Initialized, 21 Initialized,
27 SearchingForTag, 22 SearchingForTag,
diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp
index 4ed53b534..33e2ef518 100644
--- a/src/core/hle/service/nfp/nfp_user.cpp
+++ b/src/core/hle/service/nfp/nfp_user.cpp
@@ -6,12 +6,9 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hid/emulated_controller.h"
10#include "core/hid/hid_core.h"
11#include "core/hid/hid_types.h" 9#include "core/hid/hid_types.h"
12#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
13#include "core/hle/kernel/k_event.h" 11#include "core/hle/kernel/k_event.h"
14#include "core/hle/service/mii/mii_manager.h"
15#include "core/hle/service/nfp/nfp_device.h" 12#include "core/hle/service/nfp/nfp_device.h"
16#include "core/hle/service/nfp/nfp_result.h" 13#include "core/hle/service/nfp/nfp_result.h"
17#include "core/hle/service/nfp/nfp_user.h" 14#include "core/hle/service/nfp/nfp_user.h"
diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h
index 68c60ae82..47aff3695 100644
--- a/src/core/hle/service/nfp/nfp_user.h
+++ b/src/core/hle/service/nfp/nfp_user.h
@@ -4,8 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include "core/hle/service/kernel_helpers.h" 6#include "core/hle/service/kernel_helpers.h"
7#include "core/hle/service/nfp/nfp.h" 7#include "core/hle/service/service.h"
8#include "core/hle/service/nfp/nfp_types.h"
9 8
10namespace Service::NFP { 9namespace Service::NFP {
11class NfpDevice; 10class NfpDevice;
@@ -15,6 +14,11 @@ public:
15 explicit IUser(Core::System& system_); 14 explicit IUser(Core::System& system_);
16 15
17private: 16private:
17 enum class State : u32 {
18 NonInitialized,
19 Initialized,
20 };
21
18 void Initialize(Kernel::HLERequestContext& ctx); 22 void Initialize(Kernel::HLERequestContext& ctx);
19 void Finalize(Kernel::HLERequestContext& ctx); 23 void Finalize(Kernel::HLERequestContext& ctx);
20 void ListDevices(Kernel::HLERequestContext& ctx); 24 void ListDevices(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index fbd8a74a5..a51ca5444 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -255,15 +255,16 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
255 .address = handle_description->address, 255 .address = handle_description->address,
256 .size = handle_description->size, 256 .size = handle_description->size,
257 .was_uncached = handle_description->flags.map_uncached.Value() != 0, 257 .was_uncached = handle_description->flags.map_uncached.Value() != 0,
258 .can_unlock = true,
258 }; 259 };
259 } else { 260 } else {
260 return std::nullopt; 261 return std::nullopt;
261 } 262 }
262 263
263 // Handle hasn't been freed from memory, set address to 0 to mark that the handle wasn't freed 264 // If the handle hasn't been freed from memory, mark that
264 if (!hWeak.expired()) { 265 if (!hWeak.expired()) {
265 LOG_DEBUG(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle); 266 LOG_DEBUG(Service_NVDRV, "nvmap handle: {} wasn't freed as it is still in use", handle);
266 freeInfo.address = 0; 267 freeInfo.can_unlock = false;
267 } 268 }
268 269
269 return freeInfo; 270 return freeInfo;
diff --git a/src/core/hle/service/nvdrv/core/nvmap.h b/src/core/hle/service/nvdrv/core/nvmap.h
index b9dd3801f..a8e573890 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.h
+++ b/src/core/hle/service/nvdrv/core/nvmap.h
@@ -105,6 +105,7 @@ public:
105 u64 address; //!< Address the handle referred to before deletion 105 u64 address; //!< Address the handle referred to before deletion
106 u64 size; //!< Page-aligned handle size 106 u64 size; //!< Page-aligned handle size
107 bool was_uncached; //!< If the handle was allocated as uncached 107 bool was_uncached; //!< If the handle was allocated as uncached
108 bool can_unlock; //!< If the address region is ready to be unlocked
108 }; 109 };
109 110
110 explicit NvMap(Tegra::Host1x::Host1x& host1x); 111 explicit NvMap(Tegra::Host1x::Host1x& host1x);
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index b60679021..44388655d 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -251,10 +251,12 @@ NvResult nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
251 } 251 }
252 252
253 if (auto freeInfo{file.FreeHandle(params.handle, false)}) { 253 if (auto freeInfo{file.FreeHandle(params.handle, false)}) {
254 ASSERT(system.CurrentProcess() 254 if (freeInfo->can_unlock) {
255 ->PageTable() 255 ASSERT(system.CurrentProcess()
256 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) 256 ->PageTable()
257 .IsSuccess()); 257 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size)
258 .IsSuccess());
259 }
258 params.address = freeInfo->address; 260 params.address = freeInfo->address;
259 params.size = static_cast<u32>(freeInfo->size); 261 params.size = static_cast<u32>(freeInfo->size);
260 params.flags.raw = 0; 262 params.flags.raw = 0;
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 9d9924395..9f4c7c99a 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -53,7 +53,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
53} 53}
54 54
55Module::Module(Core::System& system) 55Module::Module(Core::System& system)
56 : service_context{system, "nvdrv"}, events_interface{*this}, container{system.Host1x()} { 56 : container{system.Host1x()}, service_context{system, "nvdrv"}, events_interface{*this} {
57 builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) { 57 builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) {
58 std::shared_ptr<Devices::nvdevice> device = 58 std::shared_ptr<Devices::nvdevice> device =
59 std::make_shared<Devices::nvhost_as_gpu>(system, *this, container); 59 std::make_shared<Devices::nvhost_as_gpu>(system, *this, container);
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 146d046a9..f3c81bd88 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -97,6 +97,9 @@ private:
97 friend class EventInterface; 97 friend class EventInterface;
98 friend class Service::NVFlinger::NVFlinger; 98 friend class Service::NVFlinger::NVFlinger;
99 99
100 /// Manages syncpoints on the host
101 NvCore::Container container;
102
100 /// Id to use for the next open file descriptor. 103 /// Id to use for the next open file descriptor.
101 DeviceFD next_fd = 1; 104 DeviceFD next_fd = 1;
102 105
@@ -108,9 +111,6 @@ private:
108 111
109 EventInterface events_interface; 112 EventInterface events_interface;
110 113
111 /// Manages syncpoints on the host
112 NvCore::Container container;
113
114 std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders; 114 std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
115}; 115};
116 116
diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
index 77ddbb6ef..41ba44b21 100644
--- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp
@@ -742,6 +742,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
742 return Status::NoError; 742 return Status::NoError;
743 } 743 }
744 744
745 // HACK: We are not Android. Remove handle for items in queue, and clear queue.
746 // Allows synchronous destruction of nvmap handles.
747 for (auto& item : core->queue) {
748 nvmap.FreeHandle(item.graphic_buffer->BufferId(), true);
749 }
750 core->queue.clear();
751
745 switch (api) { 752 switch (api) {
746 case NativeWindowApi::Egl: 753 case NativeWindowApi::Egl:
747 case NativeWindowApi::Cpu: 754 case NativeWindowApi::Cpu:
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index aa14d2cbc..c3af12c90 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -102,15 +102,19 @@ NVFlinger::~NVFlinger() {
102 system.CoreTiming().UnscheduleEvent(single_composition_event, {}); 102 system.CoreTiming().UnscheduleEvent(single_composition_event, {});
103 } 103 }
104 104
105 ShutdownLayers();
106
107 if (nvdrv) {
108 nvdrv->Close(disp_fd);
109 }
110}
111
112void NVFlinger::ShutdownLayers() {
105 for (auto& display : displays) { 113 for (auto& display : displays) {
106 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { 114 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
107 display.GetLayer(layer).Core().NotifyShutdown(); 115 display.GetLayer(layer).Core().NotifyShutdown();
108 } 116 }
109 } 117 }
110
111 if (nvdrv) {
112 nvdrv->Close(disp_fd);
113 }
114} 118}
115 119
116void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { 120void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
@@ -134,6 +138,19 @@ std::optional<u64> NVFlinger::OpenDisplay(std::string_view name) {
134 return itr->GetID(); 138 return itr->GetID();
135} 139}
136 140
141bool NVFlinger::CloseDisplay(u64 display_id) {
142 const auto lock_guard = Lock();
143 auto* const display = FindDisplay(display_id);
144
145 if (display == nullptr) {
146 return false;
147 }
148
149 display->Reset();
150
151 return true;
152}
153
137std::optional<u64> NVFlinger::CreateLayer(u64 display_id) { 154std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
138 const auto lock_guard = Lock(); 155 const auto lock_guard = Lock();
139 auto* const display = FindDisplay(display_id); 156 auto* const display = FindDisplay(display_id);
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 99509bc5b..460bef976 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -48,6 +48,8 @@ public:
48 explicit NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); 48 explicit NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_);
49 ~NVFlinger(); 49 ~NVFlinger();
50 50
51 void ShutdownLayers();
52
51 /// Sets the NVDrv module instance to use to send buffers to the GPU. 53 /// Sets the NVDrv module instance to use to send buffers to the GPU.
52 void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance); 54 void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
53 55
@@ -56,6 +58,11 @@ public:
56 /// If an invalid display name is provided, then an empty optional is returned. 58 /// If an invalid display name is provided, then an empty optional is returned.
57 [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name); 59 [[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name);
58 60
61 /// Closes the specified display by its ID.
62 ///
63 /// Returns false if an invalid display ID is provided.
64 [[nodiscard]] bool CloseDisplay(u64 display_id);
65
59 /// Creates a layer on the specified display and returns the layer ID. 66 /// Creates a layer on the specified display and returns the layer ID.
60 /// 67 ///
61 /// If an invalid display ID is specified, then an empty optional is returned. 68 /// If an invalid display ID is specified, then an empty optional is returned.
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index dadaf897f..5db6588e4 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -303,4 +303,8 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
303 303
304Services::~Services() = default; 304Services::~Services() = default;
305 305
306void Services::KillNVNFlinger() {
307 nv_flinger->ShutdownLayers();
308}
309
306} // namespace Service 310} // namespace Service
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 5bf197c51..ec9deeee4 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -238,6 +238,8 @@ public:
238 explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system); 238 explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
239 ~Services(); 239 ~Services();
240 240
241 void KillNVNFlinger();
242
241private: 243private:
242 std::unique_ptr<NVFlinger::HosBinderDriverServer> hos_binder_driver_server; 244 std::unique_ptr<NVFlinger::HosBinderDriverServer> hos_binder_driver_server;
243 std::unique_ptr<NVFlinger::NVFlinger> nv_flinger; 245 std::unique_ptr<NVFlinger::NVFlinger> nv_flinger;
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index 48e70f93c..cb6c0e96f 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -80,7 +80,6 @@ ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name
80 } 80 }
81 81
82 auto* port = Kernel::KPort::Create(kernel); 82 auto* port = Kernel::KPort::Create(kernel);
83 SCOPE_EXIT({ port->Close(); });
84 83
85 port->Initialize(ServerSessionCountMax, false, name); 84 port->Initialize(ServerSessionCountMax, false, name);
86 auto handler = it->second; 85 auto handler = it->second;
@@ -150,9 +149,10 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
150 return port_result.Code(); 149 return port_result.Code();
151 } 150 }
152 auto& port = port_result.Unwrap(); 151 auto& port = port_result.Unwrap();
153 SCOPE_EXIT({ port->GetClientPort().Close(); }); 152 SCOPE_EXIT({
154 153 port->GetClientPort().Close();
155 kernel.RegisterServerObject(&port->GetServerPort()); 154 port->GetServerPort().Close();
155 });
156 156
157 // Create a new session. 157 // Create a new session.
158 Kernel::KClientSession* session{}; 158 Kernel::KClientSession* session{};
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index 2a4bd64ab..46a8439d8 100644
--- a/src/core/hle/service/sm/sm_controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -15,9 +15,10 @@
15namespace Service::SM { 15namespace Service::SM {
16 16
17void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) { 17void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
18 ASSERT_MSG(!ctx.Session()->IsDomain(), "Session is already a domain"); 18 ASSERT_MSG(!ctx.Session()->GetSessionRequestManager()->IsDomain(),
19 "Session is already a domain");
19 LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId()); 20 LOG_DEBUG(Service, "called, server_session={}", ctx.Session()->GetId());
20 ctx.Session()->ConvertToDomain(); 21 ctx.Session()->GetSessionRequestManager()->ConvertToDomainOnRequestEnd();
21 22
22 IPC::ResponseBuilder rb{ctx, 3}; 23 IPC::ResponseBuilder rb{ctx, 3};
23 rb.Push(ResultSuccess); 24 rb.Push(ResultSuccess);
@@ -27,23 +28,36 @@ void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
27void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { 28void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
28 LOG_DEBUG(Service, "called"); 29 LOG_DEBUG(Service, "called");
29 30
31 auto& process = *ctx.GetThread().GetOwnerProcess();
30 auto& parent_session = *ctx.Session()->GetParent(); 32 auto& parent_session = *ctx.Session()->GetParent();
31 auto& parent_port = parent_session.GetParent()->GetParent()->GetClientPort();
32 auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager(); 33 auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager();
34 auto& session_handler = session_manager->SessionHandler();
33 35
34 // Create a session. 36 // FIXME: this is duplicated from the SVC, it should just call it instead
35 Kernel::KClientSession* session{}; 37 // once this is a proper process
36 const Result result = parent_port.CreateSession(std::addressof(session), session_manager); 38
37 if (result.IsError()) { 39 // Reserve a new session from the process resource limit.
38 LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw); 40 Kernel::KScopedResourceReservation session_reservation(&process,
39 IPC::ResponseBuilder rb{ctx, 2}; 41 Kernel::LimitableResource::Sessions);
40 rb.Push(result); 42 ASSERT(session_reservation.Succeeded());
41 } 43
44 // Create the session.
45 Kernel::KSession* session = Kernel::KSession::Create(system.Kernel());
46 ASSERT(session != nullptr);
47
48 // Initialize the session.
49 session->Initialize(nullptr, parent_session.GetName(), session_manager);
50
51 // Commit the session reservation.
52 session_reservation.Commit();
53
54 // Register the session.
55 session_handler.ClientConnected(&session->GetServerSession());
42 56
43 // We succeeded. 57 // We succeeded.
44 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; 58 IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
45 rb.Push(ResultSuccess); 59 rb.Push(ResultSuccess);
46 rb.PushMoveObjects(session); 60 rb.PushMoveObjects(session->GetClientSession());
47} 61}
48 62
49void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { 63void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 33d5f398c..0b65a65da 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -106,6 +106,12 @@ public:
106 /// 106 ///
107 void CloseLayer(u64 layer_id); 107 void CloseLayer(u64 layer_id);
108 108
109 /// Resets the display for a new connection.
110 void Reset() {
111 layers.clear();
112 got_vsync_event = false;
113 }
114
109 /// Attempts to find a layer with the given ID. 115 /// Attempts to find a layer with the given ID.
110 /// 116 ///
111 /// @param layer_id The layer ID. 117 /// @param layer_id The layer ID.
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 9c917cacf..bb283e74e 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -324,10 +324,10 @@ private:
324 IPC::RequestParser rp{ctx}; 324 IPC::RequestParser rp{ctx};
325 const u64 display = rp.Pop<u64>(); 325 const u64 display = rp.Pop<u64>();
326 326
327 LOG_WARNING(Service_VI, "(STUBBED) called. display=0x{:016X}", display); 327 const Result rc = nv_flinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown;
328 328
329 IPC::ResponseBuilder rb{ctx, 2}; 329 IPC::ResponseBuilder rb{ctx, 2};
330 rb.Push(ResultSuccess); 330 rb.Push(rc);
331 } 331 }
332 332
333 void CreateManagedLayer(Kernel::HLERequestContext& ctx) { 333 void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
@@ -508,10 +508,10 @@ private:
508 IPC::RequestParser rp{ctx}; 508 IPC::RequestParser rp{ctx};
509 const u64 display_id = rp.Pop<u64>(); 509 const u64 display_id = rp.Pop<u64>();
510 510
511 LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id); 511 const Result rc = nv_flinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown;
512 512
513 IPC::ResponseBuilder rb{ctx, 2}; 513 IPC::ResponseBuilder rb{ctx, 2};
514 rb.Push(ResultSuccess); 514 rb.Push(rc);
515 } 515 }
516 516
517 // This literally does nothing internally in the actual service itself, 517 // This literally does nothing internally in the actual service itself,
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 9637cb5b1..3ca80c8ff 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -233,18 +233,17 @@ struct Memory::Impl {
233 current_vaddr, src_addr, size); 233 current_vaddr, src_addr, size);
234 std::memset(dest_buffer, 0, copy_amount); 234 std::memset(dest_buffer, 0, copy_amount);
235 }, 235 },
236 [&dest_buffer](const std::size_t copy_amount, const u8* const src_ptr) { 236 [&](const std::size_t copy_amount, const u8* const src_ptr) {
237 std::memcpy(dest_buffer, src_ptr, copy_amount); 237 std::memcpy(dest_buffer, src_ptr, copy_amount);
238 }, 238 },
239 [&system = system, &dest_buffer](const VAddr current_vaddr, 239 [&](const VAddr current_vaddr, const std::size_t copy_amount,
240 const std::size_t copy_amount, 240 const u8* const host_ptr) {
241 const u8* const host_ptr) {
242 if constexpr (!UNSAFE) { 241 if constexpr (!UNSAFE) {
243 system.GPU().FlushRegion(current_vaddr, copy_amount); 242 system.GPU().FlushRegion(current_vaddr, copy_amount);
244 } 243 }
245 std::memcpy(dest_buffer, host_ptr, copy_amount); 244 std::memcpy(dest_buffer, host_ptr, copy_amount);
246 }, 245 },
247 [&dest_buffer](const std::size_t copy_amount) { 246 [&](const std::size_t copy_amount) {
248 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; 247 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
249 }); 248 });
250 } 249 }
@@ -267,17 +266,16 @@ struct Memory::Impl {
267 "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", 266 "Unmapped WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
268 current_vaddr, dest_addr, size); 267 current_vaddr, dest_addr, size);
269 }, 268 },
270 [&src_buffer](const std::size_t copy_amount, u8* const dest_ptr) { 269 [&](const std::size_t copy_amount, u8* const dest_ptr) {
271 std::memcpy(dest_ptr, src_buffer, copy_amount); 270 std::memcpy(dest_ptr, src_buffer, copy_amount);
272 }, 271 },
273 [&system = system, &src_buffer](const VAddr current_vaddr, 272 [&](const VAddr current_vaddr, const std::size_t copy_amount, u8* const host_ptr) {
274 const std::size_t copy_amount, u8* const host_ptr) {
275 if constexpr (!UNSAFE) { 273 if constexpr (!UNSAFE) {
276 system.GPU().InvalidateRegion(current_vaddr, copy_amount); 274 system.GPU().InvalidateRegion(current_vaddr, copy_amount);
277 } 275 }
278 std::memcpy(host_ptr, src_buffer, copy_amount); 276 std::memcpy(host_ptr, src_buffer, copy_amount);
279 }, 277 },
280 [&src_buffer](const std::size_t copy_amount) { 278 [&](const std::size_t copy_amount) {
281 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; 279 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
282 }); 280 });
283 } 281 }
@@ -301,8 +299,7 @@ struct Memory::Impl {
301 [](const std::size_t copy_amount, u8* const dest_ptr) { 299 [](const std::size_t copy_amount, u8* const dest_ptr) {
302 std::memset(dest_ptr, 0, copy_amount); 300 std::memset(dest_ptr, 0, copy_amount);
303 }, 301 },
304 [&system = system](const VAddr current_vaddr, const std::size_t copy_amount, 302 [&](const VAddr current_vaddr, const std::size_t copy_amount, u8* const host_ptr) {
305 u8* const host_ptr) {
306 system.GPU().InvalidateRegion(current_vaddr, copy_amount); 303 system.GPU().InvalidateRegion(current_vaddr, copy_amount);
307 std::memset(host_ptr, 0, copy_amount); 304 std::memset(host_ptr, 0, copy_amount);
308 }, 305 },
@@ -313,22 +310,20 @@ struct Memory::Impl {
313 const std::size_t size) { 310 const std::size_t size) {
314 WalkBlock( 311 WalkBlock(
315 process, dest_addr, size, 312 process, dest_addr, size,
316 [this, &process, &dest_addr, &src_addr, size](const std::size_t copy_amount, 313 [&](const std::size_t copy_amount, const VAddr current_vaddr) {
317 const VAddr current_vaddr) {
318 LOG_ERROR(HW_Memory, 314 LOG_ERROR(HW_Memory,
319 "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", 315 "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
320 current_vaddr, src_addr, size); 316 current_vaddr, src_addr, size);
321 ZeroBlock(process, dest_addr, copy_amount); 317 ZeroBlock(process, dest_addr, copy_amount);
322 }, 318 },
323 [this, &process, &dest_addr](const std::size_t copy_amount, const u8* const src_ptr) { 319 [&](const std::size_t copy_amount, const u8* const src_ptr) {
324 WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount); 320 WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount);
325 }, 321 },
326 [this, &system = system, &process, &dest_addr]( 322 [&](const VAddr current_vaddr, const std::size_t copy_amount, u8* const host_ptr) {
327 const VAddr current_vaddr, const std::size_t copy_amount, u8* const host_ptr) {
328 system.GPU().FlushRegion(current_vaddr, copy_amount); 323 system.GPU().FlushRegion(current_vaddr, copy_amount);
329 WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount); 324 WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount);
330 }, 325 },
331 [&dest_addr, &src_addr](const std::size_t copy_amount) { 326 [&](const std::size_t copy_amount) {
332 dest_addr += static_cast<VAddr>(copy_amount); 327 dest_addr += static_cast<VAddr>(copy_amount);
333 src_addr += static_cast<VAddr>(copy_amount); 328 src_addr += static_cast<VAddr>(copy_amount);
334 }); 329 });
@@ -575,7 +570,7 @@ struct Memory::Impl {
575 [vaddr]() { 570 [vaddr]() {
576 LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, vaddr); 571 LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, vaddr);
577 }, 572 },
578 [&system = system, vaddr]() { system.GPU().FlushRegion(vaddr, sizeof(T)); }); 573 [&]() { system.GPU().FlushRegion(vaddr, sizeof(T)); });
579 if (ptr) { 574 if (ptr) {
580 std::memcpy(&result, ptr, sizeof(T)); 575 std::memcpy(&result, ptr, sizeof(T));
581 } 576 }
@@ -599,7 +594,7 @@ struct Memory::Impl {
599 LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, 594 LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8,
600 vaddr, static_cast<u64>(data)); 595 vaddr, static_cast<u64>(data));
601 }, 596 },
602 [&system = system, vaddr]() { system.GPU().InvalidateRegion(vaddr, sizeof(T)); }); 597 [&]() { system.GPU().InvalidateRegion(vaddr, sizeof(T)); });
603 if (ptr) { 598 if (ptr) {
604 std::memcpy(ptr, &data, sizeof(T)); 599 std::memcpy(ptr, &data, sizeof(T));
605 } 600 }
@@ -613,7 +608,7 @@ struct Memory::Impl {
613 LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}", 608 LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}",
614 sizeof(T) * 8, vaddr, static_cast<u64>(data)); 609 sizeof(T) * 8, vaddr, static_cast<u64>(data));
615 }, 610 },
616 [&system = system, vaddr]() { system.GPU().InvalidateRegion(vaddr, sizeof(T)); }); 611 [&]() { system.GPU().InvalidateRegion(vaddr, sizeof(T)); });
617 if (ptr) { 612 if (ptr) {
618 const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr); 613 const auto volatile_pointer = reinterpret_cast<volatile T*>(ptr);
619 return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); 614 return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
@@ -628,7 +623,7 @@ struct Memory::Impl {
628 LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}", 623 LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}",
629 vaddr, static_cast<u64>(data[1]), static_cast<u64>(data[0])); 624 vaddr, static_cast<u64>(data[1]), static_cast<u64>(data[0]));
630 }, 625 },
631 [&system = system, vaddr]() { system.GPU().InvalidateRegion(vaddr, sizeof(u128)); }); 626 [&]() { system.GPU().InvalidateRegion(vaddr, sizeof(u128)); });
632 if (ptr) { 627 if (ptr) {
633 const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr); 628 const auto volatile_pointer = reinterpret_cast<volatile u64*>(ptr);
634 return Common::AtomicCompareAndSwap(volatile_pointer, data, expected); 629 return Common::AtomicCompareAndSwap(volatile_pointer, data, expected);
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 2cf9eb97f..cc6f0ffc0 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -39,21 +39,14 @@ add_library(input_common STATIC
39if (MSVC) 39if (MSVC)
40 target_compile_options(input_common PRIVATE 40 target_compile_options(input_common PRIVATE
41 /W4 41 /W4
42 /WX
43 42
44 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data 43 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
45 /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
46 /we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
47 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 44 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
45 /we4800 # Implicit conversion from 'type' to bool. Possible information loss
48 ) 46 )
49else() 47else()
50 target_compile_options(input_common PRIVATE 48 target_compile_options(input_common PRIVATE
51 -Werror
52 -Werror=conversion 49 -Werror=conversion
53 -Werror=ignored-qualifiers
54 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
55 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
56 -Werror=unused-variable
57 ) 50 )
58endif() 51endif()
59 52
diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp
index f4dd24e7d..826fa2109 100644
--- a/src/input_common/drivers/gc_adapter.cpp
+++ b/src/input_common/drivers/gc_adapter.cpp
@@ -324,7 +324,7 @@ bool GCAdapter::GetGCEndpoint(libusb_device* device) {
324 return true; 324 return true;
325} 325}
326 326
327Common::Input::VibrationError GCAdapter::SetRumble( 327Common::Input::VibrationError GCAdapter::SetVibration(
328 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { 328 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
329 const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f; 329 const auto mean_amplitude = (vibration.low_amplitude + vibration.high_amplitude) * 0.5f;
330 const auto processed_amplitude = 330 const auto processed_amplitude =
@@ -338,6 +338,10 @@ Common::Input::VibrationError GCAdapter::SetRumble(
338 return Common::Input::VibrationError::None; 338 return Common::Input::VibrationError::None;
339} 339}
340 340
341bool GCAdapter::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
342 return rumble_enabled;
343}
344
341void GCAdapter::UpdateVibrations() { 345void GCAdapter::UpdateVibrations() {
342 // Use 8 states to keep the switching between on/off fast enough for 346 // Use 8 states to keep the switching between on/off fast enough for
343 // a human to feel different vibration strenght 347 // a human to feel different vibration strenght
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h
index 8682da847..7f81767f7 100644
--- a/src/input_common/drivers/gc_adapter.h
+++ b/src/input_common/drivers/gc_adapter.h
@@ -25,9 +25,11 @@ public:
25 explicit GCAdapter(std::string input_engine_); 25 explicit GCAdapter(std::string input_engine_);
26 ~GCAdapter() override; 26 ~GCAdapter() override;
27 27
28 Common::Input::VibrationError SetRumble( 28 Common::Input::VibrationError SetVibration(
29 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; 29 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
30 30
31 bool IsVibrationEnabled(const PadIdentifier& identifier) override;
32
31 /// Used for automapping features 33 /// Used for automapping features
32 std::vector<Common::ParamPackage> GetInputDevices() const override; 34 std::vector<Common::ParamPackage> GetInputDevices() const override;
33 ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; 35 ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override;
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index b72e4b397..45ce588f0 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -40,8 +40,8 @@ public:
40 void EnableMotion() { 40 void EnableMotion() {
41 if (sdl_controller) { 41 if (sdl_controller) {
42 SDL_GameController* controller = sdl_controller.get(); 42 SDL_GameController* controller = sdl_controller.get();
43 has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL); 43 has_accel = SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL) == SDL_TRUE;
44 has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO); 44 has_gyro = SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO) == SDL_TRUE;
45 if (has_accel) { 45 if (has_accel) {
46 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE); 46 SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_ACCEL, SDL_TRUE);
47 } 47 }
@@ -114,6 +114,20 @@ public:
114 } 114 }
115 return false; 115 return false;
116 } 116 }
117
118 void EnableVibration(bool is_enabled) {
119 has_vibration = is_enabled;
120 is_vibration_tested = true;
121 }
122
123 bool HasVibration() const {
124 return has_vibration;
125 }
126
127 bool IsVibrationTested() const {
128 return is_vibration_tested;
129 }
130
117 /** 131 /**
118 * The Pad identifier of the joystick 132 * The Pad identifier of the joystick
119 */ 133 */
@@ -236,6 +250,8 @@ private:
236 u64 last_motion_update{}; 250 u64 last_motion_update{};
237 bool has_gyro{false}; 251 bool has_gyro{false};
238 bool has_accel{false}; 252 bool has_accel{false};
253 bool has_vibration{false};
254 bool is_vibration_tested{false};
239 BasicMotion motion; 255 BasicMotion motion;
240}; 256};
241 257
@@ -517,7 +533,7 @@ std::vector<Common::ParamPackage> SDLDriver::GetInputDevices() const {
517 return devices; 533 return devices;
518} 534}
519 535
520Common::Input::VibrationError SDLDriver::SetRumble( 536Common::Input::VibrationError SDLDriver::SetVibration(
521 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) { 537 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) {
522 const auto joystick = 538 const auto joystick =
523 GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port)); 539 GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
@@ -546,13 +562,6 @@ Common::Input::VibrationError SDLDriver::SetRumble(
546 .type = Common::Input::VibrationAmplificationType::Exponential, 562 .type = Common::Input::VibrationAmplificationType::Exponential,
547 }; 563 };
548 564
549 if (vibration.type == Common::Input::VibrationAmplificationType::Test) {
550 if (!joystick->RumblePlay(new_vibration)) {
551 return Common::Input::VibrationError::Unknown;
552 }
553 return Common::Input::VibrationError::None;
554 }
555
556 vibration_queue.Push(VibrationRequest{ 565 vibration_queue.Push(VibrationRequest{
557 .identifier = identifier, 566 .identifier = identifier,
558 .vibration = new_vibration, 567 .vibration = new_vibration,
@@ -561,6 +570,45 @@ Common::Input::VibrationError SDLDriver::SetRumble(
561 return Common::Input::VibrationError::None; 570 return Common::Input::VibrationError::None;
562} 571}
563 572
573bool SDLDriver::IsVibrationEnabled(const PadIdentifier& identifier) {
574 const auto joystick =
575 GetSDLJoystickByGUID(identifier.guid.RawString(), static_cast<int>(identifier.port));
576
577 constexpr Common::Input::VibrationStatus test_vibration{
578 .low_amplitude = 1,
579 .low_frequency = 160.0f,
580 .high_amplitude = 1,
581 .high_frequency = 320.0f,
582 .type = Common::Input::VibrationAmplificationType::Exponential,
583 };
584
585 constexpr Common::Input::VibrationStatus zero_vibration{
586 .low_amplitude = 0,
587 .low_frequency = 160.0f,
588 .high_amplitude = 0,
589 .high_frequency = 320.0f,
590 .type = Common::Input::VibrationAmplificationType::Exponential,
591 };
592
593 if (joystick->IsVibrationTested()) {
594 return joystick->HasVibration();
595 }
596
597 // First vibration might fail
598 joystick->RumblePlay(test_vibration);
599
600 // Wait for about 15ms to ensure the controller is ready for the stop command
601 std::this_thread::sleep_for(std::chrono::milliseconds(15));
602
603 if (!joystick->RumblePlay(zero_vibration)) {
604 joystick->EnableVibration(false);
605 return false;
606 }
607
608 joystick->EnableVibration(true);
609 return true;
610}
611
564void SDLDriver::SendVibrations() { 612void SDLDriver::SendVibrations() {
565 while (!vibration_queue.Empty()) { 613 while (!vibration_queue.Empty()) {
566 VibrationRequest request; 614 VibrationRequest request;
diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h
index fc3a44572..d1b4471cf 100644
--- a/src/input_common/drivers/sdl_driver.h
+++ b/src/input_common/drivers/sdl_driver.h
@@ -61,9 +61,11 @@ public:
61 61
62 bool IsStickInverted(const Common::ParamPackage& params) override; 62 bool IsStickInverted(const Common::ParamPackage& params) override;
63 63
64 Common::Input::VibrationError SetRumble( 64 Common::Input::VibrationError SetVibration(
65 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; 65 const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override;
66 66
67 bool IsVibrationEnabled(const PadIdentifier& identifier) override;
68
67private: 69private:
68 struct VibrationRequest { 70 struct VibrationRequest {
69 PadIdentifier identifier; 71 PadIdentifier identifier;
diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h
index cfbdb26bd..d4c264a8e 100644
--- a/src/input_common/input_engine.h
+++ b/src/input_common/input_engine.h
@@ -108,12 +108,17 @@ public:
108 [[maybe_unused]] const Common::Input::LedStatus& led_status) {} 108 [[maybe_unused]] const Common::Input::LedStatus& led_status) {}
109 109
110 // Sets rumble to a controller 110 // Sets rumble to a controller
111 virtual Common::Input::VibrationError SetRumble( 111 virtual Common::Input::VibrationError SetVibration(
112 [[maybe_unused]] const PadIdentifier& identifier, 112 [[maybe_unused]] const PadIdentifier& identifier,
113 [[maybe_unused]] const Common::Input::VibrationStatus& vibration) { 113 [[maybe_unused]] const Common::Input::VibrationStatus& vibration) {
114 return Common::Input::VibrationError::NotSupported; 114 return Common::Input::VibrationError::NotSupported;
115 } 115 }
116 116
117 // Returns true if device supports vibrations
118 virtual bool IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) {
119 return false;
120 }
121
117 // Sets polling mode to a controller 122 // Sets polling mode to a controller
118 virtual Common::Input::PollingError SetPollingMode( 123 virtual Common::Input::PollingError SetPollingMode(
119 [[maybe_unused]] const PadIdentifier& identifier, 124 [[maybe_unused]] const PadIdentifier& identifier,
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp
index ca33fb4eb..4ac182147 100644
--- a/src/input_common/input_poller.cpp
+++ b/src/input_common/input_poller.cpp
@@ -763,7 +763,11 @@ public:
763 763
764 Common::Input::VibrationError SetVibration( 764 Common::Input::VibrationError SetVibration(
765 const Common::Input::VibrationStatus& vibration_status) override { 765 const Common::Input::VibrationStatus& vibration_status) override {
766 return input_engine->SetRumble(identifier, vibration_status); 766 return input_engine->SetVibration(identifier, vibration_status);
767 }
768
769 bool IsVibrationEnabled() override {
770 return input_engine->IsVibrationEnabled(identifier);
767 } 771 }
768 772
769 Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override { 773 Common::Input::PollingError SetPollingMode(Common::Input::PollingMode polling_mode) override {
@@ -797,8 +801,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateButtonDevice(
797 801
798 const auto button_id = params.Get("button", 0); 802 const auto button_id = params.Get("button", 0);
799 const auto keyboard_key = params.Get("code", 0); 803 const auto keyboard_key = params.Get("code", 0);
800 const auto toggle = params.Get("toggle", false); 804 const auto toggle = params.Get("toggle", false) != 0;
801 const auto inverted = params.Get("inverted", false); 805 const auto inverted = params.Get("inverted", false) != 0;
802 input_engine->PreSetController(identifier); 806 input_engine->PreSetController(identifier);
803 input_engine->PreSetButton(identifier, button_id); 807 input_engine->PreSetButton(identifier, button_id);
804 input_engine->PreSetButton(identifier, keyboard_key); 808 input_engine->PreSetButton(identifier, keyboard_key);
@@ -820,8 +824,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateHatButtonDevice(
820 824
821 const auto button_id = params.Get("hat", 0); 825 const auto button_id = params.Get("hat", 0);
822 const auto direction = input_engine->GetHatButtonId(params.Get("direction", "")); 826 const auto direction = input_engine->GetHatButtonId(params.Get("direction", ""));
823 const auto toggle = params.Get("toggle", false); 827 const auto toggle = params.Get("toggle", false) != 0;
824 const auto inverted = params.Get("inverted", false); 828 const auto inverted = params.Get("inverted", false) != 0;
825 829
826 input_engine->PreSetController(identifier); 830 input_engine->PreSetController(identifier);
827 input_engine->PreSetHatButton(identifier, button_id); 831 input_engine->PreSetHatButton(identifier, button_id);
@@ -879,7 +883,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice(
879 .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), 883 .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f),
880 .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), 884 .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f),
881 .inverted = params.Get("invert", "+") == "-", 885 .inverted = params.Get("invert", "+") == "-",
882 .toggle = static_cast<bool>(params.Get("toggle", false)), 886 .toggle = params.Get("toggle", false) != 0,
883 }; 887 };
884 input_engine->PreSetController(identifier); 888 input_engine->PreSetController(identifier);
885 input_engine->PreSetAxis(identifier, axis); 889 input_engine->PreSetAxis(identifier, axis);
@@ -895,8 +899,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTriggerDevice(
895 }; 899 };
896 900
897 const auto button = params.Get("button", 0); 901 const auto button = params.Get("button", 0);
898 const auto toggle = params.Get("toggle", false); 902 const auto toggle = params.Get("toggle", false) != 0;
899 const auto inverted = params.Get("inverted", false); 903 const auto inverted = params.Get("inverted", false) != 0;
900 904
901 const auto axis = params.Get("axis", 0); 905 const auto axis = params.Get("axis", 0);
902 const Common::Input::AnalogProperties properties = { 906 const Common::Input::AnalogProperties properties = {
@@ -926,8 +930,8 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateTouchDevice(
926 }; 930 };
927 931
928 const auto button = params.Get("button", 0); 932 const auto button = params.Get("button", 0);
929 const auto toggle = params.Get("toggle", false); 933 const auto toggle = params.Get("toggle", false) != 0;
930 const auto inverted = params.Get("inverted", false); 934 const auto inverted = params.Get("inverted", false) != 0;
931 935
932 const auto axis_x = params.Get("axis_x", 0); 936 const auto axis_x = params.Get("axis_x", 0);
933 const Common::Input::AnalogProperties properties_x = { 937 const Common::Input::AnalogProperties properties_x = {
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index af8e51fe8..bcdd60db9 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -241,24 +241,14 @@ target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit)
241if (MSVC) 241if (MSVC)
242 target_compile_options(shader_recompiler PRIVATE 242 target_compile_options(shader_recompiler PRIVATE
243 /W4 243 /W4
244 /WX 244
245 /we4018 # 'expression' : signed/unsigned mismatch 245 /we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
246 /we4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
247 /we4245 # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
248 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 246 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
249 /we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
250 /we4305 # 'context' : truncation from 'type1' to 'type2'
251 /we4800 # Implicit conversion from 'type' to bool. Possible information loss 247 /we4800 # Implicit conversion from 'type' to bool. Possible information loss
252 /we4826 # Conversion from 'type1' to 'type2' is sign-extended. This may cause unexpected runtime behavior.
253 ) 248 )
254else() 249else()
255 target_compile_options(shader_recompiler PRIVATE 250 target_compile_options(shader_recompiler PRIVATE
256 -Werror
257 -Werror=conversion 251 -Werror=conversion
258 -Werror=ignored-qualifiers
259 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
260 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
261 -Werror=unused-variable
262 252
263 # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. 253 # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.
264 # And this in turns limits the size of a std::array. 254 # And this in turns limits the size of a std::array.
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
index 7094d8e42..1f4ffdd62 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp
@@ -5,10 +5,6 @@
5#include "shader_recompiler/backend/glasm/glasm_emit_context.h" 5#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
6#include "shader_recompiler/frontend/ir/value.h" 6#include "shader_recompiler/frontend/ir/value.h"
7 7
8#ifdef _MSC_VER
9#pragma warning(disable : 4100)
10#endif
11
12namespace Shader::Backend::GLASM { 8namespace Shader::Backend::GLASM {
13 9
14#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__) 10#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__)
diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
index b03a8ba1e..9f1ed95a4 100644
--- a/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
+++ b/src/shader_recompiler/backend/glsl/emit_glsl_not_implemented.cpp
@@ -7,10 +7,6 @@
7#include "shader_recompiler/backend/glsl/glsl_emit_context.h" 7#include "shader_recompiler/backend/glsl/glsl_emit_context.h"
8#include "shader_recompiler/frontend/ir/value.h" 8#include "shader_recompiler/frontend/ir/value.h"
9 9
10#ifdef _MSC_VER
11#pragma warning(disable : 4100)
12#endif
13
14namespace Shader::Backend::GLSL { 10namespace Shader::Backend::GLSL {
15 11
16void EmitGetRegister(EmitContext& ctx) { 12void EmitGetRegister(EmitContext& ctx) {
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index 468782eb1..84417980b 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -325,11 +325,6 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) {
325 phi_args.emplace_back(predecessor, value); 325 phi_args.emplace_back(predecessor, value);
326} 326}
327 327
328void Inst::ErasePhiOperand(size_t index) {
329 const auto operand_it{phi_args.begin() + static_cast<ptrdiff_t>(index)};
330 phi_args.erase(operand_it);
331}
332
333void Inst::OrderPhiArgs() { 328void Inst::OrderPhiArgs() {
334 if (op != Opcode::Phi) { 329 if (op != Opcode::Phi) {
335 throw LogicError("{} is not a Phi instruction", op); 330 throw LogicError("{} is not a Phi instruction", op);
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 1a2e4ccb6..6a673ca05 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -178,13 +178,9 @@ public:
178 178
179 /// Get a pointer to the block of a phi argument. 179 /// Get a pointer to the block of a phi argument.
180 [[nodiscard]] Block* PhiBlock(size_t index) const; 180 [[nodiscard]] Block* PhiBlock(size_t index) const;
181
182 /// Add phi operand to a phi instruction. 181 /// Add phi operand to a phi instruction.
183 void AddPhiOperand(Block* predecessor, const Value& value); 182 void AddPhiOperand(Block* predecessor, const Value& value);
184 183
185 // Erase the phi operand at the given index.
186 void ErasePhiOperand(size_t index);
187
188 /// Orders the Phi arguments from farthest away to nearest. 184 /// Orders the Phi arguments from farthest away to nearest.
189 void OrderPhiArgs(); 185 void OrderPhiArgs();
190 186
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
index 77efb4f57..b58741d4d 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
@@ -137,28 +137,35 @@ bool IsLegacyAttribute(IR::Attribute attribute) {
137} 137}
138 138
139std::map<IR::Attribute, IR::Attribute> GenerateLegacyToGenericMappings( 139std::map<IR::Attribute, IR::Attribute> GenerateLegacyToGenericMappings(
140 const VaryingState& state, std::queue<IR::Attribute> ununsed_generics) { 140 const VaryingState& state, std::queue<IR::Attribute> unused_generics,
141 const std::map<IR::Attribute, IR::Attribute>& previous_stage_mapping) {
141 std::map<IR::Attribute, IR::Attribute> mapping; 142 std::map<IR::Attribute, IR::Attribute> mapping;
143 auto update_mapping = [&mapping, &unused_generics, previous_stage_mapping](IR::Attribute attr,
144 size_t count) {
145 if (previous_stage_mapping.find(attr) != previous_stage_mapping.end()) {
146 for (size_t i = 0; i < count; ++i) {
147 mapping.insert({attr + i, previous_stage_mapping.at(attr + i)});
148 }
149 } else {
150 for (size_t i = 0; i < count; ++i) {
151 mapping.insert({attr + i, unused_generics.front() + i});
152 }
153 unused_generics.pop();
154 }
155 };
142 for (size_t index = 0; index < 4; ++index) { 156 for (size_t index = 0; index < 4; ++index) {
143 auto attr = IR::Attribute::ColorFrontDiffuseR + index * 4; 157 auto attr = IR::Attribute::ColorFrontDiffuseR + index * 4;
144 if (state.AnyComponent(attr)) { 158 if (state.AnyComponent(attr)) {
145 for (size_t i = 0; i < 4; ++i) { 159 update_mapping(attr, 4);
146 mapping.insert({attr + i, ununsed_generics.front() + i});
147 }
148 ununsed_generics.pop();
149 } 160 }
150 } 161 }
151 if (state[IR::Attribute::FogCoordinate]) { 162 if (state[IR::Attribute::FogCoordinate]) {
152 mapping.insert({IR::Attribute::FogCoordinate, ununsed_generics.front()}); 163 update_mapping(IR::Attribute::FogCoordinate, 1);
153 ununsed_generics.pop();
154 } 164 }
155 for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) { 165 for (size_t index = 0; index < IR::NUM_FIXEDFNCTEXTURE; ++index) {
156 auto attr = IR::Attribute::FixedFncTexture0S + index * 4; 166 auto attr = IR::Attribute::FixedFncTexture0S + index * 4;
157 if (state.AnyComponent(attr)) { 167 if (state.AnyComponent(attr)) {
158 for (size_t i = 0; i < 4; ++i) { 168 update_mapping(attr, 4);
159 mapping.insert({attr + i, ununsed_generics.front() + i});
160 }
161 ununsed_generics.pop();
162 } 169 }
163 } 170 }
164 return mapping; 171 return mapping;
@@ -265,21 +272,22 @@ IR::Program MergeDualVertexPrograms(IR::Program& vertex_a, IR::Program& vertex_b
265void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& runtime_info) { 272void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& runtime_info) {
266 auto& stores = program.info.stores; 273 auto& stores = program.info.stores;
267 if (stores.Legacy()) { 274 if (stores.Legacy()) {
268 std::queue<IR::Attribute> ununsed_output_generics{}; 275 std::queue<IR::Attribute> unused_output_generics{};
269 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { 276 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
270 if (!stores.Generic(index)) { 277 if (!stores.Generic(index)) {
271 ununsed_output_generics.push(IR::Attribute::Generic0X + index * 4); 278 unused_output_generics.push(IR::Attribute::Generic0X + index * 4);
272 } 279 }
273 } 280 }
274 auto mappings = GenerateLegacyToGenericMappings(stores, ununsed_output_generics); 281 program.info.legacy_stores_mapping =
282 GenerateLegacyToGenericMappings(stores, unused_output_generics, {});
275 for (IR::Block* const block : program.post_order_blocks) { 283 for (IR::Block* const block : program.post_order_blocks) {
276 for (IR::Inst& inst : block->Instructions()) { 284 for (IR::Inst& inst : block->Instructions()) {
277 switch (inst.GetOpcode()) { 285 switch (inst.GetOpcode()) {
278 case IR::Opcode::SetAttribute: { 286 case IR::Opcode::SetAttribute: {
279 const auto attr = inst.Arg(0).Attribute(); 287 const auto attr = inst.Arg(0).Attribute();
280 if (IsLegacyAttribute(attr)) { 288 if (IsLegacyAttribute(attr)) {
281 stores.Set(mappings[attr], true); 289 stores.Set(program.info.legacy_stores_mapping[attr], true);
282 inst.SetArg(0, Shader::IR::Value(mappings[attr])); 290 inst.SetArg(0, Shader::IR::Value(program.info.legacy_stores_mapping[attr]));
283 } 291 }
284 break; 292 break;
285 } 293 }
@@ -292,15 +300,16 @@ void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& run
292 300
293 auto& loads = program.info.loads; 301 auto& loads = program.info.loads;
294 if (loads.Legacy()) { 302 if (loads.Legacy()) {
295 std::queue<IR::Attribute> ununsed_input_generics{}; 303 std::queue<IR::Attribute> unused_input_generics{};
296 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) { 304 for (size_t index = 0; index < IR::NUM_GENERICS; ++index) {
297 const AttributeType input_type{runtime_info.generic_input_types[index]}; 305 const AttributeType input_type{runtime_info.generic_input_types[index]};
298 if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) || 306 if (!runtime_info.previous_stage_stores.Generic(index) || !loads.Generic(index) ||
299 input_type == AttributeType::Disabled) { 307 input_type == AttributeType::Disabled) {
300 ununsed_input_generics.push(IR::Attribute::Generic0X + index * 4); 308 unused_input_generics.push(IR::Attribute::Generic0X + index * 4);
301 } 309 }
302 } 310 }
303 auto mappings = GenerateLegacyToGenericMappings(loads, ununsed_input_generics); 311 auto mappings = GenerateLegacyToGenericMappings(
312 loads, unused_input_generics, runtime_info.previous_stage_legacy_stores_mapping);
304 for (IR::Block* const block : program.post_order_blocks) { 313 for (IR::Block* const block : program.post_order_blocks) {
305 for (IR::Inst& inst : block->Instructions()) { 314 for (IR::Inst& inst : block->Instructions()) {
306 switch (inst.GetOpcode()) { 315 switch (inst.GetOpcode()) {
diff --git a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
index 9a7d47344..1bd8afd6f 100644
--- a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
+++ b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp
@@ -1,104 +1,24 @@
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
6#include <boost/container/small_vector.hpp>
7
8#include "shader_recompiler/frontend/ir/basic_block.h" 4#include "shader_recompiler/frontend/ir/basic_block.h"
9#include "shader_recompiler/frontend/ir/value.h" 5#include "shader_recompiler/frontend/ir/value.h"
10#include "shader_recompiler/ir_opt/passes.h" 6#include "shader_recompiler/ir_opt/passes.h"
11 7
12namespace Shader::Optimization { 8namespace Shader::Optimization {
13namespace { 9
14template <bool TEST_USES> 10void DeadCodeEliminationPass(IR::Program& program) {
15void DeadInstElimination(IR::Block* const block) {
16 // We iterate over the instructions in reverse order. 11 // We iterate over the instructions in reverse order.
17 // This is because removing an instruction reduces the number of uses for earlier instructions. 12 // This is because removing an instruction reduces the number of uses for earlier instructions.
18 auto it{block->end()}; 13 for (IR::Block* const block : program.post_order_blocks) {
19 while (it != block->begin()) { 14 auto it{block->end()};
20 --it; 15 while (it != block->begin()) {
21 if constexpr (TEST_USES) { 16 --it;
22 if (it->HasUses() || it->MayHaveSideEffects()) { 17 if (!it->HasUses() && !it->MayHaveSideEffects()) {
23 continue; 18 it->Invalidate();
24 } 19 it = block->Instructions().erase(it);
25 }
26 it->Invalidate();
27 it = block->Instructions().erase(it);
28 }
29}
30
31void DeletedPhiArgElimination(IR::Program& program, std::span<const IR::Block*> dead_blocks) {
32 for (IR::Block* const block : program.blocks) {
33 for (IR::Inst& phi : *block) {
34 if (!IR::IsPhi(phi)) {
35 continue;
36 }
37 for (size_t i = 0; i < phi.NumArgs(); ++i) {
38 if (std::ranges::find(dead_blocks, phi.PhiBlock(i)) == dead_blocks.end()) {
39 continue;
40 }
41 // Phi operand at this index is an unreachable block
42 phi.ErasePhiOperand(i);
43 --i;
44 }
45 }
46 }
47}
48
49void DeadBranchElimination(IR::Program& program) {
50 boost::container::small_vector<const IR::Block*, 3> dead_blocks;
51 const auto begin_it{program.syntax_list.begin()};
52 for (auto node_it = begin_it; node_it != program.syntax_list.end(); ++node_it) {
53 if (node_it->type != IR::AbstractSyntaxNode::Type::If) {
54 continue;
55 }
56 IR::Inst* const cond_ref{node_it->data.if_node.cond.Inst()};
57 const IR::U1 cond{cond_ref->Arg(0)};
58 if (!cond.IsImmediate()) {
59 continue;
60 }
61 if (cond.U1()) {
62 continue;
63 }
64 // False immediate condition. Remove condition ref, erase the entire branch.
65 cond_ref->Invalidate();
66 // Account for nested if-statements within the if(false) branch
67 u32 nested_ifs{1u};
68 while (node_it->type != IR::AbstractSyntaxNode::Type::EndIf || nested_ifs > 0) {
69 node_it = program.syntax_list.erase(node_it);
70 switch (node_it->type) {
71 case IR::AbstractSyntaxNode::Type::If:
72 ++nested_ifs;
73 break;
74 case IR::AbstractSyntaxNode::Type::EndIf:
75 --nested_ifs;
76 break;
77 case IR::AbstractSyntaxNode::Type::Block: {
78 IR::Block* const block{node_it->data.block};
79 DeadInstElimination<false>(block);
80 dead_blocks.push_back(block);
81 break;
82 }
83 default:
84 break;
85 } 20 }
86 } 21 }
87 // Erase EndIf node of the if(false) branch
88 node_it = program.syntax_list.erase(node_it);
89 // Account for loop increment
90 --node_it;
91 }
92 if (!dead_blocks.empty()) {
93 DeletedPhiArgElimination(program, std::span(dead_blocks.data(), dead_blocks.size()));
94 }
95}
96} // namespace
97
98void DeadCodeEliminationPass(IR::Program& program) {
99 DeadBranchElimination(program);
100 for (IR::Block* const block : program.post_order_blocks) {
101 DeadInstElimination<true>(block);
102 } 22 }
103} 23}
104 24
diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h
index dcb5ab158..549b81ef7 100644
--- a/src/shader_recompiler/runtime_info.h
+++ b/src/shader_recompiler/runtime_info.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <array> 6#include <array>
7#include <map>
7#include <optional> 8#include <optional>
8#include <vector> 9#include <vector>
9 10
@@ -60,6 +61,7 @@ struct TransformFeedbackVarying {
60struct RuntimeInfo { 61struct RuntimeInfo {
61 std::array<AttributeType, 32> generic_input_types{}; 62 std::array<AttributeType, 32> generic_input_types{};
62 VaryingState previous_stage_stores; 63 VaryingState previous_stage_stores;
64 std::map<IR::Attribute, IR::Attribute> previous_stage_legacy_stores_mapping;
63 65
64 bool convert_depth_mode{}; 66 bool convert_depth_mode{};
65 bool force_early_z{}; 67 bool force_early_z{};
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h
index cc596da4f..81097bf1a 100644
--- a/src/shader_recompiler/shader_info.h
+++ b/src/shader_recompiler/shader_info.h
@@ -5,6 +5,7 @@
5 5
6#include <array> 6#include <array>
7#include <bitset> 7#include <bitset>
8#include <map>
8 9
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "shader_recompiler/frontend/ir/type.h" 11#include "shader_recompiler/frontend/ir/type.h"
@@ -127,6 +128,8 @@ struct Info {
127 VaryingState stores; 128 VaryingState stores;
128 VaryingState passthrough; 129 VaryingState passthrough;
129 130
131 std::map<IR::Attribute, IR::Attribute> legacy_stores_mapping;
132
130 bool loads_indexed_attributes{}; 133 bool loads_indexed_attributes{};
131 134
132 std::array<bool, 8> stores_frag_color{}; 135 std::array<bool, 8> stores_frag_color{};
diff --git a/src/tests/video_core/buffer_base.cpp b/src/tests/video_core/buffer_base.cpp
index 71121e42a..f7236afab 100644
--- a/src/tests/video_core/buffer_base.cpp
+++ b/src/tests/video_core/buffer_base.cpp
@@ -44,7 +44,7 @@ public:
44 44
45 [[nodiscard]] unsigned Count() const noexcept { 45 [[nodiscard]] unsigned Count() const noexcept {
46 unsigned count = 0; 46 unsigned count = 0;
47 for (const auto [index, value] : page_table) { 47 for (const auto& [index, value] : page_table) {
48 count += value; 48 count += value;
49 } 49 }
50 return count; 50 return count;
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index cb8b46edf..106991969 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -279,14 +279,8 @@ if (MSVC)
279else() 279else()
280 target_compile_options(video_core PRIVATE 280 target_compile_options(video_core PRIVATE
281 -Werror=conversion 281 -Werror=conversion
282 -Wno-error=sign-conversion
283 -Werror=pessimizing-move
284 -Werror=redundant-move
285 -Werror=type-limits
286 282
287 $<$<CXX_COMPILER_ID:GNU>:-Werror=class-memaccess> 283 -Wno-sign-conversion
288 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-parameter>
289 $<$<CXX_COMPILER_ID:GNU>:-Werror=unused-but-set-variable>
290 ) 284 )
291endif() 285endif()
292 286
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 89a9d1f5a..f9794dfe4 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -117,10 +117,15 @@ void Maxwell3D::InitializeRegisterDefaults() {
117 117
118 shadow_state = regs; 118 shadow_state = regs;
119 119
120 mme_inline[MAXWELL3D_REG_INDEX(draw.end)] = true; 120 draw_command[MAXWELL3D_REG_INDEX(draw.end)] = true;
121 mme_inline[MAXWELL3D_REG_INDEX(draw.begin)] = true; 121 draw_command[MAXWELL3D_REG_INDEX(draw.begin)] = true;
122 mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; 122 draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.first)] = true;
123 mme_inline[MAXWELL3D_REG_INDEX(index_buffer.count)] = true; 123 draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
124 draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true;
125 draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true;
126 draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;
127 draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;
128 draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true;
124} 129}
125 130
126void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { 131void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) {
@@ -208,25 +213,21 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume
208 return ProcessCBBind(3); 213 return ProcessCBBind(3);
209 case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): 214 case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config):
210 return ProcessCBBind(4); 215 return ProcessCBBind(4);
211 case MAXWELL3D_REG_INDEX(draw.end):
212 return DrawArrays();
213 case MAXWELL3D_REG_INDEX(index_buffer32_first): 216 case MAXWELL3D_REG_INDEX(index_buffer32_first):
214 regs.index_buffer.count = regs.index_buffer32_first.count; 217 regs.index_buffer.count = regs.index_buffer32_first.count;
215 regs.index_buffer.first = regs.index_buffer32_first.first; 218 regs.index_buffer.first = regs.index_buffer32_first.first;
216 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 219 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
217 return DrawArrays(); 220 return ProcessDraw();
218 case MAXWELL3D_REG_INDEX(index_buffer16_first): 221 case MAXWELL3D_REG_INDEX(index_buffer16_first):
219 regs.index_buffer.count = regs.index_buffer16_first.count; 222 regs.index_buffer.count = regs.index_buffer16_first.count;
220 regs.index_buffer.first = regs.index_buffer16_first.first; 223 regs.index_buffer.first = regs.index_buffer16_first.first;
221 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 224 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
222 return DrawArrays(); 225 return ProcessDraw();
223 case MAXWELL3D_REG_INDEX(index_buffer8_first): 226 case MAXWELL3D_REG_INDEX(index_buffer8_first):
224 regs.index_buffer.count = regs.index_buffer8_first.count; 227 regs.index_buffer.count = regs.index_buffer8_first.count;
225 regs.index_buffer.first = regs.index_buffer8_first.first; 228 regs.index_buffer.first = regs.index_buffer8_first.first;
226 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 229 dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
227 // a macro calls this one over and over, should it increase instancing? 230 return ProcessDraw();
228 // Used by Hades and likely other Vulkan games.
229 return DrawArrays();
230 case MAXWELL3D_REG_INDEX(topology_override): 231 case MAXWELL3D_REG_INDEX(topology_override):
231 use_topology_override = true; 232 use_topology_override = true;
232 return; 233 return;
@@ -261,14 +262,13 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters)
261 262
262 // Execute the current macro. 263 // Execute the current macro.
263 macro_engine->Execute(macro_positions[entry], parameters); 264 macro_engine->Execute(macro_positions[entry], parameters);
264 if (mme_draw.current_mode != MMEDrawMode::Undefined) { 265
265 FlushMMEInlineDraw(); 266 ProcessDeferredDraw();
266 }
267} 267}
268 268
269void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { 269void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
270 // It is an error to write to a register other than the current macro's ARG register before it 270 // It is an error to write to a register other than the current macro's ARG register before
271 // has finished execution. 271 // it has finished execution.
272 if (executing_macro != 0) { 272 if (executing_macro != 0) {
273 ASSERT(method == executing_macro + 1); 273 ASSERT(method == executing_macro + 1);
274 } 274 }
@@ -283,9 +283,33 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {
283 ASSERT_MSG(method < Regs::NUM_REGS, 283 ASSERT_MSG(method < Regs::NUM_REGS,
284 "Invalid Maxwell3D register, increase the size of the Regs structure"); 284 "Invalid Maxwell3D register, increase the size of the Regs structure");
285 285
286 const u32 argument = ProcessShadowRam(method, method_argument); 286 if (draw_command[method]) {
287 ProcessDirtyRegisters(method, argument); 287 regs.reg_array[method] = method_argument;
288 ProcessMethodCall(method, argument, method_argument, is_last_call); 288 deferred_draw_method.push_back(method);
289 auto u32_to_u8 = [&](const u32 argument) {
290 inline_index_draw_indexes.push_back(static_cast<u8>(argument & 0x000000ff));
291 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x0000ff00) >> 8));
292 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x00ff0000) >> 16));
293 inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0xff000000) >> 24));
294 };
295 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method) {
296 u32_to_u8(method_argument);
297 } else if (MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method) {
298 u32_to_u8(regs.inline_index_2x16.even);
299 u32_to_u8(regs.inline_index_2x16.odd);
300 } else if (MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
301 u32_to_u8(regs.inline_index_4x8.index0);
302 u32_to_u8(regs.inline_index_4x8.index1);
303 u32_to_u8(regs.inline_index_4x8.index2);
304 u32_to_u8(regs.inline_index_4x8.index3);
305 }
306 } else {
307 ProcessDeferredDraw();
308
309 const u32 argument = ProcessShadowRam(method, method_argument);
310 ProcessDirtyRegisters(method, argument);
311 ProcessMethodCall(method, argument, method_argument, is_last_call);
312 }
289} 313}
290 314
291void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount, 315void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
@@ -326,55 +350,6 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,
326 } 350 }
327} 351}
328 352
329void Maxwell3D::StepInstance(const MMEDrawMode expected_mode, const u32 count) {
330 if (mme_draw.current_mode == MMEDrawMode::Undefined) {
331 if (mme_draw.gl_begin_consume) {
332 mme_draw.current_mode = expected_mode;
333 mme_draw.current_count = count;
334 mme_draw.instance_count = 1;
335 mme_draw.gl_begin_consume = false;
336 mme_draw.gl_end_count = 0;
337 }
338 return;
339 } else {
340 if (mme_draw.current_mode == expected_mode && count == mme_draw.current_count &&
341 mme_draw.instance_mode && mme_draw.gl_begin_consume) {
342 mme_draw.instance_count++;
343 mme_draw.gl_begin_consume = false;
344 return;
345 } else {
346 FlushMMEInlineDraw();
347 }
348 }
349 // Tail call in case it needs to retry.
350 StepInstance(expected_mode, count);
351}
352
353void Maxwell3D::CallMethodFromMME(u32 method, u32 method_argument) {
354 if (mme_inline[method]) {
355 regs.reg_array[method] = method_argument;
356 if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count) ||
357 method == MAXWELL3D_REG_INDEX(index_buffer.count)) {
358 const MMEDrawMode expected_mode = method == MAXWELL3D_REG_INDEX(vertex_buffer.count)
359 ? MMEDrawMode::Array
360 : MMEDrawMode::Indexed;
361 StepInstance(expected_mode, method_argument);
362 } else if (method == MAXWELL3D_REG_INDEX(draw.begin)) {
363 mme_draw.instance_mode =
364 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
365 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged);
366 mme_draw.gl_begin_consume = true;
367 } else {
368 mme_draw.gl_end_count++;
369 }
370 } else {
371 if (mme_draw.current_mode != MMEDrawMode::Undefined) {
372 FlushMMEInlineDraw();
373 }
374 CallMethod(method, method_argument, true);
375 }
376}
377
378void Maxwell3D::ProcessTopologyOverride() { 353void Maxwell3D::ProcessTopologyOverride() {
379 using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology; 354 using PrimitiveTopology = Maxwell3D::Regs::PrimitiveTopology;
380 using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride; 355 using PrimitiveTopologyOverride = Maxwell3D::Regs::PrimitiveTopologyOverride;
@@ -404,41 +379,6 @@ void Maxwell3D::ProcessTopologyOverride() {
404 } 379 }
405} 380}
406 381
407void Maxwell3D::FlushMMEInlineDraw() {
408 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
409 regs.vertex_buffer.count);
410 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
411 ASSERT(mme_draw.instance_count == mme_draw.gl_end_count);
412
413 // Both instance configuration registers can not be set at the same time.
414 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
415 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
416 "Illegal combination of instancing parameters");
417
418 ProcessTopologyOverride();
419
420 const bool is_indexed = mme_draw.current_mode == MMEDrawMode::Indexed;
421 if (ShouldExecute()) {
422 rasterizer->Draw(is_indexed, true);
423 }
424
425 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
426 // the game is trying to draw indexed or direct mode. This needs to be verified on HW still -
427 // it's possible that it is incorrect and that there is some other register used to specify the
428 // drawing mode.
429 if (is_indexed) {
430 regs.index_buffer.count = 0;
431 } else {
432 regs.vertex_buffer.count = 0;
433 }
434 mme_draw.current_mode = MMEDrawMode::Undefined;
435 mme_draw.current_count = 0;
436 mme_draw.instance_count = 0;
437 mme_draw.instance_mode = false;
438 mme_draw.gl_begin_consume = false;
439 mme_draw.gl_end_count = 0;
440}
441
442void Maxwell3D::ProcessMacroUpload(u32 data) { 382void Maxwell3D::ProcessMacroUpload(u32 data) {
443 macro_engine->AddCode(regs.load_mme.instruction_ptr++, data); 383 macro_engine->AddCode(regs.load_mme.instruction_ptr++, data);
444} 384}
@@ -473,9 +413,7 @@ void Maxwell3D::ProcessQueryGet() {
473 413
474 switch (regs.report_semaphore.query.operation) { 414 switch (regs.report_semaphore.query.operation) {
475 case Regs::ReportSemaphore::Operation::Release: 415 case Regs::ReportSemaphore::Operation::Release:
476 if (regs.report_semaphore.query.release == 416 if (regs.report_semaphore.query.short_query != 0) {
477 Regs::ReportSemaphore::Release::AfterAllPreceedingWrites ||
478 regs.report_semaphore.query.short_query != 0) {
479 const GPUVAddr sequence_address{regs.report_semaphore.Address()}; 417 const GPUVAddr sequence_address{regs.report_semaphore.Address()};
480 const u32 payload = regs.report_semaphore.payload; 418 const u32 payload = regs.report_semaphore.payload;
481 std::function<void()> operation([this, sequence_address, payload] { 419 std::function<void()> operation([this, sequence_address, payload] {
@@ -489,11 +427,10 @@ void Maxwell3D::ProcessQueryGet() {
489 }; 427 };
490 const GPUVAddr sequence_address{regs.report_semaphore.Address()}; 428 const GPUVAddr sequence_address{regs.report_semaphore.Address()};
491 const u32 payload = regs.report_semaphore.payload; 429 const u32 payload = regs.report_semaphore.payload;
492 std::function<void()> operation([this, sequence_address, payload] { 430 [this, sequence_address, payload] {
493 memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks()); 431 memory_manager.Write<u64>(sequence_address + sizeof(u64), system.GPU().GetTicks());
494 memory_manager.Write<u64>(sequence_address, payload); 432 memory_manager.Write<u64>(sequence_address, payload);
495 }); 433 }();
496 rasterizer->SyncOperation(std::move(operation));
497 } 434 }
498 break; 435 break;
499 case Regs::ReportSemaphore::Operation::Acquire: 436 case Regs::ReportSemaphore::Operation::Acquire:
@@ -569,47 +506,11 @@ void Maxwell3D::ProcessCounterReset() {
569 506
570void Maxwell3D::ProcessSyncPoint() { 507void Maxwell3D::ProcessSyncPoint() {
571 const u32 sync_point = regs.sync_info.sync_point.Value(); 508 const u32 sync_point = regs.sync_info.sync_point.Value();
572 const auto condition = regs.sync_info.condition.Value(); 509 const u32 cache_flush = regs.sync_info.clean_l2.Value();
573 [[maybe_unused]] const u32 cache_flush = regs.sync_info.clean_l2.Value(); 510 if (cache_flush != 0) {
574 if (condition == Regs::SyncInfo::Condition::RopWritesDone) { 511 rasterizer->InvalidateGPUCache();
575 rasterizer->SignalSyncPoint(sync_point);
576 }
577}
578
579void Maxwell3D::DrawArrays() {
580 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
581 regs.vertex_buffer.count);
582 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
583
584 // Both instance configuration registers can not be set at the same time.
585 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
586 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
587 "Illegal combination of instancing parameters");
588
589 ProcessTopologyOverride();
590
591 if (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) {
592 // Increment the current instance *before* drawing.
593 state.current_instance++;
594 } else if (regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged) {
595 // Reset the current instance to 0.
596 state.current_instance = 0;
597 }
598
599 const bool is_indexed{regs.index_buffer.count && !regs.vertex_buffer.count};
600 if (ShouldExecute()) {
601 rasterizer->Draw(is_indexed, false);
602 }
603
604 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
605 // the game is trying to draw indexed or direct mode. This needs to be verified on HW still -
606 // it's possible that it is incorrect and that there is some other register used to specify the
607 // drawing mode.
608 if (is_indexed) {
609 regs.index_buffer.count = 0;
610 } else {
611 regs.vertex_buffer.count = 0;
612 } 512 }
513 rasterizer->SignalSyncPoint(sync_point);
613} 514}
614 515
615std::optional<u64> Maxwell3D::GetQueryResult() { 516std::optional<u64> Maxwell3D::GetQueryResult() {
@@ -694,4 +595,90 @@ void Maxwell3D::ProcessClearBuffers() {
694 rasterizer->Clear(); 595 rasterizer->Clear();
695} 596}
696 597
598void Maxwell3D::ProcessDraw(u32 instance_count) {
599 LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(),
600 regs.vertex_buffer.count);
601
602 ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?");
603
604 // Both instance configuration registers can not be set at the same time.
605 ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First ||
606 regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged,
607 "Illegal combination of instancing parameters");
608
609 ProcessTopologyOverride();
610
611 const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count;
612 if (ShouldExecute()) {
613 rasterizer->Draw(is_indexed, instance_count);
614 }
615
616 if (is_indexed) {
617 regs.index_buffer.count = 0;
618 } else {
619 regs.vertex_buffer.count = 0;
620 }
621}
622
623void Maxwell3D::ProcessDeferredDraw() {
624 if (deferred_draw_method.empty()) {
625 return;
626 }
627
628 enum class DrawMode {
629 Undefined,
630 General,
631 Instance,
632 };
633 DrawMode draw_mode{DrawMode::Undefined};
634 u32 instance_count = 1;
635
636 u32 index = 0;
637 u32 method = 0;
638 u32 method_count = static_cast<u32>(deferred_draw_method.size());
639 for (; index < method_count &&
640 (method = deferred_draw_method[index]) != MAXWELL3D_REG_INDEX(draw.begin);
641 ++index)
642 ;
643
644 if (MAXWELL3D_REG_INDEX(draw.begin) != method) {
645 return;
646 }
647
648 // The minimum number of methods for drawing must be greater than or equal to
649 // 3[draw.begin->vertex(index)count(first)->draw.end] to avoid errors in index mode drawing
650 if ((method_count - index) < 3) {
651 return;
652 }
653 draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) ||
654 (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged)
655 ? DrawMode::Instance
656 : DrawMode::General;
657
658 // Drawing will only begin with draw.begin or index_buffer method, other methods directly
659 // clear
660 if (draw_mode == DrawMode::Undefined) {
661 deferred_draw_method.clear();
662 return;
663 }
664
665 if (draw_mode == DrawMode::Instance) {
666 ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error");
667 instance_count = static_cast<u32>(method_count - index) / 4;
668 } else {
669 method = deferred_draw_method[index + 1];
670 if (MAXWELL3D_REG_INDEX(draw_inline_index) == method ||
671 MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method ||
672 MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) {
673 regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4);
674 regs.index_buffer.format = Regs::IndexFormat::UnsignedInt;
675 }
676 }
677
678 ProcessDraw(instance_count);
679
680 deferred_draw_method.clear();
681 inline_index_draw_indexes.clear();
682}
683
697} // namespace Tegra::Engines 684} // namespace Tegra::Engines
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 75e3b868d..a948fcb14 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1739,14 +1739,11 @@ public:
1739 Footprint_1x1_Virtual = 2, 1739 Footprint_1x1_Virtual = 2,
1740 }; 1740 };
1741 1741
1742 struct InlineIndex4x8Align { 1742 struct InlineIndex4x8 {
1743 union { 1743 union {
1744 BitField<0, 30, u32> count; 1744 BitField<0, 30, u32> count;
1745 BitField<30, 2, u32> start; 1745 BitField<30, 2, u32> start;
1746 }; 1746 };
1747 };
1748
1749 struct InlineIndex4x8Index {
1750 union { 1747 union {
1751 BitField<0, 8, u32> index0; 1748 BitField<0, 8, u32> index0;
1752 BitField<8, 8, u32> index1; 1749 BitField<8, 8, u32> index1;
@@ -2836,8 +2833,7 @@ public:
2836 u32 depth_write_enabled; ///< 0x12E8 2833 u32 depth_write_enabled; ///< 0x12E8
2837 u32 alpha_test_enabled; ///< 0x12EC 2834 u32 alpha_test_enabled; ///< 0x12EC
2838 INSERT_PADDING_BYTES_NOINIT(0x10); 2835 INSERT_PADDING_BYTES_NOINIT(0x10);
2839 InlineIndex4x8Align inline_index_4x8_align; ///< 0x1300 2836 InlineIndex4x8 inline_index_4x8; ///< 0x1300
2840 InlineIndex4x8Index inline_index_4x8_index; ///< 0x1304
2841 D3DCullMode d3d_cull_mode; ///< 0x1308 2837 D3DCullMode d3d_cull_mode; ///< 0x1308
2842 ComparisonOp depth_test_func; ///< 0x130C 2838 ComparisonOp depth_test_func; ///< 0x130C
2843 f32 alpha_test_ref; ///< 0x1310 2839 f32 alpha_test_ref; ///< 0x1310
@@ -3048,8 +3044,6 @@ public:
3048 }; 3044 };
3049 3045
3050 std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages; 3046 std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages;
3051
3052 u32 current_instance = 0; ///< Current instance to be used to simulate instanced rendering.
3053 }; 3047 };
3054 3048
3055 State state{}; 3049 State state{};
@@ -3064,11 +3058,6 @@ public:
3064 void CallMultiMethod(u32 method, const u32* base_start, u32 amount, 3058 void CallMultiMethod(u32 method, const u32* base_start, u32 amount,
3065 u32 methods_pending) override; 3059 u32 methods_pending) override;
3066 3060
3067 /// Write the value to the register identified by method.
3068 void CallMethodFromMME(u32 method, u32 method_argument);
3069
3070 void FlushMMEInlineDraw();
3071
3072 bool ShouldExecute() const { 3061 bool ShouldExecute() const {
3073 return execute_on; 3062 return execute_on;
3074 } 3063 }
@@ -3081,21 +3070,6 @@ public:
3081 return *rasterizer; 3070 return *rasterizer;
3082 } 3071 }
3083 3072
3084 enum class MMEDrawMode : u32 {
3085 Undefined,
3086 Array,
3087 Indexed,
3088 };
3089
3090 struct MMEDrawState {
3091 MMEDrawMode current_mode{MMEDrawMode::Undefined};
3092 u32 current_count{};
3093 u32 instance_count{};
3094 bool instance_mode{};
3095 bool gl_begin_consume{};
3096 u32 gl_end_count{};
3097 } mme_draw;
3098
3099 struct DirtyState { 3073 struct DirtyState {
3100 using Flags = std::bitset<std::numeric_limits<u8>::max()>; 3074 using Flags = std::bitset<std::numeric_limits<u8>::max()>;
3101 using Table = std::array<u8, Regs::NUM_REGS>; 3075 using Table = std::array<u8, Regs::NUM_REGS>;
@@ -3105,6 +3079,8 @@ public:
3105 Tables tables{}; 3079 Tables tables{};
3106 } dirty; 3080 } dirty;
3107 3081
3082 std::vector<u8> inline_index_draw_indexes;
3083
3108private: 3084private:
3109 void InitializeRegisterDefaults(); 3085 void InitializeRegisterDefaults();
3110 3086
@@ -3164,14 +3140,12 @@ private:
3164 /// Handles a write to the CB_BIND register. 3140 /// Handles a write to the CB_BIND register.
3165 void ProcessCBBind(size_t stage_index); 3141 void ProcessCBBind(size_t stage_index);
3166 3142
3167 /// Handles a write to the VERTEX_END_GL register, triggering a draw.
3168 void DrawArrays();
3169
3170 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) 3143 /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro)
3171 void ProcessTopologyOverride(); 3144 void ProcessTopologyOverride();
3172 3145
3173 // Handles a instance drawcall from MME 3146 void ProcessDraw(u32 instance_count = 1);
3174 void StepInstance(MMEDrawMode expected_mode, u32 count); 3147
3148 void ProcessDeferredDraw();
3175 3149
3176 /// Returns a query's value or an empty object if the value will be deferred through a cache. 3150 /// Returns a query's value or an empty object if the value will be deferred through a cache.
3177 std::optional<u64> GetQueryResult(); 3151 std::optional<u64> GetQueryResult();
@@ -3184,8 +3158,6 @@ private:
3184 /// Start offsets of each macro in macro_memory 3158 /// Start offsets of each macro in macro_memory
3185 std::array<u32, 0x80> macro_positions{}; 3159 std::array<u32, 0x80> macro_positions{};
3186 3160
3187 std::array<bool, Regs::NUM_REGS> mme_inline{};
3188
3189 /// Macro method that is currently being executed / being fed parameters. 3161 /// Macro method that is currently being executed / being fed parameters.
3190 u32 executing_macro = 0; 3162 u32 executing_macro = 0;
3191 /// Parameters that have been submitted to the macro call so far. 3163 /// Parameters that have been submitted to the macro call so far.
@@ -3198,6 +3170,9 @@ private:
3198 3170
3199 bool execute_on{true}; 3171 bool execute_on{true};
3200 bool use_topology_override{false}; 3172 bool use_topology_override{false};
3173
3174 std::array<bool, Regs::NUM_REGS> draw_command{};
3175 std::vector<u32> deferred_draw_method;
3201}; 3176};
3202 3177
3203#define ASSERT_REG_POSITION(field_name, position) \ 3178#define ASSERT_REG_POSITION(field_name, position) \
@@ -3402,8 +3377,7 @@ ASSERT_REG_POSITION(alpha_to_coverage_dither, 0x12E0);
3402ASSERT_REG_POSITION(blend_per_target_enabled, 0x12E4); 3377ASSERT_REG_POSITION(blend_per_target_enabled, 0x12E4);
3403ASSERT_REG_POSITION(depth_write_enabled, 0x12E8); 3378ASSERT_REG_POSITION(depth_write_enabled, 0x12E8);
3404ASSERT_REG_POSITION(alpha_test_enabled, 0x12EC); 3379ASSERT_REG_POSITION(alpha_test_enabled, 0x12EC);
3405ASSERT_REG_POSITION(inline_index_4x8_align, 0x1300); 3380ASSERT_REG_POSITION(inline_index_4x8, 0x1300);
3406ASSERT_REG_POSITION(inline_index_4x8_index, 0x1304);
3407ASSERT_REG_POSITION(d3d_cull_mode, 0x1308); 3381ASSERT_REG_POSITION(d3d_cull_mode, 0x1308);
3408ASSERT_REG_POSITION(depth_test_func, 0x130C); 3382ASSERT_REG_POSITION(depth_test_func, 0x130C);
3409ASSERT_REG_POSITION(alpha_test_ref, 0x1310); 3383ASSERT_REG_POSITION(alpha_test_ref, 0x1310);
diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp
index cca890792..3977bb0fb 100644
--- a/src/video_core/engines/puller.cpp
+++ b/src/video_core/engines/puller.cpp
@@ -75,11 +75,10 @@ void Puller::ProcessSemaphoreTriggerMethod() {
75 if (op == GpuSemaphoreOperation::WriteLong) { 75 if (op == GpuSemaphoreOperation::WriteLong) {
76 const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()}; 76 const GPUVAddr sequence_address{regs.semaphore_address.SemaphoreAddress()};
77 const u32 payload = regs.semaphore_sequence; 77 const u32 payload = regs.semaphore_sequence;
78 std::function<void()> operation([this, sequence_address, payload] { 78 [this, sequence_address, payload] {
79 memory_manager.Write<u64>(sequence_address + sizeof(u64), gpu.GetTicks()); 79 memory_manager.Write<u64>(sequence_address + sizeof(u64), gpu.GetTicks());
80 memory_manager.Write<u64>(sequence_address, payload); 80 memory_manager.Write<u64>(sequence_address, payload);
81 }); 81 }();
82 rasterizer->SignalFence(std::move(operation));
83 } else { 82 } else {
84 do { 83 do {
85 const u32 word{memory_manager.Read<u32>(regs.semaphore_address.SemaphoreAddress())}; 84 const u32 word{memory_manager.Read<u32>(regs.semaphore_address.SemaphoreAddress())};
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp
index 8a8adbb42..f896591bf 100644
--- a/src/video_core/macro/macro_hle.cpp
+++ b/src/video_core/macro/macro_hle.cpp
@@ -22,35 +22,29 @@ void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
22 maxwell3d.regs.draw.topology.Assign( 22 maxwell3d.regs.draw.topology.Assign(
23 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff)); 23 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0x3ffffff));
24 maxwell3d.regs.global_base_instance_index = parameters[5]; 24 maxwell3d.regs.global_base_instance_index = parameters[5];
25 maxwell3d.mme_draw.instance_count = instance_count;
26 maxwell3d.regs.global_base_vertex_index = parameters[3]; 25 maxwell3d.regs.global_base_vertex_index = parameters[3];
27 maxwell3d.regs.index_buffer.count = parameters[1]; 26 maxwell3d.regs.index_buffer.count = parameters[1];
28 maxwell3d.regs.index_buffer.first = parameters[4]; 27 maxwell3d.regs.index_buffer.first = parameters[4];
29 28
30 if (maxwell3d.ShouldExecute()) { 29 if (maxwell3d.ShouldExecute()) {
31 maxwell3d.Rasterizer().Draw(true, true); 30 maxwell3d.Rasterizer().Draw(true, instance_count);
32 } 31 }
33 maxwell3d.regs.index_buffer.count = 0; 32 maxwell3d.regs.index_buffer.count = 0;
34 maxwell3d.mme_draw.instance_count = 0;
35 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
36} 33}
37 34
38void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { 35void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
39 const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); 36 const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]);
40 37
41 maxwell3d.regs.vertex_buffer.first = parameters[3]; 38 maxwell3d.regs.vertex_buffer.first = parameters[3];
42 maxwell3d.regs.vertex_buffer.count = parameters[1]; 39 maxwell3d.regs.vertex_buffer.count = parameters[1];
43 maxwell3d.regs.global_base_instance_index = parameters[4]; 40 maxwell3d.regs.global_base_instance_index = parameters[4];
44 maxwell3d.regs.draw.topology.Assign( 41 maxwell3d.regs.draw.topology.Assign(
45 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); 42 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
46 maxwell3d.mme_draw.instance_count = count;
47 43
48 if (maxwell3d.ShouldExecute()) { 44 if (maxwell3d.ShouldExecute()) {
49 maxwell3d.Rasterizer().Draw(false, true); 45 maxwell3d.Rasterizer().Draw(false, instance_count);
50 } 46 }
51 maxwell3d.regs.vertex_buffer.count = 0; 47 maxwell3d.regs.vertex_buffer.count = 0;
52 maxwell3d.mme_draw.instance_count = 0;
53 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
54} 48}
55 49
56void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) { 50void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters) {
@@ -63,24 +57,21 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
63 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 57 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
64 maxwell3d.regs.global_base_vertex_index = element_base; 58 maxwell3d.regs.global_base_vertex_index = element_base;
65 maxwell3d.regs.global_base_instance_index = base_instance; 59 maxwell3d.regs.global_base_instance_index = base_instance;
66 maxwell3d.mme_draw.instance_count = instance_count; 60 maxwell3d.CallMethod(0x8e3, 0x640, true);
67 maxwell3d.CallMethodFromMME(0x8e3, 0x640); 61 maxwell3d.CallMethod(0x8e4, element_base, true);
68 maxwell3d.CallMethodFromMME(0x8e4, element_base); 62 maxwell3d.CallMethod(0x8e5, base_instance, true);
69 maxwell3d.CallMethodFromMME(0x8e5, base_instance);
70 maxwell3d.regs.draw.topology.Assign( 63 maxwell3d.regs.draw.topology.Assign(
71 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); 64 static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0]));
72 if (maxwell3d.ShouldExecute()) { 65 if (maxwell3d.ShouldExecute()) {
73 maxwell3d.Rasterizer().Draw(true, true); 66 maxwell3d.Rasterizer().Draw(true, instance_count);
74 } 67 }
75 maxwell3d.regs.vertex_id_base = 0x0; 68 maxwell3d.regs.vertex_id_base = 0x0;
76 maxwell3d.regs.index_buffer.count = 0; 69 maxwell3d.regs.index_buffer.count = 0;
77 maxwell3d.regs.global_base_vertex_index = 0x0; 70 maxwell3d.regs.global_base_vertex_index = 0x0;
78 maxwell3d.regs.global_base_instance_index = 0x0; 71 maxwell3d.regs.global_base_instance_index = 0x0;
79 maxwell3d.mme_draw.instance_count = 0; 72 maxwell3d.CallMethod(0x8e3, 0x640, true);
80 maxwell3d.CallMethodFromMME(0x8e3, 0x640); 73 maxwell3d.CallMethod(0x8e4, 0x0, true);
81 maxwell3d.CallMethodFromMME(0x8e4, 0x0); 74 maxwell3d.CallMethod(0x8e5, 0x0, true);
82 maxwell3d.CallMethodFromMME(0x8e5, 0x0);
83 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
84} 75}
85 76
86// Multidraw Indirect 77// Multidraw Indirect
@@ -91,11 +82,9 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
91 maxwell3d.regs.index_buffer.count = 0; 82 maxwell3d.regs.index_buffer.count = 0;
92 maxwell3d.regs.global_base_vertex_index = 0x0; 83 maxwell3d.regs.global_base_vertex_index = 0x0;
93 maxwell3d.regs.global_base_instance_index = 0x0; 84 maxwell3d.regs.global_base_instance_index = 0x0;
94 maxwell3d.mme_draw.instance_count = 0; 85 maxwell3d.CallMethod(0x8e3, 0x640, true);
95 maxwell3d.CallMethodFromMME(0x8e3, 0x640); 86 maxwell3d.CallMethod(0x8e4, 0x0, true);
96 maxwell3d.CallMethodFromMME(0x8e4, 0x0); 87 maxwell3d.CallMethod(0x8e5, 0x0, true);
97 maxwell3d.CallMethodFromMME(0x8e5, 0x0);
98 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
99 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 88 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
100 }); 89 });
101 const u32 start_indirect = parameters[0]; 90 const u32 start_indirect = parameters[0];
@@ -127,15 +116,13 @@ void HLE_3F5E74B9C9A50164(Engines::Maxwell3D& maxwell3d, const std::vector<u32>&
127 maxwell3d.regs.index_buffer.count = num_vertices; 116 maxwell3d.regs.index_buffer.count = num_vertices;
128 maxwell3d.regs.global_base_vertex_index = base_vertex; 117 maxwell3d.regs.global_base_vertex_index = base_vertex;
129 maxwell3d.regs.global_base_instance_index = base_instance; 118 maxwell3d.regs.global_base_instance_index = base_instance;
130 maxwell3d.mme_draw.instance_count = instance_count; 119 maxwell3d.CallMethod(0x8e3, 0x640, true);
131 maxwell3d.CallMethodFromMME(0x8e3, 0x640); 120 maxwell3d.CallMethod(0x8e4, base_vertex, true);
132 maxwell3d.CallMethodFromMME(0x8e4, base_vertex); 121 maxwell3d.CallMethod(0x8e5, base_instance, true);
133 maxwell3d.CallMethodFromMME(0x8e5, base_instance);
134 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; 122 maxwell3d.dirty.flags[VideoCommon::Dirty::IndexBuffer] = true;
135 if (maxwell3d.ShouldExecute()) { 123 if (maxwell3d.ShouldExecute()) {
136 maxwell3d.Rasterizer().Draw(true, true); 124 maxwell3d.Rasterizer().Draw(true, instance_count);
137 } 125 }
138 maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined;
139 } 126 }
140} 127}
141 128
diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp
index f670b1bca..c0d32c112 100644
--- a/src/video_core/macro/macro_interpreter.cpp
+++ b/src/video_core/macro/macro_interpreter.cpp
@@ -335,7 +335,7 @@ void MacroInterpreterImpl::SetMethodAddress(u32 address) {
335} 335}
336 336
337void MacroInterpreterImpl::Send(u32 value) { 337void MacroInterpreterImpl::Send(u32 value) {
338 maxwell3d.CallMethodFromMME(method_address.address, value); 338 maxwell3d.CallMethod(method_address.address, value, true);
339 // Increment the method address by the method increment. 339 // Increment the method address by the method increment.
340 method_address.address.Assign(method_address.address.Value() + 340 method_address.address.Assign(method_address.address.Value() +
341 method_address.increment.Value()); 341 method_address.increment.Value());
diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp
index a302a9603..25c1ce798 100644
--- a/src/video_core/macro/macro_jit_x64.cpp
+++ b/src/video_core/macro/macro_jit_x64.cpp
@@ -346,7 +346,7 @@ void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) {
346} 346}
347 347
348void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { 348void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) {
349 maxwell3d->CallMethodFromMME(method_address.address, value); 349 maxwell3d->CallMethod(method_address.address, value, true);
350} 350}
351 351
352void MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { 352void MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) {
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index d07b21bd6..384350dbd 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -133,7 +133,7 @@ inline void MemoryManager::SetBigPageContinous(size_t big_page_index, bool value
133template <MemoryManager::EntryType entry_type> 133template <MemoryManager::EntryType entry_type>
134GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size, 134GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size,
135 PTEKind kind) { 135 PTEKind kind) {
136 u64 remaining_size{size}; 136 [[maybe_unused]] u64 remaining_size{size};
137 if constexpr (entry_type == EntryType::Mapped) { 137 if constexpr (entry_type == EntryType::Mapped) {
138 page_table.ReserveRange(gpu_addr, size); 138 page_table.ReserveRange(gpu_addr, size);
139 } 139 }
@@ -159,7 +159,7 @@ GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cp
159template <MemoryManager::EntryType entry_type> 159template <MemoryManager::EntryType entry_type>
160GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, 160GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr,
161 size_t size, PTEKind kind) { 161 size_t size, PTEKind kind) {
162 u64 remaining_size{size}; 162 [[maybe_unused]] u64 remaining_size{size};
163 for (u64 offset{}; offset < size; offset += big_page_size) { 163 for (u64 offset{}; offset < size; offset += big_page_size) {
164 const GPUVAddr current_gpu_addr = gpu_addr + offset; 164 const GPUVAddr current_gpu_addr = gpu_addr + offset;
165 [[maybe_unused]] const auto current_entry_type = GetEntry<true>(current_gpu_addr); 165 [[maybe_unused]] const auto current_entry_type = GetEntry<true>(current_gpu_addr);
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index d2d40884c..1cbfef090 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -40,7 +40,7 @@ public:
40 virtual ~RasterizerInterface() = default; 40 virtual ~RasterizerInterface() = default;
41 41
42 /// Dispatches a draw invocation 42 /// Dispatches a draw invocation
43 virtual void Draw(bool is_indexed, bool is_instanced) = 0; 43 virtual void Draw(bool is_indexed, u32 instance_count) = 0;
44 44
45 /// Clear the current framebuffer 45 /// Clear the current framebuffer
46 virtual void Clear() = 0; 46 virtual void Clear() = 0;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index e5c09a969..1590b21de 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -205,7 +205,7 @@ void RasterizerOpenGL::Clear() {
205 ++num_queued_commands; 205 ++num_queued_commands;
206} 206}
207 207
208void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { 208void RasterizerOpenGL::Draw(bool is_indexed, u32 instance_count) {
209 MICROPROFILE_SCOPE(OpenGL_Drawing); 209 MICROPROFILE_SCOPE(OpenGL_Drawing);
210 210
211 SCOPE_EXIT({ gpu.TickWork(); }); 211 SCOPE_EXIT({ gpu.TickWork(); });
@@ -222,14 +222,15 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
222 pipeline->SetEngine(maxwell3d, gpu_memory); 222 pipeline->SetEngine(maxwell3d, gpu_memory);
223 pipeline->Configure(is_indexed); 223 pipeline->Configure(is_indexed);
224 224
225 BindInlineIndexBuffer();
226
225 SyncState(); 227 SyncState();
226 228
227 const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology); 229 const GLenum primitive_mode = MaxwellToGL::PrimitiveTopology(maxwell3d->regs.draw.topology);
228 BeginTransformFeedback(pipeline, primitive_mode); 230 BeginTransformFeedback(pipeline, primitive_mode);
229 231
230 const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.global_base_instance_index); 232 const GLuint base_instance = static_cast<GLuint>(maxwell3d->regs.global_base_instance_index);
231 const GLsizei num_instances = 233 const GLsizei num_instances = static_cast<GLsizei>(instance_count);
232 static_cast<GLsizei>(is_instanced ? maxwell3d->mme_draw.instance_count : 1);
233 if (is_indexed) { 234 if (is_indexed) {
234 const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.global_base_vertex_index); 235 const GLint base_vertex = static_cast<GLint>(maxwell3d->regs.global_base_vertex_index);
235 const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_buffer.count); 236 const GLsizei num_vertices = static_cast<GLsizei>(maxwell3d->regs.index_buffer.count);
@@ -1129,6 +1130,16 @@ void RasterizerOpenGL::ReleaseChannel(s32 channel_id) {
1129 query_cache.EraseChannel(channel_id); 1130 query_cache.EraseChannel(channel_id);
1130} 1131}
1131 1132
1133void RasterizerOpenGL::BindInlineIndexBuffer() {
1134 if (maxwell3d->inline_index_draw_indexes.empty()) {
1135 return;
1136 }
1137 const auto data_count = static_cast<u32>(maxwell3d->inline_index_draw_indexes.size());
1138 auto buffer = Buffer(buffer_cache_runtime, *this, 0, data_count);
1139 buffer.ImmediateUpload(0, maxwell3d->inline_index_draw_indexes);
1140 buffer_cache_runtime.BindIndexBuffer(buffer, 0, data_count);
1141}
1142
1132AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {} 1143AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {}
1133 1144
1134bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { 1145bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 45131b785..793e0d608 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -68,7 +68,7 @@ public:
68 StateTracker& state_tracker_); 68 StateTracker& state_tracker_);
69 ~RasterizerOpenGL() override; 69 ~RasterizerOpenGL() override;
70 70
71 void Draw(bool is_indexed, bool is_instanced) override; 71 void Draw(bool is_indexed, u32 instance_count) override;
72 void Clear() override; 72 void Clear() override;
73 void DispatchCompute() override; 73 void DispatchCompute() override;
74 void ResetCounter(VideoCore::QueryType type) override; 74 void ResetCounter(VideoCore::QueryType type) override;
@@ -199,6 +199,8 @@ private:
199 /// End a transform feedback 199 /// End a transform feedback
200 void EndTransformFeedback(); 200 void EndTransformFeedback();
201 201
202 void BindInlineIndexBuffer();
203
202 Tegra::GPU& gpu; 204 Tegra::GPU& gpu;
203 205
204 const Device& device; 206 const Device& device;
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 609f0a772..e94cfdb1a 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -63,6 +63,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key,
63 Shader::RuntimeInfo info; 63 Shader::RuntimeInfo info;
64 if (previous_program) { 64 if (previous_program) {
65 info.previous_stage_stores = previous_program->info.stores; 65 info.previous_stage_stores = previous_program->info.stores;
66 info.previous_stage_legacy_stores_mapping = previous_program->info.legacy_stores_mapping;
66 } else { 67 } else {
67 // Mark all stores as available for vertex shaders 68 // Mark all stores as available for vertex shaders
68 info.previous_stage_stores.mask.set(); 69 info.previous_stage_stores.mask.set();
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 20f1d6584..13d5a1f67 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -134,6 +134,7 @@ Shader::RuntimeInfo MakeRuntimeInfo(std::span<const Shader::IR::Program> program
134 Shader::RuntimeInfo info; 134 Shader::RuntimeInfo info;
135 if (previous_program) { 135 if (previous_program) {
136 info.previous_stage_stores = previous_program->info.stores; 136 info.previous_stage_stores = previous_program->info.stores;
137 info.previous_stage_legacy_stores_mapping = previous_program->info.legacy_stores_mapping;
137 if (previous_program->is_geometry_passthrough) { 138 if (previous_program->is_geometry_passthrough) {
138 info.previous_stage_stores.mask |= previous_program->info.passthrough.mask; 139 info.previous_stage_stores.mask |= previous_program->info.passthrough.mask;
139 } 140 }
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 6d5ea99dd..d94dbf873 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -127,11 +127,10 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3
127 return scissor; 127 return scissor;
128} 128}
129 129
130DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_instanced, 130DrawParams MakeDrawParams(const Maxwell& regs, u32 num_instances, bool is_indexed) {
131 bool is_indexed) {
132 DrawParams params{ 131 DrawParams params{
133 .base_instance = regs.global_base_instance_index, 132 .base_instance = regs.global_base_instance_index,
134 .num_instances = is_instanced ? num_instances : 1, 133 .num_instances = num_instances,
135 .base_vertex = is_indexed ? regs.global_base_vertex_index : regs.vertex_buffer.first, 134 .base_vertex = is_indexed ? regs.global_base_vertex_index : regs.vertex_buffer.first,
136 .num_vertices = is_indexed ? regs.index_buffer.count : regs.vertex_buffer.count, 135 .num_vertices = is_indexed ? regs.index_buffer.count : regs.vertex_buffer.count,
137 .first_index = is_indexed ? regs.index_buffer.first : 0, 136 .first_index = is_indexed ? regs.index_buffer.first : 0,
@@ -175,7 +174,7 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
175 174
176RasterizerVulkan::~RasterizerVulkan() = default; 175RasterizerVulkan::~RasterizerVulkan() = default;
177 176
178void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { 177void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
179 MICROPROFILE_SCOPE(Vulkan_Drawing); 178 MICROPROFILE_SCOPE(Vulkan_Drawing);
180 179
181 SCOPE_EXIT({ gpu.TickWork(); }); 180 SCOPE_EXIT({ gpu.TickWork(); });
@@ -192,13 +191,15 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
192 pipeline->SetEngine(maxwell3d, gpu_memory); 191 pipeline->SetEngine(maxwell3d, gpu_memory);
193 pipeline->Configure(is_indexed); 192 pipeline->Configure(is_indexed);
194 193
194 BindInlineIndexBuffer();
195
195 BeginTransformFeedback(); 196 BeginTransformFeedback();
196 197
197 UpdateDynamicStates(); 198 UpdateDynamicStates();
198 199
199 const auto& regs{maxwell3d->regs}; 200 const auto& regs{maxwell3d->regs};
200 const u32 num_instances{maxwell3d->mme_draw.instance_count}; 201 const u32 num_instances{instance_count};
201 const DrawParams draw_params{MakeDrawParams(regs, num_instances, is_instanced, is_indexed)}; 202 const DrawParams draw_params{MakeDrawParams(regs, num_instances, is_indexed)};
202 scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) { 203 scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
203 if (draw_params.is_indexed) { 204 if (draw_params.is_indexed) {
204 cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances, 205 cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances,
@@ -302,14 +303,19 @@ void RasterizerVulkan::Clear() {
302 } 303 }
303 } 304 }
304 305
305 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { 306 if (regs.clear_surface.R && regs.clear_surface.G && regs.clear_surface.B &&
306 const VkClearAttachment attachment{ 307 regs.clear_surface.A) {
307 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 308 scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) {
308 .colorAttachment = color_attachment, 309 const VkClearAttachment attachment{
309 .clearValue = clear_value, 310 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
310 }; 311 .colorAttachment = color_attachment,
311 cmdbuf.ClearAttachments(attachment, clear_rect); 312 .clearValue = clear_value,
312 }); 313 };
314 cmdbuf.ClearAttachments(attachment, clear_rect);
315 });
316 } else {
317 UNIMPLEMENTED_MSG("Unimplemented Clear only the specified channel");
318 }
313 } 319 }
314 320
315 if (!use_depth && !use_stencil) { 321 if (!use_depth && !use_stencil) {
@@ -1007,4 +1013,17 @@ void RasterizerVulkan::ReleaseChannel(s32 channel_id) {
1007 query_cache.EraseChannel(channel_id); 1013 query_cache.EraseChannel(channel_id);
1008} 1014}
1009 1015
1016void RasterizerVulkan::BindInlineIndexBuffer() {
1017 if (maxwell3d->inline_index_draw_indexes.empty()) {
1018 return;
1019 }
1020 const auto data_count = static_cast<u32>(maxwell3d->inline_index_draw_indexes.size());
1021 auto buffer = buffer_cache_runtime.UploadStagingBuffer(data_count);
1022 std::memcpy(buffer.mapped_span.data(), maxwell3d->inline_index_draw_indexes.data(), data_count);
1023 buffer_cache_runtime.BindIndexBuffer(
1024 maxwell3d->regs.draw.topology, maxwell3d->regs.index_buffer.format,
1025 maxwell3d->regs.index_buffer.first, maxwell3d->regs.index_buffer.count, buffer.buffer,
1026 static_cast<u32>(buffer.offset), data_count);
1027}
1028
1010} // namespace Vulkan 1029} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index e7cdeaed1..b0bc306f5 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -64,7 +64,7 @@ public:
64 StateTracker& state_tracker_, Scheduler& scheduler_); 64 StateTracker& state_tracker_, Scheduler& scheduler_);
65 ~RasterizerVulkan() override; 65 ~RasterizerVulkan() override;
66 66
67 void Draw(bool is_indexed, bool is_instanced) override; 67 void Draw(bool is_indexed, u32 instance_count) override;
68 void Clear() override; 68 void Clear() override;
69 void DispatchCompute() override; 69 void DispatchCompute() override;
70 void ResetCounter(VideoCore::QueryType type) override; 70 void ResetCounter(VideoCore::QueryType type) override;
@@ -141,6 +141,8 @@ private:
141 141
142 void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); 142 void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);
143 143
144 void BindInlineIndexBuffer();
145
144 Tegra::GPU& gpu; 146 Tegra::GPU& gpu;
145 147
146 ScreenInfo& screen_info; 148 ScreenInfo& screen_info;
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h
index c04aad08f..929216749 100644
--- a/src/video_core/renderer_vulkan/vk_scheduler.h
+++ b/src/video_core/renderer_vulkan/vk_scheduler.h
@@ -144,7 +144,6 @@ private:
144 using FuncType = TypedCommand<T>; 144 using FuncType = TypedCommand<T>;
145 static_assert(sizeof(FuncType) < sizeof(data), "Lambda is too large"); 145 static_assert(sizeof(FuncType) < sizeof(data), "Lambda is too large");
146 146
147 recorded_counts++;
148 command_offset = Common::AlignUp(command_offset, alignof(FuncType)); 147 command_offset = Common::AlignUp(command_offset, alignof(FuncType));
149 if (command_offset > sizeof(data) - sizeof(FuncType)) { 148 if (command_offset > sizeof(data) - sizeof(FuncType)) {
150 return false; 149 return false;
@@ -166,7 +165,7 @@ private:
166 } 165 }
167 166
168 bool Empty() const { 167 bool Empty() const {
169 return recorded_counts == 0; 168 return command_offset == 0;
170 } 169 }
171 170
172 bool HasSubmit() const { 171 bool HasSubmit() const {
@@ -177,7 +176,6 @@ private:
177 Command* first = nullptr; 176 Command* first = nullptr;
178 Command* last = nullptr; 177 Command* last = nullptr;
179 178
180 size_t recorded_counts = 0;
181 size_t command_offset = 0; 179 size_t command_offset = 0;
182 bool submit = false; 180 bool submit = false;
183 alignas(std::max_align_t) std::array<u8, 0x8000> data{}; 181 alignas(std::max_align_t) std::array<u8, 0x8000> data{};
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 20e56b0d1..853b80d8a 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1787,17 +1787,17 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
1787 1787
1788 const auto& resolution = runtime.resolution; 1788 const auto& resolution = runtime.resolution;
1789 1789
1790 u32 width = 0; 1790 u32 width = std::numeric_limits<u32>::max();
1791 u32 height = 0; 1791 u32 height = std::numeric_limits<u32>::max();
1792 for (size_t index = 0; index < NUM_RT; ++index) { 1792 for (size_t index = 0; index < NUM_RT; ++index) {
1793 const ImageView* const color_buffer = color_buffers[index]; 1793 const ImageView* const color_buffer = color_buffers[index];
1794 if (!color_buffer) { 1794 if (!color_buffer) {
1795 renderpass_key.color_formats[index] = PixelFormat::Invalid; 1795 renderpass_key.color_formats[index] = PixelFormat::Invalid;
1796 continue; 1796 continue;
1797 } 1797 }
1798 width = std::max(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width) 1798 width = std::min(width, is_rescaled ? resolution.ScaleUp(color_buffer->size.width)
1799 : color_buffer->size.width); 1799 : color_buffer->size.width);
1800 height = std::max(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height) 1800 height = std::min(height, is_rescaled ? resolution.ScaleUp(color_buffer->size.height)
1801 : color_buffer->size.height); 1801 : color_buffer->size.height);
1802 attachments.push_back(color_buffer->RenderTarget()); 1802 attachments.push_back(color_buffer->RenderTarget());
1803 renderpass_key.color_formats[index] = color_buffer->format; 1803 renderpass_key.color_formats[index] = color_buffer->format;
@@ -1809,9 +1809,9 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
1809 } 1809 }
1810 const size_t num_colors = attachments.size(); 1810 const size_t num_colors = attachments.size();
1811 if (depth_buffer) { 1811 if (depth_buffer) {
1812 width = std::max(width, is_rescaled ? resolution.ScaleUp(depth_buffer->size.width) 1812 width = std::min(width, is_rescaled ? resolution.ScaleUp(depth_buffer->size.width)
1813 : depth_buffer->size.width); 1813 : depth_buffer->size.width);
1814 height = std::max(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height) 1814 height = std::min(height, is_rescaled ? resolution.ScaleUp(depth_buffer->size.height)
1815 : depth_buffer->size.height); 1815 : depth_buffer->size.height);
1816 attachments.push_back(depth_buffer->RenderTarget()); 1816 attachments.push_back(depth_buffer->RenderTarget());
1817 renderpass_key.depth_format = depth_buffer->format; 1817 renderpass_key.depth_format = depth_buffer->format;
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp
index ad935d386..08aa8ca33 100644
--- a/src/video_core/texture_cache/format_lookup_table.cpp
+++ b/src/video_core/texture_cache/format_lookup_table.cpp
@@ -150,6 +150,8 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red,
150 return PixelFormat::D24_UNORM_S8_UINT; 150 return PixelFormat::D24_UNORM_S8_UINT;
151 case Hash(TextureFormat::D32S8, FLOAT, UINT, UNORM, UNORM, LINEAR): 151 case Hash(TextureFormat::D32S8, FLOAT, UINT, UNORM, UNORM, LINEAR):
152 return PixelFormat::D32_FLOAT_S8_UINT; 152 return PixelFormat::D32_FLOAT_S8_UINT;
153 case Hash(TextureFormat::R32_B24G8, FLOAT, UINT, UNORM, UNORM, LINEAR):
154 return PixelFormat::D32_FLOAT_S8_UINT;
153 case Hash(TextureFormat::BC1_RGBA, UNORM, LINEAR): 155 case Hash(TextureFormat::BC1_RGBA, UNORM, LINEAR):
154 return PixelFormat::BC1_RGBA_UNORM; 156 return PixelFormat::BC1_RGBA_UNORM;
155 case Hash(TextureFormat::BC1_RGBA, UNORM, SRGB): 157 case Hash(TextureFormat::BC1_RGBA, UNORM, SRGB):
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 0e0fd410f..8ef75fe73 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -442,7 +442,7 @@ void TextureCache<P>::WriteMemory(VAddr cpu_addr, size_t size) {
442template <class P> 442template <class P>
443void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) { 443void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) {
444 std::vector<ImageId> images; 444 std::vector<ImageId> images;
445 ForEachImageInRegion(cpu_addr, size, [this, &images](ImageId image_id, ImageBase& image) { 445 ForEachImageInRegion(cpu_addr, size, [&images](ImageId image_id, ImageBase& image) {
446 if (!image.IsSafeDownload()) { 446 if (!image.IsSafeDownload()) {
447 return; 447 return;
448 } 448 }
@@ -1502,9 +1502,9 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
1502 image.flags &= ~ImageFlagBits::BadOverlap; 1502 image.flags &= ~ImageFlagBits::BadOverlap;
1503 lru_cache.Free(image.lru_index); 1503 lru_cache.Free(image.lru_index);
1504 const auto& clear_page_table = 1504 const auto& clear_page_table =
1505 [this, image_id](u64 page, 1505 [image_id](u64 page,
1506 std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>& 1506 std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>&
1507 selected_page_table) { 1507 selected_page_table) {
1508 const auto page_it = selected_page_table.find(page); 1508 const auto page_it = selected_page_table.find(page);
1509 if (page_it == selected_page_table.end()) { 1509 if (page_it == selected_page_table.end()) {
1510 ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS); 1510 ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS);
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index 15b9d4182..69a32819a 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -1661,8 +1661,8 @@ void Decompress(std::span<const uint8_t> data, uint32_t width, uint32_t height,
1661 for (u32 z = 0; z < depth; ++z) { 1661 for (u32 z = 0; z < depth; ++z) {
1662 const u32 depth_offset = z * height * width * 4; 1662 const u32 depth_offset = z * height * width * 4;
1663 for (u32 y_index = 0; y_index < rows; ++y_index) { 1663 for (u32 y_index = 0; y_index < rows; ++y_index) {
1664 auto decompress_stride = [data, width, height, depth, block_width, block_height, output, 1664 auto decompress_stride = [data, width, height, block_width, block_height, output, rows,
1665 rows, cols, z, depth_offset, y_index] { 1665 cols, z, depth_offset, y_index] {
1666 const u32 y = y_index * block_height; 1666 const u32 y = y_index * block_height;
1667 for (u32 x_index = 0; x_index < cols; ++x_index) { 1667 for (u32 x_index = 0; x_index < cols; ++x_index) {
1668 const u32 block_index = (z * rows * cols) + (y_index * cols) + x_index; 1668 const u32 block_index = (z * rows * cols) + (y_index * cols) + x_index;
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 52d067a2d..fd1a4b987 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -21,7 +21,7 @@ constexpr u32 pdep(u32 value) {
21 u32 m = mask; 21 u32 m = mask;
22 for (u32 bit = 1; m; bit += bit) { 22 for (u32 bit = 1; m; bit += bit) {
23 if (value & bit) 23 if (value & bit)
24 result |= m & -m; 24 result |= m & (~m + 1);
25 m &= m - 1; 25 m &= m - 1;
26 } 26 }
27 return result; 27 return result;
diff --git a/src/yuzu/applets/qt_controller.ui b/src/yuzu/applets/qt_controller.ui
index c8cb6bcf3..f5eccba70 100644
--- a/src/yuzu/applets/qt_controller.ui
+++ b/src/yuzu/applets/qt_controller.ui
@@ -2300,7 +2300,7 @@
2300 <item> 2300 <item>
2301 <widget class="QRadioButton" name="radioUndocked"> 2301 <widget class="QRadioButton" name="radioUndocked">
2302 <property name="text"> 2302 <property name="text">
2303 <string>Undocked</string> 2303 <string>Handheld</string>
2304 </property> 2304 </property>
2305 </widget> 2305 </widget>
2306 </item> 2306 </item>
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 195074bf2..927dd1069 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -819,6 +819,7 @@ void Config::ReadUIGamelistValues() {
819 qt_config->beginGroup(QStringLiteral("UIGameList")); 819 qt_config->beginGroup(QStringLiteral("UIGameList"));
820 820
821 ReadBasicSetting(UISettings::values.show_add_ons); 821 ReadBasicSetting(UISettings::values.show_add_ons);
822 ReadBasicSetting(UISettings::values.show_compat);
822 ReadBasicSetting(UISettings::values.game_icon_size); 823 ReadBasicSetting(UISettings::values.game_icon_size);
823 ReadBasicSetting(UISettings::values.folder_icon_size); 824 ReadBasicSetting(UISettings::values.folder_icon_size);
824 ReadBasicSetting(UISettings::values.row_1_text_id); 825 ReadBasicSetting(UISettings::values.row_1_text_id);
@@ -1414,6 +1415,7 @@ void Config::SaveUIGamelistValues() {
1414 qt_config->beginGroup(QStringLiteral("UIGameList")); 1415 qt_config->beginGroup(QStringLiteral("UIGameList"));
1415 1416
1416 WriteBasicSetting(UISettings::values.show_add_ons); 1417 WriteBasicSetting(UISettings::values.show_add_ons);
1418 WriteBasicSetting(UISettings::values.show_compat);
1417 WriteBasicSetting(UISettings::values.game_icon_size); 1419 WriteBasicSetting(UISettings::values.game_icon_size);
1418 WriteBasicSetting(UISettings::values.folder_icon_size); 1420 WriteBasicSetting(UISettings::values.folder_icon_size);
1419 WriteBasicSetting(UISettings::values.row_1_text_id); 1421 WriteBasicSetting(UISettings::values.row_1_text_id);
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp
index 48f71b53c..92e6da6ee 100644
--- a/src/yuzu/configuration/configure_ui.cpp
+++ b/src/yuzu/configuration/configure_ui.cpp
@@ -72,6 +72,7 @@ ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent)
72 72
73 // Force game list reload if any of the relevant settings are changed. 73 // Force game list reload if any of the relevant settings are changed.
74 connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); 74 connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate);
75 connect(ui->show_compat, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate);
75 connect(ui->game_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, 76 connect(ui->game_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
76 &ConfigureUi::RequestGameListUpdate); 77 &ConfigureUi::RequestGameListUpdate);
77 connect(ui->folder_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), 78 connect(ui->folder_icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged),
@@ -109,6 +110,7 @@ void ConfigureUi::ApplyConfiguration() {
109 UISettings::values.theme = 110 UISettings::values.theme =
110 ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); 111 ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
111 UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); 112 UISettings::values.show_add_ons = ui->show_add_ons->isChecked();
113 UISettings::values.show_compat = ui->show_compat->isChecked();
112 UISettings::values.game_icon_size = ui->game_icon_size_combobox->currentData().toUInt(); 114 UISettings::values.game_icon_size = ui->game_icon_size_combobox->currentData().toUInt();
113 UISettings::values.folder_icon_size = ui->folder_icon_size_combobox->currentData().toUInt(); 115 UISettings::values.folder_icon_size = ui->folder_icon_size_combobox->currentData().toUInt();
114 UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt(); 116 UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt();
@@ -129,6 +131,7 @@ void ConfigureUi::SetConfiguration() {
129 ui->language_combobox->setCurrentIndex( 131 ui->language_combobox->setCurrentIndex(
130 ui->language_combobox->findData(UISettings::values.language)); 132 ui->language_combobox->findData(UISettings::values.language));
131 ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); 133 ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue());
134 ui->show_compat->setChecked(UISettings::values.show_compat.GetValue());
132 ui->game_icon_size_combobox->setCurrentIndex( 135 ui->game_icon_size_combobox->setCurrentIndex(
133 ui->game_icon_size_combobox->findData(UISettings::values.game_icon_size.GetValue())); 136 ui->game_icon_size_combobox->findData(UISettings::values.game_icon_size.GetValue()));
134 ui->folder_icon_size_combobox->setCurrentIndex( 137 ui->folder_icon_size_combobox->setCurrentIndex(
diff --git a/src/yuzu/configuration/configure_ui.ui b/src/yuzu/configuration/configure_ui.ui
index a50df7f6f..f0b719ba3 100644
--- a/src/yuzu/configuration/configure_ui.ui
+++ b/src/yuzu/configuration/configure_ui.ui
@@ -77,6 +77,13 @@
77 <item> 77 <item>
78 <layout class="QVBoxLayout" name="GeneralVerticalLayout"> 78 <layout class="QVBoxLayout" name="GeneralVerticalLayout">
79 <item> 79 <item>
80 <widget class="QCheckBox" name="show_compat">
81 <property name="text">
82 <string>Show Compatibility List</string>
83 </property>
84 </widget>
85 </item>
86 <item>
80 <widget class="QCheckBox" name="show_add_ons"> 87 <widget class="QCheckBox" name="show_add_ons">
81 <property name="text"> 88 <property name="text">
82 <string>Show Add-Ons Column</string> 89 <string>Show Add-Ons Column</string>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index b127badc2..d6adfca16 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -335,6 +335,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs_, FileSys::ManualContentProvid
335 RetranslateUI(); 335 RetranslateUI();
336 336
337 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons); 337 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons);
338 tree_view->setColumnHidden(COLUMN_COMPATIBILITY, !UISettings::values.show_compat);
338 item_model->setSortRole(GameListItemPath::SortRole); 339 item_model->setSortRole(GameListItemPath::SortRole);
339 340
340 connect(main_window, &GMainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons); 341 connect(main_window, &GMainWindow::UpdateThemedIcons, this, &GameList::OnUpdateThemedIcons);
@@ -786,6 +787,7 @@ void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
786 787
787 // Update the columns in case UISettings has changed 788 // Update the columns in case UISettings has changed
788 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons); 789 tree_view->setColumnHidden(COLUMN_ADD_ONS, !UISettings::values.show_add_ons);
790 tree_view->setColumnHidden(COLUMN_COMPATIBILITY, !UISettings::values.show_compat);
789 791
790 // Delete any rows that might already exist if we're repopulating 792 // Delete any rows that might already exist if we're repopulating
791 item_model->removeRows(0, item_model->rowCount()); 793 item_model->removeRows(0, item_model->rowCount());
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index 74d49dbd4..e670acc30 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -55,7 +55,6 @@
55 <addaction name="separator"/> 55 <addaction name="separator"/>
56 <addaction name="menu_recent_files"/> 56 <addaction name="menu_recent_files"/>
57 <addaction name="separator"/> 57 <addaction name="separator"/>
58 <addaction name="separator"/>
59 <addaction name="action_Load_Amiibo"/> 58 <addaction name="action_Load_Amiibo"/>
60 <addaction name="separator"/> 59 <addaction name="separator"/>
61 <addaction name="action_Open_yuzu_Folder"/> 60 <addaction name="action_Open_yuzu_Folder"/>
diff --git a/src/yuzu/multiplayer/state.cpp b/src/yuzu/multiplayer/state.cpp
index ae2738ad4..285bb150d 100644
--- a/src/yuzu/multiplayer/state.cpp
+++ b/src/yuzu/multiplayer/state.cpp
@@ -268,7 +268,7 @@ bool MultiplayerState::OnCloseRoom() {
268 return true; 268 return true;
269 } 269 }
270 // Save ban list 270 // Save ban list
271 UISettings::values.multiplayer_ban_list = std::move(room->GetBanList()); 271 UISettings::values.multiplayer_ban_list = room->GetBanList();
272 272
273 room->Destroy(); 273 room->Destroy();
274 announce_multiplayer_session->Stop(); 274 announce_multiplayer_session->Stop();
diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp
index fc2693f9d..6a91212e2 100644
--- a/src/yuzu/startup_checks.cpp
+++ b/src/yuzu/startup_checks.cpp
@@ -49,7 +49,7 @@ bool CheckEnvVars(bool* is_child) {
49 *is_child = true; 49 *is_child = true;
50 return false; 50 return false;
51 } else if (!SetEnvironmentVariableA(IS_CHILD_ENV_VAR, ENV_VAR_ENABLED_TEXT)) { 51 } else if (!SetEnvironmentVariableA(IS_CHILD_ENV_VAR, ENV_VAR_ENABLED_TEXT)) {
52 std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %d\n", 52 std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %lu\n",
53 IS_CHILD_ENV_VAR, GetLastError()); 53 IS_CHILD_ENV_VAR, GetLastError());
54 return true; 54 return true;
55 } 55 }
@@ -62,7 +62,7 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka
62 // Set the startup variable for child processes 62 // Set the startup variable for child processes
63 const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT); 63 const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT);
64 if (!env_var_set) { 64 if (!env_var_set) {
65 std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %d\n", 65 std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %lu\n",
66 STARTUP_CHECK_ENV_VAR, GetLastError()); 66 STARTUP_CHECK_ENV_VAR, GetLastError());
67 return false; 67 return false;
68 } 68 }
@@ -81,22 +81,22 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka
81 DWORD exit_code = STILL_ACTIVE; 81 DWORD exit_code = STILL_ACTIVE;
82 const int err = GetExitCodeProcess(process_info.hProcess, &exit_code); 82 const int err = GetExitCodeProcess(process_info.hProcess, &exit_code);
83 if (err == 0) { 83 if (err == 0) {
84 std::fprintf(stderr, "GetExitCodeProcess failed with error %d\n", GetLastError()); 84 std::fprintf(stderr, "GetExitCodeProcess failed with error %lu\n", GetLastError());
85 } 85 }
86 86
87 // Vulkan is broken if the child crashed (return value is not zero) 87 // Vulkan is broken if the child crashed (return value is not zero)
88 *has_broken_vulkan = (exit_code != 0); 88 *has_broken_vulkan = (exit_code != 0);
89 89
90 if (CloseHandle(process_info.hProcess) == 0) { 90 if (CloseHandle(process_info.hProcess) == 0) {
91 std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError()); 91 std::fprintf(stderr, "CloseHandle failed with error %lu\n", GetLastError());
92 } 92 }
93 if (CloseHandle(process_info.hThread) == 0) { 93 if (CloseHandle(process_info.hThread) == 0) {
94 std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError()); 94 std::fprintf(stderr, "CloseHandle failed with error %lu\n", GetLastError());
95 } 95 }
96 } 96 }
97 97
98 if (!SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, nullptr)) { 98 if (!SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, nullptr)) {
99 std::fprintf(stderr, "SetEnvironmentVariableA failed to clear %s with error %d\n", 99 std::fprintf(stderr, "SetEnvironmentVariableA failed to clear %s with error %lu\n",
100 STARTUP_CHECK_ENV_VAR, GetLastError()); 100 STARTUP_CHECK_ENV_VAR, GetLastError());
101 } 101 }
102 102
@@ -135,7 +135,8 @@ bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags) {
135 startup_info.cb = sizeof(startup_info); 135 startup_info.cb = sizeof(startup_info);
136 136
137 char p_name[255]; 137 char p_name[255];
138 std::strncpy(p_name, arg0, 255); 138 std::strncpy(p_name, arg0, 254);
139 p_name[254] = '\0';
139 140
140 const bool process_created = CreateProcessA(nullptr, // lpApplicationName 141 const bool process_created = CreateProcessA(nullptr, // lpApplicationName
141 p_name, // lpCommandLine 142 p_name, // lpCommandLine
@@ -149,7 +150,7 @@ bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags) {
149 pi // lpProcessInformation 150 pi // lpProcessInformation
150 ); 151 );
151 if (!process_created) { 152 if (!process_created) {
152 std::fprintf(stderr, "CreateProcessA failed with error %d\n", GetLastError()); 153 std::fprintf(stderr, "CreateProcessA failed with error %lu\n", GetLastError());
153 return false; 154 return false;
154 } 155 }
155 156
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 753797efc..4f5b2a99d 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -129,6 +129,9 @@ struct Values {
129 Settings::Setting<bool> favorites_expanded{true, "favorites_expanded"}; 129 Settings::Setting<bool> favorites_expanded{true, "favorites_expanded"};
130 QVector<u64> favorited_ids; 130 QVector<u64> favorited_ids;
131 131
132 // Compatibility List
133 Settings::Setting<bool> show_compat{false, "show_compat"};
134
132 bool configuration_applied; 135 bool configuration_applied;
133 bool reset_to_defaults; 136 bool reset_to_defaults;
134 Settings::Setting<bool> disable_web_applet{true, "disable_web_applet"}; 137 Settings::Setting<bool> disable_web_applet{true, "disable_web_applet"};