summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.reuse/dep54
-rw-r--r--src/android/app/build.gradle.kts15
-rw-r--r--src/android/app/debug.keystorebin0 -> 2105 bytes
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt65
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt21
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt35
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt3
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt25
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt10
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt54
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt34
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt45
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt33
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt29
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt10
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProgressDialogFragment.kt (renamed from src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt)44
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt10
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt42
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt8
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameVerificationResult.kt15
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt15
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Patch.kt16
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/PatchType.kt14
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt29
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt101
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt80
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt21
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt5
-rw-r--r--src/android/app/src/main/jni/android_common/android_common.cpp16
-rw-r--r--src/android/app/src/main/jni/android_common/android_common.h7
-rw-r--r--src/android/app/src/main/jni/android_settings.h1
-rw-r--r--src/android/app/src/main/jni/id_cache.cpp101
-rw-r--r--src/android/app/src/main/jni/id_cache.h17
-rw-r--r--src/android/app/src/main/jni/native.cpp165
-rw-r--r--src/android/app/src/main/jni/native.h2
-rw-r--r--src/android/app/src/main/res/drawable/ic_lock.xml9
-rw-r--r--src/android/app/src/main/res/drawable/ic_shortcut.xml9
-rw-r--r--src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml35
-rw-r--r--src/android/app/src/main/res/layout/card_home_option.xml6
-rw-r--r--src/android/app/src/main/res/layout/dialog_progress_bar.xml30
-rw-r--r--src/android/app/src/main/res/layout/fragment_game_info.xml8
-rw-r--r--src/android/app/src/main/res/layout/fragment_game_properties.xml40
-rw-r--r--src/android/app/src/main/res/layout/list_item_addon.xml32
-rw-r--r--src/android/app/src/main/res/layout/list_item_setting.xml2
-rw-r--r--src/android/app/src/main/res/layout/list_item_setting_switch.xml2
-rw-r--r--src/android/app/src/main/res/menu/menu_driver_manager.xml9
-rw-r--r--src/android/app/src/main/res/menu/menu_in_game.xml5
-rw-r--r--src/android/app/src/main/res/values-ar/strings.xml193
-rw-r--r--src/android/app/src/main/res/values-ckb/strings.xml18
-rw-r--r--src/android/app/src/main/res/values-cs/strings.xml265
-rw-r--r--src/android/app/src/main/res/values-de/strings.xml89
-rw-r--r--src/android/app/src/main/res/values-es/strings.xml142
-rw-r--r--src/android/app/src/main/res/values-fr/strings.xml128
-rw-r--r--src/android/app/src/main/res/values-he/strings.xml106
-rw-r--r--src/android/app/src/main/res/values-hu/strings.xml122
-rw-r--r--src/android/app/src/main/res/values-it/strings.xml61
-rw-r--r--src/android/app/src/main/res/values-ja/strings.xml35
-rw-r--r--src/android/app/src/main/res/values-ko/strings.xml209
-rw-r--r--src/android/app/src/main/res/values-nb/strings.xml23
-rw-r--r--src/android/app/src/main/res/values-pl/strings.xml24
-rw-r--r--src/android/app/src/main/res/values-pt-rBR/strings.xml360
-rw-r--r--src/android/app/src/main/res/values-pt-rPT/strings.xml120
-rw-r--r--src/android/app/src/main/res/values-ru/strings.xml124
-rw-r--r--src/android/app/src/main/res/values-uk/strings.xml23
-rw-r--r--src/android/app/src/main/res/values-vi/strings.xml24
-rw-r--r--src/android/app/src/main/res/values-zh-rCN/strings.xml124
-rw-r--r--src/android/app/src/main/res/values-zh-rTW/strings.xml210
-rw-r--r--src/android/app/src/main/res/values/strings.xml17
-rw-r--r--src/audio_core/device/device_session.cpp1
-rw-r--r--src/audio_core/renderer/command/data_source/decode.cpp1
-rw-r--r--src/common/common_types.h1
-rw-r--r--src/common/fs/file.h2
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/core.cpp14
-rw-r--r--src/core/core.h6
-rw-r--r--src/core/device_memory.h16
-rw-r--r--src/core/device_memory_manager.h211
-rw-r--r--src/core/device_memory_manager.inc581
-rw-r--r--src/core/file_sys/patch_manager.cpp43
-rw-r--r--src/core/file_sys/patch_manager.h17
-rw-r--r--src/core/gpu_dirty_memory_manager.h14
-rw-r--r--src/core/guest_memory.h214
-rw-r--r--src/core/hle/kernel/k_process.cpp14
-rw-r--r--src/core/hle/kernel/k_process.h4
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp17
-rw-r--r--src/core/hle/service/acc/profile_manager.h1
-rw-r--r--src/core/hle/service/hid/hid.cpp1
-rw-r--r--src/core/hle/service/hid/hid_server.cpp334
-rw-r--r--src/core/hle/service/hid/hid_server.h1
-rw-r--r--src/core/hle/service/hid/hid_system_server.cpp102
-rw-r--r--src/core/hle/service/hid/hid_system_server.h6
-rw-r--r--src/core/hle/service/hle_ipc.cpp61
-rw-r--r--src/core/hle/service/hle_ipc.h5
-rw-r--r--src/core/hle/service/nvdrv/core/container.cpp114
-rw-r--r--src/core/hle/service/nvdrv/core/container.h32
-rw-r--r--src/core/hle/service/nvdrv/core/heap_mapper.cpp175
-rw-r--r--src/core/hle/service/nvdrv/core/heap_mapper.h49
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.cpp120
-rw-r--r--src/core/hle/service/nvdrv/core/nvmap.h25
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdevice.h3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp36
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h15
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp9
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp13
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp7
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp31
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h7
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp27
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h6
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.cpp37
-rw-r--r--src/core/hle/service/nvdrv/nvdrv_interface.h1
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp25
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.h5
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp18
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h4
-rw-r--r--src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp2
-rw-r--r--src/core/hle/service/set/system_settings_server.cpp13
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp11
-rw-r--r--src/core/hle/service/vi/display/vi_display.h3
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h9
-rw-r--r--src/core/hle/service/vi/vi.cpp19
-rw-r--r--src/core/loader/nsp.cpp8
-rw-r--r--src/core/memory.cpp108
-rw-r--r--src/core/memory.h211
-rw-r--r--src/frontend_common/CMakeLists.txt1
-rw-r--r--src/frontend_common/content_manager.h371
-rw-r--r--src/hid_core/frontend/emulated_controller.cpp46
-rw-r--r--src/hid_core/frontend/emulated_controller.h20
-rw-r--r--src/hid_core/resource_manager.cpp123
-rw-r--r--src/hid_core/resource_manager.h25
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp2
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h6
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_pad.cpp13
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_pad.h6
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp42
-rw-r--r--src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h12
-rw-r--r--src/hid_core/resources/applet_resource.cpp19
-rw-r--r--src/hid_core/resources/applet_resource.h1
-rw-r--r--src/hid_core/resources/npad/npad.cpp312
-rw-r--r--src/hid_core/resources/npad/npad.h61
-rw-r--r--src/hid_core/resources/npad/npad_types.h6
-rw-r--r--src/hid_core/resources/npad/npad_vibration.cpp4
-rw-r--r--src/hid_core/resources/npad/npad_vibration.h2
-rw-r--r--src/hid_core/resources/vibration/gc_vibration_device.cpp56
-rw-r--r--src/hid_core/resources/vibration/gc_vibration_device.h10
-rw-r--r--src/hid_core/resources/vibration/n64_vibration_device.cpp57
-rw-r--r--src/hid_core/resources/vibration/n64_vibration_device.h8
-rw-r--r--src/hid_core/resources/vibration/vibration_base.cpp4
-rw-r--r--src/hid_core/resources/vibration/vibration_base.h10
-rw-r--r--src/hid_core/resources/vibration/vibration_device.cpp72
-rw-r--r--src/hid_core/resources/vibration/vibration_device.h16
-rw-r--r--src/tests/video_core/memory_tracker.cpp7
-rw-r--r--src/video_core/CMakeLists.txt5
-rw-r--r--src/video_core/buffer_cache/buffer_base.h3
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h451
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h98
-rw-r--r--src/video_core/buffer_cache/memory_tracker_base.h18
-rw-r--r--src/video_core/buffer_cache/word_manager.h28
-rw-r--r--src/video_core/dma_pusher.cpp10
-rw-r--r--src/video_core/engines/engine_upload.cpp5
-rw-r--r--src/video_core/engines/maxwell_3d.cpp1
-rw-r--r--src/video_core/engines/maxwell_dma.cpp26
-rw-r--r--src/video_core/engines/sw_blitter/blitter.cpp5
-rw-r--r--src/video_core/framebuffer_config.h2
-rw-r--r--src/video_core/gpu.cpp29
-rw-r--r--src/video_core/gpu.h12
-rw-r--r--src/video_core/gpu_thread.cpp6
-rw-r--r--src/video_core/gpu_thread.h18
-rw-r--r--src/video_core/guest_memory.h30
-rw-r--r--src/video_core/host1x/codecs/h264.cpp9
-rw-r--r--src/video_core/host1x/codecs/vp8.cpp4
-rw-r--r--src/video_core/host1x/codecs/vp9.cpp9
-rw-r--r--src/video_core/host1x/gpu_device_memory_manager.cpp32
-rw-r--r--src/video_core/host1x/gpu_device_memory_manager.h24
-rw-r--r--src/video_core/host1x/host1x.cpp5
-rw-r--r--src/video_core/host1x/host1x.h17
-rw-r--r--src/video_core/host1x/vic.cpp15
-rw-r--r--src/video_core/memory_manager.cpp229
-rw-r--r--src/video_core/memory_manager.h36
-rw-r--r--src/video_core/query_cache.h30
-rw-r--r--src/video_core/query_cache/query_base.h4
-rw-r--r--src/video_core/query_cache/query_cache.h37
-rw-r--r--src/video_core/query_cache/query_cache_base.h15
-rw-r--r--src/video_core/rasterizer_accelerated.cpp72
-rw-r--r--src/video_core/rasterizer_accelerated.h49
-rw-r--r--src/video_core/rasterizer_interface.h23
-rw-r--r--src/video_core/renderer_null/null_rasterizer.cpp26
-rw-r--r--src/video_core/renderer_null/null_rasterizer.h23
-rw-r--r--src/video_core/renderer_null/renderer_null.cpp5
-rw-r--r--src/video_core/renderer_null/renderer_null.h3
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp7
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h8
-rw-r--r--src/video_core/renderer_opengl/gl_query_cache.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_query_cache.h4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp41
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h28
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp11
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h11
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp10
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h4
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h1
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp12
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.h8
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp17
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.h12
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h7
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp8
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.cpp62
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp44
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h41
-rw-r--r--src/video_core/shader_cache.cpp8
-rw-r--r--src/video_core/shader_cache.h5
-rw-r--r--src/video_core/texture_cache/texture_cache.h75
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h28
-rw-r--r--src/video_core/texture_cache/util.cpp5
-rw-r--r--src/video_core/video_core.cpp15
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp10
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp7
-rw-r--r--src/yuzu/configuration/configure_vibration.cpp8
-rw-r--r--src/yuzu/game_list_worker.cpp11
-rw-r--r--src/yuzu/main.cpp328
-rw-r--r--src/yuzu/main.h13
242 files changed, 7303 insertions, 2847 deletions
diff --git a/.reuse/dep5 b/.reuse/dep5
index d98b78087..b9ae96d0b 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -155,3 +155,7 @@ License: MIT
155Files: externals/gamemode/* 155Files: externals/gamemode/*
156Copyright: Copyright 2017-2019 Feral Interactive 156Copyright: Copyright 2017-2019 Feral Interactive
157License: BSD-3-Clause 157License: BSD-3-Clause
158
159Files: src/android/app/debug.keystore
160Copyright: 2023 yuzu Emulator Project
161License: GPL-3.0-or-later
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts
index 06e59d1ac..188ef9469 100644
--- a/src/android/app/build.gradle.kts
+++ b/src/android/app/build.gradle.kts
@@ -82,8 +82,8 @@ android {
82 } 82 }
83 83
84 val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE") 84 val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
85 if (keystoreFile != null) { 85 signingConfigs {
86 signingConfigs { 86 if (keystoreFile != null) {
87 create("release") { 87 create("release") {
88 storeFile = file(keystoreFile) 88 storeFile = file(keystoreFile)
89 storePassword = System.getenv("ANDROID_KEYSTORE_PASS") 89 storePassword = System.getenv("ANDROID_KEYSTORE_PASS")
@@ -91,6 +91,12 @@ android {
91 keyPassword = System.getenv("ANDROID_KEYSTORE_PASS") 91 keyPassword = System.getenv("ANDROID_KEYSTORE_PASS")
92 } 92 }
93 } 93 }
94 create("default") {
95 storeFile = file("$projectDir/debug.keystore")
96 storePassword = "android"
97 keyAlias = "androiddebugkey"
98 keyPassword = "android"
99 }
94 } 100 }
95 101
96 // Define build types, which are orthogonal to product flavors. 102 // Define build types, which are orthogonal to product flavors.
@@ -101,7 +107,7 @@ android {
101 signingConfig = if (keystoreFile != null) { 107 signingConfig = if (keystoreFile != null) {
102 signingConfigs.getByName("release") 108 signingConfigs.getByName("release")
103 } else { 109 } else {
104 signingConfigs.getByName("debug") 110 signingConfigs.getByName("default")
105 } 111 }
106 112
107 resValue("string", "app_name_suffixed", "yuzu") 113 resValue("string", "app_name_suffixed", "yuzu")
@@ -118,7 +124,7 @@ android {
118 register("relWithDebInfo") { 124 register("relWithDebInfo") {
119 isDefault = true 125 isDefault = true
120 resValue("string", "app_name_suffixed", "yuzu Debug Release") 126 resValue("string", "app_name_suffixed", "yuzu Debug Release")
121 signingConfig = signingConfigs.getByName("debug") 127 signingConfig = signingConfigs.getByName("default")
122 isMinifyEnabled = true 128 isMinifyEnabled = true
123 isDebuggable = true 129 isDebuggable = true
124 proguardFiles( 130 proguardFiles(
@@ -133,6 +139,7 @@ android {
133 // Signed by debug key disallowing distribution on Play Store. 139 // Signed by debug key disallowing distribution on Play Store.
134 // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build. 140 // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
135 debug { 141 debug {
142 signingConfig = signingConfigs.getByName("default")
136 resValue("string", "app_name_suffixed", "yuzu Debug") 143 resValue("string", "app_name_suffixed", "yuzu Debug")
137 isDebuggable = true 144 isDebuggable = true
138 isJniDebuggable = true 145 isJniDebuggable = true
diff --git a/src/android/app/debug.keystore b/src/android/app/debug.keystore
new file mode 100644
index 000000000..e4e194af9
--- /dev/null
+++ b/src/android/app/debug.keystore
Binary files differ
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
index b7556e353..c408485c6 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
@@ -21,6 +21,9 @@ import org.yuzu.yuzu_emu.utils.DocumentsTree
21import org.yuzu.yuzu_emu.utils.FileUtil 21import org.yuzu.yuzu_emu.utils.FileUtil
22import org.yuzu.yuzu_emu.utils.Log 22import org.yuzu.yuzu_emu.utils.Log
23import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable 23import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
24import org.yuzu.yuzu_emu.model.InstallResult
25import org.yuzu.yuzu_emu.model.Patch
26import org.yuzu.yuzu_emu.model.GameVerificationResult
24 27
25/** 28/**
26 * Class which contains methods that interact 29 * Class which contains methods that interact
@@ -235,9 +238,12 @@ object NativeLibrary {
235 /** 238 /**
236 * Installs a nsp or xci file to nand 239 * Installs a nsp or xci file to nand
237 * @param filename String representation of file uri 240 * @param filename String representation of file uri
238 * @param extension Lowercase string representation of file extension without "." 241 * @return int representation of [InstallResult]
239 */ 242 */
240 external fun installFileToNand(filename: String, extension: String): Int 243 external fun installFileToNand(
244 filename: String,
245 callback: (max: Long, progress: Long) -> Boolean
246 ): Int
241 247
242 external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean 248 external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean
243 249
@@ -535,9 +541,49 @@ object NativeLibrary {
535 * 541 *
536 * @param path Path to game file. Can be a [Uri]. 542 * @param path Path to game file. Can be a [Uri].
537 * @param programId String representation of a game's program ID 543 * @param programId String representation of a game's program ID
538 * @return Array of pairs where the first value is the name of an addon and the second is the version 544 * @return Array of available patches
539 */ 545 */
540 external fun getAddonsForFile(path: String, programId: String): Array<Pair<String, String>>? 546 external fun getPatchesForFile(path: String, programId: String): Array<Patch>?
547
548 /**
549 * Removes an update for a given [programId]
550 * @param programId String representation of a game's program ID
551 */
552 external fun removeUpdate(programId: String)
553
554 /**
555 * Removes all DLC for a [programId]
556 * @param programId String representation of a game's program ID
557 */
558 external fun removeDLC(programId: String)
559
560 /**
561 * Removes a mod installed for a given [programId]
562 * @param programId String representation of a game's program ID
563 * @param name The name of a mod as given by [getPatchesForFile]. This corresponds with the name
564 * of the mod's directory in a game's load folder.
565 */
566 external fun removeMod(programId: String, name: String)
567
568 /**
569 * Verifies all installed content
570 * @param callback UI callback for verification progress. Return true in the callback to cancel.
571 * @return Array of content that failed verification. Successful if empty.
572 */
573 external fun verifyInstalledContents(
574 callback: (max: Long, progress: Long) -> Boolean
575 ): Array<String>
576
577 /**
578 * Verifies the contents of a game
579 * @param path String path to a game
580 * @param callback UI callback for verification progress. Return true in the callback to cancel.
581 * @return Int that is meant to be converted to a [GameVerificationResult]
582 */
583 external fun verifyGameContents(
584 path: String,
585 callback: (max: Long, progress: Long) -> Boolean
586 ): Int
541 587
542 /** 588 /**
543 * Gets the save location for a specific game 589 * Gets the save location for a specific game
@@ -609,15 +655,4 @@ object NativeLibrary {
609 const val RELEASED = 0 655 const val RELEASED = 0
610 const val PRESSED = 1 656 const val PRESSED = 1
611 } 657 }
612
613 /**
614 * Result from installFileToNand
615 */
616 object InstallFileToNandResult {
617 const val Success = 0
618 const val SuccessFileOverwritten = 1
619 const val Error = 2
620 const val ErrorBaseGame = 3
621 const val ErrorFilenameExtension = 4
622 }
623} 658}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt
index 94c151325..ff254d9b7 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AddonAdapter.kt
@@ -6,27 +6,32 @@ package org.yuzu.yuzu_emu.adapters
6import android.view.LayoutInflater 6import android.view.LayoutInflater
7import android.view.ViewGroup 7import android.view.ViewGroup
8import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding 8import org.yuzu.yuzu_emu.databinding.ListItemAddonBinding
9import org.yuzu.yuzu_emu.model.Addon 9import org.yuzu.yuzu_emu.model.Patch
10import org.yuzu.yuzu_emu.model.AddonViewModel
10import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder 11import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
11 12
12class AddonAdapter : AbstractDiffAdapter<Addon, AddonAdapter.AddonViewHolder>() { 13class AddonAdapter(val addonViewModel: AddonViewModel) :
14 AbstractDiffAdapter<Patch, AddonAdapter.AddonViewHolder>() {
13 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder { 15 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddonViewHolder {
14 ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false) 16 ListItemAddonBinding.inflate(LayoutInflater.from(parent.context), parent, false)
15 .also { return AddonViewHolder(it) } 17 .also { return AddonViewHolder(it) }
16 } 18 }
17 19
18 inner class AddonViewHolder(val binding: ListItemAddonBinding) : 20 inner class AddonViewHolder(val binding: ListItemAddonBinding) :
19 AbstractViewHolder<Addon>(binding) { 21 AbstractViewHolder<Patch>(binding) {
20 override fun bind(model: Addon) { 22 override fun bind(model: Patch) {
21 binding.root.setOnClickListener { 23 binding.root.setOnClickListener {
22 binding.addonSwitch.isChecked = !binding.addonSwitch.isChecked 24 binding.addonCheckbox.isChecked = !binding.addonCheckbox.isChecked
23 } 25 }
24 binding.title.text = model.title 26 binding.title.text = model.name
25 binding.version.text = model.version 27 binding.version.text = model.version
26 binding.addonSwitch.setOnCheckedChangeListener { _, checked -> 28 binding.addonCheckbox.setOnCheckedChangeListener { _, checked ->
27 model.enabled = checked 29 model.enabled = checked
28 } 30 }
29 binding.addonSwitch.isChecked = model.enabled 31 binding.addonCheckbox.isChecked = model.enabled
32 binding.buttonDelete.setOnClickListener {
33 addonViewModel.setAddonToDelete(model)
34 }
30 } 35 }
31 } 36 }
32} 37}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
index e26c2e0ab..b4f4d950f 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt
@@ -3,9 +3,6 @@
3 3
4package org.yuzu.yuzu_emu.adapters 4package org.yuzu.yuzu_emu.adapters
5 5
6import android.content.Intent
7import android.graphics.Bitmap
8import android.graphics.drawable.LayerDrawable
9import android.net.Uri 6import android.net.Uri
10import android.text.TextUtils 7import android.text.TextUtils
11import android.view.LayoutInflater 8import android.view.LayoutInflater
@@ -15,10 +12,6 @@ import android.widget.Toast
15import androidx.appcompat.app.AppCompatActivity 12import androidx.appcompat.app.AppCompatActivity
16import androidx.core.content.pm.ShortcutInfoCompat 13import androidx.core.content.pm.ShortcutInfoCompat
17import androidx.core.content.pm.ShortcutManagerCompat 14import androidx.core.content.pm.ShortcutManagerCompat
18import androidx.core.content.res.ResourcesCompat
19import androidx.core.graphics.drawable.IconCompat
20import androidx.core.graphics.drawable.toBitmap
21import androidx.core.graphics.drawable.toDrawable
22import androidx.documentfile.provider.DocumentFile 15import androidx.documentfile.provider.DocumentFile
23import androidx.lifecycle.ViewModelProvider 16import androidx.lifecycle.ViewModelProvider
24import androidx.lifecycle.lifecycleScope 17import androidx.lifecycle.lifecycleScope
@@ -30,7 +23,6 @@ import kotlinx.coroutines.withContext
30import org.yuzu.yuzu_emu.HomeNavigationDirections 23import org.yuzu.yuzu_emu.HomeNavigationDirections
31import org.yuzu.yuzu_emu.R 24import org.yuzu.yuzu_emu.R
32import org.yuzu.yuzu_emu.YuzuApplication 25import org.yuzu.yuzu_emu.YuzuApplication
33import org.yuzu.yuzu_emu.activities.EmulationActivity
34import org.yuzu.yuzu_emu.databinding.CardGameBinding 26import org.yuzu.yuzu_emu.databinding.CardGameBinding
35import org.yuzu.yuzu_emu.model.Game 27import org.yuzu.yuzu_emu.model.Game
36import org.yuzu.yuzu_emu.model.GamesViewModel 28import org.yuzu.yuzu_emu.model.GamesViewModel
@@ -89,36 +81,13 @@ class GameAdapter(private val activity: AppCompatActivity) :
89 ) 81 )
90 .apply() 82 .apply()
91 83
92 val openIntent =
93 Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
94 action = Intent.ACTION_VIEW
95 data = Uri.parse(game.path)
96 }
97
98 activity.lifecycleScope.launch { 84 activity.lifecycleScope.launch {
99 withContext(Dispatchers.IO) { 85 withContext(Dispatchers.IO) {
100 val layerDrawable = ResourcesCompat.getDrawable(
101 YuzuApplication.appContext.resources,
102 R.drawable.shortcut,
103 null
104 ) as LayerDrawable
105 layerDrawable.setDrawableByLayerId(
106 R.id.shortcut_foreground,
107 GameIconUtils.getGameIcon(activity, game)
108 .toDrawable(YuzuApplication.appContext.resources)
109 )
110 val inset = YuzuApplication.appContext.resources
111 .getDimensionPixelSize(R.dimen.icon_inset)
112 layerDrawable.setLayerInset(1, inset, inset, inset, inset)
113 val shortcut = 86 val shortcut =
114 ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path) 87 ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
115 .setShortLabel(game.title) 88 .setShortLabel(game.title)
116 .setIcon( 89 .setIcon(GameIconUtils.getShortcutIcon(activity, game))
117 IconCompat.createWithAdaptiveBitmap( 90 .setIntent(game.launchIntent)
118 layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
119 )
120 )
121 .setIntent(openIntent)
122 .build() 91 .build()
123 ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) 92 ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
124 } 93 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
index 16fb87614..71be2d0b2 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/IntSetting.kt
@@ -23,7 +23,8 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
23 THEME("theme"), 23 THEME("theme"),
24 THEME_MODE("theme_mode"), 24 THEME_MODE("theme_mode"),
25 OVERLAY_SCALE("control_scale"), 25 OVERLAY_SCALE("control_scale"),
26 OVERLAY_OPACITY("control_opacity"); 26 OVERLAY_OPACITY("control_opacity"),
27 LOCK_DRAWER("lock_drawer");
27 28
28 override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal) 29 override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal)
29 30
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt
index 816336820..adb65812c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AddonsFragment.kt
@@ -74,7 +74,7 @@ class AddonsFragment : Fragment() {
74 74
75 binding.listAddons.apply { 75 binding.listAddons.apply {
76 layoutManager = LinearLayoutManager(requireContext()) 76 layoutManager = LinearLayoutManager(requireContext())
77 adapter = AddonAdapter() 77 adapter = AddonAdapter(addonViewModel)
78 } 78 }
79 79
80 viewLifecycleOwner.lifecycleScope.apply { 80 viewLifecycleOwner.lifecycleScope.apply {
@@ -110,6 +110,21 @@ class AddonsFragment : Fragment() {
110 } 110 }
111 } 111 }
112 } 112 }
113 launch {
114 repeatOnLifecycle(Lifecycle.State.STARTED) {
115 addonViewModel.addonToDelete.collect {
116 if (it != null) {
117 MessageDialogFragment.newInstance(
118 requireActivity(),
119 titleId = R.string.confirm_uninstall,
120 descriptionId = R.string.confirm_uninstall_description,
121 positiveAction = { addonViewModel.onDeleteAddon(it) }
122 ).show(parentFragmentManager, MessageDialogFragment.TAG)
123 addonViewModel.setAddonToDelete(null)
124 }
125 }
126 }
127 }
113 } 128 }
114 129
115 binding.buttonInstall.setOnClickListener { 130 binding.buttonInstall.setOnClickListener {
@@ -156,22 +171,22 @@ class AddonsFragment : Fragment() {
156 descriptionId = R.string.invalid_directory_description 171 descriptionId = R.string.invalid_directory_description
157 ) 172 )
158 if (isValid) { 173 if (isValid) {
159 IndeterminateProgressDialogFragment.newInstance( 174 ProgressDialogFragment.newInstance(
160 requireActivity(), 175 requireActivity(),
161 R.string.installing_game_content, 176 R.string.installing_game_content,
162 false 177 false
163 ) { 178 ) { progressCallback, _ ->
164 val parentDirectoryName = externalAddonDirectory.name 179 val parentDirectoryName = externalAddonDirectory.name
165 val internalAddonDirectory = 180 val internalAddonDirectory =
166 File(args.game.addonDir + parentDirectoryName) 181 File(args.game.addonDir + parentDirectoryName)
167 try { 182 try {
168 externalAddonDirectory.copyFilesTo(internalAddonDirectory) 183 externalAddonDirectory.copyFilesTo(internalAddonDirectory, progressCallback)
169 } catch (_: Exception) { 184 } catch (_: Exception) {
170 return@newInstance errorMessage 185 return@newInstance errorMessage
171 } 186 }
172 addonViewModel.refreshAddons() 187 addonViewModel.refreshAddons()
173 return@newInstance getString(R.string.addon_installed_successfully) 188 return@newInstance getString(R.string.addon_installed_successfully)
174 }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) 189 }.show(parentFragmentManager, ProgressDialogFragment.TAG)
175 } else { 190 } else {
176 errorMessage.show(parentFragmentManager, MessageDialogFragment.TAG) 191 errorMessage.show(parentFragmentManager, MessageDialogFragment.TAG)
177 } 192 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt
index 9dabb9c41..bf017cd7c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/DriverManagerFragment.kt
@@ -75,7 +75,7 @@ class DriverManagerFragment : Fragment() {
75 driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global) 75 driverViewModel.showClearButton(!StringSetting.DRIVER_PATH.global)
76 binding.toolbarDrivers.setOnMenuItemClickListener { 76 binding.toolbarDrivers.setOnMenuItemClickListener {
77 when (it.itemId) { 77 when (it.itemId) {
78 R.id.menu_driver_clear -> { 78 R.id.menu_driver_use_global -> {
79 StringSetting.DRIVER_PATH.global = true 79 StringSetting.DRIVER_PATH.global = true
80 driverViewModel.updateDriverList() 80 driverViewModel.updateDriverList()
81 (binding.listDrivers.adapter as DriverAdapter) 81 (binding.listDrivers.adapter as DriverAdapter)
@@ -93,7 +93,7 @@ class DriverManagerFragment : Fragment() {
93 repeatOnLifecycle(Lifecycle.State.STARTED) { 93 repeatOnLifecycle(Lifecycle.State.STARTED) {
94 driverViewModel.showClearButton.collect { 94 driverViewModel.showClearButton.collect {
95 binding.toolbarDrivers.menu 95 binding.toolbarDrivers.menu
96 .findItem(R.id.menu_driver_clear).isVisible = it 96 .findItem(R.id.menu_driver_use_global).isVisible = it
97 } 97 }
98 } 98 }
99 } 99 }
@@ -173,11 +173,11 @@ class DriverManagerFragment : Fragment() {
173 return@registerForActivityResult 173 return@registerForActivityResult
174 } 174 }
175 175
176 IndeterminateProgressDialogFragment.newInstance( 176 ProgressDialogFragment.newInstance(
177 requireActivity(), 177 requireActivity(),
178 R.string.installing_driver, 178 R.string.installing_driver,
179 false 179 false
180 ) { 180 ) { _, _ ->
181 val driverPath = 181 val driverPath =
182 "${GpuDriverHelper.driverStoragePath}${FileUtil.getFilename(result)}" 182 "${GpuDriverHelper.driverStoragePath}${FileUtil.getFilename(result)}"
183 val driverFile = File(driverPath) 183 val driverFile = File(driverPath)
@@ -213,6 +213,6 @@ class DriverManagerFragment : Fragment() {
213 } 213 }
214 } 214 }
215 return@newInstance Any() 215 return@newInstance Any()
216 }.show(childFragmentManager, IndeterminateProgressDialogFragment.TAG) 216 }.show(childFragmentManager, ProgressDialogFragment.TAG)
217 } 217 }
218} 218}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 47767454a..2a97ae14d 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -182,11 +182,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
182 } 182 }
183 183
184 override fun onDrawerOpened(drawerView: View) { 184 override fun onDrawerOpened(drawerView: View) {
185 // No op 185 binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
186 } 186 }
187 187
188 override fun onDrawerClosed(drawerView: View) { 188 override fun onDrawerClosed(drawerView: View) {
189 // No op 189 binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt())
190 } 190 }
191 191
192 override fun onDrawerStateChanged(newState: Int) { 192 override fun onDrawerStateChanged(newState: Int) {
@@ -196,6 +196,28 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
196 binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) 196 binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
197 binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text = 197 binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
198 game.title 198 game.title
199
200 binding.inGameMenu.menu.findItem(R.id.menu_lock_drawer).apply {
201 val lockMode = IntSetting.LOCK_DRAWER.getInt()
202 val titleId = if (lockMode == DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
203 R.string.unlock_drawer
204 } else {
205 R.string.lock_drawer
206 }
207 val iconId = if (lockMode == DrawerLayout.LOCK_MODE_UNLOCKED) {
208 R.drawable.ic_unlock
209 } else {
210 R.drawable.ic_lock
211 }
212
213 title = getString(titleId)
214 icon = ResourcesCompat.getDrawable(
215 resources,
216 iconId,
217 requireContext().theme
218 )
219 }
220
199 binding.inGameMenu.setNavigationItemSelectedListener { 221 binding.inGameMenu.setNavigationItemSelectedListener {
200 when (it.itemId) { 222 when (it.itemId) {
201 R.id.menu_pause_emulation -> { 223 R.id.menu_pause_emulation -> {
@@ -242,6 +264,32 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
242 true 264 true
243 } 265 }
244 266
267 R.id.menu_lock_drawer -> {
268 when (IntSetting.LOCK_DRAWER.getInt()) {
269 DrawerLayout.LOCK_MODE_UNLOCKED -> {
270 IntSetting.LOCK_DRAWER.setInt(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
271 it.title = resources.getString(R.string.unlock_drawer)
272 it.icon = ResourcesCompat.getDrawable(
273 resources,
274 R.drawable.ic_lock,
275 requireContext().theme
276 )
277 }
278
279 DrawerLayout.LOCK_MODE_LOCKED_CLOSED -> {
280 IntSetting.LOCK_DRAWER.setInt(DrawerLayout.LOCK_MODE_UNLOCKED)
281 it.title = resources.getString(R.string.lock_drawer)
282 it.icon = ResourcesCompat.getDrawable(
283 resources,
284 R.drawable.ic_unlock,
285 requireContext().theme
286 )
287 }
288 }
289 NativeConfig.saveGlobalConfig()
290 true
291 }
292
245 R.id.menu_exit -> { 293 R.id.menu_exit -> {
246 emulationState.stop() 294 emulationState.stop()
247 emulationViewModel.setIsEmulationStopping(true) 295 emulationViewModel.setIsEmulationStopping(true)
@@ -326,7 +374,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
326 repeatOnLifecycle(Lifecycle.State.CREATED) { 374 repeatOnLifecycle(Lifecycle.State.CREATED) {
327 emulationViewModel.emulationStarted.collectLatest { 375 emulationViewModel.emulationStarted.collectLatest {
328 if (it) { 376 if (it) {
329 binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED) 377 binding.drawerLayout.setDrawerLockMode(IntSetting.LOCK_DRAWER.getInt())
330 ViewUtils.showView(binding.surfaceInputOverlay) 378 ViewUtils.showView(binding.surfaceInputOverlay)
331 ViewUtils.hideView(binding.loadingIndicator) 379 ViewUtils.hideView(binding.loadingIndicator)
332 380
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt
index fa2a4c9f9..5aa3f453f 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GameInfoFragment.kt
@@ -21,8 +21,10 @@ import androidx.fragment.app.activityViewModels
21import androidx.navigation.findNavController 21import androidx.navigation.findNavController
22import androidx.navigation.fragment.navArgs 22import androidx.navigation.fragment.navArgs
23import com.google.android.material.transition.MaterialSharedAxis 23import com.google.android.material.transition.MaterialSharedAxis
24import org.yuzu.yuzu_emu.NativeLibrary
24import org.yuzu.yuzu_emu.R 25import org.yuzu.yuzu_emu.R
25import org.yuzu.yuzu_emu.databinding.FragmentGameInfoBinding 26import org.yuzu.yuzu_emu.databinding.FragmentGameInfoBinding
27import org.yuzu.yuzu_emu.model.GameVerificationResult
26import org.yuzu.yuzu_emu.model.HomeViewModel 28import org.yuzu.yuzu_emu.model.HomeViewModel
27import org.yuzu.yuzu_emu.utils.GameMetadata 29import org.yuzu.yuzu_emu.utils.GameMetadata
28 30
@@ -101,6 +103,38 @@ class GameInfoFragment : Fragment() {
101 """.trimIndent() 103 """.trimIndent()
102 copyToClipboard(args.game.title, details) 104 copyToClipboard(args.game.title, details)
103 } 105 }
106
107 buttonVerifyIntegrity.setOnClickListener {
108 ProgressDialogFragment.newInstance(
109 requireActivity(),
110 R.string.verifying,
111 true
112 ) { progressCallback, _ ->
113 val result = GameVerificationResult.from(
114 NativeLibrary.verifyGameContents(
115 args.game.path,
116 progressCallback
117 )
118 )
119 return@newInstance when (result) {
120 GameVerificationResult.Success ->
121 MessageDialogFragment.newInstance(
122 titleId = R.string.verify_success,
123 descriptionId = R.string.operation_completed_successfully
124 )
125 GameVerificationResult.Failed ->
126 MessageDialogFragment.newInstance(
127 titleId = R.string.verify_failure,
128 descriptionId = R.string.verify_failure_description
129 )
130 GameVerificationResult.NotImplemented ->
131 MessageDialogFragment.newInstance(
132 titleId = R.string.verify_no_result,
133 descriptionId = R.string.verify_no_result_description
134 )
135 }
136 }.show(parentFragmentManager, ProgressDialogFragment.TAG)
137 }
104 } 138 }
105 139
106 setInsets() 140 setInsets()
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt
index b04d1208f..582df0133 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/GamePropertiesFragment.kt
@@ -4,6 +4,8 @@
4package org.yuzu.yuzu_emu.fragments 4package org.yuzu.yuzu_emu.fragments
5 5
6import android.annotation.SuppressLint 6import android.annotation.SuppressLint
7import android.content.pm.ShortcutInfo
8import android.content.pm.ShortcutManager
7import android.os.Bundle 9import android.os.Bundle
8import android.text.TextUtils 10import android.text.TextUtils
9import android.view.LayoutInflater 11import android.view.LayoutInflater
@@ -44,7 +46,6 @@ import org.yuzu.yuzu_emu.utils.FileUtil
44import org.yuzu.yuzu_emu.utils.GameIconUtils 46import org.yuzu.yuzu_emu.utils.GameIconUtils
45import org.yuzu.yuzu_emu.utils.GpuDriverHelper 47import org.yuzu.yuzu_emu.utils.GpuDriverHelper
46import org.yuzu.yuzu_emu.utils.MemoryUtil 48import org.yuzu.yuzu_emu.utils.MemoryUtil
47import java.io.BufferedInputStream
48import java.io.BufferedOutputStream 49import java.io.BufferedOutputStream
49import java.io.File 50import java.io.File
50 51
@@ -85,6 +86,24 @@ class GamePropertiesFragment : Fragment() {
85 view.findNavController().popBackStack() 86 view.findNavController().popBackStack()
86 } 87 }
87 88
89 val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java)
90 binding.buttonShortcut.isEnabled = shortcutManager.isRequestPinShortcutSupported
91 binding.buttonShortcut.setOnClickListener {
92 viewLifecycleOwner.lifecycleScope.launch {
93 withContext(Dispatchers.IO) {
94 val shortcut = ShortcutInfo.Builder(requireContext(), args.game.title)
95 .setShortLabel(args.game.title)
96 .setIcon(
97 GameIconUtils.getShortcutIcon(requireActivity(), args.game)
98 .toIcon(requireContext())
99 )
100 .setIntent(args.game.launchIntent)
101 .build()
102 shortcutManager.requestPinShortcut(shortcut, null)
103 }
104 }
105 }
106
88 GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen) 107 GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen)
89 binding.title.text = args.game.title 108 binding.title.text = args.game.title
90 binding.title.postDelayed( 109 binding.title.postDelayed(
@@ -357,27 +376,17 @@ class GamePropertiesFragment : Fragment() {
357 return@registerForActivityResult 376 return@registerForActivityResult
358 } 377 }
359 378
360 val inputZip = requireContext().contentResolver.openInputStream(result)
361 val savesFolder = File(args.game.saveDir) 379 val savesFolder = File(args.game.saveDir)
362 val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") 380 val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/")
363 cacheSaveDir.mkdir() 381 cacheSaveDir.mkdir()
364 382
365 if (inputZip == null) { 383 ProgressDialogFragment.newInstance(
366 Toast.makeText(
367 YuzuApplication.appContext,
368 getString(R.string.fatal_error),
369 Toast.LENGTH_LONG
370 ).show()
371 return@registerForActivityResult
372 }
373
374 IndeterminateProgressDialogFragment.newInstance(
375 requireActivity(), 384 requireActivity(),
376 R.string.save_files_importing, 385 R.string.save_files_importing,
377 false 386 false
378 ) { 387 ) { _, _ ->
379 try { 388 try {
380 FileUtil.unzipToInternalStorage(BufferedInputStream(inputZip), cacheSaveDir) 389 FileUtil.unzipToInternalStorage(result.toString(), cacheSaveDir)
381 val files = cacheSaveDir.listFiles() 390 val files = cacheSaveDir.listFiles()
382 var savesFolderFile: File? = null 391 var savesFolderFile: File? = null
383 if (files != null) { 392 if (files != null) {
@@ -422,7 +431,7 @@ class GamePropertiesFragment : Fragment() {
422 Toast.LENGTH_LONG 431 Toast.LENGTH_LONG
423 ).show() 432 ).show()
424 } 433 }
425 }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) 434 }.show(parentFragmentManager, ProgressDialogFragment.TAG)
426 } 435 }
427 436
428 /** 437 /**
@@ -436,11 +445,11 @@ class GamePropertiesFragment : Fragment() {
436 return@registerForActivityResult 445 return@registerForActivityResult
437 } 446 }
438 447
439 IndeterminateProgressDialogFragment.newInstance( 448 ProgressDialogFragment.newInstance(
440 requireActivity(), 449 requireActivity(),
441 R.string.save_files_exporting, 450 R.string.save_files_exporting,
442 false 451 false
443 ) { 452 ) { _, _ ->
444 val saveLocation = args.game.saveDir 453 val saveLocation = args.game.saveDir
445 val zipResult = FileUtil.zipFromInternalStorage( 454 val zipResult = FileUtil.zipFromInternalStorage(
446 File(saveLocation), 455 File(saveLocation),
@@ -452,6 +461,6 @@ class GamePropertiesFragment : Fragment() {
452 TaskState.Completed -> getString(R.string.export_success) 461 TaskState.Completed -> getString(R.string.export_success)
453 TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed) 462 TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed)
454 } 463 }
455 }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) 464 }.show(parentFragmentManager, ProgressDialogFragment.TAG)
456 } 465 }
457} 466}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
index 6ddd758e6..aefae2938 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt
@@ -32,6 +32,7 @@ import org.yuzu.yuzu_emu.BuildConfig
32import org.yuzu.yuzu_emu.HomeNavigationDirections 32import org.yuzu.yuzu_emu.HomeNavigationDirections
33import org.yuzu.yuzu_emu.NativeLibrary 33import org.yuzu.yuzu_emu.NativeLibrary
34import org.yuzu.yuzu_emu.R 34import org.yuzu.yuzu_emu.R
35import org.yuzu.yuzu_emu.YuzuApplication
35import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter 36import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
36import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding 37import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding
37import org.yuzu.yuzu_emu.features.DocumentProvider 38import org.yuzu.yuzu_emu.features.DocumentProvider
@@ -142,6 +143,38 @@ class HomeSettingsFragment : Fragment() {
142 ) 143 )
143 add( 144 add(
144 HomeSetting( 145 HomeSetting(
146 R.string.verify_installed_content,
147 R.string.verify_installed_content_description,
148 R.drawable.ic_check_circle,
149 {
150 ProgressDialogFragment.newInstance(
151 requireActivity(),
152 titleId = R.string.verifying,
153 cancellable = true
154 ) { progressCallback, _ ->
155 val result = NativeLibrary.verifyInstalledContents(progressCallback)
156 return@newInstance if (result.isEmpty()) {
157 MessageDialogFragment.newInstance(
158 titleId = R.string.verify_success,
159 descriptionId = R.string.operation_completed_successfully
160 )
161 } else {
162 val failedNames = result.joinToString("\n")
163 val errorMessage = YuzuApplication.appContext.getString(
164 R.string.verification_failed_for,
165 failedNames
166 )
167 MessageDialogFragment.newInstance(
168 titleId = R.string.verify_failure,
169 descriptionString = errorMessage
170 )
171 }
172 }.show(parentFragmentManager, ProgressDialogFragment.TAG)
173 }
174 )
175 )
176 add(
177 HomeSetting(
145 R.string.share_log, 178 R.string.share_log,
146 R.string.share_log_description, 179 R.string.share_log_description,
147 R.drawable.ic_log, 180 R.drawable.ic_log,
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt
index 5b4bf2c9f..7df8e6bf4 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/InstallableFragment.kt
@@ -34,7 +34,6 @@ import org.yuzu.yuzu_emu.model.TaskState
34import org.yuzu.yuzu_emu.ui.main.MainActivity 34import org.yuzu.yuzu_emu.ui.main.MainActivity
35import org.yuzu.yuzu_emu.utils.DirectoryInitialization 35import org.yuzu.yuzu_emu.utils.DirectoryInitialization
36import org.yuzu.yuzu_emu.utils.FileUtil 36import org.yuzu.yuzu_emu.utils.FileUtil
37import java.io.BufferedInputStream
38import java.io.BufferedOutputStream 37import java.io.BufferedOutputStream
39import java.io.File 38import java.io.File
40import java.math.BigInteger 39import java.math.BigInteger
@@ -195,26 +194,20 @@ class InstallableFragment : Fragment() {
195 return@registerForActivityResult 194 return@registerForActivityResult
196 } 195 }
197 196
198 val inputZip = requireContext().contentResolver.openInputStream(result)
199 val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") 197 val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/")
200 cacheSaveDir.mkdir() 198 cacheSaveDir.mkdir()
201 199
202 if (inputZip == null) { 200 ProgressDialogFragment.newInstance(
203 Toast.makeText(
204 YuzuApplication.appContext,
205 getString(R.string.fatal_error),
206 Toast.LENGTH_LONG
207 ).show()
208 return@registerForActivityResult
209 }
210
211 IndeterminateProgressDialogFragment.newInstance(
212 requireActivity(), 201 requireActivity(),
213 R.string.save_files_importing, 202 R.string.save_files_importing,
214 false 203 false
215 ) { 204 ) { progressCallback, _ ->
216 try { 205 try {
217 FileUtil.unzipToInternalStorage(BufferedInputStream(inputZip), cacheSaveDir) 206 FileUtil.unzipToInternalStorage(
207 result.toString(),
208 cacheSaveDir,
209 progressCallback
210 )
218 val files = cacheSaveDir.listFiles() 211 val files = cacheSaveDir.listFiles()
219 var successfulImports = 0 212 var successfulImports = 0
220 var failedImports = 0 213 var failedImports = 0
@@ -287,7 +280,7 @@ class InstallableFragment : Fragment() {
287 Toast.LENGTH_LONG 280 Toast.LENGTH_LONG
288 ).show() 281 ).show()
289 } 282 }
290 }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) 283 }.show(parentFragmentManager, ProgressDialogFragment.TAG)
291 } 284 }
292 285
293 private val exportSaves = registerForActivityResult( 286 private val exportSaves = registerForActivityResult(
@@ -297,11 +290,11 @@ class InstallableFragment : Fragment() {
297 return@registerForActivityResult 290 return@registerForActivityResult
298 } 291 }
299 292
300 IndeterminateProgressDialogFragment.newInstance( 293 ProgressDialogFragment.newInstance(
301 requireActivity(), 294 requireActivity(),
302 R.string.save_files_exporting, 295 R.string.save_files_exporting,
303 false 296 false
304 ) { 297 ) { _, _ ->
305 val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/") 298 val cacheSaveDir = File("${requireContext().cacheDir.path}/saves/")
306 cacheSaveDir.mkdir() 299 cacheSaveDir.mkdir()
307 300
@@ -338,6 +331,6 @@ class InstallableFragment : Fragment() {
338 TaskState.Completed -> getString(R.string.export_success) 331 TaskState.Completed -> getString(R.string.export_success)
339 TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed) 332 TaskState.Cancelled, TaskState.Failed -> getString(R.string.export_failed)
340 } 333 }
341 }.show(parentFragmentManager, IndeterminateProgressDialogFragment.TAG) 334 }.show(parentFragmentManager, ProgressDialogFragment.TAG)
342 } 335 }
343} 336}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt
index 32062b6fe..620d8db7c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt
@@ -69,7 +69,7 @@ class MessageDialogFragment : DialogFragment() {
69 private const val HELP_LINK = "Link" 69 private const val HELP_LINK = "Link"
70 70
71 fun newInstance( 71 fun newInstance(
72 activity: FragmentActivity, 72 activity: FragmentActivity? = null,
73 titleId: Int = 0, 73 titleId: Int = 0,
74 titleString: String = "", 74 titleString: String = "",
75 descriptionId: Int = 0, 75 descriptionId: Int = 0,
@@ -86,9 +86,11 @@ class MessageDialogFragment : DialogFragment() {
86 putString(DESCRIPTION_STRING, descriptionString) 86 putString(DESCRIPTION_STRING, descriptionString)
87 putInt(HELP_LINK, helpLinkId) 87 putInt(HELP_LINK, helpLinkId)
88 } 88 }
89 ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply { 89 if (activity != null) {
90 clear() 90 ViewModelProvider(activity)[MessageDialogViewModel::class.java].apply {
91 this.positiveAction = positiveAction 91 clear()
92 this.positiveAction = positiveAction
93 }
92 } 94 }
93 dialog.arguments = bundle 95 dialog.arguments = bundle
94 return dialog 96 return dialog
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProgressDialogFragment.kt
index 8847e5531..d201cb80c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/ProgressDialogFragment.kt
@@ -23,11 +23,13 @@ import org.yuzu.yuzu_emu.R
23import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding 23import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
24import org.yuzu.yuzu_emu.model.TaskViewModel 24import org.yuzu.yuzu_emu.model.TaskViewModel
25 25
26class IndeterminateProgressDialogFragment : DialogFragment() { 26class ProgressDialogFragment : DialogFragment() {
27 private val taskViewModel: TaskViewModel by activityViewModels() 27 private val taskViewModel: TaskViewModel by activityViewModels()
28 28
29 private lateinit var binding: DialogProgressBarBinding 29 private lateinit var binding: DialogProgressBarBinding
30 30
31 private val PROGRESS_BAR_RESOLUTION = 1000
32
31 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { 33 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
32 val titleId = requireArguments().getInt(TITLE) 34 val titleId = requireArguments().getInt(TITLE)
33 val cancellable = requireArguments().getBoolean(CANCELLABLE) 35 val cancellable = requireArguments().getBoolean(CANCELLABLE)
@@ -61,6 +63,7 @@ class IndeterminateProgressDialogFragment : DialogFragment() {
61 63
62 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 64 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
63 super.onViewCreated(view, savedInstanceState) 65 super.onViewCreated(view, savedInstanceState)
66 binding.message.isSelected = true
64 viewLifecycleOwner.lifecycleScope.apply { 67 viewLifecycleOwner.lifecycleScope.apply {
65 launch { 68 launch {
66 repeatOnLifecycle(Lifecycle.State.CREATED) { 69 repeatOnLifecycle(Lifecycle.State.CREATED) {
@@ -97,6 +100,35 @@ class IndeterminateProgressDialogFragment : DialogFragment() {
97 } 100 }
98 } 101 }
99 } 102 }
103 launch {
104 repeatOnLifecycle(Lifecycle.State.CREATED) {
105 taskViewModel.progress.collect {
106 if (it != 0.0) {
107 binding.progressBar.apply {
108 isIndeterminate = false
109 progress = (
110 (it / taskViewModel.maxProgress.value) *
111 PROGRESS_BAR_RESOLUTION
112 ).toInt()
113 min = 0
114 max = PROGRESS_BAR_RESOLUTION
115 }
116 }
117 }
118 }
119 }
120 launch {
121 repeatOnLifecycle(Lifecycle.State.CREATED) {
122 taskViewModel.message.collect {
123 if (it.isEmpty()) {
124 binding.message.visibility = View.GONE
125 } else {
126 binding.message.visibility = View.VISIBLE
127 binding.message.text = it
128 }
129 }
130 }
131 }
100 } 132 }
101 } 133 }
102 134
@@ -108,6 +140,7 @@ class IndeterminateProgressDialogFragment : DialogFragment() {
108 val negativeButton = alertDialog.getButton(Dialog.BUTTON_NEGATIVE) 140 val negativeButton = alertDialog.getButton(Dialog.BUTTON_NEGATIVE)
109 negativeButton.setOnClickListener { 141 negativeButton.setOnClickListener {
110 alertDialog.setTitle(getString(R.string.cancelling)) 142 alertDialog.setTitle(getString(R.string.cancelling))
143 binding.progressBar.isIndeterminate = true
111 taskViewModel.setCancelled(true) 144 taskViewModel.setCancelled(true)
112 } 145 }
113 } 146 }
@@ -122,9 +155,12 @@ class IndeterminateProgressDialogFragment : DialogFragment() {
122 activity: FragmentActivity, 155 activity: FragmentActivity,
123 titleId: Int, 156 titleId: Int,
124 cancellable: Boolean = false, 157 cancellable: Boolean = false,
125 task: suspend () -> Any 158 task: suspend (
126 ): IndeterminateProgressDialogFragment { 159 progressCallback: (max: Long, progress: Long) -> Boolean,
127 val dialog = IndeterminateProgressDialogFragment() 160 messageCallback: (message: String) -> Unit
161 ) -> Any
162 ): ProgressDialogFragment {
163 val dialog = ProgressDialogFragment()
128 val args = Bundle() 164 val args = Bundle()
129 ViewModelProvider(activity)[TaskViewModel::class.java].task = task 165 ViewModelProvider(activity)[TaskViewModel::class.java].task = task
130 args.putInt(TITLE, titleId) 166 args.putInt(TITLE, titleId)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt
index 64b295fbd..20b10b1a0 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt
@@ -136,14 +136,14 @@ class SearchFragment : Fragment() {
136 baseList.filter { 136 baseList.filter {
137 val lastPlayedTime = preferences.getLong(it.keyLastPlayedTime, 0L) 137 val lastPlayedTime = preferences.getLong(it.keyLastPlayedTime, 0L)
138 lastPlayedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000) 138 lastPlayedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000)
139 } 139 }.sortedByDescending { preferences.getLong(it.keyLastPlayedTime, 0L) }
140 } 140 }
141 141
142 R.id.chip_recently_added -> { 142 R.id.chip_recently_added -> {
143 baseList.filter { 143 baseList.filter {
144 val addedTime = preferences.getLong(it.keyAddedToLibraryTime, 0L) 144 val addedTime = preferences.getLong(it.keyAddedToLibraryTime, 0L)
145 addedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000) 145 addedTime > (System.currentTimeMillis() - 24 * 60 * 60 * 1000)
146 } 146 }.sortedByDescending { preferences.getLong(it.keyAddedToLibraryTime, 0L) }
147 } 147 }
148 148
149 R.id.chip_homebrew -> baseList.filter { it.isHomebrew } 149 R.id.chip_homebrew -> baseList.filter { it.isHomebrew }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt
deleted file mode 100644
index ed79a8b02..000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Addon.kt
+++ /dev/null
@@ -1,10 +0,0 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.model
5
6data class Addon(
7 var enabled: Boolean,
8 val title: String,
9 val version: String
10)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt
index 075252f5b..b9c8e49ca 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/AddonViewModel.kt
@@ -15,8 +15,8 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
15import java.util.concurrent.atomic.AtomicBoolean 15import java.util.concurrent.atomic.AtomicBoolean
16 16
17class AddonViewModel : ViewModel() { 17class AddonViewModel : ViewModel() {
18 private val _addonList = MutableStateFlow(mutableListOf<Addon>()) 18 private val _patchList = MutableStateFlow(mutableListOf<Patch>())
19 val addonList get() = _addonList.asStateFlow() 19 val addonList get() = _patchList.asStateFlow()
20 20
21 private val _showModInstallPicker = MutableStateFlow(false) 21 private val _showModInstallPicker = MutableStateFlow(false)
22 val showModInstallPicker get() = _showModInstallPicker.asStateFlow() 22 val showModInstallPicker get() = _showModInstallPicker.asStateFlow()
@@ -24,6 +24,9 @@ class AddonViewModel : ViewModel() {
24 private val _showModNoticeDialog = MutableStateFlow(false) 24 private val _showModNoticeDialog = MutableStateFlow(false)
25 val showModNoticeDialog get() = _showModNoticeDialog.asStateFlow() 25 val showModNoticeDialog get() = _showModNoticeDialog.asStateFlow()
26 26
27 private val _addonToDelete = MutableStateFlow<Patch?>(null)
28 val addonToDelete = _addonToDelete.asStateFlow()
29
27 var game: Game? = null 30 var game: Game? = null
28 31
29 private val isRefreshing = AtomicBoolean(false) 32 private val isRefreshing = AtomicBoolean(false)
@@ -40,36 +43,47 @@ class AddonViewModel : ViewModel() {
40 isRefreshing.set(true) 43 isRefreshing.set(true)
41 viewModelScope.launch { 44 viewModelScope.launch {
42 withContext(Dispatchers.IO) { 45 withContext(Dispatchers.IO) {
43 val addonList = mutableListOf<Addon>() 46 val patchList = (
44 val disabledAddons = NativeConfig.getDisabledAddons(game!!.programId) 47 NativeLibrary.getPatchesForFile(game!!.path, game!!.programId)
45 NativeLibrary.getAddonsForFile(game!!.path, game!!.programId)?.forEach { 48 ?: emptyArray()
46 val name = it.first.replace("[D] ", "") 49 ).toMutableList()
47 addonList.add(Addon(!disabledAddons.contains(name), name, it.second)) 50 patchList.sortBy { it.name }
48 } 51 _patchList.value = patchList
49 addonList.sortBy { it.title }
50 _addonList.value = addonList
51 isRefreshing.set(false) 52 isRefreshing.set(false)
52 } 53 }
53 } 54 }
54 } 55 }
55 56
57 fun setAddonToDelete(patch: Patch?) {
58 _addonToDelete.value = patch
59 }
60
61 fun onDeleteAddon(patch: Patch) {
62 when (PatchType.from(patch.type)) {
63 PatchType.Update -> NativeLibrary.removeUpdate(patch.programId)
64 PatchType.DLC -> NativeLibrary.removeDLC(patch.programId)
65 PatchType.Mod -> NativeLibrary.removeMod(patch.programId, patch.name)
66 }
67 refreshAddons()
68 }
69
56 fun onCloseAddons() { 70 fun onCloseAddons() {
57 if (_addonList.value.isEmpty()) { 71 if (_patchList.value.isEmpty()) {
58 return 72 return
59 } 73 }
60 74
61 NativeConfig.setDisabledAddons( 75 NativeConfig.setDisabledAddons(
62 game!!.programId, 76 game!!.programId,
63 _addonList.value.mapNotNull { 77 _patchList.value.mapNotNull {
64 if (it.enabled) { 78 if (it.enabled) {
65 null 79 null
66 } else { 80 } else {
67 it.title 81 it.name
68 } 82 }
69 }.toTypedArray() 83 }.toTypedArray()
70 ) 84 )
71 NativeConfig.saveGlobalConfig() 85 NativeConfig.saveGlobalConfig()
72 _addonList.value.clear() 86 _patchList.value.clear()
73 game = null 87 game = null
74 } 88 }
75 89
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt
index f1ea1e20f..c8a4a2d17 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt
@@ -3,6 +3,7 @@
3 3
4package org.yuzu.yuzu_emu.model 4package org.yuzu.yuzu_emu.model
5 5
6import android.content.Intent
6import android.net.Uri 7import android.net.Uri
7import android.os.Parcelable 8import android.os.Parcelable
8import java.util.HashSet 9import java.util.HashSet
@@ -11,6 +12,7 @@ import kotlinx.serialization.Serializable
11import org.yuzu.yuzu_emu.NativeLibrary 12import org.yuzu.yuzu_emu.NativeLibrary
12import org.yuzu.yuzu_emu.R 13import org.yuzu.yuzu_emu.R
13import org.yuzu.yuzu_emu.YuzuApplication 14import org.yuzu.yuzu_emu.YuzuApplication
15import org.yuzu.yuzu_emu.activities.EmulationActivity
14import org.yuzu.yuzu_emu.utils.DirectoryInitialization 16import org.yuzu.yuzu_emu.utils.DirectoryInitialization
15import org.yuzu.yuzu_emu.utils.FileUtil 17import org.yuzu.yuzu_emu.utils.FileUtil
16import java.time.LocalDateTime 18import java.time.LocalDateTime
@@ -61,6 +63,12 @@ class Game(
61 val addonDir: String 63 val addonDir: String
62 get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/" 64 get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/"
63 65
66 val launchIntent: Intent
67 get() = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
68 action = Intent.ACTION_VIEW
69 data = Uri.parse(path)
70 }
71
64 override fun equals(other: Any?): Boolean { 72 override fun equals(other: Any?): Boolean {
65 if (other !is Game) { 73 if (other !is Game) {
66 return false 74 return false
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameVerificationResult.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameVerificationResult.kt
new file mode 100644
index 000000000..804637fb8
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GameVerificationResult.kt
@@ -0,0 +1,15 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.model
5
6enum class GameVerificationResult(val int: Int) {
7 Success(0),
8 Failed(1),
9 NotImplemented(2);
10
11 companion object {
12 fun from(int: Int): GameVerificationResult =
13 entries.firstOrNull { it.int == int } ?: Success
14 }
15}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt
new file mode 100644
index 000000000..0c3cd0521
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt
@@ -0,0 +1,15 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.model
5
6enum class InstallResult(val int: Int) {
7 Success(0),
8 Overwrite(1),
9 Failure(2),
10 BaseInstallAttempted(3);
11
12 companion object {
13 fun from(int: Int): InstallResult = entries.firstOrNull { it.int == int } ?: Success
14 }
15}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Patch.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Patch.kt
new file mode 100644
index 000000000..25cb9e365
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Patch.kt
@@ -0,0 +1,16 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.model
5
6import androidx.annotation.Keep
7
8@Keep
9data class Patch(
10 var enabled: Boolean,
11 val name: String,
12 val version: String,
13 val type: Int,
14 val programId: String,
15 val titleId: String
16)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/PatchType.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/PatchType.kt
new file mode 100644
index 000000000..e9a54162b
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/PatchType.kt
@@ -0,0 +1,14 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.model
5
6enum class PatchType(val int: Int) {
7 Update(0),
8 DLC(1),
9 Mod(2);
10
11 companion object {
12 fun from(int: Int): PatchType = entries.firstOrNull { it.int == int } ?: Update
13 }
14}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
index e59c95733..4361eb972 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt
@@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope
8import kotlinx.coroutines.Dispatchers 8import kotlinx.coroutines.Dispatchers
9import kotlinx.coroutines.flow.MutableStateFlow 9import kotlinx.coroutines.flow.MutableStateFlow
10import kotlinx.coroutines.flow.StateFlow 10import kotlinx.coroutines.flow.StateFlow
11import kotlinx.coroutines.flow.asStateFlow
11import kotlinx.coroutines.launch 12import kotlinx.coroutines.launch
12 13
13class TaskViewModel : ViewModel() { 14class TaskViewModel : ViewModel() {
@@ -23,13 +24,28 @@ class TaskViewModel : ViewModel() {
23 val cancelled: StateFlow<Boolean> get() = _cancelled 24 val cancelled: StateFlow<Boolean> get() = _cancelled
24 private val _cancelled = MutableStateFlow(false) 25 private val _cancelled = MutableStateFlow(false)
25 26
26 lateinit var task: suspend () -> Any 27 private val _progress = MutableStateFlow(0.0)
28 val progress = _progress.asStateFlow()
29
30 private val _maxProgress = MutableStateFlow(0.0)
31 val maxProgress = _maxProgress.asStateFlow()
32
33 private val _message = MutableStateFlow("")
34 val message = _message.asStateFlow()
35
36 lateinit var task: suspend (
37 progressCallback: (max: Long, progress: Long) -> Boolean,
38 messageCallback: (message: String) -> Unit
39 ) -> Any
27 40
28 fun clear() { 41 fun clear() {
29 _result.value = Any() 42 _result.value = Any()
30 _isComplete.value = false 43 _isComplete.value = false
31 _isRunning.value = false 44 _isRunning.value = false
32 _cancelled.value = false 45 _cancelled.value = false
46 _progress.value = 0.0
47 _maxProgress.value = 0.0
48 _message.value = ""
33 } 49 }
34 50
35 fun setCancelled(value: Boolean) { 51 fun setCancelled(value: Boolean) {
@@ -43,7 +59,16 @@ class TaskViewModel : ViewModel() {
43 _isRunning.value = true 59 _isRunning.value = true
44 60
45 viewModelScope.launch(Dispatchers.IO) { 61 viewModelScope.launch(Dispatchers.IO) {
46 val res = task() 62 val res = task(
63 { max, progress ->
64 _maxProgress.value = max.toDouble()
65 _progress.value = progress.toDouble()
66 return@task cancelled.value
67 },
68 { message ->
69 _message.value = message
70 }
71 )
47 _result.value = res 72 _result.value = res
48 _isComplete.value = true 73 _isComplete.value = true
49 _isRunning.value = false 74 _isRunning.value = false
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index 644289e25..c2cc29961 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -38,12 +38,13 @@ import org.yuzu.yuzu_emu.activities.EmulationActivity
38import org.yuzu.yuzu_emu.databinding.ActivityMainBinding 38import org.yuzu.yuzu_emu.databinding.ActivityMainBinding
39import org.yuzu.yuzu_emu.features.settings.model.Settings 39import org.yuzu.yuzu_emu.features.settings.model.Settings
40import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment 40import org.yuzu.yuzu_emu.fragments.AddGameFolderDialogFragment
41import org.yuzu.yuzu_emu.fragments.IndeterminateProgressDialogFragment 41import org.yuzu.yuzu_emu.fragments.ProgressDialogFragment
42import org.yuzu.yuzu_emu.fragments.MessageDialogFragment 42import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
43import org.yuzu.yuzu_emu.model.AddonViewModel 43import org.yuzu.yuzu_emu.model.AddonViewModel
44import org.yuzu.yuzu_emu.model.DriverViewModel 44import org.yuzu.yuzu_emu.model.DriverViewModel
45import org.yuzu.yuzu_emu.model.GamesViewModel 45import org.yuzu.yuzu_emu.model.GamesViewModel
46import org.yuzu.yuzu_emu.model.HomeViewModel 46import org.yuzu.yuzu_emu.model.HomeViewModel
47import org.yuzu.yuzu_emu.model.InstallResult
47import org.yuzu.yuzu_emu.model.TaskState 48import org.yuzu.yuzu_emu.model.TaskState
48import org.yuzu.yuzu_emu.model.TaskViewModel 49import org.yuzu.yuzu_emu.model.TaskViewModel
49import org.yuzu.yuzu_emu.utils.* 50import org.yuzu.yuzu_emu.utils.*
@@ -369,26 +370,23 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
369 return@registerForActivityResult 370 return@registerForActivityResult
370 } 371 }
371 372
372 val inputZip = contentResolver.openInputStream(result)
373 if (inputZip == null) {
374 Toast.makeText(
375 applicationContext,
376 getString(R.string.fatal_error),
377 Toast.LENGTH_LONG
378 ).show()
379 return@registerForActivityResult
380 }
381
382 val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") } 373 val filterNCA = FilenameFilter { _, dirName -> dirName.endsWith(".nca") }
383 374
384 val firmwarePath = 375 val firmwarePath =
385 File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/") 376 File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
386 val cacheFirmwareDir = File("${cacheDir.path}/registered/") 377 val cacheFirmwareDir = File("${cacheDir.path}/registered/")
387 378
388 val task: () -> Any = { 379 ProgressDialogFragment.newInstance(
380 this,
381 R.string.firmware_installing
382 ) { progressCallback, _ ->
389 var messageToShow: Any 383 var messageToShow: Any
390 try { 384 try {
391 FileUtil.unzipToInternalStorage(BufferedInputStream(inputZip), cacheFirmwareDir) 385 FileUtil.unzipToInternalStorage(
386 result.toString(),
387 cacheFirmwareDir,
388 progressCallback
389 )
392 val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1 390 val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
393 val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2 391 val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
394 messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) { 392 messageToShow = if (unfilteredNumOfFiles != filteredNumOfFiles) {
@@ -404,18 +402,13 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
404 getString(R.string.save_file_imported_success) 402 getString(R.string.save_file_imported_success)
405 } 403 }
406 } catch (e: Exception) { 404 } catch (e: Exception) {
405 Log.error("[MainActivity] Firmware install failed - ${e.message}")
407 messageToShow = getString(R.string.fatal_error) 406 messageToShow = getString(R.string.fatal_error)
408 } finally { 407 } finally {
409 cacheFirmwareDir.deleteRecursively() 408 cacheFirmwareDir.deleteRecursively()
410 } 409 }
411 messageToShow 410 messageToShow
412 } 411 }.show(supportFragmentManager, ProgressDialogFragment.TAG)
413
414 IndeterminateProgressDialogFragment.newInstance(
415 this,
416 R.string.firmware_installing,
417 task = task
418 ).show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
419 } 412 }
420 413
421 val getAmiiboKey = 414 val getAmiiboKey =
@@ -474,11 +467,11 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
474 return@registerForActivityResult 467 return@registerForActivityResult
475 } 468 }
476 469
477 IndeterminateProgressDialogFragment.newInstance( 470 ProgressDialogFragment.newInstance(
478 this@MainActivity, 471 this@MainActivity,
479 R.string.verifying_content, 472 R.string.verifying_content,
480 false 473 false
481 ) { 474 ) { _, _ ->
482 var updatesMatchProgram = true 475 var updatesMatchProgram = true
483 for (document in documents) { 476 for (document in documents) {
484 val valid = NativeLibrary.doesUpdateMatchProgram( 477 val valid = NativeLibrary.doesUpdateMatchProgram(
@@ -501,44 +494,42 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
501 positiveAction = { homeViewModel.setContentToInstall(documents) } 494 positiveAction = { homeViewModel.setContentToInstall(documents) }
502 ) 495 )
503 } 496 }
504 }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) 497 }.show(supportFragmentManager, ProgressDialogFragment.TAG)
505 } 498 }
506 499
507 private fun installContent(documents: List<Uri>) { 500 private fun installContent(documents: List<Uri>) {
508 IndeterminateProgressDialogFragment.newInstance( 501 ProgressDialogFragment.newInstance(
509 this@MainActivity, 502 this@MainActivity,
510 R.string.installing_game_content 503 R.string.installing_game_content
511 ) { 504 ) { progressCallback, messageCallback ->
512 var installSuccess = 0 505 var installSuccess = 0
513 var installOverwrite = 0 506 var installOverwrite = 0
514 var errorBaseGame = 0 507 var errorBaseGame = 0
515 var errorExtension = 0 508 var error = 0
516 var errorOther = 0
517 documents.forEach { 509 documents.forEach {
510 messageCallback.invoke(FileUtil.getFilename(it))
518 when ( 511 when (
519 NativeLibrary.installFileToNand( 512 InstallResult.from(
520 it.toString(), 513 NativeLibrary.installFileToNand(
521 FileUtil.getExtension(it) 514 it.toString(),
515 progressCallback
516 )
522 ) 517 )
523 ) { 518 ) {
524 NativeLibrary.InstallFileToNandResult.Success -> { 519 InstallResult.Success -> {
525 installSuccess += 1 520 installSuccess += 1
526 } 521 }
527 522
528 NativeLibrary.InstallFileToNandResult.SuccessFileOverwritten -> { 523 InstallResult.Overwrite -> {
529 installOverwrite += 1 524 installOverwrite += 1
530 } 525 }
531 526
532 NativeLibrary.InstallFileToNandResult.ErrorBaseGame -> { 527 InstallResult.BaseInstallAttempted -> {
533 errorBaseGame += 1 528 errorBaseGame += 1
534 } 529 }
535 530
536 NativeLibrary.InstallFileToNandResult.ErrorFilenameExtension -> { 531 InstallResult.Failure -> {
537 errorExtension += 1 532 error += 1
538 }
539
540 else -> {
541 errorOther += 1
542 } 533 }
543 } 534 }
544 } 535 }
@@ -565,7 +556,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
565 ) 556 )
566 installResult.append(separator) 557 installResult.append(separator)
567 } 558 }
568 val errorTotal: Int = errorBaseGame + errorExtension + errorOther 559 val errorTotal: Int = errorBaseGame + error
569 if (errorTotal > 0) { 560 if (errorTotal > 0) {
570 installResult.append(separator) 561 installResult.append(separator)
571 installResult.append( 562 installResult.append(
@@ -582,14 +573,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
582 ) 573 )
583 installResult.append(separator) 574 installResult.append(separator)
584 } 575 }
585 if (errorExtension > 0) { 576 if (error > 0) {
586 installResult.append(separator)
587 installResult.append(
588 getString(R.string.install_game_content_failure_file_extension)
589 )
590 installResult.append(separator)
591 }
592 if (errorOther > 0) {
593 installResult.append( 577 installResult.append(
594 getString(R.string.install_game_content_failure_description) 578 getString(R.string.install_game_content_failure_description)
595 ) 579 )
@@ -608,7 +592,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
608 descriptionString = installResult.toString().trim() 592 descriptionString = installResult.toString().trim()
609 ) 593 )
610 } 594 }
611 }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) 595 }.show(supportFragmentManager, ProgressDialogFragment.TAG)
612 } 596 }
613 597
614 val exportUserData = registerForActivityResult( 598 val exportUserData = registerForActivityResult(
@@ -618,16 +602,16 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
618 return@registerForActivityResult 602 return@registerForActivityResult
619 } 603 }
620 604
621 IndeterminateProgressDialogFragment.newInstance( 605 ProgressDialogFragment.newInstance(
622 this, 606 this,
623 R.string.exporting_user_data, 607 R.string.exporting_user_data,
624 true 608 true
625 ) { 609 ) { progressCallback, _ ->
626 val zipResult = FileUtil.zipFromInternalStorage( 610 val zipResult = FileUtil.zipFromInternalStorage(
627 File(DirectoryInitialization.userDirectory!!), 611 File(DirectoryInitialization.userDirectory!!),
628 DirectoryInitialization.userDirectory!!, 612 DirectoryInitialization.userDirectory!!,
629 BufferedOutputStream(contentResolver.openOutputStream(result)), 613 BufferedOutputStream(contentResolver.openOutputStream(result)),
630 taskViewModel.cancelled, 614 progressCallback,
631 compression = false 615 compression = false
632 ) 616 )
633 return@newInstance when (zipResult) { 617 return@newInstance when (zipResult) {
@@ -635,7 +619,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
635 TaskState.Failed -> R.string.export_failed 619 TaskState.Failed -> R.string.export_failed
636 TaskState.Cancelled -> R.string.user_data_export_cancelled 620 TaskState.Cancelled -> R.string.user_data_export_cancelled
637 } 621 }
638 }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) 622 }.show(supportFragmentManager, ProgressDialogFragment.TAG)
639 } 623 }
640 624
641 val importUserData = 625 val importUserData =
@@ -644,10 +628,10 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
644 return@registerForActivityResult 628 return@registerForActivityResult
645 } 629 }
646 630
647 IndeterminateProgressDialogFragment.newInstance( 631 ProgressDialogFragment.newInstance(
648 this, 632 this,
649 R.string.importing_user_data 633 R.string.importing_user_data
650 ) { 634 ) { progressCallback, _ ->
651 val checkStream = 635 val checkStream =
652 ZipInputStream(BufferedInputStream(contentResolver.openInputStream(result))) 636 ZipInputStream(BufferedInputStream(contentResolver.openInputStream(result)))
653 var isYuzuBackup = false 637 var isYuzuBackup = false
@@ -676,8 +660,9 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
676 // Copy archive to internal storage 660 // Copy archive to internal storage
677 try { 661 try {
678 FileUtil.unzipToInternalStorage( 662 FileUtil.unzipToInternalStorage(
679 BufferedInputStream(contentResolver.openInputStream(result)), 663 result.toString(),
680 File(DirectoryInitialization.userDirectory!!) 664 File(DirectoryInitialization.userDirectory!!),
665 progressCallback
681 ) 666 )
682 } catch (e: Exception) { 667 } catch (e: Exception) {
683 return@newInstance MessageDialogFragment.newInstance( 668 return@newInstance MessageDialogFragment.newInstance(
@@ -694,6 +679,6 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
694 driverViewModel.reloadDriverData() 679 driverViewModel.reloadDriverData()
695 680
696 return@newInstance getString(R.string.user_data_import_success) 681 return@newInstance getString(R.string.user_data_import_success)
697 }.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG) 682 }.show(supportFragmentManager, ProgressDialogFragment.TAG)
698 } 683 }
699} 684}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt
index b54a19c65..fc2339f5a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt
@@ -7,7 +7,6 @@ import android.database.Cursor
7import android.net.Uri 7import android.net.Uri
8import android.provider.DocumentsContract 8import android.provider.DocumentsContract
9import androidx.documentfile.provider.DocumentFile 9import androidx.documentfile.provider.DocumentFile
10import kotlinx.coroutines.flow.StateFlow
11import java.io.BufferedInputStream 10import java.io.BufferedInputStream
12import java.io.File 11import java.io.File
13import java.io.IOException 12import java.io.IOException
@@ -19,6 +18,7 @@ import org.yuzu.yuzu_emu.YuzuApplication
19import org.yuzu.yuzu_emu.model.MinimalDocumentFile 18import org.yuzu.yuzu_emu.model.MinimalDocumentFile
20import org.yuzu.yuzu_emu.model.TaskState 19import org.yuzu.yuzu_emu.model.TaskState
21import java.io.BufferedOutputStream 20import java.io.BufferedOutputStream
21import java.io.OutputStream
22import java.lang.NullPointerException 22import java.lang.NullPointerException
23import java.nio.charset.StandardCharsets 23import java.nio.charset.StandardCharsets
24import java.util.zip.Deflater 24import java.util.zip.Deflater
@@ -283,12 +283,34 @@ object FileUtil {
283 283
284 /** 284 /**
285 * Extracts the given zip file into the given directory. 285 * Extracts the given zip file into the given directory.
286 * @param path String representation of a [Uri] or a typical path delimited by '/'
287 * @param destDir Location to unzip the contents of [path] into
288 * @param progressCallback Lambda that is called with the total number of files and the current
289 * progress through the process. Stops execution as soon as possible if this returns true.
286 */ 290 */
287 @Throws(SecurityException::class) 291 @Throws(SecurityException::class)
288 fun unzipToInternalStorage(zipStream: BufferedInputStream, destDir: File) { 292 fun unzipToInternalStorage(
289 ZipInputStream(zipStream).use { zis -> 293 path: String,
294 destDir: File,
295 progressCallback: (max: Long, progress: Long) -> Boolean = { _, _ -> false }
296 ) {
297 var totalEntries = 0L
298 ZipInputStream(getInputStream(path)).use { zis ->
299 var tempEntry = zis.nextEntry
300 while (tempEntry != null) {
301 tempEntry = zis.nextEntry
302 totalEntries++
303 }
304 }
305
306 var progress = 0L
307 ZipInputStream(getInputStream(path)).use { zis ->
290 var entry: ZipEntry? = zis.nextEntry 308 var entry: ZipEntry? = zis.nextEntry
291 while (entry != null) { 309 while (entry != null) {
310 if (progressCallback.invoke(totalEntries, progress)) {
311 return@use
312 }
313
292 val newFile = File(destDir, entry.name) 314 val newFile = File(destDir, entry.name)
293 val destinationDirectory = if (entry.isDirectory) newFile else newFile.parentFile 315 val destinationDirectory = if (entry.isDirectory) newFile else newFile.parentFile
294 316
@@ -304,6 +326,7 @@ object FileUtil {
304 newFile.outputStream().use { fos -> zis.copyTo(fos) } 326 newFile.outputStream().use { fos -> zis.copyTo(fos) }
305 } 327 }
306 entry = zis.nextEntry 328 entry = zis.nextEntry
329 progress++
307 } 330 }
308 } 331 }
309 } 332 }
@@ -313,14 +336,15 @@ object FileUtil {
313 * @param inputFile File representation of the item that will be zipped 336 * @param inputFile File representation of the item that will be zipped
314 * @param rootDir Directory containing the inputFile 337 * @param rootDir Directory containing the inputFile
315 * @param outputStream Stream where the zip file will be output 338 * @param outputStream Stream where the zip file will be output
316 * @param cancelled [StateFlow] that reports whether this process has been cancelled 339 * @param progressCallback Lambda that is called with the total number of files and the current
340 * progress through the process. Stops execution as soon as possible if this returns true.
317 * @param compression Disables compression if true 341 * @param compression Disables compression if true
318 */ 342 */
319 fun zipFromInternalStorage( 343 fun zipFromInternalStorage(
320 inputFile: File, 344 inputFile: File,
321 rootDir: String, 345 rootDir: String,
322 outputStream: BufferedOutputStream, 346 outputStream: BufferedOutputStream,
323 cancelled: StateFlow<Boolean>? = null, 347 progressCallback: (max: Long, progress: Long) -> Boolean = { _, _ -> false },
324 compression: Boolean = true 348 compression: Boolean = true
325 ): TaskState { 349 ): TaskState {
326 try { 350 try {
@@ -330,8 +354,10 @@ object FileUtil {
330 zos.setLevel(Deflater.NO_COMPRESSION) 354 zos.setLevel(Deflater.NO_COMPRESSION)
331 } 355 }
332 356
357 var count = 0L
358 val totalFiles = inputFile.walkTopDown().count().toLong()
333 inputFile.walkTopDown().forEach { file -> 359 inputFile.walkTopDown().forEach { file ->
334 if (cancelled?.value == true) { 360 if (progressCallback.invoke(totalFiles, count)) {
335 return TaskState.Cancelled 361 return TaskState.Cancelled
336 } 362 }
337 363
@@ -343,6 +369,7 @@ object FileUtil {
343 if (file.isFile) { 369 if (file.isFile) {
344 file.inputStream().use { fis -> fis.copyTo(zos) } 370 file.inputStream().use { fis -> fis.copyTo(zos) }
345 } 371 }
372 count++
346 } 373 }
347 } 374 }
348 } 375 }
@@ -356,9 +383,14 @@ object FileUtil {
356 /** 383 /**
357 * Helper function that copies the contents of a DocumentFile folder into a [File] 384 * Helper function that copies the contents of a DocumentFile folder into a [File]
358 * @param file [File] representation of the folder to copy into 385 * @param file [File] representation of the folder to copy into
386 * @param progressCallback Lambda that is called with the total number of files and the current
387 * progress through the process. Stops execution as soon as possible if this returns true.
359 * @throws IllegalStateException Fails when trying to copy a folder into a file and vice versa 388 * @throws IllegalStateException Fails when trying to copy a folder into a file and vice versa
360 */ 389 */
361 fun DocumentFile.copyFilesTo(file: File) { 390 fun DocumentFile.copyFilesTo(
391 file: File,
392 progressCallback: (max: Long, progress: Long) -> Boolean = { _, _ -> false }
393 ) {
362 file.mkdirs() 394 file.mkdirs()
363 if (!this.isDirectory || !file.isDirectory) { 395 if (!this.isDirectory || !file.isDirectory) {
364 throw IllegalStateException( 396 throw IllegalStateException(
@@ -366,7 +398,13 @@ object FileUtil {
366 ) 398 )
367 } 399 }
368 400
401 var count = 0L
402 val totalFiles = this.listFiles().size.toLong()
369 this.listFiles().forEach { 403 this.listFiles().forEach {
404 if (progressCallback.invoke(totalFiles, count)) {
405 return
406 }
407
370 val newFile = File(file, it.name!!) 408 val newFile = File(file, it.name!!)
371 if (it.isDirectory) { 409 if (it.isDirectory) {
372 newFile.mkdirs() 410 newFile.mkdirs()
@@ -381,6 +419,7 @@ object FileUtil {
381 newFile.outputStream().use { os -> bos.copyTo(os) } 419 newFile.outputStream().use { os -> bos.copyTo(os) }
382 } 420 }
383 } 421 }
422 count++
384 } 423 }
385 } 424 }
386 425
@@ -427,6 +466,18 @@ object FileUtil {
427 } 466 }
428 } 467 }
429 468
469 fun getInputStream(path: String) = if (path.contains("content://")) {
470 Uri.parse(path).inputStream()
471 } else {
472 File(path).inputStream()
473 }
474
475 fun getOutputStream(path: String) = if (path.contains("content://")) {
476 Uri.parse(path).outputStream()
477 } else {
478 File(path).outputStream()
479 }
480
430 @Throws(IOException::class) 481 @Throws(IOException::class)
431 fun getStringFromFile(file: File): String = 482 fun getStringFromFile(file: File): String =
432 String(file.readBytes(), StandardCharsets.UTF_8) 483 String(file.readBytes(), StandardCharsets.UTF_8)
@@ -434,4 +485,19 @@ object FileUtil {
434 @Throws(IOException::class) 485 @Throws(IOException::class)
435 fun getStringFromInputStream(stream: InputStream): String = 486 fun getStringFromInputStream(stream: InputStream): String =
436 String(stream.readBytes(), StandardCharsets.UTF_8) 487 String(stream.readBytes(), StandardCharsets.UTF_8)
488
489 fun DocumentFile.inputStream(): InputStream =
490 YuzuApplication.appContext.contentResolver.openInputStream(uri)!!
491
492 fun DocumentFile.outputStream(): OutputStream =
493 YuzuApplication.appContext.contentResolver.openOutputStream(uri)!!
494
495 fun Uri.inputStream(): InputStream =
496 YuzuApplication.appContext.contentResolver.openInputStream(this)!!
497
498 fun Uri.outputStream(): OutputStream =
499 YuzuApplication.appContext.contentResolver.openOutputStream(this)!!
500
501 fun Uri.asDocumentFile(): DocumentFile? =
502 DocumentFile.fromSingleUri(YuzuApplication.appContext, this)
437} 503}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt
index 2e9b0beb8..d05020560 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt
@@ -5,7 +5,10 @@ package org.yuzu.yuzu_emu.utils
5 5
6import android.graphics.Bitmap 6import android.graphics.Bitmap
7import android.graphics.BitmapFactory 7import android.graphics.BitmapFactory
8import android.graphics.drawable.LayerDrawable
8import android.widget.ImageView 9import android.widget.ImageView
10import androidx.core.content.res.ResourcesCompat
11import androidx.core.graphics.drawable.IconCompat
9import androidx.core.graphics.drawable.toBitmap 12import androidx.core.graphics.drawable.toBitmap
10import androidx.core.graphics.drawable.toDrawable 13import androidx.core.graphics.drawable.toDrawable
11import androidx.lifecycle.LifecycleOwner 14import androidx.lifecycle.LifecycleOwner
@@ -85,4 +88,22 @@ object GameIconUtils {
85 return imageLoader.execute(request) 88 return imageLoader.execute(request)
86 .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888) 89 .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888)
87 } 90 }
91
92 suspend fun getShortcutIcon(lifecycleOwner: LifecycleOwner, game: Game): IconCompat {
93 val layerDrawable = ResourcesCompat.getDrawable(
94 YuzuApplication.appContext.resources,
95 R.drawable.shortcut,
96 null
97 ) as LayerDrawable
98 layerDrawable.setDrawableByLayerId(
99 R.id.shortcut_foreground,
100 getGameIcon(lifecycleOwner, game).toDrawable(YuzuApplication.appContext.resources)
101 )
102 val inset = YuzuApplication.appContext.resources
103 .getDimensionPixelSize(R.dimen.icon_inset)
104 layerDrawable.setLayerInset(1, inset, inset, inset, inset)
105 return IconCompat.createWithAdaptiveBitmap(
106 layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
107 )
108 }
88} 109}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt
index a8f9dcc34..81212cbee 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GpuDriverHelper.kt
@@ -5,7 +5,6 @@ package org.yuzu.yuzu_emu.utils
5 5
6import android.net.Uri 6import android.net.Uri
7import android.os.Build 7import android.os.Build
8import java.io.BufferedInputStream
9import java.io.File 8import java.io.File
10import java.io.IOException 9import java.io.IOException
11import org.yuzu.yuzu_emu.NativeLibrary 10import org.yuzu.yuzu_emu.NativeLibrary
@@ -123,7 +122,7 @@ object GpuDriverHelper {
123 // Unzip the driver. 122 // Unzip the driver.
124 try { 123 try {
125 FileUtil.unzipToInternalStorage( 124 FileUtil.unzipToInternalStorage(
126 BufferedInputStream(copiedFile.inputStream()), 125 copiedFile.path,
127 File(driverInstallationPath!!) 126 File(driverInstallationPath!!)
128 ) 127 )
129 } catch (e: SecurityException) { 128 } catch (e: SecurityException) {
@@ -156,7 +155,7 @@ object GpuDriverHelper {
156 // Unzip the driver to the private installation directory 155 // Unzip the driver to the private installation directory
157 try { 156 try {
158 FileUtil.unzipToInternalStorage( 157 FileUtil.unzipToInternalStorage(
159 BufferedInputStream(driver.inputStream()), 158 driver.path,
160 File(driverInstallationPath!!) 159 File(driverInstallationPath!!)
161 ) 160 )
162 } catch (e: SecurityException) { 161 } catch (e: SecurityException) {
diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp
index 1e884ffdd..7018a52af 100644
--- a/src/android/app/src/main/jni/android_common/android_common.cpp
+++ b/src/android/app/src/main/jni/android_common/android_common.cpp
@@ -42,3 +42,19 @@ double GetJDouble(JNIEnv* env, jobject jdouble) {
42jobject ToJDouble(JNIEnv* env, double value) { 42jobject ToJDouble(JNIEnv* env, double value) {
43 return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); 43 return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value);
44} 44}
45
46s32 GetJInteger(JNIEnv* env, jobject jinteger) {
47 return env->GetIntField(jinteger, IDCache::GetIntegerValueField());
48}
49
50jobject ToJInteger(JNIEnv* env, s32 value) {
51 return env->NewObject(IDCache::GetIntegerClass(), IDCache::GetIntegerConstructor(), value);
52}
53
54bool GetJBoolean(JNIEnv* env, jobject jboolean) {
55 return env->GetBooleanField(jboolean, IDCache::GetBooleanValueField());
56}
57
58jobject ToJBoolean(JNIEnv* env, bool value) {
59 return env->NewObject(IDCache::GetBooleanClass(), IDCache::GetBooleanConstructor(), value);
60}
diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h
index 8eb803e1b..29a338c0a 100644
--- a/src/android/app/src/main/jni/android_common/android_common.h
+++ b/src/android/app/src/main/jni/android_common/android_common.h
@@ -6,6 +6,7 @@
6#include <string> 6#include <string>
7 7
8#include <jni.h> 8#include <jni.h>
9#include "common/common_types.h"
9 10
10std::string GetJString(JNIEnv* env, jstring jstr); 11std::string GetJString(JNIEnv* env, jstring jstr);
11jstring ToJString(JNIEnv* env, std::string_view str); 12jstring ToJString(JNIEnv* env, std::string_view str);
@@ -13,3 +14,9 @@ jstring ToJString(JNIEnv* env, std::u16string_view str);
13 14
14double GetJDouble(JNIEnv* env, jobject jdouble); 15double GetJDouble(JNIEnv* env, jobject jdouble);
15jobject ToJDouble(JNIEnv* env, double value); 16jobject ToJDouble(JNIEnv* env, double value);
17
18s32 GetJInteger(JNIEnv* env, jobject jinteger);
19jobject ToJInteger(JNIEnv* env, s32 value);
20
21bool GetJBoolean(JNIEnv* env, jobject jboolean);
22jobject ToJBoolean(JNIEnv* env, bool value);
diff --git a/src/android/app/src/main/jni/android_settings.h b/src/android/app/src/main/jni/android_settings.h
index 559ae83eb..cf93304da 100644
--- a/src/android/app/src/main/jni/android_settings.h
+++ b/src/android/app/src/main/jni/android_settings.h
@@ -63,6 +63,7 @@ struct Values {
63 Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay", 63 Settings::Setting<bool> show_input_overlay{linkage, true, "show_input_overlay",
64 Settings::Category::Overlay}; 64 Settings::Category::Overlay};
65 Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay}; 65 Settings::Setting<bool> touchscreen{linkage, true, "touchscreen", Settings::Category::Overlay};
66 Settings::Setting<s32> lock_drawer{linkage, false, "lock_drawer", Settings::Category::Overlay};
66}; 67};
67 68
68extern Values values; 69extern Values values;
diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp
index c79ad7d76..96f2ad3d4 100644
--- a/src/android/app/src/main/jni/id_cache.cpp
+++ b/src/android/app/src/main/jni/id_cache.cpp
@@ -43,10 +43,27 @@ static jfieldID s_overlay_control_data_landscape_position_field;
43static jfieldID s_overlay_control_data_portrait_position_field; 43static jfieldID s_overlay_control_data_portrait_position_field;
44static jfieldID s_overlay_control_data_foldable_position_field; 44static jfieldID s_overlay_control_data_foldable_position_field;
45 45
46static jclass s_patch_class;
47static jmethodID s_patch_constructor;
48static jfieldID s_patch_enabled_field;
49static jfieldID s_patch_name_field;
50static jfieldID s_patch_version_field;
51static jfieldID s_patch_type_field;
52static jfieldID s_patch_program_id_field;
53static jfieldID s_patch_title_id_field;
54
46static jclass s_double_class; 55static jclass s_double_class;
47static jmethodID s_double_constructor; 56static jmethodID s_double_constructor;
48static jfieldID s_double_value_field; 57static jfieldID s_double_value_field;
49 58
59static jclass s_integer_class;
60static jmethodID s_integer_constructor;
61static jfieldID s_integer_value_field;
62
63static jclass s_boolean_class;
64static jmethodID s_boolean_constructor;
65static jfieldID s_boolean_value_field;
66
50static constexpr jint JNI_VERSION = JNI_VERSION_1_6; 67static constexpr jint JNI_VERSION = JNI_VERSION_1_6;
51 68
52namespace IDCache { 69namespace IDCache {
@@ -186,6 +203,38 @@ jfieldID GetOverlayControlDataFoldablePositionField() {
186 return s_overlay_control_data_foldable_position_field; 203 return s_overlay_control_data_foldable_position_field;
187} 204}
188 205
206jclass GetPatchClass() {
207 return s_patch_class;
208}
209
210jmethodID GetPatchConstructor() {
211 return s_patch_constructor;
212}
213
214jfieldID GetPatchEnabledField() {
215 return s_patch_enabled_field;
216}
217
218jfieldID GetPatchNameField() {
219 return s_patch_name_field;
220}
221
222jfieldID GetPatchVersionField() {
223 return s_patch_version_field;
224}
225
226jfieldID GetPatchTypeField() {
227 return s_patch_type_field;
228}
229
230jfieldID GetPatchProgramIdField() {
231 return s_patch_program_id_field;
232}
233
234jfieldID GetPatchTitleIdField() {
235 return s_patch_title_id_field;
236}
237
189jclass GetDoubleClass() { 238jclass GetDoubleClass() {
190 return s_double_class; 239 return s_double_class;
191} 240}
@@ -198,6 +247,30 @@ jfieldID GetDoubleValueField() {
198 return s_double_value_field; 247 return s_double_value_field;
199} 248}
200 249
250jclass GetIntegerClass() {
251 return s_integer_class;
252}
253
254jmethodID GetIntegerConstructor() {
255 return s_integer_constructor;
256}
257
258jfieldID GetIntegerValueField() {
259 return s_integer_value_field;
260}
261
262jclass GetBooleanClass() {
263 return s_boolean_class;
264}
265
266jmethodID GetBooleanConstructor() {
267 return s_boolean_constructor;
268}
269
270jfieldID GetBooleanValueField() {
271 return s_boolean_value_field;
272}
273
201} // namespace IDCache 274} // namespace IDCache
202 275
203#ifdef __cplusplus 276#ifdef __cplusplus
@@ -278,12 +351,37 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
278 env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;"); 351 env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;");
279 env->DeleteLocalRef(overlay_control_data_class); 352 env->DeleteLocalRef(overlay_control_data_class);
280 353
354 const jclass patch_class = env->FindClass("org/yuzu/yuzu_emu/model/Patch");
355 s_patch_class = reinterpret_cast<jclass>(env->NewGlobalRef(patch_class));
356 s_patch_constructor = env->GetMethodID(
357 patch_class, "<init>",
358 "(ZLjava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)V");
359 s_patch_enabled_field = env->GetFieldID(patch_class, "enabled", "Z");
360 s_patch_name_field = env->GetFieldID(patch_class, "name", "Ljava/lang/String;");
361 s_patch_version_field = env->GetFieldID(patch_class, "version", "Ljava/lang/String;");
362 s_patch_type_field = env->GetFieldID(patch_class, "type", "I");
363 s_patch_program_id_field = env->GetFieldID(patch_class, "programId", "Ljava/lang/String;");
364 s_patch_title_id_field = env->GetFieldID(patch_class, "titleId", "Ljava/lang/String;");
365 env->DeleteLocalRef(patch_class);
366
281 const jclass double_class = env->FindClass("java/lang/Double"); 367 const jclass double_class = env->FindClass("java/lang/Double");
282 s_double_class = reinterpret_cast<jclass>(env->NewGlobalRef(double_class)); 368 s_double_class = reinterpret_cast<jclass>(env->NewGlobalRef(double_class));
283 s_double_constructor = env->GetMethodID(double_class, "<init>", "(D)V"); 369 s_double_constructor = env->GetMethodID(double_class, "<init>", "(D)V");
284 s_double_value_field = env->GetFieldID(double_class, "value", "D"); 370 s_double_value_field = env->GetFieldID(double_class, "value", "D");
285 env->DeleteLocalRef(double_class); 371 env->DeleteLocalRef(double_class);
286 372
373 const jclass int_class = env->FindClass("java/lang/Integer");
374 s_integer_class = reinterpret_cast<jclass>(env->NewGlobalRef(int_class));
375 s_integer_constructor = env->GetMethodID(int_class, "<init>", "(I)V");
376 s_integer_value_field = env->GetFieldID(int_class, "value", "I");
377 env->DeleteLocalRef(int_class);
378
379 const jclass boolean_class = env->FindClass("java/lang/Boolean");
380 s_boolean_class = reinterpret_cast<jclass>(env->NewGlobalRef(boolean_class));
381 s_boolean_constructor = env->GetMethodID(boolean_class, "<init>", "(Z)V");
382 s_boolean_value_field = env->GetFieldID(boolean_class, "value", "Z");
383 env->DeleteLocalRef(boolean_class);
384
287 // Initialize Android Storage 385 // Initialize Android Storage
288 Common::FS::Android::RegisterCallbacks(env, s_native_library_class); 386 Common::FS::Android::RegisterCallbacks(env, s_native_library_class);
289 387
@@ -309,7 +407,10 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) {
309 env->DeleteGlobalRef(s_string_class); 407 env->DeleteGlobalRef(s_string_class);
310 env->DeleteGlobalRef(s_pair_class); 408 env->DeleteGlobalRef(s_pair_class);
311 env->DeleteGlobalRef(s_overlay_control_data_class); 409 env->DeleteGlobalRef(s_overlay_control_data_class);
410 env->DeleteGlobalRef(s_patch_class);
312 env->DeleteGlobalRef(s_double_class); 411 env->DeleteGlobalRef(s_double_class);
412 env->DeleteGlobalRef(s_integer_class);
413 env->DeleteGlobalRef(s_boolean_class);
313 414
314 // UnInitialize applets 415 // UnInitialize applets
315 SoftwareKeyboard::CleanupJNI(env); 416 SoftwareKeyboard::CleanupJNI(env);
diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h
index 784d1412f..a002e705d 100644
--- a/src/android/app/src/main/jni/id_cache.h
+++ b/src/android/app/src/main/jni/id_cache.h
@@ -43,8 +43,25 @@ jfieldID GetOverlayControlDataLandscapePositionField();
43jfieldID GetOverlayControlDataPortraitPositionField(); 43jfieldID GetOverlayControlDataPortraitPositionField();
44jfieldID GetOverlayControlDataFoldablePositionField(); 44jfieldID GetOverlayControlDataFoldablePositionField();
45 45
46jclass GetPatchClass();
47jmethodID GetPatchConstructor();
48jfieldID GetPatchEnabledField();
49jfieldID GetPatchNameField();
50jfieldID GetPatchVersionField();
51jfieldID GetPatchTypeField();
52jfieldID GetPatchProgramIdField();
53jfieldID GetPatchTitleIdField();
54
46jclass GetDoubleClass(); 55jclass GetDoubleClass();
47jmethodID GetDoubleConstructor(); 56jmethodID GetDoubleConstructor();
48jfieldID GetDoubleValueField(); 57jfieldID GetDoubleValueField();
49 58
59jclass GetIntegerClass();
60jmethodID GetIntegerConstructor();
61jfieldID GetIntegerValueField();
62
63jclass GetBooleanClass();
64jmethodID GetBooleanConstructor();
65jfieldID GetBooleanValueField();
66
50} // namespace IDCache 67} // namespace IDCache
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index ed3b1353a..963f57380 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -17,6 +17,7 @@
17#include <core/file_sys/patch_manager.h> 17#include <core/file_sys/patch_manager.h>
18#include <core/file_sys/savedata_factory.h> 18#include <core/file_sys/savedata_factory.h>
19#include <core/loader/nro.h> 19#include <core/loader/nro.h>
20#include <frontend_common/content_manager.h>
20#include <jni.h> 21#include <jni.h>
21 22
22#include "common/detached_tasks.h" 23#include "common/detached_tasks.h"
@@ -100,67 +101,6 @@ void EmulationSession::SetNativeWindow(ANativeWindow* native_window) {
100 m_native_window = native_window; 101 m_native_window = native_window;
101} 102}
102 103
103int EmulationSession::InstallFileToNand(std::string filename, std::string file_extension) {
104 jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
105 std::size_t block_size) {
106 if (src == nullptr || dest == nullptr) {
107 return false;
108 }
109 if (!dest->Resize(src->GetSize())) {
110 return false;
111 }
112
113 using namespace Common::Literals;
114 [[maybe_unused]] std::vector<u8> buffer(1_MiB);
115
116 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
117 jconst read = src->Read(buffer.data(), buffer.size(), i);
118 dest->Write(buffer.data(), read, i);
119 }
120 return true;
121 };
122
123 enum InstallResult {
124 Success = 0,
125 SuccessFileOverwritten = 1,
126 InstallError = 2,
127 ErrorBaseGame = 3,
128 ErrorFilenameExtension = 4,
129 };
130
131 [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp;
132 if (file_extension == "nsp") {
133 nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
134 if (nsp->IsExtractedType()) {
135 return InstallError;
136 }
137 } else {
138 return ErrorFilenameExtension;
139 }
140
141 if (!nsp) {
142 return InstallError;
143 }
144
145 if (nsp->GetStatus() != Loader::ResultStatus::Success) {
146 return InstallError;
147 }
148
149 jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true,
150 copy_func);
151
152 switch (res) {
153 case FileSys::InstallResult::Success:
154 return Success;
155 case FileSys::InstallResult::OverwriteExisting:
156 return SuccessFileOverwritten;
157 case FileSys::InstallResult::ErrorBaseInstall:
158 return ErrorBaseGame;
159 default:
160 return InstallError;
161 }
162}
163
164void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir, 104void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir,
165 const std::string& custom_driver_dir, 105 const std::string& custom_driver_dir,
166 const std::string& custom_driver_name, 106 const std::string& custom_driver_name,
@@ -512,10 +452,20 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jobject
512} 452}
513 453
514int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, 454int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance,
515 jstring j_file, 455 jstring j_file, jobject jcallback) {
516 jstring j_file_extension) { 456 auto jlambdaClass = env->GetObjectClass(jcallback);
517 return EmulationSession::GetInstance().InstallFileToNand(GetJString(env, j_file), 457 auto jlambdaInvokeMethod = env->GetMethodID(
518 GetJString(env, j_file_extension)); 458 jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
459 const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) {
460 auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod,
461 ToJDouble(env, max), ToJDouble(env, progress));
462 return GetJBoolean(env, jwasCancelled);
463 };
464
465 return static_cast<int>(
466 ContentManager::InstallNSP(&EmulationSession::GetInstance().System(),
467 EmulationSession::GetInstance().System().GetFilesystem().get(),
468 GetJString(env, j_file), callback));
519} 469}
520 470
521jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, 471jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj,
@@ -824,9 +774,9 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env,
824 return true; 774 return true;
825} 775}
826 776
827jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getAddonsForFile(JNIEnv* env, jobject jobj, 777jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj,
828 jstring jpath, 778 jstring jpath,
829 jstring jprogramId) { 779 jstring jprogramId) {
830 const auto path = GetJString(env, jpath); 780 const auto path = GetJString(env, jpath);
831 const auto vFile = 781 const auto vFile =
832 Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path); 782 Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path);
@@ -843,20 +793,77 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getAddonsForFile(JNIEnv* env,
843 FileSys::VirtualFile update_raw; 793 FileSys::VirtualFile update_raw;
844 loader->ReadUpdateRaw(update_raw); 794 loader->ReadUpdateRaw(update_raw);
845 795
846 auto addons = pm.GetPatchVersionNames(update_raw); 796 auto patches = pm.GetPatches(update_raw);
847 auto jemptyString = ToJString(env, ""); 797 jobjectArray jpatchArray =
848 auto jemptyStringPair = env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), 798 env->NewObjectArray(patches.size(), IDCache::GetPatchClass(), nullptr);
849 jemptyString, jemptyString);
850 jobjectArray jaddonsArray =
851 env->NewObjectArray(addons.size(), IDCache::GetPairClass(), jemptyStringPair);
852 int i = 0; 799 int i = 0;
853 for (const auto& addon : addons) { 800 for (const auto& patch : patches) {
854 jobject jaddon = env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), 801 jobject jpatch = env->NewObject(
855 ToJString(env, addon.first), ToJString(env, addon.second)); 802 IDCache::GetPatchClass(), IDCache::GetPatchConstructor(), patch.enabled,
856 env->SetObjectArrayElement(jaddonsArray, i, jaddon); 803 ToJString(env, patch.name), ToJString(env, patch.version),
804 static_cast<jint>(patch.type), ToJString(env, std::to_string(patch.program_id)),
805 ToJString(env, std::to_string(patch.title_id)));
806 env->SetObjectArrayElement(jpatchArray, i, jpatch);
857 ++i; 807 ++i;
858 } 808 }
859 return jaddonsArray; 809 return jpatchArray;
810}
811
812void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeUpdate(JNIEnv* env, jobject jobj,
813 jstring jprogramId) {
814 auto program_id = EmulationSession::GetProgramId(env, jprogramId);
815 ContentManager::RemoveUpdate(EmulationSession::GetInstance().System().GetFileSystemController(),
816 program_id);
817}
818
819void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeDLC(JNIEnv* env, jobject jobj,
820 jstring jprogramId) {
821 auto program_id = EmulationSession::GetProgramId(env, jprogramId);
822 ContentManager::RemoveAllDLC(&EmulationSession::GetInstance().System(), program_id);
823}
824
825void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, jstring jprogramId,
826 jstring jname) {
827 auto program_id = EmulationSession::GetProgramId(env, jprogramId);
828 ContentManager::RemoveMod(EmulationSession::GetInstance().System().GetFileSystemController(),
829 program_id, GetJString(env, jname));
830}
831
832jobject Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* env, jobject jobj,
833 jobject jcallback) {
834 auto jlambdaClass = env->GetObjectClass(jcallback);
835 auto jlambdaInvokeMethod = env->GetMethodID(
836 jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
837 const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) {
838 auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod,
839 ToJDouble(env, max), ToJDouble(env, progress));
840 return GetJBoolean(env, jwasCancelled);
841 };
842
843 auto& session = EmulationSession::GetInstance();
844 std::vector<std::string> result = ContentManager::VerifyInstalledContents(
845 &session.System(), session.GetContentProvider(), callback);
846 jobjectArray jresult =
847 env->NewObjectArray(result.size(), IDCache::GetStringClass(), ToJString(env, ""));
848 for (size_t i = 0; i < result.size(); ++i) {
849 env->SetObjectArrayElement(jresult, i, ToJString(env, result[i]));
850 }
851 return jresult;
852}
853
854jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyGameContents(JNIEnv* env, jobject jobj,
855 jstring jpath, jobject jcallback) {
856 auto jlambdaClass = env->GetObjectClass(jcallback);
857 auto jlambdaInvokeMethod = env->GetMethodID(
858 jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
859 const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) {
860 auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod,
861 ToJDouble(env, max), ToJDouble(env, progress));
862 return GetJBoolean(env, jwasCancelled);
863 };
864 auto& session = EmulationSession::GetInstance();
865 return static_cast<jint>(
866 ContentManager::VerifyGameContents(&session.System(), GetJString(env, jpath), callback));
860} 867}
861 868
862jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj, 869jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj,
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
index 4a8049578..dadb138ad 100644
--- a/src/android/app/src/main/jni/native.h
+++ b/src/android/app/src/main/jni/native.h
@@ -7,6 +7,7 @@
7#include "core/file_sys/registered_cache.h" 7#include "core/file_sys/registered_cache.h"
8#include "core/hle/service/acc/profile_manager.h" 8#include "core/hle/service/acc/profile_manager.h"
9#include "core/perf_stats.h" 9#include "core/perf_stats.h"
10#include "frontend_common/content_manager.h"
10#include "jni/applets/software_keyboard.h" 11#include "jni/applets/software_keyboard.h"
11#include "jni/emu_window/emu_window.h" 12#include "jni/emu_window/emu_window.h"
12#include "video_core/rasterizer_interface.h" 13#include "video_core/rasterizer_interface.h"
@@ -29,7 +30,6 @@ public:
29 void SetNativeWindow(ANativeWindow* native_window); 30 void SetNativeWindow(ANativeWindow* native_window);
30 void SurfaceChanged(); 31 void SurfaceChanged();
31 32
32 int InstallFileToNand(std::string filename, std::string file_extension);
33 void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, 33 void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
34 const std::string& custom_driver_name, 34 const std::string& custom_driver_name,
35 const std::string& file_redirect_dir); 35 const std::string& file_redirect_dir);
diff --git a/src/android/app/src/main/res/drawable/ic_lock.xml b/src/android/app/src/main/res/drawable/ic_lock.xml
new file mode 100644
index 000000000..ef97b1936
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_lock.xml
@@ -0,0 +1,9 @@
1<vector xmlns:android="http://schemas.android.com/apk/res/android"
2 android:height="24dp"
3 android:viewportHeight="24"
4 android:viewportWidth="24"
5 android:width="24dp">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z" />
9</vector>
diff --git a/src/android/app/src/main/res/drawable/ic_shortcut.xml b/src/android/app/src/main/res/drawable/ic_shortcut.xml
new file mode 100644
index 000000000..06e1983b2
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_shortcut.xml
@@ -0,0 +1,9 @@
1<vector xmlns:android="http://schemas.android.com/apk/res/android"
2 android:width="24dp"
3 android:height="24dp"
4 android:viewportWidth="960"
5 android:viewportHeight="960">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v160h-80v-40L280,240v480h400v-40h80v160q0,33 -23.5,56.5T680,920L280,920ZM686,520L480,520v120h-80v-120q0,-33 23.5,-56.5T480,440h206l-62,-64 56,-56 160,160 -160,160 -56,-56 62,-64Z" />
9</vector>
diff --git a/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml b/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml
index 0b9633855..551f255c0 100644
--- a/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml
+++ b/src/android/app/src/main/res/layout-w600dp/fragment_game_properties.xml
@@ -43,16 +43,35 @@
43 app:layout_constraintStart_toStartOf="parent" 43 app:layout_constraintStart_toStartOf="parent"
44 app:layout_constraintTop_toTopOf="parent"> 44 app:layout_constraintTop_toTopOf="parent">
45 45
46 <Button 46 <androidx.constraintlayout.widget.ConstraintLayout
47 android:id="@+id/button_back" 47 android:layout_width="match_parent"
48 style="?attr/materialIconButtonStyle"
49 android:layout_width="wrap_content"
50 android:layout_height="wrap_content" 48 android:layout_height="wrap_content"
51 android:layout_gravity="start"
52 android:layout_margin="8dp" 49 android:layout_margin="8dp"
53 app:icon="@drawable/ic_back" 50 android:orientation="horizontal">
54 app:iconSize="24dp" 51
55 app:iconTint="?attr/colorOnSurface" /> 52 <Button
53 android:id="@+id/button_back"
54 style="?attr/materialIconButtonStyle"
55 android:layout_width="wrap_content"
56 android:layout_height="wrap_content"
57 app:icon="@drawable/ic_back"
58 app:iconSize="24dp"
59 app:iconTint="?attr/colorOnSurface"
60 app:layout_constraintStart_toStartOf="parent"
61 app:layout_constraintTop_toTopOf="parent" />
62
63 <Button
64 android:id="@+id/button_shortcut"
65 style="?attr/materialIconButtonStyle"
66 android:layout_width="wrap_content"
67 android:layout_height="wrap_content"
68 app:icon="@drawable/ic_shortcut"
69 app:iconSize="24dp"
70 app:iconTint="?attr/colorOnSurface"
71 app:layout_constraintTop_toTopOf="parent"
72 app:layout_constraintEnd_toEndOf="parent" />
73
74 </androidx.constraintlayout.widget.ConstraintLayout>
56 75
57 <com.google.android.material.card.MaterialCardView 76 <com.google.android.material.card.MaterialCardView
58 style="?attr/materialCardViewElevatedStyle" 77 style="?attr/materialCardViewElevatedStyle"
diff --git a/src/android/app/src/main/res/layout/card_home_option.xml b/src/android/app/src/main/res/layout/card_home_option.xml
index cb667c928..224ec4d89 100644
--- a/src/android/app/src/main/res/layout/card_home_option.xml
+++ b/src/android/app/src/main/res/layout/card_home_option.xml
@@ -2,16 +2,16 @@
2<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" 2<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 xmlns:tools="http://schemas.android.com/tools" 4 xmlns:tools="http://schemas.android.com/tools"
5 style="?attr/materialCardViewFilledStyle" 5 style="?attr/materialCardViewElevatedStyle"
6 android:id="@+id/option_card" 6 android:id="@+id/option_card"
7 android:layout_width="match_parent" 7 android:layout_width="match_parent"
8 android:layout_height="wrap_content" 8 android:layout_height="wrap_content"
9 android:layout_marginBottom="24dp" 9 android:layout_marginBottom="24dp"
10 android:layout_marginHorizontal="12dp" 10 android:layout_marginHorizontal="12dp"
11 android:background="?attr/selectableItemBackground" 11 android:background="?attr/selectableItemBackground"
12 android:backgroundTint="?attr/colorSurfaceVariant"
13 android:clickable="true" 12 android:clickable="true"
14 android:focusable="true"> 13 android:focusable="true"
14 app:cardElevation="4dp">
15 15
16 <LinearLayout 16 <LinearLayout
17 android:id="@+id/option_layout" 17 android:id="@+id/option_layout"
diff --git a/src/android/app/src/main/res/layout/dialog_progress_bar.xml b/src/android/app/src/main/res/layout/dialog_progress_bar.xml
index 0209ea082..e61aa5294 100644
--- a/src/android/app/src/main/res/layout/dialog_progress_bar.xml
+++ b/src/android/app/src/main/res/layout/dialog_progress_bar.xml
@@ -1,8 +1,30 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<com.google.android.material.progressindicator.LinearProgressIndicator xmlns:android="http://schemas.android.com/apk/res/android" 2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 android:id="@+id/progress_bar"
5 android:layout_width="match_parent" 4 android:layout_width="match_parent"
6 android:layout_height="wrap_content" 5 android:layout_height="wrap_content"
7 android:padding="24dp" 6 android:orientation="vertical">
8 app:trackCornerRadius="4dp" /> 7
8 <com.google.android.material.textview.MaterialTextView
9 android:id="@+id/message"
10 style="@style/TextAppearance.Material3.BodyMedium"
11 android:layout_width="match_parent"
12 android:layout_height="wrap_content"
13 android:layout_marginHorizontal="24dp"
14 android:layout_marginTop="12dp"
15 android:layout_marginBottom="6dp"
16 android:ellipsize="marquee"
17 android:marqueeRepeatLimit="marquee_forever"
18 android:requiresFadingEdge="horizontal"
19 android:singleLine="true"
20 android:textAlignment="viewStart"
21 android:visibility="gone" />
22
23 <com.google.android.material.progressindicator.LinearProgressIndicator
24 android:id="@+id/progress_bar"
25 android:layout_width="match_parent"
26 android:layout_height="wrap_content"
27 android:padding="24dp"
28 app:trackCornerRadius="4dp" />
29
30</LinearLayout>
diff --git a/src/android/app/src/main/res/layout/fragment_game_info.xml b/src/android/app/src/main/res/layout/fragment_game_info.xml
index 80ede8a8c..53af15787 100644
--- a/src/android/app/src/main/res/layout/fragment_game_info.xml
+++ b/src/android/app/src/main/res/layout/fragment_game_info.xml
@@ -118,6 +118,14 @@
118 android:layout_marginTop="16dp" 118 android:layout_marginTop="16dp"
119 android:text="@string/copy_details" /> 119 android:text="@string/copy_details" />
120 120
121 <com.google.android.material.button.MaterialButton
122 android:id="@+id/button_verify_integrity"
123 style="@style/Widget.Material3.Button"
124 android:layout_width="wrap_content"
125 android:layout_height="wrap_content"
126 android:layout_marginTop="10dp"
127 android:text="@string/verify_integrity" />
128
121 </LinearLayout> 129 </LinearLayout>
122 130
123 </androidx.core.widget.NestedScrollView> 131 </androidx.core.widget.NestedScrollView>
diff --git a/src/android/app/src/main/res/layout/fragment_game_properties.xml b/src/android/app/src/main/res/layout/fragment_game_properties.xml
index 72ecbde30..cadd0bc4a 100644
--- a/src/android/app/src/main/res/layout/fragment_game_properties.xml
+++ b/src/android/app/src/main/res/layout/fragment_game_properties.xml
@@ -1,6 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout 2<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto" 3 xmlns:app="http://schemas.android.com/apk/res-auto"
5 xmlns:tools="http://schemas.android.com/tools" 4 xmlns:tools="http://schemas.android.com/tools"
6 android:layout_width="match_parent" 5 android:layout_width="match_parent"
@@ -22,16 +21,35 @@
22 android:orientation="vertical" 21 android:orientation="vertical"
23 android:gravity="center_horizontal"> 22 android:gravity="center_horizontal">
24 23
25 <Button 24 <androidx.constraintlayout.widget.ConstraintLayout
26 android:id="@+id/button_back" 25 android:layout_width="match_parent"
27 style="?attr/materialIconButtonStyle"
28 android:layout_width="wrap_content"
29 android:layout_height="wrap_content" 26 android:layout_height="wrap_content"
30 android:layout_margin="8dp" 27 android:layout_margin="8dp"
31 android:layout_gravity="start" 28 android:orientation="horizontal">
32 app:icon="@drawable/ic_back" 29
33 app:iconSize="24dp" 30 <Button
34 app:iconTint="?attr/colorOnSurface" /> 31 android:id="@+id/button_back"
32 style="?attr/materialIconButtonStyle"
33 android:layout_width="wrap_content"
34 android:layout_height="wrap_content"
35 app:icon="@drawable/ic_back"
36 app:iconSize="24dp"
37 app:iconTint="?attr/colorOnSurface"
38 app:layout_constraintStart_toStartOf="parent"
39 app:layout_constraintTop_toTopOf="parent" />
40
41 <Button
42 android:id="@+id/button_shortcut"
43 style="?attr/materialIconButtonStyle"
44 android:layout_width="wrap_content"
45 android:layout_height="wrap_content"
46 app:icon="@drawable/ic_shortcut"
47 app:iconSize="24dp"
48 app:iconTint="?attr/colorOnSurface"
49 app:layout_constraintEnd_toEndOf="parent"
50 app:layout_constraintTop_toTopOf="parent" />
51
52 </androidx.constraintlayout.widget.ConstraintLayout>
35 53
36 <com.google.android.material.card.MaterialCardView 54 <com.google.android.material.card.MaterialCardView
37 style="?attr/materialCardViewElevatedStyle" 55 style="?attr/materialCardViewElevatedStyle"
@@ -45,7 +63,7 @@
45 android:id="@+id/image_game_screen" 63 android:id="@+id/image_game_screen"
46 android:layout_width="175dp" 64 android:layout_width="175dp"
47 android:layout_height="175dp" 65 android:layout_height="175dp"
48 tools:src="@drawable/default_icon"/> 66 tools:src="@drawable/default_icon" />
49 67
50 </com.google.android.material.card.MaterialCardView> 68 </com.google.android.material.card.MaterialCardView>
51 69
diff --git a/src/android/app/src/main/res/layout/list_item_addon.xml b/src/android/app/src/main/res/layout/list_item_addon.xml
index 74ca04ef1..3a1382fe2 100644
--- a/src/android/app/src/main/res/layout/list_item_addon.xml
+++ b/src/android/app/src/main/res/layout/list_item_addon.xml
@@ -14,12 +14,11 @@
14 android:id="@+id/text_container" 14 android:id="@+id/text_container"
15 android:layout_width="0dp" 15 android:layout_width="0dp"
16 android:layout_height="wrap_content" 16 android:layout_height="wrap_content"
17 android:layout_marginEnd="16dp"
18 android:orientation="vertical" 17 android:orientation="vertical"
19 app:layout_constraintBottom_toBottomOf="@+id/addon_switch" 18 android:layout_marginEnd="16dp"
20 app:layout_constraintEnd_toStartOf="@+id/addon_switch" 19 app:layout_constraintEnd_toStartOf="@+id/addon_checkbox"
21 app:layout_constraintStart_toStartOf="parent" 20 app:layout_constraintStart_toStartOf="parent"
22 app:layout_constraintTop_toTopOf="@+id/addon_switch"> 21 app:layout_constraintTop_toTopOf="parent">
23 22
24 <com.google.android.material.textview.MaterialTextView 23 <com.google.android.material.textview.MaterialTextView
25 android:id="@+id/title" 24 android:id="@+id/title"
@@ -42,16 +41,29 @@
42 41
43 </LinearLayout> 42 </LinearLayout>
44 43
45 <com.google.android.material.materialswitch.MaterialSwitch 44 <com.google.android.material.checkbox.MaterialCheckBox
46 android:id="@+id/addon_switch" 45 android:id="@+id/addon_checkbox"
47 android:layout_width="wrap_content" 46 android:layout_width="wrap_content"
48 android:layout_height="wrap_content" 47 android:layout_height="wrap_content"
49 android:focusable="true" 48 android:focusable="true"
50 android:gravity="center" 49 android:gravity="center"
51 android:nextFocusLeft="@id/addon_container" 50 android:layout_marginEnd="8dp"
52 app:layout_constraintBottom_toBottomOf="parent" 51 app:layout_constraintTop_toTopOf="@+id/text_container"
52 app:layout_constraintBottom_toBottomOf="@+id/text_container"
53 app:layout_constraintEnd_toStartOf="@+id/button_delete" />
54
55 <Button
56 android:id="@+id/button_delete"
57 style="@style/Widget.Material3.Button.IconButton"
58 android:layout_width="wrap_content"
59 android:layout_height="wrap_content"
60 android:layout_gravity="center_vertical"
61 android:contentDescription="@string/delete"
62 android:tooltipText="@string/delete"
63 app:icon="@drawable/ic_delete"
64 app:iconTint="?attr/colorControlNormal"
53 app:layout_constraintEnd_toEndOf="parent" 65 app:layout_constraintEnd_toEndOf="parent"
54 app:layout_constraintStart_toEndOf="@id/text_container" 66 app:layout_constraintTop_toTopOf="@+id/addon_checkbox"
55 app:layout_constraintTop_toTopOf="parent" /> 67 app:layout_constraintBottom_toBottomOf="@+id/addon_checkbox" />
56 68
57</androidx.constraintlayout.widget.ConstraintLayout> 69</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/src/android/app/src/main/res/layout/list_item_setting.xml b/src/android/app/src/main/res/layout/list_item_setting.xml
index 1f80682f1..e13431497 100644
--- a/src/android/app/src/main/res/layout/list_item_setting.xml
+++ b/src/android/app/src/main/res/layout/list_item_setting.xml
@@ -69,7 +69,7 @@
69 android:layout_height="wrap_content" 69 android:layout_height="wrap_content"
70 android:layout_marginTop="16dp" 70 android:layout_marginTop="16dp"
71 android:visibility="gone" 71 android:visibility="gone"
72 android:text="@string/clear" 72 android:text="@string/use_global_setting"
73 tools:visibility="visible" /> 73 tools:visibility="visible" />
74 74
75 </LinearLayout> 75 </LinearLayout>
diff --git a/src/android/app/src/main/res/layout/list_item_setting_switch.xml b/src/android/app/src/main/res/layout/list_item_setting_switch.xml
index 1c08e2e1b..e23337058 100644
--- a/src/android/app/src/main/res/layout/list_item_setting_switch.xml
+++ b/src/android/app/src/main/res/layout/list_item_setting_switch.xml
@@ -63,7 +63,7 @@
63 android:layout_width="wrap_content" 63 android:layout_width="wrap_content"
64 android:layout_height="wrap_content" 64 android:layout_height="wrap_content"
65 android:layout_marginTop="16dp" 65 android:layout_marginTop="16dp"
66 android:text="@string/clear" 66 android:text="@string/use_global_setting"
67 android:visibility="gone" 67 android:visibility="gone"
68 tools:visibility="visible" /> 68 tools:visibility="visible" />
69 69
diff --git a/src/android/app/src/main/res/menu/menu_driver_manager.xml b/src/android/app/src/main/res/menu/menu_driver_manager.xml
index dee5d57b6..0876c2194 100644
--- a/src/android/app/src/main/res/menu/menu_driver_manager.xml
+++ b/src/android/app/src/main/res/menu/menu_driver_manager.xml
@@ -1,11 +1,8 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<menu xmlns:android="http://schemas.android.com/apk/res/android" 2<menu xmlns:android="http://schemas.android.com/apk/res/android">
3 xmlns:app="http://schemas.android.com/apk/res-auto">
4 3
5 <item 4 <item
6 android:id="@+id/menu_driver_clear" 5 android:id="@+id/menu_driver_use_global"
7 android:icon="@drawable/ic_clear" 6 android:title="@string/use_global_setting" />
8 android:title="@string/clear"
9 app:showAsAction="always" />
10 7
11</menu> 8</menu>
diff --git a/src/android/app/src/main/res/menu/menu_in_game.xml b/src/android/app/src/main/res/menu/menu_in_game.xml
index ac6ab06ff..eecb0563b 100644
--- a/src/android/app/src/main/res/menu/menu_in_game.xml
+++ b/src/android/app/src/main/res/menu/menu_in_game.xml
@@ -22,6 +22,11 @@
22 android:title="@string/emulation_input_overlay" /> 22 android:title="@string/emulation_input_overlay" />
23 23
24 <item 24 <item
25 android:id="@+id/menu_lock_drawer"
26 android:icon="@drawable/ic_unlock"
27 android:title="@string/emulation_input_overlay" />
28
29 <item
25 android:id="@+id/menu_exit" 30 android:id="@+id/menu_exit"
26 android:icon="@drawable/ic_exit" 31 android:icon="@drawable/ic_exit"
27 android:title="@string/emulation_exit" /> 32 android:title="@string/emulation_exit" />
diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml
index 07dffffe8..53678f465 100644
--- a/src/android/app/src/main/res/values-ar/strings.xml
+++ b/src/android/app/src/main/res/values-ar/strings.xml
@@ -3,38 +3,39 @@
3 3
4 <string name="emulation_notification_channel_name">المحاكي نشط</string> 4 <string name="emulation_notification_channel_name">المحاكي نشط</string>
5 <string name="emulation_notification_channel_description">اظهار اشعار دائم عندما يكون المحاكي نشطاً</string> 5 <string name="emulation_notification_channel_description">اظهار اشعار دائم عندما يكون المحاكي نشطاً</string>
6 <string name="emulation_notification_running">يوزو يعÙÙ„</string> 6 <string name="emulation_notification_running">يوزو قيد التشغيل</string>
7 <string name="notice_notification_channel_name">الإشعارات والأخطاء</string> 7 <string name="notice_notification_channel_name">الإشعارات والأخطاء</string>
8 <string name="notice_notification_channel_description">اظهار اشعار عند حصول اي مشكلة.</string> 8 <string name="notice_notification_channel_description">اظهار اشعار عند حصول اي مشكلة.</string>
9 <string name="notification_permission_not_granted">لم يتم منح إذن الإشعار</string> 9 <string name="notification_permission_not_granted">لم يتم منح إذن الإشعار</string>
10 10
11 <!-- Setup strings --> 11 <!-- Setup strings -->
12 <string name="welcome">مرحبًا</string> 12 <string name="welcome">مرحبا</string>
13 <string name="welcome_description">والانتقال إلى المحاكاة <b>يوزو</b> تعر٠على كيÙية إعداد.</string> 13 <string name="welcome_description">تعر٠على كيÙية إعداد <b>يوزو</b> والانتقال إلى المحاكاة</string>
14 <string name="get_started">لنبدأ</string> 14 <string name="get_started">لنبدأ</string>
15 <string name="keys">Ø§Ù„Ù…ÙØ§ØªÙŠØ­</string> 15 <string name="keys">Ø§Ù„Ù…ÙØ§ØªÙŠØ­</string>
16 <string name="keys_description">اختر مل٠&lt;b>prod.keys&lt;/b> من الزر ادناه</string> 16 <string name="keys_description">اختر مل٠&lt;b>prod.keys&lt;/b> من الزر ادناه</string>
17 <string name="select_keys">إختيار Ø§Ù„Ù…ÙØ§ØªÙŠØ­</string> 17 <string name="select_keys">إختيار Ø§Ù„Ù…ÙØ§ØªÙŠØ­</string>
18 <string name="games">الألعاب</string> 18 <string name="games">الألعاب</string>
19 <string name="games_description">اختر مجلد &lt;b>العابك&lt;/b> من الزر ادناه.</string> 19 <string name="games_description">حدد مجلد &lt;b>العابك&lt;/b> من الزر ادناه.</string>
20 <string name="done">إنهاء</string> 20 <string name="done">إنهاء</string>
21 <string name="done_description">كل شيء جاهز./n استمتع بألعابك!</string> 21 <string name="done_description">Ø£ÙØª جاهز تمامًا. استمتع بألعابك!</string>
22 <string name="text_continue">استمر</string> 22 <string name="text_continue">استمر</string>
23 <string name="next">التالي</string> 23 <string name="next">التالي</string>
24 <string name="back">عودة</string> 24 <string name="back">عودة</string>
25 <string name="add_games">Ø¥Ø¶Ø§ÙØ© ألعاب</string> 25 <string name="add_games">Ø¥Ø¶Ø§ÙØ© ألعاب</string>
26 <string name="add_games_description">إختار مجلد ألعابك</string> 26 <string name="add_games_description">حدد مجلد الألعاب الخاص بك</string>
27 <string name="step_complete">مكتمل</string> 27 <string name="step_complete">مكتمل</string>
28 28
29 <!-- Home strings --> 29 <!-- Home strings -->
30 <string name="home_games">الألعاب</string> 30 <string name="home_games">الألعاب</string>
31 <string name="home_search">البحث</string> 31 <string name="home_search">البحث</string>
32 <string name="home_settings">الإعدادات</string> 32 <string name="home_settings">الإعدادات</string>
33 <string name="empty_gamelist">لم يتم العثور على Ù…Ù„ÙØ§Øª او لم يتم تحديد مسار العاب.</string> 33 <string name="empty_gamelist">لم يتم العثور على Ù…Ù„ÙØ§Øª أو لم يتم تحديد مجلد الألعاب حتى الآن.</string>
34 <string name="search_and_filter_games">بحث وتصÙية الألعاب</string> 34 <string name="search_and_filter_games">البحث وتصÙية الألعاب</string>
35 <string name="select_games_folder">تحديد مجلد الألعاب</string> 35 <string name="select_games_folder">حدد مجلد الألعاب</string>
36 <string name="manage_game_folders">إدارة مجلدات اللعبة</string>
36 <string name="select_games_folder_description">يسمح لـ يوزو بملء قائمة الألعاب</string> 37 <string name="select_games_folder_description">يسمح لـ يوزو بملء قائمة الألعاب</string>
37 <string name="add_games_warning">تخط٠اختيار مجلد الالعاب؟</string> 38 <string name="add_games_warning">تخطي تحديد مجلد الألعاب؟</string>
38 <string name="add_games_warning_description">لن يتم عرض الألعاب ÙÙŠ قائمة الألعاب إذا لم يتم تحديد مجلد</string> 39 <string name="add_games_warning_description">لن يتم عرض الألعاب ÙÙŠ قائمة الألعاب إذا لم يتم تحديد مجلد</string>
39 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 40 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
40 <string name="home_search_games">البحث عن ألعاب</string> 41 <string name="home_search_games">البحث عن ألعاب</string>
@@ -45,7 +46,7 @@
45 <string name="install_prod_keys_warning">تخطي Ø¥Ø¶Ø§ÙØ© Ø§Ù„Ù…ÙØ§ØªÙŠØ­ØŸ</string> 46 <string name="install_prod_keys_warning">تخطي Ø¥Ø¶Ø§ÙØ© Ø§Ù„Ù…ÙØ§ØªÙŠØ­ØŸ</string>
46 <string name="install_prod_keys_warning_description">مطلوب Ù…ÙØ§ØªÙŠØ­ صالحة لمحاكاة ألعاب البيع بالتجزئة. ستعمل تطبيقات البيرة المنزلية Ùقط إذا تابعت</string> 47 <string name="install_prod_keys_warning_description">مطلوب Ù…ÙØ§ØªÙŠØ­ صالحة لمحاكاة ألعاب البيع بالتجزئة. ستعمل تطبيقات البيرة المنزلية Ùقط إذا تابعت</string>
47 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> 48 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
48 <string name="notifications">التنبيهات</string> 49 <string name="notifications">الإشعارات</string>
49 <string name="notifications_description">امنح إذن الإشعار باستخدام الزر أدناه</string> 50 <string name="notifications_description">امنح إذن الإشعار باستخدام الزر أدناه</string>
50 <string name="give_permission">منح الإذن</string> 51 <string name="give_permission">منح الإذن</string>
51 <string name="notification_warning">تخطي منح إذن الإشعارات؟</string> 52 <string name="notification_warning">تخطي منح إذن الإشعارات؟</string>
@@ -62,9 +63,12 @@
62 <string name="invalid_keys_file">تم تحديد Ù…Ù„Ù Ù…ÙØ§ØªÙŠØ­ غير صالح</string> 63 <string name="invalid_keys_file">تم تحديد Ù…Ù„Ù Ù…ÙØ§ØªÙŠØ­ غير صالح</string>
63 <string name="install_keys_success">تم تثبيت Ø§Ù„Ù…ÙØ§ØªÙŠØ­ بنجاح</string> 64 <string name="install_keys_success">تم تثبيت Ø§Ù„Ù…ÙØ§ØªÙŠØ­ بنجاح</string>
64 <string name="reading_keys_failure">خطأ ÙÙŠ قراءة Ù…ÙØ§ØªÙŠØ­ التشÙير</string> 65 <string name="reading_keys_failure">خطأ ÙÙŠ قراءة Ù…ÙØ§ØªÙŠØ­ التشÙير</string>
66 <string name="install_prod_keys_failure_extension_description">وحاول مرة أخر keys تحقق من أن Ù…Ù„Ù Ø§Ù„Ù…ÙØ§ØªÙŠØ­ له امتداد</string>
67 <string name="install_amiibo_keys_failure_extension_description">وحاول مرة أخر bin تحقق من أن Ù…Ù„Ù Ø§Ù„Ù…ÙØ§ØªÙŠØ­ له امتداد</string>
65 <string name="invalid_keys_error">Ù…ÙØ§ØªÙŠØ­ التشÙير غير صالحة</string> 68 <string name="invalid_keys_error">Ù…ÙØ§ØªÙŠØ­ التشÙير غير صالحة</string>
66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
67 <string name="install_keys_failure_description">المل٠المحدد غير صحيح أو تالÙ. يرجى إعادة Ø§Ù„Ù…ÙØ§ØªÙŠØ­ الخاصة بك</string> 70 <string name="install_keys_failure_description">المل٠المحدد غير صحيح أو تالÙ. يرجى إعادة Ø§Ù„Ù…ÙØ§ØªÙŠØ­ الخاصة بك</string>
71 <string name="gpu_driver_manager">GPU مدير برنامج تشغيل</string>
68 <string name="install_gpu_driver">GPU تثبيت برنامج تشغيل</string> 72 <string name="install_gpu_driver">GPU تثبيت برنامج تشغيل</string>
69 <string name="install_gpu_driver_description">قم بتثبيت برامج تشغيل بديلة للحصول على أداء أو دقة Ø£ÙØ¶Ù„</string> 73 <string name="install_gpu_driver_description">قم بتثبيت برامج تشغيل بديلة للحصول على أداء أو دقة Ø£ÙØ¶Ù„</string>
70 <string name="advanced_settings">إعدادات متقدمة</string> 74 <string name="advanced_settings">إعدادات متقدمة</string>
@@ -82,22 +86,27 @@
82 <string name="notification_no_directory_link_description">الرجاء تحديد موقع مجلد المستخدم باستخدام اللوحة الجانبية لمدير Ø§Ù„Ù…Ù„ÙØ§Øª يدويًا</string> 86 <string name="notification_no_directory_link_description">الرجاء تحديد موقع مجلد المستخدم باستخدام اللوحة الجانبية لمدير Ø§Ù„Ù…Ù„ÙØ§Øª يدويًا</string>
83 <string name="manage_save_data">إدارة Ø­ÙØ¸ البيانات</string> 87 <string name="manage_save_data">إدارة Ø­ÙØ¸ البيانات</string>
84 <string name="manage_save_data_description">Ø­ÙØ¸ البيانات التي تم العثور عليها. يرجى اختيار أحد الخيارات التالية</string> 88 <string name="manage_save_data_description">Ø­ÙØ¸ البيانات التي تم العثور عليها. يرجى اختيار أحد الخيارات التالية</string>
89 <string name="import_save_warning">استيراد Ø­ÙØ¸ البيانات</string>
90 <string name="import_save_warning_description">سيؤدي هذا إلى استبدال جميع بيانات Ø§Ù„Ø­ÙØ¸ الموجودة بالمل٠المقدم. هل أنت متأكد أنك تريد الاستمرار؟</string>
85 <string name="import_export_saves_description">استيراد أو تصدير Ù…Ù„ÙØ§Øª Ø§Ù„Ø­ÙØ¸</string> 91 <string name="import_export_saves_description">استيراد أو تصدير Ù…Ù„ÙØ§Øª Ø§Ù„Ø­ÙØ¸</string>
92 <string name="save_files_importing">جاري استيراد Ù…Ù„ÙØ§Øª Ø§Ù„Ø­ÙØ¸</string>
93 <string name="save_files_exporting">جاري تصدير Ù…Ù„ÙØ§Øª Ø§Ù„Ø­ÙØ¸</string>
86 <string name="save_file_imported_success">تم الاستيراد بنجاح</string> 94 <string name="save_file_imported_success">تم الاستيراد بنجاح</string>
87 <string name="save_file_invalid_zip_structure">بنية مجلد Ø§Ù„Ø­ÙØ¸ غير صالحة</string> 95 <string name="save_file_invalid_zip_structure">بنية مجلد Ø§Ù„Ø­ÙØ¸ غير صالحة</string>
88 <string name="save_file_invalid_zip_structure_description">يجب أن يكون اسم المجلد Ø§Ù„ÙØ±Ø¹ÙŠ Ø§Ù„Ø£ÙˆÙ„ هو معر٠عنوان اللعبة.</string> 96 <string name="save_file_invalid_zip_structure_description">يجب أن يكون اسم المجلد Ø§Ù„ÙØ±Ø¹ÙŠ Ø§Ù„Ø£ÙˆÙ„ هو معر٠عنوان اللعبة.</string>
89 <string name="import_saves">استيراد</string> 97 <string name="import_saves">استيراد</string>
90 <string name="export_saves">تصدير</string> 98 <string name="export_saves">تصدير</string>
91 <string name="install_firmware">تثبيت البرامج الثابتة</string> 99 <string name="install_firmware">تثبيت Ùيرموير</string>
92 <string name="firmware_installing">تثبيت البرامج الثابتة</string> 100 <string name="install_firmware_description">يجب أن يكون Ùيرموير ÙÙŠ أرشي٠مضغوط وهو ضروري لتشغيل بعض الألعاب</string>
93 <string name="firmware_installed_success">تم تثبيت البرامج الثابتة بنجاح</string> 101 <string name="firmware_installing">تثبيت Ùيرموير</string>
94 <string name="firmware_installed_failure">ÙØ´Ù„ تثبيت البرامج الثابتة</string> 102 <string name="firmware_installed_success">تم تثبيت Ùيرموير بنجاح</string>
103 <string name="firmware_installed_failure">ÙØ´Ù„ تثبيت Ùيرموير</string>
95 <string name="share_log">مشاركة سجلات التصحيح</string> 104 <string name="share_log">مشاركة سجلات التصحيح</string>
96 <string name="share_log_description">مشاركة مل٠سجل يوزو لتصحيح المشكلات</string> 105 <string name="share_log_description">مشاركة مل٠سجل يوزو لتصحيح المشكلات</string>
97 <string name="share_log_missing">لم يتم العثور على مل٠السجل</string> 106 <string name="share_log_missing">لم يتم العثور على مل٠السجل</string>
98 <string name="install_game_content">تثبيت محتوى اللعبة</string> 107 <string name="install_game_content">تثبيت محتوى اللعبة</string>
99 <string name="install_game_content_description">DLC قم بتثبيت تحديثات اللعبة أو</string> 108 <string name="install_game_content_description">DLC قم بتثبيت تحديثات اللعبة أو</string>
100 <string name="installing_game_content">جار٠تثبيت المحتوى</string> 109 <string name="installing_game_content">جاري تثبيت المحتوى</string>
101 <string name="install_game_content_failure_base">لا ÙŠÙØ³Ù…Ø­ بتثبيت الألعاب الأساسية لتجنب التعارضات المحتملة.</string> 110 <string name="install_game_content_failure_base">لا ÙŠÙØ³Ù…Ø­ بتثبيت الألعاب الأساسية لتجنب التعارضات المحتملة.</string>
102 <string name="install_game_content_success_install">%1$d تم التثبيت بنجاح</string> 111 <string name="install_game_content_success_install">%1$d تم التثبيت بنجاح</string>
103 <string name="install_game_content_success_overwrite">%1$d تمت الكتابة Ùوقه بنجاح</string> 112 <string name="install_game_content_success_overwrite">%1$d تمت الكتابة Ùوقه بنجاح</string>
@@ -105,19 +114,39 @@
105 <string name="custom_driver_not_supported">برامج التشغيل المخصصة غير مدعومة</string> 114 <string name="custom_driver_not_supported">برامج التشغيل المخصصة غير مدعومة</string>
106 <string name="custom_driver_not_supported_description">تحميل برنامج التشغيل المخصص غير معتمد حاليًا لهذا الجهاز.\nحدد هذا الخيار مرة أخرى ÙÙŠ المستقبل Ù„Ù…Ø¹Ø±ÙØ© ما إذا تمت Ø¥Ø¶Ø§ÙØ© الدعم!</string> 115 <string name="custom_driver_not_supported_description">تحميل برنامج التشغيل المخصص غير معتمد حاليًا لهذا الجهاز.\nحدد هذا الخيار مرة أخرى ÙÙŠ المستقبل Ù„Ù…Ø¹Ø±ÙØ© ما إذا تمت Ø¥Ø¶Ø§ÙØ© الدعم!</string>
107 <string name="manage_yuzu_data">إدارة بيانات يوزو</string> 116 <string name="manage_yuzu_data">إدارة بيانات يوزو</string>
108 <string name="manage_yuzu_data_description">استيراد/تصدير البرامج الثابتة ÙˆØ§Ù„Ù…ÙØ§ØªÙŠØ­ وبيانات المستخدم والمزيد!</string> 117 <string name="manage_yuzu_data_description">استيراد/تصدير Ùيرموير ÙˆØ§Ù„Ù…ÙØ§ØªÙŠØ­ وبيانات المستخدم والمزيد</string>
109 <string name="share_save_file">مشاركة Ù…Ù„Ù Ø§Ù„Ø­ÙØ¸</string> 118 <string name="share_save_file">مشاركة Ù…Ù„Ù Ø§Ù„Ø­ÙØ¸</string>
110 <string name="export_save_failed">ÙØ´Ù„ تصدير Ø§Ù„Ø­ÙØ¸</string> 119 <string name="export_save_failed">ÙØ´Ù„ تصدير Ø§Ù„Ø­ÙØ¸</string>
111 120 <string name="game_folders">مجلدات اللعبة</string>
121 <string name="deep_scan">ÙØ­Øµ عميق</string>
122 <string name="add_game_folder">Ø¥Ø¶Ø§ÙØ© مجلد اللعبة</string>
123 <string name="folder_already_added">تمت Ø¥Ø¶Ø§ÙØ© هذا المجلد Ø¨Ø§Ù„ÙØ¹Ù„</string>
124 <string name="game_folder_properties">خصائص مجلد اللعبة</string>
125 <string name="no_save_data_found">لم يتم العثور على بيانات Ø§Ù„Ø­ÙØ¸</string>
126
127 <!-- Applet launcher strings -->
128 <string name="applets">قائمة التطبيقات المصغرة</string>
129 <string name="applets_description">قم بتشغيل تطبيقات النظام باستخدام Ùيرموير المثبت</string>
130 <string name="applets_error_firmware">Ùيرموير غير مثبت</string>
131 <string name="applets_error_applet">التطبيق المصغر غير Ù…ØªÙˆÙØ±</string>
132 <string name="album_applet">الألبوم</string>
133 <string name="album_applet_description">شاهد الصور المخزنة ÙÙŠ مجلد لقطات شاشة المستخدم باستخدام عارض صور النظام</string>
134 <string name="mii_edit_applet">تحرير Mii</string>
135 <string name="mii_edit_applet_description">باستخدام محرر النظام Miis عرض وتحرير</string>
136 <string name="cabinet_applet_description">تحرير وحذ٠البيانات المخزنة على أميبو</string>
137 <string name="cabinet_nickname_and_owner">إعدادات الاسم المستعار والمالك</string>
138 <string name="cabinet_game_data_eraser">ممحاة بيانات اللعبة</string>
112 <string name="copied_to_clipboard">نسخ إلى Ø§Ù„Ø­Ø§ÙØ¸Ø©</string> 139 <string name="copied_to_clipboard">نسخ إلى Ø§Ù„Ø­Ø§ÙØ¸Ø©</string>
113 <string name="about_app_description">محاكي سويتش Ù…ÙØªÙˆØ­ المصدر</string> 140 <string name="about_app_description">محاكي سويتش Ù…ÙØªÙˆØ­ المصدر</string>
114 <string name="contributors">المساهمين</string> 141 <string name="contributors">المساهمين</string>
142 <string name="contributors_description">مصنوع من ÙØ±ÙŠÙ‚ يوزو</string>
115 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 143 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
116 <string name="licenses_description">المشاريع التي تجعل تطبيق يوزو لنظام أندرويد ممكنًا</string> 144 <string name="licenses_description">المشاريع التي تجعل تطبيق يوزو لنظام أندرويد ممكنًا</string>
117 <string name="build">البناء</string> 145 <string name="build">البناء</string>
118 <string name="user_data">بيانات المستخدم</string> 146 <string name="user_data">بيانات المستخدم</string>
119 <string name="exporting_user_data">جار٠تصدير بيانات المستخدم</string> 147 <string name="user_data_description">استيراد/تصدير جميع بيانات التطبيق. عند استيراد بيانات المستخدم، سيتم حذ٠جميع بيانات المستخدم الحالية!</string>
120 <string name="importing_user_data">جار٠استيراد بيانات المستخدم</string> 148 <string name="exporting_user_data">جاري تصدير بيانات المستخدم</string>
149 <string name="importing_user_data">جاري استيراد بيانات المستخدم</string>
121 <string name="import_user_data">استيراد بيانات المستخدم</string> 150 <string name="import_user_data">استيراد بيانات المستخدم</string>
122 <string name="invalid_yuzu_backup">نسخة احتياطية يوزو غير صالحة</string> 151 <string name="invalid_yuzu_backup">نسخة احتياطية يوزو غير صالحة</string>
123 <string name="user_data_export_success">تم تصدير بيانات المستخدم بنجاح</string> 152 <string name="user_data_export_success">تم تصدير بيانات المستخدم بنجاح</string>
@@ -153,7 +182,7 @@
153 <string name="use_docked_mode">وضع الإرساء</string> 182 <string name="use_docked_mode">وضع الإرساء</string>
154 <string name="use_docked_mode_description">زيادة الدقة، ÙˆØ§Ù†Ø®ÙØ§Ø¶ الأداء. يتم استخدام الوضع المحمول عند تعطيله، مما يؤدي إلى Ø®ÙØ¶ الدقة وزيادة الأداء.</string> 183 <string name="use_docked_mode_description">زيادة الدقة، ÙˆØ§Ù†Ø®ÙØ§Ø¶ الأداء. يتم استخدام الوضع المحمول عند تعطيله، مما يؤدي إلى Ø®ÙØ¶ الدقة وزيادة الأداء.</string>
155 <string name="emulated_region">المنطقة التي تمت محاكاتها</string> 184 <string name="emulated_region">المنطقة التي تمت محاكاتها</string>
156 <string name="emulated_language">لغة المحاكاه</string> 185 <string name="emulated_language">لغة المحاكاة</string>
157 <string name="select_rtc_date">حدد التاريخ Ùˆ الساعة ÙÙŠ الوقت الحقيقي</string> 186 <string name="select_rtc_date">حدد التاريخ Ùˆ الساعة ÙÙŠ الوقت الحقيقي</string>
158 <string name="select_rtc_time">حدد وقت الساعة ÙÙŠ الوقت Ø§Ù„ÙØ¹Ù„ÙŠ</string> 187 <string name="select_rtc_time">حدد وقت الساعة ÙÙŠ الوقت Ø§Ù„ÙØ¹Ù„ÙŠ</string>
159 <string name="use_custom_rtc">ساعة مخصصة ÙÙŠ الوقت الحقيقي</string> 188 <string name="use_custom_rtc">ساعة مخصصة ÙÙŠ الوقت الحقيقي</string>
@@ -164,7 +193,7 @@
164 <string name="renderer_accuracy">مستوى الدقة</string> 193 <string name="renderer_accuracy">مستوى الدقة</string>
165 <string name="renderer_resolution">(Handheld/Docked) الدقة</string> 194 <string name="renderer_resolution">(Handheld/Docked) الدقة</string>
166 <string name="renderer_vsync">VSync وضع</string> 195 <string name="renderer_vsync">VSync وضع</string>
167 <string name="renderer_screen_layout">الاتجاه</string> 196 <string name="renderer_screen_layout">اتجاه العرض</string>
168 <string name="renderer_aspect_ratio">تناسب الابعاد</string> 197 <string name="renderer_aspect_ratio">تناسب الابعاد</string>
169 <string name="renderer_anti_aliasing">طريقة Ù…ÙƒØ§ÙØ­Ø© التعرج</string> 198 <string name="renderer_anti_aliasing">طريقة Ù…ÙƒØ§ÙØ­Ø© التعرج</string>
170 <string name="renderer_asynchronous_shaders">استخدم تظليل غير متزامن</string> 199 <string name="renderer_asynchronous_shaders">استخدم تظليل غير متزامن</string>
@@ -172,31 +201,32 @@
172 <string name="renderer_reactive_flushing">استخدم Ø§Ù„ØªÙ†Ø¸ÙŠÙ Ø§Ù„ØªÙØ§Ø¹Ù„ÙŠ</string> 201 <string name="renderer_reactive_flushing">استخدم Ø§Ù„ØªÙ†Ø¸ÙŠÙ Ø§Ù„ØªÙØ§Ø¹Ù„ÙŠ</string>
173 <string name="renderer_reactive_flushing_description">تحسين دقة العرض ÙÙŠ بعض الألعاب على حساب الأداء</string> 202 <string name="renderer_reactive_flushing_description">تحسين دقة العرض ÙÙŠ بعض الألعاب على حساب الأداء</string>
174 <string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتحميل التظليلات التي تم إنشاؤها محليًا.</string> 203 <string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتحميل التظليلات التي تم إنشاؤها محليًا.</string>
175
176 <!-- Debug settings strings --> 204 <!-- Debug settings strings -->
177 <string name="cpu">وحدة المعالج المركزية</string> 205 <string name="cpu">وحدة المعالج المركزية</string>
178 <string name="cpu_debug_mode">تصحيح أخطاء وحدة المعالجة المركزية</string> 206 <string name="cpu_debug_mode">تصحيح أخطاء وحدة المعالجة المركزية</string>
179 <string name="cpu_debug_mode_description">يضع وحدة المعالجة المركزية ÙÙŠ وضع التصحيح البطيء.</string> 207 <string name="cpu_debug_mode_description">يضع وحدة المعالجة المركزية ÙÙŠ وضع التصحيح البطيء.</string>
180 <string name="gpu">GPU</string> 208 <string name="gpu">وحدة معالجة الرسومات</string>
181 <string name="renderer_api">API</string> 209 <string name="renderer_api">واجهة برمجة التطبيقات</string>
182 <string name="renderer_debug">تصحيح الأخطاء الرسومية</string> 210 <string name="renderer_debug">تصحيح الأخطاء الرسومية</string>
183 <string name="renderer_debug_description">يضبط واجهة برمجة تطبيقات الرسومات على وضع تصحيح الأخطاء البطيء.</string> 211 <string name="renderer_debug_description">يضبط واجهة برمجة تطبيقات الرسومات على وضع تصحيح الأخطاء البطيء.</string>
184 <string name="fastmem">Fastmem</string> 212 <string name="fastmem">Fastmem</string>
185 213
186 <!-- Audio settings strings --> 214 <!-- Audio settings strings -->
187 <string name="audio_output_engine">محرك الإخراج</string> 215 <string name="audio_output_engine">محرك الإخراج</string>
188 <string name="audio_volume">حجÙ</string> 216 <string name="audio_volume">مستوى الصوت</string>
189 <string name="audio_volume_description">يحدد حج٠إخراج الصوت</string> 217 <string name="audio_volume_description">يحدد مستوى إخراج الصوت</string>
190 218
191 <!-- Miscellaneous --> 219 <!-- Miscellaneous -->
192 <string name="slider_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> 220 <string name="slider_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
193 <string name="ini_saved">الإعدادات المحÙوظة</string> 221 <string name="ini_saved">الإعدادات المحÙوظة</string>
194 <string name="gameid_saved">الإعدادات المحÙوظة لـ %1$s</string> 222 <string name="gameid_saved">الإعدادات المحÙوظة لـ %1$s</string>
223 <string name="error_saving">خطأ ÙÙŠ Ø­ÙØ¸ %1$s.ini: %2$s</string>
195 <string name="unimplemented_menu">القائمة غير Ø§Ù„Ù…Ù†ÙØ°Ø©</string> 224 <string name="unimplemented_menu">القائمة غير Ø§Ù„Ù…Ù†ÙØ°Ø©</string>
196 <string name="loading">جاري تحميل</string> 225 <string name="loading">جاري التحميل</string>
197 <string name="shutting_down">إيقا٠تشغيل</string> 226 <string name="shutting_down">إيقا٠التشغيل</string>
198 <string name="reset_setting_confirmation">هل تريد إعادة تعيين هذا الإعداد مرة أخرى إلى قيمته Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©ØŸ</string> 227 <string name="reset_setting_confirmation">هل تريد إعادة تعيين هذا الإعداد مرة أخرى إلى قيمته Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©ØŸ</string>
199 <string name="reset_to_default">إعادة تعيين إلى Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> 228 <string name="reset_to_default">إعادة التعيين إلى الوضع Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
229 <string name="reset_to_default_description">إعادة تعيين جميع الإعدادات المتقدمة</string>
200 <string name="reset_all_settings">إعادة تعيين جميع الإعدادات؟</string> 230 <string name="reset_all_settings">إعادة تعيين جميع الإعدادات؟</string>
201 <string name="reset_all_settings_description">سيتم إعادة تعيين ÙƒØ§ÙØ© الإعدادات المتقدمة إلى تكوينها Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ. هذا لا يمكن التراجع عنها.</string> 231 <string name="reset_all_settings_description">سيتم إعادة تعيين ÙƒØ§ÙØ© الإعدادات المتقدمة إلى تكوينها Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ. هذا لا يمكن التراجع عنها.</string>
202 <string name="settings_reset">إعادة تعيين الأعدادات</string> 232 <string name="settings_reset">إعادة تعيين الأعدادات</string>
@@ -204,32 +234,77 @@
204 <string name="learn_more">Ù…Ø¹Ø±ÙØ© المزيد</string> 234 <string name="learn_more">Ù…Ø¹Ø±ÙØ© المزيد</string>
205 <string name="auto">تلقائي</string> 235 <string name="auto">تلقائي</string>
206 <string name="submit">إرسال</string> 236 <string name="submit">إرسال</string>
207 <string name="string_null">قيمه خاليه</string> 237 <string name="string_null">ÙØ§ شيء</string>
208 <string name="string_import">استيراد</string> 238 <string name="string_import">استيراد</string>
209 <string name="export">تصدير</string> 239 <string name="export">تصدير</string>
210 <string name="export_failed">ÙØ´Ù„ التصدير</string> 240 <string name="export_failed">ÙØ´Ù„ التصدير</string>
211 <string name="import_failed">ÙØ´Ù„ الاستيراد</string> 241 <string name="import_failed">ÙØ´Ù„ الاستيراد</string>
212 <string name="cancelling">إلغاء</string> 242 <string name="cancelling">إلغاء</string>
213 243 <string name="install">تثبيت</string>
244 <string name="delete">حذÙ</string>
245 <string name="edit">حرر</string>
246 <string name="export_success">تم التصدير بنجاح</string>
247 <string name="start">Start</string>
248 <string name="clear">مسح</string>
249 <string name="global">عالمي</string>
250 <string name="custom">مخصص</string>
251 <string name="notice">إشعار</string>
252 <string name="import_complete">اكتمل الاستيراد</string>
214 <!-- GPU driver installation --> 253 <!-- GPU driver installation -->
215 <string name="select_gpu_driver">GPU حدد برنامج تشغيل</string> 254 <string name="select_gpu_driver">GPU حدد برنامج تشغيل</string>
216 <string name="select_gpu_driver_title">الحالي الخاص بك؟ GPU هل ترغب ÙÙŠ استبدال برنامج تشغيل</string> 255 <string name="select_gpu_driver_title">الحالي الخاص بك؟ GPU هل ترغب ÙÙŠ استبدال برنامج تشغيل</string>
217 <string name="select_gpu_driver_install">تثبيت</string> 256 <string name="select_gpu_driver_install">تثبيت</string>
218 <string name="select_gpu_driver_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> 257 <string name="select_gpu_driver_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
219 <string name="select_gpu_driver_use_default">يستخدم تعري٠معالج الرسوميات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> 258 <string name="select_gpu_driver_use_default">يستخدم تعري٠معالج الرسومات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
220 <string name="select_gpu_driver_error">تم تحديد برنامج تشغيل غير صالح ØŒ باستخدام النظام Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> 259 <string name="select_gpu_driver_error">تم تحديد برنامج تشغيل غير صالح</string>
221 <string name="system_gpu_driver">تعري٠معالج الرسوميات الخاص بالنظام</string> 260 <string name="driver_already_installed">برنامج التشغيل مثبت Ø¨Ø§Ù„ÙØ¹Ù„</string>
222 <string name="installing_driver">جار٠تثبيت برنامج التشغيل…</string> 261 <string name="system_gpu_driver">تعري٠معالج الرسومات الخاص بالنظام</string>
262 <string name="installing_driver">جاري تثبيت برنامج التشغيل…</string>
223 263
224 <!-- Preferences Screen --> 264 <!-- Preferences Screen -->
225 <string name="preferences_settings">إعدادات</string> 265 <string name="preferences_settings">إعدادات</string>
226 <string name="preferences_general">عام</string> 266 <string name="preferences_general">عام</string>
227 <string name="preferences_system">النظام</string> 267 <string name="preferences_system">النظام</string>
228 <string name="preferences_graphics">الرسوميات</string> 268 <string name="preferences_system_description">وضع الإرساء ،المنطقة ،اللغة</string>
269 <string name="preferences_graphics">الرسومات</string>
270 <string name="preferences_graphics_description">مستوى الدقة ،الدقة ،ذاكرة التخزين المؤقت للتظليل</string>
229 <string name="preferences_audio">الصوت</string> 271 <string name="preferences_audio">الصوت</string>
272 <string name="preferences_audio_description">محرك الإخراج ، حجم الصوت</string>
230 <string name="preferences_theme">السمة واللون</string> 273 <string name="preferences_theme">السمة واللون</string>
231 <string name="preferences_debug">تصحيح الأخطاء</string> 274 <string name="preferences_debug">تصحيح الأخطاء</string>
232 275 <!-- Game properties -->
276 <string name="info">معلومات</string>
277 <string name="info_description">معر٠البرنامج، المطور، الإصدار</string>
278 <string name="per_game_settings">إعدادات كل لعبة</string>
279 <string name="per_game_settings_description">تحرير الإعدادات الخاصة بهذه اللعبة</string>
280 <string name="launch_options">تشغيل الإعدادات</string>
281 <string name="path">المسار</string>
282 <string name="program_id">معر٠البرنامج</string>
283 <string name="developer">المطور</string>
284 <string name="version">إصدار</string>
285 <string name="copy_details">نسخ Ø§Ù„ØªÙØ§ØµÙŠÙ„</string>
286 <string name="add_ons">Ø§Ù„Ø¥Ø¶Ø§ÙØ§Øª</string>
287 <string name="add_ons_description">DLCالتعديلات والتحديثات و</string>
288 <string name="clear_shader_cache">مسح ذاكرة التخزين المؤقت للتظليل</string>
289 <string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string>
290 <string name="clear_shader_cache_warning_description">سو٠تواجه المزيد من التأتأة مع تجديد ذاكرة التخزين المؤقت للتظليل</string>
291 <string name="cleared_shaders_successfully">تم مسح التظليل بنجاح</string>
292 <string name="addons_game">Ø¥Ø¶Ø§ÙØ§Øª: %1$s</string>
293 <string name="save_data">Ø­ÙØ¸ البيانات</string>
294 <string name="save_data_description">إدارة Ø­ÙØ¸ البيانات الخاصة بهذه اللعبة</string>
295 <string name="delete_save_data">Ø­Ø°Ù Ø­ÙØ¸ البيانات</string>
296 <string name="delete_save_data_description">يزيل ÙƒØ§ÙØ© البيانات المحÙوظة الخاصة بهذه اللعبة</string>
297 <string name="delete_save_data_warning_description">يؤدي هذا إلى إزالة ÙƒØ§ÙØ© البيانات المحÙوظة لهذه اللعبة بشكل لا يمكن استرداده. هل أنت متأكد أنك تريد الاستمرار؟</string>
298 <string name="save_data_deleted_successfully">Ø­ÙØ¸ البيانات تم حذÙها بنجاح</string>
299 <string name="select_content_type">نوع المحتوى</string>
300 <string name="updates_and_dlc">DLC التحديثات والمحتوى القابل للتنزيل </string>
301 <string name="mods_and_cheats">تعديل وغش</string>
302 <string name="addon_notice">إشعار إضاÙÙŠ مهم</string>
303 <string name="invalid_directory">مجلد غير صالح</string>
304 <string name="addon_installed_successfully">تم تثبيت الملحق بنجاح</string>
305 <string name="verifying_content">جاري التحقق من المحتوى</string>
306 <string name="content_install_notice">إشعار تثبيت المحتوى</string>
307 <string name="content_install_notice_description">المحتوى الذي حددته لا يتطابق مع هذه اللعبة.هل تريد التثبيت على أية حال؟</string>
233 <!-- ROM loading errors --> 308 <!-- ROM loading errors -->
234 <string name="loader_error_encrypted">الخاص بك ROM تم تشÙير</string> 309 <string name="loader_error_encrypted">الخاص بك ROM تم تشÙير</string>
235 <string name="loader_error_video_core">حدث خطأ أثناء تهيئة مركز الÙيديو</string> 310 <string name="loader_error_video_core">حدث خطأ أثناء تهيئة مركز الÙيديو</string>
@@ -238,24 +313,25 @@
238 313
239 <!-- Emulation Menu --> 314 <!-- Emulation Menu -->
240 <string name="emulation_exit">الخروج من المحاكاة</string> 315 <string name="emulation_exit">الخروج من المحاكاة</string>
241 <string name="emulation_done">منجز</string> 316 <string name="emulation_done">إنهاء</string>
242 <string name="emulation_fps_counter">عداد إطار/ثانية</string> 317 <string name="emulation_fps_counter">عداد إطار/ثانية</string>
243 <string name="emulation_toggle_controls">تبديل عناصر التحكم</string> 318 <string name="emulation_toggle_controls">عناصر التحكم</string>
244 <string name="emulation_rel_stick_center">مركز العصا النسبي</string> 319 <string name="emulation_rel_stick_center">مركز العصا النسبي</string>
245 <string name="emulation_dpad_slide">مزلاق أزرار الاتجاهات</string> 320 <string name="emulation_dpad_slide">مزلاق الأسهم</string>
246 <string name="emulation_haptics">الاهتزازات الديناميكية</string> 321 <string name="emulation_haptics">الاهتزازات الديناميكية</string>
247 <string name="emulation_show_overlay">عرض التراكب</string> 322 <string name="emulation_show_overlay">عرض التراكب</string>
248 <string name="emulation_toggle_all">تبديل الكل</string> 323 <string name="emulation_toggle_all">الكل</string>
249 <string name="emulation_control_adjust">ضبط التراكب</string> 324 <string name="emulation_control_adjust">ضبط التراكب</string>
250 <string name="emulation_control_scale">حجم</string> 325 <string name="emulation_control_scale">الحجم</string>
251 <string name="emulation_control_opacity">العتاÙÙ</string> 326 <string name="emulation_control_opacity">Ø§Ù„Ø´ÙØ§Ùية</string>
252 <string name="emulation_touch_overlay_reset">إعادة تعيين التراكب</string> 327 <string name="emulation_touch_overlay_reset">إعادة تعيين التراكب</string>
253 <string name="emulation_touch_overlay_edit">تحرير التراكب</string> 328 <string name="emulation_touch_overlay_edit">تحرير التراكب</string>
254 <string name="emulation_pause">إيقا٠المحاكاة مؤقتًا</string> 329 <string name="emulation_pause">إيقا٠المحاكاة مؤقتًا</string>
255 <string name="emulation_unpause">إلغاء الإيقا٠المؤقت Ù„Ù„Ù…ØØ§Ùاة</string> 330 <string name="emulation_unpause">إلغاء الإيقا٠المؤقت للمحاكاة</string>
256 <string name="emulation_input_overlay">خيارات التراكب</string> 331 <string name="emulation_input_overlay">خيارات التراكب</string>
332 <string name="touchscreen">شاشة اللمس</string>
257 333
258 <string name="load_settings">جار٠تحميل الإعدادات</string> 334 <string name="load_settings">جاري تحميل الإعدادات</string>
259 335
260 <!-- Software keyboard --> 336 <!-- Software keyboard -->
261 <string name="software_keyboard">لوحة Ø§Ù„Ù…ÙØ§ØªÙŠØ­ البرمجية</string> 337 <string name="software_keyboard">لوحة Ø§Ù„Ù…ÙØ§ØªÙŠØ­ البرمجية</string>
@@ -282,6 +358,7 @@
282 358
283 <!-- Memory Sizes --> 359 <!-- Memory Sizes -->
284 <string name="memory_byte">Byte</string> 360 <string name="memory_byte">Byte</string>
361 <string name="memory_byte_shorthand">B</string>
285 <string name="memory_kilobyte">KB</string> 362 <string name="memory_kilobyte">KB</string>
286 <string name="memory_megabyte">MB</string> 363 <string name="memory_megabyte">MB</string>
287 <string name="memory_gigabyte">GB</string> 364 <string name="memory_gigabyte">GB</string>
@@ -326,10 +403,9 @@
326 <string name="anti_aliasing_smaa">SMAA</string> 403 <string name="anti_aliasing_smaa">SMAA</string>
327 404
328 <!-- Screen Layouts --> 405 <!-- Screen Layouts -->
329 <string name="screen_layout_landscape">اÙقي</string>
330 <string name="screen_layout_portrait">عمودي</string>
331 <string name="screen_layout_auto">تلقائي</string> 406 <string name="screen_layout_auto">تلقائي</string>
332 407 <string name="screen_layout_landscape">Ø£Ùقي</string>
408 <string name="screen_layout_portrait">عمودي</string>
333 <!-- Aspect Ratios --> 409 <!-- Aspect Ratios -->
334 <string name="ratio_default">(16:9) Ø§ÙØªØ±Ø§Ø¶ÙŠ</string> 410 <string name="ratio_default">(16:9) Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
335 <string name="ratio_force_four_three">4:3 ÙØ±Ø¶</string> 411 <string name="ratio_force_four_three">4:3 ÙØ±Ø¶</string>
@@ -337,16 +413,20 @@
337 <string name="ratio_force_sixteen_ten">16:10 ÙØ±Ø¶</string> 413 <string name="ratio_force_sixteen_ten">16:10 ÙØ±Ø¶</string>
338 <string name="ratio_stretch">تمتد إلى Ø§Ù„Ù†Ø§ÙØ°Ø©</string> 414 <string name="ratio_stretch">تمتد إلى Ø§Ù„Ù†Ø§ÙØ°Ø©</string>
339 415
416 <!-- CPU Backend -->
417 <string name="cpu_backend_dynarmic">Dynarmic (بطيء)</string>
418 <string name="cpu_backend_nce">تنÙيذ التعليمات البرمجية الأصلية (NCE)</string>
419
340 <!-- CPU Accuracy --> 420 <!-- CPU Accuracy -->
341 <string name="cpu_accuracy_accurate">دقه</string> 421 <string name="cpu_accuracy_accurate">دقه</string>
342 <string name="cpu_accuracy_unsafe">غير آمن</string> 422 <string name="cpu_accuracy_unsafe">غير آمن</string>
343 <string name="cpu_accuracy_paranoid">Paranoid (Slow)</string> 423 <string name="cpu_accuracy_paranoid">Paranoid (بطيء)</string>
344 424
345 <!-- Gamepad Buttons --> 425 <!-- Gamepad Buttons -->
346 <string name="gamepad_d_pad">أزرار الاتجاهات</string> 426 <string name="gamepad_d_pad">الأسهم</string>
347 <string name="gamepad_left_stick">العصا اليسرى</string> 427 <string name="gamepad_left_stick">العصا اليسرى</string>
348 <string name="gamepad_right_stick">العصا اليمنى</string> 428 <string name="gamepad_right_stick">العصا اليمنى</string>
349 <string name="gamepad_home">شاشة Ø§Ù„Ø¥Ø³ØªÙØ¨Ø§Ù</string> 429 <string name="gamepad_home">شاشة الرئيسية</string>
350 <string name="gamepad_screenshot">لقطة شاشة</string> 430 <string name="gamepad_screenshot">لقطة شاشة</string>
351 431
352 <!-- Disk shader cache --> 432 <!-- Disk shader cache -->
@@ -362,11 +442,16 @@
362 <string name="change_theme_mode">تغيير وضع السمة</string> 442 <string name="change_theme_mode">تغيير وضع السمة</string>
363 <string name="theme_mode_follow_system">اتبع النظام</string> 443 <string name="theme_mode_follow_system">اتبع النظام</string>
364 <string name="theme_mode_light">ÙØ§ØªØ­</string> 444 <string name="theme_mode_light">ÙØ§ØªØ­</string>
365 <string name="theme_mode_dark">غاÙÙ</string> 445 <string name="theme_mode_dark">داكÙ</string>
366 446
367 <!-- Audio output engines -->
368 <string name="cubeb">cubeb</string> 447 <string name="cubeb">cubeb</string>
369 448
449 <!-- Anisotropic filtering options -->
450 <string name="multiplier_two">2x</string>
451 <string name="multiplier_four">4x</string>
452 <string name="multiplier_eight">8x</string>
453 <string name="multiplier_sixteen">16x</string>
454
370 <!-- Black backgrounds theme --> 455 <!-- Black backgrounds theme -->
371 <string name="use_black_backgrounds">خلÙيات سوداء</string> 456 <string name="use_black_backgrounds">خلÙيات سوداء</string>
372 <string name="use_black_backgrounds_description">عند استخدام المظهر الداكن، قم بتطبيق خلÙيات سوداء.</string> 457 <string name="use_black_backgrounds_description">عند استخدام المظهر الداكن، قم بتطبيق خلÙيات سوداء.</string>
diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml
index d2e5fee19..7e1eb2b8d 100644
--- a/src/android/app/src/main/res/values-ckb/strings.xml
+++ b/src/android/app/src/main/res/values-ckb/strings.xml
@@ -157,7 +157,6 @@
157 <string name="renderer_reactive_flushing_description">وردی ڕێندەرکردن لە هەندێک یاریدا باشتر دەکات لەسەر تێچووی کارایی.</string> 157 <string name="renderer_reactive_flushing_description">وردی ڕێندەرکردن لە هەندێک یاریدا باشتر دەکات لەسەر تێچووی کارایی.</string>
158 <string name="use_disk_shader_cache">بیرگەخێرای سێبەری دیسک</string> 158 <string name="use_disk_shader_cache">بیرگەخێرای سێبەری دیسک</string>
159 <string name="use_disk_shader_cache_description">پچڕپچڕی کەمدەکاتەوە بە هەڵگرتن و بارکردنی سێبەری دروستکراو لە ناوخۆدا.</string> 159 <string name="use_disk_shader_cache_description">پچڕپچڕی کەمدەکاتەوە بە هەڵگرتن و بارکردنی سێبەری دروستکراو لە ناوخۆدا.</string>
160
161 <!-- Debug settings strings --> 160 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string> 161 <string name="cpu">CPU</string>
163 <string name="renderer_api">API گراÙیک</string> 162 <string name="renderer_api">API گراÙیک</string>
@@ -183,13 +182,15 @@
183 <string name="submit">پێشکەشکردن</string> 182 <string name="submit">پێشکەشکردن</string>
184 <string name="string_import">هاوردەکردن</string> 183 <string name="string_import">هاوردەکردن</string>
185 <string name="export">هەناردەکردن</string> 184 <string name="export">هەناردەکردن</string>
185 <string name="install">دامەزراندن</string>
186 <string name="delete">سڕینەوە</string>
187 <string name="clear">سڕینەوە</string>
186 <!-- GPU driver installation --> 188 <!-- GPU driver installation -->
187 <string name="select_gpu_driver">هەڵبژاردنی وەگەڕخەری GPU</string> 189 <string name="select_gpu_driver">هەڵبژاردنی وەگەڕخەری GPU</string>
188 <string name="select_gpu_driver_title">حەز دەکەیت وەگەڕخەری GPU ی ئێستات بگۆڕیت؟</string> 190 <string name="select_gpu_driver_title">حەز دەکەیت وەگەڕخەری GPU ی ئێستات بگۆڕیت؟</string>
189 <string name="select_gpu_driver_install">دامەزراندن</string> 191 <string name="select_gpu_driver_install">دامەزراندن</string>
190 <string name="select_gpu_driver_default">بنەڕەت</string> 192 <string name="select_gpu_driver_default">بنەڕەت</string>
191 <string name="select_gpu_driver_use_default">بەکارهێنانی وەگەڕخەری GPU ی بنەڕەت</string> 193 <string name="select_gpu_driver_use_default">بەکارهێنانی وەگەڕخەری GPU ی بنەڕەت</string>
192 <string name="select_gpu_driver_error">وەگەڕخەری نادروست هەڵبژێردرا، بە بەکارهێنانی بنەڕەتی سیستەم!</string>
193 <string name="system_gpu_driver">وەگەڕخەری GPU ی سیستەم</string> 194 <string name="system_gpu_driver">وەگەڕخەری GPU ی سیستەم</string>
194 <string name="installing_driver">دامەزراندنی وەگەڕخەر...</string> 195 <string name="installing_driver">دامەزراندنی وەگەڕخەر...</string>
195 196
@@ -201,7 +202,8 @@
201 <string name="preferences_audio">دەنگ</string> 202 <string name="preferences_audio">دەنگ</string>
202 <string name="preferences_theme">ڕەنگ و ڕووکار</string> 203 <string name="preferences_theme">ڕەنگ و ڕووکار</string>
203 <string name="preferences_debug">چاککردنەوە</string> 204 <string name="preferences_debug">چاککردنەوە</string>
204 205 <string name="path">Ú•ÛŽÚ•Û•Ùˆ</string>
206 <string name="version">وەشان</string>
205 <!-- ROM loading errors --> 207 <!-- ROM loading errors -->
206 <string name="loader_error_encrypted">ڕۆمەکەت کۆدکراوە</string> 208 <string name="loader_error_encrypted">ڕۆمەکەت کۆدکراوە</string>
207 <string name="loader_error_encrypted_keys_description"><![CDATA[تکایە دڵنیابەوە لەدامەزراوی <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ÙØ§ÛŒÙ„ەکەت بۆ ئەوەی بتوانرێت یارییەکان کۆد بکرێنەوە.]]></string> 209 <string name="loader_error_encrypted_keys_description"><![CDATA[تکایە دڵنیابەوە لەدامەزراوی <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ÙØ§ÛŒÙ„ەکەت بۆ ئەوەی بتوانرێت یارییەکان کۆد بکرێنەوە.]]></string>
@@ -228,6 +230,7 @@
228 <string name="emulation_pause">وەستاندنی ئیمولەیشن</string> 230 <string name="emulation_pause">وەستاندنی ئیمولەیشن</string>
229 <string name="emulation_unpause">لادانی وەستاندنی ئیمولەیشن</string> 231 <string name="emulation_unpause">لادانی وەستاندنی ئیمولەیشن</string>
230 <string name="emulation_input_overlay">هەڵبژاردەکانی داپۆشەر</string> 232 <string name="emulation_input_overlay">هەڵبژاردەکانی داپۆشەر</string>
233 <string name="touchscreen">رووکاری لەمسی</string>
231 234
232 <string name="load_settings">بارکردنی ڕێکخستنەکان...</string> 235 <string name="load_settings">بارکردنی ڕێکخستنەکان...</string>
233 236
@@ -253,6 +256,7 @@
253 <string name="region_korea">کۆریا</string> 256 <string name="region_korea">کۆریا</string>
254 <string name="region_taiwan">تایوان</string> 257 <string name="region_taiwan">تایوان</string>
255 258
259 <string name="memory_byte_shorthand">B</string>
256 <string name="memory_gigabyte">GB</string> 260 <string name="memory_gigabyte">GB</string>
257 <!-- Renderer APIs --> 261 <!-- Renderer APIs -->
258 <string name="renderer_vulkan">ڤوڵکان</string> 262 <string name="renderer_vulkan">ڤوڵکان</string>
@@ -290,8 +294,8 @@
290 <string name="anti_aliasing_fxaa">FXAA</string> 294 <string name="anti_aliasing_fxaa">FXAA</string>
291 <string name="anti_aliasing_smaa">SMAA</string> 295 <string name="anti_aliasing_smaa">SMAA</string>
292 296
297 <!-- Screen Layouts -->
293 <string name="screen_layout_auto">خودکار</string> 298 <string name="screen_layout_auto">خودکار</string>
294
295 <!-- Aspect Ratios --> 299 <!-- Aspect Ratios -->
296 <string name="ratio_default">بنەڕەت (16:9)</string> 300 <string name="ratio_default">بنەڕەت (16:9)</string>
297 <string name="ratio_force_four_three">ڕووبەری 4:3</string> 301 <string name="ratio_force_four_three">ڕووبەری 4:3</string>
@@ -326,6 +330,12 @@
326 <string name="theme_mode_light">ڕوناکی</string> 330 <string name="theme_mode_light">ڕوناکی</string>
327 <string name="theme_mode_dark">تاریک</string> 331 <string name="theme_mode_dark">تاریک</string>
328 332
333 <!-- Anisotropic filtering options -->
334 <string name="multiplier_two">2x</string>
335 <string name="multiplier_four">4x</string>
336 <string name="multiplier_eight">8x</string>
337 <string name="multiplier_sixteen">16x</string>
338
329 <!-- Black backgrounds theme --> 339 <!-- Black backgrounds theme -->
330 <string name="use_black_backgrounds">پاشبنەمای ڕەش</string> 340 <string name="use_black_backgrounds">پاشبنەمای ڕەش</string>
331 <string name="use_black_backgrounds_description">لە کاتی بەکارهێنانی ڕووکاری تاریکدا، پاشبنەمای ڕەش دادەنێ.</string> 341 <string name="use_black_backgrounds_description">لە کاتی بەکارهێنانی ڕووکاری تاریکدا، پاشبنەمای ڕەش دادەنێ.</string>
diff --git a/src/android/app/src/main/res/values-cs/strings.xml b/src/android/app/src/main/res/values-cs/strings.xml
new file mode 100644
index 000000000..b9a4a11e4
--- /dev/null
+++ b/src/android/app/src/main/res/values-cs/strings.xml
@@ -0,0 +1,265 @@
1<?xml version="1.0" encoding="utf-8"?>
2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3
4 <string name="emulation_notification_channel_name">Emulace je aktivní</string>
5 <string name="notice_notification_channel_name">Upozornění a chyby</string>
6 <string name="notice_notification_channel_description">Ukáže oznámení v případě chyby.</string>
7 <string name="notification_permission_not_granted">Oznámení nejsou oprávněna!</string>
8
9 <!-- Setup strings -->
10 <string name="welcome">Vítejte!</string>
11 <string name="get_started">ZaÄít</string>
12 <string name="keys">KlíÄe</string>
13 <string name="select_keys">Vybrat klíÄe</string>
14 <string name="games">Hry</string>
15 <string name="done">Hotovo</string>
16 <string name="done_description">Vše je připraveno.\nUžijte si vaše hry!</string>
17 <string name="text_continue">PokraÄovat</string>
18 <string name="next">Další</string>
19 <string name="back">Zpět</string>
20 <string name="add_games">Přidat hry</string>
21 <string name="add_games_description">Vyber svoji složku se hrami</string>
22 <!-- Home strings -->
23 <string name="home_games">Hry</string>
24 <string name="home_search">Hledat</string>
25 <string name="home_settings">Nastavení</string>
26 <string name="empty_gamelist">Nebyly nalezeny žádné soubory nebo ještě nebyl vybrán žádný adresář s hrami.</string>
27 <string name="search_and_filter_games">Hledat a filtrovat hry</string>
28 <string name="select_games_folder">Vybrat složku s hrami</string>
29 <string name="manage_game_folders">Spravovat složky s hrami</string>
30 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
31 <string name="install_prod_keys">Instalovat prod.keys</string>
32 <string name="install_prod_keys_warning">PÅ™eskoÄit pÅ™idávání klíÄů?</string>
33 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
34 <string name="notifications">Oznámení</string>
35 <string name="give_permission">Udělit oprávnění</string>
36 <string name="notification_warning">PÅ™eskoÄit udÄ›lení oprávnÄ›ní k oznámení?</string>
37 <string name="notification_warning_description">yuzu vám nebude schopno oznámit důležité informace.</string>
38 <string name="permission_denied">Oprávnění zamítnuto</string>
39 <string name="permission_denied_description">Zamítnul jste toto oprávnění příliš mnohokrát, musíte manuálně udělit oprávnění v nastavení systému.</string>
40 <string name="about">O aplikaci</string>
41 <string name="about_description">Verze sestavení, titulky a více</string>
42 <string name="warning_help">Pomoc</string>
43 <string name="warning_skip">PÅ™eskoÄit</string>
44 <string name="warning_cancel">Zrušit</string>
45 <string name="install_amiibo_keys">Instalovat Amiibo klíÄe</string>
46 <string name="install_amiibo_keys_description">Povinné použití Amiibo ve hře</string>
47 <string name="invalid_keys_file">Vybrané klíÄe jsou neplatné</string>
48 <string name="install_keys_success">KlíÄe úspěšnÄ› nainstalovány</string>
49 <string name="reading_keys_failure">Chyba pÅ™i Ätení Å¡ifrovacích klíÄů</string>
50 <string name="invalid_keys_error">Neplatné Å¡ifrovací klíÄe</string>
51 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
52 <string name="gpu_driver_manager">Správce ovladaÄe GPU</string>
53 <string name="install_gpu_driver">Instalovat GPU ovladaÄ</string>
54 <string name="advanced_settings">PokroÄilé nastavení</string>
55 <string name="settings_description">Konfigurovat nastavení emulátoru</string>
56 <string name="search_recently_played">Nedávno hrané</string>
57 <string name="search_recently_added">Nedávno přidané</string>
58 <string name="search_homebrew">Homebrew</string>
59 <string name="open_user_folder">Otevřít yuzu složku</string>
60 <string name="open_user_folder_description">Spravovat soubory yuzu</string>
61 <string name="no_file_manager">Nenalezen žádný správce souborů</string>
62 <string name="notification_no_directory_link">Nepovedlo se otevřít yuzu složku</string>
63 <string name="manage_save_data">Spravovat data postupu ve hře</string>
64 <string name="manage_save_data_description">Data postupu nalezeny. Prosím vyberte možnost.</string>
65 <string name="import_export_saves_description">Importovat nebo exportovat data postupu</string>
66 <string name="save_file_imported_success">Uspěšně importováno</string>
67 <string name="save_file_invalid_zip_structure">Neplatná struktura dat postupu</string>
68 <string name="import_saves">Importovat</string>
69 <string name="export_saves">Exportovat</string>
70 <string name="install_firmware">Nainstalovat firmware</string>
71 <string name="firmware_installing">Instalování firmwaru</string>
72 <string name="firmware_installed_success">Firmware byl úspěšně nainstalován</string>
73 <string name="firmware_installed_failure">Instalace firmwaru selhala</string>
74 <string name="install_game_content">Nainstalovat obsah hry</string>
75 <string name="install_game_content_description">Nainstalovat aktualizace hry nebo DLC</string>
76 <string name="installing_game_content">Instalování obsahu...</string>
77 <string name="install_game_content_failure">Chyba při instalaci soubor(ů) do NAND</string>
78 <string name="manage_yuzu_data">Spravovat data yuzu</string>
79 <string name="game_folders">Složky s hrami</string>
80 <string name="folder_already_added">Tato složka byla již přidána!</string>
81 <string name="game_folder_properties">Vlastnosti složky s hrami</string>
82 <string name="album_applet_description">Zobrazovat obrázky uložené v uživatelské složce se snímky obrazovky pomocí systémového prohlížeÄe fotografií</string>
83 <string name="cabinet_nickname_and_owner">Nastavení přezdívky a vlastníka</string>
84 <!-- About screen strings -->
85 <string name="gaia_is_not_real">Gaia není skuteÄná</string>
86 <string name="copied_to_clipboard">Zkopírováno do schránky</string>
87 <string name="about_app_description">Open-source Switch emulátor</string>
88 <string name="contributors">Přispěvatelé</string>
89 <string name="contributors_description">Vyrobeno s \u2764 od yuzu týmu</string>
90 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
91 <string name="build">Číslo sestavení</string>
92 <string name="user_data">Uživatelská data</string>
93 <string name="exporting_user_data">Exportování uživatelských dat...</string>
94 <string name="importing_user_data">Importování uživatelských dat...</string>
95 <string name="import_user_data">Importovat uživatelská data</string>
96 <string name="invalid_yuzu_backup">Neplatná záloha yuzu</string>
97 <string name="user_data_export_success">Uživatelská data byla úspěšně exportována.</string>
98 <string name="user_data_import_success">Uživatelská data byla úspěšně importována.</string>
99 <string name="user_data_export_cancelled">Export zrušen</string>
100 <string name="support_link">https://discord.gg/u77vRWY</string>
101 <string name="website_link">https://yuzu-emu.org/</string>
102 <string name="github_link">https://github.com/yuzu-emu</string>
103
104 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
105 <string name="no_manual_installation">Žádná manuální instalace</string>
106 <string name="prioritized_support">Prioritní podpora</string>
107 <string name="our_eternal_gratitude">NaÅ¡e vÄ›Äná vdÄ›Änost</string>
108 <string name="are_you_interested">Máte zájem?</string>
109
110 <!-- General settings strings -->
111 <string name="frame_limit_enable">Omezit rychlost</string>
112 <string name="cpu_accuracy">CPU přesnost</string>
113 <string name="emulated_region">Emulovaná oblast</string>
114 <string name="emulated_language">Emulovaný jazyk</string>
115 <string name="use_custom_rtc">Vlastní RTC</string>
116 <!-- Graphics settings strings -->
117 <string name="renderer_accuracy">Úroveň přesnosti</string>
118 <string name="renderer_vsync">VSync režim</string>
119 <string name="renderer_screen_layout">Orientace</string>
120 <string name="renderer_aspect_ratio">Poměr stran</string>
121 <!-- Debug settings strings -->
122 <string name="cpu">CPU</string>
123 <string name="renderer_api">API</string>
124 <!-- Audio settings strings -->
125 <string name="audio_output_engine">Výstupní engine</string>
126 <string name="audio_volume">Hlasitost</string>
127 <string name="audio_volume_description">Udává hlasitost zvukového výstupu.</string>
128
129 <!-- Miscellaneous -->
130 <string name="slider_default">Výchozí</string>
131 <string name="ini_saved">Nastavení uložena</string>
132 <string name="gameid_saved">Uložena nastavení pro %1$s</string>
133 <string name="loading">NaÄítání...</string>
134 <string name="shutting_down">Vypínání...</string>
135 <string name="reset_setting_confirmation">Chcete obnovit toto nastavení zpět na jeho výchozí hodnotu?</string>
136 <string name="reset_to_default">Navrátit k výchozímu</string>
137 <string name="reset_all_settings">Resetovat všechna nastavení?</string>
138 <string name="reset_all_settings_description">VÅ¡echna pokroÄilá nastavení budou obnovena na jejich výchozí konfiguraci. Toto nelze vrátit zpÄ›t.</string>
139 <string name="close">Zavřít</string>
140 <string name="learn_more">Zjistit více</string>
141 <string name="auto">Automatické</string>
142 <string name="string_import">Importovat</string>
143 <string name="export">Exportovat</string>
144 <string name="install">Nainstalovat</string>
145 <string name="delete">Smazat</string>
146 <string name="export_success">Úspěšně exportováno</string>
147 <string name="start">Start</string>
148 <string name="clear">Vymazat</string>
149 <string name="custom">Vlastní</string>
150 <!-- GPU driver installation -->
151 <string name="select_gpu_driver">Vybrat GPU ovladaÄ</string>
152 <string name="select_gpu_driver_title">Chcete nahradit váš aktuální ovladaÄ GPU?</string>
153 <string name="select_gpu_driver_install">Nainstalovat</string>
154 <string name="select_gpu_driver_default">Výchozí</string>
155 <string name="select_gpu_driver_error">Vybrán neplatný ovladaÄ</string>
156 <string name="driver_already_installed">OvladaÄ již nainstalován</string>
157 <string name="system_gpu_driver">Systémový ovladaÄ GPU</string>
158 <string name="installing_driver">Instalování ovladaÄe...</string>
159
160 <!-- Preferences Screen -->
161 <string name="preferences_settings">Nastavení</string>
162 <string name="preferences_general">Obecné</string>
163 <string name="preferences_system">Systém</string>
164 <string name="preferences_graphics">Grafika</string>
165 <string name="preferences_audio">Zvuk</string>
166 <string name="preferences_audio_description">Výstupní engine, hlasitost</string>
167 <string name="preferences_theme">Vzhled a barva</string>
168 <string name="preferences_debug">Ladění</string>
169 <!-- Game properties -->
170 <string name="info">Info</string>
171 <string name="path">Cesta</string>
172 <string name="developer">Vývojář</string>
173 <string name="version">Verze</string>
174 <string name="copy_details">Zkopírovat podrobnosti</string>
175 <string name="add_ons">Modifkace</string>
176 <string name="addons_game">Rozšíření: %1$s</string>
177 <string name="select_content_type">Typ obsahu</string>
178 <string name="updates_and_dlc">Aktualizace a DLC</string>
179 <string name="mods_and_cheats">Módy a cheaty</string>
180 <string name="addon_installed_successfully">Rozšíření úspěšně nainstalováno</string>
181 <string name="verifying_content">Ověřování obsahu...</string>
182 <string name="emulation_done">Hotovo</string>
183 <string name="emulation_control_scale">Měřítko</string>
184 <string name="emulation_control_opacity">Průhlednost</string>
185 <string name="touchscreen">Dotyková obrazovka</string>
186
187 <!-- Errors and warnings -->
188 <string name="abort_button">Přerušit</string>
189 <string name="continue_button">PokraÄovat</string>
190 <string name="system_archive_not_found">Systémový Archív Nenalezen</string>
191 <string name="save_load_error">Ukládací/NaÄítací chyba</string>
192 <string name="fatal_error">Fatální Chyba</string>
193 <!-- Region Names -->
194 <string name="region_japan">Japonsko</string>
195 <string name="region_usa">USA</string>
196 <string name="region_europe">Evropa</string>
197 <string name="region_australia">Austrálie</string>
198 <string name="region_china">Čína</string>
199 <string name="region_korea">Korea</string>
200 <string name="region_taiwan">Taiwan</string>
201
202 <string name="memory_byte_shorthand">B</string>
203 <string name="memory_gigabyte">GB</string>
204 <!-- Renderer APIs -->
205 <string name="renderer_vulkan">Vulkan</string>
206 <string name="renderer_none">Žádné</string>
207
208 <!-- Renderer Accuracy -->
209 <string name="renderer_accuracy_normal">Normální</string>
210 <string name="renderer_accuracy_high">Vysoká</string>
211 <!-- Resolutions -->
212 <string name="resolution_half">0.5X (360p/540p)</string>
213 <string name="resolution_three_quarter">0.75X (540p/810p)</string>
214 <string name="resolution_one">1X (720p/1080p)</string>
215 <string name="resolution_two">2X (1440p/2160p) (Pomalé)</string>
216 <string name="resolution_three">3X (2160p/3240p) (Pomalé)</string>
217 <string name="resolution_four">4X (2880p/4320p) (Pomalé)</string>
218
219 <string name="scaling_filter_bilinear">Bilineární</string>
220 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string>
221
222 <!-- Anti-Aliasing -->
223 <string name="anti_aliasing_none">Žádné</string>
224 <string name="anti_aliasing_fxaa">FXAA</string>
225 <string name="anti_aliasing_smaa">SMAA</string>
226
227 <!-- Screen Layouts -->
228 <string name="screen_layout_auto">Automatické</string>
229 <!-- Aspect Ratios -->
230 <string name="ratio_default">Výchozí (16:9)</string>
231 <string name="ratio_force_four_three">Vynutit 4:3</string>
232 <string name="ratio_force_twenty_one_nine">Vynutit 21:9</string>
233 <!-- CPU Accuracy -->
234 <string name="cpu_accuracy_accurate">Přesné</string>
235 <string name="cpu_accuracy_unsafe">NebezpeÄné</string>
236 <string name="gamepad_home">Home</string>
237 <string name="building_shaders">Budování shaderů</string>
238
239 <!-- Theme options -->
240 <string name="change_app_theme">Změnit vzhled aplikace</string>
241 <string name="theme_default">Výchozí</string>
242 <string name="theme_material_you">Material You</string>
243
244 <!-- Theme Modes -->
245 <string name="change_theme_mode">Změnit styl vzhledu</string>
246 <string name="theme_mode_follow_system">Podle systému</string>
247 <string name="theme_mode_light">Světlé</string>
248 <string name="theme_mode_dark">Tmavé</string>
249
250 <!-- Anisotropic filtering options -->
251 <string name="multiplier_two">2x</string>
252 <string name="multiplier_four">4x</string>
253 <string name="multiplier_eight">8x</string>
254 <string name="multiplier_sixteen">16x</string>
255
256 <!-- Black backgrounds theme -->
257 <string name="use_black_backgrounds">Černá pozadí</string>
258 <!-- Picture-In-Picture -->
259 <string name="picture_in_picture">Obraz v obraze</string>
260 <string name="mute">Ztlumit</string>
261 <string name="unmute">Vypnout ztlumení</string>
262
263 <!-- Licenses screen strings -->
264 <string name="licenses">Licence</string>
265 </resources>
diff --git a/src/android/app/src/main/res/values-de/strings.xml b/src/android/app/src/main/res/values-de/strings.xml
index 9c6590b5e..483ea8c88 100644
--- a/src/android/app/src/main/res/values-de/strings.xml
+++ b/src/android/app/src/main/res/values-de/strings.xml
@@ -34,6 +34,7 @@
34 <string name="empty_gamelist">Es wurden keine Dateien gefunden oder es wurde noch kein Spielverzeichnis ausgewählt.</string> 34 <string name="empty_gamelist">Es wurden keine Dateien gefunden oder es wurde noch kein Spielverzeichnis ausgewählt.</string>
35 <string name="search_and_filter_games">Spiele suchen und filtern</string> 35 <string name="search_and_filter_games">Spiele suchen und filtern</string>
36 <string name="select_games_folder">Spieleverzeichnis auswählen</string> 36 <string name="select_games_folder">Spieleverzeichnis auswählen</string>
37 <string name="manage_game_folders">Spiele-Ordner verwalten</string>
37 <string name="select_games_folder_description">Erlaubt yuzu die Spieleliste zu füllen</string> 38 <string name="select_games_folder_description">Erlaubt yuzu die Spieleliste zu füllen</string>
38 <string name="add_games_warning">Auswahl des Spieleverzeichnisses überspringen?</string> 39 <string name="add_games_warning">Auswahl des Spieleverzeichnisses überspringen?</string>
39 <string name="add_games_warning_description">Spiele werden in der Spieleliste nicht angezeigt, wenn kein Ordner ausgewählt ist.</string> 40 <string name="add_games_warning_description">Spiele werden in der Spieleliste nicht angezeigt, wenn kein Ordner ausgewählt ist.</string>
@@ -67,9 +68,11 @@
67 <string name="invalid_keys_error">Ungültige Schlüssel</string> 68 <string name="invalid_keys_error">Ungültige Schlüssel</string>
68 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
69 <string name="install_keys_failure_description">Die ausgewählte Datei ist falsch oder beschädigt. Bitte kopieren Sie Ihre Schlüssel erneut.</string> 70 <string name="install_keys_failure_description">Die ausgewählte Datei ist falsch oder beschädigt. Bitte kopieren Sie Ihre Schlüssel erneut.</string>
71 <string name="gpu_driver_manager">GPU-Treiber Verwaltung</string>
70 <string name="install_gpu_driver">GPU-Treiber installieren</string> 72 <string name="install_gpu_driver">GPU-Treiber installieren</string>
71 <string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string> 73 <string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string>
72 <string name="advanced_settings">Erweiterte Einstellungen</string> 74 <string name="advanced_settings">Erweiterte Einstellungen</string>
75 <string name="advanced_settings_game">Erweiterte Einstellungen: %1$s</string>
73 <string name="settings_description">Emulatoreinstellungen konfigurieren</string> 76 <string name="settings_description">Emulatoreinstellungen konfigurieren</string>
74 <string name="search_recently_played">Kürzlich gespielt</string> 77 <string name="search_recently_played">Kürzlich gespielt</string>
75 <string name="search_recently_added">Kürzlich hinzugefügt</string> 78 <string name="search_recently_added">Kürzlich hinzugefügt</string>
@@ -83,7 +86,11 @@
83 <string name="notification_no_directory_link_description">Bitte suche den Benutzerordner manuell über die Seitenleiste des Dateimanagers.</string> 86 <string name="notification_no_directory_link_description">Bitte suche den Benutzerordner manuell über die Seitenleiste des Dateimanagers.</string>
84 <string name="manage_save_data">Speicherdaten verwalten</string> 87 <string name="manage_save_data">Speicherdaten verwalten</string>
85 <string name="manage_save_data_description">Speicherdaten gefunden. Bitte wähle unten eine Option aus.</string> 88 <string name="manage_save_data_description">Speicherdaten gefunden. Bitte wähle unten eine Option aus.</string>
89 <string name="import_save_warning">Speicherdaten importieren</string>
90 <string name="import_save_warning_description">Das überschreibt alle existierenden Speicherdaten für dieses Spiel mit der ausgewählten Datei. Wirklich fortfahren?</string>
86 <string name="import_export_saves_description">Speicherdaten importieren oder exportieren</string> 91 <string name="import_export_saves_description">Speicherdaten importieren oder exportieren</string>
92 <string name="save_files_importing">Importiere Speicherdaten...</string>
93 <string name="save_files_exporting">Exportiere Speicherdaten...</string>
87 <string name="save_file_imported_success">Erfolgreich importiert</string> 94 <string name="save_file_imported_success">Erfolgreich importiert</string>
88 <string name="save_file_invalid_zip_structure">Ungültige Speicherverzeichnisstruktur</string> 95 <string name="save_file_invalid_zip_structure">Ungültige Speicherverzeichnisstruktur</string>
89 <string name="save_file_invalid_zip_structure_description">Der erste Unterordnername muss die Titel-ID des Spiels sein.</string> 96 <string name="save_file_invalid_zip_structure_description">Der erste Unterordnername muss die Titel-ID des Spiels sein.</string>
@@ -98,8 +105,17 @@
98 <string name="share_log_description">Debug-Logs an yuzu zur Untersuchung absenden</string> 105 <string name="share_log_description">Debug-Logs an yuzu zur Untersuchung absenden</string>
99 <string name="share_log_missing">Keine Log-Datei gefunden</string> 106 <string name="share_log_missing">Keine Log-Datei gefunden</string>
100 <string name="install_game_content">Spiel installieren</string> 107 <string name="install_game_content">Spiel installieren</string>
101 <string name="install_game_content_description">Spiel Update oder DLC installieren</string> 108 <string name="install_game_content_description">Spiel-Updates oder DLCs installieren</string>
109 <string name="installing_game_content">Installiere...</string>
110 <string name="install_game_content_failed_count">%1$d Installationsfehler</string>
111 <string name="install_game_content_success_install">%1$d erfolgreich installiert</string>
112 <string name="install_game_content_success_overwrite">%1$d erfolgreich überschrieben</string>
102 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> 113 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
114 <string name="manage_yuzu_data">yuzu-Daten Verwalten</string>
115 <string name="share_save_file">Speicherdaten teilen</string>
116 <string name="game_folders">Spiele-Ordner</string>
117 <string name="add_game_folder">Spiele-Ordner hinzufügen</string>
118 <string name="applets_error_firmware">Firmware nicht installiert</string>
103 <!-- About screen strings --> 119 <!-- About screen strings -->
104 <string name="gaia_is_not_real">Gaia ist nicht real</string> 120 <string name="gaia_is_not_real">Gaia ist nicht real</string>
105 <string name="copied_to_clipboard">In die Zwischenablage kopiert</string> 121 <string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
@@ -110,6 +126,10 @@
110 <string name="licenses_description">Projekte, die yuzu für Android möglich machen </string> 126 <string name="licenses_description">Projekte, die yuzu für Android möglich machen </string>
111 <string name="build">Build</string> 127 <string name="build">Build</string>
112 <string name="user_data">Nutzerdaten</string> 128 <string name="user_data">Nutzerdaten</string>
129 <string name="importing_user_data">Importiere Nutzerdaten...</string>
130 <string name="import_user_data">Nutzerdaten importieren</string>
131 <string name="user_data_export_success">Nutzerdaten erfolgreich exportiert</string>
132 <string name="user_data_import_success">Nutzerdaten erfolgreich importiert</string>
113 <string name="user_data_export_cancelled">Export abgebrochen</string> 133 <string name="user_data_export_cancelled">Export abgebrochen</string>
114 <string name="support_link">https://discord.gg/u77vRWY</string> 134 <string name="support_link">https://discord.gg/u77vRWY</string>
115 <string name="website_link">https://yuzu-emu.org/</string> 135 <string name="website_link">https://yuzu-emu.org/</string>
@@ -137,7 +157,7 @@
137 <string name="cpu_accuracy">CPU-Genauigkeit</string> 157 <string name="cpu_accuracy">CPU-Genauigkeit</string>
138 <!-- System settings strings --> 158 <!-- System settings strings -->
139 <string name="use_docked_mode">Gedockter Modus</string> 159 <string name="use_docked_mode">Gedockter Modus</string>
140 <string name="use_docked_mode_description">Der Docked Modus erhöht die Auflösung, verringert die aber die Leistung. Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die Leistung.</string> 160 <string name="use_docked_mode_description">Der Gedockte-Modus erhöht die Auflösung, verringert aber die Leistung. Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die Leistung.</string>
141 <string name="emulated_region">Emulierte Region</string> 161 <string name="emulated_region">Emulierte Region</string>
142 <string name="emulated_language">Emulierte Sprache</string> 162 <string name="emulated_language">Emulierte Sprache</string>
143 <string name="select_rtc_date">RTC-Datum auswählen</string> 163 <string name="select_rtc_date">RTC-Datum auswählen</string>
@@ -145,10 +165,12 @@
145 <string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string> 165 <string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string>
146 <!-- Graphics settings strings --> 166 <!-- Graphics settings strings -->
147 <string name="renderer_accuracy">Genauigkeitsstufe</string> 167 <string name="renderer_accuracy">Genauigkeitsstufe</string>
168 <string name="renderer_resolution">Auflösung (Mobil/Gedockt)</string>
148 <string name="renderer_vsync">VSync-Modus</string> 169 <string name="renderer_vsync">VSync-Modus</string>
149 <string name="renderer_screen_layout">Orientierung</string> 170 <string name="renderer_screen_layout">Orientierung</string>
150 <string name="renderer_aspect_ratio">Seitenverhältnis</string> 171 <string name="renderer_aspect_ratio">Seitenverhältnis</string>
151 <string name="renderer_scaling_filter">Fensteranpassungsfilter</string> 172 <string name="renderer_scaling_filter">Fensteranpassungsfilter</string>
173 <string name="renderer_anti_aliasing">Kantenglättung</string>
152 <string name="renderer_force_max_clock">Maximale Taktfrequenz erzwingen (nur Adreno)</string> 174 <string name="renderer_force_max_clock">Maximale Taktfrequenz erzwingen (nur Adreno)</string>
153 <string name="renderer_force_max_clock_description">Erzwingt den Betrieb der GPU mit der maximal möglichen Taktfrequenz (Temperaturbeschränkungen werden weiterhin angewendet).</string> 175 <string name="renderer_force_max_clock_description">Erzwingt den Betrieb der GPU mit der maximal möglichen Taktfrequenz (Temperaturbeschränkungen werden weiterhin angewendet).</string>
154 <string name="renderer_asynchronous_shaders">Asynchrone Shader nutzen</string> 176 <string name="renderer_asynchronous_shaders">Asynchrone Shader nutzen</string>
@@ -168,9 +190,12 @@
168 <string name="error_saving">Fehler beim Speichern von %1$s.ini: %2$s</string> 190 <string name="error_saving">Fehler beim Speichern von %1$s.ini: %2$s</string>
169 <string name="unimplemented_menu">Unimplementiertes Menü</string> 191 <string name="unimplemented_menu">Unimplementiertes Menü</string>
170 <string name="loading">Lädt...</string> 192 <string name="loading">Lädt...</string>
193 <string name="shutting_down">Beendet...</string>
171 <string name="reset_setting_confirmation">Möchtest du diese Einstellung auf den Standardwert zurücksetzen?</string> 194 <string name="reset_setting_confirmation">Möchtest du diese Einstellung auf den Standardwert zurücksetzen?</string>
172 <string name="reset_to_default">Auf Standard zurücksetzen</string> 195 <string name="reset_to_default">Auf Standard zurücksetzen</string>
196 <string name="reset_to_default_description">Setzt alle erweiterten Einstellungen zurück</string>
173 <string name="reset_all_settings">Alle Einstellungen zurücksetzen?</string> 197 <string name="reset_all_settings">Alle Einstellungen zurücksetzen?</string>
198 <string name="reset_all_settings_description">Alle erweiterten Einstellungen werden auf ihren Standardwert zurückgesetzt. Dies kann nicht rückgängig gemacht werden.</string>
174 <string name="settings_reset">Einstellungen zurückgesetzt</string> 199 <string name="settings_reset">Einstellungen zurückgesetzt</string>
175 <string name="close">Schließen</string> 200 <string name="close">Schließen</string>
176 <string name="learn_more">Mehr erfahren</string> 201 <string name="learn_more">Mehr erfahren</string>
@@ -182,14 +207,20 @@
182 <string name="export_failed">Export fehlgeschlagen</string> 207 <string name="export_failed">Export fehlgeschlagen</string>
183 <string name="import_failed">Import fehlgeschlagen</string> 208 <string name="import_failed">Import fehlgeschlagen</string>
184 <string name="cancelling">Abbrechen</string> 209 <string name="cancelling">Abbrechen</string>
185 210 <string name="install">Installieren</string>
211 <string name="delete">Löschen</string>
212 <string name="edit">Bearbeiten</string>
213 <string name="export_success">Erfolgreich exportiert</string>
214 <string name="start">Start</string>
215 <string name="clear">Löschen</string>
216 <string name="custom">Benutzerdefiniert</string>
186 <!-- GPU driver installation --> 217 <!-- GPU driver installation -->
187 <string name="select_gpu_driver">GPU-Treiber auswählen</string> 218 <string name="select_gpu_driver">GPU-Treiber auswählen</string>
188 <string name="select_gpu_driver_title">Möchtest du deinen aktuellen GPU-Treiber ersetzen?</string> 219 <string name="select_gpu_driver_title">Möchtest du deinen aktuellen GPU-Treiber ersetzen?</string>
189 <string name="select_gpu_driver_install">Installieren</string> 220 <string name="select_gpu_driver_install">Installieren</string>
190 <string name="select_gpu_driver_default">Standard</string> 221 <string name="select_gpu_driver_default">Standard</string>
191 <string name="select_gpu_driver_use_default">Standard GPU-Treiber wird verwendet</string> 222 <string name="select_gpu_driver_use_default">Standard GPU-Treiber wird verwendet</string>
192 <string name="select_gpu_driver_error">Ungültiger Treiber ausgewählt, Standard-Treiber wird verwendet!</string> 223 <string name="driver_already_installed">Treiber bereits installiert</string>
193 <string name="system_gpu_driver">System GPU-Treiber</string> 224 <string name="system_gpu_driver">System GPU-Treiber</string>
194 <string name="installing_driver">Treiber wird installiert...</string> 225 <string name="installing_driver">Treiber wird installiert...</string>
195 226
@@ -197,11 +228,37 @@
197 <string name="preferences_settings">Einstellungen</string> 228 <string name="preferences_settings">Einstellungen</string>
198 <string name="preferences_general">Allgemein</string> 229 <string name="preferences_general">Allgemein</string>
199 <string name="preferences_system">System</string> 230 <string name="preferences_system">System</string>
231 <string name="preferences_system_description">Gedockter Modus, Region, Sprache</string>
200 <string name="preferences_graphics">Grafik</string> 232 <string name="preferences_graphics">Grafik</string>
233 <string name="preferences_graphics_description">Genauigkeitsstufe, Auflösung, Shader-Cache</string>
201 <string name="preferences_audio">Audio</string> 234 <string name="preferences_audio">Audio</string>
235 <string name="preferences_audio_description">Ausgabe-Engine, Lautstärke</string>
202 <string name="preferences_theme">Theme und Farbe</string> 236 <string name="preferences_theme">Theme und Farbe</string>
203 <string name="preferences_debug">Debug</string> 237 <string name="preferences_debug">Debug</string>
204 238 <!-- Game properties -->
239 <string name="info">Info</string>
240 <string name="info_description">Programm-ID, Entwickler, Version</string>
241 <string name="per_game_settings">Spieleinstellungen</string>
242 <string name="per_game_settings_description">Einstellungen für dieses Spiel ändern</string>
243 <string name="path">Pfad</string>
244 <string name="program_id">Programm-ID</string>
245 <string name="developer">Entwickler</string>
246 <string name="version">Version</string>
247 <string name="copy_details">Details kopieren</string>
248 <string name="add_ons">Add-ons</string>
249 <string name="add_ons_description">Mods, Updates und DLC aktivieren oder deaktivieren</string>
250 <string name="clear_shader_cache">Shader-Cache löschen</string>
251 <string name="clear_shader_cache_description">Löscht alle für dieses Spiel erstellten Shader</string>
252 <string name="cleared_shaders_successfully">Shader erfolgreich gelöscht</string>
253 <string name="addons_game">Add-ons: %1$s</string>
254 <string name="save_data">Speicherdaten</string>
255 <string name="save_data_description">Importiert oder exportiert Speicherdaten für dieses Spiel</string>
256 <string name="delete_save_data">Speicherdaten löschen</string>
257 <string name="delete_save_data_description">Löscht alle Speicherdaten für dieses Spiel</string>
258 <string name="delete_save_data_warning_description">Das löscht unwiederbringlich alle Speicherdaten für dieses Spiel. Wirklich fortfahren?</string>
259 <string name="save_data_deleted_successfully">Speicherdaten erfolgreich gelöscht</string>
260 <string name="invalid_directory">Ungültiges Verzeichnis</string>
261 <string name="addon_installed_successfully">Add-on erfolgreich installiert</string>
205 <!-- ROM loading errors --> 262 <!-- ROM loading errors -->
206 <string name="loader_error_encrypted">Das ROM ist verschlüsselt</string> 263 <string name="loader_error_encrypted">Das ROM ist verschlüsselt</string>
207 <string name="loader_error_encrypted_keys_description"><![CDATA[Bitte stelle sicher dass die <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> Datei installiert ist, damit Spiele entschlüsselt werden können.]]></string> 264 <string name="loader_error_encrypted_keys_description"><![CDATA[Bitte stelle sicher dass die <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> Datei installiert ist, damit Spiele entschlüsselt werden können.]]></string>
@@ -220,7 +277,10 @@
220 <string name="emulation_control_opacity">Transparenz</string> 277 <string name="emulation_control_opacity">Transparenz</string>
221 <string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string> 278 <string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string>
222 <string name="emulation_touch_overlay_edit">Overlay bearbeiten</string> 279 <string name="emulation_touch_overlay_edit">Overlay bearbeiten</string>
280 <string name="emulation_pause">Emulation pausieren</string>
281 <string name="emulation_unpause">Emulation fortsetzen</string>
223 <string name="emulation_input_overlay">Overlay-Optionen</string> 282 <string name="emulation_input_overlay">Overlay-Optionen</string>
283 <string name="touchscreen">Touchscreen</string>
224 284
225 <string name="load_settings">Lade Einstellungen...</string> 285 <string name="load_settings">Lade Einstellungen...</string>
226 286
@@ -248,6 +308,7 @@
248 308
249 <!-- Memory Sizes --> 309 <!-- Memory Sizes -->
250 <string name="memory_byte">Byte</string> 310 <string name="memory_byte">Byte</string>
311 <string name="memory_byte_shorthand">B</string>
251 <string name="memory_kilobyte">KB</string> 312 <string name="memory_kilobyte">KB</string>
252 <string name="memory_megabyte">MB</string> 313 <string name="memory_megabyte">MB</string>
253 <string name="memory_gigabyte">GB</string> 314 <string name="memory_gigabyte">GB</string>
@@ -291,9 +352,10 @@
291 <string name="anti_aliasing_fxaa">FXAA</string> 352 <string name="anti_aliasing_fxaa">FXAA</string>
292 <string name="anti_aliasing_smaa">SMAA</string> 353 <string name="anti_aliasing_smaa">SMAA</string>
293 354
294 <string name="screen_layout_portrait">Portrait</string> 355 <!-- Screen Layouts -->
295 <string name="screen_layout_auto">Auto</string> 356 <string name="screen_layout_auto">Auto</string>
296 357 <string name="screen_layout_landscape">Horizontal</string>
358 <string name="screen_layout_portrait">Vertikal</string>
297 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
298 <string name="ratio_default">Standard (16:9)</string> 360 <string name="ratio_default">Standard (16:9)</string>
299 <string name="ratio_force_four_three">4:3 erzwingen</string> 361 <string name="ratio_force_four_three">4:3 erzwingen</string>
@@ -318,22 +380,27 @@
318 <string name="building_shaders">Shader werden erstellt</string> 380 <string name="building_shaders">Shader werden erstellt</string>
319 381
320 <!-- Theme options --> 382 <!-- Theme options -->
321 <string name="change_app_theme">App-Thema ändern</string> 383 <string name="change_app_theme">Theme</string>
322 <string name="theme_default">Standard</string> 384 <string name="theme_default">Standard</string>
323 <string name="theme_material_you">Material You</string> 385 <string name="theme_material_you">Material You</string>
324 386
325 <!-- Theme Modes --> 387 <!-- Theme Modes -->
326 <string name="change_theme_mode">Themen-Modus ändern</string> 388 <string name="change_theme_mode">Design</string>
327 <string name="theme_mode_follow_system">System folgen</string> 389 <string name="theme_mode_follow_system">System folgen</string>
328 <string name="theme_mode_light">Hell</string> 390 <string name="theme_mode_light">Hell</string>
329 <string name="theme_mode_dark">Dunkel</string> 391 <string name="theme_mode_dark">Dunkel</string>
330 392
331 <!-- Audio output engines -->
332 <string name="cubeb">cubeb</string> 393 <string name="cubeb">cubeb</string>
333 394
395 <!-- Anisotropic filtering options -->
396 <string name="multiplier_two">2x</string>
397 <string name="multiplier_four">4x</string>
398 <string name="multiplier_eight">8x</string>
399 <string name="multiplier_sixteen">16x</string>
400
334 <!-- Black backgrounds theme --> 401 <!-- Black backgrounds theme -->
335 <string name="use_black_backgrounds">Schwarze Hintergründe</string> 402 <string name="use_black_backgrounds">Schwarze Hintergründe</string>
336 <string name="use_black_backgrounds_description">Bei Verwendung des dunklen Themes, schwarze Hintergründe verwenden.</string> 403 <string name="use_black_backgrounds_description">Bei Verwendung des dunklen Designs, schwarze Hintergründe verwenden.</string>
337 404
338 <!-- Picture-In-Picture --> 405 <!-- Picture-In-Picture -->
339 <string name="picture_in_picture">Bild im Bild</string> 406 <string name="picture_in_picture">Bild im Bild</string>
diff --git a/src/android/app/src/main/res/values-es/strings.xml b/src/android/app/src/main/res/values-es/strings.xml
index 103ac6e65..c3825710b 100644
--- a/src/android/app/src/main/res/values-es/strings.xml
+++ b/src/android/app/src/main/res/values-es/strings.xml
@@ -4,7 +4,7 @@
4 <string name="app_disclaimer">Este software ejecuta juegos para la videoconsola Nintendo Switch. Los videojuegos o claves no vienen incluidos.&lt;br /&gt;&lt;br /&gt;Antes de empezar, por favor, localice el archivo <![CDATA[<b> prod.keys </b>]]>en el almacenamiento de su dispositivo..&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Saber más</a>]]></string> 4 <string name="app_disclaimer">Este software ejecuta juegos para la videoconsola Nintendo Switch. Los videojuegos o claves no vienen incluidos.&lt;br /&gt;&lt;br /&gt;Antes de empezar, por favor, localice el archivo <![CDATA[<b> prod.keys </b>]]>en el almacenamiento de su dispositivo..&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Saber más</a>]]></string>
5 <string name="emulation_notification_channel_name">Emulación activa</string> 5 <string name="emulation_notification_channel_name">Emulación activa</string>
6 <string name="emulation_notification_channel_description">Muestra una notificación persistente cuando la emulación está activa.</string> 6 <string name="emulation_notification_channel_description">Muestra una notificación persistente cuando la emulación está activa.</string>
7 <string name="emulation_notification_running">yuzu esta ejecutándose</string> 7 <string name="emulation_notification_running">yuzu está ejecutándose</string>
8 <string name="notice_notification_channel_name">Avisos y errores</string> 8 <string name="notice_notification_channel_name">Avisos y errores</string>
9 <string name="notice_notification_channel_description">Mostrar notificaciones cuándo algo vaya mal.</string> 9 <string name="notice_notification_channel_description">Mostrar notificaciones cuándo algo vaya mal.</string>
10 <string name="notification_permission_not_granted">¡Permisos de notificación no concedidos!</string> 10 <string name="notification_permission_not_granted">¡Permisos de notificación no concedidos!</string>
@@ -34,6 +34,7 @@
34 <string name="empty_gamelist">No se ha encontrado ningún archivo o aún no se ha seleccionado ningún directorio de juegos.</string> 34 <string name="empty_gamelist">No se ha encontrado ningún archivo o aún no se ha seleccionado ningún directorio de juegos.</string>
35 <string name="search_and_filter_games">Busca y filtra juegos</string> 35 <string name="search_and_filter_games">Busca y filtra juegos</string>
36 <string name="select_games_folder">Seleccionar carpeta de juegos</string> 36 <string name="select_games_folder">Seleccionar carpeta de juegos</string>
37 <string name="manage_game_folders">Gestionar carpetas de juegos</string>
37 <string name="select_games_folder_description">Permite que yuzu llene la lista de juegos</string> 38 <string name="select_games_folder_description">Permite que yuzu llene la lista de juegos</string>
38 <string name="add_games_warning">¿Omitir la selección de la carpeta de juegos?</string> 39 <string name="add_games_warning">¿Omitir la selección de la carpeta de juegos?</string>
39 <string name="add_games_warning_description">No se mostrará ningún juego si no se ha seleccionado una carpeta de juegos.</string> 40 <string name="add_games_warning_description">No se mostrará ningún juego si no se ha seleccionado una carpeta de juegos.</string>
@@ -44,23 +45,23 @@
44 <string name="install_prod_keys">Instalar prod.keys</string> 45 <string name="install_prod_keys">Instalar prod.keys</string>
45 <string name="install_prod_keys_description">Requerido para descifrar juegos</string> 46 <string name="install_prod_keys_description">Requerido para descifrar juegos</string>
46 <string name="install_prod_keys_warning">¿Omitir agregar claves?</string> 47 <string name="install_prod_keys_warning">¿Omitir agregar claves?</string>
47 <string name="install_prod_keys_warning_description">Se requieren claves válidas para emular juegos. Solo las aplicaciones homebrew funcionarán si continúas.</string> 48 <string name="install_prod_keys_warning_description">Se requieren claves válidas para emular juegos. Solo las aplicaciones homebrew funcionarán si continúas.</string>
48 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> 49 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
49 <string name="notifications">Notificaciones</string> 50 <string name="notifications">Notificaciones</string>
50 <string name="notifications_description">Otorgue el permiso de notificación con el botón de abajo.</string> 51 <string name="notifications_description">Otorga el permiso de notificación con el botón de abajo.</string>
51 <string name="give_permission">Conceder permiso</string> 52 <string name="give_permission">Conceder permiso</string>
52 <string name="notification_warning">¿Omitir conceder el permiso de notificación?</string> 53 <string name="notification_warning">¿Omitir conceder el permiso de notificación?</string>
53 <string name="notification_warning_description">yuzu no podrá notificarte información importante.</string> 54 <string name="notification_warning_description">yuzu no podrá notificarte información importante.</string>
54 <string name="permission_denied">Permiso denegado</string> 55 <string name="permission_denied">Permiso denegado</string>
55 <string name="permission_denied_description">Negó este permiso demasiadas veces y ahora debe otorgarlo manualmente en la configuración del sistema.</string> 56 <string name="permission_denied_description">Se ha denegado este permiso demasiadas veces y ahora debes otorgarlo de forma manual en la configuración del sistema.</string>
56 <string name="about">Acerca de</string> 57 <string name="about">Acerca de</string>
57 <string name="about_description">Versión, créditos y más</string> 58 <string name="about_description">Versión, créditos y más</string>
58 <string name="warning_help">Ayuda</string> 59 <string name="warning_help">Ayuda</string>
59 <string name="warning_skip">Siguiente</string> 60 <string name="warning_skip">Siguiente</string>
60 <string name="warning_cancel">Cancelar</string> 61 <string name="warning_cancel">Cancelar</string>
61 <string name="install_amiibo_keys">Instalar clave de Amiiboo</string> 62 <string name="install_amiibo_keys">Instalar claves de Amiibo</string>
62 <string name="install_amiibo_keys_description">Necesario para usar Amiibo en el juego</string> 63 <string name="install_amiibo_keys_description">Necesario para usar Amiibos en el juego</string>
63 <string name="invalid_keys_file">Archivo de claves seleccionado inválido</string> 64 <string name="invalid_keys_file">Archivo de claves seleccionado no válido</string>
64 <string name="install_keys_success">Claves instaladas correctamente</string> 65 <string name="install_keys_success">Claves instaladas correctamente</string>
65 <string name="reading_keys_failure">Error al leer las claves de cifrado</string> 66 <string name="reading_keys_failure">Error al leer las claves de cifrado</string>
66 <string name="install_prod_keys_failure_extension_description">Compruebe que el archivo de claves tenga una extensión .keys y pruebe otra vez.</string> 67 <string name="install_prod_keys_failure_extension_description">Compruebe que el archivo de claves tenga una extensión .keys y pruebe otra vez.</string>
@@ -68,6 +69,7 @@
68 <string name="invalid_keys_error">Claves de cifrado no válidas</string> 69 <string name="invalid_keys_error">Claves de cifrado no válidas</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string> 71 <string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string>
72 <string name="gpu_driver_manager">Explorador de drivers de GPU</string>
71 <string name="install_gpu_driver">Instalar driver de GPU</string> 73 <string name="install_gpu_driver">Instalar driver de GPU</string>
72 <string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string> 74 <string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string>
73 <string name="advanced_settings">Opciones avanzadas</string> 75 <string name="advanced_settings">Opciones avanzadas</string>
@@ -85,7 +87,11 @@
85 <string name="notification_no_directory_link_description">Por favor, busque la carpeta user con el panel lateral del explorador de archivos de forma manual.</string> 87 <string name="notification_no_directory_link_description">Por favor, busque la carpeta user con el panel lateral del explorador de archivos de forma manual.</string>
86 <string name="manage_save_data">Administrar datos de guardado</string> 88 <string name="manage_save_data">Administrar datos de guardado</string>
87 <string name="manage_save_data_description">Guardar los datos encontrados. Por favor, seleccione una opción de abajo.</string> 89 <string name="manage_save_data_description">Guardar los datos encontrados. Por favor, seleccione una opción de abajo.</string>
90 <string name="import_save_warning">Importar datos de guardado</string>
91 <string name="import_save_warning_description">Ésto sobreescribirá todos los datos de guardado existentes con el archivo proporcionado. ¿Está seguro de querer continuar?</string>
88 <string name="import_export_saves_description">Importar o exportar archivos de guardado</string> 92 <string name="import_export_saves_description">Importar o exportar archivos de guardado</string>
93 <string name="save_files_importing">Importando archivos de guardado...</string>
94 <string name="save_files_exporting">Exportando archivos de guardado...</string>
89 <string name="save_file_imported_success">Importado correctamente</string> 95 <string name="save_file_imported_success">Importado correctamente</string>
90 <string name="save_file_invalid_zip_structure">Estructura del directorio de guardado no válido</string> 96 <string name="save_file_invalid_zip_structure">Estructura del directorio de guardado no válido</string>
91 <string name="save_file_invalid_zip_structure_description">El nombre de la primera subcarpeta debe ser el Title ID del juego.</string> 97 <string name="save_file_invalid_zip_structure_description">El nombre de la primera subcarpeta debe ser el Title ID del juego.</string>
@@ -95,7 +101,7 @@
95 <string name="install_firmware_description">El firmware debe estar en un archivo ZIP y es necesario para ejecutar algunos juegos</string> 101 <string name="install_firmware_description">El firmware debe estar en un archivo ZIP y es necesario para ejecutar algunos juegos</string>
96 <string name="firmware_installing">Instalando firmware</string> 102 <string name="firmware_installing">Instalando firmware</string>
97 <string name="firmware_installed_success">Firmware instalado con éxito</string> 103 <string name="firmware_installed_success">Firmware instalado con éxito</string>
98 <string name="firmware_installed_failure">Falló la instalación de firmware</string> 104 <string name="firmware_installed_failure">Error en la instalación de firmware</string>
99 <string name="firmware_installed_failure_description">Asegúrese de que los archivos nca del firmware estén en la raíz del zip e inténtelo de nuevo.</string> 105 <string name="firmware_installed_failure_description">Asegúrese de que los archivos nca del firmware estén en la raíz del zip e inténtelo de nuevo.</string>
100 <string name="share_log">Compartir registros de depuración</string> 106 <string name="share_log">Compartir registros de depuración</string>
101 <string name="share_log_description">Comparta el archivo de registro de yuzu para depurar problemas</string> 107 <string name="share_log_description">Comparta el archivo de registro de yuzu para depurar problemas</string>
@@ -115,9 +121,43 @@
115 <string name="custom_driver_not_supported">Drivers personalizados no soportados</string> 121 <string name="custom_driver_not_supported">Drivers personalizados no soportados</string>
116 <string name="custom_driver_not_supported_description">En estos momentos, la carga de drivers personalizados no está disponible para este dispositivo..\n¡Comprueba esta opción en el futuro para ver si ya está añadido el soporte a ese dispositivo!</string> 122 <string name="custom_driver_not_supported_description">En estos momentos, la carga de drivers personalizados no está disponible para este dispositivo..\n¡Comprueba esta opción en el futuro para ver si ya está añadido el soporte a ese dispositivo!</string>
117 <string name="manage_yuzu_data">Administrar datos de yuzu</string> 123 <string name="manage_yuzu_data">Administrar datos de yuzu</string>
118 <string name="manage_yuzu_data_description">Importa/exporta el firmware, las keys, los datos de usuario, ¡y más!</string> 124 <string name="manage_yuzu_data_description">Importa/exporta el firmware, las claves, los datos de usuario, ¡y más!</string>
119 <string name="share_save_file">Compartir archivo de guardado</string> 125 <string name="share_save_file">Compartir archivo de guardado</string>
120 <string name="export_save_failed">La exportación del guardado falló</string> 126 <string name="export_save_failed">Error al exportar el archivo de guardado</string>
127 <string name="game_folders">Carpetas de juegos</string>
128 <string name="deep_scan">Escaneo recursivo </string>
129 <string name="add_game_folder">Añadir carpeta con juegos</string>
130 <string name="folder_already_added">¡Está carpeta ya se había añadido!</string>
131 <string name="game_folder_properties">Propiedades de la carpeta de juegos</string>
132 <plurals name="saves_import_failed">
133 <item quantity="one">No se ha podido importar %d archivo de guardado.</item>
134 <item quantity="many">No se han podido importar %d archivos de guardado.</item>
135 <item quantity="other">No se han podido importar %d archivos de guardado.</item>
136 </plurals>
137 <plurals name="saves_import_success">
138 <item quantity="one">%d archivo de guardado importado con éxito.</item>
139 <item quantity="many">%d archivos de guardado importados con éxito.</item>
140 <item quantity="other">%d archivos de guardado importados con éxito.</item>
141 </plurals>
142 <string name="no_save_data_found">No hay archivos de guardado</string>
143
144 <!-- Applet launcher strings -->
145 <string name="applets">Ejecutador de applet</string>
146 <string name="applets_description">Ejecutar applets de sistema usando el firmware instalado</string>
147 <string name="applets_error_firmware">Firmware no instalado</string>
148 <string name="applets_error_applet">Applet no disponible</string>
149 <string name="applets_error_description"><![CDATA[Asegúrese de que el archivo<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> y el <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> estén instalados e inténtelo de nuevo.]]></string>
150 <string name="album_applet">Ãlbum</string>
151 <string name="album_applet_description">Ver las imágenes que están en la carpeta \"screenshots\" del usuario con el visor de fotos del sistema</string>
152 <string name="mii_edit_applet">Editor de Mii</string>
153 <string name="mii_edit_applet_description">Mira y edita Mii con el editor del sistema</string>
154 <string name="cabinet_applet">Cabinet</string>
155 <string name="cabinet_applet_description">Edita y borra los datos guardado del amiibo</string>
156 <string name="cabinet_launcher">Ejecutador de Cabinet</string>
157 <string name="cabinet_nickname_and_owner">Configuración del apodo y propietario</string>
158 <string name="cabinet_game_data_eraser">Borrador de datos de juego</string>
159 <string name="cabinet_restorer">Restaurador</string>
160 <string name="cabinet_formatter">Formateador</string>
121 161
122 <!-- About screen strings --> 162 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia no es real</string> 163 <string name="gaia_is_not_real">Gaia no es real</string>
@@ -161,6 +201,7 @@
161 <string name="frame_limit_enable_description">Limita la velocidad de emulación a un porcentaje específico de la velocidad normal.</string> 201 <string name="frame_limit_enable_description">Limita la velocidad de emulación a un porcentaje específico de la velocidad normal.</string>
162 <string name="frame_limit_slider">Limitar porcentaje de velocidad</string> 202 <string name="frame_limit_slider">Limitar porcentaje de velocidad</string>
163 <string name="frame_limit_slider_description">Especifica el porcentaje para limitar la velocidad de emulación. 100% es la velocidad normal. Valores más altos o bajos incrementarán o disminuirán el límite de velocidad.</string> 203 <string name="frame_limit_slider_description">Especifica el porcentaje para limitar la velocidad de emulación. 100% es la velocidad normal. Valores más altos o bajos incrementarán o disminuirán el límite de velocidad.</string>
204 <string name="cpu_backend">Motor de CPU</string>
164 <string name="cpu_accuracy">Precisión de CPU</string> 205 <string name="cpu_accuracy">Precisión de CPU</string>
165 <string name="value_with_units">%1$s%2$s</string> 206 <string name="value_with_units">%1$s%2$s</string>
166 207
@@ -186,11 +227,13 @@
186 <string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string> 227 <string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string>
187 <string name="renderer_force_max_clock_description">Fuerza a la GPU a ejecutarse a la velocidad máxima de reloj posible (se seguirán aplicando restricciones térmicas).</string> 228 <string name="renderer_force_max_clock_description">Fuerza a la GPU a ejecutarse a la velocidad máxima de reloj posible (se seguirán aplicando restricciones térmicas).</string>
188 <string name="renderer_asynchronous_shaders">Usar shaders asíncronos</string> 229 <string name="renderer_asynchronous_shaders">Usar shaders asíncronos</string>
189 <string name="renderer_asynchronous_shaders_description">Compila shaders de manera asíncrona, reduciendo los parones, pero puede introducir fallos.</string> 230 <string name="renderer_asynchronous_shaders_description">Compila shaders de manera asíncrona, reduce los parones pero puede introducir fallos.</string>
190 <string name="renderer_reactive_flushing">Usar limpieza reactiva</string> 231 <string name="renderer_reactive_flushing">Usar limpieza reactiva</string>
191 <string name="renderer_reactive_flushing_description">Mejora la precisión de renderizado en algunos juegos, pero reduce el rendimiento.</string> 232 <string name="renderer_reactive_flushing_description">Mejora la precisión de renderizado en algunos juegos, pero reduce el rendimiento.</string>
192 <string name="use_disk_shader_cache">Caché de shaders en disco</string> 233 <string name="use_disk_shader_cache">Caché de shaders en disco</string>
193 <string name="use_disk_shader_cache_description">Reduce los parones almacenando y cargando shaders generados.</string> 234 <string name="use_disk_shader_cache_description">Reduce los parones almacenando y cargando shaders generados.</string>
235 <string name="anisotropic_filtering">Filtrado anisotrópico</string>
236 <string name="anisotropic_filtering_description">Mejora la calidad de las texturas al ser observadas desde ángulos oblicuos</string>
194 237
195 <!-- Debug settings strings --> 238 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string> 239 <string name="cpu">CPU</string>
@@ -217,6 +260,7 @@
217 <string name="shutting_down">Saliendo...</string> 260 <string name="shutting_down">Saliendo...</string>
218 <string name="reset_setting_confirmation">¿Desea restablecer esta configuración a su valor predeterminado?</string> 261 <string name="reset_setting_confirmation">¿Desea restablecer esta configuración a su valor predeterminado?</string>
219 <string name="reset_to_default">Restablecer a predeterminado</string> 262 <string name="reset_to_default">Restablecer a predeterminado</string>
263 <string name="reset_to_default_description">Reinicia todos los ajustes avanzados</string>
220 <string name="reset_all_settings">¿Restablecer todas las configuraciones?</string> 264 <string name="reset_all_settings">¿Restablecer todas las configuraciones?</string>
221 <string name="reset_all_settings_description">Todas las opciones avanzadas se restablecerán a su configuración predeterminada. Esta acción no se puede deshacer.</string> 265 <string name="reset_all_settings_description">Todas las opciones avanzadas se restablecerán a su configuración predeterminada. Esta acción no se puede deshacer.</string>
222 <string name="settings_reset">Reiniciar la configuracion</string> 266 <string name="settings_reset">Reiniciar la configuracion</string>
@@ -230,14 +274,24 @@
230 <string name="export_failed">La exportación falló</string> 274 <string name="export_failed">La exportación falló</string>
231 <string name="import_failed">La importación falló</string> 275 <string name="import_failed">La importación falló</string>
232 <string name="cancelling">Cancelando</string> 276 <string name="cancelling">Cancelando</string>
233 277 <string name="install">Instalar</string>
278 <string name="delete">Borrar</string>
279 <string name="edit">Editar</string>
280 <string name="export_success">Exportado correctamente</string>
281 <string name="start">Comenzar</string>
282 <string name="clear">Limpiar</string>
283 <string name="global">Global</string>
284 <string name="custom">Perzonalizado</string>
285 <string name="notice">Aviso</string>
286 <string name="import_complete">La importación se completó</string>
234 <!-- GPU driver installation --> 287 <!-- GPU driver installation -->
235 <string name="select_gpu_driver">Seleccionar driver GPU</string> 288 <string name="select_gpu_driver">Seleccionar driver GPU</string>
236 <string name="select_gpu_driver_title">¿Quiere reemplazar el driver de GPU actual?</string> 289 <string name="select_gpu_driver_title">¿Quiere reemplazar el driver de GPU actual?</string>
237 <string name="select_gpu_driver_install">Instalar</string> 290 <string name="select_gpu_driver_install">Instalar</string>
238 <string name="select_gpu_driver_default">Predeterminado</string> 291 <string name="select_gpu_driver_default">Predeterminado</string>
239 <string name="select_gpu_driver_use_default">Usando el driver de GPU por defecto </string> 292 <string name="select_gpu_driver_use_default">Usando el driver de GPU por defecto </string>
240 <string name="select_gpu_driver_error">¡Driver no válido, utilizando el predeterminado del sistema!</string> 293 <string name="select_gpu_driver_error">Driver no válido seleccionado</string>
294 <string name="driver_already_installed">Driver ya instalado</string>
241 <string name="system_gpu_driver">Driver GPU del sistema</string> 295 <string name="system_gpu_driver">Driver GPU del sistema</string>
242 <string name="installing_driver">Instalando driver...</string> 296 <string name="installing_driver">Instalando driver...</string>
243 297
@@ -245,11 +299,52 @@
245 <string name="preferences_settings">Ajustes</string> 299 <string name="preferences_settings">Ajustes</string>
246 <string name="preferences_general">General</string> 300 <string name="preferences_general">General</string>
247 <string name="preferences_system">Sistema</string> 301 <string name="preferences_system">Sistema</string>
302 <string name="preferences_system_description">Modo en Dock, región, idioma</string>
248 <string name="preferences_graphics">Gráficos</string> 303 <string name="preferences_graphics">Gráficos</string>
304 <string name="preferences_graphics_description">Nivel de precisión, resolución, caché de shaders</string>
249 <string name="preferences_audio">Audio</string> 305 <string name="preferences_audio">Audio</string>
306 <string name="preferences_audio_description">Motor de salida, volumen</string>
250 <string name="preferences_theme">Tema y color</string> 307 <string name="preferences_theme">Tema y color</string>
251 <string name="preferences_debug">Depuración</string> 308 <string name="preferences_debug">Depuración</string>
252 309 <string name="preferences_debug_description">CPU/GPU debug, API gráfica, fastMEM</string>
310
311 <!-- Game properties -->
312 <string name="info">Información</string>
313 <string name="info_description">ID de programa, desarrollador, versión</string>
314 <string name="per_game_settings">Configuración por juego</string>
315 <string name="per_game_settings_description">Editar opciones específicas para este juego</string>
316 <string name="launch_options">Ejecutar configuración</string>
317 <string name="path">Ruta</string>
318 <string name="program_id">ID de programa</string>
319 <string name="developer">Desarrollador</string>
320 <string name="version">Versión</string>
321 <string name="copy_details">Copiar detalles</string>
322 <string name="add_ons">Extras/Add-ons</string>
323 <string name="add_ons_description">Activa/desactiva mods, actualizaciones y DLC</string>
324 <string name="clear_shader_cache">Limpiar la caché de shaders</string>
325 <string name="clear_shader_cache_description">Elimina todos los shaders construidos mientras se jugaba al juego</string>
326 <string name="clear_shader_cache_warning_description">Experimentarás más parones mientras que la caché de shaders se regenera</string>
327 <string name="cleared_shaders_successfully">Shaders limpiados con éxito</string>
328 <string name="addons_game">Addons: %1$s</string>
329 <string name="save_data">Datos de guardado</string>
330 <string name="save_data_description">Controla los datos de guardado de este juego</string>
331 <string name="delete_save_data">Borrar datos de guardado</string>
332 <string name="delete_save_data_description">Elimina todos los datos de guardado de este juego</string>
333 <string name="delete_save_data_warning_description">Ésto elimina de manera permanente todos los datos de guardado de este juego. ¿Seguro que quieres continuar?</string>
334 <string name="save_data_deleted_successfully">Datos de guardado eliminados con éxito</string>
335 <string name="select_content_type">Tipo de contenido</string>
336 <string name="updates_and_dlc">Actualizaciones y DLC</string>
337 <string name="mods_and_cheats">Mods y trucos</string>
338 <string name="addon_notice">Aviso importante de addons</string>
339 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
340 <string name="addon_notice_description">Para instalar mods y trucos, debes seleccionar una carpeta que contiene los directorios cheats/, romfs/, o exefs/ . ¡No podemos confirmar si éstos serán compatibles con tu juego, así que ten cuidado!</string>
341 <string name="invalid_directory">Directorio no válido</string>
342 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
343 <string name="invalid_directory_description">Por favor, asegúrese de que el directorio que ha selecionado incluye las carpetas cheats/, romfs/, o exefs/ e inténtelo de nuevo.</string>
344 <string name="addon_installed_successfully">Addon instalado con éxito</string>
345 <string name="verifying_content">Verificando contenido...</string>
346 <string name="content_install_notice">Aviso importante de contenido</string>
347 <string name="content_install_notice_description">El contenido seleccionado no es de este juego.\n¿Instalar de todas maneras?</string>
253 <!-- ROM loading errors --> 348 <!-- ROM loading errors -->
254 <string name="loader_error_encrypted">Su ROM está encriptada</string> 349 <string name="loader_error_encrypted">Su ROM está encriptada</string>
255 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga las guías para redumpear<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartuchos de juegos</a> o <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">títulos instalados</a>.]]></string> 350 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga las guías para redumpear<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartuchos de juegos</a> o <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">títulos instalados</a>.]]></string>
@@ -277,6 +372,7 @@
277 <string name="emulation_pause">Pausar emulación</string> 372 <string name="emulation_pause">Pausar emulación</string>
278 <string name="emulation_unpause">Despausar emulación</string> 373 <string name="emulation_unpause">Despausar emulación</string>
279 <string name="emulation_input_overlay">Opciones de overlay</string> 374 <string name="emulation_input_overlay">Opciones de overlay</string>
375 <string name="touchscreen">Pantalla táctil</string>
280 376
281 <string name="load_settings">Cargando configuración...</string> 377 <string name="load_settings">Cargando configuración...</string>
282 378
@@ -308,6 +404,7 @@
308 404
309 <!-- Memory Sizes --> 405 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string> 406 <string name="memory_byte">Byte</string>
407 <string name="memory_byte_shorthand">B</string>
311 <string name="memory_kilobyte">KB</string> 408 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string> 409 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string> 410 <string name="memory_gigabyte">GB</string>
@@ -352,9 +449,13 @@
352 <string name="anti_aliasing_smaa">SMAA</string> 449 <string name="anti_aliasing_smaa">SMAA</string>
353 450
354 <!-- Screen Layouts --> 451 <!-- Screen Layouts -->
452 <string name="screen_layout_auto">Auto</string>
453 <string name="screen_layout_sensor_landscape">Sensor paisaje</string>
355 <string name="screen_layout_landscape">Paisaje</string> 454 <string name="screen_layout_landscape">Paisaje</string>
455 <string name="screen_layout_reverse_landscape">Paisaje inverso</string>
456 <string name="screen_layout_sensor_portrait">Sensor retrato</string>
356 <string name="screen_layout_portrait">Retrato</string> 457 <string name="screen_layout_portrait">Retrato</string>
357 <string name="screen_layout_auto">Auto</string> 458 <string name="screen_layout_reverse_portrait">Retrato inverso</string>
358 459
359 <!-- Aspect Ratios --> 460 <!-- Aspect Ratios -->
360 <string name="ratio_default">Predeterminado (16:9)</string> 461 <string name="ratio_default">Predeterminado (16:9)</string>
@@ -363,6 +464,10 @@
363 <string name="ratio_force_sixteen_ten">Forzar 16:10</string> 464 <string name="ratio_force_sixteen_ten">Forzar 16:10</string>
364 <string name="ratio_stretch">Ajustar a la ventana</string> 465 <string name="ratio_stretch">Ajustar a la ventana</string>
365 466
467 <!-- CPU Backend -->
468 <string name="cpu_backend_dynarmic">DynARMic (lento)</string>
469 <string name="cpu_backend_nce">Ejecución nativa de código (NCE)</string>
470
366 <!-- CPU Accuracy --> 471 <!-- CPU Accuracy -->
367 <string name="cpu_accuracy_accurate">Preciso</string> 472 <string name="cpu_accuracy_accurate">Preciso</string>
368 <string name="cpu_accuracy_unsafe">Impreciso</string> 473 <string name="cpu_accuracy_unsafe">Impreciso</string>
@@ -391,8 +496,15 @@
391 <string name="theme_mode_dark">Oscuro</string> 496 <string name="theme_mode_dark">Oscuro</string>
392 497
393 <!-- Audio output engines --> 498 <!-- Audio output engines -->
499 <string name="oboe">oboe</string>
394 <string name="cubeb">cubeb</string> 500 <string name="cubeb">cubeb</string>
395 501
502 <!-- Anisotropic filtering options -->
503 <string name="multiplier_two">x2</string>
504 <string name="multiplier_four">x4</string>
505 <string name="multiplier_eight">x8</string>
506 <string name="multiplier_sixteen">x16</string>
507
396 <!-- Black backgrounds theme --> 508 <!-- Black backgrounds theme -->
397 <string name="use_black_backgrounds">Fondos oscuros</string> 509 <string name="use_black_backgrounds">Fondos oscuros</string>
398 <string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string> 510 <string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string>
diff --git a/src/android/app/src/main/res/values-fr/strings.xml b/src/android/app/src/main/res/values-fr/strings.xml
index 5a827c50b..667fe33cb 100644
--- a/src/android/app/src/main/res/values-fr/strings.xml
+++ b/src/android/app/src/main/res/values-fr/strings.xml
@@ -34,6 +34,7 @@
34 <string name="empty_gamelist">Aucun fichier n\'a été trouvé ou aucun répertoire de jeu n\'a encore été sélectionné.</string> 34 <string name="empty_gamelist">Aucun fichier n\'a été trouvé ou aucun répertoire de jeu n\'a encore été sélectionné.</string>
35 <string name="search_and_filter_games">Rechercher et filtrer les jeux</string> 35 <string name="search_and_filter_games">Rechercher et filtrer les jeux</string>
36 <string name="select_games_folder">Sélectionner le dossier des jeux</string> 36 <string name="select_games_folder">Sélectionner le dossier des jeux</string>
37 <string name="manage_game_folders">Gérer les dossiers de jeux</string>
37 <string name="select_games_folder_description">Permet à yuzu de remplir la liste des jeux</string> 38 <string name="select_games_folder_description">Permet à yuzu de remplir la liste des jeux</string>
38 <string name="add_games_warning">Ne pas sélectionner le dossier des jeux ?</string> 39 <string name="add_games_warning">Ne pas sélectionner le dossier des jeux ?</string>
39 <string name="add_games_warning_description">Les jeux ne seront pas affichés dans la liste des jeux si aucun dossier n\'est sélectionné.</string> 40 <string name="add_games_warning_description">Les jeux ne seront pas affichés dans la liste des jeux si aucun dossier n\'est sélectionné.</string>
@@ -47,7 +48,7 @@
47 <string name="install_prod_keys_warning_description">Des clés valides sont nécessaires pour émuler des jeux commerciaux. Seules les applications homebrew fonctionneront si vous continuez.</string> 48 <string name="install_prod_keys_warning_description">Des clés valides sont nécessaires pour émuler des jeux commerciaux. Seules les applications homebrew fonctionneront si vous continuez.</string>
48 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> 49 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
49 <string name="notifications">Notifications</string> 50 <string name="notifications">Notifications</string>
50 <string name="notifications_description">Accordez l\'autorisation de notification avec le bouton ci-dessous.</string> 51 <string name="notifications_description">Accorder la permission de notification avec le bouton ci-dessous.</string>
51 <string name="give_permission">Accorder la permission</string> 52 <string name="give_permission">Accorder la permission</string>
52 <string name="notification_warning">Ne pas accorder la permission de notification ?</string> 53 <string name="notification_warning">Ne pas accorder la permission de notification ?</string>
53 <string name="notification_warning_description">yuzu ne pourra pas vous communiquer d\'informations importantes.</string> 54 <string name="notification_warning_description">yuzu ne pourra pas vous communiquer d\'informations importantes.</string>
@@ -68,6 +69,7 @@
68 <string name="invalid_keys_error">Clés de chiffrement invalides</string> 69 <string name="invalid_keys_error">Clés de chiffrement invalides</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string> 71 <string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string>
72 <string name="gpu_driver_manager">Gestionnaire de pilotes du GPU</string>
71 <string name="install_gpu_driver">Installer le pilote du GPU</string> 73 <string name="install_gpu_driver">Installer le pilote du GPU</string>
72 <string name="install_gpu_driver_description">Installer des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string> 74 <string name="install_gpu_driver_description">Installer des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string>
73 <string name="advanced_settings">Paramètres avancés</string> 75 <string name="advanced_settings">Paramètres avancés</string>
@@ -85,7 +87,11 @@
85 <string name="notification_no_directory_link_description">Veuillez localiser manuellement le dossier utilisateur avec le panneau latéral du gestionnaire de fichiers.</string> 87 <string name="notification_no_directory_link_description">Veuillez localiser manuellement le dossier utilisateur avec le panneau latéral du gestionnaire de fichiers.</string>
86 <string name="manage_save_data">Gérer les données de sauvegarde</string> 88 <string name="manage_save_data">Gérer les données de sauvegarde</string>
87 <string name="manage_save_data_description">Données de sauvegarde trouvées. Veuillez sélectionner une option ci-dessous.</string> 89 <string name="manage_save_data_description">Données de sauvegarde trouvées. Veuillez sélectionner une option ci-dessous.</string>
90 <string name="import_save_warning">Importer les données de sauvegarde</string>
91 <string name="import_save_warning_description">Cela écrasera toutes les données de sauvegarde existantes avec le fichier fourni. Êtes-vous sûr de vouloir continuer ?</string>
88 <string name="import_export_saves_description">Importer ou exporter des fichiers de sauvegarde</string> 92 <string name="import_export_saves_description">Importer ou exporter des fichiers de sauvegarde</string>
93 <string name="save_files_importing">Importation des fichiers de sauvegarde...</string>
94 <string name="save_files_exporting">Exportation des fichiers de sauvegarde...</string>
89 <string name="save_file_imported_success">Importé avec succès</string> 95 <string name="save_file_imported_success">Importé avec succès</string>
90 <string name="save_file_invalid_zip_structure">Structure de répertoire de sauvegarde non valide</string> 96 <string name="save_file_invalid_zip_structure">Structure de répertoire de sauvegarde non valide</string>
91 <string name="save_file_invalid_zip_structure_description">Le nom du premier sous-dossier doit être l\'identifiant du titre du jeu.</string> 97 <string name="save_file_invalid_zip_structure_description">Le nom du premier sous-dossier doit être l\'identifiant du titre du jeu.</string>
@@ -118,6 +124,40 @@
118 <string name="manage_yuzu_data_description">Importer/exporter le firmware, les clés, les données utilisateur, et bien plus encore !</string> 124 <string name="manage_yuzu_data_description">Importer/exporter le firmware, les clés, les données utilisateur, et bien plus encore !</string>
119 <string name="share_save_file">Partager le fichier de sauvegarde</string> 125 <string name="share_save_file">Partager le fichier de sauvegarde</string>
120 <string name="export_save_failed">Échec de l\'exportation de la sauvegarde</string> 126 <string name="export_save_failed">Échec de l\'exportation de la sauvegarde</string>
127 <string name="game_folders">Dossiers de jeux</string>
128 <string name="deep_scan">Analyse approfondie</string>
129 <string name="add_game_folder">Ajouter un dossier de jeu</string>
130 <string name="folder_already_added">Ce dossier a déjà été ajouté !</string>
131 <string name="game_folder_properties">Propriétés du dossier du jeu</string>
132 <plurals name="saves_import_failed">
133 <item quantity="one">Échec de l\'importation de %d sauvegarde</item>
134 <item quantity="many">Échec de l\'importation de %d sauvegardes </item>
135 <item quantity="other">Échec de l\'importation de %d sauvegardes</item>
136 </plurals>
137 <plurals name="saves_import_success">
138 <item quantity="one">%d sauvegarde importée avec succès</item>
139 <item quantity="many">%d sauvegardes importées avec succès</item>
140 <item quantity="other">%d sauvegardes importées avec succès</item>
141 </plurals>
142 <string name="no_save_data_found">Aucune donnée de sauvegarde trouvée</string>
143
144 <!-- Applet launcher strings -->
145 <string name="applets">Lanceur d\'applets</string>
146 <string name="applets_description">Lancer des applets système en utilisant le firmware installé</string>
147 <string name="applets_error_firmware">Firmware non installé</string>
148 <string name="applets_error_applet">Applet non disponible</string>
149 <string name="applets_error_description"><![CDATA[Veuillez vous assurer que le fichier <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> et le <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> sont installés et essayez à nouveau.]]></string>
150 <string name="album_applet">Album</string>
151 <string name="album_applet_description">Afficher les images stockées dans le dossier de captures d\'écran de l\'utilisateur avec le visualiseur de photos système.</string>
152 <string name="mii_edit_applet">Éditeur Mii</string>
153 <string name="mii_edit_applet_description">Visualiser et modifier les Miis avec l\'éditeur système.</string>
154 <string name="cabinet_applet">Cabinet</string>
155 <string name="cabinet_applet_description">Modifier et supprimer des données stockées sur un amiibo</string>
156 <string name="cabinet_launcher">Cabinet</string>
157 <string name="cabinet_nickname_and_owner">Paramètres du surnom et du propriétaire</string>
158 <string name="cabinet_game_data_eraser">Effaceur de données de jeu</string>
159 <string name="cabinet_restorer">Restaurateur</string>
160 <string name="cabinet_formatter">Formateur</string>
121 161
122 <!-- About screen strings --> 162 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia n\'est pas réel</string> 163 <string name="gaia_is_not_real">Gaia n\'est pas réel</string>
@@ -157,10 +197,11 @@
157 <string name="are_you_interested">Es tu intéressé ?</string> 197 <string name="are_you_interested">Es tu intéressé ?</string>
158 198
159 <!-- General settings strings --> 199 <!-- General settings strings -->
160 <string name="frame_limit_enable">Limitation de vitesse</string> 200 <string name="frame_limit_enable">Limiter la vitesse</string>
161 <string name="frame_limit_enable_description">Limiter la vitesse d\'émulation à un pourcentage spécifié de la vitesse normale</string> 201 <string name="frame_limit_enable_description">Limiter la vitesse d\'émulation à un pourcentage spécifié de la vitesse normale</string>
162 <string name="frame_limit_slider">Limite en pourcentage de vitesse</string> 202 <string name="frame_limit_slider">Limiter le pourcentage de vitesse</string>
163 <string name="frame_limit_slider_description">Spécifier le pourcentage pour limiter la vitesse d\'émulation. 100% correspond à la vitesse normale. Des valeurs plus élevées ou plus basses augmenteront ou diminueront la limite de vitesse.</string> 203 <string name="frame_limit_slider_description">Spécifier le pourcentage pour limiter la vitesse d\'émulation. 100% correspond à la vitesse normale. Des valeurs plus élevées ou plus basses augmenteront ou diminueront la limite de vitesse.</string>
204 <string name="cpu_backend">Backend du CPU</string>
164 <string name="cpu_accuracy">Précision du CPU</string> 205 <string name="cpu_accuracy">Précision du CPU</string>
165 <string name="value_with_units">%1$s%2$s</string> 206 <string name="value_with_units">%1$s%2$s</string>
166 207
@@ -191,6 +232,8 @@
191 <string name="renderer_reactive_flushing_description">Améliore la précision du rendu dans certains jeux au détriment des performances.</string> 232 <string name="renderer_reactive_flushing_description">Améliore la précision du rendu dans certains jeux au détriment des performances.</string>
192 <string name="use_disk_shader_cache">Utiliser les shader cache</string> 233 <string name="use_disk_shader_cache">Utiliser les shader cache</string>
193 <string name="use_disk_shader_cache_description">Réduire les saccades en stockant et en chargeant localement les shaders générés</string> 234 <string name="use_disk_shader_cache_description">Réduire les saccades en stockant et en chargeant localement les shaders générés</string>
235 <string name="anisotropic_filtering">Filtrage anisotropique</string>
236 <string name="anisotropic_filtering_description">Améliore la qualité des textures lorsqu\'elles sont visualisées sous des angles obliques</string>
194 237
195 <!-- Debug settings strings --> 238 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string> 239 <string name="cpu">CPU</string>
@@ -217,7 +260,8 @@
217 <string name="shutting_down">Extinction en cours...</string> 260 <string name="shutting_down">Extinction en cours...</string>
218 <string name="reset_setting_confirmation">Voulez-vous réinitialiser ce paramètre à sa valeur par défaut ?</string> 261 <string name="reset_setting_confirmation">Voulez-vous réinitialiser ce paramètre à sa valeur par défaut ?</string>
219 <string name="reset_to_default">Réinitialiser par défaut</string> 262 <string name="reset_to_default">Réinitialiser par défaut</string>
220 <string name="reset_all_settings">Réinitialiser tous les réglages ?</string> 263 <string name="reset_to_default_description">Réinitialiser tous les paramètres avancés</string>
264 <string name="reset_all_settings">Réinitialiser tous les paramètres ?</string>
221 <string name="reset_all_settings_description">Tous les paramètres avancés seront réinitialisés à leur configuration par défaut. Ça ne peut pas être annulé.</string> 265 <string name="reset_all_settings_description">Tous les paramètres avancés seront réinitialisés à leur configuration par défaut. Ça ne peut pas être annulé.</string>
222 <string name="settings_reset">Paramètres réinitialisés</string> 266 <string name="settings_reset">Paramètres réinitialisés</string>
223 <string name="close">Fermer</string> 267 <string name="close">Fermer</string>
@@ -230,14 +274,24 @@
230 <string name="export_failed">L\'exportation a échoué</string> 274 <string name="export_failed">L\'exportation a échoué</string>
231 <string name="import_failed">L\'importation a échoué</string> 275 <string name="import_failed">L\'importation a échoué</string>
232 <string name="cancelling">Annulation</string> 276 <string name="cancelling">Annulation</string>
233 277 <string name="install">Installer</string>
278 <string name="delete">Supprimer</string>
279 <string name="edit">Éditer</string>
280 <string name="export_success">Exportation réussie</string>
281 <string name="start">Start</string>
282 <string name="clear">Effacer</string>
283 <string name="global">Global</string>
284 <string name="custom">Personnalisé</string>
285 <string name="notice">Avis</string>
286 <string name="import_complete">Importation terminée</string>
234 <!-- GPU driver installation --> 287 <!-- GPU driver installation -->
235 <string name="select_gpu_driver">Sélectionner le pilote du GPU</string> 288 <string name="select_gpu_driver">Sélectionner le pilote du GPU</string>
236 <string name="select_gpu_driver_title">Souhaitez vous remplacer votre pilote actuel ?</string> 289 <string name="select_gpu_driver_title">Souhaitez vous remplacer votre pilote actuel ?</string>
237 <string name="select_gpu_driver_install">Installer</string> 290 <string name="select_gpu_driver_install">Installer</string>
238 <string name="select_gpu_driver_default">Par défaut</string> 291 <string name="select_gpu_driver_default">Par défaut</string>
239 <string name="select_gpu_driver_use_default">Utilisation du pilote du GPU par défaut</string> 292 <string name="select_gpu_driver_use_default">Utilisation du pilote du GPU par défaut</string>
240 <string name="select_gpu_driver_error">Pilote non valide sélectionné, utilisation du paramètre par défaut du système !</string> 293 <string name="select_gpu_driver_error">Pilote non valide sélectionné</string>
294 <string name="driver_already_installed">Pilote déjà installé</string>
241 <string name="system_gpu_driver">Pilote du GPU du système</string> 295 <string name="system_gpu_driver">Pilote du GPU du système</string>
242 <string name="installing_driver">Installation du pilote...</string> 296 <string name="installing_driver">Installation du pilote...</string>
243 297
@@ -245,11 +299,52 @@
245 <string name="preferences_settings">Paramètres</string> 299 <string name="preferences_settings">Paramètres</string>
246 <string name="preferences_general">Général</string> 300 <string name="preferences_general">Général</string>
247 <string name="preferences_system">Système</string> 301 <string name="preferences_system">Système</string>
302 <string name="preferences_system_description">Mode TV, région, langue</string>
248 <string name="preferences_graphics">Vidéo</string> 303 <string name="preferences_graphics">Vidéo</string>
304 <string name="preferences_graphics_description">Niveau de précision, résolution, cache de shaders</string>
249 <string name="preferences_audio">Audio</string> 305 <string name="preferences_audio">Audio</string>
306 <string name="preferences_audio_description">Moteur de sortie, volume</string>
250 <string name="preferences_theme">Thème et couleur</string> 307 <string name="preferences_theme">Thème et couleur</string>
251 <string name="preferences_debug">Débogage</string> 308 <string name="preferences_debug">Débogage</string>
252 309 <string name="preferences_debug_description">Débogage CPU/GPU, API graphique, fastmem</string>
310
311 <!-- Game properties -->
312 <string name="info">Info</string>
313 <string name="info_description">ID du programme, développeur, version</string>
314 <string name="per_game_settings">Paramètres spécifiques au jeu</string>
315 <string name="per_game_settings_description">Modifier les paramètres spécifiques à ce jeu</string>
316 <string name="launch_options">Lancer la configuration</string>
317 <string name="path">Chemin</string>
318 <string name="program_id">ID du programme</string>
319 <string name="developer">Développeur</string>
320 <string name="version">Version</string>
321 <string name="copy_details">Copier les détails</string>
322 <string name="add_ons">Extensions</string>
323 <string name="add_ons_description">Activer les mods, mises à jour et DLC</string>
324 <string name="clear_shader_cache">Effacer le cache des shaders</string>
325 <string name="clear_shader_cache_description">Supprime tous les shaders générés en jouant à ce jeu</string>
326 <string name="clear_shader_cache_warning_description">Vous risquez de rencontrer davantage de saccades pendant que le cache des shaders se régénère.</string>
327 <string name="cleared_shaders_successfully">Shaders effacés avec succès</string>
328 <string name="addons_game">Addons : %1$s</string>
329 <string name="save_data">Données de sauvegarde</string>
330 <string name="save_data_description">Gérer les données de sauvegarde spécifiques à ce jeu</string>
331 <string name="delete_save_data">Supprimer les données de sauvegarde</string>
332 <string name="delete_save_data_description">Supprime toutes les données de sauvegarde spécifiques à ce jeu</string>
333 <string name="delete_save_data_warning_description">Cela supprime de manière irréversible toutes les données de sauvegarde de ce jeu. Êtes-vous sûr de vouloir continuer ?</string>
334 <string name="save_data_deleted_successfully">Données de sauvegarde supprimées avec succès</string>
335 <string name="select_content_type">Type de contenu</string>
336 <string name="updates_and_dlc">Mises à jour et DLC</string>
337 <string name="mods_and_cheats">Mods et cheats</string>
338 <string name="addon_notice">Notification importante concernant l\'addon</string>
339 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
340 <string name="addon_notice_description">Pour installer des mods et des cheats, vous devez sélectionner un dossier contenant un répertoire cheats/, romfs/ ou exefs/. Nous ne pouvons pas garantir leur compatibilité avec votre jeu, alors soyez prudent !</string>
341 <string name="invalid_directory">Répertoire non valide</string>
342 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
343 <string name="invalid_directory_description">Veuillez vous assurer que le répertoire que vous avez sélectionné contient un dossier cheats/, romfs/ ou exefs/, puis réessayez.</string>
344 <string name="addon_installed_successfully">Addon installé avec succès</string>
345 <string name="verifying_content">Vérification du contenu...</string>
346 <string name="content_install_notice">Avis d\'installation du contenu</string>
347 <string name="content_install_notice_description">Le contenu que vous avez sélectionné ne correspond pas à ce jeu.\nInstaller quand même ?</string>
253 <!-- ROM loading errors --> 348 <!-- ROM loading errors -->
254 <string name="loader_error_encrypted">Votre ROM est cryptée</string> 349 <string name="loader_error_encrypted">Votre ROM est cryptée</string>
255 <string name="loader_error_encrypted_roms_description"><![CDATA[Veuillez suivre les guides pour refaire un dump de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartouches de jeu</a> ou de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">titres installés</a>.]]></string> 350 <string name="loader_error_encrypted_roms_description"><![CDATA[Veuillez suivre les guides pour refaire un dump de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartouches de jeu</a> ou de vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">titres installés</a>.]]></string>
@@ -277,6 +372,7 @@
277 <string name="emulation_pause">Mettre en pause l\'émulation</string> 372 <string name="emulation_pause">Mettre en pause l\'émulation</string>
278 <string name="emulation_unpause">Reprendre l\'émulation</string> 373 <string name="emulation_unpause">Reprendre l\'émulation</string>
279 <string name="emulation_input_overlay">Options de l\'overlay</string> 374 <string name="emulation_input_overlay">Options de l\'overlay</string>
375 <string name="touchscreen">Écran tactile</string>
280 376
281 <string name="load_settings">Chargement des paramètres…</string> 377 <string name="load_settings">Chargement des paramètres…</string>
282 378
@@ -308,6 +404,7 @@
308 404
309 <!-- Memory Sizes --> 405 <!-- Memory Sizes -->
310 <string name="memory_byte">Octet</string> 406 <string name="memory_byte">Octet</string>
407 <string name="memory_byte_shorthand">B</string>
311 <string name="memory_kilobyte">Ko</string> 408 <string name="memory_kilobyte">Ko</string>
312 <string name="memory_megabyte">Mo</string> 409 <string name="memory_megabyte">Mo</string>
313 <string name="memory_gigabyte">GB</string> 410 <string name="memory_gigabyte">GB</string>
@@ -352,9 +449,13 @@
352 <string name="anti_aliasing_smaa">SMAA</string> 449 <string name="anti_aliasing_smaa">SMAA</string>
353 450
354 <!-- Screen Layouts --> 451 <!-- Screen Layouts -->
452 <string name="screen_layout_auto">Auto</string>
453 <string name="screen_layout_sensor_landscape">Paysage</string>
355 <string name="screen_layout_landscape">Paysage</string> 454 <string name="screen_layout_landscape">Paysage</string>
455 <string name="screen_layout_reverse_landscape">Paysage inversé</string>
456 <string name="screen_layout_sensor_portrait">Portrait</string>
356 <string name="screen_layout_portrait">Portrait</string> 457 <string name="screen_layout_portrait">Portrait</string>
357 <string name="screen_layout_auto">Auto</string> 458 <string name="screen_layout_reverse_portrait">Portrait inversé</string>
358 459
359 <!-- Aspect Ratios --> 460 <!-- Aspect Ratios -->
360 <string name="ratio_default">Par défaut (16:9)</string> 461 <string name="ratio_default">Par défaut (16:9)</string>
@@ -363,6 +464,10 @@
363 <string name="ratio_force_sixteen_ten">Forcer le 16:10</string> 464 <string name="ratio_force_sixteen_ten">Forcer le 16:10</string>
364 <string name="ratio_stretch">Étirer à la fenêtre</string> 465 <string name="ratio_stretch">Étirer à la fenêtre</string>
365 466
467 <!-- CPU Backend -->
468 <string name="cpu_backend_dynarmic">Dynarmic (Lent)</string>
469 <string name="cpu_backend_nce">Exécution de code natif (NCE)</string>
470
366 <!-- CPU Accuracy --> 471 <!-- CPU Accuracy -->
367 <string name="cpu_accuracy_accurate">Précis</string> 472 <string name="cpu_accuracy_accurate">Précis</string>
368 <string name="cpu_accuracy_unsafe">Risqué</string> 473 <string name="cpu_accuracy_unsafe">Risqué</string>
@@ -391,8 +496,15 @@
391 <string name="theme_mode_dark">Sombre</string> 496 <string name="theme_mode_dark">Sombre</string>
392 497
393 <!-- Audio output engines --> 498 <!-- Audio output engines -->
499 <string name="oboe">oboe</string>
394 <string name="cubeb">cubeb</string> 500 <string name="cubeb">cubeb</string>
395 501
502 <!-- Anisotropic filtering options -->
503 <string name="multiplier_two">2x</string>
504 <string name="multiplier_four">4x</string>
505 <string name="multiplier_eight">8x</string>
506 <string name="multiplier_sixteen">16x</string>
507
396 <!-- Black backgrounds theme --> 508 <!-- Black backgrounds theme -->
397 <string name="use_black_backgrounds">Arrière-plan noir</string> 509 <string name="use_black_backgrounds">Arrière-plan noir</string>
398 <string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer un arrière-plan noir.</string> 510 <string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer un arrière-plan noir.</string>
diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml
index 0af78a57c..41e4450c6 100644
--- a/src/android/app/src/main/res/values-he/strings.xml
+++ b/src/android/app/src/main/res/values-he/strings.xml
@@ -34,6 +34,7 @@
34 <string name="empty_gamelist">×œ× × ×ž×¦×ו ×§×‘×¦×™× ×ו לנבחרה ספריית ×§×‘×¦×™× ×‘×™× ×ª×™×™×.</string> 34 <string name="empty_gamelist">×œ× × ×ž×¦×ו ×§×‘×¦×™× ×ו לנבחרה ספריית ×§×‘×¦×™× ×‘×™× ×ª×™×™×.</string>
35 <string name="search_and_filter_games">חפש וסנן משחקי×</string> 35 <string name="search_and_filter_games">חפש וסנן משחקי×</string>
36 <string name="select_games_folder">בחר תיקיית משחקי×</string> 36 <string name="select_games_folder">בחר תיקיית משחקי×</string>
37 <string name="manage_game_folders">נהל ×ת תיקיית המשחקי×</string>
37 <string name="select_games_folder_description">×פשר ל yuzu ל×כלס ×ת רשימת המשחקי×</string> 38 <string name="select_games_folder_description">×פשר ל yuzu ל×כלס ×ת רשימת המשחקי×</string>
38 <string name="add_games_warning">לדלג על בחירת תיקיית המשחקי×?</string> 39 <string name="add_games_warning">לדלג על בחירת תיקיית המשחקי×?</string>
39 <string name="add_games_warning_description">×ž×©×—×§×™× ×œ× ×™×•×¦×’×• ברשימת ×”×ž×©×—×§×™× ×× ×œ× ×‘×—×¨×” תיקיית משחקי×.</string> 40 <string name="add_games_warning_description">×ž×©×—×§×™× ×œ× ×™×•×¦×’×• ברשימת ×”×ž×©×—×§×™× ×× ×œ× ×‘×—×¨×” תיקיית משחקי×.</string>
@@ -68,6 +69,7 @@
68 <string name="invalid_keys_error">מפתחות הצפנה ×œ× ×—×•×§×™×™×</string> 69 <string name="invalid_keys_error">מפתחות הצפנה ×œ× ×—×•×§×™×™×</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">קבוץ שנבחר מושחת ×ו ×œ× × ×›×•×Ÿ. בבקשה ×”×•×¦× ×ž×—×“×© ×ת המפתחות שלך.</string> 71 <string name="install_keys_failure_description">קבוץ שנבחר מושחת ×ו ×œ× × ×›×•×Ÿ. בבקשה ×”×•×¦× ×ž×—×“×© ×ת המפתחות שלך.</string>
72 <string name="gpu_driver_manager">מנהל ×”×“×¨×™×™×‘×¨×™× ×©×œ המעבד הגרפי</string>
71 <string name="install_gpu_driver">התקן דרייבר למעבד הגרפי</string> 73 <string name="install_gpu_driver">התקן דרייבר למעבד הגרפי</string>
72 <string name="install_gpu_driver_description">התקן ×“×¨×™×™×‘×¨×™× ××—×¨×™× ×‘×©×‘×™×œ סיכוי ×œ×‘×™×¦×•×¢×™× ×ו דיוק ×’×‘×•×”×”×™× ×™×•×ª×¨</string> 74 <string name="install_gpu_driver_description">התקן ×“×¨×™×™×‘×¨×™× ××—×¨×™× ×‘×©×‘×™×œ סיכוי ×œ×‘×™×¦×•×¢×™× ×ו דיוק ×’×‘×•×”×”×™× ×™×•×ª×¨</string>
73 <string name="advanced_settings">הגדרות מתקדמות</string> 75 <string name="advanced_settings">הגדרות מתקדמות</string>
@@ -86,6 +88,7 @@
86 <string name="manage_save_data">נהל מידע שמור</string> 88 <string name="manage_save_data">נהל מידע שמור</string>
87 <string name="manage_save_data_description">מידע שמור ×œ× × ×ž×¦×. בבקשה בחר/×™ ×ופציה מלמטה</string> 89 <string name="manage_save_data_description">מידע שמור ×œ× × ×ž×¦×. בבקשה בחר/×™ ×ופציה מלמטה</string>
88 <string name="import_export_saves_description">×™×‘× ×ו ×™×¦× ×§×‘×¦×™ שמירה</string> 90 <string name="import_export_saves_description">×™×‘× ×ו ×™×¦× ×§×‘×¦×™ שמירה</string>
91 <string name="save_files_exporting">×ž×™×™×¦× ×§×‘×¦×™ שמירה...</string>
89 <string name="save_file_imported_success">×™×•×‘× ×‘×”×¦×œ×—×”</string> 92 <string name="save_file_imported_success">×™×•×‘× ×‘×”×¦×œ×—×”</string>
90 <string name="save_file_invalid_zip_structure">מבנה ספריית השמירות ×œ× ×—×•×§×™</string> 93 <string name="save_file_invalid_zip_structure">מבנה ספריית השמירות ×œ× ×—×•×§×™</string>
91 <string name="save_file_invalid_zip_structure_description">התת תיקייה הר×שונה חייב להיות ×” title ID של המשחק</string> 94 <string name="save_file_invalid_zip_structure_description">התת תיקייה הר×שונה חייב להיות ×” title ID של המשחק</string>
@@ -118,6 +121,28 @@
118 <string name="manage_yuzu_data_description">יב×/×™×¦× firmware, keys, מידע של משתמש ועוד!</string> 121 <string name="manage_yuzu_data_description">יב×/×™×¦× firmware, keys, מידע של משתמש ועוד!</string>
119 <string name="share_save_file">שתף קובץ שמירה</string> 122 <string name="share_save_file">שתף קובץ שמירה</string>
120 <string name="export_save_failed">נכשל ×‘×™×™×¦×•× ×©×ž×™×¨×”</string> 123 <string name="export_save_failed">נכשל ×‘×™×™×¦×•× ×©×ž×™×¨×”</string>
124 <string name="game_folders">תיקיית משחקי×</string>
125 <string name="deep_scan">סריקה עמוקה</string>
126 <string name="add_game_folder">הוסף תיקיית משחקי×</string>
127 <string name="folder_already_added">התיקייה הזו נוספה כבר!</string>
128 <string name="game_folder_properties">מ×פייני תיקיית משחקי×</string>
129 <!-- Applet launcher strings -->
130 <string name="applets">משגר Applet</string>
131 <string name="applets_description">מערכת שיגור Applet משתמשת בתוכנה המותקנת</string>
132 <string name="applets_error_firmware">×” Firmware ×œ× ×ž×•×ª×§×Ÿ</string>
133 <string name="applets_error_applet">Applet ×œ× ×–×ž×™×Ÿ</string>
134 <string name="applets_error_description"><![CDATA[בבקשה ×•×•×“× ×©×§×‘×¦×™ ×” - <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a>ו <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a>שלך ×ž×•×ª×§× ×™× ×•× ×¡×” שוב.]]></string>
135 <string name="album_applet">×לבו×</string>
136 <string name="album_applet_description">צפה בתמונות השמורות בתיקיית צילומי המסך של המשתמש בעזרת מציג התמונות של המערכת</string>
137 <string name="mii_edit_applet">עורך Mii</string>
138 <string name="mii_edit_applet_description">צפה וערוך דמויות Mii בעזרת עורך המערכת</string>
139 <string name="cabinet_applet">×רון</string>
140 <string name="cabinet_applet_description">ערוך ומחק מידע השמור על ה amiibo</string>
141 <string name="cabinet_launcher">משגר ×רונות</string>
142 <string name="cabinet_nickname_and_owner">כינוי והגדרות בעלי×</string>
143 <string name="cabinet_game_data_eraser">מחק של נתוני משחק</string>
144 <string name="cabinet_restorer">שחזר</string>
145 <string name="cabinet_formatter">בונה תבניות</string>
121 146
122 <!-- About screen strings --> 147 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia ×œ× ×מיתית</string> 148 <string name="gaia_is_not_real">Gaia ×œ× ×מיתית</string>
@@ -161,6 +186,7 @@
161 <string name="frame_limit_enable_description">מגביל ×ת מהירות ×”×מולציה ל×חוז מהירות המבוקש מהמהירות הרגילה.</string> 186 <string name="frame_limit_enable_description">מגביל ×ת מהירות ×”×מולציה ל×חוז מהירות המבוקש מהמהירות הרגילה.</string>
162 <string name="frame_limit_slider">הגבל ×ת ×חוז המהירות</string> 187 <string name="frame_limit_slider">הגבל ×ת ×חוז המהירות</string>
163 <string name="frame_limit_slider_description">מדייק ×ת ×חוז מהירות ×”×מולציה. 100% ×–×” מהירות רגילה. ×¢×¨×›×™× ×’×“×•×œ×™× ×ו ×§×˜× ×™× ×™×יצו ×ו ×™×טו ×ת מהירות ×”×מולציה.</string> 188 <string name="frame_limit_slider_description">מדייק ×ת ×חוז מהירות ×”×מולציה. 100% ×–×” מהירות רגילה. ×¢×¨×›×™× ×’×“×•×œ×™× ×ו ×§×˜× ×™× ×™×יצו ×ו ×™×טו ×ת מהירות ×”×מולציה.</string>
189 <string name="cpu_backend">קצה ×”×חורי של המעבד</string>
164 <string name="cpu_accuracy">דיוק המעבד</string> 190 <string name="cpu_accuracy">דיוק המעבד</string>
165 <string name="value_with_units">%1$s%2$s</string> 191 <string name="value_with_units">%1$s%2$s</string>
166 192
@@ -185,23 +211,38 @@
185 <string name="renderer_anti_aliasing">שיטת Anti-aliasing</string> 211 <string name="renderer_anti_aliasing">שיטת Anti-aliasing</string>
186 <string name="renderer_force_max_clock">החזק מהירות שעון מקסימלית (רק ל Adreno)</string> 212 <string name="renderer_force_max_clock">החזק מהירות שעון מקסימלית (רק ל Adreno)</string>
187 <string name="renderer_force_max_clock_description">מכריח לדחוף ×ת מהירויות המעבד הגרפי ×œ×ž×§×¡×™×ž×•× (הגבלות ×—×•× ×™×ž×©×™×›×• לתפקד).</string> 213 <string name="renderer_force_max_clock_description">מכריח לדחוף ×ת מהירויות המעבד הגרפי ×œ×ž×§×¡×™×ž×•× (הגבלות ×—×•× ×™×ž×©×™×›×• לתפקד).</string>
214 <string name="renderer_asynchronous_shaders">השתמש ×‘×©×™×™×“×¨×™× ×סינכרוני×</string>
215 <string name="renderer_asynchronous_shaders_description">מקמפל ×©×™×™×“×¨×™× ×‘×¦×•×¨×” ×סנכרונית, מפחית תקיעות ×ך עלול ×œ×’×¨×•× ×œ×‘×¢×™×•×ª גרפיות.</string>
216 <string name="renderer_reactive_flushing">השתמש בהבהוב תגובתי</string>
188 <string name="renderer_reactive_flushing_description">משפר ×ת הדיוק של ×”×מולציה ×‘×ž×©×—×§×™× ×ž×¡×•×™×™×ž×™× ×‘×ž×—×™×¨ של ביצועי×.</string> 217 <string name="renderer_reactive_flushing_description">משפר ×ת הדיוק של ×”×מולציה ×‘×ž×©×—×§×™× ×ž×¡×•×™×™×ž×™× ×‘×ž×—×™×¨ של ביצועי×.</string>
218 <string name="use_disk_shader_cache">מטמון השיידר של הדיסק</string>
219 <string name="use_disk_shader_cache_description">מפחית בתקיעות על ידי ×חסון מקומי וטעינה של ×©×™×™×“×¨×™× ×”× ×•×¦×¨×™×. </string>
189 <!-- Debug settings strings --> 220 <!-- Debug settings strings -->
190 <string name="cpu">מעבד</string> 221 <string name="cpu">מעבד</string>
222 <string name="cpu_debug_mode">דיב××’×™× ×’ למעבד</string>
191 <string name="cpu_debug_mode_description">מכניס ×ת המעבד למצב דיב××’ ×יטי</string> 223 <string name="cpu_debug_mode_description">מכניס ×ת המעבד למצב דיב××’ ×יטי</string>
192 <string name="gpu">מעבד גרפי</string> 224 <string name="gpu">מעבד גרפי</string>
225 <string name="renderer_api">ממשק תוכנה</string>
226 <string name="renderer_debug">דיב××’×™× ×’ בגרפיקה</string>
227 <string name="renderer_debug_description">קובע ×ת ממשק התוכנה של הגרפיקות למצב דיב××’×™× ×’ ×יטי.</string>
228 <string name="fastmem">Fastmem</string>
229
193 <!-- Audio settings strings --> 230 <!-- Audio settings strings -->
194 <string name="audio_output_engine">מנוע פלט</string> 231 <string name="audio_output_engine">מנוע פלט</string>
195 <string name="audio_volume">עוצמת שמע</string> 232 <string name="audio_volume">עוצמת שמע</string>
233 <string name="audio_volume_description">מציין ×ת עוצמת ×”×ודיו שיוצ×.</string>
234
196 <!-- Miscellaneous --> 235 <!-- Miscellaneous -->
197 <string name="slider_default">ברירת מחדל</string> 236 <string name="slider_default">ברירת מחדל</string>
198 <string name="ini_saved">הגדרות שמורות</string> 237 <string name="ini_saved">הגדרות שמורות</string>
199 <string name="gameid_saved">הגדרות שמורות עבור %1$s</string> 238 <string name="gameid_saved">הגדרות שמורות עבור %1$s</string>
200 <string name="error_saving">תקלה בשמירת %1$s.ini: %2$s</string> 239 <string name="error_saving">תקלה בשמירת %1$s.ini: %2$s</string>
240 <string name="unimplemented_menu">תפריט ×©×œ× ×™×•×©×</string>
201 <string name="loading">טוען...</string> 241 <string name="loading">טוען...</string>
202 <string name="shutting_down">כיבוי...</string> 242 <string name="shutting_down">כיבוי...</string>
203 <string name="reset_setting_confirmation">×תה מעוניין ל×פס ×ת ההגדרה הזו חזרה לברירת המחדל?</string> 243 <string name="reset_setting_confirmation">×תה מעוניין ל×פס ×ת ההגדרה הזו חזרה לברירת המחדל?</string>
204 <string name="reset_to_default">×פס לברירת המחדל</string> 244 <string name="reset_to_default">×פס לברירת המחדל</string>
245 <string name="reset_to_default_description">מ×פס ×ת כל ההגדרות המתקדמות.</string>
205 <string name="reset_all_settings">ל×פס ×ת כל ההגדרות?</string> 246 <string name="reset_all_settings">ל×פס ×ת כל ההגדרות?</string>
206 <string name="reset_all_settings_description">כל ההגדרות המתקדמות ×™×ופסו לברירת המחדל. ×œ× × ×™×ª×Ÿ לבטל פעולה זו.</string> 247 <string name="reset_all_settings_description">כל ההגדרות המתקדמות ×™×ופסו לברירת המחדל. ×œ× × ×™×ª×Ÿ לבטל פעולה זו.</string>
207 <string name="settings_reset">×פס הגדרות</string> 248 <string name="settings_reset">×פס הגדרות</string>
@@ -209,19 +250,26 @@
209 <string name="learn_more">למד עוד</string> 250 <string name="learn_more">למד עוד</string>
210 <string name="auto">×וטומטי</string> 251 <string name="auto">×וטומטי</string>
211 <string name="submit">שלח</string> 252 <string name="submit">שלח</string>
253 <string name="string_null">ריק</string>
212 <string name="string_import">ייבו×</string> 254 <string name="string_import">ייבו×</string>
213 <string name="export">ייצו×</string> 255 <string name="export">ייצו×</string>
214 <string name="export_failed">×™×™×¦×•× × ×›×©×œ</string> 256 <string name="export_failed">×™×™×¦×•× × ×›×©×œ</string>
215 <string name="import_failed">×™×™×‘×•× × ×›×©×œ</string> 257 <string name="import_failed">×™×™×‘×•× × ×›×©×œ</string>
216 <string name="cancelling">מבטל</string> 258 <string name="cancelling">מבטל</string>
217 259 <string name="install">התקן</string>
260 <string name="delete">מחק</string>
261 <string name="edit">ערוך</string>
262 <string name="export_success">×™×•×¦× ×‘×”×¦×œ×—×”</string>
263 <string name="start">התחלה</string>
264 <string name="clear">× ×§×”</string>
218 <!-- GPU driver installation --> 265 <!-- GPU driver installation -->
219 <string name="select_gpu_driver">בחר דרייבר למעבד הגרפי</string> 266 <string name="select_gpu_driver">בחר דרייבר למעבד הגרפי</string>
220 <string name="select_gpu_driver_title">×תה מעוניין להחליף ×ת הדרייבר של המעבד הגרפי שלך?</string> 267 <string name="select_gpu_driver_title">×תה מעוניין להחליף ×ת הדרייבר של המעבד הגרפי שלך?</string>
221 <string name="select_gpu_driver_install">התקן</string> 268 <string name="select_gpu_driver_install">התקן</string>
222 <string name="select_gpu_driver_default">ברירת מחדל</string> 269 <string name="select_gpu_driver_default">ברירת מחדל</string>
223 <string name="select_gpu_driver_use_default">משתמש בדרייבר ברירת המחדל של המעבד הגרפי</string> 270 <string name="select_gpu_driver_use_default">משתמש בדרייבר ברירת המחדל של המעבד הגרפי</string>
224 <string name="select_gpu_driver_error">דרייבר ×œ× ×—×•×§×™ נבחר, משתמש בברירת המחדל של המערכת!</string> 271 <string name="select_gpu_driver_error">נבחר דרייבר ×œ× ×—×•×§×™</string>
272 <string name="driver_already_installed">הדרייבר כבר מותקן</string>
225 <string name="system_gpu_driver">דרייבר של המעבד הגרפי של המערכת</string> 273 <string name="system_gpu_driver">דרייבר של המעבד הגרפי של המערכת</string>
226 <string name="installing_driver">מתקין דרייבר...</string> 274 <string name="installing_driver">מתקין דרייבר...</string>
227 275
@@ -229,11 +277,27 @@
229 <string name="preferences_settings">הגדרות</string> 277 <string name="preferences_settings">הגדרות</string>
230 <string name="preferences_general">כללי</string> 278 <string name="preferences_general">כללי</string>
231 <string name="preferences_system">מערכת</string> 279 <string name="preferences_system">מערכת</string>
280 <string name="preferences_system_description">מצב מעוגן, ×יזור, שפה</string>
232 <string name="preferences_graphics">גרפיקה</string> 281 <string name="preferences_graphics">גרפיקה</string>
282 <string name="preferences_graphics_description">רמת דיוק, רזולוציה, מטמון שיידרי×</string>
233 <string name="preferences_audio">שמע</string> 283 <string name="preferences_audio">שמע</string>
284 <string name="preferences_audio_description">מנוע פלט, עוצמת שמע</string>
234 <string name="preferences_theme">צבע ונוש×</string> 285 <string name="preferences_theme">צבע ונוש×</string>
286 <string name="preferences_debug">דיב××’</string>
287 <string name="preferences_debug_description">דיב××’×™× ×’ עבור מעבד/מעבד גרפי, ממשק תוכנה עבור הגרפיקות, fastmem</string>
288
289 <!-- Game properties -->
290 <string name="info">מידע</string>
291 <string name="path">דרך</string>
292 <string name="developer">מפתח</string>
293 <string name="version">גרסה</string>
294 <string name="add_ons">תוספי×</string>
235 <!-- ROM loading errors --> 295 <!-- ROM loading errors -->
236 <string name="loader_error_encrypted">המשחק שלך מוצפן</string> 296 <string name="loader_error_encrypted">המשחק שלך מוצפן</string>
297 <string name="loader_error_encrypted_roms_description"><![CDATA[×× × ×¢×§×•×‘ ×חרי ×”×ž×“×¨×™×›×™× ×›×“×™ לבצע redump של <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">כרטיסי המשחק</a>×ו <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">הכותרות המותקנות</a> שלך.]]></string>
298 <string name="loader_error_encrypted_keys_description"><![CDATA[×× × ×•×•×“× ×©×§×•×‘×¥ ×”-<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> מותקן כך שניתן ×™×”×™×” לפענח משחקי×.]]></string>
299 <string name="loader_error_video_core">התרחשה בעיה ב×תחול של ליבת הוויד×ו</string>
300 <string name="loader_error_video_core_description">×–×” בדרך כלל × ×’×¨× ×¢×œ ידי דרייבר ×œ× ×ž×ª××™× ×¢×‘×•×¨ המעבד הגרפי. התקנת דרייבר ×שר מת××™× ×œ×ž×¢×‘×“ הגרפי יכול לפתור ×ת הבעיה הזו.</string>
237 <string name="loader_error_invalid_format">×ין ×פשרות לטעון ×ת המשחק</string> 301 <string name="loader_error_invalid_format">×ין ×פשרות לטעון ×ת המשחק</string>
238 <string name="loader_error_file_not_found">קובץ המשחק ×œ× ×§×™×™×</string> 302 <string name="loader_error_file_not_found">קובץ המשחק ×œ× ×§×™×™×</string>
239 303
@@ -241,10 +305,22 @@
241 <string name="emulation_exit">×¦× ×ž×”×מולציה</string> 305 <string name="emulation_exit">×¦× ×ž×”×מולציה</string>
242 <string name="emulation_done">סיו×</string> 306 <string name="emulation_done">סיו×</string>
243 <string name="emulation_fps_counter">סופר FPS</string> 307 <string name="emulation_fps_counter">סופר FPS</string>
308 <string name="emulation_toggle_controls">החלפת בקרי×</string>
309 <string name="emulation_rel_stick_center">מרכז ג׳ויסטיק יחסי</string>
310 <string name="emulation_dpad_slide">החלקת D-pad</string>
311 <string name="emulation_haptics">רטט מגע</string>
312 <string name="emulation_show_overlay">הצג ×ת שכבת-העל</string>
313 <string name="emulation_toggle_all">החלף הכל</string>
314 <string name="emulation_control_adjust">הת×× ×ת שכבת-העל</string>
244 <string name="emulation_control_scale">קנה מידה</string> 315 <string name="emulation_control_scale">קנה מידה</string>
245 <string name="emulation_control_opacity">שקיפות</string> 316 <string name="emulation_control_opacity">שקיפות</string>
317 <string name="emulation_touch_overlay_reset">×פס ×ת שכבת-העל</string>
318 <string name="emulation_touch_overlay_edit">ערוך שכבת-על</string>
246 <string name="emulation_pause">עצור ×מולציה</string> 319 <string name="emulation_pause">עצור ×מולציה</string>
247 <string name="emulation_unpause">המשך ×מולציה</string> 320 <string name="emulation_unpause">המשך ×מולציה</string>
321 <string name="emulation_input_overlay">×ופציות עבור שכבת-על</string>
322 <string name="touchscreen">מסך מגע</string>
323
248 <string name="load_settings">טוען הגדרות...</string> 324 <string name="load_settings">טוען הגדרות...</string>
249 325
250 <!-- Software keyboard --> 326 <!-- Software keyboard -->
@@ -258,6 +334,8 @@
258 <string name="system_archive_general">×רכיון מערכת</string> 334 <string name="system_archive_general">×רכיון מערכת</string>
259 <string name="save_load_error">בעיית שמירה/טעינה</string> 335 <string name="save_load_error">בעיית שמירה/טעינה</string>
260 <string name="fatal_error">שגי××” חמורה</string> 336 <string name="fatal_error">שגי××” חמורה</string>
337 <string name="fatal_error_message">שגי××” חמורה התרחשה. בדוק ×ת היומן לפרטי×./nהמשך הסימולציה עשוי ×œ×’×¨×•× ×œ×§×¨×™×¡×•×ª ולב××’×™×.</string>
338 <string name="performance_warning">כיבוי הגדרה זו ישפיע משמעותית על ביצועי הסימולציה! לחוויה הטובה ביותר, מומלץ להש×יר ×ת הגדרה זו מופעלת.</string>
261 <string name="device_memory_inadequate">RAM המכשיר: %1$s/nמומלץ: %2$s</string> 339 <string name="device_memory_inadequate">RAM המכשיר: %1$s/nמומלץ: %2$s</string>
262 <string name="memory_formatted">%1$s%2$s</string> 340 <string name="memory_formatted">%1$s%2$s</string>
263 <string name="no_game_present">×ין משחק שניתן להריץ!</string> 341 <string name="no_game_present">×ין משחק שניתן להריץ!</string>
@@ -273,6 +351,7 @@
273 351
274 <!-- Memory Sizes --> 352 <!-- Memory Sizes -->
275 <string name="memory_byte">בייט</string> 353 <string name="memory_byte">בייט</string>
354 <string name="memory_byte_shorthand">B</string>
276 <string name="memory_kilobyte">KB</string> 355 <string name="memory_kilobyte">KB</string>
277 <string name="memory_megabyte">MB</string> 356 <string name="memory_megabyte">MB</string>
278 <string name="memory_gigabyte">GB</string> 357 <string name="memory_gigabyte">GB</string>
@@ -297,12 +376,17 @@
297 <string name="resolution_three">3X (2160p/3240p) (×יטי)</string> 376 <string name="resolution_three">3X (2160p/3240p) (×יטי)</string>
298 <string name="resolution_four">4X (2880p/4320p) (×יטי)</string> 377 <string name="resolution_four">4X (2880p/4320p) (×יטי)</string>
299 378
379 <!-- Renderer VSync -->
380 <string name="renderer_vsync_immediate">מיידי (כבוי)</string>
300 <string name="renderer_vsync_mailbox">תיבת דו×ר</string> 381 <string name="renderer_vsync_mailbox">תיבת דו×ר</string>
301 <string name="renderer_vsync_fifo">FIFO (On)</string> 382 <string name="renderer_vsync_fifo">FIFO (On)</string>
302 <string name="renderer_vsync_fifo_relaxed">FIFO נינוח</string> 383 <string name="renderer_vsync_fifo_relaxed">FIFO נינוח</string>
303 384
304 <!-- Scaling Filters --> 385 <!-- Scaling Filters -->
305 <string name="scaling_filter_nearest_neighbor">השכן הקרוב ביותר</string> 386 <string name="scaling_filter_nearest_neighbor">השכן הקרוב ביותר</string>
387 <string name="scaling_filter_bilinear">ביליני×רי</string>
388 <string name="scaling_filter_bicubic">Bicubic</string>
389 <string name="scaling_filter_gaussian">Gaussian</string>
306 <string name="scaling_filter_scale_force">ScaleForce</string> 390 <string name="scaling_filter_scale_force">ScaleForce</string>
307 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string> 391 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string>
308 392
@@ -312,10 +396,9 @@
312 <string name="anti_aliasing_smaa">SMAA</string> 396 <string name="anti_aliasing_smaa">SMAA</string>
313 397
314 <!-- Screen Layouts --> 398 <!-- Screen Layouts -->
399 <string name="screen_layout_auto">×וטומטי</string>
315 <string name="screen_layout_landscape">לרוחב</string> 400 <string name="screen_layout_landscape">לרוחב</string>
316 <string name="screen_layout_portrait">ל×ורך</string> 401 <string name="screen_layout_portrait">ל×ורך</string>
317 <string name="screen_layout_auto">×וטומטי</string>
318
319 <!-- Aspect Ratios --> 402 <!-- Aspect Ratios -->
320 <string name="ratio_default">ברירת מחדל (16:9)</string> 403 <string name="ratio_default">ברירת מחדל (16:9)</string>
321 <string name="ratio_force_four_three">הכרח 4:3</string> 404 <string name="ratio_force_four_three">הכרח 4:3</string>
@@ -323,6 +406,10 @@
323 <string name="ratio_force_sixteen_ten">הכרח 16:10</string> 406 <string name="ratio_force_sixteen_ten">הכרח 16:10</string>
324 <string name="ratio_stretch">הרחב לגודל המסך</string> 407 <string name="ratio_stretch">הרחב לגודל המסך</string>
325 408
409 <!-- CPU Backend -->
410 <string name="cpu_backend_dynarmic">דינמי (×יטי)</string>
411 <string name="cpu_backend_nce">ביצוע קוד מקורי (NCE)</string>
412
326 <!-- CPU Accuracy --> 413 <!-- CPU Accuracy -->
327 <string name="cpu_accuracy_accurate">מדויק</string> 414 <string name="cpu_accuracy_accurate">מדויק</string>
328 <string name="cpu_accuracy_unsafe">×œ× ×‘×˜×•×—</string> 415 <string name="cpu_accuracy_unsafe">×œ× ×‘×˜×•×—</string>
@@ -335,6 +422,10 @@
335 <string name="gamepad_home">בית</string> 422 <string name="gamepad_home">בית</string>
336 <string name="gamepad_screenshot">×¦×™×œ×•× ×ž×¡×š</string> 423 <string name="gamepad_screenshot">×¦×™×œ×•× ×ž×¡×š</string>
337 424
425 <!-- Disk shader cache -->
426 <string name="preparing_shaders">מכין שיידרי×</string>
427 <string name="building_shaders">בונה שיידרי×</string>
428
338 <!-- Theme options --> 429 <!-- Theme options -->
339 <string name="change_app_theme">שנה ×ת × ×•×©× ×”×פליקצייה</string> 430 <string name="change_app_theme">שנה ×ת × ×•×©× ×”×פליקצייה</string>
340 <string name="theme_default">ברירת מחדל</string> 431 <string name="theme_default">ברירת מחדל</string>
@@ -346,9 +437,14 @@
346 <string name="theme_mode_light">בהיר</string> 437 <string name="theme_mode_light">בהיר</string>
347 <string name="theme_mode_dark">×›×”×”</string> 438 <string name="theme_mode_dark">×›×”×”</string>
348 439
349 <!-- Audio output engines -->
350 <string name="cubeb">cubeb</string> 440 <string name="cubeb">cubeb</string>
351 441
442 <!-- Anisotropic filtering options -->
443 <string name="multiplier_two">2x</string>
444 <string name="multiplier_four">4x</string>
445 <string name="multiplier_eight">8x</string>
446 <string name="multiplier_sixteen">16x</string>
447
352 <!-- Black backgrounds theme --> 448 <!-- Black backgrounds theme -->
353 <string name="use_black_backgrounds">×¨×§×¢×™× ×©×—×•×¨×™×</string> 449 <string name="use_black_backgrounds">×¨×§×¢×™× ×©×—×•×¨×™×</string>
354 <string name="use_black_backgrounds_description">×›×©×ž×ª×©×ž×©×™× ×‘×ž×¦×‘ ×›×”×”, ×©× ×¨×§×¢×™× ×©×—×•×¨×™×.</string> 450 <string name="use_black_backgrounds_description">×›×©×ž×ª×©×ž×©×™× ×‘×ž×¦×‘ ×›×”×”, ×©× ×¨×§×¢×™× ×©×—×•×¨×™×.</string>
diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml
index 6563ba288..554da0816 100644
--- a/src/android/app/src/main/res/values-hu/strings.xml
+++ b/src/android/app/src/main/res/values-hu/strings.xml
@@ -35,6 +35,7 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
35 <string name="empty_gamelist">Nem található fájl, vagy még nincs kiválasztva könyvtár.</string> 35 <string name="empty_gamelist">Nem található fájl, vagy még nincs kiválasztva könyvtár.</string>
36 <string name="search_and_filter_games">Játékok keresése és szűrése</string> 36 <string name="search_and_filter_games">Játékok keresése és szűrése</string>
37 <string name="select_games_folder">Játékmappa kiválasztása</string> 37 <string name="select_games_folder">Játékmappa kiválasztása</string>
38 <string name="manage_game_folders">Játékmappák kezelése</string>
38 <string name="add_games_warning">Kihagyod a játékok mappa kiválasztását?</string> 39 <string name="add_games_warning">Kihagyod a játékok mappa kiválasztását?</string>
39 <string name="add_games_warning_description">A játékok nem jelennek meg a Játékok listában, ha egy mappa nincs kijelölve.</string> 40 <string name="add_games_warning_description">A játékok nem jelennek meg a Játékok listában, ha egy mappa nincs kijelölve.</string>
40 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 41 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
@@ -68,6 +69,7 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
68 <string name="invalid_keys_error">Érvénytelen titkosítókulcsok</string> 69 <string name="invalid_keys_error">Érvénytelen titkosítókulcsok</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">A kiválasztott fájl helytelen, vagy sérült. Ãllíts össze egy új kulcsot.</string> 71 <string name="install_keys_failure_description">A kiválasztott fájl helytelen, vagy sérült. Ãllíts össze egy új kulcsot.</string>
72 <string name="gpu_driver_manager">GPU illesztőprogram-kezelő</string>
71 <string name="install_gpu_driver">GPU illesztőprogram telepítése</string> 73 <string name="install_gpu_driver">GPU illesztőprogram telepítése</string>
72 <string name="install_gpu_driver_description">Alternatív illesztőprogramok telepítése az esetlegesen elérhető teljesítmény és pontosság érdekében</string> 74 <string name="install_gpu_driver_description">Alternatív illesztőprogramok telepítése az esetlegesen elérhető teljesítmény és pontosság érdekében</string>
73 <string name="advanced_settings">Haladó beállítások</string> 75 <string name="advanced_settings">Haladó beállítások</string>
@@ -84,7 +86,11 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
84 <string name="notification_no_directory_link_description">Kérjük, manuálisan keresd meg a felhasználói mappát a fájlkezelő oldalsó paneljével.</string> 86 <string name="notification_no_directory_link_description">Kérjük, manuálisan keresd meg a felhasználói mappát a fájlkezelő oldalsó paneljével.</string>
85 <string name="manage_save_data">Mentésadatok kezelése</string> 87 <string name="manage_save_data">Mentésadatok kezelése</string>
86 <string name="manage_save_data_description">Mentés található. Kérjük, válassz egyet az alábbi opciók közül.</string> 88 <string name="manage_save_data_description">Mentés található. Kérjük, válassz egyet az alábbi opciók közül.</string>
89 <string name="import_save_warning">Mentési fájlok importálása</string>
90 <string name="import_save_warning_description">Ezzel felülírod a fájlban lévő mentett adatokat. Biztosan szeretnéd folytatni?</string>
87 <string name="import_export_saves_description">Mentési fájlok importálás vagy exportálása</string> 91 <string name="import_export_saves_description">Mentési fájlok importálás vagy exportálása</string>
92 <string name="save_files_importing">Mentési fájlok importálása...</string>
93 <string name="save_files_exporting">Mentési fájlok exportálása...</string>
88 <string name="save_file_imported_success">Sikeresen importálva</string> 94 <string name="save_file_imported_success">Sikeresen importálva</string>
89 <string name="save_file_invalid_zip_structure">Érvénytelen mentési könyvtárstruktúra</string> 95 <string name="save_file_invalid_zip_structure">Érvénytelen mentési könyvtárstruktúra</string>
90 <string name="save_file_invalid_zip_structure_description">Az első almappa neve a játék azonosítója kell, hogy legyen.</string> 96 <string name="save_file_invalid_zip_structure_description">Az első almappa neve a játék azonosítója kell, hogy legyen.</string>
@@ -117,6 +123,38 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
117 <string name="manage_yuzu_data_description">Firmware, kulcsok, felhasználói adatok és egyebek importálása/exportálása</string> 123 <string name="manage_yuzu_data_description">Firmware, kulcsok, felhasználói adatok és egyebek importálása/exportálása</string>
118 <string name="share_save_file">Mentési fájl megosztása</string> 124 <string name="share_save_file">Mentési fájl megosztása</string>
119 <string name="export_save_failed">A mentés exportálása sikertelen</string> 125 <string name="export_save_failed">A mentés exportálása sikertelen</string>
126 <string name="game_folders">Játékmappák</string>
127 <string name="deep_scan">Mély szkennelés</string>
128 <string name="add_game_folder">Játékmappa hozzáadása</string>
129 <string name="folder_already_added">Ez a mappa már hozzá lett adva!</string>
130 <string name="game_folder_properties">Játékmappa tulajdonságok</string>
131 <plurals name="saves_import_failed">
132 <item quantity="one">%dmentés importálása sikertelen</item>
133 <item quantity="other">%dmentés importálása sikertelen</item>
134 </plurals>
135 <plurals name="saves_import_success">
136 <item quantity="one">%dmentés sikeresen importálva</item>
137 <item quantity="other">%dmentés sikeresen importálva</item>
138 </plurals>
139 <string name="no_save_data_found">Nem található mentett adat</string>
140
141 <!-- Applet launcher strings -->
142 <string name="applets">Applet indító</string>
143 <string name="applets_description">Rendszer appletek indítása a telepített firmware-rel</string>
144 <string name="applets_error_firmware">Firmware nincs telepítve</string>
145 <string name="applets_error_applet">Applet nem elérhető</string>
146 <string name="applets_error_description"><![CDATA[Kérjük, győződj meg róla, hogy a <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> fájl és a <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> telepítve van, majd próbáld újra.]]></string>
147 <string name="album_applet">Album</string>
148 <string name="album_applet_description">Képernyőképek megtekintése a rendszer fényképnézegetőjével</string>
149 <string name="mii_edit_applet">Mii szerkesztés</string>
150 <string name="mii_edit_applet_description">Miik megtekintése és szerkesztése a rendszerszerkesztővel</string>
151 <string name="cabinet_applet">Kabinet</string>
152 <string name="cabinet_applet_description">Amiibon tárolt adatok szerkesztése és törlése</string>
153 <string name="cabinet_launcher">Kabinet indító</string>
154 <string name="cabinet_nickname_and_owner">Becenév és tulajdonos beállítások</string>
155 <string name="cabinet_game_data_eraser">Játékadat eltávolító</string>
156 <string name="cabinet_restorer">Helyreállító</string>
157 <string name="cabinet_formatter">Formázó</string>
120 158
121 <!-- About screen strings --> 159 <!-- About screen strings -->
122 <string name="gaia_is_not_real">Gaia nem valódi</string> 160 <string name="gaia_is_not_real">Gaia nem valódi</string>
@@ -158,6 +196,7 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
158 <string name="frame_limit_enable_description">Korlátozza az emuláció sebességét a normál sebesség adott százalékára.</string> 196 <string name="frame_limit_enable_description">Korlátozza az emuláció sebességét a normál sebesség adott százalékára.</string>
159 <string name="frame_limit_slider">Sebességkorlát százaléka</string> 197 <string name="frame_limit_slider">Sebességkorlát százaléka</string>
160 <string name="frame_limit_slider_description">Az emuláció sebességét határozza meg. 100% a normál sebesség. A magasabb értékek növelik, az alacsonyabbak csökkentik a sebességkorlátot.</string> 198 <string name="frame_limit_slider_description">Az emuláció sebességét határozza meg. 100% a normál sebesség. A magasabb értékek növelik, az alacsonyabbak csökkentik a sebességkorlátot.</string>
199 <string name="cpu_backend">CPU backend</string>
161 <string name="cpu_accuracy">CPU pontosság</string> 200 <string name="cpu_accuracy">CPU pontosság</string>
162 <string name="value_with_units">%1$s%2$s</string> 201 <string name="value_with_units">%1$s%2$s</string>
163 202
@@ -188,7 +227,7 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
188 <string name="renderer_reactive_flushing_description">Javítja a renderelési pontosságot néhány játékban a teljesítmény rovására.</string> 227 <string name="renderer_reactive_flushing_description">Javítja a renderelési pontosságot néhány játékban a teljesítmény rovására.</string>
189 <string name="use_disk_shader_cache">Lemez árnyékoló gyorsítótár</string> 228 <string name="use_disk_shader_cache">Lemez árnyékoló gyorsítótár</string>
190 <string name="use_disk_shader_cache_description">Csökkenti az akadásokat azáltal, hogy helyileg tárolja és tölti be a generált árnyékolókat.</string> 229 <string name="use_disk_shader_cache_description">Csökkenti az akadásokat azáltal, hogy helyileg tárolja és tölti be a generált árnyékolókat.</string>
191 230 <string name="anisotropic_filtering">Anizotropikus szűrés</string>
192 <!-- Debug settings strings --> 231 <!-- Debug settings strings -->
193 <string name="cpu">CPU</string> 232 <string name="cpu">CPU</string>
194 <string name="cpu_debug_mode">CPU hibakeresés</string> 233 <string name="cpu_debug_mode">CPU hibakeresés</string>
@@ -196,9 +235,9 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
196 <string name="gpu">GPU</string> 235 <string name="gpu">GPU</string>
197 <string name="renderer_api">API</string> 236 <string name="renderer_api">API</string>
198 <string name="renderer_debug">Grafikai hibakeresés</string> 237 <string name="renderer_debug">Grafikai hibakeresés</string>
199 <string name="renderer_debug_description">Lassú hibakeresési módba állítja a grafikus API-t .</string> 238 <string name="renderer_debug_description">Lassú hibakereső módba állítja a grafikus API-t .</string>
200 <!-- Audio settings strings --> 239 <!-- Audio settings strings -->
201 <string name="audio_output_engine">Kimeneti rendszer</string> 240 <string name="audio_output_engine">Kimeneti motor</string>
202 <string name="audio_volume">Hangerő</string> 241 <string name="audio_volume">Hangerő</string>
203 <string name="audio_volume_description">Hangkimenet hangerejének megadása</string> 242 <string name="audio_volume_description">Hangkimenet hangerejének megadása</string>
204 243
@@ -212,6 +251,7 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
212 <string name="shutting_down">Leállítás...</string> 251 <string name="shutting_down">Leállítás...</string>
213 <string name="reset_setting_confirmation">Szeretnéd visszaállítani a beállítások az alapértelmezett értékekre?</string> 252 <string name="reset_setting_confirmation">Szeretnéd visszaállítani a beállítások az alapértelmezett értékekre?</string>
214 <string name="reset_to_default">Alaphelyzetbe állítás</string> 253 <string name="reset_to_default">Alaphelyzetbe állítás</string>
254 <string name="reset_to_default_description">Visszaállítja a haladó beállításokat</string>
215 <string name="reset_all_settings">Alaphelyzetbe állítod a beállításokat?</string> 255 <string name="reset_all_settings">Alaphelyzetbe állítod a beállításokat?</string>
216 <string name="reset_all_settings_description">Minden haladó beállítás vissza lesz állítva az alapértelmezett konfigurációra. Ez a művelet nem vonható vissza.</string> 256 <string name="reset_all_settings_description">Minden haladó beállítás vissza lesz állítva az alapértelmezett konfigurációra. Ez a művelet nem vonható vissza.</string>
217 <string name="settings_reset">Beállítások alaphelyzetbe állítva</string> 257 <string name="settings_reset">Beállítások alaphelyzetbe állítva</string>
@@ -219,12 +259,24 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
219 <string name="learn_more">Tudj meg többet</string> 259 <string name="learn_more">Tudj meg többet</string>
220 <string name="auto">Automatikus</string> 260 <string name="auto">Automatikus</string>
221 <string name="submit">Küldés</string> 261 <string name="submit">Küldés</string>
222 <string name="string_null">Nulla</string> 262 <string name="string_null">Null</string>
223 <string name="string_import">Importálás</string> 263 <string name="string_import">Importálás</string>
224 <string name="export">Exportálás</string> 264 <string name="export">Exportálás</string>
225 <string name="export_failed">Exportálás sikertelen</string> 265 <string name="export_failed">Exportálás sikertelen</string>
226 <string name="import_failed">Importálás sikertelen</string> 266 <string name="import_failed">Importálás sikertelen</string>
227 <string name="cancelling">Megszakítás</string> 267 <string name="cancelling">Megszakítás</string>
268 <string name="install">Telepítés</string>
269 <string name="delete">Törlés</string>
270 <string name="edit">Szerkesztés</string>
271 <string name="export_success">Sikeresen exportálva</string>
272 <string name="start">Start</string>
273 <string name="clear">Törlés</string>
274 <string name="global">Globális</string>
275 <string name="custom">Egyéni</string>
276 <string name="notice">Értesítés</string>
277 <string name="import_complete">Importálás befejezve</string>
278 <string name="more_options">További opciók</string>
279 <string name="use_global_setting">Globális beállítás használata</string>
228 280
229 <!-- GPU driver installation --> 281 <!-- GPU driver installation -->
230 <string name="select_gpu_driver">Válassz GPU illesztőprogramot</string> 282 <string name="select_gpu_driver">Válassz GPU illesztőprogramot</string>
@@ -232,7 +284,8 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
232 <string name="select_gpu_driver_install">Telepítés</string> 284 <string name="select_gpu_driver_install">Telepítés</string>
233 <string name="select_gpu_driver_default">Alapértelmezett</string> 285 <string name="select_gpu_driver_default">Alapértelmezett</string>
234 <string name="select_gpu_driver_use_default">Alapértelmezett GPU illesztőprogram használata</string> 286 <string name="select_gpu_driver_use_default">Alapértelmezett GPU illesztőprogram használata</string>
235 <string name="select_gpu_driver_error">Érvénytelen driver kiválasztva, a rendszer alapértelmezett lesz használva!</string> 287 <string name="select_gpu_driver_error">Érvénytelen illesztőprogram kiválasztva</string>
288 <string name="driver_already_installed">Az illesztőprogram már telepítve van</string>
236 <string name="system_gpu_driver">Rendszer GPU illesztőprogram</string> 289 <string name="system_gpu_driver">Rendszer GPU illesztőprogram</string>
237 <string name="installing_driver">Illesztőprogram telepítése...</string> 290 <string name="installing_driver">Illesztőprogram telepítése...</string>
238 291
@@ -240,10 +293,54 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
240 <string name="preferences_settings">Beállítások</string> 293 <string name="preferences_settings">Beállítások</string>
241 <string name="preferences_general">Ãltalános</string> 294 <string name="preferences_general">Ãltalános</string>
242 <string name="preferences_system">Rendszer</string> 295 <string name="preferences_system">Rendszer</string>
296 <string name="preferences_system_description">Dokkolt mód, régió, nyelv</string>
243 <string name="preferences_graphics">Grafika</string> 297 <string name="preferences_graphics">Grafika</string>
298 <string name="preferences_graphics_description">Pontossági szint, felbontás, árnyékoló gyorsítótár</string>
244 <string name="preferences_audio">Hang</string> 299 <string name="preferences_audio">Hang</string>
300 <string name="preferences_audio_description">Kimeneti motor, hangerő</string>
245 <string name="preferences_theme">Téma és színek</string> 301 <string name="preferences_theme">Téma és színek</string>
246 <string name="preferences_debug">Hibakeresés</string> 302 <string name="preferences_debug">Hibakeresés</string>
303 <string name="preferences_debug_description">CPU/GPU hibakeresés, grafikus API, fastmem</string>
304
305 <!-- Game properties -->
306 <string name="info">Infó</string>
307 <string name="info_description">Program ID, fejlesztő, verzió</string>
308 <string name="per_game_settings">Játékonkénti beállítások</string>
309 <string name="per_game_settings_description">Játékspecifikus beállítások szerkesztése</string>
310 <string name="launch_options">Indítási konfiguráció</string>
311 <string name="path">Útvonal</string>
312 <string name="program_id">Program ID</string>
313 <string name="developer">Fejlesztő</string>
314 <string name="version">Verzió</string>
315 <string name="copy_details">Részletek másolása</string>
316 <string name="add_ons">Kiegészítők</string>
317 <string name="add_ons_description">Modok, frissítések és DLC váltása</string>
318 <string name="clear_shader_cache">Ãrnyékoló gyorsítótár ürítése</string>
319 <string name="clear_shader_cache_description">Eltávolítja a játék által létrehozott árnyékolókat.</string>
320 <string name="clear_shader_cache_warning_description">Az árnyékoló gyorsítótár regenerálódása során több akadozást fogsz tapasztalni.</string>
321 <string name="cleared_shaders_successfully">Ãrnyékolók sikeresen ürítve</string>
322 <string name="addons_game">Kiegészítők: %1$s</string>
323 <string name="save_data">Mentett adatok</string>
324 <string name="save_data_description">Játékspecifikus mentett adatok kezelése</string>
325 <string name="delete_save_data">Mentett adatok törlése</string>
326 <string name="delete_save_data_description">Eltávolítja az összes játékhoz tartozó mentett adatot.</string>
327 <string name="delete_save_data_warning_description">Ez helyreállíthatatlanul eltávolítja a játék összes mentett adatát. Biztosan szeretnéd folytatni?</string>
328 <string name="save_data_deleted_successfully">Mentett adatok sikeresen törölve</string>
329 <string name="select_content_type">Tartalom típusa</string>
330 <string name="updates_and_dlc">Frissítések és DLC</string>
331 <string name="mods_and_cheats">Modok és csalások</string>
332 <string name="addon_notice">Fontos kiegészítő értesítés</string>
333 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
334 <string name="addon_notice_description">A modok és csalások telepítéséhez olyan mappát válassz, amely tartalmaz cheats/, romfs/ vagy exefs/ könyvtárat. Nem tudjuk garantálni, hogy ezek kompatibilisek lesznek a játékoddal, ezért légy óvatos!</string>
335 <string name="invalid_directory">Érvénytelen könyvtár</string>
336 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
337 <string name="invalid_directory_description">Kérjük, győződj meg róla, hogy a kiválasztott könyvtár tartalmazza a cheats/, romfs/ vagy exefs/ mappát, majd próbáld újra.</string>
338 <string name="addon_installed_successfully">Kiegészítő sikeresen telepítve</string>
339 <string name="verifying_content">Tartalom ellenőrzése...</string>
340 <string name="content_install_notice">Tartalom telepítési értesítés</string>
341 <string name="content_install_notice_description">A kiválasztott tartalom nem ehhez a játékhoz tartozik.\nÃgy is telepíted?</string>
342 <string name="confirm_uninstall">Eltávolítás megerősítése</string>
343 <string name="confirm_uninstall_description">Biztosan törölni szeretnéd ezt a kiegészítőt?</string>
247 344
248 <!-- ROM loading errors --> 345 <!-- ROM loading errors -->
249 <string name="loader_error_encrypted">ROM titkosítva</string> 346 <string name="loader_error_encrypted">ROM titkosítva</string>
@@ -270,6 +367,7 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
270 <string name="emulation_pause">Emuláció szünetelése</string> 367 <string name="emulation_pause">Emuláció szünetelése</string>
271 <string name="emulation_unpause">Emuláció folytatása</string> 368 <string name="emulation_unpause">Emuláció folytatása</string>
272 <string name="emulation_input_overlay">Ãtfedés beállításai</string> 369 <string name="emulation_input_overlay">Ãtfedés beállításai</string>
370 <string name="touchscreen">Érintőképernyő</string>
273 371
274 <string name="load_settings">Beállítások betöltése...</string> 372 <string name="load_settings">Beállítások betöltése...</string>
275 373
@@ -301,6 +399,7 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
301 399
302 <!-- Memory Sizes --> 400 <!-- Memory Sizes -->
303 <string name="memory_byte">Bájt</string> 401 <string name="memory_byte">Bájt</string>
402 <string name="memory_byte_shorthand">B</string>
304 <string name="memory_kilobyte">KB</string> 403 <string name="memory_kilobyte">KB</string>
305 <string name="memory_megabyte">MB</string> 404 <string name="memory_megabyte">MB</string>
306 <string name="memory_gigabyte">GB</string> 405 <string name="memory_gigabyte">GB</string>
@@ -345,9 +444,11 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
345 <string name="anti_aliasing_smaa">SMAA</string> 444 <string name="anti_aliasing_smaa">SMAA</string>
346 445
347 <!-- Screen Layouts --> 446 <!-- Screen Layouts -->
447 <string name="screen_layout_auto">Automatikus</string>
348 <string name="screen_layout_landscape">Fekvő</string> 448 <string name="screen_layout_landscape">Fekvő</string>
449 <string name="screen_layout_reverse_landscape">Fekvő (fejjel lefelé)</string>
349 <string name="screen_layout_portrait">Ãlló</string> 450 <string name="screen_layout_portrait">Ãlló</string>
350 <string name="screen_layout_auto">Automatikus</string> 451 <string name="screen_layout_reverse_portrait">Ãlló (fejjel lefelé)</string>
351 452
352 <!-- Aspect Ratios --> 453 <!-- Aspect Ratios -->
353 <string name="ratio_default">Alapértelmezett (16:9)</string> 454 <string name="ratio_default">Alapértelmezett (16:9)</string>
@@ -356,6 +457,8 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
356 <string name="ratio_force_sixteen_ten">16:10 kényszerítése</string> 457 <string name="ratio_force_sixteen_ten">16:10 kényszerítése</string>
357 <string name="ratio_stretch">Ablakhoz nyújtás</string> 458 <string name="ratio_stretch">Ablakhoz nyújtás</string>
358 459
460 <!-- CPU Backend -->
461 <string name="cpu_backend_dynarmic">Dinamikus (lassú)</string>
359 <!-- CPU Accuracy --> 462 <!-- CPU Accuracy -->
360 <string name="cpu_accuracy_accurate">Pontos</string> 463 <string name="cpu_accuracy_accurate">Pontos</string>
361 <string name="cpu_accuracy_unsafe">Nem biztonságos</string> 464 <string name="cpu_accuracy_unsafe">Nem biztonságos</string>
@@ -382,8 +485,15 @@ Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
382 <string name="theme_mode_dark">Sötét</string> 485 <string name="theme_mode_dark">Sötét</string>
383 486
384 <!-- Audio output engines --> 487 <!-- Audio output engines -->
488 <string name="oboe">oboe</string>
385 <string name="cubeb">cubeb</string> 489 <string name="cubeb">cubeb</string>
386 490
491 <!-- Anisotropic filtering options -->
492 <string name="multiplier_two">2x</string>
493 <string name="multiplier_four">4x</string>
494 <string name="multiplier_eight">8x</string>
495 <string name="multiplier_sixteen">16x</string>
496
387 <!-- Black backgrounds theme --> 497 <!-- Black backgrounds theme -->
388 <string name="use_black_backgrounds">Fekete háttér</string> 498 <string name="use_black_backgrounds">Fekete háttér</string>
389 <string name="use_black_backgrounds_description">Sötét téma használatakor fekete háttér használata.</string> 499 <string name="use_black_backgrounds_description">Sötét téma használatakor fekete háttér használata.</string>
diff --git a/src/android/app/src/main/res/values-it/strings.xml b/src/android/app/src/main/res/values-it/strings.xml
index 5afebb4c4..61b39f57f 100644
--- a/src/android/app/src/main/res/values-it/strings.xml
+++ b/src/android/app/src/main/res/values-it/strings.xml
@@ -17,7 +17,7 @@
17 <string name="keys_description">Seleziona il tuo file &lt;b>prod.keys&lt;/b> con il pulsante in basso.</string> 17 <string name="keys_description">Seleziona il tuo file &lt;b>prod.keys&lt;/b> con il pulsante in basso.</string>
18 <string name="select_keys">Seleziona le chiavi</string> 18 <string name="select_keys">Seleziona le chiavi</string>
19 <string name="games">Giochi</string> 19 <string name="games">Giochi</string>
20 <string name="games_description">Seleziona la cartella &lt;b>Games&lt;/b> con il pulsante in basso.</string> 20 <string name="games_description">Seleziona la cartella dei &lt;b>giochi&lt;/b> con il pulsante in basso.</string>
21 <string name="done">Fatto</string> 21 <string name="done">Fatto</string>
22 <string name="done_description">È tutto pronto.\nDivertiti a giocare!</string> 22 <string name="done_description">È tutto pronto.\nDivertiti a giocare!</string>
23 <string name="text_continue">Continua</string> 23 <string name="text_continue">Continua</string>
@@ -33,7 +33,7 @@
33 <string name="home_settings">Impostazioni</string> 33 <string name="home_settings">Impostazioni</string>
34 <string name="empty_gamelist">Non sono stati trovati file o non è stata ancora selezionata alcuna directory di gioco.</string> 34 <string name="empty_gamelist">Non sono stati trovati file o non è stata ancora selezionata alcuna directory di gioco.</string>
35 <string name="search_and_filter_games">Cerca e filtra i giochi</string> 35 <string name="search_and_filter_games">Cerca e filtra i giochi</string>
36 <string name="select_games_folder">Seleziona la cartella di gioco</string> 36 <string name="select_games_folder">Seleziona la cartella dei giochi</string>
37 <string name="select_games_folder_description">Consente a yuzu di popolare l\'elenco dei giochi</string> 37 <string name="select_games_folder_description">Consente a yuzu di popolare l\'elenco dei giochi</string>
38 <string name="add_games_warning">Saltare la selezione della cartella dei giochi?</string> 38 <string name="add_games_warning">Saltare la selezione della cartella dei giochi?</string>
39 <string name="add_games_warning_description">I giochi non saranno mostrati nella lista dei giochi se una cartella non è selezionata.</string> 39 <string name="add_games_warning_description">I giochi non saranno mostrati nella lista dei giochi se una cartella non è selezionata.</string>
@@ -68,6 +68,7 @@
68 <string name="invalid_keys_error">Chiavi di crittografia non valide</string> 68 <string name="invalid_keys_error">Chiavi di crittografia non valide</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">Il file selezionato è incorretto o corrotto. Per favore riesegui il dump delle tue chiavi.</string> 70 <string name="install_keys_failure_description">Il file selezionato è incorretto o corrotto. Per favore riesegui il dump delle tue chiavi.</string>
71 <string name="gpu_driver_manager">Gestore driver GPU</string>
71 <string name="install_gpu_driver">Installa i driver GPU</string> 72 <string name="install_gpu_driver">Installa i driver GPU</string>
72 <string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string> 73 <string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string>
73 <string name="advanced_settings">Impostazioni avanzate</string> 74 <string name="advanced_settings">Impostazioni avanzate</string>
@@ -118,6 +119,23 @@
118 <string name="manage_yuzu_data_description">Importa/Esporta il firmware, le keys, i dati utente, e altro!</string> 119 <string name="manage_yuzu_data_description">Importa/Esporta il firmware, le keys, i dati utente, e altro!</string>
119 <string name="share_save_file">Condividi i tuoi dati di salvataggio</string> 120 <string name="share_save_file">Condividi i tuoi dati di salvataggio</string>
120 <string name="export_save_failed">Errore durante l\'esportazione del salvataggio</string> 121 <string name="export_save_failed">Errore durante l\'esportazione del salvataggio</string>
122 <!-- Applet launcher strings -->
123 <string name="applets">Avvia applet</string>
124 <string name="applets_description">Avvia applet di sistema usando il firmware installato</string>
125 <string name="applets_error_firmware">Firmware non installato</string>
126 <string name="applets_error_applet">Applet non disponibile</string>
127 <string name="applets_error_description"><![CDATA[Assicurati che il file <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> e il <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> siano installati e riprova.]]></string>
128 <string name="album_applet">Album</string>
129 <string name="album_applet_description">Visualizza le immagini salvate nella cartella screenshots dell\'utente con il visualizzatore immagini di sistema</string>
130 <string name="mii_edit_applet">Modifica Mii</string>
131 <string name="mii_edit_applet_description">Visualizza e modifica Mii con l\'editor di sistema</string>
132 <string name="cabinet_applet">Cabinet</string>
133 <string name="cabinet_applet_description">Modifica ed elimina i dati salvati sugli amiibo</string>
134 <string name="cabinet_launcher">Avvia Cabinet</string>
135 <string name="cabinet_nickname_and_owner">Impostazioni nickname e proprietario</string>
136 <string name="cabinet_game_data_eraser">Cancella dati di gioco</string>
137 <string name="cabinet_restorer">Ripristina</string>
138 <string name="cabinet_formatter">Formatta</string>
121 139
122 <!-- About screen strings --> 140 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia non è reale</string> 141 <string name="gaia_is_not_real">Gaia non è reale</string>
@@ -191,7 +209,6 @@
191 <string name="renderer_reactive_flushing_description">Migliora l\'accuratezza della grafica in alcuni giochi, al costo delle performance.</string> 209 <string name="renderer_reactive_flushing_description">Migliora l\'accuratezza della grafica in alcuni giochi, al costo delle performance.</string>
192 <string name="use_disk_shader_cache">Usa la cache delle shader</string> 210 <string name="use_disk_shader_cache">Usa la cache delle shader</string>
193 <string name="use_disk_shader_cache_description">Riduce lo stuttering caricando le shader già compilate all\'avvio.</string> 211 <string name="use_disk_shader_cache_description">Riduce lo stuttering caricando le shader già compilate all\'avvio.</string>
194
195 <!-- Debug settings strings --> 212 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string> 213 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">Debug della CPU</string> 214 <string name="cpu_debug_mode">Debug della CPU</string>
@@ -230,14 +247,19 @@
230 <string name="export_failed">Esportazione Fallita</string> 247 <string name="export_failed">Esportazione Fallita</string>
231 <string name="import_failed">Importazione Fallita</string> 248 <string name="import_failed">Importazione Fallita</string>
232 <string name="cancelling">Cancellazione</string> 249 <string name="cancelling">Cancellazione</string>
233 250 <string name="install">Installa</string>
251 <string name="delete">Elimina</string>
252 <string name="start">Start</string>
253 <string name="clear">Cancella</string>
254 <string name="custom">Personalizzato</string>
234 <!-- GPU driver installation --> 255 <!-- GPU driver installation -->
235 <string name="select_gpu_driver">Seleziona il driver della GPU</string> 256 <string name="select_gpu_driver">Seleziona il driver della GPU</string>
236 <string name="select_gpu_driver_title">Vuoi sostituire il driver della tua GPU attuale?</string> 257 <string name="select_gpu_driver_title">Vuoi sostituire il driver della tua GPU attuale?</string>
237 <string name="select_gpu_driver_install">Installa</string> 258 <string name="select_gpu_driver_install">Installa</string>
238 <string name="select_gpu_driver_default">Predefinito</string> 259 <string name="select_gpu_driver_default">Predefinito</string>
239 <string name="select_gpu_driver_use_default">Utilizza il driver predefinito della GPU.</string> 260 <string name="select_gpu_driver_use_default">Utilizza il driver predefinito della GPU.</string>
240 <string name="select_gpu_driver_error">Il driver selezionato è invalido, è in utilizzo quello predefinito di sistema!</string> 261 <string name="select_gpu_driver_error">Driver selezionato non valido</string>
262 <string name="driver_already_installed">Driver già installato</string>
241 <string name="system_gpu_driver">Driver GPU del sistema</string> 263 <string name="system_gpu_driver">Driver GPU del sistema</string>
242 <string name="installing_driver">Installando i driver...</string> 264 <string name="installing_driver">Installando i driver...</string>
243 265
@@ -249,7 +271,12 @@
249 <string name="preferences_audio">Audio</string> 271 <string name="preferences_audio">Audio</string>
250 <string name="preferences_theme">Tema e colori</string> 272 <string name="preferences_theme">Tema e colori</string>
251 <string name="preferences_debug">Debug</string> 273 <string name="preferences_debug">Debug</string>
252 274 <!-- Game properties -->
275 <string name="info">Info</string>
276 <string name="path">Percorso</string>
277 <string name="developer">Sviluppatore</string>
278 <string name="version">Versione</string>
279 <string name="add_ons">Add-on</string>
253 <!-- ROM loading errors --> 280 <!-- ROM loading errors -->
254 <string name="loader_error_encrypted">La tua ROM è criptata</string> 281 <string name="loader_error_encrypted">La tua ROM è criptata</string>
255 <string name="loader_error_encrypted_roms_description"><![CDATA[Segui la nostra guida per fare il <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">dump delle tue cartucce di gioco</a>oppure <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">dei titoli già installati</a>.]]></string> 282 <string name="loader_error_encrypted_roms_description"><![CDATA[Segui la nostra guida per fare il <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">dump delle tue cartucce di gioco</a>oppure <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">dei titoli già installati</a>.]]></string>
@@ -263,20 +290,21 @@
263 <string name="emulation_exit">Arresta emulazione</string> 290 <string name="emulation_exit">Arresta emulazione</string>
264 <string name="emulation_done">Fatto</string> 291 <string name="emulation_done">Fatto</string>
265 <string name="emulation_fps_counter">Contatore FPS</string> 292 <string name="emulation_fps_counter">Contatore FPS</string>
266 <string name="emulation_toggle_controls">Controlli a interruttore</string> 293 <string name="emulation_toggle_controls">Attiva/disattiva comandi</string>
267 <string name="emulation_rel_stick_center">Centro relativo degli Stick</string> 294 <string name="emulation_rel_stick_center">Centro relativo degli Stick</string>
268 <string name="emulation_dpad_slide">DPad A Scorrimento</string> 295 <string name="emulation_dpad_slide">DPad A Scorrimento</string>
269 <string name="emulation_haptics">Feedback Aptico</string> 296 <string name="emulation_haptics">Feedback Aptico</string>
270 <string name="emulation_show_overlay">Mostra l\'Overlay</string> 297 <string name="emulation_show_overlay">Mostra l\'overlay</string>
271 <string name="emulation_toggle_all">Attiva/Disattiva tutto</string> 298 <string name="emulation_toggle_all">Attiva/Disattiva tutto</string>
272 <string name="emulation_control_adjust">Modifica l\'Overlay</string> 299 <string name="emulation_control_adjust">Regola l\'overlay</string>
273 <string name="emulation_control_scale">Scala</string> 300 <string name="emulation_control_scale">Scala</string>
274 <string name="emulation_control_opacity">Opacità</string> 301 <string name="emulation_control_opacity">Opacità</string>
275 <string name="emulation_touch_overlay_reset">Reimposta l\'Overlay</string> 302 <string name="emulation_touch_overlay_reset">Reimposta l\'overlay</string>
276 <string name="emulation_touch_overlay_edit">Modifica l\'Overlay</string> 303 <string name="emulation_touch_overlay_edit">Modifica l\'overlay</string>
277 <string name="emulation_pause">Sospendi l\'emulazione</string> 304 <string name="emulation_pause">Sospendi l\'emulazione</string>
278 <string name="emulation_unpause">Riprendi l\'emulazione</string> 305 <string name="emulation_unpause">Riprendi l\'emulazione</string>
279 <string name="emulation_input_overlay">Opzioni overlay</string> 306 <string name="emulation_input_overlay">Opzioni overlay</string>
307 <string name="touchscreen">Touchscreen</string>
280 308
281 <string name="load_settings">Carico le impostazioni...</string> 309 <string name="load_settings">Carico le impostazioni...</string>
282 310
@@ -308,6 +336,7 @@
308 336
309 <!-- Memory Sizes --> 337 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string> 338 <string name="memory_byte">Byte</string>
339 <string name="memory_byte_shorthand">B</string>
311 <string name="memory_kilobyte">Kb</string> 340 <string name="memory_kilobyte">Kb</string>
312 <string name="memory_megabyte">Mb</string> 341 <string name="memory_megabyte">Mb</string>
313 <string name="memory_gigabyte">GB</string> 342 <string name="memory_gigabyte">GB</string>
@@ -352,10 +381,9 @@
352 <string name="anti_aliasing_smaa">SMAA</string> 381 <string name="anti_aliasing_smaa">SMAA</string>
353 382
354 <!-- Screen Layouts --> 383 <!-- Screen Layouts -->
384 <string name="screen_layout_auto">Automatico</string>
355 <string name="screen_layout_landscape">Layout Orizzontale</string> 385 <string name="screen_layout_landscape">Layout Orizzontale</string>
356 <string name="screen_layout_portrait">Layout Verticale</string> 386 <string name="screen_layout_portrait">Layout Verticale</string>
357 <string name="screen_layout_auto">Automatico</string>
358
359 <!-- Aspect Ratios --> 387 <!-- Aspect Ratios -->
360 <string name="ratio_default">Predefinito (16:9)</string> 388 <string name="ratio_default">Predefinito (16:9)</string>
361 <string name="ratio_force_four_three">Forza 4:3</string> 389 <string name="ratio_force_four_three">Forza 4:3</string>
@@ -390,9 +418,14 @@
390 <string name="theme_mode_light">Chiaro</string> 418 <string name="theme_mode_light">Chiaro</string>
391 <string name="theme_mode_dark">Scuro</string> 419 <string name="theme_mode_dark">Scuro</string>
392 420
393 <!-- Audio output engines -->
394 <string name="cubeb">cubeb</string> 421 <string name="cubeb">cubeb</string>
395 422
423 <!-- Anisotropic filtering options -->
424 <string name="multiplier_two">2x</string>
425 <string name="multiplier_four">4x</string>
426 <string name="multiplier_eight">8x</string>
427 <string name="multiplier_sixteen">16x</string>
428
396 <!-- Black backgrounds theme --> 429 <!-- Black backgrounds theme -->
397 <string name="use_black_backgrounds">Sfondi neri</string> 430 <string name="use_black_backgrounds">Sfondi neri</string>
398 <string name="use_black_backgrounds_description">Quando utilizzi il tema scuro, applica sfondi neri.</string> 431 <string name="use_black_backgrounds_description">Quando utilizzi il tema scuro, applica sfondi neri.</string>
diff --git a/src/android/app/src/main/res/values-ja/strings.xml b/src/android/app/src/main/res/values-ja/strings.xml
index 3be4e7d26..0cff40bb6 100644
--- a/src/android/app/src/main/res/values-ja/strings.xml
+++ b/src/android/app/src/main/res/values-ja/strings.xml
@@ -39,7 +39,7 @@
39 <string name="add_games_warning_description">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ãªã„ã¨ã€ã‚²ãƒ¼ãƒ ãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•れã¾ã›ã‚“。</string> 39 <string name="add_games_warning_description">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ãªã„ã¨ã€ã‚²ãƒ¼ãƒ ãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•れã¾ã›ã‚“。</string>
40 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 40 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
41 <string name="home_search_games">ゲームを検索</string> 41 <string name="home_search_games">ゲームを検索</string>
42 <string name="search_settings">検索設定</string> 42 <string name="search_settings">設定を検索</string>
43 <string name="games_dir_selected">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¾ã—ãŸ</string> 43 <string name="games_dir_selected">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¾ã—ãŸ</string>
44 <string name="install_prod_keys">prod.keys</string> 44 <string name="install_prod_keys">prod.keys</string>
45 <string name="install_prod_keys_description">製å“版ゲームã®å¾©å·åŒ–ã«å¿…è¦ã§ã™</string> 45 <string name="install_prod_keys_description">製å“版ゲームã®å¾©å·åŒ–ã«å¿…è¦ã§ã™</string>
@@ -68,6 +68,7 @@
68 <string name="invalid_keys_error">æš—å·åŒ–キーãŒç„¡åй</string> 68 <string name="invalid_keys_error">æš—å·åŒ–キーãŒç„¡åй</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">ファイルãŒé–“é•ã£ã¦ã„ã‚‹ã‹ç ´æã—ã¦ã„ã¾ã™ã€‚キーをå†ãƒ€ãƒ³ãƒ—ã—ã¦ãã ã•ã„。</string> 70 <string name="install_keys_failure_description">ファイルãŒé–“é•ã£ã¦ã„ã‚‹ã‹ç ´æã—ã¦ã„ã¾ã™ã€‚キーをå†ãƒ€ãƒ³ãƒ—ã—ã¦ãã ã•ã„。</string>
71 <string name="gpu_driver_manager">GPUドライãƒãƒ¼ã®ç®¡ç†</string>
71 <string name="install_gpu_driver">GPUドライãƒãƒ¼</string> 72 <string name="install_gpu_driver">GPUドライãƒãƒ¼</string>
72 <string name="install_gpu_driver_description">代替ドライãƒãƒ¼ã‚’インストールã—ã¦ãƒ‘フォーマンスや精度をå‘上ã•ã›ã¾ã™</string> 73 <string name="install_gpu_driver_description">代替ドライãƒãƒ¼ã‚’インストールã—ã¦ãƒ‘フォーマンスや精度をå‘上ã•ã›ã¾ã™</string>
73 <string name="advanced_settings">高度ãªè¨­å®š</string> 74 <string name="advanced_settings">高度ãªè¨­å®š</string>
@@ -111,6 +112,9 @@
111 <string name="custom_driver_not_supported">カスタムドライãƒã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“</string> 112 <string name="custom_driver_not_supported">カスタムドライãƒã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“</string>
112 <string name="manage_yuzu_data">yuzu データを管ç†</string> 113 <string name="manage_yuzu_data">yuzu データを管ç†</string>
113 <string name="share_save_file">セーブファイルを共有</string> 114 <string name="share_save_file">セーブファイルを共有</string>
115 <string name="applets_error_firmware">ファームウェア未インストール</string>
116 <string name="album_applet">アルãƒãƒ </string>
117 <string name="cabinet_nickname_and_owner">ニックãƒãƒ¼ãƒ ã¨æ‰€æœ‰è€…ã®è¨­å®š</string>
114 <!-- About screen strings --> 118 <!-- About screen strings -->
115 <string name="gaia_is_not_real">ガイアã¯å®Ÿåœ¨ã—ãªã„</string> 119 <string name="gaia_is_not_real">ガイアã¯å®Ÿåœ¨ã—ãªã„</string>
116 <string name="copied_to_clipboard">クリップボードã«ã‚³ãƒ”ーã—ã¾ã—ãŸ</string> 120 <string name="copied_to_clipboard">クリップボードã«ã‚³ãƒ”ーã—ã¾ã—ãŸ</string>
@@ -178,10 +182,9 @@
178 <string name="renderer_reactive_flushing_description">一部ã®ã‚²ãƒ¼ãƒ ã«ãŠã„ã¦ã€ãƒ‘フォーマンスを犠牲ã«ã—ãªãŒã‚‰ã‚‚ã€ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ç²¾åº¦ã‚’å‘上ã•ã›ã¾ã™ã€‚</string> 182 <string name="renderer_reactive_flushing_description">一部ã®ã‚²ãƒ¼ãƒ ã«ãŠã„ã¦ã€ãƒ‘フォーマンスを犠牲ã«ã—ãªãŒã‚‰ã‚‚ã€ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ç²¾åº¦ã‚’å‘上ã•ã›ã¾ã™ã€‚</string>
179 <string name="use_disk_shader_cache">ディスクシェーダーキャッシュ</string> 183 <string name="use_disk_shader_cache">ディスクシェーダーキャッシュ</string>
180 <string name="use_disk_shader_cache_description">生æˆã—ãŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã‚’端末ã«ä¿å­˜ã—ã¦èª­ã¿è¾¼ã¿ã€ã‚³ãƒžè½ã¡ã‚’軽減ã—ã¾ã™ã€‚</string> 184 <string name="use_disk_shader_cache_description">生æˆã—ãŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã‚’端末ã«ä¿å­˜ã—ã¦èª­ã¿è¾¼ã¿ã€ã‚³ãƒžè½ã¡ã‚’軽減ã—ã¾ã™ã€‚</string>
181
182 <!-- Debug settings strings --> 185 <!-- Debug settings strings -->
183 <string name="cpu">CPU</string> 186 <string name="cpu">CPU</string>
184 <string name="cpu_debug_mode">CPU デãƒãƒƒã‚®ãƒ³ã‚°</string> 187 <string name="cpu_debug_mode">CPUデãƒãƒƒã‚°</string>
185 <string name="gpu">GPU</string> 188 <string name="gpu">GPU</string>
186 <string name="renderer_api">API</string> 189 <string name="renderer_api">API</string>
187 <string name="renderer_debug">グラフィックデãƒãƒƒã‚°</string> 190 <string name="renderer_debug">グラフィックデãƒãƒƒã‚°</string>
@@ -215,14 +218,17 @@
215 <string name="export_failed">エクスãƒãƒ¼ãƒˆå¤±æ•—</string> 218 <string name="export_failed">エクスãƒãƒ¼ãƒˆå¤±æ•—</string>
216 <string name="import_failed">インãƒãƒ¼ãƒˆå¤±æ•—</string> 219 <string name="import_failed">インãƒãƒ¼ãƒˆå¤±æ•—</string>
217 <string name="cancelling">キャンセル中</string> 220 <string name="cancelling">キャンセル中</string>
218 221 <string name="install">インストール</string>
222 <string name="delete">削除</string>
223 <string name="start">é–‹å§‹</string>
224 <string name="clear">クリア</string>
225 <string name="custom">カスタム</string>
219 <!-- GPU driver installation --> 226 <!-- GPU driver installation -->
220 <string name="select_gpu_driver">GPUドライãƒã‚’é¸æŠž</string> 227 <string name="select_gpu_driver">GPUドライãƒã‚’é¸æŠž</string>
221 <string name="select_gpu_driver_title">ç¾åœ¨ã®GPUドライãƒã‚’ç½®ãæ›ãˆã¾ã™ã‹ï¼Ÿ</string> 228 <string name="select_gpu_driver_title">ç¾åœ¨ã®GPUドライãƒã‚’ç½®ãæ›ãˆã¾ã™ã‹ï¼Ÿ</string>
222 <string name="select_gpu_driver_install">インストール</string> 229 <string name="select_gpu_driver_install">インストール</string>
223 <string name="select_gpu_driver_default">デフォルト</string> 230 <string name="select_gpu_driver_default">デフォルト</string>
224 <string name="select_gpu_driver_use_default">デフォルトã®ãƒ‰ãƒ©ã‚¤ãƒã‚’使用ã—ã¾ã™</string> 231 <string name="select_gpu_driver_use_default">デフォルトã®ãƒ‰ãƒ©ã‚¤ãƒã‚’使用ã—ã¾ã™</string>
225 <string name="select_gpu_driver_error">é¸æŠžã•れãŸãƒ‰ãƒ©ã‚¤ãƒãŒç„¡åйã€ã‚·ã‚¹ãƒ†ãƒ ã®ãƒ‡ãƒ•ォルトを使用ã—ã¾ã™!</string>
226 <string name="system_gpu_driver">システムã®GPUドライãƒ</string> 232 <string name="system_gpu_driver">システムã®GPUドライãƒ</string>
227 <string name="installing_driver">インストール中…</string> 233 <string name="installing_driver">インストール中…</string>
228 234
@@ -234,7 +240,12 @@
234 <string name="preferences_audio">サウンド</string> 240 <string name="preferences_audio">サウンド</string>
235 <string name="preferences_theme">テーマã¨è‰²</string> 241 <string name="preferences_theme">テーマã¨è‰²</string>
236 <string name="preferences_debug">デãƒãƒƒã‚°</string> 242 <string name="preferences_debug">デãƒãƒƒã‚°</string>
237 243 <!-- Game properties -->
244 <string name="info">情報</string>
245 <string name="path">パス</string>
246 <string name="developer">開発元</string>
247 <string name="version">ãƒãƒ¼ã‚¸ãƒ§ãƒ³</string>
248 <string name="add_ons">アドオン</string>
238 <!-- ROM loading errors --> 249 <!-- ROM loading errors -->
239 <string name="loader_error_encrypted">ROMãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™</string> 250 <string name="loader_error_encrypted">ROMãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™</string>
240 <string name="loader_error_encrypted_keys_description"><![CDATA[ゲームã®å¾©å·åŒ–ã«å¿…è¦ãª <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ファイルãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。]]></string> 251 <string name="loader_error_encrypted_keys_description"><![CDATA[ゲームã®å¾©å·åŒ–ã«å¿…è¦ãª <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ファイルãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。]]></string>
@@ -261,6 +272,7 @@
261 <string name="emulation_pause">ä¸€æ™‚åœæ­¢</string> 272 <string name="emulation_pause">ä¸€æ™‚åœæ­¢</string>
262 <string name="emulation_unpause">å†é–‹</string> 273 <string name="emulation_unpause">å†é–‹</string>
263 <string name="emulation_input_overlay">表示オプション</string> 274 <string name="emulation_input_overlay">表示オプション</string>
275 <string name="touchscreen">タッãƒã‚¹ã‚¯ãƒªãƒ¼ãƒ³</string>
264 276
265 <string name="load_settings">設定をロード中…</string> 277 <string name="load_settings">設定をロード中…</string>
266 278
@@ -292,6 +304,7 @@
292 304
293 <!-- Memory Sizes --> 305 <!-- Memory Sizes -->
294 <string name="memory_byte">Byte</string> 306 <string name="memory_byte">Byte</string>
307 <string name="memory_byte_shorthand">B</string>
295 <string name="memory_kilobyte">KB</string> 308 <string name="memory_kilobyte">KB</string>
296 <string name="memory_megabyte">MB</string> 309 <string name="memory_megabyte">MB</string>
297 <string name="memory_gigabyte">GB</string> 310 <string name="memory_gigabyte">GB</string>
@@ -336,10 +349,9 @@
336 <string name="anti_aliasing_smaa">SMAA</string> 349 <string name="anti_aliasing_smaa">SMAA</string>
337 350
338 <!-- Screen Layouts --> 351 <!-- Screen Layouts -->
352 <string name="screen_layout_auto">自動</string>
339 <string name="screen_layout_landscape">横長</string> 353 <string name="screen_layout_landscape">横長</string>
340 <string name="screen_layout_portrait">縦長</string> 354 <string name="screen_layout_portrait">縦長</string>
341 <string name="screen_layout_auto">自動</string>
342
343 <!-- Aspect Ratios --> 355 <!-- Aspect Ratios -->
344 <string name="ratio_default">デフォルト (16:9)</string> 356 <string name="ratio_default">デフォルト (16:9)</string>
345 <string name="ratio_force_four_three">強制 4:3</string> 357 <string name="ratio_force_four_three">強制 4:3</string>
@@ -374,9 +386,14 @@
374 <string name="theme_mode_light">ライト</string> 386 <string name="theme_mode_light">ライト</string>
375 <string name="theme_mode_dark">ダーク</string> 387 <string name="theme_mode_dark">ダーク</string>
376 388
377 <!-- Audio output engines -->
378 <string name="cubeb">cubeb</string> 389 <string name="cubeb">cubeb</string>
379 390
391 <!-- Anisotropic filtering options -->
392 <string name="multiplier_two">2x</string>
393 <string name="multiplier_four">4x</string>
394 <string name="multiplier_eight">8x</string>
395 <string name="multiplier_sixteen">16x</string>
396
380 <!-- Black backgrounds theme --> 397 <!-- Black backgrounds theme -->
381 <string name="use_black_backgrounds">完全ãªé»’を使用</string> 398 <string name="use_black_backgrounds">完全ãªé»’を使用</string>
382 <string name="use_black_backgrounds_description">ダークテーマã®èƒŒæ™¯è‰²ã«é»’ãŒé©ç”¨ã•れã¾ã™ã€‚</string> 399 <string name="use_black_backgrounds_description">ダークテーマã®èƒŒæ™¯è‰²ã«é»’ãŒé©ç”¨ã•れã¾ã™ã€‚</string>
diff --git a/src/android/app/src/main/res/values-ko/strings.xml b/src/android/app/src/main/res/values-ko/strings.xml
index 1b9160a23..eaa6c23ce 100644
--- a/src/android/app/src/main/res/values-ko/strings.xml
+++ b/src/android/app/src/main/res/values-ko/strings.xml
@@ -25,6 +25,8 @@
25 <string name="back">ì´ì „</string> 25 <string name="back">ì´ì „</string>
26 <string name="add_games">게임 추가</string> 26 <string name="add_games">게임 추가</string>
27 <string name="add_games_description">게임 í´ë” ì„ íƒ</string> 27 <string name="add_games_description">게임 í´ë” ì„ íƒ</string>
28 <string name="step_complete">완료ë˜ì—ˆìŠµë‹ˆë‹¤!</string>
29
28 <!-- Home strings --> 30 <!-- Home strings -->
29 <string name="home_games">게임</string> 31 <string name="home_games">게임</string>
30 <string name="home_search">검색</string> 32 <string name="home_search">검색</string>
@@ -32,11 +34,13 @@
32 <string name="empty_gamelist">파ì¼ì„ ì°¾ì„ ìˆ˜ 없거나 ì•„ì§ ê²Œìž„ 디렉터리를 ì„ íƒí•˜ì§€ 않았습니다.</string> 34 <string name="empty_gamelist">파ì¼ì„ ì°¾ì„ ìˆ˜ 없거나 ì•„ì§ ê²Œìž„ 디렉터리를 ì„ íƒí•˜ì§€ 않았습니다.</string>
33 <string name="search_and_filter_games">게임 검색 ë° í•„í„°ë§</string> 35 <string name="search_and_filter_games">게임 검색 ë° í•„í„°ë§</string>
34 <string name="select_games_folder">게임 í´ë” ì„ íƒ</string> 36 <string name="select_games_folder">게임 í´ë” ì„ íƒ</string>
35 <string name="select_games_folder_description">yuzuê°€ 게임 목ë¡ì„ 채울 수 있ë„ë¡ í—ˆìš©</string> 37 <string name="manage_game_folders">게임 í´ë” 관리</string>
38 <string name="select_games_folder_description">yuzuì— ê²Œìž„ ëª©ë¡ ì¶”ê°€í•˜ê¸°</string>
36 <string name="add_games_warning">게임 í´ë” ì„ íƒì„ 건너뛰겠습니까?</string> 39 <string name="add_games_warning">게임 í´ë” ì„ íƒì„ 건너뛰겠습니까?</string>
37 <string name="add_games_warning_description">í´ë”를 ì„ íƒí•˜ì§€ 않으면 게임 목ë¡ì— ê²Œìž„ì´ í‘œì‹œë˜ì§€ 않습니다.</string> 40 <string name="add_games_warning_description">í´ë”를 ì„ íƒí•˜ì§€ 않으면 게임 목ë¡ì— ê²Œìž„ì´ í‘œì‹œë˜ì§€ 않습니다.</string>
38 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 41 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
39 <string name="home_search_games">게임 검색</string> 42 <string name="home_search_games">게임 검색</string>
43 <string name="search_settings">검색 설정</string>
40 <string name="games_dir_selected">게임 디렉터리를 설정했습니다.</string> 44 <string name="games_dir_selected">게임 디렉터리를 설정했습니다.</string>
41 <string name="install_prod_keys">prod.keys 설치</string> 45 <string name="install_prod_keys">prod.keys 설치</string>
42 <string name="install_prod_keys_description">패키지 게임 암호 í•´ë…ì— í•„ìš”</string> 46 <string name="install_prod_keys_description">패키지 게임 암호 í•´ë…ì— í•„ìš”</string>
@@ -65,9 +69,11 @@
65 <string name="invalid_keys_error">암호화 키가 올바르지 않ìŒ</string> 69 <string name="invalid_keys_error">암호화 키가 올바르지 않ìŒ</string>
66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
67 <string name="install_keys_failure_description">ì„ íƒí•œ 파ì¼ì´ 잘못ë˜ì—ˆê±°ë‚˜ ì†ìƒë˜ì—ˆìŠµë‹ˆë‹¤. 키를 다시 ë¤í”„하세요.</string> 71 <string name="install_keys_failure_description">ì„ íƒí•œ 파ì¼ì´ 잘못ë˜ì—ˆê±°ë‚˜ ì†ìƒë˜ì—ˆìŠµë‹ˆë‹¤. 키를 다시 ë¤í”„하세요.</string>
72 <string name="gpu_driver_manager">GPU 드ë¼ì´ë²„ 관리ìž</string>
68 <string name="install_gpu_driver">GPU 드ë¼ì´ë²„ 설치</string> 73 <string name="install_gpu_driver">GPU 드ë¼ì´ë²„ 설치</string>
69 <string name="install_gpu_driver_description">잠재ì ìœ¼ë¡œ ë” ë‚˜ì€ ì„±ëŠ¥ ë˜ëŠ” ì •í™•ì„±ì„ ìœ„í•´ 대체 드ë¼ì´ë²„를 설치하세요.</string> 74 <string name="install_gpu_driver_description">잠재ì ì¸ 성능 ë˜ëŠ” ì •í™•ë„ ê°œì„ ì„ ìœ„í•´ 대체 드ë¼ì´ë²„ 설치</string>
70 <string name="advanced_settings">고급 설정</string> 75 <string name="advanced_settings">고급 설정</string>
76 <string name="advanced_settings_game">고급 설정: %1$s</string>
71 <string name="settings_description">ì—뮬레ì´í„° 설정 구성</string> 77 <string name="settings_description">ì—뮬레ì´í„° 설정 구성</string>
72 <string name="search_recently_played">최근 플레ì´</string> 78 <string name="search_recently_played">최근 플레ì´</string>
73 <string name="search_recently_added">최근 추가</string> 79 <string name="search_recently_added">최근 추가</string>
@@ -79,9 +85,13 @@
79 <string name="no_file_manager">íŒŒì¼ ê´€ë¦¬ìžë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string> 85 <string name="no_file_manager">íŒŒì¼ ê´€ë¦¬ìžë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string>
80 <string name="notification_no_directory_link">yuzu 디렉터리를 ì—´ 수 ì—†ìŒ</string> 86 <string name="notification_no_directory_link">yuzu 디렉터리를 ì—´ 수 ì—†ìŒ</string>
81 <string name="notification_no_directory_link_description">íŒŒì¼ ê´€ë¦¬ìžì˜ 사ì´ë“œ 패ë„ì—서 ì‚¬ìš©ìž í´ë”를 수ë™ìœ¼ë¡œ 찾아주세요.</string> 87 <string name="notification_no_directory_link_description">íŒŒì¼ ê´€ë¦¬ìžì˜ 사ì´ë“œ 패ë„ì—서 ì‚¬ìš©ìž í´ë”를 수ë™ìœ¼ë¡œ 찾아주세요.</string>
82 <string name="manage_save_data">저장 ë°ì´í„° 관리</string> 88 <string name="manage_save_data">세ì´ë¸Œ ë°ì´í„° 관리</string>
83 <string name="manage_save_data_description">저장 ë°ì´í„°ë¥¼ 발견했습니다. 아래ì—서 ì˜µì…˜ì„ ì„ íƒí•˜ì„¸ìš”.</string> 89 <string name="manage_save_data_description">세ì´ë¸Œ ë°ì´í„°ë¥¼ 발견했습니다. 아래ì—서 ì˜µì…˜ì„ ì„ íƒí•˜ì„¸ìš”.</string>
84 <string name="import_export_saves_description">저장 íŒŒì¼ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string> 90 <string name="import_save_warning">세ì´ë¸Œ ë°ì´í„° 가져오기</string>
91 <string name="import_save_warning_description">ì´ ìž‘ì—…ì€ ê¸°ì¡´ ë°ì´í„° 전체를 ì„ íƒí•œ 파ì¼ë¡œ ë®ì–´ì”Œì›ë‹ˆë‹¤. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</string>
92 <string name="import_export_saves_description">세ì´ë¸Œ íŒŒì¼ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string>
93 <string name="save_files_importing">세ì´ë¸Œ íŒŒì¼ ê°€ì ¸ì˜¤ëŠ” 중...</string>
94 <string name="save_files_exporting">세ì´ë¸Œ íŒŒì¼ ë‚´ë³´ë‚´ëŠ” 중...</string>
85 <string name="save_file_imported_success">ë°ì´í„°ë¥¼ 불러왔습니다.</string> 95 <string name="save_file_imported_success">ë°ì´í„°ë¥¼ 불러왔습니다.</string>
86 <string name="save_file_invalid_zip_structure">올바르지 ì•Šì€ ì €ìž¥ 디렉터리 구조</string> 96 <string name="save_file_invalid_zip_structure">올바르지 ì•Šì€ ì €ìž¥ 디렉터리 구조</string>
87 <string name="save_file_invalid_zip_structure_description">첫 번째 하위 í´ë” ì´ë¦„ì€ ê²Œìž„ì˜ íƒ€ì´í‹€ ID여야 합니다.</string> 97 <string name="save_file_invalid_zip_structure_description">첫 번째 하위 í´ë” ì´ë¦„ì€ ê²Œìž„ì˜ íƒ€ì´í‹€ ID여야 합니다.</string>
@@ -89,15 +99,62 @@
89 <string name="export_saves">내보내기</string> 99 <string name="export_saves">내보내기</string>
90 <string name="install_firmware">펌웨어 설치</string> 100 <string name="install_firmware">펌웨어 설치</string>
91 <string name="install_firmware_description">펌웨어는 ZIP 파ì¼ì´ë©° ì¼ë¶€ ê²Œìž„ì„ ë¶€íŒ…í•˜ëŠ” ë° í•„ìš”í•©ë‹ˆë‹¤.</string> 101 <string name="install_firmware_description">펌웨어는 ZIP 파ì¼ì´ë©° ì¼ë¶€ ê²Œìž„ì„ ë¶€íŒ…í•˜ëŠ” ë° í•„ìš”í•©ë‹ˆë‹¤.</string>
92 <string name="firmware_installing">펌웨어 설치</string> 102 <string name="firmware_installing">펌웨어 설치 중...</string>
93 <string name="firmware_installed_success">펌웨어를 설치했습니다.</string> 103 <string name="firmware_installed_success">펌웨어를 설치했습니다.</string>
94 <string name="firmware_installed_failure">펌웨어 설치 실패</string> 104 <string name="firmware_installed_failure">펌웨어 설치 실패</string>
105 <string name="firmware_installed_failure_description">펌웨어 NCA 파ì¼ì´ ZIP 파ì¼ì˜ 루트 ë””ë ‰í† ë¦¬ì— ìœ„ì¹˜í•œì§€ 확ì¸í•˜ê³  다시 시ë„하세요.</string>
95 <string name="share_log">디버그 로그 공유</string> 106 <string name="share_log">디버그 로그 공유</string>
96 <string name="share_log_description">yuzuì˜ ë¡œê·¸ 파ì¼ì„ 공유하여 문제 디버깅하기</string> 107 <string name="share_log_description">문제 í•´ê²°ì„ ìœ„í•œ yuzu 로그 íŒŒì¼ ê³µìœ </string>
97 <string name="share_log_missing">로그 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다.</string> 108 <string name="share_log_missing">로그 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다.</string>
98 <string name="install_game_content">게임 콘í…츠 설치</string> 109 <string name="install_game_content">게임 콘í…츠 설치</string>
99 <string name="install_game_content_description">게임 ì—…ë°ì´íЏ ë˜ëŠ” DLC 설치</string> 110 <string name="install_game_content_description">게임 ì—…ë°ì´íЏ ë˜ëŠ” DLC 설치</string>
111 <string name="installing_game_content">콘í…츠 설치 중...</string>
112 <string name="install_game_content_failure">NANDì— íŒŒì¼ì„ 설치하는 ë™ì•ˆ 오류 ë°œìƒ</string>
113 <string name="install_game_content_failure_description">콘í…츠가 유효하고 prod.keysê°€ 설치ë˜ì—ˆëŠ”ì§€ 확ì¸í•˜ì„¸ìš”.</string>
114 <string name="install_game_content_failure_base">ì¶©ëŒì„ 방지하기 위해 기본 게임 설치는 허용ë˜ì§€ 않습니다.</string>
115 <string name="install_game_content_failure_file_extension">NSP ë° XCI 콘í…츠만 ì§€ì›í•©ë‹ˆë‹¤. 게임 콘í…츠가 유효한지 확ì¸í•˜ì„¸ìš”.</string>
116 <string name="install_game_content_failed_count">%1$dê°œì˜ ì„¤ì¹˜ 오류</string>
117 <string name="install_game_content_success">게임 콘í…츠 설치ë¨</string>
118 <string name="install_game_content_success_install">%1$d개를 설치했습니다.</string>
119 <string name="install_game_content_success_overwrite">%1$d개를 ë®ì–´ì”Œì› ìŠµë‹ˆë‹¤.</string>
100 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> 120 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
121 <string name="custom_driver_not_supported">ì‚¬ìš©ìž ì§€ì • 드ë¼ì´ë²„는 ì§€ì›í•˜ì§€ 않습니다.</string>
122 <string name="custom_driver_not_supported_description">ì´ ìž¥ì¹˜ì˜ ì‚¬ìš©ìž ì§€ì • 드ë¼ì´ë²„ ë¡œë”©ì€ í˜„ìž¬ ì§€ì›í•˜ì§€ 않습니다.\në‚˜ì¤‘ì— ì´ ì˜µì…˜ì„ í™•ì¸í•˜ë©´ ì§€ì›ì´ 추가ë˜ì—ˆëŠ”ì§€ 확ì¸í•  수 있습니다.</string>
123 <string name="manage_yuzu_data">yuzu ë°ì´í„° 관리</string>
124 <string name="manage_yuzu_data_description">펌웨어, 키 ê°’, 유저 ë°ì´í„° ë“±ì„ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string>
125 <string name="share_save_file">세ì´ë¸Œ íŒŒì¼ ê³µìœ </string>
126 <string name="export_save_failed">세ì´ë¸Œ 내보내기 실패</string>
127 <string name="game_folders">게임 í´ë”</string>
128 <string name="deep_scan">딥 스캔(하위 í´ë” íƒìƒ‰)</string>
129 <string name="add_game_folder">게임 í´ë” 추가</string>
130 <string name="folder_already_added">ì´ í´ë”는 ì´ë¯¸ 추가ë˜ì–´ 있습니다!</string>
131 <string name="game_folder_properties">게임 í´ë” ì†ì„±</string>
132 <plurals name="saves_import_failed">
133 <item quantity="other">%dê°œì˜ ì„¸ì´ë¸Œ 가져오기 실패</item>
134 </plurals>
135 <plurals name="saves_import_success">
136 <item quantity="other">%dê°œì˜ ì„¸ì´ë¸Œë¥¼ 가져왔습니다.</item>
137 </plurals>
138 <string name="no_save_data_found">세ì´ë¸Œ ë°ì´í„°ë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string>
139
140 <!-- Applet launcher strings -->
141 <string name="applets">애플릿 런처</string>
142 <string name="applets_description">ì„¤ì¹˜ëœ íŽŒì›¨ì–´ë¥¼ 사용해 시스템 ì• í”Œë¦¿ì„ ì‹¤í–‰í•©ë‹ˆë‹¤.</string>
143 <string name="applets_error_firmware">펌웨어가 설치ë˜ì§€ 않았습니다.</string>
144 <string name="applets_error_applet">ì• í”Œë¦¿ì„ ì‚¬ìš©í•  수 ì—†ìŒ</string>
145 <string name="applets_error_description"><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파ì¼ê³¼ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">펌웨어가</a> 설치ë˜ì—ˆëŠ”ì§€ 확ì¸í•˜ê³  다시 시ë„하세요.]]></string>
146 <string name="album_applet">앨범</string>
147 <string name="album_applet_description">시스템 사진 뷰어로 유저 스í¬ë¦°ìƒ· í´ë”ì— ì €ìž¥ëœ ì´ë¯¸ì§€ë¥¼ 확ì¸í•©ë‹ˆë‹¤. </string>
148 <string name="mii_edit_applet">Mii 편집</string>
149 <string name="mii_edit_applet_description">시스템 ì—디터로 Mii를 ë³´ê³  편집합니다.</string>
150 <string name="cabinet_applet">ìºë¹„ë‹›</string>
151 <string name="cabinet_applet_description">amiiboì— ì €ìž¥ëœ ë°ì´í„°ë¥¼ 편집하고 삭제합니다.</string>
152 <string name="cabinet_launcher">ìºë¹„ë‹› 런처</string>
153 <string name="cabinet_nickname_and_owner">닉네임 ë° ì†Œìœ ìž ì„¤ì •</string>
154 <string name="cabinet_game_data_eraser">게임 ë°ì´í„° ì‚­ì œ</string>
155 <string name="cabinet_restorer">ë³µì›</string>
156 <string name="cabinet_formatter">í¬ë§·í„°</string>
157
101 <!-- About screen strings --> 158 <!-- About screen strings -->
102 <string name="gaia_is_not_real">ê°€ì´ì•„는 진짜가 아님</string> 159 <string name="gaia_is_not_real">ê°€ì´ì•„는 진짜가 아님</string>
103 <string name="copied_to_clipboard">í´ë¦½ë³´ë“œì— 복사ë˜ì—ˆìŠµë‹ˆë‹¤.</string> 160 <string name="copied_to_clipboard">í´ë¦½ë³´ë“œì— 복사ë˜ì—ˆìŠµë‹ˆë‹¤.</string>
@@ -107,6 +164,16 @@
107 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 164 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
108 <string name="licenses_description">Androidìš© yuzu를 가능하게 하는 프로ì íЏ</string> 165 <string name="licenses_description">Androidìš© yuzu를 가능하게 하는 프로ì íЏ</string>
109 <string name="build">빌드</string> 166 <string name="build">빌드</string>
167 <string name="user_data">유저 ë°ì´í„°</string>
168 <string name="user_data_description">모든 앱 ë°ì´í„°ë¥¼ 가져오거나 내보냅니다.\n\n유저 ë°ì´í„°ë¥¼ 가져올 경우 í˜„ìž¬ì˜ ëª¨ë“  ë°ì´í„°ëŠ” ì‚­ì œë©ë‹ˆë‹¤.</string>
169 <string name="exporting_user_data">유저 ë°ì´í„° 내보내는 중...</string>
170 <string name="importing_user_data">유저 ë°ì´í„° 가져오는 중...</string>
171 <string name="import_user_data">유저 ë°ì´í„° 가져오기</string>
172 <string name="invalid_yuzu_backup">올바르지 ì•Šì€ yuzu 백업 파ì¼</string>
173 <string name="user_data_export_success">유저 ë°ì´í„°ë¥¼ 내보냈습니다.</string>
174 <string name="user_data_import_success">유저 ë°ì´í„°ë¥¼ 가져왔습니다.</string>
175 <string name="user_data_export_cancelled">내보내기 취소ë¨</string>
176 <string name="user_data_import_failed_description">유저 ë°ì´í„° í´ë”ê°€ ZIP í´ë”ì˜ ë£¨íŠ¸ ë””ë ‰í† ë¦¬ì— ìœ„ì¹˜í•˜ê³  config/config.ini 구성 파ì¼ì´ 있는지 확ì¸í•˜ê³  다시 시ë„하세요.</string>
110 <string name="support_link">https://discord.gg/u77vRWY</string> 177 <string name="support_link">https://discord.gg/u77vRWY</string>
111 <string name="website_link">https://yuzu-emu.org/</string> 178 <string name="website_link">https://yuzu-emu.org/</string>
112 <string name="github_link">https://github.com/yuzu-emu</string> 179 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -130,7 +197,10 @@
130 <string name="frame_limit_enable_description">ì—뮬레ì´ì…˜ ì†ë„를 ì •ìƒ ì†ë„ì˜ ì§€ì •ëœ ë¹„ìœ¨ë¡œ 제한합니다.</string> 197 <string name="frame_limit_enable_description">ì—뮬레ì´ì…˜ ì†ë„를 ì •ìƒ ì†ë„ì˜ ì§€ì •ëœ ë¹„ìœ¨ë¡œ 제한합니다.</string>
131 <string name="frame_limit_slider">ì†ë„ 제한 비율</string> 198 <string name="frame_limit_slider">ì†ë„ 제한 비율</string>
132 <string name="frame_limit_slider_description">ì—뮬레ì´ì…˜ ì†ë„ì˜ ì œí•œ ë¹„ìœ¨ì„ ì§€ì •í•©ë‹ˆë‹¤. 100%ê°€ ì •ìƒ ì†ë„입니다. ê°’ì´ ë†’ê±°ë‚˜ 낮으면 ì†ë„ ì œí•œì´ ì¦ê°€í•˜ê±°ë‚˜ ê°ì†Œí•©ë‹ˆë‹¤.</string> 199 <string name="frame_limit_slider_description">ì—뮬레ì´ì…˜ ì†ë„ì˜ ì œí•œ ë¹„ìœ¨ì„ ì§€ì •í•©ë‹ˆë‹¤. 100%ê°€ ì •ìƒ ì†ë„입니다. ê°’ì´ ë†’ê±°ë‚˜ 낮으면 ì†ë„ ì œí•œì´ ì¦ê°€í•˜ê±°ë‚˜ ê°ì†Œí•©ë‹ˆë‹¤.</string>
200 <string name="cpu_backend">CPU 백엔드</string>
133 <string name="cpu_accuracy">CPU 정확ë„</string> 201 <string name="cpu_accuracy">CPU 정확ë„</string>
202 <string name="value_with_units">%1$s%2$s</string>
203
134 <!-- System settings strings --> 204 <!-- System settings strings -->
135 <string name="use_docked_mode">ë… ëª¨ë“œ</string> 205 <string name="use_docked_mode">ë… ëª¨ë“œ</string>
136 <string name="use_docked_mode_description">í•´ìƒë„를 높ì´ë©° ì„±ëŠ¥ì´ ì €í•˜ë©ë‹ˆë‹¤. 비활성화시 휴대 모드가 사용ë˜ë©° í•´ìƒë„는 낮아지고 ì„±ëŠ¥ì€ í–¥ìƒë©ë‹ˆë‹¤.</string> 206 <string name="use_docked_mode_description">í•´ìƒë„를 높ì´ë©° ì„±ëŠ¥ì´ ì €í•˜ë©ë‹ˆë‹¤. 비활성화시 휴대 모드가 사용ë˜ë©° í•´ìƒë„는 낮아지고 ì„±ëŠ¥ì€ í–¥ìƒë©ë‹ˆë‹¤.</string>
@@ -139,13 +209,14 @@
139 <string name="select_rtc_date">RTC ë‚ ì§œ ì„ íƒ</string> 209 <string name="select_rtc_date">RTC ë‚ ì§œ ì„ íƒ</string>
140 <string name="select_rtc_time">RTC 시간 ì„ íƒ</string> 210 <string name="select_rtc_time">RTC 시간 ì„ íƒ</string>
141 <string name="use_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC</string> 211 <string name="use_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC</string>
142 <string name="use_custom_rtc_description">현재 시스템 시간과 별ë„로 ì‚¬ìš©ìž ì§€ì • 실시간 시계를 설정할 수 있습니다.</string> 212 <string name="use_custom_rtc_description">현재 시스템 시간과 별ë„로 ì‚¬ìš©ìž ì§€ì • RTC를 설정할 수 있습니다.</string>
143 <string name="set_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC 설정</string> 213 <string name="set_custom_rtc">ì‚¬ìš©ìž ì§€ì • RTC 설정</string>
144 214
145 <!-- Graphics settings strings --> 215 <!-- Graphics settings strings -->
146 <string name="renderer_accuracy">ì •í™•ë„ ìˆ˜ì¤€</string> 216 <string name="renderer_accuracy">ì •í™•ë„ ìˆ˜ì¤€</string>
147 <string name="renderer_resolution">í•´ìƒë„ (휴대 모드/ë… ëª¨ë“œ)</string> 217 <string name="renderer_resolution">í•´ìƒë„ (휴대 모드/ë… ëª¨ë“œ)</string>
148 <string name="renderer_vsync">수ì§ë™ê¸°í™” 모드</string> 218 <string name="renderer_vsync">수ì§ë™ê¸°í™” 모드</string>
219 <string name="renderer_screen_layout">화면 방향</string>
149 <string name="renderer_aspect_ratio">화면비</string> 220 <string name="renderer_aspect_ratio">화면비</string>
150 <string name="renderer_scaling_filter">윈ë„ìš° ì ì‘ í•„í„°</string> 221 <string name="renderer_scaling_filter">윈ë„ìš° ì ì‘ í•„í„°</string>
151 <string name="renderer_anti_aliasing">안티ì—ì¼ë¦¬ì–´ì‹± 방법</string> 222 <string name="renderer_anti_aliasing">안티ì—ì¼ë¦¬ì–´ì‹± 방법</string>
@@ -157,12 +228,21 @@
157 <string name="renderer_reactive_flushing_description">ì¼ë¶€ 게임ì—서 성능 저하를 ê°ìˆ˜í•˜ê³  ë Œë”ë§ ì •í™•ë„를 í–¥ìƒí•©ë‹ˆë‹¤.</string> 228 <string name="renderer_reactive_flushing_description">ì¼ë¶€ 게임ì—서 성능 저하를 ê°ìˆ˜í•˜ê³  ë Œë”ë§ ì •í™•ë„를 í–¥ìƒí•©ë‹ˆë‹¤.</string>
158 <string name="use_disk_shader_cache">ë””ìŠ¤í¬ ì…°ì´ë” ìºì‹œ</string> 229 <string name="use_disk_shader_cache">ë””ìŠ¤í¬ ì…°ì´ë” ìºì‹œ</string>
159 <string name="use_disk_shader_cache_description">ìƒì„±ëœ ì…°ì´ë”를 ë¡œì»¬ì— ì €ìž¥í•˜ê³  로드하여 ëŠê¹€ 현ìƒì„ 줄입니다.</string> 230 <string name="use_disk_shader_cache_description">ìƒì„±ëœ ì…°ì´ë”를 ë¡œì»¬ì— ì €ìž¥í•˜ê³  로드하여 ëŠê¹€ 현ìƒì„ 줄입니다.</string>
231 <string name="anisotropic_filtering">비등방성 í•„í„°ë§</string>
232 <string name="anisotropic_filtering_description">경사ê°ì—서 ë³´ì´ëŠ” í…ìŠ¤ì²˜ì˜ í’ˆì§ˆì„ í–¥ìƒì‹œí‚µë‹ˆë‹¤.</string>
160 233
161 <!-- Debug settings strings --> 234 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string> 235 <string name="cpu">CPU</string>
236 <string name="cpu_debug_mode">CPU 디버깅</string>
237 <string name="cpu_debug_mode_description">CPU를 ëŠë¦° 디버깅 모드로 설정합니다.</string>
238 <string name="gpu">GPU</string>
163 <string name="renderer_api">API</string> 239 <string name="renderer_api">API</string>
164 <string name="renderer_debug">그래픽 디버깅</string> 240 <string name="renderer_debug">그래픽 디버깅</string>
165 <string name="renderer_debug_description">그래픽 API를 ëŠë¦° 디버깅 모드로 설정합니다.</string> 241 <string name="renderer_debug_description">그래픽 API를 ëŠë¦° 디버깅 모드로 설정합니다.</string>
242 <string name="fastmem">Fastmem</string>
243
244 <!-- Audio settings strings -->
245 <string name="audio_output_engine">출력 엔진</string>
166 <string name="audio_volume">볼륨</string> 246 <string name="audio_volume">볼륨</string>
167 <string name="audio_volume_description">오디오 ì¶œë ¥ì˜ ë³¼ë¥¨ì„ ì§€ì •í•©ë‹ˆë‹¤.</string> 247 <string name="audio_volume_description">오디오 ì¶œë ¥ì˜ ë³¼ë¥¨ì„ ì§€ì •í•©ë‹ˆë‹¤.</string>
168 248
@@ -171,12 +251,15 @@
171 <string name="ini_saved">ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string> 251 <string name="ini_saved">ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string>
172 <string name="gameid_saved">%1$s ì „ìš© ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string> 252 <string name="gameid_saved">%1$s ì „ìš© ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string>
173 <string name="error_saving">%1$s.ini 저장 중 오류 ë°œìƒ: %2$s</string> 253 <string name="error_saving">%1$s.ini 저장 중 오류 ë°œìƒ: %2$s</string>
254 <string name="unimplemented_menu">구현ë˜ì§€ ì•Šì€ ë©”ë‰´</string>
174 <string name="loading">불러오는 중...</string> 255 <string name="loading">불러오는 중...</string>
256 <string name="shutting_down">종료하는 중...</string>
175 <string name="reset_setting_confirmation">ì´ ì„¤ì •ì„ ê¸°ë³¸ê°’ìœ¼ë¡œ 재설정하겠습니까?</string> 257 <string name="reset_setting_confirmation">ì´ ì„¤ì •ì„ ê¸°ë³¸ê°’ìœ¼ë¡œ 재설정하겠습니까?</string>
176 <string name="reset_to_default">기본값으로 재설정</string> 258 <string name="reset_to_default">기본값으로 재설정</string>
259 <string name="reset_to_default_description">모든 고급 설정 초기화</string>
177 <string name="reset_all_settings">모든 ì„¤ì •ì„ ì´ˆê¸°í™”í•˜ê² ìŠµë‹ˆê¹Œ?</string> 260 <string name="reset_all_settings">모든 ì„¤ì •ì„ ì´ˆê¸°í™”í•˜ê² ìŠµë‹ˆê¹Œ?</string>
178 <string name="reset_all_settings_description">모든 고급 ì„¤ì •ì´ ê¸°ë³¸ 구성으로 재설정ë©ë‹ˆë‹¤. ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다.</string> 261 <string name="reset_all_settings_description">모든 고급 ì„¤ì •ì´ ê¸°ë³¸ 구성으로 재설정ë©ë‹ˆë‹¤. ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다.</string>
179 <string name="settings_reset">설정 초기화</string> 262 <string name="settings_reset">ì„¤ì •ì„ ì´ˆê¸°í™”í–ˆìŠµë‹ˆë‹¤.</string>
180 <string name="close">닫기</string> 263 <string name="close">닫기</string>
181 <string name="learn_more">ìžì„¸ížˆ</string> 264 <string name="learn_more">ìžì„¸ížˆ</string>
182 <string name="auto">ìžë™</string> 265 <string name="auto">ìžë™</string>
@@ -184,13 +267,30 @@
184 <string name="string_null">Null</string> 267 <string name="string_null">Null</string>
185 <string name="string_import">가져오기</string> 268 <string name="string_import">가져오기</string>
186 <string name="export">내보내기</string> 269 <string name="export">내보내기</string>
270 <string name="export_failed">내보내기 실패</string>
271 <string name="import_failed">가져오기 실패</string>
272 <string name="cancelling">취소하는 중</string>
273 <string name="install">설치</string>
274 <string name="delete">삭제</string>
275 <string name="edit">편집</string>
276 <string name="export_success">ë°ì´í„°ë¥¼ 내보냈습니다.</string>
277 <string name="start">시작</string>
278 <string name="clear">초기화</string>
279 <string name="global">글로벌</string>
280 <string name="custom">커스텀</string>
281 <string name="notice">알림</string>
282 <string name="import_complete">가져오기 완료</string>
283 <string name="more_options">추가 옵션</string>
284 <string name="use_global_setting">글로벌 설정 사용</string>
285
187 <!-- GPU driver installation --> 286 <!-- GPU driver installation -->
188 <string name="select_gpu_driver">GPU 드ë¼ì´ë²„ ì„ íƒ</string> 287 <string name="select_gpu_driver">GPU 드ë¼ì´ë²„ ì„ íƒ</string>
189 <string name="select_gpu_driver_title">현재 ì‚¬ìš©ì¤‘ì¸ GPU 드ë¼ì´ë²„를 변경하겠습니까?</string> 288 <string name="select_gpu_driver_title">현재 ì‚¬ìš©ì¤‘ì¸ GPU 드ë¼ì´ë²„를 변경하겠습니까?</string>
190 <string name="select_gpu_driver_install">설치</string> 289 <string name="select_gpu_driver_install">설치</string>
191 <string name="select_gpu_driver_default">기본값</string> 290 <string name="select_gpu_driver_default">기본값</string>
192 <string name="select_gpu_driver_use_default">기본 GPU 드ë¼ì´ë²„를 사용합니다.</string> 291 <string name="select_gpu_driver_use_default">기본 GPU 드ë¼ì´ë²„를 사용합니다.</string>
193 <string name="select_gpu_driver_error">ìž˜ëª»ëœ ë“œë¼ì´ë¸Œê°€ ì„ íƒë˜ì—ˆìŠµë‹ˆë‹¤. 시스템 ê¸°ë³¸ê°’ì„ ì‚¬ìš©í•©ë‹ˆë‹¤.</string> 292 <string name="select_gpu_driver_error">ìž˜ëª»ëœ ë“œë¼ì´ë²„ê°€ ì„ íƒë˜ì—ˆìŠµë‹ˆë‹¤.</string>
293 <string name="driver_already_installed">ì´ë¯¸ ì„¤ì¹˜ëœ ë“œë¼ì´ë²„입니다.</string>
194 <string name="system_gpu_driver">시스템 GPU 드ë¼ì´ë²„</string> 294 <string name="system_gpu_driver">시스템 GPU 드ë¼ì´ë²„</string>
195 <string name="installing_driver">드ë¼ì´ë²„ 설치 중...</string> 295 <string name="installing_driver">드ë¼ì´ë²„ 설치 중...</string>
196 296
@@ -198,13 +298,58 @@
198 <string name="preferences_settings">설정</string> 298 <string name="preferences_settings">설정</string>
199 <string name="preferences_general">ì¼ë°˜</string> 299 <string name="preferences_general">ì¼ë°˜</string>
200 <string name="preferences_system">시스템</string> 300 <string name="preferences_system">시스템</string>
301 <string name="preferences_system_description">ë… ëª¨ë“œ, 지역, 언어</string>
201 <string name="preferences_graphics">그래픽</string> 302 <string name="preferences_graphics">그래픽</string>
303 <string name="preferences_graphics_description">ì •í™•ë„ ìˆ˜ì¤€, í•´ìƒë„, ì…°ì´ë” ìºì‹œ</string>
202 <string name="preferences_audio">오디오</string> 304 <string name="preferences_audio">오디오</string>
305 <string name="preferences_audio_description">출력 엔진, 불륨</string>
203 <string name="preferences_theme">테마 ë° ìƒ‰ìƒ</string> 306 <string name="preferences_theme">테마 ë° ìƒ‰ìƒ</string>
204 <string name="preferences_debug">디버그</string> 307 <string name="preferences_debug">디버그</string>
308 <string name="preferences_debug_description">CPU/GPU 디버깅, 그래픽 API, Fastmem</string>
309
310 <!-- Game properties -->
311 <string name="info">ì •ë³´</string>
312 <string name="info_description">프로그램 ID, 개발ìž, 버전</string>
313 <string name="per_game_settings">게임별 설정</string>
314 <string name="per_game_settings_description">현재 ê²Œìž„ì— ì ìš©ë˜ëŠ” ì„¤ì •ì„ íŽ¸ì§‘í•©ë‹ˆë‹¤.</string>
315 <string name="launch_options">실행 구성</string>
316 <string name="path">주소</string>
317 <string name="program_id">프로그램 ID</string>
318 <string name="developer">개발ìž</string>
319 <string name="version">버전</string>
320 <string name="copy_details">세부사항 복사</string>
321 <string name="add_ons">부가 기능</string>
322 <string name="add_ons_description">모드, ì—…ë°ì´íЏ ë° DLC 전환하기</string>
323 <string name="clear_shader_cache">ì…°ì´ë” ìºì‹œ 비우기</string>
324 <string name="clear_shader_cache_description">현재 ê²Œìž„ì„ ì‹¤í–‰í•˜ëŠ” ì¤‘ì— ìƒì„±ëœ 모든 ì…°ì´ë”를 삭제합니다.</string>
325 <string name="clear_shader_cache_warning_description">ì…°ì´ë” ìºì‹œê°€ 재ìƒì„±ë˜ì–´ ê²Œìž„ì´ ë²„ë²…ì¼ ìˆ˜ 있습니다.</string>
326 <string name="cleared_shaders_successfully">ì…°ì´ë”를 비웠습니다.</string>
327 <string name="addons_game">애드온: %1$s</string>
328 <string name="save_data">세ì´ë¸Œ ë°ì´í„°</string>
329 <string name="save_data_description">현재 ê²Œìž„ì— ì‚¬ìš©ë˜ëŠ” 세ì´ë¸Œ ë°ì´í„°ë¥¼ 관리합니다.</string>
330 <string name="delete_save_data">세ì´ë¸Œ ë°ì´í„° 삭제하기</string>
331 <string name="delete_save_data_description">현재 ê²Œìž„ì— ì‚¬ìš©ë˜ëŠ” 모든 세ì´ë¸Œ ë°ì´í„°ë¥¼ 삭제합니다.</string>
332 <string name="delete_save_data_warning_description">ì´ ìž‘ì—…ì€ í˜„ìž¬ ê²Œìž„ì˜ ì„¸ì´ë¸Œ ë°ì´í„°ë¥¼ ëª¨ë‘ ì‚­ì œí•˜ê³  ë˜ëŒë¦´ 수 없습니다. 계ì†í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</string>
333 <string name="save_data_deleted_successfully">세ì´ë¸Œ ë°ì´í„°ë¥¼ 삭제했습니다.</string>
334 <string name="select_content_type">콘í…츠 형태</string>
335 <string name="updates_and_dlc">ì—…ë°ì´íЏ ë° DLC</string>
336 <string name="mods_and_cheats">모드 ë° ì¹˜íŠ¸</string>
337 <string name="addon_notice">중요 애드온 알림</string>
338 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
339 <string name="addon_notice_description">모드와 치트를 설치하려면 cheats/, romfs/, ë˜ëŠ” exefs/ 디렉토리를 í¬í•¨í•˜ëŠ” í´ë”를 ì„ íƒí•´ì•¼ 합니다. ê²Œìž„ê³¼ì˜ í˜¸í™˜ 여부를 확ì¸í•  수 없기 ë•Œë¬¸ì— ì‹ ì¤‘í•˜ê²Œ 결정하세요.</string>
340 <string name="invalid_directory">ìž˜ëª»ëœ ë””ë ‰í† ë¦¬</string>
341 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
342 <string name="invalid_directory_description">ì„ íƒí•œ 디렉토리가 cheats/, romfs/, ë˜ëŠ” exefs/ í´ë”를 í¬í•¨í•˜ëŠ”ì§€ 확ì¸í•˜ê³  다시 시ë„하세요.</string>
343 <string name="addon_installed_successfully">ì• ë“œì˜¨ì„ ì„¤ì¹˜í–ˆìŠµë‹ˆë‹¤.</string>
344 <string name="verifying_content">콘í…츠 í™•ì¸ ì¤‘...</string>
345 <string name="content_install_notice">콘í…츠 설치 안내</string>
346 <string name="content_install_notice_description">ì„ íƒí•œ 콘í…츠가 현재 게임과 ì¼ì¹˜í•˜ì§€ 않습니다.\n무시하고 설치하시겠습니까?</string>
347 <string name="confirm_uninstall">제거 확ì¸</string>
348 <string name="confirm_uninstall_description">ì´ ì• ë“œì˜¨ì„ ì œê±°í•˜ì‹œê² ìŠµë‹ˆê¹Œ?</string>
205 349
206 <!-- ROM loading errors --> 350 <!-- ROM loading errors -->
207 <string name="loader_error_encrypted">롬 파ì¼ì´ 암호화ë˜ì–´ìžˆìŒ</string> 351 <string name="loader_error_encrypted">롬 파ì¼ì´ 암호화ë˜ì–´ìžˆìŒ</string>
352 <string name="loader_error_encrypted_roms_description"><![CDATA[ê°€ì´ë“œì— ë”°ë¼ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">게임 카트리지</a> ë˜ëŠ” <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">ì„¤ì¹˜ëœ íƒ€ì´í‹€</a>ì„ ë‹¤ì‹œ ë¤í”„하세요.]]></string>
208 <string name="loader_error_encrypted_keys_description"><![CDATA[ê²Œìž„ì„ í•´ë…í•  수 있ë„ë¡ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파ì¼ì´ 설치ë˜ì–´ 있는지 확ì¸í•˜ì„¸ìš”.]]></string> 353 <string name="loader_error_encrypted_keys_description"><![CDATA[ê²Œìž„ì„ í•´ë…í•  수 있ë„ë¡ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파ì¼ì´ 설치ë˜ì–´ 있는지 확ì¸í•˜ì„¸ìš”.]]></string>
209 <string name="loader_error_video_core">비디오 코어를 초기화하는 ë™ì•ˆ 오류 ë°œìƒ</string> 354 <string name="loader_error_video_core">비디오 코어를 초기화하는 ë™ì•ˆ 오류 ë°œìƒ</string>
210 <string name="loader_error_video_core_description">ì¼ë°˜ì ìœ¼ë¡œ ì´ ë¬¸ì œëŠ” 호환ë˜ì§€ 않는 GPU 드ë¼ì´ë²„로 ì¸í•´ ë°œìƒí•©ë‹ˆë‹¤. ì‚¬ìš©ìž ì§€ì • GPU 드ë¼ì´ë²„를 설치하면 ì´ ë¬¸ì œê°€ í•´ê²°ë  ìˆ˜ 있습니다.</string> 355 <string name="loader_error_video_core_description">ì¼ë°˜ì ìœ¼ë¡œ ì´ ë¬¸ì œëŠ” 호환ë˜ì§€ 않는 GPU 드ë¼ì´ë²„로 ì¸í•´ ë°œìƒí•©ë‹ˆë‹¤. ì‚¬ìš©ìž ì§€ì • GPU 드ë¼ì´ë²„를 설치하면 ì´ ë¬¸ì œê°€ í•´ê²°ë  ìˆ˜ 있습니다.</string>
@@ -229,6 +374,7 @@
229 <string name="emulation_pause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지</string> 374 <string name="emulation_pause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지</string>
230 <string name="emulation_unpause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지 í•´ì œ</string> 375 <string name="emulation_unpause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지 í•´ì œ</string>
231 <string name="emulation_input_overlay">화면 ì˜¤ë²„ë ˆì´ ì„¤ì •</string> 376 <string name="emulation_input_overlay">화면 ì˜¤ë²„ë ˆì´ ì„¤ì •</string>
377 <string name="touchscreen">터치 스í¬ë¦°</string>
232 378
233 <string name="load_settings">설정 불러오는 중...</string> 379 <string name="load_settings">설정 불러오는 중...</string>
234 380
@@ -245,6 +391,10 @@
245 <string name="fatal_error">ì¹˜ëª…ì  ì˜¤ë¥˜</string> 391 <string name="fatal_error">ì¹˜ëª…ì  ì˜¤ë¥˜</string>
246 <string name="fatal_error_message">ì¹˜ëª…ì  ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¡œê·¸ë¥¼ 확ì¸í•˜ì‹­ì‹œì˜¤.\nì—뮬레ì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí•  수 있습니다.</string> 392 <string name="fatal_error_message">ì¹˜ëª…ì  ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¡œê·¸ë¥¼ 확ì¸í•˜ì‹­ì‹œì˜¤.\nì—뮬레ì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí•  수 있습니다.</string>
247 <string name="performance_warning">ì´ ì„¤ì •ì„ ë„ë©´ ì—뮬레ì´ì…˜ ì„±ëŠ¥ì´ í¬ê²Œ 저하ë©ë‹ˆë‹¤! 최ìƒì˜ í™˜ê²½ì„ ìœ„í•´ ì´ ì„¤ì •ì„ í™œì„±í™”ëœ ìƒíƒœë¡œ ë‘는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</string> 393 <string name="performance_warning">ì´ ì„¤ì •ì„ ë„ë©´ ì—뮬레ì´ì…˜ ì„±ëŠ¥ì´ í¬ê²Œ 저하ë©ë‹ˆë‹¤! 최ìƒì˜ í™˜ê²½ì„ ìœ„í•´ ì´ ì„¤ì •ì„ í™œì„±í™”ëœ ìƒíƒœë¡œ ë‘는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</string>
394 <string name="device_memory_inadequate">장치 RAM: %1$s\n권장: %2$s</string>
395 <string name="memory_formatted">%1$s %2$s</string>
396 <string name="no_game_present">실행 가능한 ê²Œìž„ì´ ì—†ìŠµë‹ˆë‹¤!</string>
397
248 <!-- Region Names --> 398 <!-- Region Names -->
249 <string name="region_japan">ì¼ë³¸</string> 399 <string name="region_japan">ì¼ë³¸</string>
250 <string name="region_usa">미국</string> 400 <string name="region_usa">미국</string>
@@ -254,7 +404,16 @@
254 <string name="region_korea">대한민국</string> 404 <string name="region_korea">대한민국</string>
255 <string name="region_taiwan">대만</string> 405 <string name="region_taiwan">대만</string>
256 406
407 <!-- Memory Sizes -->
408 <string name="memory_byte">Byte</string>
409 <string name="memory_byte_shorthand">B</string>
410 <string name="memory_kilobyte">KB</string>
411 <string name="memory_megabyte">MB</string>
257 <string name="memory_gigabyte">ì˜êµ­ 하계 표준시(GB)</string> 412 <string name="memory_gigabyte">ì˜êµ­ 하계 표준시(GB)</string>
413 <string name="memory_terabyte">TB</string>
414 <string name="memory_petabyte">PB</string>
415 <string name="memory_exabyte">EB</string>
416
258 <!-- Renderer APIs --> 417 <!-- Renderer APIs -->
259 <string name="renderer_vulkan">Vulcan</string> 418 <string name="renderer_vulkan">Vulcan</string>
260 <string name="renderer_none">ì—†ìŒ</string> 419 <string name="renderer_none">ì—†ìŒ</string>
@@ -291,7 +450,14 @@
291 <string name="anti_aliasing_fxaa">FXAA</string> 450 <string name="anti_aliasing_fxaa">FXAA</string>
292 <string name="anti_aliasing_smaa">SMAA</string> 451 <string name="anti_aliasing_smaa">SMAA</string>
293 452
453 <!-- Screen Layouts -->
294 <string name="screen_layout_auto">ìžë™</string> 454 <string name="screen_layout_auto">ìžë™</string>
455 <string name="screen_layout_sensor_landscape">가로 ê³ ì • (ë°©í–¥ ê°ì§€)</string>
456 <string name="screen_layout_landscape">가로</string>
457 <string name="screen_layout_reverse_landscape">가로 고정 (역방향 고정)</string>
458 <string name="screen_layout_sensor_portrait">세로 ê³ ì • (ë°©í–¥ ê°ì§€)</string>
459 <string name="screen_layout_portrait">세로</string>
460 <string name="screen_layout_reverse_portrait">세로 고정 (역방향 고정)</string>
295 461
296 <!-- Aspect Ratios --> 462 <!-- Aspect Ratios -->
297 <string name="ratio_default">기본 (16:9)</string> 463 <string name="ratio_default">기본 (16:9)</string>
@@ -300,6 +466,10 @@
300 <string name="ratio_force_sixteen_ten">강제 16:10</string> 466 <string name="ratio_force_sixteen_ten">강제 16:10</string>
301 <string name="ratio_stretch">í™”ë©´ì— ë§žì¶¤</string> 467 <string name="ratio_stretch">í™”ë©´ì— ë§žì¶¤</string>
302 468
469 <!-- CPU Backend -->
470 <string name="cpu_backend_dynarmic">Dynarmic (ëŠë¦¼)</string>
471 <string name="cpu_backend_nce">네ì´í‹°ë¸Œ 코드 실행 (NCE)</string>
472
303 <!-- CPU Accuracy --> 473 <!-- CPU Accuracy -->
304 <string name="cpu_accuracy_accurate">정확함</string> 474 <string name="cpu_accuracy_accurate">정확함</string>
305 <string name="cpu_accuracy_unsafe">최ì í™” (안전하지 않ìŒ)</string> 475 <string name="cpu_accuracy_unsafe">최ì í™” (안전하지 않ìŒ)</string>
@@ -327,14 +497,29 @@
327 <string name="theme_mode_light">ë¼ì´íЏ 모드</string> 497 <string name="theme_mode_light">ë¼ì´íЏ 모드</string>
328 <string name="theme_mode_dark">ë‹¤í¬ ëª¨ë“œ</string> 498 <string name="theme_mode_dark">ë‹¤í¬ ëª¨ë“œ</string>
329 499
500 <!-- Audio output engines -->
501 <string name="oboe">oboe</string>
502 <string name="cubeb">cubeb</string>
503
504 <!-- Anisotropic filtering options -->
505 <string name="multiplier_two">2x</string>
506 <string name="multiplier_four">4x</string>
507 <string name="multiplier_eight">8x</string>
508 <string name="multiplier_sixteen">16x</string>
509
330 <!-- Black backgrounds theme --> 510 <!-- Black backgrounds theme -->
331 <string name="use_black_backgrounds">검정 배경</string> 511 <string name="use_black_backgrounds">검정 배경</string>
332 <string name="use_black_backgrounds_description">ì–´ë‘ìš´ 테마를 사용할 때는 검정 ë°°ê²½ì„ ì ìš©í•©ë‹ˆë‹¤.</string> 512 <string name="use_black_backgrounds_description">ì–´ë‘ìš´ 테마 사용 시 검정 ë°°ê²½ì„ ì ìš©í•©ë‹ˆë‹¤.</string>
333 513
514 <!-- Picture-In-Picture -->
515 <string name="picture_in_picture">픽처 ì¸ í”½ì²˜ (Picture-in-Picture)</string>
516 <string name="picture_in_picture_description">ì•±ì„ ë°±ê·¸ë¼ìš´ë“œì—서 실행할 때 ì°½ì„ ìµœì†Œí™”í•©ë‹ˆë‹¤.</string>
517 <string name="pause">ì¼ì‹œì¤‘ì§€</string>
518 <string name="play">재ìƒ</string>
334 <string name="mute">ìŒì†Œê±°</string> 519 <string name="mute">ìŒì†Œê±°</string>
335 <string name="unmute">ìŒì†Œê±° í•´ì œ</string> 520 <string name="unmute">ìŒì†Œê±° í•´ì œ</string>
336 521
337 <!-- Licenses screen strings --> 522 <!-- Licenses screen strings -->
338 <string name="licenses">ë¼ì´ì„¼ìФ</string> 523 <string name="licenses">ë¼ì´ì„¼ìФ</string>
339 <string name="license_fidelityfx_fsr_description">AMDì˜ ê³ í’ˆì§ˆ 업스케ì¼ë§</string> 524 <string name="license_fidelityfx_fsr_description">AMD 고품질 업스케ì¼ë§</string>
340 </resources> 525 </resources>
diff --git a/src/android/app/src/main/res/values-nb/strings.xml b/src/android/app/src/main/res/values-nb/strings.xml
index 3162a9d41..e92dc62d9 100644
--- a/src/android/app/src/main/res/values-nb/strings.xml
+++ b/src/android/app/src/main/res/values-nb/strings.xml
@@ -157,7 +157,6 @@
157 <string name="renderer_reactive_flushing_description">Forbedrer gjengivelsesnøyaktigheten i enkelte spill på bekostning av ytelsen.</string> 157 <string name="renderer_reactive_flushing_description">Forbedrer gjengivelsesnøyaktigheten i enkelte spill på bekostning av ytelsen.</string>
158 <string name="use_disk_shader_cache">Disk shader-hurtigbuffer</string> 158 <string name="use_disk_shader_cache">Disk shader-hurtigbuffer</string>
159 <string name="use_disk_shader_cache_description">Reduserer hakking ved å lagre og laste inn genererte shaders lokalt.</string> 159 <string name="use_disk_shader_cache_description">Reduserer hakking ved å lagre og laste inn genererte shaders lokalt.</string>
160
161 <!-- Debug settings strings --> 160 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string> 161 <string name="cpu">CPU</string>
163 <string name="renderer_api">API</string> 162 <string name="renderer_api">API</string>
@@ -184,13 +183,16 @@
184 <string name="string_null">Null</string> 183 <string name="string_null">Null</string>
185 <string name="string_import">Importer</string> 184 <string name="string_import">Importer</string>
186 <string name="export">Eksporter</string> 185 <string name="export">Eksporter</string>
186 <string name="install">Installer</string>
187 <string name="delete">Slett</string>
188 <string name="start">Start</string>
189 <string name="clear">Fjern</string>
187 <!-- GPU driver installation --> 190 <!-- GPU driver installation -->
188 <string name="select_gpu_driver">Velg GPU-driver</string> 191 <string name="select_gpu_driver">Velg GPU-driver</string>
189 <string name="select_gpu_driver_title">Ønsker du å bytte ut din nåværende GPU-driver?</string> 192 <string name="select_gpu_driver_title">Ønsker du å bytte ut din nåværende GPU-driver?</string>
190 <string name="select_gpu_driver_install">Installer</string> 193 <string name="select_gpu_driver_install">Installer</string>
191 <string name="select_gpu_driver_default">Standard</string> 194 <string name="select_gpu_driver_default">Standard</string>
192 <string name="select_gpu_driver_use_default">Bruk av standard GPU-driver</string> 195 <string name="select_gpu_driver_use_default">Bruk av standard GPU-driver</string>
193 <string name="select_gpu_driver_error">Ugyldig driver valgt, bruker systemstandard!</string>
194 <string name="system_gpu_driver">Systemets GPU-driver</string> 196 <string name="system_gpu_driver">Systemets GPU-driver</string>
195 <string name="installing_driver">Installerer driver...</string> 197 <string name="installing_driver">Installerer driver...</string>
196 198
@@ -202,7 +204,12 @@
202 <string name="preferences_audio">Lyd</string> 204 <string name="preferences_audio">Lyd</string>
203 <string name="preferences_theme">Tema og farge</string> 205 <string name="preferences_theme">Tema og farge</string>
204 <string name="preferences_debug">Feilsøk</string> 206 <string name="preferences_debug">Feilsøk</string>
205 207 <!-- Game properties -->
208 <string name="info">Info</string>
209 <string name="path">Sti</string>
210 <string name="developer">Utvikler</string>
211 <string name="version">Versjon</string>
212 <string name="add_ons">Tilleggsprogrammer</string>
206 <!-- ROM loading errors --> 213 <!-- ROM loading errors -->
207 <string name="loader_error_encrypted">ROM-en din er kryptert</string> 214 <string name="loader_error_encrypted">ROM-en din er kryptert</string>
208 <string name="loader_error_encrypted_keys_description"><![CDATA[Vennligst sørg for at <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> filen er installert slik at spillene kan dekrypteres.]]></string> 215 <string name="loader_error_encrypted_keys_description"><![CDATA[Vennligst sørg for at <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> filen er installert slik at spillene kan dekrypteres.]]></string>
@@ -229,6 +236,7 @@
229 <string name="emulation_pause">Pause emulering</string> 236 <string name="emulation_pause">Pause emulering</string>
230 <string name="emulation_unpause">Ta emuleringen ut av pause</string> 237 <string name="emulation_unpause">Ta emuleringen ut av pause</string>
231 <string name="emulation_input_overlay">Overlay-alternativer</string> 238 <string name="emulation_input_overlay">Overlay-alternativer</string>
239 <string name="touchscreen">Touch-skjerm</string>
232 240
233 <string name="load_settings">Laster inn innstillinger...</string> 241 <string name="load_settings">Laster inn innstillinger...</string>
234 242
@@ -254,6 +262,7 @@
254 <string name="region_korea">Korea</string> 262 <string name="region_korea">Korea</string>
255 <string name="region_taiwan">Taiwan</string> 263 <string name="region_taiwan">Taiwan</string>
256 264
265 <string name="memory_byte_shorthand">B</string>
257 <string name="memory_gigabyte">GB</string> 266 <string name="memory_gigabyte">GB</string>
258 <!-- Renderer APIs --> 267 <!-- Renderer APIs -->
259 <string name="renderer_vulkan">Vulkan</string> 268 <string name="renderer_vulkan">Vulkan</string>
@@ -291,8 +300,8 @@
291 <string name="anti_aliasing_fxaa">FXAA</string> 300 <string name="anti_aliasing_fxaa">FXAA</string>
292 <string name="anti_aliasing_smaa">SMAA</string> 301 <string name="anti_aliasing_smaa">SMAA</string>
293 302
303 <!-- Screen Layouts -->
294 <string name="screen_layout_auto">Auto</string> 304 <string name="screen_layout_auto">Auto</string>
295
296 <!-- Aspect Ratios --> 305 <!-- Aspect Ratios -->
297 <string name="ratio_default">Standard (16:9)</string> 306 <string name="ratio_default">Standard (16:9)</string>
298 <string name="ratio_force_four_three">Tving 4:3</string> 307 <string name="ratio_force_four_three">Tving 4:3</string>
@@ -327,6 +336,12 @@
327 <string name="theme_mode_light">Lys</string> 336 <string name="theme_mode_light">Lys</string>
328 <string name="theme_mode_dark">Mørk</string> 337 <string name="theme_mode_dark">Mørk</string>
329 338
339 <!-- Anisotropic filtering options -->
340 <string name="multiplier_two">2x</string>
341 <string name="multiplier_four">4x</string>
342 <string name="multiplier_eight">8x</string>
343 <string name="multiplier_sixteen">16x</string>
344
330 <!-- Black backgrounds theme --> 345 <!-- Black backgrounds theme -->
331 <string name="use_black_backgrounds">Svart bakgrunn</string> 346 <string name="use_black_backgrounds">Svart bakgrunn</string>
332 <string name="use_black_backgrounds_description">Bruk svart bakgrunn når du bruker det mørke temaet.</string> 347 <string name="use_black_backgrounds_description">Bruk svart bakgrunn når du bruker det mørke temaet.</string>
diff --git a/src/android/app/src/main/res/values-pl/strings.xml b/src/android/app/src/main/res/values-pl/strings.xml
index f4d9920c2..fbd0ad7e9 100644
--- a/src/android/app/src/main/res/values-pl/strings.xml
+++ b/src/android/app/src/main/res/values-pl/strings.xml
@@ -157,7 +157,6 @@
157 <string name="renderer_reactive_flushing_description">Poprawia jakość renderowania w kilku grach, kosztem wydajności.</string> 157 <string name="renderer_reactive_flushing_description">Poprawia jakość renderowania w kilku grach, kosztem wydajności.</string>
158 <string name="use_disk_shader_cache">Pamięć podręczna shaderów</string> 158 <string name="use_disk_shader_cache">Pamięć podręczna shaderów</string>
159 <string name="use_disk_shader_cache_description">Zmniejsza przycięcia przez przechowywanie gotowych wygenerowanych plików oświetlenia w pamięci urządzenia.</string> 159 <string name="use_disk_shader_cache_description">Zmniejsza przycięcia przez przechowywanie gotowych wygenerowanych plików oświetlenia w pamięci urządzenia.</string>
160
161 <!-- Debug settings strings --> 160 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string> 161 <string name="cpu">CPU</string>
163 <string name="renderer_api">Interfejs graficzny</string> 162 <string name="renderer_api">Interfejs graficzny</string>
@@ -183,13 +182,17 @@
183 <string name="submit">Zatwierdź</string> 182 <string name="submit">Zatwierdź</string>
184 <string name="string_import">Importuj</string> 183 <string name="string_import">Importuj</string>
185 <string name="export">Eksportuj</string> 184 <string name="export">Eksportuj</string>
185 <string name="install">Zainstaluj</string>
186 <string name="delete">Usuń</string>
187 <string name="start">Start</string>
188 <string name="clear">Wyczyść</string>
189 <string name="custom">Losowy</string>
186 <!-- GPU driver installation --> 190 <!-- GPU driver installation -->
187 <string name="select_gpu_driver">Wybierz sterownik GPU </string> 191 <string name="select_gpu_driver">Wybierz sterownik GPU </string>
188 <string name="select_gpu_driver_title">Chcesz zastąpić obecny sterownik układu graficznego?</string> 192 <string name="select_gpu_driver_title">Chcesz zastąpić obecny sterownik układu graficznego?</string>
189 <string name="select_gpu_driver_install">Zainstaluj</string> 193 <string name="select_gpu_driver_install">Zainstaluj</string>
190 <string name="select_gpu_driver_default">Domyślne</string> 194 <string name="select_gpu_driver_default">Domyślne</string>
191 <string name="select_gpu_driver_use_default">Aktywny domyślny sterownik GPU</string> 195 <string name="select_gpu_driver_use_default">Aktywny domyślny sterownik GPU</string>
192 <string name="select_gpu_driver_error">Wybrano błędny sterownik, powrót do domyślnego. </string>
193 <string name="system_gpu_driver">Systemowy sterownik GPU</string> 196 <string name="system_gpu_driver">Systemowy sterownik GPU</string>
194 <string name="installing_driver">Instalowanie sterownika...</string> 197 <string name="installing_driver">Instalowanie sterownika...</string>
195 198
@@ -201,7 +204,12 @@
201 <string name="preferences_audio">Dźwięk</string> 204 <string name="preferences_audio">Dźwięk</string>
202 <string name="preferences_theme">Motyw i kolor</string> 205 <string name="preferences_theme">Motyw i kolor</string>
203 <string name="preferences_debug">Debug</string> 206 <string name="preferences_debug">Debug</string>
204 207 <!-- Game properties -->
208 <string name="info">Informacje</string>
209 <string name="path">Ścieżka</string>
210 <string name="developer">Deweloper</string>
211 <string name="version">Wersja</string>
212 <string name="add_ons">Dodatki</string>
205 <!-- ROM loading errors --> 213 <!-- ROM loading errors -->
206 <string name="loader_error_encrypted">Twój ROM jest zakodowany</string> 214 <string name="loader_error_encrypted">Twój ROM jest zakodowany</string>
207 <string name="loader_error_encrypted_keys_description"><![CDATA[Upewnij się że plik kluczy <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> jest zainstalowany aby gry mogły zostać odczytane.]]></string> 215 <string name="loader_error_encrypted_keys_description"><![CDATA[Upewnij się że plik kluczy <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> jest zainstalowany aby gry mogły zostać odczytane.]]></string>
@@ -228,6 +236,7 @@
228 <string name="emulation_pause">Wstrzymaj emulacjÄ™</string> 236 <string name="emulation_pause">Wstrzymaj emulacjÄ™</string>
229 <string name="emulation_unpause">Wznów emulację</string> 237 <string name="emulation_unpause">Wznów emulację</string>
230 <string name="emulation_input_overlay">Opcje nakładki</string> 238 <string name="emulation_input_overlay">Opcje nakładki</string>
239 <string name="touchscreen">Ekran dotykowy</string>
231 240
232 <string name="load_settings">WczytujÄ™ ustawienia...</string> 241 <string name="load_settings">WczytujÄ™ ustawienia...</string>
233 242
@@ -253,6 +262,7 @@
253 <string name="region_korea">Korea</string> 262 <string name="region_korea">Korea</string>
254 <string name="region_taiwan">Tajwan</string> 263 <string name="region_taiwan">Tajwan</string>
255 264
265 <string name="memory_byte_shorthand">B</string>
256 <string name="memory_gigabyte">GB</string> 266 <string name="memory_gigabyte">GB</string>
257 <!-- Renderer APIs --> 267 <!-- Renderer APIs -->
258 <string name="renderer_vulkan">Vulkan</string> 268 <string name="renderer_vulkan">Vulkan</string>
@@ -290,8 +300,8 @@
290 <string name="anti_aliasing_fxaa">FXAA</string> 300 <string name="anti_aliasing_fxaa">FXAA</string>
291 <string name="anti_aliasing_smaa">SMAA</string> 301 <string name="anti_aliasing_smaa">SMAA</string>
292 302
303 <!-- Screen Layouts -->
293 <string name="screen_layout_auto">Automatyczny</string> 304 <string name="screen_layout_auto">Automatyczny</string>
294
295 <!-- Aspect Ratios --> 305 <!-- Aspect Ratios -->
296 <string name="ratio_default">Domyślne (16:9)</string> 306 <string name="ratio_default">Domyślne (16:9)</string>
297 <string name="ratio_force_four_three">WymuÅ› 4:3</string> 307 <string name="ratio_force_four_three">WymuÅ› 4:3</string>
@@ -326,6 +336,12 @@
326 <string name="theme_mode_light">Jasny</string> 336 <string name="theme_mode_light">Jasny</string>
327 <string name="theme_mode_dark">Ciemny</string> 337 <string name="theme_mode_dark">Ciemny</string>
328 338
339 <!-- Anisotropic filtering options -->
340 <string name="multiplier_two">2x</string>
341 <string name="multiplier_four">4x</string>
342 <string name="multiplier_eight">8x</string>
343 <string name="multiplier_sixteen">16x</string>
344
329 <!-- Black backgrounds theme --> 345 <!-- Black backgrounds theme -->
330 <string name="use_black_backgrounds">Czarne tła</string> 346 <string name="use_black_backgrounds">Czarne tła</string>
331 <string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string> 347 <string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string>
diff --git a/src/android/app/src/main/res/values-pt-rBR/strings.xml b/src/android/app/src/main/res/values-pt-rBR/strings.xml
index 8888fc750..a87eb11e4 100644
--- a/src/android/app/src/main/res/values-pt-rBR/strings.xml
+++ b/src/android/app/src/main/res/values-pt-rBR/strings.xml
@@ -1,10 +1,10 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation"> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Este software executa jogos do console Nintendo Switch. Não estão inclusos nem jogos ou chaves. &lt;br /&gt;&lt;br /&gt;Antes de começar, por favor localize o arquivo <![CDATA[1 prod.keys 1]]> no armazenamento de seu dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[2Saiba mais2]]></string> 4 <string name="app_disclaimer">Este software executa jogos do console Nintendo Switch. Não estão inclusos nem jogos ou chaves.&lt;br /&gt;&lt;br /&gt;Antes de começar, por favor localize o arquivo <![CDATA[<b> prod.keys </b>]]> no armazenamento de seu dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Saiba mais</a>]]></string>
5 <string name="emulation_notification_channel_name">Emulação está Ativa</string> 5 <string name="emulation_notification_channel_name">A emulação está Ativa</string>
6 <string name="emulation_notification_channel_description">Mostra uma notificação permanente enquanto a emulação estiver em andamento.</string> 6 <string name="emulation_notification_channel_description">Mostra uma notificação permanente enquanto a emulação estiver em andamento.</string>
7 <string name="emulation_notification_running">Yuzu está em execução </string> 7 <string name="emulation_notification_running">O Yuzu está em execução </string>
8 <string name="notice_notification_channel_name">Notificações e erros</string> 8 <string name="notice_notification_channel_name">Notificações e erros</string>
9 <string name="notice_notification_channel_description">Mostra notificações quando algo dá errado.</string> 9 <string name="notice_notification_channel_description">Mostra notificações quando algo dá errado.</string>
10 <string name="notification_permission_not_granted">Acesso às notificações não concedido!</string> 10 <string name="notification_permission_not_granted">Acesso às notificações não concedido!</string>
@@ -17,7 +17,7 @@
17 <string name="keys_description">Selecione seu arquivo &lt;b>prod.keys&lt;/b> com o botão abaixo.</string> 17 <string name="keys_description">Selecione seu arquivo &lt;b>prod.keys&lt;/b> com o botão abaixo.</string>
18 <string name="select_keys">Selecione as Keys</string> 18 <string name="select_keys">Selecione as Keys</string>
19 <string name="games">Jogos</string> 19 <string name="games">Jogos</string>
20 <string name="games_description">Seleciona sua pasta &lt;b>Jogos&lt;/b> com o botão abaixo.</string> 20 <string name="games_description">Selecione sua pasta &lt;b>Jogos&lt;/b> com o botão abaixo.</string>
21 <string name="done">Feito</string> 21 <string name="done">Feito</string>
22 <string name="done_description">Tudo pronto.\nAproveite seus jogos!</string> 22 <string name="done_description">Tudo pronto.\nAproveite seus jogos!</string>
23 <string name="text_continue">Continuar</string> 23 <string name="text_continue">Continuar</string>
@@ -34,61 +34,67 @@
34 <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string> 34 <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string>
35 <string name="search_and_filter_games">Procura e filtra jogos.</string> 35 <string name="search_and_filter_games">Procura e filtra jogos.</string>
36 <string name="select_games_folder">Seleciona a pasta de jogos.</string> 36 <string name="select_games_folder">Seleciona a pasta de jogos.</string>
37 <string name="manage_game_folders">Gerencie as pastas de jogos</string>
37 <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string> 38 <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string>
38 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> 39 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string>
39 <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string> 40 <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string>
40 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 41 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
41 <string name="home_search_games">Procurar jogos</string> 42 <string name="home_search_games">Procurar jogos</string>
42 <string name="search_settings">Procurar nas definições</string> 43 <string name="search_settings">Procurar nas configurações</string>
43 <string name="games_dir_selected">Pasta de Jogos selecionada</string> 44 <string name="games_dir_selected">Pasta de jogos selecionada</string>
44 <string name="install_prod_keys">Instala prod.keys</string> 45 <string name="install_prod_keys">Instalar prod.keys</string>
45 <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string> 46 <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string>
46 <string name="install_prod_keys_warning">Ignorar a adição de chaves?</string> 47 <string name="install_prod_keys_warning">Ignorar a adição de chaves?</string>
47 <string name="install_prod_keys_warning_description">São necessárias chaves válidas para emular jogos comerciais. Somente aplicativos homebrew funcionarão se você continuar.</string> 48 <string name="install_prod_keys_warning_description">São necessárias chaves válidas para emular jogos comerciais. Somente aplicativos homebrew funcionarão se você continuar.</string>
48 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#Guia de introdução</string> 49 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
49 <string name="notifications">Notificações</string> 50 <string name="notifications">Notificações</string>
50 <string name="notifications_description">Conceda a permissão de notificação com o botão abaixo.</string> 51 <string name="notifications_description">Conceda a permissão de notificação com o botão abaixo.</string>
51 <string name="give_permission">Conceda permissão</string> 52 <string name="give_permission">Conceder permissão</string>
52 <string name="notification_warning">Saltar a concessão da permissão de notificação?</string> 53 <string name="notification_warning">Ignorar a concessão da permissão de notificação?</string>
53 <string name="notification_warning_description">Yuzu não conseguirá te notificar de informações importantes. </string> 54 <string name="notification_warning_description">Yuzu não conseguirá te notificar de informações importantes. </string>
54 <string name="permission_denied">Permissão negada</string> 55 <string name="permission_denied">Permissão negada</string>
55 <string name="permission_denied_description">Você negou essa permissão muitas vezes e agora precisa concedê-la manualmente nas configurações do sistema.</string> 56 <string name="permission_denied_description">Você negou essa permissão muitas vezes e agora precisa concedê-la manualmente nas configurações do sistema.</string>
56 <string name="about">Sobre</string> 57 <string name="about">Sobre</string>
57 <string name="about_description">Versão de compilação, créditos e mais</string> 58 <string name="about_description">Versão de compilação, créditos e mais</string>
58 <string name="warning_help">Ajuda</string> 59 <string name="warning_help">Ajuda</string>
59 <string name="warning_skip">Saltar</string> 60 <string name="warning_skip">Ignorar</string>
60 <string name="warning_cancel">Cancelar</string> 61 <string name="warning_cancel">Cancelar</string>
61 <string name="install_amiibo_keys">Instala chaves Amiibo</string> 62 <string name="install_amiibo_keys">Instalar chaves Amiibo</string>
62 <string name="install_amiibo_keys_description">Necessário para usares Amiibo no jogo</string> 63 <string name="install_amiibo_keys_description">Necessário para usar Amiibos em um jogo</string>
63 <string name="invalid_keys_file">Ficheiro de chaves inválido</string> 64 <string name="invalid_keys_file">Arquivo de chaves selecionado inválido</string>
64 <string name="install_keys_success">Chaves instaladas com sucesso</string> 65 <string name="install_keys_success">Chaves instaladas com sucesso</string>
65 <string name="reading_keys_failure">Erro ao ler chaves de encriptação</string> 66 <string name="reading_keys_failure">Erro ao ler chaves de encriptação</string>
66 <string name="install_prod_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .keys e tente novamente.</string> 67 <string name="install_prod_keys_failure_extension_description">Verifique se seu arquivo de chaves possui a extensão .keys e tente novamente.</string>
67 <string name="install_amiibo_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .bin e tente novamente.</string> 68 <string name="install_amiibo_keys_failure_extension_description">Verifique se seu arquivo de chaves possui a extensão .bin e tente novamente.</string>
68 <string name="invalid_keys_error">Chaves de encriptação inválidas</string> 69 <string name="invalid_keys_error">Chaves de encriptação inválidas</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string> 71 <string name="install_keys_failure_description">O arquivo selecionado está incorreto ou corrompido. Por favor extraia suas chaves novamente.</string>
72 <string name="gpu_driver_manager">Gerenciador de driver de GPU</string>
71 <string name="install_gpu_driver">Instala driver para GPU</string> 73 <string name="install_gpu_driver">Instala driver para GPU</string>
72 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> 74 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string>
73 <string name="advanced_settings">Definições avançadas</string> 75 <string name="advanced_settings">Configurações avançadas</string>
74 <string name="advanced_settings_game">Definições avançadas: %1$s</string> 76 <string name="advanced_settings_game">Configurações avançadas: %1$s</string>
75 <string name="settings_description">Configura definições do emulador</string> 77 <string name="settings_description">Configure opções do emulador</string>
76 <string name="search_recently_played">Jogado recentemente</string> 78 <string name="search_recently_played">Jogado recentemente</string>
77 <string name="search_recently_added">Adicionado recentemente</string> 79 <string name="search_recently_added">Adicionado recentemente</string>
78 <string name="search_retail">Jogos comerciais</string> 80 <string name="search_retail">Jogos comerciais</string>
79 <string name="search_homebrew">Homebrew</string> 81 <string name="search_homebrew">Homebrew</string>
80 <string name="open_user_folder">Abre a pasta Yuzu</string> 82 <string name="open_user_folder">Abrir a pasta do Yuzu</string>
81 <string name="open_user_folder_description">Gere os ficheiro internos do Yuzu</string> 83 <string name="open_user_folder_description">Gerencie os arquivos internos do Yuzu</string>
82 <string name="theme_and_color_description">Modifica a aparência da App</string> 84 <string name="theme_and_color_description">Altere a aparência do aplicativo</string>
83 <string name="no_file_manager">Nenhum gestor de ficheiros encontrado</string> 85 <string name="no_file_manager">Nenhum gerenciador de arquivos encontrado</string>
84 <string name="notification_no_directory_link">Impossível abrir pasta Yuzu</string> 86 <string name="notification_no_directory_link">Não foi possível abrir a pasta do Yuzu</string>
85 <string name="notification_no_directory_link_description">Localiza a pasta de utilizador manualmente com o painel lateral do gestor de ficheiros.</string> 87 <string name="notification_no_directory_link_description">Por favor localize a pasta do usuário com o painel lateral do gerenciador de arquivos manualmente.</string>
86 <string name="manage_save_data">Gerir dados guardados</string> 88 <string name="manage_save_data">Gerenciar os dados salvos dos jogos</string>
87 <string name="manage_save_data_description">Dados não encontrados. Por favor seleciona uma opção abaixo.</string> 89 <string name="manage_save_data_description">Dados salvos encontrados. Por favor selecione uma opção abaixo.</string>
88 <string name="import_export_saves_description">Importa ou exporta dados guardados</string> 90 <string name="import_save_warning">Importar dados salvos</string>
91 <string name="import_save_warning_description">Isso irá sobrescrever seus dados salvos com o arquivo selecionado. Você tem certeza que quer continuar?</string>
92 <string name="import_export_saves_description">Importa ou exporta arquivos de dados salvos</string>
93 <string name="save_files_importing">Importando dados salvos...</string>
94 <string name="save_files_exporting">Exportando arquivos de dados salvos...</string>
89 <string name="save_file_imported_success">Importado com sucesso</string> 95 <string name="save_file_imported_success">Importado com sucesso</string>
90 <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados invalida</string> 96 <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados salvos inválida</string>
91 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string> 97 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta deve ser a ID do jogo.</string>
92 <string name="import_saves">Importar</string> 98 <string name="import_saves">Importar</string>
93 <string name="export_saves">Exportar</string> 99 <string name="export_saves">Exportar</string>
94 <string name="install_firmware">Instalar firmware</string> 100 <string name="install_firmware">Instalar firmware</string>
@@ -96,55 +102,89 @@
96 <string name="firmware_installing">Instalando firmware</string> 102 <string name="firmware_installing">Instalando firmware</string>
97 <string name="firmware_installed_success">Firmware instalado com sucesso.</string> 103 <string name="firmware_installed_success">Firmware instalado com sucesso.</string>
98 <string name="firmware_installed_failure">Falha na instalação do firmware</string> 104 <string name="firmware_installed_failure">Falha na instalação do firmware</string>
99 <string name="firmware_installed_failure_description">Cofirma que os ficheiros firmware nca estão no root do finheiro zip e tenta de novo.</string> 105 <string name="firmware_installed_failure_description">Verifique se os arquivos nca do firmware estão na raiz do arquivo zip e tente novamente.</string>
100 <string name="share_log">Compartilhe registros de debug.</string> 106 <string name="share_log">Compartilhar registros de debug</string>
101 <string name="share_log_description">Compartilhe o arquivo de registro do yuzu para obter ajuda com problemas</string> 107 <string name="share_log_description">Compartilhe o arquivo de registro do yuzu para obter ajuda com problemas</string>
102 <string name="share_log_missing">Arquivo de registro não encontrado</string> 108 <string name="share_log_missing">Arquivo de registro não encontrado</string>
103 <string name="install_game_content">Instalar conteúdo de jogos</string> 109 <string name="install_game_content">Instalar conteúdo de jogos</string>
104 <string name="install_game_content_description">Instalar atualizações de jogos ou DLC</string> 110 <string name="install_game_content_description">Instala atualizações de jogos ou DLC</string>
105 <string name="installing_game_content">A instalar conteúdo...</string> 111 <string name="installing_game_content">Instalando conteúdo...</string>
106 <string name="install_game_content_failure">Erro ao instalar ficheiro(s) para NAND</string> 112 <string name="install_game_content_failure">Erro ao instalar arquivo(s) na NAND</string>
107 <string name="install_game_content_failure_description">Por favor confitma que o conteúdo(s) é válido e que as prod.keys estão instaladas.</string> 113 <string name="install_game_content_failure_description">Por favor certifique-se de que o(s) conteúdo(s) é (são) válido(s) e que as prod.keys estão instaladas.</string>
108 <string name="install_game_content_failure_base">A instalação de jogos base não é permitida para evitar possíveis conflitos.</string> 114 <string name="install_game_content_failure_base">A instalação de jogos base não é permitida para evitar possíveis conflitos.</string>
109 <string name="install_game_content_failure_file_extension">Sò conteúdos NSP e XCI são suportados. Por favor verifica que o conteúdo(s) do jogo são válidos.</string> 115 <string name="install_game_content_failure_file_extension">Somente conteúdos NSP e XCI são suportados. Por favor verifique se o(s) conteúdo(s) do jogo é (são) válido(s).</string>
110 <string name="install_game_content_failed_count">%1$d erro(s) de instalação</string> 116 <string name="install_game_content_failed_count">%1$d erro(s) de instalação</string>
111 <string name="install_game_content_success">Conteúdo(s) de jogo instalados com sucesso</string> 117 <string name="install_game_content_success">Conteúdo(s) de jogo instalado(s) com sucesso</string>
112 <string name="install_game_content_success_install">%1$d instalado com sucesso</string> 118 <string name="install_game_content_success_install">%1$d instalado com sucesso</string>
113 <string name="install_game_content_success_overwrite">%1$d substituída com êxito</string> 119 <string name="install_game_content_success_overwrite">%1$d substituído com sucesso</string>
114 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> 120 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
115 <string name="custom_driver_not_supported">Drivers personalizados não suportados</string> 121 <string name="custom_driver_not_supported">Drivers personalizados não suportados</string>
116 <string name="custom_driver_not_supported_description">Carrea«gamento de drivers personalizados não é suportado pr este dispositivo. \nCheck verifica esta opção de futuro para confirmar se o suporte foi adicionado!</string> 122 <string name="custom_driver_not_supported_description">Carregamento de drivers personalizados não suportado para este dispositivo no momento.\nVerifique esse opção novamente no futuro para ver se o suporte foi adicionado!</string>
117 <string name="manage_yuzu_data">Administrar dados yuzu</string> 123 <string name="manage_yuzu_data">Administrar dados do yuzu</string>
118 <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string> 124 <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string>
119 <string name="share_save_file">Partilha ficheiro duardado</string> 125 <string name="share_save_file">Compartilhar arquivo de dados salvos</string>
120 <string name="export_save_failed">Erro ao exportar dados guardados</string> 126 <string name="export_save_failed">Erro ao exportar arquivo de dados salvos</string>
127 <string name="game_folders">Pastas de jogos</string>
128 <string name="deep_scan">Varredura profunda</string>
129 <string name="add_game_folder">Adicionar pasta de jogo</string>
130 <string name="folder_already_added">Esta pasta já foi adicionada!</string>
131 <string name="game_folder_properties">Propriedades da pasta de jogo</string>
132 <plurals name="saves_import_failed">
133 <item quantity="one">Falha ao importar dado salvo de %d</item>
134 <item quantity="many">Falha ao importar dados salvos de %d</item>
135 <item quantity="other">Falha ao importar dados salvos de %d</item>
136 </plurals>
137 <plurals name="saves_import_success">
138 <item quantity="one">Dado salvo de %d importado com sucesso</item>
139 <item quantity="many">Dados salvos de %d importados com sucesso</item>
140 <item quantity="other">Dados salvos de %d importados com sucesso</item>
141 </plurals>
142 <string name="no_save_data_found">Dados salvos não encontrados</string>
143
144 <!-- Applet launcher strings -->
145 <string name="applets">Launcher de miniaplicativos</string>
146 <string name="applets_description">Inicia miniaplicativos do sistema usando o firmware instalado</string>
147 <string name="applets_error_firmware">Firmware não instalado</string>
148 <string name="applets_error_applet">Miniaplicativo não disponível</string>
149 <string name="applets_error_description"><![CDATA[Por favor verifique se o arquivo 1prod.keys1 e o 2firmware2 estão instalados e tente novamente.]]></string>
150 <string name="album_applet">Ãlbum</string>
151 <string name="album_applet_description">Visualize imagens armazenadas na pasta de capturas de telas do usuário com o visualizador de imagens do sistema</string>
152 <string name="mii_edit_applet">Editor de Mii</string>
153 <string name="mii_edit_applet_description">Visualize e edite os Miis com o editor do sistema</string>
154 <string name="cabinet_applet">Arquivo</string>
155 <string name="cabinet_applet_description">Edite e delete dados armazenados nos amiibos</string>
156 <string name="cabinet_launcher">Inicializador do Arquivo</string>
157 <string name="cabinet_nickname_and_owner">Apelido e configurações do proprietário</string>
158 <string name="cabinet_game_data_eraser">Apagar dados de jogo</string>
159 <string name="cabinet_restorer">Restaurar</string>
160 <string name="cabinet_formatter">Formatar</string>
121 161
122 <!-- About screen strings --> 162 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia não é real</string> 163 <string name="gaia_is_not_real">Gaia não é real</string>
124 <string name="copied_to_clipboard">Copiado para a área de transferência</string> 164 <string name="copied_to_clipboard">Copiado para a área de transferência</string>
125 <string name="about_app_description">Um emulador Switch de código aberto</string> 165 <string name="about_app_description">Um emulador de Switch de código aberto</string>
126 <string name="contributors">Contribuidores</string> 166 <string name="contributors">Colaboradores</string>
127 <string name="contributors_description">Feito com \u2764 da equipa do Yuzu</string> 167 <string name="contributors_description">Feito com \u2764 da equipe do Yuzu</string>
128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 168 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">Projetos que tornam o yuzu para Android possível</string> 169 <string name="licenses_description">Projetos que tornam o yuzu para Android possível</string>
130 <string name="build">Versão</string> 170 <string name="build">Versão</string>
131 <string name="user_data">Dado de utilizados</string> 171 <string name="user_data">Dados do usuário</string>
132 <string name="user_data_description">Importar/exportar todos dados da aplicação data.\n\n Ao importar dados do utilizados, todos os dados existentes do utilizados serão excluídos!</string> 172 <string name="user_data_description">Importar/exportar todos os dados do aplicativo.\n\n Ao importar dados de usuário, todos os dados existentes do usuário serão excluídos!</string>
133 <string name="exporting_user_data">A exportar dados de utilizados...</string> 173 <string name="exporting_user_data">Exportando dados do usuário...</string>
134 <string name="importing_user_data">A importar dados de utilizador...</string> 174 <string name="importing_user_data">Importando dados do usuário...</string>
135 <string name="import_user_data">Importar dados de utilizados...</string> 175 <string name="import_user_data">Importar dados do usuário</string>
136 <string name="invalid_yuzu_backup">Backup yuzu inválido</string> 176 <string name="invalid_yuzu_backup">Backup do yuzu inválido</string>
137 <string name="user_data_export_success">Dados de utilizados exportados com sucesso</string> 177 <string name="user_data_export_success">Dados de usuário exportados com sucesso</string>
138 <string name="user_data_import_success">Dados de utilizador importado com sucesso</string> 178 <string name="user_data_import_success">Dados de usuário importados com sucesso</string>
139 <string name="user_data_export_cancelled">Exportação cancelada</string> 179 <string name="user_data_export_cancelled">Exportação cancelada</string>
140 <string name="user_data_import_failed_description">Verifiqua se as pastas de dados do utilizados estão na raiz da pasta zip e contêm um arquivo de configuração em config/config.ini e tenta novamente.</string> 180 <string name="user_data_import_failed_description">Verifiqua se as pastas de dados do usuário estão na raiz da pasta zip e contêm um arquivo de configuração em config/config.ini e tente novamente.</string>
141 <string name="support_link">https://discord.gg/u77vRWY</string> 181 <string name="support_link">https://discord.gg/u77vRWY</string>
142 <string name="website_link">https://yuzu-emu.org/</string> 182 <string name="website_link">https://yuzu-emu.org/</string>
143 <string name="github_link">https://github.com/yuzu-emu</string> 183 <string name="github_link">https://github.com/yuzu-emu</string>
144 184
145 <!-- Early access upgrade strings --> 185 <!-- Early access upgrade strings -->
146 <string name="early_access">Acesso antecipado</string> 186 <string name="early_access">Acesso Antecipado</string>
147 <string name="get_early_access">Obtém Acesso Antecipado</string> 187 <string name="get_early_access">Obtenha o Acesso Antecipado</string>
148 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string> 188 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
149 <string name="get_early_access_description">Recursos de ponta, acesso antecipado a atualizações e muito mais</string> 189 <string name="get_early_access_description">Recursos de ponta, acesso antecipado a atualizações e muito mais</string>
150 <string name="early_access_benefits">Benefícios do Acesso Antecipado</string> 190 <string name="early_access_benefits">Benefícios do Acesso Antecipado</string>
@@ -154,18 +194,19 @@
154 <string name="prioritized_support">Suporte prioritário</string> 194 <string name="prioritized_support">Suporte prioritário</string>
155 <string name="helping_game_preservation">Ajuda na preservação dos jogos</string> 195 <string name="helping_game_preservation">Ajuda na preservação dos jogos</string>
156 <string name="our_eternal_gratitude">A nossa eterna gratidão</string> 196 <string name="our_eternal_gratitude">A nossa eterna gratidão</string>
157 <string name="are_you_interested">Estás interessado?</string> 197 <string name="are_you_interested">Tem interesse?</string>
158 198
159 <!-- General settings strings --> 199 <!-- General settings strings -->
160 <string name="frame_limit_enable">Limite de velocidade</string> 200 <string name="frame_limit_enable">Limite de velocidade</string>
161 <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string> 201 <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
162 <string name="frame_limit_slider">Percentagem do limite de velocidade</string> 202 <string name="frame_limit_slider">Porcentagem do limite de velocidade</string>
163 <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string> 203 <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string>
164 <string name="cpu_accuracy">Precisão do CPU</string> 204 <string name="cpu_backend">Backend da CPU</string>
205 <string name="cpu_accuracy">Precisão da CPU</string>
165 <string name="value_with_units">%1$s%2$s</string> 206 <string name="value_with_units">%1$s%2$s</string>
166 207
167 <!-- System settings strings --> 208 <!-- System settings strings -->
168 <string name="use_docked_mode">Modo Ancorado</string> 209 <string name="use_docked_mode">Modo TV</string>
169 <string name="use_docked_mode_description">Aumenta a resolução, diminuindo o desempenho. O Modo Portátil é utilizado quando estiver desabilitado, diminuindo a resolução e melhorando o desempenho.</string> 210 <string name="use_docked_mode_description">Aumenta a resolução, diminuindo o desempenho. O Modo Portátil é utilizado quando estiver desabilitado, diminuindo a resolução e melhorando o desempenho.</string>
170 <string name="emulated_region">Região da emulação</string> 211 <string name="emulated_region">Região da emulação</string>
171 <string name="emulated_language">Idioma da emulação</string> 212 <string name="emulated_language">Idioma da emulação</string>
@@ -177,20 +218,22 @@
177 218
178 <!-- Graphics settings strings --> 219 <!-- Graphics settings strings -->
179 <string name="renderer_accuracy">Nível de precisão</string> 220 <string name="renderer_accuracy">Nível de precisão</string>
180 <string name="renderer_resolution">Resolução (Portátil/Ancorado)</string> 221 <string name="renderer_resolution">Resolução (Portátil/Modo TV)</string>
181 <string name="renderer_vsync">Modo VSync</string> 222 <string name="renderer_vsync">Modo VSync</string>
182 <string name="renderer_screen_layout">Oriantação</string> 223 <string name="renderer_screen_layout">Oriantação</string>
183 <string name="renderer_aspect_ratio">Proporção da tela</string> 224 <string name="renderer_aspect_ratio">Proporção da tela</string>
184 <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string> 225 <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
185 <string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string> 226 <string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string>
186 <string name="renderer_force_max_clock">Força velocidade máxima (Adreno only)</string> 227 <string name="renderer_force_max_clock">Forçar velocidade máxima (somente Adreno)</string>
187 <string name="renderer_force_max_clock_description">Força o GPU a correr à velocidade máxima (restrições térmicas serão aplicadas)</string> 228 <string name="renderer_force_max_clock_description">Força o GPU a rodar na velocidade máxima (restrições térmicas serão aplicadas)</string>
188 <string name="renderer_asynchronous_shaders">Usa shaders assíncronos </string> 229 <string name="renderer_asynchronous_shaders">Usar shaders assíncronos </string>
189 <string name="renderer_asynchronous_shaders_description">Compila os shaders de forma assíncrona, reduzindo travamentos, mas pode apresentar problemas.</string> 230 <string name="renderer_asynchronous_shaders_description">Compila os shaders de forma assíncrona, reduzindo travamentos, mas pode apresentar problemas.</string>
190 <string name="renderer_reactive_flushing">Usar flushing reativo</string> 231 <string name="renderer_reactive_flushing">Usar flushing reativo</string>
191 <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string> 232 <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string>
192 <string name="use_disk_shader_cache">Cache de shaders em disco</string> 233 <string name="use_disk_shader_cache">Cache de shaders em disco</string>
193 <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string> 234 <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string>
235 <string name="anisotropic_filtering">Filtragem anisotrópica</string>
236 <string name="anisotropic_filtering_description">Melhora a qualidade das texturas quando visualizadas de ângulos oblíquos</string>
194 237
195 <!-- Debug settings strings --> 238 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string> 239 <string name="cpu">CPU</string>
@@ -198,28 +241,29 @@
198 <string name="cpu_debug_mode_description">Coloca a CPU em um modo de depuração lento.</string> 241 <string name="cpu_debug_mode_description">Coloca a CPU em um modo de depuração lento.</string>
199 <string name="gpu">GPU</string> 242 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string> 243 <string name="renderer_api">API</string>
201 <string name="renderer_debug">Ativar depuração de gráficos</string> 244 <string name="renderer_debug">Depuração de gráficos</string>
202 <string name="renderer_debug_description">Quando selecionado, a API gráfica entra num modo de depuração mais lento.</string> 245 <string name="renderer_debug_description">Define a API gráfica para um modo de depuração mais lento.</string>
203 <string name="fastmem">Fastmem</string> 246 <string name="fastmem">Fastmem</string>
204 247
205 <!-- Audio settings strings --> 248 <!-- Audio settings strings -->
206 <string name="audio_output_engine">Motor de saída</string> 249 <string name="audio_output_engine">Engine de reprodução</string>
207 <string name="audio_volume">Volume</string> 250 <string name="audio_volume">Volume</string>
208 <string name="audio_volume_description">Especifica o volume de saída.</string> 251 <string name="audio_volume_description">Especifica o volume de reprodução.</string>
209 252
210 <!-- Miscellaneous --> 253 <!-- Miscellaneous -->
211 <string name="slider_default">Padrão</string> 254 <string name="slider_default">Padrão</string>
212 <string name="ini_saved">Definições guardadas</string> 255 <string name="ini_saved">Configurações salvas</string>
213 <string name="gameid_saved">Definições guardadas para %1$s</string> 256 <string name="gameid_saved">Configurações salvas para %1$s</string>
214 <string name="error_saving">Erro ao guardar %1$s.ini: %2$s</string> 257 <string name="error_saving">Erro ao salvar %1$s.ini: %2$s</string>
215 <string name="unimplemented_menu">Menu não implementado</string> 258 <string name="unimplemented_menu">Menu não implementado</string>
216 <string name="loading">A carregar...</string> 259 <string name="loading">Carregando...</string>
217 <string name="shutting_down">A desligar...</string> 260 <string name="shutting_down">Encerrando...</string>
218 <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string> 261 <string name="reset_setting_confirmation">Deseja reverter esta configuração para os valores padrões?</string>
219 <string name="reset_to_default">Reverter para padrão</string> 262 <string name="reset_to_default">Reverter para o padrão</string>
220 <string name="reset_all_settings">Redefinir todas as definições?</string> 263 <string name="reset_to_default_description">Redefine todas as configurações avançadas</string>
264 <string name="reset_all_settings">Redefinir todas as configurações?</string>
221 <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string> 265 <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string>
222 <string name="settings_reset">Redefinir definições</string> 266 <string name="settings_reset">Configurações redefinidas</string>
223 <string name="close">Fechar</string> 267 <string name="close">Fechar</string>
224 <string name="learn_more">Saiba mais</string> 268 <string name="learn_more">Saiba mais</string>
225 <string name="auto">Automático</string> 269 <string name="auto">Automático</string>
@@ -227,44 +271,95 @@
227 <string name="string_null">Nenhum (desativado)</string> 271 <string name="string_null">Nenhum (desativado)</string>
228 <string name="string_import">Importar</string> 272 <string name="string_import">Importar</string>
229 <string name="export">Exportar</string> 273 <string name="export">Exportar</string>
230 <string name="export_failed">Exportação falhada</string> 274 <string name="export_failed">Falha ao exportar</string>
231 <string name="import_failed">IMportação falhada</string> 275 <string name="import_failed">Falha ao importar</string>
232 <string name="cancelling">A cancelar</string> 276 <string name="cancelling">Cancelando</string>
233 277 <string name="install">Instalar</string>
278 <string name="delete">Deletar</string>
279 <string name="edit">Editar</string>
280 <string name="export_success">Exportado com sucesso</string>
281 <string name="start">Start</string>
282 <string name="clear">Limpar</string>
283 <string name="global">Global</string>
284 <string name="custom">Personalizado</string>
285 <string name="notice">Aviso</string>
286 <string name="import_complete">Importação concluída</string>
234 <!-- GPU driver installation --> 287 <!-- GPU driver installation -->
235 <string name="select_gpu_driver">Seleciona a driver para o GPU</string> 288 <string name="select_gpu_driver">Selecione o driver para a GPU</string>
236 <string name="select_gpu_driver_title">Queres substituir o driver do GPU atual? </string> 289 <string name="select_gpu_driver_title">Gostaria de substituir o driver atual da GPU? </string>
237 <string name="select_gpu_driver_install">Instalar</string> 290 <string name="select_gpu_driver_install">Instalar</string>
238 <string name="select_gpu_driver_default">Padrão</string> 291 <string name="select_gpu_driver_default">Padrão</string>
239 <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string> 292 <string name="select_gpu_driver_use_default">Usar o driver padrão da GPU</string>
240 <string name="select_gpu_driver_error">Driver selecionado inválido, a usar o padrão do sistema!</string> 293 <string name="select_gpu_driver_error">Driver selecionado inválido</string>
241 <string name="system_gpu_driver">Driver do GPU padrão</string> 294 <string name="driver_already_installed">Driver já instalado</string>
242 <string name="installing_driver">A instalar o Driver...</string> 295 <string name="system_gpu_driver">Driver padrão da GPU</string>
296 <string name="installing_driver">Instalando driver...</string>
243 297
244 <!-- Preferences Screen --> 298 <!-- Preferences Screen -->
245 <string name="preferences_settings">Configurações</string> 299 <string name="preferences_settings">Configurações</string>
246 <string name="preferences_general">Geral</string> 300 <string name="preferences_general">Geral</string>
247 <string name="preferences_system">Sistema</string> 301 <string name="preferences_system">Sistema</string>
302 <string name="preferences_system_description">Modo TV, região, idioma</string>
248 <string name="preferences_graphics">Gráficos</string> 303 <string name="preferences_graphics">Gráficos</string>
304 <string name="preferences_graphics_description">Nível de precisão, resolução, cache de shader</string>
249 <string name="preferences_audio">Ãudio</string> 305 <string name="preferences_audio">Ãudio</string>
250 <string name="preferences_theme">Cor e tema.</string> 306 <string name="preferences_audio_description">Engine de reprodução, volume</string>
307 <string name="preferences_theme">Tema e cor</string>
251 <string name="preferences_debug">Depuração</string> 308 <string name="preferences_debug">Depuração</string>
252 309 <string name="preferences_debug_description">Depuração de CPU/GPU, API gráfica, fastmem</string>
310
311 <!-- Game properties -->
312 <string name="info">Informações</string>
313 <string name="info_description">ID do Programa, desenvolvedora, versão</string>
314 <string name="per_game_settings">Configurações por jogo</string>
315 <string name="per_game_settings_description">Edite configurações específicas para este jogo</string>
316 <string name="launch_options">Configurações de inicialização</string>
317 <string name="path">Caminho</string>
318 <string name="program_id">ID do Programa</string>
319 <string name="developer">Desenvolvedora</string>
320 <string name="version">Versão</string>
321 <string name="copy_details">Copiar detalhes</string>
322 <string name="add_ons">Adicionais</string>
323 <string name="add_ons_description">Gerencie mods, atualizações e DLC</string>
324 <string name="clear_shader_cache">Excluir cache de shaders</string>
325 <string name="clear_shader_cache_description">Remove todos os shaders compilados durante a execução do jogo</string>
326 <string name="clear_shader_cache_warning_description">Você terá mais travamentos enquanto o cache de shaders for recompilado</string>
327 <string name="cleared_shaders_successfully">Shaders excluídos com sucesso</string>
328 <string name="addons_game">Adicionais: %1$s</string>
329 <string name="save_data">Dados salvos</string>
330 <string name="save_data_description">Gerencie dados salvos específicos deste jogo</string>
331 <string name="delete_save_data">Deletar dados salvos</string>
332 <string name="delete_save_data_description">Remove todos os dados salvos específicos deste jogo</string>
333 <string name="delete_save_data_warning_description">Isso removerá permanentemente todos os dados salvos do jogo. Tem certeza de que quer continuar?</string>
334 <string name="save_data_deleted_successfully">Dados salvos deletados com sucesso </string>
335 <string name="select_content_type">Tipo de conteúdo</string>
336 <string name="updates_and_dlc">Atualizações e DLC</string>
337 <string name="mods_and_cheats">Mods e cheats</string>
338 <string name="addon_notice">Aviso importante sobre os adicionais</string>
339 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
340 <string name="addon_notice_description">Para instalar mods e cheats, você deve selecionar uma pasta que contenha um diretório cheats/, romfs/ ou exefs. Não podemos verificar se eles são compatíveis com seu jogo, então tenha cuidado!</string>
341 <string name="invalid_directory">Diretório inválido </string>
342 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
343 <string name="invalid_directory_description">Por favor verifique se o diretório selecionado contém uma pasta cheats/, romfs/ ou exefs/ e tente novamente.</string>
344 <string name="addon_installed_successfully">Adicional instalado com sucesso</string>
345 <string name="verifying_content">Verificando conteúdo...</string>
346 <string name="content_install_notice">Aviso sobre conteúdo adicional</string>
347 <string name="content_install_notice_description">O conteúdo que você selecionou não corresponde a este jogo.\nInstalar mesmo assim?</string>
253 <!-- ROM loading errors --> 348 <!-- ROM loading errors -->
254 <string name="loader_error_encrypted">A tua ROM está encriptada</string> 349 <string name="loader_error_encrypted">Sua ROM está encriptada</string>
255 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para despejar novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">títulos instalados</a>.]]></string> 350 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para extrair novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> ou <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">títulos instalados</a>.]]></string>
256 <string name="loader_error_encrypted_keys_description"><![CDATA[Por favor confirma que o teu ficheiro <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> está instalado para que os jogos possam ser desencriptados.]]></string> 351 <string name="loader_error_encrypted_keys_description"><![CDATA[Por favor verifique se o seu arquivo <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> está instalado para que os jogos possam ser decriptados.]]></string>
257 <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vídeo.</string> 352 <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vídeo.</string>
258 <string name="loader_error_video_core_description">Isto é normalmente causado por um driver de GPU incompatível. Instalar um driver GPU pode resolver este problema.</string> 353 <string name="loader_error_video_core_description">Isto é normalmente causado por um driver de GPU incompatível. Instalar um driver de GPU pode resolver este problema.</string>
259 <string name="loader_error_invalid_format">Impossível carregar a tua ROM</string> 354 <string name="loader_error_invalid_format">Impossível carregar a ROM</string>
260 <string name="loader_error_file_not_found">O ficheiro da ROM não existe</string> 355 <string name="loader_error_file_not_found">O arquivo ROM não existe</string>
261 356
262 <!-- Emulation Menu --> 357 <!-- Emulation Menu -->
263 <string name="emulation_exit">Parar emulação</string> 358 <string name="emulation_exit">Sair da emulação</string>
264 <string name="emulation_done">Feito</string> 359 <string name="emulation_done">Feito</string>
265 <string name="emulation_fps_counter">Contador de FPS</string> 360 <string name="emulation_fps_counter">Contador de FPS</string>
266 <string name="emulation_toggle_controls">Alterar controles</string> 361 <string name="emulation_toggle_controls">Marcar/Desmarcar botões</string>
267 <string name="emulation_rel_stick_center">Centro Relativo de Analógico</string> 362 <string name="emulation_rel_stick_center">Centro Relativo do Analógico</string>
268 <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string> 363 <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string>
269 <string name="emulation_haptics">Vibração ao tocar</string> 364 <string name="emulation_haptics">Vibração ao tocar</string>
270 <string name="emulation_show_overlay">Mostrar overlay</string> 365 <string name="emulation_show_overlay">Mostrar overlay</string>
@@ -272,28 +367,29 @@
272 <string name="emulation_control_adjust">Ajustar overlay</string> 367 <string name="emulation_control_adjust">Ajustar overlay</string>
273 <string name="emulation_control_scale">Escala</string> 368 <string name="emulation_control_scale">Escala</string>
274 <string name="emulation_control_opacity">Opacidade</string> 369 <string name="emulation_control_opacity">Opacidade</string>
275 <string name="emulation_touch_overlay_reset">Restaurar overlay padrão</string> 370 <string name="emulation_touch_overlay_reset">Resetar overlay</string>
276 <string name="emulation_touch_overlay_edit">Editar overlay</string> 371 <string name="emulation_touch_overlay_edit">Editar overlay</string>
277 <string name="emulation_pause">Pausar emulação</string> 372 <string name="emulation_pause">Pausar emulação</string>
278 <string name="emulation_unpause">Retomar emulação</string> 373 <string name="emulation_unpause">Retomar a emulação</string>
279 <string name="emulation_input_overlay">Opções de overlay</string> 374 <string name="emulation_input_overlay">Opções de overlay</string>
375 <string name="touchscreen">Tela de toque</string>
280 376
281 <string name="load_settings">Carregando configurações...</string> 377 <string name="load_settings">Carregando configurações...</string>
282 378
283 <!-- Software keyboard --> 379 <!-- Software keyboard -->
284 <string name="software_keyboard">Teclado de software</string> 380 <string name="software_keyboard">Teclado do software</string>
285 381
286 <!-- Errors and warnings --> 382 <!-- Errors and warnings -->
287 <string name="abort_button">Abortar</string> 383 <string name="abort_button">Abortar</string>
288 <string name="continue_button">Continuar</string> 384 <string name="continue_button">Continuar</string>
289 <string name="system_archive_not_found">Arquivo do sistema não encontrado</string> 385 <string name="system_archive_not_found">Arquivo do Sistema Não Encontrado</string>
290 <string name="system_archive_not_found_message">%s está em falta. Por favor apaga os teus ficheiros de sistema.\nContinuar a emulação pode causar erros.</string> 386 <string name="system_archive_not_found_message">%s está faltando. Por favor extraia seus arquivos de sistema.\nContinuar a emulação pode causar travamentos e bugs.</string>
291 <string name="system_archive_general">Um arquivo do sistema</string> 387 <string name="system_archive_general">Um arquivo do sistema</string>
292 <string name="save_load_error">Erro Guardar/Carregar</string> 388 <string name="save_load_error">Erro de Salvamento/Carregamento</string>
293 <string name="fatal_error">Erro fatal</string> 389 <string name="fatal_error">Erro fatal</string>
294 <string name="fatal_error_message">Ocorreu um erro fatal. Verifica o teu registro para detalhes. \nContinuar a emulação pode causar erros.</string> 390 <string name="fatal_error_message">Ocorreu um erro fatal. Verifique o arquivo de registro para detalhes.\nContinuar a emulação pode causar travamentos e bugs.</string>
295 <string name="performance_warning">Desligar esta configuração irá reduzir a performance da emulação significantemente! Para a melhor experiência é recomendado que deixes esta configuração ativada.</string> 391 <string name="performance_warning">Desligar esta configuração irá reduzir a performance da emulação significantemente! Para a melhor experiência é recomendado deixar esta configuração ativada.</string>
296 <string name="device_memory_inadequate">RAM do dispositivo: %1$s\nRecommended: %2$s</string> 392 <string name="device_memory_inadequate">RAM do dispositivo: %1$s\nRecomendada: %2$s</string>
297 <string name="memory_formatted">%1$s %2$s</string> 393 <string name="memory_formatted">%1$s %2$s</string>
298 <string name="no_game_present">Nenhum jogo inicializável presente!</string> 394 <string name="no_game_present">Nenhum jogo inicializável presente!</string>
299 395
@@ -308,6 +404,7 @@
308 404
309 <!-- Memory Sizes --> 405 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string> 406 <string name="memory_byte">Byte</string>
407 <string name="memory_byte_shorthand">B</string>
311 <string name="memory_kilobyte">KB</string> 408 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string> 409 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string> 410 <string name="memory_gigabyte">GB</string>
@@ -316,19 +413,19 @@
316 <string name="memory_exabyte">EB</string> 413 <string name="memory_exabyte">EB</string>
317 414
318 <!-- Renderer APIs --> 415 <!-- Renderer APIs -->
319 <string name="renderer_vulkan">Vulcano</string> 416 <string name="renderer_vulkan">Vulkan</string>
320 <string name="renderer_none">Nenhum</string> 417 <string name="renderer_none">Nenhum</string>
321 418
322 <!-- Renderer Accuracy --> 419 <!-- Renderer Accuracy -->
323 <string name="renderer_accuracy_normal">Normal</string> 420 <string name="renderer_accuracy_normal">Normal</string>
324 <string name="renderer_accuracy_high">Alto</string> 421 <string name="renderer_accuracy_high">Alto</string>
325 <string name="renderer_accuracy_extreme">Estremo (Lento)</string> 422 <string name="renderer_accuracy_extreme">Extremo (Lento)</string>
326 423
327 <!-- Resolutions --> 424 <!-- Resolutions -->
328 <string name="resolution_half">0.5X (360p/540p)</string> 425 <string name="resolution_half">0.5X (360p/540p)</string>
329 <string name="resolution_three_quarter">0.75X (540p/810p)</string> 426 <string name="resolution_three_quarter">0.75X (540p/810p)</string>
330 <string name="resolution_one">1X (720p/1080p)</string> 427 <string name="resolution_one">1X (720p/1080p)</string>
331 <string name="resolution_two">2X (1440p/2160p) (Slow)</string> 428 <string name="resolution_two">2X (1440p/2160p) (Lento)</string>
332 <string name="resolution_three">3X (2160p/3240p) (Lento)</string> 429 <string name="resolution_three">3X (2160p/3240p) (Lento)</string>
333 <string name="resolution_four">4X (2880p/4320p) (Lento)</string> 430 <string name="resolution_four">4X (2880p/4320p) (Lento)</string>
334 431
@@ -352,9 +449,13 @@
352 <string name="anti_aliasing_smaa">SMAA</string> 449 <string name="anti_aliasing_smaa">SMAA</string>
353 450
354 <!-- Screen Layouts --> 451 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">Landscape</string> 452 <string name="screen_layout_auto">Automática</string>
356 <string name="screen_layout_portrait">Portrait</string> 453 <string name="screen_layout_sensor_landscape">Paisagem pelo sensor</string>
357 <string name="screen_layout_auto">Automático</string> 454 <string name="screen_layout_landscape">Paisagem</string>
455 <string name="screen_layout_reverse_landscape">Paisagem invertida</string>
456 <string name="screen_layout_sensor_portrait">Retrato pelo sensor</string>
457 <string name="screen_layout_portrait">Retrato</string>
458 <string name="screen_layout_reverse_portrait">Retrato invertido</string>
358 459
359 <!-- Aspect Ratios --> 460 <!-- Aspect Ratios -->
360 <string name="ratio_default">Padrão (16:9)</string> 461 <string name="ratio_default">Padrão (16:9)</string>
@@ -363,21 +464,25 @@
363 <string name="ratio_force_sixteen_ten">Forçar 16:10</string> 464 <string name="ratio_force_sixteen_ten">Forçar 16:10</string>
364 <string name="ratio_stretch">Esticar à janela</string> 465 <string name="ratio_stretch">Esticar à janela</string>
365 466
467 <!-- CPU Backend -->
468 <string name="cpu_backend_dynarmic">Dynarmic (Lento)</string>
469 <string name="cpu_backend_nce">Execução de código nativo (NCE)</string>
470
366 <!-- CPU Accuracy --> 471 <!-- CPU Accuracy -->
367 <string name="cpu_accuracy_accurate">Preciso</string> 472 <string name="cpu_accuracy_accurate">Preciso</string>
368 <string name="cpu_accuracy_unsafe">Não seguro</string> 473 <string name="cpu_accuracy_unsafe">Não seguro</string>
369 <string name="cpu_accuracy_paranoid">Paranoid (Lento)</string> 474 <string name="cpu_accuracy_paranoid">Paranóico (Lento)</string>
370 475
371 <!-- Gamepad Buttons --> 476 <!-- Gamepad Buttons -->
372 <string name="gamepad_d_pad">Botões Direcionais</string> 477 <string name="gamepad_d_pad">Botões Direcionais</string>
373 <string name="gamepad_left_stick">Analógico esquerdo</string> 478 <string name="gamepad_left_stick">Analógico esquerdo</string>
374 <string name="gamepad_right_stick">Analógico direito</string> 479 <string name="gamepad_right_stick">Analógico direito</string>
375 <string name="gamepad_home">Botão Home</string> 480 <string name="gamepad_home">Botão Home</string>
376 <string name="gamepad_screenshot">Captura de ecrã</string> 481 <string name="gamepad_screenshot">Captura de tela</string>
377 482
378 <!-- Disk shader cache --> 483 <!-- Disk shader cache -->
379 <string name="preparing_shaders">A preparar shaders</string> 484 <string name="preparing_shaders">Preparando shaders</string>
380 <string name="building_shaders">A criar shaders</string> 485 <string name="building_shaders">Criando shaders</string>
381 486
382 <!-- Theme options --> 487 <!-- Theme options -->
383 <string name="change_app_theme">Mudar o tema do aplicativo</string> 488 <string name="change_app_theme">Mudar o tema do aplicativo</string>
@@ -391,19 +496,26 @@
391 <string name="theme_mode_dark">Escuro</string> 496 <string name="theme_mode_dark">Escuro</string>
392 497
393 <!-- Audio output engines --> 498 <!-- Audio output engines -->
499 <string name="oboe">oboe</string>
394 <string name="cubeb">cubeb</string> 500 <string name="cubeb">cubeb</string>
395 501
502 <!-- Anisotropic filtering options -->
503 <string name="multiplier_two">2x</string>
504 <string name="multiplier_four">4x</string>
505 <string name="multiplier_eight">8x</string>
506 <string name="multiplier_sixteen">16x</string>
507
396 <!-- Black backgrounds theme --> 508 <!-- Black backgrounds theme -->
397 <string name="use_black_backgrounds">Plano de fundo preto</string> 509 <string name="use_black_backgrounds">Plano de fundo preto</string>
398 <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string> 510 <string name="use_black_backgrounds_description">Quando usar o tema escuro, aplicar fundos pretos</string>
399 511
400 <!-- Picture-In-Picture --> 512 <!-- Picture-In-Picture -->
401 <string name="picture_in_picture">Picture in Picture</string> 513 <string name="picture_in_picture">Picture in Picture</string>
402 <string name="picture_in_picture_description">Minimizar a janela quando colocada em segundo plano</string> 514 <string name="picture_in_picture_description">Minimiza a janela quando colocada em segundo plano</string>
403 <string name="pause">Pausa</string> 515 <string name="pause">Pausar</string>
404 <string name="play">Correr</string> 516 <string name="play">Executar</string>
405 <string name="mute">Mudo</string> 517 <string name="mute">Mudo</string>
406 <string name="unmute">Unmute</string> 518 <string name="unmute">Tirar do Mudo</string>
407 519
408 <!-- Licenses screen strings --> 520 <!-- Licenses screen strings -->
409 <string name="licenses">Licenças</string> 521 <string name="licenses">Licenças</string>
diff --git a/src/android/app/src/main/res/values-pt-rPT/strings.xml b/src/android/app/src/main/res/values-pt-rPT/strings.xml
index 6afea9b03..684a71616 100644
--- a/src/android/app/src/main/res/values-pt-rPT/strings.xml
+++ b/src/android/app/src/main/res/values-pt-rPT/strings.xml
@@ -34,6 +34,7 @@
34 <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string> 34 <string name="empty_gamelist">Não foram encontrados jogos ou a pasta de Jogos ainda não foi definida. </string>
35 <string name="search_and_filter_games">Procura e filtra jogos.</string> 35 <string name="search_and_filter_games">Procura e filtra jogos.</string>
36 <string name="select_games_folder">Seleciona a pasta de jogos.</string> 36 <string name="select_games_folder">Seleciona a pasta de jogos.</string>
37 <string name="manage_game_folders">Gerencie as pastas de jogos</string>
37 <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string> 38 <string name="select_games_folder_description">Permite que o Yuzu preencha a lista de jogos</string>
38 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> 39 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string>
39 <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string> 40 <string name="add_games_warning_description">Os jogos não serão exibidos na lista de jogos se uma pasta não estiver selecionada.</string>
@@ -68,6 +69,7 @@
68 <string name="invalid_keys_error">Chaves de encriptação inválidas</string> 69 <string name="invalid_keys_error">Chaves de encriptação inválidas</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string> 71 <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string>
72 <string name="gpu_driver_manager">Gerenciador de driver de GPU</string>
71 <string name="install_gpu_driver">Instala driver para GPU</string> 73 <string name="install_gpu_driver">Instala driver para GPU</string>
72 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> 74 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string>
73 <string name="advanced_settings">Configurações avançadas</string> 75 <string name="advanced_settings">Configurações avançadas</string>
@@ -85,7 +87,11 @@
85 <string name="notification_no_directory_link_description">Localiza a pasta de utilizador manualmente com o painel lateral do gestor de ficheiros.</string> 87 <string name="notification_no_directory_link_description">Localiza a pasta de utilizador manualmente com o painel lateral do gestor de ficheiros.</string>
86 <string name="manage_save_data">Gerir dados guardados</string> 88 <string name="manage_save_data">Gerir dados guardados</string>
87 <string name="manage_save_data_description">Dados não encontrados. Por favor seleciona uma opção abaixo.</string> 89 <string name="manage_save_data_description">Dados não encontrados. Por favor seleciona uma opção abaixo.</string>
90 <string name="import_save_warning">Importar dados salvos</string>
91 <string name="import_save_warning_description">Isso irá sobrescrever seus dados salvos com o arquivo selecionado. Você tem certeza que quer continuar?</string>
88 <string name="import_export_saves_description">Importa ou exporta dados guardados</string> 92 <string name="import_export_saves_description">Importa ou exporta dados guardados</string>
93 <string name="save_files_importing">Importando dados salvos...</string>
94 <string name="save_files_exporting">Exportando arquivos de dados salvos...</string>
89 <string name="save_file_imported_success">Importado com sucesso</string> 95 <string name="save_file_imported_success">Importado com sucesso</string>
90 <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados invalida</string> 96 <string name="save_file_invalid_zip_structure">Estrutura de diretório de dados invalida</string>
91 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string> 97 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string>
@@ -118,6 +124,40 @@
118 <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string> 124 <string name="manage_yuzu_data_description">Importa/exporta firmware, chaves, dados do usuário e mais!</string>
119 <string name="share_save_file">Partilha ficheiro duardado</string> 125 <string name="share_save_file">Partilha ficheiro duardado</string>
120 <string name="export_save_failed">Erro ao exportar dados guardados</string> 126 <string name="export_save_failed">Erro ao exportar dados guardados</string>
127 <string name="game_folders">Pastas de jogos</string>
128 <string name="deep_scan">Varredura profunda</string>
129 <string name="add_game_folder">Adicionar pasta de jogo</string>
130 <string name="folder_already_added">Esta pasta já foi adicionada!</string>
131 <string name="game_folder_properties">Propriedades da pasta de jogo</string>
132 <plurals name="saves_import_failed">
133 <item quantity="one">Falha ao importar dado salvo de %d</item>
134 <item quantity="many">Falha ao importar dados salvos de %d</item>
135 <item quantity="other">Falha ao importar dados salvos de %d</item>
136 </plurals>
137 <plurals name="saves_import_success">
138 <item quantity="one">Dado salvo de %d importado com sucesso</item>
139 <item quantity="many">Dados salvos de %d importados com sucesso</item>
140 <item quantity="other">Dados salvos de %d importados com sucesso</item>
141 </plurals>
142 <string name="no_save_data_found">Dados salvos não encontrados</string>
143
144 <!-- Applet launcher strings -->
145 <string name="applets">Launcher de miniaplicativos</string>
146 <string name="applets_description">Inicie miniaplicativos do sistema usando o firmware instalado</string>
147 <string name="applets_error_firmware">Firmware não instalado</string>
148 <string name="applets_error_applet">Miniaplicativo não disponível</string>
149 <string name="applets_error_description"><![CDATA[Por favor verifique se o arquivo 1prod.keys1 e o 2firmware2 estão instalados e tente novamente.]]></string>
150 <string name="album_applet">Ãlbum</string>
151 <string name="album_applet_description">Visualize imagens armazenadas na pasta de capturas de telas do usuário com o visualizador de imagens do sistema</string>
152 <string name="mii_edit_applet">Editor de Mii</string>
153 <string name="mii_edit_applet_description">Visualize e edite os Miis com o editor do sistema</string>
154 <string name="cabinet_applet">Arquivo</string>
155 <string name="cabinet_applet_description">Edite e delete dados armazenados nos amiibos</string>
156 <string name="cabinet_launcher">Inicializador do Arquivo</string>
157 <string name="cabinet_nickname_and_owner">Apelido e configurações do proprietário</string>
158 <string name="cabinet_game_data_eraser">Apagar dados de jogo</string>
159 <string name="cabinet_restorer">Restaurar</string>
160 <string name="cabinet_formatter">Formatar</string>
121 161
122 <!-- About screen strings --> 162 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia não é real</string> 163 <string name="gaia_is_not_real">Gaia não é real</string>
@@ -161,6 +201,7 @@
161 <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string> 201 <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
162 <string name="frame_limit_slider">Percentagem do limite de velocidade</string> 202 <string name="frame_limit_slider">Percentagem do limite de velocidade</string>
163 <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string> 203 <string name="frame_limit_slider_description">Especifica a porcentagem para limitar a velocidade de emulação. 100% é o normal. Valores mais altos ou mais baixos irão aumentar ou diminuir o limite de velocidade.</string>
204 <string name="cpu_backend">Backend da CPU</string>
164 <string name="cpu_accuracy">Precisão do CPU</string> 205 <string name="cpu_accuracy">Precisão do CPU</string>
165 <string name="value_with_units">%1$s%2$s</string> 206 <string name="value_with_units">%1$s%2$s</string>
166 207
@@ -191,6 +232,8 @@
191 <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string> 232 <string name="renderer_reactive_flushing_description">Melhora a precisão da renderização em alguns jogos ao custo de desempenho.</string>
192 <string name="use_disk_shader_cache">Cache de shaders em disco</string> 233 <string name="use_disk_shader_cache">Cache de shaders em disco</string>
193 <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string> 234 <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string>
235 <string name="anisotropic_filtering">Filtragem anisotrópica</string>
236 <string name="anisotropic_filtering_description">Melhora a qualidade das texturas quando visualizadas de ângulos oblíquos</string>
194 237
195 <!-- Debug settings strings --> 238 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string> 239 <string name="cpu">CPU</string>
@@ -217,6 +260,7 @@
217 <string name="shutting_down">A desligar...</string> 260 <string name="shutting_down">A desligar...</string>
218 <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string> 261 <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string>
219 <string name="reset_to_default">Reverter para padrão</string> 262 <string name="reset_to_default">Reverter para padrão</string>
263 <string name="reset_to_default_description">Reverte todas as configurações avançadas</string>
220 <string name="reset_all_settings">Redefinir todas as configurações?</string> 264 <string name="reset_all_settings">Redefinir todas as configurações?</string>
221 <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string> 265 <string name="reset_all_settings_description">Todas as configurações avançadas retornarão ao padrão. Isto não pode ser desfeito.</string>
222 <string name="settings_reset">Redefinir configurações </string> 266 <string name="settings_reset">Redefinir configurações </string>
@@ -230,14 +274,24 @@
230 <string name="export_failed">Exportação falhada</string> 274 <string name="export_failed">Exportação falhada</string>
231 <string name="import_failed">IMportação falhada</string> 275 <string name="import_failed">IMportação falhada</string>
232 <string name="cancelling">A cancelar</string> 276 <string name="cancelling">A cancelar</string>
233 277 <string name="install">Instalar</string>
278 <string name="delete">Apagar</string>
279 <string name="edit">Editar</string>
280 <string name="export_success">Exportado com sucesso</string>
281 <string name="start">Começar</string>
282 <string name="clear">Limpar</string>
283 <string name="global">Global</string>
284 <string name="custom">Personalizado</string>
285 <string name="notice">Aviso</string>
286 <string name="import_complete">Importação concluída</string>
234 <!-- GPU driver installation --> 287 <!-- GPU driver installation -->
235 <string name="select_gpu_driver">Seleciona a driver para o GPU</string> 288 <string name="select_gpu_driver">Seleciona a driver para o GPU</string>
236 <string name="select_gpu_driver_title">Queres substituir o driver do GPU atual? </string> 289 <string name="select_gpu_driver_title">Queres substituir o driver do GPU atual? </string>
237 <string name="select_gpu_driver_install">Instalar</string> 290 <string name="select_gpu_driver_install">Instalar</string>
238 <string name="select_gpu_driver_default">Padrão</string> 291 <string name="select_gpu_driver_default">Padrão</string>
239 <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string> 292 <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string>
240 <string name="select_gpu_driver_error">Driver selecionado inválido, a usar o padrão do sistema!</string> 293 <string name="select_gpu_driver_error">Driver selecionado inválido</string>
294 <string name="driver_already_installed">Driver já instalado</string>
241 <string name="system_gpu_driver">Driver do GPU padrão</string> 295 <string name="system_gpu_driver">Driver do GPU padrão</string>
242 <string name="installing_driver">A instalar o Driver...</string> 296 <string name="installing_driver">A instalar o Driver...</string>
243 297
@@ -245,11 +299,52 @@
245 <string name="preferences_settings">Configurações</string> 299 <string name="preferences_settings">Configurações</string>
246 <string name="preferences_general">Geral</string> 300 <string name="preferences_general">Geral</string>
247 <string name="preferences_system">Sistema</string> 301 <string name="preferences_system">Sistema</string>
302 <string name="preferences_system_description">Modo ancorado, região, idioma</string>
248 <string name="preferences_graphics">Gráficos</string> 303 <string name="preferences_graphics">Gráficos</string>
304 <string name="preferences_graphics_description">Nível de precisão, resolução, cache de shader</string>
249 <string name="preferences_audio">Audio</string> 305 <string name="preferences_audio">Audio</string>
306 <string name="preferences_audio_description">Engine de reprodução, volume</string>
250 <string name="preferences_theme">Cor e tema.</string> 307 <string name="preferences_theme">Cor e tema.</string>
251 <string name="preferences_debug">Depurar</string> 308 <string name="preferences_debug">Depurar</string>
252 309 <string name="preferences_debug_description">Depuração de CPU/GPU, API gráfica, fastmem</string>
310
311 <!-- Game properties -->
312 <string name="info">Informação</string>
313 <string name="info_description">ID do programa, desenvolvedor, versão</string>
314 <string name="per_game_settings">Configurações por jogo</string>
315 <string name="per_game_settings_description">Editar configurações específicas para este jogo</string>
316 <string name="launch_options">Iniciar configuração</string>
317 <string name="path">Caminho</string>
318 <string name="program_id">ID do programa</string>
319 <string name="developer">Desenvolvedor</string>
320 <string name="version">Versão</string>
321 <string name="copy_details">Copiar detalhes</string>
322 <string name="add_ons">Add-ons</string>
323 <string name="add_ons_description">Gerencie mods, atualizações e DLC</string>
324 <string name="clear_shader_cache">Limpar cache de shaders</string>
325 <string name="clear_shader_cache_description">Remove todos os shaders compilados enquanto esse jogo era jogado</string>
326 <string name="clear_shader_cache_warning_description">Você terá mais travamentos enquanto o cache de shaders for recompilado</string>
327 <string name="cleared_shaders_successfully">Shaders excluídos com sucesso</string>
328 <string name="addons_game">Adicionais: %1$s</string>
329 <string name="save_data">Salvar dados</string>
330 <string name="save_data_description">Gerenciar dados salvos específicos deste jogo</string>
331 <string name="delete_save_data">Apagar dados salvos</string>
332 <string name="delete_save_data_description">Remover todos os dados salvos específicos deste jogo</string>
333 <string name="delete_save_data_warning_description">Isso removerá permanentemente todos os dados salvos do jogo. Tem certeza de que quer continuar?</string>
334 <string name="save_data_deleted_successfully">Dados salvos removidos com sucesso </string>
335 <string name="select_content_type">Tipo de conteúdo</string>
336 <string name="updates_and_dlc">Atualizações e DLC</string>
337 <string name="mods_and_cheats">Mods e trapaças</string>
338 <string name="addon_notice">Aviso importante sobre os adicionais</string>
339 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
340 <string name="addon_notice_description">Para instalar mods e cheats, você deve selecionar uma pasta que contenha um diretório cheats/, romfs/ ou exefs. Não podemos verificar se eles são compatíveis com seu jogo, então tenha cuidado!</string>
341 <string name="invalid_directory">Diretório inválido </string>
342 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
343 <string name="invalid_directory_description">Por favor verifique se o diretório selecionado contém uma pasta cheats/, romfs ou exefs e tente novamente.</string>
344 <string name="addon_installed_successfully">Adicional instalado com sucesso</string>
345 <string name="verifying_content">Verificando conteúdo</string>
346 <string name="content_install_notice">Aviso sobre conteúdo adicional</string>
347 <string name="content_install_notice_description">O conteúdo que você selecionou não corresponde a este jogo.\nInstalar mesmo assim?</string>
253 <!-- ROM loading errors --> 348 <!-- ROM loading errors -->
254 <string name="loader_error_encrypted">A tua ROM está encriptada</string> 349 <string name="loader_error_encrypted">A tua ROM está encriptada</string>
255 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para despejar novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">títulos instalados</a>.]]></string> 350 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor, siga os guias para despejar novamente o seu <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">cartucho de jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">títulos instalados</a>.]]></string>
@@ -277,6 +372,7 @@
277 <string name="emulation_pause">Pausar emulação</string> 372 <string name="emulation_pause">Pausar emulação</string>
278 <string name="emulation_unpause">Despausar emulação</string> 373 <string name="emulation_unpause">Despausar emulação</string>
279 <string name="emulation_input_overlay">Opções de overlay</string> 374 <string name="emulation_input_overlay">Opções de overlay</string>
375 <string name="touchscreen">Ecrã Táctil</string>
280 376
281 <string name="load_settings">Carregando configurações...</string> 377 <string name="load_settings">Carregando configurações...</string>
282 378
@@ -308,6 +404,7 @@
308 404
309 <!-- Memory Sizes --> 405 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string> 406 <string name="memory_byte">Byte</string>
407 <string name="memory_byte_shorthand">B</string>
311 <string name="memory_kilobyte">KB</string> 408 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string> 409 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string> 410 <string name="memory_gigabyte">GB</string>
@@ -352,9 +449,13 @@
352 <string name="anti_aliasing_smaa">SMAA</string> 449 <string name="anti_aliasing_smaa">SMAA</string>
353 450
354 <!-- Screen Layouts --> 451 <!-- Screen Layouts -->
452 <string name="screen_layout_auto">Automático</string>
453 <string name="screen_layout_sensor_landscape">Paisagem pelo sensor</string>
355 <string name="screen_layout_landscape">Landscape</string> 454 <string name="screen_layout_landscape">Landscape</string>
455 <string name="screen_layout_reverse_landscape">Paisagem invertida</string>
456 <string name="screen_layout_sensor_portrait">Retrato pelo sensor</string>
356 <string name="screen_layout_portrait">Portrait</string> 457 <string name="screen_layout_portrait">Portrait</string>
357 <string name="screen_layout_auto">Automático</string> 458 <string name="screen_layout_reverse_portrait">Retrato invertido</string>
358 459
359 <!-- Aspect Ratios --> 460 <!-- Aspect Ratios -->
360 <string name="ratio_default">Padrão (16:9)</string> 461 <string name="ratio_default">Padrão (16:9)</string>
@@ -363,6 +464,10 @@
363 <string name="ratio_force_sixteen_ten">Forçar 16:10</string> 464 <string name="ratio_force_sixteen_ten">Forçar 16:10</string>
364 <string name="ratio_stretch">Esticar à janela</string> 465 <string name="ratio_stretch">Esticar à janela</string>
365 466
467 <!-- CPU Backend -->
468 <string name="cpu_backend_dynarmic">Dynarmic (Lento)</string>
469 <string name="cpu_backend_nce">Native code execution (NCE)</string>
470
366 <!-- CPU Accuracy --> 471 <!-- CPU Accuracy -->
367 <string name="cpu_accuracy_accurate">Preciso</string> 472 <string name="cpu_accuracy_accurate">Preciso</string>
368 <string name="cpu_accuracy_unsafe">Inseguro</string> 473 <string name="cpu_accuracy_unsafe">Inseguro</string>
@@ -391,8 +496,15 @@
391 <string name="theme_mode_dark">Escuro</string> 496 <string name="theme_mode_dark">Escuro</string>
392 497
393 <!-- Audio output engines --> 498 <!-- Audio output engines -->
499 <string name="oboe">oboe</string>
394 <string name="cubeb">cubeb</string> 500 <string name="cubeb">cubeb</string>
395 501
502 <!-- Anisotropic filtering options -->
503 <string name="multiplier_two">2x</string>
504 <string name="multiplier_four">4x</string>
505 <string name="multiplier_eight">8x</string>
506 <string name="multiplier_sixteen">16x</string>
507
396 <!-- Black backgrounds theme --> 508 <!-- Black backgrounds theme -->
397 <string name="use_black_backgrounds">Plano de fundo preto</string> 509 <string name="use_black_backgrounds">Plano de fundo preto</string>
398 <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string> 510 <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string>
diff --git a/src/android/app/src/main/res/values-ru/strings.xml b/src/android/app/src/main/res/values-ru/strings.xml
index c614257a8..099b2c9eb 100644
--- a/src/android/app/src/main/res/values-ru/strings.xml
+++ b/src/android/app/src/main/res/values-ru/strings.xml
@@ -34,6 +34,7 @@
34 <string name="empty_gamelist">Ðе найдены файлы или еще не выбрана папка Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸.</string> 34 <string name="empty_gamelist">Ðе найдены файлы или еще не выбрана папка Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸.</string>
35 <string name="search_and_filter_games">ПоиÑк и Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¸Ð³Ñ€</string> 35 <string name="search_and_filter_games">ПоиÑк и Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð¸Ð³Ñ€</string>
36 <string name="select_games_folder">Выберите папку Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string> 36 <string name="select_games_folder">Выберите папку Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string>
37 <string name="manage_game_folders">Управление папками</string>
37 <string name="select_games_folder_description">ПозволÑет yuzu заполнить ÑпиÑок игр</string> 38 <string name="select_games_folder_description">ПозволÑет yuzu заполнить ÑпиÑок игр</string>
38 <string name="add_games_warning">ПропуÑтить выбор папки Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸?</string> 39 <string name="add_games_warning">ПропуÑтить выбор папки Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸?</string>
39 <string name="add_games_warning_description">Игры не будут отображатьÑÑ Ð² ÑпиÑке Игры, еÑли папка не выбрана.</string> 40 <string name="add_games_warning_description">Игры не будут отображатьÑÑ Ð² ÑпиÑке Игры, еÑли папка не выбрана.</string>
@@ -68,6 +69,7 @@
68 <string name="invalid_keys_error">Ðеверные ключи шифрованиÑ</string> 69 <string name="invalid_keys_error">Ðеверные ключи шифрованиÑ</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">Выбранный файл неверен или поврежден. ПожалуйÑта, пере-дампите ваши ключи.</string> 71 <string name="install_keys_failure_description">Выбранный файл неверен или поврежден. ПожалуйÑта, пере-дампите ваши ключи.</string>
72 <string name="gpu_driver_manager">Менеджер драйверов ГП</string>
71 <string name="install_gpu_driver">УÑтановить драйвер ГП</string> 73 <string name="install_gpu_driver">УÑтановить драйвер ГП</string>
72 <string name="install_gpu_driver_description">УÑтановите альтернативные драйверы Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾ лучшей производительноÑти и/или точноÑти</string> 74 <string name="install_gpu_driver_description">УÑтановите альтернативные драйверы Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾ лучшей производительноÑти и/или точноÑти</string>
73 <string name="advanced_settings">РаÑширенные наÑтройки</string> 75 <string name="advanced_settings">РаÑширенные наÑтройки</string>
@@ -85,7 +87,11 @@
85 <string name="notification_no_directory_link_description">ПожалуйÑта, найдите папку Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ боковой панели файлового менеджера вручную.</string> 87 <string name="notification_no_directory_link_description">ПожалуйÑта, найдите папку Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ боковой панели файлового менеджера вручную.</string>
86 <string name="manage_save_data">Управление данными Ñохранений</string> 88 <string name="manage_save_data">Управление данными Ñохранений</string>
87 <string name="manage_save_data_description">Ðайдено данные Ñохранений. ПожалуйÑта, выберите вариант ниже.</string> 89 <string name="manage_save_data_description">Ðайдено данные Ñохранений. ПожалуйÑта, выберите вариант ниже.</string>
90 <string name="import_save_warning">Импортировать ÑохранениÑ</string>
91 <string name="import_save_warning_description">Это перезапишет вÑе ÑущеÑтвующие данные ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ð¼ файлом. Ð’Ñ‹ уверены, что хотите продолжить?</string>
88 <string name="import_export_saves_description">Импорт или ÑкÑпорт файлов ÑохранениÑ</string> 92 <string name="import_export_saves_description">Импорт или ÑкÑпорт файлов ÑохранениÑ</string>
93 <string name="save_files_importing">Импорт файлов ÑохранениÑ…</string>
94 <string name="save_files_exporting">ЭкÑпорт файлов ÑохранениÑ…</string>
89 <string name="save_file_imported_success">УÑпешно импортировано</string> 95 <string name="save_file_imported_success">УÑпешно импортировано</string>
90 <string name="save_file_invalid_zip_structure">ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñтруктура папки ÑохранениÑ</string> 96 <string name="save_file_invalid_zip_structure">ÐедопуÑÑ‚Ð¸Ð¼Ð°Ñ Ñтруктура папки ÑохранениÑ</string>
91 <string name="save_file_invalid_zip_structure_description">Ðазвание первой вложенной папки должно быть идентификатором игры.</string> 97 <string name="save_file_invalid_zip_structure_description">Ðазвание первой вложенной папки должно быть идентификатором игры.</string>
@@ -119,6 +125,42 @@
119 <string name="manage_yuzu_data_description">Импортируйте/ÑкÑпортируйте прошивку, ключи, пользовательÑкие данные и многое другое!</string> 125 <string name="manage_yuzu_data_description">Импортируйте/ÑкÑпортируйте прошивку, ключи, пользовательÑкие данные и многое другое!</string>
120 <string name="share_save_file">ПоделитьÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ ÑохранениÑ</string> 126 <string name="share_save_file">ПоделитьÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ ÑохранениÑ</string>
121 <string name="export_save_failed">Ðе удалоÑÑŒ ÑкÑпортировать Ñохранение</string> 127 <string name="export_save_failed">Ðе удалоÑÑŒ ÑкÑпортировать Ñохранение</string>
128 <string name="game_folders">Папки Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string>
129 <string name="deep_scan">Глубокий анализ</string>
130 <string name="add_game_folder">Добавить папку Ñ Ð¸Ð³Ñ€Ð¾Ð¹</string>
131 <string name="folder_already_added">Эта папка уже была добавлена!</string>
132 <string name="game_folder_properties">СвойÑтва папки игры</string>
133 <plurals name="saves_import_failed">
134 <item quantity="one">Ðе удалоÑÑŒ импортировать %d Ñохранение</item>
135 <item quantity="few">Ðе удалоÑÑŒ импортировать %d ÑохранениÑ</item>
136 <item quantity="many">Ðе удалоÑÑŒ импортировать %d Ñохранений</item>
137 <item quantity="other">Ðе удалоÑÑŒ импортировать %d Ñохранений</item>
138 </plurals>
139 <plurals name="saves_import_success">
140 <item quantity="one">Импортировано %d Ñохранение</item>
141 <item quantity="few">Импортировано %d ÑохранениÑ</item>
142 <item quantity="many">Импортировано %d Ñохранений</item>
143 <item quantity="other">Импортировано %d Ñохранений</item>
144 </plurals>
145 <string name="no_save_data_found">Ðе найдены ÑохраненмиÑ</string>
146
147 <!-- Applet launcher strings -->
148 <string name="applets">ЗапуÑк апплета</string>
149 <string name="applets_description">ЗапуÑк ÑиÑтемных апплетов на уÑтановленной прошивке</string>
150 <string name="applets_error_firmware">Прошивка не уÑтановлена</string>
151 <string name="applets_error_applet">Ðпплет недоÑтупен</string>
152 <string name="applets_error_description"><![CDATA[ПожалуйÑта, убедитеÑÑŒ, что ваш<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> и <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">firmware</a> уÑтановлены и попробуйте еще раз.]]></string>
153 <string name="album_applet">Ðльбом</string>
154 <string name="album_applet_description">ПроÑмотрите изображениÑ, Ñохраненные в папке Ñкриншотов пользователÑ, Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемного проÑмотрщика фотографий.</string>
155 <string name="mii_edit_applet">Mii редактор</string>
156 <string name="mii_edit_applet_description">ПроÑмотр и редактирование Mii Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ ÑиÑтемного редактора</string>
157 <string name="cabinet_applet">Шкаф</string>
158 <string name="cabinet_applet_description">Редактирование и удаление данных, хранÑщихÑÑ Ð½Ð° amiibo</string>
159 <string name="cabinet_launcher">ЗапуÑк шкафа</string>
160 <string name="cabinet_nickname_and_owner">Ðикнейм и наÑтройки владельца</string>
161 <string name="cabinet_game_data_eraser">Удаление игровых данных</string>
162 <string name="cabinet_restorer">ВоÑÑтановитель</string>
163 <string name="cabinet_formatter">Форматтер</string>
122 164
123 <!-- About screen strings --> 165 <!-- About screen strings -->
124 <string name="gaia_is_not_real">Gaia не ÑущеÑтвует</string> 166 <string name="gaia_is_not_real">Gaia не ÑущеÑтвует</string>
@@ -162,6 +204,7 @@
162 <string name="frame_limit_enable_description">Ограничивает ÑкороÑть ÑмулÑции указанным процентом от нормальной ÑкороÑти.</string> 204 <string name="frame_limit_enable_description">Ограничивает ÑкороÑть ÑмулÑции указанным процентом от нормальной ÑкороÑти.</string>
163 <string name="frame_limit_slider">Ограничение процента cкороÑти</string> 205 <string name="frame_limit_slider">Ограничение процента cкороÑти</string>
164 <string name="frame_limit_slider_description">Указывает процент Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ ÑкороÑти ÑмулÑции. 100% - Ñто Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÑкороÑть. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ или меньше увеличивают или уменьшают ограничение ÑкороÑти.</string> 206 <string name="frame_limit_slider_description">Указывает процент Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ ÑкороÑти ÑмулÑции. 100% - Ñто Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÑкороÑть. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ или меньше увеличивают или уменьшают ограничение ÑкороÑти.</string>
207 <string name="cpu_backend">БÑкÑнд ЦП</string>
165 <string name="cpu_accuracy">ТочноÑть ЦП</string> 208 <string name="cpu_accuracy">ТочноÑть ЦП</string>
166 <string name="value_with_units">%1$s%2$s</string> 209 <string name="value_with_units">%1$s%2$s</string>
167 210
@@ -192,6 +235,8 @@
192 <string name="renderer_reactive_flushing_description">Повышение точноÑти рендеринга в некоторых играх за Ñчет ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти.</string> 235 <string name="renderer_reactive_flushing_description">Повышение точноÑти рендеринга в некоторых играх за Ñчет ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти.</string>
193 <string name="use_disk_shader_cache">КÑш шейдеров на диÑке</string> 236 <string name="use_disk_shader_cache">КÑш шейдеров на диÑке</string>
194 <string name="use_disk_shader_cache_description">Уменьшение завиÑаний за Ñчет Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸ загрузки Ñгенерированных шейдеров.</string> 237 <string name="use_disk_shader_cache_description">Уменьшение завиÑаний за Ñчет Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸ загрузки Ñгенерированных шейдеров.</string>
238 <string name="anisotropic_filtering">ÐÐ½Ð¸Ð·Ð¾Ñ‚Ñ€Ð¾Ð¿Ð½Ð°Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð°Ñ†Ð¸Ñ</string>
239 <string name="anisotropic_filtering_description">Улучшает качеÑтво текÑтур под углом</string>
195 240
196 <!-- Debug settings strings --> 241 <!-- Debug settings strings -->
197 <string name="cpu">ЦП</string> 242 <string name="cpu">ЦП</string>
@@ -203,6 +248,8 @@
203 <string name="renderer_debug_description">Переводит графичеÑкий API в режим медленной отладки.</string> 248 <string name="renderer_debug_description">Переводит графичеÑкий API в режим медленной отладки.</string>
204 <string name="fastmem">Fastmem</string> 249 <string name="fastmem">Fastmem</string>
205 250
251 <!-- Audio settings strings -->
252 <string name="audio_output_engine">Движок вывода</string>
206 <string name="audio_volume">ГромкоÑть</string> 253 <string name="audio_volume">ГромкоÑть</string>
207 <string name="audio_volume_description">Задает громкоÑть аудиовыхода.</string> 254 <string name="audio_volume_description">Задает громкоÑть аудиовыхода.</string>
208 255
@@ -216,6 +263,7 @@
216 <string name="shutting_down">Выключение…</string> 263 <string name="shutting_down">Выключение…</string>
217 <string name="reset_setting_confirmation">Хотите ли вы вернуть Ñтот параметр к значению по умолчанию?</string> 264 <string name="reset_setting_confirmation">Хотите ли вы вернуть Ñтот параметр к значению по умолчанию?</string>
218 <string name="reset_to_default">Ð¡Ð±Ñ€Ð¾Ñ Ðº наÑтройкам по умолчанию</string> 265 <string name="reset_to_default">Ð¡Ð±Ñ€Ð¾Ñ Ðº наÑтройкам по умолчанию</string>
266 <string name="reset_to_default_description">СброÑить вÑе раÑширенные наÑтройки</string>
219 <string name="reset_all_settings">СброÑить вÑе наÑтройки?</string> 267 <string name="reset_all_settings">СброÑить вÑе наÑтройки?</string>
220 <string name="reset_all_settings_description">Ð’Ñе дополнительные наÑтройки будут Ñброшены к наÑтройке по умолчанию. Это невозможно отменить.</string> 268 <string name="reset_all_settings_description">Ð’Ñе дополнительные наÑтройки будут Ñброшены к наÑтройке по умолчанию. Это невозможно отменить.</string>
221 <string name="settings_reset">ÐаÑтройки Ñброшены</string> 269 <string name="settings_reset">ÐаÑтройки Ñброшены</string>
@@ -229,14 +277,24 @@
229 <string name="export_failed">Ошибка ÑкÑпорта</string> 277 <string name="export_failed">Ошибка ÑкÑпорта</string>
230 <string name="import_failed">Ошибка импортированиÑ</string> 278 <string name="import_failed">Ошибка импортированиÑ</string>
231 <string name="cancelling">ОтменÑÑŽ</string> 279 <string name="cancelling">ОтменÑÑŽ</string>
232 280 <string name="install">УÑтановить</string>
281 <string name="delete">Удалить</string>
282 <string name="edit">Редактировать</string>
283 <string name="export_success">ЭкÑпорт уÑпешно выполнен</string>
284 <string name="start">Start</string>
285 <string name="clear">ОчиÑтить</string>
286 <string name="global">Глобальный</string>
287 <string name="custom">Другое</string>
288 <string name="notice">Уведомление</string>
289 <string name="import_complete">Импорт завершен</string>
233 <!-- GPU driver installation --> 290 <!-- GPU driver installation -->
234 <string name="select_gpu_driver">Выбрать драйвер ГП</string> 291 <string name="select_gpu_driver">Выбрать драйвер ГП</string>
235 <string name="select_gpu_driver_title">Хотите заменить текущий драйвер ГП?</string> 292 <string name="select_gpu_driver_title">Хотите заменить текущий драйвер ГП?</string>
236 <string name="select_gpu_driver_install">УÑтановить</string> 293 <string name="select_gpu_driver_install">УÑтановить</string>
237 <string name="select_gpu_driver_default">По умолчанию</string> 294 <string name="select_gpu_driver_default">По умолчанию</string>
238 <string name="select_gpu_driver_use_default">ИÑпользуетÑÑ Ñтандартный драйвер ГП </string> 295 <string name="select_gpu_driver_use_default">ИÑпользуетÑÑ Ñтандартный драйвер ГП </string>
239 <string name="select_gpu_driver_error">Выбран неверный драйвер, иÑпользуетÑÑ Ñтандартный ÑиÑтемный!</string> 296 <string name="select_gpu_driver_error">Выбран неподходÑщий драйвер</string>
297 <string name="driver_already_installed">Драйвер уже уÑтановлен</string>
240 <string name="system_gpu_driver">СиÑтемный драйвер ГП</string> 298 <string name="system_gpu_driver">СиÑтемный драйвер ГП</string>
241 <string name="installing_driver">УÑтановка драйвера...</string> 299 <string name="installing_driver">УÑтановка драйвера...</string>
242 300
@@ -244,11 +302,52 @@
244 <string name="preferences_settings">ÐаÑтройки</string> 302 <string name="preferences_settings">ÐаÑтройки</string>
245 <string name="preferences_general">Общие</string> 303 <string name="preferences_general">Общие</string>
246 <string name="preferences_system">СиÑтема</string> 304 <string name="preferences_system">СиÑтема</string>
305 <string name="preferences_system_description">Режим дока, регион, Ñзык</string>
247 <string name="preferences_graphics">Графика</string> 306 <string name="preferences_graphics">Графика</string>
307 <string name="preferences_graphics_description">Уровень точноÑти, разрешение, кÑш шейдеров</string>
248 <string name="preferences_audio">Ðудио</string> 308 <string name="preferences_audio">Ðудио</string>
309 <string name="preferences_audio_description">Движок вывода, громкоÑть</string>
249 <string name="preferences_theme">Тема и цвет</string> 310 <string name="preferences_theme">Тема и цвет</string>
250 <string name="preferences_debug">Отладка</string> 311 <string name="preferences_debug">Отладка</string>
251 312 <string name="preferences_debug_description">Отладка ЦП/ГП, графичеÑкий API, fastmem</string>
313
314 <!-- Game properties -->
315 <string name="info">ИнформациÑ</string>
316 <string name="info_description">ID программы, Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚Ñ‡Ð¸ÐºÐ¾Ð², верÑиÑ</string>
317 <string name="per_game_settings">ÐаÑтройки Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ игры</string>
318 <string name="per_game_settings_description">Изменить наÑтройки Ñтой игры</string>
319 <string name="launch_options">ÐšÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ Ð·Ð°Ð¿ÑƒÑка</string>
320 <string name="path">Путь</string>
321 <string name="program_id">ID программы</string>
322 <string name="developer">Разработчик</string>
323 <string name="version">ВерÑиÑ</string>
324 <string name="copy_details">Копировать детали</string>
325 <string name="add_ons">ДополнениÑ</string>
326 <string name="add_ons_description">Включение модов, обновлений и DLC</string>
327 <string name="clear_shader_cache">ОчиÑтить кÑш шейдеров</string>
328 <string name="clear_shader_cache_description">УдалÑет вÑе шейдеры, Ñозданные во Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð³Ñ€Ñ‹.</string>
329 <string name="clear_shader_cache_warning_description">У Ð²Ð°Ñ Ð±ÑƒÐ´ÐµÑ‚ больше лагов во Ð²Ñ€ÐµÐ¼Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð¹ генерации кÑша шейдеров</string>
330 <string name="cleared_shaders_successfully">УÑпешно очищены шейдеры</string>
331 <string name="addons_game">Ðддоны: %1$s</string>
332 <string name="save_data">Сохранить данные</string>
333 <string name="save_data_description">УправлÑть ÑохранениÑми Ñтой игры.</string>
334 <string name="delete_save_data">Удалить ÑохранениÑ</string>
335 <string name="delete_save_data_description">Удалить вÑе ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñтой игры</string>
336 <string name="delete_save_data_warning_description">Это безвозвратно удалÑет вÑе Ñохраненные данные Ñтой игры. Ð’Ñ‹ уверены, что хотите продолжить?</string>
337 <string name="save_data_deleted_successfully">Данные уÑпешно удалены</string>
338 <string name="select_content_type">Тип контента</string>
339 <string name="updates_and_dlc">ÐžÐ±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸ DLC</string>
340 <string name="mods_and_cheats">Моды и читы</string>
341 <string name="addon_notice">Важное уведомление о дополнении</string>
342 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
343 <string name="addon_notice_description">Ð”Ð»Ñ ÑƒÑтановки модов и читов необходимо выбрать папку, Ñодержащую каталог cheats/, romfs/ или exefs/. Мы не можем гарантировать их ÑовмеÑтимоÑть Ñ Ð²Ð°ÑˆÐµÐ¹ игрой, поÑтому будьте оÑторожны!</string>
344 <string name="invalid_directory">Ðеверный каталог</string>
345 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
346 <string name="invalid_directory_description">ПожалуйÑта, убедитеÑÑŒ, что Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð°Ñ Ð²Ð°Ð¼Ð¸ Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ñодержит папку cheats/, romfs/ или exefs/ и попробуйте Ñнова.</string>
347 <string name="addon_installed_successfully">Ðддон уÑпешно уÑтановлен</string>
348 <string name="verifying_content">Проверка Ñодержимого...</string>
349 <string name="content_install_notice">Уведомление об уÑтановке контента</string>
350 <string name="content_install_notice_description">Содержимое, которое вы выбрали, не ÑоответÑтвует Ñтой игре.\nУÑтановить вÑе равно?</string>
252 <!-- ROM loading errors --> 351 <!-- ROM loading errors -->
253 <string name="loader_error_encrypted">Ваш ROM зашифрованный</string> 352 <string name="loader_error_encrypted">Ваш ROM зашифрованный</string>
254 <string name="loader_error_encrypted_roms_description"><![CDATA[Следуйте инÑтрукциÑм, чтобы пере-дампить игровые картриджи <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\"> или <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\"> уÑтановленные игры</a>.]]></string> 353 <string name="loader_error_encrypted_roms_description"><![CDATA[Следуйте инÑтрукциÑм, чтобы пере-дампить игровые картриджи <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\"> или <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\"> уÑтановленные игры</a>.]]></string>
@@ -276,6 +375,7 @@
276 <string name="emulation_pause">Пауза ÑмулÑции</string> 375 <string name="emulation_pause">Пауза ÑмулÑции</string>
277 <string name="emulation_unpause">Возобновить ÑмулÑцию</string> 376 <string name="emulation_unpause">Возобновить ÑмулÑцию</string>
278 <string name="emulation_input_overlay">ÐаÑтройка оверлеÑ</string> 377 <string name="emulation_input_overlay">ÐаÑтройка оверлеÑ</string>
378 <string name="touchscreen">СенÑорный Ñкран</string>
279 379
280 <string name="load_settings">Загрузка наÑтроек...</string> 380 <string name="load_settings">Загрузка наÑтроек...</string>
281 381
@@ -307,6 +407,7 @@
307 407
308 <!-- Memory Sizes --> 408 <!-- Memory Sizes -->
309 <string name="memory_byte">Байт</string> 409 <string name="memory_byte">Байт</string>
410 <string name="memory_byte_shorthand">B</string>
310 <string name="memory_kilobyte">КБ</string> 411 <string name="memory_kilobyte">КБ</string>
311 <string name="memory_megabyte">МБ</string> 412 <string name="memory_megabyte">МБ</string>
312 <string name="memory_gigabyte">GB</string> 413 <string name="memory_gigabyte">GB</string>
@@ -351,9 +452,13 @@
351 <string name="anti_aliasing_smaa">SMAA</string> 452 <string name="anti_aliasing_smaa">SMAA</string>
352 453
353 <!-- Screen Layouts --> 454 <!-- Screen Layouts -->
455 <string name="screen_layout_auto">Ðвто</string>
456 <string name="screen_layout_sensor_landscape">ÐÐ»ÑŒÐ±Ð¾Ð¼Ð½Ð°Ñ (ÑенÑор)</string>
354 <string name="screen_layout_landscape">Пейзаж</string> 457 <string name="screen_layout_landscape">Пейзаж</string>
458 <string name="screen_layout_reverse_landscape">ÐžÐ±Ñ€Ð°Ñ‚Ð½Ð°Ñ Ð°Ð»ÑŒÐ±Ð¾Ð¼Ð½Ð°Ñ</string>
459 <string name="screen_layout_sensor_portrait">ÐŸÐ¾Ñ€Ñ‚Ñ€ÐµÑ‚Ð½Ð°Ñ (ÑенÑор)</string>
355 <string name="screen_layout_portrait">Портрет</string> 460 <string name="screen_layout_portrait">Портрет</string>
356 <string name="screen_layout_auto">Ðвто</string> 461 <string name="screen_layout_reverse_portrait">ÐžÐ±Ñ€Ð°Ñ‚Ð½Ð°Ñ Ð¿Ð¾Ñ€Ñ‚Ñ€ÐµÑ‚Ð½Ð°Ñ</string>
357 462
358 <!-- Aspect Ratios --> 463 <!-- Aspect Ratios -->
359 <string name="ratio_default">Стандартное (16:9)</string> 464 <string name="ratio_default">Стандартное (16:9)</string>
@@ -362,6 +467,10 @@
362 <string name="ratio_force_sixteen_ten">ЗаÑтавить 16:10</string> 467 <string name="ratio_force_sixteen_ten">ЗаÑтавить 16:10</string>
363 <string name="ratio_stretch">РаÑÑ‚Ñнуть до окна</string> 468 <string name="ratio_stretch">РаÑÑ‚Ñнуть до окна</string>
364 469
470 <!-- CPU Backend -->
471 <string name="cpu_backend_dynarmic">Dynarmic (Медленно)</string>
472 <string name="cpu_backend_nce">Ðативное выполнение (NCE)</string>
473
365 <!-- CPU Accuracy --> 474 <!-- CPU Accuracy -->
366 <string name="cpu_accuracy_accurate">Точно</string> 475 <string name="cpu_accuracy_accurate">Точно</string>
367 <string name="cpu_accuracy_unsafe">ÐебезопаÑно</string> 476 <string name="cpu_accuracy_unsafe">ÐебезопаÑно</string>
@@ -390,8 +499,15 @@
390 <string name="theme_mode_dark">ТемнаÑ</string> 499 <string name="theme_mode_dark">ТемнаÑ</string>
391 500
392 <!-- Audio output engines --> 501 <!-- Audio output engines -->
502 <string name="oboe">oboe</string>
393 <string name="cubeb">cubeb</string> 503 <string name="cubeb">cubeb</string>
394 504
505 <!-- Anisotropic filtering options -->
506 <string name="multiplier_two">2x</string>
507 <string name="multiplier_four">4x</string>
508 <string name="multiplier_eight">8x</string>
509 <string name="multiplier_sixteen">16x</string>
510
395 <!-- Black backgrounds theme --> 511 <!-- Black backgrounds theme -->
396 <string name="use_black_backgrounds">Чёрный фон</string> 512 <string name="use_black_backgrounds">Чёрный фон</string>
397 <string name="use_black_backgrounds_description">При иÑпользовании темной темы применÑйте черный фон.</string> 513 <string name="use_black_backgrounds_description">При иÑпользовании темной темы применÑйте черный фон.</string>
diff --git a/src/android/app/src/main/res/values-uk/strings.xml b/src/android/app/src/main/res/values-uk/strings.xml
index 34809dbb8..361f0b726 100644
--- a/src/android/app/src/main/res/values-uk/strings.xml
+++ b/src/android/app/src/main/res/values-uk/strings.xml
@@ -143,13 +143,16 @@
143 <string name="string_null">Null</string> 143 <string name="string_null">Null</string>
144 <string name="string_import">Імпорт</string> 144 <string name="string_import">Імпорт</string>
145 <string name="export">ЕкÑпорт</string> 145 <string name="export">ЕкÑпорт</string>
146 <string name="install">Ð’Ñтановити</string>
147 <string name="delete">Видалити</string>
148 <string name="start">Start</string>
149 <string name="clear">ОчиÑтити</string>
146 <!-- GPU driver installation --> 150 <!-- GPU driver installation -->
147 <string name="select_gpu_driver">Вибрати драйвер ГП</string> 151 <string name="select_gpu_driver">Вибрати драйвер ГП</string>
148 <string name="select_gpu_driver_title">Хочете замінити поточний драйвер ГП?</string> 152 <string name="select_gpu_driver_title">Хочете замінити поточний драйвер ГП?</string>
149 <string name="select_gpu_driver_install">Ð’Ñтановити</string> 153 <string name="select_gpu_driver_install">Ð’Ñтановити</string>
150 <string name="select_gpu_driver_default">За замовчуваннÑм</string> 154 <string name="select_gpu_driver_default">За замовчуваннÑм</string>
151 <string name="select_gpu_driver_use_default">ВикориÑтовуєтьÑÑ Ñтандартний драйвер ГП</string> 155 <string name="select_gpu_driver_use_default">ВикориÑтовуєтьÑÑ Ñтандартний драйвер ГП</string>
152 <string name="select_gpu_driver_error">Обрано неправильний драйвер, викориÑтовуєтьÑÑ Ñтандартний ÑиÑтемний!</string>
153 <string name="system_gpu_driver">СиÑтемний драйвер ГП</string> 156 <string name="system_gpu_driver">СиÑтемний драйвер ГП</string>
154 <string name="installing_driver">Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð°...</string> 157 <string name="installing_driver">Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð°...</string>
155 158
@@ -161,7 +164,12 @@
161 <string name="preferences_audio">Ðудіо</string> 164 <string name="preferences_audio">Ðудіо</string>
162 <string name="preferences_theme">Тема і колір</string> 165 <string name="preferences_theme">Тема і колір</string>
163 <string name="preferences_debug">ÐалагодженнÑ</string> 166 <string name="preferences_debug">ÐалагодженнÑ</string>
164 167 <!-- Game properties -->
168 <string name="info">ІнформаціÑ</string>
169 <string name="path">ШлÑÑ…</string>
170 <string name="developer">Розробник</string>
171 <string name="version">ВерÑÑ–Ñ</string>
172 <string name="add_ons">ДоповненнÑ</string>
165 <!-- ROM loading errors --> 173 <!-- ROM loading errors -->
166 <string name="loader_error_encrypted">Ваш ROM зашифрований</string> 174 <string name="loader_error_encrypted">Ваш ROM зашифрований</string>
167 <string name="loader_error_encrypted_keys_description"><![CDATA[Будь лаÑка, переконайтеÑÑ, що ваш файл <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> вÑтановлено, щоб ігри можна було розшифрувати.]]></string> 175 <string name="loader_error_encrypted_keys_description"><![CDATA[Будь лаÑка, переконайтеÑÑ, що ваш файл <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> вÑтановлено, щоб ігри можна було розшифрувати.]]></string>
@@ -173,6 +181,8 @@
173 <string name="emulation_done">Готово</string> 181 <string name="emulation_done">Готово</string>
174 <string name="emulation_control_scale">МаÑштаб</string> 182 <string name="emulation_control_scale">МаÑштаб</string>
175 <string name="emulation_control_opacity">ÐепрозоріÑть</string> 183 <string name="emulation_control_opacity">ÐепрозоріÑть</string>
184 <string name="touchscreen">СенÑорний екран</string>
185
176 <!-- Errors and warnings --> 186 <!-- Errors and warnings -->
177 <string name="abort_button">Перервати</string> 187 <string name="abort_button">Перервати</string>
178 <string name="continue_button">Продовжити</string> 188 <string name="continue_button">Продовжити</string>
@@ -192,6 +202,7 @@
192 <string name="region_korea">КореÑ</string> 202 <string name="region_korea">КореÑ</string>
193 <string name="region_taiwan">Тайвань</string> 203 <string name="region_taiwan">Тайвань</string>
194 204
205 <string name="memory_byte_shorthand">B</string>
195 <string name="memory_gigabyte">GB</string> 206 <string name="memory_gigabyte">GB</string>
196 <!-- Renderer APIs --> 207 <!-- Renderer APIs -->
197 <string name="renderer_vulkan">Vulkan</string> 208 <string name="renderer_vulkan">Vulkan</string>
@@ -229,8 +240,8 @@
229 <string name="anti_aliasing_fxaa">FXAA</string> 240 <string name="anti_aliasing_fxaa">FXAA</string>
230 <string name="anti_aliasing_smaa">SMAA</string> 241 <string name="anti_aliasing_smaa">SMAA</string>
231 242
243 <!-- Screen Layouts -->
232 <string name="screen_layout_auto">Ðвто</string> 244 <string name="screen_layout_auto">Ðвто</string>
233
234 <!-- Aspect Ratios --> 245 <!-- Aspect Ratios -->
235 <string name="ratio_default">За замовчуваннÑм (16:9)</string> 246 <string name="ratio_default">За замовчуваннÑм (16:9)</string>
236 <string name="ratio_force_four_three">ЗмуÑити 4:3</string> 247 <string name="ratio_force_four_three">ЗмуÑити 4:3</string>
@@ -255,6 +266,12 @@
255 <string name="theme_mode_light">Світла</string> 266 <string name="theme_mode_light">Світла</string>
256 <string name="theme_mode_dark">Темна</string> 267 <string name="theme_mode_dark">Темна</string>
257 268
269 <!-- Anisotropic filtering options -->
270 <string name="multiplier_two">2x</string>
271 <string name="multiplier_four">4x</string>
272 <string name="multiplier_eight">8x</string>
273 <string name="multiplier_sixteen">16x</string>
274
258 <string name="use_black_backgrounds_description">У разі викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— теми заÑтоÑовуйте чорне тло.</string> 275 <string name="use_black_backgrounds_description">У разі викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— теми заÑтоÑовуйте чорне тло.</string>
259 276
260 <string name="mute">Вимкнути звук</string> 277 <string name="mute">Вимкнути звук</string>
diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml
index f977db3a2..0a722f329 100644
--- a/src/android/app/src/main/res/values-vi/strings.xml
+++ b/src/android/app/src/main/res/values-vi/strings.xml
@@ -157,7 +157,6 @@
157 <string name="renderer_reactive_flushing_description">Cải thiện độ chính xác kết xuất trong má»™t số game nhưng đồng thá»i giảm hiệu suất.</string> 157 <string name="renderer_reactive_flushing_description">Cải thiện độ chính xác kết xuất trong má»™t số game nhưng đồng thá»i giảm hiệu suất.</string>
158 <string name="use_disk_shader_cache">Lưu bộ nhớ đệm shader trên ổ cứng</string> 158 <string name="use_disk_shader_cache">Lưu bộ nhớ đệm shader trên ổ cứng</string>
159 <string name="use_disk_shader_cache_description">Giảm tình trạng giật lag bằng cách lưu trữ và tải các shader được tạo ra nội bộ.</string> 159 <string name="use_disk_shader_cache_description">Giảm tình trạng giật lag bằng cách lưu trữ và tải các shader được tạo ra nội bộ.</string>
160
161 <!-- Debug settings strings --> 160 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string> 161 <string name="cpu">CPU</string>
163 <string name="renderer_api">API</string> 162 <string name="renderer_api">API</string>
@@ -184,13 +183,17 @@
184 <string name="string_null">Null</string> 183 <string name="string_null">Null</string>
185 <string name="string_import">Nhập</string> 184 <string name="string_import">Nhập</string>
186 <string name="export">Xuất</string> 185 <string name="export">Xuất</string>
186 <string name="install">Cài đặt</string>
187 <string name="delete">Xoá</string>
188 <string name="start">Bắt đầu</string>
189 <string name="clear">Xóa</string>
190 <string name="custom">Tùy chỉnh</string>
187 <!-- GPU driver installation --> 191 <!-- GPU driver installation -->
188 <string name="select_gpu_driver">Chá»n driver GPU</string> 192 <string name="select_gpu_driver">Chá»n driver GPU</string>
189 <string name="select_gpu_driver_title">Bạn có muốn thay thế driver GPU hiện tại không?</string> 193 <string name="select_gpu_driver_title">Bạn có muốn thay thế driver GPU hiện tại không?</string>
190 <string name="select_gpu_driver_install">Cài đặt</string> 194 <string name="select_gpu_driver_install">Cài đặt</string>
191 <string name="select_gpu_driver_default">Mặc định</string> 195 <string name="select_gpu_driver_default">Mặc định</string>
192 <string name="select_gpu_driver_use_default">Dùng driver GPU mặc định</string> 196 <string name="select_gpu_driver_use_default">Dùng driver GPU mặc định</string>
193 <string name="select_gpu_driver_error">Driver không hợp lệ đã được chá»n, dùng mặc định hệ thống!</string>
194 <string name="system_gpu_driver">Driver GPU hệ thống</string> 197 <string name="system_gpu_driver">Driver GPU hệ thống</string>
195 <string name="installing_driver">Äang cài đặt driver...</string> 198 <string name="installing_driver">Äang cài đặt driver...</string>
196 199
@@ -202,7 +205,12 @@
202 <string name="preferences_audio">Âm thanh</string> 205 <string name="preferences_audio">Âm thanh</string>
203 <string name="preferences_theme">Chủ đỠvà màu sắc</string> 206 <string name="preferences_theme">Chủ đỠvà màu sắc</string>
204 <string name="preferences_debug">Gỡ lỗi</string> 207 <string name="preferences_debug">Gỡ lỗi</string>
205 208 <!-- Game properties -->
209 <string name="info">Thông tin</string>
210 <string name="path">ÄÆ°á»ng dẫn</string>
211 <string name="developer">Nhà phát triển</string>
212 <string name="version">Phiên bản</string>
213 <string name="add_ons">Add-ons</string>
206 <!-- ROM loading errors --> 214 <!-- ROM loading errors -->
207 <string name="loader_error_encrypted">ROM của bạn đã bị mã hoá</string> 215 <string name="loader_error_encrypted">ROM của bạn đã bị mã hoá</string>
208 <string name="loader_error_encrypted_keys_description"><![CDATA[Vui lòng đảm bảo tệp <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> đã được cài đặt để các game có thể được giải mã.]]></string> 216 <string name="loader_error_encrypted_keys_description"><![CDATA[Vui lòng đảm bảo tệp <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> đã được cài đặt để các game có thể được giải mã.]]></string>
@@ -229,6 +237,7 @@
229 <string name="emulation_pause">Tạm đừng giả lập</string> 237 <string name="emulation_pause">Tạm đừng giả lập</string>
230 <string name="emulation_unpause">Tiếp tục giả lập</string> 238 <string name="emulation_unpause">Tiếp tục giả lập</string>
231 <string name="emulation_input_overlay">Tuỳ chá»n lá»›p phá»§</string> 239 <string name="emulation_input_overlay">Tuỳ chá»n lá»›p phá»§</string>
240 <string name="touchscreen">Màn hình cảm ứng</string>
232 241
233 <string name="load_settings">Äang tải cài đặt...</string> 242 <string name="load_settings">Äang tải cài đặt...</string>
234 243
@@ -254,6 +263,7 @@
254 <string name="region_korea">Hàn Quốc</string> 263 <string name="region_korea">Hàn Quốc</string>
255 <string name="region_taiwan">Äài Loan</string> 264 <string name="region_taiwan">Äài Loan</string>
256 265
266 <string name="memory_byte_shorthand">B</string>
257 <string name="memory_gigabyte">GB</string> 267 <string name="memory_gigabyte">GB</string>
258 <!-- Renderer APIs --> 268 <!-- Renderer APIs -->
259 <string name="renderer_vulkan">Vulkan</string> 269 <string name="renderer_vulkan">Vulkan</string>
@@ -291,8 +301,8 @@
291 <string name="anti_aliasing_fxaa">FXAA</string> 301 <string name="anti_aliasing_fxaa">FXAA</string>
292 <string name="anti_aliasing_smaa">SMAA</string> 302 <string name="anti_aliasing_smaa">SMAA</string>
293 303
304 <!-- Screen Layouts -->
294 <string name="screen_layout_auto">Tự động</string> 305 <string name="screen_layout_auto">Tự động</string>
295
296 <!-- Aspect Ratios --> 306 <!-- Aspect Ratios -->
297 <string name="ratio_default">Mặc định (16:9)</string> 307 <string name="ratio_default">Mặc định (16:9)</string>
298 <string name="ratio_force_four_three">Dùng 4:3</string> 308 <string name="ratio_force_four_three">Dùng 4:3</string>
@@ -327,6 +337,12 @@
327 <string name="theme_mode_light">Sáng</string> 337 <string name="theme_mode_light">Sáng</string>
328 <string name="theme_mode_dark">Tối</string> 338 <string name="theme_mode_dark">Tối</string>
329 339
340 <!-- Anisotropic filtering options -->
341 <string name="multiplier_two">2x</string>
342 <string name="multiplier_four">4x</string>
343 <string name="multiplier_eight">8x</string>
344 <string name="multiplier_sixteen">16x</string>
345
330 <!-- Black backgrounds theme --> 346 <!-- Black backgrounds theme -->
331 <string name="use_black_backgrounds">Ná»n Ä‘en</string> 347 <string name="use_black_backgrounds">Ná»n Ä‘en</string>
332 <string name="use_black_backgrounds_description">Khi sá»­ dụng chá»§ đỠtối, hãy áp dụng ná»n Ä‘en.</string> 348 <string name="use_black_backgrounds_description">Khi sá»­ dụng chá»§ đỠtối, hãy áp dụng ná»n Ä‘en.</string>
diff --git a/src/android/app/src/main/res/values-zh-rCN/strings.xml b/src/android/app/src/main/res/values-zh-rCN/strings.xml
index 13455564f..b840591a4 100644
--- a/src/android/app/src/main/res/values-zh-rCN/strings.xml
+++ b/src/android/app/src/main/res/values-zh-rCN/strings.xml
@@ -34,6 +34,7 @@
34 <string name="empty_gamelist">找ä¸åˆ°æ¸¸æˆï¼Œæˆ–è€…å°šæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ã€‚</string> 34 <string name="empty_gamelist">找ä¸åˆ°æ¸¸æˆï¼Œæˆ–è€…å°šæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ã€‚</string>
35 <string name="search_and_filter_games">æœç´¢æ¸¸æˆ</string> 35 <string name="search_and_filter_games">æœç´¢æ¸¸æˆ</string>
36 <string name="select_games_folder">é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹</string> 36 <string name="select_games_folder">é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹</string>
37 <string name="manage_game_folders">ç®¡ç†æ¸¸æˆæ–‡ä»¶å¤¹</string>
37 <string name="select_games_folder_description">å…许 yuzu 填充游æˆåˆ—表</string> 38 <string name="select_games_folder_description">å…许 yuzu 填充游æˆåˆ—表</string>
38 <string name="add_games_warning">è·³è¿‡é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Ÿ</string> 39 <string name="add_games_warning">è·³è¿‡é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Ÿ</string>
39 <string name="add_games_warning_description">å¦‚æžœæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Œæ¸¸æˆå°†ä¸ä¼šæ˜¾ç¤ºåœ¨æ¸¸æˆåˆ—表中。</string> 40 <string name="add_games_warning_description">å¦‚æžœæœªé€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹ï¼Œæ¸¸æˆå°†ä¸ä¼šæ˜¾ç¤ºåœ¨æ¸¸æˆåˆ—表中。</string>
@@ -68,6 +69,7 @@
68 <string name="invalid_keys_error">无效的加密密钥</string> 69 <string name="invalid_keys_error">无效的加密密钥</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">é€‰æ‹©çš„å¯†é’¥æ–‡ä»¶ä¸æ­£ç¡®æˆ–å·²æŸåã€‚è¯·é‡æ–°è½¬å‚¨å¯†é’¥æ–‡ä»¶ã€‚</string> 71 <string name="install_keys_failure_description">é€‰æ‹©çš„å¯†é’¥æ–‡ä»¶ä¸æ­£ç¡®æˆ–å·²æŸåã€‚è¯·é‡æ–°è½¬å‚¨å¯†é’¥æ–‡ä»¶ã€‚</string>
72 <string name="gpu_driver_manager">GPU 驱动管ç†å™¨</string>
71 <string name="install_gpu_driver">安装 GPU 驱动</string> 73 <string name="install_gpu_driver">安装 GPU 驱动</string>
72 <string name="install_gpu_driver_description">安装替代的驱动程åºä»¥èŽ·å¾—æ›´å¥½çš„æ€§èƒ½å’Œç²¾åº¦</string> 74 <string name="install_gpu_driver_description">安装替代的驱动程åºä»¥èŽ·å¾—æ›´å¥½çš„æ€§èƒ½å’Œç²¾åº¦</string>
73 <string name="advanced_settings">高级选项</string> 75 <string name="advanced_settings">高级选项</string>
@@ -85,8 +87,12 @@
85 <string name="notification_no_directory_link_description">请使用文件管ç†å™¨çš„ä¾§éƒ¨é¢æ¿æ‰‹åŠ¨å®šä½ç”¨æˆ·æ–‡ä»¶å¤¹ã€‚</string> 87 <string name="notification_no_directory_link_description">请使用文件管ç†å™¨çš„ä¾§éƒ¨é¢æ¿æ‰‹åŠ¨å®šä½ç”¨æˆ·æ–‡ä»¶å¤¹ã€‚</string>
86 <string name="manage_save_data">管ç†å­˜æ¡£æ•°æ®</string> 88 <string name="manage_save_data">管ç†å­˜æ¡£æ•°æ®</string>
87 <string name="manage_save_data_description">已找到存档数æ®ï¼Œè¯·é€‰æ‹©ä¸‹æ–¹çš„选项。</string> 89 <string name="manage_save_data_description">已找到存档数æ®ï¼Œè¯·é€‰æ‹©ä¸‹æ–¹çš„选项。</string>
90 <string name="import_save_warning">导入ä¿å­˜æ•°æ®</string>
91 <string name="import_save_warning_description">这将用您所æä¾›çš„ä¿å­˜æ•°æ®è¦†ç›–当剿‰€æœ‰çš„ä¿å­˜æ•°æ®ã€‚您确定è¦ç»§ç»­å—?</string>
88 <string name="import_export_saves_description">导入或导出存档</string> 92 <string name="import_export_saves_description">导入或导出存档</string>
89 <string name="save_file_imported_success">å·²æˆåŠŸå¯¼å…¥å­˜æ¡£</string> 93 <string name="save_files_importing">正在导入存档文件...</string>
94 <string name="save_files_exporting">正在导出存档文件...</string>
95 <string name="save_file_imported_success">导入æˆåŠŸ</string>
90 <string name="save_file_invalid_zip_structure">无效的存档目录</string> 96 <string name="save_file_invalid_zip_structure">无效的存档目录</string>
91 <string name="save_file_invalid_zip_structure_description">ç¬¬ä¸€ä¸ªå­æ–‡ä»¶å¤¹åç§°å¿…é¡»ä¸ºå½“å‰æ¸¸æˆçš„ ID。</string> 97 <string name="save_file_invalid_zip_structure_description">ç¬¬ä¸€ä¸ªå­æ–‡ä»¶å¤¹åç§°å¿…é¡»ä¸ºå½“å‰æ¸¸æˆçš„ ID。</string>
92 <string name="import_saves">导入</string> 98 <string name="import_saves">导入</string>
@@ -118,13 +124,43 @@
118 <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string> 124 <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string>
119 <string name="share_save_file">分享存档文件</string> 125 <string name="share_save_file">分享存档文件</string>
120 <string name="export_save_failed">导出存档文件失败</string> 126 <string name="export_save_failed">导出存档文件失败</string>
127 <string name="game_folders">æ¸¸æˆæ–‡ä»¶å¤¹</string>
128 <string name="deep_scan">深度扫æ</string>
129 <string name="add_game_folder">æ·»åŠ æ¸¸æˆæ–‡ä»¶å¤¹</string>
130 <string name="folder_already_added">这个文件夹先å‰å·²è¢«æ·»åŠ ï¼</string>
131 <string name="game_folder_properties">æ¸¸æˆæ–‡ä»¶å¤¹å±žæ€§</string>
132 <plurals name="saves_import_failed">
133 <item quantity="other">%d 个存档导入失败</item>
134 </plurals>
135 <plurals name="saves_import_success">
136 <item quantity="other">æˆåŠŸå¯¼å…¥ %d 个存档</item>
137 </plurals>
138 <string name="no_save_data_found">未找到存档数æ®</string>
139
140 <!-- Applet launcher strings -->
141 <string name="applets">å°ç¨‹åºå¯åЍ噍</string>
142 <string name="applets_description">使用已安装的固件å¯åŠ¨ç³»ç»Ÿå°ç¨‹åº</string>
143 <string name="applets_error_firmware">未安装固件</string>
144 <string name="applets_error_applet">å°ç¨‹åºä¸å¯ç”¨</string>
145 <string name="applets_error_description"><![CDATA[è¯·ç¡®ä¿ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 文件和<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">固件</a>已安装,然åŽå†è¯•一次。]]></string>
146 <string name="album_applet">相册</string>
147 <string name="album_applet_description">查看存储在用户å±å¹•截图文件夹中的图åƒ</string>
148 <string name="mii_edit_applet">Mii edit</string>
149 <string name="mii_edit_applet_description">查看和编辑 Mii</string>
150 <string name="cabinet_applet">Cabinet</string>
151 <string name="cabinet_applet_description">编辑ã€åˆ é™¤å­˜å‚¨åœ¨ amiibo 上的数æ®</string>
152 <string name="cabinet_launcher">Cabinet å¯åЍ噍</string>
153 <string name="cabinet_nickname_and_owner">昵称和所有者设置</string>
154 <string name="cabinet_game_data_eraser">æ¸¸æˆæ•°æ®æ“¦é™¤å™¨</string>
155 <string name="cabinet_restorer">æ¢å¤å™¨</string>
156 <string name="cabinet_formatter">æ ¼å¼åŒ–程åº</string>
121 157
122 <!-- About screen strings --> 158 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia ä¸çœŸå®ž</string> 159 <string name="gaia_is_not_real">Gaia ä¸çœŸå®ž</string>
124 <string name="copied_to_clipboard">å·²å¤åˆ¶åˆ°å‰ªè´´æ¿</string> 160 <string name="copied_to_clipboard">å·²å¤åˆ¶åˆ°å‰ªè´´æ¿</string>
125 <string name="about_app_description">一款开放æºä»£ç çš„ Switch 模拟器</string> 161 <string name="about_app_description">一款开放æºä»£ç çš„ Switch 模拟器</string>
126 <string name="contributors">贡献者</string> 162 <string name="contributors">贡献者</string>
127 <string name="contributors_description">使用æ¥è‡ª yuzu 团队的 \u2764 制作</string> 163 <string name="contributors_description">yuzu 团队的用 \u2764 制作</string>
128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 164 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">Android 版 yuzu 离ä¸å¼€è¿™äº›é¡¹ç›®çš„æ”¯æŒ</string> 165 <string name="licenses_description">Android 版 yuzu 离ä¸å¼€è¿™äº›é¡¹ç›®çš„æ”¯æŒ</string>
130 <string name="build">构建版本</string> 166 <string name="build">构建版本</string>
@@ -161,6 +197,7 @@
161 <string name="frame_limit_enable_description">å°†è¿è¡Œé€Ÿåº¦é™åˆ¶ä¸ºæ­£å¸¸é€Ÿåº¦çš„æŒ‡å®šç™¾åˆ†æ¯”。</string> 197 <string name="frame_limit_enable_description">å°†è¿è¡Œé€Ÿåº¦é™åˆ¶ä¸ºæ­£å¸¸é€Ÿåº¦çš„æŒ‡å®šç™¾åˆ†æ¯”。</string>
162 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> 198 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string>
163 <string name="frame_limit_slider_description">指定é™åˆ¶è¿è¡Œé€Ÿåº¦çš„百分比。100% 为正常速度。更高或更低的值将增加或é™ä½Žé€Ÿåº¦é™åˆ¶ä¸Šé™ã€‚</string> 199 <string name="frame_limit_slider_description">指定é™åˆ¶è¿è¡Œé€Ÿåº¦çš„百分比。100% 为正常速度。更高或更低的值将增加或é™ä½Žé€Ÿåº¦é™åˆ¶ä¸Šé™ã€‚</string>
200 <string name="cpu_backend">CPU åŽç«¯</string>
164 <string name="cpu_accuracy">CPU 精度</string> 201 <string name="cpu_accuracy">CPU 精度</string>
165 <string name="value_with_units">%1$s%2$s</string> 202 <string name="value_with_units">%1$s%2$s</string>
166 203
@@ -191,6 +228,8 @@
191 <string name="renderer_reactive_flushing_description">牺牲性能,æé«˜æŸäº›æ¸¸æˆçš„æ¸²æŸ“精度。</string> 228 <string name="renderer_reactive_flushing_description">牺牲性能,æé«˜æŸäº›æ¸¸æˆçš„æ¸²æŸ“精度。</string>
192 <string name="use_disk_shader_cache">ç£ç›˜ç€è‰²å™¨ç¼“å­˜</string> 229 <string name="use_disk_shader_cache">ç£ç›˜ç€è‰²å™¨ç¼“å­˜</string>
193 <string name="use_disk_shader_cache_description">将生æˆçš„ç€è‰²å™¨ç¼“存于ç£ç›˜ä¸­å¹¶è¿›è¡Œè¯»å–,以å‡å°‘å¡é¡¿ã€‚</string> 230 <string name="use_disk_shader_cache_description">将生æˆçš„ç€è‰²å™¨ç¼“存于ç£ç›˜ä¸­å¹¶è¿›è¡Œè¯»å–,以å‡å°‘å¡é¡¿ã€‚</string>
231 <string name="anisotropic_filtering">å„å‘异性过滤</string>
232 <string name="anisotropic_filtering_description">æé«˜æ–œè§’的纹ç†è´¨é‡</string>
194 233
195 <!-- Debug settings strings --> 234 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string> 235 <string name="cpu">CPU</string>
@@ -217,6 +256,7 @@
217 <string name="shutting_down">正在关闭…</string> 256 <string name="shutting_down">正在关闭…</string>
218 <string name="reset_setting_confirmation">您è¦å°†æ­¤è®¾å®šé‡è®¾ä¸ºé»˜è®¤å€¼å—?</string> 257 <string name="reset_setting_confirmation">您è¦å°†æ­¤è®¾å®šé‡è®¾ä¸ºé»˜è®¤å€¼å—?</string>
219 <string name="reset_to_default">æ¢å¤é»˜è®¤</string> 258 <string name="reset_to_default">æ¢å¤é»˜è®¤</string>
259 <string name="reset_to_default_description">é‡ç½®æ‰€æœ‰é«˜çº§é€‰é¡¹</string>
220 <string name="reset_all_settings">é‡ç½®æ‰€æœ‰è®¾ç½®é¡¹ï¼Ÿ</string> 260 <string name="reset_all_settings">é‡ç½®æ‰€æœ‰è®¾ç½®é¡¹ï¼Ÿ</string>
221 <string name="reset_all_settings_description">所有高级选项都将被é‡è®¾ï¼Œæ­¤åŠ¨ä½œæ— æ³•è¿˜åŽŸã€‚</string> 261 <string name="reset_all_settings_description">所有高级选项都将被é‡è®¾ï¼Œæ­¤åŠ¨ä½œæ— æ³•è¿˜åŽŸã€‚</string>
222 <string name="settings_reset">é‡è®¾è®¾ç½®é¡¹</string> 262 <string name="settings_reset">é‡è®¾è®¾ç½®é¡¹</string>
@@ -230,6 +270,18 @@
230 <string name="export_failed">导出失败</string> 270 <string name="export_failed">导出失败</string>
231 <string name="import_failed">导入失败</string> 271 <string name="import_failed">导入失败</string>
232 <string name="cancelling">å–æ¶ˆä¸­</string> 272 <string name="cancelling">å–æ¶ˆä¸­</string>
273 <string name="install">安装</string>
274 <string name="delete">删除</string>
275 <string name="edit">编辑</string>
276 <string name="export_success">导出æˆåŠŸ</string>
277 <string name="start">开始</string>
278 <string name="clear">清除</string>
279 <string name="global">全局</string>
280 <string name="custom">自定义</string>
281 <string name="notice">æé†’</string>
282 <string name="import_complete">导入完æˆ</string>
283 <string name="more_options">更多选项</string>
284 <string name="use_global_setting">使用全局设置</string>
233 285
234 <!-- GPU driver installation --> 286 <!-- GPU driver installation -->
235 <string name="select_gpu_driver">选择 GPU 驱动程åº</string> 287 <string name="select_gpu_driver">选择 GPU 驱动程åº</string>
@@ -237,7 +289,8 @@
237 <string name="select_gpu_driver_install">安装</string> 289 <string name="select_gpu_driver_install">安装</string>
238 <string name="select_gpu_driver_default">系统默认</string> 290 <string name="select_gpu_driver_default">系统默认</string>
239 <string name="select_gpu_driver_use_default">使用默认 GPU 驱动程åº</string> 291 <string name="select_gpu_driver_use_default">使用默认 GPU 驱动程åº</string>
240 <string name="select_gpu_driver_error">é€‰æ‹©çš„é©±åŠ¨ç¨‹åºæ— æ•ˆï¼Œå°†ä½¿ç”¨ç³»ç»Ÿé»˜è®¤çš„驱动程åºï¼</string> 292 <string name="select_gpu_driver_error">选择的驱动无效</string>
293 <string name="driver_already_installed">驱动已安装</string>
241 <string name="system_gpu_driver">系统 GPU 驱动程åº</string> 294 <string name="system_gpu_driver">系统 GPU 驱动程åº</string>
242 <string name="installing_driver">正在安装驱动程åºâ€¦</string> 295 <string name="installing_driver">正在安装驱动程åºâ€¦</string>
243 296
@@ -245,10 +298,54 @@
245 <string name="preferences_settings">设置</string> 298 <string name="preferences_settings">设置</string>
246 <string name="preferences_general">通用</string> 299 <string name="preferences_general">通用</string>
247 <string name="preferences_system">系统</string> 300 <string name="preferences_system">系统</string>
301 <string name="preferences_system_description">主机è¿è¡Œæ¨¡å¼ã€åŒºåŸŸåŠè¯­è¨€</string>
248 <string name="preferences_graphics">图形</string> 302 <string name="preferences_graphics">图形</string>
303 <string name="preferences_graphics_description">精度等级ã€åˆ†è¾¨çއåŠç€è‰²å™¨ç¼“å­˜</string>
249 <string name="preferences_audio">声音</string> 304 <string name="preferences_audio">声音</string>
305 <string name="preferences_audio_description">输出引擎åŠéŸ³é‡</string>
250 <string name="preferences_theme">主题和色彩</string> 306 <string name="preferences_theme">主题和色彩</string>
251 <string name="preferences_debug">调试</string> 307 <string name="preferences_debug">调试</string>
308 <string name="preferences_debug_description">CPU/GPU 调试ã€å›¾å½¢ API åŠ fastmem 内存访问</string>
309
310 <!-- Game properties -->
311 <string name="info">ä¿¡æ¯</string>
312 <string name="info_description">æ¸¸æˆ IDã€å¼€å‘者åŠç‰ˆæœ¬ä¿¡æ¯</string>
313 <string name="per_game_settings">游æˆå•独设置</string>
314 <string name="per_game_settings_description">编辑此游æˆçš„å•独设置项</string>
315 <string name="launch_options">载入é…ç½®</string>
316 <string name="path">路径</string>
317 <string name="program_id">æ¸¸æˆ ID</string>
318 <string name="developer">å¼€å‘商</string>
319 <string name="version">版本</string>
320 <string name="copy_details">å¤åˆ¶æ˜Žç»†</string>
321 <string name="add_ons">附加项</string>
322 <string name="add_ons_description">ç®¡ç† modã€æ¸¸æˆæ›´æ–°åŠ DLC</string>
323 <string name="clear_shader_cache">清除ç€è‰²å™¨ç¼“å­˜</string>
324 <string name="clear_shader_cache_description">删除此游æˆçš„æ‰€æœ‰ç€è‰²å™¨ç¼“å­˜</string>
325 <string name="clear_shader_cache_warning_description">由于ç€è‰²å™¨ç¼“å­˜çš„é‡æ–°ç”Ÿæˆï¼Œæ‚¨å°†é­é‡æ›´å¤šå¡é¡¿</string>
326 <string name="cleared_shaders_successfully">ç€è‰²å™¨ç¼“存清除æˆåŠŸ</string>
327 <string name="addons_game">附加项: %1$s</string>
328 <string name="save_data">ä¿å­˜æ•°æ®</string>
329 <string name="save_data_description">ç®¡ç†æ­¤æ¸¸æˆçš„ä¿å­˜æ•°æ®</string>
330 <string name="delete_save_data">删除ä¿å­˜æ•°æ®</string>
331 <string name="delete_save_data_description">删除此游æˆçš„æ‰€æœ‰ä¿å­˜æ•°æ®</string>
332 <string name="delete_save_data_warning_description">这将删除此游æˆçš„æ‰€æœ‰ä¿å­˜æ•°æ®ä¸”ä¸å¯æ’¤é”€ã€‚您确定è¦ç»§ç»­å—?</string>
333 <string name="save_data_deleted_successfully">ä¿å­˜æ•°æ®åˆ é™¤æˆåŠŸ</string>
334 <string name="select_content_type">内容类型</string>
335 <string name="updates_and_dlc">æ¸¸æˆæ›´æ–°å’Œ DLC</string>
336 <string name="mods_and_cheats">Mod 和金手指</string>
337 <string name="addon_notice">附加项é‡è¦æé†’</string>
338 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
339 <string name="addon_notice_description">为了安装 mod å’Œé‡‘æ‰‹æŒ‡ï¼Œæ‚¨å¿…é¡»é€‰æ‹©ä¸€ä¸ªåŒ…å« cheats/ã€romfs/ 或 exefs/ 目录的文件夹。我们无法验è¯è¿™äº›å†…容是å¦ä¸Žæ‚¨çš„æ¸¸æˆå…¼å®¹ï¼Œæ‰€ä»¥è¯·å°å¿ƒä½¿ç”¨ï¼</string>
340 <string name="invalid_directory">无效目录</string>
341 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
342 <string name="invalid_directory_description">è¯·ç¡®ä¿æ‚¨é€‰æ‹©çš„ç›®å½•ä¸‹åŒ…å« cheats/ã€romfs/ 或 exefs/ 文件夹然åŽé‡è¯•。</string>
343 <string name="addon_installed_successfully">附加项安装æˆåŠŸ</string>
344 <string name="verifying_content">验è¯å®‰è£…内容...</string>
345 <string name="content_install_notice">安装æé†’</string>
346 <string name="content_install_notice_description">您选择安装的内容与此游æˆä¸åŒ¹é…。\n继续安装?</string>
347 <string name="confirm_uninstall">å¸è½½ç¡®è®¤</string>
348 <string name="confirm_uninstall_description">您确定è¦å¸è½½æ­¤é™„加项å—?</string>
252 349
253 <!-- ROM loading errors --> 350 <!-- ROM loading errors -->
254 <string name="loader_error_encrypted">您的 ROM 已加密</string> 351 <string name="loader_error_encrypted">您的 ROM 已加密</string>
@@ -277,6 +374,7 @@
277 <string name="emulation_pause">æš‚åœæ¨¡æ‹Ÿ</string> 374 <string name="emulation_pause">æš‚åœæ¨¡æ‹Ÿ</string>
278 <string name="emulation_unpause">继续模拟</string> 375 <string name="emulation_unpause">继续模拟</string>
279 <string name="emulation_input_overlay">虚拟按键选项</string> 376 <string name="emulation_input_overlay">虚拟按键选项</string>
377 <string name="touchscreen">触摸å±</string>
280 378
281 <string name="load_settings">正在载入设定…</string> 379 <string name="load_settings">正在载入设定…</string>
282 380
@@ -308,6 +406,7 @@
308 406
309 <!-- Memory Sizes --> 407 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string> 408 <string name="memory_byte">Byte</string>
409 <string name="memory_byte_shorthand">B</string>
311 <string name="memory_kilobyte">KB</string> 410 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string> 411 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string> 412 <string name="memory_gigabyte">GB</string>
@@ -352,9 +451,13 @@
352 <string name="anti_aliasing_smaa">å­åƒç´ å½¢æ€å­¦æŠ—锯齿</string> 451 <string name="anti_aliasing_smaa">å­åƒç´ å½¢æ€å­¦æŠ—锯齿</string>
353 452
354 <!-- Screen Layouts --> 453 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">横å‘大å±</string>
356 <string name="screen_layout_portrait">纵å‘å±å¹•</string>
357 <string name="screen_layout_auto">自动</string> 454 <string name="screen_layout_auto">自动</string>
455 <string name="screen_layout_sensor_landscape">ä¼ æ„Ÿå™¨æ–¹å‘æ¨ªå±</string>
456 <string name="screen_layout_landscape">横å±</string>
457 <string name="screen_layout_reverse_landscape">å呿¨ªå±</string>
458 <string name="screen_layout_sensor_portrait">传感器方å‘ç«–å±</string>
459 <string name="screen_layout_portrait">ç«–å±</string>
460 <string name="screen_layout_reverse_portrait">åå‘ç«–å±</string>
358 461
359 <!-- Aspect Ratios --> 462 <!-- Aspect Ratios -->
360 <string name="ratio_default">默认 (16:9)</string> 463 <string name="ratio_default">默认 (16:9)</string>
@@ -363,6 +466,10 @@
363 <string name="ratio_force_sixteen_ten">强制 16:10</string> 466 <string name="ratio_force_sixteen_ten">强制 16:10</string>
364 <string name="ratio_stretch">拉伸窗å£</string> 467 <string name="ratio_stretch">拉伸窗å£</string>
365 468
469 <!-- CPU Backend -->
470 <string name="cpu_backend_dynarmic">动æ€ç¼–译 (慢速)</string>
471 <string name="cpu_backend_nce">æœ¬æœºä»£ç æ‰§è¡Œ (NCE)</string>
472
366 <!-- CPU Accuracy --> 473 <!-- CPU Accuracy -->
367 <string name="cpu_accuracy_accurate">高精度</string> 474 <string name="cpu_accuracy_accurate">高精度</string>
368 <string name="cpu_accuracy_unsafe">低精度</string> 475 <string name="cpu_accuracy_unsafe">低精度</string>
@@ -391,8 +498,15 @@
391 <string name="theme_mode_dark">深色</string> 498 <string name="theme_mode_dark">深色</string>
392 499
393 <!-- Audio output engines --> 500 <!-- Audio output engines -->
501 <string name="oboe">oboe</string>
394 <string name="cubeb">cubeb</string> 502 <string name="cubeb">cubeb</string>
395 503
504 <!-- Anisotropic filtering options -->
505 <string name="multiplier_two">2x</string>
506 <string name="multiplier_four">4x</string>
507 <string name="multiplier_eight">8x</string>
508 <string name="multiplier_sixteen">16x</string>
509
396 <!-- Black backgrounds theme --> 510 <!-- Black backgrounds theme -->
397 <string name="use_black_backgrounds">使用黑色背景</string> 511 <string name="use_black_backgrounds">使用黑色背景</string>
398 <string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string> 512 <string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string>
diff --git a/src/android/app/src/main/res/values-zh-rTW/strings.xml b/src/android/app/src/main/res/values-zh-rTW/strings.xml
index b8f468c68..d39255714 100644
--- a/src/android/app/src/main/res/values-zh-rTW/strings.xml
+++ b/src/android/app/src/main/res/values-zh-rTW/strings.xml
@@ -34,12 +34,13 @@
34 <string name="empty_gamelist">找ä¸åˆ°æª”案,或者尚未é¸å–éŠæˆ²ç›®éŒ„。</string> 34 <string name="empty_gamelist">找ä¸åˆ°æª”案,或者尚未é¸å–éŠæˆ²ç›®éŒ„。</string>
35 <string name="search_and_filter_games">æœå°‹ä¸¦ç¯©é¸éŠæˆ²</string> 35 <string name="search_and_filter_games">æœå°‹ä¸¦ç¯©é¸éŠæˆ²</string>
36 <string name="select_games_folder">é¸å–éŠæˆ²è³‡æ–™å¤¾</string> 36 <string name="select_games_folder">é¸å–éŠæˆ²è³‡æ–™å¤¾</string>
37 <string name="manage_game_folders">管ç†éŠæˆ²è³‡æ–™å¤¾</string>
37 <string name="select_games_folder_description">å…許 yuzu å¡«å…¥éŠæˆ²æ¸…å–®</string> 38 <string name="select_games_folder_description">å…許 yuzu å¡«å…¥éŠæˆ²æ¸…å–®</string>
38 <string name="add_games_warning">è·³éŽé¸å–éŠæˆ²è³‡æ–™å¤¾ï¼Ÿ</string> 39 <string name="add_games_warning">è·³éŽé¸å–éŠæˆ²è³‡æ–™å¤¾ï¼Ÿ</string>
39 <string name="add_games_warning_description">如果資料夾未é¸å–ï¼ŒéŠæˆ²å°‡ä¸æœƒé¡¯ç¤ºåœ¨éŠæˆ²æ¸…單。</string> 40 <string name="add_games_warning_description">如果資料夾未é¸å–ï¼ŒéŠæˆ²å°‡ä¸æœƒé¡¯ç¤ºåœ¨éŠæˆ²æ¸…單。</string>
40 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 41 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
41 <string name="home_search_games">æœå°‹éŠæˆ²</string> 42 <string name="home_search_games">æœå°‹éŠæˆ²</string>
42 <string name="search_settings">æœç´¢è®¾ç½®</string> 43 <string name="search_settings">æœå°‹è¨­å®š</string>
43 <string name="games_dir_selected">éŠæˆ²ç›®éŒ„å·²é¸å–</string> 44 <string name="games_dir_selected">éŠæˆ²ç›®éŒ„å·²é¸å–</string>
44 <string name="install_prod_keys">å®‰è£ prod.keys</string> 45 <string name="install_prod_keys">å®‰è£ prod.keys</string>
45 <string name="install_prod_keys_description">需è¦è§£å¯†é›¶å”®éŠæˆ²</string> 46 <string name="install_prod_keys_description">需è¦è§£å¯†é›¶å”®éŠæˆ²</string>
@@ -68,10 +69,11 @@
68 <string name="invalid_keys_error">無效的加密金鑰</string> 69 <string name="invalid_keys_error">無效的加密金鑰</string>
69 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 70 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
70 <string name="install_keys_failure_description">é¸å–çš„æª”æ¡ˆä¸æ­£ç¢ºæˆ–å·²ææ¯€ï¼Œè«‹é‡æ–°å‚¾å°æ‚¨çš„金鑰。</string> 71 <string name="install_keys_failure_description">é¸å–çš„æª”æ¡ˆä¸æ­£ç¢ºæˆ–å·²ææ¯€ï¼Œè«‹é‡æ–°å‚¾å°æ‚¨çš„金鑰。</string>
72 <string name="gpu_driver_manager">GPU 驅動程å¼ç®¡ç†å“¡</string>
71 <string name="install_gpu_driver">å®‰è£ GPU 驅動程å¼</string> 73 <string name="install_gpu_driver">å®‰è£ GPU 驅動程å¼</string>
72 <string name="install_gpu_driver_description">å®‰è£æ›¿ä»£é©…動程å¼ä»¥å–得潛在的更佳效能或準確度</string> 74 <string name="install_gpu_driver_description">å®‰è£æ›¿ä»£é©…動程å¼ä»¥å–得潛在的更佳效能或準確度</string>
73 <string name="advanced_settings">進階設定</string> 75 <string name="advanced_settings">進階設定</string>
74 <string name="advanced_settings_game">高级é项: %1$s</string> 76 <string name="advanced_settings_game">進階設定:%1$s</string>
75 <string name="settings_description">進行模擬器設定</string> 77 <string name="settings_description">進行模擬器設定</string>
76 <string name="search_recently_played">最近éŠçŽ©</string> 78 <string name="search_recently_played">最近éŠçŽ©</string>
77 <string name="search_recently_added">最近新增</string> 79 <string name="search_recently_added">最近新增</string>
@@ -85,7 +87,11 @@
85 <string name="notification_no_directory_link_description">請使用檔案管ç†å“¡çš„å´é‚Šé¢æ¿æ‰‹å‹•定ä½åˆ°ä½¿ç”¨è€…資料夾。</string> 87 <string name="notification_no_directory_link_description">請使用檔案管ç†å“¡çš„å´é‚Šé¢æ¿æ‰‹å‹•定ä½åˆ°ä½¿ç”¨è€…資料夾。</string>
86 <string name="manage_save_data">管ç†å„²å­˜è³‡æ–™</string> 88 <string name="manage_save_data">管ç†å„²å­˜è³‡æ–™</string>
87 <string name="manage_save_data_description">已找到儲存資料,請é¸å–下方的é¸é …。</string> 89 <string name="manage_save_data_description">已找到儲存資料,請é¸å–下方的é¸é …。</string>
90 <string name="import_save_warning">匯入儲存資料</string>
91 <string name="import_save_warning_description">這將會以æä¾›çš„æª”æ¡ˆè¦†å¯«æ‰€æœ‰ç¾æœ‰çš„儲存資料,您確定è¦ç¹¼çºŒå—Žï¼Ÿ</string>
88 <string name="import_export_saves_description">匯入或匯出儲存檔案</string> 92 <string name="import_export_saves_description">匯入或匯出儲存檔案</string>
93 <string name="save_files_importing">正在匯入儲存檔案…</string>
94 <string name="save_files_exporting">正在匯出儲存檔案…</string>
89 <string name="save_file_imported_success">å·²æˆåŠŸåŒ¯å…¥</string> 95 <string name="save_file_imported_success">å·²æˆåŠŸåŒ¯å…¥</string>
90 <string name="save_file_invalid_zip_structure">ç„¡æ•ˆçš„å„²å­˜ç›®éŒ„çµæ§‹</string> 96 <string name="save_file_invalid_zip_structure">ç„¡æ•ˆçš„å„²å­˜ç›®éŒ„çµæ§‹</string>
91 <string name="save_file_invalid_zip_structure_description">首個å­è³‡æ–™å¤¾åç¨±å¿…é ˆç‚ºéŠæˆ²æ¨™é¡Œ ID。</string> 97 <string name="save_file_invalid_zip_structure_description">首個å­è³‡æ–™å¤¾åç¨±å¿…é ˆç‚ºéŠæˆ²æ¨™é¡Œ ID。</string>
@@ -96,28 +102,58 @@
96 <string name="firmware_installing">正在安è£éŸŒé«”</string> 102 <string name="firmware_installing">正在安è£éŸŒé«”</string>
97 <string name="firmware_installed_success">韌體已æˆåŠŸå®‰è£</string> 103 <string name="firmware_installed_success">韌體已æˆåŠŸå®‰è£</string>
98 <string name="firmware_installed_failure">韌體安è£å¤±æ•—</string> 104 <string name="firmware_installed_failure">韌體安è£å¤±æ•—</string>
99 <string name="firmware_installed_failure_description">请确ä¿å›ºä»¶ nca 文件ä½äºŽ zip 压缩包的根目录,然åŽé‡è¯•。</string> 105 <string name="firmware_installed_failure_description">請確ä¿éŸŒé«” nca æª”æ¡ˆä½æ–¼ zip 壓縮檔的根目錄,然後å†è©¦ä¸€æ¬¡ã€‚</string>
100 <string name="share_log">分享åµéŒ¯è¨˜éŒ„</string> 106 <string name="share_log">分享åµéŒ¯è¨˜éŒ„</string>
101 <string name="share_log_description">分享 yuzu 的記錄檔以便å°ç›¸é—œå•題進行åµéŒ¯</string> 107 <string name="share_log_description">分享 yuzu 的記錄檔以便å°ç›¸é—œå•題進行åµéŒ¯</string>
102 <string name="share_log_missing">找ä¸åˆ°è¨˜éŒ„檔</string> 108 <string name="share_log_missing">找ä¸åˆ°è¨˜éŒ„檔</string>
103 <string name="install_game_content">安è£éŠæˆ²å…§å®¹</string> 109 <string name="install_game_content">安è£éŠæˆ²å…§å®¹</string>
104 <string name="install_game_content_description">安è£éŠæˆ²æ›´æ–°æˆ– DLC</string> 110 <string name="install_game_content_description">安è£éŠæˆ²æ›´æ–°æˆ– DLC</string>
105 <string name="installing_game_content">安装中...</string> 111 <string name="installing_game_content">正在安è£å§å®¹â€¦</string>
106 <string name="install_game_content_failure">å‘ NAND å®‰è£æä»¶æ—¶å¤±è´¥</string> 112 <string name="install_game_content_failure">å®‰è£æª”æ¡ˆè³ NAND 時發生錯誤</string>
107 <string name="install_game_content_failure_description">请确ä¿é™„加内容的有效性,并且 prod.keys 密钥文件已安装。</string> 113 <string name="install_game_content_failure_description">請確ä¿å…§å®¹æœ‰æ•ˆä¸¦ä¸” prod.keys 檔案已安è£ã€‚</string>
108 <string name="install_game_content_failure_base">为é¿å…产生冲çªï¼Œæ­¤åŠŸèƒ½ä¸èƒ½ç”¨äºŽå®‰è£…æ¸¸æˆæœ¬ä½“。</string> 114 <string name="install_game_content_failure_base">為é¿å…å¯èƒ½çš„è¡çªï¼Œä¸å…許安è£åŸºç¤ŽéŠæˆ²ã€‚</string>
109 <string name="install_game_content_failure_file_extension">åªæœ‰ NSP 或 XCI æ ¼å¼çš„附加内容å¯ä»¥å®‰è£…ã€‚è¯·ç¡®ä¿æ‚¨çš„æ¸¸æˆé™„加内容是有效的。</string> 115 <string name="install_game_content_failure_file_extension">åƒ…æ”¯æ´ NSP å’Œ XCI å…§å®¹ï¼Œè«‹é©—è­‰éŠæˆ²å…§å®¹æ˜¯å¦æœ‰æ•ˆã€‚</string>
110 <string name="install_game_content_failed_count">%1$d 安装出错</string> 116 <string name="install_game_content_failed_count">%1$d 安è£éŒ¯èª¤</string>
111 <string name="install_game_content_success">游æˆé™„加å…容已æˆåŠŸå®‰è£</string> 117 <string name="install_game_content_success">éŠæˆ²å…§å®¹å·²æˆåŠŸå®‰è£</string>
112 <string name="install_game_content_success_install">%1$d å®‰è£æˆåŠŸ</string> 118 <string name="install_game_content_success_install">%1$d å®‰è£æˆåŠŸ</string>
113 <string name="install_game_content_success_overwrite">%1$d 覆盖安装æˆåŠŸ</string> 119 <string name="install_game_content_success_overwrite">%1$d 覆寫æˆåŠŸ</string>
114 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string> 120 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
115 <string name="custom_driver_not_supported">䏿”¯æŒè‡ªå®šä¹‰é©±åЍ</string> 121 <string name="custom_driver_not_supported">䏿”¯æ´è‡ªè¨‚的驅動程å¼</string>
116 <string name="custom_driver_not_supported_description">æ­¤è®¾å¤‡ä¸æ”¯æŒè‡ªå®šä¹‰é©±åŠ¨ã€‚\n请之åŽå†è®¿é—®æ­¤é¡¹ï¼ŒæŸ¥çœ‹æ˜¯å¦å·²ä¸ºæ­¤è®¾å¤‡æ·»åŠ æ”¯æŒã€‚</string> 122 <string name="custom_driver_not_supported_description">æ­¤è£ç½®ä¸æ”¯æ´è‡ªè¨‚的驅動程å¼ã€‚\n請以後å†ä¾†æŸ¥çœ‹æ˜¯å¦å·²æ–°å¢žæ”¯æ´ï¼</string>
117 <string name="manage_yuzu_data">ç®¡ç† yuzu æ•°æ®</string> 123 <string name="manage_yuzu_data">ç®¡ç† yuzu 資料</string>
118 <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string> 124 <string name="manage_yuzu_data_description">匯入/匯出韌體ã€é‡‘é‘°ã€ä½¿ç”¨è€…資料åŠå…¶ä»–é …ç›®ï¼</string>
119 <string name="share_save_file">分享存档文件</string> 125 <string name="share_save_file">分享儲存檔案</string>
120 <string name="export_save_failed">导出存档文件失败</string> 126 <string name="export_save_failed">無法匯出儲存檔案</string>
127 <string name="game_folders">éŠæˆ²è³‡æ–™å¤¾</string>
128 <string name="deep_scan">深度掃æ</string>
129 <string name="add_game_folder">æ–°å¢žéŠæˆ²è³‡æ–™å¤¾</string>
130 <string name="folder_already_added">這個資料夾已經新增éŽäº†ï¼</string>
131 <string name="game_folder_properties">éŠæˆ²è³‡æ–™å¤¾å±¬æ€§</string>
132 <plurals name="saves_import_failed">
133 <item quantity="other">%d 个存档导入失败</item>
134 </plurals>
135 <plurals name="saves_import_success">
136 <item quantity="other">æˆåŠŸå¯¼å…¥ %d 个存档</item>
137 </plurals>
138 <string name="no_save_data_found">未找到存档数æ®</string>
139
140 <!-- Applet launcher strings -->
141 <string name="applets">å°ç¨‹å¼å•Ÿå‹•器</string>
142 <string name="applets_description">使用已安è£çš„韌體啟動系統å°ç¨‹å¼</string>
143 <string name="applets_error_firmware">未安è£éŸŒé«”</string>
144 <string name="applets_error_applet">無法使用å°ç¨‹å¼</string>
145 <string name="applets_error_description"><![CDATA[è«‹ç¢ºä¿æ‚¨çš„ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 檔案和<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-system-firmware\">韌體</a>已安è£ï¼Œç„¶å¾Œå†è©¦ä¸€æ¬¡ã€‚]]></string>
146 <string name="album_applet">相簿</string>
147 <string name="album_applet_description">使用系統相片檢視器查看儲存在使用者螢幕截圖資料夾中的影åƒ</string>
148 <string name="mii_edit_applet">Mii 編輯</string>
149 <string name="mii_edit_applet_description">使用系統編輯器來檢視並編輯 Mii</string>
150 <string name="cabinet_applet">Cabinet</string>
151 <string name="cabinet_applet_description">編輯ã€åˆªé™¤å„²å­˜åœ¨ amiibo 上的資料</string>
152 <string name="cabinet_launcher">Cabinet 啟動器</string>
153 <string name="cabinet_nickname_and_owner">æš±ç¨±å’Œæ“æœ‰è€…設定</string>
154 <string name="cabinet_game_data_eraser">éŠæˆ²è³‡æ–™æ©¡ç𮿓¦</string>
155 <string name="cabinet_restorer">還原程å¼</string>
156 <string name="cabinet_formatter">æ ¼å¼å™¨</string>
121 157
122 <!-- About screen strings --> 158 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia ä¸çœŸå¯¦</string> 159 <string name="gaia_is_not_real">Gaia ä¸çœŸå¯¦</string>
@@ -128,16 +164,16 @@
128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 164 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">這些專案使 yuzu Android 版æˆç‚ºå¯èƒ½</string> 165 <string name="licenses_description">這些專案使 yuzu Android 版æˆç‚ºå¯èƒ½</string>
130 <string name="build">組建</string> 166 <string name="build">組建</string>
131 <string name="user_data">用户数æ®</string> 167 <string name="user_data">使用者資料</string>
132 <string name="user_data_description">导入/å¯¼å‡ºåº”ç”¨ç¨‹åºæ‰€æœ‰æ•°æ®ã€‚\n\nå¯¼å…¥ç”¨æˆ·æ•°æ®æ—¶ï¼Œå°†åˆ é™¤å½“剿‰€æœ‰çš„用户数æ®ï¼</string> 168 <string name="user_data_description">匯入/匯出所有應用程å¼è³‡æ–™ã€‚\n\nåŒ¯å…¥ä½¿ç”¨è€…è³‡æ–™æ™‚ï¼Œç¾æœ‰çš„使用者資料將被刪除ï¼</string>
133 <string name="exporting_user_data">正在导出用户数æ®...</string> 169 <string name="exporting_user_data">正在匯出使用者資料…</string>
134 <string name="importing_user_data">正在导入用户数æ®...</string> 170 <string name="importing_user_data">正在匯入使用者資料…</string>
135 <string name="import_user_data">导入用户数æ®</string> 171 <string name="import_user_data">匯入使用者資料</string>
136 <string name="invalid_yuzu_backup">无效的 yuzu 备份</string> 172 <string name="invalid_yuzu_backup">無效的 yuzu 備份</string>
137 <string name="user_data_export_success">å¯¼å‡ºç”¨æˆ·æ•°æ®æˆåŠŸ</string> 173 <string name="user_data_export_success">使用者資料匯出æˆåŠŸ</string>
138 <string name="user_data_import_success">å¯¼å…¥ç”¨æˆ·æ•°æ®æˆåŠŸ</string> 174 <string name="user_data_import_success">使用者資料匯入æˆåŠŸ</string>
139 <string name="user_data_export_cancelled">已喿¶ˆå¯¼å‡ºæ•°æ®</string> 175 <string name="user_data_export_cancelled">åŒ¯å‡ºå·²å–æ¶ˆ</string>
140 <string name="user_data_import_failed_description">请确ä¿ç”¨æˆ·æ•°æ®æ–‡ä»¶å¤¹ä½äºŽ zip 压缩包的根目录,并在 config/config.ini 路径中包å«é…置文件,然åŽé‡è¯•。</string> 176 <string name="user_data_import_failed_description">請確ä¿ä½¿ç”¨è€…è³‡æ–™å¤¾ä½æ–¼ zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包å«çµ„態檔案,並å†è©¦ä¸€æ¬¡ã€‚</string>
141 <string name="support_link">https://discord.gg/u77vRWY</string> 177 <string name="support_link">https://discord.gg/u77vRWY</string>
142 <string name="website_link">https://yuzu-emu.org/</string> 178 <string name="website_link">https://yuzu-emu.org/</string>
143 <string name="github_link">https://github.com/yuzu-emu</string> 179 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -161,6 +197,7 @@
161 <string name="frame_limit_enable_description">將模擬速度é™åˆ¶åœ¨æ¨™æº–速度的指定百分比。</string> 197 <string name="frame_limit_enable_description">將模擬速度é™åˆ¶åœ¨æ¨™æº–速度的指定百分比。</string>
162 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> 198 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string>
163 <string name="frame_limit_slider_description">指定é™åˆ¶æ¨¡æ“¬é€Ÿåº¦çš„百分比。100% 為標準速度,更高或更低的值將會增加或減少速度é™åˆ¶ã€‚</string> 199 <string name="frame_limit_slider_description">指定é™åˆ¶æ¨¡æ“¬é€Ÿåº¦çš„百分比。100% 為標準速度,更高或更低的值將會增加或減少速度é™åˆ¶ã€‚</string>
200 <string name="cpu_backend">CPU 後端</string>
164 <string name="cpu_accuracy">CPU 準確度</string> 201 <string name="cpu_accuracy">CPU 準確度</string>
165 <string name="value_with_units">%1$s%2$s</string> 202 <string name="value_with_units">%1$s%2$s</string>
166 203
@@ -179,7 +216,7 @@
179 <string name="renderer_accuracy">準確度層級</string> 216 <string name="renderer_accuracy">準確度層級</string>
180 <string name="renderer_resolution">è§£æžåº¦ (手æ/底座)</string> 217 <string name="renderer_resolution">è§£æžåº¦ (手æ/底座)</string>
181 <string name="renderer_vsync">VSync 模å¼</string> 218 <string name="renderer_vsync">VSync 模å¼</string>
182 <string name="renderer_screen_layout">å±å¹•æ–¹å‘</string> 219 <string name="renderer_screen_layout">æ–¹å‘</string>
183 <string name="renderer_aspect_ratio">長寬比</string> 220 <string name="renderer_aspect_ratio">長寬比</string>
184 <string name="renderer_scaling_filter">è¦–çª—é©æ‡‰éŽæ¿¾å™¨</string> 221 <string name="renderer_scaling_filter">è¦–çª—é©æ‡‰éŽæ¿¾å™¨</string>
185 <string name="renderer_anti_aliasing">消除鋸齒方法</string> 222 <string name="renderer_anti_aliasing">消除鋸齒方法</string>
@@ -191,11 +228,13 @@
191 <string name="renderer_reactive_flushing_description">çŠ§ç‰²æ•ˆèƒ½ï¼Œä»¥æ”¹å–„éƒ¨åˆ†éŠæˆ²çš„轉譯準確度。</string> 228 <string name="renderer_reactive_flushing_description">çŠ§ç‰²æ•ˆèƒ½ï¼Œä»¥æ”¹å–„éƒ¨åˆ†éŠæˆ²çš„轉譯準確度。</string>
192 <string name="use_disk_shader_cache">ç£ç¢Ÿè‘—色器快å–</string> 229 <string name="use_disk_shader_cache">ç£ç¢Ÿè‘—色器快å–</string>
193 <string name="use_disk_shader_cache_description">é€éŽå°‡ç”¢ç”Ÿçš„著色器儲存並載入至ç£ç¢Ÿï¼Œæ¸›å°‘中斷。</string> 230 <string name="use_disk_shader_cache_description">é€éŽå°‡ç”¢ç”Ÿçš„著色器儲存並載入至ç£ç¢Ÿï¼Œæ¸›å°‘中斷。</string>
231 <string name="anisotropic_filtering">éžç­‰å‘æ€§éŽæ¿¾</string>
232 <string name="anisotropic_filtering_description">改善斜角檢視時的紋ç†å“質</string>
194 233
195 <!-- Debug settings strings --> 234 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string> 235 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">CPU è°ƒè¯</string> 236 <string name="cpu_debug_mode">CPU åµéŒ¯</string>
198 <string name="cpu_debug_mode_description">å° CPU è®¾ç½®ä¸ºè¾ƒæ…¢çš„è°ƒè¯æ¨¡å¼ã€‚</string> 237 <string name="cpu_debug_mode_description">å° CPU è¨­å®šçºæ…¢é€ŸåµéŒ¯æ¨¡å¼ã€‚</string>
199 <string name="gpu">GPU</string> 238 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string> 239 <string name="renderer_api">API</string>
201 <string name="renderer_debug">圖形åµéŒ¯</string> 240 <string name="renderer_debug">圖形åµéŒ¯</string>
@@ -203,7 +242,7 @@
203 <string name="fastmem">Fastmem</string> 242 <string name="fastmem">Fastmem</string>
204 243
205 <!-- Audio settings strings --> 244 <!-- Audio settings strings -->
206 <string name="audio_output_engine">输出引擎</string> 245 <string name="audio_output_engine">輸出引擎</string>
207 <string name="audio_volume">音é‡</string> 246 <string name="audio_volume">音é‡</string>
208 <string name="audio_volume_description">指定音訊輸出音é‡ã€‚</string> 247 <string name="audio_volume_description">指定音訊輸出音é‡ã€‚</string>
209 248
@@ -212,11 +251,12 @@
212 <string name="ini_saved">已儲存設定</string> 251 <string name="ini_saved">已儲存設定</string>
213 <string name="gameid_saved">已儲存 %1$s 設定</string> 252 <string name="gameid_saved">已儲存 %1$s 設定</string>
214 <string name="error_saving">儲存 %1$s 時發生錯誤 ini: %2$s</string> 253 <string name="error_saving">儲存 %1$s 時發生錯誤 ini: %2$s</string>
215 <string name="unimplemented_menu">未生效èœå</string> 254 <string name="unimplemented_menu">未實作的é¸å–®</string>
216 <string name="loading">正在載入…</string> 255 <string name="loading">正在載入…</string>
217 <string name="shutting_down">正在关闭…</string> 256 <string name="shutting_down">正在關閉…</string>
218 <string name="reset_setting_confirmation">è¦å°‡æ­¤è¨­å®šé‡è¨­å›žé è¨­å€¼å—Žï¼Ÿ</string> 257 <string name="reset_setting_confirmation">è¦å°‡æ­¤è¨­å®šé‡è¨­å›žé è¨­å€¼å—Žï¼Ÿ</string>
219 <string name="reset_to_default">é‡è¨­ç‚ºé è¨­å€¼</string> 258 <string name="reset_to_default">é‡è¨­ç‚ºé è¨­å€¼</string>
259 <string name="reset_to_default_description">é‡è¨­æ‰€æœ‰é€²éšŽè¨­å®š</string>
220 <string name="reset_all_settings">é‡è¨­æ‰€æœ‰è¨­å®šï¼Ÿ</string> 260 <string name="reset_all_settings">é‡è¨­æ‰€æœ‰è¨­å®šï¼Ÿ</string>
221 <string name="reset_all_settings_description">所有進階設定將被é‡è¨­ç‚ºé è¨­çµ„態,此動作無法復原。</string> 261 <string name="reset_all_settings_description">所有進階設定將被é‡è¨­ç‚ºé è¨­çµ„態,此動作無法復原。</string>
222 <string name="settings_reset">設定已é‡è¨­</string> 262 <string name="settings_reset">設定已é‡è¨­</string>
@@ -227,9 +267,21 @@
227 <string name="string_null">ç„¡</string> 267 <string name="string_null">ç„¡</string>
228 <string name="string_import">匯入</string> 268 <string name="string_import">匯入</string>
229 <string name="export">匯出</string> 269 <string name="export">匯出</string>
230 <string name="export_failed">导出失败</string> 270 <string name="export_failed">匯出失敗</string>
231 <string name="import_failed">导入失败</string> 271 <string name="import_failed">匯入失敗</string>
232 <string name="cancelling">å–æ¶ˆä¸­</string> 272 <string name="cancelling">æ­£åœ¨å–æ¶ˆ</string>
273 <string name="install">安è£</string>
274 <string name="delete">刪除</string>
275 <string name="edit">編輯</string>
276 <string name="export_success">å·²æˆåŠŸåŒ¯å‡º</string>
277 <string name="start">é–‹å§‹</string>
278 <string name="clear">清除</string>
279 <string name="global">全域</string>
280 <string name="custom">自定义</string>
281 <string name="notice">通知</string>
282 <string name="import_complete">导入完æˆ</string>
283 <string name="more_options">更多选项</string>
284 <string name="use_global_setting">使用全局设置</string>
233 285
234 <!-- GPU driver installation --> 286 <!-- GPU driver installation -->
235 <string name="select_gpu_driver">é¸å– GPU 驅動程å¼</string> 287 <string name="select_gpu_driver">é¸å– GPU 驅動程å¼</string>
@@ -237,7 +289,8 @@
237 <string name="select_gpu_driver_install">安è£</string> 289 <string name="select_gpu_driver_install">安è£</string>
238 <string name="select_gpu_driver_default">é è¨­</string> 290 <string name="select_gpu_driver_default">é è¨­</string>
239 <string name="select_gpu_driver_use_default">使用é è¨­ GPU 驅動程å¼</string> 291 <string name="select_gpu_driver_use_default">使用é è¨­ GPU 驅動程å¼</string>
240 <string name="select_gpu_driver_error">é¸å–的驅動程å¼ç„¡æ•ˆï¼Œå°‡ä½¿ç”¨ç³»çµ±é è¨­é©…動程å¼ï¼</string> 292 <string name="select_gpu_driver_error">é¸å–的驅動程å¼ç„¡æ•ˆ</string>
293 <string name="driver_already_installed">驅動程å¼å·²å®‰è£</string>
241 <string name="system_gpu_driver">系統 GPU 驅動程å¼</string> 294 <string name="system_gpu_driver">系統 GPU 驅動程å¼</string>
242 <string name="installing_driver">正在安è£é©…動程å¼â€¦</string> 295 <string name="installing_driver">正在安è£é©…動程å¼â€¦</string>
243 296
@@ -245,14 +298,58 @@
245 <string name="preferences_settings">設定</string> 298 <string name="preferences_settings">設定</string>
246 <string name="preferences_general">一般</string> 299 <string name="preferences_general">一般</string>
247 <string name="preferences_system">系統</string> 300 <string name="preferences_system">系統</string>
301 <string name="preferences_system_description">底座模å¼ã€å€åŸŸåŠèªžè¨€</string>
248 <string name="preferences_graphics">圖形</string> 302 <string name="preferences_graphics">圖形</string>
303 <string name="preferences_graphics_description">準確度層級ã€è§£æžåº¦åŠè‘—色器快å–</string>
249 <string name="preferences_audio">音訊</string> 304 <string name="preferences_audio">音訊</string>
305 <string name="preferences_audio_description">輸出引擎åŠéŸ³é‡</string>
250 <string name="preferences_theme">主題和色彩</string> 306 <string name="preferences_theme">主題和色彩</string>
251 <string name="preferences_debug">åµéŒ¯</string> 307 <string name="preferences_debug">åµéŒ¯</string>
308 <string name="preferences_debug_description">CPU/GPU åµéŒ¯ã€åœ–å½¢ API åŠ fastmem</string>
309
310 <!-- Game properties -->
311 <string name="info">資訊</string>
312 <string name="info_description">ç¨‹å¼ IDã€é–‹ç™¼äººå“¡åŠç‰ˆæœ¬è³‡è¨Š</string>
313 <string name="per_game_settings">å€‹åˆ¥éŠæˆ²è¨­å®š</string>
314 <string name="per_game_settings_description">ç·¨è¼¯æ­¤éŠæˆ²çš„特定設定</string>
315 <string name="launch_options">啟動組態</string>
316 <string name="path">路徑</string>
317 <string name="program_id">ç¨‹å¼ ID</string>
318 <string name="developer">出版商</string>
319 <string name="version">版本</string>
320 <string name="copy_details">複製詳細資料</string>
321 <string name="add_ons">延伸模組</string>
322 <string name="add_ons_description">åˆ‡æ›æ¨¡çµ„ã€æ›´æ–°åŠ DLC</string>
323 <string name="clear_shader_cache">清除著色器快å–</string>
324 <string name="clear_shader_cache_description">éŠçŽ©æ­¤éŠæˆ²æ™‚移除所有著色器組建</string>
325 <string name="clear_shader_cache_warning_description">由於著色器快å–çš„é‡æ–°ç”¢ç”Ÿï¼Œæ‚¨å¯èƒ½æœƒæ„Ÿåˆ°ä¸å¤ªé †æš¢</string>
326 <string name="cleared_shaders_successfully">著色器快å–å·²æˆåŠŸæ¸…é™¤</string>
327 <string name="addons_game">附加元件:%1$s</string>
328 <string name="save_data">儲存資料</string>
329 <string name="save_data_description">ç®¡ç†æ­¤éŠæˆ²ç‰¹å®šçš„儲存資料</string>
330 <string name="delete_save_data">刪除儲存資料</string>
331 <string name="delete_save_data_description">ç§»é™¤æ­¤éŠæˆ²ç‰¹å®šçš„æ‰€æœ‰å„²å­˜è³‡æ–™</string>
332 <string name="delete_save_data_warning_description">é€™å°‡æœƒç§»é™¤æ­¤éŠæˆ²çš„æ‰€æœ‰å„²å­˜è³‡æ–™ï¼Œä¸”無法復原,您確定è¦ç¹¼çºŒå—Žï¼Ÿ</string>
333 <string name="save_data_deleted_successfully">儲存資料已æˆåŠŸåˆªé™¤</string>
334 <string name="select_content_type">內容類型</string>
335 <string name="updates_and_dlc">æ›´æ–°åŠ DLC</string>
336 <string name="mods_and_cheats">模組åŠå¯†æŠ€</string>
337 <string name="addon_notice">é‡è¦çš„˙附加元件通知</string>
338 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
339 <string name="addon_notice_description">è‹¥è¦å®‰è£æ¨¡çµ„åŠå¯†æŠ€ï¼Œæ‚¨å¿…é ˆé¸å–ä¸€å€‹åŒ…å« cheats/ã€romfs/ 或 exefs/ 的目錄。我們無法驗證這些內容是å¦èˆ‡æ‚¨çš„éŠæˆ²ç›¸å®¹ï¼Œæ‰€ä»¥è«‹å°å¿ƒä½œæ¥­ï¼</string>
340 <string name="invalid_directory">無效的目錄</string>
341 <!-- "cheats/" "romfs/" and "exefs/ should not be translated -->
342 <string name="invalid_directory_description">è«‹ç¢ºä¿æ‚¨é¸å–çš„ç›®éŒ„åŒ…å« cheats/ã€romfs/ 或 exefs/ 資料夾,然後å†è©¦ä¸€æ¬¡ã€‚</string>
343 <string name="addon_installed_successfully">附加元件已æˆåŠŸå®‰è£</string>
344 <string name="verifying_content">正在驗證內容…</string>
345 <string name="content_install_notice">內容安è£é€šçŸ¥</string>
346 <string name="content_install_notice_description">您é¸å–çš„å…§å®¹èˆ‡æ­¤éŠæˆ²ä¸ç›¸ç¬¦ã€‚\nä»è¦ç¹¼çºŒå®‰è£å—Žï¼Ÿ</string>
347 <string name="confirm_uninstall">确认å¸è½½</string>
348 <string name="confirm_uninstall_description">您确定è¦å¸è½½æ­¤é™„加项å—?</string>
252 349
253 <!-- ROM loading errors --> 350 <!-- ROM loading errors -->
254 <string name="loader_error_encrypted">您的 ROM 已加密</string> 351 <string name="loader_error_encrypted">您的 ROM 已加密</string>
255 <string name="loader_error_encrypted_roms_description"><![CDATA[请按照指å—釿–°è½¬å‚¨æ‚¨çš„<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">游æˆå¡å¸¦</a>或<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">已安装的游æˆ</a>。]]></string> 352 <string name="loader_error_encrypted_roms_description"><![CDATA[è«‹ä¾å¾ªæŒ‡å—釿–°å‚¾å°æ‚¨çš„<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards\">éŠæˆ²å¡åŒ£</a>或<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop\">已安è£çš„éŠæˆ²</a>。]]></string>
256 <string name="loader_error_encrypted_keys_description"><![CDATA[è«‹ç¢ºä¿æ‚¨çš„ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 檔案已安è£ï¼Œè®“éŠæˆ²å¯ä»¥è§£å¯†ã€‚]]></string> 353 <string name="loader_error_encrypted_keys_description"><![CDATA[è«‹ç¢ºä¿æ‚¨çš„ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 檔案已安è£ï¼Œè®“éŠæˆ²å¯ä»¥è§£å¯†ã€‚]]></string>
257 <string name="loader_error_video_core">åˆå§‹åŒ–視訊核心時發生錯誤</string> 354 <string name="loader_error_video_core">åˆå§‹åŒ–視訊核心時發生錯誤</string>
258 <string name="loader_error_video_core_description">這經常由ä¸ç›¸å®¹çš„ GPU 驅動程å¼é€ æˆï¼Œå®‰è£è‡ªè¨‚ GPU 驅動程å¼å¯èƒ½æœƒè§£æ±ºæ­¤å•題。</string> 355 <string name="loader_error_video_core_description">這經常由ä¸ç›¸å®¹çš„ GPU 驅動程å¼é€ æˆï¼Œå®‰è£è‡ªè¨‚ GPU 驅動程å¼å¯èƒ½æœƒè§£æ±ºæ­¤å•題。</string>
@@ -277,6 +374,7 @@
277 <string name="emulation_pause">æš«åœæ¨¡æ“¬</string> 374 <string name="emulation_pause">æš«åœæ¨¡æ“¬</string>
278 <string name="emulation_unpause">å–æ¶ˆæš«åœæ¨¡æ“¬</string> 375 <string name="emulation_unpause">å–æ¶ˆæš«åœæ¨¡æ“¬</string>
279 <string name="emulation_input_overlay">覆疊é¸é …</string> 376 <string name="emulation_input_overlay">覆疊é¸é …</string>
377 <string name="touchscreen">觸控螢幕</string>
280 378
281 <string name="load_settings">正在載入設定…</string> 379 <string name="load_settings">正在載入設定…</string>
282 380
@@ -293,9 +391,9 @@
293 <string name="fatal_error">åš´é‡éŒ¯èª¤</string> 391 <string name="fatal_error">åš´é‡éŒ¯èª¤</string>
294 <string name="fatal_error_message">發生嚴é‡éŒ¯èª¤ï¼Œæª¢æŸ¥è¨˜éŒ„以å–得詳細資訊。\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string> 392 <string name="fatal_error_message">發生嚴é‡éŒ¯èª¤ï¼Œæª¢æŸ¥è¨˜éŒ„以å–得詳細資訊。\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string>
295 <string name="performance_warning">關閉此設定會顯著é™ä½Žæ¨¡æ“¬æ•ˆèƒ½ï¼å¦‚éœ€æœ€ä½³é«”é©—ï¼Œå»ºè­°æ‚¨å°‡æ­¤è¨­å®šä¿æŒç‚ºå•Ÿç”¨ç‹€æ…‹ã€‚</string> 393 <string name="performance_warning">關閉此設定會顯著é™ä½Žæ¨¡æ“¬æ•ˆèƒ½ï¼å¦‚éœ€æœ€ä½³é«”é©—ï¼Œå»ºè­°æ‚¨å°‡æ­¤è¨­å®šä¿æŒç‚ºå•Ÿç”¨ç‹€æ…‹ã€‚</string>
296 <string name="device_memory_inadequate">设备 RAM: %1$s\n推è RAM: %2$s</string> 394 <string name="device_memory_inadequate">è£ç½® RAM: %1$s\n建議 RAM: %2$s</string>
297 <string name="memory_formatted">%1$s%2$s</string> 395 <string name="memory_formatted">%1$s%2$s</string>
298 <string name="no_game_present">当剿²¡æœ‰å¯å¯åŠ¨çš„æ¸¸æˆï¼</string> 396 <string name="no_game_present">ç›®å‰æ²æœ‰å¯å•Ÿå‹•çš„éŠæˆ²ï¼</string>
299 397
300 <!-- Region Names --> 398 <!-- Region Names -->
301 <string name="region_japan">日本</string> 399 <string name="region_japan">日本</string>
@@ -308,9 +406,10 @@
308 406
309 <!-- Memory Sizes --> 407 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string> 408 <string name="memory_byte">Byte</string>
409 <string name="memory_byte_shorthand">B</string>
311 <string name="memory_kilobyte">KB</string> 410 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string> 411 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">英國</string> 412 <string name="memory_gigabyte">GB</string>
314 <string name="memory_terabyte">TB</string> 413 <string name="memory_terabyte">TB</string>
315 <string name="memory_petabyte">PB</string> 414 <string name="memory_petabyte">PB</string>
316 <string name="memory_exabyte">EB</string> 415 <string name="memory_exabyte">EB</string>
@@ -352,9 +451,13 @@
352 <string name="anti_aliasing_smaa">SMAA</string> 451 <string name="anti_aliasing_smaa">SMAA</string>
353 452
354 <!-- Screen Layouts --> 453 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">横å‘大å±</string>
356 <string name="screen_layout_portrait">纵å‘å±å¹•</string>
357 <string name="screen_layout_auto">自動</string> 454 <string name="screen_layout_auto">自動</string>
455 <string name="screen_layout_sensor_landscape">感應器橫å‘螢幕</string>
456 <string name="screen_layout_landscape">æ©«å‘</string>
457 <string name="screen_layout_reverse_landscape">å轉橫å‘螢幕</string>
458 <string name="screen_layout_sensor_portrait">感應器直å‘螢幕</string>
459 <string name="screen_layout_portrait">ç›´å‘</string>
460 <string name="screen_layout_reverse_portrait">å轉直å‘螢幕</string>
358 461
359 <!-- Aspect Ratios --> 462 <!-- Aspect Ratios -->
360 <string name="ratio_default">é è¨­ (16:9)</string> 463 <string name="ratio_default">é è¨­ (16:9)</string>
@@ -363,6 +466,10 @@
363 <string name="ratio_force_sixteen_ten">強制 16:10</string> 466 <string name="ratio_force_sixteen_ten">強制 16:10</string>
364 <string name="ratio_stretch">延展視窗</string> 467 <string name="ratio_stretch">延展視窗</string>
365 468
469 <!-- CPU Backend -->
470 <string name="cpu_backend_dynarmic">å‹•æ…‹ (æ…¢)</string>
471 <string name="cpu_backend_nce">機器碼執行 (NCE)</string>
472
366 <!-- CPU Accuracy --> 473 <!-- CPU Accuracy -->
367 <string name="cpu_accuracy_accurate">高精度</string> 474 <string name="cpu_accuracy_accurate">高精度</string>
368 <string name="cpu_accuracy_unsafe">低精度</string> 475 <string name="cpu_accuracy_unsafe">低精度</string>
@@ -391,17 +498,24 @@
391 <string name="theme_mode_dark">深色</string> 498 <string name="theme_mode_dark">深色</string>
392 499
393 <!-- Audio output engines --> 500 <!-- Audio output engines -->
501 <string name="oboe">oboe</string>
394 <string name="cubeb">cubeb</string> 502 <string name="cubeb">cubeb</string>
395 503
504 <!-- Anisotropic filtering options -->
505 <string name="multiplier_two">2x</string>
506 <string name="multiplier_four">4x</string>
507 <string name="multiplier_eight">8x</string>
508 <string name="multiplier_sixteen">16x</string>
509
396 <!-- Black backgrounds theme --> 510 <!-- Black backgrounds theme -->
397 <string name="use_black_backgrounds">黑色背景</string> 511 <string name="use_black_backgrounds">黑色背景</string>
398 <string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string> 512 <string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string>
399 513
400 <!-- Picture-In-Picture --> 514 <!-- Picture-In-Picture -->
401 <string name="picture_in_picture">画中画</string> 515 <string name="picture_in_picture">å­æ¯ç•«é¢</string>
402 <string name="picture_in_picture_description">模拟器ä½äºŽåŽå°æ—¶æœ€å°åŒ–窗å£</string> 516 <string name="picture_in_picture_description">使–¼èƒŒæ™¯æ™‚最å°åŒ–視窗</string>
403 <string name="pause">æšåœ</string> 517 <string name="pause">æš«åœ</string>
404 <string name="play">开始</string> 518 <string name="play">開始</string>
405 <string name="mute">éœéŸ³</string> 519 <string name="mute">éœéŸ³</string>
406 <string name="unmute">å–æ¶ˆéœéŸ³</string> 520 <string name="unmute">å–æ¶ˆéœéŸ³</string>
407 521
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 547752bda..779eb36a8 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -142,6 +142,8 @@
142 <item quantity="other">Successfully imported %d saves</item> 142 <item quantity="other">Successfully imported %d saves</item>
143 </plurals> 143 </plurals>
144 <string name="no_save_data_found">No save data found</string> 144 <string name="no_save_data_found">No save data found</string>
145 <string name="verify_installed_content">Verify installed content</string>
146 <string name="verify_installed_content_description">Checks all installed content for corruption</string>
145 147
146 <!-- Applet launcher strings --> 148 <!-- Applet launcher strings -->
147 <string name="applets">Applet launcher</string> 149 <string name="applets">Applet launcher</string>
@@ -286,6 +288,9 @@
286 <string name="custom">Custom</string> 288 <string name="custom">Custom</string>
287 <string name="notice">Notice</string> 289 <string name="notice">Notice</string>
288 <string name="import_complete">Import complete</string> 290 <string name="import_complete">Import complete</string>
291 <string name="more_options">More options</string>
292 <string name="use_global_setting">Use global setting</string>
293 <string name="operation_completed_successfully">The operation completed successfully</string>
289 294
290 <!-- GPU driver installation --> 295 <!-- GPU driver installation -->
291 <string name="select_gpu_driver">Select GPU driver</string> 296 <string name="select_gpu_driver">Select GPU driver</string>
@@ -348,6 +353,16 @@
348 <string name="verifying_content">Verifying content…</string> 353 <string name="verifying_content">Verifying content…</string>
349 <string name="content_install_notice">Content install notice</string> 354 <string name="content_install_notice">Content install notice</string>
350 <string name="content_install_notice_description">The content that you selected does not match this game.\nInstall anyway?</string> 355 <string name="content_install_notice_description">The content that you selected does not match this game.\nInstall anyway?</string>
356 <string name="confirm_uninstall">Confirm uninstall</string>
357 <string name="confirm_uninstall_description">Are you sure you want to uninstall this addon?</string>
358 <string name="verify_integrity">Verify integrity</string>
359 <string name="verifying">Verifying…</string>
360 <string name="verify_success">Integrity verification succeeded!</string>
361 <string name="verify_failure">Integrity verification failed!</string>
362 <string name="verify_failure_description">File contents may be corrupt</string>
363 <string name="verify_no_result">Integrity verification couldn\'t be performed</string>
364 <string name="verify_no_result_description">File contents were not checked for validity</string>
365 <string name="verification_failed_for">Verification failed for the following files:\n%1$s</string>
351 366
352 <!-- ROM loading errors --> 367 <!-- ROM loading errors -->
353 <string name="loader_error_encrypted">Your ROM is encrypted</string> 368 <string name="loader_error_encrypted">Your ROM is encrypted</string>
@@ -377,6 +392,8 @@
377 <string name="emulation_unpause">Unpause emulation</string> 392 <string name="emulation_unpause">Unpause emulation</string>
378 <string name="emulation_input_overlay">Overlay options</string> 393 <string name="emulation_input_overlay">Overlay options</string>
379 <string name="touchscreen">Touchscreen</string> 394 <string name="touchscreen">Touchscreen</string>
395 <string name="lock_drawer">Lock drawer</string>
396 <string name="unlock_drawer">Unlock drawer</string>
380 397
381 <string name="load_settings">Loading settings…</string> 398 <string name="load_settings">Loading settings…</string>
382 399
diff --git a/src/audio_core/device/device_session.cpp b/src/audio_core/device/device_session.cpp
index 3c214ec00..2a1ae1bb3 100644
--- a/src/audio_core/device/device_session.cpp
+++ b/src/audio_core/device/device_session.cpp
@@ -8,6 +8,7 @@
8#include "audio_core/sink/sink_stream.h" 8#include "audio_core/sink/sink_stream.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/core_timing.h" 10#include "core/core_timing.h"
11#include "core/guest_memory.h"
11#include "core/memory.h" 12#include "core/memory.h"
12 13
13#include "core/hle/kernel/k_process.h" 14#include "core/hle/kernel/k_process.h"
diff --git a/src/audio_core/renderer/command/data_source/decode.cpp b/src/audio_core/renderer/command/data_source/decode.cpp
index 911dae3c1..905613a5a 100644
--- a/src/audio_core/renderer/command/data_source/decode.cpp
+++ b/src/audio_core/renderer/command/data_source/decode.cpp
@@ -9,6 +9,7 @@
9#include "common/fixed_point.h" 9#include "common/fixed_point.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/scratch_buffer.h" 11#include "common/scratch_buffer.h"
12#include "core/guest_memory.h"
12#include "core/memory.h" 13#include "core/memory.h"
13 14
14namespace AudioCore::Renderer { 15namespace AudioCore::Renderer {
diff --git a/src/common/common_types.h b/src/common/common_types.h
index 0fc225aff..ae04c4d60 100644
--- a/src/common/common_types.h
+++ b/src/common/common_types.h
@@ -45,6 +45,7 @@ using f32 = float; ///< 32-bit floating point
45using f64 = double; ///< 64-bit floating point 45using f64 = double; ///< 64-bit floating point
46 46
47using VAddr = u64; ///< Represents a pointer in the userspace virtual address space. 47using VAddr = u64; ///< Represents a pointer in the userspace virtual address space.
48using DAddr = u64; ///< Represents a pointer in the device specific virtual address space.
48using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space. 49using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space.
49using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space. 50using GPUVAddr = u64; ///< Represents a pointer in the GPU virtual address space.
50 51
diff --git a/src/common/fs/file.h b/src/common/fs/file.h
index 167c4d826..2e2396075 100644
--- a/src/common/fs/file.h
+++ b/src/common/fs/file.h
@@ -37,7 +37,7 @@ void OpenFileStream(FileStream& file_stream, const std::filesystem::path& path,
37template <typename FileStream, typename Path> 37template <typename FileStream, typename Path>
38void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::openmode open_mode) { 38void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::openmode open_mode) {
39 if constexpr (IsChar<typename Path::value_type>) { 39 if constexpr (IsChar<typename Path::value_type>) {
40 file_stream.open(ToU8String(path), open_mode); 40 file_stream.open(std::filesystem::path{ToU8String(path)}, open_mode);
41 } else { 41 } else {
42 file_stream.open(std::filesystem::path{path}, open_mode); 42 file_stream.open(std::filesystem::path{path}, open_mode);
43 } 43 }
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index a630c257f..f75b5e10a 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -37,6 +37,8 @@ add_library(core STATIC
37 debugger/gdbstub_arch.h 37 debugger/gdbstub_arch.h
38 debugger/gdbstub.cpp 38 debugger/gdbstub.cpp
39 debugger/gdbstub.h 39 debugger/gdbstub.h
40 device_memory_manager.h
41 device_memory_manager.inc
40 device_memory.cpp 42 device_memory.cpp
41 device_memory.h 43 device_memory.h
42 file_sys/fssystem/fs_i_storage.h 44 file_sys/fssystem/fs_i_storage.h
@@ -627,6 +629,8 @@ add_library(core STATIC
627 hle/service/ns/pdm_qry.h 629 hle/service/ns/pdm_qry.h
628 hle/service/nvdrv/core/container.cpp 630 hle/service/nvdrv/core/container.cpp
629 hle/service/nvdrv/core/container.h 631 hle/service/nvdrv/core/container.h
632 hle/service/nvdrv/core/heap_mapper.cpp
633 hle/service/nvdrv/core/heap_mapper.h
630 hle/service/nvdrv/core/nvmap.cpp 634 hle/service/nvdrv/core/nvmap.cpp
631 hle/service/nvdrv/core/nvmap.h 635 hle/service/nvdrv/core/nvmap.h
632 hle/service/nvdrv/core/syncpoint_manager.cpp 636 hle/service/nvdrv/core/syncpoint_manager.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 33afc6049..dd9de948c 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -28,6 +28,7 @@
28#include "core/file_sys/savedata_factory.h" 28#include "core/file_sys/savedata_factory.h"
29#include "core/file_sys/vfs_concat.h" 29#include "core/file_sys/vfs_concat.h"
30#include "core/file_sys/vfs_real.h" 30#include "core/file_sys/vfs_real.h"
31#include "core/gpu_dirty_memory_manager.h"
31#include "core/hle/kernel/k_memory_manager.h" 32#include "core/hle/kernel/k_memory_manager.h"
32#include "core/hle/kernel/k_process.h" 33#include "core/hle/kernel/k_process.h"
33#include "core/hle/kernel/k_resource_limit.h" 34#include "core/hle/kernel/k_resource_limit.h"
@@ -606,6 +607,9 @@ struct System::Impl {
606 std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; 607 std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
607 std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; 608 std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
608 609
610 std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES>
611 gpu_dirty_memory_managers;
612
609 std::deque<std::vector<u8>> user_channel; 613 std::deque<std::vector<u8>> user_channel;
610}; 614};
611 615
@@ -692,8 +696,14 @@ size_t System::GetCurrentHostThreadID() const {
692 return impl->kernel.GetCurrentHostThreadID(); 696 return impl->kernel.GetCurrentHostThreadID();
693} 697}
694 698
695void System::GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback) { 699std::span<GPUDirtyMemoryManager> System::GetGPUDirtyMemoryManager() {
696 return this->ApplicationProcess()->GatherGPUDirtyMemory(callback); 700 return impl->gpu_dirty_memory_managers;
701}
702
703void System::GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback) {
704 for (auto& manager : impl->gpu_dirty_memory_managers) {
705 manager.Gather(callback);
706 }
697} 707}
698 708
699PerfStatsResults System::GetAndResetPerfStats() { 709PerfStatsResults System::GetAndResetPerfStats() {
diff --git a/src/core/core.h b/src/core/core.h
index 7d49e5028..183410602 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -8,6 +8,7 @@
8#include <functional> 8#include <functional>
9#include <memory> 9#include <memory>
10#include <mutex> 10#include <mutex>
11#include <span>
11#include <string> 12#include <string>
12#include <vector> 13#include <vector>
13 14
@@ -112,6 +113,7 @@ class CpuManager;
112class Debugger; 113class Debugger;
113class DeviceMemory; 114class DeviceMemory;
114class ExclusiveMonitor; 115class ExclusiveMonitor;
116class GPUDirtyMemoryManager;
115class PerfStats; 117class PerfStats;
116class Reporter; 118class Reporter;
117class SpeedLimiter; 119class SpeedLimiter;
@@ -220,7 +222,9 @@ public:
220 /// Prepare the core emulation for a reschedule 222 /// Prepare the core emulation for a reschedule
221 void PrepareReschedule(u32 core_index); 223 void PrepareReschedule(u32 core_index);
222 224
223 void GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback); 225 std::span<GPUDirtyMemoryManager> GetGPUDirtyMemoryManager();
226
227 void GatherGPUDirtyMemory(std::function<void(PAddr, size_t)>& callback);
224 228
225 [[nodiscard]] size_t GetCurrentHostThreadID() const; 229 [[nodiscard]] size_t GetCurrentHostThreadID() const;
226 230
diff --git a/src/core/device_memory.h b/src/core/device_memory.h
index 13388b73e..11bf0e326 100644
--- a/src/core/device_memory.h
+++ b/src/core/device_memory.h
@@ -32,6 +32,12 @@ public:
32 } 32 }
33 33
34 template <typename T> 34 template <typename T>
35 PAddr GetRawPhysicalAddr(const T* ptr) const {
36 return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) -
37 reinterpret_cast<uintptr_t>(buffer.BackingBasePointer()));
38 }
39
40 template <typename T>
35 T* GetPointer(Common::PhysicalAddress addr) { 41 T* GetPointer(Common::PhysicalAddress addr) {
36 return reinterpret_cast<T*>(buffer.BackingBasePointer() + 42 return reinterpret_cast<T*>(buffer.BackingBasePointer() +
37 (GetInteger(addr) - DramMemoryMap::Base)); 43 (GetInteger(addr) - DramMemoryMap::Base));
@@ -43,6 +49,16 @@ public:
43 (GetInteger(addr) - DramMemoryMap::Base)); 49 (GetInteger(addr) - DramMemoryMap::Base));
44 } 50 }
45 51
52 template <typename T>
53 T* GetPointerFromRaw(PAddr addr) {
54 return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr);
55 }
56
57 template <typename T>
58 const T* GetPointerFromRaw(PAddr addr) const {
59 return reinterpret_cast<T*>(buffer.BackingBasePointer() + addr);
60 }
61
46 Common::HostMemory buffer; 62 Common::HostMemory buffer;
47}; 63};
48 64
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h
new file mode 100644
index 000000000..ffeed46cc
--- /dev/null
+++ b/src/core/device_memory_manager.h
@@ -0,0 +1,211 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <atomic>
8#include <deque>
9#include <memory>
10#include <mutex>
11
12#include "common/common_types.h"
13#include "common/scratch_buffer.h"
14#include "common/virtual_buffer.h"
15
16namespace Core {
17
18constexpr size_t DEVICE_PAGEBITS = 12ULL;
19constexpr size_t DEVICE_PAGESIZE = 1ULL << DEVICE_PAGEBITS;
20constexpr size_t DEVICE_PAGEMASK = DEVICE_PAGESIZE - 1ULL;
21
22class DeviceMemory;
23
24namespace Memory {
25class Memory;
26}
27
28template <typename DTraits>
29struct DeviceMemoryManagerAllocator;
30
31struct Asid {
32 size_t id;
33};
34
35template <typename Traits>
36class DeviceMemoryManager {
37 using DeviceInterface = typename Traits::DeviceInterface;
38 using DeviceMethods = typename Traits::DeviceMethods;
39
40public:
41 DeviceMemoryManager(const DeviceMemory& device_memory);
42 ~DeviceMemoryManager();
43
44 void BindInterface(DeviceInterface* device_inter);
45
46 DAddr Allocate(size_t size);
47 void AllocateFixed(DAddr start, size_t size);
48 void Free(DAddr start, size_t size);
49
50 void Map(DAddr address, VAddr virtual_address, size_t size, Asid asid, bool track = false);
51
52 void Unmap(DAddr address, size_t size);
53
54 void TrackContinuityImpl(DAddr address, VAddr virtual_address, size_t size, Asid asid);
55 void TrackContinuity(DAddr address, VAddr virtual_address, size_t size, Asid asid) {
56 std::scoped_lock lk(mapping_guard);
57 TrackContinuityImpl(address, virtual_address, size, asid);
58 }
59
60 // Write / Read
61 template <typename T>
62 T* GetPointer(DAddr address);
63
64 template <typename T>
65 const T* GetPointer(DAddr address) const;
66
67 template <typename Func>
68 void ApplyOpOnPAddr(PAddr address, Common::ScratchBuffer<u32>& buffer, Func&& operation) {
69 DAddr subbits = static_cast<DAddr>(address & page_mask);
70 const u32 base = compressed_device_addr[(address >> page_bits)];
71 if ((base >> MULTI_FLAG_BITS) == 0) [[likely]] {
72 const DAddr d_address = (static_cast<DAddr>(base) << page_bits) + subbits;
73 operation(d_address);
74 return;
75 }
76 InnerGatherDeviceAddresses(buffer, address);
77 for (u32 value : buffer) {
78 operation((static_cast<DAddr>(value) << page_bits) + subbits);
79 }
80 }
81
82 template <typename Func>
83 void ApplyOpOnPointer(const u8* p, Common::ScratchBuffer<u32>& buffer, Func&& operation) {
84 PAddr address = GetRawPhysicalAddr<u8>(p);
85 ApplyOpOnPAddr(address, buffer, operation);
86 }
87
88 PAddr GetPhysicalRawAddressFromDAddr(DAddr address) const {
89 PAddr subbits = static_cast<PAddr>(address & page_mask);
90 auto paddr = compressed_physical_ptr[(address >> page_bits)];
91 if (paddr == 0) {
92 return 0;
93 }
94 return (static_cast<PAddr>(paddr - 1) << page_bits) + subbits;
95 }
96
97 template <typename T>
98 void Write(DAddr address, T value);
99
100 template <typename T>
101 T Read(DAddr address) const;
102
103 u8* GetSpan(const DAddr src_addr, const std::size_t size);
104 const u8* GetSpan(const DAddr src_addr, const std::size_t size) const;
105
106 void ReadBlock(DAddr address, void* dest_pointer, size_t size);
107 void ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size);
108 void WriteBlock(DAddr address, const void* src_pointer, size_t size);
109 void WriteBlockUnsafe(DAddr address, const void* src_pointer, size_t size);
110
111 Asid RegisterProcess(Memory::Memory* memory);
112 void UnregisterProcess(Asid id);
113
114 void UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta);
115
116 static constexpr size_t AS_BITS = Traits::device_virtual_bits;
117
118private:
119 static constexpr size_t device_virtual_bits = Traits::device_virtual_bits;
120 static constexpr size_t device_as_size = 1ULL << device_virtual_bits;
121 static constexpr size_t physical_min_bits = 32;
122 static constexpr size_t physical_max_bits = 33;
123 static constexpr size_t page_bits = 12;
124 static constexpr size_t page_size = 1ULL << page_bits;
125 static constexpr size_t page_mask = page_size - 1ULL;
126 static constexpr u32 physical_address_base = 1U << page_bits;
127 static constexpr u32 MULTI_FLAG_BITS = 31;
128 static constexpr u32 MULTI_FLAG = 1U << MULTI_FLAG_BITS;
129 static constexpr u32 MULTI_MASK = ~MULTI_FLAG;
130
131 template <typename T>
132 T* GetPointerFromRaw(PAddr addr) {
133 return reinterpret_cast<T*>(physical_base + addr);
134 }
135
136 template <typename T>
137 const T* GetPointerFromRaw(PAddr addr) const {
138 return reinterpret_cast<T*>(physical_base + addr);
139 }
140
141 template <typename T>
142 PAddr GetRawPhysicalAddr(const T* ptr) const {
143 return static_cast<PAddr>(reinterpret_cast<uintptr_t>(ptr) - physical_base);
144 }
145
146 void WalkBlock(const DAddr addr, const std::size_t size, auto on_unmapped, auto on_memory,
147 auto increment);
148
149 void InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer, PAddr address);
150
151 std::unique_ptr<DeviceMemoryManagerAllocator<Traits>> impl;
152
153 const uintptr_t physical_base;
154 DeviceInterface* device_inter;
155 Common::VirtualBuffer<u32> compressed_physical_ptr;
156 Common::VirtualBuffer<u32> compressed_device_addr;
157 Common::VirtualBuffer<u32> continuity_tracker;
158
159 // Process memory interfaces
160
161 std::deque<size_t> id_pool;
162 std::deque<Memory::Memory*> registered_processes;
163
164 // Memory protection management
165
166 static constexpr size_t guest_max_as_bits = 39;
167 static constexpr size_t guest_as_size = 1ULL << guest_max_as_bits;
168 static constexpr size_t guest_mask = guest_as_size - 1ULL;
169 static constexpr size_t asid_start_bit = guest_max_as_bits;
170
171 std::pair<Asid, VAddr> ExtractCPUBacking(size_t page_index) {
172 auto content = cpu_backing_address[page_index];
173 const VAddr address = content & guest_mask;
174 const Asid asid{static_cast<size_t>(content >> asid_start_bit)};
175 return std::make_pair(asid, address);
176 }
177
178 void InsertCPUBacking(size_t page_index, VAddr address, Asid asid) {
179 cpu_backing_address[page_index] = address | (asid.id << asid_start_bit);
180 }
181
182 Common::VirtualBuffer<VAddr> cpu_backing_address;
183 static constexpr size_t subentries = 8 / sizeof(u8);
184 static constexpr size_t subentries_mask = subentries - 1;
185 class CounterEntry final {
186 public:
187 CounterEntry() = default;
188
189 std::atomic_uint8_t& Count(std::size_t page) {
190 return values[page & subentries_mask];
191 }
192
193 const std::atomic_uint8_t& Count(std::size_t page) const {
194 return values[page & subentries_mask];
195 }
196
197 private:
198 std::array<std::atomic_uint8_t, subentries> values{};
199 };
200 static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
201 "CounterEntry should be 8 bytes!");
202
203 static constexpr size_t num_counter_entries =
204 (1ULL << (device_virtual_bits - page_bits)) / subentries;
205 using CachedPages = std::array<CounterEntry, num_counter_entries>;
206 std::unique_ptr<CachedPages> cached_pages;
207 std::mutex counter_guard;
208 std::mutex mapping_guard;
209};
210
211} // namespace Core
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc
new file mode 100644
index 000000000..eab8a2731
--- /dev/null
+++ b/src/core/device_memory_manager.inc
@@ -0,0 +1,581 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <atomic>
5#include <limits>
6#include <memory>
7#include <type_traits>
8
9#include "common/address_space.h"
10#include "common/address_space.inc"
11#include "common/alignment.h"
12#include "common/assert.h"
13#include "common/div_ceil.h"
14#include "common/scope_exit.h"
15#include "common/settings.h"
16#include "core/device_memory.h"
17#include "core/device_memory_manager.h"
18#include "core/memory.h"
19
20namespace Core {
21
22namespace {
23
24class MultiAddressContainer {
25public:
26 MultiAddressContainer() = default;
27 ~MultiAddressContainer() = default;
28
29 void GatherValues(u32 start_entry, Common::ScratchBuffer<u32>& buffer) {
30 buffer.resize(8);
31 buffer.resize(0);
32 size_t index = 0;
33 const auto add_value = [&](u32 value) {
34 buffer.resize(index + 1);
35 buffer[index++] = value;
36 };
37
38 u32 iter_entry = start_entry;
39 Entry* current = &storage[iter_entry - 1];
40 add_value(current->value);
41 while (current->next_entry != 0) {
42 iter_entry = current->next_entry;
43 current = &storage[iter_entry - 1];
44 add_value(current->value);
45 }
46 }
47
48 u32 Register(u32 value) {
49 return RegisterImplementation(value);
50 }
51
52 void Register(u32 value, u32 start_entry) {
53 auto entry_id = RegisterImplementation(value);
54 u32 iter_entry = start_entry;
55 Entry* current = &storage[iter_entry - 1];
56 while (current->next_entry != 0) {
57 iter_entry = current->next_entry;
58 current = &storage[iter_entry - 1];
59 }
60 current->next_entry = entry_id;
61 }
62
63 std::pair<bool, u32> Unregister(u32 value, u32 start_entry) {
64 u32 iter_entry = start_entry;
65 Entry* previous{};
66 Entry* current = &storage[iter_entry - 1];
67 Entry* next{};
68 bool more_than_one_remaining = false;
69 u32 result_start{start_entry};
70 size_t count = 0;
71 while (current->value != value) {
72 count++;
73 previous = current;
74 iter_entry = current->next_entry;
75 current = &storage[iter_entry - 1];
76 }
77 // Find next
78 u32 next_entry = current->next_entry;
79 if (next_entry != 0) {
80 next = &storage[next_entry - 1];
81 more_than_one_remaining = next->next_entry != 0 || previous != nullptr;
82 }
83 if (previous) {
84 previous->next_entry = next_entry;
85 } else {
86 result_start = next_entry;
87 }
88 free_entries.emplace_back(iter_entry);
89 return std::make_pair(more_than_one_remaining || count > 1, result_start);
90 }
91
92 u32 ReleaseEntry(u32 start_entry) {
93 Entry* current = &storage[start_entry - 1];
94 free_entries.emplace_back(start_entry);
95 return current->value;
96 }
97
98private:
99 u32 RegisterImplementation(u32 value) {
100 auto entry_id = GetNewEntry();
101 auto& entry = storage[entry_id - 1];
102 entry.next_entry = 0;
103 entry.value = value;
104 return entry_id;
105 }
106 u32 GetNewEntry() {
107 if (!free_entries.empty()) {
108 u32 result = free_entries.front();
109 free_entries.pop_front();
110 return result;
111 }
112 storage.emplace_back();
113 u32 new_entry = static_cast<u32>(storage.size());
114 return new_entry;
115 }
116
117 struct Entry {
118 u32 next_entry{};
119 u32 value{};
120 };
121
122 std::deque<Entry> storage;
123 std::deque<u32> free_entries;
124};
125
126struct EmptyAllocator {
127 EmptyAllocator([[maybe_unused]] DAddr address) {}
128};
129
130} // namespace
131
132template <typename DTraits>
133struct DeviceMemoryManagerAllocator {
134 static constexpr size_t device_virtual_bits = DTraits::device_virtual_bits;
135 static constexpr DAddr first_address = 1ULL << Memory::YUZU_PAGEBITS;
136 static constexpr DAddr max_device_area = 1ULL << device_virtual_bits;
137
138 DeviceMemoryManagerAllocator() : main_allocator(first_address) {}
139
140 Common::FlatAllocator<DAddr, 0, device_virtual_bits> main_allocator;
141 MultiAddressContainer multi_dev_address;
142
143 /// Returns true when vaddr -> vaddr+size is fully contained in the buffer
144 template <bool pin_area>
145 [[nodiscard]] bool IsInBounds(VAddr addr, u64 size) const noexcept {
146 return addr >= 0 && addr + size <= max_device_area;
147 }
148
149 DAddr Allocate(size_t size) {
150 return main_allocator.Allocate(size);
151 }
152
153 void AllocateFixed(DAddr b_address, size_t b_size) {
154 main_allocator.AllocateFixed(b_address, b_size);
155 }
156
157 void Free(DAddr b_address, size_t b_size) {
158 main_allocator.Free(b_address, b_size);
159 }
160};
161
162template <typename Traits>
163DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_)
164 : physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())},
165 device_inter{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS),
166 compressed_device_addr(1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
167 Settings::MemoryLayout::Memory_4Gb
168 ? physical_min_bits
169 : physical_max_bits) -
170 Memory::YUZU_PAGEBITS)),
171 continuity_tracker(device_as_size >> Memory::YUZU_PAGEBITS),
172 cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) {
173 impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>();
174 cached_pages = std::make_unique<CachedPages>();
175
176 const size_t total_virtual = device_as_size >> Memory::YUZU_PAGEBITS;
177 for (size_t i = 0; i < total_virtual; i++) {
178 compressed_physical_ptr[i] = 0;
179 continuity_tracker[i] = 1;
180 cpu_backing_address[i] = 0;
181 }
182 const size_t total_phys = 1ULL << ((Settings::values.memory_layout_mode.GetValue() ==
183 Settings::MemoryLayout::Memory_4Gb
184 ? physical_min_bits
185 : physical_max_bits) -
186 Memory::YUZU_PAGEBITS);
187 for (size_t i = 0; i < total_phys; i++) {
188 compressed_device_addr[i] = 0;
189 }
190}
191
192template <typename Traits>
193DeviceMemoryManager<Traits>::~DeviceMemoryManager() = default;
194
195template <typename Traits>
196void DeviceMemoryManager<Traits>::BindInterface(DeviceInterface* device_inter_) {
197 device_inter = device_inter_;
198}
199
200template <typename Traits>
201DAddr DeviceMemoryManager<Traits>::Allocate(size_t size) {
202 return impl->Allocate(size);
203}
204
205template <typename Traits>
206void DeviceMemoryManager<Traits>::AllocateFixed(DAddr start, size_t size) {
207 return impl->AllocateFixed(start, size);
208}
209
210template <typename Traits>
211void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
212 impl->Free(start, size);
213}
214
215template <typename Traits>
216void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
217 Asid asid, bool track) {
218 Core::Memory::Memory* process_memory = registered_processes[asid.id];
219 size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
220 size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
221 std::scoped_lock lk(mapping_guard);
222 for (size_t i = 0; i < num_pages; i++) {
223 const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE;
224 auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress));
225 if (ptr == nullptr) [[unlikely]] {
226 compressed_physical_ptr[start_page_d + i] = 0;
227 continue;
228 }
229 auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U;
230 compressed_physical_ptr[start_page_d + i] = phys_addr;
231 InsertCPUBacking(start_page_d + i, new_vaddress, asid);
232 const u32 base_dev = compressed_device_addr[phys_addr - 1U];
233 const u32 new_dev = static_cast<u32>(start_page_d + i);
234 if (base_dev == 0) [[likely]] {
235 compressed_device_addr[phys_addr - 1U] = new_dev;
236 continue;
237 }
238 u32 start_id = base_dev & MULTI_MASK;
239 if ((base_dev >> MULTI_FLAG_BITS) == 0) {
240 start_id = impl->multi_dev_address.Register(base_dev);
241 compressed_device_addr[phys_addr - 1U] = MULTI_FLAG | start_id;
242 }
243 impl->multi_dev_address.Register(new_dev, start_id);
244 }
245 if (track) {
246 TrackContinuityImpl(address, virtual_address, size, asid);
247 }
248}
249
250template <typename Traits>
251void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
252 size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
253 size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
254 device_inter->InvalidateRegion(address, size);
255 std::scoped_lock lk(mapping_guard);
256 for (size_t i = 0; i < num_pages; i++) {
257 auto phys_addr = compressed_physical_ptr[start_page_d + i];
258 compressed_physical_ptr[start_page_d + i] = 0;
259 cpu_backing_address[start_page_d + i] = 0;
260 if (phys_addr != 0) [[likely]] {
261 const u32 base_dev = compressed_device_addr[phys_addr - 1U];
262 if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] {
263 compressed_device_addr[phys_addr - 1] = 0;
264 continue;
265 }
266 const auto [more_entries, new_start] = impl->multi_dev_address.Unregister(
267 static_cast<u32>(start_page_d + i), base_dev & MULTI_MASK);
268 if (!more_entries) {
269 compressed_device_addr[phys_addr - 1] =
270 impl->multi_dev_address.ReleaseEntry(new_start);
271 continue;
272 }
273 compressed_device_addr[phys_addr - 1] = new_start | MULTI_FLAG;
274 }
275 }
276}
277template <typename Traits>
278void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address,
279 size_t size, Asid asid) {
280 Core::Memory::Memory* process_memory = registered_processes[asid.id];
281 size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
282 size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
283 uintptr_t last_ptr = 0;
284 size_t page_count = 1;
285 for (size_t i = num_pages; i > 0; i--) {
286 size_t index = i - 1;
287 const VAddr new_vaddress = virtual_address + index * Memory::YUZU_PAGESIZE;
288 const uintptr_t new_ptr = reinterpret_cast<uintptr_t>(
289 process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress)));
290 if (new_ptr + page_size == last_ptr) {
291 page_count++;
292 } else {
293 page_count = 1;
294 }
295 last_ptr = new_ptr;
296 continuity_tracker[start_page_d + index] = static_cast<u32>(page_count);
297 }
298}
299template <typename Traits>
300u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) {
301 size_t page_index = src_addr >> page_bits;
302 size_t subbits = src_addr & page_mask;
303 if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
304 return GetPointer<u8>(src_addr);
305 }
306 return nullptr;
307}
308
309template <typename Traits>
310const u8* DeviceMemoryManager<Traits>::GetSpan(const DAddr src_addr, const std::size_t size) const {
311 size_t page_index = src_addr >> page_bits;
312 size_t subbits = src_addr & page_mask;
313 if ((static_cast<size_t>(continuity_tracker[page_index]) << page_bits) >= size + subbits) {
314 return GetPointer<u8>(src_addr);
315 }
316 return nullptr;
317}
318
319template <typename Traits>
320void DeviceMemoryManager<Traits>::InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer,
321 PAddr address) {
322 size_t phys_addr = address >> page_bits;
323 std::scoped_lock lk(mapping_guard);
324 u32 backing = compressed_device_addr[phys_addr];
325 if ((backing >> MULTI_FLAG_BITS) != 0) {
326 impl->multi_dev_address.GatherValues(backing & MULTI_MASK, buffer);
327 return;
328 }
329 buffer.resize(1);
330 buffer[0] = backing;
331}
332
333template <typename Traits>
334template <typename T>
335T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) {
336 const size_t index = address >> Memory::YUZU_PAGEBITS;
337 const size_t offset = address & Memory::YUZU_PAGEMASK;
338 auto phys_addr = compressed_physical_ptr[index];
339 if (phys_addr == 0) [[unlikely]] {
340 return nullptr;
341 }
342 return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
343 offset);
344}
345
346template <typename Traits>
347template <typename T>
348const T* DeviceMemoryManager<Traits>::GetPointer(DAddr address) const {
349 const size_t index = address >> Memory::YUZU_PAGEBITS;
350 const size_t offset = address & Memory::YUZU_PAGEMASK;
351 auto phys_addr = compressed_physical_ptr[index];
352 if (phys_addr == 0) [[unlikely]] {
353 return nullptr;
354 }
355 return GetPointerFromRaw<T>((static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) +
356 offset);
357}
358
359template <typename Traits>
360template <typename T>
361void DeviceMemoryManager<Traits>::Write(DAddr address, T value) {
362 T* ptr = GetPointer<T>(address);
363 if (!ptr) [[unlikely]] {
364 return;
365 }
366 std::memcpy(ptr, &value, sizeof(T));
367}
368
369template <typename Traits>
370template <typename T>
371T DeviceMemoryManager<Traits>::Read(DAddr address) const {
372 const T* ptr = GetPointer<T>(address);
373 T result{};
374 if (!ptr) [[unlikely]] {
375 return result;
376 }
377 std::memcpy(&result, ptr, sizeof(T));
378 return result;
379}
380
381template <typename Traits>
382void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto on_unmapped,
383 auto on_memory, auto increment) {
384 std::size_t remaining_size = size;
385 std::size_t page_index = addr >> Memory::YUZU_PAGEBITS;
386 std::size_t page_offset = addr & Memory::YUZU_PAGEMASK;
387
388 while (remaining_size) {
389 const size_t next_pages = static_cast<std::size_t>(continuity_tracker[page_index]);
390 const std::size_t copy_amount =
391 std::min((next_pages << Memory::YUZU_PAGEBITS) - page_offset, remaining_size);
392 const auto current_vaddr =
393 static_cast<u64>((page_index << Memory::YUZU_PAGEBITS) + page_offset);
394 SCOPE_EXIT({
395 page_index += next_pages;
396 page_offset = 0;
397 increment(copy_amount);
398 remaining_size -= copy_amount;
399 });
400
401 auto phys_addr = compressed_physical_ptr[page_index];
402 if (phys_addr == 0) {
403 on_unmapped(copy_amount, current_vaddr);
404 continue;
405 }
406 auto* mem_ptr = GetPointerFromRaw<u8>(
407 (static_cast<PAddr>(phys_addr - 1) << Memory::YUZU_PAGEBITS) + page_offset);
408 on_memory(copy_amount, mem_ptr);
409 }
410}
411
412template <typename Traits>
413void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) {
414 device_inter->FlushRegion(address, size);
415 WalkBlock(
416 address, size,
417 [&](size_t copy_amount, DAddr current_vaddr) {
418 LOG_ERROR(
419 HW_Memory,
420 "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
421 current_vaddr, address, size);
422 std::memset(dest_pointer, 0, copy_amount);
423 },
424 [&](size_t copy_amount, const u8* const src_ptr) {
425 std::memcpy(dest_pointer, src_ptr, copy_amount);
426 },
427 [&](const std::size_t copy_amount) {
428 dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount;
429 });
430}
431
432template <typename Traits>
433void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_pointer, size_t size) {
434 WalkBlock(
435 address, size,
436 [&](size_t copy_amount, DAddr current_vaddr) {
437 LOG_ERROR(
438 HW_Memory,
439 "Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
440 current_vaddr, address, size);
441 },
442 [&](size_t copy_amount, u8* const dst_ptr) {
443 std::memcpy(dst_ptr, src_pointer, copy_amount);
444 },
445 [&](const std::size_t copy_amount) {
446 src_pointer = static_cast<const u8*>(src_pointer) + copy_amount;
447 });
448 device_inter->InvalidateRegion(address, size);
449}
450
451template <typename Traits>
452void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size) {
453 WalkBlock(
454 address, size,
455 [&](size_t copy_amount, DAddr current_vaddr) {
456 LOG_ERROR(
457 HW_Memory,
458 "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
459 current_vaddr, address, size);
460 std::memset(dest_pointer, 0, copy_amount);
461 },
462 [&](size_t copy_amount, const u8* const src_ptr) {
463 std::memcpy(dest_pointer, src_ptr, copy_amount);
464 },
465 [&](const std::size_t copy_amount) {
466 dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount;
467 });
468}
469
470template <typename Traits>
471void DeviceMemoryManager<Traits>::WriteBlockUnsafe(DAddr address, const void* src_pointer,
472 size_t size) {
473 WalkBlock(
474 address, size,
475 [&](size_t copy_amount, DAddr current_vaddr) {
476 LOG_ERROR(
477 HW_Memory,
478 "Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
479 current_vaddr, address, size);
480 },
481 [&](size_t copy_amount, u8* const dst_ptr) {
482 std::memcpy(dst_ptr, src_pointer, copy_amount);
483 },
484 [&](const std::size_t copy_amount) {
485 src_pointer = static_cast<const u8*>(src_pointer) + copy_amount;
486 });
487}
488
489template <typename Traits>
490Asid DeviceMemoryManager<Traits>::RegisterProcess(Memory::Memory* memory_device_inter) {
491 size_t new_id{};
492 if (!id_pool.empty()) {
493 new_id = id_pool.front();
494 id_pool.pop_front();
495 registered_processes[new_id] = memory_device_inter;
496 } else {
497 registered_processes.emplace_back(memory_device_inter);
498 new_id = registered_processes.size() - 1U;
499 }
500 return Asid{new_id};
501}
502
503template <typename Traits>
504void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
505 registered_processes[asid.id] = nullptr;
506 id_pool.push_front(asid.id);
507}
508
509template <typename Traits>
510void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
511 std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock);
512 const auto Lock = [&] {
513 if (!lk) {
514 lk.lock();
515 }
516 };
517 u64 uncache_begin = 0;
518 u64 cache_begin = 0;
519 u64 uncache_bytes = 0;
520 u64 cache_bytes = 0;
521 const auto MarkRegionCaching = &DeviceMemoryManager<Traits>::DeviceMethods::MarkRegionCaching;
522
523 std::atomic_thread_fence(std::memory_order_acquire);
524 const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
525 size_t page = addr >> Memory::YUZU_PAGEBITS;
526 auto [asid, base_vaddress] = ExtractCPUBacking(page);
527 size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
528 auto* memory_device_inter = registered_processes[asid.id];
529 for (; page != page_end; ++page) {
530 std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
531
532 if (delta > 0) {
533 ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
534 "Count may overflow!");
535 } else if (delta < 0) {
536 ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
537 } else {
538 ASSERT_MSG(false, "Delta must be non-zero!");
539 }
540
541 // Adds or subtracts 1, as count is a unsigned 8-bit value
542 count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
543
544 // Assume delta is either -1 or 1
545 if (count.load(std::memory_order::relaxed) == 0) {
546 if (uncache_bytes == 0) {
547 uncache_begin = vpage;
548 }
549 uncache_bytes += Memory::YUZU_PAGESIZE;
550 } else if (uncache_bytes > 0) {
551 Lock();
552 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
553 uncache_bytes, false);
554 uncache_bytes = 0;
555 }
556 if (count.load(std::memory_order::relaxed) == 1 && delta > 0) {
557 if (cache_bytes == 0) {
558 cache_begin = vpage;
559 }
560 cache_bytes += Memory::YUZU_PAGESIZE;
561 } else if (cache_bytes > 0) {
562 Lock();
563 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
564 true);
565 cache_bytes = 0;
566 }
567 vpage++;
568 }
569 if (uncache_bytes > 0) {
570 Lock();
571 MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
572 false);
573 }
574 if (cache_bytes > 0) {
575 Lock();
576 MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
577 true);
578 }
579}
580
581} // namespace Core
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 4a3dbc6a3..612122224 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -466,12 +466,12 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs
466 return romfs; 466 return romfs;
467} 467}
468 468
469PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile update_raw) const { 469std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
470 if (title_id == 0) { 470 if (title_id == 0) {
471 return {}; 471 return {};
472 } 472 }
473 473
474 std::map<std::string, std::string, std::less<>> out; 474 std::vector<Patch> out;
475 const auto& disabled = Settings::values.disabled_addons[title_id]; 475 const auto& disabled = Settings::values.disabled_addons[title_id];
476 476
477 // Game Updates 477 // Game Updates
@@ -482,20 +482,28 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
482 482
483 const auto update_disabled = 483 const auto update_disabled =
484 std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); 484 std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
485 const auto update_label = update_disabled ? "[D] Update" : "Update"; 485 Patch update_patch = {.enabled = !update_disabled,
486 .name = "Update",
487 .version = "",
488 .type = PatchType::Update,
489 .program_id = title_id,
490 .title_id = title_id};
486 491
487 if (nacp != nullptr) { 492 if (nacp != nullptr) {
488 out.insert_or_assign(update_label, nacp->GetVersionString()); 493 update_patch.version = nacp->GetVersionString();
494 out.push_back(update_patch);
489 } else { 495 } else {
490 if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { 496 if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) {
491 const auto meta_ver = content_provider.GetEntryVersion(update_tid); 497 const auto meta_ver = content_provider.GetEntryVersion(update_tid);
492 if (meta_ver.value_or(0) == 0) { 498 if (meta_ver.value_or(0) == 0) {
493 out.insert_or_assign(update_label, ""); 499 out.push_back(update_patch);
494 } else { 500 } else {
495 out.insert_or_assign(update_label, FormatTitleVersion(*meta_ver)); 501 update_patch.version = FormatTitleVersion(*meta_ver);
502 out.push_back(update_patch);
496 } 503 }
497 } else if (update_raw != nullptr) { 504 } else if (update_raw != nullptr) {
498 out.insert_or_assign(update_label, "PACKED"); 505 update_patch.version = "PACKED";
506 out.push_back(update_patch);
499 } 507 }
500 } 508 }
501 509
@@ -539,7 +547,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
539 547
540 const auto mod_disabled = 548 const auto mod_disabled =
541 std::find(disabled.begin(), disabled.end(), mod->GetName()) != disabled.end(); 549 std::find(disabled.begin(), disabled.end(), mod->GetName()) != disabled.end();
542 out.insert_or_assign(mod_disabled ? "[D] " + mod->GetName() : mod->GetName(), types); 550 out.push_back({.enabled = !mod_disabled,
551 .name = mod->GetName(),
552 .version = types,
553 .type = PatchType::Mod,
554 .program_id = title_id,
555 .title_id = title_id});
543 } 556 }
544 } 557 }
545 558
@@ -557,7 +570,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
557 if (!types.empty()) { 570 if (!types.empty()) {
558 const auto mod_disabled = 571 const auto mod_disabled =
559 std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end(); 572 std::find(disabled.begin(), disabled.end(), "SDMC") != disabled.end();
560 out.insert_or_assign(mod_disabled ? "[D] SDMC" : "SDMC", types); 573 out.push_back({.enabled = !mod_disabled,
574 .name = "SDMC",
575 .version = types,
576 .type = PatchType::Mod,
577 .program_id = title_id,
578 .title_id = title_id});
561 } 579 }
562 } 580 }
563 581
@@ -584,7 +602,12 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
584 602
585 const auto dlc_disabled = 603 const auto dlc_disabled =
586 std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end(); 604 std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end();
587 out.insert_or_assign(dlc_disabled ? "[D] DLC" : "DLC", std::move(list)); 605 out.push_back({.enabled = !dlc_disabled,
606 .name = "DLC",
607 .version = std::move(list),
608 .type = PatchType::DLC,
609 .program_id = title_id,
610 .title_id = dlc_match.back().title_id});
588 } 611 }
589 612
590 return out; 613 return out;
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h
index 03e9c7301..2601b8217 100644
--- a/src/core/file_sys/patch_manager.h
+++ b/src/core/file_sys/patch_manager.h
@@ -26,12 +26,22 @@ class ContentProvider;
26class NCA; 26class NCA;
27class NACP; 27class NACP;
28 28
29enum class PatchType { Update, DLC, Mod };
30
31struct Patch {
32 bool enabled;
33 std::string name;
34 std::string version;
35 PatchType type;
36 u64 program_id;
37 u64 title_id;
38};
39
29// A centralized class to manage patches to games. 40// A centralized class to manage patches to games.
30class PatchManager { 41class PatchManager {
31public: 42public:
32 using BuildID = std::array<u8, 0x20>; 43 using BuildID = std::array<u8, 0x20>;
33 using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; 44 using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>;
34 using PatchVersionNames = std::map<std::string, std::string, std::less<>>;
35 45
36 explicit PatchManager(u64 title_id_, 46 explicit PatchManager(u64 title_id_,
37 const Service::FileSystem::FileSystemController& fs_controller_, 47 const Service::FileSystem::FileSystemController& fs_controller_,
@@ -66,9 +76,8 @@ public:
66 VirtualFile packed_update_raw = nullptr, 76 VirtualFile packed_update_raw = nullptr,
67 bool apply_layeredfs = true) const; 77 bool apply_layeredfs = true) const;
68 78
69 // Returns a vector of pairs between patch names and patch versions. 79 // Returns a vector of patches
70 // i.e. Update 3.2.2 will return {"Update", "3.2.2"} 80 [[nodiscard]] std::vector<Patch> GetPatches(VirtualFile update_raw = nullptr) const;
71 [[nodiscard]] PatchVersionNames GetPatchVersionNames(VirtualFile update_raw = nullptr) const;
72 81
73 // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails, 82 // If the game update exists, returns the u32 version field in its Meta-type NCA. If that fails,
74 // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be 83 // it will fallback to the Meta-type NCA of the base game. If that fails, the result will be
diff --git a/src/core/gpu_dirty_memory_manager.h b/src/core/gpu_dirty_memory_manager.h
index 9687531e8..cc8fc176f 100644
--- a/src/core/gpu_dirty_memory_manager.h
+++ b/src/core/gpu_dirty_memory_manager.h
@@ -10,7 +10,7 @@
10#include <utility> 10#include <utility>
11#include <vector> 11#include <vector>
12 12
13#include "core/memory.h" 13#include "core/device_memory_manager.h"
14 14
15namespace Core { 15namespace Core {
16 16
@@ -23,7 +23,7 @@ public:
23 23
24 ~GPUDirtyMemoryManager() = default; 24 ~GPUDirtyMemoryManager() = default;
25 25
26 void Collect(VAddr address, size_t size) { 26 void Collect(PAddr address, size_t size) {
27 TransformAddress t = BuildTransform(address, size); 27 TransformAddress t = BuildTransform(address, size);
28 TransformAddress tmp, original; 28 TransformAddress tmp, original;
29 do { 29 do {
@@ -47,7 +47,7 @@ public:
47 std::memory_order_relaxed)); 47 std::memory_order_relaxed));
48 } 48 }
49 49
50 void Gather(std::function<void(VAddr, size_t)>& callback) { 50 void Gather(std::function<void(PAddr, size_t)>& callback) {
51 { 51 {
52 std::scoped_lock lk(guard); 52 std::scoped_lock lk(guard);
53 TransformAddress t = current.exchange(default_transform, std::memory_order_relaxed); 53 TransformAddress t = current.exchange(default_transform, std::memory_order_relaxed);
@@ -65,7 +65,7 @@ public:
65 mask = mask >> empty_bits; 65 mask = mask >> empty_bits;
66 66
67 const size_t continuous_bits = std::countr_one(mask); 67 const size_t continuous_bits = std::countr_one(mask);
68 callback((static_cast<VAddr>(transform.address) << page_bits) + offset, 68 callback((static_cast<PAddr>(transform.address) << page_bits) + offset,
69 continuous_bits << align_bits); 69 continuous_bits << align_bits);
70 mask = continuous_bits < align_size ? (mask >> continuous_bits) : 0; 70 mask = continuous_bits < align_size ? (mask >> continuous_bits) : 0;
71 offset += continuous_bits << align_bits; 71 offset += continuous_bits << align_bits;
@@ -80,7 +80,7 @@ private:
80 u32 mask; 80 u32 mask;
81 }; 81 };
82 82
83 constexpr static size_t page_bits = Memory::YUZU_PAGEBITS - 1; 83 constexpr static size_t page_bits = DEVICE_PAGEBITS - 1;
84 constexpr static size_t page_size = 1ULL << page_bits; 84 constexpr static size_t page_size = 1ULL << page_bits;
85 constexpr static size_t page_mask = page_size - 1; 85 constexpr static size_t page_mask = page_size - 1;
86 86
@@ -89,7 +89,7 @@ private:
89 constexpr static size_t align_mask = align_size - 1; 89 constexpr static size_t align_mask = align_size - 1;
90 constexpr static TransformAddress default_transform = {.address = ~0U, .mask = 0U}; 90 constexpr static TransformAddress default_transform = {.address = ~0U, .mask = 0U};
91 91
92 bool IsValid(VAddr address) { 92 bool IsValid(PAddr address) {
93 return address < (1ULL << 39); 93 return address < (1ULL << 39);
94 } 94 }
95 95
@@ -103,7 +103,7 @@ private:
103 return mask; 103 return mask;
104 } 104 }
105 105
106 TransformAddress BuildTransform(VAddr address, size_t size) { 106 TransformAddress BuildTransform(PAddr address, size_t size) {
107 const size_t minor_address = address & page_mask; 107 const size_t minor_address = address & page_mask;
108 const size_t minor_bit = minor_address >> align_bits; 108 const size_t minor_bit = minor_address >> align_bits;
109 const size_t top_bit = (minor_address + size + align_mask) >> align_bits; 109 const size_t top_bit = (minor_address + size + align_mask) >> align_bits;
diff --git a/src/core/guest_memory.h b/src/core/guest_memory.h
new file mode 100644
index 000000000..7ee18c126
--- /dev/null
+++ b/src/core/guest_memory.h
@@ -0,0 +1,214 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <iterator>
7#include <memory>
8#include <optional>
9#include <span>
10#include <vector>
11
12#include "common/assert.h"
13#include "common/scratch_buffer.h"
14
15namespace Core::Memory {
16
17enum GuestMemoryFlags : u32 {
18 Read = 1 << 0,
19 Write = 1 << 1,
20 Safe = 1 << 2,
21 Cached = 1 << 3,
22
23 SafeRead = Read | Safe,
24 SafeWrite = Write | Safe,
25 SafeReadWrite = SafeRead | SafeWrite,
26 SafeReadCachedWrite = SafeReadWrite | Cached,
27
28 UnsafeRead = Read,
29 UnsafeWrite = Write,
30 UnsafeReadWrite = UnsafeRead | UnsafeWrite,
31 UnsafeReadCachedWrite = UnsafeReadWrite | Cached,
32};
33
34namespace {
35template <typename M, typename T, GuestMemoryFlags FLAGS>
36class GuestMemory {
37 using iterator = T*;
38 using const_iterator = const T*;
39 using value_type = T;
40 using element_type = T;
41 using iterator_category = std::contiguous_iterator_tag;
42
43public:
44 GuestMemory() = delete;
45 explicit GuestMemory(M& memory, u64 addr, std::size_t size,
46 Common::ScratchBuffer<T>* backup = nullptr)
47 : m_memory{memory}, m_addr{addr}, m_size{size} {
48 static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
49 if constexpr (FLAGS & GuestMemoryFlags::Read) {
50 Read(addr, size, backup);
51 }
52 }
53
54 ~GuestMemory() = default;
55
56 T* data() noexcept {
57 return m_data_span.data();
58 }
59
60 const T* data() const noexcept {
61 return m_data_span.data();
62 }
63
64 size_t size() const noexcept {
65 return m_size;
66 }
67
68 size_t size_bytes() const noexcept {
69 return this->size() * sizeof(T);
70 }
71
72 [[nodiscard]] T* begin() noexcept {
73 return this->data();
74 }
75
76 [[nodiscard]] const T* begin() const noexcept {
77 return this->data();
78 }
79
80 [[nodiscard]] T* end() noexcept {
81 return this->data() + this->size();
82 }
83
84 [[nodiscard]] const T* end() const noexcept {
85 return this->data() + this->size();
86 }
87
88 T& operator[](size_t index) noexcept {
89 return m_data_span[index];
90 }
91
92 const T& operator[](size_t index) const noexcept {
93 return m_data_span[index];
94 }
95
96 void SetAddressAndSize(u64 addr, std::size_t size) noexcept {
97 m_addr = addr;
98 m_size = size;
99 m_addr_changed = true;
100 }
101
102 std::span<T> Read(u64 addr, std::size_t size,
103 Common::ScratchBuffer<T>* backup = nullptr) noexcept {
104 m_addr = addr;
105 m_size = size;
106 if (m_size == 0) {
107 m_is_data_copy = true;
108 return {};
109 }
110
111 if (this->TrySetSpan()) {
112 if constexpr (FLAGS & GuestMemoryFlags::Safe) {
113 m_memory.FlushRegion(m_addr, this->size_bytes());
114 }
115 } else {
116 if (backup) {
117 backup->resize_destructive(this->size());
118 m_data_span = *backup;
119 } else {
120 m_data_copy.resize(this->size());
121 m_data_span = std::span(m_data_copy);
122 }
123 m_is_data_copy = true;
124 m_span_valid = true;
125 if constexpr (FLAGS & GuestMemoryFlags::Safe) {
126 m_memory.ReadBlock(m_addr, this->data(), this->size_bytes());
127 } else {
128 m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
129 }
130 }
131 return m_data_span;
132 }
133
134 void Write(std::span<T> write_data) noexcept {
135 if constexpr (FLAGS & GuestMemoryFlags::Cached) {
136 m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
137 } else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
138 m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes());
139 } else {
140 m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
141 }
142 }
143
144 bool TrySetSpan() noexcept {
145 if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) {
146 m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
147 m_span_valid = true;
148 return true;
149 }
150 return false;
151 }
152
153protected:
154 bool IsDataCopy() const noexcept {
155 return m_is_data_copy;
156 }
157
158 bool AddressChanged() const noexcept {
159 return m_addr_changed;
160 }
161
162 M& m_memory;
163 u64 m_addr{};
164 size_t m_size{};
165 std::span<T> m_data_span{};
166 std::vector<T> m_data_copy{};
167 bool m_span_valid{false};
168 bool m_is_data_copy{false};
169 bool m_addr_changed{false};
170};
171
172template <typename M, typename T, GuestMemoryFlags FLAGS>
173class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> {
174public:
175 GuestMemoryScoped() = delete;
176 explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
177 Common::ScratchBuffer<T>* backup = nullptr)
178 : GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {
179 if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
180 if (!this->TrySetSpan()) {
181 if (backup) {
182 this->m_data_span = *backup;
183 this->m_span_valid = true;
184 this->m_is_data_copy = true;
185 }
186 }
187 }
188 }
189
190 ~GuestMemoryScoped() {
191 if constexpr (FLAGS & GuestMemoryFlags::Write) {
192 if (this->size() == 0) [[unlikely]] {
193 return;
194 }
195
196 if (this->AddressChanged() || this->IsDataCopy()) {
197 ASSERT(this->m_span_valid);
198 if constexpr (FLAGS & GuestMemoryFlags::Cached) {
199 this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
200 } else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
201 this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes());
202 } else {
203 this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
204 }
205 } else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
206 (FLAGS & GuestMemoryFlags::Cached)) {
207 this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes());
208 }
209 }
210 }
211};
212} // namespace
213
214} // namespace Core::Memory
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 53735a225..0b08e877e 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -5,6 +5,7 @@
5#include "common/scope_exit.h" 5#include "common/scope_exit.h"
6#include "common/settings.h" 6#include "common/settings.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/gpu_dirty_memory_manager.h"
8#include "core/hle/kernel/k_process.h" 9#include "core/hle/kernel/k_process.h"
9#include "core/hle/kernel/k_scoped_resource_reservation.h" 10#include "core/hle/kernel/k_scoped_resource_reservation.h"
10#include "core/hle/kernel/k_shared_memory.h" 11#include "core/hle/kernel/k_shared_memory.h"
@@ -320,7 +321,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa
320 321
321 // Ensure our memory is initialized. 322 // Ensure our memory is initialized.
322 m_memory.SetCurrentPageTable(*this); 323 m_memory.SetCurrentPageTable(*this);
323 m_memory.SetGPUDirtyManagers(m_dirty_memory_managers); 324 m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager());
324 325
325 // Ensure we can insert the code region. 326 // Ensure we can insert the code region.
326 R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, 327 R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize,
@@ -417,7 +418,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params,
417 418
418 // Ensure our memory is initialized. 419 // Ensure our memory is initialized.
419 m_memory.SetCurrentPageTable(*this); 420 m_memory.SetCurrentPageTable(*this);
420 m_memory.SetGPUDirtyManagers(m_dirty_memory_managers); 421 m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager());
421 422
422 // Ensure we can insert the code region. 423 // Ensure we can insert the code region.
423 R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), 424 R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code),
@@ -1141,8 +1142,7 @@ void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {}
1141KProcess::KProcess(KernelCore& kernel) 1142KProcess::KProcess(KernelCore& kernel)
1142 : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel}, 1143 : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel},
1143 m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()}, 1144 m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()},
1144 m_handle_table{kernel}, m_dirty_memory_managers{}, 1145 m_handle_table{kernel}, m_exclusive_monitor{}, m_memory{kernel.System()} {}
1145 m_exclusive_monitor{}, m_memory{kernel.System()} {}
1146KProcess::~KProcess() = default; 1146KProcess::~KProcess() = default;
1147 1147
1148Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, 1148Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
@@ -1324,10 +1324,4 @@ bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointT
1324 return true; 1324 return true;
1325} 1325}
1326 1326
1327void KProcess::GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback) {
1328 for (auto& manager : m_dirty_memory_managers) {
1329 manager.Gather(callback);
1330 }
1331}
1332
1333} // namespace Kernel 1327} // namespace Kernel
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 53c0e3316..ab1358a12 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -7,7 +7,6 @@
7 7
8#include "core/arm/arm_interface.h" 8#include "core/arm/arm_interface.h"
9#include "core/file_sys/program_metadata.h" 9#include "core/file_sys/program_metadata.h"
10#include "core/gpu_dirty_memory_manager.h"
11#include "core/hle/kernel/code_set.h" 10#include "core/hle/kernel/code_set.h"
12#include "core/hle/kernel/k_address_arbiter.h" 11#include "core/hle/kernel/k_address_arbiter.h"
13#include "core/hle/kernel/k_capabilities.h" 12#include "core/hle/kernel/k_capabilities.h"
@@ -128,7 +127,6 @@ private:
128#ifdef HAS_NCE 127#ifdef HAS_NCE
129 std::unordered_map<u64, u64> m_post_handlers{}; 128 std::unordered_map<u64, u64> m_post_handlers{};
130#endif 129#endif
131 std::array<Core::GPUDirtyMemoryManager, Core::Hardware::NUM_CPU_CORES> m_dirty_memory_managers;
132 std::unique_ptr<Core::ExclusiveMonitor> m_exclusive_monitor; 130 std::unique_ptr<Core::ExclusiveMonitor> m_exclusive_monitor;
133 Core::Memory::Memory m_memory; 131 Core::Memory::Memory m_memory;
134 132
@@ -511,8 +509,6 @@ public:
511 return m_memory; 509 return m_memory;
512 } 510 }
513 511
514 void GatherGPUDirtyMemory(std::function<void(VAddr, size_t)>& callback);
515
516 Core::ExclusiveMonitor& GetExclusiveMonitor() const { 512 Core::ExclusiveMonitor& GetExclusiveMonitor() const {
517 return *m_exclusive_monitor; 513 return *m_exclusive_monitor;
518 } 514 }
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 683f44e27..29a10ad13 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -11,6 +11,7 @@
11#include "common/fs/path_util.h" 11#include "common/fs/path_util.h"
12#include "common/polyfill_ranges.h" 12#include "common/polyfill_ranges.h"
13#include "common/settings.h" 13#include "common/settings.h"
14#include "common/string_util.h"
14#include "core/hle/service/acc/profile_manager.h" 15#include "core/hle/service/acc/profile_manager.h"
15 16
16namespace Service::Account { 17namespace Service::Account {
@@ -164,6 +165,22 @@ std::optional<std::size_t> ProfileManager::GetUserIndex(const ProfileInfo& user)
164 return GetUserIndex(user.user_uuid); 165 return GetUserIndex(user.user_uuid);
165} 166}
166 167
168/// Returns the first user profile seen based on username (which does not enforce uniqueness)
169std::optional<std::size_t> ProfileManager::GetUserIndex(const std::string& username) const {
170 const auto iter =
171 std::find_if(profiles.begin(), profiles.end(), [&username](const ProfileInfo& p) {
172 const std::string profile_username = Common::StringFromFixedZeroTerminatedBuffer(
173 reinterpret_cast<const char*>(p.username.data()), p.username.size());
174
175 return username.compare(profile_username) == 0;
176 });
177 if (iter == profiles.end()) {
178 return std::nullopt;
179 }
180
181 return static_cast<std::size_t>(std::distance(profiles.begin(), iter));
182}
183
167/// Returns the data structure used by the switch when GetProfileBase is called on acc:* 184/// Returns the data structure used by the switch when GetProfileBase is called on acc:*
168bool ProfileManager::GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const { 185bool ProfileManager::GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const {
169 if (!index || index >= MAX_USERS) { 186 if (!index || index >= MAX_USERS) {
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index e21863e64..f94157300 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -70,6 +70,7 @@ public:
70 std::optional<Common::UUID> GetUser(std::size_t index) const; 70 std::optional<Common::UUID> GetUser(std::size_t index) const;
71 std::optional<std::size_t> GetUserIndex(const Common::UUID& uuid) const; 71 std::optional<std::size_t> GetUserIndex(const Common::UUID& uuid) const;
72 std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const; 72 std::optional<std::size_t> GetUserIndex(const ProfileInfo& user) const;
73 std::optional<std::size_t> GetUserIndex(const std::string& username) const;
73 bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const; 74 bool GetProfileBase(std::optional<std::size_t> index, ProfileBase& profile) const;
74 bool GetProfileBase(Common::UUID uuid, ProfileBase& profile) const; 75 bool GetProfileBase(Common::UUID uuid, ProfileBase& profile) const;
75 bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const; 76 bool GetProfileBase(const ProfileInfo& user, ProfileBase& profile) const;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 03ebdc137..595a3372e 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -26,6 +26,7 @@ void LoopProcess(Core::System& system) {
26 resource_manager->Initialize(); 26 resource_manager->Initialize();
27 resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), 27 resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(),
28 true); 28 true);
29 resource_manager->SetAruidValidForVibration(system.ApplicationProcess()->GetProcessId(), true);
29 30
30 server_manager->RegisterNamedService( 31 server_manager->RegisterNamedService(
31 "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); 32 "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings));
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp
index 1951da33b..30afed812 100644
--- a/src/core/hle/service/hid/hid_server.cpp
+++ b/src/core/hle/service/hid/hid_server.cpp
@@ -22,12 +22,16 @@
22#include "hid_core/resources/mouse/mouse.h" 22#include "hid_core/resources/mouse/mouse.h"
23#include "hid_core/resources/npad/npad.h" 23#include "hid_core/resources/npad/npad.h"
24#include "hid_core/resources/npad/npad_types.h" 24#include "hid_core/resources/npad/npad_types.h"
25#include "hid_core/resources/npad/npad_vibration.h"
25#include "hid_core/resources/palma/palma.h" 26#include "hid_core/resources/palma/palma.h"
26#include "hid_core/resources/six_axis/console_six_axis.h" 27#include "hid_core/resources/six_axis/console_six_axis.h"
27#include "hid_core/resources/six_axis/seven_six_axis.h" 28#include "hid_core/resources/six_axis/seven_six_axis.h"
28#include "hid_core/resources/six_axis/six_axis.h" 29#include "hid_core/resources/six_axis/six_axis.h"
29#include "hid_core/resources/touch_screen/gesture.h" 30#include "hid_core/resources/touch_screen/gesture.h"
30#include "hid_core/resources/touch_screen/touch_screen.h" 31#include "hid_core/resources/touch_screen/touch_screen.h"
32#include "hid_core/resources/vibration/gc_vibration_device.h"
33#include "hid_core/resources/vibration/n64_vibration_device.h"
34#include "hid_core/resources/vibration/vibration_device.h"
31 35
32namespace Service::HID { 36namespace Service::HID {
33 37
@@ -38,7 +42,7 @@ public:
38 : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) { 42 : ServiceFramework{system_, "IActiveVibrationDeviceList"}, resource_manager(resource) {
39 // clang-format off 43 // clang-format off
40 static const FunctionInfo functions[] = { 44 static const FunctionInfo functions[] = {
41 {0, &IActiveVibrationDeviceList::InitializeVibrationDevice, "InitializeVibrationDevice"}, 45 {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"},
42 }; 46 };
43 // clang-format on 47 // clang-format on
44 48
@@ -46,22 +50,49 @@ public:
46 } 50 }
47 51
48private: 52private:
49 void InitializeVibrationDevice(HLERequestContext& ctx) { 53 void ActivateVibrationDevice(HLERequestContext& ctx) {
50 IPC::RequestParser rp{ctx}; 54 IPC::RequestParser rp{ctx};
51 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; 55 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
52 56
53 if (resource_manager != nullptr && resource_manager->GetNpad()) {
54 resource_manager->GetNpad()->InitializeVibrationDevice(vibration_device_handle);
55 }
56
57 LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}", 57 LOG_DEBUG(Service_HID, "called, npad_type={}, npad_id={}, device_index={}",
58 vibration_device_handle.npad_type, vibration_device_handle.npad_id, 58 vibration_device_handle.npad_type, vibration_device_handle.npad_id,
59 vibration_device_handle.device_index); 59 vibration_device_handle.device_index);
60 60
61 const auto result = ActivateVibrationDeviceImpl(vibration_device_handle);
62
61 IPC::ResponseBuilder rb{ctx, 2}; 63 IPC::ResponseBuilder rb{ctx, 2};
62 rb.Push(ResultSuccess); 64 rb.Push(result);
63 } 65 }
64 66
67 Result ActivateVibrationDeviceImpl(const Core::HID::VibrationDeviceHandle& handle) {
68 std::scoped_lock lock{mutex};
69
70 const Result is_valid = IsVibrationHandleValid(handle);
71 if (is_valid.IsError()) {
72 return is_valid;
73 }
74
75 for (std::size_t i = 0; i < list_size; i++) {
76 if (handle.device_index == vibration_device_list[i].device_index &&
77 handle.npad_id == vibration_device_list[i].npad_id &&
78 handle.npad_type == vibration_device_list[i].npad_type) {
79 return ResultSuccess;
80 }
81 }
82 if (list_size == vibration_device_list.size()) {
83 return ResultVibrationDeviceIndexOutOfRange;
84 }
85 const Result result = resource_manager->GetVibrationDevice(handle)->Activate();
86 if (result.IsError()) {
87 return result;
88 }
89 vibration_device_list[list_size++] = handle;
90 return ResultSuccess;
91 }
92
93 mutable std::mutex mutex;
94 std::size_t list_size{};
95 std::array<Core::HID::VibrationDeviceHandle, 0x100> vibration_device_list{};
65 std::shared_ptr<ResourceManager> resource_manager; 96 std::shared_ptr<ResourceManager> resource_manager;
66}; 97};
67 98
@@ -153,7 +184,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r
153 {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, 184 {209, &IHidServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
154 {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"}, 185 {210, &IHidServer::EndPermitVibrationSession, "EndPermitVibrationSession"},
155 {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"}, 186 {211, &IHidServer::IsVibrationDeviceMounted, "IsVibrationDeviceMounted"},
156 {212, nullptr, "SendVibrationValueInBool"}, 187 {212, &IHidServer::SendVibrationValueInBool, "SendVibrationValueInBool"},
157 {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, 188 {300, &IHidServer::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
158 {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, 189 {301, &IHidServer::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
159 {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, 190 {302, &IHidServer::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"},
@@ -1492,59 +1523,13 @@ void IHidServer::ClearNpadCaptureButtonAssignment(HLERequestContext& ctx) {
1492void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) { 1523void IHidServer::GetVibrationDeviceInfo(HLERequestContext& ctx) {
1493 IPC::RequestParser rp{ctx}; 1524 IPC::RequestParser rp{ctx};
1494 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()}; 1525 const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
1495 const auto controller = GetResourceManager()->GetNpad();
1496
1497 Core::HID::VibrationDeviceInfo vibration_device_info;
1498 bool check_device_index = false;
1499
1500 switch (vibration_device_handle.npad_type) {
1501 case Core::HID::NpadStyleIndex::Fullkey:
1502 case Core::HID::NpadStyleIndex::Handheld:
1503 case Core::HID::NpadStyleIndex::JoyconDual:
1504 case Core::HID::NpadStyleIndex::JoyconLeft:
1505 case Core::HID::NpadStyleIndex::JoyconRight:
1506 vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
1507 check_device_index = true;
1508 break;
1509 case Core::HID::NpadStyleIndex::GameCube:
1510 vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
1511 break;
1512 case Core::HID::NpadStyleIndex::N64:
1513 vibration_device_info.type = Core::HID::VibrationDeviceType::N64;
1514 break;
1515 default:
1516 vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
1517 break;
1518 }
1519
1520 vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
1521 if (check_device_index) {
1522 switch (vibration_device_handle.device_index) {
1523 case Core::HID::DeviceIndex::Left:
1524 vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
1525 break;
1526 case Core::HID::DeviceIndex::Right:
1527 vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
1528 break;
1529 case Core::HID::DeviceIndex::None:
1530 default:
1531 ASSERT_MSG(false, "DeviceIndex should never be None!");
1532 break;
1533 }
1534 }
1535 1526
1536 LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}", 1527 Core::HID::VibrationDeviceInfo vibration_device_info{};
1537 vibration_device_info.type, vibration_device_info.position); 1528 const auto result = GetResourceManager()->GetVibrationDeviceInfo(vibration_device_info,
1538 1529 vibration_device_handle);
1539 const auto result = IsVibrationHandleValid(vibration_device_handle);
1540 if (result.IsError()) {
1541 IPC::ResponseBuilder rb{ctx, 2};
1542 rb.Push(result);
1543 return;
1544 }
1545 1530
1546 IPC::ResponseBuilder rb{ctx, 4}; 1531 IPC::ResponseBuilder rb{ctx, 4};
1547 rb.Push(ResultSuccess); 1532 rb.Push(result);
1548 rb.PushRaw(vibration_device_info); 1533 rb.PushRaw(vibration_device_info);
1549} 1534}
1550 1535
@@ -1560,16 +1545,16 @@ void IHidServer::SendVibrationValue(HLERequestContext& ctx) {
1560 1545
1561 const auto parameters{rp.PopRaw<Parameters>()}; 1546 const auto parameters{rp.PopRaw<Parameters>()};
1562 1547
1563 GetResourceManager()->GetNpad()->VibrateController(parameters.applet_resource_user_id,
1564 parameters.vibration_device_handle,
1565 parameters.vibration_value);
1566
1567 LOG_DEBUG(Service_HID, 1548 LOG_DEBUG(Service_HID,
1568 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 1549 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1569 parameters.vibration_device_handle.npad_type, 1550 parameters.vibration_device_handle.npad_type,
1570 parameters.vibration_device_handle.npad_id, 1551 parameters.vibration_device_handle.npad_id,
1571 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); 1552 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1572 1553
1554 GetResourceManager()->SendVibrationValue(parameters.applet_resource_user_id,
1555 parameters.vibration_device_handle,
1556 parameters.vibration_value);
1557
1573 IPC::ResponseBuilder rb{ctx, 2}; 1558 IPC::ResponseBuilder rb{ctx, 2};
1574 rb.Push(ResultSuccess); 1559 rb.Push(ResultSuccess);
1575} 1560}
@@ -1591,10 +1576,28 @@ void IHidServer::GetActualVibrationValue(HLERequestContext& ctx) {
1591 parameters.vibration_device_handle.npad_id, 1576 parameters.vibration_device_handle.npad_id,
1592 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); 1577 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1593 1578
1579 bool has_active_aruid{};
1580 NpadVibrationDevice* device{nullptr};
1581 Core::HID::VibrationValue vibration_value{};
1582 Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id,
1583 has_active_aruid);
1584
1585 if (result.IsSuccess() && has_active_aruid) {
1586 result = IsVibrationHandleValid(parameters.vibration_device_handle);
1587 }
1588 if (result.IsSuccess() && has_active_aruid) {
1589 device = GetResourceManager()->GetNSVibrationDevice(parameters.vibration_device_handle);
1590 }
1591 if (device != nullptr) {
1592 result = device->GetActualVibrationValue(vibration_value);
1593 }
1594 if (result.IsError()) {
1595 vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE;
1596 }
1597
1594 IPC::ResponseBuilder rb{ctx, 6}; 1598 IPC::ResponseBuilder rb{ctx, 6};
1595 rb.Push(ResultSuccess); 1599 rb.Push(ResultSuccess);
1596 rb.PushRaw(GetResourceManager()->GetNpad()->GetLastVibration( 1600 rb.PushRaw(vibration_value);
1597 parameters.applet_resource_user_id, parameters.vibration_device_handle));
1598} 1601}
1599 1602
1600void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) { 1603void IHidServer::CreateActiveVibrationDeviceList(HLERequestContext& ctx) {
@@ -1609,25 +1612,27 @@ void IHidServer::PermitVibration(HLERequestContext& ctx) {
1609 IPC::RequestParser rp{ctx}; 1612 IPC::RequestParser rp{ctx};
1610 const auto can_vibrate{rp.Pop<bool>()}; 1613 const auto can_vibrate{rp.Pop<bool>()};
1611 1614
1612 // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
1613 // by converting it to a bool
1614 Settings::values.vibration_enabled.SetValue(can_vibrate);
1615
1616 LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); 1615 LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
1617 1616
1617 const auto result =
1618 GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume(
1619 can_vibrate ? 1.0f : 0.0f);
1620
1618 IPC::ResponseBuilder rb{ctx, 2}; 1621 IPC::ResponseBuilder rb{ctx, 2};
1619 rb.Push(ResultSuccess); 1622 rb.Push(result);
1620} 1623}
1621 1624
1622void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) { 1625void IHidServer::IsVibrationPermitted(HLERequestContext& ctx) {
1623 LOG_DEBUG(Service_HID, "called"); 1626 LOG_DEBUG(Service_HID, "called");
1624 1627
1625 // nnSDK checks if a float is greater than zero. We return the bool we stored earlier 1628 f32 master_volume{};
1626 const auto is_enabled = Settings::values.vibration_enabled.GetValue(); 1629 const auto result =
1630 GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume(
1631 master_volume);
1627 1632
1628 IPC::ResponseBuilder rb{ctx, 3}; 1633 IPC::ResponseBuilder rb{ctx, 3};
1629 rb.Push(ResultSuccess); 1634 rb.Push(result);
1630 rb.Push(is_enabled); 1635 rb.Push(master_volume > 0.0f);
1631} 1636}
1632 1637
1633void IHidServer::SendVibrationValues(HLERequestContext& ctx) { 1638void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
@@ -1645,13 +1650,22 @@ void IHidServer::SendVibrationValues(HLERequestContext& ctx) {
1645 auto vibration_values = std::span( 1650 auto vibration_values = std::span(
1646 reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count); 1651 reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
1647 1652
1648 GetResourceManager()->GetNpad()->VibrateControllers(applet_resource_user_id,
1649 vibration_device_handles, vibration_values);
1650
1651 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1653 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1652 1654
1655 Result result = ResultSuccess;
1656 if (handle_count != vibration_count) {
1657 result = ResultVibrationArraySizeMismatch;
1658 }
1659
1660 for (std::size_t i = 0; i < handle_count; i++) {
1661 if (result.IsSuccess()) {
1662 result = GetResourceManager()->SendVibrationValue(
1663 applet_resource_user_id, vibration_device_handles[i], vibration_values[i]);
1664 }
1665 }
1666
1653 IPC::ResponseBuilder rb{ctx, 2}; 1667 IPC::ResponseBuilder rb{ctx, 2};
1654 rb.Push(ResultSuccess); 1668 rb.Push(result);
1655} 1669}
1656 1670
1657void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) { 1671void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
@@ -1666,43 +1680,6 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
1666 1680
1667 const auto parameters{rp.PopRaw<Parameters>()}; 1681 const auto parameters{rp.PopRaw<Parameters>()};
1668 1682
1669 /**
1670 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1671 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined below,
1672 * in order to differentiate between Stop and StopHard commands.
1673 * This is done to reuse the controller vibration functions made for regular controllers.
1674 */
1675 const auto vibration_value = [parameters] {
1676 switch (parameters.gc_erm_command) {
1677 case Core::HID::VibrationGcErmCommand::Stop:
1678 return Core::HID::VibrationValue{
1679 .low_amplitude = 0.0f,
1680 .low_frequency = 160.0f,
1681 .high_amplitude = 0.0f,
1682 .high_frequency = 320.0f,
1683 };
1684 case Core::HID::VibrationGcErmCommand::Start:
1685 return Core::HID::VibrationValue{
1686 .low_amplitude = 1.0f,
1687 .low_frequency = 160.0f,
1688 .high_amplitude = 1.0f,
1689 .high_frequency = 320.0f,
1690 };
1691 case Core::HID::VibrationGcErmCommand::StopHard:
1692 return Core::HID::VibrationValue{
1693 .low_amplitude = 0.0f,
1694 .low_frequency = 0.0f,
1695 .high_amplitude = 0.0f,
1696 .high_frequency = 0.0f,
1697 };
1698 default:
1699 return Core::HID::DEFAULT_VIBRATION_VALUE;
1700 }
1701 }();
1702
1703 GetResourceManager()->GetNpad()->VibrateController(
1704 parameters.applet_resource_user_id, parameters.vibration_device_handle, vibration_value);
1705
1706 LOG_DEBUG(Service_HID, 1683 LOG_DEBUG(Service_HID,
1707 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, " 1684 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
1708 "gc_erm_command={}", 1685 "gc_erm_command={}",
@@ -1711,8 +1688,23 @@ void IHidServer::SendVibrationGcErmCommand(HLERequestContext& ctx) {
1711 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id, 1688 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id,
1712 parameters.gc_erm_command); 1689 parameters.gc_erm_command);
1713 1690
1691 bool has_active_aruid{};
1692 NpadGcVibrationDevice* gc_device{nullptr};
1693 Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id,
1694 has_active_aruid);
1695
1696 if (result.IsSuccess() && has_active_aruid) {
1697 result = IsVibrationHandleValid(parameters.vibration_device_handle);
1698 }
1699 if (result.IsSuccess() && has_active_aruid) {
1700 gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle);
1701 }
1702 if (gc_device != nullptr) {
1703 result = gc_device->SendVibrationGcErmCommand(parameters.gc_erm_command);
1704 }
1705
1714 IPC::ResponseBuilder rb{ctx, 2}; 1706 IPC::ResponseBuilder rb{ctx, 2};
1715 rb.Push(ResultSuccess); 1707 rb.Push(result);
1716} 1708}
1717 1709
1718void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) { 1710void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
@@ -1725,33 +1717,31 @@ void IHidServer::GetActualVibrationGcErmCommand(HLERequestContext& ctx) {
1725 1717
1726 const auto parameters{rp.PopRaw<Parameters>()}; 1718 const auto parameters{rp.PopRaw<Parameters>()};
1727 1719
1728 const auto last_vibration = GetResourceManager()->GetNpad()->GetLastVibration(
1729 parameters.applet_resource_user_id, parameters.vibration_device_handle);
1730
1731 const auto gc_erm_command = [last_vibration] {
1732 if (last_vibration.low_amplitude != 0.0f || last_vibration.high_amplitude != 0.0f) {
1733 return Core::HID::VibrationGcErmCommand::Start;
1734 }
1735
1736 /**
1737 * Note: This uses yuzu-specific behavior such that the StopHard command produces
1738 * vibrations where freq_low == 0.0f and freq_high == 0.0f, as defined in the HID function
1739 * SendVibrationGcErmCommand, in order to differentiate between Stop and StopHard commands.
1740 * This is done to reuse the controller vibration functions made for regular controllers.
1741 */
1742 if (last_vibration.low_frequency == 0.0f && last_vibration.high_frequency == 0.0f) {
1743 return Core::HID::VibrationGcErmCommand::StopHard;
1744 }
1745
1746 return Core::HID::VibrationGcErmCommand::Stop;
1747 }();
1748
1749 LOG_DEBUG(Service_HID, 1720 LOG_DEBUG(Service_HID,
1750 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}", 1721 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
1751 parameters.vibration_device_handle.npad_type, 1722 parameters.vibration_device_handle.npad_type,
1752 parameters.vibration_device_handle.npad_id, 1723 parameters.vibration_device_handle.npad_id,
1753 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); 1724 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1754 1725
1726 bool has_active_aruid{};
1727 NpadGcVibrationDevice* gc_device{nullptr};
1728 Core::HID::VibrationGcErmCommand gc_erm_command{};
1729 Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id,
1730 has_active_aruid);
1731
1732 if (result.IsSuccess() && has_active_aruid) {
1733 result = IsVibrationHandleValid(parameters.vibration_device_handle);
1734 }
1735 if (result.IsSuccess() && has_active_aruid) {
1736 gc_device = GetResourceManager()->GetGcVibrationDevice(parameters.vibration_device_handle);
1737 }
1738 if (gc_device != nullptr) {
1739 result = gc_device->GetActualVibrationGcErmCommand(gc_erm_command);
1740 }
1741 if (result.IsError()) {
1742 gc_erm_command = Core::HID::VibrationGcErmCommand::Stop;
1743 }
1744
1755 IPC::ResponseBuilder rb{ctx, 4}; 1745 IPC::ResponseBuilder rb{ctx, 4};
1756 rb.Push(ResultSuccess); 1746 rb.Push(ResultSuccess);
1757 rb.PushEnum(gc_erm_command); 1747 rb.PushEnum(gc_erm_command);
@@ -1761,21 +1751,24 @@ void IHidServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
1761 IPC::RequestParser rp{ctx}; 1751 IPC::RequestParser rp{ctx};
1762 const auto applet_resource_user_id{rp.Pop<u64>()}; 1752 const auto applet_resource_user_id{rp.Pop<u64>()};
1763 1753
1764 GetResourceManager()->GetNpad()->SetPermitVibrationSession(true);
1765
1766 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id); 1754 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
1767 1755
1756 const auto result =
1757 GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession(
1758 applet_resource_user_id);
1759
1768 IPC::ResponseBuilder rb{ctx, 2}; 1760 IPC::ResponseBuilder rb{ctx, 2};
1769 rb.Push(ResultSuccess); 1761 rb.Push(result);
1770} 1762}
1771 1763
1772void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) { 1764void IHidServer::EndPermitVibrationSession(HLERequestContext& ctx) {
1773 GetResourceManager()->GetNpad()->SetPermitVibrationSession(false);
1774
1775 LOG_DEBUG(Service_HID, "called"); 1765 LOG_DEBUG(Service_HID, "called");
1776 1766
1767 const auto result =
1768 GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession();
1769
1777 IPC::ResponseBuilder rb{ctx, 2}; 1770 IPC::ResponseBuilder rb{ctx, 2};
1778 rb.Push(ResultSuccess); 1771 rb.Push(result);
1779} 1772}
1780 1773
1781void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) { 1774void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) {
@@ -1795,10 +1788,61 @@ void IHidServer::IsVibrationDeviceMounted(HLERequestContext& ctx) {
1795 parameters.vibration_device_handle.npad_id, 1788 parameters.vibration_device_handle.npad_id,
1796 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id); 1789 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id);
1797 1790
1791 bool is_mounted{};
1792 NpadVibrationBase* device{nullptr};
1793 Result result = IsVibrationHandleValid(parameters.vibration_device_handle);
1794
1795 if (result.IsSuccess()) {
1796 device = GetResourceManager()->GetVibrationDevice(parameters.vibration_device_handle);
1797 }
1798
1799 if (device != nullptr) {
1800 is_mounted = device->IsVibrationMounted();
1801 }
1802
1798 IPC::ResponseBuilder rb{ctx, 3}; 1803 IPC::ResponseBuilder rb{ctx, 3};
1799 rb.Push(ResultSuccess); 1804 rb.Push(result);
1800 rb.Push(GetResourceManager()->GetNpad()->IsVibrationDeviceMounted( 1805 rb.Push(is_mounted);
1801 parameters.applet_resource_user_id, parameters.vibration_device_handle)); 1806}
1807
1808void IHidServer::SendVibrationValueInBool(HLERequestContext& ctx) {
1809 IPC::RequestParser rp{ctx};
1810 struct Parameters {
1811 Core::HID::VibrationDeviceHandle vibration_device_handle;
1812 INSERT_PADDING_WORDS_NOINIT(1);
1813 u64 applet_resource_user_id;
1814 bool is_vibrating;
1815 };
1816 static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
1817
1818 const auto parameters{rp.PopRaw<Parameters>()};
1819
1820 LOG_DEBUG(Service_HID,
1821 "called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}, "
1822 "is_vibrating={}",
1823 parameters.vibration_device_handle.npad_type,
1824 parameters.vibration_device_handle.npad_id,
1825 parameters.vibration_device_handle.device_index, parameters.applet_resource_user_id,
1826 parameters.is_vibrating);
1827
1828 bool has_active_aruid{};
1829 NpadN64VibrationDevice* n64_device{nullptr};
1830 Result result = GetResourceManager()->IsVibrationAruidActive(parameters.applet_resource_user_id,
1831 has_active_aruid);
1832
1833 if (result.IsSuccess() && has_active_aruid) {
1834 result = IsVibrationHandleValid(parameters.vibration_device_handle);
1835 }
1836 if (result.IsSuccess() && has_active_aruid) {
1837 n64_device =
1838 GetResourceManager()->GetN64VibrationDevice(parameters.vibration_device_handle);
1839 }
1840 if (n64_device != nullptr) {
1841 result = n64_device->SendValueInBool(parameters.is_vibrating);
1842 }
1843
1844 IPC::ResponseBuilder rb{ctx, 2};
1845 rb.Push(result);
1802} 1846}
1803 1847
1804void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) { 1848void IHidServer::ActivateConsoleSixAxisSensor(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/hid/hid_server.h b/src/core/hle/service/hid/hid_server.h
index cc7c4ebdd..3a2e0a230 100644
--- a/src/core/hle/service/hid/hid_server.h
+++ b/src/core/hle/service/hid/hid_server.h
@@ -97,6 +97,7 @@ private:
97 void BeginPermitVibrationSession(HLERequestContext& ctx); 97 void BeginPermitVibrationSession(HLERequestContext& ctx);
98 void EndPermitVibrationSession(HLERequestContext& ctx); 98 void EndPermitVibrationSession(HLERequestContext& ctx);
99 void IsVibrationDeviceMounted(HLERequestContext& ctx); 99 void IsVibrationDeviceMounted(HLERequestContext& ctx);
100 void SendVibrationValueInBool(HLERequestContext& ctx);
100 void ActivateConsoleSixAxisSensor(HLERequestContext& ctx); 101 void ActivateConsoleSixAxisSensor(HLERequestContext& ctx);
101 void StartConsoleSixAxisSensor(HLERequestContext& ctx); 102 void StartConsoleSixAxisSensor(HLERequestContext& ctx);
102 void StopConsoleSixAxisSensor(HLERequestContext& ctx); 103 void StopConsoleSixAxisSensor(HLERequestContext& ctx);
diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp
index 3a0cb3cb1..bf27ddfbf 100644
--- a/src/core/hle/service/hid/hid_system_server.cpp
+++ b/src/core/hle/service/hid/hid_system_server.cpp
@@ -7,6 +7,7 @@
7#include "hid_core/resource_manager.h" 7#include "hid_core/resource_manager.h"
8#include "hid_core/resources/npad/npad.h" 8#include "hid_core/resources/npad/npad.h"
9#include "hid_core/resources/npad/npad_types.h" 9#include "hid_core/resources/npad/npad_types.h"
10#include "hid_core/resources/npad/npad_vibration.h"
10#include "hid_core/resources/palma/palma.h" 11#include "hid_core/resources/palma/palma.h"
11#include "hid_core/resources/touch_screen/touch_screen.h" 12#include "hid_core/resources/touch_screen/touch_screen.h"
12 13
@@ -67,14 +68,14 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
67 {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"}, 68 {501, &IHidSystemServer::RegisterAppletResourceUserId, "RegisterAppletResourceUserId"},
68 {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"}, 69 {502, &IHidSystemServer::UnregisterAppletResourceUserId, "UnregisterAppletResourceUserId"},
69 {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"}, 70 {503, &IHidSystemServer::EnableAppletToGetInput, "EnableAppletToGetInput"},
70 {504, nullptr, "SetAruidValidForVibration"}, 71 {504, &IHidSystemServer::SetAruidValidForVibration, "SetAruidValidForVibration"},
71 {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"}, 72 {505, &IHidSystemServer::EnableAppletToGetSixAxisSensor, "EnableAppletToGetSixAxisSensor"},
72 {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"}, 73 {506, &IHidSystemServer::EnableAppletToGetPadInput, "EnableAppletToGetPadInput"},
73 {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"}, 74 {507, &IHidSystemServer::EnableAppletToGetTouchScreen, "EnableAppletToGetTouchScreen"},
74 {510, nullptr, "SetVibrationMasterVolume"}, 75 {510, &IHidSystemServer::SetVibrationMasterVolume, "SetVibrationMasterVolume"},
75 {511, nullptr, "GetVibrationMasterVolume"}, 76 {511, &IHidSystemServer::GetVibrationMasterVolume, "GetVibrationMasterVolume"},
76 {512, nullptr, "BeginPermitVibrationSession"}, 77 {512, &IHidSystemServer::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
77 {513, nullptr, "EndPermitVibrationSession"}, 78 {513, &IHidSystemServer::EndPermitVibrationSession, "EndPermitVibrationSession"},
78 {514, nullptr, "Unknown514"}, 79 {514, nullptr, "Unknown514"},
79 {520, nullptr, "EnableHandheldHids"}, 80 {520, nullptr, "EnableHandheldHids"},
80 {521, nullptr, "DisableHandheldHids"}, 81 {521, nullptr, "DisableHandheldHids"},
@@ -156,7 +157,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour
156 {1152, nullptr, "SetTouchScreenDefaultConfiguration"}, 157 {1152, nullptr, "SetTouchScreenDefaultConfiguration"},
157 {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"}, 158 {1153, &IHidSystemServer::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
158 {1154, nullptr, "IsFirmwareAvailableForNotification"}, 159 {1154, nullptr, "IsFirmwareAvailableForNotification"},
159 {1155, nullptr, "SetForceHandheldStyleVibration"}, 160 {1155, &IHidSystemServer::SetForceHandheldStyleVibration, "SetForceHandheldStyleVibration"},
160 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"}, 161 {1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
161 {1157, nullptr, "CancelConnectionTrigger"}, 162 {1157, nullptr, "CancelConnectionTrigger"},
162 {1200, nullptr, "IsButtonConfigSupported"}, 163 {1200, nullptr, "IsButtonConfigSupported"},
@@ -532,7 +533,28 @@ void IHidSystemServer::EnableAppletToGetInput(HLERequestContext& ctx) {
532 parameters.is_enabled, parameters.applet_resource_user_id); 533 parameters.is_enabled, parameters.applet_resource_user_id);
533 534
534 GetResourceManager()->EnableInput(parameters.applet_resource_user_id, parameters.is_enabled); 535 GetResourceManager()->EnableInput(parameters.applet_resource_user_id, parameters.is_enabled);
535 // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); 536 GetResourceManager()->GetNpad()->EnableAppletToGetInput(parameters.applet_resource_user_id);
537
538 IPC::ResponseBuilder rb{ctx, 2};
539 rb.Push(ResultSuccess);
540}
541
542void IHidSystemServer::SetAruidValidForVibration(HLERequestContext& ctx) {
543 IPC::RequestParser rp{ctx};
544 struct Parameters {
545 bool is_enabled;
546 INSERT_PADDING_WORDS_NOINIT(1);
547 u64 applet_resource_user_id;
548 };
549 static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
550
551 const auto parameters{rp.PopRaw<Parameters>()};
552
553 LOG_INFO(Service_HID, "called, is_enabled={}, applet_resource_user_id={}",
554 parameters.is_enabled, parameters.applet_resource_user_id);
555
556 GetResourceManager()->SetAruidValidForVibration(parameters.applet_resource_user_id,
557 parameters.is_enabled);
536 558
537 IPC::ResponseBuilder rb{ctx, 2}; 559 IPC::ResponseBuilder rb{ctx, 2};
538 rb.Push(ResultSuccess); 560 rb.Push(ResultSuccess);
@@ -574,7 +596,7 @@ void IHidSystemServer::EnableAppletToGetPadInput(HLERequestContext& ctx) {
574 parameters.is_enabled, parameters.applet_resource_user_id); 596 parameters.is_enabled, parameters.applet_resource_user_id);
575 597
576 GetResourceManager()->EnablePadInput(parameters.applet_resource_user_id, parameters.is_enabled); 598 GetResourceManager()->EnablePadInput(parameters.applet_resource_user_id, parameters.is_enabled);
577 // GetResourceManager()->GetNpad()->EnableInput(parameters.applet_resource_user_id); 599 GetResourceManager()->GetNpad()->EnableAppletToGetInput(parameters.applet_resource_user_id);
578 600
579 IPC::ResponseBuilder rb{ctx, 2}; 601 IPC::ResponseBuilder rb{ctx, 2};
580 rb.Push(ResultSuccess); 602 rb.Push(ResultSuccess);
@@ -601,6 +623,57 @@ void IHidSystemServer::EnableAppletToGetTouchScreen(HLERequestContext& ctx) {
601 rb.Push(ResultSuccess); 623 rb.Push(ResultSuccess);
602} 624}
603 625
626void IHidSystemServer::SetVibrationMasterVolume(HLERequestContext& ctx) {
627 IPC::RequestParser rp{ctx};
628 const auto master_volume{rp.Pop<f32>()};
629
630 LOG_INFO(Service_HID, "called, volume={}", master_volume);
631
632 const auto result =
633 GetResourceManager()->GetNpad()->GetVibrationHandler()->SetVibrationMasterVolume(
634 master_volume);
635
636 IPC::ResponseBuilder rb{ctx, 2};
637 rb.Push(result);
638}
639
640void IHidSystemServer::GetVibrationMasterVolume(HLERequestContext& ctx) {
641 f32 master_volume{};
642 const auto result =
643 GetResourceManager()->GetNpad()->GetVibrationHandler()->GetVibrationMasterVolume(
644 master_volume);
645
646 LOG_INFO(Service_HID, "called, volume={}", master_volume);
647
648 IPC::ResponseBuilder rb{ctx, 3};
649 rb.Push(result);
650 rb.Push(master_volume);
651}
652
653void IHidSystemServer::BeginPermitVibrationSession(HLERequestContext& ctx) {
654 IPC::RequestParser rp{ctx};
655 const auto applet_resource_user_id{rp.Pop<u64>()};
656
657 LOG_INFO(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
658
659 const auto result =
660 GetResourceManager()->GetNpad()->GetVibrationHandler()->BeginPermitVibrationSession(
661 applet_resource_user_id);
662
663 IPC::ResponseBuilder rb{ctx, 2};
664 rb.Push(result);
665}
666
667void IHidSystemServer::EndPermitVibrationSession(HLERequestContext& ctx) {
668 LOG_INFO(Service_HID, "called");
669
670 const auto result =
671 GetResourceManager()->GetNpad()->GetVibrationHandler()->EndPermitVibrationSession();
672
673 IPC::ResponseBuilder rb{ctx, 2};
674 rb.Push(result);
675}
676
604void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) { 677void IHidSystemServer::IsJoyConAttachedOnAllRail(HLERequestContext& ctx) {
605 const bool is_attached = true; 678 const bool is_attached = true;
606 679
@@ -749,6 +822,19 @@ void IHidSystemServer::GetTouchScreenDefaultConfiguration(HLERequestContext& ctx
749 rb.PushRaw(touchscreen_config); 822 rb.PushRaw(touchscreen_config);
750} 823}
751 824
825void IHidSystemServer::SetForceHandheldStyleVibration(HLERequestContext& ctx) {
826 IPC::RequestParser rp{ctx};
827 const auto is_forced{rp.Pop<bool>()};
828
829 LOG_INFO(Service_HID, "called, is_forced={}", is_forced);
830
831 GetResourceManager()->SetForceHandheldStyleVibration(is_forced);
832 GetResourceManager()->GetNpad()->UpdateHandheldAbstractState();
833
834 IPC::ResponseBuilder rb{ctx, 2};
835 rb.Push(ResultSuccess);
836}
837
752void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { 838void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) {
753 const bool is_enabled = false; 839 const bool is_enabled = false;
754 840
diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h
index 0c2634e3f..90a719f02 100644
--- a/src/core/hle/service/hid/hid_system_server.h
+++ b/src/core/hle/service/hid/hid_system_server.h
@@ -42,9 +42,14 @@ private:
42 void RegisterAppletResourceUserId(HLERequestContext& ctx); 42 void RegisterAppletResourceUserId(HLERequestContext& ctx);
43 void UnregisterAppletResourceUserId(HLERequestContext& ctx); 43 void UnregisterAppletResourceUserId(HLERequestContext& ctx);
44 void EnableAppletToGetInput(HLERequestContext& ctx); 44 void EnableAppletToGetInput(HLERequestContext& ctx);
45 void SetAruidValidForVibration(HLERequestContext& ctx);
45 void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx); 46 void EnableAppletToGetSixAxisSensor(HLERequestContext& ctx);
46 void EnableAppletToGetPadInput(HLERequestContext& ctx); 47 void EnableAppletToGetPadInput(HLERequestContext& ctx);
47 void EnableAppletToGetTouchScreen(HLERequestContext& ctx); 48 void EnableAppletToGetTouchScreen(HLERequestContext& ctx);
49 void SetVibrationMasterVolume(HLERequestContext& ctx);
50 void GetVibrationMasterVolume(HLERequestContext& ctx);
51 void BeginPermitVibrationSession(HLERequestContext& ctx);
52 void EndPermitVibrationSession(HLERequestContext& ctx);
48 void IsJoyConAttachedOnAllRail(HLERequestContext& ctx); 53 void IsJoyConAttachedOnAllRail(HLERequestContext& ctx);
49 void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx); 54 void AcquireConnectionTriggerTimeoutEvent(HLERequestContext& ctx);
50 void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx); 55 void AcquireDeviceRegisteredEventForControllerSupport(HLERequestContext& ctx);
@@ -61,6 +66,7 @@ private:
61 void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx); 66 void FinalizeUsbFirmwareUpdate(HLERequestContext& ctx);
62 void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx); 67 void InitializeUsbFirmwareUpdateWithoutMemory(HLERequestContext& ctx);
63 void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); 68 void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx);
69 void SetForceHandheldStyleVibration(HLERequestContext& ctx);
64 void IsUsingCustomButtonConfig(HLERequestContext& ctx); 70 void IsUsingCustomButtonConfig(HLERequestContext& ctx);
65 71
66 std::shared_ptr<ResourceManager> GetResourceManager(); 72 std::shared_ptr<ResourceManager> GetResourceManager();
diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp
index 3f38ceb03..e491dd260 100644
--- a/src/core/hle/service/hle_ipc.cpp
+++ b/src/core/hle/service/hle_ipc.cpp
@@ -12,6 +12,7 @@
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "common/logging/log.h" 13#include "common/logging/log.h"
14#include "common/scratch_buffer.h" 14#include "common/scratch_buffer.h"
15#include "core/guest_memory.h"
15#include "core/hle/kernel/k_auto_object.h" 16#include "core/hle/kernel/k_auto_object.h"
16#include "core/hle/kernel/k_handle_table.h" 17#include "core/hle/kernel/k_handle_table.h"
17#include "core/hle/kernel/k_process.h" 18#include "core/hle/kernel/k_process.h"
@@ -23,19 +24,6 @@
23#include "core/hle/service/ipc_helpers.h" 24#include "core/hle/service/ipc_helpers.h"
24#include "core/memory.h" 25#include "core/memory.h"
25 26
26namespace {
27static thread_local std::array read_buffer_data_a{
28 Common::ScratchBuffer<u8>(),
29 Common::ScratchBuffer<u8>(),
30 Common::ScratchBuffer<u8>(),
31};
32static thread_local std::array read_buffer_data_x{
33 Common::ScratchBuffer<u8>(),
34 Common::ScratchBuffer<u8>(),
35 Common::ScratchBuffer<u8>(),
36};
37} // Anonymous namespace
38
39namespace Service { 27namespace Service {
40 28
41SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_) 29SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_)
@@ -343,48 +331,27 @@ std::vector<u8> HLERequestContext::ReadBufferCopy(std::size_t buffer_index) cons
343} 331}
344 332
345std::span<const u8> HLERequestContext::ReadBufferA(std::size_t buffer_index) const { 333std::span<const u8> HLERequestContext::ReadBufferA(std::size_t buffer_index) const {
346 static thread_local std::array read_buffer_a{ 334 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0);
347 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
348 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
349 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
350 };
351 335
352 ASSERT_OR_EXECUTE_MSG( 336 ASSERT_OR_EXECUTE_MSG(
353 BufferDescriptorA().size() > buffer_index, { return {}; }, 337 BufferDescriptorA().size() > buffer_index, { return {}; },
354 "BufferDescriptorA invalid buffer_index {}", buffer_index); 338 "BufferDescriptorA invalid buffer_index {}", buffer_index);
355 auto& read_buffer = read_buffer_a[buffer_index]; 339 return gm.Read(BufferDescriptorA()[buffer_index].Address(),
356 return read_buffer.Read(BufferDescriptorA()[buffer_index].Address(), 340 BufferDescriptorA()[buffer_index].Size(), &read_buffer_data_a[buffer_index]);
357 BufferDescriptorA()[buffer_index].Size(),
358 &read_buffer_data_a[buffer_index]);
359} 341}
360 342
361std::span<const u8> HLERequestContext::ReadBufferX(std::size_t buffer_index) const { 343std::span<const u8> HLERequestContext::ReadBufferX(std::size_t buffer_index) const {
362 static thread_local std::array read_buffer_x{ 344 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0);
363 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
364 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
365 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
366 };
367 345
368 ASSERT_OR_EXECUTE_MSG( 346 ASSERT_OR_EXECUTE_MSG(
369 BufferDescriptorX().size() > buffer_index, { return {}; }, 347 BufferDescriptorX().size() > buffer_index, { return {}; },
370 "BufferDescriptorX invalid buffer_index {}", buffer_index); 348 "BufferDescriptorX invalid buffer_index {}", buffer_index);
371 auto& read_buffer = read_buffer_x[buffer_index]; 349 return gm.Read(BufferDescriptorX()[buffer_index].Address(),
372 return read_buffer.Read(BufferDescriptorX()[buffer_index].Address(), 350 BufferDescriptorX()[buffer_index].Size(), &read_buffer_data_x[buffer_index]);
373 BufferDescriptorX()[buffer_index].Size(),
374 &read_buffer_data_x[buffer_index]);
375} 351}
376 352
377std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { 353std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
378 static thread_local std::array read_buffer_a{ 354 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> gm(memory, 0, 0);
379 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
380 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
381 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
382 };
383 static thread_local std::array read_buffer_x{
384 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
385 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
386 Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
387 };
388 355
389 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && 356 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
390 BufferDescriptorA()[buffer_index].Size()}; 357 BufferDescriptorA()[buffer_index].Size()};
@@ -401,18 +368,14 @@ std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) cons
401 ASSERT_OR_EXECUTE_MSG( 368 ASSERT_OR_EXECUTE_MSG(
402 BufferDescriptorA().size() > buffer_index, { return {}; }, 369 BufferDescriptorA().size() > buffer_index, { return {}; },
403 "BufferDescriptorA invalid buffer_index {}", buffer_index); 370 "BufferDescriptorA invalid buffer_index {}", buffer_index);
404 auto& read_buffer = read_buffer_a[buffer_index]; 371 return gm.Read(BufferDescriptorA()[buffer_index].Address(),
405 return read_buffer.Read(BufferDescriptorA()[buffer_index].Address(), 372 BufferDescriptorA()[buffer_index].Size(), &read_buffer_data_a[buffer_index]);
406 BufferDescriptorA()[buffer_index].Size(),
407 &read_buffer_data_a[buffer_index]);
408 } else { 373 } else {
409 ASSERT_OR_EXECUTE_MSG( 374 ASSERT_OR_EXECUTE_MSG(
410 BufferDescriptorX().size() > buffer_index, { return {}; }, 375 BufferDescriptorX().size() > buffer_index, { return {}; },
411 "BufferDescriptorX invalid buffer_index {}", buffer_index); 376 "BufferDescriptorX invalid buffer_index {}", buffer_index);
412 auto& read_buffer = read_buffer_x[buffer_index]; 377 return gm.Read(BufferDescriptorX()[buffer_index].Address(),
413 return read_buffer.Read(BufferDescriptorX()[buffer_index].Address(), 378 BufferDescriptorX()[buffer_index].Size(), &read_buffer_data_x[buffer_index]);
414 BufferDescriptorX()[buffer_index].Size(),
415 &read_buffer_data_x[buffer_index]);
416 } 379 }
417} 380}
418 381
diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h
index 440737db5..8329d7265 100644
--- a/src/core/hle/service/hle_ipc.h
+++ b/src/core/hle/service/hle_ipc.h
@@ -41,6 +41,8 @@ class KernelCore;
41class KHandleTable; 41class KHandleTable;
42class KProcess; 42class KProcess;
43class KServerSession; 43class KServerSession;
44template <typename T>
45class KScopedAutoObject;
44class KThread; 46class KThread;
45} // namespace Kernel 47} // namespace Kernel
46 48
@@ -424,6 +426,9 @@ private:
424 426
425 Kernel::KernelCore& kernel; 427 Kernel::KernelCore& kernel;
426 Core::Memory::Memory& memory; 428 Core::Memory::Memory& memory;
429
430 mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_a{};
431 mutable std::array<Common::ScratchBuffer<u8>, 3> read_buffer_data_x{};
427}; 432};
428 433
429} // namespace Service 434} // namespace Service
diff --git a/src/core/hle/service/nvdrv/core/container.cpp b/src/core/hle/service/nvdrv/core/container.cpp
index 37ca24f5d..21ef57d27 100644
--- a/src/core/hle/service/nvdrv/core/container.cpp
+++ b/src/core/hle/service/nvdrv/core/container.cpp
@@ -2,27 +2,135 @@
2// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors 2// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors
3// SPDX-License-Identifier: GPL-3.0-or-later 3// SPDX-License-Identifier: GPL-3.0-or-later
4 4
5#include <atomic>
6#include <deque>
7#include <mutex>
8
9#include "core/hle/kernel/k_process.h"
5#include "core/hle/service/nvdrv/core/container.h" 10#include "core/hle/service/nvdrv/core/container.h"
11#include "core/hle/service/nvdrv/core/heap_mapper.h"
6#include "core/hle/service/nvdrv/core/nvmap.h" 12#include "core/hle/service/nvdrv/core/nvmap.h"
7#include "core/hle/service/nvdrv/core/syncpoint_manager.h" 13#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
14#include "core/memory.h"
8#include "video_core/host1x/host1x.h" 15#include "video_core/host1x/host1x.h"
9 16
10namespace Service::Nvidia::NvCore { 17namespace Service::Nvidia::NvCore {
11 18
19Session::Session(SessionId id_, Kernel::KProcess* process_, Core::Asid asid_)
20 : id{id_}, process{process_}, asid{asid_}, has_preallocated_area{}, mapper{}, is_active{} {}
21
22Session::~Session() = default;
23
12struct ContainerImpl { 24struct ContainerImpl {
13 explicit ContainerImpl(Tegra::Host1x::Host1x& host1x_) 25 explicit ContainerImpl(Container& core, Tegra::Host1x::Host1x& host1x_)
14 : file{host1x_}, manager{host1x_}, device_file_data{} {} 26 : host1x{host1x_}, file{core, host1x_}, manager{host1x_}, device_file_data{} {}
27 Tegra::Host1x::Host1x& host1x;
15 NvMap file; 28 NvMap file;
16 SyncpointManager manager; 29 SyncpointManager manager;
17 Container::Host1xDeviceFileData device_file_data; 30 Container::Host1xDeviceFileData device_file_data;
31 std::deque<Session> sessions;
32 size_t new_ids{};
33 std::deque<size_t> id_pool;
34 std::mutex session_guard;
18}; 35};
19 36
20Container::Container(Tegra::Host1x::Host1x& host1x_) { 37Container::Container(Tegra::Host1x::Host1x& host1x_) {
21 impl = std::make_unique<ContainerImpl>(host1x_); 38 impl = std::make_unique<ContainerImpl>(*this, host1x_);
22} 39}
23 40
24Container::~Container() = default; 41Container::~Container() = default;
25 42
43SessionId Container::OpenSession(Kernel::KProcess* process) {
44 using namespace Common::Literals;
45
46 std::scoped_lock lk(impl->session_guard);
47 for (auto& session : impl->sessions) {
48 if (!session.is_active) {
49 continue;
50 }
51 if (session.process == process) {
52 return session.id;
53 }
54 }
55 size_t new_id{};
56 auto* memory_interface = &process->GetMemory();
57 auto& smmu = impl->host1x.MemoryManager();
58 auto asid = smmu.RegisterProcess(memory_interface);
59 if (!impl->id_pool.empty()) {
60 new_id = impl->id_pool.front();
61 impl->id_pool.pop_front();
62 impl->sessions[new_id] = Session{SessionId{new_id}, process, asid};
63 } else {
64 new_id = impl->new_ids++;
65 impl->sessions.emplace_back(SessionId{new_id}, process, asid);
66 }
67 auto& session = impl->sessions[new_id];
68 session.is_active = true;
69 // Optimization
70 if (process->IsApplication()) {
71 auto& page_table = process->GetPageTable().GetBasePageTable();
72 auto heap_start = page_table.GetHeapRegionStart();
73
74 Kernel::KProcessAddress cur_addr = heap_start;
75 size_t region_size = 0;
76 VAddr region_start = 0;
77 while (true) {
78 Kernel::KMemoryInfo mem_info{};
79 Kernel::Svc::PageInfo page_info{};
80 R_ASSERT(page_table.QueryInfo(std::addressof(mem_info), std::addressof(page_info),
81 cur_addr));
82 auto svc_mem_info = mem_info.GetSvcMemoryInfo();
83
84 // Check if this memory block is heap.
85 if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
86 if (svc_mem_info.size > region_size) {
87 region_size = svc_mem_info.size;
88 region_start = svc_mem_info.base_address;
89 }
90 }
91
92 // Check if we're done.
93 const uintptr_t next_address = svc_mem_info.base_address + svc_mem_info.size;
94 if (next_address <= GetInteger(cur_addr)) {
95 break;
96 }
97
98 cur_addr = next_address;
99 }
100 session.has_preallocated_area = false;
101 auto start_region = region_size >= 32_MiB ? smmu.Allocate(region_size) : 0;
102 if (start_region != 0) {
103 session.mapper = std::make_unique<HeapMapper>(region_start, start_region, region_size,
104 asid, impl->host1x);
105 smmu.TrackContinuity(start_region, region_start, region_size, asid);
106 session.has_preallocated_area = true;
107 LOG_DEBUG(Debug, "Preallocation created!");
108 }
109 }
110 return SessionId{new_id};
111}
112
113void Container::CloseSession(SessionId session_id) {
114 std::scoped_lock lk(impl->session_guard);
115 auto& session = impl->sessions[session_id.id];
116 auto& smmu = impl->host1x.MemoryManager();
117 if (session.has_preallocated_area) {
118 const DAddr region_start = session.mapper->GetRegionStart();
119 const size_t region_size = session.mapper->GetRegionSize();
120 session.mapper.reset();
121 smmu.Free(region_start, region_size);
122 session.has_preallocated_area = false;
123 }
124 session.is_active = false;
125 smmu.UnregisterProcess(impl->sessions[session_id.id].asid);
126 impl->id_pool.emplace_front(session_id.id);
127}
128
129Session* Container::GetSession(SessionId session_id) {
130 std::atomic_thread_fence(std::memory_order_acquire);
131 return &impl->sessions[session_id.id];
132}
133
26NvMap& Container::GetNvMapFile() { 134NvMap& Container::GetNvMapFile() {
27 return impl->file; 135 return impl->file;
28} 136}
diff --git a/src/core/hle/service/nvdrv/core/container.h b/src/core/hle/service/nvdrv/core/container.h
index b4b63ac90..b4d3938a8 100644
--- a/src/core/hle/service/nvdrv/core/container.h
+++ b/src/core/hle/service/nvdrv/core/container.h
@@ -8,24 +8,56 @@
8#include <memory> 8#include <memory>
9#include <unordered_map> 9#include <unordered_map>
10 10
11#include "core/device_memory_manager.h"
11#include "core/hle/service/nvdrv/nvdata.h" 12#include "core/hle/service/nvdrv/nvdata.h"
12 13
14namespace Kernel {
15class KProcess;
16}
17
13namespace Tegra::Host1x { 18namespace Tegra::Host1x {
14class Host1x; 19class Host1x;
15} // namespace Tegra::Host1x 20} // namespace Tegra::Host1x
16 21
17namespace Service::Nvidia::NvCore { 22namespace Service::Nvidia::NvCore {
18 23
24class HeapMapper;
19class NvMap; 25class NvMap;
20class SyncpointManager; 26class SyncpointManager;
21 27
22struct ContainerImpl; 28struct ContainerImpl;
23 29
30struct SessionId {
31 size_t id;
32};
33
34struct Session {
35 Session(SessionId id_, Kernel::KProcess* process_, Core::Asid asid_);
36 ~Session();
37
38 Session(const Session&) = delete;
39 Session& operator=(const Session&) = delete;
40 Session(Session&&) = default;
41 Session& operator=(Session&&) = default;
42
43 SessionId id;
44 Kernel::KProcess* process;
45 Core::Asid asid;
46 bool has_preallocated_area{};
47 std::unique_ptr<HeapMapper> mapper{};
48 bool is_active{};
49};
50
24class Container { 51class Container {
25public: 52public:
26 explicit Container(Tegra::Host1x::Host1x& host1x); 53 explicit Container(Tegra::Host1x::Host1x& host1x);
27 ~Container(); 54 ~Container();
28 55
56 SessionId OpenSession(Kernel::KProcess* process);
57 void CloseSession(SessionId id);
58
59 Session* GetSession(SessionId id);
60
29 NvMap& GetNvMapFile(); 61 NvMap& GetNvMapFile();
30 62
31 const NvMap& GetNvMapFile() const; 63 const NvMap& GetNvMapFile() const;
diff --git a/src/core/hle/service/nvdrv/core/heap_mapper.cpp b/src/core/hle/service/nvdrv/core/heap_mapper.cpp
new file mode 100644
index 000000000..096dc5deb
--- /dev/null
+++ b/src/core/hle/service/nvdrv/core/heap_mapper.cpp
@@ -0,0 +1,175 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#include <mutex>
5
6#include <boost/container/small_vector.hpp>
7#define BOOST_NO_MT
8#include <boost/pool/detail/mutex.hpp>
9#undef BOOST_NO_MT
10#include <boost/icl/interval.hpp>
11#include <boost/icl/interval_base_set.hpp>
12#include <boost/icl/interval_set.hpp>
13#include <boost/icl/split_interval_map.hpp>
14#include <boost/pool/pool.hpp>
15#include <boost/pool/pool_alloc.hpp>
16#include <boost/pool/poolfwd.hpp>
17
18#include "core/hle/service/nvdrv/core/heap_mapper.h"
19#include "video_core/host1x/host1x.h"
20
21namespace boost {
22template <typename T>
23class fast_pool_allocator<T, default_user_allocator_new_delete, details::pool::null_mutex, 4096, 0>;
24}
25
26namespace Service::Nvidia::NvCore {
27
28using IntervalCompare = std::less<DAddr>;
29using IntervalInstance = boost::icl::interval_type_default<DAddr, std::less>;
30using IntervalAllocator = boost::fast_pool_allocator<DAddr>;
31using IntervalSet = boost::icl::interval_set<DAddr>;
32using IntervalType = typename IntervalSet::interval_type;
33
34template <typename Type>
35struct counter_add_functor : public boost::icl::identity_based_inplace_combine<Type> {
36 // types
37 typedef counter_add_functor<Type> type;
38 typedef boost::icl::identity_based_inplace_combine<Type> base_type;
39
40 // public member functions
41 void operator()(Type& current, const Type& added) const {
42 current += added;
43 if (current < base_type::identity_element()) {
44 current = base_type::identity_element();
45 }
46 }
47
48 // public static functions
49 static void version(Type&){};
50};
51
52using OverlapCombine = counter_add_functor<int>;
53using OverlapSection = boost::icl::inter_section<int>;
54using OverlapCounter = boost::icl::split_interval_map<DAddr, int>;
55
56struct HeapMapper::HeapMapperInternal {
57 HeapMapperInternal(Tegra::Host1x::Host1x& host1x) : device_memory{host1x.MemoryManager()} {}
58 ~HeapMapperInternal() = default;
59
60 template <typename Func>
61 void ForEachInOverlapCounter(OverlapCounter& current_range, VAddr cpu_addr, u64 size,
62 Func&& func) {
63 const DAddr start_address = cpu_addr;
64 const DAddr end_address = start_address + size;
65 const IntervalType search_interval{start_address, end_address};
66 auto it = current_range.lower_bound(search_interval);
67 if (it == current_range.end()) {
68 return;
69 }
70 auto end_it = current_range.upper_bound(search_interval);
71 for (; it != end_it; it++) {
72 auto& inter = it->first;
73 DAddr inter_addr_end = inter.upper();
74 DAddr inter_addr = inter.lower();
75 if (inter_addr_end > end_address) {
76 inter_addr_end = end_address;
77 }
78 if (inter_addr < start_address) {
79 inter_addr = start_address;
80 }
81 func(inter_addr, inter_addr_end, it->second);
82 }
83 }
84
85 void RemoveEachInOverlapCounter(OverlapCounter& current_range,
86 const IntervalType search_interval, int subtract_value) {
87 bool any_removals = false;
88 current_range.add(std::make_pair(search_interval, subtract_value));
89 do {
90 any_removals = false;
91 auto it = current_range.lower_bound(search_interval);
92 if (it == current_range.end()) {
93 return;
94 }
95 auto end_it = current_range.upper_bound(search_interval);
96 for (; it != end_it; it++) {
97 if (it->second <= 0) {
98 any_removals = true;
99 current_range.erase(it);
100 break;
101 }
102 }
103 } while (any_removals);
104 }
105
106 IntervalSet base_set;
107 OverlapCounter mapping_overlaps;
108 Tegra::MaxwellDeviceMemoryManager& device_memory;
109 std::mutex guard;
110};
111
112HeapMapper::HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, Core::Asid asid,
113 Tegra::Host1x::Host1x& host1x)
114 : m_vaddress{start_vaddress}, m_daddress{start_daddress}, m_size{size}, m_asid{asid} {
115 m_internal = std::make_unique<HeapMapperInternal>(host1x);
116}
117
118HeapMapper::~HeapMapper() {
119 m_internal->device_memory.Unmap(m_daddress, m_size);
120}
121
122DAddr HeapMapper::Map(VAddr start, size_t size) {
123 std::scoped_lock lk(m_internal->guard);
124 m_internal->base_set.clear();
125 const IntervalType interval{start, start + size};
126 m_internal->base_set.insert(interval);
127 m_internal->ForEachInOverlapCounter(m_internal->mapping_overlaps, start, size,
128 [this](VAddr start_addr, VAddr end_addr, int) {
129 const IntervalType other{start_addr, end_addr};
130 m_internal->base_set.subtract(other);
131 });
132 if (!m_internal->base_set.empty()) {
133 auto it = m_internal->base_set.begin();
134 auto end_it = m_internal->base_set.end();
135 for (; it != end_it; it++) {
136 const VAddr inter_addr_end = it->upper();
137 const VAddr inter_addr = it->lower();
138 const size_t offset = inter_addr - m_vaddress;
139 const size_t sub_size = inter_addr_end - inter_addr;
140 m_internal->device_memory.Map(m_daddress + offset, m_vaddress + offset, sub_size,
141 m_asid);
142 }
143 }
144 m_internal->mapping_overlaps += std::make_pair(interval, 1);
145 m_internal->base_set.clear();
146 return m_daddress + (start - m_vaddress);
147}
148
149void HeapMapper::Unmap(VAddr start, size_t size) {
150 std::scoped_lock lk(m_internal->guard);
151 m_internal->base_set.clear();
152 m_internal->ForEachInOverlapCounter(m_internal->mapping_overlaps, start, size,
153 [this](VAddr start_addr, VAddr end_addr, int value) {
154 if (value <= 1) {
155 const IntervalType other{start_addr, end_addr};
156 m_internal->base_set.insert(other);
157 }
158 });
159 if (!m_internal->base_set.empty()) {
160 auto it = m_internal->base_set.begin();
161 auto end_it = m_internal->base_set.end();
162 for (; it != end_it; it++) {
163 const VAddr inter_addr_end = it->upper();
164 const VAddr inter_addr = it->lower();
165 const size_t offset = inter_addr - m_vaddress;
166 const size_t sub_size = inter_addr_end - inter_addr;
167 m_internal->device_memory.Unmap(m_daddress + offset, sub_size);
168 }
169 }
170 const IntervalType to_remove{start, start + size};
171 m_internal->RemoveEachInOverlapCounter(m_internal->mapping_overlaps, to_remove, -1);
172 m_internal->base_set.clear();
173}
174
175} // namespace Service::Nvidia::NvCore
diff --git a/src/core/hle/service/nvdrv/core/heap_mapper.h b/src/core/hle/service/nvdrv/core/heap_mapper.h
new file mode 100644
index 000000000..491a12e4f
--- /dev/null
+++ b/src/core/hle/service/nvdrv/core/heap_mapper.h
@@ -0,0 +1,49 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <memory>
7
8#include "common/common_types.h"
9#include "core/device_memory_manager.h"
10
11namespace Tegra::Host1x {
12class Host1x;
13} // namespace Tegra::Host1x
14
15namespace Service::Nvidia::NvCore {
16
17class HeapMapper {
18public:
19 HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, Core::Asid asid,
20 Tegra::Host1x::Host1x& host1x);
21 ~HeapMapper();
22
23 bool IsInBounds(VAddr start, size_t size) const {
24 VAddr end = start + size;
25 return start >= m_vaddress && end <= (m_vaddress + m_size);
26 }
27
28 DAddr Map(VAddr start, size_t size);
29
30 void Unmap(VAddr start, size_t size);
31
32 DAddr GetRegionStart() const {
33 return m_daddress;
34 }
35
36 size_t GetRegionSize() const {
37 return m_size;
38 }
39
40private:
41 struct HeapMapperInternal;
42 VAddr m_vaddress;
43 DAddr m_daddress;
44 size_t m_size;
45 Core::Asid m_asid;
46 std::unique_ptr<HeapMapperInternal> m_internal;
47};
48
49} // namespace Service::Nvidia::NvCore
diff --git a/src/core/hle/service/nvdrv/core/nvmap.cpp b/src/core/hle/service/nvdrv/core/nvmap.cpp
index 0ca05257e..1b59c6b15 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/core/nvmap.cpp
@@ -2,14 +2,19 @@
2// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors 2// SPDX-FileCopyrightText: 2022 Skyline Team and Contributors
3// SPDX-License-Identifier: GPL-3.0-or-later 3// SPDX-License-Identifier: GPL-3.0-or-later
4 4
5#include <functional>
6
5#include "common/alignment.h" 7#include "common/alignment.h"
6#include "common/assert.h" 8#include "common/assert.h"
7#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/hle/service/nvdrv/core/container.h"
11#include "core/hle/service/nvdrv/core/heap_mapper.h"
8#include "core/hle/service/nvdrv/core/nvmap.h" 12#include "core/hle/service/nvdrv/core/nvmap.h"
9#include "core/memory.h" 13#include "core/memory.h"
10#include "video_core/host1x/host1x.h" 14#include "video_core/host1x/host1x.h"
11 15
12using Core::Memory::YUZU_PAGESIZE; 16using Core::Memory::YUZU_PAGESIZE;
17constexpr size_t BIG_PAGE_SIZE = YUZU_PAGESIZE * 16;
13 18
14namespace Service::Nvidia::NvCore { 19namespace Service::Nvidia::NvCore {
15NvMap::Handle::Handle(u64 size_, Id id_) 20NvMap::Handle::Handle(u64 size_, Id id_)
@@ -17,9 +22,9 @@ NvMap::Handle::Handle(u64 size_, Id id_)
17 flags.raw = 0; 22 flags.raw = 0;
18} 23}
19 24
20NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress) { 25NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress,
26 NvCore::SessionId pSessionId) {
21 std::scoped_lock lock(mutex); 27 std::scoped_lock lock(mutex);
22
23 // Handles cannot be allocated twice 28 // Handles cannot be allocated twice
24 if (allocated) { 29 if (allocated) {
25 return NvResult::AccessDenied; 30 return NvResult::AccessDenied;
@@ -28,6 +33,7 @@ NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress)
28 flags = pFlags; 33 flags = pFlags;
29 kind = pKind; 34 kind = pKind;
30 align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign; 35 align = pAlign < YUZU_PAGESIZE ? YUZU_PAGESIZE : pAlign;
36 session_id = pSessionId;
31 37
32 // This flag is only applicable for handles with an address passed 38 // This flag is only applicable for handles with an address passed
33 if (pAddress) { 39 if (pAddress) {
@@ -63,7 +69,7 @@ NvResult NvMap::Handle::Duplicate(bool internal_session) {
63 return NvResult::Success; 69 return NvResult::Success;
64} 70}
65 71
66NvMap::NvMap(Tegra::Host1x::Host1x& host1x_) : host1x{host1x_} {} 72NvMap::NvMap(Container& core_, Tegra::Host1x::Host1x& host1x_) : host1x{host1x_}, core{core_} {}
67 73
68void NvMap::AddHandle(std::shared_ptr<Handle> handle_description) { 74void NvMap::AddHandle(std::shared_ptr<Handle> handle_description) {
69 std::scoped_lock lock(handles_lock); 75 std::scoped_lock lock(handles_lock);
@@ -78,12 +84,30 @@ void NvMap::UnmapHandle(Handle& handle_description) {
78 handle_description.unmap_queue_entry.reset(); 84 handle_description.unmap_queue_entry.reset();
79 } 85 }
80 86
87 // Free and unmap the handle from Host1x GMMU
88 if (handle_description.pin_virt_address) {
89 host1x.GMMU().Unmap(static_cast<GPUVAddr>(handle_description.pin_virt_address),
90 handle_description.aligned_size);
91 host1x.Allocator().Free(handle_description.pin_virt_address,
92 static_cast<u32>(handle_description.aligned_size));
93 handle_description.pin_virt_address = 0;
94 }
95
81 // Free and unmap the handle from the SMMU 96 // Free and unmap the handle from the SMMU
82 host1x.MemoryManager().Unmap(static_cast<GPUVAddr>(handle_description.pin_virt_address), 97 const size_t map_size = handle_description.aligned_size;
83 handle_description.aligned_size); 98 if (!handle_description.in_heap) {
84 host1x.Allocator().Free(handle_description.pin_virt_address, 99 auto& smmu = host1x.MemoryManager();
85 static_cast<u32>(handle_description.aligned_size)); 100 size_t aligned_up = Common::AlignUp(map_size, BIG_PAGE_SIZE);
86 handle_description.pin_virt_address = 0; 101 smmu.Unmap(handle_description.d_address, map_size);
102 smmu.Free(handle_description.d_address, static_cast<size_t>(aligned_up));
103 handle_description.d_address = 0;
104 return;
105 }
106 const VAddr vaddress = handle_description.address;
107 auto* session = core.GetSession(handle_description.session_id);
108 session->mapper->Unmap(vaddress, map_size);
109 handle_description.d_address = 0;
110 handle_description.in_heap = false;
87} 111}
88 112
89bool NvMap::TryRemoveHandle(const Handle& handle_description) { 113bool NvMap::TryRemoveHandle(const Handle& handle_description) {
@@ -124,22 +148,33 @@ std::shared_ptr<NvMap::Handle> NvMap::GetHandle(Handle::Id handle) {
124 } 148 }
125} 149}
126 150
127VAddr NvMap::GetHandleAddress(Handle::Id handle) { 151DAddr NvMap::GetHandleAddress(Handle::Id handle) {
128 std::scoped_lock lock(handles_lock); 152 std::scoped_lock lock(handles_lock);
129 try { 153 try {
130 return handles.at(handle)->address; 154 return handles.at(handle)->d_address;
131 } catch (std::out_of_range&) { 155 } catch (std::out_of_range&) {
132 return 0; 156 return 0;
133 } 157 }
134} 158}
135 159
136u32 NvMap::PinHandle(NvMap::Handle::Id handle) { 160DAddr NvMap::PinHandle(NvMap::Handle::Id handle, bool low_area_pin) {
137 auto handle_description{GetHandle(handle)}; 161 auto handle_description{GetHandle(handle)};
138 if (!handle_description) [[unlikely]] { 162 if (!handle_description) [[unlikely]] {
139 return 0; 163 return 0;
140 } 164 }
141 165
142 std::scoped_lock lock(handle_description->mutex); 166 std::scoped_lock lock(handle_description->mutex);
167 const auto map_low_area = [&] {
168 if (handle_description->pin_virt_address == 0) {
169 auto& gmmu_allocator = host1x.Allocator();
170 auto& gmmu = host1x.GMMU();
171 u32 address =
172 gmmu_allocator.Allocate(static_cast<u32>(handle_description->aligned_size));
173 gmmu.Map(static_cast<GPUVAddr>(address), handle_description->d_address,
174 handle_description->aligned_size);
175 handle_description->pin_virt_address = address;
176 }
177 };
143 if (!handle_description->pins) { 178 if (!handle_description->pins) {
144 // If we're in the unmap queue we can just remove ourselves and return since we're already 179 // If we're in the unmap queue we can just remove ourselves and return since we're already
145 // mapped 180 // mapped
@@ -151,37 +186,58 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
151 unmap_queue.erase(*handle_description->unmap_queue_entry); 186 unmap_queue.erase(*handle_description->unmap_queue_entry);
152 handle_description->unmap_queue_entry.reset(); 187 handle_description->unmap_queue_entry.reset();
153 188
189 if (low_area_pin) {
190 map_low_area();
191 handle_description->pins++;
192 return static_cast<DAddr>(handle_description->pin_virt_address);
193 }
194
154 handle_description->pins++; 195 handle_description->pins++;
155 return handle_description->pin_virt_address; 196 return handle_description->d_address;
156 } 197 }
157 } 198 }
158 199
200 using namespace std::placeholders;
159 // If not then allocate some space and map it 201 // If not then allocate some space and map it
160 u32 address{}; 202 DAddr address{};
161 auto& smmu_allocator = host1x.Allocator(); 203 auto& smmu = host1x.MemoryManager();
162 auto& smmu_memory_manager = host1x.MemoryManager(); 204 auto* session = core.GetSession(handle_description->session_id);
163 while ((address = smmu_allocator.Allocate( 205 const VAddr vaddress = handle_description->address;
164 static_cast<u32>(handle_description->aligned_size))) == 0) { 206 const size_t map_size = handle_description->aligned_size;
165 // Free handles until the allocation succeeds 207 if (session->has_preallocated_area && session->mapper->IsInBounds(vaddress, map_size)) {
166 std::scoped_lock queueLock(unmap_queue_lock); 208 handle_description->d_address = session->mapper->Map(vaddress, map_size);
167 if (auto freeHandleDesc{unmap_queue.front()}) { 209 handle_description->in_heap = true;
168 // Handles in the unmap queue are guaranteed not to be pinned so don't bother 210 } else {
169 // checking if they are before unmapping 211 size_t aligned_up = Common::AlignUp(map_size, BIG_PAGE_SIZE);
170 std::scoped_lock freeLock(freeHandleDesc->mutex); 212 while ((address = smmu.Allocate(aligned_up)) == 0) {
171 if (handle_description->pin_virt_address) 213 // Free handles until the allocation succeeds
172 UnmapHandle(*freeHandleDesc); 214 std::scoped_lock queueLock(unmap_queue_lock);
173 } else { 215 if (auto freeHandleDesc{unmap_queue.front()}) {
174 LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!"); 216 // Handles in the unmap queue are guaranteed not to be pinned so don't bother
217 // checking if they are before unmapping
218 std::scoped_lock freeLock(freeHandleDesc->mutex);
219 if (handle_description->d_address)
220 UnmapHandle(*freeHandleDesc);
221 } else {
222 LOG_CRITICAL(Service_NVDRV, "Ran out of SMMU address space!");
223 }
175 } 224 }
225
226 handle_description->d_address = address;
227 smmu.Map(address, vaddress, map_size, session->asid, true);
228 handle_description->in_heap = false;
176 } 229 }
230 }
177 231
178 smmu_memory_manager.Map(static_cast<GPUVAddr>(address), handle_description->address, 232 if (low_area_pin) {
179 handle_description->aligned_size); 233 map_low_area();
180 handle_description->pin_virt_address = address;
181 } 234 }
182 235
183 handle_description->pins++; 236 handle_description->pins++;
184 return handle_description->pin_virt_address; 237 if (low_area_pin) {
238 return static_cast<DAddr>(handle_description->pin_virt_address);
239 }
240 return handle_description->d_address;
185} 241}
186 242
187void NvMap::UnpinHandle(Handle::Id handle) { 243void NvMap::UnpinHandle(Handle::Id handle) {
@@ -232,7 +288,7 @@ std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool interna
232 LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!"); 288 LOG_WARNING(Service_NVDRV, "User duplicate count imbalance detected!");
233 } else if (handle_description->dupes == 0) { 289 } else if (handle_description->dupes == 0) {
234 // Force unmap the handle 290 // Force unmap the handle
235 if (handle_description->pin_virt_address) { 291 if (handle_description->d_address) {
236 std::scoped_lock queueLock(unmap_queue_lock); 292 std::scoped_lock queueLock(unmap_queue_lock);
237 UnmapHandle(*handle_description); 293 UnmapHandle(*handle_description);
238 } 294 }
diff --git a/src/core/hle/service/nvdrv/core/nvmap.h b/src/core/hle/service/nvdrv/core/nvmap.h
index a8e573890..d7f695845 100644
--- a/src/core/hle/service/nvdrv/core/nvmap.h
+++ b/src/core/hle/service/nvdrv/core/nvmap.h
@@ -14,6 +14,7 @@
14 14
15#include "common/bit_field.h" 15#include "common/bit_field.h"
16#include "common/common_types.h" 16#include "common/common_types.h"
17#include "core/hle/service/nvdrv/core/container.h"
17#include "core/hle/service/nvdrv/nvdata.h" 18#include "core/hle/service/nvdrv/nvdata.h"
18 19
19namespace Tegra { 20namespace Tegra {
@@ -25,6 +26,8 @@ class Host1x;
25} // namespace Tegra 26} // namespace Tegra
26 27
27namespace Service::Nvidia::NvCore { 28namespace Service::Nvidia::NvCore {
29
30class Container;
28/** 31/**
29 * @brief The nvmap core class holds the global state for nvmap and provides methods to manage 32 * @brief The nvmap core class holds the global state for nvmap and provides methods to manage
30 * handles 33 * handles
@@ -48,7 +51,7 @@ public:
48 using Id = u32; 51 using Id = u32;
49 Id id; //!< A globally unique identifier for this handle 52 Id id; //!< A globally unique identifier for this handle
50 53
51 s32 pins{}; 54 s64 pins{};
52 u32 pin_virt_address{}; 55 u32 pin_virt_address{};
53 std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{}; 56 std::optional<typename std::list<std::shared_ptr<Handle>>::iterator> unmap_queue_entry{};
54 57
@@ -61,15 +64,18 @@ public:
61 } flags{}; 64 } flags{};
62 static_assert(sizeof(Flags) == sizeof(u32)); 65 static_assert(sizeof(Flags) == sizeof(u32));
63 66
64 u64 address{}; //!< The memory location in the guest's AS that this handle corresponds to, 67 VAddr address{}; //!< The memory location in the guest's AS that this handle corresponds to,
65 //!< this can also be in the nvdrv tmem 68 //!< this can also be in the nvdrv tmem
66 bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC 69 bool is_shared_mem_mapped{}; //!< If this nvmap has been mapped with the MapSharedMem IPC
67 //!< call 70 //!< call
68 71
69 u8 kind{}; //!< Used for memory compression 72 u8 kind{}; //!< Used for memory compression
70 bool allocated{}; //!< If the handle has been allocated with `Alloc` 73 bool allocated{}; //!< If the handle has been allocated with `Alloc`
74 bool in_heap{};
75 NvCore::SessionId session_id{};
71 76
72 u64 dma_map_addr{}; //! remove me after implementing pinning. 77 DAddr d_address{}; //!< The memory location in the device's AS that this handle corresponds
78 //!< to, this can also be in the nvdrv tmem
73 79
74 Handle(u64 size, Id id); 80 Handle(u64 size, Id id);
75 81
@@ -77,7 +83,8 @@ public:
77 * @brief Sets up the handle with the given memory config, can allocate memory from the tmem 83 * @brief Sets up the handle with the given memory config, can allocate memory from the tmem
78 * if a 0 address is passed 84 * if a 0 address is passed
79 */ 85 */
80 [[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress); 86 [[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress,
87 NvCore::SessionId pSessionId);
81 88
82 /** 89 /**
83 * @brief Increases the dupe counter of the handle for the given session 90 * @brief Increases the dupe counter of the handle for the given session
@@ -108,7 +115,7 @@ public:
108 bool can_unlock; //!< If the address region is ready to be unlocked 115 bool can_unlock; //!< If the address region is ready to be unlocked
109 }; 116 };
110 117
111 explicit NvMap(Tegra::Host1x::Host1x& host1x); 118 explicit NvMap(Container& core, Tegra::Host1x::Host1x& host1x);
112 119
113 /** 120 /**
114 * @brief Creates an unallocated handle of the given size 121 * @brief Creates an unallocated handle of the given size
@@ -117,7 +124,7 @@ public:
117 124
118 std::shared_ptr<Handle> GetHandle(Handle::Id handle); 125 std::shared_ptr<Handle> GetHandle(Handle::Id handle);
119 126
120 VAddr GetHandleAddress(Handle::Id handle); 127 DAddr GetHandleAddress(Handle::Id handle);
121 128
122 /** 129 /**
123 * @brief Maps a handle into the SMMU address space 130 * @brief Maps a handle into the SMMU address space
@@ -125,7 +132,7 @@ public:
125 * number of calls to `UnpinHandle` 132 * number of calls to `UnpinHandle`
126 * @return The SMMU virtual address that the handle has been mapped to 133 * @return The SMMU virtual address that the handle has been mapped to
127 */ 134 */
128 u32 PinHandle(Handle::Id handle); 135 DAddr PinHandle(Handle::Id handle, bool low_area_pin);
129 136
130 /** 137 /**
131 * @brief When this has been called an equal number of times to `PinHandle` for the supplied 138 * @brief When this has been called an equal number of times to `PinHandle` for the supplied
@@ -172,5 +179,7 @@ private:
172 * @return If the handle was removed from the map 179 * @return If the handle was removed from the map
173 */ 180 */
174 bool TryRemoveHandle(const Handle& handle_description); 181 bool TryRemoveHandle(const Handle& handle_description);
182
183 Container& core;
175}; 184};
176} // namespace Service::Nvidia::NvCore 185} // namespace Service::Nvidia::NvCore
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h
index a04538d5d..8adaddc60 100644
--- a/src/core/hle/service/nvdrv/devices/nvdevice.h
+++ b/src/core/hle/service/nvdrv/devices/nvdevice.h
@@ -7,6 +7,7 @@
7#include <vector> 7#include <vector>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/hle/service/nvdrv/core/container.h"
10#include "core/hle/service/nvdrv/nvdata.h" 11#include "core/hle/service/nvdrv/nvdata.h"
11 12
12namespace Core { 13namespace Core {
@@ -62,7 +63,7 @@ public:
62 * Called once a device is opened 63 * Called once a device is opened
63 * @param fd The device fd 64 * @param fd The device fd
64 */ 65 */
65 virtual void OnOpen(DeviceFD fd) = 0; 66 virtual void OnOpen(NvCore::SessionId session_id, DeviceFD fd) = 0;
66 67
67 /** 68 /**
68 * Called once a device is closed 69 * Called once a device is closed
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 05a43d8dc..c1ebbd62d 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -35,14 +35,14 @@ NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
35 return NvResult::NotImplemented; 35 return NvResult::NotImplemented;
36} 36}
37 37
38void nvdisp_disp0::OnOpen(DeviceFD fd) {} 38void nvdisp_disp0::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
39void nvdisp_disp0::OnClose(DeviceFD fd) {} 39void nvdisp_disp0::OnClose(DeviceFD fd) {}
40 40
41void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width, 41void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width,
42 u32 height, u32 stride, android::BufferTransformFlags transform, 42 u32 height, u32 stride, android::BufferTransformFlags transform,
43 const Common::Rectangle<int>& crop_rect, 43 const Common::Rectangle<int>& crop_rect,
44 std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences) { 44 std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences) {
45 const VAddr addr = nvmap.GetHandleAddress(buffer_handle); 45 const DAddr addr = nvmap.GetHandleAddress(buffer_handle);
46 LOG_TRACE(Service, 46 LOG_TRACE(Service,
47 "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", 47 "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}",
48 addr, offset, width, height, stride, format); 48 addr, offset, width, height, stride, format);
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index daee05fe8..5f13a50a2 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -32,7 +32,7 @@ public:
32 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 32 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
33 std::span<u8> inline_output) override; 33 std::span<u8> inline_output) override;
34 34
35 void OnOpen(DeviceFD fd) override; 35 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
36 void OnClose(DeviceFD fd) override; 36 void OnClose(DeviceFD fd) override;
37 37
38 /// Performs a screen flip, drawing the buffer pointed to by the handle. 38 /// Performs a screen flip, drawing the buffer pointed to by the handle.
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 6b3639008..e6646ba04 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -86,7 +86,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
86 return NvResult::NotImplemented; 86 return NvResult::NotImplemented;
87} 87}
88 88
89void nvhost_as_gpu::OnOpen(DeviceFD fd) {} 89void nvhost_as_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
90void nvhost_as_gpu::OnClose(DeviceFD fd) {} 90void nvhost_as_gpu::OnClose(DeviceFD fd) {}
91 91
92NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) { 92NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
@@ -206,6 +206,8 @@ void nvhost_as_gpu::FreeMappingLocked(u64 offset) {
206 static_cast<u32>(aligned_size >> page_size_bits)); 206 static_cast<u32>(aligned_size >> page_size_bits));
207 } 207 }
208 208
209 nvmap.UnpinHandle(mapping->handle);
210
209 // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state 211 // Sparse mappings shouldn't be fully unmapped, just returned to their sparse state
210 // Only FreeSpace can unmap them fully 212 // Only FreeSpace can unmap them fully
211 if (mapping->sparse_alloc) { 213 if (mapping->sparse_alloc) {
@@ -293,12 +295,12 @@ NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
293 return NvResult::BadValue; 295 return NvResult::BadValue;
294 } 296 }
295 297
296 VAddr cpu_address{static_cast<VAddr>( 298 DAddr base = nvmap.PinHandle(entry.handle, false);
297 handle->address + 299 DAddr device_address{static_cast<DAddr>(
298 (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))}; 300 base + (static_cast<u64>(entry.handle_offset_big_pages) << vm.big_page_size_bits))};
299 301
300 gmmu->Map(virtual_address, cpu_address, size, static_cast<Tegra::PTEKind>(entry.kind), 302 gmmu->Map(virtual_address, device_address, size,
301 use_big_pages); 303 static_cast<Tegra::PTEKind>(entry.kind), use_big_pages);
302 } 304 }
303 } 305 }
304 306
@@ -331,9 +333,9 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
331 } 333 }
332 334
333 u64 gpu_address{static_cast<u64>(params.offset + params.buffer_offset)}; 335 u64 gpu_address{static_cast<u64>(params.offset + params.buffer_offset)};
334 VAddr cpu_address{mapping->ptr + params.buffer_offset}; 336 VAddr device_address{mapping->ptr + params.buffer_offset};
335 337
336 gmmu->Map(gpu_address, cpu_address, params.mapping_size, 338 gmmu->Map(gpu_address, device_address, params.mapping_size,
337 static_cast<Tegra::PTEKind>(params.kind), mapping->big_page); 339 static_cast<Tegra::PTEKind>(params.kind), mapping->big_page);
338 340
339 return NvResult::Success; 341 return NvResult::Success;
@@ -349,7 +351,8 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
349 return NvResult::BadValue; 351 return NvResult::BadValue;
350 } 352 }
351 353
352 VAddr cpu_address{static_cast<VAddr>(handle->address + params.buffer_offset)}; 354 DAddr device_address{
355 static_cast<DAddr>(nvmap.PinHandle(params.handle, false) + params.buffer_offset)};
353 u64 size{params.mapping_size ? params.mapping_size : handle->orig_size}; 356 u64 size{params.mapping_size ? params.mapping_size : handle->orig_size};
354 357
355 bool big_page{[&]() { 358 bool big_page{[&]() {
@@ -373,15 +376,14 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
373 } 376 }
374 377
375 const bool use_big_pages = alloc->second.big_pages && big_page; 378 const bool use_big_pages = alloc->second.big_pages && big_page;
376 gmmu->Map(params.offset, cpu_address, size, static_cast<Tegra::PTEKind>(params.kind), 379 gmmu->Map(params.offset, device_address, size, static_cast<Tegra::PTEKind>(params.kind),
377 use_big_pages); 380 use_big_pages);
378 381
379 auto mapping{std::make_shared<Mapping>(cpu_address, params.offset, size, true, 382 auto mapping{std::make_shared<Mapping>(params.handle, device_address, params.offset, size,
380 use_big_pages, alloc->second.sparse)}; 383 true, use_big_pages, alloc->second.sparse)};
381 alloc->second.mappings.push_back(mapping); 384 alloc->second.mappings.push_back(mapping);
382 mapping_map[params.offset] = mapping; 385 mapping_map[params.offset] = mapping;
383 } else { 386 } else {
384
385 auto& allocator{big_page ? *vm.big_page_allocator : *vm.small_page_allocator}; 387 auto& allocator{big_page ? *vm.big_page_allocator : *vm.small_page_allocator};
386 u32 page_size{big_page ? vm.big_page_size : VM::YUZU_PAGESIZE}; 388 u32 page_size{big_page ? vm.big_page_size : VM::YUZU_PAGESIZE};
387 u32 page_size_bits{big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS}; 389 u32 page_size_bits{big_page ? vm.big_page_size_bits : VM::PAGE_SIZE_BITS};
@@ -394,11 +396,11 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
394 return NvResult::InsufficientMemory; 396 return NvResult::InsufficientMemory;
395 } 397 }
396 398
397 gmmu->Map(params.offset, cpu_address, Common::AlignUp(size, page_size), 399 gmmu->Map(params.offset, device_address, Common::AlignUp(size, page_size),
398 static_cast<Tegra::PTEKind>(params.kind), big_page); 400 static_cast<Tegra::PTEKind>(params.kind), big_page);
399 401
400 auto mapping{ 402 auto mapping{std::make_shared<Mapping>(params.handle, device_address, params.offset, size,
401 std::make_shared<Mapping>(cpu_address, params.offset, size, false, big_page, false)}; 403 false, big_page, false)};
402 mapping_map[params.offset] = mapping; 404 mapping_map[params.offset] = mapping;
403 } 405 }
404 406
@@ -433,6 +435,8 @@ NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
433 gmmu->Unmap(params.offset, mapping->size); 435 gmmu->Unmap(params.offset, mapping->size);
434 } 436 }
435 437
438 nvmap.UnpinHandle(mapping->handle);
439
436 mapping_map.erase(params.offset); 440 mapping_map.erase(params.offset);
437 } catch (const std::out_of_range&) { 441 } catch (const std::out_of_range&) {
438 LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at 0x{:X}", params.offset); 442 LOG_WARNING(Service_NVDRV, "Couldn't find region to unmap at 0x{:X}", params.offset);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index 79a21683d..7d0a99988 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -55,7 +55,7 @@ public:
55 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 55 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
56 std::span<u8> inline_output) override; 56 std::span<u8> inline_output) override;
57 57
58 void OnOpen(DeviceFD fd) override; 58 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
59 void OnClose(DeviceFD fd) override; 59 void OnClose(DeviceFD fd) override;
60 60
61 Kernel::KEvent* QueryEvent(u32 event_id) override; 61 Kernel::KEvent* QueryEvent(u32 event_id) override;
@@ -159,16 +159,18 @@ private:
159 NvCore::NvMap& nvmap; 159 NvCore::NvMap& nvmap;
160 160
161 struct Mapping { 161 struct Mapping {
162 VAddr ptr; 162 NvCore::NvMap::Handle::Id handle;
163 DAddr ptr;
163 u64 offset; 164 u64 offset;
164 u64 size; 165 u64 size;
165 bool fixed; 166 bool fixed;
166 bool big_page; // Only valid if fixed == false 167 bool big_page; // Only valid if fixed == false
167 bool sparse_alloc; 168 bool sparse_alloc;
168 169
169 Mapping(VAddr ptr_, u64 offset_, u64 size_, bool fixed_, bool big_page_, bool sparse_alloc_) 170 Mapping(NvCore::NvMap::Handle::Id handle_, DAddr ptr_, u64 offset_, u64 size_, bool fixed_,
170 : ptr(ptr_), offset(offset_), size(size_), fixed(fixed_), big_page(big_page_), 171 bool big_page_, bool sparse_alloc_)
171 sparse_alloc(sparse_alloc_) {} 172 : handle(handle_), ptr(ptr_), offset(offset_), size(size_), fixed(fixed_),
173 big_page(big_page_), sparse_alloc(sparse_alloc_) {}
172 }; 174 };
173 175
174 struct Allocation { 176 struct Allocation {
@@ -212,9 +214,6 @@ private:
212 bool initialised{}; 214 bool initialised{};
213 } vm; 215 } vm;
214 std::shared_ptr<Tegra::MemoryManager> gmmu; 216 std::shared_ptr<Tegra::MemoryManager> gmmu;
215
216 // s32 channel{};
217 // u32 big_page_size{VM::DEFAULT_BIG_PAGE_SIZE};
218}; 217};
219 218
220} // namespace Service::Nvidia::Devices 219} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index b8dd34e24..250d01de3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -76,7 +76,7 @@ NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inp
76 return NvResult::NotImplemented; 76 return NvResult::NotImplemented;
77} 77}
78 78
79void nvhost_ctrl::OnOpen(DeviceFD fd) {} 79void nvhost_ctrl::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
80 80
81void nvhost_ctrl::OnClose(DeviceFD fd) {} 81void nvhost_ctrl::OnClose(DeviceFD fd) {}
82 82
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 992124b60..403f1a746 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -32,7 +32,7 @@ public:
32 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 32 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
33 std::span<u8> inline_output) override; 33 std::span<u8> inline_output) override;
34 34
35 void OnOpen(DeviceFD fd) override; 35 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
36 void OnClose(DeviceFD fd) override; 36 void OnClose(DeviceFD fd) override;
37 37
38 Kernel::KEvent* QueryEvent(u32 event_id) override; 38 Kernel::KEvent* QueryEvent(u32 event_id) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 3e0c96456..ddd85678b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -82,7 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
82 return NvResult::NotImplemented; 82 return NvResult::NotImplemented;
83} 83}
84 84
85void nvhost_ctrl_gpu::OnOpen(DeviceFD fd) {} 85void nvhost_ctrl_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
86void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {} 86void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {}
87 87
88NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) { 88NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
index d170299bd..d2ab05b21 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -28,7 +28,7 @@ public:
28 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 28 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
29 std::span<u8> inline_output) override; 29 std::span<u8> inline_output) override;
30 30
31 void OnOpen(DeviceFD fd) override; 31 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
32 void OnClose(DeviceFD fd) override; 32 void OnClose(DeviceFD fd) override;
33 33
34 Kernel::KEvent* QueryEvent(u32 event_id) override; 34 Kernel::KEvent* QueryEvent(u32 event_id) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index b0395c2f0..bf12d69a5 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -120,7 +120,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
120 return NvResult::NotImplemented; 120 return NvResult::NotImplemented;
121} 121}
122 122
123void nvhost_gpu::OnOpen(DeviceFD fd) {} 123void nvhost_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
124void nvhost_gpu::OnClose(DeviceFD fd) {} 124void nvhost_gpu::OnClose(DeviceFD fd) {}
125 125
126NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) { 126NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 88fd228ff..e34a978db 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -47,7 +47,7 @@ public:
47 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 47 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
48 std::span<u8> inline_output) override; 48 std::span<u8> inline_output) override;
49 49
50 void OnOpen(DeviceFD fd) override; 50 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
51 void OnClose(DeviceFD fd) override; 51 void OnClose(DeviceFD fd) override;
52 52
53 Kernel::KEvent* QueryEvent(u32 event_id) override; 53 Kernel::KEvent* QueryEvent(u32 event_id) override;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index f43914e1b..2c0ac2a46 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -35,7 +35,7 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> in
35 case 0x7: 35 case 0x7:
36 return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output); 36 return WrapFixed(this, &nvhost_nvdec::SetSubmitTimeout, input, output);
37 case 0x9: 37 case 0x9:
38 return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output); 38 return WrapFixedVariable(this, &nvhost_nvdec::MapBuffer, input, output, fd);
39 case 0xa: 39 case 0xa:
40 return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output); 40 return WrapFixedVariable(this, &nvhost_nvdec::UnmapBuffer, input, output);
41 default: 41 default:
@@ -68,9 +68,10 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
68 return NvResult::NotImplemented; 68 return NvResult::NotImplemented;
69} 69}
70 70
71void nvhost_nvdec::OnOpen(DeviceFD fd) { 71void nvhost_nvdec::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
72 LOG_INFO(Service_NVDRV, "NVDEC video stream started"); 72 LOG_INFO(Service_NVDRV, "NVDEC video stream started");
73 system.SetNVDECActive(true); 73 system.SetNVDECActive(true);
74 sessions[fd] = session_id;
74} 75}
75 76
76void nvhost_nvdec::OnClose(DeviceFD fd) { 77void nvhost_nvdec::OnClose(DeviceFD fd) {
@@ -81,6 +82,10 @@ void nvhost_nvdec::OnClose(DeviceFD fd) {
81 system.GPU().ClearCdmaInstance(iter->second); 82 system.GPU().ClearCdmaInstance(iter->second);
82 } 83 }
83 system.SetNVDECActive(false); 84 system.SetNVDECActive(false);
85 auto it = sessions.find(fd);
86 if (it != sessions.end()) {
87 sessions.erase(it);
88 }
84} 89}
85 90
86} // namespace Service::Nvidia::Devices 91} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index ad2233c49..627686757 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -20,7 +20,7 @@ public:
20 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 20 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
21 std::span<u8> inline_output) override; 21 std::span<u8> inline_output) override;
22 22
23 void OnOpen(DeviceFD fd) override; 23 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
24 void OnClose(DeviceFD fd) override; 24 void OnClose(DeviceFD fd) override;
25}; 25};
26 26
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 74c701b95..a0a7bfa40 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -8,6 +8,7 @@
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/hle/kernel/k_process.h"
11#include "core/hle/service/nvdrv/core/container.h" 12#include "core/hle/service/nvdrv/core/container.h"
12#include "core/hle/service/nvdrv/core/nvmap.h" 13#include "core/hle/service/nvdrv/core/nvmap.h"
13#include "core/hle/service/nvdrv/core/syncpoint_manager.h" 14#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
@@ -95,6 +96,8 @@ NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, De
95 offset += SliceVectors(data, fence_thresholds, params.fence_count, offset); 96 offset += SliceVectors(data, fence_thresholds, params.fence_count, offset);
96 97
97 auto& gpu = system.GPU(); 98 auto& gpu = system.GPU();
99 auto* session = core.GetSession(sessions[fd]);
100
98 if (gpu.UseNvdec()) { 101 if (gpu.UseNvdec()) {
99 for (std::size_t i = 0; i < syncpt_increments.size(); i++) { 102 for (std::size_t i = 0; i < syncpt_increments.size(); i++) {
100 const SyncptIncr& syncpt_incr = syncpt_increments[i]; 103 const SyncptIncr& syncpt_incr = syncpt_increments[i];
@@ -106,8 +109,8 @@ NvResult nvhost_nvdec_common::Submit(IoctlSubmit& params, std::span<u8> data, De
106 const auto object = nvmap.GetHandle(cmd_buffer.memory_id); 109 const auto object = nvmap.GetHandle(cmd_buffer.memory_id);
107 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;); 110 ASSERT_OR_EXECUTE(object, return NvResult::InvalidState;);
108 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count); 111 Tegra::ChCommandHeaderList cmdlist(cmd_buffer.word_count);
109 system.ApplicationMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(), 112 session->process->GetMemory().ReadBlock(object->address + cmd_buffer.offset, cmdlist.data(),
110 cmdlist.size() * sizeof(u32)); 113 cmdlist.size() * sizeof(u32));
111 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist); 114 gpu.PushCommandBuffer(core.Host1xDeviceFile().fd_to_id[fd], cmdlist);
112 } 115 }
113 // Some games expect command_buffers to be written back 116 // Some games expect command_buffers to be written back
@@ -133,10 +136,12 @@ NvResult nvhost_nvdec_common::GetWaitbase(IoctlGetWaitbase& params) {
133 return NvResult::Success; 136 return NvResult::Success;
134} 137}
135 138
136NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries) { 139NvResult nvhost_nvdec_common::MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries,
140 DeviceFD fd) {
137 const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size())); 141 const size_t num_entries = std::min(params.num_entries, static_cast<u32>(entries.size()));
138 for (size_t i = 0; i < num_entries; i++) { 142 for (size_t i = 0; i < num_entries; i++) {
139 entries[i].map_address = nvmap.PinHandle(entries[i].map_handle); 143 DAddr pin_address = nvmap.PinHandle(entries[i].map_handle, true);
144 entries[i].map_address = static_cast<u32>(pin_address);
140 } 145 }
141 146
142 return NvResult::Success; 147 return NvResult::Success;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
index 7ce748e18..900db81d2 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.h
@@ -4,7 +4,9 @@
4#pragma once 4#pragma once
5 5
6#include <deque> 6#include <deque>
7#include <unordered_map>
7#include <vector> 8#include <vector>
9
8#include "common/common_types.h" 10#include "common/common_types.h"
9#include "common/swap.h" 11#include "common/swap.h"
10#include "core/hle/service/nvdrv/core/syncpoint_manager.h" 12#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
@@ -111,7 +113,7 @@ protected:
111 NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd); 113 NvResult Submit(IoctlSubmit& params, std::span<u8> input, DeviceFD fd);
112 NvResult GetSyncpoint(IoctlGetSyncpoint& params); 114 NvResult GetSyncpoint(IoctlGetSyncpoint& params);
113 NvResult GetWaitbase(IoctlGetWaitbase& params); 115 NvResult GetWaitbase(IoctlGetWaitbase& params);
114 NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); 116 NvResult MapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries, DeviceFD fd);
115 NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries); 117 NvResult UnmapBuffer(IoctlMapBuffer& params, std::span<MapBufferEntry> entries);
116 NvResult SetSubmitTimeout(u32 timeout); 118 NvResult SetSubmitTimeout(u32 timeout);
117 119
@@ -125,6 +127,7 @@ protected:
125 NvCore::NvMap& nvmap; 127 NvCore::NvMap& nvmap;
126 NvCore::ChannelType channel_type; 128 NvCore::ChannelType channel_type;
127 std::array<u32, MaxSyncPoints> device_syncpoints{}; 129 std::array<u32, MaxSyncPoints> device_syncpoints{};
130 std::unordered_map<DeviceFD, NvCore::SessionId> sessions;
128}; 131};
129}; // namespace Devices 132}; // namespace Devices
130} // namespace Service::Nvidia 133} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
index 9e6b86458..f87d53f12 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -44,7 +44,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
44 return NvResult::NotImplemented; 44 return NvResult::NotImplemented;
45} 45}
46 46
47void nvhost_nvjpg::OnOpen(DeviceFD fd) {} 47void nvhost_nvjpg::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
48void nvhost_nvjpg::OnClose(DeviceFD fd) {} 48void nvhost_nvjpg::OnClose(DeviceFD fd) {}
49 49
50NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) { 50NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
index 790c97f6a..def9c254d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -22,7 +22,7 @@ public:
22 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 22 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
23 std::span<u8> inline_output) override; 23 std::span<u8> inline_output) override;
24 24
25 void OnOpen(DeviceFD fd) override; 25 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
26 void OnClose(DeviceFD fd) override; 26 void OnClose(DeviceFD fd) override;
27 27
28private: 28private:
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index 87f8d7c22..bf090f5eb 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -33,7 +33,7 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu
33 case 0x3: 33 case 0x3:
34 return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output); 34 return WrapFixed(this, &nvhost_vic::GetWaitbase, input, output);
35 case 0x9: 35 case 0x9:
36 return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output); 36 return WrapFixedVariable(this, &nvhost_vic::MapBuffer, input, output, fd);
37 case 0xa: 37 case 0xa:
38 return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output); 38 return WrapFixedVariable(this, &nvhost_vic::UnmapBuffer, input, output);
39 default: 39 default:
@@ -68,7 +68,9 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
68 return NvResult::NotImplemented; 68 return NvResult::NotImplemented;
69} 69}
70 70
71void nvhost_vic::OnOpen(DeviceFD fd) {} 71void nvhost_vic::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
72 sessions[fd] = session_id;
73}
72 74
73void nvhost_vic::OnClose(DeviceFD fd) { 75void nvhost_vic::OnClose(DeviceFD fd) {
74 auto& host1x_file = core.Host1xDeviceFile(); 76 auto& host1x_file = core.Host1xDeviceFile();
@@ -76,6 +78,7 @@ void nvhost_vic::OnClose(DeviceFD fd) {
76 if (iter != host1x_file.fd_to_id.end()) { 78 if (iter != host1x_file.fd_to_id.end()) {
77 system.GPU().ClearCdmaInstance(iter->second); 79 system.GPU().ClearCdmaInstance(iter->second);
78 } 80 }
81 sessions.erase(fd);
79} 82}
80 83
81} // namespace Service::Nvidia::Devices 84} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
index cadbcb0a5..0cc04354a 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -19,7 +19,7 @@ public:
19 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 19 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
20 std::span<u8> inline_output) override; 20 std::span<u8> inline_output) override;
21 21
22 void OnOpen(DeviceFD fd) override; 22 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
23 void OnClose(DeviceFD fd) override; 23 void OnClose(DeviceFD fd) override;
24}; 24};
25} // namespace Service::Nvidia::Devices 25} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 71b2e62ec..da61a3bfe 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -36,9 +36,9 @@ NvResult nvmap::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input,
36 case 0x3: 36 case 0x3:
37 return WrapFixed(this, &nvmap::IocFromId, input, output); 37 return WrapFixed(this, &nvmap::IocFromId, input, output);
38 case 0x4: 38 case 0x4:
39 return WrapFixed(this, &nvmap::IocAlloc, input, output); 39 return WrapFixed(this, &nvmap::IocAlloc, input, output, fd);
40 case 0x5: 40 case 0x5:
41 return WrapFixed(this, &nvmap::IocFree, input, output); 41 return WrapFixed(this, &nvmap::IocFree, input, output, fd);
42 case 0x9: 42 case 0x9:
43 return WrapFixed(this, &nvmap::IocParam, input, output); 43 return WrapFixed(this, &nvmap::IocParam, input, output);
44 case 0xe: 44 case 0xe:
@@ -67,8 +67,15 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, st
67 return NvResult::NotImplemented; 67 return NvResult::NotImplemented;
68} 68}
69 69
70void nvmap::OnOpen(DeviceFD fd) {} 70void nvmap::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
71void nvmap::OnClose(DeviceFD fd) {} 71 sessions[fd] = session_id;
72}
73void nvmap::OnClose(DeviceFD fd) {
74 auto it = sessions.find(fd);
75 if (it != sessions.end()) {
76 sessions.erase(it);
77 }
78}
72 79
73NvResult nvmap::IocCreate(IocCreateParams& params) { 80NvResult nvmap::IocCreate(IocCreateParams& params) {
74 LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size); 81 LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size);
@@ -87,7 +94,7 @@ NvResult nvmap::IocCreate(IocCreateParams& params) {
87 return NvResult::Success; 94 return NvResult::Success;
88} 95}
89 96
90NvResult nvmap::IocAlloc(IocAllocParams& params) { 97NvResult nvmap::IocAlloc(IocAllocParams& params, DeviceFD fd) {
91 LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address); 98 LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.address);
92 99
93 if (!params.handle) { 100 if (!params.handle) {
@@ -116,15 +123,15 @@ NvResult nvmap::IocAlloc(IocAllocParams& params) {
116 return NvResult::InsufficientMemory; 123 return NvResult::InsufficientMemory;
117 } 124 }
118 125
119 const auto result = 126 const auto result = handle_description->Alloc(params.flags, params.align, params.kind,
120 handle_description->Alloc(params.flags, params.align, params.kind, params.address); 127 params.address, sessions[fd]);
121 if (result != NvResult::Success) { 128 if (result != NvResult::Success) {
122 LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle); 129 LOG_CRITICAL(Service_NVDRV, "Object failed to allocate, handle={:08X}", params.handle);
123 return result; 130 return result;
124 } 131 }
125 bool is_out_io{}; 132 bool is_out_io{};
126 ASSERT(system.ApplicationProcess() 133 auto process = container.GetSession(sessions[fd])->process;
127 ->GetPageTable() 134 ASSERT(process->GetPageTable()
128 .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address, 135 .LockForMapDeviceAddressSpace(&is_out_io, handle_description->address,
129 handle_description->size, 136 handle_description->size,
130 Kernel::KMemoryPermission::None, true, false) 137 Kernel::KMemoryPermission::None, true, false)
@@ -224,7 +231,7 @@ NvResult nvmap::IocParam(IocParamParams& params) {
224 return NvResult::Success; 231 return NvResult::Success;
225} 232}
226 233
227NvResult nvmap::IocFree(IocFreeParams& params) { 234NvResult nvmap::IocFree(IocFreeParams& params, DeviceFD fd) {
228 LOG_DEBUG(Service_NVDRV, "called"); 235 LOG_DEBUG(Service_NVDRV, "called");
229 236
230 if (!params.handle) { 237 if (!params.handle) {
@@ -233,9 +240,9 @@ NvResult nvmap::IocFree(IocFreeParams& params) {
233 } 240 }
234 241
235 if (auto freeInfo{file.FreeHandle(params.handle, false)}) { 242 if (auto freeInfo{file.FreeHandle(params.handle, false)}) {
243 auto process = container.GetSession(sessions[fd])->process;
236 if (freeInfo->can_unlock) { 244 if (freeInfo->can_unlock) {
237 ASSERT(system.ApplicationProcess() 245 ASSERT(process->GetPageTable()
238 ->GetPageTable()
239 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size) 246 .UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size)
240 .IsSuccess()); 247 .IsSuccess());
241 } 248 }
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 049c11028..d07d85f88 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -33,7 +33,7 @@ public:
33 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output, 33 NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
34 std::span<u8> inline_output) override; 34 std::span<u8> inline_output) override;
35 35
36 void OnOpen(DeviceFD fd) override; 36 void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
37 void OnClose(DeviceFD fd) override; 37 void OnClose(DeviceFD fd) override;
38 38
39 enum class HandleParameterType : u32_le { 39 enum class HandleParameterType : u32_le {
@@ -100,11 +100,11 @@ public:
100 static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size"); 100 static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size");
101 101
102 NvResult IocCreate(IocCreateParams& params); 102 NvResult IocCreate(IocCreateParams& params);
103 NvResult IocAlloc(IocAllocParams& params); 103 NvResult IocAlloc(IocAllocParams& params, DeviceFD fd);
104 NvResult IocGetId(IocGetIdParams& params); 104 NvResult IocGetId(IocGetIdParams& params);
105 NvResult IocFromId(IocFromIdParams& params); 105 NvResult IocFromId(IocFromIdParams& params);
106 NvResult IocParam(IocParamParams& params); 106 NvResult IocParam(IocParamParams& params);
107 NvResult IocFree(IocFreeParams& params); 107 NvResult IocFree(IocFreeParams& params, DeviceFD fd);
108 108
109private: 109private:
110 /// Id to use for the next handle that is created. 110 /// Id to use for the next handle that is created.
@@ -115,6 +115,7 @@ private:
115 115
116 NvCore::Container& container; 116 NvCore::Container& container;
117 NvCore::NvMap& file; 117 NvCore::NvMap& file;
118 std::unordered_map<DeviceFD, NvCore::SessionId> sessions;
118}; 119};
119 120
120} // namespace Service::Nvidia::Devices 121} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 9e46ee8dd..cb256e5b4 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -45,13 +45,22 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) {
45void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) { 45void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
46 auto server_manager = std::make_unique<ServerManager>(system); 46 auto server_manager = std::make_unique<ServerManager>(system);
47 auto module = std::make_shared<Module>(system); 47 auto module = std::make_shared<Module>(system);
48 server_manager->RegisterNamedService("nvdrv", std::make_shared<NVDRV>(system, module, "nvdrv")); 48 const auto NvdrvInterfaceFactoryForApplication = [&, module] {
49 server_manager->RegisterNamedService("nvdrv:a", 49 return std::make_shared<NVDRV>(system, module, "nvdrv");
50 std::make_shared<NVDRV>(system, module, "nvdrv:a")); 50 };
51 server_manager->RegisterNamedService("nvdrv:s", 51 const auto NvdrvInterfaceFactoryForApplets = [&, module] {
52 std::make_shared<NVDRV>(system, module, "nvdrv:s")); 52 return std::make_shared<NVDRV>(system, module, "nvdrv:a");
53 server_manager->RegisterNamedService("nvdrv:t", 53 };
54 std::make_shared<NVDRV>(system, module, "nvdrv:t")); 54 const auto NvdrvInterfaceFactoryForSysmodules = [&, module] {
55 return std::make_shared<NVDRV>(system, module, "nvdrv:s");
56 };
57 const auto NvdrvInterfaceFactoryForTesting = [&, module] {
58 return std::make_shared<NVDRV>(system, module, "nvdrv:t");
59 };
60 server_manager->RegisterNamedService("nvdrv", NvdrvInterfaceFactoryForApplication);
61 server_manager->RegisterNamedService("nvdrv:a", NvdrvInterfaceFactoryForApplets);
62 server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules);
63 server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting);
55 server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system)); 64 server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
56 nvnflinger.SetNVDrvInstance(module); 65 nvnflinger.SetNVDrvInstance(module);
57 ServerManager::RunServer(std::move(server_manager)); 66 ServerManager::RunServer(std::move(server_manager));
@@ -113,7 +122,7 @@ NvResult Module::VerifyFD(DeviceFD fd) const {
113 return NvResult::Success; 122 return NvResult::Success;
114} 123}
115 124
116DeviceFD Module::Open(const std::string& device_name) { 125DeviceFD Module::Open(const std::string& device_name, NvCore::SessionId session_id) {
117 auto it = builders.find(device_name); 126 auto it = builders.find(device_name);
118 if (it == builders.end()) { 127 if (it == builders.end()) {
119 LOG_ERROR(Service_NVDRV, "Trying to open unknown device {}", device_name); 128 LOG_ERROR(Service_NVDRV, "Trying to open unknown device {}", device_name);
@@ -124,7 +133,7 @@ DeviceFD Module::Open(const std::string& device_name) {
124 auto& builder = it->second; 133 auto& builder = it->second;
125 auto device = builder(fd)->second; 134 auto device = builder(fd)->second;
126 135
127 device->OnOpen(fd); 136 device->OnOpen(session_id, fd);
128 137
129 return fd; 138 return fd;
130} 139}
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index d8622b3ca..c594f0e5e 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -77,7 +77,7 @@ public:
77 NvResult VerifyFD(DeviceFD fd) const; 77 NvResult VerifyFD(DeviceFD fd) const;
78 78
79 /// Opens a device node and returns a file descriptor to it. 79 /// Opens a device node and returns a file descriptor to it.
80 DeviceFD Open(const std::string& device_name); 80 DeviceFD Open(const std::string& device_name, NvCore::SessionId session_id);
81 81
82 /// Sends an ioctl command to the specified file descriptor. 82 /// Sends an ioctl command to the specified file descriptor.
83 NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output); 83 NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output);
@@ -93,6 +93,10 @@ public:
93 93
94 NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event); 94 NvResult QueryEvent(DeviceFD fd, u32 event_id, Kernel::KEvent*& event);
95 95
96 NvCore::Container& GetContainer() {
97 return container;
98 }
99
96private: 100private:
97 friend class EventInterface; 101 friend class EventInterface;
98 friend class Service::Nvnflinger::Nvnflinger; 102 friend class Service::Nvnflinger::Nvnflinger;
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.cpp b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
index c8a880e84..ffe72f281 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.cpp
@@ -3,8 +3,11 @@
3// SPDX-License-Identifier: GPL-3.0-or-later 3// SPDX-License-Identifier: GPL-3.0-or-later
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/scope_exit.h"
7#include "common/string_util.h"
6#include "core/core.h" 8#include "core/core.h"
7#include "core/hle/kernel/k_event.h" 9#include "core/hle/kernel/k_event.h"
10#include "core/hle/kernel/k_process.h"
8#include "core/hle/kernel/k_readable_event.h" 11#include "core/hle/kernel/k_readable_event.h"
9#include "core/hle/service/ipc_helpers.h" 12#include "core/hle/service/ipc_helpers.h"
10#include "core/hle/service/nvdrv/nvdata.h" 13#include "core/hle/service/nvdrv/nvdata.h"
@@ -27,7 +30,7 @@ void NVDRV::Open(HLERequestContext& ctx) {
27 } 30 }
28 31
29 const auto& buffer = ctx.ReadBuffer(); 32 const auto& buffer = ctx.ReadBuffer();
30 const std::string device_name(buffer.begin(), buffer.end()); 33 const std::string device_name(Common::StringFromBuffer(buffer));
31 34
32 if (device_name == "/dev/nvhost-prof-gpu") { 35 if (device_name == "/dev/nvhost-prof-gpu") {
33 rb.Push<DeviceFD>(0); 36 rb.Push<DeviceFD>(0);
@@ -37,7 +40,7 @@ void NVDRV::Open(HLERequestContext& ctx) {
37 return; 40 return;
38 } 41 }
39 42
40 DeviceFD fd = nvdrv->Open(device_name); 43 DeviceFD fd = nvdrv->Open(device_name, session_id);
41 44
42 rb.Push<DeviceFD>(fd); 45 rb.Push<DeviceFD>(fd);
43 rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed); 46 rb.PushEnum(fd != INVALID_NVDRV_FD ? NvResult::Success : NvResult::FileOperationFailed);
@@ -150,12 +153,29 @@ void NVDRV::Close(HLERequestContext& ctx) {
150 153
151void NVDRV::Initialize(HLERequestContext& ctx) { 154void NVDRV::Initialize(HLERequestContext& ctx) {
152 LOG_WARNING(Service_NVDRV, "(STUBBED) called"); 155 LOG_WARNING(Service_NVDRV, "(STUBBED) called");
156 IPC::ResponseBuilder rb{ctx, 3};
157 SCOPE_EXIT({
158 rb.Push(ResultSuccess);
159 rb.PushEnum(NvResult::Success);
160 });
153 161
154 is_initialized = true; 162 if (is_initialized) {
163 // No need to initialize again
164 return;
165 }
155 166
156 IPC::ResponseBuilder rb{ctx, 3}; 167 IPC::RequestParser rp{ctx};
157 rb.Push(ResultSuccess); 168 const auto process_handle{ctx.GetCopyHandle(0)};
158 rb.PushEnum(NvResult::Success); 169 // The transfer memory is lent to nvdrv as a work buffer since nvdrv is
170 // unable to allocate as much memory on its own. For HLE it's unnecessary to handle it
171 [[maybe_unused]] const auto transfer_memory_handle{ctx.GetCopyHandle(1)};
172 [[maybe_unused]] const auto transfer_memory_size = rp.Pop<u32>();
173
174 auto& container = nvdrv->GetContainer();
175 auto process = ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle);
176 session_id = container.OpenSession(process.GetPointerUnsafe());
177
178 is_initialized = true;
159} 179}
160 180
161void NVDRV::QueryEvent(HLERequestContext& ctx) { 181void NVDRV::QueryEvent(HLERequestContext& ctx) {
@@ -242,6 +262,9 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char*
242 RegisterHandlers(functions); 262 RegisterHandlers(functions);
243} 263}
244 264
245NVDRV::~NVDRV() = default; 265NVDRV::~NVDRV() {
266 auto& container = nvdrv->GetContainer();
267 container.CloseSession(session_id);
268}
246 269
247} // namespace Service::Nvidia 270} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvdrv_interface.h b/src/core/hle/service/nvdrv/nvdrv_interface.h
index 6e98115dc..f2195ae1e 100644
--- a/src/core/hle/service/nvdrv/nvdrv_interface.h
+++ b/src/core/hle/service/nvdrv/nvdrv_interface.h
@@ -35,6 +35,7 @@ private:
35 35
36 u64 pid{}; 36 u64 pid{};
37 bool is_initialized{}; 37 bool is_initialized{};
38 NvCore::SessionId session_id{};
38 Common::ScratchBuffer<u8> output_buffer; 39 Common::ScratchBuffer<u8> output_buffer;
39 Common::ScratchBuffer<u8> inline_output_buffer; 40 Common::ScratchBuffer<u8> inline_output_buffer;
40}; 41};
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
index 2fef6cc1a..86e272b41 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
@@ -87,19 +87,20 @@ Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap,
87 R_SUCCEED(); 87 R_SUCCEED();
88} 88}
89 89
90Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { 90Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Nvidia::DeviceFD nvmap_fd) {
91 // Free the handle. 91 // Free the handle.
92 Nvidia::Devices::nvmap::IocFreeParams free_params{ 92 Nvidia::Devices::nvmap::IocFreeParams free_params{
93 .handle = handle, 93 .handle = handle,
94 }; 94 };
95 R_UNLESS(nvmap.IocFree(free_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); 95 R_UNLESS(nvmap.IocFree(free_params, nvmap_fd) == Nvidia::NvResult::Success,
96 VI::ResultOperationFailed);
96 97
97 // We succeeded. 98 // We succeeded.
98 R_SUCCEED(); 99 R_SUCCEED();
99} 100}
100 101
101Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, 102Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer,
102 u32 size) { 103 u32 size, Nvidia::DeviceFD nvmap_fd) {
103 // Assign the allocated memory to the handle. 104 // Assign the allocated memory to the handle.
104 Nvidia::Devices::nvmap::IocAllocParams alloc_params{ 105 Nvidia::Devices::nvmap::IocAllocParams alloc_params{
105 .handle = handle, 106 .handle = handle,
@@ -109,16 +110,16 @@ Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::Proce
109 .kind = 0, 110 .kind = 0,
110 .address = GetInteger(buffer), 111 .address = GetInteger(buffer),
111 }; 112 };
112 R_UNLESS(nvmap.IocAlloc(alloc_params) == Nvidia::NvResult::Success, VI::ResultOperationFailed); 113 R_UNLESS(nvmap.IocAlloc(alloc_params, nvmap_fd) == Nvidia::NvResult::Success,
114 VI::ResultOperationFailed);
113 115
114 // We succeeded. 116 // We succeeded.
115 R_SUCCEED(); 117 R_SUCCEED();
116} 118}
117 119
118Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, 120Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd,
119 Common::ProcessAddress buffer, u32 size) { 121 Common::ProcessAddress buffer, u32 size) {
120 // Get the nvmap device. 122 // Get the nvmap device.
121 auto nvmap_fd = nvdrv.Open("/dev/nvmap");
122 auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); 123 auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
123 ASSERT(nvmap != nullptr); 124 ASSERT(nvmap != nullptr);
124 125
@@ -127,11 +128,11 @@ Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv,
127 128
128 // Ensure we maintain a clean state on failure. 129 // Ensure we maintain a clean state on failure.
129 ON_RESULT_FAILURE { 130 ON_RESULT_FAILURE {
130 ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle))); 131 ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd)));
131 }; 132 };
132 133
133 // Assign the allocated memory to the handle. 134 // Assign the allocated memory to the handle.
134 R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size)); 135 R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd));
135} 136}
136 137
137constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; 138constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888;
@@ -197,9 +198,13 @@ Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u
197 std::addressof(m_buffer_page_group), m_system, 198 std::addressof(m_buffer_page_group), m_system,
198 SharedBufferSize)); 199 SharedBufferSize));
199 200
201 auto& container = m_nvdrv->GetContainer();
202 m_session_id = container.OpenSession(m_system.ApplicationProcess());
203 m_nvmap_fd = m_nvdrv->Open("/dev/nvmap", m_session_id);
204
200 // Create an nvmap handle for the buffer and assign the memory to it. 205 // Create an nvmap handle for the buffer and assign the memory to it.
201 R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, map_address, 206 R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, m_nvmap_fd,
202 SharedBufferSize)); 207 map_address, SharedBufferSize));
203 208
204 // Record the display id. 209 // Record the display id.
205 m_display_id = display_id; 210 m_display_id = display_id;
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
index c809c01b4..033bf4bbe 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
@@ -4,6 +4,8 @@
4#pragma once 4#pragma once
5 5
6#include "common/math_util.h" 6#include "common/math_util.h"
7#include "core/hle/service/nvdrv/core/container.h"
8#include "core/hle/service/nvdrv/nvdata.h"
7#include "core/hle/service/nvnflinger/nvnflinger.h" 9#include "core/hle/service/nvnflinger/nvnflinger.h"
8#include "core/hle/service/nvnflinger/ui/fence.h" 10#include "core/hle/service/nvnflinger/ui/fence.h"
9 11
@@ -53,7 +55,8 @@ private:
53 u64 m_layer_id = 0; 55 u64 m_layer_id = 0;
54 u32 m_buffer_nvmap_handle = 0; 56 u32 m_buffer_nvmap_handle = 0;
55 SharedMemoryPoolLayout m_pool_layout = {}; 57 SharedMemoryPoolLayout m_pool_layout = {};
56 58 Nvidia::DeviceFD m_nvmap_fd = {};
59 Nvidia::NvCore::SessionId m_session_id = {};
57 std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; 60 std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
58 61
59 std::mutex m_guard; 62 std::mutex m_guard;
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index 0469110e8..71d6fdb0c 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -112,9 +112,7 @@ void Nvnflinger::ShutdownLayers() {
112 { 112 {
113 const auto lock_guard = Lock(); 113 const auto lock_guard = Lock();
114 for (auto& display : displays) { 114 for (auto& display : displays) {
115 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { 115 display.Abandon();
116 display.GetLayer(layer).GetConsumer().Abandon();
117 }
118 } 116 }
119 117
120 is_abandoned = true; 118 is_abandoned = true;
@@ -126,7 +124,7 @@ void Nvnflinger::ShutdownLayers() {
126 124
127void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { 125void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
128 nvdrv = std::move(instance); 126 nvdrv = std::move(instance);
129 disp_fd = nvdrv->Open("/dev/nvdisp_disp0"); 127 disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
130} 128}
131 129
132std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) { 130std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) {
@@ -176,24 +174,28 @@ void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
176 display.CreateLayer(layer_id, buffer_id, nvdrv->container); 174 display.CreateLayer(layer_id, buffer_id, nvdrv->container);
177} 175}
178 176
179void Nvnflinger::OpenLayer(u64 layer_id) { 177bool Nvnflinger::OpenLayer(u64 layer_id) {
180 const auto lock_guard = Lock(); 178 const auto lock_guard = Lock();
181 179
182 for (auto& display : displays) { 180 for (auto& display : displays) {
183 if (auto* layer = display.FindLayer(layer_id); layer) { 181 if (auto* layer = display.FindLayer(layer_id); layer) {
184 layer->Open(); 182 return layer->Open();
185 } 183 }
186 } 184 }
185
186 return false;
187} 187}
188 188
189void Nvnflinger::CloseLayer(u64 layer_id) { 189bool Nvnflinger::CloseLayer(u64 layer_id) {
190 const auto lock_guard = Lock(); 190 const auto lock_guard = Lock();
191 191
192 for (auto& display : displays) { 192 for (auto& display : displays) {
193 if (auto* layer = display.FindLayer(layer_id); layer) { 193 if (auto* layer = display.FindLayer(layer_id); layer) {
194 layer->Close(); 194 return layer->Close();
195 } 195 }
196 } 196 }
197
198 return false;
197} 199}
198 200
199void Nvnflinger::DestroyLayer(u64 layer_id) { 201void Nvnflinger::DestroyLayer(u64 layer_id) {
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index 871285764..a60e0ae6b 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -74,10 +74,10 @@ public:
74 [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); 74 [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id);
75 75
76 /// Opens a layer on all displays for the given layer ID. 76 /// Opens a layer on all displays for the given layer ID.
77 void OpenLayer(u64 layer_id); 77 bool OpenLayer(u64 layer_id);
78 78
79 /// Closes a layer on all displays for the given layer ID. 79 /// Closes a layer on all displays for the given layer ID.
80 void CloseLayer(u64 layer_id); 80 bool CloseLayer(u64 layer_id);
81 81
82 /// Destroys the given layer ID. 82 /// Destroys the given layer ID.
83 void DestroyLayer(u64 layer_id); 83 void DestroyLayer(u64 layer_id);
diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp
index ce70946ec..ede2a1193 100644
--- a/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp
+++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.cpp
@@ -22,11 +22,13 @@ GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
22 : NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) { 22 : NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) {
23 if (this->BufferId() > 0) { 23 if (this->BufferId() > 0) {
24 m_nvmap->DuplicateHandle(this->BufferId(), true); 24 m_nvmap->DuplicateHandle(this->BufferId(), true);
25 m_nvmap->PinHandle(this->BufferId(), false);
25 } 26 }
26} 27}
27 28
28GraphicBuffer::~GraphicBuffer() { 29GraphicBuffer::~GraphicBuffer() {
29 if (m_nvmap != nullptr && this->BufferId() > 0) { 30 if (m_nvmap != nullptr && this->BufferId() > 0) {
31 m_nvmap->UnpinHandle(this->BufferId());
30 m_nvmap->FreeHandle(this->BufferId(), true); 32 m_nvmap->FreeHandle(this->BufferId(), true);
31 } 33 }
32} 34}
diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp
index 688c54b58..f40a1c8f3 100644
--- a/src/core/hle/service/set/system_settings_server.cpp
+++ b/src/core/hle/service/set/system_settings_server.cpp
@@ -709,12 +709,12 @@ void ISystemSettingsServer::GetSettingsItemValueSize(HLERequestContext& ctx) {
709 // The category of the setting. This corresponds to the top-level keys of 709 // The category of the setting. This corresponds to the top-level keys of
710 // system_settings.ini. 710 // system_settings.ini.
711 const auto setting_category_buf{ctx.ReadBuffer(0)}; 711 const auto setting_category_buf{ctx.ReadBuffer(0)};
712 const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()}; 712 const std::string setting_category{Common::StringFromBuffer(setting_category_buf)};
713 713
714 // The name of the setting. This corresponds to the second-level keys of 714 // The name of the setting. This corresponds to the second-level keys of
715 // system_settings.ini. 715 // system_settings.ini.
716 const auto setting_name_buf{ctx.ReadBuffer(1)}; 716 const auto setting_name_buf{ctx.ReadBuffer(1)};
717 const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()}; 717 const std::string setting_name{Common::StringFromBuffer(setting_name_buf)};
718 718
719 auto settings{GetSettings()}; 719 auto settings{GetSettings()};
720 u64 response_size{0}; 720 u64 response_size{0};
@@ -732,12 +732,12 @@ void ISystemSettingsServer::GetSettingsItemValue(HLERequestContext& ctx) {
732 // The category of the setting. This corresponds to the top-level keys of 732 // The category of the setting. This corresponds to the top-level keys of
733 // system_settings.ini. 733 // system_settings.ini.
734 const auto setting_category_buf{ctx.ReadBuffer(0)}; 734 const auto setting_category_buf{ctx.ReadBuffer(0)};
735 const std::string setting_category{setting_category_buf.begin(), setting_category_buf.end()}; 735 const std::string setting_category{Common::StringFromBuffer(setting_category_buf)};
736 736
737 // The name of the setting. This corresponds to the second-level keys of 737 // The name of the setting. This corresponds to the second-level keys of
738 // system_settings.ini. 738 // system_settings.ini.
739 const auto setting_name_buf{ctx.ReadBuffer(1)}; 739 const auto setting_name_buf{ctx.ReadBuffer(1)};
740 const std::string setting_name{setting_name_buf.begin(), setting_name_buf.end()}; 740 const std::string setting_name{Common::StringFromBuffer(setting_name_buf)};
741 741
742 std::vector<u8> value; 742 std::vector<u8> value;
743 auto response = GetSettingsItemValue(value, setting_category, setting_name); 743 auto response = GetSettingsItemValue(value, setting_category, setting_name);
@@ -1036,6 +1036,11 @@ void ISystemSettingsServer::SetBluetoothEnableFlag(HLERequestContext& ctx) {
1036} 1036}
1037 1037
1038void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) { 1038void ISystemSettingsServer::GetMiiAuthorId(HLERequestContext& ctx) {
1039 if (m_system_settings.mii_author_id.IsInvalid()) {
1040 m_system_settings.mii_author_id = Common::UUID::MakeDefault();
1041 SetSaveNeeded();
1042 }
1043
1039 LOG_INFO(Service_SET, "called, author_id={}", 1044 LOG_INFO(Service_SET, "called, author_id={}",
1040 m_system_settings.mii_author_id.FormattedString()); 1045 m_system_settings.mii_author_id.FormattedString());
1041 1046
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index e2d9cd98a..725311c53 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -91,6 +91,10 @@ void Display::CreateLayer(u64 layer_id, u32 binder_id,
91 layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, 91 layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer,
92 std::move(buffer_item_consumer))); 92 std::move(buffer_item_consumer)));
93 93
94 if (is_abandoned) {
95 this->FindLayer(layer_id)->GetConsumer().Abandon();
96 }
97
94 hos_binder_driver_server.RegisterProducer(std::move(producer)); 98 hos_binder_driver_server.RegisterProducer(std::move(producer));
95} 99}
96 100
@@ -103,6 +107,13 @@ void Display::DestroyLayer(u64 layer_id) {
103 [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); 107 [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; });
104} 108}
105 109
110void Display::Abandon() {
111 for (auto& layer : layers) {
112 layer->GetConsumer().Abandon();
113 }
114 is_abandoned = true;
115}
116
106Layer* Display::FindLayer(u64 layer_id) { 117Layer* Display::FindLayer(u64 layer_id) {
107 const auto itr = 118 const auto itr =
108 std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { 119 std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) {
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 7e68ee79b..8eb8a5155 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -98,6 +98,8 @@ public:
98 layers.clear(); 98 layers.clear();
99 } 99 }
100 100
101 void Abandon();
102
101 /// Attempts to find a layer with the given ID. 103 /// Attempts to find a layer with the given ID.
102 /// 104 ///
103 /// @param layer_id The layer ID. 105 /// @param layer_id The layer ID.
@@ -124,6 +126,7 @@ private:
124 126
125 std::vector<std::unique_ptr<Layer>> layers; 127 std::vector<std::unique_ptr<Layer>> layers;
126 Kernel::KEvent* vsync_event{}; 128 Kernel::KEvent* vsync_event{};
129 bool is_abandoned{};
127}; 130};
128 131
129} // namespace Service::VI 132} // namespace Service::VI
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h
index 295005e23..f95e2dc71 100644
--- a/src/core/hle/service/vi/layer/vi_layer.h
+++ b/src/core/hle/service/vi/layer/vi_layer.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <memory> 6#include <memory>
7#include <utility>
7 8
8#include "common/common_types.h" 9#include "common/common_types.h"
9 10
@@ -75,12 +76,12 @@ public:
75 return open; 76 return open;
76 } 77 }
77 78
78 void Close() { 79 bool Close() {
79 open = false; 80 return std::exchange(open, false);
80 } 81 }
81 82
82 void Open() { 83 bool Open() {
83 open = true; 84 return !std::exchange(open, true);
84 } 85 }
85 86
86private: 87private:
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 39d5be90d..1f3d82c57 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -15,6 +15,7 @@
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/math_util.h" 16#include "common/math_util.h"
17#include "common/settings.h" 17#include "common/settings.h"
18#include "common/string_util.h"
18#include "common/swap.h" 19#include "common/swap.h"
19#include "core/core_timing.h" 20#include "core/core_timing.h"
20#include "core/hle/kernel/k_readable_event.h" 21#include "core/hle/kernel/k_readable_event.h"
@@ -694,9 +695,7 @@ private:
694 void OpenLayer(HLERequestContext& ctx) { 695 void OpenLayer(HLERequestContext& ctx) {
695 IPC::RequestParser rp{ctx}; 696 IPC::RequestParser rp{ctx};
696 const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); 697 const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
697 const auto end = std::find(name_buf.begin(), name_buf.end(), '\0'); 698 const std::string display_name(Common::StringFromBuffer(name_buf));
698
699 const std::string display_name(name_buf.begin(), end);
700 699
701 const u64 layer_id = rp.Pop<u64>(); 700 const u64 layer_id = rp.Pop<u64>();
702 const u64 aruid = rp.Pop<u64>(); 701 const u64 aruid = rp.Pop<u64>();
@@ -719,7 +718,12 @@ private:
719 return; 718 return;
720 } 719 }
721 720
722 nvnflinger.OpenLayer(layer_id); 721 if (!nvnflinger.OpenLayer(layer_id)) {
722 LOG_WARNING(Service_VI, "Tried to open layer which was already open");
723 IPC::ResponseBuilder rb{ctx, 2};
724 rb.Push(ResultOperationFailed);
725 return;
726 }
723 727
724 android::OutputParcel parcel; 728 android::OutputParcel parcel;
725 parcel.WriteInterface(NativeWindow{*buffer_queue_id}); 729 parcel.WriteInterface(NativeWindow{*buffer_queue_id});
@@ -737,7 +741,12 @@ private:
737 741
738 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); 742 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
739 743
740 nvnflinger.CloseLayer(layer_id); 744 if (!nvnflinger.CloseLayer(layer_id)) {
745 LOG_WARNING(Service_VI, "Tried to close layer which was not open");
746 IPC::ResponseBuilder rb{ctx, 2};
747 rb.Push(ResultOperationFailed);
748 return;
749 }
741 750
742 IPC::ResponseBuilder rb{ctx, 2}; 751 IPC::ResponseBuilder rb{ctx, 2};
743 rb.Push(ResultSuccess); 752 rb.Push(ResultSuccess);
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index 28116ff3a..3016d5f25 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -10,6 +10,7 @@
10#include "core/file_sys/nca_metadata.h" 10#include "core/file_sys/nca_metadata.h"
11#include "core/file_sys/patch_manager.h" 11#include "core/file_sys/patch_manager.h"
12#include "core/file_sys/registered_cache.h" 12#include "core/file_sys/registered_cache.h"
13#include "core/file_sys/romfs_factory.h"
13#include "core/file_sys/submission_package.h" 14#include "core/file_sys/submission_package.h"
14#include "core/hle/kernel/k_process.h" 15#include "core/hle/kernel/k_process.h"
15#include "core/hle/service/filesystem/filesystem.h" 16#include "core/hle/service/filesystem/filesystem.h"
@@ -109,6 +110,13 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
109 return result; 110 return result;
110 } 111 }
111 112
113 if (nsp->IsExtractedType()) {
114 system.GetFileSystemController().RegisterProcess(
115 process.GetProcessId(), {},
116 std::make_shared<FileSys::RomFSFactory>(*this, system.GetContentProvider(),
117 system.GetFileSystemController()));
118 }
119
112 FileSys::VirtualFile update_raw; 120 FileSys::VirtualFile update_raw;
113 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) { 121 if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
114 system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(), 122 system.GetFileSystemController().SetPackedUpdate(process.GetProcessId(),
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 8176a41be..1c218566f 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -24,6 +24,8 @@
24#include "core/hle/kernel/k_process.h" 24#include "core/hle/kernel/k_process.h"
25#include "core/memory.h" 25#include "core/memory.h"
26#include "video_core/gpu.h" 26#include "video_core/gpu.h"
27#include "video_core/host1x/gpu_device_memory_manager.h"
28#include "video_core/host1x/host1x.h"
27#include "video_core/rasterizer_download_area.h" 29#include "video_core/rasterizer_download_area.h"
28 30
29namespace Core::Memory { 31namespace Core::Memory {
@@ -637,17 +639,6 @@ struct Memory::Impl {
637 LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", GetInteger(target), 639 LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", GetInteger(target),
638 base * YUZU_PAGESIZE, (base + size) * YUZU_PAGESIZE); 640 base * YUZU_PAGESIZE, (base + size) * YUZU_PAGESIZE);
639 641
640 // During boot, current_page_table might not be set yet, in which case we need not flush
641 if (system.IsPoweredOn()) {
642 auto& gpu = system.GPU();
643 for (u64 i = 0; i < size; i++) {
644 const auto page = base + i;
645 if (page_table.pointers[page].Type() == Common::PageType::RasterizerCachedMemory) {
646 gpu.FlushAndInvalidateRegion(page << YUZU_PAGEBITS, YUZU_PAGESIZE);
647 }
648 }
649 }
650
651 const auto end = base + size; 642 const auto end = base + size;
652 ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", 643 ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}",
653 base + page_table.pointers.size()); 644 base + page_table.pointers.size());
@@ -811,21 +802,33 @@ struct Memory::Impl {
811 return true; 802 return true;
812 } 803 }
813 804
814 void HandleRasterizerDownload(VAddr address, size_t size) { 805 void HandleRasterizerDownload(VAddr v_address, size_t size) {
806 const auto* p = GetPointerImpl(
807 v_address, []() {}, []() {});
808 if (!gpu_device_memory) [[unlikely]] {
809 gpu_device_memory = &system.Host1x().MemoryManager();
810 }
815 const size_t core = system.GetCurrentHostThreadID(); 811 const size_t core = system.GetCurrentHostThreadID();
816 auto& current_area = rasterizer_read_areas[core]; 812 auto& current_area = rasterizer_read_areas[core];
817 const VAddr end_address = address + size; 813 gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) {
818 if (current_area.start_address <= address && end_address <= current_area.end_address) 814 const DAddr end_address = address + size;
819 [[likely]] { 815 if (current_area.start_address <= address && end_address <= current_area.end_address)
820 return; 816 [[likely]] {
821 } 817 return;
822 current_area = system.GPU().OnCPURead(address, size); 818 }
819 current_area = system.GPU().OnCPURead(address, size);
820 });
823 } 821 }
824 822
825 void HandleRasterizerWrite(VAddr address, size_t size) { 823 void HandleRasterizerWrite(VAddr v_address, size_t size) {
824 const auto* p = GetPointerImpl(
825 v_address, []() {}, []() {});
826 constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1; 826 constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1;
827 const size_t core = std::min(system.GetCurrentHostThreadID(), 827 const size_t core = std::min(system.GetCurrentHostThreadID(),
828 sys_core); // any other calls threads go to syscore. 828 sys_core); // any other calls threads go to syscore.
829 if (!gpu_device_memory) [[unlikely]] {
830 gpu_device_memory = &system.Host1x().MemoryManager();
831 }
829 // Guard on sys_core; 832 // Guard on sys_core;
830 if (core == sys_core) [[unlikely]] { 833 if (core == sys_core) [[unlikely]] {
831 sys_core_guard.lock(); 834 sys_core_guard.lock();
@@ -835,36 +838,53 @@ struct Memory::Impl {
835 sys_core_guard.unlock(); 838 sys_core_guard.unlock();
836 } 839 }
837 }); 840 });
838 auto& current_area = rasterizer_write_areas[core]; 841 gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) {
839 VAddr subaddress = address >> YUZU_PAGEBITS; 842 auto& current_area = rasterizer_write_areas[core];
840 bool do_collection = current_area.last_address == subaddress; 843 PAddr subaddress = address >> YUZU_PAGEBITS;
841 if (!do_collection) [[unlikely]] { 844 bool do_collection = current_area.last_address == subaddress;
842 do_collection = system.GPU().OnCPUWrite(address, size); 845 if (!do_collection) [[unlikely]] {
843 if (!do_collection) { 846 do_collection = system.GPU().OnCPUWrite(address, size);
844 return; 847 if (!do_collection) {
848 return;
849 }
850 current_area.last_address = subaddress;
845 } 851 }
846 current_area.last_address = subaddress; 852 gpu_dirty_managers[core].Collect(address, size);
847 } 853 });
848 gpu_dirty_managers[core].Collect(address, size);
849 } 854 }
850 855
851 struct GPUDirtyState { 856 struct GPUDirtyState {
852 VAddr last_address; 857 PAddr last_address;
853 }; 858 };
854 859
855 void InvalidateRegion(Common::ProcessAddress dest_addr, size_t size) { 860 void InvalidateGPUMemory(u8* p, size_t size) {
856 system.GPU().InvalidateRegion(GetInteger(dest_addr), size); 861 constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1;
857 } 862 const size_t core = std::min(system.GetCurrentHostThreadID(),
858 863 sys_core); // any other calls threads go to syscore.
859 void FlushRegion(Common::ProcessAddress dest_addr, size_t size) { 864 if (!gpu_device_memory) [[unlikely]] {
860 system.GPU().FlushRegion(GetInteger(dest_addr), size); 865 gpu_device_memory = &system.Host1x().MemoryManager();
866 }
867 // Guard on sys_core;
868 if (core == sys_core) [[unlikely]] {
869 sys_core_guard.lock();
870 }
871 SCOPE_EXIT({
872 if (core == sys_core) [[unlikely]] {
873 sys_core_guard.unlock();
874 }
875 });
876 auto& gpu = system.GPU();
877 gpu_device_memory->ApplyOpOnPointer(
878 p, scratch_buffers[core], [&](DAddr address) { gpu.InvalidateRegion(address, size); });
861 } 879 }
862 880
863 Core::System& system; 881 Core::System& system;
882 Tegra::MaxwellDeviceMemoryManager* gpu_device_memory{};
864 Common::PageTable* current_page_table = nullptr; 883 Common::PageTable* current_page_table = nullptr;
865 std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES> 884 std::array<VideoCore::RasterizerDownloadArea, Core::Hardware::NUM_CPU_CORES>
866 rasterizer_read_areas{}; 885 rasterizer_read_areas{};
867 std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; 886 std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
887 std::array<Common::ScratchBuffer<u32>, Core::Hardware::NUM_CPU_CORES> scratch_buffers{};
868 std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; 888 std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
869 std::mutex sys_core_guard; 889 std::mutex sys_core_guard;
870 890
@@ -1059,14 +1079,6 @@ void Memory::MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug)
1059 impl->MarkRegionDebug(GetInteger(vaddr), size, debug); 1079 impl->MarkRegionDebug(GetInteger(vaddr), size, debug);
1060} 1080}
1061 1081
1062void Memory::InvalidateRegion(Common::ProcessAddress dest_addr, size_t size) {
1063 impl->InvalidateRegion(dest_addr, size);
1064}
1065
1066void Memory::FlushRegion(Common::ProcessAddress dest_addr, size_t size) {
1067 impl->FlushRegion(dest_addr, size);
1068}
1069
1070bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { 1082bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
1071 [[maybe_unused]] bool mapped = true; 1083 [[maybe_unused]] bool mapped = true;
1072 [[maybe_unused]] bool rasterizer = false; 1084 [[maybe_unused]] bool rasterizer = false;
@@ -1078,10 +1090,10 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
1078 GetInteger(vaddr)); 1090 GetInteger(vaddr));
1079 mapped = false; 1091 mapped = false;
1080 }, 1092 },
1081 [&] { 1093 [&] { rasterizer = true; });
1082 impl->system.GPU().InvalidateRegion(GetInteger(vaddr), size); 1094 if (rasterizer) {
1083 rasterizer = true; 1095 impl->InvalidateGPUMemory(ptr, size);
1084 }); 1096 }
1085 1097
1086#ifdef __linux__ 1098#ifdef __linux__
1087 if (!rasterizer && mapped) { 1099 if (!rasterizer && mapped) {
diff --git a/src/core/memory.h b/src/core/memory.h
index dddfaf4a4..f7e6b297f 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -12,6 +12,7 @@
12 12
13#include "common/scratch_buffer.h" 13#include "common/scratch_buffer.h"
14#include "common/typed_address.h" 14#include "common/typed_address.h"
15#include "core/guest_memory.h"
15#include "core/hle/result.h" 16#include "core/hle/result.h"
16 17
17namespace Common { 18namespace Common {
@@ -486,10 +487,10 @@ public:
486 void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug); 487 void MarkRegionDebug(Common::ProcessAddress vaddr, u64 size, bool debug);
487 488
488 void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers); 489 void SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers);
489 void InvalidateRegion(Common::ProcessAddress dest_addr, size_t size); 490
490 bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); 491 bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size);
492
491 bool InvalidateSeparateHeap(void* fault_address); 493 bool InvalidateSeparateHeap(void* fault_address);
492 void FlushRegion(Common::ProcessAddress dest_addr, size_t size);
493 494
494private: 495private:
495 Core::System& system; 496 Core::System& system;
@@ -498,209 +499,9 @@ private:
498 std::unique_ptr<Impl> impl; 499 std::unique_ptr<Impl> impl;
499}; 500};
500 501
501enum GuestMemoryFlags : u32 {
502 Read = 1 << 0,
503 Write = 1 << 1,
504 Safe = 1 << 2,
505 Cached = 1 << 3,
506
507 SafeRead = Read | Safe,
508 SafeWrite = Write | Safe,
509 SafeReadWrite = SafeRead | SafeWrite,
510 SafeReadCachedWrite = SafeReadWrite | Cached,
511
512 UnsafeRead = Read,
513 UnsafeWrite = Write,
514 UnsafeReadWrite = UnsafeRead | UnsafeWrite,
515 UnsafeReadCachedWrite = UnsafeReadWrite | Cached,
516};
517
518namespace {
519template <typename M, typename T, GuestMemoryFlags FLAGS>
520class GuestMemory {
521 using iterator = T*;
522 using const_iterator = const T*;
523 using value_type = T;
524 using element_type = T;
525 using iterator_category = std::contiguous_iterator_tag;
526
527public:
528 GuestMemory() = delete;
529 explicit GuestMemory(M& memory, u64 addr, std::size_t size,
530 Common::ScratchBuffer<T>* backup = nullptr)
531 : m_memory{memory}, m_addr{addr}, m_size{size} {
532 static_assert(FLAGS & GuestMemoryFlags::Read || FLAGS & GuestMemoryFlags::Write);
533 if constexpr (FLAGS & GuestMemoryFlags::Read) {
534 Read(addr, size, backup);
535 }
536 }
537
538 ~GuestMemory() = default;
539
540 T* data() noexcept {
541 return m_data_span.data();
542 }
543
544 const T* data() const noexcept {
545 return m_data_span.data();
546 }
547
548 size_t size() const noexcept {
549 return m_size;
550 }
551
552 size_t size_bytes() const noexcept {
553 return this->size() * sizeof(T);
554 }
555
556 [[nodiscard]] T* begin() noexcept {
557 return this->data();
558 }
559
560 [[nodiscard]] const T* begin() const noexcept {
561 return this->data();
562 }
563
564 [[nodiscard]] T* end() noexcept {
565 return this->data() + this->size();
566 }
567
568 [[nodiscard]] const T* end() const noexcept {
569 return this->data() + this->size();
570 }
571
572 T& operator[](size_t index) noexcept {
573 return m_data_span[index];
574 }
575
576 const T& operator[](size_t index) const noexcept {
577 return m_data_span[index];
578 }
579
580 void SetAddressAndSize(u64 addr, std::size_t size) noexcept {
581 m_addr = addr;
582 m_size = size;
583 m_addr_changed = true;
584 }
585
586 std::span<T> Read(u64 addr, std::size_t size,
587 Common::ScratchBuffer<T>* backup = nullptr) noexcept {
588 m_addr = addr;
589 m_size = size;
590 if (m_size == 0) {
591 m_is_data_copy = true;
592 return {};
593 }
594
595 if (this->TrySetSpan()) {
596 if constexpr (FLAGS & GuestMemoryFlags::Safe) {
597 m_memory.FlushRegion(m_addr, this->size_bytes());
598 }
599 } else {
600 if (backup) {
601 backup->resize_destructive(this->size());
602 m_data_span = *backup;
603 } else {
604 m_data_copy.resize(this->size());
605 m_data_span = std::span(m_data_copy);
606 }
607 m_is_data_copy = true;
608 m_span_valid = true;
609 if constexpr (FLAGS & GuestMemoryFlags::Safe) {
610 m_memory.ReadBlock(m_addr, this->data(), this->size_bytes());
611 } else {
612 m_memory.ReadBlockUnsafe(m_addr, this->data(), this->size_bytes());
613 }
614 }
615 return m_data_span;
616 }
617
618 void Write(std::span<T> write_data) noexcept {
619 if constexpr (FLAGS & GuestMemoryFlags::Cached) {
620 m_memory.WriteBlockCached(m_addr, write_data.data(), this->size_bytes());
621 } else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
622 m_memory.WriteBlock(m_addr, write_data.data(), this->size_bytes());
623 } else {
624 m_memory.WriteBlockUnsafe(m_addr, write_data.data(), this->size_bytes());
625 }
626 }
627
628 bool TrySetSpan() noexcept {
629 if (u8* ptr = m_memory.GetSpan(m_addr, this->size_bytes()); ptr) {
630 m_data_span = {reinterpret_cast<T*>(ptr), this->size()};
631 m_span_valid = true;
632 return true;
633 }
634 return false;
635 }
636
637protected:
638 bool IsDataCopy() const noexcept {
639 return m_is_data_copy;
640 }
641
642 bool AddressChanged() const noexcept {
643 return m_addr_changed;
644 }
645
646 M& m_memory;
647 u64 m_addr{};
648 size_t m_size{};
649 std::span<T> m_data_span{};
650 std::vector<T> m_data_copy{};
651 bool m_span_valid{false};
652 bool m_is_data_copy{false};
653 bool m_addr_changed{false};
654};
655
656template <typename M, typename T, GuestMemoryFlags FLAGS>
657class GuestMemoryScoped : public GuestMemory<M, T, FLAGS> {
658public:
659 GuestMemoryScoped() = delete;
660 explicit GuestMemoryScoped(M& memory, u64 addr, std::size_t size,
661 Common::ScratchBuffer<T>* backup = nullptr)
662 : GuestMemory<M, T, FLAGS>(memory, addr, size, backup) {
663 if constexpr (!(FLAGS & GuestMemoryFlags::Read)) {
664 if (!this->TrySetSpan()) {
665 if (backup) {
666 this->m_data_span = *backup;
667 this->m_span_valid = true;
668 this->m_is_data_copy = true;
669 }
670 }
671 }
672 }
673
674 ~GuestMemoryScoped() {
675 if constexpr (FLAGS & GuestMemoryFlags::Write) {
676 if (this->size() == 0) [[unlikely]] {
677 return;
678 }
679
680 if (this->AddressChanged() || this->IsDataCopy()) {
681 ASSERT(this->m_span_valid);
682 if constexpr (FLAGS & GuestMemoryFlags::Cached) {
683 this->m_memory.WriteBlockCached(this->m_addr, this->data(), this->size_bytes());
684 } else if constexpr (FLAGS & GuestMemoryFlags::Safe) {
685 this->m_memory.WriteBlock(this->m_addr, this->data(), this->size_bytes());
686 } else {
687 this->m_memory.WriteBlockUnsafe(this->m_addr, this->data(), this->size_bytes());
688 }
689 } else if constexpr ((FLAGS & GuestMemoryFlags::Safe) ||
690 (FLAGS & GuestMemoryFlags::Cached)) {
691 this->m_memory.InvalidateRegion(this->m_addr, this->size_bytes());
692 }
693 }
694 }
695};
696} // namespace
697
698template <typename T, GuestMemoryFlags FLAGS> 502template <typename T, GuestMemoryFlags FLAGS>
699using CpuGuestMemory = GuestMemory<Memory, T, FLAGS>; 503using CpuGuestMemory = GuestMemory<Core::Memory::Memory, T, FLAGS>;
700template <typename T, GuestMemoryFlags FLAGS> 504template <typename T, GuestMemoryFlags FLAGS>
701using CpuGuestMemoryScoped = GuestMemoryScoped<Memory, T, FLAGS>; 505using CpuGuestMemoryScoped = GuestMemoryScoped<Core::Memory::Memory, T, FLAGS>;
702template <typename T, GuestMemoryFlags FLAGS> 506
703using GpuGuestMemory = GuestMemory<Tegra::MemoryManager, T, FLAGS>;
704template <typename T, GuestMemoryFlags FLAGS>
705using GpuGuestMemoryScoped = GuestMemoryScoped<Tegra::MemoryManager, T, FLAGS>;
706} // namespace Core::Memory 507} // namespace Core::Memory
diff --git a/src/frontend_common/CMakeLists.txt b/src/frontend_common/CMakeLists.txt
index 22e9337c4..94d8cc4c3 100644
--- a/src/frontend_common/CMakeLists.txt
+++ b/src/frontend_common/CMakeLists.txt
@@ -4,6 +4,7 @@
4add_library(frontend_common STATIC 4add_library(frontend_common STATIC
5 config.cpp 5 config.cpp
6 config.h 6 config.h
7 content_manager.h
7) 8)
8 9
9create_target_directory_groups(frontend_common) 10create_target_directory_groups(frontend_common)
diff --git a/src/frontend_common/content_manager.h b/src/frontend_common/content_manager.h
new file mode 100644
index 000000000..0b0fee73e
--- /dev/null
+++ b/src/frontend_common/content_manager.h
@@ -0,0 +1,371 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <boost/algorithm/string.hpp>
7#include "common/common_types.h"
8#include "common/literals.h"
9#include "core/core.h"
10#include "core/file_sys/common_funcs.h"
11#include "core/file_sys/content_archive.h"
12#include "core/file_sys/mode.h"
13#include "core/file_sys/nca_metadata.h"
14#include "core/file_sys/patch_manager.h"
15#include "core/file_sys/registered_cache.h"
16#include "core/file_sys/submission_package.h"
17#include "core/hle/service/filesystem/filesystem.h"
18#include "core/loader/loader.h"
19#include "core/loader/nca.h"
20
21namespace ContentManager {
22
23enum class InstallResult {
24 Success,
25 Overwrite,
26 Failure,
27 BaseInstallAttempted,
28};
29
30enum class GameVerificationResult {
31 Success,
32 Failed,
33 NotImplemented,
34};
35
36/**
37 * \brief Removes a single installed DLC
38 * \param fs_controller [FileSystemController] reference from the Core::System instance
39 * \param title_id Unique title ID representing the DLC which will be removed
40 * \return 'true' if successful
41 */
42inline bool RemoveDLC(const Service::FileSystem::FileSystemController& fs_controller,
43 const u64 title_id) {
44 return fs_controller.GetUserNANDContents()->RemoveExistingEntry(title_id) ||
45 fs_controller.GetSDMCContents()->RemoveExistingEntry(title_id);
46}
47
48/**
49 * \brief Removes all DLC for a game
50 * \param system Raw pointer to the system instance
51 * \param program_id Program ID for the game that will have all of its DLC removed
52 * \return Number of DLC removed
53 */
54inline size_t RemoveAllDLC(Core::System* system, const u64 program_id) {
55 size_t count{};
56 const auto& fs_controller = system->GetFileSystemController();
57 const auto dlc_entries = system->GetContentProvider().ListEntriesFilter(
58 FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
59 std::vector<u64> program_dlc_entries;
60
61 for (const auto& entry : dlc_entries) {
62 if (FileSys::GetBaseTitleID(entry.title_id) == program_id) {
63 program_dlc_entries.push_back(entry.title_id);
64 }
65 }
66
67 for (const auto& entry : program_dlc_entries) {
68 if (RemoveDLC(fs_controller, entry)) {
69 ++count;
70 }
71 }
72 return count;
73}
74
75/**
76 * \brief Removes the installed update for a game
77 * \param fs_controller [FileSystemController] reference from the Core::System instance
78 * \param program_id Program ID for the game that will have its installed update removed
79 * \return 'true' if successful
80 */
81inline bool RemoveUpdate(const Service::FileSystem::FileSystemController& fs_controller,
82 const u64 program_id) {
83 const auto update_id = program_id | 0x800;
84 return fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) ||
85 fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id);
86}
87
88/**
89 * \brief Removes the base content for a game
90 * \param fs_controller [FileSystemController] reference from the Core::System instance
91 * \param program_id Program ID for the game that will have its base content removed
92 * \return 'true' if successful
93 */
94inline bool RemoveBaseContent(const Service::FileSystem::FileSystemController& fs_controller,
95 const u64 program_id) {
96 return fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) ||
97 fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id);
98}
99
100/**
101 * \brief Removes a mod for a game
102 * \param fs_controller [FileSystemController] reference from the Core::System instance
103 * \param program_id Program ID for the game where [mod_name] will be removed
104 * \param mod_name The name of a mod as given by FileSys::PatchManager::GetPatches. This corresponds
105 * with the name of the mod's directory in a game's load folder.
106 * \return 'true' if successful
107 */
108inline bool RemoveMod(const Service::FileSystem::FileSystemController& fs_controller,
109 const u64 program_id, const std::string& mod_name) {
110 // Check general Mods (LayeredFS and IPS)
111 const auto mod_dir = fs_controller.GetModificationLoadRoot(program_id);
112 if (mod_dir != nullptr) {
113 return mod_dir->DeleteSubdirectoryRecursive(mod_name);
114 }
115
116 // Check SDMC mod directory (RomFS LayeredFS)
117 const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(program_id);
118 if (sdmc_mod_dir != nullptr) {
119 return sdmc_mod_dir->DeleteSubdirectoryRecursive(mod_name);
120 }
121
122 return false;
123}
124
125/**
126 * \brief Installs an NSP
127 * \param system Raw pointer to the system instance
128 * \param vfs Raw pointer to the VfsFilesystem instance in Core::System
129 * \param filename Path to the NSP file
130 * \param callback Callback to report the progress of the installation. The first size_t
131 * parameter is the total size of the virtual file and the second is the current progress. If you
132 * return true to the callback, it will cancel the installation as soon as possible.
133 * \return [InstallResult] representing how the installation finished
134 */
135inline InstallResult InstallNSP(Core::System* system, FileSys::VfsFilesystem* vfs,
136 const std::string& filename,
137 const std::function<bool(size_t, size_t)>& callback) {
138 const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
139 std::size_t block_size) {
140 if (src == nullptr || dest == nullptr) {
141 return false;
142 }
143 if (!dest->Resize(src->GetSize())) {
144 return false;
145 }
146
147 using namespace Common::Literals;
148 std::vector<u8> buffer(1_MiB);
149
150 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
151 if (callback(src->GetSize(), i)) {
152 dest->Resize(0);
153 return false;
154 }
155 const auto read = src->Read(buffer.data(), buffer.size(), i);
156 dest->Write(buffer.data(), read, i);
157 }
158 return true;
159 };
160
161 std::shared_ptr<FileSys::NSP> nsp;
162 FileSys::VirtualFile file = vfs->OpenFile(filename, FileSys::Mode::Read);
163 if (boost::to_lower_copy(file->GetName()).ends_with(std::string("nsp"))) {
164 nsp = std::make_shared<FileSys::NSP>(file);
165 if (nsp->IsExtractedType()) {
166 return InstallResult::Failure;
167 }
168 } else {
169 return InstallResult::Failure;
170 }
171
172 if (nsp->GetStatus() != Loader::ResultStatus::Success) {
173 return InstallResult::Failure;
174 }
175 const auto res =
176 system->GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true, copy);
177 switch (res) {
178 case FileSys::InstallResult::Success:
179 return InstallResult::Success;
180 case FileSys::InstallResult::OverwriteExisting:
181 return InstallResult::Overwrite;
182 case FileSys::InstallResult::ErrorBaseInstall:
183 return InstallResult::BaseInstallAttempted;
184 default:
185 return InstallResult::Failure;
186 }
187}
188
189/**
190 * \brief Installs an NCA
191 * \param vfs Raw pointer to the VfsFilesystem instance in Core::System
192 * \param filename Path to the NCA file
193 * \param registered_cache Raw pointer to the registered cache that the NCA will be installed to
194 * \param title_type Type of NCA package to install
195 * \param callback Callback to report the progress of the installation. The first size_t
196 * parameter is the total size of the virtual file and the second is the current progress. If you
197 * return true to the callback, it will cancel the installation as soon as possible.
198 * \return [InstallResult] representing how the installation finished
199 */
200inline InstallResult InstallNCA(FileSys::VfsFilesystem* vfs, const std::string& filename,
201 FileSys::RegisteredCache* registered_cache,
202 const FileSys::TitleType title_type,
203 const std::function<bool(size_t, size_t)>& callback) {
204 const auto copy = [callback](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
205 std::size_t block_size) {
206 if (src == nullptr || dest == nullptr) {
207 return false;
208 }
209 if (!dest->Resize(src->GetSize())) {
210 return false;
211 }
212
213 using namespace Common::Literals;
214 std::vector<u8> buffer(1_MiB);
215
216 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
217 if (callback(src->GetSize(), i)) {
218 dest->Resize(0);
219 return false;
220 }
221 const auto read = src->Read(buffer.data(), buffer.size(), i);
222 dest->Write(buffer.data(), read, i);
223 }
224 return true;
225 };
226
227 const auto nca = std::make_shared<FileSys::NCA>(vfs->OpenFile(filename, FileSys::Mode::Read));
228 const auto id = nca->GetStatus();
229
230 // Game updates necessary are missing base RomFS
231 if (id != Loader::ResultStatus::Success &&
232 id != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
233 return InstallResult::Failure;
234 }
235
236 const auto res = registered_cache->InstallEntry(*nca, title_type, true, copy);
237 if (res == FileSys::InstallResult::Success) {
238 return InstallResult::Success;
239 } else if (res == FileSys::InstallResult::OverwriteExisting) {
240 return InstallResult::Overwrite;
241 } else {
242 return InstallResult::Failure;
243 }
244}
245
246/**
247 * \brief Verifies the installed contents for a given ManualContentProvider
248 * \param system Raw pointer to the system instance
249 * \param provider Raw pointer to the content provider that's tracking indexed games
250 * \param callback Callback to report the progress of the installation. The first size_t
251 * parameter is the total size of the installed contents and the second is the current progress. If
252 * you return true to the callback, it will cancel the installation as soon as possible.
253 * \return A list of entries that failed to install. Returns an empty vector if successful.
254 */
255inline std::vector<std::string> VerifyInstalledContents(
256 Core::System* system, FileSys::ManualContentProvider* provider,
257 const std::function<bool(size_t, size_t)>& callback) {
258 // Get content registries.
259 auto bis_contents = system->GetFileSystemController().GetSystemNANDContents();
260 auto user_contents = system->GetFileSystemController().GetUserNANDContents();
261
262 std::vector<FileSys::RegisteredCache*> content_providers;
263 if (bis_contents) {
264 content_providers.push_back(bis_contents);
265 }
266 if (user_contents) {
267 content_providers.push_back(user_contents);
268 }
269
270 // Get associated NCA files.
271 std::vector<FileSys::VirtualFile> nca_files;
272
273 // Get all installed IDs.
274 size_t total_size = 0;
275 for (auto nca_provider : content_providers) {
276 const auto entries = nca_provider->ListEntriesFilter();
277
278 for (const auto& entry : entries) {
279 auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type);
280 if (!nca_file) {
281 continue;
282 }
283
284 total_size += nca_file->GetSize();
285 nca_files.push_back(std::move(nca_file));
286 }
287 }
288
289 // Declare a list of file names which failed to verify.
290 std::vector<std::string> failed;
291
292 size_t processed_size = 0;
293 bool cancelled = false;
294 auto nca_callback = [&](size_t nca_processed, size_t nca_total) {
295 cancelled = callback(total_size, processed_size + nca_processed);
296 return !cancelled;
297 };
298
299 // Using the NCA loader, determine if all NCAs are valid.
300 for (auto& nca_file : nca_files) {
301 Loader::AppLoader_NCA nca_loader(nca_file);
302
303 auto status = nca_loader.VerifyIntegrity(nca_callback);
304 if (cancelled) {
305 break;
306 }
307 if (status != Loader::ResultStatus::Success) {
308 FileSys::NCA nca(nca_file);
309 const auto title_id = nca.GetTitleId();
310 std::string title_name = "unknown";
311
312 const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id),
313 FileSys::ContentRecordType::Control);
314 if (control && control->GetStatus() == Loader::ResultStatus::Success) {
315 const FileSys::PatchManager pm{title_id, system->GetFileSystemController(),
316 *provider};
317 const auto [nacp, logo] = pm.ParseControlNCA(*control);
318 if (nacp) {
319 title_name = nacp->GetApplicationName();
320 }
321 }
322
323 if (title_id > 0) {
324 failed.push_back(
325 fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name));
326 } else {
327 failed.push_back(fmt::format("{} (unknown)", nca_file->GetName()));
328 }
329 }
330
331 processed_size += nca_file->GetSize();
332 }
333 return failed;
334}
335
336/**
337 * \brief Verifies the contents of a given game
338 * \param system Raw pointer to the system instance
339 * \param game_path Patch to the game file
340 * \param callback Callback to report the progress of the installation. The first size_t
341 * parameter is the total size of the installed contents and the second is the current progress. If
342 * you return true to the callback, it will cancel the installation as soon as possible.
343 * \return GameVerificationResult representing how the verification process finished
344 */
345inline GameVerificationResult VerifyGameContents(
346 Core::System* system, const std::string& game_path,
347 const std::function<bool(size_t, size_t)>& callback) {
348 const auto loader = Loader::GetLoader(
349 *system, system->GetFilesystem()->OpenFile(game_path, FileSys::Mode::Read));
350 if (loader == nullptr) {
351 return GameVerificationResult::NotImplemented;
352 }
353
354 bool cancelled = false;
355 auto loader_callback = [&](size_t processed, size_t total) {
356 cancelled = callback(total, processed);
357 return !cancelled;
358 };
359
360 const auto status = loader->VerifyIntegrity(loader_callback);
361 if (cancelled || status == Loader::ResultStatus::ErrorIntegrityVerificationNotImplemented) {
362 return GameVerificationResult::NotImplemented;
363 }
364
365 if (status == Loader::ResultStatus::ErrorIntegrityVerificationFailed) {
366 return GameVerificationResult::Failed;
367 }
368 return GameVerificationResult::Success;
369}
370
371} // namespace ContentManager
diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp
index 2ab93402d..e12e5a77e 100644
--- a/src/hid_core/frontend/emulated_controller.cpp
+++ b/src/hid_core/frontend/emulated_controller.cpp
@@ -110,6 +110,7 @@ void EmulatedController::ReloadFromSettings() {
110 original_npad_type = npad_type; 110 original_npad_type = npad_type;
111 } 111 }
112 112
113 SetPollingMode(EmulatedDeviceIndex::RightIndex, Common::Input::PollingMode::Active);
113 Disconnect(); 114 Disconnect();
114 if (player.connected) { 115 if (player.connected) {
115 Connect(); 116 Connect();
@@ -144,8 +145,8 @@ void EmulatedController::ReloadColorsFromSettings() {
144 145
145void EmulatedController::LoadDevices() { 146void EmulatedController::LoadDevices() {
146 // TODO(german77): Use more buttons to detect the correct device 147 // TODO(german77): Use more buttons to detect the correct device
147 const auto left_joycon = button_params[Settings::NativeButton::DRight]; 148 const auto& left_joycon = button_params[Settings::NativeButton::DRight];
148 const auto right_joycon = button_params[Settings::NativeButton::A]; 149 const auto& right_joycon = button_params[Settings::NativeButton::A];
149 150
150 // Triggers for GC controllers 151 // Triggers for GC controllers
151 trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL]; 152 trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
@@ -1208,16 +1209,44 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
1208 controller.nfc_state = controller.nfc_values; 1209 controller.nfc_state = controller.nfc_values;
1209} 1210}
1210 1211
1211bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) { 1212bool EmulatedController::SetVibration(bool should_vibrate) {
1213 VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE;
1214 if (should_vibrate) {
1215 vibration_value.high_amplitude = 1.0f;
1216 vibration_value.low_amplitude = 1.0f;
1217 }
1218
1219 return SetVibration(DeviceIndex::Left, vibration_value);
1220}
1221
1222bool EmulatedController::SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command) {
1223 VibrationValue vibration_value = DEFAULT_VIBRATION_VALUE;
1224 if (erm_command == Core::HID::VibrationGcErmCommand::Start) {
1225 vibration_value.high_amplitude = 1.0f;
1226 vibration_value.low_amplitude = 1.0f;
1227 }
1228
1229 return SetVibration(DeviceIndex::Left, vibration_value);
1230}
1231
1232bool EmulatedController::SetVibration(DeviceIndex device_index, const VibrationValue& vibration) {
1212 if (!is_initialized) { 1233 if (!is_initialized) {
1213 return false; 1234 return false;
1214 } 1235 }
1215 if (device_index >= output_devices.size()) { 1236 if (device_index >= DeviceIndex::MaxDeviceIndex) {
1216 return false; 1237 return false;
1217 } 1238 }
1218 if (!output_devices[device_index]) { 1239 const std::size_t index = static_cast<std::size_t>(device_index);
1240 if (!output_devices[index]) {
1241 return false;
1242 }
1243
1244 last_vibration_value = vibration;
1245
1246 if (!Settings::values.vibration_enabled) {
1219 return false; 1247 return false;
1220 } 1248 }
1249
1221 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type); 1250 const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
1222 const auto& player = Settings::values.players.GetValue()[player_index]; 1251 const auto& player = Settings::values.players.GetValue()[player_index];
1223 const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f; 1252 const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
@@ -1239,8 +1268,11 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
1239 .high_frequency = vibration.high_frequency, 1268 .high_frequency = vibration.high_frequency,
1240 .type = type, 1269 .type = type,
1241 }; 1270 };
1242 return output_devices[device_index]->SetVibration(status) == 1271 return output_devices[index]->SetVibration(status) == Common::Input::DriverResult::Success;
1243 Common::Input::DriverResult::Success; 1272}
1273
1274VibrationValue EmulatedController::GetActualVibrationValue(DeviceIndex device_index) const {
1275 return last_vibration_value;
1244} 1276}
1245 1277
1246bool EmulatedController::IsVibrationEnabled(std::size_t device_index) { 1278bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
diff --git a/src/hid_core/frontend/emulated_controller.h b/src/hid_core/frontend/emulated_controller.h
index 90e536e07..168abe089 100644
--- a/src/hid_core/frontend/emulated_controller.h
+++ b/src/hid_core/frontend/emulated_controller.h
@@ -356,10 +356,27 @@ public:
356 const NfcState& GetNfc() const; 356 const NfcState& GetNfc() const;
357 357
358 /** 358 /**
359 * Sends an on/off vibration to the left device
360 * @return true if vibration had no errors
361 */
362 bool SetVibration(bool should_vibrate);
363
364 /**
365 * Sends an GC vibration to the left device
366 * @return true if vibration had no errors
367 */
368 bool SetVibration(u32 slot, Core::HID::VibrationGcErmCommand erm_command);
369
370 /**
359 * Sends a specific vibration to the output device 371 * Sends a specific vibration to the output device
360 * @return true if vibration had no errors 372 * @return true if vibration had no errors
361 */ 373 */
362 bool SetVibration(std::size_t device_index, VibrationValue vibration); 374 bool SetVibration(DeviceIndex device_index, const VibrationValue& vibration);
375
376 /**
377 * @return The last sent vibration
378 */
379 VibrationValue GetActualVibrationValue(DeviceIndex device_index) const;
363 380
364 /** 381 /**
365 * Sends a small vibration to the output device 382 * Sends a small vibration to the output device
@@ -564,6 +581,7 @@ private:
564 f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard}; 581 f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
565 u32 turbo_button_state{0}; 582 u32 turbo_button_state{0};
566 std::size_t nfc_handles{0}; 583 std::size_t nfc_handles{0};
584 VibrationValue last_vibration_value{DEFAULT_VIBRATION_VALUE};
567 585
568 // Temporary values to avoid doing changes while the controller is in configuring mode 586 // Temporary values to avoid doing changes while the controller is in configuring mode
569 NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; 587 NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
diff --git a/src/hid_core/resource_manager.cpp b/src/hid_core/resource_manager.cpp
index 2c5fe6d51..ca824b4a3 100644
--- a/src/hid_core/resource_manager.cpp
+++ b/src/hid_core/resource_manager.cpp
@@ -7,6 +7,7 @@
7#include "core/hle/kernel/k_shared_memory.h" 7#include "core/hle/kernel/k_shared_memory.h"
8#include "core/hle/service/ipc_helpers.h" 8#include "core/hle/service/ipc_helpers.h"
9#include "hid_core/hid_core.h" 9#include "hid_core/hid_core.h"
10#include "hid_core/hid_util.h"
10#include "hid_core/resource_manager.h" 11#include "hid_core/resource_manager.h"
11 12
12#include "hid_core/resources/applet_resource.h" 13#include "hid_core/resources/applet_resource.h"
@@ -27,6 +28,10 @@
27#include "hid_core/resources/touch_screen/gesture.h" 28#include "hid_core/resources/touch_screen/gesture.h"
28#include "hid_core/resources/touch_screen/touch_screen.h" 29#include "hid_core/resources/touch_screen/touch_screen.h"
29#include "hid_core/resources/unique_pad/unique_pad.h" 30#include "hid_core/resources/unique_pad/unique_pad.h"
31#include "hid_core/resources/vibration/gc_vibration_device.h"
32#include "hid_core/resources/vibration/n64_vibration_device.h"
33#include "hid_core/resources/vibration/vibration_base.h"
34#include "hid_core/resources/vibration/vibration_device.h"
30 35
31namespace Service::HID { 36namespace Service::HID {
32 37
@@ -52,6 +57,7 @@ void ResourceManager::Initialize() {
52 57
53 system.HIDCore().ReloadInputDevices(); 58 system.HIDCore().ReloadInputDevices();
54 59
60 handheld_config = std::make_shared<HandheldConfig>();
55 InitializeHidCommonSampler(); 61 InitializeHidCommonSampler();
56 InitializeTouchScreenSampler(); 62 InitializeTouchScreenSampler();
57 InitializeConsoleSixAxisSampler(); 63 InitializeConsoleSixAxisSampler();
@@ -174,7 +180,7 @@ void ResourceManager::InitializeHidCommonSampler() {
174 debug_pad->SetAppletResource(applet_resource, &shared_mutex); 180 debug_pad->SetAppletResource(applet_resource, &shared_mutex);
175 digitizer->SetAppletResource(applet_resource, &shared_mutex); 181 digitizer->SetAppletResource(applet_resource, &shared_mutex);
176 keyboard->SetAppletResource(applet_resource, &shared_mutex); 182 keyboard->SetAppletResource(applet_resource, &shared_mutex);
177 npad->SetNpadExternals(applet_resource, &shared_mutex); 183 npad->SetNpadExternals(applet_resource, &shared_mutex, handheld_config);
178 six_axis->SetAppletResource(applet_resource, &shared_mutex); 184 six_axis->SetAppletResource(applet_resource, &shared_mutex);
179 mouse->SetAppletResource(applet_resource, &shared_mutex); 185 mouse->SetAppletResource(applet_resource, &shared_mutex);
180 debug_mouse->SetAppletResource(applet_resource, &shared_mutex); 186 debug_mouse->SetAppletResource(applet_resource, &shared_mutex);
@@ -257,6 +263,121 @@ void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) {
257 applet_resource->EnableTouchScreen(aruid, is_enabled); 263 applet_resource->EnableTouchScreen(aruid, is_enabled);
258} 264}
259 265
266NpadVibrationBase* ResourceManager::GetVibrationDevice(
267 const Core::HID::VibrationDeviceHandle& handle) {
268 return npad->GetVibrationDevice(handle);
269}
270
271NpadN64VibrationDevice* ResourceManager::GetN64VibrationDevice(
272 const Core::HID::VibrationDeviceHandle& handle) {
273 return npad->GetN64VibrationDevice(handle);
274}
275
276NpadVibrationDevice* ResourceManager::GetNSVibrationDevice(
277 const Core::HID::VibrationDeviceHandle& handle) {
278 return npad->GetNSVibrationDevice(handle);
279}
280
281NpadGcVibrationDevice* ResourceManager::GetGcVibrationDevice(
282 const Core::HID::VibrationDeviceHandle& handle) {
283 return npad->GetGcVibrationDevice(handle);
284}
285
286Result ResourceManager::SetAruidValidForVibration(u64 aruid, bool is_enabled) {
287 std::scoped_lock lock{shared_mutex};
288 const bool has_changed = applet_resource->SetAruidValidForVibration(aruid, is_enabled);
289
290 if (has_changed) {
291 auto devices = npad->GetAllVibrationDevices();
292 for ([[maybe_unused]] auto* device : devices) {
293 // TODO
294 }
295 }
296
297 auto* vibration_handler = npad->GetVibrationHandler();
298 if (aruid != vibration_handler->GetSessionAruid()) {
299 vibration_handler->EndPermitVibrationSession();
300 }
301
302 return ResultSuccess;
303}
304
305void ResourceManager::SetForceHandheldStyleVibration(bool is_forced) {
306 handheld_config->is_force_handheld_style_vibration = is_forced;
307}
308
309Result ResourceManager::IsVibrationAruidActive(u64 aruid, bool& is_active) const {
310 std::scoped_lock lock{shared_mutex};
311 is_active = applet_resource->IsVibrationAruidActive(aruid);
312 return ResultSuccess;
313}
314
315Result ResourceManager::GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info,
316 const Core::HID::VibrationDeviceHandle& handle) {
317 bool check_device_index = false;
318
319 const Result is_valid = IsVibrationHandleValid(handle);
320 if (is_valid.IsError()) {
321 return is_valid;
322 }
323
324 switch (handle.npad_type) {
325 case Core::HID::NpadStyleIndex::Fullkey:
326 case Core::HID::NpadStyleIndex::Handheld:
327 case Core::HID::NpadStyleIndex::JoyconDual:
328 case Core::HID::NpadStyleIndex::JoyconLeft:
329 case Core::HID::NpadStyleIndex::JoyconRight:
330 device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
331 check_device_index = true;
332 break;
333 case Core::HID::NpadStyleIndex::GameCube:
334 device_info.type = Core::HID::VibrationDeviceType::GcErm;
335 break;
336 case Core::HID::NpadStyleIndex::N64:
337 device_info.type = Core::HID::VibrationDeviceType::N64;
338 break;
339 default:
340 device_info.type = Core::HID::VibrationDeviceType::Unknown;
341 break;
342 }
343
344 device_info.position = Core::HID::VibrationDevicePosition::None;
345 if (check_device_index) {
346 switch (handle.device_index) {
347 case Core::HID::DeviceIndex::Left:
348 device_info.position = Core::HID::VibrationDevicePosition::Left;
349 break;
350 case Core::HID::DeviceIndex::Right:
351 device_info.position = Core::HID::VibrationDevicePosition::Right;
352 break;
353 case Core::HID::DeviceIndex::None:
354 default:
355 ASSERT_MSG(false, "DeviceIndex should never be None!");
356 break;
357 }
358 }
359 return ResultSuccess;
360}
361
362Result ResourceManager::SendVibrationValue(u64 aruid,
363 const Core::HID::VibrationDeviceHandle& handle,
364 const Core::HID::VibrationValue& value) {
365 bool has_active_aruid{};
366 NpadVibrationDevice* device{nullptr};
367 Result result = IsVibrationAruidActive(aruid, has_active_aruid);
368
369 if (result.IsSuccess() && has_active_aruid) {
370 result = IsVibrationHandleValid(handle);
371 }
372 if (result.IsSuccess() && has_active_aruid) {
373 device = GetNSVibrationDevice(handle);
374 }
375 if (device != nullptr) {
376 result = device->SendVibrationValue(value);
377 }
378 return result;
379}
380
260void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) { 381void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) {
261 auto& core_timing = system.CoreTiming(); 382 auto& core_timing = system.CoreTiming();
262 debug_pad->OnUpdate(core_timing); 383 debug_pad->OnUpdate(core_timing);
diff --git a/src/hid_core/resource_manager.h b/src/hid_core/resource_manager.h
index 7a21d8eb8..128e00125 100644
--- a/src/hid_core/resource_manager.h
+++ b/src/hid_core/resource_manager.h
@@ -10,6 +10,12 @@ namespace Core {
10class System; 10class System;
11} 11}
12 12
13namespace Core::HID {
14struct VibrationDeviceHandle;
15struct VibrationValue;
16struct VibrationDeviceInfo;
17} // namespace Core::HID
18
13namespace Core::Timing { 19namespace Core::Timing {
14struct EventType; 20struct EventType;
15} 21}
@@ -37,6 +43,11 @@ class SixAxis;
37class SleepButton; 43class SleepButton;
38class TouchScreen; 44class TouchScreen;
39class UniquePad; 45class UniquePad;
46class NpadVibrationBase;
47class NpadN64VibrationDevice;
48class NpadGcVibrationDevice;
49class NpadVibrationDevice;
50struct HandheldConfig;
40 51
41class ResourceManager { 52class ResourceManager {
42 53
@@ -79,6 +90,18 @@ public:
79 void EnablePadInput(u64 aruid, bool is_enabled); 90 void EnablePadInput(u64 aruid, bool is_enabled);
80 void EnableTouchScreen(u64 aruid, bool is_enabled); 91 void EnableTouchScreen(u64 aruid, bool is_enabled);
81 92
93 NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
94 NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
95 NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
96 NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
97 Result SetAruidValidForVibration(u64 aruid, bool is_enabled);
98 void SetForceHandheldStyleVibration(bool is_forced);
99 Result IsVibrationAruidActive(u64 aruid, bool& is_active) const;
100 Result GetVibrationDeviceInfo(Core::HID::VibrationDeviceInfo& device_info,
101 const Core::HID::VibrationDeviceHandle& handle);
102 Result SendVibrationValue(u64 aruid, const Core::HID::VibrationDeviceHandle& handle,
103 const Core::HID::VibrationValue& value);
104
82 void UpdateControllers(std::chrono::nanoseconds ns_late); 105 void UpdateControllers(std::chrono::nanoseconds ns_late);
83 void UpdateNpad(std::chrono::nanoseconds ns_late); 106 void UpdateNpad(std::chrono::nanoseconds ns_late);
84 void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late); 107 void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late);
@@ -113,6 +136,8 @@ private:
113 std::shared_ptr<TouchScreen> touch_screen = nullptr; 136 std::shared_ptr<TouchScreen> touch_screen = nullptr;
114 std::shared_ptr<UniquePad> unique_pad = nullptr; 137 std::shared_ptr<UniquePad> unique_pad = nullptr;
115 138
139 std::shared_ptr<HandheldConfig> handheld_config = nullptr;
140
116 // TODO: Create these resources 141 // TODO: Create these resources
117 // std::shared_ptr<AudioControl> audio_control = nullptr; 142 // std::shared_ptr<AudioControl> audio_control = nullptr;
118 // std::shared_ptr<ButtonConfig> button_config = nullptr; 143 // std::shared_ptr<ButtonConfig> button_config = nullptr;
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp
index d4e4181bf..e399edfd7 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp
+++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.cpp
@@ -115,7 +115,7 @@ Result NpadAbstractIrSensorHandler::GetXcdHandleForNpadWithIrSensor(u64& handle)
115 if (sensor_state < NpadIrSensorState::Available) { 115 if (sensor_state < NpadIrSensorState::Available) {
116 return ResultIrSensorIsNotReady; 116 return ResultIrSensorIsNotReady;
117 } 117 }
118 handle = xcd_handle; 118 // handle = xcd_handle;
119 return ResultSuccess; 119 return ResultSuccess;
120} 120}
121 121
diff --git a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h
index fe8e005af..997811511 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h
+++ b/src/hid_core/resources/abstracted_pad/abstract_ir_sensor_handler.h
@@ -7,6 +7,10 @@
7#include "core/hle/result.h" 7#include "core/hle/result.h"
8#include "hid_core/hid_types.h" 8#include "hid_core/hid_types.h"
9 9
10namespace Core::HID {
11class EmulatedController;
12}
13
10namespace Kernel { 14namespace Kernel {
11class KEvent; 15class KEvent;
12class KReadableEvent; 16class KReadableEvent;
@@ -50,7 +54,7 @@ private:
50 54
51 s32 ref_counter{}; 55 s32 ref_counter{};
52 Kernel::KEvent* ir_sensor_event{nullptr}; 56 Kernel::KEvent* ir_sensor_event{nullptr};
53 u64 xcd_handle{}; 57 Core::HID::EmulatedController* xcd_handle{};
54 NpadIrSensorState sensor_state{}; 58 NpadIrSensorState sensor_state{};
55}; 59};
56} // namespace Service::HID 60} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp
index 2c7691d7c..435b095f0 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_pad.cpp
+++ b/src/hid_core/resources/abstracted_pad/abstract_pad.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include "hid_core/hid_core.h"
4#include "hid_core/hid_result.h" 5#include "hid_core/hid_result.h"
5#include "hid_core/resources/abstracted_pad/abstract_pad.h" 6#include "hid_core/resources/abstracted_pad/abstract_pad.h"
6#include "hid_core/resources/applet_resource.h" 7#include "hid_core/resources/applet_resource.h"
@@ -16,7 +17,7 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource,
16 CaptureButtonResource* capture_button_resource, 17 CaptureButtonResource* capture_button_resource,
17 HomeButtonResource* home_button_resource, 18 HomeButtonResource* home_button_resource,
18 SixAxisResource* sixaxis_resource, PalmaResource* palma_resource, 19 SixAxisResource* sixaxis_resource, PalmaResource* palma_resource,
19 VibrationHandler* vibration) { 20 NpadVibration* vibration, Core::HID::HIDCore* core) {
20 applet_resource_holder = applet_resource; 21 applet_resource_holder = applet_resource;
21 22
22 properties_handler.SetAppletResource(applet_resource_holder); 23 properties_handler.SetAppletResource(applet_resource_holder);
@@ -35,13 +36,14 @@ void AbstractPad::SetExternals(AppletResourceHolder* applet_resource,
35 mcu_handler.SetAbstractPadHolder(&abstract_pad_holder); 36 mcu_handler.SetAbstractPadHolder(&abstract_pad_holder);
36 mcu_handler.SetPropertiesHandler(&properties_handler); 37 mcu_handler.SetPropertiesHandler(&properties_handler);
37 38
38 std::array<NpadVibrationDevice*, 2> vibration_devices{&vibration_left, &vibration_right};
39 vibration_handler.SetAppletResource(applet_resource_holder); 39 vibration_handler.SetAppletResource(applet_resource_holder);
40 vibration_handler.SetAbstractPadHolder(&abstract_pad_holder); 40 vibration_handler.SetAbstractPadHolder(&abstract_pad_holder);
41 vibration_handler.SetPropertiesHandler(&properties_handler); 41 vibration_handler.SetPropertiesHandler(&properties_handler);
42 vibration_handler.SetN64Vibration(&vibration_n64); 42 vibration_handler.SetN64Vibration(&vibration_n64);
43 vibration_handler.SetVibration(vibration_devices); 43 vibration_handler.SetVibration(&vibration_left, &vibration_right);
44 vibration_handler.SetGcVibration(&vibration_gc); 44 vibration_handler.SetGcVibration(&vibration_gc);
45 vibration_handler.SetVibrationHandler(vibration);
46 vibration_handler.SetHidCore(core);
45 47
46 sixaxis_handler.SetAppletResource(applet_resource_holder); 48 sixaxis_handler.SetAppletResource(applet_resource_holder);
47 sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder); 49 sixaxis_handler.SetAbstractPadHolder(&abstract_pad_holder);
@@ -239,11 +241,6 @@ NpadVibrationDevice* AbstractPad::GetVibrationDevice(Core::HID::DeviceIndex devi
239 return &vibration_left; 241 return &vibration_left;
240} 242}
241 243
242void AbstractPad::GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list) {
243 list.emplace_back(&vibration_left);
244 list.emplace_back(&vibration_right);
245}
246
247NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() { 244NpadGcVibrationDevice* AbstractPad::GetGCVibrationDevice() {
248 return &vibration_gc; 245 return &vibration_gc;
249} 246}
diff --git a/src/hid_core/resources/abstracted_pad/abstract_pad.h b/src/hid_core/resources/abstracted_pad/abstract_pad.h
index cbdf84af7..329792457 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_pad.h
+++ b/src/hid_core/resources/abstracted_pad/abstract_pad.h
@@ -32,7 +32,6 @@ class AppletResource;
32class SixAxisResource; 32class SixAxisResource;
33class PalmaResource; 33class PalmaResource;
34class NPadResource; 34class NPadResource;
35class AbstractPad;
36class NpadLastActiveHandler; 35class NpadLastActiveHandler;
37class NpadIrNfcHandler; 36class NpadIrNfcHandler;
38class UniquePads; 37class UniquePads;
@@ -44,7 +43,6 @@ class NpadGcVibration;
44 43
45class CaptureButtonResource; 44class CaptureButtonResource;
46class HomeButtonResource; 45class HomeButtonResource;
47class VibrationHandler;
48 46
49struct HandheldConfig; 47struct HandheldConfig;
50 48
@@ -57,7 +55,8 @@ public:
57 void SetExternals(AppletResourceHolder* applet_resource, 55 void SetExternals(AppletResourceHolder* applet_resource,
58 CaptureButtonResource* capture_button_resource, 56 CaptureButtonResource* capture_button_resource,
59 HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource, 57 HomeButtonResource* home_button_resource, SixAxisResource* sixaxis_resource,
60 PalmaResource* palma_resource, VibrationHandler* vibration); 58 PalmaResource* palma_resource, NpadVibration* vibration,
59 Core::HID::HIDCore* core);
61 void SetNpadId(Core::HID::NpadIdType npad_id); 60 void SetNpadId(Core::HID::NpadIdType npad_id);
62 61
63 Result Activate(); 62 Result Activate();
@@ -78,7 +77,6 @@ public:
78 77
79 NpadN64VibrationDevice* GetN64VibrationDevice(); 78 NpadN64VibrationDevice* GetN64VibrationDevice();
80 NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index); 79 NpadVibrationDevice* GetVibrationDevice(Core::HID::DeviceIndex device_index);
81 void GetLeftRightVibrationDevice(std::vector<NpadVibrationDevice*> list);
82 NpadGcVibrationDevice* GetGCVibrationDevice(); 80 NpadGcVibrationDevice* GetGCVibrationDevice();
83 81
84 Core::HID::NpadIdType GetLastActiveNpad(); 82 Core::HID::NpadIdType GetLastActiveNpad();
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp
index a00d6c9de..ca64b0a43 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp
+++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.cpp
@@ -1,6 +1,8 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include "hid_core/frontend/emulated_controller.h"
5#include "hid_core/hid_core.h"
4#include "hid_core/hid_result.h" 6#include "hid_core/hid_result.h"
5#include "hid_core/hid_util.h" 7#include "hid_core/hid_util.h"
6#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h" 8#include "hid_core/resources/abstracted_pad/abstract_pad_holder.h"
@@ -30,14 +32,22 @@ void NpadAbstractVibrationHandler::SetPropertiesHandler(NpadAbstractPropertiesHa
30 properties_handler = handler; 32 properties_handler = handler;
31} 33}
32 34
35void NpadAbstractVibrationHandler::SetVibrationHandler(NpadVibration* handler) {
36 vibration_handler = handler;
37}
38
39void NpadAbstractVibrationHandler::SetHidCore(Core::HID::HIDCore* core) {
40 hid_core = core;
41}
42
33void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) { 43void NpadAbstractVibrationHandler::SetN64Vibration(NpadN64VibrationDevice* n64_device) {
34 n64_vibration_device = n64_device; 44 n64_vibration_device = n64_device;
35} 45}
36 46
37void NpadAbstractVibrationHandler::SetVibration(std::span<NpadVibrationDevice*> device) { 47void NpadAbstractVibrationHandler::SetVibration(NpadVibrationDevice* left_device,
38 for (std::size_t i = 0; i < device.size() && i < vibration_device.size(); i++) { 48 NpadVibrationDevice* right_device) {
39 vibration_device[i] = device[i]; 49 left_vibration_device = left_device;
40 } 50 right_vibration_device = right_device;
41} 51}
42 52
43void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) { 53void NpadAbstractVibrationHandler::SetGcVibration(NpadGcVibrationDevice* gc_device) {
@@ -69,5 +79,29 @@ void NpadAbstractVibrationHandler::UpdateVibrationState() {
69 if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) { 79 if (!is_handheld_hid_enabled && is_force_handheld_style_vibration) {
70 // TODO 80 // TODO
71 } 81 }
82
83 // TODO: This function isn't accurate. It's supposed to get 5 abstracted pads from the
84 // NpadAbstractPropertiesHandler but this handler isn't fully implemented yet
85 IAbstractedPad abstracted_pad{};
86 const auto npad_id = properties_handler->GetNpadId();
87 abstracted_pad.xcd_handle = hid_core->GetEmulatedController(npad_id);
88 abstracted_pad.internal_flags.is_connected.Assign(abstracted_pad.xcd_handle->IsConnected());
89
90 if (abstracted_pad.internal_flags.is_connected) {
91 left_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Left,
92 vibration_handler);
93 right_vibration_device->Mount(abstracted_pad, Core::HID::DeviceIndex::Right,
94 vibration_handler);
95 gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler);
96 gc_vibration_device->Mount(abstracted_pad, 0, vibration_handler);
97 n64_vibration_device->Mount(abstracted_pad, vibration_handler);
98 return;
99 }
100
101 left_vibration_device->Unmount();
102 right_vibration_device->Unmount();
103 gc_vibration_device->Unmount();
104 gc_vibration_device->Unmount();
105 n64_vibration_device->Unmount();
72} 106}
73} // namespace Service::HID 107} // namespace Service::HID
diff --git a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h
index aeb07ce86..8bc8129c2 100644
--- a/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h
+++ b/src/hid_core/resources/abstracted_pad/abstract_vibration_handler.h
@@ -9,6 +9,10 @@
9#include "core/hle/result.h" 9#include "core/hle/result.h"
10#include "hid_core/hid_types.h" 10#include "hid_core/hid_types.h"
11 11
12namespace Core::HID {
13class HIDCore;
14}
15
12namespace Service::HID { 16namespace Service::HID {
13struct AppletResourceHolder; 17struct AppletResourceHolder;
14class NpadAbstractedPadHolder; 18class NpadAbstractedPadHolder;
@@ -27,9 +31,11 @@ public:
27 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder); 31 void SetAbstractPadHolder(NpadAbstractedPadHolder* holder);
28 void SetAppletResource(AppletResourceHolder* applet_resource); 32 void SetAppletResource(AppletResourceHolder* applet_resource);
29 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler); 33 void SetPropertiesHandler(NpadAbstractPropertiesHandler* handler);
34 void SetVibrationHandler(NpadVibration* handler);
35 void SetHidCore(Core::HID::HIDCore* core);
30 36
31 void SetN64Vibration(NpadN64VibrationDevice* n64_device); 37 void SetN64Vibration(NpadN64VibrationDevice* n64_device);
32 void SetVibration(std::span<NpadVibrationDevice*> device); 38 void SetVibration(NpadVibrationDevice* left_device, NpadVibrationDevice* right_device);
33 void SetGcVibration(NpadGcVibrationDevice* gc_device); 39 void SetGcVibration(NpadGcVibrationDevice* gc_device);
34 40
35 Result IncrementRefCounter(); 41 Result IncrementRefCounter();
@@ -41,9 +47,11 @@ private:
41 AppletResourceHolder* applet_resource_holder{nullptr}; 47 AppletResourceHolder* applet_resource_holder{nullptr};
42 NpadAbstractedPadHolder* abstract_pad_holder{nullptr}; 48 NpadAbstractedPadHolder* abstract_pad_holder{nullptr};
43 NpadAbstractPropertiesHandler* properties_handler{nullptr}; 49 NpadAbstractPropertiesHandler* properties_handler{nullptr};
50 Core::HID::HIDCore* hid_core{nullptr};
44 51
45 NpadN64VibrationDevice* n64_vibration_device{nullptr}; 52 NpadN64VibrationDevice* n64_vibration_device{nullptr};
46 std::array<NpadVibrationDevice*, 2> vibration_device{}; 53 NpadVibrationDevice* left_vibration_device{};
54 NpadVibrationDevice* right_vibration_device{};
47 NpadGcVibrationDevice* gc_vibration_device{nullptr}; 55 NpadGcVibrationDevice* gc_vibration_device{nullptr};
48 NpadVibration* vibration_handler{nullptr}; 56 NpadVibration* vibration_handler{nullptr};
49 s32 ref_counter{}; 57 s32 ref_counter{};
diff --git a/src/hid_core/resources/applet_resource.cpp b/src/hid_core/resources/applet_resource.cpp
index a84826050..db4134037 100644
--- a/src/hid_core/resources/applet_resource.cpp
+++ b/src/hid_core/resources/applet_resource.cpp
@@ -200,6 +200,25 @@ void AppletResource::EnableInput(u64 aruid, bool is_enabled) {
200 data[index].flag.enable_touchscreen.Assign(is_enabled); 200 data[index].flag.enable_touchscreen.Assign(is_enabled);
201} 201}
202 202
203bool AppletResource::SetAruidValidForVibration(u64 aruid, bool is_enabled) {
204 const u64 index = GetIndexFromAruid(aruid);
205 if (index >= AruidIndexMax) {
206 return false;
207 }
208
209 if (!is_enabled && aruid == active_vibration_aruid) {
210 active_vibration_aruid = SystemAruid;
211 return true;
212 }
213
214 if (is_enabled && aruid != active_vibration_aruid) {
215 active_vibration_aruid = aruid;
216 return true;
217 }
218
219 return false;
220}
221
203void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) { 222void AppletResource::EnableSixAxisSensor(u64 aruid, bool is_enabled) {
204 const u64 index = GetIndexFromAruid(aruid); 223 const u64 index = GetIndexFromAruid(aruid);
205 if (index >= AruidIndexMax) { 224 if (index >= AruidIndexMax) {
diff --git a/src/hid_core/resources/applet_resource.h b/src/hid_core/resources/applet_resource.h
index f3f32bac1..e9710d306 100644
--- a/src/hid_core/resources/applet_resource.h
+++ b/src/hid_core/resources/applet_resource.h
@@ -101,6 +101,7 @@ public:
101 Result DestroySevenSixAxisTransferMemory(); 101 Result DestroySevenSixAxisTransferMemory();
102 102
103 void EnableInput(u64 aruid, bool is_enabled); 103 void EnableInput(u64 aruid, bool is_enabled);
104 bool SetAruidValidForVibration(u64 aruid, bool is_enabled);
104 void EnableSixAxisSensor(u64 aruid, bool is_enabled); 105 void EnableSixAxisSensor(u64 aruid, bool is_enabled);
105 void EnablePadInput(u64 aruid, bool is_enabled); 106 void EnablePadInput(u64 aruid, bool is_enabled);
106 void EnableTouchScreen(u64 aruid, bool is_enabled); 107 void EnableTouchScreen(u64 aruid, bool is_enabled);
diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp
index 97537a2e2..d13a489c9 100644
--- a/src/hid_core/resources/npad/npad.cpp
+++ b/src/hid_core/resources/npad/npad.cpp
@@ -21,6 +21,7 @@
21#include "hid_core/hid_util.h" 21#include "hid_core/hid_util.h"
22#include "hid_core/resources/applet_resource.h" 22#include "hid_core/resources/applet_resource.h"
23#include "hid_core/resources/npad/npad.h" 23#include "hid_core/resources/npad/npad.h"
24#include "hid_core/resources/npad/npad_vibration.h"
24#include "hid_core/resources/shared_memory_format.h" 25#include "hid_core/resources/shared_memory_format.h"
25 26
26namespace Service::HID { 27namespace Service::HID {
@@ -31,10 +32,6 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service
31 for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) { 32 for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
32 auto& controller = controller_data[aruid_index][i]; 33 auto& controller = controller_data[aruid_index][i];
33 controller.device = hid_core.GetEmulatedControllerByIndex(i); 34 controller.device = hid_core.GetEmulatedControllerByIndex(i);
34 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
35 Core::HID::DEFAULT_VIBRATION_VALUE;
36 controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex]
37 .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE;
38 Core::HID::ControllerUpdateCallback engine_callback{ 35 Core::HID::ControllerUpdateCallback engine_callback{
39 .on_change = 36 .on_change =
40 [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, 37 [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
@@ -43,6 +40,10 @@ NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service
43 controller.callback_key = controller.device->SetCallback(engine_callback); 40 controller.callback_key = controller.device->SetCallback(engine_callback);
44 } 41 }
45 } 42 }
43 for (std::size_t i = 0; i < abstracted_pads.size(); ++i) {
44 abstracted_pads[i] = AbstractPad{};
45 abstracted_pads[i].SetNpadId(IndexToNpadIdType(i));
46 }
46} 47}
47 48
48NPad::~NPad() { 49NPad::~NPad() {
@@ -359,6 +360,7 @@ void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) {
359 npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id); 360 npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id);
360 WriteEmptyEntry(controller.shared_memory); 361 WriteEmptyEntry(controller.shared_memory);
361 hid_core.SetLastActiveController(npad_id); 362 hid_core.SetLastActiveController(npad_id);
363 abstracted_pads[NpadIdTypeToIndex(npad_id)].Update();
362} 364}
363 365
364void NPad::WriteEmptyEntry(NpadInternalState* npad) { 366void NPad::WriteEmptyEntry(NpadInternalState* npad) {
@@ -478,6 +480,10 @@ void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
478 continue; 480 continue;
479 } 481 }
480 482
483 if (!data->flag.enable_pad_input) {
484 continue;
485 }
486
481 RequestPadStateUpdate(aruid, controller.device->GetNpadIdType()); 487 RequestPadStateUpdate(aruid, controller.device->GetNpadIdType());
482 auto& pad_state = controller.npad_pad_state; 488 auto& pad_state = controller.npad_pad_state;
483 auto& libnx_state = controller.npad_libnx_state; 489 auto& libnx_state = controller.npad_libnx_state;
@@ -740,171 +746,6 @@ bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID:
740 return true; 746 return true;
741} 747}
742 748
743bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id,
744 std::size_t device_index,
745 const Core::HID::VibrationValue& vibration_value) {
746 auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
747 if (!controller.device->IsConnected()) {
748 return false;
749 }
750
751 if (!controller.device->IsVibrationEnabled(device_index)) {
752 if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
753 controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
754 // Send an empty vibration to stop any vibrations.
755 Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
756 controller.device->SetVibration(device_index, vibration);
757 // Then reset the vibration value to its default value.
758 controller.vibration[device_index].latest_vibration_value =
759 Core::HID::DEFAULT_VIBRATION_VALUE;
760 }
761
762 return false;
763 }
764
765 if (!Settings::values.enable_accurate_vibrations.GetValue()) {
766 using std::chrono::duration_cast;
767 using std::chrono::milliseconds;
768 using std::chrono::steady_clock;
769
770 const auto now = steady_clock::now();
771
772 // Filter out non-zero vibrations that are within 15ms of each other.
773 if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
774 duration_cast<milliseconds>(
775 now - controller.vibration[device_index].last_vibration_timepoint) <
776 milliseconds(15)) {
777 return false;
778 }
779
780 controller.vibration[device_index].last_vibration_timepoint = now;
781 }
782
783 Core::HID::VibrationValue vibration{
784 vibration_value.low_amplitude, vibration_value.low_frequency,
785 vibration_value.high_amplitude, vibration_value.high_frequency};
786 return controller.device->SetVibration(device_index, vibration);
787}
788
789void NPad::VibrateController(u64 aruid,
790 const Core::HID::VibrationDeviceHandle& vibration_device_handle,
791 const Core::HID::VibrationValue& vibration_value) {
792 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
793 return;
794 }
795
796 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
797 return;
798 }
799
800 auto& controller = GetControllerFromHandle(aruid, vibration_device_handle);
801 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
802
803 if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
804 return;
805 }
806
807 if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
808 ASSERT_MSG(false, "DeviceIndex should never be None!");
809 return;
810 }
811
812 // Some games try to send mismatched parameters in the device handle, block these.
813 if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
814 (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
815 vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
816 (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
817 (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
818 vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
819 return;
820 }
821
822 // Filter out vibrations with equivalent values to reduce unnecessary state changes.
823 if (vibration_value.low_amplitude ==
824 controller.vibration[device_index].latest_vibration_value.low_amplitude &&
825 vibration_value.high_amplitude ==
826 controller.vibration[device_index].latest_vibration_value.high_amplitude) {
827 return;
828 }
829
830 if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index,
831 vibration_value)) {
832 controller.vibration[device_index].latest_vibration_value = vibration_value;
833 }
834}
835
836void NPad::VibrateControllers(
837 u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
838 std::span<const Core::HID::VibrationValue> vibration_values) {
839 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
840 return;
841 }
842
843 ASSERT_OR_EXECUTE_MSG(
844 vibration_device_handles.size() == vibration_values.size(), { return; },
845 "The amount of device handles does not match with the amount of vibration values,"
846 "this is undefined behavior!");
847
848 for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
849 VibrateController(aruid, vibration_device_handles[i], vibration_values[i]);
850 }
851}
852
853Core::HID::VibrationValue NPad::GetLastVibration(
854 u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
855 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
856 return {};
857 }
858
859 const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle);
860 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
861 return controller.vibration[device_index].latest_vibration_value;
862}
863
864void NPad::InitializeVibrationDevice(
865 const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
866 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
867 return;
868 }
869
870 const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
871 const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
872 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
873
874 if (aruid == 0) {
875 return;
876 }
877
878 InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index);
879}
880
881void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id,
882 std::size_t device_index) {
883 auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
884 if (!Settings::values.vibration_enabled.GetValue()) {
885 controller.vibration[device_index].device_mounted = false;
886 return;
887 }
888
889 controller.vibration[device_index].device_mounted =
890 controller.device->IsVibrationEnabled(device_index);
891}
892
893void NPad::SetPermitVibrationSession(bool permit_vibration_session) {
894 permit_vibration_session_enabled = permit_vibration_session;
895}
896
897bool NPad::IsVibrationDeviceMounted(
898 u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
899 if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
900 return false;
901 }
902
903 const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle);
904 const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
905 return controller.vibration[device_index].device_mounted;
906}
907
908Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, 749Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event,
909 Core::HID::NpadIdType npad_id) { 750 Core::HID::NpadIdType npad_id) {
910 std::scoped_lock lock{mutex}; 751 std::scoped_lock lock{mutex};
@@ -936,11 +777,6 @@ Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) {
936 777
937 LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id); 778 LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
938 auto& controller = GetControllerFromNpadIdType(aruid, npad_id); 779 auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
939 for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
940 // Send an empty vibration to stop any vibrations.
941 VibrateControllerAtIndex(aruid, npad_id, device_idx, {});
942 controller.vibration[device_idx].device_mounted = false;
943 }
944 780
945 auto* shared_memory = controller.shared_memory; 781 auto* shared_memory = controller.shared_memory;
946 // Don't reset shared_memory->assignment_mode this value is persistent 782 // Don't reset shared_memory->assignment_mode this value is persistent
@@ -1232,26 +1068,28 @@ Result NPad::RegisterAppletResourceUserId(u64 aruid) {
1232} 1068}
1233 1069
1234void NPad::UnregisterAppletResourceUserId(u64 aruid) { 1070void NPad::UnregisterAppletResourceUserId(u64 aruid) {
1071 // TODO: Remove this once abstract pad is emulated properly
1072 const auto aruid_index = npad_resource.GetIndexFromAruid(aruid);
1073 for (auto& controller : controller_data[aruid_index]) {
1074 controller.is_connected = false;
1075 controller.shared_memory = nullptr;
1076 }
1077
1235 npad_resource.UnregisterAppletResourceUserId(aruid); 1078 npad_resource.UnregisterAppletResourceUserId(aruid);
1236} 1079}
1237 1080
1238void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource, 1081void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource,
1239 std::recursive_mutex* shared_mutex) { 1082 std::recursive_mutex* shared_mutex,
1083 std::shared_ptr<HandheldConfig> handheld_config) {
1240 applet_resource_holder.applet_resource = resource; 1084 applet_resource_holder.applet_resource = resource;
1241 applet_resource_holder.shared_mutex = shared_mutex; 1085 applet_resource_holder.shared_mutex = shared_mutex;
1242 applet_resource_holder.shared_npad_resource = &npad_resource; 1086 applet_resource_holder.shared_npad_resource = &npad_resource;
1243} 1087 applet_resource_holder.handheld_config = handheld_config;
1244
1245NPad::NpadControllerData& NPad::GetControllerFromHandle(
1246 u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) {
1247 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
1248 return GetControllerFromNpadIdType(aruid, npad_id);
1249}
1250 1088
1251const NPad::NpadControllerData& NPad::GetControllerFromHandle( 1089 for (auto& abstract_pad : abstracted_pads) {
1252 u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const { 1090 abstract_pad.SetExternals(&applet_resource_holder, nullptr, nullptr, nullptr, nullptr,
1253 const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id); 1091 &vibration_handler, &hid_core);
1254 return GetControllerFromNpadIdType(aruid, npad_id); 1092 }
1255} 1093}
1256 1094
1257NPad::NpadControllerData& NPad::GetControllerFromHandle( 1095NPad::NpadControllerData& NPad::GetControllerFromHandle(
@@ -1389,4 +1227,106 @@ Result NPad::GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const {
1389 return ResultSuccess; 1227 return ResultSuccess;
1390} 1228}
1391 1229
1230NpadVibration* NPad::GetVibrationHandler() {
1231 return &vibration_handler;
1232}
1233
1234std::vector<NpadVibrationBase*> NPad::GetAllVibrationDevices() {
1235 std::vector<NpadVibrationBase*> vibration_devices;
1236
1237 for (auto& abstract_pad : abstracted_pads) {
1238 auto* left_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Left);
1239 auto* right_device = abstract_pad.GetVibrationDevice(Core::HID::DeviceIndex::Right);
1240 auto* n64_device = abstract_pad.GetGCVibrationDevice();
1241 auto* gc_device = abstract_pad.GetGCVibrationDevice();
1242
1243 if (left_device != nullptr) {
1244 vibration_devices.emplace_back(left_device);
1245 }
1246 if (right_device != nullptr) {
1247 vibration_devices.emplace_back(right_device);
1248 }
1249 if (n64_device != nullptr) {
1250 vibration_devices.emplace_back(n64_device);
1251 }
1252 if (gc_device != nullptr) {
1253 vibration_devices.emplace_back(gc_device);
1254 }
1255 }
1256
1257 return vibration_devices;
1258}
1259
1260NpadVibrationBase* NPad::GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) {
1261 if (IsVibrationHandleValid(handle).IsError()) {
1262 return nullptr;
1263 }
1264
1265 const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id));
1266 const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type);
1267 if (style_inde == Core::HID::NpadStyleIndex::GameCube) {
1268 return abstracted_pads[npad_index].GetGCVibrationDevice();
1269 }
1270 if (style_inde == Core::HID::NpadStyleIndex::N64) {
1271 return abstracted_pads[npad_index].GetN64VibrationDevice();
1272 }
1273 return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index);
1274}
1275
1276NpadN64VibrationDevice* NPad::GetN64VibrationDevice(
1277 const Core::HID::VibrationDeviceHandle& handle) {
1278 if (IsVibrationHandleValid(handle).IsError()) {
1279 return nullptr;
1280 }
1281
1282 const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id));
1283 const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type);
1284 if (style_inde != Core::HID::NpadStyleIndex::N64) {
1285 return nullptr;
1286 }
1287 return abstracted_pads[npad_index].GetN64VibrationDevice();
1288}
1289
1290NpadVibrationDevice* NPad::GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) {
1291 if (IsVibrationHandleValid(handle).IsError()) {
1292 return nullptr;
1293 }
1294
1295 const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id));
1296 const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type);
1297 if (style_inde == Core::HID::NpadStyleIndex::GameCube ||
1298 style_inde == Core::HID::NpadStyleIndex::N64) {
1299 return nullptr;
1300 }
1301
1302 return abstracted_pads[npad_index].GetVibrationDevice(handle.device_index);
1303}
1304
1305NpadGcVibrationDevice* NPad::GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle) {
1306 if (IsVibrationHandleValid(handle).IsError()) {
1307 return nullptr;
1308 }
1309
1310 const auto npad_index = NpadIdTypeToIndex(static_cast<Core::HID::NpadIdType>(handle.npad_id));
1311 const auto style_inde = static_cast<Core::HID::NpadStyleIndex>(handle.npad_type);
1312 if (style_inde != Core::HID::NpadStyleIndex::GameCube) {
1313 return nullptr;
1314 }
1315 return abstracted_pads[npad_index].GetGCVibrationDevice();
1316}
1317
1318void NPad::UpdateHandheldAbstractState() {
1319 std::scoped_lock lock{mutex};
1320 abstracted_pads[NpadIdTypeToIndex(Core::HID::NpadIdType::Handheld)].Update();
1321}
1322
1323void NPad::EnableAppletToGetInput(u64 aruid) {
1324 std::scoped_lock lock{mutex};
1325 std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex};
1326
1327 for (auto& abstract_pad : abstracted_pads) {
1328 abstract_pad.EnableAppletToGetInput(aruid);
1329 }
1330}
1331
1392} // namespace Service::HID 1332} // namespace Service::HID
diff --git a/src/hid_core/resources/npad/npad.h b/src/hid_core/resources/npad/npad.h
index 01f3dabb1..88289fa2b 100644
--- a/src/hid_core/resources/npad/npad.h
+++ b/src/hid_core/resources/npad/npad.h
@@ -10,9 +10,15 @@
10 10
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "hid_core/hid_types.h" 12#include "hid_core/hid_types.h"
13#include "hid_core/resources/abstracted_pad/abstract_pad.h"
13#include "hid_core/resources/controller_base.h" 14#include "hid_core/resources/controller_base.h"
14#include "hid_core/resources/npad/npad_resource.h" 15#include "hid_core/resources/npad/npad_resource.h"
15#include "hid_core/resources/npad/npad_types.h" 16#include "hid_core/resources/npad/npad_types.h"
17#include "hid_core/resources/npad/npad_vibration.h"
18#include "hid_core/resources/vibration/gc_vibration_device.h"
19#include "hid_core/resources/vibration/n64_vibration_device.h"
20#include "hid_core/resources/vibration/vibration_base.h"
21#include "hid_core/resources/vibration/vibration_device.h"
16 22
17namespace Core::HID { 23namespace Core::HID {
18class EmulatedController; 24class EmulatedController;
@@ -32,6 +38,7 @@ union Result;
32 38
33namespace Service::HID { 39namespace Service::HID {
34class AppletResource; 40class AppletResource;
41struct HandheldConfig;
35struct NpadInternalState; 42struct NpadInternalState;
36struct NpadSixAxisSensorLifo; 43struct NpadSixAxisSensorLifo;
37struct NpadSharedMemoryFormat; 44struct NpadSharedMemoryFormat;
@@ -68,31 +75,6 @@ public:
68 bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id, 75 bool SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
69 NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode); 76 NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode);
70 77
71 bool VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id,
72 std::size_t device_index,
73 const Core::HID::VibrationValue& vibration_value);
74
75 void VibrateController(u64 aruid,
76 const Core::HID::VibrationDeviceHandle& vibration_device_handle,
77 const Core::HID::VibrationValue& vibration_value);
78
79 void VibrateControllers(
80 u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
81 std::span<const Core::HID::VibrationValue> vibration_values);
82
83 Core::HID::VibrationValue GetLastVibration(
84 u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
85
86 void InitializeVibrationDevice(const Core::HID::VibrationDeviceHandle& vibration_device_handle);
87
88 void InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id,
89 std::size_t device_index);
90
91 void SetPermitVibrationSession(bool permit_vibration_session);
92
93 bool IsVibrationDeviceMounted(
94 u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
95
96 Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event, 78 Result AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event,
97 Core::HID::NpadIdType npad_id); 79 Core::HID::NpadIdType npad_id);
98 80
@@ -145,7 +127,8 @@ public:
145 Result RegisterAppletResourceUserId(u64 aruid); 127 Result RegisterAppletResourceUserId(u64 aruid);
146 void UnregisterAppletResourceUserId(u64 aruid); 128 void UnregisterAppletResourceUserId(u64 aruid);
147 void SetNpadExternals(std::shared_ptr<AppletResource> resource, 129 void SetNpadExternals(std::shared_ptr<AppletResource> resource,
148 std::recursive_mutex* shared_mutex); 130 std::recursive_mutex* shared_mutex,
131 std::shared_ptr<HandheldConfig> handheld_config);
149 132
150 AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id); 133 AppletDetailedUiType GetAppletDetailedUiType(Core::HID::NpadIdType npad_id);
151 134
@@ -161,18 +144,22 @@ public:
161 144
162 Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const; 145 Result GetLastActiveNpad(Core::HID::NpadIdType& out_npad_id) const;
163 146
164private: 147 NpadVibration* GetVibrationHandler();
165 struct VibrationData { 148 std::vector<NpadVibrationBase*> GetAllVibrationDevices();
166 bool device_mounted{}; 149 NpadVibrationBase* GetVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
167 Core::HID::VibrationValue latest_vibration_value{}; 150 NpadN64VibrationDevice* GetN64VibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
168 std::chrono::steady_clock::time_point last_vibration_timepoint{}; 151 NpadVibrationDevice* GetNSVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
169 }; 152 NpadGcVibrationDevice* GetGcVibrationDevice(const Core::HID::VibrationDeviceHandle& handle);
153
154 void UpdateHandheldAbstractState();
155
156 void EnableAppletToGetInput(u64 aruid);
170 157
158private:
171 struct NpadControllerData { 159 struct NpadControllerData {
172 NpadInternalState* shared_memory = nullptr; 160 NpadInternalState* shared_memory = nullptr;
173 Core::HID::EmulatedController* device = nullptr; 161 Core::HID::EmulatedController* device = nullptr;
174 162
175 std::array<VibrationData, 2> vibration{};
176 bool is_connected{}; 163 bool is_connected{};
177 164
178 // Dual joycons can have only one side connected 165 // Dual joycons can have only one side connected
@@ -192,10 +179,6 @@ private:
192 void WriteEmptyEntry(NpadInternalState* npad); 179 void WriteEmptyEntry(NpadInternalState* npad);
193 180
194 NpadControllerData& GetControllerFromHandle( 181 NpadControllerData& GetControllerFromHandle(
195 u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle);
196 const NpadControllerData& GetControllerFromHandle(
197 u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const;
198 NpadControllerData& GetControllerFromHandle(
199 u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle); 182 u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle);
200 const NpadControllerData& GetControllerFromHandle( 183 const NpadControllerData& GetControllerFromHandle(
201 u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const; 184 u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const;
@@ -215,11 +198,13 @@ private:
215 mutable std::mutex mutex; 198 mutable std::mutex mutex;
216 NPadResource npad_resource; 199 NPadResource npad_resource;
217 AppletResourceHolder applet_resource_holder{}; 200 AppletResourceHolder applet_resource_holder{};
201 std::array<AbstractPad, MaxSupportedNpadIdTypes> abstracted_pads;
202 NpadVibration vibration_handler{};
203
218 Kernel::KEvent* input_event{nullptr}; 204 Kernel::KEvent* input_event{nullptr};
219 std::mutex* input_mutex{nullptr}; 205 std::mutex* input_mutex{nullptr};
220 206
221 std::atomic<u64> press_state{}; 207 std::atomic<u64> press_state{};
222 bool permit_vibration_session_enabled;
223 std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax> 208 std::array<std::array<NpadControllerData, MaxSupportedNpadIdTypes>, AruidIndexMax>
224 controller_data{}; 209 controller_data{};
225}; 210};
diff --git a/src/hid_core/resources/npad/npad_types.h b/src/hid_core/resources/npad/npad_types.h
index fd86c8e40..92700d69a 100644
--- a/src/hid_core/resources/npad/npad_types.h
+++ b/src/hid_core/resources/npad/npad_types.h
@@ -8,6 +8,10 @@
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "hid_core/hid_types.h" 9#include "hid_core/hid_types.h"
10 10
11namespace Core::HID {
12class EmulatedController;
13}
14
11namespace Service::HID { 15namespace Service::HID {
12static constexpr std::size_t MaxSupportedNpadIdTypes = 10; 16static constexpr std::size_t MaxSupportedNpadIdTypes = 10;
13static constexpr std::size_t StyleIndexCount = 7; 17static constexpr std::size_t StyleIndexCount = 7;
@@ -348,7 +352,7 @@ struct IAbstractedPad {
348 u8 indicator; 352 u8 indicator;
349 std::vector<f32> virtual_six_axis_sensor_acceleration; 353 std::vector<f32> virtual_six_axis_sensor_acceleration;
350 std::vector<f32> virtual_six_axis_sensor_angle; 354 std::vector<f32> virtual_six_axis_sensor_angle;
351 u64 xcd_handle; 355 Core::HID::EmulatedController* xcd_handle;
352 u64 color; 356 u64 color;
353}; 357};
354} // namespace Service::HID 358} // namespace Service::HID
diff --git a/src/hid_core/resources/npad/npad_vibration.cpp b/src/hid_core/resources/npad/npad_vibration.cpp
index 7056e8eab..05aad4c54 100644
--- a/src/hid_core/resources/npad/npad_vibration.cpp
+++ b/src/hid_core/resources/npad/npad_vibration.cpp
@@ -77,4 +77,8 @@ Result NpadVibration::EndPermitVibrationSession() {
77 return ResultSuccess; 77 return ResultSuccess;
78} 78}
79 79
80u64 NpadVibration::GetSessionAruid() const {
81 return session_aruid;
82}
83
80} // namespace Service::HID 84} // namespace Service::HID
diff --git a/src/hid_core/resources/npad/npad_vibration.h b/src/hid_core/resources/npad/npad_vibration.h
index 0748aeffc..d5a95f2a0 100644
--- a/src/hid_core/resources/npad/npad_vibration.h
+++ b/src/hid_core/resources/npad/npad_vibration.h
@@ -25,6 +25,8 @@ public:
25 Result BeginPermitVibrationSession(u64 aruid); 25 Result BeginPermitVibrationSession(u64 aruid);
26 Result EndPermitVibrationSession(); 26 Result EndPermitVibrationSession();
27 27
28 u64 GetSessionAruid() const;
29
28private: 30private:
29 f32 volume{}; 31 f32 volume{};
30 u64 session_aruid{}; 32 u64 session_aruid{};
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.cpp b/src/hid_core/resources/vibration/gc_vibration_device.cpp
index f01f81b9a..ad42b9d66 100644
--- a/src/hid_core/resources/vibration/gc_vibration_device.cpp
+++ b/src/hid_core/resources/vibration/gc_vibration_device.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include "hid_core/frontend/emulated_controller.h"
4#include "hid_core/hid_result.h" 5#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_types.h" 6#include "hid_core/resources/npad/npad_types.h"
6#include "hid_core/resources/npad/npad_vibration.h" 7#include "hid_core/resources/npad/npad_vibration.h"
@@ -10,24 +11,25 @@ namespace Service::HID {
10 11
11NpadGcVibrationDevice::NpadGcVibrationDevice() {} 12NpadGcVibrationDevice::NpadGcVibrationDevice() {}
12 13
13Result NpadGcVibrationDevice::IncrementRefCounter() { 14Result NpadGcVibrationDevice::Activate() {
14 if (ref_counter == 0 && is_mounted) { 15 if (ref_counter == 0 && is_mounted) {
15 f32 volume = 1.0f; 16 f32 volume = 1.0f;
16 const auto result = vibration_handler->GetVibrationVolume(volume); 17 const auto result = vibration_handler->GetVibrationVolume(volume);
17 if (result.IsSuccess()) { 18 if (result.IsSuccess()) {
18 // TODO: SendVibrationGcErmCommand 19 xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop);
19 } 20 }
20 } 21 }
22
21 ref_counter++; 23 ref_counter++;
22 return ResultSuccess; 24 return ResultSuccess;
23} 25}
24 26
25Result NpadGcVibrationDevice::DecrementRefCounter() { 27Result NpadGcVibrationDevice::Deactivate() {
26 if (ref_counter == 1 && !is_mounted) { 28 if (ref_counter == 1 && is_mounted) {
27 f32 volume = 1.0f; 29 f32 volume = 1.0f;
28 const auto result = vibration_handler->GetVibrationVolume(volume); 30 const auto result = vibration_handler->GetVibrationVolume(volume);
29 if (result.IsSuccess()) { 31 if (result.IsSuccess()) {
30 // TODO: SendVibrationGcErmCommand 32 xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop);
31 } 33 }
32 } 34 }
33 35
@@ -38,6 +40,48 @@ Result NpadGcVibrationDevice::DecrementRefCounter() {
38 return ResultSuccess; 40 return ResultSuccess;
39} 41}
40 42
43Result NpadGcVibrationDevice::Mount(IAbstractedPad& abstracted_pad, u32 slot,
44 NpadVibration* handler) {
45 if (!abstracted_pad.internal_flags.is_connected) {
46 return ResultSuccess;
47 }
48
49 // TODO: This device doesn't use a xcd handle instead has an GC adapter handle. This is just to
50 // keep compatibility with the front end.
51 xcd_handle = abstracted_pad.xcd_handle;
52 adapter_slot = slot;
53 vibration_handler = handler;
54 is_mounted = true;
55
56 if (ref_counter == 0) {
57 return ResultSuccess;
58 }
59
60 f32 volume{1.0f};
61 const auto result = vibration_handler->GetVibrationVolume(volume);
62 if (result.IsSuccess()) {
63 xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop);
64 }
65
66 return ResultSuccess;
67}
68
69Result NpadGcVibrationDevice::Unmount() {
70 if (ref_counter == 0 || !is_mounted) {
71 is_mounted = false;
72 return ResultSuccess;
73 }
74
75 f32 volume{1.0f};
76 const auto result = vibration_handler->GetVibrationVolume(volume);
77 if (result.IsSuccess()) {
78 xcd_handle->SetVibration(adapter_slot, Core::HID::VibrationGcErmCommand::Stop);
79 }
80
81 is_mounted = false;
82 return ResultSuccess;
83}
84
41Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) { 85Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command) {
42 if (!is_mounted) { 86 if (!is_mounted) {
43 return ResultSuccess; 87 return ResultSuccess;
@@ -55,7 +99,7 @@ Result NpadGcVibrationDevice::SendVibrationGcErmCommand(Core::HID::VibrationGcEr
55 return ResultSuccess; 99 return ResultSuccess;
56 } 100 }
57 } 101 }
58 // TODO: SendVibrationGcErmCommand 102 xcd_handle->SetVibration(adapter_slot, command);
59 return ResultSuccess; 103 return ResultSuccess;
60} 104}
61 105
diff --git a/src/hid_core/resources/vibration/gc_vibration_device.h b/src/hid_core/resources/vibration/gc_vibration_device.h
index 87abca57d..c624cbb28 100644
--- a/src/hid_core/resources/vibration/gc_vibration_device.h
+++ b/src/hid_core/resources/vibration/gc_vibration_device.h
@@ -20,12 +20,18 @@ class NpadGcVibrationDevice final : public NpadVibrationBase {
20public: 20public:
21 explicit NpadGcVibrationDevice(); 21 explicit NpadGcVibrationDevice();
22 22
23 Result IncrementRefCounter() override; 23 Result Activate() override;
24 Result DecrementRefCounter() override; 24 Result Deactivate() override;
25
26 Result Mount(IAbstractedPad& abstracted_pad, u32 slot, NpadVibration* handler);
27 Result Unmount();
25 28
26 Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command); 29 Result SendVibrationGcErmCommand(Core::HID::VibrationGcErmCommand command);
27 30
28 Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command); 31 Result GetActualVibrationGcErmCommand(Core::HID::VibrationGcErmCommand& out_command);
29 Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command); 32 Result SendVibrationNotificationPattern(Core::HID::VibrationGcErmCommand command);
33
34private:
35 u32 adapter_slot;
30}; 36};
31} // namespace Service::HID 37} // namespace Service::HID
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.cpp b/src/hid_core/resources/vibration/n64_vibration_device.cpp
index 639f87abf..94ad37c8f 100644
--- a/src/hid_core/resources/vibration/n64_vibration_device.cpp
+++ b/src/hid_core/resources/vibration/n64_vibration_device.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include "hid_core/frontend/emulated_controller.h"
4#include "hid_core/hid_result.h" 5#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_types.h" 6#include "hid_core/resources/npad/npad_types.h"
6#include "hid_core/resources/npad/npad_vibration.h" 7#include "hid_core/resources/npad/npad_vibration.h"
@@ -10,12 +11,12 @@ namespace Service::HID {
10 11
11NpadN64VibrationDevice::NpadN64VibrationDevice() {} 12NpadN64VibrationDevice::NpadN64VibrationDevice() {}
12 13
13Result NpadN64VibrationDevice::IncrementRefCounter() { 14Result NpadN64VibrationDevice::Activate() {
14 if (ref_counter == 0 && is_mounted) { 15 if (ref_counter == 0 && is_mounted) {
15 f32 volume = 1.0f; 16 f32 volume = 1.0f;
16 const auto result = vibration_handler->GetVibrationVolume(volume); 17 const auto result = vibration_handler->GetVibrationVolume(volume);
17 if (result.IsSuccess()) { 18 if (result.IsSuccess()) {
18 // TODO: SendVibrationInBool 19 xcd_handle->SetVibration(false);
19 } 20 }
20 } 21 }
21 22
@@ -23,19 +24,12 @@ Result NpadN64VibrationDevice::IncrementRefCounter() {
23 return ResultSuccess; 24 return ResultSuccess;
24} 25}
25 26
26Result NpadN64VibrationDevice::DecrementRefCounter() { 27Result NpadN64VibrationDevice::Deactivate() {
27 if (ref_counter == 1) { 28 if (ref_counter == 1 && is_mounted) {
28 if (!is_mounted) {
29 ref_counter = 0;
30 if (is_mounted != false) {
31 // TODO: SendVibrationInBool
32 }
33 return ResultSuccess;
34 }
35 f32 volume = 1.0f; 29 f32 volume = 1.0f;
36 const auto result = vibration_handler->GetVibrationVolume(volume); 30 const auto result = vibration_handler->GetVibrationVolume(volume);
37 if (result.IsSuccess()) { 31 if (result.IsSuccess()) {
38 // TODO 32 xcd_handle->SetVibration(false);
39 } 33 }
40 } 34 }
41 35
@@ -46,6 +40,43 @@ Result NpadN64VibrationDevice::DecrementRefCounter() {
46 return ResultSuccess; 40 return ResultSuccess;
47} 41}
48 42
43Result NpadN64VibrationDevice::Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler) {
44 if (!abstracted_pad.internal_flags.is_connected) {
45 return ResultSuccess;
46 }
47 xcd_handle = abstracted_pad.xcd_handle;
48 vibration_handler = handler;
49 is_mounted = true;
50
51 if (ref_counter == 0) {
52 return ResultSuccess;
53 }
54
55 f32 volume{1.0f};
56 const auto result = vibration_handler->GetVibrationVolume(volume);
57 if (result.IsSuccess()) {
58 xcd_handle->SetVibration(false);
59 }
60
61 return ResultSuccess;
62}
63
64Result NpadN64VibrationDevice::Unmount() {
65 if (ref_counter == 0 || !is_mounted) {
66 is_mounted = false;
67 return ResultSuccess;
68 }
69
70 f32 volume{1.0f};
71 const auto result = vibration_handler->GetVibrationVolume(volume);
72 if (result.IsSuccess()) {
73 xcd_handle->SetVibration(false);
74 }
75
76 is_mounted = false;
77 return ResultSuccess;
78}
79
49Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) { 80Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) {
50 if (ref_counter < 1) { 81 if (ref_counter < 1) {
51 return ResultVibrationNotInitialized; 82 return ResultVibrationNotInitialized;
@@ -56,7 +87,7 @@ Result NpadN64VibrationDevice::SendValueInBool(bool is_vibrating) {
56 if (result.IsError()) { 87 if (result.IsError()) {
57 return result; 88 return result;
58 } 89 }
59 // TODO: SendVibrationInBool 90 xcd_handle->SetVibration(false);
60 } 91 }
61 return ResultSuccess; 92 return ResultSuccess;
62} 93}
diff --git a/src/hid_core/resources/vibration/n64_vibration_device.h b/src/hid_core/resources/vibration/n64_vibration_device.h
index 54e6efc1a..09de7701c 100644
--- a/src/hid_core/resources/vibration/n64_vibration_device.h
+++ b/src/hid_core/resources/vibration/n64_vibration_device.h
@@ -14,14 +14,18 @@
14 14
15namespace Service::HID { 15namespace Service::HID {
16class NpadVibration; 16class NpadVibration;
17struct IAbstractedPad;
17 18
18/// Handles Npad request from HID interfaces 19/// Handles Npad request from HID interfaces
19class NpadN64VibrationDevice final : public NpadVibrationBase { 20class NpadN64VibrationDevice final : public NpadVibrationBase {
20public: 21public:
21 explicit NpadN64VibrationDevice(); 22 explicit NpadN64VibrationDevice();
22 23
23 Result IncrementRefCounter() override; 24 Result Activate() override;
24 Result DecrementRefCounter() override; 25 Result Deactivate() override;
26
27 Result Mount(IAbstractedPad& abstracted_pad, NpadVibration* handler);
28 Result Unmount();
25 29
26 Result SendValueInBool(bool is_vibrating); 30 Result SendValueInBool(bool is_vibrating);
27 Result SendVibrationNotificationPattern(u32 pattern); 31 Result SendVibrationNotificationPattern(u32 pattern);
diff --git a/src/hid_core/resources/vibration/vibration_base.cpp b/src/hid_core/resources/vibration/vibration_base.cpp
index 350f349c2..f28d30406 100644
--- a/src/hid_core/resources/vibration/vibration_base.cpp
+++ b/src/hid_core/resources/vibration/vibration_base.cpp
@@ -10,12 +10,12 @@ namespace Service::HID {
10 10
11NpadVibrationBase::NpadVibrationBase() {} 11NpadVibrationBase::NpadVibrationBase() {}
12 12
13Result NpadVibrationBase::IncrementRefCounter() { 13Result NpadVibrationBase::Activate() {
14 ref_counter++; 14 ref_counter++;
15 return ResultSuccess; 15 return ResultSuccess;
16} 16}
17 17
18Result NpadVibrationBase::DecrementRefCounter() { 18Result NpadVibrationBase::Deactivate() {
19 if (ref_counter > 0) { 19 if (ref_counter > 0) {
20 ref_counter--; 20 ref_counter--;
21 } 21 }
diff --git a/src/hid_core/resources/vibration/vibration_base.h b/src/hid_core/resources/vibration/vibration_base.h
index c6c5fc4d9..69c26e669 100644
--- a/src/hid_core/resources/vibration/vibration_base.h
+++ b/src/hid_core/resources/vibration/vibration_base.h
@@ -6,6 +6,10 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/hle/result.h" 7#include "core/hle/result.h"
8 8
9namespace Core::HID {
10class EmulatedController;
11}
12
9namespace Service::HID { 13namespace Service::HID {
10class NpadVibration; 14class NpadVibration;
11 15
@@ -14,13 +18,13 @@ class NpadVibrationBase {
14public: 18public:
15 explicit NpadVibrationBase(); 19 explicit NpadVibrationBase();
16 20
17 virtual Result IncrementRefCounter(); 21 virtual Result Activate();
18 virtual Result DecrementRefCounter(); 22 virtual Result Deactivate();
19 23
20 bool IsVibrationMounted() const; 24 bool IsVibrationMounted() const;
21 25
22protected: 26protected:
23 u64 xcd_handle{}; 27 Core::HID::EmulatedController* xcd_handle{nullptr};
24 s32 ref_counter{}; 28 s32 ref_counter{};
25 bool is_mounted{}; 29 bool is_mounted{};
26 NpadVibration* vibration_handler{nullptr}; 30 NpadVibration* vibration_handler{nullptr};
diff --git a/src/hid_core/resources/vibration/vibration_device.cpp b/src/hid_core/resources/vibration/vibration_device.cpp
index 888c3a7ed..08b14591f 100644
--- a/src/hid_core/resources/vibration/vibration_device.cpp
+++ b/src/hid_core/resources/vibration/vibration_device.cpp
@@ -1,6 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#include "hid_core/frontend/emulated_controller.h"
4#include "hid_core/hid_result.h" 5#include "hid_core/hid_result.h"
5#include "hid_core/resources/npad/npad_types.h" 6#include "hid_core/resources/npad/npad_types.h"
6#include "hid_core/resources/npad/npad_vibration.h" 7#include "hid_core/resources/npad/npad_vibration.h"
@@ -10,12 +11,30 @@ namespace Service::HID {
10 11
11NpadVibrationDevice::NpadVibrationDevice() {} 12NpadVibrationDevice::NpadVibrationDevice() {}
12 13
13Result NpadVibrationDevice::IncrementRefCounter() { 14Result NpadVibrationDevice::Activate() {
15 if (ref_counter == 0 && is_mounted) {
16 f32 volume = 1.0f;
17 const auto result = vibration_handler->GetVibrationVolume(volume);
18 if (result.IsSuccess()) {
19 xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE);
20 // TODO: SendNotificationPattern;
21 }
22 }
23
14 ref_counter++; 24 ref_counter++;
15 return ResultSuccess; 25 return ResultSuccess;
16} 26}
17 27
18Result NpadVibrationDevice::DecrementRefCounter() { 28Result NpadVibrationDevice::Deactivate() {
29 if (ref_counter == 1 && is_mounted) {
30 f32 volume = 1.0f;
31 const auto result = vibration_handler->GetVibrationVolume(volume);
32 if (result.IsSuccess()) {
33 xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE);
34 // TODO: SendNotificationPattern;
35 }
36 }
37
19 if (ref_counter > 0) { 38 if (ref_counter > 0) {
20 ref_counter--; 39 ref_counter--;
21 } 40 }
@@ -23,6 +42,45 @@ Result NpadVibrationDevice::DecrementRefCounter() {
23 return ResultSuccess; 42 return ResultSuccess;
24} 43}
25 44
45Result NpadVibrationDevice::Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index,
46 NpadVibration* handler) {
47 if (!abstracted_pad.internal_flags.is_connected) {
48 return ResultSuccess;
49 }
50 xcd_handle = abstracted_pad.xcd_handle;
51 device_index = index;
52 vibration_handler = handler;
53 is_mounted = true;
54
55 if (ref_counter == 0) {
56 return ResultSuccess;
57 }
58
59 f32 volume{1.0f};
60 const auto result = vibration_handler->GetVibrationVolume(volume);
61 if (result.IsSuccess()) {
62 xcd_handle->SetVibration(false);
63 }
64
65 return ResultSuccess;
66}
67
68Result NpadVibrationDevice::Unmount() {
69 if (ref_counter == 0 || !is_mounted) {
70 is_mounted = false;
71 return ResultSuccess;
72 }
73
74 f32 volume{1.0f};
75 const auto result = vibration_handler->GetVibrationVolume(volume);
76 if (result.IsSuccess()) {
77 xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE);
78 }
79
80 is_mounted = false;
81 return ResultSuccess;
82}
83
26Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) { 84Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue& value) {
27 if (ref_counter == 0) { 85 if (ref_counter == 0) {
28 return ResultVibrationNotInitialized; 86 return ResultVibrationNotInitialized;
@@ -37,7 +95,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue&
37 return result; 95 return result;
38 } 96 }
39 if (volume <= 0.0f) { 97 if (volume <= 0.0f) {
40 // TODO: SendVibrationValue 98 xcd_handle->SetVibration(device_index, Core::HID::DEFAULT_VIBRATION_VALUE);
41 return ResultSuccess; 99 return ResultSuccess;
42 } 100 }
43 101
@@ -45,7 +103,7 @@ Result NpadVibrationDevice::SendVibrationValue(const Core::HID::VibrationValue&
45 vibration_value.high_amplitude *= volume; 103 vibration_value.high_amplitude *= volume;
46 vibration_value.low_amplitude *= volume; 104 vibration_value.low_amplitude *= volume;
47 105
48 // TODO: SendVibrationValue 106 xcd_handle->SetVibration(device_index, vibration_value);
49 return ResultSuccess; 107 return ResultSuccess;
50} 108}
51 109
@@ -63,11 +121,11 @@ Result NpadVibrationDevice::SendVibrationNotificationPattern([[maybe_unused]] u3
63 pattern = 0; 121 pattern = 0;
64 } 122 }
65 123
66 // return xcd_handle->SendVibrationNotificationPattern(pattern); 124 // TODO: SendVibrationNotificationPattern;
67 return ResultSuccess; 125 return ResultSuccess;
68} 126}
69 127
70Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) { 128Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& out_value) const {
71 if (ref_counter < 1) { 129 if (ref_counter < 1) {
72 return ResultVibrationNotInitialized; 130 return ResultVibrationNotInitialized;
73 } 131 }
@@ -77,7 +135,7 @@ Result NpadVibrationDevice::GetActualVibrationValue(Core::HID::VibrationValue& o
77 return ResultSuccess; 135 return ResultSuccess;
78 } 136 }
79 137
80 // TODO: SendVibrationValue 138 out_value = xcd_handle->GetActualVibrationValue(device_index);
81 return ResultSuccess; 139 return ResultSuccess;
82} 140}
83 141
diff --git a/src/hid_core/resources/vibration/vibration_device.h b/src/hid_core/resources/vibration/vibration_device.h
index 3574ad60b..c2f9891d3 100644
--- a/src/hid_core/resources/vibration/vibration_device.h
+++ b/src/hid_core/resources/vibration/vibration_device.h
@@ -12,6 +12,10 @@
12#include "hid_core/resources/npad/npad_types.h" 12#include "hid_core/resources/npad/npad_types.h"
13#include "hid_core/resources/vibration/vibration_base.h" 13#include "hid_core/resources/vibration/vibration_base.h"
14 14
15namespace Core::HID {
16enum class DeviceIndex : u8;
17}
18
15namespace Service::HID { 19namespace Service::HID {
16class NpadVibration; 20class NpadVibration;
17 21
@@ -20,16 +24,20 @@ class NpadVibrationDevice final : public NpadVibrationBase {
20public: 24public:
21 explicit NpadVibrationDevice(); 25 explicit NpadVibrationDevice();
22 26
23 Result IncrementRefCounter(); 27 Result Activate();
24 Result DecrementRefCounter(); 28 Result Deactivate();
29
30 Result Mount(IAbstractedPad& abstracted_pad, Core::HID::DeviceIndex index,
31 NpadVibration* handler);
32 Result Unmount();
25 33
26 Result SendVibrationValue(const Core::HID::VibrationValue& value); 34 Result SendVibrationValue(const Core::HID::VibrationValue& value);
27 Result SendVibrationNotificationPattern(u32 pattern); 35 Result SendVibrationNotificationPattern(u32 pattern);
28 36
29 Result GetActualVibrationValue(Core::HID::VibrationValue& out_value); 37 Result GetActualVibrationValue(Core::HID::VibrationValue& out_value) const;
30 38
31private: 39private:
32 u32 device_index{}; 40 Core::HID::DeviceIndex device_index{};
33}; 41};
34 42
35} // namespace Service::HID 43} // namespace Service::HID
diff --git a/src/tests/video_core/memory_tracker.cpp b/src/tests/video_core/memory_tracker.cpp
index f15fefe2d..45b1a91dc 100644
--- a/src/tests/video_core/memory_tracker.cpp
+++ b/src/tests/video_core/memory_tracker.cpp
@@ -24,9 +24,8 @@ constexpr VAddr c = 16 * HIGH_PAGE_SIZE;
24class RasterizerInterface { 24class RasterizerInterface {
25public: 25public:
26 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) { 26 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
27 const u64 page_start{addr >> Core::Memory::YUZU_PAGEBITS}; 27 const u64 page_start{addr >> Core::DEVICE_PAGEBITS};
28 const u64 page_end{(addr + size + Core::Memory::YUZU_PAGESIZE - 1) >> 28 const u64 page_end{(addr + size + Core::DEVICE_PAGESIZE - 1) >> Core::DEVICE_PAGEBITS};
29 Core::Memory::YUZU_PAGEBITS};
30 for (u64 page = page_start; page < page_end; ++page) { 29 for (u64 page = page_start; page < page_end; ++page) {
31 int& value = page_table[page]; 30 int& value = page_table[page];
32 value += delta; 31 value += delta;
@@ -40,7 +39,7 @@ public:
40 } 39 }
41 40
42 [[nodiscard]] int Count(VAddr addr) const noexcept { 41 [[nodiscard]] int Count(VAddr addr) const noexcept {
43 const auto it = page_table.find(addr >> Core::Memory::YUZU_PAGEBITS); 42 const auto it = page_table.find(addr >> Core::DEVICE_PAGEBITS);
44 return it == page_table.end() ? 0 : it->second; 43 return it == page_table.end() ? 0 : it->second;
45 } 44 }
46 45
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index c22c7631c..5ed0ad0ed 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -71,6 +71,8 @@ add_library(video_core STATIC
71 host1x/ffmpeg/ffmpeg.h 71 host1x/ffmpeg/ffmpeg.h
72 host1x/control.cpp 72 host1x/control.cpp
73 host1x/control.h 73 host1x/control.h
74 host1x/gpu_device_memory_manager.cpp
75 host1x/gpu_device_memory_manager.h
74 host1x/host1x.cpp 76 host1x/host1x.cpp
75 host1x/host1x.h 77 host1x/host1x.h
76 host1x/nvdec.cpp 78 host1x/nvdec.cpp
@@ -93,6 +95,7 @@ add_library(video_core STATIC
93 gpu.h 95 gpu.h
94 gpu_thread.cpp 96 gpu_thread.cpp
95 gpu_thread.h 97 gpu_thread.h
98 guest_memory.h
96 invalidation_accumulator.h 99 invalidation_accumulator.h
97 memory_manager.cpp 100 memory_manager.cpp
98 memory_manager.h 101 memory_manager.h
@@ -105,8 +108,6 @@ add_library(video_core STATIC
105 query_cache/query_stream.h 108 query_cache/query_stream.h
106 query_cache/types.h 109 query_cache/types.h
107 query_cache.h 110 query_cache.h
108 rasterizer_accelerated.cpp
109 rasterizer_accelerated.h
110 rasterizer_interface.h 111 rasterizer_interface.h
111 renderer_base.cpp 112 renderer_base.cpp
112 renderer_base.h 113 renderer_base.h
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h
index 0bb3bf8ae..40e98e395 100644
--- a/src/video_core/buffer_cache/buffer_base.h
+++ b/src/video_core/buffer_cache/buffer_base.h
@@ -33,13 +33,12 @@ struct NullBufferParams {};
33 * 33 *
34 * The buffer size and address is forcefully aligned to CPU page boundaries. 34 * The buffer size and address is forcefully aligned to CPU page boundaries.
35 */ 35 */
36template <class RasterizerInterface>
37class BufferBase { 36class BufferBase {
38public: 37public:
39 static constexpr u64 BASE_PAGE_BITS = 16; 38 static constexpr u64 BASE_PAGE_BITS = 16;
40 static constexpr u64 BASE_PAGE_SIZE = 1ULL << BASE_PAGE_BITS; 39 static constexpr u64 BASE_PAGE_SIZE = 1ULL << BASE_PAGE_BITS;
41 40
42 explicit BufferBase(RasterizerInterface& rasterizer_, VAddr cpu_addr_, u64 size_bytes_) 41 explicit BufferBase(VAddr cpu_addr_, u64 size_bytes_)
43 : cpu_addr{cpu_addr_}, size_bytes{size_bytes_} {} 42 : cpu_addr{cpu_addr_}, size_bytes{size_bytes_} {}
44 43
45 explicit BufferBase(NullBufferParams) {} 44 explicit BufferBase(NullBufferParams) {}
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 6d1fc3887..b4bf369d1 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -8,16 +8,16 @@
8#include <numeric> 8#include <numeric>
9 9
10#include "video_core/buffer_cache/buffer_cache_base.h" 10#include "video_core/buffer_cache/buffer_cache_base.h"
11#include "video_core/guest_memory.h"
12#include "video_core/host1x/gpu_device_memory_manager.h"
11 13
12namespace VideoCommon { 14namespace VideoCommon {
13 15
14using Core::Memory::YUZU_PAGESIZE; 16using Core::DEVICE_PAGESIZE;
15 17
16template <class P> 18template <class P>
17BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_, 19BufferCache<P>::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, Runtime& runtime_)
18 Core::Memory::Memory& cpu_memory_, Runtime& runtime_) 20 : runtime{runtime_}, device_memory{device_memory_}, memory_tracker{device_memory} {
19 : runtime{runtime_}, rasterizer{rasterizer_}, cpu_memory{cpu_memory_}, memory_tracker{
20 rasterizer} {
21 // Ensure the first slot is used for the null buffer 21 // Ensure the first slot is used for the null buffer
22 void(slot_buffers.insert(runtime, NullBufferParams{})); 22 void(slot_buffers.insert(runtime, NullBufferParams{}));
23 common_ranges.clear(); 23 common_ranges.clear();
@@ -29,17 +29,17 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_,
29 return; 29 return;
30 } 30 }
31 31
32 const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); 32 const s64 device_local_memory = static_cast<s64>(runtime.GetDeviceLocalMemory());
33 const s64 min_spacing_expected = device_memory - 1_GiB; 33 const s64 min_spacing_expected = device_local_memory - 1_GiB;
34 const s64 min_spacing_critical = device_memory - 512_MiB; 34 const s64 min_spacing_critical = device_local_memory - 512_MiB;
35 const s64 mem_threshold = std::min(device_memory, TARGET_THRESHOLD); 35 const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD);
36 const s64 min_vacancy_expected = (6 * mem_threshold) / 10; 36 const s64 min_vacancy_expected = (6 * mem_threshold) / 10;
37 const s64 min_vacancy_critical = (3 * mem_threshold) / 10; 37 const s64 min_vacancy_critical = (3 * mem_threshold) / 10;
38 minimum_memory = static_cast<u64>( 38 minimum_memory = static_cast<u64>(
39 std::max(std::min(device_memory - min_vacancy_expected, min_spacing_expected), 39 std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected),
40 DEFAULT_EXPECTED_MEMORY)); 40 DEFAULT_EXPECTED_MEMORY));
41 critical_memory = static_cast<u64>( 41 critical_memory = static_cast<u64>(
42 std::max(std::min(device_memory - min_vacancy_critical, min_spacing_critical), 42 std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
43 DEFAULT_CRITICAL_MEMORY)); 43 DEFAULT_CRITICAL_MEMORY));
44} 44}
45 45
@@ -105,71 +105,71 @@ void BufferCache<P>::TickFrame() {
105} 105}
106 106
107template <class P> 107template <class P>
108void BufferCache<P>::WriteMemory(VAddr cpu_addr, u64 size) { 108void BufferCache<P>::WriteMemory(DAddr device_addr, u64 size) {
109 if (memory_tracker.IsRegionGpuModified(cpu_addr, size)) { 109 if (memory_tracker.IsRegionGpuModified(device_addr, size)) {
110 const IntervalType subtract_interval{cpu_addr, cpu_addr + size}; 110 const IntervalType subtract_interval{device_addr, device_addr + size};
111 ClearDownload(subtract_interval); 111 ClearDownload(subtract_interval);
112 common_ranges.subtract(subtract_interval); 112 common_ranges.subtract(subtract_interval);
113 } 113 }
114 memory_tracker.MarkRegionAsCpuModified(cpu_addr, size); 114 memory_tracker.MarkRegionAsCpuModified(device_addr, size);
115} 115}
116 116
117template <class P> 117template <class P>
118void BufferCache<P>::CachedWriteMemory(VAddr cpu_addr, u64 size) { 118void BufferCache<P>::CachedWriteMemory(DAddr device_addr, u64 size) {
119 const bool is_dirty = IsRegionRegistered(cpu_addr, size); 119 const bool is_dirty = IsRegionRegistered(device_addr, size);
120 if (!is_dirty) { 120 if (!is_dirty) {
121 return; 121 return;
122 } 122 }
123 VAddr aligned_start = Common::AlignDown(cpu_addr, YUZU_PAGESIZE); 123 DAddr aligned_start = Common::AlignDown(device_addr, DEVICE_PAGESIZE);
124 VAddr aligned_end = Common::AlignUp(cpu_addr + size, YUZU_PAGESIZE); 124 DAddr aligned_end = Common::AlignUp(device_addr + size, DEVICE_PAGESIZE);
125 if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) { 125 if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) {
126 WriteMemory(cpu_addr, size); 126 WriteMemory(device_addr, size);
127 return; 127 return;
128 } 128 }
129 129
130 tmp_buffer.resize_destructive(size); 130 tmp_buffer.resize_destructive(size);
131 cpu_memory.ReadBlockUnsafe(cpu_addr, tmp_buffer.data(), size); 131 device_memory.ReadBlockUnsafe(device_addr, tmp_buffer.data(), size);
132 132
133 InlineMemoryImplementation(cpu_addr, size, tmp_buffer); 133 InlineMemoryImplementation(device_addr, size, tmp_buffer);
134} 134}
135 135
136template <class P> 136template <class P>
137bool BufferCache<P>::OnCPUWrite(VAddr cpu_addr, u64 size) { 137bool BufferCache<P>::OnCPUWrite(DAddr device_addr, u64 size) {
138 const bool is_dirty = IsRegionRegistered(cpu_addr, size); 138 const bool is_dirty = IsRegionRegistered(device_addr, size);
139 if (!is_dirty) { 139 if (!is_dirty) {
140 return false; 140 return false;
141 } 141 }
142 if (memory_tracker.IsRegionGpuModified(cpu_addr, size)) { 142 if (memory_tracker.IsRegionGpuModified(device_addr, size)) {
143 return true; 143 return true;
144 } 144 }
145 WriteMemory(cpu_addr, size); 145 WriteMemory(device_addr, size);
146 return false; 146 return false;
147} 147}
148 148
149template <class P> 149template <class P>
150std::optional<VideoCore::RasterizerDownloadArea> BufferCache<P>::GetFlushArea(VAddr cpu_addr, 150std::optional<VideoCore::RasterizerDownloadArea> BufferCache<P>::GetFlushArea(DAddr device_addr,
151 u64 size) { 151 u64 size) {
152 std::optional<VideoCore::RasterizerDownloadArea> area{}; 152 std::optional<VideoCore::RasterizerDownloadArea> area{};
153 area.emplace(); 153 area.emplace();
154 VAddr cpu_addr_start_aligned = Common::AlignDown(cpu_addr, Core::Memory::YUZU_PAGESIZE); 154 DAddr device_addr_start_aligned = Common::AlignDown(device_addr, Core::DEVICE_PAGESIZE);
155 VAddr cpu_addr_end_aligned = Common::AlignUp(cpu_addr + size, Core::Memory::YUZU_PAGESIZE); 155 DAddr device_addr_end_aligned = Common::AlignUp(device_addr + size, Core::DEVICE_PAGESIZE);
156 area->start_address = cpu_addr_start_aligned; 156 area->start_address = device_addr_start_aligned;
157 area->end_address = cpu_addr_end_aligned; 157 area->end_address = device_addr_end_aligned;
158 if (memory_tracker.IsRegionPreflushable(cpu_addr, size)) { 158 if (memory_tracker.IsRegionPreflushable(device_addr, size)) {
159 area->preemtive = true; 159 area->preemtive = true;
160 return area; 160 return area;
161 }; 161 };
162 area->preemtive = 162 area->preemtive = !IsRegionGpuModified(device_addr_start_aligned,
163 !IsRegionGpuModified(cpu_addr_start_aligned, cpu_addr_end_aligned - cpu_addr_start_aligned); 163 device_addr_end_aligned - device_addr_start_aligned);
164 memory_tracker.MarkRegionAsPreflushable(cpu_addr_start_aligned, 164 memory_tracker.MarkRegionAsPreflushable(device_addr_start_aligned,
165 cpu_addr_end_aligned - cpu_addr_start_aligned); 165 device_addr_end_aligned - device_addr_start_aligned);
166 return area; 166 return area;
167} 167}
168 168
169template <class P> 169template <class P>
170void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) { 170void BufferCache<P>::DownloadMemory(DAddr device_addr, u64 size) {
171 ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) { 171 ForEachBufferInRange(device_addr, size, [&](BufferId, Buffer& buffer) {
172 DownloadBufferMemory(buffer, cpu_addr, size); 172 DownloadBufferMemory(buffer, device_addr, size);
173 }); 173 });
174} 174}
175 175
@@ -184,8 +184,8 @@ void BufferCache<P>::ClearDownload(IntervalType subtract_interval) {
184 184
185template <class P> 185template <class P>
186bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { 186bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) {
187 const std::optional<VAddr> cpu_src_address = gpu_memory->GpuToCpuAddress(src_address); 187 const std::optional<DAddr> cpu_src_address = gpu_memory->GpuToCpuAddress(src_address);
188 const std::optional<VAddr> cpu_dest_address = gpu_memory->GpuToCpuAddress(dest_address); 188 const std::optional<DAddr> cpu_dest_address = gpu_memory->GpuToCpuAddress(dest_address);
189 if (!cpu_src_address || !cpu_dest_address) { 189 if (!cpu_src_address || !cpu_dest_address) {
190 return false; 190 return false;
191 } 191 }
@@ -216,10 +216,10 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am
216 }}; 216 }};
217 217
218 boost::container::small_vector<IntervalType, 4> tmp_intervals; 218 boost::container::small_vector<IntervalType, 4> tmp_intervals;
219 auto mirror = [&](VAddr base_address, VAddr base_address_end) { 219 auto mirror = [&](DAddr base_address, DAddr base_address_end) {
220 const u64 size = base_address_end - base_address; 220 const u64 size = base_address_end - base_address;
221 const VAddr diff = base_address - *cpu_src_address; 221 const DAddr diff = base_address - *cpu_src_address;
222 const VAddr new_base_address = *cpu_dest_address + diff; 222 const DAddr new_base_address = *cpu_dest_address + diff;
223 const IntervalType add_interval{new_base_address, new_base_address + size}; 223 const IntervalType add_interval{new_base_address, new_base_address + size};
224 tmp_intervals.push_back(add_interval); 224 tmp_intervals.push_back(add_interval);
225 uncommitted_ranges.add(add_interval); 225 uncommitted_ranges.add(add_interval);
@@ -239,15 +239,15 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am
239 memory_tracker.MarkRegionAsGpuModified(*cpu_dest_address, amount); 239 memory_tracker.MarkRegionAsGpuModified(*cpu_dest_address, amount);
240 } 240 }
241 241
242 Core::Memory::CpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadWrite> tmp( 242 Tegra::Memory::DeviceGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::UnsafeReadWrite>
243 cpu_memory, *cpu_src_address, amount, &tmp_buffer); 243 tmp(device_memory, *cpu_src_address, amount, &tmp_buffer);
244 tmp.SetAddressAndSize(*cpu_dest_address, amount); 244 tmp.SetAddressAndSize(*cpu_dest_address, amount);
245 return true; 245 return true;
246} 246}
247 247
248template <class P> 248template <class P>
249bool BufferCache<P>::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) { 249bool BufferCache<P>::DMAClear(GPUVAddr dst_address, u64 amount, u32 value) {
250 const std::optional<VAddr> cpu_dst_address = gpu_memory->GpuToCpuAddress(dst_address); 250 const std::optional<DAddr> cpu_dst_address = gpu_memory->GpuToCpuAddress(dst_address);
251 if (!cpu_dst_address) { 251 if (!cpu_dst_address) {
252 return false; 252 return false;
253 } 253 }
@@ -273,23 +273,23 @@ template <class P>
273std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_addr, u32 size, 273std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_addr, u32 size,
274 ObtainBufferSynchronize sync_info, 274 ObtainBufferSynchronize sync_info,
275 ObtainBufferOperation post_op) { 275 ObtainBufferOperation post_op) {
276 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 276 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
277 if (!cpu_addr) { 277 if (!device_addr) {
278 return {&slot_buffers[NULL_BUFFER_ID], 0}; 278 return {&slot_buffers[NULL_BUFFER_ID], 0};
279 } 279 }
280 return ObtainCPUBuffer(*cpu_addr, size, sync_info, post_op); 280 return ObtainCPUBuffer(*device_addr, size, sync_info, post_op);
281} 281}
282 282
283template <class P> 283template <class P>
284std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer( 284std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
285 VAddr cpu_addr, u32 size, ObtainBufferSynchronize sync_info, ObtainBufferOperation post_op) { 285 DAddr device_addr, u32 size, ObtainBufferSynchronize sync_info, ObtainBufferOperation post_op) {
286 const BufferId buffer_id = FindBuffer(cpu_addr, size); 286 const BufferId buffer_id = FindBuffer(device_addr, size);
287 Buffer& buffer = slot_buffers[buffer_id]; 287 Buffer& buffer = slot_buffers[buffer_id];
288 288
289 // synchronize op 289 // synchronize op
290 switch (sync_info) { 290 switch (sync_info) {
291 case ObtainBufferSynchronize::FullSynchronize: 291 case ObtainBufferSynchronize::FullSynchronize:
292 SynchronizeBuffer(buffer, cpu_addr, size); 292 SynchronizeBuffer(buffer, device_addr, size);
293 break; 293 break;
294 default: 294 default:
295 break; 295 break;
@@ -297,12 +297,12 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
297 297
298 switch (post_op) { 298 switch (post_op) {
299 case ObtainBufferOperation::MarkAsWritten: 299 case ObtainBufferOperation::MarkAsWritten:
300 MarkWrittenBuffer(buffer_id, cpu_addr, size); 300 MarkWrittenBuffer(buffer_id, device_addr, size);
301 break; 301 break;
302 case ObtainBufferOperation::DiscardWrite: { 302 case ObtainBufferOperation::DiscardWrite: {
303 VAddr cpu_addr_start = Common::AlignDown(cpu_addr, 64); 303 DAddr device_addr_start = Common::AlignDown(device_addr, 64);
304 VAddr cpu_addr_end = Common::AlignUp(cpu_addr + size, 64); 304 DAddr device_addr_end = Common::AlignUp(device_addr + size, 64);
305 IntervalType interval{cpu_addr_start, cpu_addr_end}; 305 IntervalType interval{device_addr_start, device_addr_end};
306 ClearDownload(interval); 306 ClearDownload(interval);
307 common_ranges.subtract(interval); 307 common_ranges.subtract(interval);
308 break; 308 break;
@@ -311,15 +311,15 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainCPUBuffer(
311 break; 311 break;
312 } 312 }
313 313
314 return {&buffer, buffer.Offset(cpu_addr)}; 314 return {&buffer, buffer.Offset(device_addr)};
315} 315}
316 316
317template <class P> 317template <class P>
318void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, 318void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr,
319 u32 size) { 319 u32 size) {
320 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 320 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
321 const Binding binding{ 321 const Binding binding{
322 .cpu_addr = *cpu_addr, 322 .device_addr = *device_addr,
323 .size = size, 323 .size = size,
324 .buffer_id = BufferId{}, 324 .buffer_id = BufferId{},
325 }; 325 };
@@ -555,16 +555,17 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
555 for (const IntervalSet& intervals : committed_ranges) { 555 for (const IntervalSet& intervals : committed_ranges) {
556 for (auto& interval : intervals) { 556 for (auto& interval : intervals) {
557 const std::size_t size = interval.upper() - interval.lower(); 557 const std::size_t size = interval.upper() - interval.lower();
558 const VAddr cpu_addr = interval.lower(); 558 const DAddr device_addr = interval.lower();
559 ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { 559 ForEachBufferInRange(device_addr, size, [&](BufferId buffer_id, Buffer& buffer) {
560 const VAddr buffer_start = buffer.CpuAddr(); 560 const DAddr buffer_start = buffer.CpuAddr();
561 const VAddr buffer_end = buffer_start + buffer.SizeBytes(); 561 const DAddr buffer_end = buffer_start + buffer.SizeBytes();
562 const VAddr new_start = std::max(buffer_start, cpu_addr); 562 const DAddr new_start = std::max(buffer_start, device_addr);
563 const VAddr new_end = std::min(buffer_end, cpu_addr + size); 563 const DAddr new_end = std::min(buffer_end, device_addr + size);
564 memory_tracker.ForEachDownloadRange( 564 memory_tracker.ForEachDownloadRange(
565 new_start, new_end - new_start, false, [&](u64 cpu_addr_out, u64 range_size) { 565 new_start, new_end - new_start, false,
566 const VAddr buffer_addr = buffer.CpuAddr(); 566 [&](u64 device_addr_out, u64 range_size) {
567 const auto add_download = [&](VAddr start, VAddr end) { 567 const DAddr buffer_addr = buffer.CpuAddr();
568 const auto add_download = [&](DAddr start, DAddr end) {
568 const u64 new_offset = start - buffer_addr; 569 const u64 new_offset = start - buffer_addr;
569 const u64 new_size = end - start; 570 const u64 new_size = end - start;
570 downloads.push_back({ 571 downloads.push_back({
@@ -582,7 +583,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
582 largest_copy = std::max(largest_copy, new_size); 583 largest_copy = std::max(largest_copy, new_size);
583 }; 584 };
584 585
585 ForEachInRangeSet(common_ranges, cpu_addr_out, range_size, add_download); 586 ForEachInRangeSet(common_ranges, device_addr_out, range_size, add_download);
586 }); 587 });
587 }); 588 });
588 } 589 }
@@ -605,8 +606,8 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
605 BufferCopy second_copy{copy}; 606 BufferCopy second_copy{copy};
606 Buffer& buffer = slot_buffers[buffer_id]; 607 Buffer& buffer = slot_buffers[buffer_id];
607 second_copy.src_offset = static_cast<size_t>(buffer.CpuAddr()) + copy.src_offset; 608 second_copy.src_offset = static_cast<size_t>(buffer.CpuAddr()) + copy.src_offset;
608 VAddr orig_cpu_addr = static_cast<VAddr>(second_copy.src_offset); 609 DAddr orig_device_addr = static_cast<DAddr>(second_copy.src_offset);
609 const IntervalType base_interval{orig_cpu_addr, orig_cpu_addr + copy.size}; 610 const IntervalType base_interval{orig_device_addr, orig_device_addr + copy.size};
610 async_downloads += std::make_pair(base_interval, 1); 611 async_downloads += std::make_pair(base_interval, 1);
611 buffer.MarkUsage(copy.src_offset, copy.size); 612 buffer.MarkUsage(copy.src_offset, copy.size);
612 runtime.CopyBuffer(download_staging.buffer, buffer, copies, false); 613 runtime.CopyBuffer(download_staging.buffer, buffer, copies, false);
@@ -635,11 +636,11 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
635 runtime.Finish(); 636 runtime.Finish();
636 for (const auto& [copy, buffer_id] : downloads) { 637 for (const auto& [copy, buffer_id] : downloads) {
637 const Buffer& buffer = slot_buffers[buffer_id]; 638 const Buffer& buffer = slot_buffers[buffer_id];
638 const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; 639 const DAddr device_addr = buffer.CpuAddr() + copy.src_offset;
639 // Undo the modified offset 640 // Undo the modified offset
640 const u64 dst_offset = copy.dst_offset - download_staging.offset; 641 const u64 dst_offset = copy.dst_offset - download_staging.offset;
641 const u8* read_mapped_memory = download_staging.mapped_span.data() + dst_offset; 642 const u8* read_mapped_memory = download_staging.mapped_span.data() + dst_offset;
642 cpu_memory.WriteBlockUnsafe(cpu_addr, read_mapped_memory, copy.size); 643 device_memory.WriteBlockUnsafe(device_addr, read_mapped_memory, copy.size);
643 } 644 }
644 } else { 645 } else {
645 const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); 646 const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy);
@@ -647,8 +648,8 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
647 Buffer& buffer = slot_buffers[buffer_id]; 648 Buffer& buffer = slot_buffers[buffer_id];
648 buffer.ImmediateDownload(copy.src_offset, 649 buffer.ImmediateDownload(copy.src_offset,
649 immediate_buffer.subspan(0, copy.size)); 650 immediate_buffer.subspan(0, copy.size));
650 const VAddr cpu_addr = buffer.CpuAddr() + copy.src_offset; 651 const DAddr device_addr = buffer.CpuAddr() + copy.src_offset;
651 cpu_memory.WriteBlockUnsafe(cpu_addr, immediate_buffer.data(), copy.size); 652 device_memory.WriteBlockUnsafe(device_addr, immediate_buffer.data(), copy.size);
652 } 653 }
653 } 654 }
654 } 655 }
@@ -681,19 +682,19 @@ void BufferCache<P>::PopAsyncBuffers() {
681 u8* base = async_buffer->mapped_span.data(); 682 u8* base = async_buffer->mapped_span.data();
682 const size_t base_offset = async_buffer->offset; 683 const size_t base_offset = async_buffer->offset;
683 for (const auto& copy : downloads) { 684 for (const auto& copy : downloads) {
684 const VAddr cpu_addr = static_cast<VAddr>(copy.src_offset); 685 const DAddr device_addr = static_cast<DAddr>(copy.src_offset);
685 const u64 dst_offset = copy.dst_offset - base_offset; 686 const u64 dst_offset = copy.dst_offset - base_offset;
686 const u8* read_mapped_memory = base + dst_offset; 687 const u8* read_mapped_memory = base + dst_offset;
687 ForEachInOverlapCounter( 688 ForEachInOverlapCounter(
688 async_downloads, cpu_addr, copy.size, [&](VAddr start, VAddr end, int count) { 689 async_downloads, device_addr, copy.size, [&](DAddr start, DAddr end, int count) {
689 cpu_memory.WriteBlockUnsafe(start, &read_mapped_memory[start - cpu_addr], 690 device_memory.WriteBlockUnsafe(start, &read_mapped_memory[start - device_addr],
690 end - start); 691 end - start);
691 if (count == 1) { 692 if (count == 1) {
692 const IntervalType base_interval{start, end}; 693 const IntervalType base_interval{start, end};
693 common_ranges.subtract(base_interval); 694 common_ranges.subtract(base_interval);
694 } 695 }
695 }); 696 });
696 const IntervalType subtract_interval{cpu_addr, cpu_addr + copy.size}; 697 const IntervalType subtract_interval{device_addr, device_addr + copy.size};
697 RemoveEachInOverlapCounter(async_downloads, subtract_interval, -1); 698 RemoveEachInOverlapCounter(async_downloads, subtract_interval, -1);
698 } 699 }
699 async_buffers_death_ring.emplace_back(*async_buffer); 700 async_buffers_death_ring.emplace_back(*async_buffer);
@@ -703,15 +704,15 @@ void BufferCache<P>::PopAsyncBuffers() {
703} 704}
704 705
705template <class P> 706template <class P>
706bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) { 707bool BufferCache<P>::IsRegionGpuModified(DAddr addr, size_t size) {
707 bool is_dirty = false; 708 bool is_dirty = false;
708 ForEachInRangeSet(common_ranges, addr, size, [&](VAddr, VAddr) { is_dirty = true; }); 709 ForEachInRangeSet(common_ranges, addr, size, [&](DAddr, DAddr) { is_dirty = true; });
709 return is_dirty; 710 return is_dirty;
710} 711}
711 712
712template <class P> 713template <class P>
713bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) { 714bool BufferCache<P>::IsRegionRegistered(DAddr addr, size_t size) {
714 const VAddr end_addr = addr + size; 715 const DAddr end_addr = addr + size;
715 const u64 page_end = Common::DivCeil(end_addr, CACHING_PAGESIZE); 716 const u64 page_end = Common::DivCeil(end_addr, CACHING_PAGESIZE);
716 for (u64 page = addr >> CACHING_PAGEBITS; page < page_end;) { 717 for (u64 page = addr >> CACHING_PAGEBITS; page < page_end;) {
717 const BufferId buffer_id = page_table[page]; 718 const BufferId buffer_id = page_table[page];
@@ -720,8 +721,8 @@ bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) {
720 continue; 721 continue;
721 } 722 }
722 Buffer& buffer = slot_buffers[buffer_id]; 723 Buffer& buffer = slot_buffers[buffer_id];
723 const VAddr buf_start_addr = buffer.CpuAddr(); 724 const DAddr buf_start_addr = buffer.CpuAddr();
724 const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes(); 725 const DAddr buf_end_addr = buf_start_addr + buffer.SizeBytes();
725 if (buf_start_addr < end_addr && addr < buf_end_addr) { 726 if (buf_start_addr < end_addr && addr < buf_end_addr) {
726 return true; 727 return true;
727 } 728 }
@@ -731,7 +732,7 @@ bool BufferCache<P>::IsRegionRegistered(VAddr addr, size_t size) {
731} 732}
732 733
733template <class P> 734template <class P>
734bool BufferCache<P>::IsRegionCpuModified(VAddr addr, size_t size) { 735bool BufferCache<P>::IsRegionCpuModified(DAddr addr, size_t size) {
735 return memory_tracker.IsRegionCpuModified(addr, size); 736 return memory_tracker.IsRegionCpuModified(addr, size);
736} 737}
737 738
@@ -739,7 +740,7 @@ template <class P>
739void BufferCache<P>::BindHostIndexBuffer() { 740void BufferCache<P>::BindHostIndexBuffer() {
740 Buffer& buffer = slot_buffers[channel_state->index_buffer.buffer_id]; 741 Buffer& buffer = slot_buffers[channel_state->index_buffer.buffer_id];
741 TouchBuffer(buffer, channel_state->index_buffer.buffer_id); 742 TouchBuffer(buffer, channel_state->index_buffer.buffer_id);
742 const u32 offset = buffer.Offset(channel_state->index_buffer.cpu_addr); 743 const u32 offset = buffer.Offset(channel_state->index_buffer.device_addr);
743 const u32 size = channel_state->index_buffer.size; 744 const u32 size = channel_state->index_buffer.size;
744 const auto& draw_state = maxwell3d->draw_manager->GetDrawState(); 745 const auto& draw_state = maxwell3d->draw_manager->GetDrawState();
745 if (!draw_state.inline_index_draw_indexes.empty()) [[unlikely]] { 746 if (!draw_state.inline_index_draw_indexes.empty()) [[unlikely]] {
@@ -754,7 +755,7 @@ void BufferCache<P>::BindHostIndexBuffer() {
754 buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes); 755 buffer.ImmediateUpload(0, draw_state.inline_index_draw_indexes);
755 } 756 }
756 } else { 757 } else {
757 SynchronizeBuffer(buffer, channel_state->index_buffer.cpu_addr, size); 758 SynchronizeBuffer(buffer, channel_state->index_buffer.device_addr, size);
758 } 759 }
759 if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { 760 if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) {
760 const u32 new_offset = 761 const u32 new_offset =
@@ -777,7 +778,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
777 const Binding& binding = channel_state->vertex_buffers[index]; 778 const Binding& binding = channel_state->vertex_buffers[index];
778 Buffer& buffer = slot_buffers[binding.buffer_id]; 779 Buffer& buffer = slot_buffers[binding.buffer_id];
779 TouchBuffer(buffer, binding.buffer_id); 780 TouchBuffer(buffer, binding.buffer_id);
780 SynchronizeBuffer(buffer, binding.cpu_addr, binding.size); 781 SynchronizeBuffer(buffer, binding.device_addr, binding.size);
781 if (!flags[Dirty::VertexBuffer0 + index]) { 782 if (!flags[Dirty::VertexBuffer0 + index]) {
782 continue; 783 continue;
783 } 784 }
@@ -797,7 +798,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
797 Buffer& buffer = slot_buffers[binding.buffer_id]; 798 Buffer& buffer = slot_buffers[binding.buffer_id];
798 799
799 const u32 stride = maxwell3d->regs.vertex_streams[index].stride; 800 const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
800 const u32 offset = buffer.Offset(binding.cpu_addr); 801 const u32 offset = buffer.Offset(binding.device_addr);
801 buffer.MarkUsage(offset, binding.size); 802 buffer.MarkUsage(offset, binding.size);
802 803
803 host_bindings.buffers.push_back(&buffer); 804 host_bindings.buffers.push_back(&buffer);
@@ -814,7 +815,7 @@ void BufferCache<P>::BindHostDrawIndirectBuffers() {
814 const auto bind_buffer = [this](const Binding& binding) { 815 const auto bind_buffer = [this](const Binding& binding) {
815 Buffer& buffer = slot_buffers[binding.buffer_id]; 816 Buffer& buffer = slot_buffers[binding.buffer_id];
816 TouchBuffer(buffer, binding.buffer_id); 817 TouchBuffer(buffer, binding.buffer_id);
817 SynchronizeBuffer(buffer, binding.cpu_addr, binding.size); 818 SynchronizeBuffer(buffer, binding.device_addr, binding.size);
818 }; 819 };
819 if (current_draw_indirect->include_count) { 820 if (current_draw_indirect->include_count) {
820 bind_buffer(channel_state->count_buffer_binding); 821 bind_buffer(channel_state->count_buffer_binding);
@@ -842,13 +843,13 @@ template <class P>
842void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, 843void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index,
843 bool needs_bind) { 844 bool needs_bind) {
844 const Binding& binding = channel_state->uniform_buffers[stage][index]; 845 const Binding& binding = channel_state->uniform_buffers[stage][index];
845 const VAddr cpu_addr = binding.cpu_addr; 846 const DAddr device_addr = binding.device_addr;
846 const u32 size = std::min(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); 847 const u32 size = std::min(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]);
847 Buffer& buffer = slot_buffers[binding.buffer_id]; 848 Buffer& buffer = slot_buffers[binding.buffer_id];
848 TouchBuffer(buffer, binding.buffer_id); 849 TouchBuffer(buffer, binding.buffer_id);
849 const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && 850 const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID &&
850 size <= channel_state->uniform_buffer_skip_cache_size && 851 size <= channel_state->uniform_buffer_skip_cache_size &&
851 !memory_tracker.IsRegionGpuModified(cpu_addr, size); 852 !memory_tracker.IsRegionGpuModified(device_addr, size);
852 if (use_fast_buffer) { 853 if (use_fast_buffer) {
853 if constexpr (IS_OPENGL) { 854 if constexpr (IS_OPENGL) {
854 if (runtime.HasFastBufferSubData()) { 855 if (runtime.HasFastBufferSubData()) {
@@ -862,7 +863,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
862 channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size; 863 channel_state->uniform_buffer_binding_sizes[stage][binding_index] = size;
863 runtime.BindFastUniformBuffer(stage, binding_index, size); 864 runtime.BindFastUniformBuffer(stage, binding_index, size);
864 } 865 }
865 const auto span = ImmediateBufferWithData(cpu_addr, size); 866 const auto span = ImmediateBufferWithData(device_addr, size);
866 runtime.PushFastUniformBuffer(stage, binding_index, span); 867 runtime.PushFastUniformBuffer(stage, binding_index, span);
867 return; 868 return;
868 } 869 }
@@ -873,11 +874,11 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
873 } 874 }
874 // Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan 875 // Stream buffer path to avoid stalling on non-Nvidia drivers or Vulkan
875 const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size); 876 const std::span<u8> span = runtime.BindMappedUniformBuffer(stage, binding_index, size);
876 cpu_memory.ReadBlockUnsafe(cpu_addr, span.data(), size); 877 device_memory.ReadBlockUnsafe(device_addr, span.data(), size);
877 return; 878 return;
878 } 879 }
879 // Classic cached path 880 // Classic cached path
880 const bool sync_cached = SynchronizeBuffer(buffer, cpu_addr, size); 881 const bool sync_cached = SynchronizeBuffer(buffer, device_addr, size);
881 if (sync_cached) { 882 if (sync_cached) {
882 ++channel_state->uniform_cache_hits[0]; 883 ++channel_state->uniform_cache_hits[0];
883 } 884 }
@@ -892,7 +893,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
892 if (!needs_bind) { 893 if (!needs_bind) {
893 return; 894 return;
894 } 895 }
895 const u32 offset = buffer.Offset(cpu_addr); 896 const u32 offset = buffer.Offset(device_addr);
896 if constexpr (IS_OPENGL) { 897 if constexpr (IS_OPENGL) {
897 // Fast buffer will be unbound 898 // Fast buffer will be unbound
898 channel_state->fast_bound_uniform_buffers[stage] &= ~(1U << binding_index); 899 channel_state->fast_bound_uniform_buffers[stage] &= ~(1U << binding_index);
@@ -920,14 +921,14 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
920 Buffer& buffer = slot_buffers[binding.buffer_id]; 921 Buffer& buffer = slot_buffers[binding.buffer_id];
921 TouchBuffer(buffer, binding.buffer_id); 922 TouchBuffer(buffer, binding.buffer_id);
922 const u32 size = binding.size; 923 const u32 size = binding.size;
923 SynchronizeBuffer(buffer, binding.cpu_addr, size); 924 SynchronizeBuffer(buffer, binding.device_addr, size);
924 925
925 const u32 offset = buffer.Offset(binding.cpu_addr); 926 const u32 offset = buffer.Offset(binding.device_addr);
926 buffer.MarkUsage(offset, size); 927 buffer.MarkUsage(offset, size);
927 const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0; 928 const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
928 929
929 if (is_written) { 930 if (is_written) {
930 MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); 931 MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
931 } 932 }
932 933
933 if constexpr (NEEDS_BIND_STORAGE_INDEX) { 934 if constexpr (NEEDS_BIND_STORAGE_INDEX) {
@@ -945,14 +946,14 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
945 const TextureBufferBinding& binding = channel_state->texture_buffers[stage][index]; 946 const TextureBufferBinding& binding = channel_state->texture_buffers[stage][index];
946 Buffer& buffer = slot_buffers[binding.buffer_id]; 947 Buffer& buffer = slot_buffers[binding.buffer_id];
947 const u32 size = binding.size; 948 const u32 size = binding.size;
948 SynchronizeBuffer(buffer, binding.cpu_addr, size); 949 SynchronizeBuffer(buffer, binding.device_addr, size);
949 950
950 const bool is_written = ((channel_state->written_texture_buffers[stage] >> index) & 1) != 0; 951 const bool is_written = ((channel_state->written_texture_buffers[stage] >> index) & 1) != 0;
951 if (is_written) { 952 if (is_written) {
952 MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); 953 MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
953 } 954 }
954 955
955 const u32 offset = buffer.Offset(binding.cpu_addr); 956 const u32 offset = buffer.Offset(binding.device_addr);
956 const PixelFormat format = binding.format; 957 const PixelFormat format = binding.format;
957 buffer.MarkUsage(offset, size); 958 buffer.MarkUsage(offset, size);
958 if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { 959 if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@@ -982,11 +983,11 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
982 Buffer& buffer = slot_buffers[binding.buffer_id]; 983 Buffer& buffer = slot_buffers[binding.buffer_id];
983 TouchBuffer(buffer, binding.buffer_id); 984 TouchBuffer(buffer, binding.buffer_id);
984 const u32 size = binding.size; 985 const u32 size = binding.size;
985 SynchronizeBuffer(buffer, binding.cpu_addr, size); 986 SynchronizeBuffer(buffer, binding.device_addr, size);
986 987
987 MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); 988 MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
988 989
989 const u32 offset = buffer.Offset(binding.cpu_addr); 990 const u32 offset = buffer.Offset(binding.device_addr);
990 buffer.MarkUsage(offset, size); 991 buffer.MarkUsage(offset, size);
991 host_bindings.buffers.push_back(&buffer); 992 host_bindings.buffers.push_back(&buffer);
992 host_bindings.offsets.push_back(offset); 993 host_bindings.offsets.push_back(offset);
@@ -1011,9 +1012,9 @@ void BufferCache<P>::BindHostComputeUniformBuffers() {
1011 TouchBuffer(buffer, binding.buffer_id); 1012 TouchBuffer(buffer, binding.buffer_id);
1012 const u32 size = 1013 const u32 size =
1013 std::min(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]); 1014 std::min(binding.size, (*channel_state->compute_uniform_buffer_sizes)[index]);
1014 SynchronizeBuffer(buffer, binding.cpu_addr, size); 1015 SynchronizeBuffer(buffer, binding.device_addr, size);
1015 1016
1016 const u32 offset = buffer.Offset(binding.cpu_addr); 1017 const u32 offset = buffer.Offset(binding.device_addr);
1017 buffer.MarkUsage(offset, size); 1018 buffer.MarkUsage(offset, size);
1018 if constexpr (NEEDS_BIND_UNIFORM_INDEX) { 1019 if constexpr (NEEDS_BIND_UNIFORM_INDEX) {
1019 runtime.BindComputeUniformBuffer(binding_index, buffer, offset, size); 1020 runtime.BindComputeUniformBuffer(binding_index, buffer, offset, size);
@@ -1032,15 +1033,15 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
1032 Buffer& buffer = slot_buffers[binding.buffer_id]; 1033 Buffer& buffer = slot_buffers[binding.buffer_id];
1033 TouchBuffer(buffer, binding.buffer_id); 1034 TouchBuffer(buffer, binding.buffer_id);
1034 const u32 size = binding.size; 1035 const u32 size = binding.size;
1035 SynchronizeBuffer(buffer, binding.cpu_addr, size); 1036 SynchronizeBuffer(buffer, binding.device_addr, size);
1036 1037
1037 const u32 offset = buffer.Offset(binding.cpu_addr); 1038 const u32 offset = buffer.Offset(binding.device_addr);
1038 buffer.MarkUsage(offset, size); 1039 buffer.MarkUsage(offset, size);
1039 const bool is_written = 1040 const bool is_written =
1040 ((channel_state->written_compute_storage_buffers >> index) & 1) != 0; 1041 ((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
1041 1042
1042 if (is_written) { 1043 if (is_written) {
1043 MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); 1044 MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
1044 } 1045 }
1045 1046
1046 if constexpr (NEEDS_BIND_STORAGE_INDEX) { 1047 if constexpr (NEEDS_BIND_STORAGE_INDEX) {
@@ -1058,15 +1059,15 @@ void BufferCache<P>::BindHostComputeTextureBuffers() {
1058 const TextureBufferBinding& binding = channel_state->compute_texture_buffers[index]; 1059 const TextureBufferBinding& binding = channel_state->compute_texture_buffers[index];
1059 Buffer& buffer = slot_buffers[binding.buffer_id]; 1060 Buffer& buffer = slot_buffers[binding.buffer_id];
1060 const u32 size = binding.size; 1061 const u32 size = binding.size;
1061 SynchronizeBuffer(buffer, binding.cpu_addr, size); 1062 SynchronizeBuffer(buffer, binding.device_addr, size);
1062 1063
1063 const bool is_written = 1064 const bool is_written =
1064 ((channel_state->written_compute_texture_buffers >> index) & 1) != 0; 1065 ((channel_state->written_compute_texture_buffers >> index) & 1) != 0;
1065 if (is_written) { 1066 if (is_written) {
1066 MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size); 1067 MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
1067 } 1068 }
1068 1069
1069 const u32 offset = buffer.Offset(binding.cpu_addr); 1070 const u32 offset = buffer.Offset(binding.device_addr);
1070 const PixelFormat format = binding.format; 1071 const PixelFormat format = binding.format;
1071 buffer.MarkUsage(offset, size); 1072 buffer.MarkUsage(offset, size);
1072 if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { 1073 if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@@ -1131,7 +1132,7 @@ void BufferCache<P>::UpdateIndexBuffer() {
1131 inline_buffer_id = CreateBuffer(0, buffer_size); 1132 inline_buffer_id = CreateBuffer(0, buffer_size);
1132 } 1133 }
1133 channel_state->index_buffer = Binding{ 1134 channel_state->index_buffer = Binding{
1134 .cpu_addr = 0, 1135 .device_addr = 0,
1135 .size = inline_index_size, 1136 .size = inline_index_size,
1136 .buffer_id = inline_buffer_id, 1137 .buffer_id = inline_buffer_id,
1137 }; 1138 };
@@ -1140,19 +1141,19 @@ void BufferCache<P>::UpdateIndexBuffer() {
1140 1141
1141 const GPUVAddr gpu_addr_begin = index_buffer_ref.StartAddress(); 1142 const GPUVAddr gpu_addr_begin = index_buffer_ref.StartAddress();
1142 const GPUVAddr gpu_addr_end = index_buffer_ref.EndAddress(); 1143 const GPUVAddr gpu_addr_end = index_buffer_ref.EndAddress();
1143 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin); 1144 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin);
1144 const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); 1145 const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin);
1145 const u32 draw_size = 1146 const u32 draw_size =
1146 (index_buffer_ref.count + index_buffer_ref.first) * index_buffer_ref.FormatSizeInBytes(); 1147 (index_buffer_ref.count + index_buffer_ref.first) * index_buffer_ref.FormatSizeInBytes();
1147 const u32 size = std::min(address_size, draw_size); 1148 const u32 size = std::min(address_size, draw_size);
1148 if (size == 0 || !cpu_addr) { 1149 if (size == 0 || !device_addr) {
1149 channel_state->index_buffer = NULL_BINDING; 1150 channel_state->index_buffer = NULL_BINDING;
1150 return; 1151 return;
1151 } 1152 }
1152 channel_state->index_buffer = Binding{ 1153 channel_state->index_buffer = Binding{
1153 .cpu_addr = *cpu_addr, 1154 .device_addr = *device_addr,
1154 .size = size, 1155 .size = size,
1155 .buffer_id = FindBuffer(*cpu_addr, size), 1156 .buffer_id = FindBuffer(*device_addr, size),
1156 }; 1157 };
1157} 1158}
1158 1159
@@ -1178,19 +1179,19 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
1178 const auto& limit = maxwell3d->regs.vertex_stream_limits[index]; 1179 const auto& limit = maxwell3d->regs.vertex_stream_limits[index];
1179 const GPUVAddr gpu_addr_begin = array.Address(); 1180 const GPUVAddr gpu_addr_begin = array.Address();
1180 const GPUVAddr gpu_addr_end = limit.Address() + 1; 1181 const GPUVAddr gpu_addr_end = limit.Address() + 1;
1181 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin); 1182 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr_begin);
1182 const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); 1183 const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin);
1183 u32 size = address_size; // TODO: Analyze stride and number of vertices 1184 u32 size = address_size; // TODO: Analyze stride and number of vertices
1184 if (array.enable == 0 || size == 0 || !cpu_addr) { 1185 if (array.enable == 0 || size == 0 || !device_addr) {
1185 channel_state->vertex_buffers[index] = NULL_BINDING; 1186 channel_state->vertex_buffers[index] = NULL_BINDING;
1186 return; 1187 return;
1187 } 1188 }
1188 if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) { 1189 if (!gpu_memory->IsWithinGPUAddressRange(gpu_addr_end)) {
1189 size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size)); 1190 size = static_cast<u32>(gpu_memory->MaxContinuousRange(gpu_addr_begin, size));
1190 } 1191 }
1191 const BufferId buffer_id = FindBuffer(*cpu_addr, size); 1192 const BufferId buffer_id = FindBuffer(*device_addr, size);
1192 channel_state->vertex_buffers[index] = Binding{ 1193 channel_state->vertex_buffers[index] = Binding{
1193 .cpu_addr = *cpu_addr, 1194 .device_addr = *device_addr,
1194 .size = size, 1195 .size = size,
1195 .buffer_id = buffer_id, 1196 .buffer_id = buffer_id,
1196 }; 1197 };
@@ -1199,15 +1200,15 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) {
1199template <class P> 1200template <class P>
1200void BufferCache<P>::UpdateDrawIndirect() { 1201void BufferCache<P>::UpdateDrawIndirect() {
1201 const auto update = [this](GPUVAddr gpu_addr, size_t size, Binding& binding) { 1202 const auto update = [this](GPUVAddr gpu_addr, size_t size, Binding& binding) {
1202 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1203 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1203 if (!cpu_addr) { 1204 if (!device_addr) {
1204 binding = NULL_BINDING; 1205 binding = NULL_BINDING;
1205 return; 1206 return;
1206 } 1207 }
1207 binding = Binding{ 1208 binding = Binding{
1208 .cpu_addr = *cpu_addr, 1209 .device_addr = *device_addr,
1209 .size = static_cast<u32>(size), 1210 .size = static_cast<u32>(size),
1210 .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), 1211 .buffer_id = FindBuffer(*device_addr, static_cast<u32>(size)),
1211 }; 1212 };
1212 }; 1213 };
1213 if (current_draw_indirect->include_count) { 1214 if (current_draw_indirect->include_count) {
@@ -1231,7 +1232,7 @@ void BufferCache<P>::UpdateUniformBuffers(size_t stage) {
1231 channel_state->dirty_uniform_buffers[stage] |= 1U << index; 1232 channel_state->dirty_uniform_buffers[stage] |= 1U << index;
1232 } 1233 }
1233 // Resolve buffer 1234 // Resolve buffer
1234 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1235 binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
1235 }); 1236 });
1236} 1237}
1237 1238
@@ -1240,7 +1241,7 @@ void BufferCache<P>::UpdateStorageBuffers(size_t stage) {
1240 ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) { 1241 ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) {
1241 // Resolve buffer 1242 // Resolve buffer
1242 Binding& binding = channel_state->storage_buffers[stage][index]; 1243 Binding& binding = channel_state->storage_buffers[stage][index];
1243 const BufferId buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1244 const BufferId buffer_id = FindBuffer(binding.device_addr, binding.size);
1244 binding.buffer_id = buffer_id; 1245 binding.buffer_id = buffer_id;
1245 }); 1246 });
1246} 1247}
@@ -1249,7 +1250,7 @@ template <class P>
1249void BufferCache<P>::UpdateTextureBuffers(size_t stage) { 1250void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
1250 ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) { 1251 ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) {
1251 Binding& binding = channel_state->texture_buffers[stage][index]; 1252 Binding& binding = channel_state->texture_buffers[stage][index];
1252 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1253 binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
1253 }); 1254 });
1254} 1255}
1255 1256
@@ -1268,14 +1269,14 @@ void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) {
1268 const auto& binding = maxwell3d->regs.transform_feedback.buffers[index]; 1269 const auto& binding = maxwell3d->regs.transform_feedback.buffers[index];
1269 const GPUVAddr gpu_addr = binding.Address() + binding.start_offset; 1270 const GPUVAddr gpu_addr = binding.Address() + binding.start_offset;
1270 const u32 size = binding.size; 1271 const u32 size = binding.size;
1271 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1272 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1272 if (binding.enable == 0 || size == 0 || !cpu_addr) { 1273 if (binding.enable == 0 || size == 0 || !device_addr) {
1273 channel_state->transform_feedback_buffers[index] = NULL_BINDING; 1274 channel_state->transform_feedback_buffers[index] = NULL_BINDING;
1274 return; 1275 return;
1275 } 1276 }
1276 const BufferId buffer_id = FindBuffer(*cpu_addr, size); 1277 const BufferId buffer_id = FindBuffer(*device_addr, size);
1277 channel_state->transform_feedback_buffers[index] = Binding{ 1278 channel_state->transform_feedback_buffers[index] = Binding{
1278 .cpu_addr = *cpu_addr, 1279 .device_addr = *device_addr,
1279 .size = size, 1280 .size = size,
1280 .buffer_id = buffer_id, 1281 .buffer_id = buffer_id,
1281 }; 1282 };
@@ -1289,13 +1290,13 @@ void BufferCache<P>::UpdateComputeUniformBuffers() {
1289 const auto& launch_desc = kepler_compute->launch_description; 1290 const auto& launch_desc = kepler_compute->launch_description;
1290 if (((launch_desc.const_buffer_enable_mask >> index) & 1) != 0) { 1291 if (((launch_desc.const_buffer_enable_mask >> index) & 1) != 0) {
1291 const auto& cbuf = launch_desc.const_buffer_config[index]; 1292 const auto& cbuf = launch_desc.const_buffer_config[index];
1292 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(cbuf.Address()); 1293 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(cbuf.Address());
1293 if (cpu_addr) { 1294 if (device_addr) {
1294 binding.cpu_addr = *cpu_addr; 1295 binding.device_addr = *device_addr;
1295 binding.size = cbuf.size; 1296 binding.size = cbuf.size;
1296 } 1297 }
1297 } 1298 }
1298 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1299 binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
1299 }); 1300 });
1300} 1301}
1301 1302
@@ -1304,7 +1305,7 @@ void BufferCache<P>::UpdateComputeStorageBuffers() {
1304 ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) { 1305 ForEachEnabledBit(channel_state->enabled_compute_storage_buffers, [&](u32 index) {
1305 // Resolve buffer 1306 // Resolve buffer
1306 Binding& binding = channel_state->compute_storage_buffers[index]; 1307 Binding& binding = channel_state->compute_storage_buffers[index];
1307 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1308 binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
1308 }); 1309 });
1309} 1310}
1310 1311
@@ -1312,45 +1313,63 @@ template <class P>
1312void BufferCache<P>::UpdateComputeTextureBuffers() { 1313void BufferCache<P>::UpdateComputeTextureBuffers() {
1313 ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) { 1314 ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) {
1314 Binding& binding = channel_state->compute_texture_buffers[index]; 1315 Binding& binding = channel_state->compute_texture_buffers[index];
1315 binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); 1316 binding.buffer_id = FindBuffer(binding.device_addr, binding.size);
1316 }); 1317 });
1317} 1318}
1318 1319
1319template <class P> 1320template <class P>
1320void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) { 1321void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size) {
1321 memory_tracker.MarkRegionAsGpuModified(cpu_addr, size); 1322 memory_tracker.MarkRegionAsGpuModified(device_addr, size);
1322 1323
1323 const IntervalType base_interval{cpu_addr, cpu_addr + size}; 1324 const IntervalType base_interval{device_addr, device_addr + size};
1324 common_ranges.add(base_interval); 1325 common_ranges.add(base_interval);
1325 uncommitted_ranges.add(base_interval); 1326 uncommitted_ranges.add(base_interval);
1326} 1327}
1327 1328
1328template <class P> 1329template <class P>
1329BufferId BufferCache<P>::FindBuffer(VAddr cpu_addr, u32 size) { 1330BufferId BufferCache<P>::FindBuffer(DAddr device_addr, u32 size) {
1330 if (cpu_addr == 0) { 1331 if (device_addr == 0) {
1331 return NULL_BUFFER_ID; 1332 return NULL_BUFFER_ID;
1332 } 1333 }
1333 const u64 page = cpu_addr >> CACHING_PAGEBITS; 1334 const u64 page = device_addr >> CACHING_PAGEBITS;
1334 const BufferId buffer_id = page_table[page]; 1335 const BufferId buffer_id = page_table[page];
1335 if (!buffer_id) { 1336 if (!buffer_id) {
1336 return CreateBuffer(cpu_addr, size); 1337 return CreateBuffer(device_addr, size);
1337 } 1338 }
1338 const Buffer& buffer = slot_buffers[buffer_id]; 1339 const Buffer& buffer = slot_buffers[buffer_id];
1339 if (buffer.IsInBounds(cpu_addr, size)) { 1340 if (buffer.IsInBounds(device_addr, size)) {
1340 return buffer_id; 1341 return buffer_id;
1341 } 1342 }
1342 return CreateBuffer(cpu_addr, size); 1343 return CreateBuffer(device_addr, size);
1343} 1344}
1344 1345
1345template <class P> 1346template <class P>
1346typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu_addr, 1347typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(DAddr device_addr,
1347 u32 wanted_size) { 1348 u32 wanted_size) {
1348 static constexpr int STREAM_LEAP_THRESHOLD = 16; 1349 static constexpr int STREAM_LEAP_THRESHOLD = 16;
1349 boost::container::small_vector<BufferId, 16> overlap_ids; 1350 boost::container::small_vector<BufferId, 16> overlap_ids;
1350 VAddr begin = cpu_addr; 1351 DAddr begin = device_addr;
1351 VAddr end = cpu_addr + wanted_size; 1352 DAddr end = device_addr + wanted_size;
1352 int stream_score = 0; 1353 int stream_score = 0;
1353 bool has_stream_leap = false; 1354 bool has_stream_leap = false;
1355 auto expand_begin = [&](DAddr add_value) {
1356 static constexpr DAddr min_page = CACHING_PAGESIZE + Core::DEVICE_PAGESIZE;
1357 if (add_value > begin - min_page) {
1358 begin = min_page;
1359 device_addr = Core::DEVICE_PAGESIZE;
1360 return;
1361 }
1362 begin -= add_value;
1363 device_addr = begin - CACHING_PAGESIZE;
1364 };
1365 auto expand_end = [&](DAddr add_value) {
1366 static constexpr DAddr max_page = 1ULL << Tegra::MaxwellDeviceMemoryManager::AS_BITS;
1367 if (add_value > max_page - end) {
1368 end = max_page;
1369 return;
1370 }
1371 end += add_value;
1372 };
1354 if (begin == 0) { 1373 if (begin == 0) {
1355 return OverlapResult{ 1374 return OverlapResult{
1356 .ids = std::move(overlap_ids), 1375 .ids = std::move(overlap_ids),
@@ -1359,9 +1378,9 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
1359 .has_stream_leap = has_stream_leap, 1378 .has_stream_leap = has_stream_leap,
1360 }; 1379 };
1361 } 1380 }
1362 for (; cpu_addr >> CACHING_PAGEBITS < Common::DivCeil(end, CACHING_PAGESIZE); 1381 for (; device_addr >> CACHING_PAGEBITS < Common::DivCeil(end, CACHING_PAGESIZE);
1363 cpu_addr += CACHING_PAGESIZE) { 1382 device_addr += CACHING_PAGESIZE) {
1364 const BufferId overlap_id = page_table[cpu_addr >> CACHING_PAGEBITS]; 1383 const BufferId overlap_id = page_table[device_addr >> CACHING_PAGEBITS];
1365 if (!overlap_id) { 1384 if (!overlap_id) {
1366 continue; 1385 continue;
1367 } 1386 }
@@ -1371,12 +1390,12 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
1371 } 1390 }
1372 overlap_ids.push_back(overlap_id); 1391 overlap_ids.push_back(overlap_id);
1373 overlap.Pick(); 1392 overlap.Pick();
1374 const VAddr overlap_cpu_addr = overlap.CpuAddr(); 1393 const DAddr overlap_device_addr = overlap.CpuAddr();
1375 const bool expands_left = overlap_cpu_addr < begin; 1394 const bool expands_left = overlap_device_addr < begin;
1376 if (expands_left) { 1395 if (expands_left) {
1377 begin = overlap_cpu_addr; 1396 begin = overlap_device_addr;
1378 } 1397 }
1379 const VAddr overlap_end = overlap_cpu_addr + overlap.SizeBytes(); 1398 const DAddr overlap_end = overlap_device_addr + overlap.SizeBytes();
1380 const bool expands_right = overlap_end > end; 1399 const bool expands_right = overlap_end > end;
1381 if (overlap_end > end) { 1400 if (overlap_end > end) {
1382 end = overlap_end; 1401 end = overlap_end;
@@ -1387,11 +1406,10 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
1387 // as a stream buffer. Increase the size to skip constantly recreating buffers. 1406 // as a stream buffer. Increase the size to skip constantly recreating buffers.
1388 has_stream_leap = true; 1407 has_stream_leap = true;
1389 if (expands_right) { 1408 if (expands_right) {
1390 begin -= CACHING_PAGESIZE * 256; 1409 expand_begin(CACHING_PAGESIZE * 128);
1391 cpu_addr = begin - CACHING_PAGESIZE;
1392 } 1410 }
1393 if (expands_left) { 1411 if (expands_left) {
1394 end += CACHING_PAGESIZE * 256; 1412 expand_end(CACHING_PAGESIZE * 128);
1395 } 1413 }
1396 } 1414 }
1397 } 1415 }
@@ -1424,13 +1442,13 @@ void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id,
1424} 1442}
1425 1443
1426template <class P> 1444template <class P>
1427BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) { 1445BufferId BufferCache<P>::CreateBuffer(DAddr device_addr, u32 wanted_size) {
1428 VAddr cpu_addr_end = Common::AlignUp(cpu_addr + wanted_size, CACHING_PAGESIZE); 1446 DAddr device_addr_end = Common::AlignUp(device_addr + wanted_size, CACHING_PAGESIZE);
1429 cpu_addr = Common::AlignDown(cpu_addr, CACHING_PAGESIZE); 1447 device_addr = Common::AlignDown(device_addr, CACHING_PAGESIZE);
1430 wanted_size = static_cast<u32>(cpu_addr_end - cpu_addr); 1448 wanted_size = static_cast<u32>(device_addr_end - device_addr);
1431 const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size); 1449 const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size);
1432 const u32 size = static_cast<u32>(overlap.end - overlap.begin); 1450 const u32 size = static_cast<u32>(overlap.end - overlap.begin);
1433 const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size); 1451 const BufferId new_buffer_id = slot_buffers.insert(runtime, overlap.begin, size);
1434 auto& new_buffer = slot_buffers[new_buffer_id]; 1452 auto& new_buffer = slot_buffers[new_buffer_id];
1435 const size_t size_bytes = new_buffer.SizeBytes(); 1453 const size_t size_bytes = new_buffer.SizeBytes();
1436 runtime.ClearBuffer(new_buffer, 0, size_bytes, 0); 1454 runtime.ClearBuffer(new_buffer, 0, size_bytes, 0);
@@ -1465,10 +1483,10 @@ void BufferCache<P>::ChangeRegister(BufferId buffer_id) {
1465 total_used_memory -= Common::AlignUp(size, 1024); 1483 total_used_memory -= Common::AlignUp(size, 1024);
1466 lru_cache.Free(buffer.getLRUID()); 1484 lru_cache.Free(buffer.getLRUID());
1467 } 1485 }
1468 const VAddr cpu_addr_begin = buffer.CpuAddr(); 1486 const DAddr device_addr_begin = buffer.CpuAddr();
1469 const VAddr cpu_addr_end = cpu_addr_begin + size; 1487 const DAddr device_addr_end = device_addr_begin + size;
1470 const u64 page_begin = cpu_addr_begin / CACHING_PAGESIZE; 1488 const u64 page_begin = device_addr_begin / CACHING_PAGESIZE;
1471 const u64 page_end = Common::DivCeil(cpu_addr_end, CACHING_PAGESIZE); 1489 const u64 page_end = Common::DivCeil(device_addr_end, CACHING_PAGESIZE);
1472 for (u64 page = page_begin; page != page_end; ++page) { 1490 for (u64 page = page_begin; page != page_end; ++page) {
1473 if constexpr (insert) { 1491 if constexpr (insert) {
1474 page_table[page] = buffer_id; 1492 page_table[page] = buffer_id;
@@ -1486,15 +1504,15 @@ void BufferCache<P>::TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept {
1486} 1504}
1487 1505
1488template <class P> 1506template <class P>
1489bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size) { 1507bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size) {
1490 boost::container::small_vector<BufferCopy, 4> copies; 1508 boost::container::small_vector<BufferCopy, 4> copies;
1491 u64 total_size_bytes = 0; 1509 u64 total_size_bytes = 0;
1492 u64 largest_copy = 0; 1510 u64 largest_copy = 0;
1493 VAddr buffer_start = buffer.CpuAddr(); 1511 DAddr buffer_start = buffer.CpuAddr();
1494 memory_tracker.ForEachUploadRange(cpu_addr, size, [&](u64 cpu_addr_out, u64 range_size) { 1512 memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
1495 copies.push_back(BufferCopy{ 1513 copies.push_back(BufferCopy{
1496 .src_offset = total_size_bytes, 1514 .src_offset = total_size_bytes,
1497 .dst_offset = cpu_addr_out - buffer_start, 1515 .dst_offset = device_addr_out - buffer_start,
1498 .size = range_size, 1516 .size = range_size,
1499 }); 1517 });
1500 total_size_bytes += range_size; 1518 total_size_bytes += range_size;
@@ -1526,14 +1544,14 @@ void BufferCache<P>::ImmediateUploadMemory([[maybe_unused]] Buffer& buffer,
1526 std::span<u8> immediate_buffer; 1544 std::span<u8> immediate_buffer;
1527 for (const BufferCopy& copy : copies) { 1545 for (const BufferCopy& copy : copies) {
1528 std::span<const u8> upload_span; 1546 std::span<const u8> upload_span;
1529 const VAddr cpu_addr = buffer.CpuAddr() + copy.dst_offset; 1547 const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
1530 if (IsRangeGranular(cpu_addr, copy.size)) { 1548 if (IsRangeGranular(device_addr, copy.size)) {
1531 upload_span = std::span(cpu_memory.GetPointer(cpu_addr), copy.size); 1549 upload_span = std::span(device_memory.GetPointer<u8>(device_addr), copy.size);
1532 } else { 1550 } else {
1533 if (immediate_buffer.empty()) { 1551 if (immediate_buffer.empty()) {
1534 immediate_buffer = ImmediateBuffer(largest_copy); 1552 immediate_buffer = ImmediateBuffer(largest_copy);
1535 } 1553 }
1536 cpu_memory.ReadBlockUnsafe(cpu_addr, immediate_buffer.data(), copy.size); 1554 device_memory.ReadBlockUnsafe(device_addr, immediate_buffer.data(), copy.size);
1537 upload_span = immediate_buffer.subspan(0, copy.size); 1555 upload_span = immediate_buffer.subspan(0, copy.size);
1538 } 1556 }
1539 buffer.ImmediateUpload(copy.dst_offset, upload_span); 1557 buffer.ImmediateUpload(copy.dst_offset, upload_span);
@@ -1550,8 +1568,8 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer,
1550 const std::span<u8> staging_pointer = upload_staging.mapped_span; 1568 const std::span<u8> staging_pointer = upload_staging.mapped_span;
1551 for (BufferCopy& copy : copies) { 1569 for (BufferCopy& copy : copies) {
1552 u8* const src_pointer = staging_pointer.data() + copy.src_offset; 1570 u8* const src_pointer = staging_pointer.data() + copy.src_offset;
1553 const VAddr cpu_addr = buffer.CpuAddr() + copy.dst_offset; 1571 const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
1554 cpu_memory.ReadBlockUnsafe(cpu_addr, src_pointer, copy.size); 1572 device_memory.ReadBlockUnsafe(device_addr, src_pointer, copy.size);
1555 1573
1556 // Apply the staging offset 1574 // Apply the staging offset
1557 copy.src_offset += upload_staging.offset; 1575 copy.src_offset += upload_staging.offset;
@@ -1562,14 +1580,14 @@ void BufferCache<P>::MappedUploadMemory([[maybe_unused]] Buffer& buffer,
1562} 1580}
1563 1581
1564template <class P> 1582template <class P>
1565bool BufferCache<P>::InlineMemory(VAddr dest_address, size_t copy_size, 1583bool BufferCache<P>::InlineMemory(DAddr dest_address, size_t copy_size,
1566 std::span<const u8> inlined_buffer) { 1584 std::span<const u8> inlined_buffer) {
1567 const bool is_dirty = IsRegionRegistered(dest_address, copy_size); 1585 const bool is_dirty = IsRegionRegistered(dest_address, copy_size);
1568 if (!is_dirty) { 1586 if (!is_dirty) {
1569 return false; 1587 return false;
1570 } 1588 }
1571 VAddr aligned_start = Common::AlignDown(dest_address, YUZU_PAGESIZE); 1589 DAddr aligned_start = Common::AlignDown(dest_address, DEVICE_PAGESIZE);
1572 VAddr aligned_end = Common::AlignUp(dest_address + copy_size, YUZU_PAGESIZE); 1590 DAddr aligned_end = Common::AlignUp(dest_address + copy_size, DEVICE_PAGESIZE);
1573 if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) { 1591 if (!IsRegionGpuModified(aligned_start, aligned_end - aligned_start)) {
1574 return false; 1592 return false;
1575 } 1593 }
@@ -1580,7 +1598,7 @@ bool BufferCache<P>::InlineMemory(VAddr dest_address, size_t copy_size,
1580} 1598}
1581 1599
1582template <class P> 1600template <class P>
1583void BufferCache<P>::InlineMemoryImplementation(VAddr dest_address, size_t copy_size, 1601void BufferCache<P>::InlineMemoryImplementation(DAddr dest_address, size_t copy_size,
1584 std::span<const u8> inlined_buffer) { 1602 std::span<const u8> inlined_buffer) {
1585 const IntervalType subtract_interval{dest_address, dest_address + copy_size}; 1603 const IntervalType subtract_interval{dest_address, dest_address + copy_size};
1586 ClearDownload(subtract_interval); 1604 ClearDownload(subtract_interval);
@@ -1612,14 +1630,14 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer) {
1612} 1630}
1613 1631
1614template <class P> 1632template <class P>
1615void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 size) { 1633void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, DAddr device_addr, u64 size) {
1616 boost::container::small_vector<BufferCopy, 1> copies; 1634 boost::container::small_vector<BufferCopy, 1> copies;
1617 u64 total_size_bytes = 0; 1635 u64 total_size_bytes = 0;
1618 u64 largest_copy = 0; 1636 u64 largest_copy = 0;
1619 memory_tracker.ForEachDownloadRangeAndClear( 1637 memory_tracker.ForEachDownloadRangeAndClear(
1620 cpu_addr, size, [&](u64 cpu_addr_out, u64 range_size) { 1638 device_addr, size, [&](u64 device_addr_out, u64 range_size) {
1621 const VAddr buffer_addr = buffer.CpuAddr(); 1639 const DAddr buffer_addr = buffer.CpuAddr();
1622 const auto add_download = [&](VAddr start, VAddr end) { 1640 const auto add_download = [&](DAddr start, DAddr end) {
1623 const u64 new_offset = start - buffer_addr; 1641 const u64 new_offset = start - buffer_addr;
1624 const u64 new_size = end - start; 1642 const u64 new_size = end - start;
1625 copies.push_back(BufferCopy{ 1643 copies.push_back(BufferCopy{
@@ -1634,8 +1652,8 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si
1634 largest_copy = std::max(largest_copy, new_size); 1652 largest_copy = std::max(largest_copy, new_size);
1635 }; 1653 };
1636 1654
1637 const VAddr start_address = cpu_addr_out; 1655 const DAddr start_address = device_addr_out;
1638 const VAddr end_address = start_address + range_size; 1656 const DAddr end_address = start_address + range_size;
1639 ForEachInRangeSet(common_ranges, start_address, range_size, add_download); 1657 ForEachInRangeSet(common_ranges, start_address, range_size, add_download);
1640 const IntervalType subtract_interval{start_address, end_address}; 1658 const IntervalType subtract_interval{start_address, end_address};
1641 ClearDownload(subtract_interval); 1659 ClearDownload(subtract_interval);
@@ -1658,18 +1676,18 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si
1658 runtime.CopyBuffer(download_staging.buffer, buffer, copies_span, true); 1676 runtime.CopyBuffer(download_staging.buffer, buffer, copies_span, true);
1659 runtime.Finish(); 1677 runtime.Finish();
1660 for (const BufferCopy& copy : copies) { 1678 for (const BufferCopy& copy : copies) {
1661 const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset; 1679 const DAddr copy_device_addr = buffer.CpuAddr() + copy.src_offset;
1662 // Undo the modified offset 1680 // Undo the modified offset
1663 const u64 dst_offset = copy.dst_offset - download_staging.offset; 1681 const u64 dst_offset = copy.dst_offset - download_staging.offset;
1664 const u8* copy_mapped_memory = mapped_memory + dst_offset; 1682 const u8* copy_mapped_memory = mapped_memory + dst_offset;
1665 cpu_memory.WriteBlockUnsafe(copy_cpu_addr, copy_mapped_memory, copy.size); 1683 device_memory.WriteBlockUnsafe(copy_device_addr, copy_mapped_memory, copy.size);
1666 } 1684 }
1667 } else { 1685 } else {
1668 const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy); 1686 const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy);
1669 for (const BufferCopy& copy : copies) { 1687 for (const BufferCopy& copy : copies) {
1670 buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size)); 1688 buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size));
1671 const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset; 1689 const DAddr copy_device_addr = buffer.CpuAddr() + copy.src_offset;
1672 cpu_memory.WriteBlockUnsafe(copy_cpu_addr, immediate_buffer.data(), copy.size); 1690 device_memory.WriteBlockUnsafe(copy_device_addr, immediate_buffer.data(), copy.size);
1673 } 1691 }
1674 } 1692 }
1675} 1693}
@@ -1758,20 +1776,20 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
1758 const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment); 1776 const GPUVAddr aligned_gpu_addr = Common::AlignDown(gpu_addr, alignment);
1759 const u32 aligned_size = static_cast<u32>(gpu_addr - aligned_gpu_addr) + size; 1777 const u32 aligned_size = static_cast<u32>(gpu_addr - aligned_gpu_addr) + size;
1760 1778
1761 const std::optional<VAddr> aligned_cpu_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr); 1779 const std::optional<DAddr> aligned_device_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr);
1762 if (!aligned_cpu_addr || size == 0) { 1780 if (!aligned_device_addr || size == 0) {
1763 LOG_WARNING(HW_GPU, "Failed to find storage buffer for cbuf index {}", cbuf_index); 1781 LOG_WARNING(HW_GPU, "Failed to find storage buffer for cbuf index {}", cbuf_index);
1764 return NULL_BINDING; 1782 return NULL_BINDING;
1765 } 1783 }
1766 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1784 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1767 ASSERT_MSG(cpu_addr, "Unaligned storage buffer address not found for cbuf index {}", 1785 ASSERT_MSG(device_addr, "Unaligned storage buffer address not found for cbuf index {}",
1768 cbuf_index); 1786 cbuf_index);
1769 // The end address used for size calculation does not need to be aligned 1787 // The end address used for size calculation does not need to be aligned
1770 const VAddr cpu_end = Common::AlignUp(*cpu_addr + size, Core::Memory::YUZU_PAGESIZE); 1788 const DAddr cpu_end = Common::AlignUp(*device_addr + size, Core::DEVICE_PAGESIZE);
1771 1789
1772 const Binding binding{ 1790 const Binding binding{
1773 .cpu_addr = *aligned_cpu_addr, 1791 .device_addr = *aligned_device_addr,
1774 .size = is_written ? aligned_size : static_cast<u32>(cpu_end - *aligned_cpu_addr), 1792 .size = is_written ? aligned_size : static_cast<u32>(cpu_end - *aligned_device_addr),
1775 .buffer_id = BufferId{}, 1793 .buffer_id = BufferId{},
1776 }; 1794 };
1777 return binding; 1795 return binding;
@@ -1780,15 +1798,15 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
1780template <class P> 1798template <class P>
1781TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size, 1799TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size,
1782 PixelFormat format) { 1800 PixelFormat format) {
1783 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1801 const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1784 TextureBufferBinding binding; 1802 TextureBufferBinding binding;
1785 if (!cpu_addr || size == 0) { 1803 if (!device_addr || size == 0) {
1786 binding.cpu_addr = 0; 1804 binding.device_addr = 0;
1787 binding.size = 0; 1805 binding.size = 0;
1788 binding.buffer_id = NULL_BUFFER_ID; 1806 binding.buffer_id = NULL_BUFFER_ID;
1789 binding.format = PixelFormat::Invalid; 1807 binding.format = PixelFormat::Invalid;
1790 } else { 1808 } else {
1791 binding.cpu_addr = *cpu_addr; 1809 binding.device_addr = *device_addr;
1792 binding.size = size; 1810 binding.size = size;
1793 binding.buffer_id = BufferId{}; 1811 binding.buffer_id = BufferId{};
1794 binding.format = format; 1812 binding.format = format;
@@ -1797,14 +1815,14 @@ TextureBufferBinding BufferCache<P>::GetTextureBufferBinding(GPUVAddr gpu_addr,
1797} 1815}
1798 1816
1799template <class P> 1817template <class P>
1800std::span<const u8> BufferCache<P>::ImmediateBufferWithData(VAddr cpu_addr, size_t size) { 1818std::span<const u8> BufferCache<P>::ImmediateBufferWithData(DAddr device_addr, size_t size) {
1801 u8* const base_pointer = cpu_memory.GetPointer(cpu_addr); 1819 u8* const base_pointer = device_memory.GetPointer<u8>(device_addr);
1802 if (IsRangeGranular(cpu_addr, size) || 1820 if (IsRangeGranular(device_addr, size) ||
1803 base_pointer + size == cpu_memory.GetPointer(cpu_addr + size)) { 1821 base_pointer + size == device_memory.GetPointer<u8>(device_addr + size)) {
1804 return std::span(base_pointer, size); 1822 return std::span(base_pointer, size);
1805 } else { 1823 } else {
1806 const std::span<u8> span = ImmediateBuffer(size); 1824 const std::span<u8> span = ImmediateBuffer(size);
1807 cpu_memory.ReadBlockUnsafe(cpu_addr, span.data(), size); 1825 device_memory.ReadBlockUnsafe(device_addr, span.data(), size);
1808 return span; 1826 return span;
1809 } 1827 }
1810} 1828}
@@ -1828,13 +1846,14 @@ bool BufferCache<P>::HasFastUniformBufferBound(size_t stage, u32 binding_index)
1828template <class P> 1846template <class P>
1829std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectCount() { 1847std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectCount() {
1830 auto& buffer = slot_buffers[channel_state->count_buffer_binding.buffer_id]; 1848 auto& buffer = slot_buffers[channel_state->count_buffer_binding.buffer_id];
1831 return std::make_pair(&buffer, buffer.Offset(channel_state->count_buffer_binding.cpu_addr)); 1849 return std::make_pair(&buffer, buffer.Offset(channel_state->count_buffer_binding.device_addr));
1832} 1850}
1833 1851
1834template <class P> 1852template <class P>
1835std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectBuffer() { 1853std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectBuffer() {
1836 auto& buffer = slot_buffers[channel_state->indirect_buffer_binding.buffer_id]; 1854 auto& buffer = slot_buffers[channel_state->indirect_buffer_binding.buffer_id];
1837 return std::make_pair(&buffer, buffer.Offset(channel_state->indirect_buffer_binding.cpu_addr)); 1855 return std::make_pair(&buffer,
1856 buffer.Offset(channel_state->indirect_buffer_binding.device_addr));
1838} 1857}
1839 1858
1840} // namespace VideoCommon 1859} // namespace VideoCommon
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index d6d696d8c..80dbb81e7 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -32,7 +32,6 @@
32#include "common/microprofile.h" 32#include "common/microprofile.h"
33#include "common/scope_exit.h" 33#include "common/scope_exit.h"
34#include "common/settings.h" 34#include "common/settings.h"
35#include "core/memory.h"
36#include "video_core/buffer_cache/buffer_base.h" 35#include "video_core/buffer_cache/buffer_base.h"
37#include "video_core/control/channel_state_cache.h" 36#include "video_core/control/channel_state_cache.h"
38#include "video_core/delayed_destruction_ring.h" 37#include "video_core/delayed_destruction_ring.h"
@@ -41,7 +40,6 @@
41#include "video_core/engines/kepler_compute.h" 40#include "video_core/engines/kepler_compute.h"
42#include "video_core/engines/maxwell_3d.h" 41#include "video_core/engines/maxwell_3d.h"
43#include "video_core/memory_manager.h" 42#include "video_core/memory_manager.h"
44#include "video_core/rasterizer_interface.h"
45#include "video_core/surface.h" 43#include "video_core/surface.h"
46#include "video_core/texture_cache/slot_vector.h" 44#include "video_core/texture_cache/slot_vector.h"
47#include "video_core/texture_cache/types.h" 45#include "video_core/texture_cache/types.h"
@@ -94,7 +92,7 @@ static constexpr BufferId NULL_BUFFER_ID{0};
94static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = static_cast<u32>(4_KiB); 92static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = static_cast<u32>(4_KiB);
95 93
96struct Binding { 94struct Binding {
97 VAddr cpu_addr{}; 95 DAddr device_addr{};
98 u32 size{}; 96 u32 size{};
99 BufferId buffer_id; 97 BufferId buffer_id;
100}; 98};
@@ -104,7 +102,7 @@ struct TextureBufferBinding : Binding {
104}; 102};
105 103
106static constexpr Binding NULL_BINDING{ 104static constexpr Binding NULL_BINDING{
107 .cpu_addr = 0, 105 .device_addr = 0,
108 .size = 0, 106 .size = 0,
109 .buffer_id = NULL_BUFFER_ID, 107 .buffer_id = NULL_BUFFER_ID,
110}; 108};
@@ -204,10 +202,10 @@ class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInf
204 using Async_Buffer = typename P::Async_Buffer; 202 using Async_Buffer = typename P::Async_Buffer;
205 using MemoryTracker = typename P::MemoryTracker; 203 using MemoryTracker = typename P::MemoryTracker;
206 204
207 using IntervalCompare = std::less<VAddr>; 205 using IntervalCompare = std::less<DAddr>;
208 using IntervalInstance = boost::icl::interval_type_default<VAddr, std::less>; 206 using IntervalInstance = boost::icl::interval_type_default<DAddr, std::less>;
209 using IntervalAllocator = boost::fast_pool_allocator<VAddr>; 207 using IntervalAllocator = boost::fast_pool_allocator<DAddr>;
210 using IntervalSet = boost::icl::interval_set<VAddr>; 208 using IntervalSet = boost::icl::interval_set<DAddr>;
211 using IntervalType = typename IntervalSet::interval_type; 209 using IntervalType = typename IntervalSet::interval_type;
212 210
213 template <typename Type> 211 template <typename Type>
@@ -230,32 +228,31 @@ class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInf
230 228
231 using OverlapCombine = counter_add_functor<int>; 229 using OverlapCombine = counter_add_functor<int>;
232 using OverlapSection = boost::icl::inter_section<int>; 230 using OverlapSection = boost::icl::inter_section<int>;
233 using OverlapCounter = boost::icl::split_interval_map<VAddr, int>; 231 using OverlapCounter = boost::icl::split_interval_map<DAddr, int>;
234 232
235 struct OverlapResult { 233 struct OverlapResult {
236 boost::container::small_vector<BufferId, 16> ids; 234 boost::container::small_vector<BufferId, 16> ids;
237 VAddr begin; 235 DAddr begin;
238 VAddr end; 236 DAddr end;
239 bool has_stream_leap = false; 237 bool has_stream_leap = false;
240 }; 238 };
241 239
242public: 240public:
243 explicit BufferCache(VideoCore::RasterizerInterface& rasterizer_, 241 explicit BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, Runtime& runtime_);
244 Core::Memory::Memory& cpu_memory_, Runtime& runtime_);
245 242
246 void TickFrame(); 243 void TickFrame();
247 244
248 void WriteMemory(VAddr cpu_addr, u64 size); 245 void WriteMemory(DAddr device_addr, u64 size);
249 246
250 void CachedWriteMemory(VAddr cpu_addr, u64 size); 247 void CachedWriteMemory(DAddr device_addr, u64 size);
251 248
252 bool OnCPUWrite(VAddr cpu_addr, u64 size); 249 bool OnCPUWrite(DAddr device_addr, u64 size);
253 250
254 void DownloadMemory(VAddr cpu_addr, u64 size); 251 void DownloadMemory(DAddr device_addr, u64 size);
255 252
256 std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); 253 std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(DAddr device_addr, u64 size);
257 254
258 bool InlineMemory(VAddr dest_address, size_t copy_size, std::span<const u8> inlined_buffer); 255 bool InlineMemory(DAddr dest_address, size_t copy_size, std::span<const u8> inlined_buffer);
259 256
260 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size); 257 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size);
261 258
@@ -300,7 +297,7 @@ public:
300 ObtainBufferSynchronize sync_info, 297 ObtainBufferSynchronize sync_info,
301 ObtainBufferOperation post_op); 298 ObtainBufferOperation post_op);
302 299
303 [[nodiscard]] std::pair<Buffer*, u32> ObtainCPUBuffer(VAddr gpu_addr, u32 size, 300 [[nodiscard]] std::pair<Buffer*, u32> ObtainCPUBuffer(DAddr gpu_addr, u32 size,
304 ObtainBufferSynchronize sync_info, 301 ObtainBufferSynchronize sync_info,
305 ObtainBufferOperation post_op); 302 ObtainBufferOperation post_op);
306 void FlushCachedWrites(); 303 void FlushCachedWrites();
@@ -326,13 +323,13 @@ public:
326 bool DMAClear(GPUVAddr src_address, u64 amount, u32 value); 323 bool DMAClear(GPUVAddr src_address, u64 amount, u32 value);
327 324
328 /// Return true when a CPU region is modified from the GPU 325 /// Return true when a CPU region is modified from the GPU
329 [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); 326 [[nodiscard]] bool IsRegionGpuModified(DAddr addr, size_t size);
330 327
331 /// Return true when a region is registered on the cache 328 /// Return true when a region is registered on the cache
332 [[nodiscard]] bool IsRegionRegistered(VAddr addr, size_t size); 329 [[nodiscard]] bool IsRegionRegistered(DAddr addr, size_t size);
333 330
334 /// Return true when a CPU region is modified from the CPU 331 /// Return true when a CPU region is modified from the CPU
335 [[nodiscard]] bool IsRegionCpuModified(VAddr addr, size_t size); 332 [[nodiscard]] bool IsRegionCpuModified(DAddr addr, size_t size);
336 333
337 void SetDrawIndirect( 334 void SetDrawIndirect(
338 const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect_) { 335 const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect_) {
@@ -366,9 +363,9 @@ private:
366 } 363 }
367 364
368 template <typename Func> 365 template <typename Func>
369 void ForEachBufferInRange(VAddr cpu_addr, u64 size, Func&& func) { 366 void ForEachBufferInRange(DAddr device_addr, u64 size, Func&& func) {
370 const u64 page_end = Common::DivCeil(cpu_addr + size, CACHING_PAGESIZE); 367 const u64 page_end = Common::DivCeil(device_addr + size, CACHING_PAGESIZE);
371 for (u64 page = cpu_addr >> CACHING_PAGEBITS; page < page_end;) { 368 for (u64 page = device_addr >> CACHING_PAGEBITS; page < page_end;) {
372 const BufferId buffer_id = page_table[page]; 369 const BufferId buffer_id = page_table[page];
373 if (!buffer_id) { 370 if (!buffer_id) {
374 ++page; 371 ++page;
@@ -377,15 +374,15 @@ private:
377 Buffer& buffer = slot_buffers[buffer_id]; 374 Buffer& buffer = slot_buffers[buffer_id];
378 func(buffer_id, buffer); 375 func(buffer_id, buffer);
379 376
380 const VAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes(); 377 const DAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes();
381 page = Common::DivCeil(end_addr, CACHING_PAGESIZE); 378 page = Common::DivCeil(end_addr, CACHING_PAGESIZE);
382 } 379 }
383 } 380 }
384 381
385 template <typename Func> 382 template <typename Func>
386 void ForEachInRangeSet(IntervalSet& current_range, VAddr cpu_addr, u64 size, Func&& func) { 383 void ForEachInRangeSet(IntervalSet& current_range, DAddr device_addr, u64 size, Func&& func) {
387 const VAddr start_address = cpu_addr; 384 const DAddr start_address = device_addr;
388 const VAddr end_address = start_address + size; 385 const DAddr end_address = start_address + size;
389 const IntervalType search_interval{start_address, end_address}; 386 const IntervalType search_interval{start_address, end_address};
390 auto it = current_range.lower_bound(search_interval); 387 auto it = current_range.lower_bound(search_interval);
391 if (it == current_range.end()) { 388 if (it == current_range.end()) {
@@ -393,8 +390,8 @@ private:
393 } 390 }
394 auto end_it = current_range.upper_bound(search_interval); 391 auto end_it = current_range.upper_bound(search_interval);
395 for (; it != end_it; it++) { 392 for (; it != end_it; it++) {
396 VAddr inter_addr_end = it->upper(); 393 DAddr inter_addr_end = it->upper();
397 VAddr inter_addr = it->lower(); 394 DAddr inter_addr = it->lower();
398 if (inter_addr_end > end_address) { 395 if (inter_addr_end > end_address) {
399 inter_addr_end = end_address; 396 inter_addr_end = end_address;
400 } 397 }
@@ -406,10 +403,10 @@ private:
406 } 403 }
407 404
408 template <typename Func> 405 template <typename Func>
409 void ForEachInOverlapCounter(OverlapCounter& current_range, VAddr cpu_addr, u64 size, 406 void ForEachInOverlapCounter(OverlapCounter& current_range, DAddr device_addr, u64 size,
410 Func&& func) { 407 Func&& func) {
411 const VAddr start_address = cpu_addr; 408 const DAddr start_address = device_addr;
412 const VAddr end_address = start_address + size; 409 const DAddr end_address = start_address + size;
413 const IntervalType search_interval{start_address, end_address}; 410 const IntervalType search_interval{start_address, end_address};
414 auto it = current_range.lower_bound(search_interval); 411 auto it = current_range.lower_bound(search_interval);
415 if (it == current_range.end()) { 412 if (it == current_range.end()) {
@@ -418,8 +415,8 @@ private:
418 auto end_it = current_range.upper_bound(search_interval); 415 auto end_it = current_range.upper_bound(search_interval);
419 for (; it != end_it; it++) { 416 for (; it != end_it; it++) {
420 auto& inter = it->first; 417 auto& inter = it->first;
421 VAddr inter_addr_end = inter.upper(); 418 DAddr inter_addr_end = inter.upper();
422 VAddr inter_addr = inter.lower(); 419 DAddr inter_addr = inter.lower();
423 if (inter_addr_end > end_address) { 420 if (inter_addr_end > end_address) {
424 inter_addr_end = end_address; 421 inter_addr_end = end_address;
425 } 422 }
@@ -451,9 +448,9 @@ private:
451 } while (any_removals); 448 } while (any_removals);
452 } 449 }
453 450
454 static bool IsRangeGranular(VAddr cpu_addr, size_t size) { 451 static bool IsRangeGranular(DAddr device_addr, size_t size) {
455 return (cpu_addr & ~Core::Memory::YUZU_PAGEMASK) == 452 return (device_addr & ~Core::DEVICE_PAGEMASK) ==
456 ((cpu_addr + size) & ~Core::Memory::YUZU_PAGEMASK); 453 ((device_addr + size) & ~Core::DEVICE_PAGEMASK);
457 } 454 }
458 455
459 void RunGarbageCollector(); 456 void RunGarbageCollector();
@@ -508,15 +505,15 @@ private:
508 505
509 void UpdateComputeTextureBuffers(); 506 void UpdateComputeTextureBuffers();
510 507
511 void MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size); 508 void MarkWrittenBuffer(BufferId buffer_id, DAddr device_addr, u32 size);
512 509
513 [[nodiscard]] BufferId FindBuffer(VAddr cpu_addr, u32 size); 510 [[nodiscard]] BufferId FindBuffer(DAddr device_addr, u32 size);
514 511
515 [[nodiscard]] OverlapResult ResolveOverlaps(VAddr cpu_addr, u32 wanted_size); 512 [[nodiscard]] OverlapResult ResolveOverlaps(DAddr device_addr, u32 wanted_size);
516 513
517 void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score); 514 void JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, bool accumulate_stream_score);
518 515
519 [[nodiscard]] BufferId CreateBuffer(VAddr cpu_addr, u32 wanted_size); 516 [[nodiscard]] BufferId CreateBuffer(DAddr device_addr, u32 wanted_size);
520 517
521 void Register(BufferId buffer_id); 518 void Register(BufferId buffer_id);
522 519
@@ -527,7 +524,7 @@ private:
527 524
528 void TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept; 525 void TouchBuffer(Buffer& buffer, BufferId buffer_id) noexcept;
529 526
530 bool SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size); 527 bool SynchronizeBuffer(Buffer& buffer, DAddr device_addr, u32 size);
531 528
532 void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, 529 void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy,
533 std::span<BufferCopy> copies); 530 std::span<BufferCopy> copies);
@@ -539,7 +536,7 @@ private:
539 536
540 void DownloadBufferMemory(Buffer& buffer_id); 537 void DownloadBufferMemory(Buffer& buffer_id);
541 538
542 void DownloadBufferMemory(Buffer& buffer_id, VAddr cpu_addr, u64 size); 539 void DownloadBufferMemory(Buffer& buffer_id, DAddr device_addr, u64 size);
543 540
544 void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false); 541 void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false);
545 542
@@ -549,7 +546,7 @@ private:
549 [[nodiscard]] TextureBufferBinding GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size, 546 [[nodiscard]] TextureBufferBinding GetTextureBufferBinding(GPUVAddr gpu_addr, u32 size,
550 PixelFormat format); 547 PixelFormat format);
551 548
552 [[nodiscard]] std::span<const u8> ImmediateBufferWithData(VAddr cpu_addr, size_t size); 549 [[nodiscard]] std::span<const u8> ImmediateBufferWithData(DAddr device_addr, size_t size);
553 550
554 [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity); 551 [[nodiscard]] std::span<u8> ImmediateBuffer(size_t wanted_capacity);
555 552
@@ -557,11 +554,10 @@ private:
557 554
558 void ClearDownload(IntervalType subtract_interval); 555 void ClearDownload(IntervalType subtract_interval);
559 556
560 void InlineMemoryImplementation(VAddr dest_address, size_t copy_size, 557 void InlineMemoryImplementation(DAddr dest_address, size_t copy_size,
561 std::span<const u8> inlined_buffer); 558 std::span<const u8> inlined_buffer);
562 559
563 VideoCore::RasterizerInterface& rasterizer; 560 Tegra::MaxwellDeviceMemoryManager& device_memory;
564 Core::Memory::Memory& cpu_memory;
565 561
566 SlotVector<Buffer> slot_buffers; 562 SlotVector<Buffer> slot_buffers;
567 DelayedDestructionRing<Buffer, 8> delayed_destruction_ring; 563 DelayedDestructionRing<Buffer, 8> delayed_destruction_ring;
@@ -598,7 +594,7 @@ private:
598 u64 critical_memory = 0; 594 u64 critical_memory = 0;
599 BufferId inline_buffer_id; 595 BufferId inline_buffer_id;
600 596
601 std::array<BufferId, ((1ULL << 39) >> CACHING_PAGEBITS)> page_table; 597 std::array<BufferId, ((1ULL << 34) >> CACHING_PAGEBITS)> page_table;
602 Common::ScratchBuffer<u8> tmp_buffer; 598 Common::ScratchBuffer<u8> tmp_buffer;
603}; 599};
604 600
diff --git a/src/video_core/buffer_cache/memory_tracker_base.h b/src/video_core/buffer_cache/memory_tracker_base.h
index 6c1c8287b..c95eed1f6 100644
--- a/src/video_core/buffer_cache/memory_tracker_base.h
+++ b/src/video_core/buffer_cache/memory_tracker_base.h
@@ -17,19 +17,19 @@
17 17
18namespace VideoCommon { 18namespace VideoCommon {
19 19
20template <class RasterizerInterface> 20template <typename DeviceTracker>
21class MemoryTrackerBase { 21class MemoryTrackerBase {
22 static constexpr size_t MAX_CPU_PAGE_BITS = 39; 22 static constexpr size_t MAX_CPU_PAGE_BITS = 34;
23 static constexpr size_t HIGHER_PAGE_BITS = 22; 23 static constexpr size_t HIGHER_PAGE_BITS = 22;
24 static constexpr size_t HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS; 24 static constexpr size_t HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS;
25 static constexpr size_t HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL; 25 static constexpr size_t HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL;
26 static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS); 26 static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS);
27 static constexpr size_t MANAGER_POOL_SIZE = 32; 27 static constexpr size_t MANAGER_POOL_SIZE = 32;
28 static constexpr size_t WORDS_STACK_NEEDED = HIGHER_PAGE_SIZE / BYTES_PER_WORD; 28 static constexpr size_t WORDS_STACK_NEEDED = HIGHER_PAGE_SIZE / BYTES_PER_WORD;
29 using Manager = WordManager<RasterizerInterface, WORDS_STACK_NEEDED>; 29 using Manager = WordManager<DeviceTracker, WORDS_STACK_NEEDED>;
30 30
31public: 31public:
32 MemoryTrackerBase(RasterizerInterface& rasterizer_) : rasterizer{&rasterizer_} {} 32 MemoryTrackerBase(DeviceTracker& device_tracker_) : device_tracker{&device_tracker_} {}
33 ~MemoryTrackerBase() = default; 33 ~MemoryTrackerBase() = default;
34 34
35 /// Returns the inclusive CPU modified range in a begin end pair 35 /// Returns the inclusive CPU modified range in a begin end pair
@@ -74,7 +74,7 @@ public:
74 }); 74 });
75 } 75 }
76 76
77 /// Mark region as CPU modified, notifying the rasterizer about this change 77 /// Mark region as CPU modified, notifying the device_tracker about this change
78 void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { 78 void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) {
79 IteratePages<true>(dirty_cpu_addr, query_size, 79 IteratePages<true>(dirty_cpu_addr, query_size,
80 [](Manager* manager, u64 offset, size_t size) { 80 [](Manager* manager, u64 offset, size_t size) {
@@ -83,7 +83,7 @@ public:
83 }); 83 });
84 } 84 }
85 85
86 /// Unmark region as CPU modified, notifying the rasterizer about this change 86 /// Unmark region as CPU modified, notifying the device_tracker about this change
87 void UnmarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { 87 void UnmarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) {
88 IteratePages<true>(dirty_cpu_addr, query_size, 88 IteratePages<true>(dirty_cpu_addr, query_size,
89 [](Manager* manager, u64 offset, size_t size) { 89 [](Manager* manager, u64 offset, size_t size) {
@@ -139,7 +139,7 @@ public:
139 }); 139 });
140 } 140 }
141 141
142 /// Flushes cached CPU writes, and notify the rasterizer about the deltas 142 /// Flushes cached CPU writes, and notify the device_tracker about the deltas
143 void FlushCachedWrites(VAddr query_cpu_addr, u64 query_size) noexcept { 143 void FlushCachedWrites(VAddr query_cpu_addr, u64 query_size) noexcept {
144 IteratePages<false>(query_cpu_addr, query_size, 144 IteratePages<false>(query_cpu_addr, query_size,
145 [](Manager* manager, [[maybe_unused]] u64 offset, 145 [](Manager* manager, [[maybe_unused]] u64 offset,
@@ -280,7 +280,7 @@ private:
280 manager_pool.emplace_back(); 280 manager_pool.emplace_back();
281 auto& last_pool = manager_pool.back(); 281 auto& last_pool = manager_pool.back();
282 for (size_t i = 0; i < MANAGER_POOL_SIZE; i++) { 282 for (size_t i = 0; i < MANAGER_POOL_SIZE; i++) {
283 new (&last_pool[i]) Manager(0, *rasterizer, HIGHER_PAGE_SIZE); 283 new (&last_pool[i]) Manager(0, *device_tracker, HIGHER_PAGE_SIZE);
284 free_managers.push_back(&last_pool[i]); 284 free_managers.push_back(&last_pool[i]);
285 } 285 }
286 return on_return(); 286 return on_return();
@@ -293,7 +293,7 @@ private:
293 293
294 std::unordered_set<u32> cached_pages; 294 std::unordered_set<u32> cached_pages;
295 295
296 RasterizerInterface* rasterizer = nullptr; 296 DeviceTracker* device_tracker = nullptr;
297}; 297};
298 298
299} // namespace VideoCommon 299} // namespace VideoCommon
diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h
index a336bde41..3db9d8b42 100644
--- a/src/video_core/buffer_cache/word_manager.h
+++ b/src/video_core/buffer_cache/word_manager.h
@@ -13,12 +13,12 @@
13#include "common/common_funcs.h" 13#include "common/common_funcs.h"
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/div_ceil.h" 15#include "common/div_ceil.h"
16#include "core/memory.h" 16#include "video_core/host1x/gpu_device_memory_manager.h"
17 17
18namespace VideoCommon { 18namespace VideoCommon {
19 19
20constexpr u64 PAGES_PER_WORD = 64; 20constexpr u64 PAGES_PER_WORD = 64;
21constexpr u64 BYTES_PER_PAGE = Core::Memory::YUZU_PAGESIZE; 21constexpr u64 BYTES_PER_PAGE = Core::DEVICE_PAGESIZE;
22constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE; 22constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE;
23 23
24enum class Type { 24enum class Type {
@@ -163,11 +163,11 @@ struct Words {
163 WordsArray<stack_words> preflushable; 163 WordsArray<stack_words> preflushable;
164}; 164};
165 165
166template <class RasterizerInterface, size_t stack_words = 1> 166template <class DeviceTracker, size_t stack_words = 1>
167class WordManager { 167class WordManager {
168public: 168public:
169 explicit WordManager(VAddr cpu_addr_, RasterizerInterface& rasterizer_, u64 size_bytes) 169 explicit WordManager(VAddr cpu_addr_, DeviceTracker& tracker_, u64 size_bytes)
170 : cpu_addr{cpu_addr_}, rasterizer{&rasterizer_}, words{size_bytes} {} 170 : cpu_addr{cpu_addr_}, tracker{&tracker_}, words{size_bytes} {}
171 171
172 explicit WordManager() = default; 172 explicit WordManager() = default;
173 173
@@ -279,7 +279,7 @@ public:
279 } 279 }
280 280
281 /** 281 /**
282 * Loop over each page in the given range, turn off those bits and notify the rasterizer if 282 * Loop over each page in the given range, turn off those bits and notify the tracker if
283 * needed. Call the given function on each turned off range. 283 * needed. Call the given function on each turned off range.
284 * 284 *
285 * @param query_cpu_range Base CPU address to loop over 285 * @param query_cpu_range Base CPU address to loop over
@@ -459,26 +459,26 @@ private:
459 } 459 }
460 460
461 /** 461 /**
462 * Notify rasterizer about changes in the CPU tracking state of a word in the buffer 462 * Notify tracker about changes in the CPU tracking state of a word in the buffer
463 * 463 *
464 * @param word_index Index to the word to notify to the rasterizer 464 * @param word_index Index to the word to notify to the tracker
465 * @param current_bits Current state of the word 465 * @param current_bits Current state of the word
466 * @param new_bits New state of the word 466 * @param new_bits New state of the word
467 * 467 *
468 * @tparam add_to_rasterizer True when the rasterizer should start tracking the new pages 468 * @tparam add_to_tracker True when the tracker should start tracking the new pages
469 */ 469 */
470 template <bool add_to_rasterizer> 470 template <bool add_to_tracker>
471 void NotifyRasterizer(u64 word_index, u64 current_bits, u64 new_bits) const { 471 void NotifyRasterizer(u64 word_index, u64 current_bits, u64 new_bits) const {
472 u64 changed_bits = (add_to_rasterizer ? current_bits : ~current_bits) & new_bits; 472 u64 changed_bits = (add_to_tracker ? current_bits : ~current_bits) & new_bits;
473 VAddr addr = cpu_addr + word_index * BYTES_PER_WORD; 473 VAddr addr = cpu_addr + word_index * BYTES_PER_WORD;
474 IteratePages(changed_bits, [&](size_t offset, size_t size) { 474 IteratePages(changed_bits, [&](size_t offset, size_t size) {
475 rasterizer->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE, 475 tracker->UpdatePagesCachedCount(addr + offset * BYTES_PER_PAGE, size * BYTES_PER_PAGE,
476 size * BYTES_PER_PAGE, add_to_rasterizer ? 1 : -1); 476 add_to_tracker ? 1 : -1);
477 }); 477 });
478 } 478 }
479 479
480 VAddr cpu_addr = 0; 480 VAddr cpu_addr = 0;
481 RasterizerInterface* rasterizer = nullptr; 481 DeviceTracker* tracker = nullptr;
482 Words<stack_words> words; 482 Words<stack_words> words;
483}; 483};
484 484
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 58ce0d8c2..fb2060ca4 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -5,10 +5,10 @@
5#include "common/microprofile.h" 5#include "common/microprofile.h"
6#include "common/settings.h" 6#include "common/settings.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/memory.h"
9#include "video_core/dma_pusher.h" 8#include "video_core/dma_pusher.h"
10#include "video_core/engines/maxwell_3d.h" 9#include "video_core/engines/maxwell_3d.h"
11#include "video_core/gpu.h" 10#include "video_core/gpu.h"
11#include "video_core/guest_memory.h"
12#include "video_core/memory_manager.h" 12#include "video_core/memory_manager.h"
13 13
14namespace Tegra { 14namespace Tegra {
@@ -85,15 +85,15 @@ bool DmaPusher::Step() {
85 } 85 }
86 } 86 }
87 const auto safe_process = [&] { 87 const auto safe_process = [&] {
88 Core::Memory::GpuGuestMemory<Tegra::CommandHeader, 88 Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader,
89 Core::Memory::GuestMemoryFlags::SafeRead> 89 Tegra::Memory::GuestMemoryFlags::SafeRead>
90 headers(memory_manager, dma_state.dma_get, command_list_header.size, 90 headers(memory_manager, dma_state.dma_get, command_list_header.size,
91 &command_headers); 91 &command_headers);
92 ProcessCommands(headers); 92 ProcessCommands(headers);
93 }; 93 };
94 const auto unsafe_process = [&] { 94 const auto unsafe_process = [&] {
95 Core::Memory::GpuGuestMemory<Tegra::CommandHeader, 95 Tegra::Memory::GpuGuestMemory<Tegra::CommandHeader,
96 Core::Memory::GuestMemoryFlags::UnsafeRead> 96 Tegra::Memory::GuestMemoryFlags::UnsafeRead>
97 headers(memory_manager, dma_state.dma_get, command_list_header.size, 97 headers(memory_manager, dma_state.dma_get, command_list_header.size,
98 &command_headers); 98 &command_headers);
99 ProcessCommands(headers); 99 ProcessCommands(headers);
diff --git a/src/video_core/engines/engine_upload.cpp b/src/video_core/engines/engine_upload.cpp
index bc64d4486..e5cc04ec4 100644
--- a/src/video_core/engines/engine_upload.cpp
+++ b/src/video_core/engines/engine_upload.cpp
@@ -5,8 +5,8 @@
5 5
6#include "common/algorithm.h" 6#include "common/algorithm.h"
7#include "common/assert.h" 7#include "common/assert.h"
8#include "core/memory.h"
9#include "video_core/engines/engine_upload.h" 8#include "video_core/engines/engine_upload.h"
9#include "video_core/guest_memory.h"
10#include "video_core/memory_manager.h" 10#include "video_core/memory_manager.h"
11#include "video_core/rasterizer_interface.h" 11#include "video_core/rasterizer_interface.h"
12#include "video_core/textures/decoders.h" 12#include "video_core/textures/decoders.h"
@@ -68,7 +68,8 @@ void State::ProcessData(std::span<const u8> read_buffer) {
68 true, bytes_per_pixel, width, regs.dest.height, regs.dest.depth, 68 true, bytes_per_pixel, width, regs.dest.height, regs.dest.depth,
69 regs.dest.BlockHeight(), regs.dest.BlockDepth()); 69 regs.dest.BlockHeight(), regs.dest.BlockDepth());
70 70
71 Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> 71 Tegra::Memory::GpuGuestMemoryScoped<u8,
72 Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite>
72 tmp(memory_manager, address, dst_size, &tmp_buffer); 73 tmp(memory_manager, address, dst_size, &tmp_buffer);
73 74
74 Tegra::Texture::SwizzleSubrect(tmp, read_buffer, bytes_per_pixel, width, regs.dest.height, 75 Tegra::Texture::SwizzleSubrect(tmp, read_buffer, bytes_per_pixel, width, regs.dest.height,
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 95ba4f76c..a94e1f043 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -9,7 +9,6 @@
9#include "common/settings.h" 9#include "common/settings.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/core_timing.h" 11#include "core/core_timing.h"
12#include "core/memory.h"
13#include "video_core/dirty_flags.h" 12#include "video_core/dirty_flags.h"
14#include "video_core/engines/draw_manager.h" 13#include "video_core/engines/draw_manager.h"
15#include "video_core/engines/maxwell_3d.h" 14#include "video_core/engines/maxwell_3d.h"
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp
index 56fbff306..2ebd21fc5 100644
--- a/src/video_core/engines/maxwell_dma.cpp
+++ b/src/video_core/engines/maxwell_dma.cpp
@@ -8,9 +8,9 @@
8#include "common/polyfill_ranges.h" 8#include "common/polyfill_ranges.h"
9#include "common/settings.h" 9#include "common/settings.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/memory.h"
12#include "video_core/engines/maxwell_3d.h" 11#include "video_core/engines/maxwell_3d.h"
13#include "video_core/engines/maxwell_dma.h" 12#include "video_core/engines/maxwell_dma.h"
13#include "video_core/guest_memory.h"
14#include "video_core/memory_manager.h" 14#include "video_core/memory_manager.h"
15#include "video_core/renderer_base.h" 15#include "video_core/renderer_base.h"
16#include "video_core/textures/decoders.h" 16#include "video_core/textures/decoders.h"
@@ -133,8 +133,8 @@ void MaxwellDMA::Launch() {
133 UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); 133 UNIMPLEMENTED_IF(regs.offset_out % 16 != 0);
134 read_buffer.resize_destructive(16); 134 read_buffer.resize_destructive(16);
135 for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { 135 for (u32 offset = 0; offset < regs.line_length_in; offset += 16) {
136 Core::Memory::GpuGuestMemoryScoped< 136 Tegra::Memory::GpuGuestMemoryScoped<
137 u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> 137 u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite>
138 tmp_write_buffer(memory_manager, 138 tmp_write_buffer(memory_manager,
139 convert_linear_2_blocklinear_addr(regs.offset_in + offset), 139 convert_linear_2_blocklinear_addr(regs.offset_in + offset),
140 16, &read_buffer); 140 16, &read_buffer);
@@ -146,16 +146,16 @@ void MaxwellDMA::Launch() {
146 UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); 146 UNIMPLEMENTED_IF(regs.offset_out % 16 != 0);
147 read_buffer.resize_destructive(16); 147 read_buffer.resize_destructive(16);
148 for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { 148 for (u32 offset = 0; offset < regs.line_length_in; offset += 16) {
149 Core::Memory::GpuGuestMemoryScoped< 149 Tegra::Memory::GpuGuestMemoryScoped<
150 u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> 150 u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite>
151 tmp_write_buffer(memory_manager, regs.offset_in + offset, 16, &read_buffer); 151 tmp_write_buffer(memory_manager, regs.offset_in + offset, 16, &read_buffer);
152 tmp_write_buffer.SetAddressAndSize( 152 tmp_write_buffer.SetAddressAndSize(
153 convert_linear_2_blocklinear_addr(regs.offset_out + offset), 16); 153 convert_linear_2_blocklinear_addr(regs.offset_out + offset), 16);
154 } 154 }
155 } else { 155 } else {
156 if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) { 156 if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) {
157 Core::Memory::GpuGuestMemoryScoped< 157 Tegra::Memory::GpuGuestMemoryScoped<
158 u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> 158 u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite>
159 tmp_write_buffer(memory_manager, regs.offset_in, regs.line_length_in, 159 tmp_write_buffer(memory_manager, regs.offset_in, regs.line_length_in,
160 &read_buffer); 160 &read_buffer);
161 tmp_write_buffer.SetAddressAndSize(regs.offset_out, regs.line_length_in); 161 tmp_write_buffer.SetAddressAndSize(regs.offset_out, regs.line_length_in);
@@ -226,9 +226,9 @@ void MaxwellDMA::CopyBlockLinearToPitch() {
226 226
227 const size_t dst_size = dst_operand.pitch * regs.line_count; 227 const size_t dst_size = dst_operand.pitch * regs.line_count;
228 228
229 Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( 229 Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer(
230 memory_manager, src_operand.address, src_size, &read_buffer); 230 memory_manager, src_operand.address, src_size, &read_buffer);
231 Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadCachedWrite> 231 Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::UnsafeReadCachedWrite>
232 tmp_write_buffer(memory_manager, dst_operand.address, dst_size, &write_buffer); 232 tmp_write_buffer(memory_manager, dst_operand.address, dst_size, &write_buffer);
233 233
234 UnswizzleSubrect(tmp_write_buffer, tmp_read_buffer, bytes_per_pixel, width, height, depth, 234 UnswizzleSubrect(tmp_write_buffer, tmp_read_buffer, bytes_per_pixel, width, height, depth,
@@ -290,9 +290,9 @@ void MaxwellDMA::CopyPitchToBlockLinear() {
290 290
291 GPUVAddr src_addr = regs.offset_in; 291 GPUVAddr src_addr = regs.offset_in;
292 GPUVAddr dst_addr = regs.offset_out; 292 GPUVAddr dst_addr = regs.offset_out;
293 Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( 293 Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer(
294 memory_manager, src_addr, src_size, &read_buffer); 294 memory_manager, src_addr, src_size, &read_buffer);
295 Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadCachedWrite> 295 Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::UnsafeReadCachedWrite>
296 tmp_write_buffer(memory_manager, dst_addr, dst_size, &write_buffer); 296 tmp_write_buffer(memory_manager, dst_addr, dst_size, &write_buffer);
297 297
298 // If the input is linear and the output is tiled, swizzle the input and copy it over. 298 // If the input is linear and the output is tiled, swizzle the input and copy it over.
@@ -344,9 +344,9 @@ void MaxwellDMA::CopyBlockLinearToBlockLinear() {
344 344
345 intermediate_buffer.resize_destructive(mid_buffer_size); 345 intermediate_buffer.resize_destructive(mid_buffer_size);
346 346
347 Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer( 347 Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_read_buffer(
348 memory_manager, regs.offset_in, src_size, &read_buffer); 348 memory_manager, regs.offset_in, src_size, &read_buffer);
349 Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::SafeReadCachedWrite> 349 Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::SafeReadCachedWrite>
350 tmp_write_buffer(memory_manager, regs.offset_out, dst_size, &write_buffer); 350 tmp_write_buffer(memory_manager, regs.offset_out, dst_size, &write_buffer);
351 351
352 UnswizzleSubrect(intermediate_buffer, tmp_read_buffer, bytes_per_pixel, src_width, src.height, 352 UnswizzleSubrect(intermediate_buffer, tmp_read_buffer, bytes_per_pixel, src_width, src.height,
diff --git a/src/video_core/engines/sw_blitter/blitter.cpp b/src/video_core/engines/sw_blitter/blitter.cpp
index 67ce9134b..4bc079024 100644
--- a/src/video_core/engines/sw_blitter/blitter.cpp
+++ b/src/video_core/engines/sw_blitter/blitter.cpp
@@ -8,6 +8,7 @@
8#include "common/scratch_buffer.h" 8#include "common/scratch_buffer.h"
9#include "video_core/engines/sw_blitter/blitter.h" 9#include "video_core/engines/sw_blitter/blitter.h"
10#include "video_core/engines/sw_blitter/converter.h" 10#include "video_core/engines/sw_blitter/converter.h"
11#include "video_core/guest_memory.h"
11#include "video_core/memory_manager.h" 12#include "video_core/memory_manager.h"
12#include "video_core/surface.h" 13#include "video_core/surface.h"
13#include "video_core/textures/decoders.h" 14#include "video_core/textures/decoders.h"
@@ -160,7 +161,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
160 const auto dst_bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(dst.format)); 161 const auto dst_bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(dst.format));
161 const size_t src_size = get_surface_size(src, src_bytes_per_pixel); 162 const size_t src_size = get_surface_size(src, src_bytes_per_pixel);
162 163
163 Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead> tmp_buffer( 164 Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::SafeRead> tmp_buffer(
164 memory_manager, src.Address(), src_size, &impl->tmp_buffer); 165 memory_manager, src.Address(), src_size, &impl->tmp_buffer);
165 166
166 const size_t src_copy_size = src_extent_x * src_extent_y * src_bytes_per_pixel; 167 const size_t src_copy_size = src_extent_x * src_extent_y * src_bytes_per_pixel;
@@ -220,7 +221,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
220 } 221 }
221 222
222 const size_t dst_size = get_surface_size(dst, dst_bytes_per_pixel); 223 const size_t dst_size = get_surface_size(dst, dst_bytes_per_pixel);
223 Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::SafeReadWrite> 224 Tegra::Memory::GpuGuestMemoryScoped<u8, Tegra::Memory::GuestMemoryFlags::SafeReadWrite>
224 tmp_buffer2(memory_manager, dst.Address(), dst_size, &impl->tmp_buffer); 225 tmp_buffer2(memory_manager, dst.Address(), dst_size, &impl->tmp_buffer);
225 226
226 if (dst.linear == Fermi2D::MemoryLayout::BlockLinear) { 227 if (dst.linear == Fermi2D::MemoryLayout::BlockLinear) {
diff --git a/src/video_core/framebuffer_config.h b/src/video_core/framebuffer_config.h
index 5f3bffcab..856f4bd52 100644
--- a/src/video_core/framebuffer_config.h
+++ b/src/video_core/framebuffer_config.h
@@ -14,7 +14,7 @@ namespace Tegra {
14 * Struct describing framebuffer configuration 14 * Struct describing framebuffer configuration
15 */ 15 */
16struct FramebufferConfig { 16struct FramebufferConfig {
17 VAddr address{}; 17 DAddr address{};
18 u32 offset{}; 18 u32 offset{};
19 u32 width{}; 19 u32 width{};
20 u32 height{}; 20 u32 height{};
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 11549d448..609704b33 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -85,7 +85,8 @@ struct GPU::Impl {
85 void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { 85 void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
86 renderer = std::move(renderer_); 86 renderer = std::move(renderer_);
87 rasterizer = renderer->ReadRasterizer(); 87 rasterizer = renderer->ReadRasterizer();
88 host1x.MemoryManager().BindRasterizer(rasterizer); 88 host1x.MemoryManager().BindInterface(rasterizer);
89 host1x.GMMU().BindRasterizer(rasterizer);
89 } 90 }
90 91
91 /// Flush all current written commands into the host GPU for execution. 92 /// Flush all current written commands into the host GPU for execution.
@@ -95,8 +96,8 @@ struct GPU::Impl {
95 96
96 /// Synchronizes CPU writes with Host GPU memory. 97 /// Synchronizes CPU writes with Host GPU memory.
97 void InvalidateGPUCache() { 98 void InvalidateGPUCache() {
98 std::function<void(VAddr, size_t)> callback_writes( 99 std::function<void(PAddr, size_t)> callback_writes(
99 [this](VAddr address, size_t size) { rasterizer->OnCacheInvalidation(address, size); }); 100 [this](PAddr address, size_t size) { rasterizer->OnCacheInvalidation(address, size); });
100 system.GatherGPUDirtyMemory(callback_writes); 101 system.GatherGPUDirtyMemory(callback_writes);
101 } 102 }
102 103
@@ -279,11 +280,11 @@ struct GPU::Impl {
279 } 280 }
280 281
281 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 282 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
282 void FlushRegion(VAddr addr, u64 size) { 283 void FlushRegion(DAddr addr, u64 size) {
283 gpu_thread.FlushRegion(addr, size); 284 gpu_thread.FlushRegion(addr, size);
284 } 285 }
285 286
286 VideoCore::RasterizerDownloadArea OnCPURead(VAddr addr, u64 size) { 287 VideoCore::RasterizerDownloadArea OnCPURead(DAddr addr, u64 size) {
287 auto raster_area = rasterizer->GetFlushArea(addr, size); 288 auto raster_area = rasterizer->GetFlushArea(addr, size);
288 if (raster_area.preemtive) { 289 if (raster_area.preemtive) {
289 return raster_area; 290 return raster_area;
@@ -299,16 +300,16 @@ struct GPU::Impl {
299 } 300 }
300 301
301 /// Notify rasterizer that any caches of the specified region should be invalidated 302 /// Notify rasterizer that any caches of the specified region should be invalidated
302 void InvalidateRegion(VAddr addr, u64 size) { 303 void InvalidateRegion(DAddr addr, u64 size) {
303 gpu_thread.InvalidateRegion(addr, size); 304 gpu_thread.InvalidateRegion(addr, size);
304 } 305 }
305 306
306 bool OnCPUWrite(VAddr addr, u64 size) { 307 bool OnCPUWrite(DAddr addr, u64 size) {
307 return rasterizer->OnCPUWrite(addr, size); 308 return rasterizer->OnCPUWrite(addr, size);
308 } 309 }
309 310
310 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated 311 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
311 void FlushAndInvalidateRegion(VAddr addr, u64 size) { 312 void FlushAndInvalidateRegion(DAddr addr, u64 size) {
312 gpu_thread.FlushAndInvalidateRegion(addr, size); 313 gpu_thread.FlushAndInvalidateRegion(addr, size);
313 } 314 }
314 315
@@ -437,7 +438,7 @@ void GPU::OnCommandListEnd() {
437 impl->OnCommandListEnd(); 438 impl->OnCommandListEnd();
438} 439}
439 440
440u64 GPU::RequestFlush(VAddr addr, std::size_t size) { 441u64 GPU::RequestFlush(DAddr addr, std::size_t size) {
441 return impl->RequestSyncOperation( 442 return impl->RequestSyncOperation(
442 [this, addr, size]() { impl->rasterizer->FlushRegion(addr, size); }); 443 [this, addr, size]() { impl->rasterizer->FlushRegion(addr, size); });
443} 444}
@@ -557,23 +558,23 @@ void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
557 impl->SwapBuffers(framebuffer); 558 impl->SwapBuffers(framebuffer);
558} 559}
559 560
560VideoCore::RasterizerDownloadArea GPU::OnCPURead(VAddr addr, u64 size) { 561VideoCore::RasterizerDownloadArea GPU::OnCPURead(PAddr addr, u64 size) {
561 return impl->OnCPURead(addr, size); 562 return impl->OnCPURead(addr, size);
562} 563}
563 564
564void GPU::FlushRegion(VAddr addr, u64 size) { 565void GPU::FlushRegion(DAddr addr, u64 size) {
565 impl->FlushRegion(addr, size); 566 impl->FlushRegion(addr, size);
566} 567}
567 568
568void GPU::InvalidateRegion(VAddr addr, u64 size) { 569void GPU::InvalidateRegion(DAddr addr, u64 size) {
569 impl->InvalidateRegion(addr, size); 570 impl->InvalidateRegion(addr, size);
570} 571}
571 572
572bool GPU::OnCPUWrite(VAddr addr, u64 size) { 573bool GPU::OnCPUWrite(DAddr addr, u64 size) {
573 return impl->OnCPUWrite(addr, size); 574 return impl->OnCPUWrite(addr, size);
574} 575}
575 576
576void GPU::FlushAndInvalidateRegion(VAddr addr, u64 size) { 577void GPU::FlushAndInvalidateRegion(DAddr addr, u64 size) {
577 impl->FlushAndInvalidateRegion(addr, size); 578 impl->FlushAndInvalidateRegion(addr, size);
578} 579}
579 580
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index ba2838b89..b3c1d15bd 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -158,7 +158,7 @@ public:
158 void InitAddressSpace(Tegra::MemoryManager& memory_manager); 158 void InitAddressSpace(Tegra::MemoryManager& memory_manager);
159 159
160 /// Request a host GPU memory flush from the CPU. 160 /// Request a host GPU memory flush from the CPU.
161 [[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size); 161 [[nodiscard]] u64 RequestFlush(DAddr addr, std::size_t size);
162 162
163 /// Obtains current flush request fence id. 163 /// Obtains current flush request fence id.
164 [[nodiscard]] u64 CurrentSyncRequestFence() const; 164 [[nodiscard]] u64 CurrentSyncRequestFence() const;
@@ -242,20 +242,20 @@ public:
242 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); 242 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
243 243
244 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 244 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
245 [[nodiscard]] VideoCore::RasterizerDownloadArea OnCPURead(VAddr addr, u64 size); 245 [[nodiscard]] VideoCore::RasterizerDownloadArea OnCPURead(DAddr addr, u64 size);
246 246
247 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 247 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
248 void FlushRegion(VAddr addr, u64 size); 248 void FlushRegion(DAddr addr, u64 size);
249 249
250 /// Notify rasterizer that any caches of the specified region should be invalidated 250 /// Notify rasterizer that any caches of the specified region should be invalidated
251 void InvalidateRegion(VAddr addr, u64 size); 251 void InvalidateRegion(DAddr addr, u64 size);
252 252
253 /// Notify rasterizer that CPU is trying to write this area. It returns true if the area is 253 /// Notify rasterizer that CPU is trying to write this area. It returns true if the area is
254 /// sensible, false otherwise 254 /// sensible, false otherwise
255 bool OnCPUWrite(VAddr addr, u64 size); 255 bool OnCPUWrite(DAddr addr, u64 size);
256 256
257 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated 257 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
258 void FlushAndInvalidateRegion(VAddr addr, u64 size); 258 void FlushAndInvalidateRegion(DAddr addr, u64 size);
259 259
260private: 260private:
261 struct Impl; 261 struct Impl;
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 2f0f9f593..788d4f61e 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -82,7 +82,7 @@ void ThreadManager::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
82 PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt)); 82 PushCommand(SwapBuffersCommand(framebuffer ? std::make_optional(*framebuffer) : std::nullopt));
83} 83}
84 84
85void ThreadManager::FlushRegion(VAddr addr, u64 size) { 85void ThreadManager::FlushRegion(DAddr addr, u64 size) {
86 if (!is_async) { 86 if (!is_async) {
87 // Always flush with synchronous GPU mode 87 // Always flush with synchronous GPU mode
88 PushCommand(FlushRegionCommand(addr, size)); 88 PushCommand(FlushRegionCommand(addr, size));
@@ -101,11 +101,11 @@ void ThreadManager::TickGPU() {
101 PushCommand(GPUTickCommand()); 101 PushCommand(GPUTickCommand());
102} 102}
103 103
104void ThreadManager::InvalidateRegion(VAddr addr, u64 size) { 104void ThreadManager::InvalidateRegion(DAddr addr, u64 size) {
105 rasterizer->OnCacheInvalidation(addr, size); 105 rasterizer->OnCacheInvalidation(addr, size);
106} 106}
107 107
108void ThreadManager::FlushAndInvalidateRegion(VAddr addr, u64 size) { 108void ThreadManager::FlushAndInvalidateRegion(DAddr addr, u64 size) {
109 // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important 109 // Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
110 rasterizer->OnCacheInvalidation(addr, size); 110 rasterizer->OnCacheInvalidation(addr, size);
111} 111}
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index 43940bd6d..2de25e9ef 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -54,26 +54,26 @@ struct SwapBuffersCommand final {
54 54
55/// Command to signal to the GPU thread to flush a region 55/// Command to signal to the GPU thread to flush a region
56struct FlushRegionCommand final { 56struct FlushRegionCommand final {
57 explicit constexpr FlushRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {} 57 explicit constexpr FlushRegionCommand(DAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
58 58
59 VAddr addr; 59 DAddr addr;
60 u64 size; 60 u64 size;
61}; 61};
62 62
63/// Command to signal to the GPU thread to invalidate a region 63/// Command to signal to the GPU thread to invalidate a region
64struct InvalidateRegionCommand final { 64struct InvalidateRegionCommand final {
65 explicit constexpr InvalidateRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {} 65 explicit constexpr InvalidateRegionCommand(DAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
66 66
67 VAddr addr; 67 DAddr addr;
68 u64 size; 68 u64 size;
69}; 69};
70 70
71/// Command to signal to the GPU thread to flush and invalidate a region 71/// Command to signal to the GPU thread to flush and invalidate a region
72struct FlushAndInvalidateRegionCommand final { 72struct FlushAndInvalidateRegionCommand final {
73 explicit constexpr FlushAndInvalidateRegionCommand(VAddr addr_, u64 size_) 73 explicit constexpr FlushAndInvalidateRegionCommand(DAddr addr_, u64 size_)
74 : addr{addr_}, size{size_} {} 74 : addr{addr_}, size{size_} {}
75 75
76 VAddr addr; 76 DAddr addr;
77 u64 size; 77 u64 size;
78}; 78};
79 79
@@ -122,13 +122,13 @@ public:
122 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer); 122 void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
123 123
124 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 124 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
125 void FlushRegion(VAddr addr, u64 size); 125 void FlushRegion(DAddr addr, u64 size);
126 126
127 /// Notify rasterizer that any caches of the specified region should be invalidated 127 /// Notify rasterizer that any caches of the specified region should be invalidated
128 void InvalidateRegion(VAddr addr, u64 size); 128 void InvalidateRegion(DAddr addr, u64 size);
129 129
130 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated 130 /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
131 void FlushAndInvalidateRegion(VAddr addr, u64 size); 131 void FlushAndInvalidateRegion(DAddr addr, u64 size);
132 132
133 void TickGPU(); 133 void TickGPU();
134 134
diff --git a/src/video_core/guest_memory.h b/src/video_core/guest_memory.h
new file mode 100644
index 000000000..8b6213172
--- /dev/null
+++ b/src/video_core/guest_memory.h
@@ -0,0 +1,30 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <iterator>
7#include <memory>
8#include <optional>
9#include <span>
10#include <vector>
11
12#include "common/scratch_buffer.h"
13#include "core/guest_memory.h"
14#include "video_core/memory_manager.h"
15
16namespace Tegra::Memory {
17
18using GuestMemoryFlags = Core::Memory::GuestMemoryFlags;
19
20template <typename T, GuestMemoryFlags FLAGS>
21using DeviceGuestMemory = Core::Memory::GuestMemory<Tegra::MaxwellDeviceMemoryManager, T, FLAGS>;
22template <typename T, GuestMemoryFlags FLAGS>
23using DeviceGuestMemoryScoped =
24 Core::Memory::GuestMemoryScoped<Tegra::MaxwellDeviceMemoryManager, T, FLAGS>;
25template <typename T, GuestMemoryFlags FLAGS>
26using GpuGuestMemory = Core::Memory::GuestMemory<Tegra::MemoryManager, T, FLAGS>;
27template <typename T, GuestMemoryFlags FLAGS>
28using GpuGuestMemoryScoped = Core::Memory::GuestMemoryScoped<Tegra::MemoryManager, T, FLAGS>;
29
30} // namespace Tegra::Memory
diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp
index 309a7f1d5..994591c8d 100644
--- a/src/video_core/host1x/codecs/h264.cpp
+++ b/src/video_core/host1x/codecs/h264.cpp
@@ -32,13 +32,12 @@ H264::~H264() = default;
32std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state, 32std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state,
33 size_t* out_configuration_size, bool is_first_frame) { 33 size_t* out_configuration_size, bool is_first_frame) {
34 H264DecoderContext context; 34 H264DecoderContext context;
35 host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context, 35 host1x.GMMU().ReadBlock(state.picture_info_offset, &context, sizeof(H264DecoderContext));
36 sizeof(H264DecoderContext));
37 36
38 const s64 frame_number = context.h264_parameter_set.frame_number.Value(); 37 const s64 frame_number = context.h264_parameter_set.frame_number.Value();
39 if (!is_first_frame && frame_number != 0) { 38 if (!is_first_frame && frame_number != 0) {
40 frame.resize_destructive(context.stream_len); 39 frame.resize_destructive(context.stream_len);
41 host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size()); 40 host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size());
42 *out_configuration_size = 0; 41 *out_configuration_size = 0;
43 return frame; 42 return frame;
44 } 43 }
@@ -159,8 +158,8 @@ std::span<const u8> H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters
159 std::memcpy(frame.data(), encoded_header.data(), encoded_header.size()); 158 std::memcpy(frame.data(), encoded_header.data(), encoded_header.size());
160 159
161 *out_configuration_size = encoded_header.size(); 160 *out_configuration_size = encoded_header.size();
162 host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, 161 host1x.GMMU().ReadBlock(state.frame_bitstream_offset, frame.data() + encoded_header.size(),
163 frame.data() + encoded_header.size(), context.stream_len); 162 context.stream_len);
164 163
165 return frame; 164 return frame;
166} 165}
diff --git a/src/video_core/host1x/codecs/vp8.cpp b/src/video_core/host1x/codecs/vp8.cpp
index ee6392ff9..be97e3b00 100644
--- a/src/video_core/host1x/codecs/vp8.cpp
+++ b/src/video_core/host1x/codecs/vp8.cpp
@@ -14,7 +14,7 @@ VP8::~VP8() = default;
14 14
15std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) { 15std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) {
16 VP8PictureInfo info; 16 VP8PictureInfo info;
17 host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo)); 17 host1x.GMMU().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo));
18 18
19 const bool is_key_frame = info.key_frame == 1u; 19 const bool is_key_frame = info.key_frame == 1u;
20 const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size); 20 const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size);
@@ -45,7 +45,7 @@ std::span<const u8> VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters&
45 frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f)); 45 frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f));
46 } 46 }
47 const u64 bitstream_offset = state.frame_bitstream_offset; 47 const u64 bitstream_offset = state.frame_bitstream_offset;
48 host1x.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size); 48 host1x.GMMU().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size);
49 49
50 return frame; 50 return frame;
51} 51}
diff --git a/src/video_core/host1x/codecs/vp9.cpp b/src/video_core/host1x/codecs/vp9.cpp
index 306c3d0e8..65d6fb2d5 100644
--- a/src/video_core/host1x/codecs/vp9.cpp
+++ b/src/video_core/host1x/codecs/vp9.cpp
@@ -358,7 +358,7 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_
358 358
359Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) { 359Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) {
360 PictureInfo picture_info; 360 PictureInfo picture_info;
361 host1x.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo)); 361 host1x.GMMU().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo));
362 Vp9PictureInfo vp9_info = picture_info.Convert(); 362 Vp9PictureInfo vp9_info = picture_info.Convert();
363 363
364 InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy); 364 InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy);
@@ -373,7 +373,7 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters&
373 373
374void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) { 374void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) {
375 EntropyProbs entropy; 375 EntropyProbs entropy;
376 host1x.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs)); 376 host1x.GMMU().ReadBlock(offset, &entropy, sizeof(EntropyProbs));
377 entropy.Convert(dst); 377 entropy.Convert(dst);
378} 378}
379 379
@@ -383,9 +383,8 @@ Vp9FrameContainer VP9::GetCurrentFrame(const Host1x::NvdecCommon::NvdecRegisters
383 // gpu.SyncGuestHost(); epic, why? 383 // gpu.SyncGuestHost(); epic, why?
384 current_frame.info = GetVp9PictureInfo(state); 384 current_frame.info = GetVp9PictureInfo(state);
385 current_frame.bit_stream.resize(current_frame.info.bitstream_size); 385 current_frame.bit_stream.resize(current_frame.info.bitstream_size);
386 host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, 386 host1x.GMMU().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(),
387 current_frame.bit_stream.data(), 387 current_frame.info.bitstream_size);
388 current_frame.info.bitstream_size);
389 } 388 }
390 if (!next_frame.bit_stream.empty()) { 389 if (!next_frame.bit_stream.empty()) {
391 Vp9FrameContainer temp{ 390 Vp9FrameContainer temp{
diff --git a/src/video_core/host1x/gpu_device_memory_manager.cpp b/src/video_core/host1x/gpu_device_memory_manager.cpp
new file mode 100644
index 000000000..668c2f08b
--- /dev/null
+++ b/src/video_core/host1x/gpu_device_memory_manager.cpp
@@ -0,0 +1,32 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/device_memory_manager.inc"
5#include "video_core/host1x/gpu_device_memory_manager.h"
6#include "video_core/rasterizer_interface.h"
7
8namespace Tegra {
9
10struct MaxwellDeviceMethods {
11 static inline void MarkRegionCaching(Core::Memory::Memory* interface, VAddr address,
12 size_t size, bool caching) {
13 interface->RasterizerMarkRegionCached(address, size, caching);
14 }
15};
16
17} // namespace Tegra
18
19template struct Core::DeviceMemoryManagerAllocator<Tegra::MaxwellDeviceTraits>;
20template class Core::DeviceMemoryManager<Tegra::MaxwellDeviceTraits>;
21
22template const u8* Tegra::MaxwellDeviceMemoryManager::GetPointer<u8>(DAddr addr) const;
23template u8* Tegra::MaxwellDeviceMemoryManager::GetPointer<u8>(DAddr addr);
24
25template u8 Tegra::MaxwellDeviceMemoryManager::Read<u8>(DAddr addr) const;
26template u16 Tegra::MaxwellDeviceMemoryManager::Read<u16>(DAddr addr) const;
27template u32 Tegra::MaxwellDeviceMemoryManager::Read<u32>(DAddr addr) const;
28template u64 Tegra::MaxwellDeviceMemoryManager::Read<u64>(DAddr addr) const;
29template void Tegra::MaxwellDeviceMemoryManager::Write<u8>(DAddr addr, u8 data);
30template void Tegra::MaxwellDeviceMemoryManager::Write<u16>(DAddr addr, u16 data);
31template void Tegra::MaxwellDeviceMemoryManager::Write<u32>(DAddr addr, u32 data);
32template void Tegra::MaxwellDeviceMemoryManager::Write<u64>(DAddr addr, u64 data); \ No newline at end of file
diff --git a/src/video_core/host1x/gpu_device_memory_manager.h b/src/video_core/host1x/gpu_device_memory_manager.h
new file mode 100644
index 000000000..a9f249991
--- /dev/null
+++ b/src/video_core/host1x/gpu_device_memory_manager.h
@@ -0,0 +1,24 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/device_memory_manager.h"
7
8namespace VideoCore {
9class RasterizerInterface;
10}
11
12namespace Tegra {
13
14struct MaxwellDeviceMethods;
15
16struct MaxwellDeviceTraits {
17 static constexpr size_t device_virtual_bits = 34;
18 using DeviceInterface = typename VideoCore::RasterizerInterface;
19 using DeviceMethods = MaxwellDeviceMethods;
20};
21
22using MaxwellDeviceMemoryManager = Core::DeviceMemoryManager<MaxwellDeviceTraits>;
23
24} // namespace Tegra \ No newline at end of file
diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp
index 7c317a85d..c4c7a5883 100644
--- a/src/video_core/host1x/host1x.cpp
+++ b/src/video_core/host1x/host1x.cpp
@@ -9,9 +9,12 @@ namespace Tegra {
9namespace Host1x { 9namespace Host1x {
10 10
11Host1x::Host1x(Core::System& system_) 11Host1x::Host1x(Core::System& system_)
12 : system{system_}, syncpoint_manager{}, memory_manager{system, 32, 12}, 12 : system{system_}, syncpoint_manager{},
13 memory_manager(system.DeviceMemory()), gmmu_manager{system, memory_manager, 32, 12},
13 allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {} 14 allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {}
14 15
16Host1x::~Host1x() = default;
17
15} // namespace Host1x 18} // namespace Host1x
16 19
17} // namespace Tegra 20} // namespace Tegra
diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h
index 57082ae54..d72d97b7b 100644
--- a/src/video_core/host1x/host1x.h
+++ b/src/video_core/host1x/host1x.h
@@ -6,6 +6,7 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7 7
8#include "common/address_space.h" 8#include "common/address_space.h"
9#include "video_core/host1x/gpu_device_memory_manager.h"
9#include "video_core/host1x/syncpoint_manager.h" 10#include "video_core/host1x/syncpoint_manager.h"
10#include "video_core/memory_manager.h" 11#include "video_core/memory_manager.h"
11 12
@@ -20,6 +21,7 @@ namespace Host1x {
20class Host1x { 21class Host1x {
21public: 22public:
22 explicit Host1x(Core::System& system); 23 explicit Host1x(Core::System& system);
24 ~Host1x();
23 25
24 SyncpointManager& GetSyncpointManager() { 26 SyncpointManager& GetSyncpointManager() {
25 return syncpoint_manager; 27 return syncpoint_manager;
@@ -29,14 +31,22 @@ public:
29 return syncpoint_manager; 31 return syncpoint_manager;
30 } 32 }
31 33
32 Tegra::MemoryManager& MemoryManager() { 34 Tegra::MaxwellDeviceMemoryManager& MemoryManager() {
33 return memory_manager; 35 return memory_manager;
34 } 36 }
35 37
36 const Tegra::MemoryManager& MemoryManager() const { 38 const Tegra::MaxwellDeviceMemoryManager& MemoryManager() const {
37 return memory_manager; 39 return memory_manager;
38 } 40 }
39 41
42 Tegra::MemoryManager& GMMU() {
43 return gmmu_manager;
44 }
45
46 const Tegra::MemoryManager& GMMU() const {
47 return gmmu_manager;
48 }
49
40 Common::FlatAllocator<u32, 0, 32>& Allocator() { 50 Common::FlatAllocator<u32, 0, 32>& Allocator() {
41 return *allocator; 51 return *allocator;
42 } 52 }
@@ -48,7 +58,8 @@ public:
48private: 58private:
49 Core::System& system; 59 Core::System& system;
50 SyncpointManager syncpoint_manager; 60 SyncpointManager syncpoint_manager;
51 Tegra::MemoryManager memory_manager; 61 Tegra::MaxwellDeviceMemoryManager memory_manager;
62 Tegra::MemoryManager gmmu_manager;
52 std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator; 63 std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator;
53}; 64};
54 65
diff --git a/src/video_core/host1x/vic.cpp b/src/video_core/host1x/vic.cpp
index 2a5eba415..d154746af 100644
--- a/src/video_core/host1x/vic.cpp
+++ b/src/video_core/host1x/vic.cpp
@@ -81,7 +81,7 @@ void Vic::Execute() {
81 LOG_ERROR(Service_NVDRV, "VIC Luma address not set."); 81 LOG_ERROR(Service_NVDRV, "VIC Luma address not set.");
82 return; 82 return;
83 } 83 }
84 const VicConfig config{host1x.MemoryManager().Read<u64>(config_struct_address + 0x20)}; 84 const VicConfig config{host1x.GMMU().Read<u64>(config_struct_address + 0x20)};
85 auto frame = nvdec_processor->GetFrame(); 85 auto frame = nvdec_processor->GetFrame();
86 if (!frame) { 86 if (!frame) {
87 return; 87 return;
@@ -162,12 +162,12 @@ void Vic::WriteRGBFrame(std::unique_ptr<FFmpeg::Frame> frame, const VicConfig& c
162 Texture::SwizzleSubrect(luma_buffer, frame_buff, 4, width, height, 1, 0, 0, width, height, 162 Texture::SwizzleSubrect(luma_buffer, frame_buff, 4, width, height, 1, 0, 0, width, height,
163 block_height, 0, width * 4); 163 block_height, 0, width * 4);
164 164
165 host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); 165 host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
166 } else { 166 } else {
167 // send pitch linear frame 167 // send pitch linear frame
168 const size_t linear_size = width * height * 4; 168 const size_t linear_size = width * height * 4;
169 host1x.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr, 169 host1x.GMMU().WriteBlock(output_surface_luma_address, converted_frame_buf_addr,
170 linear_size); 170 linear_size);
171 } 171 }
172} 172}
173 173
@@ -193,8 +193,7 @@ void Vic::WriteYUVFrame(std::unique_ptr<FFmpeg::Frame> frame, const VicConfig& c
193 const std::size_t dst = y * aligned_width; 193 const std::size_t dst = y * aligned_width;
194 std::memcpy(luma_buffer.data() + dst, luma_src + src, frame_width); 194 std::memcpy(luma_buffer.data() + dst, luma_src + src, frame_width);
195 } 195 }
196 host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), 196 host1x.GMMU().WriteBlock(output_surface_luma_address, luma_buffer.data(), luma_buffer.size());
197 luma_buffer.size());
198 197
199 // Chroma 198 // Chroma
200 const std::size_t half_height = frame_height / 2; 199 const std::size_t half_height = frame_height / 2;
@@ -233,8 +232,8 @@ void Vic::WriteYUVFrame(std::unique_ptr<FFmpeg::Frame> frame, const VicConfig& c
233 ASSERT(false); 232 ASSERT(false);
234 break; 233 break;
235 } 234 }
236 host1x.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(), 235 host1x.GMMU().WriteBlock(output_surface_chroma_address, chroma_buffer.data(),
237 chroma_buffer.size()); 236 chroma_buffer.size());
238} 237}
239 238
240} // namespace Host1x 239} // namespace Host1x
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index d16040613..a52f8e486 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -7,25 +7,26 @@
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/device_memory.h"
11#include "core/hle/kernel/k_page_table.h" 10#include "core/hle/kernel/k_page_table.h"
12#include "core/hle/kernel/k_process.h" 11#include "core/hle/kernel/k_process.h"
12#include "video_core/guest_memory.h"
13#include "video_core/host1x/host1x.h"
13#include "video_core/invalidation_accumulator.h" 14#include "video_core/invalidation_accumulator.h"
14#include "video_core/memory_manager.h" 15#include "video_core/memory_manager.h"
15#include "video_core/rasterizer_interface.h" 16#include "video_core/rasterizer_interface.h"
16#include "video_core/renderer_base.h" 17#include "video_core/renderer_base.h"
17 18
18namespace Tegra { 19namespace Tegra {
19using Core::Memory::GuestMemoryFlags; 20using Tegra::Memory::GuestMemoryFlags;
20 21
21std::atomic<size_t> MemoryManager::unique_identifier_generator{}; 22std::atomic<size_t> MemoryManager::unique_identifier_generator{};
22 23
23MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_, 24MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
24 u64 page_bits_) 25 u64 address_space_bits_, u64 big_page_bits_, u64 page_bits_)
25 : system{system_}, memory{system.ApplicationMemory()}, device_memory{system.DeviceMemory()}, 26 : system{system_}, memory{memory_}, address_space_bits{address_space_bits_},
26 address_space_bits{address_space_bits_}, page_bits{page_bits_}, big_page_bits{big_page_bits_}, 27 page_bits{page_bits_}, big_page_bits{big_page_bits_}, entries{}, big_entries{},
27 entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38, 28 page_table{address_space_bits, address_space_bits + page_bits - 38,
28 page_bits != big_page_bits ? page_bits : 0}, 29 page_bits != big_page_bits ? page_bits : 0},
29 kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add( 30 kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add(
30 1, std::memory_order_acq_rel)}, 31 1, std::memory_order_acq_rel)},
31 accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} { 32 accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} {
@@ -42,11 +43,16 @@ MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64
42 big_page_table_mask = big_page_table_size - 1; 43 big_page_table_mask = big_page_table_size - 1;
43 44
44 big_entries.resize(big_page_table_size / 32, 0); 45 big_entries.resize(big_page_table_size / 32, 0);
45 big_page_table_cpu.resize(big_page_table_size); 46 big_page_table_dev.resize(big_page_table_size);
46 big_page_continuous.resize(big_page_table_size / continuous_bits, 0); 47 big_page_continuous.resize(big_page_table_size / continuous_bits, 0);
47 entries.resize(page_table_size / 32, 0); 48 entries.resize(page_table_size / 32, 0);
48} 49}
49 50
51MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_,
52 u64 page_bits_)
53 : MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, big_page_bits_,
54 page_bits_) {}
55
50MemoryManager::~MemoryManager() = default; 56MemoryManager::~MemoryManager() = default;
51 57
52template <bool is_big_page> 58template <bool is_big_page>
@@ -100,7 +106,7 @@ inline void MemoryManager::SetBigPageContinuous(size_t big_page_index, bool valu
100} 106}
101 107
102template <MemoryManager::EntryType entry_type> 108template <MemoryManager::EntryType entry_type>
103GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size, 109GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, size_t size,
104 PTEKind kind) { 110 PTEKind kind) {
105 [[maybe_unused]] u64 remaining_size{size}; 111 [[maybe_unused]] u64 remaining_size{size};
106 if constexpr (entry_type == EntryType::Mapped) { 112 if constexpr (entry_type == EntryType::Mapped) {
@@ -114,9 +120,9 @@ GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cp
114 rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, page_size); 120 rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, page_size);
115 } 121 }
116 if constexpr (entry_type == EntryType::Mapped) { 122 if constexpr (entry_type == EntryType::Mapped) {
117 const VAddr current_cpu_addr = cpu_addr + offset; 123 const DAddr current_dev_addr = dev_addr + offset;
118 const auto index = PageEntryIndex<false>(current_gpu_addr); 124 const auto index = PageEntryIndex<false>(current_gpu_addr);
119 const u32 sub_value = static_cast<u32>(current_cpu_addr >> cpu_page_bits); 125 const u32 sub_value = static_cast<u32>(current_dev_addr >> cpu_page_bits);
120 page_table[index] = sub_value; 126 page_table[index] = sub_value;
121 } 127 }
122 remaining_size -= page_size; 128 remaining_size -= page_size;
@@ -126,7 +132,7 @@ GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cp
126} 132}
127 133
128template <MemoryManager::EntryType entry_type> 134template <MemoryManager::EntryType entry_type>
129GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, 135GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr,
130 size_t size, PTEKind kind) { 136 size_t size, PTEKind kind) {
131 [[maybe_unused]] u64 remaining_size{size}; 137 [[maybe_unused]] u64 remaining_size{size};
132 for (u64 offset{}; offset < size; offset += big_page_size) { 138 for (u64 offset{}; offset < size; offset += big_page_size) {
@@ -137,20 +143,20 @@ GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr
137 rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, big_page_size); 143 rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, big_page_size);
138 } 144 }
139 if constexpr (entry_type == EntryType::Mapped) { 145 if constexpr (entry_type == EntryType::Mapped) {
140 const VAddr current_cpu_addr = cpu_addr + offset; 146 const DAddr current_dev_addr = dev_addr + offset;
141 const auto index = PageEntryIndex<true>(current_gpu_addr); 147 const auto index = PageEntryIndex<true>(current_gpu_addr);
142 const u32 sub_value = static_cast<u32>(current_cpu_addr >> cpu_page_bits); 148 const u32 sub_value = static_cast<u32>(current_dev_addr >> cpu_page_bits);
143 big_page_table_cpu[index] = sub_value; 149 big_page_table_dev[index] = sub_value;
144 const bool is_continuous = ([&] { 150 const bool is_continuous = ([&] {
145 uintptr_t base_ptr{ 151 uintptr_t base_ptr{
146 reinterpret_cast<uintptr_t>(memory.GetPointerSilent(current_cpu_addr))}; 152 reinterpret_cast<uintptr_t>(memory.GetPointer<u8>(current_dev_addr))};
147 if (base_ptr == 0) { 153 if (base_ptr == 0) {
148 return false; 154 return false;
149 } 155 }
150 for (VAddr start_cpu = current_cpu_addr + page_size; 156 for (DAddr start_cpu = current_dev_addr + page_size;
151 start_cpu < current_cpu_addr + big_page_size; start_cpu += page_size) { 157 start_cpu < current_dev_addr + big_page_size; start_cpu += page_size) {
152 base_ptr += page_size; 158 base_ptr += page_size;
153 auto next_ptr = reinterpret_cast<uintptr_t>(memory.GetPointerSilent(start_cpu)); 159 auto next_ptr = reinterpret_cast<uintptr_t>(memory.GetPointer<u8>(start_cpu));
154 if (next_ptr == 0 || base_ptr != next_ptr) { 160 if (next_ptr == 0 || base_ptr != next_ptr) {
155 return false; 161 return false;
156 } 162 }
@@ -172,12 +178,12 @@ void MemoryManager::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_)
172 rasterizer = rasterizer_; 178 rasterizer = rasterizer_;
173} 179}
174 180
175GPUVAddr MemoryManager::Map(GPUVAddr gpu_addr, VAddr cpu_addr, std::size_t size, PTEKind kind, 181GPUVAddr MemoryManager::Map(GPUVAddr gpu_addr, DAddr dev_addr, std::size_t size, PTEKind kind,
176 bool is_big_pages) { 182 bool is_big_pages) {
177 if (is_big_pages) [[likely]] { 183 if (is_big_pages) [[likely]] {
178 return BigPageTableOp<EntryType::Mapped>(gpu_addr, cpu_addr, size, kind); 184 return BigPageTableOp<EntryType::Mapped>(gpu_addr, dev_addr, size, kind);
179 } 185 }
180 return PageTableOp<EntryType::Mapped>(gpu_addr, cpu_addr, size, kind); 186 return PageTableOp<EntryType::Mapped>(gpu_addr, dev_addr, size, kind);
181} 187}
182 188
183GPUVAddr MemoryManager::MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages) { 189GPUVAddr MemoryManager::MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages) {
@@ -202,7 +208,7 @@ void MemoryManager::Unmap(GPUVAddr gpu_addr, std::size_t size) {
202 PageTableOp<EntryType::Free>(gpu_addr, 0, size, PTEKind::INVALID); 208 PageTableOp<EntryType::Free>(gpu_addr, 0, size, PTEKind::INVALID);
203} 209}
204 210
205std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const { 211std::optional<DAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const {
206 if (!IsWithinGPUAddressRange(gpu_addr)) [[unlikely]] { 212 if (!IsWithinGPUAddressRange(gpu_addr)) [[unlikely]] {
207 return std::nullopt; 213 return std::nullopt;
208 } 214 }
@@ -211,17 +217,17 @@ std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const {
211 return std::nullopt; 217 return std::nullopt;
212 } 218 }
213 219
214 const VAddr cpu_addr_base = static_cast<VAddr>(page_table[PageEntryIndex<false>(gpu_addr)]) 220 const DAddr dev_addr_base = static_cast<DAddr>(page_table[PageEntryIndex<false>(gpu_addr)])
215 << cpu_page_bits; 221 << cpu_page_bits;
216 return cpu_addr_base + (gpu_addr & page_mask); 222 return dev_addr_base + (gpu_addr & page_mask);
217 } 223 }
218 224
219 const VAddr cpu_addr_base = 225 const DAddr dev_addr_base =
220 static_cast<VAddr>(big_page_table_cpu[PageEntryIndex<true>(gpu_addr)]) << cpu_page_bits; 226 static_cast<DAddr>(big_page_table_dev[PageEntryIndex<true>(gpu_addr)]) << cpu_page_bits;
221 return cpu_addr_base + (gpu_addr & big_page_mask); 227 return dev_addr_base + (gpu_addr & big_page_mask);
222} 228}
223 229
224std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr, std::size_t size) const { 230std::optional<DAddr> MemoryManager::GpuToCpuAddress(GPUVAddr addr, std::size_t size) const {
225 size_t page_index{addr >> page_bits}; 231 size_t page_index{addr >> page_bits};
226 const size_t page_last{(addr + size + page_size - 1) >> page_bits}; 232 const size_t page_last{(addr + size + page_size - 1) >> page_bits};
227 while (page_index < page_last) { 233 while (page_index < page_last) {
@@ -274,7 +280,7 @@ u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) {
274 return {}; 280 return {};
275 } 281 }
276 282
277 return memory.GetPointer(*address); 283 return memory.GetPointer<u8>(*address);
278} 284}
279 285
280const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const { 286const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const {
@@ -283,7 +289,7 @@ const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const {
283 return {}; 289 return {};
284 } 290 }
285 291
286 return memory.GetPointer(*address); 292 return memory.GetPointer<u8>(*address);
287} 293}
288 294
289#ifdef _MSC_VER // no need for gcc / clang but msvc's compiler is more conservative with inlining. 295#ifdef _MSC_VER // no need for gcc / clang but msvc's compiler is more conservative with inlining.
@@ -367,25 +373,25 @@ void MemoryManager::ReadBlockImpl(GPUVAddr gpu_src_addr, void* dest_buffer, std:
367 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; 373 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
368 }; 374 };
369 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 375 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
370 const VAddr cpu_addr_base = 376 const DAddr dev_addr_base =
371 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 377 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
372 if constexpr (is_safe) { 378 if constexpr (is_safe) {
373 rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); 379 rasterizer->FlushRegion(dev_addr_base, copy_amount, which);
374 } 380 }
375 u8* physical = memory.GetPointer(cpu_addr_base); 381 u8* physical = memory.GetPointer<u8>(dev_addr_base);
376 std::memcpy(dest_buffer, physical, copy_amount); 382 std::memcpy(dest_buffer, physical, copy_amount);
377 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; 383 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
378 }; 384 };
379 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 385 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
380 const VAddr cpu_addr_base = 386 const DAddr dev_addr_base =
381 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 387 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
382 if constexpr (is_safe) { 388 if constexpr (is_safe) {
383 rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); 389 rasterizer->FlushRegion(dev_addr_base, copy_amount, which);
384 } 390 }
385 if (!IsBigPageContinuous(page_index)) [[unlikely]] { 391 if (!IsBigPageContinuous(page_index)) [[unlikely]] {
386 memory.ReadBlockUnsafe(cpu_addr_base, dest_buffer, copy_amount); 392 memory.ReadBlockUnsafe(dev_addr_base, dest_buffer, copy_amount);
387 } else { 393 } else {
388 u8* physical = memory.GetPointer(cpu_addr_base); 394 u8* physical = memory.GetPointer<u8>(dev_addr_base);
389 std::memcpy(dest_buffer, physical, copy_amount); 395 std::memcpy(dest_buffer, physical, copy_amount);
390 } 396 }
391 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; 397 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
@@ -416,25 +422,25 @@ void MemoryManager::WriteBlockImpl(GPUVAddr gpu_dest_addr, const void* src_buffe
416 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; 422 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
417 }; 423 };
418 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 424 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
419 const VAddr cpu_addr_base = 425 const DAddr dev_addr_base =
420 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 426 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
421 if constexpr (is_safe) { 427 if constexpr (is_safe) {
422 rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); 428 rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which);
423 } 429 }
424 u8* physical = memory.GetPointer(cpu_addr_base); 430 u8* physical = memory.GetPointer<u8>(dev_addr_base);
425 std::memcpy(physical, src_buffer, copy_amount); 431 std::memcpy(physical, src_buffer, copy_amount);
426 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; 432 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
427 }; 433 };
428 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 434 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
429 const VAddr cpu_addr_base = 435 const DAddr dev_addr_base =
430 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 436 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
431 if constexpr (is_safe) { 437 if constexpr (is_safe) {
432 rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); 438 rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which);
433 } 439 }
434 if (!IsBigPageContinuous(page_index)) [[unlikely]] { 440 if (!IsBigPageContinuous(page_index)) [[unlikely]] {
435 memory.WriteBlockUnsafe(cpu_addr_base, src_buffer, copy_amount); 441 memory.WriteBlockUnsafe(dev_addr_base, src_buffer, copy_amount);
436 } else { 442 } else {
437 u8* physical = memory.GetPointer(cpu_addr_base); 443 u8* physical = memory.GetPointer<u8>(dev_addr_base);
438 std::memcpy(physical, src_buffer, copy_amount); 444 std::memcpy(physical, src_buffer, copy_amount);
439 } 445 }
440 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; 446 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
@@ -470,14 +476,14 @@ void MemoryManager::FlushRegion(GPUVAddr gpu_addr, size_t size,
470 [[maybe_unused]] std::size_t copy_amount) {}; 476 [[maybe_unused]] std::size_t copy_amount) {};
471 477
472 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 478 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
473 const VAddr cpu_addr_base = 479 const DAddr dev_addr_base =
474 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 480 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
475 rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); 481 rasterizer->FlushRegion(dev_addr_base, copy_amount, which);
476 }; 482 };
477 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 483 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
478 const VAddr cpu_addr_base = 484 const DAddr dev_addr_base =
479 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 485 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
480 rasterizer->FlushRegion(cpu_addr_base, copy_amount, which); 486 rasterizer->FlushRegion(dev_addr_base, copy_amount, which);
481 }; 487 };
482 auto flush_short_pages = [&](std::size_t page_index, std::size_t offset, 488 auto flush_short_pages = [&](std::size_t page_index, std::size_t offset,
483 std::size_t copy_amount) { 489 std::size_t copy_amount) {
@@ -495,15 +501,15 @@ bool MemoryManager::IsMemoryDirty(GPUVAddr gpu_addr, size_t size,
495 [[maybe_unused]] std::size_t copy_amount) { return false; }; 501 [[maybe_unused]] std::size_t copy_amount) { return false; };
496 502
497 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 503 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
498 const VAddr cpu_addr_base = 504 const DAddr dev_addr_base =
499 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 505 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
500 result |= rasterizer->MustFlushRegion(cpu_addr_base, copy_amount, which); 506 result |= rasterizer->MustFlushRegion(dev_addr_base, copy_amount, which);
501 return result; 507 return result;
502 }; 508 };
503 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 509 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
504 const VAddr cpu_addr_base = 510 const DAddr dev_addr_base =
505 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 511 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
506 result |= rasterizer->MustFlushRegion(cpu_addr_base, copy_amount, which); 512 result |= rasterizer->MustFlushRegion(dev_addr_base, copy_amount, which);
507 return result; 513 return result;
508 }; 514 };
509 auto check_short_pages = [&](std::size_t page_index, std::size_t offset, 515 auto check_short_pages = [&](std::size_t page_index, std::size_t offset,
@@ -517,7 +523,7 @@ bool MemoryManager::IsMemoryDirty(GPUVAddr gpu_addr, size_t size,
517} 523}
518 524
519size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const { 525size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const {
520 std::optional<VAddr> old_page_addr{}; 526 std::optional<DAddr> old_page_addr{};
521 size_t range_so_far = 0; 527 size_t range_so_far = 0;
522 bool result{false}; 528 bool result{false};
523 auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, 529 auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset,
@@ -526,24 +532,24 @@ size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const {
526 return true; 532 return true;
527 }; 533 };
528 auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 534 auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
529 const VAddr cpu_addr_base = 535 const DAddr dev_addr_base =
530 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 536 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
531 if (old_page_addr && *old_page_addr != cpu_addr_base) { 537 if (old_page_addr && *old_page_addr != dev_addr_base) {
532 result = true; 538 result = true;
533 return true; 539 return true;
534 } 540 }
535 range_so_far += copy_amount; 541 range_so_far += copy_amount;
536 old_page_addr = {cpu_addr_base + copy_amount}; 542 old_page_addr = {dev_addr_base + copy_amount};
537 return false; 543 return false;
538 }; 544 };
539 auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 545 auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
540 const VAddr cpu_addr_base = 546 const DAddr dev_addr_base =
541 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 547 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
542 if (old_page_addr && *old_page_addr != cpu_addr_base) { 548 if (old_page_addr && *old_page_addr != dev_addr_base) {
543 return true; 549 return true;
544 } 550 }
545 range_so_far += copy_amount; 551 range_so_far += copy_amount;
546 old_page_addr = {cpu_addr_base + copy_amount}; 552 old_page_addr = {dev_addr_base + copy_amount};
547 return false; 553 return false;
548 }; 554 };
549 auto check_short_pages = [&](std::size_t page_index, std::size_t offset, 555 auto check_short_pages = [&](std::size_t page_index, std::size_t offset,
@@ -568,14 +574,14 @@ void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size,
568 [[maybe_unused]] std::size_t copy_amount) {}; 574 [[maybe_unused]] std::size_t copy_amount) {};
569 575
570 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 576 auto mapped_normal = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
571 const VAddr cpu_addr_base = 577 const DAddr dev_addr_base =
572 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 578 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
573 rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); 579 rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which);
574 }; 580 };
575 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 581 auto mapped_big = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
576 const VAddr cpu_addr_base = 582 const DAddr dev_addr_base =
577 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 583 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
578 rasterizer->InvalidateRegion(cpu_addr_base, copy_amount, which); 584 rasterizer->InvalidateRegion(dev_addr_base, copy_amount, which);
579 }; 585 };
580 auto invalidate_short_pages = [&](std::size_t page_index, std::size_t offset, 586 auto invalidate_short_pages = [&](std::size_t page_index, std::size_t offset,
581 std::size_t copy_amount) { 587 std::size_t copy_amount) {
@@ -587,7 +593,7 @@ void MemoryManager::InvalidateRegion(GPUVAddr gpu_addr, size_t size,
587 593
588void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size, 594void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size,
589 VideoCommon::CacheType which) { 595 VideoCommon::CacheType which) {
590 Core::Memory::GpuGuestMemoryScoped<u8, GuestMemoryFlags::SafeReadWrite> data( 596 Tegra::Memory::GpuGuestMemoryScoped<u8, GuestMemoryFlags::SafeReadWrite> data(
591 *this, gpu_src_addr, size); 597 *this, gpu_src_addr, size);
592 data.SetAddressAndSize(gpu_dest_addr, size); 598 data.SetAddressAndSize(gpu_dest_addr, size);
593 FlushRegion(gpu_dest_addr, size, which); 599 FlushRegion(gpu_dest_addr, size, which);
@@ -600,18 +606,18 @@ bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const {
600 const std::size_t page{(page_index & big_page_mask) + size}; 606 const std::size_t page{(page_index & big_page_mask) + size};
601 return page <= big_page_size; 607 return page <= big_page_size;
602 } 608 }
603 const std::size_t page{(gpu_addr & Core::Memory::YUZU_PAGEMASK) + size}; 609 const std::size_t page{(gpu_addr & Core::DEVICE_PAGEMASK) + size};
604 return page <= Core::Memory::YUZU_PAGESIZE; 610 return page <= Core::DEVICE_PAGESIZE;
605 } 611 }
606 if (GetEntry<false>(gpu_addr) != EntryType::Mapped) { 612 if (GetEntry<false>(gpu_addr) != EntryType::Mapped) {
607 return false; 613 return false;
608 } 614 }
609 const std::size_t page{(gpu_addr & Core::Memory::YUZU_PAGEMASK) + size}; 615 const std::size_t page{(gpu_addr & Core::DEVICE_PAGEMASK) + size};
610 return page <= Core::Memory::YUZU_PAGESIZE; 616 return page <= Core::DEVICE_PAGESIZE;
611} 617}
612 618
613bool MemoryManager::IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const { 619bool MemoryManager::IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const {
614 std::optional<VAddr> old_page_addr{}; 620 std::optional<DAddr> old_page_addr{};
615 bool result{true}; 621 bool result{true};
616 auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset, 622 auto fail = [&]([[maybe_unused]] std::size_t page_index, [[maybe_unused]] std::size_t offset,
617 std::size_t copy_amount) { 623 std::size_t copy_amount) {
@@ -619,23 +625,23 @@ bool MemoryManager::IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const
619 return true; 625 return true;
620 }; 626 };
621 auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 627 auto short_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
622 const VAddr cpu_addr_base = 628 const DAddr dev_addr_base =
623 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 629 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
624 if (old_page_addr && *old_page_addr != cpu_addr_base) { 630 if (old_page_addr && *old_page_addr != dev_addr_base) {
625 result = false; 631 result = false;
626 return true; 632 return true;
627 } 633 }
628 old_page_addr = {cpu_addr_base + copy_amount}; 634 old_page_addr = {dev_addr_base + copy_amount};
629 return false; 635 return false;
630 }; 636 };
631 auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) { 637 auto big_check = [&](std::size_t page_index, std::size_t offset, std::size_t copy_amount) {
632 const VAddr cpu_addr_base = 638 const DAddr dev_addr_base =
633 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 639 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
634 if (old_page_addr && *old_page_addr != cpu_addr_base) { 640 if (old_page_addr && *old_page_addr != dev_addr_base) {
635 result = false; 641 result = false;
636 return true; 642 return true;
637 } 643 }
638 old_page_addr = {cpu_addr_base + copy_amount}; 644 old_page_addr = {dev_addr_base + copy_amount};
639 return false; 645 return false;
640 }; 646 };
641 auto check_short_pages = [&](std::size_t page_index, std::size_t offset, 647 auto check_short_pages = [&](std::size_t page_index, std::size_t offset,
@@ -678,11 +684,11 @@ template <bool is_gpu_address>
678void MemoryManager::GetSubmappedRangeImpl( 684void MemoryManager::GetSubmappedRangeImpl(
679 GPUVAddr gpu_addr, std::size_t size, 685 GPUVAddr gpu_addr, std::size_t size,
680 boost::container::small_vector< 686 boost::container::small_vector<
681 std::pair<std::conditional_t<is_gpu_address, GPUVAddr, VAddr>, std::size_t>, 32>& result) 687 std::pair<std::conditional_t<is_gpu_address, GPUVAddr, DAddr>, std::size_t>, 32>& result)
682 const { 688 const {
683 std::optional<std::pair<std::conditional_t<is_gpu_address, GPUVAddr, VAddr>, std::size_t>> 689 std::optional<std::pair<std::conditional_t<is_gpu_address, GPUVAddr, DAddr>, std::size_t>>
684 last_segment{}; 690 last_segment{};
685 std::optional<VAddr> old_page_addr{}; 691 std::optional<DAddr> old_page_addr{};
686 const auto split = [&last_segment, &result]([[maybe_unused]] std::size_t page_index, 692 const auto split = [&last_segment, &result]([[maybe_unused]] std::size_t page_index,
687 [[maybe_unused]] std::size_t offset, 693 [[maybe_unused]] std::size_t offset,
688 [[maybe_unused]] std::size_t copy_amount) { 694 [[maybe_unused]] std::size_t copy_amount) {
@@ -694,20 +700,20 @@ void MemoryManager::GetSubmappedRangeImpl(
694 const auto extend_size_big = [this, &split, &old_page_addr, 700 const auto extend_size_big = [this, &split, &old_page_addr,
695 &last_segment](std::size_t page_index, std::size_t offset, 701 &last_segment](std::size_t page_index, std::size_t offset,
696 std::size_t copy_amount) { 702 std::size_t copy_amount) {
697 const VAddr cpu_addr_base = 703 const DAddr dev_addr_base =
698 (static_cast<VAddr>(big_page_table_cpu[page_index]) << cpu_page_bits) + offset; 704 (static_cast<DAddr>(big_page_table_dev[page_index]) << cpu_page_bits) + offset;
699 if (old_page_addr) { 705 if (old_page_addr) {
700 if (*old_page_addr != cpu_addr_base) { 706 if (*old_page_addr != dev_addr_base) {
701 split(0, 0, 0); 707 split(0, 0, 0);
702 } 708 }
703 } 709 }
704 old_page_addr = {cpu_addr_base + copy_amount}; 710 old_page_addr = {dev_addr_base + copy_amount};
705 if (!last_segment) { 711 if (!last_segment) {
706 if constexpr (is_gpu_address) { 712 if constexpr (is_gpu_address) {
707 const GPUVAddr new_base_addr = (page_index << big_page_bits) + offset; 713 const GPUVAddr new_base_addr = (page_index << big_page_bits) + offset;
708 last_segment = {new_base_addr, copy_amount}; 714 last_segment = {new_base_addr, copy_amount};
709 } else { 715 } else {
710 last_segment = {cpu_addr_base, copy_amount}; 716 last_segment = {dev_addr_base, copy_amount};
711 } 717 }
712 } else { 718 } else {
713 last_segment->second += copy_amount; 719 last_segment->second += copy_amount;
@@ -716,20 +722,20 @@ void MemoryManager::GetSubmappedRangeImpl(
716 const auto extend_size_short = [this, &split, &old_page_addr, 722 const auto extend_size_short = [this, &split, &old_page_addr,
717 &last_segment](std::size_t page_index, std::size_t offset, 723 &last_segment](std::size_t page_index, std::size_t offset,
718 std::size_t copy_amount) { 724 std::size_t copy_amount) {
719 const VAddr cpu_addr_base = 725 const DAddr dev_addr_base =
720 (static_cast<VAddr>(page_table[page_index]) << cpu_page_bits) + offset; 726 (static_cast<DAddr>(page_table[page_index]) << cpu_page_bits) + offset;
721 if (old_page_addr) { 727 if (old_page_addr) {
722 if (*old_page_addr != cpu_addr_base) { 728 if (*old_page_addr != dev_addr_base) {
723 split(0, 0, 0); 729 split(0, 0, 0);
724 } 730 }
725 } 731 }
726 old_page_addr = {cpu_addr_base + copy_amount}; 732 old_page_addr = {dev_addr_base + copy_amount};
727 if (!last_segment) { 733 if (!last_segment) {
728 if constexpr (is_gpu_address) { 734 if constexpr (is_gpu_address) {
729 const GPUVAddr new_base_addr = (page_index << page_bits) + offset; 735 const GPUVAddr new_base_addr = (page_index << page_bits) + offset;
730 last_segment = {new_base_addr, copy_amount}; 736 last_segment = {new_base_addr, copy_amount};
731 } else { 737 } else {
732 last_segment = {cpu_addr_base, copy_amount}; 738 last_segment = {dev_addr_base, copy_amount};
733 } 739 }
734 } else { 740 } else {
735 last_segment->second += copy_amount; 741 last_segment->second += copy_amount;
@@ -756,9 +762,12 @@ void MemoryManager::FlushCaching() {
756} 762}
757 763
758const u8* MemoryManager::GetSpan(const GPUVAddr src_addr, const std::size_t size) const { 764const u8* MemoryManager::GetSpan(const GPUVAddr src_addr, const std::size_t size) const {
759 auto cpu_addr = GpuToCpuAddress(src_addr); 765 if (!IsContinuousRange(src_addr, size)) {
760 if (cpu_addr) { 766 return nullptr;
761 return memory.GetSpan(*cpu_addr, size); 767 }
768 auto dev_addr = GpuToCpuAddress(src_addr);
769 if (dev_addr) {
770 return memory.GetSpan(*dev_addr, size);
762 } 771 }
763 return nullptr; 772 return nullptr;
764} 773}
@@ -767,9 +776,9 @@ u8* MemoryManager::GetSpan(const GPUVAddr src_addr, const std::size_t size) {
767 if (!IsContinuousRange(src_addr, size)) { 776 if (!IsContinuousRange(src_addr, size)) {
768 return nullptr; 777 return nullptr;
769 } 778 }
770 auto cpu_addr = GpuToCpuAddress(src_addr); 779 auto dev_addr = GpuToCpuAddress(src_addr);
771 if (cpu_addr) { 780 if (dev_addr) {
772 return memory.GetSpan(*cpu_addr, size); 781 return memory.GetSpan(*dev_addr, size);
773 } 782 }
774 return nullptr; 783 return nullptr;
775} 784}
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index 9b311b9e5..c5255f36c 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -15,8 +15,8 @@
15#include "common/range_map.h" 15#include "common/range_map.h"
16#include "common/scratch_buffer.h" 16#include "common/scratch_buffer.h"
17#include "common/virtual_buffer.h" 17#include "common/virtual_buffer.h"
18#include "core/memory.h"
19#include "video_core/cache_types.h" 18#include "video_core/cache_types.h"
19#include "video_core/host1x/gpu_device_memory_manager.h"
20#include "video_core/pte_kind.h" 20#include "video_core/pte_kind.h"
21 21
22namespace VideoCore { 22namespace VideoCore {
@@ -28,10 +28,6 @@ class InvalidationAccumulator;
28} 28}
29 29
30namespace Core { 30namespace Core {
31class DeviceMemory;
32namespace Memory {
33class Memory;
34} // namespace Memory
35class System; 31class System;
36} // namespace Core 32} // namespace Core
37 33
@@ -41,6 +37,9 @@ class MemoryManager final {
41public: 37public:
42 explicit MemoryManager(Core::System& system_, u64 address_space_bits_ = 40, 38 explicit MemoryManager(Core::System& system_, u64 address_space_bits_ = 40,
43 u64 big_page_bits_ = 16, u64 page_bits_ = 12); 39 u64 big_page_bits_ = 16, u64 page_bits_ = 12);
40 explicit MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
41 u64 address_space_bits_ = 40, u64 big_page_bits_ = 16,
42 u64 page_bits_ = 12);
44 ~MemoryManager(); 43 ~MemoryManager();
45 44
46 size_t GetID() const { 45 size_t GetID() const {
@@ -50,9 +49,9 @@ public:
50 /// Binds a renderer to the memory manager. 49 /// Binds a renderer to the memory manager.
51 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); 50 void BindRasterizer(VideoCore::RasterizerInterface* rasterizer);
52 51
53 [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr) const; 52 [[nodiscard]] std::optional<DAddr> GpuToCpuAddress(GPUVAddr addr) const;
54 53
55 [[nodiscard]] std::optional<VAddr> GpuToCpuAddress(GPUVAddr addr, std::size_t size) const; 54 [[nodiscard]] std::optional<DAddr> GpuToCpuAddress(GPUVAddr addr, std::size_t size) const;
56 55
57 template <typename T> 56 template <typename T>
58 [[nodiscard]] T Read(GPUVAddr addr) const; 57 [[nodiscard]] T Read(GPUVAddr addr) const;
@@ -69,7 +68,7 @@ public:
69 if (!address) { 68 if (!address) {
70 return {}; 69 return {};
71 } 70 }
72 return memory.GetPointer(*address); 71 return memory.GetPointer<T>(*address);
73 } 72 }
74 73
75 template <typename T> 74 template <typename T>
@@ -110,7 +109,7 @@ public:
110 [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const; 109 [[nodiscard]] bool IsGranularRange(GPUVAddr gpu_addr, std::size_t size) const;
111 110
112 /** 111 /**
113 * Checks if a gpu region is mapped by a single range of cpu addresses. 112 * Checks if a gpu region is mapped by a single range of device addresses.
114 */ 113 */
115 [[nodiscard]] bool IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const; 114 [[nodiscard]] bool IsContinuousRange(GPUVAddr gpu_addr, std::size_t size) const;
116 115
@@ -120,14 +119,14 @@ public:
120 [[nodiscard]] bool IsFullyMappedRange(GPUVAddr gpu_addr, std::size_t size) const; 119 [[nodiscard]] bool IsFullyMappedRange(GPUVAddr gpu_addr, std::size_t size) const;
121 120
122 /** 121 /**
123 * Returns a vector with all the subranges of cpu addresses mapped beneath. 122 * Returns a vector with all the subranges of device addresses mapped beneath.
124 * if the region is continuous, a single pair will be returned. If it's unmapped, an empty 123 * if the region is continuous, a single pair will be returned. If it's unmapped, an empty
125 * vector will be returned; 124 * vector will be returned;
126 */ 125 */
127 boost::container::small_vector<std::pair<GPUVAddr, std::size_t>, 32> GetSubmappedRange( 126 boost::container::small_vector<std::pair<GPUVAddr, std::size_t>, 32> GetSubmappedRange(
128 GPUVAddr gpu_addr, std::size_t size) const; 127 GPUVAddr gpu_addr, std::size_t size) const;
129 128
130 GPUVAddr Map(GPUVAddr gpu_addr, VAddr cpu_addr, std::size_t size, 129 GPUVAddr Map(GPUVAddr gpu_addr, DAddr dev_addr, std::size_t size,
131 PTEKind kind = PTEKind::INVALID, bool is_big_pages = true); 130 PTEKind kind = PTEKind::INVALID, bool is_big_pages = true);
132 GPUVAddr MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages = true); 131 GPUVAddr MapSparse(GPUVAddr gpu_addr, std::size_t size, bool is_big_pages = true);
133 void Unmap(GPUVAddr gpu_addr, std::size_t size); 132 void Unmap(GPUVAddr gpu_addr, std::size_t size);
@@ -186,12 +185,11 @@ private:
186 void GetSubmappedRangeImpl( 185 void GetSubmappedRangeImpl(
187 GPUVAddr gpu_addr, std::size_t size, 186 GPUVAddr gpu_addr, std::size_t size,
188 boost::container::small_vector< 187 boost::container::small_vector<
189 std::pair<std::conditional_t<is_gpu_address, GPUVAddr, VAddr>, std::size_t>, 32>& 188 std::pair<std::conditional_t<is_gpu_address, GPUVAddr, DAddr>, std::size_t>, 32>&
190 result) const; 189 result) const;
191 190
192 Core::System& system; 191 Core::System& system;
193 Core::Memory::Memory& memory; 192 MaxwellDeviceMemoryManager& memory;
194 Core::DeviceMemory& device_memory;
195 193
196 const u64 address_space_bits; 194 const u64 address_space_bits;
197 const u64 page_bits; 195 const u64 page_bits;
@@ -218,11 +216,11 @@ private:
218 std::vector<u64> big_entries; 216 std::vector<u64> big_entries;
219 217
220 template <EntryType entry_type> 218 template <EntryType entry_type>
221 GPUVAddr PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size, 219 GPUVAddr PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, size_t size,
222 PTEKind kind); 220 PTEKind kind);
223 221
224 template <EntryType entry_type> 222 template <EntryType entry_type>
225 GPUVAddr BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr cpu_addr, size_t size, 223 GPUVAddr BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, size_t size,
226 PTEKind kind); 224 PTEKind kind);
227 225
228 template <bool is_big_page> 226 template <bool is_big_page>
@@ -233,11 +231,11 @@ private:
233 231
234 Common::MultiLevelPageTable<u32> page_table; 232 Common::MultiLevelPageTable<u32> page_table;
235 Common::RangeMap<GPUVAddr, PTEKind> kind_map; 233 Common::RangeMap<GPUVAddr, PTEKind> kind_map;
236 Common::VirtualBuffer<u32> big_page_table_cpu; 234 Common::VirtualBuffer<u32> big_page_table_dev;
237 235
238 std::vector<u64> big_page_continuous; 236 std::vector<u64> big_page_continuous;
239 boost::container::small_vector<std::pair<VAddr, std::size_t>, 32> page_stash{}; 237 boost::container::small_vector<std::pair<DAddr, std::size_t>, 32> page_stash{};
240 boost::container::small_vector<std::pair<VAddr, std::size_t>, 32> page_stash2{}; 238 boost::container::small_vector<std::pair<DAddr, std::size_t>, 32> page_stash2{};
241 239
242 mutable std::mutex guard; 240 mutable std::mutex guard;
243 241
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h
index a64404ce4..4861b123a 100644
--- a/src/video_core/query_cache.h
+++ b/src/video_core/query_cache.h
@@ -18,9 +18,9 @@
18 18
19#include "common/assert.h" 19#include "common/assert.h"
20#include "common/settings.h" 20#include "common/settings.h"
21#include "core/memory.h"
22#include "video_core/control/channel_state_cache.h" 21#include "video_core/control/channel_state_cache.h"
23#include "video_core/engines/maxwell_3d.h" 22#include "video_core/engines/maxwell_3d.h"
23#include "video_core/host1x/gpu_device_memory_manager.h"
24#include "video_core/memory_manager.h" 24#include "video_core/memory_manager.h"
25#include "video_core/rasterizer_interface.h" 25#include "video_core/rasterizer_interface.h"
26#include "video_core/texture_cache/slot_vector.h" 26#include "video_core/texture_cache/slot_vector.h"
@@ -102,18 +102,19 @@ template <class QueryCache, class CachedQuery, class CounterStream, class HostCo
102class QueryCacheLegacy : public VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { 102class QueryCacheLegacy : public VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
103public: 103public:
104 explicit QueryCacheLegacy(VideoCore::RasterizerInterface& rasterizer_, 104 explicit QueryCacheLegacy(VideoCore::RasterizerInterface& rasterizer_,
105 Core::Memory::Memory& cpu_memory_) 105 Tegra::MaxwellDeviceMemoryManager& device_memory_)
106 : rasterizer{rasterizer_}, 106 : rasterizer{rasterizer_},
107 // Use reinterpret_cast instead of static_cast as workaround for 107 // Use reinterpret_cast instead of static_cast as workaround for
108 // UBSan bug (https://github.com/llvm/llvm-project/issues/59060) 108 // UBSan bug (https://github.com/llvm/llvm-project/issues/59060)
109 cpu_memory{cpu_memory_}, streams{{ 109 device_memory{device_memory_},
110 {CounterStream{reinterpret_cast<QueryCache&>(*this), 110 streams{{
111 VideoCore::QueryType::SamplesPassed}}, 111 {CounterStream{reinterpret_cast<QueryCache&>(*this),
112 {CounterStream{reinterpret_cast<QueryCache&>(*this), 112 VideoCore::QueryType::SamplesPassed}},
113 VideoCore::QueryType::PrimitivesGenerated}}, 113 {CounterStream{reinterpret_cast<QueryCache&>(*this),
114 {CounterStream{reinterpret_cast<QueryCache&>(*this), 114 VideoCore::QueryType::PrimitivesGenerated}},
115 VideoCore::QueryType::TfbPrimitivesWritten}}, 115 {CounterStream{reinterpret_cast<QueryCache&>(*this),
116 }} { 116 VideoCore::QueryType::TfbPrimitivesWritten}},
117 }} {
117 (void)slot_async_jobs.insert(); // Null value 118 (void)slot_async_jobs.insert(); // Null value
118 } 119 }
119 120
@@ -322,13 +323,14 @@ private:
322 local_lock.unlock(); 323 local_lock.unlock();
323 if (timestamp) { 324 if (timestamp) {
324 u64 timestamp_value = *timestamp; 325 u64 timestamp_value = *timestamp;
325 cpu_memory.WriteBlockUnsafe(address + sizeof(u64), &timestamp_value, sizeof(u64)); 326 device_memory.WriteBlockUnsafe(address + sizeof(u64), &timestamp_value,
326 cpu_memory.WriteBlockUnsafe(address, &value, sizeof(u64)); 327 sizeof(u64));
328 device_memory.WriteBlockUnsafe(address, &value, sizeof(u64));
327 rasterizer.InvalidateRegion(address, sizeof(u64) * 2, 329 rasterizer.InvalidateRegion(address, sizeof(u64) * 2,
328 VideoCommon::CacheType::NoQueryCache); 330 VideoCommon::CacheType::NoQueryCache);
329 } else { 331 } else {
330 u32 small_value = static_cast<u32>(value); 332 u32 small_value = static_cast<u32>(value);
331 cpu_memory.WriteBlockUnsafe(address, &small_value, sizeof(u32)); 333 device_memory.WriteBlockUnsafe(address, &small_value, sizeof(u32));
332 rasterizer.InvalidateRegion(address, sizeof(u32), 334 rasterizer.InvalidateRegion(address, sizeof(u32),
333 VideoCommon::CacheType::NoQueryCache); 335 VideoCommon::CacheType::NoQueryCache);
334 } 336 }
@@ -342,7 +344,7 @@ private:
342 SlotVector<AsyncJob> slot_async_jobs; 344 SlotVector<AsyncJob> slot_async_jobs;
343 345
344 VideoCore::RasterizerInterface& rasterizer; 346 VideoCore::RasterizerInterface& rasterizer;
345 Core::Memory::Memory& cpu_memory; 347 Tegra::MaxwellDeviceMemoryManager& device_memory;
346 348
347 mutable std::recursive_mutex mutex; 349 mutable std::recursive_mutex mutex;
348 350
diff --git a/src/video_core/query_cache/query_base.h b/src/video_core/query_cache/query_base.h
index 68f1d38c1..d5d21beaa 100644
--- a/src/video_core/query_cache/query_base.h
+++ b/src/video_core/query_cache/query_base.h
@@ -23,7 +23,7 @@ DECLARE_ENUM_FLAG_OPERATORS(QueryFlagBits)
23 23
24class QueryBase { 24class QueryBase {
25public: 25public:
26 VAddr guest_address{}; 26 DAddr guest_address{};
27 QueryFlagBits flags{}; 27 QueryFlagBits flags{};
28 u64 value{}; 28 u64 value{};
29 29
@@ -32,7 +32,7 @@ protected:
32 QueryBase() = default; 32 QueryBase() = default;
33 33
34 // Parameterized constructor 34 // Parameterized constructor
35 QueryBase(VAddr address, QueryFlagBits flags_, u64 value_) 35 QueryBase(DAddr address, QueryFlagBits flags_, u64 value_)
36 : guest_address(address), flags(flags_), value{value_} {} 36 : guest_address(address), flags(flags_), value{value_} {}
37}; 37};
38 38
diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h
index 94f0c4466..08b779055 100644
--- a/src/video_core/query_cache/query_cache.h
+++ b/src/video_core/query_cache/query_cache.h
@@ -15,9 +15,9 @@
15#include "common/logging/log.h" 15#include "common/logging/log.h"
16#include "common/scope_exit.h" 16#include "common/scope_exit.h"
17#include "common/settings.h" 17#include "common/settings.h"
18#include "core/memory.h"
19#include "video_core/engines/maxwell_3d.h" 18#include "video_core/engines/maxwell_3d.h"
20#include "video_core/gpu.h" 19#include "video_core/gpu.h"
20#include "video_core/host1x/gpu_device_memory_manager.h"
21#include "video_core/memory_manager.h" 21#include "video_core/memory_manager.h"
22#include "video_core/query_cache/bank_base.h" 22#include "video_core/query_cache/bank_base.h"
23#include "video_core/query_cache/query_base.h" 23#include "video_core/query_cache/query_base.h"
@@ -113,9 +113,10 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl {
113 using RuntimeType = typename Traits::RuntimeType; 113 using RuntimeType = typename Traits::RuntimeType;
114 114
115 QueryCacheBaseImpl(QueryCacheBase<Traits>* owner_, VideoCore::RasterizerInterface& rasterizer_, 115 QueryCacheBaseImpl(QueryCacheBase<Traits>* owner_, VideoCore::RasterizerInterface& rasterizer_,
116 Core::Memory::Memory& cpu_memory_, RuntimeType& runtime_, Tegra::GPU& gpu_) 116 Tegra::MaxwellDeviceMemoryManager& device_memory_, RuntimeType& runtime_,
117 Tegra::GPU& gpu_)
117 : owner{owner_}, rasterizer{rasterizer_}, 118 : owner{owner_}, rasterizer{rasterizer_},
118 cpu_memory{cpu_memory_}, runtime{runtime_}, gpu{gpu_} { 119 device_memory{device_memory_}, runtime{runtime_}, gpu{gpu_} {
119 streamer_mask = 0; 120 streamer_mask = 0;
120 for (size_t i = 0; i < static_cast<size_t>(QueryType::MaxQueryTypes); i++) { 121 for (size_t i = 0; i < static_cast<size_t>(QueryType::MaxQueryTypes); i++) {
121 streamers[i] = runtime.GetStreamerInterface(static_cast<QueryType>(i)); 122 streamers[i] = runtime.GetStreamerInterface(static_cast<QueryType>(i));
@@ -158,7 +159,7 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl {
158 159
159 QueryCacheBase<Traits>* owner; 160 QueryCacheBase<Traits>* owner;
160 VideoCore::RasterizerInterface& rasterizer; 161 VideoCore::RasterizerInterface& rasterizer;
161 Core::Memory::Memory& cpu_memory; 162 Tegra::MaxwellDeviceMemoryManager& device_memory;
162 RuntimeType& runtime; 163 RuntimeType& runtime;
163 Tegra::GPU& gpu; 164 Tegra::GPU& gpu;
164 std::array<StreamerInterface*, static_cast<size_t>(QueryType::MaxQueryTypes)> streamers; 165 std::array<StreamerInterface*, static_cast<size_t>(QueryType::MaxQueryTypes)> streamers;
@@ -171,10 +172,11 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl {
171template <typename Traits> 172template <typename Traits>
172QueryCacheBase<Traits>::QueryCacheBase(Tegra::GPU& gpu_, 173QueryCacheBase<Traits>::QueryCacheBase(Tegra::GPU& gpu_,
173 VideoCore::RasterizerInterface& rasterizer_, 174 VideoCore::RasterizerInterface& rasterizer_,
174 Core::Memory::Memory& cpu_memory_, RuntimeType& runtime_) 175 Tegra::MaxwellDeviceMemoryManager& device_memory_,
176 RuntimeType& runtime_)
175 : cached_queries{} { 177 : cached_queries{} {
176 impl = std::make_unique<QueryCacheBase<Traits>::QueryCacheBaseImpl>( 178 impl = std::make_unique<QueryCacheBase<Traits>::QueryCacheBaseImpl>(
177 this, rasterizer_, cpu_memory_, runtime_, gpu_); 179 this, rasterizer_, device_memory_, runtime_, gpu_);
178} 180}
179 181
180template <typename Traits> 182template <typename Traits>
@@ -240,7 +242,7 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
240 if (!cpu_addr_opt) [[unlikely]] { 242 if (!cpu_addr_opt) [[unlikely]] {
241 return; 243 return;
242 } 244 }
243 VAddr cpu_addr = *cpu_addr_opt; 245 DAddr cpu_addr = *cpu_addr_opt;
244 const size_t new_query_id = streamer->WriteCounter(cpu_addr, has_timestamp, payload, subreport); 246 const size_t new_query_id = streamer->WriteCounter(cpu_addr, has_timestamp, payload, subreport);
245 auto* query = streamer->GetQuery(new_query_id); 247 auto* query = streamer->GetQuery(new_query_id);
246 if (is_fence) { 248 if (is_fence) {
@@ -250,13 +252,12 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
250 query_location.stream_id.Assign(static_cast<u32>(streamer_id)); 252 query_location.stream_id.Assign(static_cast<u32>(streamer_id));
251 query_location.query_id.Assign(static_cast<u32>(new_query_id)); 253 query_location.query_id.Assign(static_cast<u32>(new_query_id));
252 const auto gen_caching_indexing = [](VAddr cur_addr) { 254 const auto gen_caching_indexing = [](VAddr cur_addr) {
253 return std::make_pair<u64, u32>(cur_addr >> Core::Memory::YUZU_PAGEBITS, 255 return std::make_pair<u64, u32>(cur_addr >> Core::DEVICE_PAGEBITS,
254 static_cast<u32>(cur_addr & Core::Memory::YUZU_PAGEMASK)); 256 static_cast<u32>(cur_addr & Core::DEVICE_PAGEMASK));
255 }; 257 };
256 u8* pointer = impl->cpu_memory.GetPointer(cpu_addr); 258 u8* pointer = impl->device_memory.template GetPointer<u8>(cpu_addr);
257 u8* pointer_timestamp = impl->cpu_memory.GetPointer(cpu_addr + 8); 259 u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8);
258 bool is_synced = !Settings::IsGPULevelHigh() && is_fence; 260 bool is_synced = !Settings::IsGPULevelHigh() && is_fence;
259
260 std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location, 261 std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location,
261 pointer, pointer_timestamp] { 262 pointer, pointer_timestamp] {
262 if (True(query_base->flags & QueryFlagBits::IsInvalidated)) { 263 if (True(query_base->flags & QueryFlagBits::IsInvalidated)) {
@@ -323,8 +324,8 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
323template <typename Traits> 324template <typename Traits>
324void QueryCacheBase<Traits>::UnregisterPending() { 325void QueryCacheBase<Traits>::UnregisterPending() {
325 const auto gen_caching_indexing = [](VAddr cur_addr) { 326 const auto gen_caching_indexing = [](VAddr cur_addr) {
326 return std::make_pair<u64, u32>(cur_addr >> Core::Memory::YUZU_PAGEBITS, 327 return std::make_pair<u64, u32>(cur_addr >> Core::DEVICE_PAGEBITS,
327 static_cast<u32>(cur_addr & Core::Memory::YUZU_PAGEMASK)); 328 static_cast<u32>(cur_addr & Core::DEVICE_PAGEMASK));
328 }; 329 };
329 std::scoped_lock lock(cache_mutex); 330 std::scoped_lock lock(cache_mutex);
330 for (QueryLocation loc : impl->pending_unregister) { 331 for (QueryLocation loc : impl->pending_unregister) {
@@ -388,7 +389,7 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() {
388 } 389 }
389 VAddr cpu_addr = *cpu_addr_opt; 390 VAddr cpu_addr = *cpu_addr_opt;
390 std::scoped_lock lock(cache_mutex); 391 std::scoped_lock lock(cache_mutex);
391 auto it1 = cached_queries.find(cpu_addr >> Core::Memory::YUZU_PAGEBITS); 392 auto it1 = cached_queries.find(cpu_addr >> Core::DEVICE_PAGEBITS);
392 if (it1 == cached_queries.end()) { 393 if (it1 == cached_queries.end()) {
393 return VideoCommon::LookupData{ 394 return VideoCommon::LookupData{
394 .address = cpu_addr, 395 .address = cpu_addr,
@@ -396,10 +397,10 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() {
396 }; 397 };
397 } 398 }
398 auto& sub_container = it1->second; 399 auto& sub_container = it1->second;
399 auto it_current = sub_container.find(cpu_addr & Core::Memory::YUZU_PAGEMASK); 400 auto it_current = sub_container.find(cpu_addr & Core::DEVICE_PAGEMASK);
400 401
401 if (it_current == sub_container.end()) { 402 if (it_current == sub_container.end()) {
402 auto it_current_2 = sub_container.find((cpu_addr & Core::Memory::YUZU_PAGEMASK) + 4); 403 auto it_current_2 = sub_container.find((cpu_addr & Core::DEVICE_PAGEMASK) + 4);
403 if (it_current_2 == sub_container.end()) { 404 if (it_current_2 == sub_container.end()) {
404 return VideoCommon::LookupData{ 405 return VideoCommon::LookupData{
405 .address = cpu_addr, 406 .address = cpu_addr,
@@ -559,7 +560,7 @@ bool QueryCacheBase<Traits>::SemiFlushQueryDirty(QueryCacheBase<Traits>::QueryLo
559 } 560 }
560 if (True(query_base->flags & QueryFlagBits::IsFinalValueSynced) && 561 if (True(query_base->flags & QueryFlagBits::IsFinalValueSynced) &&
561 False(query_base->flags & QueryFlagBits::IsGuestSynced)) { 562 False(query_base->flags & QueryFlagBits::IsGuestSynced)) {
562 auto* ptr = impl->cpu_memory.GetPointer(query_base->guest_address); 563 auto* ptr = impl->device_memory.template GetPointer<u8>(query_base->guest_address);
563 if (True(query_base->flags & QueryFlagBits::HasTimestamp)) { 564 if (True(query_base->flags & QueryFlagBits::HasTimestamp)) {
564 std::memcpy(ptr, &query_base->value, sizeof(query_base->value)); 565 std::memcpy(ptr, &query_base->value, sizeof(query_base->value));
565 return false; 566 return false;
diff --git a/src/video_core/query_cache/query_cache_base.h b/src/video_core/query_cache/query_cache_base.h
index 5a88e7f0a..00c25c8d6 100644
--- a/src/video_core/query_cache/query_cache_base.h
+++ b/src/video_core/query_cache/query_cache_base.h
@@ -13,15 +13,11 @@
13#include "common/assert.h" 13#include "common/assert.h"
14#include "common/bit_field.h" 14#include "common/bit_field.h"
15#include "common/common_types.h" 15#include "common/common_types.h"
16#include "core/memory.h"
17#include "video_core/control/channel_state_cache.h" 16#include "video_core/control/channel_state_cache.h"
17#include "video_core/host1x/gpu_device_memory_manager.h"
18#include "video_core/query_cache/query_base.h" 18#include "video_core/query_cache/query_base.h"
19#include "video_core/query_cache/types.h" 19#include "video_core/query_cache/types.h"
20 20
21namespace Core::Memory {
22class Memory;
23}
24
25namespace VideoCore { 21namespace VideoCore {
26class RasterizerInterface; 22class RasterizerInterface;
27} 23}
@@ -53,7 +49,8 @@ public:
53 }; 49 };
54 50
55 explicit QueryCacheBase(Tegra::GPU& gpu, VideoCore::RasterizerInterface& rasterizer_, 51 explicit QueryCacheBase(Tegra::GPU& gpu, VideoCore::RasterizerInterface& rasterizer_,
56 Core::Memory::Memory& cpu_memory_, RuntimeType& runtime_); 52 Tegra::MaxwellDeviceMemoryManager& device_memory_,
53 RuntimeType& runtime_);
57 54
58 ~QueryCacheBase(); 55 ~QueryCacheBase();
59 56
@@ -125,10 +122,10 @@ protected:
125 const u64 addr_begin = addr; 122 const u64 addr_begin = addr;
126 const u64 addr_end = addr_begin + size; 123 const u64 addr_end = addr_begin + size;
127 124
128 const u64 page_end = addr_end >> Core::Memory::YUZU_PAGEBITS; 125 const u64 page_end = addr_end >> Core::DEVICE_PAGEBITS;
129 std::scoped_lock lock(cache_mutex); 126 std::scoped_lock lock(cache_mutex);
130 for (u64 page = addr_begin >> Core::Memory::YUZU_PAGEBITS; page <= page_end; ++page) { 127 for (u64 page = addr_begin >> Core::DEVICE_PAGEBITS; page <= page_end; ++page) {
131 const u64 page_start = page << Core::Memory::YUZU_PAGEBITS; 128 const u64 page_start = page << Core::DEVICE_PAGEBITS;
132 const auto in_range = [page_start, addr_begin, addr_end](const u32 query_location) { 129 const auto in_range = [page_start, addr_begin, addr_end](const u32 query_location) {
133 const u64 cache_begin = page_start + query_location; 130 const u64 cache_begin = page_start + query_location;
134 const u64 cache_end = cache_begin + sizeof(u32); 131 const u64 cache_end = cache_begin + sizeof(u32);
diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp
deleted file mode 100644
index f200a650f..000000000
--- a/src/video_core/rasterizer_accelerated.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <atomic>
5
6#include "common/assert.h"
7#include "common/common_types.h"
8#include "common/div_ceil.h"
9#include "core/memory.h"
10#include "video_core/rasterizer_accelerated.h"
11
12namespace VideoCore {
13
14using namespace Core::Memory;
15
16RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_)
17 : cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {}
18
19RasterizerAccelerated::~RasterizerAccelerated() = default;
20
21void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
22 u64 uncache_begin = 0;
23 u64 cache_begin = 0;
24 u64 uncache_bytes = 0;
25 u64 cache_bytes = 0;
26
27 std::atomic_thread_fence(std::memory_order_acquire);
28 const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
29 for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
30 std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
31
32 if (delta > 0) {
33 ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
34 } else if (delta < 0) {
35 ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
36 } else {
37 ASSERT_MSG(false, "Delta must be non-zero!");
38 }
39
40 // Adds or subtracts 1, as count is a unsigned 8-bit value
41 count.fetch_add(static_cast<u16>(delta), std::memory_order_release);
42
43 // Assume delta is either -1 or 1
44 if (count.load(std::memory_order::relaxed) == 0) {
45 if (uncache_bytes == 0) {
46 uncache_begin = page;
47 }
48 uncache_bytes += YUZU_PAGESIZE;
49 } else if (uncache_bytes > 0) {
50 cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes,
51 false);
52 uncache_bytes = 0;
53 }
54 if (count.load(std::memory_order::relaxed) == 1 && delta > 0) {
55 if (cache_bytes == 0) {
56 cache_begin = page;
57 }
58 cache_bytes += YUZU_PAGESIZE;
59 } else if (cache_bytes > 0) {
60 cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
61 cache_bytes = 0;
62 }
63 }
64 if (uncache_bytes > 0) {
65 cpu_memory.RasterizerMarkRegionCached(uncache_begin << YUZU_PAGEBITS, uncache_bytes, false);
66 }
67 if (cache_bytes > 0) {
68 cpu_memory.RasterizerMarkRegionCached(cache_begin << YUZU_PAGEBITS, cache_bytes, true);
69 }
70}
71
72} // namespace VideoCore
diff --git a/src/video_core/rasterizer_accelerated.h b/src/video_core/rasterizer_accelerated.h
deleted file mode 100644
index e6c0ea87a..000000000
--- a/src/video_core/rasterizer_accelerated.h
+++ /dev/null
@@ -1,49 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <array>
7#include <atomic>
8
9#include "common/common_types.h"
10#include "video_core/rasterizer_interface.h"
11
12namespace Core::Memory {
13class Memory;
14}
15
16namespace VideoCore {
17
18/// Implements the shared part in GPU accelerated rasterizers in RasterizerInterface.
19class RasterizerAccelerated : public RasterizerInterface {
20public:
21 explicit RasterizerAccelerated(Core::Memory::Memory& cpu_memory_);
22 ~RasterizerAccelerated() override;
23
24 void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) override;
25
26private:
27 class CacheEntry final {
28 public:
29 CacheEntry() = default;
30
31 std::atomic_uint16_t& Count(std::size_t page) {
32 return values[page & 3];
33 }
34
35 const std::atomic_uint16_t& Count(std::size_t page) const {
36 return values[page & 3];
37 }
38
39 private:
40 std::array<std::atomic_uint16_t, 4> values{};
41 };
42 static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
43
44 using CachedPages = std::array<CacheEntry, 0x2000000>;
45 std::unique_ptr<CachedPages> cached_pages;
46 Core::Memory::Memory& cpu_memory;
47};
48
49} // namespace VideoCore
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 49224ca85..8fa4e4d9a 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -86,35 +86,35 @@ public:
86 virtual void FlushAll() = 0; 86 virtual void FlushAll() = 0;
87 87
88 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 88 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
89 virtual void FlushRegion(VAddr addr, u64 size, 89 virtual void FlushRegion(DAddr addr, u64 size,
90 VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; 90 VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0;
91 91
92 /// Check if the the specified memory area requires flushing to CPU Memory. 92 /// Check if the the specified memory area requires flushing to CPU Memory.
93 virtual bool MustFlushRegion(VAddr addr, u64 size, 93 virtual bool MustFlushRegion(DAddr addr, u64 size,
94 VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; 94 VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0;
95 95
96 virtual RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) = 0; 96 virtual RasterizerDownloadArea GetFlushArea(DAddr addr, u64 size) = 0;
97 97
98 /// Notify rasterizer that any caches of the specified region should be invalidated 98 /// Notify rasterizer that any caches of the specified region should be invalidated
99 virtual void InvalidateRegion(VAddr addr, u64 size, 99 virtual void InvalidateRegion(DAddr addr, u64 size,
100 VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; 100 VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0;
101 101
102 virtual void InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) { 102 virtual void InnerInvalidation(std::span<const std::pair<DAddr, std::size_t>> sequences) {
103 for (const auto& [cpu_addr, size] : sequences) { 103 for (const auto& [cpu_addr, size] : sequences) {
104 InvalidateRegion(cpu_addr, size); 104 InvalidateRegion(cpu_addr, size);
105 } 105 }
106 } 106 }
107 107
108 /// Notify rasterizer that any caches of the specified region are desync with guest 108 /// Notify rasterizer that any caches of the specified region are desync with guest
109 virtual void OnCacheInvalidation(VAddr addr, u64 size) = 0; 109 virtual void OnCacheInvalidation(PAddr addr, u64 size) = 0;
110 110
111 virtual bool OnCPUWrite(VAddr addr, u64 size) = 0; 111 virtual bool OnCPUWrite(PAddr addr, u64 size) = 0;
112 112
113 /// Sync memory between guest and host. 113 /// Sync memory between guest and host.
114 virtual void InvalidateGPUCache() = 0; 114 virtual void InvalidateGPUCache() = 0;
115 115
116 /// Unmap memory range 116 /// Unmap memory range
117 virtual void UnmapMemory(VAddr addr, u64 size) = 0; 117 virtual void UnmapMemory(DAddr addr, u64 size) = 0;
118 118
119 /// Remap GPU memory range. This means underneath backing memory changed 119 /// Remap GPU memory range. This means underneath backing memory changed
120 virtual void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) = 0; 120 virtual void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) = 0;
@@ -122,7 +122,7 @@ public:
122 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory 122 /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
123 /// and invalidated 123 /// and invalidated
124 virtual void FlushAndInvalidateRegion( 124 virtual void FlushAndInvalidateRegion(
125 VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0; 125 DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) = 0;
126 126
127 /// Notify the host renderer to wait for previous primitive and compute operations. 127 /// Notify the host renderer to wait for previous primitive and compute operations.
128 virtual void WaitForIdle() = 0; 128 virtual void WaitForIdle() = 0;
@@ -157,13 +157,10 @@ public:
157 157
158 /// Attempt to use a faster method to display the framebuffer to screen 158 /// Attempt to use a faster method to display the framebuffer to screen
159 [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, 159 [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config,
160 VAddr framebuffer_addr, u32 pixel_stride) { 160 DAddr framebuffer_addr, u32 pixel_stride) {
161 return false; 161 return false;
162 } 162 }
163 163
164 /// Increase/decrease the number of object in pages touching the specified region
165 virtual void UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {}
166
167 /// Initialize disk cached resources for the game being emulated 164 /// Initialize disk cached resources for the game being emulated
168 virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 165 virtual void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
169 const DiskResourceLoadCallback& callback) {} 166 const DiskResourceLoadCallback& callback) {}
diff --git a/src/video_core/renderer_null/null_rasterizer.cpp b/src/video_core/renderer_null/null_rasterizer.cpp
index 4f1d5b548..abfabb65b 100644
--- a/src/video_core/renderer_null/null_rasterizer.cpp
+++ b/src/video_core/renderer_null/null_rasterizer.cpp
@@ -2,7 +2,6 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/alignment.h" 4#include "common/alignment.h"
5#include "core/memory.h"
6#include "video_core/control/channel_state.h" 5#include "video_core/control/channel_state.h"
7#include "video_core/host1x/host1x.h" 6#include "video_core/host1x/host1x.h"
8#include "video_core/memory_manager.h" 7#include "video_core/memory_manager.h"
@@ -19,8 +18,7 @@ bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) {
19 return true; 18 return true;
20} 19}
21 20
22RasterizerNull::RasterizerNull(Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu) 21RasterizerNull::RasterizerNull(Tegra::GPU& gpu) : m_gpu{gpu} {}
23 : RasterizerAccelerated(cpu_memory_), m_gpu{gpu} {}
24RasterizerNull::~RasterizerNull() = default; 22RasterizerNull::~RasterizerNull() = default;
25 23
26void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} 24void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {}
@@ -45,25 +43,25 @@ void RasterizerNull::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr
45 u32 size) {} 43 u32 size) {}
46void RasterizerNull::DisableGraphicsUniformBuffer(size_t stage, u32 index) {} 44void RasterizerNull::DisableGraphicsUniformBuffer(size_t stage, u32 index) {}
47void RasterizerNull::FlushAll() {} 45void RasterizerNull::FlushAll() {}
48void RasterizerNull::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} 46void RasterizerNull::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType) {}
49bool RasterizerNull::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType) { 47bool RasterizerNull::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType) {
50 return false; 48 return false;
51} 49}
52void RasterizerNull::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} 50void RasterizerNull::InvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType) {}
53bool RasterizerNull::OnCPUWrite(VAddr addr, u64 size) { 51bool RasterizerNull::OnCPUWrite(PAddr addr, u64 size) {
54 return false; 52 return false;
55} 53}
56void RasterizerNull::OnCacheInvalidation(VAddr addr, u64 size) {} 54void RasterizerNull::OnCacheInvalidation(PAddr addr, u64 size) {}
57VideoCore::RasterizerDownloadArea RasterizerNull::GetFlushArea(VAddr addr, u64 size) { 55VideoCore::RasterizerDownloadArea RasterizerNull::GetFlushArea(PAddr addr, u64 size) {
58 VideoCore::RasterizerDownloadArea new_area{ 56 VideoCore::RasterizerDownloadArea new_area{
59 .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), 57 .start_address = Common::AlignDown(addr, Core::DEVICE_PAGESIZE),
60 .end_address = Common::AlignUp(addr + size, Core::Memory::YUZU_PAGESIZE), 58 .end_address = Common::AlignUp(addr + size, Core::DEVICE_PAGESIZE),
61 .preemtive = true, 59 .preemtive = true,
62 }; 60 };
63 return new_area; 61 return new_area;
64} 62}
65void RasterizerNull::InvalidateGPUCache() {} 63void RasterizerNull::InvalidateGPUCache() {}
66void RasterizerNull::UnmapMemory(VAddr addr, u64 size) {} 64void RasterizerNull::UnmapMemory(DAddr addr, u64 size) {}
67void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {} 65void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {}
68void RasterizerNull::SignalFence(std::function<void()>&& func) { 66void RasterizerNull::SignalFence(std::function<void()>&& func) {
69 func(); 67 func();
@@ -78,7 +76,7 @@ void RasterizerNull::SignalSyncPoint(u32 value) {
78} 76}
79void RasterizerNull::SignalReference() {} 77void RasterizerNull::SignalReference() {}
80void RasterizerNull::ReleaseFences(bool) {} 78void RasterizerNull::ReleaseFences(bool) {}
81void RasterizerNull::FlushAndInvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType) {} 79void RasterizerNull::FlushAndInvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType) {}
82void RasterizerNull::WaitForIdle() {} 80void RasterizerNull::WaitForIdle() {}
83void RasterizerNull::FragmentBarrier() {} 81void RasterizerNull::FragmentBarrier() {}
84void RasterizerNull::TiledCacheBarrier() {} 82void RasterizerNull::TiledCacheBarrier() {}
@@ -95,7 +93,7 @@ bool RasterizerNull::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surfac
95void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 93void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
96 std::span<const u8> memory) {} 94 std::span<const u8> memory) {}
97bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config, 95bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config,
98 VAddr framebuffer_addr, u32 pixel_stride) { 96 DAddr framebuffer_addr, u32 pixel_stride) {
99 return true; 97 return true;
100} 98}
101void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, 99void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
diff --git a/src/video_core/renderer_null/null_rasterizer.h b/src/video_core/renderer_null/null_rasterizer.h
index 23001eeb8..a5789604f 100644
--- a/src/video_core/renderer_null/null_rasterizer.h
+++ b/src/video_core/renderer_null/null_rasterizer.h
@@ -6,7 +6,6 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/control/channel_state_cache.h" 7#include "video_core/control/channel_state_cache.h"
8#include "video_core/engines/maxwell_dma.h" 8#include "video_core/engines/maxwell_dma.h"
9#include "video_core/rasterizer_accelerated.h"
10#include "video_core/rasterizer_interface.h" 9#include "video_core/rasterizer_interface.h"
11 10
12namespace Core { 11namespace Core {
@@ -32,10 +31,10 @@ public:
32 } 31 }
33}; 32};
34 33
35class RasterizerNull final : public VideoCore::RasterizerAccelerated, 34class RasterizerNull final : public VideoCore::RasterizerInterface,
36 protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { 35 protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
37public: 36public:
38 explicit RasterizerNull(Core::Memory::Memory& cpu_memory, Tegra::GPU& gpu); 37 explicit RasterizerNull(Tegra::GPU& gpu);
39 ~RasterizerNull() override; 38 ~RasterizerNull() override;
40 39
41 void Draw(bool is_indexed, u32 instance_count) override; 40 void Draw(bool is_indexed, u32 instance_count) override;
@@ -48,17 +47,17 @@ public:
48 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; 47 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
49 void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; 48 void DisableGraphicsUniformBuffer(size_t stage, u32 index) override;
50 void FlushAll() override; 49 void FlushAll() override;
51 void FlushRegion(VAddr addr, u64 size, 50 void FlushRegion(DAddr addr, u64 size,
52 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 51 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
53 bool MustFlushRegion(VAddr addr, u64 size, 52 bool MustFlushRegion(DAddr addr, u64 size,
54 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 53 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
55 void InvalidateRegion(VAddr addr, u64 size, 54 void InvalidateRegion(DAddr addr, u64 size,
56 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 55 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
57 void OnCacheInvalidation(VAddr addr, u64 size) override; 56 void OnCacheInvalidation(DAddr addr, u64 size) override;
58 bool OnCPUWrite(VAddr addr, u64 size) override; 57 bool OnCPUWrite(DAddr addr, u64 size) override;
59 VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; 58 VideoCore::RasterizerDownloadArea GetFlushArea(DAddr addr, u64 size) override;
60 void InvalidateGPUCache() override; 59 void InvalidateGPUCache() override;
61 void UnmapMemory(VAddr addr, u64 size) override; 60 void UnmapMemory(DAddr addr, u64 size) override;
62 void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; 61 void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
63 void SignalFence(std::function<void()>&& func) override; 62 void SignalFence(std::function<void()>&& func) override;
64 void SyncOperation(std::function<void()>&& func) override; 63 void SyncOperation(std::function<void()>&& func) override;
@@ -66,7 +65,7 @@ public:
66 void SignalReference() override; 65 void SignalReference() override;
67 void ReleaseFences(bool force) override; 66 void ReleaseFences(bool force) override;
68 void FlushAndInvalidateRegion( 67 void FlushAndInvalidateRegion(
69 VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 68 DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
70 void WaitForIdle() override; 69 void WaitForIdle() override;
71 void FragmentBarrier() override; 70 void FragmentBarrier() override;
72 void TiledCacheBarrier() override; 71 void TiledCacheBarrier() override;
@@ -78,7 +77,7 @@ public:
78 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; 77 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
79 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 78 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
80 std::span<const u8> memory) override; 79 std::span<const u8> memory) override;
81 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 80 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr,
82 u32 pixel_stride) override; 81 u32 pixel_stride) override;
83 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 82 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
84 const VideoCore::DiskResourceLoadCallback& callback) override; 83 const VideoCore::DiskResourceLoadCallback& callback) override;
diff --git a/src/video_core/renderer_null/renderer_null.cpp b/src/video_core/renderer_null/renderer_null.cpp
index be92cc2f4..078feb925 100644
--- a/src/video_core/renderer_null/renderer_null.cpp
+++ b/src/video_core/renderer_null/renderer_null.cpp
@@ -7,10 +7,9 @@
7 7
8namespace Null { 8namespace Null {
9 9
10RendererNull::RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, 10RendererNull::RendererNull(Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
11 Tegra::GPU& gpu,
12 std::unique_ptr<Core::Frontend::GraphicsContext> context_) 11 std::unique_ptr<Core::Frontend::GraphicsContext> context_)
13 : RendererBase(emu_window, std::move(context_)), m_gpu(gpu), m_rasterizer(cpu_memory, gpu) {} 12 : RendererBase(emu_window, std::move(context_)), m_gpu(gpu), m_rasterizer(gpu) {}
14 13
15RendererNull::~RendererNull() = default; 14RendererNull::~RendererNull() = default;
16 15
diff --git a/src/video_core/renderer_null/renderer_null.h b/src/video_core/renderer_null/renderer_null.h
index 967ff5645..9531b43f6 100644
--- a/src/video_core/renderer_null/renderer_null.h
+++ b/src/video_core/renderer_null/renderer_null.h
@@ -13,8 +13,7 @@ namespace Null {
13 13
14class RendererNull final : public VideoCore::RendererBase { 14class RendererNull final : public VideoCore::RendererBase {
15public: 15public:
16 explicit RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, 16 explicit RendererNull(Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
17 Tegra::GPU& gpu,
18 std::unique_ptr<Core::Frontend::GraphicsContext> context); 17 std::unique_ptr<Core::Frontend::GraphicsContext> context);
19 ~RendererNull() override; 18 ~RendererNull() override;
20 19
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index 517ac14dd..ade72e1f9 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -47,11 +47,10 @@ constexpr std::array PROGRAM_LUT{
47} // Anonymous namespace 47} // Anonymous namespace
48 48
49Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params) 49Buffer::Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params)
50 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params) {} 50 : VideoCommon::BufferBase(null_params) {}
51 51
52Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, 52Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_)
53 VAddr cpu_addr_, u64 size_bytes_) 53 : VideoCommon::BufferBase(cpu_addr_, size_bytes_) {
54 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_) {
55 buffer.Create(); 54 buffer.Create();
56 if (runtime.device.HasDebuggingToolAttached()) { 55 if (runtime.device.HasDebuggingToolAttached()) {
57 const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr()); 56 const std::string name = fmt::format("Buffer 0x{:x}", CpuAddr());
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index 2c18de166..af34c272b 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -10,7 +10,6 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/buffer_cache/buffer_cache_base.h" 11#include "video_core/buffer_cache/buffer_cache_base.h"
12#include "video_core/buffer_cache/memory_tracker_base.h" 12#include "video_core/buffer_cache/memory_tracker_base.h"
13#include "video_core/rasterizer_interface.h"
14#include "video_core/renderer_opengl/gl_device.h" 13#include "video_core/renderer_opengl/gl_device.h"
15#include "video_core/renderer_opengl/gl_resource_manager.h" 14#include "video_core/renderer_opengl/gl_resource_manager.h"
16#include "video_core/renderer_opengl/gl_staging_buffer_pool.h" 15#include "video_core/renderer_opengl/gl_staging_buffer_pool.h"
@@ -19,10 +18,9 @@ namespace OpenGL {
19 18
20class BufferCacheRuntime; 19class BufferCacheRuntime;
21 20
22class Buffer : public VideoCommon::BufferBase<VideoCore::RasterizerInterface> { 21class Buffer : public VideoCommon::BufferBase {
23public: 22public:
24 explicit Buffer(BufferCacheRuntime&, VideoCore::RasterizerInterface& rasterizer, VAddr cpu_addr, 23 explicit Buffer(BufferCacheRuntime&, DAddr cpu_addr, u64 size_bytes);
25 u64 size_bytes);
26 explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams); 24 explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams);
27 25
28 void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept; 26 void ImmediateUpload(size_t offset, std::span<const u8> data) noexcept;
@@ -244,7 +242,7 @@ struct BufferCacheParams {
244 using Runtime = OpenGL::BufferCacheRuntime; 242 using Runtime = OpenGL::BufferCacheRuntime;
245 using Buffer = OpenGL::Buffer; 243 using Buffer = OpenGL::Buffer;
246 using Async_Buffer = OpenGL::StagingBufferMap; 244 using Async_Buffer = OpenGL::StagingBufferMap;
247 using MemoryTracker = VideoCommon::MemoryTrackerBase<VideoCore::RasterizerInterface>; 245 using MemoryTracker = VideoCommon::MemoryTrackerBase<Tegra::MaxwellDeviceMemoryManager>;
248 246
249 static constexpr bool IS_OPENGL = true; 247 static constexpr bool IS_OPENGL = true;
250 static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = true; 248 static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = true;
diff --git a/src/video_core/renderer_opengl/gl_query_cache.cpp b/src/video_core/renderer_opengl/gl_query_cache.cpp
index fef7360ed..2147d587f 100644
--- a/src/video_core/renderer_opengl/gl_query_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_query_cache.cpp
@@ -35,8 +35,9 @@ constexpr GLenum GetTarget(VideoCore::QueryType type) {
35 35
36} // Anonymous namespace 36} // Anonymous namespace
37 37
38QueryCache::QueryCache(RasterizerOpenGL& rasterizer_, Core::Memory::Memory& cpu_memory_) 38QueryCache::QueryCache(RasterizerOpenGL& rasterizer_,
39 : QueryCacheLegacy(rasterizer_, cpu_memory_), gl_rasterizer{rasterizer_} { 39 Tegra::MaxwellDeviceMemoryManager& device_memory_)
40 : QueryCacheLegacy(rasterizer_, device_memory_), gl_rasterizer{rasterizer_} {
40 EnableCounters(); 41 EnableCounters();
41} 42}
42 43
diff --git a/src/video_core/renderer_opengl/gl_query_cache.h b/src/video_core/renderer_opengl/gl_query_cache.h
index 0721e0b3d..38118f355 100644
--- a/src/video_core/renderer_opengl/gl_query_cache.h
+++ b/src/video_core/renderer_opengl/gl_query_cache.h
@@ -8,6 +8,7 @@
8#include <vector> 8#include <vector>
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/host1x/gpu_device_memory_manager.h"
11#include "video_core/query_cache.h" 12#include "video_core/query_cache.h"
12#include "video_core/rasterizer_interface.h" 13#include "video_core/rasterizer_interface.h"
13#include "video_core/renderer_opengl/gl_resource_manager.h" 14#include "video_core/renderer_opengl/gl_resource_manager.h"
@@ -28,7 +29,8 @@ using CounterStream = VideoCommon::CounterStreamBase<QueryCache, HostCounter>;
28class QueryCache final 29class QueryCache final
29 : public VideoCommon::QueryCacheLegacy<QueryCache, CachedQuery, CounterStream, HostCounter> { 30 : public VideoCommon::QueryCacheLegacy<QueryCache, CachedQuery, CounterStream, HostCounter> {
30public: 31public:
31 explicit QueryCache(RasterizerOpenGL& rasterizer_, Core::Memory::Memory& cpu_memory_); 32 explicit QueryCache(RasterizerOpenGL& rasterizer_,
33 Tegra::MaxwellDeviceMemoryManager& device_memory_);
32 ~QueryCache(); 34 ~QueryCache();
33 35
34 OGLQuery AllocateQuery(VideoCore::QueryType type); 36 OGLQuery AllocateQuery(VideoCore::QueryType type);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 7a5fad735..d5354ef2d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -70,18 +70,18 @@ std::optional<VideoCore::QueryType> MaxwellToVideoCoreQuery(VideoCommon::QueryTy
70} // Anonymous namespace 70} // Anonymous namespace
71 71
72RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 72RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
73 Core::Memory::Memory& cpu_memory_, const Device& device_, 73 Tegra::MaxwellDeviceMemoryManager& device_memory_,
74 ScreenInfo& screen_info_, ProgramManager& program_manager_, 74 const Device& device_, ScreenInfo& screen_info_,
75 StateTracker& state_tracker_) 75 ProgramManager& program_manager_, StateTracker& state_tracker_)
76 : RasterizerAccelerated(cpu_memory_), gpu(gpu_), device(device_), screen_info(screen_info_), 76 : gpu(gpu_), device_memory(device_memory_), device(device_), screen_info(screen_info_),
77 program_manager(program_manager_), state_tracker(state_tracker_), 77 program_manager(program_manager_), state_tracker(state_tracker_),
78 texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool), 78 texture_cache_runtime(device, program_manager, state_tracker, staging_buffer_pool),
79 texture_cache(texture_cache_runtime, *this), 79 texture_cache(texture_cache_runtime, device_memory_),
80 buffer_cache_runtime(device, staging_buffer_pool), 80 buffer_cache_runtime(device, staging_buffer_pool),
81 buffer_cache(*this, cpu_memory_, buffer_cache_runtime), 81 buffer_cache(device_memory_, buffer_cache_runtime),
82 shader_cache(*this, emu_window_, device, texture_cache, buffer_cache, program_manager, 82 shader_cache(device_memory_, emu_window_, device, texture_cache, buffer_cache,
83 state_tracker, gpu.ShaderNotify()), 83 program_manager, state_tracker, gpu.ShaderNotify()),
84 query_cache(*this, cpu_memory_), accelerate_dma(buffer_cache, texture_cache), 84 query_cache(*this, device_memory_), accelerate_dma(buffer_cache, texture_cache),
85 fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), 85 fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache),
86 blit_image(program_manager_) {} 86 blit_image(program_manager_) {}
87 87
@@ -475,7 +475,7 @@ void RasterizerOpenGL::DisableGraphicsUniformBuffer(size_t stage, u32 index) {
475 475
476void RasterizerOpenGL::FlushAll() {} 476void RasterizerOpenGL::FlushAll() {}
477 477
478void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { 478void RasterizerOpenGL::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
479 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 479 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
480 if (addr == 0 || size == 0) { 480 if (addr == 0 || size == 0) {
481 return; 481 return;
@@ -493,7 +493,7 @@ void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType
493 } 493 }
494} 494}
495 495
496bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { 496bool RasterizerOpenGL::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
497 if ((True(which & VideoCommon::CacheType::BufferCache))) { 497 if ((True(which & VideoCommon::CacheType::BufferCache))) {
498 std::scoped_lock lock{buffer_cache.mutex}; 498 std::scoped_lock lock{buffer_cache.mutex};
499 if (buffer_cache.IsRegionGpuModified(addr, size)) { 499 if (buffer_cache.IsRegionGpuModified(addr, size)) {
@@ -510,7 +510,7 @@ bool RasterizerOpenGL::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheT
510 return false; 510 return false;
511} 511}
512 512
513VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(VAddr addr, u64 size) { 513VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(DAddr addr, u64 size) {
514 { 514 {
515 std::scoped_lock lock{texture_cache.mutex}; 515 std::scoped_lock lock{texture_cache.mutex};
516 auto area = texture_cache.GetFlushArea(addr, size); 516 auto area = texture_cache.GetFlushArea(addr, size);
@@ -526,14 +526,14 @@ VideoCore::RasterizerDownloadArea RasterizerOpenGL::GetFlushArea(VAddr addr, u64
526 } 526 }
527 } 527 }
528 VideoCore::RasterizerDownloadArea new_area{ 528 VideoCore::RasterizerDownloadArea new_area{
529 .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), 529 .start_address = Common::AlignDown(addr, Core::DEVICE_PAGESIZE),
530 .end_address = Common::AlignUp(addr + size, Core::Memory::YUZU_PAGESIZE), 530 .end_address = Common::AlignUp(addr + size, Core::DEVICE_PAGESIZE),
531 .preemtive = true, 531 .preemtive = true,
532 }; 532 };
533 return new_area; 533 return new_area;
534} 534}
535 535
536void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { 536void RasterizerOpenGL::InvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
537 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 537 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
538 if (addr == 0 || size == 0) { 538 if (addr == 0 || size == 0) {
539 return; 539 return;
@@ -554,7 +554,7 @@ void RasterizerOpenGL::InvalidateRegion(VAddr addr, u64 size, VideoCommon::Cache
554 } 554 }
555} 555}
556 556
557bool RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) { 557bool RasterizerOpenGL::OnCPUWrite(DAddr addr, u64 size) {
558 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 558 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
559 if (addr == 0 || size == 0) { 559 if (addr == 0 || size == 0) {
560 return false; 560 return false;
@@ -576,8 +576,9 @@ bool RasterizerOpenGL::OnCPUWrite(VAddr addr, u64 size) {
576 return false; 576 return false;
577} 577}
578 578
579void RasterizerOpenGL::OnCacheInvalidation(VAddr addr, u64 size) { 579void RasterizerOpenGL::OnCacheInvalidation(DAddr addr, u64 size) {
580 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 580 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
581
581 if (addr == 0 || size == 0) { 582 if (addr == 0 || size == 0) {
582 return; 583 return;
583 } 584 }
@@ -596,7 +597,7 @@ void RasterizerOpenGL::InvalidateGPUCache() {
596 gpu.InvalidateGPUCache(); 597 gpu.InvalidateGPUCache();
597} 598}
598 599
599void RasterizerOpenGL::UnmapMemory(VAddr addr, u64 size) { 600void RasterizerOpenGL::UnmapMemory(DAddr addr, u64 size) {
600 { 601 {
601 std::scoped_lock lock{texture_cache.mutex}; 602 std::scoped_lock lock{texture_cache.mutex};
602 texture_cache.UnmapMemory(addr, size); 603 texture_cache.UnmapMemory(addr, size);
@@ -635,7 +636,7 @@ void RasterizerOpenGL::ReleaseFences(bool force) {
635 fence_manager.WaitPendingFences(force); 636 fence_manager.WaitPendingFences(force);
636} 637}
637 638
638void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size, 639void RasterizerOpenGL::FlushAndInvalidateRegion(DAddr addr, u64 size,
639 VideoCommon::CacheType which) { 640 VideoCommon::CacheType which) {
640 if (Settings::IsGPULevelExtreme()) { 641 if (Settings::IsGPULevelExtreme()) {
641 FlushRegion(addr, size, which); 642 FlushRegion(addr, size, which);
@@ -739,7 +740,7 @@ void RasterizerOpenGL::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
739} 740}
740 741
741bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, 742bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
742 VAddr framebuffer_addr, u32 pixel_stride) { 743 DAddr framebuffer_addr, u32 pixel_stride) {
743 if (framebuffer_addr == 0) { 744 if (framebuffer_addr == 0) {
744 return false; 745 return false;
745 } 746 }
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index ce3460938..34aa73526 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -14,7 +14,6 @@
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "video_core/control/channel_state_cache.h" 15#include "video_core/control/channel_state_cache.h"
16#include "video_core/engines/maxwell_dma.h" 16#include "video_core/engines/maxwell_dma.h"
17#include "video_core/rasterizer_accelerated.h"
18#include "video_core/rasterizer_interface.h" 17#include "video_core/rasterizer_interface.h"
19#include "video_core/renderer_opengl/blit_image.h" 18#include "video_core/renderer_opengl/blit_image.h"
20#include "video_core/renderer_opengl/gl_buffer_cache.h" 19#include "video_core/renderer_opengl/gl_buffer_cache.h"
@@ -72,13 +71,13 @@ private:
72 TextureCache& texture_cache; 71 TextureCache& texture_cache;
73}; 72};
74 73
75class RasterizerOpenGL : public VideoCore::RasterizerAccelerated, 74class RasterizerOpenGL : public VideoCore::RasterizerInterface,
76 protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { 75 protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
77public: 76public:
78 explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 77 explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
79 Core::Memory::Memory& cpu_memory_, const Device& device_, 78 Tegra::MaxwellDeviceMemoryManager& device_memory_,
80 ScreenInfo& screen_info_, ProgramManager& program_manager_, 79 const Device& device_, ScreenInfo& screen_info_,
81 StateTracker& state_tracker_); 80 ProgramManager& program_manager_, StateTracker& state_tracker_);
82 ~RasterizerOpenGL() override; 81 ~RasterizerOpenGL() override;
83 82
84 void Draw(bool is_indexed, u32 instance_count) override; 83 void Draw(bool is_indexed, u32 instance_count) override;
@@ -92,17 +91,17 @@ public:
92 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; 91 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
93 void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; 92 void DisableGraphicsUniformBuffer(size_t stage, u32 index) override;
94 void FlushAll() override; 93 void FlushAll() override;
95 void FlushRegion(VAddr addr, u64 size, 94 void FlushRegion(DAddr addr, u64 size,
96 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 95 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
97 bool MustFlushRegion(VAddr addr, u64 size, 96 bool MustFlushRegion(DAddr addr, u64 size,
98 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 97 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
99 VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; 98 VideoCore::RasterizerDownloadArea GetFlushArea(PAddr addr, u64 size) override;
100 void InvalidateRegion(VAddr addr, u64 size, 99 void InvalidateRegion(DAddr addr, u64 size,
101 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 100 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
102 void OnCacheInvalidation(VAddr addr, u64 size) override; 101 void OnCacheInvalidation(PAddr addr, u64 size) override;
103 bool OnCPUWrite(VAddr addr, u64 size) override; 102 bool OnCPUWrite(PAddr addr, u64 size) override;
104 void InvalidateGPUCache() override; 103 void InvalidateGPUCache() override;
105 void UnmapMemory(VAddr addr, u64 size) override; 104 void UnmapMemory(DAddr addr, u64 size) override;
106 void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; 105 void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
107 void SignalFence(std::function<void()>&& func) override; 106 void SignalFence(std::function<void()>&& func) override;
108 void SyncOperation(std::function<void()>&& func) override; 107 void SyncOperation(std::function<void()>&& func) override;
@@ -110,7 +109,7 @@ public:
110 void SignalReference() override; 109 void SignalReference() override;
111 void ReleaseFences(bool force = true) override; 110 void ReleaseFences(bool force = true) override;
112 void FlushAndInvalidateRegion( 111 void FlushAndInvalidateRegion(
113 VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 112 DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
114 void WaitForIdle() override; 113 void WaitForIdle() override;
115 void FragmentBarrier() override; 114 void FragmentBarrier() override;
116 void TiledCacheBarrier() override; 115 void TiledCacheBarrier() override;
@@ -123,7 +122,7 @@ public:
123 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; 122 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
124 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 123 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
125 std::span<const u8> memory) override; 124 std::span<const u8> memory) override;
126 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 125 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr,
127 u32 pixel_stride) override; 126 u32 pixel_stride) override;
128 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 127 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
129 const VideoCore::DiskResourceLoadCallback& callback) override; 128 const VideoCore::DiskResourceLoadCallback& callback) override;
@@ -235,6 +234,7 @@ private:
235 VideoCommon::QueryPropertiesFlags flags, u32 payload, u32 subreport); 234 VideoCommon::QueryPropertiesFlags flags, u32 payload, u32 subreport);
236 235
237 Tegra::GPU& gpu; 236 Tegra::GPU& gpu;
237 Tegra::MaxwellDeviceMemoryManager& device_memory;
238 238
239 const Device& device; 239 const Device& device;
240 ScreenInfo& screen_info; 240 ScreenInfo& screen_info;
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 30df41b7d..50462cdde 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -168,11 +168,12 @@ void SetXfbState(VideoCommon::TransformFeedbackState& state, const Maxwell& regs
168} 168}
169} // Anonymous namespace 169} // Anonymous namespace
170 170
171ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, 171ShaderCache::ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
172 const Device& device_, TextureCache& texture_cache_, 172 Core::Frontend::EmuWindow& emu_window_, const Device& device_,
173 BufferCache& buffer_cache_, ProgramManager& program_manager_, 173 TextureCache& texture_cache_, BufferCache& buffer_cache_,
174 StateTracker& state_tracker_, VideoCore::ShaderNotify& shader_notify_) 174 ProgramManager& program_manager_, StateTracker& state_tracker_,
175 : VideoCommon::ShaderCache{rasterizer_}, emu_window{emu_window_}, device{device_}, 175 VideoCore::ShaderNotify& shader_notify_)
176 : VideoCommon::ShaderCache{device_memory_}, emu_window{emu_window_}, device{device_},
176 texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_}, 177 texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_},
177 state_tracker{state_tracker_}, shader_notify{shader_notify_}, 178 state_tracker{state_tracker_}, shader_notify{shader_notify_},
178 use_asynchronous_shaders{device.UseAsynchronousShaders()}, 179 use_asynchronous_shaders{device.UseAsynchronousShaders()},
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index 6b9732fca..5ac413529 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -17,7 +17,7 @@
17 17
18namespace Tegra { 18namespace Tegra {
19class MemoryManager; 19class MemoryManager;
20} 20} // namespace Tegra
21 21
22namespace OpenGL { 22namespace OpenGL {
23 23
@@ -28,10 +28,11 @@ using ShaderWorker = Common::StatefulThreadWorker<ShaderContext::Context>;
28 28
29class ShaderCache : public VideoCommon::ShaderCache { 29class ShaderCache : public VideoCommon::ShaderCache {
30public: 30public:
31 explicit ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindow& emu_window_, 31 explicit ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
32 const Device& device_, TextureCache& texture_cache_, 32 Core::Frontend::EmuWindow& emu_window_, const Device& device_,
33 BufferCache& buffer_cache_, ProgramManager& program_manager_, 33 TextureCache& texture_cache_, BufferCache& buffer_cache_,
34 StateTracker& state_tracker_, VideoCore::ShaderNotify& shader_notify_); 34 ProgramManager& program_manager_, StateTracker& state_tracker_,
35 VideoCore::ShaderNotify& shader_notify_);
35 ~ShaderCache(); 36 ~ShaderCache();
36 37
37 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 38 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 2933718b6..b75376fdb 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -15,7 +15,6 @@
15#include "common/telemetry.h" 15#include "common/telemetry.h"
16#include "core/core_timing.h" 16#include "core/core_timing.h"
17#include "core/frontend/emu_window.h" 17#include "core/frontend/emu_window.h"
18#include "core/memory.h"
19#include "core/telemetry_session.h" 18#include "core/telemetry_session.h"
20#include "video_core/host_shaders/ffx_a_h.h" 19#include "video_core/host_shaders/ffx_a_h.h"
21#include "video_core/host_shaders/ffx_fsr1_h.h" 20#include "video_core/host_shaders/ffx_fsr1_h.h"
@@ -144,12 +143,13 @@ void APIENTRY DebugHandler(GLenum source, GLenum type, GLuint id, GLenum severit
144 143
145RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_, 144RendererOpenGL::RendererOpenGL(Core::TelemetrySession& telemetry_session_,
146 Core::Frontend::EmuWindow& emu_window_, 145 Core::Frontend::EmuWindow& emu_window_,
147 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, 146 Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
148 std::unique_ptr<Core::Frontend::GraphicsContext> context_) 147 std::unique_ptr<Core::Frontend::GraphicsContext> context_)
149 : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_}, 148 : RendererBase{emu_window_, std::move(context_)}, telemetry_session{telemetry_session_},
150 emu_window{emu_window_}, cpu_memory{cpu_memory_}, gpu{gpu_}, device{emu_window_}, 149 emu_window{emu_window_}, device_memory{device_memory_}, gpu{gpu_}, device{emu_window_},
151 state_tracker{}, program_manager{device}, 150 state_tracker{}, program_manager{device},
152 rasterizer(emu_window, gpu, cpu_memory, device, screen_info, program_manager, state_tracker) { 151 rasterizer(emu_window, gpu, device_memory, device, screen_info, program_manager,
152 state_tracker) {
153 if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) { 153 if (Settings::values.renderer_debug && GLAD_GL_KHR_debug) {
154 glEnable(GL_DEBUG_OUTPUT); 154 glEnable(GL_DEBUG_OUTPUT);
155 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 155 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
@@ -242,7 +242,7 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
242 const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)}; 242 const u32 bytes_per_pixel{VideoCore::Surface::BytesPerBlock(pixel_format)};
243 const u64 size_in_bytes{Tegra::Texture::CalculateSize( 243 const u64 size_in_bytes{Tegra::Texture::CalculateSize(
244 true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; 244 true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
245 const u8* const host_ptr{cpu_memory.GetPointer(framebuffer_addr)}; 245 const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
246 const std::span<const u8> input_data(host_ptr, size_in_bytes); 246 const std::span<const u8> input_data(host_ptr, size_in_bytes);
247 Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, 247 Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
248 framebuffer.width, framebuffer.height, 1, block_height_log2, 248 framebuffer.width, framebuffer.height, 1, block_height_log2,
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index b70607635..18699610a 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -61,7 +61,7 @@ class RendererOpenGL final : public VideoCore::RendererBase {
61public: 61public:
62 explicit RendererOpenGL(Core::TelemetrySession& telemetry_session_, 62 explicit RendererOpenGL(Core::TelemetrySession& telemetry_session_,
63 Core::Frontend::EmuWindow& emu_window_, 63 Core::Frontend::EmuWindow& emu_window_,
64 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, 64 Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
65 std::unique_ptr<Core::Frontend::GraphicsContext> context_); 65 std::unique_ptr<Core::Frontend::GraphicsContext> context_);
66 ~RendererOpenGL() override; 66 ~RendererOpenGL() override;
67 67
@@ -101,7 +101,7 @@ private:
101 101
102 Core::TelemetrySession& telemetry_session; 102 Core::TelemetrySession& telemetry_session;
103 Core::Frontend::EmuWindow& emu_window; 103 Core::Frontend::EmuWindow& emu_window;
104 Core::Memory::Memory& cpu_memory; 104 Tegra::MaxwellDeviceMemoryManager& device_memory;
105 Tegra::GPU& gpu; 105 Tegra::GPU& gpu;
106 106
107 Device device; 107 Device device;
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index 71c783709..850c34a3a 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -12,7 +12,6 @@
12#include "shader_recompiler/shader_info.h" 12#include "shader_recompiler/shader_info.h"
13#include "video_core/renderer_vulkan/vk_texture_cache.h" 13#include "video_core/renderer_vulkan/vk_texture_cache.h"
14#include "video_core/renderer_vulkan/vk_update_descriptor.h" 14#include "video_core/renderer_vulkan/vk_update_descriptor.h"
15#include "video_core/texture_cache/texture_cache.h"
16#include "video_core/texture_cache/types.h" 15#include "video_core/texture_cache/types.h"
17#include "video_core/vulkan_common/vulkan_device.h" 16#include "video_core/vulkan_common/vulkan_device.h"
18 17
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 100b70918..1631276c6 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -82,10 +82,10 @@ Device CreateDevice(const vk::Instance& instance, const vk::InstanceDispatch& dl
82 82
83RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, 83RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
84 Core::Frontend::EmuWindow& emu_window, 84 Core::Frontend::EmuWindow& emu_window,
85 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, 85 Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
86 std::unique_ptr<Core::Frontend::GraphicsContext> context_) try 86 std::unique_ptr<Core::Frontend::GraphicsContext> context_) try
87 : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_), 87 : RendererBase(emu_window, std::move(context_)), telemetry_session(telemetry_session_),
88 cpu_memory(cpu_memory_), gpu(gpu_), library(OpenLibrary(context.get())), 88 device_memory(device_memory_), gpu(gpu_), library(OpenLibrary(context.get())),
89 instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, 89 instance(CreateInstance(*library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type,
90 Settings::values.renderer_debug.GetValue())), 90 Settings::values.renderer_debug.GetValue())),
91 debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance) 91 debug_messenger(Settings::values.renderer_debug ? CreateDebugUtilsCallback(instance)
@@ -97,9 +97,9 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
97 render_window.GetFramebufferLayout().height), 97 render_window.GetFramebufferLayout().height),
98 present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain, 98 present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
99 surface), 99 surface),
100 blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager, 100 blit_screen(device_memory, render_window, device, memory_allocator, swapchain,
101 scheduler, screen_info), 101 present_manager, scheduler, screen_info),
102 rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator, 102 rasterizer(render_window, gpu, device_memory, screen_info, device, memory_allocator,
103 state_tracker, scheduler) { 103 state_tracker, scheduler) {
104 if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) { 104 if (Settings::values.renderer_force_max_clock.GetValue() && device.ShouldBoostClocks()) {
105 turbo_mode.emplace(instance, dld); 105 turbo_mode.emplace(instance, dld);
@@ -128,7 +128,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
128 screen_info.width = framebuffer->width; 128 screen_info.width = framebuffer->width;
129 screen_info.height = framebuffer->height; 129 screen_info.height = framebuffer->height;
130 130
131 const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset; 131 const DAddr framebuffer_addr = framebuffer->address + framebuffer->offset;
132 const bool use_accelerated = 132 const bool use_accelerated =
133 rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); 133 rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
134 RenderScreenshot(*framebuffer, use_accelerated); 134 RenderScreenshot(*framebuffer, use_accelerated);
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h
index 14e257cf7..11c52287a 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.h
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.h
@@ -7,12 +7,12 @@
7#include <string> 7#include <string>
8#include <variant> 8#include <variant>
9 9
10#include "video_core/renderer_vulkan/vk_rasterizer.h"
11
12#include "common/dynamic_library.h" 10#include "common/dynamic_library.h"
11#include "video_core/host1x/gpu_device_memory_manager.h"
13#include "video_core/renderer_base.h" 12#include "video_core/renderer_base.h"
14#include "video_core/renderer_vulkan/vk_blit_screen.h" 13#include "video_core/renderer_vulkan/vk_blit_screen.h"
15#include "video_core/renderer_vulkan/vk_present_manager.h" 14#include "video_core/renderer_vulkan/vk_present_manager.h"
15#include "video_core/renderer_vulkan/vk_rasterizer.h"
16#include "video_core/renderer_vulkan/vk_scheduler.h" 16#include "video_core/renderer_vulkan/vk_scheduler.h"
17#include "video_core/renderer_vulkan/vk_state_tracker.h" 17#include "video_core/renderer_vulkan/vk_state_tracker.h"
18#include "video_core/renderer_vulkan/vk_swapchain.h" 18#include "video_core/renderer_vulkan/vk_swapchain.h"
@@ -42,7 +42,7 @@ class RendererVulkan final : public VideoCore::RendererBase {
42public: 42public:
43 explicit RendererVulkan(Core::TelemetrySession& telemtry_session, 43 explicit RendererVulkan(Core::TelemetrySession& telemtry_session,
44 Core::Frontend::EmuWindow& emu_window, 44 Core::Frontend::EmuWindow& emu_window,
45 Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu_, 45 Tegra::MaxwellDeviceMemoryManager& device_memory_, Tegra::GPU& gpu_,
46 std::unique_ptr<Core::Frontend::GraphicsContext> context_); 46 std::unique_ptr<Core::Frontend::GraphicsContext> context_);
47 ~RendererVulkan() override; 47 ~RendererVulkan() override;
48 48
@@ -62,7 +62,7 @@ private:
62 void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated); 62 void RenderScreenshot(const Tegra::FramebufferConfig& framebuffer, bool use_accelerated);
63 63
64 Core::TelemetrySession& telemetry_session; 64 Core::TelemetrySession& telemetry_session;
65 Core::Memory::Memory& cpu_memory; 65 Tegra::MaxwellDeviceMemoryManager& device_memory;
66 Tegra::GPU& gpu; 66 Tegra::GPU& gpu;
67 67
68 std::shared_ptr<Common::DynamicLibrary> library; 68 std::shared_ptr<Common::DynamicLibrary> library;
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 60432f5ad..610f27c84 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -14,8 +14,8 @@
14#include "common/settings.h" 14#include "common/settings.h"
15#include "core/core.h" 15#include "core/core.h"
16#include "core/frontend/emu_window.h" 16#include "core/frontend/emu_window.h"
17#include "core/memory.h"
18#include "video_core/gpu.h" 17#include "video_core/gpu.h"
18#include "video_core/host1x/gpu_device_memory_manager.h"
19#include "video_core/host_shaders/fxaa_frag_spv.h" 19#include "video_core/host_shaders/fxaa_frag_spv.h"
20#include "video_core/host_shaders/fxaa_vert_spv.h" 20#include "video_core/host_shaders/fxaa_vert_spv.h"
21#include "video_core/host_shaders/present_bicubic_frag_spv.h" 21#include "video_core/host_shaders/present_bicubic_frag_spv.h"
@@ -121,11 +121,12 @@ struct BlitScreen::BufferData {
121 // Unaligned image data goes here 121 // Unaligned image data goes here
122}; 122};
123 123
124BlitScreen::BlitScreen(Core::Memory::Memory& cpu_memory_, Core::Frontend::EmuWindow& render_window_, 124BlitScreen::BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory_,
125 const Device& device_, MemoryAllocator& memory_allocator_, 125 Core::Frontend::EmuWindow& render_window_, const Device& device_,
126 Swapchain& swapchain_, PresentManager& present_manager_, 126 MemoryAllocator& memory_allocator_, Swapchain& swapchain_,
127 Scheduler& scheduler_, const ScreenInfo& screen_info_) 127 PresentManager& present_manager_, Scheduler& scheduler_,
128 : cpu_memory{cpu_memory_}, render_window{render_window_}, device{device_}, 128 const ScreenInfo& screen_info_)
129 : device_memory{device_memory_}, render_window{render_window_}, device{device_},
129 memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_}, 130 memory_allocator{memory_allocator_}, swapchain{swapchain_}, present_manager{present_manager_},
130 scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} { 131 scheduler{scheduler_}, image_count{swapchain.GetImageCount()}, screen_info{screen_info_} {
131 resource_ticks.resize(image_count); 132 resource_ticks.resize(image_count);
@@ -219,8 +220,8 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
219 if (!use_accelerated) { 220 if (!use_accelerated) {
220 const u64 image_offset = GetRawImageOffset(framebuffer); 221 const u64 image_offset = GetRawImageOffset(framebuffer);
221 222
222 const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset; 223 const DAddr framebuffer_addr = framebuffer.address + framebuffer.offset;
223 const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr); 224 const u8* const host_ptr = device_memory.GetPointer<u8>(framebuffer_addr);
224 225
225 // TODO(Rodrigo): Read this from HLE 226 // TODO(Rodrigo): Read this from HLE
226 constexpr u32 block_height_log2 = 4; 227 constexpr u32 block_height_log2 = 4;
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.h b/src/video_core/renderer_vulkan/vk_blit_screen.h
index 78b32416d..3eff76009 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.h
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.h
@@ -6,6 +6,7 @@
6#include <memory> 6#include <memory>
7 7
8#include "core/frontend/framebuffer_layout.h" 8#include "core/frontend/framebuffer_layout.h"
9#include "video_core/host1x/gpu_device_memory_manager.h"
9#include "video_core/vulkan_common/vulkan_memory_allocator.h" 10#include "video_core/vulkan_common/vulkan_memory_allocator.h"
10#include "video_core/vulkan_common/vulkan_wrapper.h" 11#include "video_core/vulkan_common/vulkan_wrapper.h"
11 12
@@ -13,10 +14,6 @@ namespace Core {
13class System; 14class System;
14} 15}
15 16
16namespace Core::Memory {
17class Memory;
18}
19
20namespace Core::Frontend { 17namespace Core::Frontend {
21class EmuWindow; 18class EmuWindow;
22} 19}
@@ -56,8 +53,9 @@ struct ScreenInfo {
56 53
57class BlitScreen { 54class BlitScreen {
58public: 55public:
59 explicit BlitScreen(Core::Memory::Memory& cpu_memory, Core::Frontend::EmuWindow& render_window, 56 explicit BlitScreen(Tegra::MaxwellDeviceMemoryManager& device_memory,
60 const Device& device, MemoryAllocator& memory_manager, Swapchain& swapchain, 57 Core::Frontend::EmuWindow& render_window, const Device& device,
58 MemoryAllocator& memory_manager, Swapchain& swapchain,
61 PresentManager& present_manager, Scheduler& scheduler, 59 PresentManager& present_manager, Scheduler& scheduler,
62 const ScreenInfo& screen_info); 60 const ScreenInfo& screen_info);
63 ~BlitScreen(); 61 ~BlitScreen();
@@ -109,7 +107,7 @@ private:
109 u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const; 107 u64 CalculateBufferSize(const Tegra::FramebufferConfig& framebuffer) const;
110 u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer) const; 108 u64 GetRawImageOffset(const Tegra::FramebufferConfig& framebuffer) const;
111 109
112 Core::Memory::Memory& cpu_memory; 110 Tegra::MaxwellDeviceMemoryManager& device_memory;
113 Core::Frontend::EmuWindow& render_window; 111 Core::Frontend::EmuWindow& render_window;
114 const Device& device; 112 const Device& device;
115 MemoryAllocator& memory_allocator; 113 MemoryAllocator& memory_allocator;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 3c61799fa..31001d142 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -79,7 +79,7 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo
79} // Anonymous namespace 79} // Anonymous namespace
80 80
81Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_params) 81Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_params)
82 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(null_params), tracker{4096} { 82 : VideoCommon::BufferBase(null_params), tracker{4096} {
83 if (runtime.device.HasNullDescriptor()) { 83 if (runtime.device.HasNullDescriptor()) {
84 return; 84 return;
85 } 85 }
@@ -88,11 +88,9 @@ Buffer::Buffer(BufferCacheRuntime& runtime, VideoCommon::NullBufferParams null_p
88 is_null = true; 88 is_null = true;
89} 89}
90 90
91Buffer::Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, 91Buffer::Buffer(BufferCacheRuntime& runtime, DAddr cpu_addr_, u64 size_bytes_)
92 VAddr cpu_addr_, u64 size_bytes_) 92 : VideoCommon::BufferBase(cpu_addr_, size_bytes_), device{&runtime.device},
93 : VideoCommon::BufferBase<VideoCore::RasterizerInterface>(rasterizer_, cpu_addr_, size_bytes_), 93 buffer{CreateBuffer(*device, runtime.memory_allocator, SizeBytes())}, tracker{SizeBytes()} {
94 device{&runtime.device}, buffer{CreateBuffer(*device, runtime.memory_allocator, SizeBytes())},
95 tracker{SizeBytes()} {
96 if (runtime.device.HasDebuggingToolAttached()) { 94 if (runtime.device.HasDebuggingToolAttached()) {
97 buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str()); 95 buffer.SetObjectNameEXT(fmt::format("Buffer 0x{:x}", CpuAddr()).c_str());
98 } 96 }
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index dc300d7cb..e273f4988 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -23,11 +23,10 @@ struct HostVertexBinding;
23 23
24class BufferCacheRuntime; 24class BufferCacheRuntime;
25 25
26class Buffer : public VideoCommon::BufferBase<VideoCore::RasterizerInterface> { 26class Buffer : public VideoCommon::BufferBase {
27public: 27public:
28 explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params); 28 explicit Buffer(BufferCacheRuntime&, VideoCommon::NullBufferParams null_params);
29 explicit Buffer(BufferCacheRuntime& runtime, VideoCore::RasterizerInterface& rasterizer_, 29 explicit Buffer(BufferCacheRuntime& runtime, VAddr cpu_addr_, u64 size_bytes_);
30 VAddr cpu_addr_, u64 size_bytes_);
31 30
32 [[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format); 31 [[nodiscard]] VkBufferView View(u32 offset, u32 size, VideoCore::Surface::PixelFormat format);
33 32
@@ -173,7 +172,7 @@ struct BufferCacheParams {
173 using Runtime = Vulkan::BufferCacheRuntime; 172 using Runtime = Vulkan::BufferCacheRuntime;
174 using Buffer = Vulkan::Buffer; 173 using Buffer = Vulkan::Buffer;
175 using Async_Buffer = Vulkan::StagingBufferRef; 174 using Async_Buffer = Vulkan::StagingBufferRef;
176 using MemoryTracker = VideoCommon::MemoryTrackerBase<VideoCore::RasterizerInterface>; 175 using MemoryTracker = VideoCommon::MemoryTrackerBase<Tegra::MaxwellDeviceMemoryManager>;
177 176
178 static constexpr bool IS_OPENGL = false; 177 static constexpr bool IS_OPENGL = false;
179 static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = false; 178 static constexpr bool HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS = false;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index f2fd2670f..ec6b3a4b0 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -19,6 +19,7 @@
19#include "video_core/renderer_vulkan/vk_texture_cache.h" 19#include "video_core/renderer_vulkan/vk_texture_cache.h"
20#include "video_core/renderer_vulkan/vk_update_descriptor.h" 20#include "video_core/renderer_vulkan/vk_update_descriptor.h"
21#include "video_core/shader_notify.h" 21#include "video_core/shader_notify.h"
22#include "video_core/texture_cache/texture_cache.h"
22#include "video_core/vulkan_common/vulkan_device.h" 23#include "video_core/vulkan_common/vulkan_device.h"
23 24
24#if defined(_MSC_VER) && defined(NDEBUG) 25#if defined(_MSC_VER) && defined(NDEBUG)
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index d1841198d..1e1821b10 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -30,7 +30,6 @@
30#include "video_core/renderer_vulkan/vk_compute_pipeline.h" 30#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
31#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 31#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
32#include "video_core/renderer_vulkan/vk_pipeline_cache.h" 32#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
33#include "video_core/renderer_vulkan/vk_rasterizer.h"
34#include "video_core/renderer_vulkan/vk_scheduler.h" 33#include "video_core/renderer_vulkan/vk_scheduler.h"
35#include "video_core/renderer_vulkan/vk_shader_util.h" 34#include "video_core/renderer_vulkan/vk_shader_util.h"
36#include "video_core/renderer_vulkan/vk_update_descriptor.h" 35#include "video_core/renderer_vulkan/vk_update_descriptor.h"
@@ -299,12 +298,13 @@ bool GraphicsPipelineCacheKey::operator==(const GraphicsPipelineCacheKey& rhs) c
299 return std::memcmp(&rhs, this, Size()) == 0; 298 return std::memcmp(&rhs, this, Size()) == 0;
300} 299}
301 300
302PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device_, 301PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
303 Scheduler& scheduler_, DescriptorPool& descriptor_pool_, 302 const Device& device_, Scheduler& scheduler_,
303 DescriptorPool& descriptor_pool_,
304 GuestDescriptorQueue& guest_descriptor_queue_, 304 GuestDescriptorQueue& guest_descriptor_queue_,
305 RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_, 305 RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_,
306 TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_) 306 TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_)
307 : VideoCommon::ShaderCache{rasterizer_}, device{device_}, scheduler{scheduler_}, 307 : VideoCommon::ShaderCache{device_memory_}, device{device_}, scheduler{scheduler_},
308 descriptor_pool{descriptor_pool_}, guest_descriptor_queue{guest_descriptor_queue_}, 308 descriptor_pool{descriptor_pool_}, guest_descriptor_queue{guest_descriptor_queue_},
309 render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_}, 309 render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_},
310 texture_cache{texture_cache_}, shader_notify{shader_notify_}, 310 texture_cache{texture_cache_}, shader_notify{shader_notify_},
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index e323ea0fd..797700128 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -20,6 +20,7 @@
20#include "shader_recompiler/object_pool.h" 20#include "shader_recompiler/object_pool.h"
21#include "shader_recompiler/profile.h" 21#include "shader_recompiler/profile.h"
22#include "video_core/engines/maxwell_3d.h" 22#include "video_core/engines/maxwell_3d.h"
23#include "video_core/host1x/gpu_device_memory_manager.h"
23#include "video_core/renderer_vulkan/fixed_pipeline_state.h" 24#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
24#include "video_core/renderer_vulkan/vk_buffer_cache.h" 25#include "video_core/renderer_vulkan/vk_buffer_cache.h"
25#include "video_core/renderer_vulkan/vk_compute_pipeline.h" 26#include "video_core/renderer_vulkan/vk_compute_pipeline.h"
@@ -79,7 +80,6 @@ class ComputePipeline;
79class DescriptorPool; 80class DescriptorPool;
80class Device; 81class Device;
81class PipelineStatistics; 82class PipelineStatistics;
82class RasterizerVulkan;
83class RenderPassCache; 83class RenderPassCache;
84class Scheduler; 84class Scheduler;
85 85
@@ -99,8 +99,8 @@ struct ShaderPools {
99 99
100class PipelineCache : public VideoCommon::ShaderCache { 100class PipelineCache : public VideoCommon::ShaderCache {
101public: 101public:
102 explicit PipelineCache(RasterizerVulkan& rasterizer, const Device& device, Scheduler& scheduler, 102 explicit PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, const Device& device,
103 DescriptorPool& descriptor_pool, 103 Scheduler& scheduler, DescriptorPool& descriptor_pool,
104 GuestDescriptorQueue& guest_descriptor_queue, 104 GuestDescriptorQueue& guest_descriptor_queue,
105 RenderPassCache& render_pass_cache, BufferCache& buffer_cache, 105 RenderPassCache& render_pass_cache, BufferCache& buffer_cache,
106 TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_); 106 TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_);
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index 792ed9615..5e7518d96 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -329,7 +329,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
329 // to account for that. 329 // to account for that.
330 const bool is_suboptimal = swapchain.NeedsRecreation(); 330 const bool is_suboptimal = swapchain.NeedsRecreation();
331 const bool size_changed = 331 const bool size_changed =
332 swapchain.GetWidth() < frame->width || swapchain.GetHeight() < frame->height; 332 swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;
333 if (is_suboptimal || size_changed) { 333 if (is_suboptimal || size_changed) {
334 RecreateSwapchain(frame); 334 RecreateSwapchain(frame);
335 } 335 }
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp
index ad4caf688..7cbc9c73c 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp
@@ -13,9 +13,10 @@
13 13
14#include "common/bit_util.h" 14#include "common/bit_util.h"
15#include "common/common_types.h" 15#include "common/common_types.h"
16#include "core/memory.h"
17#include "video_core/engines/draw_manager.h" 16#include "video_core/engines/draw_manager.h"
17#include "video_core/host1x/gpu_device_memory_manager.h"
18#include "video_core/query_cache/query_cache.h" 18#include "video_core/query_cache/query_cache.h"
19#include "video_core/rasterizer_interface.h"
19#include "video_core/renderer_vulkan/vk_buffer_cache.h" 20#include "video_core/renderer_vulkan/vk_buffer_cache.h"
20#include "video_core/renderer_vulkan/vk_compute_pass.h" 21#include "video_core/renderer_vulkan/vk_compute_pass.h"
21#include "video_core/renderer_vulkan/vk_query_cache.h" 22#include "video_core/renderer_vulkan/vk_query_cache.h"
@@ -102,7 +103,7 @@ private:
102using BaseStreamer = VideoCommon::SimpleStreamer<VideoCommon::HostQueryBase>; 103using BaseStreamer = VideoCommon::SimpleStreamer<VideoCommon::HostQueryBase>;
103 104
104struct HostSyncValues { 105struct HostSyncValues {
105 VAddr address; 106 DAddr address;
106 size_t size; 107 size_t size;
107 size_t offset; 108 size_t offset;
108 109
@@ -317,7 +318,7 @@ public:
317 pending_sync.clear(); 318 pending_sync.clear();
318 } 319 }
319 320
320 size_t WriteCounter(VAddr address, bool has_timestamp, u32 value, 321 size_t WriteCounter(DAddr address, bool has_timestamp, u32 value,
321 [[maybe_unused]] std::optional<u32> subreport) override { 322 [[maybe_unused]] std::optional<u32> subreport) override {
322 PauseCounter(); 323 PauseCounter();
323 auto index = BuildQuery(); 324 auto index = BuildQuery();
@@ -738,7 +739,7 @@ public:
738 pending_sync.clear(); 739 pending_sync.clear();
739 } 740 }
740 741
741 size_t WriteCounter(VAddr address, bool has_timestamp, u32 value, 742 size_t WriteCounter(DAddr address, bool has_timestamp, u32 value,
742 std::optional<u32> subreport_) override { 743 std::optional<u32> subreport_) override {
743 auto index = BuildQuery(); 744 auto index = BuildQuery();
744 auto* new_query = GetQuery(index); 745 auto* new_query = GetQuery(index);
@@ -769,9 +770,9 @@ public:
769 return index; 770 return index;
770 } 771 }
771 772
772 std::optional<std::pair<VAddr, size_t>> GetLastQueryStream(size_t stream) { 773 std::optional<std::pair<DAddr, size_t>> GetLastQueryStream(size_t stream) {
773 if (last_queries[stream] != 0) { 774 if (last_queries[stream] != 0) {
774 std::pair<VAddr, size_t> result(last_queries[stream], last_queries_stride[stream]); 775 std::pair<DAddr, size_t> result(last_queries[stream], last_queries_stride[stream]);
775 return result; 776 return result;
776 } 777 }
777 return std::nullopt; 778 return std::nullopt;
@@ -974,7 +975,7 @@ private:
974 size_t buffers_count{}; 975 size_t buffers_count{};
975 std::array<VkBuffer, NUM_STREAMS> counter_buffers{}; 976 std::array<VkBuffer, NUM_STREAMS> counter_buffers{};
976 std::array<VkDeviceSize, NUM_STREAMS> offsets{}; 977 std::array<VkDeviceSize, NUM_STREAMS> offsets{};
977 std::array<VAddr, NUM_STREAMS> last_queries; 978 std::array<DAddr, NUM_STREAMS> last_queries;
978 std::array<size_t, NUM_STREAMS> last_queries_stride; 979 std::array<size_t, NUM_STREAMS> last_queries_stride;
979 Maxwell3D::Regs::PrimitiveTopology out_topology; 980 Maxwell3D::Regs::PrimitiveTopology out_topology;
980 u64 streams_mask; 981 u64 streams_mask;
@@ -987,7 +988,7 @@ public:
987 : VideoCommon::QueryBase(0, VideoCommon::QueryFlagBits::IsHostManaged, 0) {} 988 : VideoCommon::QueryBase(0, VideoCommon::QueryFlagBits::IsHostManaged, 0) {}
988 989
989 // Parameterized constructor 990 // Parameterized constructor
990 PrimitivesQueryBase(bool has_timestamp, VAddr address) 991 PrimitivesQueryBase(bool has_timestamp, DAddr address)
991 : VideoCommon::QueryBase(address, VideoCommon::QueryFlagBits::IsHostManaged, 0) { 992 : VideoCommon::QueryBase(address, VideoCommon::QueryFlagBits::IsHostManaged, 0) {
992 if (has_timestamp) { 993 if (has_timestamp) {
993 flags |= VideoCommon::QueryFlagBits::HasTimestamp; 994 flags |= VideoCommon::QueryFlagBits::HasTimestamp;
@@ -995,7 +996,7 @@ public:
995 } 996 }
996 997
997 u64 stride{}; 998 u64 stride{};
998 VAddr dependant_address{}; 999 DAddr dependant_address{};
999 Maxwell3D::Regs::PrimitiveTopology topology{Maxwell3D::Regs::PrimitiveTopology::Points}; 1000 Maxwell3D::Regs::PrimitiveTopology topology{Maxwell3D::Regs::PrimitiveTopology::Points};
1000 size_t dependant_index{}; 1001 size_t dependant_index{};
1001 bool dependant_manage{}; 1002 bool dependant_manage{};
@@ -1005,15 +1006,15 @@ class PrimitivesSucceededStreamer : public VideoCommon::SimpleStreamer<Primitive
1005public: 1006public:
1006 explicit PrimitivesSucceededStreamer(size_t id_, QueryCacheRuntime& runtime_, 1007 explicit PrimitivesSucceededStreamer(size_t id_, QueryCacheRuntime& runtime_,
1007 TFBCounterStreamer& tfb_streamer_, 1008 TFBCounterStreamer& tfb_streamer_,
1008 Core::Memory::Memory& cpu_memory_) 1009 Tegra::MaxwellDeviceMemoryManager& device_memory_)
1009 : VideoCommon::SimpleStreamer<PrimitivesQueryBase>(id_), runtime{runtime_}, 1010 : VideoCommon::SimpleStreamer<PrimitivesQueryBase>(id_), runtime{runtime_},
1010 tfb_streamer{tfb_streamer_}, cpu_memory{cpu_memory_} { 1011 tfb_streamer{tfb_streamer_}, device_memory{device_memory_} {
1011 MakeDependent(&tfb_streamer); 1012 MakeDependent(&tfb_streamer);
1012 } 1013 }
1013 1014
1014 ~PrimitivesSucceededStreamer() = default; 1015 ~PrimitivesSucceededStreamer() = default;
1015 1016
1016 size_t WriteCounter(VAddr address, bool has_timestamp, u32 value, 1017 size_t WriteCounter(DAddr address, bool has_timestamp, u32 value,
1017 std::optional<u32> subreport_) override { 1018 std::optional<u32> subreport_) override {
1018 auto index = BuildQuery(); 1019 auto index = BuildQuery();
1019 auto* new_query = GetQuery(index); 1020 auto* new_query = GetQuery(index);
@@ -1063,6 +1064,8 @@ public:
1063 } 1064 }
1064 }); 1065 });
1065 } 1066 }
1067 auto* ptr = device_memory.GetPointer<u8>(new_query->dependant_address);
1068 ASSERT(ptr != nullptr);
1066 1069
1067 new_query->dependant_manage = must_manage_dependance; 1070 new_query->dependant_manage = must_manage_dependance;
1068 pending_flush_queries.push_back(index); 1071 pending_flush_queries.push_back(index);
@@ -1100,7 +1103,7 @@ public:
1100 num_vertices = dependant_query->value / query->stride; 1103 num_vertices = dependant_query->value / query->stride;
1101 tfb_streamer.Free(query->dependant_index); 1104 tfb_streamer.Free(query->dependant_index);
1102 } else { 1105 } else {
1103 u8* pointer = cpu_memory.GetPointer(query->dependant_address); 1106 u8* pointer = device_memory.GetPointer<u8>(query->dependant_address);
1104 u32 result; 1107 u32 result;
1105 std::memcpy(&result, pointer, sizeof(u32)); 1108 std::memcpy(&result, pointer, sizeof(u32));
1106 num_vertices = static_cast<u64>(result) / query->stride; 1109 num_vertices = static_cast<u64>(result) / query->stride;
@@ -1137,7 +1140,7 @@ public:
1137private: 1140private:
1138 QueryCacheRuntime& runtime; 1141 QueryCacheRuntime& runtime;
1139 TFBCounterStreamer& tfb_streamer; 1142 TFBCounterStreamer& tfb_streamer;
1140 Core::Memory::Memory& cpu_memory; 1143 Tegra::MaxwellDeviceMemoryManager& device_memory;
1141 1144
1142 // syncing queue 1145 // syncing queue
1143 std::vector<size_t> pending_sync; 1146 std::vector<size_t> pending_sync;
@@ -1152,12 +1155,13 @@ private:
1152 1155
1153struct QueryCacheRuntimeImpl { 1156struct QueryCacheRuntimeImpl {
1154 QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_, 1157 QueryCacheRuntimeImpl(QueryCacheRuntime& runtime, VideoCore::RasterizerInterface* rasterizer_,
1155 Core::Memory::Memory& cpu_memory_, Vulkan::BufferCache& buffer_cache_, 1158 Tegra::MaxwellDeviceMemoryManager& device_memory_,
1156 const Device& device_, const MemoryAllocator& memory_allocator_, 1159 Vulkan::BufferCache& buffer_cache_, const Device& device_,
1157 Scheduler& scheduler_, StagingBufferPool& staging_pool_, 1160 const MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
1161 StagingBufferPool& staging_pool_,
1158 ComputePassDescriptorQueue& compute_pass_descriptor_queue, 1162 ComputePassDescriptorQueue& compute_pass_descriptor_queue,
1159 DescriptorPool& descriptor_pool) 1163 DescriptorPool& descriptor_pool)
1160 : rasterizer{rasterizer_}, cpu_memory{cpu_memory_}, 1164 : rasterizer{rasterizer_}, device_memory{device_memory_},
1161 buffer_cache{buffer_cache_}, device{device_}, 1165 buffer_cache{buffer_cache_}, device{device_},
1162 memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_}, 1166 memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_},
1163 guest_streamer(0, runtime), 1167 guest_streamer(0, runtime),
@@ -1168,7 +1172,7 @@ struct QueryCacheRuntimeImpl {
1168 scheduler, memory_allocator, staging_pool), 1172 scheduler, memory_allocator, staging_pool),
1169 primitives_succeeded_streamer( 1173 primitives_succeeded_streamer(
1170 static_cast<size_t>(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer, 1174 static_cast<size_t>(QueryType::StreamingPrimitivesSucceeded), runtime, tfb_streamer,
1171 cpu_memory_), 1175 device_memory_),
1172 primitives_needed_minus_succeeded_streamer( 1176 primitives_needed_minus_succeeded_streamer(
1173 static_cast<size_t>(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u), 1177 static_cast<size_t>(QueryType::StreamingPrimitivesNeededMinusSucceeded), runtime, 0u),
1174 hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} { 1178 hcr_setup{}, hcr_is_set{}, is_hcr_running{}, maxwell3d{} {
@@ -1195,7 +1199,7 @@ struct QueryCacheRuntimeImpl {
1195 } 1199 }
1196 1200
1197 VideoCore::RasterizerInterface* rasterizer; 1201 VideoCore::RasterizerInterface* rasterizer;
1198 Core::Memory::Memory& cpu_memory; 1202 Tegra::MaxwellDeviceMemoryManager& device_memory;
1199 Vulkan::BufferCache& buffer_cache; 1203 Vulkan::BufferCache& buffer_cache;
1200 1204
1201 const Device& device; 1205 const Device& device;
@@ -1210,7 +1214,7 @@ struct QueryCacheRuntimeImpl {
1210 PrimitivesSucceededStreamer primitives_succeeded_streamer; 1214 PrimitivesSucceededStreamer primitives_succeeded_streamer;
1211 VideoCommon::StubStreamer<QueryCacheParams> primitives_needed_minus_succeeded_streamer; 1215 VideoCommon::StubStreamer<QueryCacheParams> primitives_needed_minus_succeeded_streamer;
1212 1216
1213 std::vector<std::pair<VAddr, VAddr>> little_cache; 1217 std::vector<std::pair<DAddr, DAddr>> little_cache;
1214 std::vector<std::pair<VkBuffer, VkDeviceSize>> buffers_to_upload_to; 1218 std::vector<std::pair<VkBuffer, VkDeviceSize>> buffers_to_upload_to;
1215 std::vector<size_t> redirect_cache; 1219 std::vector<size_t> redirect_cache;
1216 std::vector<std::vector<VkBufferCopy>> copies_setup; 1220 std::vector<std::vector<VkBufferCopy>> copies_setup;
@@ -1229,14 +1233,14 @@ struct QueryCacheRuntimeImpl {
1229}; 1233};
1230 1234
1231QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, 1235QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer,
1232 Core::Memory::Memory& cpu_memory_, 1236 Tegra::MaxwellDeviceMemoryManager& device_memory_,
1233 Vulkan::BufferCache& buffer_cache_, const Device& device_, 1237 Vulkan::BufferCache& buffer_cache_, const Device& device_,
1234 const MemoryAllocator& memory_allocator_, 1238 const MemoryAllocator& memory_allocator_,
1235 Scheduler& scheduler_, StagingBufferPool& staging_pool_, 1239 Scheduler& scheduler_, StagingBufferPool& staging_pool_,
1236 ComputePassDescriptorQueue& compute_pass_descriptor_queue, 1240 ComputePassDescriptorQueue& compute_pass_descriptor_queue,
1237 DescriptorPool& descriptor_pool) { 1241 DescriptorPool& descriptor_pool) {
1238 impl = std::make_unique<QueryCacheRuntimeImpl>( 1242 impl = std::make_unique<QueryCacheRuntimeImpl>(
1239 *this, rasterizer, cpu_memory_, buffer_cache_, device_, memory_allocator_, scheduler_, 1243 *this, rasterizer, device_memory_, buffer_cache_, device_, memory_allocator_, scheduler_,
1240 staging_pool_, compute_pass_descriptor_queue, descriptor_pool); 1244 staging_pool_, compute_pass_descriptor_queue, descriptor_pool);
1241} 1245}
1242 1246
@@ -1309,7 +1313,7 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo
1309 ResumeHostConditionalRendering(); 1313 ResumeHostConditionalRendering();
1310} 1314}
1311 1315
1312void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(VAddr address, bool is_equal) { 1316void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal) {
1313 VkBuffer to_resolve; 1317 VkBuffer to_resolve;
1314 u32 to_resolve_offset; 1318 u32 to_resolve_offset;
1315 { 1319 {
@@ -1350,11 +1354,11 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
1350 return false; 1354 return false;
1351 } 1355 }
1352 1356
1353 const auto check_in_bc = [&](VAddr address) { 1357 const auto check_in_bc = [&](DAddr address) {
1354 return impl->buffer_cache.IsRegionGpuModified(address, 8); 1358 return impl->buffer_cache.IsRegionGpuModified(address, 8);
1355 }; 1359 };
1356 const auto check_value = [&](VAddr address) { 1360 const auto check_value = [&](DAddr address) {
1357 u8* ptr = impl->cpu_memory.GetPointer(address); 1361 u8* ptr = impl->device_memory.GetPointer<u8>(address);
1358 u64 value{}; 1362 u64 value{};
1359 std::memcpy(&value, ptr, sizeof(value)); 1363 std::memcpy(&value, ptr, sizeof(value));
1360 return value == 0; 1364 return value == 0;
@@ -1477,8 +1481,8 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba
1477 for (auto& sync_val : values) { 1481 for (auto& sync_val : values) {
1478 total_size += sync_val.size; 1482 total_size += sync_val.size;
1479 bool found = false; 1483 bool found = false;
1480 VAddr base = Common::AlignDown(sync_val.address, Core::Memory::YUZU_PAGESIZE); 1484 DAddr base = Common::AlignDown(sync_val.address, Core::DEVICE_PAGESIZE);
1481 VAddr base_end = base + Core::Memory::YUZU_PAGESIZE; 1485 DAddr base_end = base + Core::DEVICE_PAGESIZE;
1482 for (size_t i = 0; i < impl->little_cache.size(); i++) { 1486 for (size_t i = 0; i < impl->little_cache.size(); i++) {
1483 const auto set_found = [&] { 1487 const auto set_found = [&] {
1484 impl->redirect_cache.push_back(i); 1488 impl->redirect_cache.push_back(i);
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.h b/src/video_core/renderer_vulkan/vk_query_cache.h
index e9a1ea169..f6151123e 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.h
+++ b/src/video_core/renderer_vulkan/vk_query_cache.h
@@ -27,7 +27,7 @@ struct QueryCacheRuntimeImpl;
27class QueryCacheRuntime { 27class QueryCacheRuntime {
28public: 28public:
29 explicit QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, 29 explicit QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer,
30 Core::Memory::Memory& cpu_memory_, 30 Tegra::MaxwellDeviceMemoryManager& device_memory_,
31 Vulkan::BufferCache& buffer_cache_, const Device& device_, 31 Vulkan::BufferCache& buffer_cache_, const Device& device_,
32 const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, 32 const MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
33 StagingBufferPool& staging_pool_, 33 StagingBufferPool& staging_pool_,
@@ -61,7 +61,7 @@ public:
61 61
62private: 62private:
63 void HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal); 63 void HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal);
64 void HostConditionalRenderingCompareBCImpl(VAddr address, bool is_equal); 64 void HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal);
65 friend struct QueryCacheRuntimeImpl; 65 friend struct QueryCacheRuntimeImpl;
66 std::unique_ptr<QueryCacheRuntimeImpl> impl; 66 std::unique_ptr<QueryCacheRuntimeImpl> impl;
67}; 67};
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 241fc34be..5bf41b81f 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -18,6 +18,7 @@
18#include "video_core/engines/draw_manager.h" 18#include "video_core/engines/draw_manager.h"
19#include "video_core/engines/kepler_compute.h" 19#include "video_core/engines/kepler_compute.h"
20#include "video_core/engines/maxwell_3d.h" 20#include "video_core/engines/maxwell_3d.h"
21#include "video_core/host1x/gpu_device_memory_manager.h"
21#include "video_core/renderer_vulkan/blit_image.h" 22#include "video_core/renderer_vulkan/blit_image.h"
22#include "video_core/renderer_vulkan/fixed_pipeline_state.h" 23#include "video_core/renderer_vulkan/fixed_pipeline_state.h"
23#include "video_core/renderer_vulkan/maxwell_to_vk.h" 24#include "video_core/renderer_vulkan/maxwell_to_vk.h"
@@ -163,10 +164,11 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances,
163} // Anonymous namespace 164} // Anonymous namespace
164 165
165RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 166RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
166 Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_, 167 Tegra::MaxwellDeviceMemoryManager& device_memory_,
167 const Device& device_, MemoryAllocator& memory_allocator_, 168 ScreenInfo& screen_info_, const Device& device_,
168 StateTracker& state_tracker_, Scheduler& scheduler_) 169 MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
169 : RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, screen_info{screen_info_}, device{device_}, 170 Scheduler& scheduler_)
171 : gpu{gpu_}, device_memory{device_memory_}, screen_info{screen_info_}, device{device_},
170 memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_}, 172 memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
171 staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler), 173 staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
172 guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler), 174 guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler),
@@ -174,14 +176,14 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
174 texture_cache_runtime{ 176 texture_cache_runtime{
175 device, scheduler, memory_allocator, staging_pool, 177 device, scheduler, memory_allocator, staging_pool,
176 blit_image, render_pass_cache, descriptor_pool, compute_pass_descriptor_queue}, 178 blit_image, render_pass_cache, descriptor_pool, compute_pass_descriptor_queue},
177 texture_cache(texture_cache_runtime, *this), 179 texture_cache(texture_cache_runtime, device_memory),
178 buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool, 180 buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool,
179 guest_descriptor_queue, compute_pass_descriptor_queue, descriptor_pool), 181 guest_descriptor_queue, compute_pass_descriptor_queue, descriptor_pool),
180 buffer_cache(*this, cpu_memory_, buffer_cache_runtime), 182 buffer_cache(device_memory, buffer_cache_runtime),
181 query_cache_runtime(this, cpu_memory_, buffer_cache, device, memory_allocator, scheduler, 183 query_cache_runtime(this, device_memory, buffer_cache, device, memory_allocator, scheduler,
182 staging_pool, compute_pass_descriptor_queue, descriptor_pool), 184 staging_pool, compute_pass_descriptor_queue, descriptor_pool),
183 query_cache(gpu, *this, cpu_memory_, query_cache_runtime), 185 query_cache(gpu, *this, device_memory, query_cache_runtime),
184 pipeline_cache(*this, device, scheduler, descriptor_pool, guest_descriptor_queue, 186 pipeline_cache(device_memory, device, scheduler, descriptor_pool, guest_descriptor_queue,
185 render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()), 187 render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()),
186 accelerate_dma(buffer_cache, texture_cache, scheduler), 188 accelerate_dma(buffer_cache, texture_cache, scheduler),
187 fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), 189 fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler),
@@ -508,7 +510,7 @@ void Vulkan::RasterizerVulkan::DisableGraphicsUniformBuffer(size_t stage, u32 in
508 510
509void RasterizerVulkan::FlushAll() {} 511void RasterizerVulkan::FlushAll() {}
510 512
511void RasterizerVulkan::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { 513void RasterizerVulkan::FlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
512 if (addr == 0 || size == 0) { 514 if (addr == 0 || size == 0) {
513 return; 515 return;
514 } 516 }
@@ -525,7 +527,7 @@ void RasterizerVulkan::FlushRegion(VAddr addr, u64 size, VideoCommon::CacheType
525 } 527 }
526} 528}
527 529
528bool RasterizerVulkan::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { 530bool RasterizerVulkan::MustFlushRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
529 if ((True(which & VideoCommon::CacheType::BufferCache))) { 531 if ((True(which & VideoCommon::CacheType::BufferCache))) {
530 std::scoped_lock lock{buffer_cache.mutex}; 532 std::scoped_lock lock{buffer_cache.mutex};
531 if (buffer_cache.IsRegionGpuModified(addr, size)) { 533 if (buffer_cache.IsRegionGpuModified(addr, size)) {
@@ -542,7 +544,7 @@ bool RasterizerVulkan::MustFlushRegion(VAddr addr, u64 size, VideoCommon::CacheT
542 return false; 544 return false;
543} 545}
544 546
545VideoCore::RasterizerDownloadArea RasterizerVulkan::GetFlushArea(VAddr addr, u64 size) { 547VideoCore::RasterizerDownloadArea RasterizerVulkan::GetFlushArea(DAddr addr, u64 size) {
546 { 548 {
547 std::scoped_lock lock{texture_cache.mutex}; 549 std::scoped_lock lock{texture_cache.mutex};
548 auto area = texture_cache.GetFlushArea(addr, size); 550 auto area = texture_cache.GetFlushArea(addr, size);
@@ -551,14 +553,14 @@ VideoCore::RasterizerDownloadArea RasterizerVulkan::GetFlushArea(VAddr addr, u64
551 } 553 }
552 } 554 }
553 VideoCore::RasterizerDownloadArea new_area{ 555 VideoCore::RasterizerDownloadArea new_area{
554 .start_address = Common::AlignDown(addr, Core::Memory::YUZU_PAGESIZE), 556 .start_address = Common::AlignDown(addr, Core::DEVICE_PAGESIZE),
555 .end_address = Common::AlignUp(addr + size, Core::Memory::YUZU_PAGESIZE), 557 .end_address = Common::AlignUp(addr + size, Core::DEVICE_PAGESIZE),
556 .preemtive = true, 558 .preemtive = true,
557 }; 559 };
558 return new_area; 560 return new_area;
559} 561}
560 562
561void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size, VideoCommon::CacheType which) { 563void RasterizerVulkan::InvalidateRegion(DAddr addr, u64 size, VideoCommon::CacheType which) {
562 if (addr == 0 || size == 0) { 564 if (addr == 0 || size == 0) {
563 return; 565 return;
564 } 566 }
@@ -578,7 +580,7 @@ void RasterizerVulkan::InvalidateRegion(VAddr addr, u64 size, VideoCommon::Cache
578 } 580 }
579} 581}
580 582
581void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) { 583void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<DAddr, std::size_t>> sequences) {
582 { 584 {
583 std::scoped_lock lock{texture_cache.mutex}; 585 std::scoped_lock lock{texture_cache.mutex};
584 for (const auto& [addr, size] : sequences) { 586 for (const auto& [addr, size] : sequences) {
@@ -599,7 +601,7 @@ void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<VAddr, std::s
599 } 601 }
600} 602}
601 603
602bool RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) { 604bool RasterizerVulkan::OnCPUWrite(DAddr addr, u64 size) {
603 if (addr == 0 || size == 0) { 605 if (addr == 0 || size == 0) {
604 return false; 606 return false;
605 } 607 }
@@ -620,7 +622,7 @@ bool RasterizerVulkan::OnCPUWrite(VAddr addr, u64 size) {
620 return false; 622 return false;
621} 623}
622 624
623void RasterizerVulkan::OnCacheInvalidation(VAddr addr, u64 size) { 625void RasterizerVulkan::OnCacheInvalidation(DAddr addr, u64 size) {
624 if (addr == 0 || size == 0) { 626 if (addr == 0 || size == 0) {
625 return; 627 return;
626 } 628 }
@@ -640,7 +642,7 @@ void RasterizerVulkan::InvalidateGPUCache() {
640 gpu.InvalidateGPUCache(); 642 gpu.InvalidateGPUCache();
641} 643}
642 644
643void RasterizerVulkan::UnmapMemory(VAddr addr, u64 size) { 645void RasterizerVulkan::UnmapMemory(DAddr addr, u64 size) {
644 { 646 {
645 std::scoped_lock lock{texture_cache.mutex}; 647 std::scoped_lock lock{texture_cache.mutex};
646 texture_cache.UnmapMemory(addr, size); 648 texture_cache.UnmapMemory(addr, size);
@@ -679,7 +681,7 @@ void RasterizerVulkan::ReleaseFences(bool force) {
679 fence_manager.WaitPendingFences(force); 681 fence_manager.WaitPendingFences(force);
680} 682}
681 683
682void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size, 684void RasterizerVulkan::FlushAndInvalidateRegion(DAddr addr, u64 size,
683 VideoCommon::CacheType which) { 685 VideoCommon::CacheType which) {
684 if (Settings::IsGPULevelExtreme()) { 686 if (Settings::IsGPULevelExtreme()) {
685 FlushRegion(addr, size, which); 687 FlushRegion(addr, size, which);
@@ -782,7 +784,7 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
782} 784}
783 785
784bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, 786bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
785 VAddr framebuffer_addr, u32 pixel_stride) { 787 DAddr framebuffer_addr, u32 pixel_stride) {
786 if (!framebuffer_addr) { 788 if (!framebuffer_addr) {
787 return false; 789 return false;
788 } 790 }
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index ad069556c..881ee0993 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -7,14 +7,13 @@
7 7
8#include <boost/container/static_vector.hpp> 8#include <boost/container/static_vector.hpp>
9 9
10#include "video_core/renderer_vulkan/vk_buffer_cache.h"
11
12#include "common/common_types.h" 10#include "common/common_types.h"
13#include "video_core/control/channel_state_cache.h" 11#include "video_core/control/channel_state_cache.h"
14#include "video_core/engines/maxwell_dma.h" 12#include "video_core/engines/maxwell_dma.h"
15#include "video_core/rasterizer_accelerated.h" 13#include "video_core/host1x/gpu_device_memory_manager.h"
16#include "video_core/rasterizer_interface.h" 14#include "video_core/rasterizer_interface.h"
17#include "video_core/renderer_vulkan/blit_image.h" 15#include "video_core/renderer_vulkan/blit_image.h"
16#include "video_core/renderer_vulkan/vk_buffer_cache.h"
18#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 17#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
19#include "video_core/renderer_vulkan/vk_fence_manager.h" 18#include "video_core/renderer_vulkan/vk_fence_manager.h"
20#include "video_core/renderer_vulkan/vk_pipeline_cache.h" 19#include "video_core/renderer_vulkan/vk_pipeline_cache.h"
@@ -34,10 +33,14 @@ namespace Core::Frontend {
34class EmuWindow; 33class EmuWindow;
35} 34}
36 35
37namespace Tegra::Engines { 36namespace Tegra {
37
38namespace Engines {
38class Maxwell3D; 39class Maxwell3D;
39} 40}
40 41
42} // namespace Tegra
43
41namespace Vulkan { 44namespace Vulkan {
42 45
43struct ScreenInfo; 46struct ScreenInfo;
@@ -70,13 +73,14 @@ private:
70 Scheduler& scheduler; 73 Scheduler& scheduler;
71}; 74};
72 75
73class RasterizerVulkan final : public VideoCore::RasterizerAccelerated, 76class RasterizerVulkan final : public VideoCore::RasterizerInterface,
74 protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { 77 protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
75public: 78public:
76 explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, 79 explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
77 Core::Memory::Memory& cpu_memory_, ScreenInfo& screen_info_, 80 Tegra::MaxwellDeviceMemoryManager& device_memory_,
78 const Device& device_, MemoryAllocator& memory_allocator_, 81 ScreenInfo& screen_info_, const Device& device_,
79 StateTracker& state_tracker_, Scheduler& scheduler_); 82 MemoryAllocator& memory_allocator_, StateTracker& state_tracker_,
83 Scheduler& scheduler_);
80 ~RasterizerVulkan() override; 84 ~RasterizerVulkan() override;
81 85
82 void Draw(bool is_indexed, u32 instance_count) override; 86 void Draw(bool is_indexed, u32 instance_count) override;
@@ -90,18 +94,18 @@ public:
90 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; 94 void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
91 void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; 95 void DisableGraphicsUniformBuffer(size_t stage, u32 index) override;
92 void FlushAll() override; 96 void FlushAll() override;
93 void FlushRegion(VAddr addr, u64 size, 97 void FlushRegion(DAddr addr, u64 size,
94 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 98 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
95 bool MustFlushRegion(VAddr addr, u64 size, 99 bool MustFlushRegion(DAddr addr, u64 size,
96 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 100 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
97 VideoCore::RasterizerDownloadArea GetFlushArea(VAddr addr, u64 size) override; 101 VideoCore::RasterizerDownloadArea GetFlushArea(DAddr addr, u64 size) override;
98 void InvalidateRegion(VAddr addr, u64 size, 102 void InvalidateRegion(DAddr addr, u64 size,
99 VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 103 VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
100 void InnerInvalidation(std::span<const std::pair<VAddr, std::size_t>> sequences) override; 104 void InnerInvalidation(std::span<const std::pair<DAddr, std::size_t>> sequences) override;
101 void OnCacheInvalidation(VAddr addr, u64 size) override; 105 void OnCacheInvalidation(DAddr addr, u64 size) override;
102 bool OnCPUWrite(VAddr addr, u64 size) override; 106 bool OnCPUWrite(DAddr addr, u64 size) override;
103 void InvalidateGPUCache() override; 107 void InvalidateGPUCache() override;
104 void UnmapMemory(VAddr addr, u64 size) override; 108 void UnmapMemory(DAddr addr, u64 size) override;
105 void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; 109 void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override;
106 void SignalFence(std::function<void()>&& func) override; 110 void SignalFence(std::function<void()>&& func) override;
107 void SyncOperation(std::function<void()>&& func) override; 111 void SyncOperation(std::function<void()>&& func) override;
@@ -109,7 +113,7 @@ public:
109 void SignalReference() override; 113 void SignalReference() override;
110 void ReleaseFences(bool force = true) override; 114 void ReleaseFences(bool force = true) override;
111 void FlushAndInvalidateRegion( 115 void FlushAndInvalidateRegion(
112 VAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override; 116 DAddr addr, u64 size, VideoCommon::CacheType which = VideoCommon::CacheType::All) override;
113 void WaitForIdle() override; 117 void WaitForIdle() override;
114 void FragmentBarrier() override; 118 void FragmentBarrier() override;
115 void TiledCacheBarrier() override; 119 void TiledCacheBarrier() override;
@@ -122,7 +126,7 @@ public:
122 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; 126 Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override;
123 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, 127 void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size,
124 std::span<const u8> memory) override; 128 std::span<const u8> memory) override;
125 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 129 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, DAddr framebuffer_addr,
126 u32 pixel_stride) override; 130 u32 pixel_stride) override;
127 void LoadDiskResources(u64 title_id, std::stop_token stop_loading, 131 void LoadDiskResources(u64 title_id, std::stop_token stop_loading,
128 const VideoCore::DiskResourceLoadCallback& callback) override; 132 const VideoCore::DiskResourceLoadCallback& callback) override;
@@ -176,6 +180,7 @@ private:
176 void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs); 180 void UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs);
177 181
178 Tegra::GPU& gpu; 182 Tegra::GPU& gpu;
183 Tegra::MaxwellDeviceMemoryManager& device_memory;
179 184
180 ScreenInfo& screen_info; 185 ScreenInfo& screen_info;
181 const Device& device; 186 const Device& device;
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp
index e81cd031b..2af32c8f2 100644
--- a/src/video_core/shader_cache.cpp
+++ b/src/video_core/shader_cache.cpp
@@ -12,6 +12,7 @@
12#include "video_core/dirty_flags.h" 12#include "video_core/dirty_flags.h"
13#include "video_core/engines/kepler_compute.h" 13#include "video_core/engines/kepler_compute.h"
14#include "video_core/engines/maxwell_3d.h" 14#include "video_core/engines/maxwell_3d.h"
15#include "video_core/host1x/gpu_device_memory_manager.h"
15#include "video_core/memory_manager.h" 16#include "video_core/memory_manager.h"
16#include "video_core/shader_cache.h" 17#include "video_core/shader_cache.h"
17#include "video_core/shader_environment.h" 18#include "video_core/shader_environment.h"
@@ -34,7 +35,8 @@ void ShaderCache::SyncGuestHost() {
34 RemovePendingShaders(); 35 RemovePendingShaders();
35} 36}
36 37
37ShaderCache::ShaderCache(VideoCore::RasterizerInterface& rasterizer_) : rasterizer{rasterizer_} {} 38ShaderCache::ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_)
39 : device_memory{device_memory_} {}
38 40
39bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) { 41bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) {
40 auto& dirty{maxwell3d->dirty.flags}; 42 auto& dirty{maxwell3d->dirty.flags};
@@ -132,7 +134,7 @@ void ShaderCache::Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t
132 134
133 storage.push_back(std::move(data)); 135 storage.push_back(std::move(data));
134 136
135 rasterizer.UpdatePagesCachedCount(addr, size, 1); 137 device_memory.UpdatePagesCachedCount(addr, size, 1);
136} 138}
137 139
138void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) { 140void ShaderCache::InvalidatePagesInRegion(VAddr addr, size_t size) {
@@ -209,7 +211,7 @@ void ShaderCache::UnmarkMemory(Entry* entry) {
209 211
210 const VAddr addr = entry->addr_start; 212 const VAddr addr = entry->addr_start;
211 const size_t size = entry->addr_end - addr; 213 const size_t size = entry->addr_end - addr;
212 rasterizer.UpdatePagesCachedCount(addr, size, -1); 214 device_memory.UpdatePagesCachedCount(addr, size, -1);
213} 215}
214 216
215void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) { 217void ShaderCache::RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders) {
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h
index a76896620..fd9bf2562 100644
--- a/src/video_core/shader_cache.h
+++ b/src/video_core/shader_cache.h
@@ -14,6 +14,7 @@
14#include "common/common_types.h" 14#include "common/common_types.h"
15#include "common/polyfill_ranges.h" 15#include "common/polyfill_ranges.h"
16#include "video_core/control/channel_state_cache.h" 16#include "video_core/control/channel_state_cache.h"
17#include "video_core/host1x/gpu_device_memory_manager.h"
17#include "video_core/rasterizer_interface.h" 18#include "video_core/rasterizer_interface.h"
18#include "video_core/shader_environment.h" 19#include "video_core/shader_environment.h"
19 20
@@ -77,7 +78,7 @@ protected:
77 } 78 }
78 }; 79 };
79 80
80 explicit ShaderCache(VideoCore::RasterizerInterface& rasterizer_); 81 explicit ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory);
81 82
82 /// @brief Update the hashes and information of shader stages 83 /// @brief Update the hashes and information of shader stages
83 /// @param unique_hashes Shader hashes to store into when a stage is enabled 84 /// @param unique_hashes Shader hashes to store into when a stage is enabled
@@ -145,7 +146,7 @@ private:
145 /// @brief Create a new shader entry and register it 146 /// @brief Create a new shader entry and register it
146 const ShaderInfo* MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr); 147 const ShaderInfo* MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr);
147 148
148 VideoCore::RasterizerInterface& rasterizer; 149 Tegra::MaxwellDeviceMemoryManager& device_memory;
149 150
150 mutable std::mutex lookup_mutex; 151 mutable std::mutex lookup_mutex;
151 std::mutex invalidation_mutex; 152 std::mutex invalidation_mutex;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 0d5a1709f..7398ed2ec 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -8,10 +8,11 @@
8 8
9#include "common/alignment.h" 9#include "common/alignment.h"
10#include "common/settings.h" 10#include "common/settings.h"
11#include "core/memory.h"
12#include "video_core/control/channel_state.h" 11#include "video_core/control/channel_state.h"
13#include "video_core/dirty_flags.h" 12#include "video_core/dirty_flags.h"
14#include "video_core/engines/kepler_compute.h" 13#include "video_core/engines/kepler_compute.h"
14#include "video_core/guest_memory.h"
15#include "video_core/host1x/gpu_device_memory_manager.h"
15#include "video_core/texture_cache/image_view_base.h" 16#include "video_core/texture_cache/image_view_base.h"
16#include "video_core/texture_cache/samples_helper.h" 17#include "video_core/texture_cache/samples_helper.h"
17#include "video_core/texture_cache/texture_cache_base.h" 18#include "video_core/texture_cache/texture_cache_base.h"
@@ -27,8 +28,8 @@ using VideoCore::Surface::SurfaceType;
27using namespace Common::Literals; 28using namespace Common::Literals;
28 29
29template <class P> 30template <class P>
30TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& rasterizer_) 31TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManager& device_memory_)
31 : runtime{runtime_}, rasterizer{rasterizer_} { 32 : runtime{runtime_}, device_memory{device_memory_} {
32 // Configure null sampler 33 // Configure null sampler
33 TSCEntry sampler_descriptor{}; 34 TSCEntry sampler_descriptor{};
34 sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear); 35 sampler_descriptor.min_filter.Assign(Tegra::Texture::TextureFilter::Linear);
@@ -49,19 +50,19 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
49 void(slot_samplers.insert(runtime, sampler_descriptor)); 50 void(slot_samplers.insert(runtime, sampler_descriptor));
50 51
51 if constexpr (HAS_DEVICE_MEMORY_INFO) { 52 if constexpr (HAS_DEVICE_MEMORY_INFO) {
52 const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); 53 const s64 device_local_memory = static_cast<s64>(runtime.GetDeviceLocalMemory());
53 const s64 min_spacing_expected = device_memory - 1_GiB; 54 const s64 min_spacing_expected = device_local_memory - 1_GiB;
54 const s64 min_spacing_critical = device_memory - 512_MiB; 55 const s64 min_spacing_critical = device_local_memory - 512_MiB;
55 const s64 mem_threshold = std::min(device_memory, TARGET_THRESHOLD); 56 const s64 mem_threshold = std::min(device_local_memory, TARGET_THRESHOLD);
56 const s64 min_vacancy_expected = (6 * mem_threshold) / 10; 57 const s64 min_vacancy_expected = (6 * mem_threshold) / 10;
57 const s64 min_vacancy_critical = (3 * mem_threshold) / 10; 58 const s64 min_vacancy_critical = (3 * mem_threshold) / 10;
58 expected_memory = static_cast<u64>( 59 expected_memory = static_cast<u64>(
59 std::max(std::min(device_memory - min_vacancy_expected, min_spacing_expected), 60 std::max(std::min(device_local_memory - min_vacancy_expected, min_spacing_expected),
60 DEFAULT_EXPECTED_MEMORY)); 61 DEFAULT_EXPECTED_MEMORY));
61 critical_memory = static_cast<u64>( 62 critical_memory = static_cast<u64>(
62 std::max(std::min(device_memory - min_vacancy_critical, min_spacing_critical), 63 std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
63 DEFAULT_CRITICAL_MEMORY)); 64 DEFAULT_CRITICAL_MEMORY));
64 minimum_memory = static_cast<u64>((device_memory - mem_threshold) / 2); 65 minimum_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
65 } else { 66 } else {
66 expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB; 67 expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB;
67 critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB; 68 critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB;
@@ -513,7 +514,7 @@ FramebufferId TextureCache<P>::GetFramebufferId(const RenderTargets& key) {
513} 514}
514 515
515template <class P> 516template <class P>
516void TextureCache<P>::WriteMemory(VAddr cpu_addr, size_t size) { 517void TextureCache<P>::WriteMemory(DAddr cpu_addr, size_t size) {
517 ForEachImageInRegion(cpu_addr, size, [this](ImageId image_id, Image& image) { 518 ForEachImageInRegion(cpu_addr, size, [this](ImageId image_id, Image& image) {
518 if (True(image.flags & ImageFlagBits::CpuModified)) { 519 if (True(image.flags & ImageFlagBits::CpuModified)) {
519 return; 520 return;
@@ -526,7 +527,7 @@ void TextureCache<P>::WriteMemory(VAddr cpu_addr, size_t size) {
526} 527}
527 528
528template <class P> 529template <class P>
529void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) { 530void TextureCache<P>::DownloadMemory(DAddr cpu_addr, size_t size) {
530 boost::container::small_vector<ImageId, 16> images; 531 boost::container::small_vector<ImageId, 16> images;
531 ForEachImageInRegion(cpu_addr, size, [&images](ImageId image_id, ImageBase& image) { 532 ForEachImageInRegion(cpu_addr, size, [&images](ImageId image_id, ImageBase& image) {
532 if (!image.IsSafeDownload()) { 533 if (!image.IsSafeDownload()) {
@@ -553,7 +554,7 @@ void TextureCache<P>::DownloadMemory(VAddr cpu_addr, size_t size) {
553} 554}
554 555
555template <class P> 556template <class P>
556std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(VAddr cpu_addr, 557std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(DAddr cpu_addr,
557 u64 size) { 558 u64 size) {
558 std::optional<VideoCore::RasterizerDownloadArea> area{}; 559 std::optional<VideoCore::RasterizerDownloadArea> area{};
559 ForEachImageInRegion(cpu_addr, size, [&](ImageId, ImageBase& image) { 560 ForEachImageInRegion(cpu_addr, size, [&](ImageId, ImageBase& image) {
@@ -579,7 +580,7 @@ std::optional<VideoCore::RasterizerDownloadArea> TextureCache<P>::GetFlushArea(V
579} 580}
580 581
581template <class P> 582template <class P>
582void TextureCache<P>::UnmapMemory(VAddr cpu_addr, size_t size) { 583void TextureCache<P>::UnmapMemory(DAddr cpu_addr, size_t size) {
583 boost::container::small_vector<ImageId, 16> deleted_images; 584 boost::container::small_vector<ImageId, 16> deleted_images;
584 ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); }); 585 ForEachImageInRegion(cpu_addr, size, [&](ImageId id, Image&) { deleted_images.push_back(id); });
585 for (const ImageId id : deleted_images) { 586 for (const ImageId id : deleted_images) {
@@ -713,7 +714,7 @@ bool TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
713 714
714template <class P> 715template <class P>
715typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView( 716typename P::ImageView* TextureCache<P>::TryFindFramebufferImageView(
716 const Tegra::FramebufferConfig& config, VAddr cpu_addr) { 717 const Tegra::FramebufferConfig& config, DAddr cpu_addr) {
717 // TODO: Properly implement this 718 // TODO: Properly implement this
718 const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS); 719 const auto it = page_table.find(cpu_addr >> YUZU_PAGEBITS);
719 if (it == page_table.end()) { 720 if (it == page_table.end()) {
@@ -940,7 +941,7 @@ bool TextureCache<P>::IsRescaling(const ImageViewBase& image_view) const noexcep
940} 941}
941 942
942template <class P> 943template <class P>
943bool TextureCache<P>::IsRegionGpuModified(VAddr addr, size_t size) { 944bool TextureCache<P>::IsRegionGpuModified(DAddr addr, size_t size) {
944 bool is_modified = false; 945 bool is_modified = false;
945 ForEachImageInRegion(addr, size, [&is_modified](ImageId, ImageBase& image) { 946 ForEachImageInRegion(addr, size, [&is_modified](ImageId, ImageBase& image) {
946 if (False(image.flags & ImageFlagBits::GpuModified)) { 947 if (False(image.flags & ImageFlagBits::GpuModified)) {
@@ -1059,7 +1060,7 @@ void TextureCache<P>::UploadImageContents(Image& image, StagingBuffer& staging)
1059 return; 1060 return;
1060 } 1061 }
1061 1062
1062 Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data( 1063 Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data(
1063 *gpu_memory, gpu_addr, image.guest_size_bytes, &swizzle_data_buffer); 1064 *gpu_memory, gpu_addr, image.guest_size_bytes, &swizzle_data_buffer);
1064 1065
1065 if (True(image.flags & ImageFlagBits::Converted)) { 1066 if (True(image.flags & ImageFlagBits::Converted)) {
@@ -1124,7 +1125,7 @@ ImageId TextureCache<P>::FindOrInsertImage(const ImageInfo& info, GPUVAddr gpu_a
1124template <class P> 1125template <class P>
1125ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr, 1126ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
1126 RelaxedOptions options) { 1127 RelaxedOptions options) {
1127 std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1128 std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1128 if (!cpu_addr) { 1129 if (!cpu_addr) {
1129 cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info)); 1130 cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info));
1130 if (!cpu_addr) { 1131 if (!cpu_addr) {
@@ -1265,7 +1266,7 @@ void TextureCache<P>::QueueAsyncDecode(Image& image, ImageId image_id) {
1265 1266
1266 static Common::ScratchBuffer<u8> local_unswizzle_data_buffer; 1267 static Common::ScratchBuffer<u8> local_unswizzle_data_buffer;
1267 local_unswizzle_data_buffer.resize_destructive(image.unswizzled_size_bytes); 1268 local_unswizzle_data_buffer.resize_destructive(image.unswizzled_size_bytes);
1268 Core::Memory::GpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data( 1269 Tegra::Memory::GpuGuestMemory<u8, Tegra::Memory::GuestMemoryFlags::UnsafeRead> swizzle_data(
1269 *gpu_memory, image.gpu_addr, image.guest_size_bytes, &swizzle_data_buffer); 1270 *gpu_memory, image.gpu_addr, image.guest_size_bytes, &swizzle_data_buffer);
1270 1271
1271 auto copies = UnswizzleImage(*gpu_memory, image.gpu_addr, image.info, swizzle_data, 1272 auto copies = UnswizzleImage(*gpu_memory, image.gpu_addr, image.info, swizzle_data,
@@ -1339,14 +1340,14 @@ bool TextureCache<P>::ScaleDown(Image& image) {
1339template <class P> 1340template <class P>
1340ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr, 1341ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr,
1341 RelaxedOptions options) { 1342 RelaxedOptions options) {
1342 std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1343 std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1343 if (!cpu_addr) { 1344 if (!cpu_addr) {
1344 const auto size = CalculateGuestSizeInBytes(info); 1345 const auto size = CalculateGuestSizeInBytes(info);
1345 cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, size); 1346 cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, size);
1346 if (!cpu_addr) { 1347 if (!cpu_addr) {
1347 const VAddr fake_addr = ~(1ULL << 40ULL) + virtual_invalid_space; 1348 const DAddr fake_addr = ~(1ULL << 40ULL) + virtual_invalid_space;
1348 virtual_invalid_space += Common::AlignUp(size, 32); 1349 virtual_invalid_space += Common::AlignUp(size, 32);
1349 cpu_addr = std::optional<VAddr>(fake_addr); 1350 cpu_addr = std::optional<DAddr>(fake_addr);
1350 } 1351 }
1351 } 1352 }
1352 ASSERT_MSG(cpu_addr, "Tried to insert an image to an invalid gpu_addr=0x{:x}", gpu_addr); 1353 ASSERT_MSG(cpu_addr, "Tried to insert an image to an invalid gpu_addr=0x{:x}", gpu_addr);
@@ -1362,7 +1363,7 @@ ImageId TextureCache<P>::InsertImage(const ImageInfo& info, GPUVAddr gpu_addr,
1362} 1363}
1363 1364
1364template <class P> 1365template <class P>
1365ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr) { 1366ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DAddr cpu_addr) {
1366 ImageInfo new_info = info; 1367 ImageInfo new_info = info;
1367 const size_t size_bytes = CalculateGuestSizeInBytes(new_info); 1368 const size_t size_bytes = CalculateGuestSizeInBytes(new_info);
1368 const bool broken_views = runtime.HasBrokenTextureViewFormats(); 1369 const bool broken_views = runtime.HasBrokenTextureViewFormats();
@@ -1650,7 +1651,7 @@ std::optional<typename TextureCache<P>::BlitImages> TextureCache<P>::GetBlitImag
1650 1651
1651template <class P> 1652template <class P>
1652ImageId TextureCache<P>::FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr) { 1653ImageId TextureCache<P>::FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr) {
1653 std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1654 std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1654 if (!cpu_addr) { 1655 if (!cpu_addr) {
1655 cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info)); 1656 cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr, CalculateGuestSizeInBytes(info));
1656 if (!cpu_addr) { 1657 if (!cpu_addr) {
@@ -1780,7 +1781,7 @@ ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAdd
1780 1781
1781template <class P> 1782template <class P>
1782template <typename Func> 1783template <typename Func>
1783void TextureCache<P>::ForEachImageInRegion(VAddr cpu_addr, size_t size, Func&& func) { 1784void TextureCache<P>::ForEachImageInRegion(DAddr cpu_addr, size_t size, Func&& func) {
1784 using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type; 1785 using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type;
1785 static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; 1786 static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
1786 boost::container::small_vector<ImageId, 32> images; 1787 boost::container::small_vector<ImageId, 32> images;
@@ -1924,11 +1925,11 @@ void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size,
1924template <class P> 1925template <class P>
1925template <typename Func> 1926template <typename Func>
1926void TextureCache<P>::ForEachSparseSegment(ImageBase& image, Func&& func) { 1927void TextureCache<P>::ForEachSparseSegment(ImageBase& image, Func&& func) {
1927 using FuncReturn = typename std::invoke_result<Func, GPUVAddr, VAddr, size_t>::type; 1928 using FuncReturn = typename std::invoke_result<Func, GPUVAddr, DAddr, size_t>::type;
1928 static constexpr bool RETURNS_BOOL = std::is_same_v<FuncReturn, bool>; 1929 static constexpr bool RETURNS_BOOL = std::is_same_v<FuncReturn, bool>;
1929 const auto segments = gpu_memory->GetSubmappedRange(image.gpu_addr, image.guest_size_bytes); 1930 const auto segments = gpu_memory->GetSubmappedRange(image.gpu_addr, image.guest_size_bytes);
1930 for (const auto& [gpu_addr, size] : segments) { 1931 for (const auto& [gpu_addr, size] : segments) {
1931 std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1932 std::optional<DAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
1932 ASSERT(cpu_addr); 1933 ASSERT(cpu_addr);
1933 if constexpr (RETURNS_BOOL) { 1934 if constexpr (RETURNS_BOOL) {
1934 if (func(gpu_addr, *cpu_addr, size)) { 1935 if (func(gpu_addr, *cpu_addr, size)) {
@@ -1980,7 +1981,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
1980 } 1981 }
1981 boost::container::small_vector<ImageViewId, 16> sparse_maps; 1982 boost::container::small_vector<ImageViewId, 16> sparse_maps;
1982 ForEachSparseSegment( 1983 ForEachSparseSegment(
1983 image, [this, image_id, &sparse_maps](GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) { 1984 image, [this, image_id, &sparse_maps](GPUVAddr gpu_addr, DAddr cpu_addr, size_t size) {
1984 auto map_id = slot_map_views.insert(gpu_addr, cpu_addr, size, image_id); 1985 auto map_id = slot_map_views.insert(gpu_addr, cpu_addr, size, image_id);
1985 ForEachCPUPage(cpu_addr, size, 1986 ForEachCPUPage(cpu_addr, size,
1986 [this, map_id](u64 page) { page_table[page].push_back(map_id); }); 1987 [this, map_id](u64 page) { page_table[page].push_back(map_id); });
@@ -2048,7 +2049,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
2048 auto& sparse_maps = it->second; 2049 auto& sparse_maps = it->second;
2049 for (auto& map_view_id : sparse_maps) { 2050 for (auto& map_view_id : sparse_maps) {
2050 const auto& map_range = slot_map_views[map_view_id]; 2051 const auto& map_range = slot_map_views[map_view_id];
2051 const VAddr cpu_addr = map_range.cpu_addr; 2052 const DAddr cpu_addr = map_range.cpu_addr;
2052 const std::size_t size = map_range.size; 2053 const std::size_t size = map_range.size;
2053 ForEachCPUPage(cpu_addr, size, [this, image_id](u64 page) { 2054 ForEachCPUPage(cpu_addr, size, [this, image_id](u64 page) {
2054 const auto page_it = page_table.find(page); 2055 const auto page_it = page_table.find(page);
@@ -2080,7 +2081,7 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
2080 ASSERT(False(image.flags & ImageFlagBits::Tracked)); 2081 ASSERT(False(image.flags & ImageFlagBits::Tracked));
2081 image.flags |= ImageFlagBits::Tracked; 2082 image.flags |= ImageFlagBits::Tracked;
2082 if (False(image.flags & ImageFlagBits::Sparse)) { 2083 if (False(image.flags & ImageFlagBits::Sparse)) {
2083 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); 2084 device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1);
2084 return; 2085 return;
2085 } 2086 }
2086 if (True(image.flags & ImageFlagBits::Registered)) { 2087 if (True(image.flags & ImageFlagBits::Registered)) {
@@ -2089,15 +2090,15 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
2089 auto& sparse_maps = it->second; 2090 auto& sparse_maps = it->second;
2090 for (auto& map_view_id : sparse_maps) { 2091 for (auto& map_view_id : sparse_maps) {
2091 const auto& map = slot_map_views[map_view_id]; 2092 const auto& map = slot_map_views[map_view_id];
2092 const VAddr cpu_addr = map.cpu_addr; 2093 const DAddr cpu_addr = map.cpu_addr;
2093 const std::size_t size = map.size; 2094 const std::size_t size = map.size;
2094 rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); 2095 device_memory.UpdatePagesCachedCount(cpu_addr, size, 1);
2095 } 2096 }
2096 return; 2097 return;
2097 } 2098 }
2098 ForEachSparseSegment(image, 2099 ForEachSparseSegment(image,
2099 [this]([[maybe_unused]] GPUVAddr gpu_addr, VAddr cpu_addr, size_t size) { 2100 [this]([[maybe_unused]] GPUVAddr gpu_addr, DAddr cpu_addr, size_t size) {
2100 rasterizer.UpdatePagesCachedCount(cpu_addr, size, 1); 2101 device_memory.UpdatePagesCachedCount(cpu_addr, size, 1);
2101 }); 2102 });
2102} 2103}
2103 2104
@@ -2106,7 +2107,7 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
2106 ASSERT(True(image.flags & ImageFlagBits::Tracked)); 2107 ASSERT(True(image.flags & ImageFlagBits::Tracked));
2107 image.flags &= ~ImageFlagBits::Tracked; 2108 image.flags &= ~ImageFlagBits::Tracked;
2108 if (False(image.flags & ImageFlagBits::Sparse)) { 2109 if (False(image.flags & ImageFlagBits::Sparse)) {
2109 rasterizer.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); 2110 device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1);
2110 return; 2111 return;
2111 } 2112 }
2112 ASSERT(True(image.flags & ImageFlagBits::Registered)); 2113 ASSERT(True(image.flags & ImageFlagBits::Registered));
@@ -2115,9 +2116,9 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) {
2115 auto& sparse_maps = it->second; 2116 auto& sparse_maps = it->second;
2116 for (auto& map_view_id : sparse_maps) { 2117 for (auto& map_view_id : sparse_maps) {
2117 const auto& map = slot_map_views[map_view_id]; 2118 const auto& map = slot_map_views[map_view_id];
2118 const VAddr cpu_addr = map.cpu_addr; 2119 const DAddr cpu_addr = map.cpu_addr;
2119 const std::size_t size = map.size; 2120 const std::size_t size = map.size;
2120 rasterizer.UpdatePagesCachedCount(cpu_addr, size, -1); 2121 device_memory.UpdatePagesCachedCount(cpu_addr, size, -1);
2121 } 2122 }
2122} 2123}
2123 2124
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h
index 6caf75b46..8699d40d4 100644
--- a/src/video_core/texture_cache/texture_cache_base.h
+++ b/src/video_core/texture_cache/texture_cache_base.h
@@ -36,9 +36,11 @@
36#include "video_core/texture_cache/types.h" 36#include "video_core/texture_cache/types.h"
37#include "video_core/textures/texture.h" 37#include "video_core/textures/texture.h"
38 38
39namespace Tegra::Control { 39namespace Tegra {
40namespace Control {
40struct ChannelState; 41struct ChannelState;
41} 42}
43} // namespace Tegra
42 44
43namespace VideoCommon { 45namespace VideoCommon {
44 46
@@ -126,7 +128,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI
126 }; 128 };
127 129
128public: 130public:
129 explicit TextureCache(Runtime&, VideoCore::RasterizerInterface&); 131 explicit TextureCache(Runtime&, Tegra::MaxwellDeviceMemoryManager&);
130 132
131 /// Notify the cache that a new frame has been queued 133 /// Notify the cache that a new frame has been queued
132 void TickFrame(); 134 void TickFrame();
@@ -190,15 +192,15 @@ public:
190 Framebuffer* GetFramebuffer(); 192 Framebuffer* GetFramebuffer();
191 193
192 /// Mark images in a range as modified from the CPU 194 /// Mark images in a range as modified from the CPU
193 void WriteMemory(VAddr cpu_addr, size_t size); 195 void WriteMemory(DAddr cpu_addr, size_t size);
194 196
195 /// Download contents of host images to guest memory in a region 197 /// Download contents of host images to guest memory in a region
196 void DownloadMemory(VAddr cpu_addr, size_t size); 198 void DownloadMemory(DAddr cpu_addr, size_t size);
197 199
198 std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(VAddr cpu_addr, u64 size); 200 std::optional<VideoCore::RasterizerDownloadArea> GetFlushArea(DAddr cpu_addr, u64 size);
199 201
200 /// Remove images in a region 202 /// Remove images in a region
201 void UnmapMemory(VAddr cpu_addr, size_t size); 203 void UnmapMemory(DAddr cpu_addr, size_t size);
202 204
203 /// Remove images in a region 205 /// Remove images in a region
204 void UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size); 206 void UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t size);
@@ -210,7 +212,7 @@ public:
210 212
211 /// Try to find a cached image view in the given CPU address 213 /// Try to find a cached image view in the given CPU address
212 [[nodiscard]] ImageView* TryFindFramebufferImageView(const Tegra::FramebufferConfig& config, 214 [[nodiscard]] ImageView* TryFindFramebufferImageView(const Tegra::FramebufferConfig& config,
213 VAddr cpu_addr); 215 DAddr cpu_addr);
214 216
215 /// Return true when there are uncommitted images to be downloaded 217 /// Return true when there are uncommitted images to be downloaded
216 [[nodiscard]] bool HasUncommittedFlushes() const noexcept; 218 [[nodiscard]] bool HasUncommittedFlushes() const noexcept;
@@ -235,7 +237,7 @@ public:
235 GPUVAddr address = 0, size_t size = 0); 237 GPUVAddr address = 0, size_t size = 0);
236 238
237 /// Return true when a CPU region is modified from the GPU 239 /// Return true when a CPU region is modified from the GPU
238 [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); 240 [[nodiscard]] bool IsRegionGpuModified(DAddr addr, size_t size);
239 241
240 [[nodiscard]] bool IsRescaling() const noexcept; 242 [[nodiscard]] bool IsRescaling() const noexcept;
241 243
@@ -252,7 +254,7 @@ public:
252private: 254private:
253 /// Iterate over all page indices in a range 255 /// Iterate over all page indices in a range
254 template <typename Func> 256 template <typename Func>
255 static void ForEachCPUPage(VAddr addr, size_t size, Func&& func) { 257 static void ForEachCPUPage(DAddr addr, size_t size, Func&& func) {
256 static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>; 258 static constexpr bool RETURNS_BOOL = std::is_same_v<std::invoke_result<Func, u64>, bool>;
257 const u64 page_end = (addr + size - 1) >> YUZU_PAGEBITS; 259 const u64 page_end = (addr + size - 1) >> YUZU_PAGEBITS;
258 for (u64 page = addr >> YUZU_PAGEBITS; page <= page_end; ++page) { 260 for (u64 page = addr >> YUZU_PAGEBITS; page <= page_end; ++page) {
@@ -326,7 +328,7 @@ private:
326 328
327 /// Create a new image and join perfectly matching existing images 329 /// Create a new image and join perfectly matching existing images
328 /// Remove joined images from the cache 330 /// Remove joined images from the cache
329 [[nodiscard]] ImageId JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VAddr cpu_addr); 331 [[nodiscard]] ImageId JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DAddr cpu_addr);
330 332
331 [[nodiscard]] ImageId FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr); 333 [[nodiscard]] ImageId FindDMAImage(const ImageInfo& info, GPUVAddr gpu_addr);
332 334
@@ -349,7 +351,7 @@ private:
349 351
350 /// Iterates over all the images in a region calling func 352 /// Iterates over all the images in a region calling func
351 template <typename Func> 353 template <typename Func>
352 void ForEachImageInRegion(VAddr cpu_addr, size_t size, Func&& func); 354 void ForEachImageInRegion(DAddr cpu_addr, size_t size, Func&& func);
353 355
354 template <typename Func> 356 template <typename Func>
355 void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func); 357 void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
@@ -421,7 +423,7 @@ private:
421 423
422 Runtime& runtime; 424 Runtime& runtime;
423 425
424 VideoCore::RasterizerInterface& rasterizer; 426 Tegra::MaxwellDeviceMemoryManager& device_memory;
425 std::deque<TextureCacheGPUMap> gpu_page_table_storage; 427 std::deque<TextureCacheGPUMap> gpu_page_table_storage;
426 428
427 RenderTargets render_targets; 429 RenderTargets render_targets;
@@ -432,7 +434,7 @@ private:
432 std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table; 434 std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table;
433 std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views; 435 std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views;
434 436
435 VAddr virtual_invalid_space{}; 437 DAddr virtual_invalid_space{};
436 438
437 bool has_deleted_images = false; 439 bool has_deleted_images = false;
438 bool is_rescaling = false; 440 bool is_rescaling = false;
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index fcf70068e..1a6f0d1ad 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -20,9 +20,9 @@
20#include "common/div_ceil.h" 20#include "common/div_ceil.h"
21#include "common/scratch_buffer.h" 21#include "common/scratch_buffer.h"
22#include "common/settings.h" 22#include "common/settings.h"
23#include "core/memory.h"
24#include "video_core/compatible_formats.h" 23#include "video_core/compatible_formats.h"
25#include "video_core/engines/maxwell_3d.h" 24#include "video_core/engines/maxwell_3d.h"
25#include "video_core/guest_memory.h"
26#include "video_core/memory_manager.h" 26#include "video_core/memory_manager.h"
27#include "video_core/surface.h" 27#include "video_core/surface.h"
28#include "video_core/texture_cache/decode_bc.h" 28#include "video_core/texture_cache/decode_bc.h"
@@ -552,7 +552,8 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
552 for (s32 layer = 0; layer < info.resources.layers; ++layer) { 552 for (s32 layer = 0; layer < info.resources.layers; ++layer) {
553 const std::span<const u8> src = input.subspan(host_offset); 553 const std::span<const u8> src = input.subspan(host_offset);
554 { 554 {
555 Core::Memory::GpuGuestMemoryScoped<u8, Core::Memory::GuestMemoryFlags::UnsafeReadWrite> 555 Tegra::Memory::GpuGuestMemoryScoped<u8,
556 Tegra::Memory::GuestMemoryFlags::UnsafeReadWrite>
556 dst(gpu_memory, gpu_addr + guest_offset, subresource_size, &tmp_buffer); 557 dst(gpu_memory, gpu_addr + guest_offset, subresource_size, &tmp_buffer);
557 558
558 SwizzleTexture(dst, src, bytes_per_block, num_tiles.width, num_tiles.height, 559 SwizzleTexture(dst, src, bytes_per_block, num_tiles.width, num_tiles.height,
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index b42d48416..0efb7b49d 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -6,6 +6,8 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "common/settings.h" 7#include "common/settings.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "video_core/host1x/gpu_device_memory_manager.h"
10#include "video_core/host1x/host1x.h"
9#include "video_core/renderer_base.h" 11#include "video_core/renderer_base.h"
10#include "video_core/renderer_null/renderer_null.h" 12#include "video_core/renderer_null/renderer_null.h"
11#include "video_core/renderer_opengl/renderer_opengl.h" 13#include "video_core/renderer_opengl/renderer_opengl.h"
@@ -18,18 +20,17 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer(
18 Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu, 20 Core::System& system, Core::Frontend::EmuWindow& emu_window, Tegra::GPU& gpu,
19 std::unique_ptr<Core::Frontend::GraphicsContext> context) { 21 std::unique_ptr<Core::Frontend::GraphicsContext> context) {
20 auto& telemetry_session = system.TelemetrySession(); 22 auto& telemetry_session = system.TelemetrySession();
21 auto& cpu_memory = system.ApplicationMemory(); 23 auto& device_memory = system.Host1x().MemoryManager();
22 24
23 switch (Settings::values.renderer_backend.GetValue()) { 25 switch (Settings::values.renderer_backend.GetValue()) {
24 case Settings::RendererBackend::OpenGL: 26 case Settings::RendererBackend::OpenGL:
25 return std::make_unique<OpenGL::RendererOpenGL>(telemetry_session, emu_window, cpu_memory, 27 return std::make_unique<OpenGL::RendererOpenGL>(telemetry_session, emu_window,
26 gpu, std::move(context)); 28 device_memory, gpu, std::move(context));
27 case Settings::RendererBackend::Vulkan: 29 case Settings::RendererBackend::Vulkan:
28 return std::make_unique<Vulkan::RendererVulkan>(telemetry_session, emu_window, cpu_memory, 30 return std::make_unique<Vulkan::RendererVulkan>(telemetry_session, emu_window,
29 gpu, std::move(context)); 31 device_memory, gpu, std::move(context));
30 case Settings::RendererBackend::Null: 32 case Settings::RendererBackend::Null:
31 return std::make_unique<Null::RendererNull>(emu_window, cpu_memory, gpu, 33 return std::make_unique<Null::RendererNull>(emu_window, gpu, std::move(context));
32 std::move(context));
33 default: 34 default:
34 return nullptr; 35 return nullptr;
35 } 36 }
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 074aed964..3966bd61e 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -39,6 +39,10 @@ void SortPhysicalDevicesPerVendor(std::vector<VkPhysicalDevice>& devices,
39 } 39 }
40} 40}
41 41
42bool IsMicrosoftDozen(const char* device_name) {
43 return std::strstr(device_name, "Microsoft") != nullptr;
44}
45
42void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) { 46void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) {
43 // Sort by name, this will set a base and make GPUs with higher numbers appear first 47 // Sort by name, this will set a base and make GPUs with higher numbers appear first
44 // (e.g. GTX 1650 will intentionally be listed before a GTX 1080). 48 // (e.g. GTX 1650 will intentionally be listed before a GTX 1080).
@@ -52,6 +56,12 @@ void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceD
52 }); 56 });
53 // Prefer Nvidia over AMD, AMD over Intel, Intel over the rest. 57 // Prefer Nvidia over AMD, AMD over Intel, Intel over the rest.
54 SortPhysicalDevicesPerVendor(devices, dld, {0x10DE, 0x1002, 0x8086}); 58 SortPhysicalDevicesPerVendor(devices, dld, {0x10DE, 0x1002, 0x8086});
59 // Demote Microsoft's Dozen devices to the bottom.
60 SortPhysicalDevices(
61 devices, dld,
62 [](const VkPhysicalDeviceProperties& lhs, const VkPhysicalDeviceProperties& rhs) {
63 return IsMicrosoftDozen(rhs.deviceName) && !IsMicrosoftDozen(lhs.deviceName);
64 });
55} 65}
56 66
57template <typename T> 67template <typename T>
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 90278052a..93b03b917 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -351,7 +351,7 @@ if (APPLE)
351 351
352 if (NOT USE_SYSTEM_MOLTENVK) 352 if (NOT USE_SYSTEM_MOLTENVK)
353 set(MOLTENVK_PLATFORM "macOS") 353 set(MOLTENVK_PLATFORM "macOS")
354 set(MOLTENVK_VERSION "v1.2.5") 354 set(MOLTENVK_VERSION "v1.2.7")
355 download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION}) 355 download_moltenvk_external(${MOLTENVK_PLATFORM} ${MOLTENVK_VERSION})
356 endif() 356 endif()
357 find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED) 357 find_library(MOLTENVK_LIBRARY MoltenVK REQUIRED)
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 140a7fe5d..568775027 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -122,9 +122,8 @@ void ConfigurePerGameAddons::LoadConfiguration() {
122 122
123 const auto& disabled = Settings::values.disabled_addons[title_id]; 123 const auto& disabled = Settings::values.disabled_addons[title_id];
124 124
125 for (const auto& patch : pm.GetPatchVersionNames(update_raw)) { 125 for (const auto& patch : pm.GetPatches(update_raw)) {
126 const auto name = 126 const auto name = QString::fromStdString(patch.name);
127 QString::fromStdString(patch.first).replace(QStringLiteral("[D] "), QString{});
128 127
129 auto* const first_item = new QStandardItem; 128 auto* const first_item = new QStandardItem;
130 first_item->setText(name); 129 first_item->setText(name);
@@ -136,7 +135,7 @@ void ConfigurePerGameAddons::LoadConfiguration() {
136 first_item->setCheckState(patch_disabled ? Qt::Unchecked : Qt::Checked); 135 first_item->setCheckState(patch_disabled ? Qt::Unchecked : Qt::Checked);
137 136
138 list_items.push_back(QList<QStandardItem*>{ 137 list_items.push_back(QList<QStandardItem*>{
139 first_item, new QStandardItem{QString::fromStdString(patch.second)}}); 138 first_item, new QStandardItem{QString::fromStdString(patch.version)}});
140 item_model->appendRow(list_items.back()); 139 item_model->appendRow(list_items.back());
141 } 140 }
142 141
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index d898d8acc..6b1f4527b 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -116,8 +116,8 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type
116 .high_amplitude = 1.0f, 116 .high_amplitude = 1.0f,
117 .high_frequency = 320.0f, 117 .high_frequency = 320.0f,
118 }; 118 };
119 controller->SetVibration(0, vibration); 119 controller->SetVibration(Core::HID::DeviceIndex::Left, vibration);
120 controller->SetVibration(1, vibration); 120 controller->SetVibration(Core::HID::DeviceIndex::Right, vibration);
121 121
122 // Restore previous values 122 // Restore previous values
123 player.vibration_enabled = old_vibration_enabled; 123 player.vibration_enabled = old_vibration_enabled;
@@ -127,7 +127,7 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type
127void ConfigureVibration::StopVibrations() { 127void ConfigureVibration::StopVibrations() {
128 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { 128 for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
129 auto controller = hid_core.GetEmulatedControllerByIndex(i); 129 auto controller = hid_core.GetEmulatedControllerByIndex(i);
130 controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE); 130 controller->SetVibration(Core::HID::DeviceIndex::Left, Core::HID::DEFAULT_VIBRATION_VALUE);
131 controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE); 131 controller->SetVibration(Core::HID::DeviceIndex::Right, Core::HID::DEFAULT_VIBRATION_VALUE);
132 } 132 }
133} 133}
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index dc006832e..9747e3fb3 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -164,18 +164,19 @@ QString FormatPatchNameVersions(const FileSys::PatchManager& patch_manager,
164 QString out; 164 QString out;
165 FileSys::VirtualFile update_raw; 165 FileSys::VirtualFile update_raw;
166 loader.ReadUpdateRaw(update_raw); 166 loader.ReadUpdateRaw(update_raw);
167 for (const auto& kv : patch_manager.GetPatchVersionNames(update_raw)) { 167 for (const auto& patch : patch_manager.GetPatches(update_raw)) {
168 const bool is_update = kv.first == "Update" || kv.first == "[D] Update"; 168 const bool is_update = patch.name == "Update";
169 if (!updatable && is_update) { 169 if (!updatable && is_update) {
170 continue; 170 continue;
171 } 171 }
172 172
173 const QString type = QString::fromStdString(kv.first); 173 const QString type =
174 QString::fromStdString(patch.enabled ? patch.name : "[D] " + patch.name);
174 175
175 if (kv.second.empty()) { 176 if (patch.version.empty()) {
176 out.append(QStringLiteral("%1\n").arg(type)); 177 out.append(QStringLiteral("%1\n").arg(type));
177 } else { 178 } else {
178 auto ver = kv.second; 179 auto ver = patch.version;
179 180
180 // Display container name for packed updates 181 // Display container name for packed updates
181 if (is_update && ver == "PACKED") { 182 if (is_update && ver == "PACKED") {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 33756febf..d8b0beadf 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -47,6 +47,7 @@
47#include "core/hle/service/am/applet_oe.h" 47#include "core/hle/service/am/applet_oe.h"
48#include "core/hle/service/am/applets/applets.h" 48#include "core/hle/service/am/applets/applets.h"
49#include "core/hle/service/set/system_settings_server.h" 49#include "core/hle/service/set/system_settings_server.h"
50#include "frontend_common/content_manager.h"
50#include "hid_core/frontend/emulated_controller.h" 51#include "hid_core/frontend/emulated_controller.h"
51#include "hid_core/hid_core.h" 52#include "hid_core/hid_core.h"
52#include "yuzu/multiplayer/state.h" 53#include "yuzu/multiplayer/state.h"
@@ -518,12 +519,21 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
518 continue; 519 continue;
519 } 520 }
520 521
522 int user_arg_idx = ++i;
521 bool argument_ok; 523 bool argument_ok;
522 const std::size_t selected_user = args[++i].toUInt(&argument_ok); 524 std::size_t selected_user = args[user_arg_idx].toUInt(&argument_ok);
523 525
524 if (!argument_ok) { 526 if (!argument_ok) {
525 LOG_ERROR(Frontend, "Invalid user argument"); 527 // try to look it up by username, only finds the first username that matches.
526 continue; 528 const std::string user_arg_str = args[user_arg_idx].toStdString();
529 const auto user_idx = system->GetProfileManager().GetUserIndex(user_arg_str);
530
531 if (user_idx == std::nullopt) {
532 LOG_ERROR(Frontend, "Invalid user argument");
533 continue;
534 }
535
536 selected_user = user_idx.value();
527 } 537 }
528 538
529 if (!system->GetProfileManager().UserExistsIndex(selected_user)) { 539 if (!system->GetProfileManager().UserExistsIndex(selected_user)) {
@@ -532,6 +542,8 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
532 } 542 }
533 543
534 Settings::values.current_user = static_cast<s32>(selected_user); 544 Settings::values.current_user = static_cast<s32>(selected_user);
545
546 user_flag_cmd_line = true;
535 continue; 547 continue;
536 } 548 }
537 549
@@ -1942,7 +1954,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1942 1954
1943 Settings::LogSettings(); 1955 Settings::LogSettings();
1944 1956
1945 if (UISettings::values.select_user_on_boot) { 1957 if (UISettings::values.select_user_on_boot && !user_flag_cmd_line) {
1946 const Core::Frontend::ProfileSelectParameters parameters{ 1958 const Core::Frontend::ProfileSelectParameters parameters{
1947 .mode = Service::AM::Applets::UiMode::UserSelector, 1959 .mode = Service::AM::Applets::UiMode::UserSelector,
1948 .invalid_uid_list = {}, 1960 .invalid_uid_list = {},
@@ -1954,6 +1966,11 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
1954 } 1966 }
1955 } 1967 }
1956 1968
1969 // If the user specifies -u (successfully) on the cmd line, don't prompt for a user on first
1970 // game startup only. If the user stops emulation and starts a new one, go back to the expected
1971 // behavior of asking.
1972 user_flag_cmd_line = false;
1973
1957 if (!LoadROM(filename, program_id, program_index, launch_type)) { 1974 if (!LoadROM(filename, program_id, program_index, launch_type)) {
1958 return; 1975 return;
1959 } 1976 }
@@ -2460,10 +2477,8 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT
2460} 2477}
2461 2478
2462void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { 2479void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) {
2463 const auto& fs_controller = system->GetFileSystemController(); 2480 const auto res =
2464 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || 2481 ContentManager::RemoveBaseContent(system->GetFileSystemController(), program_id);
2465 fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id);
2466
2467 if (res) { 2482 if (res) {
2468 QMessageBox::information(this, tr("Successfully Removed"), 2483 QMessageBox::information(this, tr("Successfully Removed"),
2469 tr("Successfully removed the installed base game.")); 2484 tr("Successfully removed the installed base game."));
@@ -2475,11 +2490,7 @@ void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) {
2475} 2490}
2476 2491
2477void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { 2492void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) {
2478 const auto update_id = program_id | 0x800; 2493 const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id);
2479 const auto& fs_controller = system->GetFileSystemController();
2480 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) ||
2481 fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id);
2482
2483 if (res) { 2494 if (res) {
2484 QMessageBox::information(this, tr("Successfully Removed"), 2495 QMessageBox::information(this, tr("Successfully Removed"),
2485 tr("Successfully removed the installed update.")); 2496 tr("Successfully removed the installed update."));
@@ -2490,22 +2501,7 @@ void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) {
2490} 2501}
2491 2502
2492void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) { 2503void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) {
2493 u32 count{}; 2504 const size_t count = ContentManager::RemoveAllDLC(system.get(), program_id);
2494 const auto& fs_controller = system->GetFileSystemController();
2495 const auto dlc_entries = system->GetContentProvider().ListEntriesFilter(
2496 FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
2497
2498 for (const auto& entry : dlc_entries) {
2499 if (FileSys::GetBaseTitleID(entry.title_id) == program_id) {
2500 const auto res =
2501 fs_controller.GetUserNANDContents()->RemoveExistingEntry(entry.title_id) ||
2502 fs_controller.GetSDMCContents()->RemoveExistingEntry(entry.title_id);
2503 if (res) {
2504 ++count;
2505 }
2506 }
2507 }
2508
2509 if (count == 0) { 2505 if (count == 0) {
2510 QMessageBox::warning(this, GetGameListErrorRemoving(type), 2506 QMessageBox::warning(this, GetGameListErrorRemoving(type),
2511 tr("There are no DLC installed for this title.")); 2507 tr("There are no DLC installed for this title."));
@@ -2790,16 +2786,6 @@ void GMainWindow::OnGameListVerifyIntegrity(const std::string& game_path) {
2790 QMessageBox::warning(this, tr("Integrity verification couldn't be performed!"), 2786 QMessageBox::warning(this, tr("Integrity verification couldn't be performed!"),
2791 tr("File contents were not checked for validity.")); 2787 tr("File contents were not checked for validity."));
2792 }; 2788 };
2793 const auto Failed = [this] {
2794 QMessageBox::critical(this, tr("Integrity verification failed!"),
2795 tr("File contents may be corrupt."));
2796 };
2797
2798 const auto loader = Loader::GetLoader(*system, vfs->OpenFile(game_path, FileSys::Mode::Read));
2799 if (loader == nullptr) {
2800 NotImplemented();
2801 return;
2802 }
2803 2789
2804 QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); 2790 QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this);
2805 progress.setWindowModality(Qt::WindowModal); 2791 progress.setWindowModality(Qt::WindowModal);
@@ -2807,30 +2793,26 @@ void GMainWindow::OnGameListVerifyIntegrity(const std::string& game_path) {
2807 progress.setAutoClose(false); 2793 progress.setAutoClose(false);
2808 progress.setAutoReset(false); 2794 progress.setAutoReset(false);
2809 2795
2810 const auto QtProgressCallback = [&](size_t processed_size, size_t total_size) { 2796 const auto QtProgressCallback = [&](size_t total_size, size_t processed_size) {
2811 if (progress.wasCanceled()) {
2812 return false;
2813 }
2814
2815 progress.setValue(static_cast<int>((processed_size * 100) / total_size)); 2797 progress.setValue(static_cast<int>((processed_size * 100) / total_size));
2816 return true; 2798 return progress.wasCanceled();
2817 }; 2799 };
2818 2800
2819 const auto status = loader->VerifyIntegrity(QtProgressCallback); 2801 const auto result =
2820 if (progress.wasCanceled() || 2802 ContentManager::VerifyGameContents(system.get(), game_path, QtProgressCallback);
2821 status == Loader::ResultStatus::ErrorIntegrityVerificationNotImplemented) { 2803 progress.close();
2804 switch (result) {
2805 case ContentManager::GameVerificationResult::Success:
2806 QMessageBox::information(this, tr("Integrity verification succeeded!"),
2807 tr("The operation completed successfully."));
2808 break;
2809 case ContentManager::GameVerificationResult::Failed:
2810 QMessageBox::critical(this, tr("Integrity verification failed!"),
2811 tr("File contents may be corrupt."));
2812 break;
2813 case ContentManager::GameVerificationResult::NotImplemented:
2822 NotImplemented(); 2814 NotImplemented();
2823 return;
2824 } 2815 }
2825
2826 if (status == Loader::ResultStatus::ErrorIntegrityVerificationFailed) {
2827 Failed();
2828 return;
2829 }
2830
2831 progress.close();
2832 QMessageBox::information(this, tr("Integrity verification succeeded!"),
2833 tr("The operation completed successfully."));
2834} 2816}
2835 2817
2836void GMainWindow::OnGameListCopyTID(u64 program_id) { 2818void GMainWindow::OnGameListCopyTID(u64 program_id) {
@@ -3274,12 +3256,21 @@ void GMainWindow::OnMenuInstallToNAND() {
3274 install_progress->setLabelText( 3256 install_progress->setLabelText(
3275 tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName())); 3257 tr("Installing file \"%1\"...").arg(QFileInfo(file).fileName()));
3276 3258
3277 QFuture<InstallResult> future; 3259 QFuture<ContentManager::InstallResult> future;
3278 InstallResult result; 3260 ContentManager::InstallResult result;
3279 3261
3280 if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) { 3262 if (file.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
3281 3263 const auto progress_callback = [this](size_t size, size_t progress) {
3282 future = QtConcurrent::run([this, &file] { return InstallNSP(file); }); 3264 emit UpdateInstallProgress();
3265 if (install_progress->wasCanceled()) {
3266 return true;
3267 }
3268 return false;
3269 };
3270 future = QtConcurrent::run([this, &file, progress_callback] {
3271 return ContentManager::InstallNSP(system.get(), vfs.get(), file.toStdString(),
3272 progress_callback);
3273 });
3283 3274
3284 while (!future.isFinished()) { 3275 while (!future.isFinished()) {
3285 QCoreApplication::processEvents(); 3276 QCoreApplication::processEvents();
@@ -3295,16 +3286,16 @@ void GMainWindow::OnMenuInstallToNAND() {
3295 std::this_thread::sleep_for(std::chrono::milliseconds(10)); 3286 std::this_thread::sleep_for(std::chrono::milliseconds(10));
3296 3287
3297 switch (result) { 3288 switch (result) {
3298 case InstallResult::Success: 3289 case ContentManager::InstallResult::Success:
3299 new_files.append(QFileInfo(file).fileName()); 3290 new_files.append(QFileInfo(file).fileName());
3300 break; 3291 break;
3301 case InstallResult::Overwrite: 3292 case ContentManager::InstallResult::Overwrite:
3302 overwritten_files.append(QFileInfo(file).fileName()); 3293 overwritten_files.append(QFileInfo(file).fileName());
3303 break; 3294 break;
3304 case InstallResult::Failure: 3295 case ContentManager::InstallResult::Failure:
3305 failed_files.append(QFileInfo(file).fileName()); 3296 failed_files.append(QFileInfo(file).fileName());
3306 break; 3297 break;
3307 case InstallResult::BaseInstallAttempted: 3298 case ContentManager::InstallResult::BaseInstallAttempted:
3308 failed_files.append(QFileInfo(file).fileName()); 3299 failed_files.append(QFileInfo(file).fileName());
3309 detected_base_install = true; 3300 detected_base_install = true;
3310 break; 3301 break;
@@ -3338,96 +3329,7 @@ void GMainWindow::OnMenuInstallToNAND() {
3338 ui->action_Install_File_NAND->setEnabled(true); 3329 ui->action_Install_File_NAND->setEnabled(true);
3339} 3330}
3340 3331
3341InstallResult GMainWindow::InstallNSP(const QString& filename) { 3332ContentManager::InstallResult GMainWindow::InstallNCA(const QString& filename) {
3342 const auto qt_raw_copy = [this](const FileSys::VirtualFile& src,
3343 const FileSys::VirtualFile& dest, std::size_t block_size) {
3344 if (src == nullptr || dest == nullptr) {
3345 return false;
3346 }
3347 if (!dest->Resize(src->GetSize())) {
3348 return false;
3349 }
3350
3351 std::vector<u8> buffer(CopyBufferSize);
3352
3353 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
3354 if (install_progress->wasCanceled()) {
3355 dest->Resize(0);
3356 return false;
3357 }
3358
3359 emit UpdateInstallProgress();
3360
3361 const auto read = src->Read(buffer.data(), buffer.size(), i);
3362 dest->Write(buffer.data(), read, i);
3363 }
3364 return true;
3365 };
3366
3367 std::shared_ptr<FileSys::NSP> nsp;
3368 if (filename.endsWith(QStringLiteral("nsp"), Qt::CaseInsensitive)) {
3369 nsp = std::make_shared<FileSys::NSP>(
3370 vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
3371 if (nsp->IsExtractedType()) {
3372 return InstallResult::Failure;
3373 }
3374 } else {
3375 return InstallResult::Failure;
3376 }
3377
3378 if (nsp->GetStatus() != Loader::ResultStatus::Success) {
3379 return InstallResult::Failure;
3380 }
3381 const auto res = system->GetFileSystemController().GetUserNANDContents()->InstallEntry(
3382 *nsp, true, qt_raw_copy);
3383 switch (res) {
3384 case FileSys::InstallResult::Success:
3385 return InstallResult::Success;
3386 case FileSys::InstallResult::OverwriteExisting:
3387 return InstallResult::Overwrite;
3388 case FileSys::InstallResult::ErrorBaseInstall:
3389 return InstallResult::BaseInstallAttempted;
3390 default:
3391 return InstallResult::Failure;
3392 }
3393}
3394
3395InstallResult GMainWindow::InstallNCA(const QString& filename) {
3396 const auto qt_raw_copy = [this](const FileSys::VirtualFile& src,
3397 const FileSys::VirtualFile& dest, std::size_t block_size) {
3398 if (src == nullptr || dest == nullptr) {
3399 return false;
3400 }
3401 if (!dest->Resize(src->GetSize())) {
3402 return false;
3403 }
3404
3405 std::vector<u8> buffer(CopyBufferSize);
3406
3407 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
3408 if (install_progress->wasCanceled()) {
3409 dest->Resize(0);
3410 return false;
3411 }
3412
3413 emit UpdateInstallProgress();
3414
3415 const auto read = src->Read(buffer.data(), buffer.size(), i);
3416 dest->Write(buffer.data(), read, i);
3417 }
3418 return true;
3419 };
3420
3421 const auto nca =
3422 std::make_shared<FileSys::NCA>(vfs->OpenFile(filename.toStdString(), FileSys::Mode::Read));
3423 const auto id = nca->GetStatus();
3424
3425 // Game updates necessary are missing base RomFS
3426 if (id != Loader::ResultStatus::Success &&
3427 id != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
3428 return InstallResult::Failure;
3429 }
3430
3431 const QStringList tt_options{tr("System Application"), 3333 const QStringList tt_options{tr("System Application"),
3432 tr("System Archive"), 3334 tr("System Archive"),
3433 tr("System Application Update"), 3335 tr("System Application Update"),
@@ -3448,7 +3350,7 @@ InstallResult GMainWindow::InstallNCA(const QString& filename) {
3448 if (!ok || index == -1) { 3350 if (!ok || index == -1) {
3449 QMessageBox::warning(this, tr("Failed to Install"), 3351 QMessageBox::warning(this, tr("Failed to Install"),
3450 tr("The title type you selected for the NCA is invalid.")); 3352 tr("The title type you selected for the NCA is invalid."));
3451 return InstallResult::Failure; 3353 return ContentManager::InstallResult::Failure;
3452 } 3354 }
3453 3355
3454 // If index is equal to or past Game, add the jump in TitleType. 3356 // If index is equal to or past Game, add the jump in TitleType.
@@ -3462,15 +3364,15 @@ InstallResult GMainWindow::InstallNCA(const QString& filename) {
3462 auto* registered_cache = is_application ? fs_controller.GetUserNANDContents() 3364 auto* registered_cache = is_application ? fs_controller.GetUserNANDContents()
3463 : fs_controller.GetSystemNANDContents(); 3365 : fs_controller.GetSystemNANDContents();
3464 3366
3465 const auto res = registered_cache->InstallEntry(*nca, static_cast<FileSys::TitleType>(index), 3367 const auto progress_callback = [this](size_t size, size_t progress) {
3466 true, qt_raw_copy); 3368 emit UpdateInstallProgress();
3467 if (res == FileSys::InstallResult::Success) { 3369 if (install_progress->wasCanceled()) {
3468 return InstallResult::Success; 3370 return true;
3469 } else if (res == FileSys::InstallResult::OverwriteExisting) { 3371 }
3470 return InstallResult::Overwrite; 3372 return false;
3471 } else { 3373 };
3472 return InstallResult::Failure; 3374 return ContentManager::InstallNCA(vfs.get(), filename.toStdString(), registered_cache,
3473 } 3375 static_cast<FileSys::TitleType>(index), progress_callback);
3474} 3376}
3475 3377
3476void GMainWindow::OnMenuRecentFile() { 3378void GMainWindow::OnMenuRecentFile() {
@@ -4205,10 +4107,6 @@ void GMainWindow::OnOpenYuzuFolder() {
4205} 4107}
4206 4108
4207void GMainWindow::OnVerifyInstalledContents() { 4109void GMainWindow::OnVerifyInstalledContents() {
4208 // Declare sizes.
4209 size_t total_size = 0;
4210 size_t processed_size = 0;
4211
4212 // Initialize a progress dialog. 4110 // Initialize a progress dialog.
4213 QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this); 4111 QProgressDialog progress(tr("Verifying integrity..."), tr("Cancel"), 0, 100, this);
4214 progress.setWindowModality(Qt::WindowModal); 4112 progress.setWindowModality(Qt::WindowModal);
@@ -4216,93 +4114,25 @@ void GMainWindow::OnVerifyInstalledContents() {
4216 progress.setAutoClose(false); 4114 progress.setAutoClose(false);
4217 progress.setAutoReset(false); 4115 progress.setAutoReset(false);
4218 4116
4219 // Declare a list of file names which failed to verify.
4220 std::vector<std::string> failed;
4221
4222 // Declare progress callback. 4117 // Declare progress callback.
4223 auto QtProgressCallback = [&](size_t nca_processed, size_t nca_total) { 4118 auto QtProgressCallback = [&](size_t total_size, size_t processed_size) {
4224 if (progress.wasCanceled()) { 4119 progress.setValue(static_cast<int>((processed_size * 100) / total_size));
4225 return false; 4120 return progress.wasCanceled();
4226 }
4227 progress.setValue(static_cast<int>(((processed_size + nca_processed) * 100) / total_size));
4228 return true;
4229 }; 4121 };
4230 4122
4231 // Get content registries. 4123 const std::vector<std::string> result =
4232 auto bis_contents = system->GetFileSystemController().GetSystemNANDContents(); 4124 ContentManager::VerifyInstalledContents(system.get(), provider.get(), QtProgressCallback);
4233 auto user_contents = system->GetFileSystemController().GetUserNANDContents();
4234
4235 std::vector<FileSys::RegisteredCache*> content_providers;
4236 if (bis_contents) {
4237 content_providers.push_back(bis_contents);
4238 }
4239 if (user_contents) {
4240 content_providers.push_back(user_contents);
4241 }
4242
4243 // Get associated NCA files.
4244 std::vector<FileSys::VirtualFile> nca_files;
4245
4246 // Get all installed IDs.
4247 for (auto nca_provider : content_providers) {
4248 const auto entries = nca_provider->ListEntriesFilter();
4249
4250 for (const auto& entry : entries) {
4251 auto nca_file = nca_provider->GetEntryRaw(entry.title_id, entry.type);
4252 if (!nca_file) {
4253 continue;
4254 }
4255
4256 total_size += nca_file->GetSize();
4257 nca_files.push_back(std::move(nca_file));
4258 }
4259 }
4260
4261 // Using the NCA loader, determine if all NCAs are valid.
4262 for (auto& nca_file : nca_files) {
4263 Loader::AppLoader_NCA nca_loader(nca_file);
4264
4265 auto status = nca_loader.VerifyIntegrity(QtProgressCallback);
4266 if (progress.wasCanceled()) {
4267 break;
4268 }
4269 if (status != Loader::ResultStatus::Success) {
4270 FileSys::NCA nca(nca_file);
4271 const auto title_id = nca.GetTitleId();
4272 std::string title_name = "unknown";
4273
4274 const auto control = provider->GetEntry(FileSys::GetBaseTitleID(title_id),
4275 FileSys::ContentRecordType::Control);
4276 if (control && control->GetStatus() == Loader::ResultStatus::Success) {
4277 const FileSys::PatchManager pm{title_id, system->GetFileSystemController(),
4278 *provider};
4279 const auto [nacp, logo] = pm.ParseControlNCA(*control);
4280 if (nacp) {
4281 title_name = nacp->GetApplicationName();
4282 }
4283 }
4284
4285 if (title_id > 0) {
4286 failed.push_back(
4287 fmt::format("{} ({:016X}) ({})", nca_file->GetName(), title_id, title_name));
4288 } else {
4289 failed.push_back(fmt::format("{} (unknown)", nca_file->GetName()));
4290 }
4291 }
4292
4293 processed_size += nca_file->GetSize();
4294 }
4295
4296 progress.close(); 4125 progress.close();
4297 4126
4298 if (failed.size() > 0) { 4127 if (result.empty()) {
4299 auto failed_names = QString::fromStdString(fmt::format("{}", fmt::join(failed, "\n"))); 4128 QMessageBox::information(this, tr("Integrity verification succeeded!"),
4129 tr("The operation completed successfully."));
4130 } else {
4131 const auto failed_names =
4132 QString::fromStdString(fmt::format("{}", fmt::join(result, "\n")));
4300 QMessageBox::critical( 4133 QMessageBox::critical(
4301 this, tr("Integrity verification failed!"), 4134 this, tr("Integrity verification failed!"),
4302 tr("Verification failed for the following files:\n\n%1").arg(failed_names)); 4135 tr("Verification failed for the following files:\n\n%1").arg(failed_names));
4303 } else {
4304 QMessageBox::information(this, tr("Integrity verification succeeded!"),
4305 tr("The operation completed successfully."));
4306 } 4136 }
4307} 4137}
4308 4138
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 366e806d5..280fae5c3 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -16,6 +16,7 @@
16#include "common/announce_multiplayer_room.h" 16#include "common/announce_multiplayer_room.h"
17#include "common/common_types.h" 17#include "common/common_types.h"
18#include "configuration/qt_config.h" 18#include "configuration/qt_config.h"
19#include "frontend_common/content_manager.h"
19#include "input_common/drivers/tas_input.h" 20#include "input_common/drivers/tas_input.h"
20#include "yuzu/compatibility_list.h" 21#include "yuzu/compatibility_list.h"
21#include "yuzu/hotkeys.h" 22#include "yuzu/hotkeys.h"
@@ -124,13 +125,6 @@ enum class EmulatedDirectoryTarget {
124 SDMC, 125 SDMC,
125}; 126};
126 127
127enum class InstallResult {
128 Success,
129 Overwrite,
130 Failure,
131 BaseInstallAttempted,
132};
133
134enum class ReinitializeKeyBehavior { 128enum class ReinitializeKeyBehavior {
135 NoWarning, 129 NoWarning,
136 Warning, 130 Warning,
@@ -427,8 +421,7 @@ private:
427 void RemoveCacheStorage(u64 program_id); 421 void RemoveCacheStorage(u64 program_id);
428 bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id, 422 bool SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id,
429 u64* selected_title_id, u8* selected_content_record_type); 423 u64* selected_title_id, u8* selected_content_record_type);
430 InstallResult InstallNSP(const QString& filename); 424 ContentManager::InstallResult InstallNCA(const QString& filename);
431 InstallResult InstallNCA(const QString& filename);
432 void MigrateConfigFiles(); 425 void MigrateConfigFiles();
433 void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, 426 void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {},
434 std::string_view gpu_vendor = {}); 427 std::string_view gpu_vendor = {});
@@ -523,6 +516,8 @@ private:
523 std::unique_ptr<EmuThread> emu_thread; 516 std::unique_ptr<EmuThread> emu_thread;
524 // The path to the game currently running 517 // The path to the game currently running
525 QString current_game_path; 518 QString current_game_path;
519 // Whether a user was set on the command line (skips UserSelector if it's forced to show up)
520 bool user_flag_cmd_line = false;
526 521
527 bool auto_paused = false; 522 bool auto_paused = false;
528 bool auto_muted = false; 523 bool auto_muted = false;