summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/build.gradle.kts4
-rw-r--r--src/android/app/src/main/AndroidManifest.xml1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt98
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt20
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt90
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt72
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AppletLauncherFragment.kt113
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/CabinetLauncherDialogFragment.kt41
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt66
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/HomeSettingsFragment.kt90
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/MessageDialogFragment.kt5
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Applet.kt55
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt21
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt46
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt3
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.kt70
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt17
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt6
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt17
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt3
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameMetadata.kt20
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt55
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt45
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt34
-rw-r--r--src/android/app/src/main/jni/CMakeLists.txt3
-rw-r--r--src/android/app/src/main/jni/game_metadata.cpp112
-rw-r--r--src/android/app/src/main/jni/native.cpp821
-rw-r--r--src/android/app/src/main/jni/native.h84
-rw-r--r--src/android/app/src/main/jni/native_log.cpp31
-rw-r--r--src/android/app/src/main/res/drawable/ic_album.xml9
-rw-r--r--src/android/app/src/main/res/drawable/ic_applet.xml9
-rw-r--r--src/android/app/src/main/res/drawable/ic_edit.xml9
-rw-r--r--src/android/app/src/main/res/drawable/ic_mii.xml18
-rw-r--r--src/android/app/src/main/res/drawable/ic_refresh.xml9
-rw-r--r--src/android/app/src/main/res/drawable/ic_restore.xml9
-rw-r--r--src/android/app/src/main/res/layout/card_applet_option.xml57
-rw-r--r--src/android/app/src/main/res/layout/card_game.xml45
-rw-r--r--src/android/app/src/main/res/layout/card_home_option.xml3
-rw-r--r--src/android/app/src/main/res/layout/dialog_list.xml15
-rw-r--r--src/android/app/src/main/res/layout/dialog_list_item.xml30
-rw-r--r--src/android/app/src/main/res/layout/fragment_applet_launcher.xml31
-rw-r--r--src/android/app/src/main/res/layout/fragment_emulation.xml8
-rw-r--r--src/android/app/src/main/res/navigation/home_navigation.xml15
-rw-r--r--src/android/app/src/main/res/resources.properties1
-rw-r--r--src/android/app/src/main/res/values-ar/strings.xml385
-rw-r--r--src/android/app/src/main/res/values-ckb/strings.xml336
-rw-r--r--src/android/app/src/main/res/values-de/strings.xml119
-rw-r--r--src/android/app/src/main/res/values-es/strings.xml180
-rw-r--r--src/android/app/src/main/res/values-fr/strings.xml180
-rw-r--r--src/android/app/src/main/res/values-he/strings.xml367
-rw-r--r--src/android/app/src/main/res/values-hu/strings.xml402
-rw-r--r--src/android/app/src/main/res/values-it/strings.xml192
-rw-r--r--src/android/app/src/main/res/values-ja/strings.xml218
-rw-r--r--src/android/app/src/main/res/values-ko/strings.xml273
-rw-r--r--src/android/app/src/main/res/values-nb/strings.xml113
-rw-r--r--src/android/app/src/main/res/values-pl/strings.xml81
-rw-r--r--src/android/app/src/main/res/values-pt-rBR/strings.xml210
-rw-r--r--src/android/app/src/main/res/values-pt-rPT/strings.xml192
-rw-r--r--src/android/app/src/main/res/values-ru/strings.xml159
-rw-r--r--src/android/app/src/main/res/values-uk/strings.xml90
-rw-r--r--src/android/app/src/main/res/values-vi/strings.xml340
-rw-r--r--src/android/app/src/main/res/values-zh-rCN/strings.xml138
-rw-r--r--src/android/app/src/main/res/values-zh-rTW/strings.xml137
-rw-r--r--src/android/app/src/main/res/values/strings.xml20
-rw-r--r--src/android/app/src/main/res/xml/locales_config.xml17
-rw-r--r--src/audio_core/adsp/apps/opus/opus_decode_object.cpp214
-rw-r--r--src/audio_core/adsp/apps/opus/opus_decoder.cpp4
-rw-r--r--src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp222
-rw-r--r--src/audio_core/opus/decoder.cpp358
-rw-r--r--src/audio_core/opus/decoder.h106
-rw-r--r--src/audio_core/opus/decoder_manager.cpp204
-rw-r--r--src/audio_core/opus/decoder_manager.h76
-rw-r--r--src/audio_core/opus/hardware_opus.cpp482
-rw-r--r--src/audio_core/opus/hardware_opus.h90
-rw-r--r--src/common/CMakeLists.txt6
-rw-r--r--src/common/arm64/native_clock.cpp21
-rw-r--r--src/common/fs/fs_android.cpp33
-rw-r--r--src/common/fs/fs_android.h15
-rw-r--r--src/common/fs/fs_paths.h1
-rw-r--r--src/common/fs/path_util.cpp11
-rw-r--r--src/common/fs/path_util.h1
-rw-r--r--src/common/nvidia_flags.cpp1
-rw-r--r--src/common/settings.h1
-rw-r--r--src/common/stb.cpp8
-rw-r--r--src/common/stb.h8
-rw-r--r--src/common/string_util.cpp12
-rw-r--r--src/core/arm/arm_interface.cpp6
-rw-r--r--src/core/core.cpp11
-rw-r--r--src/core/debugger/debugger.cpp24
-rw-r--r--src/core/debugger/gdbstub.cpp42
-rw-r--r--src/core/file_sys/program_metadata.cpp10
-rw-r--r--src/core/file_sys/program_metadata.h15
-rw-r--r--src/core/file_sys/romfs.cpp44
-rw-r--r--src/core/file_sys/romfs.h9
-rw-r--r--src/core/hid/emulated_controller.cpp51
-rw-r--r--src/core/hid/emulated_controller.h3
-rw-r--r--src/core/hid/hid_types.h15
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp59
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_system_control.h13
-rw-r--r--src/core/hle/kernel/k_capabilities.h4
-rw-r--r--src/core/hle/kernel/k_condition_variable.cpp22
-rw-r--r--src/core/hle/kernel/k_condition_variable.h9
-rw-r--r--src/core/hle/kernel/k_interrupt_manager.cpp2
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp125
-rw-r--r--src/core/hle/kernel/k_memory_manager.h12
-rw-r--r--src/core/hle/kernel/k_page_table.cpp14
-rw-r--r--src/core/hle/kernel/k_page_table.h4
-rw-r--r--src/core/hle/kernel/k_process.cpp1442
-rw-r--r--src/core/hle/kernel/k_process.h724
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp4
-rw-r--r--src/core/hle/kernel/k_system_resource.cpp87
-rw-r--r--src/core/hle/kernel/k_thread.cpp28
-rw-r--r--src/core/hle/kernel/k_thread.h1
-rw-r--r--src/core/hle/kernel/kernel.cpp53
-rw-r--r--src/core/hle/kernel/kernel.h3
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_info.cpp28
-rw-r--r--src/core/hle/kernel/svc/svc_lock.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_physical_memory.cpp4
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp7
-rw-r--r--src/core/hle/kernel/svc_generator.py2
-rw-r--r--src/core/hle/kernel/svc_types.h46
-rw-r--r--src/core/hle/service/acc/acc.cpp56
-rw-r--r--src/core/hle/service/am/am.cpp100
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.cpp4
-rw-r--r--src/core/hle/service/am/applets/applet_web_browser.cpp3
-rw-r--r--src/core/hle/service/am/applets/applets.h24
-rw-r--r--src/core/hle/service/caps/caps_manager.cpp30
-rw-r--r--src/core/hle/service/caps/caps_manager.h9
-rw-r--r--src/core/hle/service/caps/caps_ss.cpp10
-rw-r--r--src/core/hle/service/caps/caps_su.cpp42
-rw-r--r--src/core/hle/service/caps/caps_su.h9
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp6
-rw-r--r--src/core/hle/service/hid/controllers/palma.cpp4
-rw-r--r--src/core/hle/service/hid/hid.cpp16
-rw-r--r--src/core/hle/service/hid/hidbus/hidbus_base.cpp5
-rw-r--r--src/core/hle/service/hid/ring_lifo.h6
-rw-r--r--src/core/hle/service/kernel_helpers.cpp6
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_core.cpp6
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.cpp5
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp15
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h3
-rw-r--r--src/core/hle/service/pctl/pctl_module.cpp6
-rw-r--r--src/core/hle/service/pm/pm.cpp2
-rw-r--r--src/core/hle/service/sockets/bsd.cpp77
-rw-r--r--src/core/hle/service/sockets/bsd.h2
-rw-r--r--src/core/reporter.cpp2
-rw-r--r--src/input_common/helpers/joycon_driver.cpp16
-rw-r--r--src/input_common/helpers/joycon_driver.h5
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h13
-rw-r--r--src/video_core/renderer_null/null_rasterizer.cpp13
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp6
-rw-r--r--src/yuzu/CMakeLists.txt10
-rw-r--r--src/yuzu/applets/qt_controller.cpp52
-rw-r--r--src/yuzu/applets/qt_controller.h4
-rw-r--r--src/yuzu/breakpad.cpp77
-rw-r--r--src/yuzu/breakpad.h10
-rw-r--r--src/yuzu/configuration/config.h2
-rw-r--r--src/yuzu/configuration/configure_camera.h2
-rw-r--r--src/yuzu/configuration/configure_debug.cpp18
-rw-r--r--src/yuzu/configuration/configure_debug.ui7
-rw-r--r--src/yuzu/configuration/configure_input.cpp61
-rw-r--r--src/yuzu/configuration/configure_input.h9
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp8
-rw-r--r--src/yuzu/configuration/configure_input_advanced.h8
-rw-r--r--src/yuzu/configuration/configure_input_player.h7
-rw-r--r--src/yuzu/configuration/configure_per_game.h2
-rw-r--r--src/yuzu/configuration/configure_profile_manager.cpp6
-rw-r--r--src/yuzu/configuration/configure_ringcon.h2
-rw-r--r--src/yuzu/configuration/configure_tas.h2
-rw-r--r--src/yuzu/configuration/configure_touchscreen_advanced.h2
-rw-r--r--src/yuzu/configuration/shared_translation.cpp1
-rw-r--r--src/yuzu/debugger/wait_tree.cpp2
-rw-r--r--src/yuzu/game_list.cpp26
-rw-r--r--src/yuzu/game_list.h10
-rw-r--r--src/yuzu/game_list_worker.cpp102
-rw-r--r--src/yuzu/game_list_worker.h35
-rw-r--r--src/yuzu/main.cpp82
-rw-r--r--src/yuzu/main.h25
-rw-r--r--src/yuzu/mini_dump.cpp202
-rw-r--r--src/yuzu/mini_dump.h19
-rw-r--r--src/yuzu/uisettings.h4
190 files changed, 8637 insertions, 3949 deletions
diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts
index ac43d84b7..021b070e0 100644
--- a/src/android/app/build.gradle.kts
+++ b/src/android/app/build.gradle.kts
@@ -47,6 +47,10 @@ android {
47 jniLibs.useLegacyPackaging = true 47 jniLibs.useLegacyPackaging = true
48 } 48 }
49 49
50 androidResources {
51 generateLocaleConfig = true
52 }
53
50 defaultConfig { 54 defaultConfig {
51 // TODO If this is ever modified, change application_id in strings.xml 55 // TODO If this is ever modified, change application_id in strings.xml
52 applicationId = "org.yuzu.yuzu_emu" 56 applicationId = "org.yuzu.yuzu_emu"
diff --git a/src/android/app/src/main/AndroidManifest.xml b/src/android/app/src/main/AndroidManifest.xml
index a67351727..f10131b24 100644
--- a/src/android/app/src/main/AndroidManifest.xml
+++ b/src/android/app/src/main/AndroidManifest.xml
@@ -26,7 +26,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
26 android:supportsRtl="true" 26 android:supportsRtl="true"
27 android:isGame="true" 27 android:isGame="true"
28 android:appCategory="game" 28 android:appCategory="game"
29 android:localeConfig="@xml/locales_config"
30 android:banner="@drawable/tv_banner" 29 android:banner="@drawable/tv_banner"
31 android:fullBackupContent="@xml/data_extraction_rules" 30 android:fullBackupContent="@xml/data_extraction_rules"
32 android:dataExtractionRules="@xml/data_extraction_rules_api_31" 31 android:dataExtractionRules="@xml/data_extraction_rules_api_31"
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 115f72710..9ebd6c732 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
@@ -5,6 +5,7 @@ package org.yuzu.yuzu_emu
5 5
6import android.app.Dialog 6import android.app.Dialog
7import android.content.DialogInterface 7import android.content.DialogInterface
8import android.net.Uri
8import android.os.Bundle 9import android.os.Bundle
9import android.text.Html 10import android.text.Html
10import android.text.method.LinkMovementMethod 11import android.text.method.LinkMovementMethod
@@ -16,7 +17,7 @@ import androidx.fragment.app.DialogFragment
16import com.google.android.material.dialog.MaterialAlertDialogBuilder 17import com.google.android.material.dialog.MaterialAlertDialogBuilder
17import java.lang.ref.WeakReference 18import java.lang.ref.WeakReference
18import org.yuzu.yuzu_emu.activities.EmulationActivity 19import org.yuzu.yuzu_emu.activities.EmulationActivity
19import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath 20import org.yuzu.yuzu_emu.utils.DocumentsTree
20import org.yuzu.yuzu_emu.utils.FileUtil 21import org.yuzu.yuzu_emu.utils.FileUtil
21import org.yuzu.yuzu_emu.utils.Log 22import org.yuzu.yuzu_emu.utils.Log
22import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable 23import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
@@ -68,7 +69,7 @@ object NativeLibrary {
68 @Keep 69 @Keep
69 @JvmStatic 70 @JvmStatic
70 fun openContentUri(path: String?, openmode: String?): Int { 71 fun openContentUri(path: String?, openmode: String?): Int {
71 return if (isNativePath(path!!)) { 72 return if (DocumentsTree.isNativePath(path!!)) {
72 YuzuApplication.documentsTree!!.openContentUri(path, openmode) 73 YuzuApplication.documentsTree!!.openContentUri(path, openmode)
73 } else { 74 } else {
74 FileUtil.openContentUri(path, openmode) 75 FileUtil.openContentUri(path, openmode)
@@ -78,7 +79,7 @@ object NativeLibrary {
78 @Keep 79 @Keep
79 @JvmStatic 80 @JvmStatic
80 fun getSize(path: String?): Long { 81 fun getSize(path: String?): Long {
81 return if (isNativePath(path!!)) { 82 return if (DocumentsTree.isNativePath(path!!)) {
82 YuzuApplication.documentsTree!!.getFileSize(path) 83 YuzuApplication.documentsTree!!.getFileSize(path)
83 } else { 84 } else {
84 FileUtil.getFileSize(path) 85 FileUtil.getFileSize(path)
@@ -88,23 +89,41 @@ object NativeLibrary {
88 @Keep 89 @Keep
89 @JvmStatic 90 @JvmStatic
90 fun exists(path: String?): Boolean { 91 fun exists(path: String?): Boolean {
91 return if (isNativePath(path!!)) { 92 return if (DocumentsTree.isNativePath(path!!)) {
92 YuzuApplication.documentsTree!!.exists(path) 93 YuzuApplication.documentsTree!!.exists(path)
93 } else { 94 } else {
94 FileUtil.exists(path) 95 FileUtil.exists(path, suppressLog = true)
95 } 96 }
96 } 97 }
97 98
98 @Keep 99 @Keep
99 @JvmStatic 100 @JvmStatic
100 fun isDirectory(path: String?): Boolean { 101 fun isDirectory(path: String?): Boolean {
101 return if (isNativePath(path!!)) { 102 return if (DocumentsTree.isNativePath(path!!)) {
102 YuzuApplication.documentsTree!!.isDirectory(path) 103 YuzuApplication.documentsTree!!.isDirectory(path)
103 } else { 104 } else {
104 FileUtil.isDirectory(path) 105 FileUtil.isDirectory(path)
105 } 106 }
106 } 107 }
107 108
109 @Keep
110 @JvmStatic
111 fun getParentDirectory(path: String): String =
112 if (DocumentsTree.isNativePath(path)) {
113 YuzuApplication.documentsTree!!.getParentDirectory(path)
114 } else {
115 path
116 }
117
118 @Keep
119 @JvmStatic
120 fun getFilename(path: String): String =
121 if (DocumentsTree.isNativePath(path)) {
122 YuzuApplication.documentsTree!!.getFilename(path)
123 } else {
124 FileUtil.getFilename(Uri.parse(path))
125 }
126
108 /** 127 /**
109 * Returns true if pro controller isn't available and handheld is 128 * Returns true if pro controller isn't available and handheld is
110 */ 129 */
@@ -215,32 +234,6 @@ object NativeLibrary {
215 234
216 external fun initGameIni(gameID: String?) 235 external fun initGameIni(gameID: String?)
217 236
218 /**
219 * Gets the embedded icon within the given ROM.
220 *
221 * @param filename the file path to the ROM.
222 * @return a byte array containing the JPEG data for the icon.
223 */
224 external fun getIcon(filename: String): ByteArray
225
226 /**
227 * Gets the embedded title of the given ISO/ROM.
228 *
229 * @param filename The file path to the ISO/ROM.
230 * @return the embedded title of the ISO/ROM.
231 */
232 external fun getTitle(filename: String): String
233
234 external fun getDescription(filename: String): String
235
236 external fun getGameId(filename: String): String
237
238 external fun getRegions(filename: String): String
239
240 external fun getCompany(filename: String): String
241
242 external fun isHomebrew(filename: String): Boolean
243
244 external fun setAppDirectory(directory: String) 237 external fun setAppDirectory(directory: String)
245 238
246 /** 239 /**
@@ -259,7 +252,7 @@ object NativeLibrary {
259 252
260 external fun reloadKeys(): Boolean 253 external fun reloadKeys(): Boolean
261 254
262 external fun initializeEmulation() 255 external fun initializeSystem(reload: Boolean)
263 256
264 external fun defaultCPUCore(): Int 257 external fun defaultCPUCore(): Int
265 258
@@ -294,11 +287,6 @@ object NativeLibrary {
294 external fun stopEmulation() 287 external fun stopEmulation()
295 288
296 /** 289 /**
297 * Resets the in-memory ROM metadata cache.
298 */
299 external fun resetRomMetadata()
300
301 /**
302 * Returns true if emulation is running (or is paused). 290 * Returns true if emulation is running (or is paused).
303 */ 291 */
304 external fun isRunning(): Boolean 292 external fun isRunning(): Boolean
@@ -474,12 +462,12 @@ object NativeLibrary {
474 } 462 }
475 463
476 fun setEmulationActivity(emulationActivity: EmulationActivity?) { 464 fun setEmulationActivity(emulationActivity: EmulationActivity?) {
477 Log.verbose("[NativeLibrary] Registering EmulationActivity.") 465 Log.debug("[NativeLibrary] Registering EmulationActivity.")
478 sEmulationActivity = WeakReference(emulationActivity) 466 sEmulationActivity = WeakReference(emulationActivity)
479 } 467 }
480 468
481 fun clearEmulationActivity() { 469 fun clearEmulationActivity() {
482 Log.verbose("[NativeLibrary] Unregistering EmulationActivity.") 470 Log.debug("[NativeLibrary] Unregistering EmulationActivity.")
483 sEmulationActivity.clear() 471 sEmulationActivity.clear()
484 } 472 }
485 473
@@ -518,6 +506,36 @@ object NativeLibrary {
518 external fun initializeEmptyUserDirectory() 506 external fun initializeEmptyUserDirectory()
519 507
520 /** 508 /**
509 * Gets the launch path for a given applet. It is the caller's responsibility to also
510 * set the system's current applet ID before trying to launch the nca given by this function.
511 *
512 * @param id The applet entry ID
513 * @return The applet's launch path
514 */
515 external fun getAppletLaunchPath(id: Long): String
516
517 /**
518 * Sets the system's current applet ID before launching.
519 *
520 * @param appletId One of the ids in the Service::AM::Applets::AppletId enum
521 */
522 external fun setCurrentAppletId(appletId: Int)
523
524 /**
525 * Sets the cabinet mode for launching the cabinet applet.
526 *
527 * @param cabinetMode One of the modes that corresponds to the enum in Service::NFP::CabinetMode
528 */
529 external fun setCabinetMode(cabinetMode: Int)
530
531 /**
532 * Checks whether NAND contents are available and valid.
533 *
534 * @return 'true' if firmware is available
535 */
536 external fun isFirmwareAvailable(): Boolean
537
538 /**
521 * Button type for use in onTouchEvent 539 * Button type for use in onTouchEvent
522 */ 540 */
523 object ButtonType { 541 object ButtonType {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
index 8c053670c..d114bd53d 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
@@ -11,6 +11,7 @@ import java.io.File
11import org.yuzu.yuzu_emu.utils.DirectoryInitialization 11import org.yuzu.yuzu_emu.utils.DirectoryInitialization
12import org.yuzu.yuzu_emu.utils.DocumentsTree 12import org.yuzu.yuzu_emu.utils.DocumentsTree
13import org.yuzu.yuzu_emu.utils.GpuDriverHelper 13import org.yuzu.yuzu_emu.utils.GpuDriverHelper
14import org.yuzu.yuzu_emu.utils.Log
14 15
15fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir 16fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
16 17
@@ -49,6 +50,7 @@ class YuzuApplication : Application() {
49 DirectoryInitialization.start() 50 DirectoryInitialization.start()
50 GpuDriverHelper.initializeDriverParameters() 51 GpuDriverHelper.initializeDriverParameters()
51 NativeLibrary.logDeviceInfo() 52 NativeLibrary.logDeviceInfo()
53 Log.logDeviceInfo()
52 54
53 createNotificationChannels() 55 createNotificationChannels()
54 } 56 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
index e96a2059b..054e4b755 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
@@ -45,9 +45,9 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
45import org.yuzu.yuzu_emu.features.settings.model.Settings 45import org.yuzu.yuzu_emu.features.settings.model.Settings
46import org.yuzu.yuzu_emu.model.EmulationViewModel 46import org.yuzu.yuzu_emu.model.EmulationViewModel
47import org.yuzu.yuzu_emu.model.Game 47import org.yuzu.yuzu_emu.model.Game
48import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
49import org.yuzu.yuzu_emu.utils.ForegroundService 48import org.yuzu.yuzu_emu.utils.ForegroundService
50import org.yuzu.yuzu_emu.utils.InputHandler 49import org.yuzu.yuzu_emu.utils.InputHandler
50import org.yuzu.yuzu_emu.utils.Log
51import org.yuzu.yuzu_emu.utils.MemoryUtil 51import org.yuzu.yuzu_emu.utils.MemoryUtil
52import org.yuzu.yuzu_emu.utils.NfcReader 52import org.yuzu.yuzu_emu.utils.NfcReader
53import org.yuzu.yuzu_emu.utils.ThemeHelper 53import org.yuzu.yuzu_emu.utils.ThemeHelper
@@ -57,17 +57,16 @@ import kotlin.math.roundToInt
57class EmulationActivity : AppCompatActivity(), SensorEventListener { 57class EmulationActivity : AppCompatActivity(), SensorEventListener {
58 private lateinit var binding: ActivityEmulationBinding 58 private lateinit var binding: ActivityEmulationBinding
59 59
60 private var controllerMappingHelper: ControllerMappingHelper? = null
61
62 var isActivityRecreated = false 60 var isActivityRecreated = false
63 private lateinit var nfcReader: NfcReader 61 private lateinit var nfcReader: NfcReader
64 private lateinit var inputHandler: InputHandler
65 62
66 private val gyro = FloatArray(3) 63 private val gyro = FloatArray(3)
67 private val accel = FloatArray(3) 64 private val accel = FloatArray(3)
68 private var motionTimestamp: Long = 0 65 private var motionTimestamp: Long = 0
69 private var flipMotionOrientation: Boolean = false 66 private var flipMotionOrientation: Boolean = false
70 67
68 private var controllerIds = InputHandler.getGameControllerIds()
69
71 private val actionPause = "ACTION_EMULATOR_PAUSE" 70 private val actionPause = "ACTION_EMULATOR_PAUSE"
72 private val actionPlay = "ACTION_EMULATOR_PLAY" 71 private val actionPlay = "ACTION_EMULATOR_PLAY"
73 private val actionMute = "ACTION_EMULATOR_MUTE" 72 private val actionMute = "ACTION_EMULATOR_MUTE"
@@ -82,6 +81,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
82 } 81 }
83 82
84 override fun onCreate(savedInstanceState: Bundle?) { 83 override fun onCreate(savedInstanceState: Bundle?) {
84 Log.gameLaunched = true
85 ThemeHelper.setTheme(this) 85 ThemeHelper.setTheme(this)
86 86
87 super.onCreate(savedInstanceState) 87 super.onCreate(savedInstanceState)
@@ -95,8 +95,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
95 95
96 isActivityRecreated = savedInstanceState != null 96 isActivityRecreated = savedInstanceState != null
97 97
98 controllerMappingHelper = ControllerMappingHelper()
99
100 // Set these options now so that the SurfaceView the game renders into is the right size. 98 // Set these options now so that the SurfaceView the game renders into is the right size.
101 enableFullscreenImmersive() 99 enableFullscreenImmersive()
102 100
@@ -105,12 +103,11 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
105 nfcReader = NfcReader(this) 103 nfcReader = NfcReader(this)
106 nfcReader.initialize() 104 nfcReader.initialize()
107 105
108 inputHandler = InputHandler() 106 InputHandler.initialize()
109 inputHandler.initialize()
110 107
111 val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) 108 val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
112 if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) { 109 if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) {
113 if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.Gb)) { 110 if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.totalMemory)) {
114 Toast.makeText( 111 Toast.makeText(
115 this, 112 this,
116 getString( 113 getString(
@@ -162,6 +159,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
162 super.onResume() 159 super.onResume()
163 nfcReader.startScanning() 160 nfcReader.startScanning()
164 startMotionSensorListener() 161 startMotionSensorListener()
162 InputHandler.updateControllerIds()
165 163
166 buildPictureInPictureParams() 164 buildPictureInPictureParams()
167 } 165 }
@@ -195,7 +193,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
195 return super.dispatchKeyEvent(event) 193 return super.dispatchKeyEvent(event)
196 } 194 }
197 195
198 return inputHandler.dispatchKeyEvent(event) 196 return InputHandler.dispatchKeyEvent(event)
199 } 197 }
200 198
201 override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean { 199 override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
@@ -210,7 +208,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
210 return true 208 return true
211 } 209 }
212 210
213 return inputHandler.dispatchGenericMotionEvent(event) 211 return InputHandler.dispatchGenericMotionEvent(event)
214 } 212 }
215 213
216 override fun onSensorChanged(event: SensorEvent) { 214 override fun onSensorChanged(event: SensorEvent) {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt
new file mode 100644
index 000000000..a21a705c1
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AppletAdapter.kt
@@ -0,0 +1,90 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.adapters
5
6import android.view.LayoutInflater
7import android.view.View
8import android.view.ViewGroup
9import android.widget.Toast
10import androidx.core.content.res.ResourcesCompat
11import androidx.fragment.app.FragmentActivity
12import androidx.navigation.findNavController
13import androidx.recyclerview.widget.RecyclerView
14import org.yuzu.yuzu_emu.HomeNavigationDirections
15import org.yuzu.yuzu_emu.NativeLibrary
16import org.yuzu.yuzu_emu.R
17import org.yuzu.yuzu_emu.YuzuApplication
18import org.yuzu.yuzu_emu.databinding.CardAppletOptionBinding
19import org.yuzu.yuzu_emu.model.Applet
20import org.yuzu.yuzu_emu.model.AppletInfo
21import org.yuzu.yuzu_emu.model.Game
22
23class AppletAdapter(val activity: FragmentActivity, var applets: List<Applet>) :
24 RecyclerView.Adapter<AppletAdapter.AppletViewHolder>(),
25 View.OnClickListener {
26
27 override fun onCreateViewHolder(
28 parent: ViewGroup,
29 viewType: Int
30 ): AppletAdapter.AppletViewHolder {
31 CardAppletOptionBinding.inflate(LayoutInflater.from(parent.context), parent, false)
32 .apply { root.setOnClickListener(this@AppletAdapter) }
33 .also { return AppletViewHolder(it) }
34 }
35
36 override fun onBindViewHolder(holder: AppletViewHolder, position: Int) =
37 holder.bind(applets[position])
38
39 override fun getItemCount(): Int = applets.size
40
41 override fun onClick(view: View) {
42 val applet = (view.tag as AppletViewHolder).applet
43 val appletPath = NativeLibrary.getAppletLaunchPath(applet.appletInfo.entryId)
44 if (appletPath.isEmpty()) {
45 Toast.makeText(
46 YuzuApplication.appContext,
47 R.string.applets_error_applet,
48 Toast.LENGTH_SHORT
49 ).show()
50 return
51 }
52
53 if (applet.appletInfo == AppletInfo.Cabinet) {
54 view.findNavController()
55 .navigate(R.id.action_appletLauncherFragment_to_cabinetLauncherDialogFragment)
56 return
57 }
58
59 NativeLibrary.setCurrentAppletId(applet.appletInfo.appletId)
60 val appletGame = Game(
61 title = YuzuApplication.appContext.getString(applet.titleId),
62 path = appletPath
63 )
64 val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame)
65 view.findNavController().navigate(action)
66 }
67
68 inner class AppletViewHolder(val binding: CardAppletOptionBinding) :
69 RecyclerView.ViewHolder(binding.root) {
70 lateinit var applet: Applet
71
72 init {
73 itemView.tag = this
74 }
75
76 fun bind(applet: Applet) {
77 this.applet = applet
78
79 binding.title.setText(applet.titleId)
80 binding.description.setText(applet.descriptionId)
81 binding.icon.setImageDrawable(
82 ResourcesCompat.getDrawable(
83 binding.icon.context.resources,
84 applet.iconId,
85 binding.icon.context.theme
86 )
87 )
88 }
89 }
90}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt
new file mode 100644
index 000000000..e7b7c0f2f
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/CabinetLauncherDialogAdapter.kt
@@ -0,0 +1,72 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.adapters
5
6import android.view.LayoutInflater
7import android.view.View
8import android.view.ViewGroup
9import androidx.core.content.res.ResourcesCompat
10import androidx.fragment.app.Fragment
11import androidx.navigation.fragment.findNavController
12import androidx.recyclerview.widget.RecyclerView
13import org.yuzu.yuzu_emu.HomeNavigationDirections
14import org.yuzu.yuzu_emu.NativeLibrary
15import org.yuzu.yuzu_emu.R
16import org.yuzu.yuzu_emu.YuzuApplication
17import org.yuzu.yuzu_emu.databinding.DialogListItemBinding
18import org.yuzu.yuzu_emu.model.CabinetMode
19import org.yuzu.yuzu_emu.adapters.CabinetLauncherDialogAdapter.CabinetModeViewHolder
20import org.yuzu.yuzu_emu.model.AppletInfo
21import org.yuzu.yuzu_emu.model.Game
22
23class CabinetLauncherDialogAdapter(val fragment: Fragment) :
24 RecyclerView.Adapter<CabinetModeViewHolder>(),
25 View.OnClickListener {
26 private val cabinetModes = CabinetMode.values().copyOfRange(1, CabinetMode.values().size)
27
28 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CabinetModeViewHolder {
29 DialogListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
30 .apply { root.setOnClickListener(this@CabinetLauncherDialogAdapter) }
31 .also { return CabinetModeViewHolder(it) }
32 }
33
34 override fun getItemCount(): Int = cabinetModes.size
35
36 override fun onBindViewHolder(holder: CabinetModeViewHolder, position: Int) =
37 holder.bind(cabinetModes[position])
38
39 override fun onClick(view: View) {
40 val mode = (view.tag as CabinetModeViewHolder).cabinetMode
41 val appletPath = NativeLibrary.getAppletLaunchPath(AppletInfo.Cabinet.entryId)
42 NativeLibrary.setCurrentAppletId(AppletInfo.Cabinet.appletId)
43 NativeLibrary.setCabinetMode(mode.id)
44 val appletGame = Game(
45 title = YuzuApplication.appContext.getString(R.string.cabinet_applet),
46 path = appletPath
47 )
48 val action = HomeNavigationDirections.actionGlobalEmulationActivity(appletGame)
49 fragment.findNavController().navigate(action)
50 }
51
52 inner class CabinetModeViewHolder(val binding: DialogListItemBinding) :
53 RecyclerView.ViewHolder(binding.root) {
54 lateinit var cabinetMode: CabinetMode
55
56 init {
57 itemView.tag = this
58 }
59
60 fun bind(cabinetMode: CabinetMode) {
61 this.cabinetMode = cabinetMode
62 binding.icon.setImageDrawable(
63 ResourcesCompat.getDrawable(
64 binding.icon.context.resources,
65 cabinetMode.iconId,
66 binding.icon.context.theme
67 )
68 )
69 binding.title.setText(cabinetMode.titleId)
70 }
71 }
72}
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 f9f88a1d2..0c82cdba8 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
@@ -147,7 +147,7 @@ class GameAdapter(private val activity: AppCompatActivity) :
147 147
148 private class DiffCallback : DiffUtil.ItemCallback<Game>() { 148 private class DiffCallback : DiffUtil.ItemCallback<Game>() {
149 override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean { 149 override fun areItemsTheSame(oldItem: Game, newItem: Game): Boolean {
150 return oldItem.gameId == newItem.gameId 150 return oldItem.programId == newItem.programId
151 } 151 }
152 152
153 override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean { 153 override fun areContentsTheSame(oldItem: Game, newItem: Game): Boolean {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AppletLauncherFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AppletLauncherFragment.kt
new file mode 100644
index 000000000..1f66b440d
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/AppletLauncherFragment.kt
@@ -0,0 +1,113 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.fragments
5
6import android.os.Bundle
7import android.view.LayoutInflater
8import android.view.View
9import android.view.ViewGroup
10import androidx.core.view.ViewCompat
11import androidx.core.view.WindowInsetsCompat
12import androidx.core.view.updatePadding
13import androidx.fragment.app.Fragment
14import androidx.fragment.app.activityViewModels
15import androidx.navigation.findNavController
16import androidx.recyclerview.widget.GridLayoutManager
17import com.google.android.material.transition.MaterialSharedAxis
18import org.yuzu.yuzu_emu.R
19import org.yuzu.yuzu_emu.adapters.AppletAdapter
20import org.yuzu.yuzu_emu.databinding.FragmentAppletLauncherBinding
21import org.yuzu.yuzu_emu.model.Applet
22import org.yuzu.yuzu_emu.model.AppletInfo
23import org.yuzu.yuzu_emu.model.HomeViewModel
24
25class AppletLauncherFragment : Fragment() {
26 private var _binding: FragmentAppletLauncherBinding? = null
27 private val binding get() = _binding!!
28
29 private val homeViewModel: HomeViewModel by activityViewModels()
30
31 override fun onCreate(savedInstanceState: Bundle?) {
32 super.onCreate(savedInstanceState)
33 enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
34 returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
35 reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
36 }
37
38 override fun onCreateView(
39 inflater: LayoutInflater,
40 container: ViewGroup?,
41 savedInstanceState: Bundle?
42 ): View {
43 _binding = FragmentAppletLauncherBinding.inflate(inflater)
44 return binding.root
45 }
46
47 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
48 super.onViewCreated(view, savedInstanceState)
49 homeViewModel.setNavigationVisibility(visible = false, animated = true)
50 homeViewModel.setStatusBarShadeVisibility(visible = false)
51
52 binding.toolbarApplets.setNavigationOnClickListener {
53 binding.root.findNavController().popBackStack()
54 }
55
56 val applets = listOf(
57 Applet(
58 R.string.album_applet,
59 R.string.album_applet_description,
60 R.drawable.ic_album,
61 AppletInfo.PhotoViewer
62 ),
63 Applet(
64 R.string.cabinet_applet,
65 R.string.cabinet_applet_description,
66 R.drawable.ic_nfc,
67 AppletInfo.Cabinet
68 ),
69 Applet(
70 R.string.mii_edit_applet,
71 R.string.mii_edit_applet_description,
72 R.drawable.ic_mii,
73 AppletInfo.MiiEdit
74 )
75 )
76
77 binding.listApplets.apply {
78 layoutManager = GridLayoutManager(
79 requireContext(),
80 resources.getInteger(R.integer.grid_columns)
81 )
82 adapter = AppletAdapter(requireActivity(), applets)
83 }
84
85 setInsets()
86 }
87
88 private fun setInsets() =
89 ViewCompat.setOnApplyWindowInsetsListener(
90 binding.root
91 ) { _: View, windowInsets: WindowInsetsCompat ->
92 val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
93 val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
94
95 val leftInsets = barInsets.left + cutoutInsets.left
96 val rightInsets = barInsets.right + cutoutInsets.right
97
98 val mlpAppBar = binding.toolbarApplets.layoutParams as ViewGroup.MarginLayoutParams
99 mlpAppBar.leftMargin = leftInsets
100 mlpAppBar.rightMargin = rightInsets
101 binding.toolbarApplets.layoutParams = mlpAppBar
102
103 val mlpListApplets =
104 binding.listApplets.layoutParams as ViewGroup.MarginLayoutParams
105 mlpListApplets.leftMargin = leftInsets
106 mlpListApplets.rightMargin = rightInsets
107 binding.listApplets.layoutParams = mlpListApplets
108
109 binding.listApplets.updatePadding(bottom = barInsets.bottom)
110
111 windowInsets
112 }
113}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/CabinetLauncherDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/CabinetLauncherDialogFragment.kt
new file mode 100644
index 000000000..5933677fd
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/CabinetLauncherDialogFragment.kt
@@ -0,0 +1,41 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.fragments
5
6import android.app.Dialog
7import android.os.Bundle
8import android.view.LayoutInflater
9import android.view.View
10import android.view.ViewGroup
11import androidx.fragment.app.DialogFragment
12import androidx.recyclerview.widget.LinearLayoutManager
13import com.google.android.material.dialog.MaterialAlertDialogBuilder
14import org.yuzu.yuzu_emu.R
15import org.yuzu.yuzu_emu.adapters.CabinetLauncherDialogAdapter
16import org.yuzu.yuzu_emu.databinding.DialogListBinding
17
18class CabinetLauncherDialogFragment : DialogFragment() {
19 private lateinit var binding: DialogListBinding
20
21 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
22 binding = DialogListBinding.inflate(layoutInflater)
23 binding.dialogList.apply {
24 layoutManager = LinearLayoutManager(requireContext())
25 adapter = CabinetLauncherDialogAdapter(this@CabinetLauncherDialogFragment)
26 }
27
28 return MaterialAlertDialogBuilder(requireContext())
29 .setTitle(R.string.cabinet_launcher)
30 .setView(binding.root)
31 .create()
32 }
33
34 override fun onCreateView(
35 inflater: LayoutInflater,
36 container: ViewGroup?,
37 savedInstanceState: Bundle?
38 ): View {
39 return binding.root
40 }
41}
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 598a9d42b..c32fa0d7e 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
@@ -10,11 +10,11 @@ import android.content.DialogInterface
10import android.content.SharedPreferences 10import android.content.SharedPreferences
11import android.content.pm.ActivityInfo 11import android.content.pm.ActivityInfo
12import android.content.res.Configuration 12import android.content.res.Configuration
13import android.graphics.Color
14import android.net.Uri 13import android.net.Uri
15import android.os.Bundle 14import android.os.Bundle
16import android.os.Handler 15import android.os.Handler
17import android.os.Looper 16import android.os.Looper
17import android.os.SystemClock
18import android.view.* 18import android.view.*
19import android.widget.TextView 19import android.widget.TextView
20import android.widget.Toast 20import android.widget.Toast
@@ -25,6 +25,7 @@ import androidx.core.graphics.Insets
25import androidx.core.view.ViewCompat 25import androidx.core.view.ViewCompat
26import androidx.core.view.WindowInsetsCompat 26import androidx.core.view.WindowInsetsCompat
27import androidx.drawerlayout.widget.DrawerLayout 27import androidx.drawerlayout.widget.DrawerLayout
28import androidx.drawerlayout.widget.DrawerLayout.DrawerListener
28import androidx.fragment.app.Fragment 29import androidx.fragment.app.Fragment
29import androidx.fragment.app.activityViewModels 30import androidx.fragment.app.activityViewModels
30import androidx.lifecycle.Lifecycle 31import androidx.lifecycle.Lifecycle
@@ -153,9 +154,34 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
153 } 154 }
154 155
155 binding.surfaceEmulation.holder.addCallback(this) 156 binding.surfaceEmulation.holder.addCallback(this)
156 binding.showFpsText.setTextColor(Color.YELLOW)
157 binding.doneControlConfig.setOnClickListener { stopConfiguringControls() } 157 binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }
158 158
159 binding.drawerLayout.addDrawerListener(object : DrawerListener {
160 override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
161 binding.surfaceInputOverlay.dispatchTouchEvent(
162 MotionEvent.obtain(
163 SystemClock.uptimeMillis(),
164 SystemClock.uptimeMillis() + 100,
165 MotionEvent.ACTION_UP,
166 0f,
167 0f,
168 0
169 )
170 )
171 }
172
173 override fun onDrawerOpened(drawerView: View) {
174 // No op
175 }
176
177 override fun onDrawerClosed(drawerView: View) {
178 // No op
179 }
180
181 override fun onDrawerStateChanged(newState: Int) {
182 // No op
183 }
184 })
159 binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) 185 binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
160 binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text = 186 binding.inGameMenu.getHeaderView(0).findViewById<TextView>(R.id.text_game_title).text =
161 game.title 187 game.title
@@ -284,6 +310,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
284 ViewUtils.showView(binding.surfaceInputOverlay) 310 ViewUtils.showView(binding.surfaceInputOverlay)
285 ViewUtils.hideView(binding.loadingIndicator) 311 ViewUtils.hideView(binding.loadingIndicator)
286 312
313 emulationState.updateSurface()
314
287 // Setup overlay 315 // Setup overlay
288 updateShowFpsOverlay() 316 updateShowFpsOverlay()
289 } 317 }
@@ -384,12 +412,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
384 val FRAMETIME = 2 412 val FRAMETIME = 2
385 val SPEED = 3 413 val SPEED = 3
386 perfStatsUpdater = { 414 perfStatsUpdater = {
387 if (emulationViewModel.emulationStarted.value == true) { 415 if (emulationViewModel.emulationStarted.value) {
388 val perfStats = NativeLibrary.getPerfStats() 416 val perfStats = NativeLibrary.getPerfStats()
389 if (perfStats[FPS] > 0 && _binding != null) { 417 if (_binding != null) {
390 binding.showFpsText.text = String.format("FPS: %.1f", perfStats[FPS]) 418 binding.showFpsText.text = String.format("FPS: %.1f", perfStats[FPS])
391 } 419 }
392 perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 100) 420 perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 800)
393 } 421 }
394 } 422 }
395 perfStatsUpdateHandler.post(perfStatsUpdater!!) 423 perfStatsUpdateHandler.post(perfStatsUpdater!!)
@@ -434,7 +462,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
434 if (it.orientation == FoldingFeature.Orientation.HORIZONTAL) { 462 if (it.orientation == FoldingFeature.Orientation.HORIZONTAL) {
435 // Restrict emulation and overlays to the top of the screen 463 // Restrict emulation and overlays to the top of the screen
436 binding.emulationContainer.layoutParams.height = it.bounds.top 464 binding.emulationContainer.layoutParams.height = it.bounds.top
437 binding.overlayContainer.layoutParams.height = it.bounds.top
438 // Restrict input and menu drawer to the bottom of the screen 465 // Restrict input and menu drawer to the bottom of the screen
439 binding.inputContainer.layoutParams.height = it.bounds.bottom 466 binding.inputContainer.layoutParams.height = it.bounds.bottom
440 binding.inGameMenu.layoutParams.height = it.bounds.bottom 467 binding.inGameMenu.layoutParams.height = it.bounds.bottom
@@ -448,7 +475,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
448 if (!isFolding) { 475 if (!isFolding) {
449 binding.emulationContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT 476 binding.emulationContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
450 binding.inputContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT 477 binding.inputContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
451 binding.overlayContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
452 binding.inGameMenu.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT 478 binding.inGameMenu.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
453 isInFoldableLayout = false 479 isInFoldableLayout = false
454 updateOrientation() 480 updateOrientation()
@@ -456,7 +482,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
456 } 482 }
457 binding.emulationContainer.requestLayout() 483 binding.emulationContainer.requestLayout()
458 binding.inputContainer.requestLayout() 484 binding.inputContainer.requestLayout()
459 binding.overlayContainer.requestLayout()
460 binding.inGameMenu.requestLayout() 485 binding.inGameMenu.requestLayout()
461 } 486 }
462 487
@@ -682,24 +707,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
682 } 707 }
683 708
684 v.setPadding(left, cutInsets.top, right, 0) 709 v.setPadding(left, cutInsets.top, right, 0)
685
686 // Ensure FPS text doesn't get cut off by rounded display corners
687 val sidePadding = resources.getDimensionPixelSize(R.dimen.spacing_xtralarge)
688 if (cutInsets.left == 0) {
689 binding.showFpsText.setPadding(
690 sidePadding,
691 cutInsets.top,
692 cutInsets.right,
693 cutInsets.bottom
694 )
695 } else {
696 binding.showFpsText.setPadding(
697 cutInsets.left,
698 cutInsets.top,
699 cutInsets.right,
700 cutInsets.bottom
701 )
702 }
703 windowInsets 710 windowInsets
704 } 711 }
705 } 712 }
@@ -777,6 +784,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
777 } 784 }
778 785
779 @Synchronized 786 @Synchronized
787 fun updateSurface() {
788 if (surface != null) {
789 NativeLibrary.surfaceChanged(surface)
790 }
791 }
792
793 @Synchronized
780 fun clearSurface() { 794 fun clearSurface() {
781 if (surface == null) { 795 if (surface == null) {
782 Log.warning("[EmulationFragment] clearSurface called, but surface already null.") 796 Log.warning("[EmulationFragment] clearSurface called, but surface already null.")
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 fd9785075..4720daec4 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
@@ -26,10 +26,11 @@ import androidx.fragment.app.Fragment
26import androidx.fragment.app.activityViewModels 26import androidx.fragment.app.activityViewModels
27import androidx.navigation.findNavController 27import androidx.navigation.findNavController
28import androidx.navigation.fragment.findNavController 28import androidx.navigation.fragment.findNavController
29import androidx.recyclerview.widget.LinearLayoutManager 29import androidx.recyclerview.widget.GridLayoutManager
30import com.google.android.material.transition.MaterialSharedAxis 30import com.google.android.material.transition.MaterialSharedAxis
31import org.yuzu.yuzu_emu.BuildConfig 31import 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.R 34import org.yuzu.yuzu_emu.R
34import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter 35import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter
35import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding 36import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding
@@ -41,6 +42,7 @@ import org.yuzu.yuzu_emu.model.HomeViewModel
41import org.yuzu.yuzu_emu.ui.main.MainActivity 42import org.yuzu.yuzu_emu.ui.main.MainActivity
42import org.yuzu.yuzu_emu.utils.FileUtil 43import org.yuzu.yuzu_emu.utils.FileUtil
43import org.yuzu.yuzu_emu.utils.GpuDriverHelper 44import org.yuzu.yuzu_emu.utils.GpuDriverHelper
45import org.yuzu.yuzu_emu.utils.Log
44 46
45class HomeSettingsFragment : Fragment() { 47class HomeSettingsFragment : Fragment() {
46 private var _binding: FragmentHomeSettingsBinding? = null 48 private var _binding: FragmentHomeSettingsBinding? = null
@@ -85,28 +87,6 @@ class HomeSettingsFragment : Fragment() {
85 ) 87 )
86 add( 88 add(
87 HomeSetting( 89 HomeSetting(
88 R.string.open_user_folder,
89 R.string.open_user_folder_description,
90 R.drawable.ic_folder_open,
91 { openFileManager() }
92 )
93 )
94 add(
95 HomeSetting(
96 R.string.preferences_theme,
97 R.string.theme_and_color_description,
98 R.drawable.ic_palette,
99 {
100 val action = HomeNavigationDirections.actionGlobalSettingsActivity(
101 null,
102 Settings.MenuTag.SECTION_THEME
103 )
104 binding.root.findNavController().navigate(action)
105 }
106 )
107 )
108 add(
109 HomeSetting(
110 R.string.gpu_driver_manager, 90 R.string.gpu_driver_manager,
111 R.string.install_gpu_driver_description, 91 R.string.install_gpu_driver_description,
112 R.drawable.ic_build, 92 R.drawable.ic_build,
@@ -122,6 +102,20 @@ class HomeSettingsFragment : Fragment() {
122 ) 102 )
123 add( 103 add(
124 HomeSetting( 104 HomeSetting(
105 R.string.applets,
106 R.string.applets_description,
107 R.drawable.ic_applet,
108 {
109 binding.root.findNavController()
110 .navigate(R.id.action_homeSettingsFragment_to_appletLauncherFragment)
111 },
112 { NativeLibrary.isFirmwareAvailable() },
113 R.string.applets_error_firmware,
114 R.string.applets_error_description
115 )
116 )
117 add(
118 HomeSetting(
125 R.string.manage_yuzu_data, 119 R.string.manage_yuzu_data,
126 R.string.manage_yuzu_data_description, 120 R.string.manage_yuzu_data_description,
127 R.drawable.ic_install, 121 R.drawable.ic_install,
@@ -157,6 +151,28 @@ class HomeSettingsFragment : Fragment() {
157 ) 151 )
158 add( 152 add(
159 HomeSetting( 153 HomeSetting(
154 R.string.open_user_folder,
155 R.string.open_user_folder_description,
156 R.drawable.ic_folder_open,
157 { openFileManager() }
158 )
159 )
160 add(
161 HomeSetting(
162 R.string.preferences_theme,
163 R.string.theme_and_color_description,
164 R.drawable.ic_palette,
165 {
166 val action = HomeNavigationDirections.actionGlobalSettingsActivity(
167 null,
168 Settings.MenuTag.SECTION_THEME
169 )
170 binding.root.findNavController().navigate(action)
171 }
172 )
173 )
174 add(
175 HomeSetting(
160 R.string.about, 176 R.string.about,
161 R.string.about_description, 177 R.string.about_description,
162 R.drawable.ic_info_outline, 178 R.drawable.ic_info_outline,
@@ -186,7 +202,8 @@ class HomeSettingsFragment : Fragment() {
186 } 202 }
187 203
188 binding.homeSettingsList.apply { 204 binding.homeSettingsList.apply {
189 layoutManager = LinearLayoutManager(requireContext()) 205 layoutManager =
206 GridLayoutManager(requireContext(), resources.getInteger(R.integer.grid_columns))
190 adapter = HomeSettingAdapter( 207 adapter = HomeSettingAdapter(
191 requireActivity() as AppCompatActivity, 208 requireActivity() as AppCompatActivity,
192 viewLifecycleOwner, 209 viewLifecycleOwner,
@@ -296,19 +313,32 @@ class HomeSettingsFragment : Fragment() {
296 } 313 }
297 } 314 }
298 315
316 // Share the current log if we just returned from a game but share the old log
317 // if we just started the app and the old log exists.
299 private fun shareLog() { 318 private fun shareLog() {
300 val file = DocumentFile.fromSingleUri( 319 val currentLog = DocumentFile.fromSingleUri(
301 mainActivity, 320 mainActivity,
302 DocumentsContract.buildDocumentUri( 321 DocumentsContract.buildDocumentUri(
303 DocumentProvider.AUTHORITY, 322 DocumentProvider.AUTHORITY,
304 "${DocumentProvider.ROOT_ID}/log/yuzu_log.txt" 323 "${DocumentProvider.ROOT_ID}/log/yuzu_log.txt"
305 ) 324 )
306 )!! 325 )!!
307 if (file.exists()) { 326 val oldLog = DocumentFile.fromSingleUri(
308 val intent = Intent(Intent.ACTION_SEND) 327 mainActivity,
309 .setDataAndType(file.uri, FileUtil.TEXT_PLAIN) 328 DocumentsContract.buildDocumentUri(
310 .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) 329 DocumentProvider.AUTHORITY,
311 .putExtra(Intent.EXTRA_STREAM, file.uri) 330 "${DocumentProvider.ROOT_ID}/log/yuzu_log.txt.old.txt"
331 )
332 )!!
333
334 val intent = Intent(Intent.ACTION_SEND)
335 .setDataAndType(currentLog.uri, FileUtil.TEXT_PLAIN)
336 .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
337 if (!Log.gameLaunched && oldLog.exists()) {
338 intent.putExtra(Intent.EXTRA_STREAM, oldLog.uri)
339 startActivity(Intent.createChooser(intent, getText(R.string.share_log)))
340 } else if (currentLog.exists()) {
341 intent.putExtra(Intent.EXTRA_STREAM, currentLog.uri)
312 startActivity(Intent.createChooser(intent, getText(R.string.share_log))) 342 startActivity(Intent.createChooser(intent, getText(R.string.share_log)))
313 } else { 343 } else {
314 Toast.makeText( 344 Toast.makeText(
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 541b22f47..a6183d19e 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
@@ -8,6 +8,7 @@ import android.content.DialogInterface
8import android.content.Intent 8import android.content.Intent
9import android.net.Uri 9import android.net.Uri
10import android.os.Bundle 10import android.os.Bundle
11import android.text.Html
11import androidx.fragment.app.DialogFragment 12import androidx.fragment.app.DialogFragment
12import androidx.fragment.app.FragmentActivity 13import androidx.fragment.app.FragmentActivity
13import androidx.fragment.app.activityViewModels 14import androidx.fragment.app.activityViewModels
@@ -32,7 +33,9 @@ class MessageDialogFragment : DialogFragment() {
32 if (titleId != 0) dialog.setTitle(titleId) 33 if (titleId != 0) dialog.setTitle(titleId)
33 if (titleString.isNotEmpty()) dialog.setTitle(titleString) 34 if (titleString.isNotEmpty()) dialog.setTitle(titleString)
34 35
35 if (descriptionId != 0) dialog.setMessage(descriptionId) 36 if (descriptionId != 0) {
37 dialog.setMessage(Html.fromHtml(getString(descriptionId), Html.FROM_HTML_MODE_LEGACY))
38 }
36 if (descriptionString.isNotEmpty()) dialog.setMessage(descriptionString) 39 if (descriptionString.isNotEmpty()) dialog.setMessage(descriptionString)
37 40
38 if (helpLinkId != 0) { 41 if (helpLinkId != 0) {
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Applet.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Applet.kt
new file mode 100644
index 000000000..8677674a3
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Applet.kt
@@ -0,0 +1,55 @@
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.DrawableRes
7import androidx.annotation.StringRes
8import org.yuzu.yuzu_emu.R
9
10data class Applet(
11 @StringRes val titleId: Int,
12 @StringRes val descriptionId: Int,
13 @DrawableRes val iconId: Int,
14 val appletInfo: AppletInfo,
15 val cabinetMode: CabinetMode = CabinetMode.None
16)
17
18// Combination of Common::AM::Applets::AppletId enum and the entry id
19enum class AppletInfo(val appletId: Int, val entryId: Long = 0) {
20 None(0x00),
21 Application(0x01),
22 OverlayDisplay(0x02),
23 QLaunch(0x03),
24 Starter(0x04),
25 Auth(0x0A),
26 Cabinet(0x0B, 0x0100000000001002),
27 Controller(0x0C),
28 DataErase(0x0D),
29 Error(0x0E),
30 NetConnect(0x0F),
31 ProfileSelect(0x10),
32 SoftwareKeyboard(0x11),
33 MiiEdit(0x12, 0x0100000000001009),
34 Web(0x13),
35 Shop(0x14),
36 PhotoViewer(0x015, 0x010000000000100D),
37 Settings(0x16),
38 OfflineWeb(0x17),
39 LoginShare(0x18),
40 WebAuth(0x19),
41 MyPage(0x1A)
42}
43
44// Matches enum in Service::NFP::CabinetMode with extra metadata
45enum class CabinetMode(
46 val id: Int,
47 @StringRes val titleId: Int = 0,
48 @DrawableRes val iconId: Int = 0
49) {
50 None(-1),
51 StartNicknameAndOwnerSettings(0, R.string.cabinet_nickname_and_owner, R.drawable.ic_edit),
52 StartGameDataEraser(1, R.string.cabinet_game_data_eraser, R.drawable.ic_refresh),
53 StartRestorer(2, R.string.cabinet_restorer, R.drawable.ic_restore),
54 StartFormatter(3, R.string.cabinet_formatter, R.drawable.ic_clear)
55}
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 6527c64ab..de84b2adb 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
@@ -11,16 +11,15 @@ import kotlinx.serialization.Serializable
11@Parcelize 11@Parcelize
12@Serializable 12@Serializable
13class Game( 13class Game(
14 val title: String, 14 val title: String = "",
15 val description: String,
16 val regions: String,
17 val path: String, 15 val path: String,
18 val gameId: String, 16 val programId: String = "",
19 val company: String, 17 val developer: String = "",
20 val isHomebrew: Boolean 18 val version: String = "",
19 val isHomebrew: Boolean = false
21) : Parcelable { 20) : Parcelable {
22 val keyAddedToLibraryTime get() = "${gameId}_AddedToLibraryTime" 21 val keyAddedToLibraryTime get() = "${programId}_AddedToLibraryTime"
23 val keyLastPlayedTime get() = "${gameId}_LastPlayed" 22 val keyLastPlayedTime get() = "${programId}_LastPlayed"
24 23
25 override fun equals(other: Any?): Boolean { 24 override fun equals(other: Any?): Boolean {
26 if (other !is Game) { 25 if (other !is Game) {
@@ -32,11 +31,9 @@ class Game(
32 31
33 override fun hashCode(): Int { 32 override fun hashCode(): Int {
34 var result = title.hashCode() 33 var result = title.hashCode()
35 result = 31 * result + description.hashCode()
36 result = 31 * result + regions.hashCode()
37 result = 31 * result + path.hashCode() 34 result = 31 * result + path.hashCode()
38 result = 31 * result + gameId.hashCode() 35 result = 31 * result + programId.hashCode()
39 result = 31 * result + company.hashCode() 36 result = 31 * result + developer.hashCode()
40 result = 31 * result + isHomebrew.hashCode() 37 result = 31 * result + isHomebrew.hashCode()
41 return result 38 return result
42 } 39 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
index 6e09fa81d..8512ed17c 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/GamesViewModel.kt
@@ -14,15 +14,13 @@ import kotlinx.coroutines.flow.MutableStateFlow
14import kotlinx.coroutines.flow.StateFlow 14import kotlinx.coroutines.flow.StateFlow
15import kotlinx.coroutines.launch 15import kotlinx.coroutines.launch
16import kotlinx.coroutines.withContext 16import kotlinx.coroutines.withContext
17import kotlinx.serialization.ExperimentalSerializationApi
18import kotlinx.serialization.MissingFieldException
19import kotlinx.serialization.decodeFromString 17import kotlinx.serialization.decodeFromString
20import kotlinx.serialization.json.Json 18import kotlinx.serialization.json.Json
21import org.yuzu.yuzu_emu.NativeLibrary 19import org.yuzu.yuzu_emu.NativeLibrary
22import org.yuzu.yuzu_emu.YuzuApplication 20import org.yuzu.yuzu_emu.YuzuApplication
23import org.yuzu.yuzu_emu.utils.GameHelper 21import org.yuzu.yuzu_emu.utils.GameHelper
22import org.yuzu.yuzu_emu.utils.GameMetadata
24 23
25@OptIn(ExperimentalSerializationApi::class)
26class GamesViewModel : ViewModel() { 24class GamesViewModel : ViewModel() {
27 val games: StateFlow<List<Game>> get() = _games 25 val games: StateFlow<List<Game>> get() = _games
28 private val _games = MutableStateFlow(emptyList<Game>()) 26 private val _games = MutableStateFlow(emptyList<Game>())
@@ -49,26 +47,34 @@ class GamesViewModel : ViewModel() {
49 // Retrieve list of cached games 47 // Retrieve list of cached games
50 val storedGames = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) 48 val storedGames = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
51 .getStringSet(GameHelper.KEY_GAMES, emptySet()) 49 .getStringSet(GameHelper.KEY_GAMES, emptySet())
52 if (storedGames!!.isNotEmpty()) {
53 val deserializedGames = mutableSetOf<Game>()
54 storedGames.forEach {
55 val game: Game
56 try {
57 game = Json.decodeFromString(it)
58 } catch (e: MissingFieldException) {
59 return@forEach
60 }
61 50
62 val gameExists = 51 viewModelScope.launch {
63 DocumentFile.fromSingleUri(YuzuApplication.appContext, Uri.parse(game.path)) 52 withContext(Dispatchers.IO) {
64 ?.exists() 53 if (storedGames!!.isNotEmpty()) {
65 if (gameExists == true) { 54 val deserializedGames = mutableSetOf<Game>()
66 deserializedGames.add(game) 55 storedGames.forEach {
56 val game: Game
57 try {
58 game = Json.decodeFromString(it)
59 } catch (e: Exception) {
60 // We don't care about any errors related to parsing the game cache
61 return@forEach
62 }
63
64 val gameExists =
65 DocumentFile.fromSingleUri(
66 YuzuApplication.appContext,
67 Uri.parse(game.path)
68 )?.exists()
69 if (gameExists == true) {
70 deserializedGames.add(game)
71 }
72 }
73 setGames(deserializedGames.toList())
67 } 74 }
75 reloadGames(false)
68 } 76 }
69 setGames(deserializedGames.toList())
70 } 77 }
71 reloadGames(false)
72 } 78 }
73 79
74 fun setGames(games: List<Game>) { 80 fun setGames(games: List<Game>) {
@@ -106,7 +112,7 @@ class GamesViewModel : ViewModel() {
106 112
107 viewModelScope.launch { 113 viewModelScope.launch {
108 withContext(Dispatchers.IO) { 114 withContext(Dispatchers.IO) {
109 NativeLibrary.resetRomMetadata() 115 GameMetadata.resetMetadata()
110 setGames(GameHelper.getGames()) 116 setGames(GameHelper.getGames())
111 _isReloading.value = false 117 _isReloading.value = false
112 118
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 233aa4101..211b7cf69 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
@@ -403,6 +403,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
403 } else { 403 } else {
404 firmwarePath.deleteRecursively() 404 firmwarePath.deleteRecursively()
405 cacheFirmwareDir.copyRecursively(firmwarePath, true) 405 cacheFirmwareDir.copyRecursively(firmwarePath, true)
406 NativeLibrary.initializeSystem(true)
406 getString(R.string.save_file_imported_success) 407 getString(R.string.save_file_imported_success)
407 } 408 }
408 } catch (e: Exception) { 409 } catch (e: Exception) {
@@ -648,7 +649,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
648 } 649 }
649 650
650 // Reinitialize relevant data 651 // Reinitialize relevant data
651 NativeLibrary.initializeEmulation() 652 NativeLibrary.initializeSystem(true)
652 gamesViewModel.reloadGames(false) 653 gamesViewModel.reloadGames(false)
653 654
654 return@newInstance getString(R.string.user_data_import_success) 655 return@newInstance getString(R.string.user_data_import_success)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.kt
deleted file mode 100644
index eeefcdf20..000000000
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/ControllerMappingHelper.kt
+++ /dev/null
@@ -1,70 +0,0 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.utils
5
6import android.view.InputDevice
7import android.view.KeyEvent
8import android.view.MotionEvent
9
10/**
11 * Some controllers have incorrect mappings. This class has special-case fixes for them.
12 */
13class ControllerMappingHelper {
14 /**
15 * Some controllers report extra button presses that can be ignored.
16 */
17 fun shouldKeyBeIgnored(inputDevice: InputDevice, keyCode: Int): Boolean {
18 return if (isDualShock4(inputDevice)) {
19 // The two analog triggers generate analog motion events as well as a keycode.
20 // We always prefer to use the analog values, so throw away the button press
21 keyCode == KeyEvent.KEYCODE_BUTTON_L2 || keyCode == KeyEvent.KEYCODE_BUTTON_R2
22 } else {
23 false
24 }
25 }
26
27 /**
28 * Scale an axis to be zero-centered with a proper range.
29 */
30 fun scaleAxis(inputDevice: InputDevice, axis: Int, value: Float): Float {
31 if (isDualShock4(inputDevice)) {
32 // Android doesn't have correct mappings for this controller's triggers. It reports them
33 // as RX & RY, centered at -1.0, and with a range of [-1.0, 1.0]
34 // Scale them to properly zero-centered with a range of [0.0, 1.0].
35 if (axis == MotionEvent.AXIS_RX || axis == MotionEvent.AXIS_RY) {
36 return (value + 1) / 2.0f
37 }
38 } else if (isXboxOneWireless(inputDevice)) {
39 // Same as the DualShock 4, the mappings are missing.
40 if (axis == MotionEvent.AXIS_Z || axis == MotionEvent.AXIS_RZ) {
41 return (value + 1) / 2.0f
42 }
43 if (axis == MotionEvent.AXIS_GENERIC_1) {
44 // This axis is stuck at ~.5. Ignore it.
45 return 0.0f
46 }
47 } else if (isMogaPro2Hid(inputDevice)) {
48 // This controller has a broken axis that reports a constant value. Ignore it.
49 if (axis == MotionEvent.AXIS_GENERIC_1) {
50 return 0.0f
51 }
52 }
53 return value
54 }
55
56 // Sony DualShock 4 controller
57 private fun isDualShock4(inputDevice: InputDevice): Boolean {
58 return inputDevice.vendorId == 0x54c && inputDevice.productId == 0x9cc
59 }
60
61 // Microsoft Xbox One controller
62 private fun isXboxOneWireless(inputDevice: InputDevice): Boolean {
63 return inputDevice.vendorId == 0x45e && inputDevice.productId == 0x2e0
64 }
65
66 // Moga Pro 2 HID
67 private fun isMogaPro2Hid(inputDevice: InputDevice): Boolean {
68 return inputDevice.vendorId == 0x20d6 && inputDevice.productId == 0x6271
69 }
70}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
index 3c9f6bad0..5e9a1176a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
@@ -15,7 +15,7 @@ object DirectoryInitialization {
15 fun start() { 15 fun start() {
16 if (!areDirectoriesReady) { 16 if (!areDirectoriesReady) {
17 initializeInternalStorage() 17 initializeInternalStorage()
18 NativeLibrary.initializeEmulation() 18 NativeLibrary.initializeSystem(false)
19 areDirectoriesReady = true 19 areDirectoriesReady = true
20 } 20 }
21 } 21 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt
index eafcf9e42..738275297 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt
@@ -42,6 +42,23 @@ class DocumentsTree {
42 return node != null && node.isDirectory 42 return node != null && node.isDirectory
43 } 43 }
44 44
45 fun getParentDirectory(filepath: String): String {
46 val node = resolvePath(filepath)!!
47 val parentNode = node.parent
48 if (parentNode != null && parentNode.isDirectory) {
49 return parentNode.uri!!.toString()
50 }
51 return node.uri!!.toString()
52 }
53
54 fun getFilename(filepath: String): String {
55 val node = resolvePath(filepath)
56 if (node != null) {
57 return node.name!!
58 }
59 return filepath
60 }
61
45 private fun resolvePath(filepath: String): DocumentsNode? { 62 private fun resolvePath(filepath: String): DocumentsNode? {
46 val tokens = StringTokenizer(filepath, File.separator, false) 63 val tokens = StringTokenizer(filepath, File.separator, false)
47 var iterator = root 64 var iterator = root
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 5ee74a52c..8c3268e9c 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
@@ -144,7 +144,7 @@ object FileUtil {
144 * @param path Native content uri path 144 * @param path Native content uri path
145 * @return bool 145 * @return bool
146 */ 146 */
147 fun exists(path: String?): Boolean { 147 fun exists(path: String?, suppressLog: Boolean = false): Boolean {
148 var c: Cursor? = null 148 var c: Cursor? = null
149 try { 149 try {
150 val mUri = Uri.parse(path) 150 val mUri = Uri.parse(path)
@@ -152,7 +152,9 @@ object FileUtil {
152 c = context.contentResolver.query(mUri, columns, null, null, null) 152 c = context.contentResolver.query(mUri, columns, null, null, null)
153 return c!!.count > 0 153 return c!!.count > 0
154 } catch (e: Exception) { 154 } catch (e: Exception) {
155 Log.info("[FileUtil] Cannot find file from given path, error: " + e.message) 155 if (!suppressLog) {
156 Log.info("[FileUtil] Cannot find file from given path, error: " + e.message)
157 }
156 } finally { 158 } finally {
157 closeQuietly(c) 159 closeQuietly(c)
158 } 160 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt
index 9001ca9ab..e6aca6b44 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt
@@ -71,27 +71,26 @@ object GameHelper {
71 71
72 fun getGame(uri: Uri, addedToLibrary: Boolean): Game { 72 fun getGame(uri: Uri, addedToLibrary: Boolean): Game {
73 val filePath = uri.toString() 73 val filePath = uri.toString()
74 var name = NativeLibrary.getTitle(filePath) 74 var name = GameMetadata.getTitle(filePath)
75 75
76 // If the game's title field is empty, use the filename. 76 // If the game's title field is empty, use the filename.
77 if (name.isEmpty()) { 77 if (name.isEmpty()) {
78 name = FileUtil.getFilename(uri) 78 name = FileUtil.getFilename(uri)
79 } 79 }
80 var gameId = NativeLibrary.getGameId(filePath) 80 var programId = GameMetadata.getProgramId(filePath)
81 81
82 // If the game's ID field is empty, use the filename without extension. 82 // If the game's ID field is empty, use the filename without extension.
83 if (gameId.isEmpty()) { 83 if (programId.isEmpty()) {
84 gameId = name.substring(0, name.lastIndexOf(".")) 84 programId = name.substring(0, name.lastIndexOf("."))
85 } 85 }
86 86
87 val newGame = Game( 87 val newGame = Game(
88 name, 88 name,
89 NativeLibrary.getDescription(filePath).replace("\n", " "),
90 NativeLibrary.getRegions(filePath),
91 filePath, 89 filePath,
92 gameId, 90 programId,
93 NativeLibrary.getCompany(filePath), 91 GameMetadata.getDeveloper(filePath),
94 NativeLibrary.isHomebrew(filePath) 92 GameMetadata.getVersion(filePath),
93 GameMetadata.getIsHomebrew(filePath)
95 ) 94 )
96 95
97 if (addedToLibrary) { 96 if (addedToLibrary) {
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 9fe99fab1..654d62f52 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
@@ -18,7 +18,6 @@ import coil.key.Keyer
18import coil.memory.MemoryCache 18import coil.memory.MemoryCache
19import coil.request.ImageRequest 19import coil.request.ImageRequest
20import coil.request.Options 20import coil.request.Options
21import org.yuzu.yuzu_emu.NativeLibrary
22import org.yuzu.yuzu_emu.R 21import org.yuzu.yuzu_emu.R
23import org.yuzu.yuzu_emu.YuzuApplication 22import org.yuzu.yuzu_emu.YuzuApplication
24import org.yuzu.yuzu_emu.model.Game 23import org.yuzu.yuzu_emu.model.Game
@@ -36,7 +35,7 @@ class GameIconFetcher(
36 } 35 }
37 36
38 private fun decodeGameIcon(uri: String): Bitmap? { 37 private fun decodeGameIcon(uri: String): Bitmap? {
39 val data = NativeLibrary.getIcon(uri) 38 val data = GameMetadata.getIcon(uri)
40 return BitmapFactory.decodeByteArray( 39 return BitmapFactory.decodeByteArray(
41 data, 40 data,
42 0, 41 0,
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameMetadata.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameMetadata.kt
new file mode 100644
index 000000000..0f3542ac6
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameMetadata.kt
@@ -0,0 +1,20 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.utils
5
6object GameMetadata {
7 external fun getTitle(path: String): String
8
9 external fun getProgramId(path: String): String
10
11 external fun getDeveloper(path: String): String
12
13 external fun getVersion(path: String): String
14
15 external fun getIcon(path: String): ByteArray
16
17 external fun getIsHomebrew(path: String): Boolean
18
19 external fun resetMetadata()
20}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt
index e963dfbc1..47bde5081 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/InputHandler.kt
@@ -3,17 +3,24 @@
3 3
4package org.yuzu.yuzu_emu.utils 4package org.yuzu.yuzu_emu.utils
5 5
6import android.view.InputDevice
6import android.view.KeyEvent 7import android.view.KeyEvent
7import android.view.MotionEvent 8import android.view.MotionEvent
8import kotlin.math.sqrt 9import kotlin.math.sqrt
9import org.yuzu.yuzu_emu.NativeLibrary 10import org.yuzu.yuzu_emu.NativeLibrary
10 11
11class InputHandler { 12object InputHandler {
13 private var controllerIds = getGameControllerIds()
14
12 fun initialize() { 15 fun initialize() {
13 // Connect first controller 16 // Connect first controller
14 NativeLibrary.onGamePadConnectEvent(getPlayerNumber(NativeLibrary.Player1Device)) 17 NativeLibrary.onGamePadConnectEvent(getPlayerNumber(NativeLibrary.Player1Device))
15 } 18 }
16 19
20 fun updateControllerIds() {
21 controllerIds = getGameControllerIds()
22 }
23
17 fun dispatchKeyEvent(event: KeyEvent): Boolean { 24 fun dispatchKeyEvent(event: KeyEvent): Boolean {
18 val button: Int = when (event.device.vendorId) { 25 val button: Int = when (event.device.vendorId) {
19 0x045E -> getInputXboxButtonKey(event.keyCode) 26 0x045E -> getInputXboxButtonKey(event.keyCode)
@@ -35,7 +42,7 @@ class InputHandler {
35 } 42 }
36 43
37 return NativeLibrary.onGamePadButtonEvent( 44 return NativeLibrary.onGamePadButtonEvent(
38 getPlayerNumber(event.device.controllerNumber), 45 getPlayerNumber(event.device.controllerNumber, event.deviceId),
39 button, 46 button,
40 action 47 action
41 ) 48 )
@@ -58,9 +65,14 @@ class InputHandler {
58 return true 65 return true
59 } 66 }
60 67
61 private fun getPlayerNumber(index: Int): Int { 68 private fun getPlayerNumber(index: Int, deviceId: Int = -1): Int {
69 var deviceIndex = index
70 if (deviceId != -1) {
71 deviceIndex = controllerIds[deviceId] ?: 0
72 }
73
62 // TODO: Joycons are handled as different controllers. Find a way to merge them. 74 // TODO: Joycons are handled as different controllers. Find a way to merge them.
63 return when (index) { 75 return when (deviceIndex) {
64 2 -> NativeLibrary.Player2Device 76 2 -> NativeLibrary.Player2Device
65 3 -> NativeLibrary.Player3Device 77 3 -> NativeLibrary.Player3Device
66 4 -> NativeLibrary.Player4Device 78 4 -> NativeLibrary.Player4Device
@@ -238,7 +250,7 @@ class InputHandler {
238 } 250 }
239 251
240 private fun setGenericAxisInput(event: MotionEvent, axis: Int) { 252 private fun setGenericAxisInput(event: MotionEvent, axis: Int) {
241 val playerNumber = getPlayerNumber(event.device.controllerNumber) 253 val playerNumber = getPlayerNumber(event.device.controllerNumber, event.deviceId)
242 254
243 when (axis) { 255 when (axis) {
244 MotionEvent.AXIS_X, MotionEvent.AXIS_Y -> 256 MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
@@ -297,7 +309,7 @@ class InputHandler {
297 309
298 private fun setJoyconAxisInput(event: MotionEvent, axis: Int) { 310 private fun setJoyconAxisInput(event: MotionEvent, axis: Int) {
299 // Joycon support is half dead. Right joystick doesn't work 311 // Joycon support is half dead. Right joystick doesn't work
300 val playerNumber = getPlayerNumber(event.device.controllerNumber) 312 val playerNumber = getPlayerNumber(event.device.controllerNumber, event.deviceId)
301 313
302 when (axis) { 314 when (axis) {
303 MotionEvent.AXIS_X, MotionEvent.AXIS_Y -> 315 MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
@@ -325,7 +337,7 @@ class InputHandler {
325 } 337 }
326 338
327 private fun setRazerAxisInput(event: MotionEvent, axis: Int) { 339 private fun setRazerAxisInput(event: MotionEvent, axis: Int) {
328 val playerNumber = getPlayerNumber(event.device.controllerNumber) 340 val playerNumber = getPlayerNumber(event.device.controllerNumber, event.deviceId)
329 341
330 when (axis) { 342 when (axis) {
331 MotionEvent.AXIS_X, MotionEvent.AXIS_Y -> 343 MotionEvent.AXIS_X, MotionEvent.AXIS_Y ->
@@ -362,4 +374,33 @@ class InputHandler {
362 ) 374 )
363 } 375 }
364 } 376 }
377
378 fun getGameControllerIds(): Map<Int, Int> {
379 val gameControllerDeviceIds = mutableMapOf<Int, Int>()
380 val deviceIds = InputDevice.getDeviceIds()
381 var controllerSlot = 1
382 deviceIds.forEach { deviceId ->
383 InputDevice.getDevice(deviceId)?.apply {
384 // Don't over-assign controllers
385 if (controllerSlot >= 8) {
386 return gameControllerDeviceIds
387 }
388
389 // Verify that the device has gamepad buttons, control sticks, or both.
390 if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
391 sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
392 ) {
393 // This device is a game controller. Store its device ID.
394 if (deviceId and id and vendorId and productId != 0) {
395 // Additionally filter out devices that have no ID
396 gameControllerDeviceIds
397 .takeIf { !it.contains(deviceId) }
398 ?.put(deviceId, controllerSlot)
399 controllerSlot++
400 }
401 }
402 }
403 }
404 return gameControllerDeviceIds
405 }
365} 406}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt
index a193e82a4..aebe84b0f 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt
@@ -3,38 +3,29 @@
3 3
4package org.yuzu.yuzu_emu.utils 4package org.yuzu.yuzu_emu.utils
5 5
6import android.util.Log 6import android.os.Build
7import org.yuzu.yuzu_emu.BuildConfig 7
8
9/**
10 * Contains methods that call through to [android.util.Log], but
11 * with the same TAG automatically provided. Also no-ops VERBOSE and DEBUG log
12 * levels in release builds.
13 */
14object Log { 8object Log {
15 private const val TAG = "Yuzu Frontend" 9 // Tracks whether we should share the old log or the current log
10 var gameLaunched = false
16 11
17 fun verbose(message: String) { 12 external fun debug(message: String)
18 if (BuildConfig.DEBUG) {
19 Log.v(TAG, message)
20 }
21 }
22 13
23 fun debug(message: String) { 14 external fun warning(message: String)
24 if (BuildConfig.DEBUG) {
25 Log.d(TAG, message)
26 }
27 }
28 15
29 fun info(message: String) { 16 external fun info(message: String)
30 Log.i(TAG, message)
31 }
32 17
33 fun warning(message: String) { 18 external fun error(message: String)
34 Log.w(TAG, message)
35 }
36 19
37 fun error(message: String) { 20 external fun critical(message: String)
38 Log.e(TAG, message) 21
22 fun logDeviceInfo() {
23 info("Device Manufacturer - ${Build.MANUFACTURER}")
24 info("Device Model - ${Build.MODEL}")
25 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
26 info("SoC Manufacturer - ${Build.SOC_MANUFACTURER}")
27 info("SoC Model - ${Build.SOC_MODEL}")
28 }
29 info("Total System Memory - ${MemoryUtil.getDeviceRAM()}")
39 } 30 }
40} 31}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt
index aa4a5539a..9076a86c4 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt
@@ -27,7 +27,7 @@ object MemoryUtil {
27 const val Pb = Tb * 1024 27 const val Pb = Tb * 1024
28 const val Eb = Pb * 1024 28 const val Eb = Pb * 1024
29 29
30 private fun bytesToSizeUnit(size: Float): String = 30 private fun bytesToSizeUnit(size: Float, roundUp: Boolean = false): String =
31 when { 31 when {
32 size < Kb -> { 32 size < Kb -> {
33 context.getString( 33 context.getString(
@@ -39,63 +39,59 @@ object MemoryUtil {
39 size < Mb -> { 39 size < Mb -> {
40 context.getString( 40 context.getString(
41 R.string.memory_formatted, 41 R.string.memory_formatted,
42 (size / Kb).hundredths, 42 if (roundUp) ceil(size / Kb) else (size / Kb).hundredths,
43 context.getString(R.string.memory_kilobyte) 43 context.getString(R.string.memory_kilobyte)
44 ) 44 )
45 } 45 }
46 size < Gb -> { 46 size < Gb -> {
47 context.getString( 47 context.getString(
48 R.string.memory_formatted, 48 R.string.memory_formatted,
49 (size / Mb).hundredths, 49 if (roundUp) ceil(size / Mb) else (size / Mb).hundredths,
50 context.getString(R.string.memory_megabyte) 50 context.getString(R.string.memory_megabyte)
51 ) 51 )
52 } 52 }
53 size < Tb -> { 53 size < Tb -> {
54 context.getString( 54 context.getString(
55 R.string.memory_formatted, 55 R.string.memory_formatted,
56 (size / Gb).hundredths, 56 if (roundUp) ceil(size / Gb) else (size / Gb).hundredths,
57 context.getString(R.string.memory_gigabyte) 57 context.getString(R.string.memory_gigabyte)
58 ) 58 )
59 } 59 }
60 size < Pb -> { 60 size < Pb -> {
61 context.getString( 61 context.getString(
62 R.string.memory_formatted, 62 R.string.memory_formatted,
63 (size / Tb).hundredths, 63 if (roundUp) ceil(size / Tb) else (size / Tb).hundredths,
64 context.getString(R.string.memory_terabyte) 64 context.getString(R.string.memory_terabyte)
65 ) 65 )
66 } 66 }
67 size < Eb -> { 67 size < Eb -> {
68 context.getString( 68 context.getString(
69 R.string.memory_formatted, 69 R.string.memory_formatted,
70 (size / Pb).hundredths, 70 if (roundUp) ceil(size / Pb) else (size / Pb).hundredths,
71 context.getString(R.string.memory_petabyte) 71 context.getString(R.string.memory_petabyte)
72 ) 72 )
73 } 73 }
74 else -> { 74 else -> {
75 context.getString( 75 context.getString(
76 R.string.memory_formatted, 76 R.string.memory_formatted,
77 (size / Eb).hundredths, 77 if (roundUp) ceil(size / Eb) else (size / Eb).hundredths,
78 context.getString(R.string.memory_exabyte) 78 context.getString(R.string.memory_exabyte)
79 ) 79 )
80 } 80 }
81 } 81 }
82 82
83 // Devices are unlikely to have 0.5GB increments of memory so we'll just round up to account for 83 val totalMemory: Float
84 // the potential error created by memInfo.totalMem
85 private val totalMemory: Float
86 get() { 84 get() {
87 val memInfo = ActivityManager.MemoryInfo() 85 val memInfo = ActivityManager.MemoryInfo()
88 with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) { 86 with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) {
89 getMemoryInfo(memInfo) 87 getMemoryInfo(memInfo)
90 } 88 }
91 89
92 return ceil( 90 return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
93 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { 91 memInfo.advertisedMem.toFloat()
94 memInfo.advertisedMem.toFloat() 92 } else {
95 } else { 93 memInfo.totalMem.toFloat()
96 memInfo.totalMem.toFloat() 94 }
97 }
98 )
99 } 95 }
100 96
101 fun isLessThan(minimum: Int, size: Float): Boolean = 97 fun isLessThan(minimum: Int, size: Float): Boolean =
@@ -109,5 +105,7 @@ object MemoryUtil {
109 else -> totalMemory < Kb && totalMemory < minimum 105 else -> totalMemory < Kb && totalMemory < minimum
110 } 106 }
111 107
112 fun getDeviceRAM(): String = bytesToSizeUnit(totalMemory) 108 // Devices are unlikely to have 0.5GB increments of memory so we'll just round up to account for
109 // the potential error created by memInfo.totalMem
110 fun getDeviceRAM(): String = bytesToSizeUnit(totalMemory, true)
113} 111}
diff --git a/src/android/app/src/main/jni/CMakeLists.txt b/src/android/app/src/main/jni/CMakeLists.txt
index e15d1480b..88a570f68 100644
--- a/src/android/app/src/main/jni/CMakeLists.txt
+++ b/src/android/app/src/main/jni/CMakeLists.txt
@@ -14,8 +14,11 @@ add_library(yuzu-android SHARED
14 id_cache.cpp 14 id_cache.cpp
15 id_cache.h 15 id_cache.h
16 native.cpp 16 native.cpp
17 native.h
17 native_config.cpp 18 native_config.cpp
18 uisettings.cpp 19 uisettings.cpp
20 game_metadata.cpp
21 native_log.cpp
19) 22)
20 23
21set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) 24set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR})
diff --git a/src/android/app/src/main/jni/game_metadata.cpp b/src/android/app/src/main/jni/game_metadata.cpp
new file mode 100644
index 000000000..24d9df702
--- /dev/null
+++ b/src/android/app/src/main/jni/game_metadata.cpp
@@ -0,0 +1,112 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <core/core.h>
5#include <core/file_sys/patch_manager.h>
6#include <core/loader/nro.h>
7#include <jni.h>
8#include "core/loader/loader.h"
9#include "jni/android_common/android_common.h"
10#include "native.h"
11
12struct RomMetadata {
13 std::string title;
14 u64 programId;
15 std::string developer;
16 std::string version;
17 std::vector<u8> icon;
18 bool isHomebrew;
19};
20
21std::unordered_map<std::string, RomMetadata> m_rom_metadata_cache;
22
23RomMetadata CacheRomMetadata(const std::string& path) {
24 const auto file =
25 Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path);
26 auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
27
28 RomMetadata entry;
29 loader->ReadTitle(entry.title);
30 loader->ReadProgramId(entry.programId);
31 loader->ReadIcon(entry.icon);
32
33 const FileSys::PatchManager pm{
34 entry.programId, EmulationSession::GetInstance().System().GetFileSystemController(),
35 EmulationSession::GetInstance().System().GetContentProvider()};
36 const auto control = pm.GetControlMetadata();
37
38 if (control.first != nullptr) {
39 entry.developer = control.first->GetDeveloperName();
40 entry.version = control.first->GetVersionString();
41 } else {
42 FileSys::NACP nacp;
43 if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) {
44 entry.developer = nacp.GetDeveloperName();
45 } else {
46 entry.developer = "";
47 }
48
49 entry.version = "1.0.0";
50 }
51
52 if (loader->GetFileType() == Loader::FileType::NRO) {
53 auto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
54 entry.isHomebrew = loader_nro->IsHomebrew();
55 } else {
56 entry.isHomebrew = false;
57 }
58
59 m_rom_metadata_cache[path] = entry;
60
61 return entry;
62}
63
64RomMetadata GetRomMetadata(const std::string& path) {
65 if (auto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) {
66 return search->second;
67 }
68
69 return CacheRomMetadata(path);
70}
71
72extern "C" {
73
74jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj,
75 jstring jpath) {
76 return ToJString(env, GetRomMetadata(GetJString(env, jpath)).title);
77}
78
79jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj,
80 jstring jpath) {
81 return ToJString(env, std::to_string(GetRomMetadata(GetJString(env, jpath)).programId));
82}
83
84jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj,
85 jstring jpath) {
86 return ToJString(env, GetRomMetadata(GetJString(env, jpath)).developer);
87}
88
89jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj,
90 jstring jpath) {
91 return ToJString(env, GetRomMetadata(GetJString(env, jpath)).version);
92}
93
94jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj,
95 jstring jpath) {
96 auto icon_data = GetRomMetadata(GetJString(env, jpath)).icon;
97 jbyteArray icon = env->NewByteArray(static_cast<jsize>(icon_data.size()));
98 env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon),
99 reinterpret_cast<jbyte*>(icon_data.data()));
100 return icon;
101}
102
103jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj,
104 jstring jpath) {
105 return static_cast<jboolean>(GetRomMetadata(GetJString(env, jpath)).isHomebrew);
106}
107
108void Java_org_yuzu_yuzu_1emu_utils_GameMetadata_resetMetadata(JNIEnv* env, jobject obj) {
109 return m_rom_metadata_cache.clear();
110}
111
112} // extern "C"
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 598f4e8bf..1484cc224 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -33,7 +33,6 @@
33#include "core/crypto/key_manager.h" 33#include "core/crypto/key_manager.h"
34#include "core/file_sys/card_image.h" 34#include "core/file_sys/card_image.h"
35#include "core/file_sys/content_archive.h" 35#include "core/file_sys/content_archive.h"
36#include "core/file_sys/registered_cache.h"
37#include "core/file_sys/submission_package.h" 36#include "core/file_sys/submission_package.h"
38#include "core/file_sys/vfs.h" 37#include "core/file_sys/vfs.h"
39#include "core/file_sys/vfs_real.h" 38#include "core/file_sys/vfs_real.h"
@@ -48,520 +47,423 @@
48#include "core/hid/emulated_controller.h" 47#include "core/hid/emulated_controller.h"
49#include "core/hid/hid_core.h" 48#include "core/hid/hid_core.h"
50#include "core/hid/hid_types.h" 49#include "core/hid/hid_types.h"
51#include "core/hle/service/acc/profile_manager.h"
52#include "core/hle/service/am/applet_ae.h" 50#include "core/hle/service/am/applet_ae.h"
53#include "core/hle/service/am/applet_oe.h" 51#include "core/hle/service/am/applet_oe.h"
54#include "core/hle/service/am/applets/applets.h" 52#include "core/hle/service/am/applets/applets.h"
55#include "core/hle/service/filesystem/filesystem.h" 53#include "core/hle/service/filesystem/filesystem.h"
56#include "core/loader/loader.h" 54#include "core/loader/loader.h"
57#include "core/perf_stats.h"
58#include "jni/android_common/android_common.h" 55#include "jni/android_common/android_common.h"
59#include "jni/applets/software_keyboard.h"
60#include "jni/config.h" 56#include "jni/config.h"
61#include "jni/emu_window/emu_window.h"
62#include "jni/id_cache.h" 57#include "jni/id_cache.h"
63#include "video_core/rasterizer_interface.h" 58#include "jni/native.h"
64#include "video_core/renderer_base.h" 59#include "video_core/renderer_base.h"
65 60
66#define jconst [[maybe_unused]] const auto 61#define jconst [[maybe_unused]] const auto
67#define jauto [[maybe_unused]] auto 62#define jauto [[maybe_unused]] auto
68 63
69namespace { 64static EmulationSession s_instance;
70 65
71class EmulationSession final { 66EmulationSession::EmulationSession() {
72public: 67 m_vfs = std::make_shared<FileSys::RealVfsFilesystem>();
73 EmulationSession() { 68}
74 m_vfs = std::make_shared<FileSys::RealVfsFilesystem>();
75 }
76
77 ~EmulationSession() = default;
78
79 static EmulationSession& GetInstance() {
80 return s_instance;
81 }
82
83 const Core::System& System() const {
84 return m_system;
85 }
86 69
87 Core::System& System() { 70EmulationSession& EmulationSession::GetInstance() {
88 return m_system; 71 return s_instance;
89 } 72}
90 73
91 const EmuWindow_Android& Window() const { 74const Core::System& EmulationSession::System() const {
92 return *m_window; 75 return m_system;
93 } 76}
94 77
95 EmuWindow_Android& Window() { 78Core::System& EmulationSession::System() {
96 return *m_window; 79 return m_system;
97 } 80}
98 81
99 ANativeWindow* NativeWindow() const { 82const EmuWindow_Android& EmulationSession::Window() const {
100 return m_native_window; 83 return *m_window;
101 } 84}
102 85
103 void SetNativeWindow(ANativeWindow* native_window) { 86EmuWindow_Android& EmulationSession::Window() {
104 m_native_window = native_window; 87 return *m_window;
105 } 88}
106 89
107 int InstallFileToNand(std::string filename, std::string file_extension) { 90ANativeWindow* EmulationSession::NativeWindow() const {
108 jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, 91 return m_native_window;
109 std::size_t block_size) { 92}
110 if (src == nullptr || dest == nullptr) {
111 return false;
112 }
113 if (!dest->Resize(src->GetSize())) {
114 return false;
115 }
116 93
117 using namespace Common::Literals; 94void EmulationSession::SetNativeWindow(ANativeWindow* native_window) {
118 [[maybe_unused]] std::vector<u8> buffer(1_MiB); 95 m_native_window = native_window;
96}
119 97
120 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { 98int EmulationSession::InstallFileToNand(std::string filename, std::string file_extension) {
121 jconst read = src->Read(buffer.data(), buffer.size(), i); 99 jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
122 dest->Write(buffer.data(), read, i); 100 std::size_t block_size) {
123 } 101 if (src == nullptr || dest == nullptr) {
124 return true; 102 return false;
125 };
126
127 enum InstallResult {
128 Success = 0,
129 SuccessFileOverwritten = 1,
130 InstallError = 2,
131 ErrorBaseGame = 3,
132 ErrorFilenameExtension = 4,
133 };
134
135 m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
136 m_system.GetFileSystemController().CreateFactories(*m_vfs);
137
138 [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp;
139 if (file_extension == "nsp") {
140 nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
141 if (nsp->IsExtractedType()) {
142 return InstallError;
143 }
144 } else {
145 return ErrorFilenameExtension;
146 } 103 }
147 104 if (!dest->Resize(src->GetSize())) {
148 if (!nsp) { 105 return false;
149 return InstallError;
150 } 106 }
151 107
152 if (nsp->GetStatus() != Loader::ResultStatus::Success) { 108 using namespace Common::Literals;
153 return InstallError; 109 [[maybe_unused]] std::vector<u8> buffer(1_MiB);
154 }
155 110
156 jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry( 111 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
157 *nsp, true, copy_func); 112 jconst read = src->Read(buffer.data(), buffer.size(), i);
158 113 dest->Write(buffer.data(), read, i);
159 switch (res) {
160 case FileSys::InstallResult::Success:
161 return Success;
162 case FileSys::InstallResult::OverwriteExisting:
163 return SuccessFileOverwritten;
164 case FileSys::InstallResult::ErrorBaseInstall:
165 return ErrorBaseGame;
166 default:
167 return InstallError;
168 } 114 }
169 } 115 return true;
116 };
170 117
171 void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, 118 enum InstallResult {
172 const std::string& custom_driver_name, 119 Success = 0,
173 const std::string& file_redirect_dir) { 120 SuccessFileOverwritten = 1,
174#ifdef ARCHITECTURE_arm64 121 InstallError = 2,
175 void* handle{}; 122 ErrorBaseGame = 3,
176 const char* file_redirect_dir_{}; 123 ErrorFilenameExtension = 4,
177 int featureFlags{}; 124 };
178
179 // Enable driver file redirection when renderer debugging is enabled.
180 if (Settings::values.renderer_debug && file_redirect_dir.size()) {
181 featureFlags |= ADRENOTOOLS_DRIVER_FILE_REDIRECT;
182 file_redirect_dir_ = file_redirect_dir.c_str();
183 }
184 125
185 // Try to load a custom driver. 126 m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
186 if (custom_driver_name.size()) { 127 m_system.GetFileSystemController().CreateFactories(*m_vfs);
187 handle = adrenotools_open_libvulkan(
188 RTLD_NOW, featureFlags | ADRENOTOOLS_DRIVER_CUSTOM, nullptr, hook_lib_dir.c_str(),
189 custom_driver_dir.c_str(), custom_driver_name.c_str(), file_redirect_dir_, nullptr);
190 }
191 128
192 // Try to load the system driver. 129 [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp;
193 if (!handle) { 130 if (file_extension == "nsp") {
194 handle = 131 nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
195 adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(), 132 if (nsp->IsExtractedType()) {
196 nullptr, nullptr, file_redirect_dir_, nullptr); 133 return InstallError;
197 } 134 }
198 135 } else {
199 m_vulkan_library = std::make_shared<Common::DynamicLibrary>(handle); 136 return ErrorFilenameExtension;
200#endif
201 } 137 }
202 138
203 bool IsRunning() const { 139 if (!nsp) {
204 return m_is_running; 140 return InstallError;
205 } 141 }
206 142
207 bool IsPaused() const { 143 if (nsp->GetStatus() != Loader::ResultStatus::Success) {
208 return m_is_running && m_is_paused; 144 return InstallError;
209 } 145 }
210 146
211 const Core::PerfStatsResults& PerfStats() const { 147 jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true,
212 std::scoped_lock m_perf_stats_lock(m_perf_stats_mutex); 148 copy_func);
213 return m_perf_stats;
214 }
215 149
216 void SurfaceChanged() { 150 switch (res) {
217 if (!IsRunning()) { 151 case FileSys::InstallResult::Success:
218 return; 152 return Success;
219 } 153 case FileSys::InstallResult::OverwriteExisting:
220 m_window->OnSurfaceChanged(m_native_window); 154 return SuccessFileOverwritten;
155 case FileSys::InstallResult::ErrorBaseInstall:
156 return ErrorBaseGame;
157 default:
158 return InstallError;
221 } 159 }
160}
222 161
223 void ConfigureFilesystemProvider(const std::string& filepath) { 162void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir,
224 const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::Mode::Read); 163 const std::string& custom_driver_dir,
225 if (!file) { 164 const std::string& custom_driver_name,
226 return; 165 const std::string& file_redirect_dir) {
227 } 166#ifdef ARCHITECTURE_arm64
228 167 void* handle{};
229 auto loader = Loader::GetLoader(m_system, file); 168 const char* file_redirect_dir_{};
230 if (!loader) { 169 int featureFlags{};
231 return;
232 }
233
234 const auto file_type = loader->GetFileType();
235 if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
236 return;
237 }
238 170
239 u64 program_id = 0; 171 // Enable driver file redirection when renderer debugging is enabled.
240 const auto res2 = loader->ReadProgramId(program_id); 172 if (Settings::values.renderer_debug && file_redirect_dir.size()) {
241 if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) { 173 featureFlags |= ADRENOTOOLS_DRIVER_FILE_REDIRECT;
242 m_manual_provider->AddEntry(FileSys::TitleType::Application, 174 file_redirect_dir_ = file_redirect_dir.c_str();
243 FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()),
244 program_id, file);
245 } else if (res2 == Loader::ResultStatus::Success &&
246 (file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
247 const auto nsp = file_type == Loader::FileType::NSP
248 ? std::make_shared<FileSys::NSP>(file)
249 : FileSys::XCI{file}.GetSecurePartitionNSP();
250 for (const auto& title : nsp->GetNCAs()) {
251 for (const auto& entry : title.second) {
252 m_manual_provider->AddEntry(entry.first.first, entry.first.second, title.first,
253 entry.second->GetBaseFile());
254 }
255 }
256 }
257 } 175 }
258 176
259 Core::SystemResultStatus InitializeEmulation(const std::string& filepath) { 177 // Try to load a custom driver.
260 std::scoped_lock lock(m_mutex); 178 if (custom_driver_name.size()) {
261 179 handle = adrenotools_open_libvulkan(
262 // Create the render window. 180 RTLD_NOW, featureFlags | ADRENOTOOLS_DRIVER_CUSTOM, nullptr, hook_lib_dir.c_str(),
263 m_window = std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window, 181 custom_driver_dir.c_str(), custom_driver_name.c_str(), file_redirect_dir_, nullptr);
264 m_vulkan_library); 182 }
265
266 m_system.SetFilesystem(m_vfs);
267 m_system.GetUserChannel().clear();
268
269 // Initialize system.
270 jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
271 m_software_keyboard = android_keyboard.get();
272 m_system.SetShuttingDown(false);
273 m_system.ApplySettings();
274 Settings::LogSettings();
275 m_system.HIDCore().ReloadInputDevices();
276 m_system.SetAppletFrontendSet({
277 nullptr, // Amiibo Settings
278 nullptr, // Controller Selector
279 nullptr, // Error Display
280 nullptr, // Mii Editor
281 nullptr, // Parental Controls
282 nullptr, // Photo Viewer
283 nullptr, // Profile Selector
284 std::move(android_keyboard), // Software Keyboard
285 nullptr, // Web Browser
286 });
287
288 // Initialize filesystem.
289 m_manual_provider = std::make_unique<FileSys::ManualContentProvider>();
290 m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
291 m_system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual,
292 m_manual_provider.get());
293 m_system.GetFileSystemController().CreateFactories(*m_vfs);
294 ConfigureFilesystemProvider(filepath);
295
296 // Initialize account manager
297 m_profile_manager = std::make_unique<Service::Account::ProfileManager>();
298
299 // Load the ROM.
300 m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
301 if (m_load_result != Core::SystemResultStatus::Success) {
302 return m_load_result;
303 }
304
305 // Complete initialization.
306 m_system.GPU().Start();
307 m_system.GetCpuManager().OnGpuReady();
308 m_system.RegisterExitCallback([&] { HaltEmulation(); });
309 183
310 return Core::SystemResultStatus::Success; 184 // Try to load the system driver.
185 if (!handle) {
186 handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(),
187 nullptr, nullptr, file_redirect_dir_, nullptr);
311 } 188 }
312 189
313 void ShutdownEmulation() { 190 m_vulkan_library = std::make_shared<Common::DynamicLibrary>(handle);
314 std::scoped_lock lock(m_mutex); 191#endif
192}
315 193
316 m_is_running = false; 194bool EmulationSession::IsRunning() const {
195 return m_is_running;
196}
317 197
318 // Unload user input. 198bool EmulationSession::IsPaused() const {
319 m_system.HIDCore().UnloadInputDevices(); 199 return m_is_running && m_is_paused;
200}
320 201
321 // Shutdown the main emulated process 202const Core::PerfStatsResults& EmulationSession::PerfStats() {
322 if (m_load_result == Core::SystemResultStatus::Success) { 203 m_perf_stats = m_system.GetAndResetPerfStats();
323 m_system.DetachDebugger(); 204 return m_perf_stats;
324 m_system.ShutdownMainProcess(); 205}
325 m_detached_tasks.WaitForAllTasks();
326 m_load_result = Core::SystemResultStatus::ErrorNotInitialized;
327 m_window.reset();
328 OnEmulationStopped(Core::SystemResultStatus::Success);
329 return;
330 }
331 206
332 // Tear down the render window. 207void EmulationSession::SurfaceChanged() {
333 m_window.reset(); 208 if (!IsRunning()) {
209 return;
334 } 210 }
211 m_window->OnSurfaceChanged(m_native_window);
212}
335 213
336 void PauseEmulation() { 214void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath) {
337 std::scoped_lock lock(m_mutex); 215 const auto file = m_system.GetFilesystem()->OpenFile(filepath, FileSys::Mode::Read);
338 m_system.Pause(); 216 if (!file) {
339 m_is_paused = true; 217 return;
340 } 218 }
341 219
342 void UnPauseEmulation() { 220 auto loader = Loader::GetLoader(m_system, file);
343 std::scoped_lock lock(m_mutex); 221 if (!loader) {
344 m_system.Run(); 222 return;
345 m_is_paused = false;
346 } 223 }
347 224
348 void HaltEmulation() { 225 const auto file_type = loader->GetFileType();
349 std::scoped_lock lock(m_mutex); 226 if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
350 m_is_running = false; 227 return;
351 m_cv.notify_one();
352 } 228 }
353 229
354 void RunEmulation() { 230 u64 program_id = 0;
355 { 231 const auto res2 = loader->ReadProgramId(program_id);
356 std::scoped_lock lock(m_mutex); 232 if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) {
357 m_is_running = true; 233 m_manual_provider->AddEntry(FileSys::TitleType::Application,
358 } 234 FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()),
359 235 program_id, file);
360 // Load the disk shader cache. 236 } else if (res2 == Loader::ResultStatus::Success &&
361 if (Settings::values.use_disk_shader_cache.GetValue()) { 237 (file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
362 LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); 238 const auto nsp = file_type == Loader::FileType::NSP
363 m_system.Renderer().ReadRasterizer()->LoadDiskResources( 239 ? std::make_shared<FileSys::NSP>(file)
364 m_system.GetApplicationProcessProgramID(), std::stop_token{}, 240 : FileSys::XCI{file}.GetSecurePartitionNSP();
365 LoadDiskCacheProgress); 241 for (const auto& title : nsp->GetNCAs()) {
366 LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0); 242 for (const auto& entry : title.second) {
243 m_manual_provider->AddEntry(entry.first.first, entry.first.second, title.first,
244 entry.second->GetBaseFile());
245 }
367 } 246 }
247 }
248}
368 249
369 void(m_system.Run()); 250void EmulationSession::InitializeSystem(bool reload) {
251 if (!reload) {
252 // Initialize logging system
253 Common::Log::Initialize();
254 Common::Log::SetColorConsoleBackendEnabled(true);
255 Common::Log::Start();
256 }
257
258 // Initialize filesystem.
259 m_system.SetFilesystem(m_vfs);
260 m_system.GetUserChannel().clear();
261 m_manual_provider = std::make_unique<FileSys::ManualContentProvider>();
262 m_system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
263 m_system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual,
264 m_manual_provider.get());
265 m_system.GetFileSystemController().CreateFactories(*m_vfs);
266}
267
268Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath) {
269 std::scoped_lock lock(m_mutex);
270
271 // Create the render window.
272 m_window =
273 std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window, m_vulkan_library);
274
275 // Initialize system.
276 jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>();
277 m_software_keyboard = android_keyboard.get();
278 m_system.SetShuttingDown(false);
279 m_system.ApplySettings();
280 Settings::LogSettings();
281 m_system.HIDCore().ReloadInputDevices();
282 m_system.SetAppletFrontendSet({
283 nullptr, // Amiibo Settings
284 nullptr, // Controller Selector
285 nullptr, // Error Display
286 nullptr, // Mii Editor
287 nullptr, // Parental Controls
288 nullptr, // Photo Viewer
289 nullptr, // Profile Selector
290 std::move(android_keyboard), // Software Keyboard
291 nullptr, // Web Browser
292 });
293
294 // Initialize filesystem.
295 ConfigureFilesystemProvider(filepath);
296
297 // Initialize account manager
298 m_profile_manager = std::make_unique<Service::Account::ProfileManager>();
299
300 // Load the ROM.
301 m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath);
302 if (m_load_result != Core::SystemResultStatus::Success) {
303 return m_load_result;
304 }
305
306 // Complete initialization.
307 m_system.GPU().Start();
308 m_system.GetCpuManager().OnGpuReady();
309 m_system.RegisterExitCallback([&] { HaltEmulation(); });
370 310
371 if (m_system.DebuggerEnabled()) { 311 return Core::SystemResultStatus::Success;
372 m_system.InitializeDebugger(); 312}
373 }
374
375 OnEmulationStarted();
376 313
377 while (true) { 314void EmulationSession::ShutdownEmulation() {
378 { 315 std::scoped_lock lock(m_mutex);
379 [[maybe_unused]] std::unique_lock lock(m_mutex);
380 if (m_cv.wait_for(lock, std::chrono::milliseconds(800),
381 [&]() { return !m_is_running; })) {
382 // Emulation halted.
383 break;
384 }
385 }
386 {
387 // Refresh performance stats.
388 std::scoped_lock m_perf_stats_lock(m_perf_stats_mutex);
389 m_perf_stats = m_system.GetAndResetPerfStats();
390 }
391 }
392 }
393 316
394 std::string GetRomTitle(const std::string& path) { 317 m_is_running = false;
395 return GetRomMetadata(path).title;
396 }
397 318
398 std::vector<u8> GetRomIcon(const std::string& path) { 319 // Unload user input.
399 return GetRomMetadata(path).icon; 320 m_system.HIDCore().UnloadInputDevices();
400 }
401 321
402 bool GetIsHomebrew(const std::string& path) { 322 // Shutdown the main emulated process
403 return GetRomMetadata(path).isHomebrew; 323 if (m_load_result == Core::SystemResultStatus::Success) {
324 m_system.DetachDebugger();
325 m_system.ShutdownMainProcess();
326 m_detached_tasks.WaitForAllTasks();
327 m_load_result = Core::SystemResultStatus::ErrorNotInitialized;
328 m_window.reset();
329 OnEmulationStopped(Core::SystemResultStatus::Success);
330 return;
404 } 331 }
405 332
406 void ResetRomMetadata() { 333 // Tear down the render window.
407 m_rom_metadata_cache.clear(); 334 m_window.reset();
408 } 335}
409 336
410 bool IsHandheldOnly() { 337void EmulationSession::PauseEmulation() {
411 jconst npad_style_set = m_system.HIDCore().GetSupportedStyleTag(); 338 std::scoped_lock lock(m_mutex);
339 m_system.Pause();
340 m_is_paused = true;
341}
412 342
413 if (npad_style_set.fullkey == 1) { 343void EmulationSession::UnPauseEmulation() {
414 return false; 344 std::scoped_lock lock(m_mutex);
415 } 345 m_system.Run();
346 m_is_paused = false;
347}
416 348
417 if (npad_style_set.handheld == 0) { 349void EmulationSession::HaltEmulation() {
418 return false; 350 std::scoped_lock lock(m_mutex);
419 } 351 m_is_running = false;
352 m_cv.notify_one();
353}
420 354
421 return !Settings::IsDockedMode(); 355void EmulationSession::RunEmulation() {
356 {
357 std::scoped_lock lock(m_mutex);
358 m_is_running = true;
422 } 359 }
423 360
424 void SetDeviceType([[maybe_unused]] int index, int type) { 361 // Load the disk shader cache.
425 jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); 362 if (Settings::values.use_disk_shader_cache.GetValue()) {
426 controller->SetNpadStyleIndex(static_cast<Core::HID::NpadStyleIndex>(type)); 363 LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
364 m_system.Renderer().ReadRasterizer()->LoadDiskResources(
365 m_system.GetApplicationProcessProgramID(), std::stop_token{}, LoadDiskCacheProgress);
366 LoadDiskCacheProgress(VideoCore::LoadCallbackStage::Complete, 0, 0);
427 } 367 }
428 368
429 void OnGamepadConnectEvent([[maybe_unused]] int index) { 369 void(m_system.Run());
430 jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
431
432 // Ensure that player1 is configured correctly and handheld disconnected
433 if (controller->GetNpadIdType() == Core::HID::NpadIdType::Player1) {
434 jauto handheld =
435 m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
436 370
437 if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) { 371 if (m_system.DebuggerEnabled()) {
438 handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); 372 m_system.InitializeDebugger();
439 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); 373 }
440 handheld->Disconnect();
441 }
442 }
443 374
444 // Ensure that handheld is configured correctly and player 1 disconnected 375 OnEmulationStarted();
445 if (controller->GetNpadIdType() == Core::HID::NpadIdType::Handheld) {
446 jauto player1 =
447 m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
448 376
449 if (controller->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::Handheld) { 377 while (true) {
450 player1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); 378 {
451 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); 379 [[maybe_unused]] std::unique_lock lock(m_mutex);
452 player1->Disconnect(); 380 if (m_cv.wait_for(lock, std::chrono::milliseconds(800),
381 [&]() { return !m_is_running; })) {
382 // Emulation halted.
383 break;
453 } 384 }
454 } 385 }
455
456 if (!controller->IsConnected()) {
457 controller->Connect();
458 }
459 } 386 }
387}
388
389bool EmulationSession::IsHandheldOnly() {
390 jconst npad_style_set = m_system.HIDCore().GetSupportedStyleTag();
460 391
461 void OnGamepadDisconnectEvent([[maybe_unused]] int index) { 392 if (npad_style_set.fullkey == 1) {
462 jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); 393 return false;
463 controller->Disconnect();
464 } 394 }
465 395
466 SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard() { 396 if (npad_style_set.handheld == 0) {
467 return m_software_keyboard; 397 return false;
468 } 398 }
469 399
470private: 400 return !Settings::IsDockedMode();
471 struct RomMetadata { 401}
472 std::string title;
473 std::vector<u8> icon;
474 bool isHomebrew;
475 };
476 402
477 RomMetadata GetRomMetadata(const std::string& path) { 403void EmulationSession::SetDeviceType([[maybe_unused]] int index, int type) {
478 if (jauto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) { 404 jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
479 return search->second; 405 controller->SetNpadStyleIndex(static_cast<Core::HID::NpadStyleIndex>(type));
480 } 406}
481 407
482 return CacheRomMetadata(path); 408void EmulationSession::OnGamepadConnectEvent([[maybe_unused]] int index) {
483 } 409 jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
484 410
485 RomMetadata CacheRomMetadata(const std::string& path) { 411 // Ensure that player1 is configured correctly and handheld disconnected
486 jconst file = Core::GetGameFileFromPath(m_vfs, path); 412 if (controller->GetNpadIdType() == Core::HID::NpadIdType::Player1) {
487 jauto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0); 413 jauto handheld = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
488 414
489 RomMetadata entry; 415 if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) {
490 loader->ReadTitle(entry.title); 416 handheld->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
491 loader->ReadIcon(entry.icon); 417 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
492 if (loader->GetFileType() == Loader::FileType::NRO) { 418 handheld->Disconnect();
493 jauto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
494 entry.isHomebrew = loader_nro->IsHomebrew();
495 } else {
496 entry.isHomebrew = false;
497 } 419 }
498
499 m_rom_metadata_cache[path] = entry;
500
501 return entry;
502 } 420 }
503 421
504private: 422 // Ensure that handheld is configured correctly and player 1 disconnected
505 static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max) { 423 if (controller->GetNpadIdType() == Core::HID::NpadIdType::Handheld) {
506 JNIEnv* env = IDCache::GetEnvForThread(); 424 jauto player1 = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
507 env->CallStaticVoidMethod(IDCache::GetDiskCacheProgressClass(),
508 IDCache::GetDiskCacheLoadProgress(), static_cast<jint>(stage),
509 static_cast<jint>(progress), static_cast<jint>(max));
510 }
511 425
512 static void OnEmulationStarted() { 426 if (controller->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::Handheld) {
513 JNIEnv* env = IDCache::GetEnvForThread(); 427 player1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
514 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), 428 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
515 IDCache::GetOnEmulationStarted()); 429 player1->Disconnect();
430 }
516 } 431 }
517 432
518 static void OnEmulationStopped(Core::SystemResultStatus result) { 433 if (!controller->IsConnected()) {
519 JNIEnv* env = IDCache::GetEnvForThread(); 434 controller->Connect();
520 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
521 IDCache::GetOnEmulationStopped(), static_cast<jint>(result));
522 } 435 }
436}
523 437
524private: 438void EmulationSession::OnGamepadDisconnectEvent([[maybe_unused]] int index) {
525 static EmulationSession s_instance; 439 jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index);
526 440 controller->Disconnect();
527 // Frontend management 441}
528 std::unordered_map<std::string, RomMetadata> m_rom_metadata_cache;
529
530 // Window management
531 std::unique_ptr<EmuWindow_Android> m_window;
532 ANativeWindow* m_native_window{};
533
534 // Core emulation
535 Core::System m_system;
536 InputCommon::InputSubsystem m_input_subsystem;
537 Common::DetachedTasks m_detached_tasks;
538 Core::PerfStatsResults m_perf_stats{};
539 std::shared_ptr<FileSys::VfsFilesystem> m_vfs;
540 Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized};
541 std::atomic<bool> m_is_running = false;
542 std::atomic<bool> m_is_paused = false;
543 SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
544 std::unique_ptr<Service::Account::ProfileManager> m_profile_manager;
545 std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
546 442
547 // GPU driver parameters 443SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() {
548 std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; 444 return m_software_keyboard;
445}
549 446
550 // Synchronization 447void EmulationSession::LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress,
551 std::condition_variable_any m_cv; 448 int max) {
552 mutable std::mutex m_perf_stats_mutex; 449 JNIEnv* env = IDCache::GetEnvForThread();
553 mutable std::mutex m_mutex; 450 env->CallStaticVoidMethod(IDCache::GetDiskCacheProgressClass(),
554}; 451 IDCache::GetDiskCacheLoadProgress(), static_cast<jint>(stage),
452 static_cast<jint>(progress), static_cast<jint>(max));
453}
555 454
556/*static*/ EmulationSession EmulationSession::s_instance; 455void EmulationSession::OnEmulationStarted() {
456 JNIEnv* env = IDCache::GetEnvForThread();
457 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnEmulationStarted());
458}
557 459
558} // Anonymous namespace 460void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) {
461 JNIEnv* env = IDCache::GetEnvForThread();
462 env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnEmulationStopped(),
463 static_cast<jint>(result));
464}
559 465
560static Core::SystemResultStatus RunEmulation(const std::string& filepath) { 466static Core::SystemResultStatus RunEmulation(const std::string& filepath) {
561 Common::Log::Initialize();
562 Common::Log::SetColorConsoleBackendEnabled(true);
563 Common::Log::Start();
564
565 MicroProfileOnThreadCreate("EmuThread"); 467 MicroProfileOnThreadCreate("EmuThread");
566 SCOPE_EXIT({ MicroProfileShutdown(); }); 468 SCOPE_EXIT({ MicroProfileShutdown(); });
567 469
@@ -657,10 +559,6 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_stopEmulation(JNIEnv* env, jclass cla
657 EmulationSession::GetInstance().HaltEmulation(); 559 EmulationSession::GetInstance().HaltEmulation();
658} 560}
659 561
660void Java_org_yuzu_yuzu_1emu_NativeLibrary_resetRomMetadata(JNIEnv* env, jclass clazz) {
661 EmulationSession::GetInstance().ResetRomMetadata();
662}
663
664jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isRunning(JNIEnv* env, jclass clazz) { 562jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isRunning(JNIEnv* env, jclass clazz) {
665 return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning()); 563 return static_cast<jboolean>(EmulationSession::GetInstance().IsRunning());
666} 564}
@@ -766,51 +664,15 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased(JNIEnv* env, jclass c
766 } 664 }
767} 665}
768 666
769jbyteArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getIcon(JNIEnv* env, jclass clazz, 667void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz,
770 jstring j_filename) { 668 jboolean reload) {
771 jauto icon_data = EmulationSession::GetInstance().GetRomIcon(GetJString(env, j_filename));
772 jbyteArray icon = env->NewByteArray(static_cast<jsize>(icon_data.size()));
773 env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon),
774 reinterpret_cast<jbyte*>(icon_data.data()));
775 return icon;
776}
777
778jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getTitle(JNIEnv* env, jclass clazz,
779 jstring j_filename) {
780 jauto title = EmulationSession::GetInstance().GetRomTitle(GetJString(env, j_filename));
781 return env->NewStringUTF(title.c_str());
782}
783
784jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getDescription(JNIEnv* env, jclass clazz,
785 jstring j_filename) {
786 return j_filename;
787}
788
789jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGameId(JNIEnv* env, jclass clazz,
790 jstring j_filename) {
791 return j_filename;
792}
793
794jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getRegions(JNIEnv* env, jclass clazz,
795 jstring j_filename) {
796 return env->NewStringUTF("");
797}
798
799jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCompany(JNIEnv* env, jclass clazz,
800 jstring j_filename) {
801 return env->NewStringUTF("");
802}
803
804jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isHomebrew(JNIEnv* env, jclass clazz,
805 jstring j_filename) {
806 return EmulationSession::GetInstance().GetIsHomebrew(GetJString(env, j_filename));
807}
808
809void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation(JNIEnv* env, jclass clazz) {
810 // Create the default config.ini. 669 // Create the default config.ini.
811 Config{}; 670 Config{};
812 // Initialize the emulated system. 671 // Initialize the emulated system.
813 EmulationSession::GetInstance().System().Initialize(); 672 if (!reload) {
673 EmulationSession::GetInstance().System().Initialize();
674 }
675 EmulationSession::GetInstance().InitializeSystem(reload);
814} 676}
815 677
816jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass clazz) { 678jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass clazz) {
@@ -898,4 +760,49 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmptyUserDirectory(JNIEnv*
898 } 760 }
899} 761}
900 762
763jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, jclass clazz,
764 jlong jid) {
765 auto bis_system =
766 EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents();
767 if (!bis_system) {
768 return ToJString(env, "");
769 }
770
771 auto applet_nca =
772 bis_system->GetEntry(static_cast<u64>(jid), FileSys::ContentRecordType::Program);
773 if (!applet_nca) {
774 return ToJString(env, "");
775 }
776
777 return ToJString(env, applet_nca->GetFullPath());
778}
779
780void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz,
781 jint jappletId) {
782 EmulationSession::GetInstance().System().GetAppletManager().SetCurrentAppletId(
783 static_cast<Service::AM::Applets::AppletId>(jappletId));
784}
785
786void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCabinetMode(JNIEnv* env, jclass clazz,
787 jint jcabinetMode) {
788 EmulationSession::GetInstance().System().GetAppletManager().SetCabinetMode(
789 static_cast<Service::NFP::CabinetMode>(jcabinetMode));
790}
791
792jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env, jclass clazz) {
793 auto bis_system =
794 EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents();
795 if (!bis_system) {
796 return false;
797 }
798
799 // Query an applet to see if it's available
800 auto applet_nca =
801 bis_system->GetEntry(0x010000000000100Dull, FileSys::ContentRecordType::Program);
802 if (!applet_nca) {
803 return false;
804 }
805 return true;
806}
807
901} // extern "C" 808} // extern "C"
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
new file mode 100644
index 000000000..6b02c44b5
--- /dev/null
+++ b/src/android/app/src/main/jni/native.h
@@ -0,0 +1,84 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <android/native_window_jni.h>
5#include "common/detached_tasks.h"
6#include "core/core.h"
7#include "core/file_sys/registered_cache.h"
8#include "core/hle/service/acc/profile_manager.h"
9#include "core/perf_stats.h"
10#include "jni/applets/software_keyboard.h"
11#include "jni/emu_window/emu_window.h"
12#include "video_core/rasterizer_interface.h"
13
14#pragma once
15
16class EmulationSession final {
17public:
18 explicit EmulationSession();
19 ~EmulationSession() = default;
20
21 static EmulationSession& GetInstance();
22 const Core::System& System() const;
23 Core::System& System();
24
25 const EmuWindow_Android& Window() const;
26 EmuWindow_Android& Window();
27 ANativeWindow* NativeWindow() const;
28 void SetNativeWindow(ANativeWindow* native_window);
29 void SurfaceChanged();
30
31 int InstallFileToNand(std::string filename, std::string file_extension);
32 void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
33 const std::string& custom_driver_name,
34 const std::string& file_redirect_dir);
35
36 bool IsRunning() const;
37 bool IsPaused() const;
38 void PauseEmulation();
39 void UnPauseEmulation();
40 void HaltEmulation();
41 void RunEmulation();
42 void ShutdownEmulation();
43
44 const Core::PerfStatsResults& PerfStats();
45 void ConfigureFilesystemProvider(const std::string& filepath);
46 void InitializeSystem(bool reload);
47 Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
48
49 bool IsHandheldOnly();
50 void SetDeviceType([[maybe_unused]] int index, int type);
51 void OnGamepadConnectEvent([[maybe_unused]] int index);
52 void OnGamepadDisconnectEvent([[maybe_unused]] int index);
53 SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard();
54
55private:
56 static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max);
57 static void OnEmulationStarted();
58 static void OnEmulationStopped(Core::SystemResultStatus result);
59
60private:
61 // Window management
62 std::unique_ptr<EmuWindow_Android> m_window;
63 ANativeWindow* m_native_window{};
64
65 // Core emulation
66 Core::System m_system;
67 InputCommon::InputSubsystem m_input_subsystem;
68 Common::DetachedTasks m_detached_tasks;
69 Core::PerfStatsResults m_perf_stats{};
70 std::shared_ptr<FileSys::VfsFilesystem> m_vfs;
71 Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized};
72 std::atomic<bool> m_is_running = false;
73 std::atomic<bool> m_is_paused = false;
74 SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{};
75 std::unique_ptr<Service::Account::ProfileManager> m_profile_manager;
76 std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider;
77
78 // GPU driver parameters
79 std::shared_ptr<Common::DynamicLibrary> m_vulkan_library;
80
81 // Synchronization
82 std::condition_variable_any m_cv;
83 mutable std::mutex m_mutex;
84};
diff --git a/src/android/app/src/main/jni/native_log.cpp b/src/android/app/src/main/jni/native_log.cpp
new file mode 100644
index 000000000..33d691dc8
--- /dev/null
+++ b/src/android/app/src/main/jni/native_log.cpp
@@ -0,0 +1,31 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <common/logging/log.h>
5#include <jni.h>
6
7#include "android_common/android_common.h"
8
9extern "C" {
10
11void Java_org_yuzu_yuzu_1emu_utils_Log_debug(JNIEnv* env, jobject obj, jstring jmessage) {
12 LOG_DEBUG(Frontend, "{}", GetJString(env, jmessage));
13}
14
15void Java_org_yuzu_yuzu_1emu_utils_Log_warning(JNIEnv* env, jobject obj, jstring jmessage) {
16 LOG_WARNING(Frontend, "{}", GetJString(env, jmessage));
17}
18
19void Java_org_yuzu_yuzu_1emu_utils_Log_info(JNIEnv* env, jobject obj, jstring jmessage) {
20 LOG_INFO(Frontend, "{}", GetJString(env, jmessage));
21}
22
23void Java_org_yuzu_yuzu_1emu_utils_Log_error(JNIEnv* env, jobject obj, jstring jmessage) {
24 LOG_ERROR(Frontend, "{}", GetJString(env, jmessage));
25}
26
27void Java_org_yuzu_yuzu_1emu_utils_Log_critical(JNIEnv* env, jobject obj, jstring jmessage) {
28 LOG_CRITICAL(Frontend, "{}", GetJString(env, jmessage));
29}
30
31} // extern "C"
diff --git a/src/android/app/src/main/res/drawable/ic_album.xml b/src/android/app/src/main/res/drawable/ic_album.xml
new file mode 100644
index 000000000..f2b63813f
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_album.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="24"
5 android:viewportHeight="24">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z" />
9</vector>
diff --git a/src/android/app/src/main/res/drawable/ic_applet.xml b/src/android/app/src/main/res/drawable/ic_applet.xml
new file mode 100644
index 000000000..b154e6f56
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_applet.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="24"
5 android:viewportHeight="24">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M17,16l-4,-4V8.82C14.16,8.4 15,7.3 15,6c0,-1.66 -1.34,-3 -3,-3S9,4.34 9,6c0,1.3 0.84,2.4 2,2.82V12l-4,4H3v5h5v-3.05l4,-4.2 4,4.2V21h5v-5h-4z" />
9</vector>
diff --git a/src/android/app/src/main/res/drawable/ic_edit.xml b/src/android/app/src/main/res/drawable/ic_edit.xml
new file mode 100644
index 000000000..ac22ce8a5
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_edit.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="24"
5 android:viewportHeight="24">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z" />
9</vector>
diff --git a/src/android/app/src/main/res/drawable/ic_mii.xml b/src/android/app/src/main/res/drawable/ic_mii.xml
new file mode 100644
index 000000000..1271ec401
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_mii.xml
@@ -0,0 +1,18 @@
1<vector xmlns:android="http://schemas.android.com/apk/res/android"
2 android:width="24dp"
3 android:height="24dp"
4 android:viewportWidth="24"
5 android:viewportHeight="24">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M9,13m-1.25,0a1.25,1.25 0,1 1,2.5 0a1.25,1.25 0,1 1,-2.5 0" />
9 <path
10 android:fillColor="?attr/colorControlNormal"
11 android:pathData="M20.77,8.58l-0.92,2.01c0.09,0.46 0.15,0.93 0.15,1.41 0,4.41 -3.59,8 -8,8s-8,-3.59 -8,-8c0,-0.05 0.01,-0.1 0,-0.14 2.6,-0.98 4.69,-2.99 5.74,-5.55C11.58,8.56 14.37,10 17.5,10c0.45,0 0.89,-0.04 1.33,-0.1l-0.6,-1.32 -0.88,-1.93 -1.93,-0.88 -2.79,-1.27 2.79,-1.27 0.71,-0.32C14.87,2.33 13.47,2 12,2 6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10c0,-1.47 -0.33,-2.87 -0.9,-4.13l-0.33,0.71z" />
12 <path
13 android:fillColor="?attr/colorControlNormal"
14 android:pathData="M15,13m-1.25,0a1.25,1.25 0,1 1,2.5 0a1.25,1.25 0,1 1,-2.5 0" />
15 <path
16 android:fillColor="?attr/colorControlNormal"
17 android:pathData="M20.6,5.6L19.5,8l-1.1,-2.4L16,4.5l2.4,-1.1L19.5,1l1.1,2.4L23,4.5z" />
18</vector>
diff --git a/src/android/app/src/main/res/drawable/ic_refresh.xml b/src/android/app/src/main/res/drawable/ic_refresh.xml
new file mode 100644
index 000000000..d0d87ecc2
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_refresh.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="24"
5 android:viewportHeight="24">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z" />
9</vector>
diff --git a/src/android/app/src/main/res/drawable/ic_restore.xml b/src/android/app/src/main/res/drawable/ic_restore.xml
new file mode 100644
index 000000000..d6d9d4017
--- /dev/null
+++ b/src/android/app/src/main/res/drawable/ic_restore.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="24"
5 android:viewportHeight="24">
6 <path
7 android:fillColor="?attr/colorControlNormal"
8 android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z" />
9</vector>
diff --git a/src/android/app/src/main/res/layout/card_applet_option.xml b/src/android/app/src/main/res/layout/card_applet_option.xml
new file mode 100644
index 000000000..19fbec9f1
--- /dev/null
+++ b/src/android/app/src/main/res/layout/card_applet_option.xml
@@ -0,0 +1,57 @@
1<?xml version="1.0" encoding="utf-8"?>
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"
4 xmlns:tools="http://schemas.android.com/tools"
5 style="?attr/materialCardViewOutlinedStyle"
6 android:layout_width="match_parent"
7 android:layout_height="wrap_content"
8 android:layout_marginHorizontal="16dp"
9 android:layout_marginVertical="12dp"
10 android:background="?attr/selectableItemBackground"
11 android:clickable="true"
12 android:focusable="true">
13
14 <LinearLayout
15 android:layout_width="match_parent"
16 android:layout_height="wrap_content"
17 android:orientation="horizontal"
18 android:layout_gravity="center"
19 android:padding="24dp">
20
21 <ImageView
22 android:id="@+id/icon"
23 android:layout_width="24dp"
24 android:layout_height="24dp"
25 android:layout_marginEnd="20dp"
26 android:layout_gravity="center_vertical"
27 app:tint="?attr/colorOnSurface" />
28
29 <LinearLayout
30 android:layout_width="0dp"
31 android:layout_height="wrap_content"
32 android:layout_weight="1"
33 android:orientation="vertical"
34 android:layout_gravity="center_vertical">
35
36 <com.google.android.material.textview.MaterialTextView
37 android:id="@+id/title"
38 style="@style/TextAppearance.Material3.TitleMedium"
39 android:layout_width="match_parent"
40 android:layout_height="wrap_content"
41 android:textAlignment="viewStart"
42 tools:text="@string/applets" />
43
44 <com.google.android.material.textview.MaterialTextView
45 android:id="@+id/description"
46 style="@style/TextAppearance.Material3.BodyMedium"
47 android:layout_width="match_parent"
48 android:layout_height="wrap_content"
49 android:layout_marginTop="6dp"
50 android:textAlignment="viewStart"
51 tools:text="@string/applets_description" />
52
53 </LinearLayout>
54
55 </LinearLayout>
56
57</com.google.android.material.card.MaterialCardView>
diff --git a/src/android/app/src/main/res/layout/card_game.xml b/src/android/app/src/main/res/layout/card_game.xml
index 1f5de219b..6340171ec 100644
--- a/src/android/app/src/main/res/layout/card_game.xml
+++ b/src/android/app/src/main/res/layout/card_game.xml
@@ -1,63 +1,54 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<FrameLayout 2<FrameLayout 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"
7 android:layout_height="wrap_content"> 6 android:layout_height="wrap_content">
8 7
9 <com.google.android.material.card.MaterialCardView 8 <com.google.android.material.card.MaterialCardView
10 style="?attr/materialCardViewElevatedStyle"
11 android:id="@+id/card_game" 9 android:id="@+id/card_game"
10 style="?attr/materialCardViewElevatedStyle"
12 android:layout_width="wrap_content" 11 android:layout_width="wrap_content"
13 android:layout_height="wrap_content" 12 android:layout_height="wrap_content"
13 android:layout_gravity="center"
14 android:background="?attr/selectableItemBackground" 14 android:background="?attr/selectableItemBackground"
15 android:clickable="true" 15 android:clickable="true"
16 android:clipToPadding="false" 16 android:clipToPadding="false"
17 android:focusable="true" 17 android:focusable="true"
18 android:transitionName="card_game" 18 android:transitionName="card_game"
19 android:layout_gravity="center" 19 app:cardCornerRadius="4dp"
20 app:cardElevation="0dp" 20 app:cardElevation="0dp">
21 app:cardCornerRadius="12dp">
22 21
23 <androidx.constraintlayout.widget.ConstraintLayout 22 <androidx.constraintlayout.widget.ConstraintLayout
24 android:layout_width="wrap_content" 23 android:layout_width="wrap_content"
25 android:layout_height="wrap_content" 24 android:layout_height="wrap_content"
26 android:padding="6dp"> 25 android:padding="6dp">
27 26
28 <com.google.android.material.card.MaterialCardView 27 <com.google.android.material.imageview.ShapeableImageView
29 style="?attr/materialCardViewElevatedStyle" 28 android:id="@+id/image_game_screen"
30 android:id="@+id/card_game_art"
31 android:layout_width="150dp" 29 android:layout_width="150dp"
32 android:layout_height="150dp" 30 android:layout_height="150dp"
33 app:cardCornerRadius="4dp"
34 app:layout_constraintEnd_toEndOf="parent" 31 app:layout_constraintEnd_toEndOf="parent"
35 app:layout_constraintStart_toStartOf="parent" 32 app:layout_constraintStart_toStartOf="parent"
36 app:layout_constraintTop_toTopOf="parent"> 33 app:layout_constraintTop_toTopOf="parent"
37 34 app:shapeAppearance="@style/ShapeAppearance.Material3.Corner.ExtraSmall"
38 <ImageView 35 tools:src="@drawable/default_icon" />
39 android:id="@+id/image_game_screen"
40 android:layout_width="match_parent"
41 android:layout_height="match_parent"
42 tools:src="@drawable/default_icon" />
43
44 </com.google.android.material.card.MaterialCardView>
45 36
46 <com.google.android.material.textview.MaterialTextView 37 <com.google.android.material.textview.MaterialTextView
47 style="@style/TextAppearance.Material3.TitleMedium"
48 android:id="@+id/text_game_title" 38 android:id="@+id/text_game_title"
39 style="@style/TextAppearance.Material3.TitleMedium"
49 android:layout_width="0dp" 40 android:layout_width="0dp"
50 android:layout_height="wrap_content" 41 android:layout_height="wrap_content"
51 android:layout_marginTop="8dp" 42 android:layout_marginTop="8dp"
52 android:textAlignment="center"
53 android:textSize="14sp"
54 android:singleLine="true"
55 android:marqueeRepeatLimit="marquee_forever"
56 android:ellipsize="none" 43 android:ellipsize="none"
44 android:marqueeRepeatLimit="marquee_forever"
57 android:requiresFadingEdge="horizontal" 45 android:requiresFadingEdge="horizontal"
58 app:layout_constraintEnd_toEndOf="@+id/card_game_art" 46 android:singleLine="true"
59 app:layout_constraintStart_toStartOf="@+id/card_game_art" 47 android:textAlignment="center"
60 app:layout_constraintTop_toBottomOf="@+id/card_game_art" 48 android:textSize="14sp"
49 app:layout_constraintEnd_toEndOf="@+id/image_game_screen"
50 app:layout_constraintStart_toStartOf="@+id/image_game_screen"
51 app:layout_constraintTop_toBottomOf="@+id/image_game_screen"
61 tools:text="The Legend of Zelda: Skyward Sword" /> 52 tools:text="The Legend of Zelda: Skyward Sword" />
62 53
63 </androidx.constraintlayout.widget.ConstraintLayout> 54 </androidx.constraintlayout.widget.ConstraintLayout>
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 f9f1d89fb..6e8a232f9 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
@@ -16,7 +16,8 @@
16 <LinearLayout 16 <LinearLayout
17 android:id="@+id/option_layout" 17 android:id="@+id/option_layout"
18 android:layout_width="match_parent" 18 android:layout_width="match_parent"
19 android:layout_height="wrap_content"> 19 android:layout_height="wrap_content"
20 android:layout_gravity="center_vertical">
20 21
21 <ImageView 22 <ImageView
22 android:id="@+id/option_icon" 23 android:id="@+id/option_icon"
diff --git a/src/android/app/src/main/res/layout/dialog_list.xml b/src/android/app/src/main/res/layout/dialog_list.xml
new file mode 100644
index 000000000..7de2b2c3a
--- /dev/null
+++ b/src/android/app/src/main/res/layout/dialog_list.xml
@@ -0,0 +1,15 @@
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="wrap_content">
5
6 <androidx.recyclerview.widget.RecyclerView
7 android:id="@+id/dialog_list"
8 android:layout_width="match_parent"
9 android:layout_height="wrap_content"
10 android:clipToPadding="false"
11 android:fadeScrollbars="false"
12 android:paddingVertical="12dp"
13 android:scrollbars="vertical" />
14
15</androidx.appcompat.widget.LinearLayoutCompat>
diff --git a/src/android/app/src/main/res/layout/dialog_list_item.xml b/src/android/app/src/main/res/layout/dialog_list_item.xml
new file mode 100644
index 000000000..39f3558ff
--- /dev/null
+++ b/src/android/app/src/main/res/layout/dialog_list_item.xml
@@ -0,0 +1,30 @@
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
4 android:layout_width="match_parent"
5 android:layout_height="wrap_content"
6 android:background="?attr/selectableItemBackground"
7 android:clickable="true"
8 android:focusable="true"
9 android:orientation="horizontal"
10 android:paddingHorizontal="24dp"
11 android:paddingVertical="16dp">
12
13 <ImageView
14 android:id="@+id/icon"
15 android:layout_width="20dp"
16 android:layout_height="20dp"
17 android:layout_gravity="center"
18 tools:src="@drawable/ic_nfc" />
19
20 <com.google.android.material.textview.MaterialTextView
21 android:id="@+id/title"
22 style="@style/TextAppearance.Material3.BodyMedium"
23 android:layout_width="match_parent"
24 android:layout_height="wrap_content"
25 android:layout_marginStart="16dp"
26 android:layout_gravity="center_vertical|start"
27 android:textAlignment="viewStart"
28 tools:text="List option" />
29
30</LinearLayout>
diff --git a/src/android/app/src/main/res/layout/fragment_applet_launcher.xml b/src/android/app/src/main/res/layout/fragment_applet_launcher.xml
new file mode 100644
index 000000000..fe8fae40f
--- /dev/null
+++ b/src/android/app/src/main/res/layout/fragment_applet_launcher.xml
@@ -0,0 +1,31 @@
1<?xml version="1.0" encoding="utf-8"?>
2<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 android:id="@+id/coordinator_applets"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:background="?attr/colorSurface">
8
9 <com.google.android.material.appbar.AppBarLayout
10 android:id="@+id/appbar_applets"
11 android:layout_width="match_parent"
12 android:layout_height="wrap_content"
13 android:fitsSystemWindows="true">
14
15 <com.google.android.material.appbar.MaterialToolbar
16 android:id="@+id/toolbar_applets"
17 android:layout_width="match_parent"
18 android:layout_height="?attr/actionBarSize"
19 app:navigationIcon="@drawable/ic_back"
20 app:title="@string/applets" />
21
22 </com.google.android.material.appbar.AppBarLayout>
23
24 <androidx.recyclerview.widget.RecyclerView
25 android:id="@+id/list_applets"
26 android:layout_width="match_parent"
27 android:layout_height="match_parent"
28 android:clipToPadding="false"
29 app:layout_behavior="@string/appbar_scrolling_view_behavior" />
30
31</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/src/android/app/src/main/res/layout/fragment_emulation.xml b/src/android/app/src/main/res/layout/fragment_emulation.xml
index 750ce094a..cd6360b45 100644
--- a/src/android/app/src/main/res/layout/fragment_emulation.xml
+++ b/src/android/app/src/main/res/layout/fragment_emulation.xml
@@ -134,16 +134,18 @@
134 <FrameLayout 134 <FrameLayout
135 android:id="@+id/overlay_container" 135 android:id="@+id/overlay_container"
136 android:layout_width="match_parent" 136 android:layout_width="match_parent"
137 android:layout_height="match_parent"> 137 android:layout_height="match_parent"
138 android:fitsSystemWindows="true">
138 139
139 <TextView 140 <com.google.android.material.textview.MaterialTextView
140 android:id="@+id/show_fps_text" 141 android:id="@+id/show_fps_text"
142 style="@style/TextAppearance.Material3.BodyMedium"
141 android:layout_width="wrap_content" 143 android:layout_width="wrap_content"
142 android:layout_height="wrap_content" 144 android:layout_height="wrap_content"
143 android:layout_gravity="left" 145 android:layout_gravity="left"
144 android:clickable="false" 146 android:clickable="false"
145 android:focusable="false" 147 android:focusable="false"
146 android:shadowColor="@android:color/black" 148 android:paddingHorizontal="20dp"
147 android:textColor="@android:color/white" 149 android:textColor="@android:color/white"
148 android:textSize="12sp" 150 android:textSize="12sp"
149 tools:ignore="RtlHardcoded" /> 151 tools:ignore="RtlHardcoded" />
diff --git a/src/android/app/src/main/res/navigation/home_navigation.xml b/src/android/app/src/main/res/navigation/home_navigation.xml
index 82749359d..6d4c1f86d 100644
--- a/src/android/app/src/main/res/navigation/home_navigation.xml
+++ b/src/android/app/src/main/res/navigation/home_navigation.xml
@@ -25,6 +25,9 @@
25 <action 25 <action
26 android:id="@+id/action_homeSettingsFragment_to_driverManagerFragment" 26 android:id="@+id/action_homeSettingsFragment_to_driverManagerFragment"
27 app:destination="@id/driverManagerFragment" /> 27 app:destination="@id/driverManagerFragment" />
28 <action
29 android:id="@+id/action_homeSettingsFragment_to_appletLauncherFragment"
30 app:destination="@id/appletLauncherFragment" />
28 </fragment> 31 </fragment>
29 32
30 <fragment 33 <fragment
@@ -102,5 +105,17 @@
102 android:id="@+id/driverManagerFragment" 105 android:id="@+id/driverManagerFragment"
103 android:name="org.yuzu.yuzu_emu.fragments.DriverManagerFragment" 106 android:name="org.yuzu.yuzu_emu.fragments.DriverManagerFragment"
104 android:label="DriverManagerFragment" /> 107 android:label="DriverManagerFragment" />
108 <fragment
109 android:id="@+id/appletLauncherFragment"
110 android:name="org.yuzu.yuzu_emu.fragments.AppletLauncherFragment"
111 android:label="AppletLauncherFragment" >
112 <action
113 android:id="@+id/action_appletLauncherFragment_to_cabinetLauncherDialogFragment"
114 app:destination="@id/cabinetLauncherDialogFragment" />
115 </fragment>
116 <dialog
117 android:id="@+id/cabinetLauncherDialogFragment"
118 android:name="org.yuzu.yuzu_emu.fragments.CabinetLauncherDialogFragment"
119 android:label="CabinetLauncherDialogFragment" />
105 120
106</navigation> 121</navigation>
diff --git a/src/android/app/src/main/res/resources.properties b/src/android/app/src/main/res/resources.properties
new file mode 100644
index 000000000..467b3efec
--- /dev/null
+++ b/src/android/app/src/main/res/resources.properties
@@ -0,0 +1 @@
unqualifiedResLocale=en-US
diff --git a/src/android/app/src/main/res/values-ar/strings.xml b/src/android/app/src/main/res/values-ar/strings.xml
new file mode 100644
index 000000000..07dffffe8
--- /dev/null
+++ b/src/android/app/src/main/res/values-ar/strings.xml
@@ -0,0 +1,385 @@
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">المحاكي نشط</string>
5 <string name="emulation_notification_channel_description">اظهار اشعار دائم عندما يكون المحاكي نشطاً</string>
6 <string name="emulation_notification_running">يوزو يعمل</string>
7 <string name="notice_notification_channel_name">الإشعارات والأخطاء</string>
8 <string name="notice_notification_channel_description">اظهار اشعار عند حصول اي مشكلة.</string>
9 <string name="notification_permission_not_granted">لم يتم منح إذن الإشعار</string>
10
11 <!-- Setup strings -->
12 <string name="welcome">مرحبًا</string>
13 <string name="welcome_description">والانتقال إلى المحاكاة <b>يوزو</b> تعر٠على كيÙية إعداد.</string>
14 <string name="get_started">لنبدأ</string>
15 <string name="keys">Ø§Ù„Ù…ÙØ§ØªÙŠØ­</string>
16 <string name="keys_description">اختر مل٠&lt;b>prod.keys&lt;/b> من الزر ادناه</string>
17 <string name="select_keys">إختيار Ø§Ù„Ù…ÙØ§ØªÙŠØ­</string>
18 <string name="games">الألعاب</string>
19 <string name="games_description">اختر مجلد &lt;b>العابك&lt;/b> من الزر ادناه.</string>
20 <string name="done">إنهاء</string>
21 <string name="done_description">كل شيء جاهز./n استمتع بألعابك!</string>
22 <string name="text_continue">استمر</string>
23 <string name="next">التالي</string>
24 <string name="back">عودة</string>
25 <string name="add_games">Ø¥Ø¶Ø§ÙØ© ألعاب</string>
26 <string name="add_games_description">إختار مجلد ألعابك</string>
27 <string name="step_complete">مكتمل</string>
28
29 <!-- Home strings -->
30 <string name="home_games">الألعاب</string>
31 <string name="home_search">البحث</string>
32 <string name="home_settings">الإعدادات</string>
33 <string name="empty_gamelist">لم يتم العثور على Ù…Ù„ÙØ§Øª او لم يتم تحديد مسار العاب.</string>
34 <string name="search_and_filter_games">بحث وتصÙية الألعاب</string>
35 <string name="select_games_folder">تحديد مجلد الألعاب</string>
36 <string name="select_games_folder_description">يسمح لـ يوزو بملء قائمة الألعاب</string>
37 <string name="add_games_warning">تخط٠اختيار مجلد الالعاب؟</string>
38 <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="home_search_games">البحث عن ألعاب</string>
41 <string name="search_settings">إعدادات البحث</string>
42 <string name="games_dir_selected">تم تحديد مجلد الألعاب</string>
43 <string name="install_prod_keys">تثبيت prod.keys</string>
44 <string name="install_prod_keys_description">مطلوب Ù„ÙÙƒ تشÙير ألعاب البيع بالتجزئة</string>
45 <string name="install_prod_keys_warning">تخطي Ø¥Ø¶Ø§ÙØ© Ø§Ù„Ù…ÙØ§ØªÙŠØ­ØŸ</string>
46 <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="notifications">التنبيهات</string>
49 <string name="notifications_description">امنح إذن الإشعار باستخدام الزر أدناه</string>
50 <string name="give_permission">منح الإذن</string>
51 <string name="notification_warning">تخطي منح إذن الإشعارات؟</string>
52 <string name="notification_warning_description">لن يتمكن يوزو من إشعارك بالمعلومات المهمة</string>
53 <string name="permission_denied">تم Ø±ÙØ¶ الإذن</string>
54 <string name="permission_denied_description">لقد Ø±ÙØ¶Øª هذا الإذن عدة مرات ويتعين عليك الآن منحه يدويًا ÙÙŠ إعدادات النظام</string>
55 <string name="about">حول</string>
56 <string name="about_description">بناء الإصدار، والاعتمادات، وأكثر من ذلك</string>
57 <string name="warning_help">مساعدة</string>
58 <string name="warning_skip">تخطي</string>
59 <string name="warning_cancel">إلغاء</string>
60 <string name="install_amiibo_keys">تثبيت Ù…ÙØ§ØªÙŠØ­ أميبو</string>
61 <string name="install_amiibo_keys_description">مطلوب لاستخدام أميبو ÙÙŠ اللعبة</string>
62 <string name="invalid_keys_file">تم تحديد Ù…Ù„Ù Ù…ÙØ§ØªÙŠØ­ غير صالح</string>
63 <string name="install_keys_success">تم تثبيت Ø§Ù„Ù…ÙØ§ØªÙŠØ­ بنجاح</string>
64 <string name="reading_keys_failure">خطأ ÙÙŠ قراءة Ù…ÙØ§ØªÙŠØ­ التشÙير</string>
65 <string name="invalid_keys_error">Ù…ÙØ§ØªÙŠØ­ التشÙير غير صالحة</string>
66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
67 <string name="install_keys_failure_description">المل٠المحدد غير صحيح أو تالÙ. يرجى إعادة Ø§Ù„Ù…ÙØ§ØªÙŠØ­ الخاصة بك</string>
68 <string name="install_gpu_driver">GPU تثبيت برنامج تشغيل</string>
69 <string name="install_gpu_driver_description">قم بتثبيت برامج تشغيل بديلة للحصول على أداء أو دقة Ø£ÙØ¶Ù„</string>
70 <string name="advanced_settings">إعدادات متقدمة</string>
71 <string name="advanced_settings_game">إعدادات متقدمة: %1$s</string>
72 <string name="settings_description">تكوين إعدادات المحاكي</string>
73 <string name="search_recently_played">لعبت مؤخرا</string>
74 <string name="search_recently_added">أضي٠مؤخرا</string>
75 <string name="search_retail">بيع بالتجزئة</string>
76 <string name="search_homebrew">البيرة المنزلية</string>
77 <string name="open_user_folder">ÙØªØ­ مجلد يوزو</string>
78 <string name="open_user_folder_description">إدارة Ù…Ù„ÙØ§Øª يوزو الداخلية</string>
79 <string name="theme_and_color_description">تعديل مظهر التطبيق</string>
80 <string name="no_file_manager">لم يتم العثور على مدير Ø§Ù„Ù…Ù„ÙØ§Øª</string>
81 <string name="notification_no_directory_link">لا يمكن ÙØªØ­ مجلد يوزو</string>
82 <string name="notification_no_directory_link_description">الرجاء تحديد موقع مجلد المستخدم باستخدام اللوحة الجانبية لمدير Ø§Ù„Ù…Ù„ÙØ§Øª يدويًا</string>
83 <string name="manage_save_data">إدارة Ø­ÙØ¸ البيانات</string>
84 <string name="manage_save_data_description">Ø­ÙØ¸ البيانات التي تم العثور عليها. يرجى اختيار أحد الخيارات التالية</string>
85 <string name="import_export_saves_description">استيراد أو تصدير Ù…Ù„ÙØ§Øª Ø§Ù„Ø­ÙØ¸</string>
86 <string name="save_file_imported_success">تم الاستيراد بنجاح</string>
87 <string name="save_file_invalid_zip_structure">بنية مجلد Ø§Ù„Ø­ÙØ¸ غير صالحة</string>
88 <string name="save_file_invalid_zip_structure_description">يجب أن يكون اسم المجلد Ø§Ù„ÙØ±Ø¹ÙŠ Ø§Ù„Ø£ÙˆÙ„ هو معر٠عنوان اللعبة.</string>
89 <string name="import_saves">استيراد</string>
90 <string name="export_saves">تصدير</string>
91 <string name="install_firmware">تثبيت البرامج الثابتة</string>
92 <string name="firmware_installing">تثبيت البرامج الثابتة</string>
93 <string name="firmware_installed_success">تم تثبيت البرامج الثابتة بنجاح</string>
94 <string name="firmware_installed_failure">ÙØ´Ù„ تثبيت البرامج الثابتة</string>
95 <string name="share_log">مشاركة سجلات التصحيح</string>
96 <string name="share_log_description">مشاركة مل٠سجل يوزو لتصحيح المشكلات</string>
97 <string name="share_log_missing">لم يتم العثور على مل٠السجل</string>
98 <string name="install_game_content">تثبيت محتوى اللعبة</string>
99 <string name="install_game_content_description">DLC قم بتثبيت تحديثات اللعبة أو</string>
100 <string name="installing_game_content">جار٠تثبيت المحتوى</string>
101 <string name="install_game_content_failure_base">لا ÙŠÙØ³Ù…Ø­ بتثبيت الألعاب الأساسية لتجنب التعارضات المحتملة.</string>
102 <string name="install_game_content_success_install">%1$d تم التثبيت بنجاح</string>
103 <string name="install_game_content_success_overwrite">%1$d تمت الكتابة Ùوقه بنجاح</string>
104 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
105 <string name="custom_driver_not_supported">برامج التشغيل المخصصة غير مدعومة</string>
106 <string name="custom_driver_not_supported_description">تحميل برنامج التشغيل المخصص غير معتمد حاليًا لهذا الجهاز.\nحدد هذا الخيار مرة أخرى ÙÙŠ المستقبل Ù„Ù…Ø¹Ø±ÙØ© ما إذا تمت Ø¥Ø¶Ø§ÙØ© الدعم!</string>
107 <string name="manage_yuzu_data">إدارة بيانات يوزو</string>
108 <string name="manage_yuzu_data_description">استيراد/تصدير البرامج الثابتة ÙˆØ§Ù„Ù…ÙØ§ØªÙŠØ­ وبيانات المستخدم والمزيد!</string>
109 <string name="share_save_file">مشاركة Ù…Ù„Ù Ø§Ù„Ø­ÙØ¸</string>
110 <string name="export_save_failed">ÙØ´Ù„ تصدير Ø§Ù„Ø­ÙØ¸</string>
111
112 <string name="copied_to_clipboard">نسخ إلى Ø§Ù„Ø­Ø§ÙØ¸Ø©</string>
113 <string name="about_app_description">محاكي سويتش Ù…ÙØªÙˆØ­ المصدر</string>
114 <string name="contributors">المساهمين</string>
115 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
116 <string name="licenses_description">المشاريع التي تجعل تطبيق يوزو لنظام أندرويد ممكنًا</string>
117 <string name="build">البناء</string>
118 <string name="user_data">بيانات المستخدم</string>
119 <string name="exporting_user_data">جار٠تصدير بيانات المستخدم</string>
120 <string name="importing_user_data">جار٠استيراد بيانات المستخدم</string>
121 <string name="import_user_data">استيراد بيانات المستخدم</string>
122 <string name="invalid_yuzu_backup">نسخة احتياطية يوزو غير صالحة</string>
123 <string name="user_data_export_success">تم تصدير بيانات المستخدم بنجاح</string>
124 <string name="user_data_import_success">تم استيراد بيانات المستخدم بنجاح</string>
125 <string name="user_data_export_cancelled">تم إلغاء التصدير</string>
126 <string name="support_link">https://discord.gg/u77vRWY</string>
127 <string name="website_link">https://yuzu-emu.org/</string>
128 <string name="github_link">https://github.com/yuzu-emu</string>
129
130 <!-- Early access upgrade strings -->
131 <string name="early_access">الوصول المبكر</string>
132 <string name="get_early_access">احصل على الوصول المبكر</string>
133 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
134 <string name="get_early_access_description">الميزات المتطورة، والوصول المبكر إلى التحديثات، وأكثر من ذلك</string>
135 <string name="early_access_benefits">مزايا الوصول المبكر</string>
136 <string name="cutting_edge_features">ميزات متطورة</string>
137 <string name="early_access_updates">الوصول المبكر إلى التحديثات</string>
138 <string name="no_manual_installation">لا يوجد التثبيت اليدوي</string>
139 <string name="prioritized_support">الدعم ذو الأولوية</string>
140 <string name="helping_game_preservation">المساعدة ÙÙŠ Ø§Ù„Ø­ÙØ§Ø¸ على اللعبة</string>
141 <string name="our_eternal_gratitude">امتناننا الأبدي</string>
142 <string name="are_you_interested">هل انت مهتم؟</string>
143
144 <!-- General settings strings -->
145 <string name="frame_limit_enable">الحد من السرعة</string>
146 <string name="frame_limit_enable_description">يحد من سرعة المحاكاة بنسبة محددة من السرعة العادية</string>
147 <string name="frame_limit_slider">الحد من السرعة ÙÙŠ المئة</string>
148 <string name="frame_limit_slider_description">يحدد النسبة المئوية للحد من سرعة المحاكاة. 100% هي السرعة الطبيعية. ستؤدي القيم الأعلى أو الأدنى إلى زيادة أو تقليل حد السرعة.</string>
149 <string name="cpu_accuracy">دقة وحدة المعالجة المركزية</string>
150 <string name="value_with_units">%1$s%2$s</string>
151
152 <!-- System settings strings -->
153 <string name="use_docked_mode">وضع الإرساء</string>
154 <string name="use_docked_mode_description">زيادة الدقة، ÙˆØ§Ù†Ø®ÙØ§Ø¶ الأداء. يتم استخدام الوضع المحمول عند تعطيله، مما يؤدي إلى Ø®ÙØ¶ الدقة وزيادة الأداء.</string>
155 <string name="emulated_region">المنطقة التي تمت محاكاتها</string>
156 <string name="emulated_language">لغة المحاكاه</string>
157 <string name="select_rtc_date">حدد التاريخ Ùˆ الساعة ÙÙŠ الوقت الحقيقي</string>
158 <string name="select_rtc_time">حدد وقت الساعة ÙÙŠ الوقت Ø§Ù„ÙØ¹Ù„ÙŠ</string>
159 <string name="use_custom_rtc">ساعة مخصصة ÙÙŠ الوقت الحقيقي</string>
160 <string name="use_custom_rtc_description">يسمح لك بتعيين ساعة مخصصة ÙÙŠ الوقت Ø§Ù„ÙØ¹Ù„ÙŠ Ù…Ù†ÙØµÙ„Ø© عن وقت النظام الحالي لديك</string>
161 <string name="set_custom_rtc">تعيين ساعة مخصصة ÙÙŠ الوقت الحقيقي</string>
162
163 <!-- Graphics settings strings -->
164 <string name="renderer_accuracy">مستوى الدقة</string>
165 <string name="renderer_resolution">(Handheld/Docked) الدقة</string>
166 <string name="renderer_vsync">VSync وضع</string>
167 <string name="renderer_screen_layout">الاتجاه</string>
168 <string name="renderer_aspect_ratio">تناسب الابعاد</string>
169 <string name="renderer_anti_aliasing">طريقة Ù…ÙƒØ§ÙØ­Ø© التعرج</string>
170 <string name="renderer_asynchronous_shaders">استخدم تظليل غير متزامن</string>
171 <string name="renderer_asynchronous_shaders_description">يجمع التظليل بشكل غير متزامن، مما يقلل من التأتأة ولكنه قد يؤدي إلى حدوث بعض الأخطاء.</string>
172 <string name="renderer_reactive_flushing">استخدم Ø§Ù„ØªÙ†Ø¸ÙŠÙ Ø§Ù„ØªÙØ§Ø¹Ù„ÙŠ</string>
173 <string name="renderer_reactive_flushing_description">تحسين دقة العرض ÙÙŠ بعض الألعاب على حساب الأداء</string>
174 <string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتحميل التظليلات التي تم إنشاؤها محليًا.</string>
175
176 <!-- Debug settings strings -->
177 <string name="cpu">وحدة المعالج المركزية</string>
178 <string name="cpu_debug_mode">تصحيح أخطاء وحدة المعالجة المركزية</string>
179 <string name="cpu_debug_mode_description">يضع وحدة المعالجة المركزية ÙÙŠ وضع التصحيح البطيء.</string>
180 <string name="gpu">GPU</string>
181 <string name="renderer_api">API</string>
182 <string name="renderer_debug">تصحيح الأخطاء الرسومية</string>
183 <string name="renderer_debug_description">يضبط واجهة برمجة تطبيقات الرسومات على وضع تصحيح الأخطاء البطيء.</string>
184 <string name="fastmem">Fastmem</string>
185
186 <!-- Audio settings strings -->
187 <string name="audio_output_engine">محرك الإخراج</string>
188 <string name="audio_volume">حجم</string>
189 <string name="audio_volume_description">يحدد حجم إخراج الصوت</string>
190
191 <!-- Miscellaneous -->
192 <string name="slider_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
193 <string name="ini_saved">الإعدادات المحÙوظة</string>
194 <string name="gameid_saved">الإعدادات المحÙوظة لـ %1$s</string>
195 <string name="unimplemented_menu">القائمة غير Ø§Ù„Ù…Ù†ÙØ°Ø©</string>
196 <string name="loading">جاري تحميل</string>
197 <string name="shutting_down">إيقا٠تشغيل</string>
198 <string name="reset_setting_confirmation">هل تريد إعادة تعيين هذا الإعداد مرة أخرى إلى قيمته Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠØ©ØŸ</string>
199 <string name="reset_to_default">إعادة تعيين إلى Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
200 <string name="reset_all_settings">إعادة تعيين جميع الإعدادات؟</string>
201 <string name="reset_all_settings_description">سيتم إعادة تعيين ÙƒØ§ÙØ© الإعدادات المتقدمة إلى تكوينها Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ. هذا لا يمكن التراجع عنها.</string>
202 <string name="settings_reset">إعادة تعيين الأعدادات</string>
203 <string name="close">إغلاق</string>
204 <string name="learn_more">Ù…Ø¹Ø±ÙØ© المزيد</string>
205 <string name="auto">تلقائي</string>
206 <string name="submit">إرسال</string>
207 <string name="string_null">قيمه خاليه</string>
208 <string name="string_import">استيراد</string>
209 <string name="export">تصدير</string>
210 <string name="export_failed">ÙØ´Ù„ التصدير</string>
211 <string name="import_failed">ÙØ´Ù„ الاستيراد</string>
212 <string name="cancelling">إلغاء</string>
213
214 <!-- GPU driver installation -->
215 <string name="select_gpu_driver">GPU حدد برنامج تشغيل</string>
216 <string name="select_gpu_driver_title">الحالي الخاص بك؟ GPU هل ترغب ÙÙŠ استبدال برنامج تشغيل</string>
217 <string name="select_gpu_driver_install">تثبيت</string>
218 <string name="select_gpu_driver_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
219 <string name="select_gpu_driver_use_default">يستخدم تعري٠معالج الرسوميات Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
220 <string name="select_gpu_driver_error">تم تحديد برنامج تشغيل غير صالح ØŒ باستخدام النظام Ø§Ù„Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
221 <string name="system_gpu_driver">تعري٠معالج الرسوميات الخاص بالنظام</string>
222 <string name="installing_driver">جار٠تثبيت برنامج التشغيل…</string>
223
224 <!-- Preferences Screen -->
225 <string name="preferences_settings">إعدادات</string>
226 <string name="preferences_general">عام</string>
227 <string name="preferences_system">النظام</string>
228 <string name="preferences_graphics">الرسوميات</string>
229 <string name="preferences_audio">الصوت</string>
230 <string name="preferences_theme">السمة واللون</string>
231 <string name="preferences_debug">تصحيح الأخطاء</string>
232
233 <!-- ROM loading errors -->
234 <string name="loader_error_encrypted">الخاص بك ROM تم تشÙير</string>
235 <string name="loader_error_video_core">حدث خطأ أثناء تهيئة مركز الÙيديو</string>
236 <string name="loader_error_invalid_format">ROM غير قادر على تحميل</string>
237 <string name="loader_error_file_not_found">غير موجود ROM ملÙ</string>
238
239 <!-- Emulation Menu -->
240 <string name="emulation_exit">الخروج من المحاكاة</string>
241 <string name="emulation_done">منجز</string>
242 <string name="emulation_fps_counter">عداد إطار/ثانية</string>
243 <string name="emulation_toggle_controls">تبديل عناصر التحكم</string>
244 <string name="emulation_rel_stick_center">مركز العصا النسبي</string>
245 <string name="emulation_dpad_slide">مزلاق أزرار الاتجاهات</string>
246 <string name="emulation_haptics">الاهتزازات الديناميكية</string>
247 <string name="emulation_show_overlay">عرض التراكب</string>
248 <string name="emulation_toggle_all">تبديل الكل</string>
249 <string name="emulation_control_adjust">ضبط التراكب</string>
250 <string name="emulation_control_scale">حجم</string>
251 <string name="emulation_control_opacity">العتامه</string>
252 <string name="emulation_touch_overlay_reset">إعادة تعيين التراكب</string>
253 <string name="emulation_touch_overlay_edit">تحرير التراكب</string>
254 <string name="emulation_pause">إيقا٠المحاكاة مؤقتًا</string>
255 <string name="emulation_unpause">إلغاء الإيقا٠المؤقت للمضاهاة</string>
256 <string name="emulation_input_overlay">خيارات التراكب</string>
257
258 <string name="load_settings">جار٠تحميل الإعدادات</string>
259
260 <!-- Software keyboard -->
261 <string name="software_keyboard">لوحة Ø§Ù„Ù…ÙØ§ØªÙŠØ­ البرمجية</string>
262
263 <!-- Errors and warnings -->
264 <string name="abort_button">إلغاء</string>
265 <string name="continue_button">استمر</string>
266 <string name="system_archive_not_found">لم يتم العثور على أرشي٠النظام</string>
267 <string name="system_archive_general">أرشي٠النظام</string>
268 <string name="save_load_error">خطأ ÙÙŠ Ø§Ù„Ø­ÙØ¸/التحميل</string>
269 <string name="fatal_error">خطا ÙØ§Ø¯Ø­</string>
270 <string name="performance_warning">سيؤدي إيقا٠تشغيل هذا الإعداد إلى تقليل أداء المحاكاة بشكل ملحوظ! للحصول على Ø£ÙØ¶Ù„ تجربة، يوصى بترك هذا الإعداد ممكنًا.</string>
271 <string name="memory_formatted">%1$s %2$s</string>
272 <string name="no_game_present">لا توجد لعبة قابلة للتمهيد</string>
273
274 <!-- Region Names -->
275 <string name="region_japan">اليابان</string>
276 <string name="region_usa">الولايات المتحدة الأمريكية</string>
277 <string name="region_europe">أوروبا</string>
278 <string name="region_australia">أستراليا</string>
279 <string name="region_china">الصين</string>
280 <string name="region_korea">كوريا</string>
281 <string name="region_taiwan">تايوان</string>
282
283 <!-- Memory Sizes -->
284 <string name="memory_byte">Byte</string>
285 <string name="memory_kilobyte">KB</string>
286 <string name="memory_megabyte">MB</string>
287 <string name="memory_gigabyte">GB</string>
288 <string name="memory_terabyte">TB</string>
289 <string name="memory_petabyte">PB</string>
290 <string name="memory_exabyte">EB</string>
291
292 <!-- Renderer APIs -->
293 <string name="renderer_vulkan">Vulkan</string>
294 <string name="renderer_none">لاشيء</string>
295
296 <!-- Renderer Accuracy -->
297 <string name="renderer_accuracy_normal">عادي</string>
298 <string name="renderer_accuracy_high">عالي</string>
299 <string name="renderer_accuracy_extreme">Extreme (بطيء)</string>
300
301 <!-- Resolutions -->
302 <string name="resolution_half">0.5X (360p/540p)</string>
303 <string name="resolution_three_quarter">0.75X (540p/810p)</string>
304 <string name="resolution_one">1X (720p/1080p)</string>
305 <string name="resolution_two">2X (1440p/2160p) (بطيء)</string>
306 <string name="resolution_three">3X (2160p/3240p) (بطيء)</string>
307 <string name="resolution_four">4X (2880p/4320p) (بطيء)</string>
308
309 <!-- Renderer VSync -->
310 <string name="renderer_vsync_immediate">Immediate (Off)</string>
311 <string name="renderer_vsync_mailbox">Mailbox</string>
312 <string name="renderer_vsync_fifo">FIFO (On)</string>
313 <string name="renderer_vsync_fifo_relaxed">FIFO Relaxed</string>
314
315 <!-- Scaling Filters -->
316 <string name="scaling_filter_nearest_neighbor">Nearest Neighbor</string>
317 <string name="scaling_filter_bilinear">Bilinear</string>
318 <string name="scaling_filter_bicubic">Bicubic</string>
319 <string name="scaling_filter_gaussian">Gaussian</string>
320 <string name="scaling_filter_scale_force">ScaleForce</string>
321 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string>
322
323 <!-- Anti-Aliasing -->
324 <string name="anti_aliasing_none">لا شيء</string>
325 <string name="anti_aliasing_fxaa">FXAA</string>
326 <string name="anti_aliasing_smaa">SMAA</string>
327
328 <!-- Screen Layouts -->
329 <string name="screen_layout_landscape">اÙقي</string>
330 <string name="screen_layout_portrait">عمودي</string>
331 <string name="screen_layout_auto">تلقائي</string>
332
333 <!-- Aspect Ratios -->
334 <string name="ratio_default">(16:9) Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
335 <string name="ratio_force_four_three">4:3 ÙØ±Ø¶</string>
336 <string name="ratio_force_twenty_one_nine">21:9 ÙØ±Ø¶</string>
337 <string name="ratio_force_sixteen_ten">16:10 ÙØ±Ø¶</string>
338 <string name="ratio_stretch">تمتد إلى Ø§Ù„Ù†Ø§ÙØ°Ø©</string>
339
340 <!-- CPU Accuracy -->
341 <string name="cpu_accuracy_accurate">دقه</string>
342 <string name="cpu_accuracy_unsafe">غير آمن</string>
343 <string name="cpu_accuracy_paranoid">Paranoid (Slow)</string>
344
345 <!-- Gamepad Buttons -->
346 <string name="gamepad_d_pad">أزرار الاتجاهات</string>
347 <string name="gamepad_left_stick">العصا اليسرى</string>
348 <string name="gamepad_right_stick">العصا اليمنى</string>
349 <string name="gamepad_home">شاشة الإستقبال</string>
350 <string name="gamepad_screenshot">لقطة شاشة</string>
351
352 <!-- Disk shader cache -->
353 <string name="preparing_shaders">تحضير التظليل</string>
354 <string name="building_shaders">بناء التظليل</string>
355
356 <!-- Theme options -->
357 <string name="change_app_theme">تغيير سمة التطبيق</string>
358 <string name="theme_default">Ø§ÙØªØ±Ø§Ø¶ÙŠ</string>
359 <string name="theme_material_you">Material You</string>
360
361 <!-- Theme Modes -->
362 <string name="change_theme_mode">تغيير وضع السمة</string>
363 <string name="theme_mode_follow_system">اتبع النظام</string>
364 <string name="theme_mode_light">ÙØ§ØªØ­</string>
365 <string name="theme_mode_dark">غامق</string>
366
367 <!-- Audio output engines -->
368 <string name="cubeb">cubeb</string>
369
370 <!-- Black backgrounds theme -->
371 <string name="use_black_backgrounds">خلÙيات سوداء</string>
372 <string name="use_black_backgrounds_description">عند استخدام المظهر الداكن، قم بتطبيق خلÙيات سوداء.</string>
373
374 <!-- Picture-In-Picture -->
375 <string name="picture_in_picture">صورة داخل صورة</string>
376 <string name="picture_in_picture_description">تصغير Ø§Ù„Ù†Ø§ÙØ°Ø© عند وضعها ÙÙŠ الخلÙية</string>
377 <string name="pause">توقÙ</string>
378 <string name="play">تشغيل</string>
379 <string name="mute">كتم</string>
380 <string name="unmute">إلغاء الكتم</string>
381
382 <!-- Licenses screen strings -->
383 <string name="licenses">التراخيص</string>
384 <string name="license_fidelityfx_fsr_description">AMD ترقية عالية الجودة من</string>
385 </resources>
diff --git a/src/android/app/src/main/res/values-ckb/strings.xml b/src/android/app/src/main/res/values-ckb/strings.xml
new file mode 100644
index 000000000..d2e5fee19
--- /dev/null
+++ b/src/android/app/src/main/res/values-ckb/strings.xml
@@ -0,0 +1,336 @@
1<?xml version="1.0" encoding="utf-8"?>
2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3
4 <string name="app_disclaimer">ئەم نەرمەکاڵایە یارییەکانی کۆنسۆلی نینتێندۆ سویچ کارپێدەکات. هیچ ناونیشانێکی یاری Ùˆ کلیلی تێدا نییە..&lt;br /&gt;&lt;br /&gt;Ù¾ÛŽØ´ ئەوەی دەست Ù¾ÛŽ بکەیت، تکایە شوێنی ÙØ§ÛŒÙ„ÛŒ <![CDATA[<b> prod.keys </b>]]> دیاریبکە Ù„Û• Ù†ÛŽÙˆ کۆگای ئامێرەکەت.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">زیاتر Ùێربە</a>]]></string>
5 <string name="emulation_notification_channel_name">ئیمولەیشن کارایە</string>
6 <string name="emulation_notification_channel_description">ئاگادارکردنەوەیەکی بەردەوام نیشان دەدات کاتێک ئیمولەیشن کاردەکات.</string>
7 <string name="emulation_notification_running">یوزو کاردەکات</string>
8 <string name="notice_notification_channel_name">ئاگاداری و هەڵەکان</string>
9 <string name="notice_notification_channel_description">ئاگادارکردنەوەکان پیشان دەدات کاتێک شتێک بە هەڵەدا دەچێت.</string>
10 <string name="notification_permission_not_granted">مۆڵەتی ئاگادارکردنەوە نەدراوە!</string>
11
12 <!-- Setup strings -->
13 <string name="welcome">بەخێربێیت!</string>
14 <string name="welcome_description">Ùێربە Ú†Û†Ù† &lt;b>yuzu&lt;/b> ڕێکبخەیت Ùˆ بچییە ناو ئیمولەیشن.</string>
15 <string name="get_started">دەست پێبکە</string>
16 <string name="keys">کلیلەکان</string>
17 <string name="keys_description">ÙØ§ÛŒÙ„ÛŒ &lt;b>prod.keys&lt;/b> هەڵبژێرە بە دوگمەی خوارەوە.</string>
18 <string name="select_keys">کلیلەکان هەڵبژێرە</string>
19 <string name="games">یاریەکان</string>
20 <string name="games_description">Ùۆڵدەری &lt;b>Games&lt;/b> هەڵبژێرە بە دوگمەی خوارەوە.</string>
21 <string name="done">تەواو</string>
22 <string name="done_description">تۆ تەواو ئامادەیت.\nچێژ لە یارییەکانت وەربگرە!</string>
23 <string name="text_continue">بەردەوام بوون</string>
24 <string name="next">دواتر</string>
25 <string name="back">گەڕانەوە</string>
26 <string name="add_games">زیادکردنی یاری</string>
27 <string name="add_games_description">Ùۆڵدەری یارییەکانت هەڵبژێرە</string>
28 <!-- Home strings -->
29 <string name="home_games">یاریەکان</string>
30 <string name="home_search">گەڕان</string>
31 <string name="home_settings">ڕێکخستنەکان</string>
32 <string name="empty_gamelist">تا ئێستا هیچ ÙØ§ÛŒÙ„ÛŽÚ© نەدۆزراوەتەوە یان هیچ ناونیشانێکی یاری هەڵنەبژێردراوە.</string>
33 <string name="search_and_filter_games">گەڕان Ùˆ Ùلتەرکردنی یارییەکان</string>
34 <string name="select_games_folder">Ùۆڵدەری یارییەکان هەڵبژێرە</string>
35 <string name="select_games_folder_description">ڕێگە بە یوزو دەدات بۆ پڕکردنەوەی لیستی یارییەکان</string>
36 <string name="add_games_warning">هەڵبژاردنی Ùۆڵدەری یارییەکان تێپەڕدەکەیت؟</string>
37 <string name="add_games_warning_description">یارییەکان Ù„Û• لیستی یارییەکاندا پیشان نادرێن ئەگەر Ùۆڵدەرێک هەڵنەبژێردرێت.</string>
38 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
39 <string name="home_search_games">گەڕان بەدوای یارییەکاندا</string>
40 <string name="games_dir_selected">ناونیشانی یارییەکان هەڵبژێردرا</string>
41 <string name="install_prod_keys">دابمەزرێنە prod.keys</string>
42 <string name="install_prod_keys_description">پێویستە بۆ کۆدکردنەوەى یارییە تاکەکەسییەکان</string>
43 <string name="install_prod_keys_warning">زیادکردنی کلیلەکان تێپەڕدەکەیت؟</string>
44 <string name="install_prod_keys_warning_description">کلیلی دروست پێویستە بۆ وەرگرتنی یارییەکانی تاکەکەسی. تەنها ئەپەکانی homebrew کاردەکەن ئەگەر بەردەوام بیت.</string>
45 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
46 <string name="notifications">ئاگادارکردنەوەکان</string>
47 <string name="notifications_description">بە دوگمەی خوارەوە مۆڵەتی ئاگادارکردنەوەکە بدە.</string>
48 <string name="give_permission">مۆڵەت بدە</string>
49 <string name="notification_warning">پێدانی مۆڵەتی ئاگادارکردنەوە تێپەڕدەکەیت؟</string>
50 <string name="notification_warning_description">یوزو ناتوانێت لە زانیاری گرنگ ئاگادارت بکاتەوە.</string>
51 <string name="permission_denied">مۆڵەت پێدان ڕەتکرایەوە</string>
52 <string name="permission_denied_description">زۆر جار ئەم مۆڵەتەت ڕەتکردۆتەوە و ئێستا دەبێت بە دەستی ڕێگەپێدان بکەیت لە ڕێکخستنەکانی سیستەمدا.</string>
53 <string name="about">دەربارە</string>
54 <string name="about_description">وەشانی دروستکردن، بیتبێن و زۆر شتیتر</string>
55 <string name="warning_help">یارمەتی</string>
56 <string name="warning_skip">پەڕاندن</string>
57 <string name="warning_cancel">ڕەتکردنەوە</string>
58 <string name="install_amiibo_keys">دامەزراندنی کلیلی Amiibo</string>
59 <string name="install_amiibo_keys_description">پێویستە بۆ بەکارهێنانی Amiibo لە یاریدا</string>
60 <string name="invalid_keys_file">ÙØ§ÛŒÙ„ÛŒ کلیلێکی نادروست هەڵبژێردرا</string>
61 <string name="install_keys_success">کلیلەکان بە سەرکەوتوویی دامەزران</string>
62 <string name="reading_keys_failure">هەڵە لە خوێندنەوەی کۆدکردنی کلیل</string>
63 <string name="install_prod_keys_failure_extension_description">دڵنیابەوە Ú©Û• ÙØ§ÛŒÙ„ÛŒ کلیلەکانت درێژکراوەی .keys ÛŒ هەیە Ùˆ دووبارە هەوڵبدەرەوە.</string>
64 <string name="install_amiibo_keys_failure_extension_description">دڵنیابە Ú©Û• ÙØ§ÛŒÙ„ÛŒ کلیلەکانت درێژکراوەی .bin ÛŒ هەیە Ùˆ دووبارە هەوڵبدەرەوە.</string>
65 <string name="invalid_keys_error">کلیلی کۆدکردنی نادروستە</string>
66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
67 <string name="install_keys_failure_description">ÙØ§ÛŒÙ„Û• هەڵبژێردراوەکە هەڵەیە یان تێکچووە. تکایە دووبارە کلیلەکانت دەربێنەوە.</string>
68 <string name="install_gpu_driver">دامەزراندنی وەگەڕخەری GPU</string>
69 <string name="install_gpu_driver_description">دامەزراندنی وەگەڕخەری بەدیل بۆ ئەوەی بە ئەگەرێکی زۆرەوە کارایی باشتر یان وردبینی هەبێت</string>
70 <string name="advanced_settings">ڕێکخستنە پێشکەوتووەکان</string>
71 <string name="settings_description">سازدانی ڕێکخستنەکانی ئیمولەیتەر</string>
72 <string name="search_recently_played">بەم دواییە یاری کردووە</string>
73 <string name="search_recently_added">بەم دواییە زیادکرا</string>
74 <string name="search_retail">بەتاک</string>
75 <string name="search_homebrew">هۆم بریو</string>
76 <string name="open_user_folder">کردنەوەی Ùۆڵدەری یوزو</string>
77 <string name="open_user_folder_description">بەڕێوەبردنی ÙØ§ÛŒÙ„Û• ناوخۆییەکانی یوزو</string>
78 <string name="theme_and_color_description">دەستکاری کردنی شێوازی ئەپەکە</string>
79 <string name="no_file_manager">هیچ ÙØ§ÛŒÙ„ بەڕێوەبەرێک نەدۆزرایەوە</string>
80 <string name="notification_no_directory_link">نەتوانرا ناونیشانی یوزو بکرێتەوە</string>
81 <string name="notification_no_directory_link_description">تکایە شوێنی Ùۆڵدەری بەکارهێنەر Ù„Û•Ú¯Û•Úµ پانێڵی لایەنی ÙØ§ÛŒÙ„ بەڕێوەبارەکان بە دەست بدۆزەرەوە.</string>
82 <string name="manage_save_data">بەڕێوەبردنی داتای پاشەکەوتکراو</string>
83 <string name="manage_save_data_description">داتای پاشەکەوتکراو دۆزراوە. تکایە لە خوارەوە بژاردەیەک هەڵبژێرە.</string>
84 <string name="import_export_saves_description">هاوردەکردن یان هەناردەکردنی ÙØ§ÛŒÙ„ÛŒ پاشەکەوتکراو</string>
85 <string name="save_file_imported_success">بە سەرکەوتوویی هاوردە کرا</string>
86 <string name="save_file_invalid_zip_structure">پێکهاتەی شوێنی پاشەکەوتکراو نادروستە</string>
87 <string name="save_file_invalid_zip_structure_description">ناوی یەکەمی Ùۆڵدەر دەبێت ناسنامەی ناونیشانی یارییەکە بێت.</string>
88 <string name="import_saves">هاوردەکردن</string>
89 <string name="export_saves">هەناردەکردن</string>
90 <string name="install_firmware">دامەزراندنی پتەوواڵا</string>
91 <string name="install_firmware_description">پتەوواڵا دەبێت Ù„Û• ئەرشیÙÛŒ زیپدا بێت Ùˆ پێویستە بۆ بووتکردنی هەندێک یاری</string>
92 <string name="firmware_installing">دامەزرانی پتەوواڵا</string>
93 <string name="firmware_installed_success">پتەوواڵا بە سەرکەوتوویی دامەزرا</string>
94 <string name="firmware_installed_failure">دامەزراندنی پتەوواڵا شکستی هێنا</string>
95 <string name="share_log">هاوبەشی پێکردنی لۆگەکانی چاککردنەوە</string>
96 <string name="share_log_description">ÙØ§ÛŒÙ„Û• Ù„Û†Ú¯Û•Ú©Û•ÛŒ یوزو هاوبەش بکە بۆ چاککردنی کێشەکان</string>
97 <string name="share_log_missing">هیچ ÙØ§ÛŒÙ„ÛŽÚ©ÛŒ Ù„Û†Ú¯ نەدۆزراوە</string>
98 <string name="install_game_content">دامەزراندنی ناوەڕۆکی یاری</string>
99 <string name="install_game_content_description">دامەزراندنی نوێکاری یارییەکان یان DLC</string>
100 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
101 <!-- About screen strings -->
102 <string name="gaia_is_not_real">گایا ڕاستەقینە نییە</string>
103 <string name="copied_to_clipboard">کۆپی کرا بۆ تەختەی نووسین</string>
104 <string name="about_app_description">ئیمۆلیتەرێکی سەرچاوە-کراوەی سویچ</string>
105 <string name="contributors">بەشداربووان</string>
106 <string name="contributors_description">دروستکراوە لەگەڵ \u2764 لەلایەن تیمەکەی یوزو</string>
107 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
108 <string name="licenses_description">ئەو پڕۆژانەی کە یوزوی بۆ ئەندرۆید ڕەخساند</string>
109 <string name="build">بونیات</string>
110 <string name="support_link">https://discord.gg/u77vRWY</string>
111 <string name="website_link">https://yuzu-emu.org/</string>
112 <string name="github_link">https://github.com/yuzu-emu</string>
113
114 <!-- Early access upgrade strings -->
115 <string name="early_access">بەزوویی دەسپێگەشتن</string>
116 <string name="get_early_access">بەدەستهێنانی بەزوویی دەسپێگەشتن</string>
117 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
118 <string name="get_early_access_description">تایبەتمەندییە پێشکەوتووەکان، بەزوویی دەستگەیشتن بە نوێکارییەکان و زۆر شتی تر</string>
119 <string name="early_access_benefits">سوودەکانی بەزوویی دەسپێگەشتن</string>
120 <string name="cutting_edge_features">تایبەتمەندییە پێشکەوتووەکان</string>
121 <string name="early_access_updates">زوو دەستگەیشتن بە نوێکارییەکان</string>
122 <string name="no_manual_installation">چیتر دامەزراندنی دەستی نییە</string>
123 <string name="prioritized_support">پشتگیری لە پێشینە</string>
124 <string name="helping_game_preservation">یارمەتیدانی پاراستنی یارییەکان</string>
125 <string name="our_eternal_gratitude">سوپاس و پێزانینی هەمیشەییمان</string>
126 <string name="are_you_interested">ئایا تۆ خوازیاریت؟</string>
127
128 <!-- General settings strings -->
129 <string name="frame_limit_enable">سنووردارکردنی خێرایی</string>
130 <string name="frame_limit_enable_description">خێرایی ئیمولەیشن سنووردار دەکات بۆ ڕێژەیەکی دیاریکراو لە خێرایی ئاسایی.</string>
131 <string name="frame_limit_slider">سنووردارکردنی لەسەدای خێرایی</string>
132 <string name="frame_limit_slider_description">ڕێژەی سەدی دیاری دەکات بۆ سنووردارکردنی خێرایی ئیمولەیشن. 100% خێرایی ئاساییە. بەهایی بەرزتر یان نزمتر دەبێتە هۆی زیاد یان کەمکردنەوەی سنووری خێرایی.</string>
133 <string name="cpu_accuracy">وردی CPU</string>
134 <!-- System settings strings -->
135 <string name="use_docked_mode">دۆخی دۆککراو</string>
136 <string name="use_docked_mode_description">ڕوونی زیاد دەکات، کارایی کەم دەکاتەوە. دۆخی دەستی بەکاردێت کاتێک لەکاردەخرێت، ئەمەش ڕوونی دادەبەزێنێت و کارایی زیاد دەکات.</string>
137 <string name="emulated_region">ناوچەی ئیمولەیشن</string>
138 <string name="emulated_language">زمانی ئیمولەیتەر</string>
139 <string name="select_rtc_date">هەڵبژاردنی بەرواری RTC</string>
140 <string name="select_rtc_time">هەڵبژاردنی کاتی RTC</string>
141 <string name="use_custom_rtc">RTCی تایبەتمەند</string>
142 <string name="use_custom_rtc_description">ڕێگەت پێدەدات کاتژمێرێکی کاتی ڕاستەقینەی تایبەتمەند دابنێیت کە جیاوازە لە کاتی ئێستای سیستەمەکەت.</string>
143 <string name="set_custom_rtc">دانانی RTCی تایبەتمەند</string>
144
145 <!-- Graphics settings strings -->
146 <string name="renderer_accuracy">ئاستی وردبینی</string>
147 <string name="renderer_resolution">ڕوونی (دۆخی دەستی/دۆخی دۆک)</string>
148 <string name="renderer_vsync">دۆخی VSync</string>
149 <string name="renderer_aspect_ratio">ڕێژەی ڕووبەری شاشە</string>
150 <string name="renderer_scaling_filter">Ùلتەری گونجاندنی پەنجەرە</string>
151 <string name="renderer_anti_aliasing">شێوازی دژە-خاوڕۆیی</string>
152 <string name="renderer_force_max_clock">ناچاریکردن بۆ زۆرترین کاتژمێر (تەنها ئەدرینۆ)</string>
153 <string name="renderer_force_max_clock_description">GPU ناچار دەکات بە زۆرترین کاتژمێر کاربکات (هێشتا سنووردارکردنی گەرمی جێبەجێ دەکرێت).</string>
154 <string name="renderer_asynchronous_shaders">بەکارهێنانی سێبەری ناهاوسەنگ</string>
155 <string name="renderer_asynchronous_shaders_description">سێبەرەکان بە شێوەیەکی ناهاوسەنگ کۆدەکاتەوە، پچڕپچڕی کەمدەکاتەوە بەڵام لەوانەیە گلێچ دروستکا.</string>
156 <string name="renderer_reactive_flushing">بەکارهێنانی بەرپێچدەرەوە</string>
157 <string name="renderer_reactive_flushing_description">وردی ڕێندەرکردن لە هەندێک یاریدا باشتر دەکات لەسەر تێچووی کارایی.</string>
158 <string name="use_disk_shader_cache">بیرگەخێرای سێبەری دیسک</string>
159 <string name="use_disk_shader_cache_description">پچڕپچڕی کەمدەکاتەوە بە هەڵگرتن و بارکردنی سێبەری دروستکراو لە ناوخۆدا.</string>
160
161 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string>
163 <string name="renderer_api">API گراÙیک</string>
164 <string name="renderer_debug">چاککردنەوەی گراÙیک</string>
165 <string name="renderer_debug_description">API ÛŒ گراÙیکەکان ڕێکدەخات بۆ دۆخی چاککردنی خاو.</string>
166 <string name="audio_volume">قەبارەی دەنگی</string>
167 <string name="audio_volume_description">دیاریکردنی قەبارەی دەنگی دەرچووی بیستۆک و بزوێنەری دەنگی دەرەکی.</string>
168
169 <!-- Miscellaneous -->
170 <string name="slider_default">بنەڕەت</string>
171 <string name="ini_saved">ڕێکخستنە پاشەکەوتکراوەکان</string>
172 <string name="gameid_saved">ڕێکخستنە پاشەکەوتکراوەکان بۆ %1$s</string>
173 <string name="error_saving">هەڵە لە پاشەکەوتکردن %1$s.ini: %2$s</string>
174 <string name="loading">بارکردن...</string>
175 <string name="reset_setting_confirmation">ئایا دەتەوێت ئەم ڕێکخستنە بگەڕێنیتەوە بۆ بەهای بنەڕەتی خۆی؟</string>
176 <string name="reset_to_default">دوبارە ڕێکخستنەوەی بۆ بنەڕەت</string>
177 <string name="reset_all_settings">هەموو ڕێکخستنەکان دوبارە ڕێک دەخاتەوە؟</string>
178 <string name="reset_all_settings_description">هەموو ڕێکخستنە پێشکەوتووەکان دەگەڕێنەوە بۆ ڕێکخستنی بنەڕەتی خۆیان. پاشگەز بوونەوەی نییه.</string>
179 <string name="settings_reset">دوبارە ڕێککردنەوەی ڕێکخستنەکان</string>
180 <string name="close">داخستن</string>
181 <string name="learn_more">زیاتر Ùێربە</string>
182 <string name="auto">خودکار</string>
183 <string name="submit">پێشکەشکردن</string>
184 <string name="string_import">هاوردەکردن</string>
185 <string name="export">هەناردەکردن</string>
186 <!-- GPU driver installation -->
187 <string name="select_gpu_driver">هەڵبژاردنی وەگەڕخەری GPU</string>
188 <string name="select_gpu_driver_title">حەز دەکەیت وەگەڕخەری GPU ی ئێستات بگۆڕیت؟</string>
189 <string name="select_gpu_driver_install">دامەزراندن</string>
190 <string name="select_gpu_driver_default">بنەڕەت</string>
191 <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="installing_driver">دامەزراندنی وەگەڕخەر...</string>
195
196 <!-- Preferences Screen -->
197 <string name="preferences_settings">ڕێکخستنەکان</string>
198 <string name="preferences_general">گشتی</string>
199 <string name="preferences_system">سیستەم</string>
200 <string name="preferences_graphics">گراÙیک</string>
201 <string name="preferences_audio">دەنگ</string>
202 <string name="preferences_theme">ڕەنگ و ڕووکار</string>
203 <string name="preferences_debug">چاککردنەوە</string>
204
205 <!-- ROM loading errors -->
206 <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>
208 <string name="loader_error_video_core">هەڵەیەک لە دەستپێکردنی ناوەکی ڤیدیۆکەدا ڕوویدا</string>
209 <string name="loader_error_video_core_description">ئەمەش بەزۆری بەهۆی وەگەڕخەرێکی ناتەبای GPU ەوەیە. دامەزراندنی وەگەڕخەری GPU ی تایبەتمەندکراو لەوانەیە ئەم کێشەیە چارەسەر بکات.</string>
210 <string name="loader_error_invalid_format">ناتوانرێت ڕۆم باربکرێت</string>
211 <string name="loader_error_file_not_found">ÙØ§ÛŒÙ„ÛŒ Ú•Û†Ù… بوونی نییە</string>
212
213 <!-- Emulation Menu -->
214 <string name="emulation_exit">دەرچوون لە ئیمولەیشن</string>
215 <string name="emulation_done">تەواو</string>
216 <string name="emulation_fps_counter">FPS ژمێر</string>
217 <string name="emulation_toggle_controls">گۆڕینی کۆنتڕۆڵ</string>
218 <string name="emulation_rel_stick_center">ناوەندی گێڕ بەنزیکەیی</string>
219 <string name="emulation_dpad_slide">خلیسکانی 4 دوگمەکە</string>
220 <string name="emulation_haptics">لەرینەوەی پەنجەلێدان</string>
221 <string name="emulation_show_overlay">نیشاندانی داپۆشەر</string>
222 <string name="emulation_toggle_all">گۆڕینی سەرجەم</string>
223 <string name="emulation_control_adjust">ڕێکخستنی داپۆشەر</string>
224 <string name="emulation_control_scale">پێوەر</string>
225 <string name="emulation_control_opacity">ڕوونی</string>
226 <string name="emulation_touch_overlay_reset">دووبارە ڕێکخستنەوەی داپۆشەر</string>
227 <string name="emulation_touch_overlay_edit">دەستکاریکردنی داپۆشەر</string>
228 <string name="emulation_pause">وەستاندنی ئیمولەیشن</string>
229 <string name="emulation_unpause">لادانی وەستاندنی ئیمولەیشن</string>
230 <string name="emulation_input_overlay">هەڵبژاردەکانی داپۆشەر</string>
231
232 <string name="load_settings">بارکردنی ڕێکخستنەکان...</string>
233
234 <!-- Software keyboard -->
235 <string name="software_keyboard">کیبۆردی نەرمەکاڵا</string>
236
237 <!-- Errors and warnings -->
238 <string name="abort_button">دەربارە</string>
239 <string name="continue_button">بەردەوام بوون</string>
240 <string name="system_archive_not_found">ئەرشیÙÛŒ سیستەم نەدۆزراوە</string>
241 <string name="system_archive_not_found_message">%s دیار نییە. تکایە ئەرشیÙÛŒ سیستەمەکەت ÙÚ•ÛŽ بدە.\nبەردەوامی ئیمولەیشن لەوانەیە ببێتە Ù‡Û†ÛŒ تێکچوون Ùˆ Ùڕێدانەدەرەوە.</string>
242 <string name="system_archive_general">ئەرشیÙÛŽÚ©ÛŒ سیستەم</string>
243 <string name="save_load_error">هەڵەی پاشەکەوتکردن/بارکردن</string>
244 <string name="fatal_error">هەڵەی کوشندە</string>
245 <string name="fatal_error_message">هەڵەیەکی کوشندە ڕوویدا. بۆ وردەکارییەکان Ù„Û†Ú¯Û•Ú©Û• بپشکنە.\nبەردەوامی ئیمولەیشن لەوانەیە ببێتە Ù‡Û†ÛŒ تێکچوون Ùˆ Ùڕێدانەدەرەوە.</string>
246 <string name="performance_warning">کوژاندنەوەی ئەم ڕێکخستنە دەبێتە هۆی کەمکردنەوەی کارایی ئیمولەیشن! بۆ باشترین ئەزموون، باشترە ئەم ڕێکخستنە چالاک بهێڵیتەوە.</string>
247 <!-- Region Names -->
248 <string name="region_japan">ژاپۆن</string>
249 <string name="region_usa">ئەمریکا</string>
250 <string name="region_europe">ئەورووپا</string>
251 <string name="region_australia">ئوسترالیا</string>
252 <string name="region_china">چین</string>
253 <string name="region_korea">کۆریا</string>
254 <string name="region_taiwan">تایوان</string>
255
256 <string name="memory_gigabyte">GB</string>
257 <!-- Renderer APIs -->
258 <string name="renderer_vulkan">ڤوڵکان</string>
259 <string name="renderer_none">هیچ</string>
260
261 <!-- Renderer Accuracy -->
262 <string name="renderer_accuracy_normal">ئاسایی</string>
263 <string name="renderer_accuracy_high">بەرز</string>
264 <string name="renderer_accuracy_extreme">ئەوپەڕ (خاو)</string>
265
266 <!-- Resolutions -->
267 <string name="resolution_half">0.5X (360p/540p)</string>
268 <string name="resolution_three_quarter">0.75X (540p/810p)</string>
269 <string name="resolution_one">1X (720p/1080p)</string>
270 <string name="resolution_two">2X (1440p/2160p) (خاو)</string>
271 <string name="resolution_three">3X (2160p/3240p) (خاو)</string>
272 <string name="resolution_four">4X (2880p/4320p) (خاو)</string>
273
274 <!-- Renderer VSync -->
275 <string name="renderer_vsync_immediate">دەستبەجێ (کوژاوە)</string>
276 <string name="renderer_vsync_mailbox">سندوقی پۆستە</string>
277 <string name="renderer_vsync_fifo">FIFO (پێکراو)</string>
278 <string name="renderer_vsync_fifo_relaxed">FIFO ئارام</string>
279
280 <!-- Scaling Filters -->
281 <string name="scaling_filter_nearest_neighbor">نزیکترین دراوسێ</string>
282 <string name="scaling_filter_bilinear">دوو هێڵی</string>
283 <string name="scaling_filter_bicubic">دووخشتەکی</string>
284 <string name="scaling_filter_gaussian">گاوسی</string>
285 <string name="scaling_filter_scale_force">پێوەرهێز</string>
286 <string name="scaling_filter_fsr">AMD FidelityFX™ سوپەر ووردبینی</string>
287
288 <!-- Anti-Aliasing -->
289 <string name="anti_aliasing_none">هیچ</string>
290 <string name="anti_aliasing_fxaa">FXAA</string>
291 <string name="anti_aliasing_smaa">SMAA</string>
292
293 <string name="screen_layout_auto">خودکار</string>
294
295 <!-- Aspect Ratios -->
296 <string name="ratio_default">بنەڕەت (16:9)</string>
297 <string name="ratio_force_four_three">ڕووبەری 4:3</string>
298 <string name="ratio_force_twenty_one_nine">ڕووبەری 21:9</string>
299 <string name="ratio_force_sixteen_ten">ڕووبەری 16:10</string>
300 <string name="ratio_stretch">کشانی پڕ بەشاشە</string>
301
302 <!-- CPU Accuracy -->
303 <string name="cpu_accuracy_accurate">وورد</string>
304 <string name="cpu_accuracy_unsafe">ناسەقامگیر</string>
305 <string name="cpu_accuracy_paranoid">بەگومان (خاو)</string>
306
307 <!-- Gamepad Buttons -->
308 <string name="gamepad_d_pad">4 دوگمەکە</string>
309 <string name="gamepad_left_stick">گێڕی چەپ</string>
310 <string name="gamepad_right_stick">گێڕی ڕاست</string>
311 <string name="gamepad_home">ماڵەوە</string>
312 <string name="gamepad_screenshot">وێنەگرتنی شاشە</string>
313
314 <!-- Disk shader cache -->
315 <string name="preparing_shaders">ئامادەکردنی سێبەرەکان</string>
316 <string name="building_shaders">دروستکردنی سێبەرەکان</string>
317
318 <!-- Theme options -->
319 <string name="change_app_theme">گۆڕینی ڕووکاری ئەپەکە</string>
320 <string name="theme_default">بنەڕەت</string>
321 <string name="theme_material_you">کەرەستەی تۆ</string>
322
323 <!-- Theme Modes -->
324 <string name="change_theme_mode">گۆڕینی دۆخی ڕووکار</string>
325 <string name="theme_mode_follow_system">پەیڕەوی کردنی سیستەم</string>
326 <string name="theme_mode_light">ڕوناکی</string>
327 <string name="theme_mode_dark">تاریک</string>
328
329 <!-- Black backgrounds theme -->
330 <string name="use_black_backgrounds">پاشبنەمای ڕەش</string>
331 <string name="use_black_backgrounds_description">لە کاتی بەکارهێنانی ڕووکاری تاریکدا، پاشبنەمای ڕەش دادەنێ.</string>
332
333 <!-- Licenses screen strings -->
334 <string name="licenses">مۆڵەتەکان</string>
335 <string name="license_fidelityfx_fsr_description">بەرزکردنەوەی کوالێتی بەرز لە کۆمپانیای AMD</string>
336 </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 72a47fbdb..9c6590b5e 100644
--- a/src/android/app/src/main/res/values-de/strings.xml
+++ b/src/android/app/src/main/res/values-de/strings.xml
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Diese Software kann Spiele für die Nintendo Switch abspielen. Keine Spiele oder Spielekeys sind enthalten.&lt;br /&gt;&lt;br /&gt;Bevor du beginnst, bitte halte deine <![CDATA[<b> prod.keys </b>]]> auf deinem Gerät bereit. .&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Mehr Infos</a>]]></string> 4 <string name="app_disclaimer">Diese Software kann Spiele für die Nintendo Switch abspielen. Keine Spiele oder Spielekeys sind enthalten.&lt;br /&gt;&lt;br /&gt;Bevor du beginnst, bitte halte deine <![CDATA[<b> prod.keys </b>]]> auf deinem Gerät bereit. .&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Mehr Infos</a>]]></string>
5 <string name="emulation_notification_channel_name">Emulation ist aktiv</string> 5 <string name="emulation_notification_channel_name">Emulation ist aktiv</string>
@@ -25,6 +25,7 @@
25 <string name="back">Zurück</string> 25 <string name="back">Zurück</string>
26 <string name="add_games">Spiele hinzufügen</string> 26 <string name="add_games">Spiele hinzufügen</string>
27 <string name="add_games_description">Spieleverzeichnis auswählen</string> 27 <string name="add_games_description">Spieleverzeichnis auswählen</string>
28 <string name="step_complete">Fertig!</string>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">Spiele</string> 31 <string name="home_games">Spiele</string>
@@ -38,6 +39,7 @@
38 <string name="add_games_warning_description">Spiele werden in der Spieleliste nicht angezeigt, wenn kein Ordner ausgewählt ist.</string> 39 <string name="add_games_warning_description">Spiele werden in der Spieleliste nicht angezeigt, wenn kein Ordner ausgewählt ist.</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">Spiele suchen</string> 41 <string name="home_search_games">Spiele suchen</string>
42 <string name="search_settings">Einstellungen suchen</string>
41 <string name="games_dir_selected">Spieleverzeichnis ausgewählt</string> 43 <string name="games_dir_selected">Spieleverzeichnis ausgewählt</string>
42 <string name="install_prod_keys">prod.keys installieren</string> 44 <string name="install_prod_keys">prod.keys installieren</string>
43 <string name="install_prod_keys_description">Zum Entschlüsseln von Spielen benötigt</string> 45 <string name="install_prod_keys_description">Zum Entschlüsseln von Spielen benötigt</string>
@@ -60,8 +62,11 @@
60 <string name="invalid_keys_file">Ungültige Schlüsseldatei ausgewählt</string> 62 <string name="invalid_keys_file">Ungültige Schlüsseldatei ausgewählt</string>
61 <string name="install_keys_success">Schlüssel erfolgreich installiert</string> 63 <string name="install_keys_success">Schlüssel erfolgreich installiert</string>
62 <string name="reading_keys_failure">Fehler beim Lesen der Schlüssel</string> 64 <string name="reading_keys_failure">Fehler beim Lesen der Schlüssel</string>
65 <string name="install_prod_keys_failure_extension_description">Überprüfen Sie, ob Ihre Schlüsseldatei die Erweiterung \".keys\" hat, und versuchen Sie es erneut.</string>
66 <string name="install_amiibo_keys_failure_extension_description">Überprüfen Sie, ob Ihre Schlüsseldatei die Erweiterung \".bin\" hat, und versuchen Sie es erneut.</string>
63 <string name="invalid_keys_error">Ungültige Schlüssel</string> 67 <string name="invalid_keys_error">Ungültige Schlüssel</string>
64 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 68 <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>
65 <string name="install_gpu_driver">GPU-Treiber installieren</string> 70 <string name="install_gpu_driver">GPU-Treiber installieren</string>
66 <string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string> 71 <string name="install_gpu_driver_description">Alternative Treiber für eventuell bessere Leistung oder Genauigkeit installieren</string>
67 <string name="advanced_settings">Erweiterte Einstellungen</string> 72 <string name="advanced_settings">Erweiterte Einstellungen</string>
@@ -84,7 +89,17 @@
84 <string name="save_file_invalid_zip_structure_description">Der erste Unterordnername muss die Titel-ID des Spiels sein.</string> 89 <string name="save_file_invalid_zip_structure_description">Der erste Unterordnername muss die Titel-ID des Spiels sein.</string>
85 <string name="import_saves">Importieren</string> 90 <string name="import_saves">Importieren</string>
86 <string name="export_saves">Exportieren</string> 91 <string name="export_saves">Exportieren</string>
87 92 <string name="install_firmware">Firmware installieren</string>
93 <string name="install_firmware_description">Die Firmware muss in einem ZIP-Archiv vorliegen und wird zum Booten einiger Spiele benötigt</string>
94 <string name="firmware_installing">Firmware wird installiert</string>
95 <string name="firmware_installed_success">Die Firmware wurde erfolgreich installiert!</string>
96 <string name="firmware_installed_failure">Bei der Firmware installation ist etwas fehlgeschlagen.</string>
97 <string name="share_log">Debug-Logs teilen</string>
98 <string name="share_log_description">Debug-Logs an yuzu zur Untersuchung absenden</string>
99 <string name="share_log_missing">Keine Log-Datei gefunden</string>
100 <string name="install_game_content">Spiel installieren</string>
101 <string name="install_game_content_description">Spiel Update oder DLC installieren</string>
102 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
88 <!-- About screen strings --> 103 <!-- About screen strings -->
89 <string name="gaia_is_not_real">Gaia ist nicht real</string> 104 <string name="gaia_is_not_real">Gaia ist nicht real</string>
90 <string name="copied_to_clipboard">In die Zwischenablage kopiert</string> 105 <string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
@@ -92,7 +107,10 @@
92 <string name="contributors">Beitragende</string> 107 <string name="contributors">Beitragende</string>
93 <string name="contributors_description">Gemacht mit \u2764 vom yuzu Team</string> 108 <string name="contributors_description">Gemacht mit \u2764 vom yuzu Team</string>
94 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 109 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
110 <string name="licenses_description">Projekte, die yuzu für Android möglich machen </string>
95 <string name="build">Build</string> 111 <string name="build">Build</string>
112 <string name="user_data">Nutzerdaten</string>
113 <string name="user_data_export_cancelled">Export abgebrochen</string>
96 <string name="support_link">https://discord.gg/u77vRWY</string> 114 <string name="support_link">https://discord.gg/u77vRWY</string>
97 <string name="website_link">https://yuzu-emu.org/</string> 115 <string name="website_link">https://yuzu-emu.org/</string>
98 <string name="github_link">https://github.com/yuzu-emu</string> 116 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -107,45 +125,39 @@
107 <string name="early_access_updates">Früherer Zugriff auf Updates</string> 125 <string name="early_access_updates">Früherer Zugriff auf Updates</string>
108 <string name="no_manual_installation">Keine manuelle Installation</string> 126 <string name="no_manual_installation">Keine manuelle Installation</string>
109 <string name="prioritized_support">Priorisierte Unterstützung</string> 127 <string name="prioritized_support">Priorisierte Unterstützung</string>
128 <string name="helping_game_preservation">Beitrag zur Erhaltung der Spiele</string>
110 <string name="our_eternal_gratitude">Unsere ewige Dankbarkeit</string> 129 <string name="our_eternal_gratitude">Unsere ewige Dankbarkeit</string>
111 <string name="are_you_interested">Bist du interessiert?</string> 130 <string name="are_you_interested">Bist du interessiert?</string>
112 131
113 <!-- General settings strings --> 132 <!-- General settings strings -->
114 <string name="frame_limit_enable">Geschwindigkeitsbegrenzung aktivieren</string> 133 <string name="frame_limit_enable">Limitierte Geschwindigkeit</string>
115 <string name="frame_limit_enable_description">Wenn aktiviert, wird die Emulationsgeschwindigkeit auf einen Prozentsatz der normalen Geschwindigkeit begrenzt.</string> 134 <string name="frame_limit_enable_description">Limitiert die Geschwindigkeit auf einen von dir festgelegten Prozentsatz.</string>
116 <string name="frame_limit_slider">Geschwindkeitsbegrenzung in Prozent</string> 135 <string name="frame_limit_slider">Geschwindkeitsbegrenzung in Prozent</string>
117 <string name="frame_limit_slider_description">Legt den Prozentsatz der Bergrenzung der Emulationsgeschwindigkeit fest. Mit dem Standardwert von 100% wird die Emulation auf die normale Geschwindigkeit begrenzt. Höhere oder niedrigere Werte erhöhen oder verringern die Geschwindigkeitsbegrenzung.</string> 136 <string name="frame_limit_slider_description">Gibt die prozentuale Geschwindigkeit der Emulation an. 100% sind normal. Werte darüber oder drunter werden die Geschwindigkeit entsprechend verändern.</string>
118 <string name="cpu_accuracy">CPU-Genauigkeit</string> 137 <string name="cpu_accuracy">CPU-Genauigkeit</string>
119
120 <!-- System settings strings --> 138 <!-- System settings strings -->
121 <string name="use_docked_mode">Dock-Modus</string> 139 <string name="use_docked_mode">Gedockter Modus</string>
122 <string name="use_docked_mode_description">Emuliert im Dock-Modus, was die Auflösung verbessert, aber die Leistung senkt.</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>
123 <string name="emulated_region">Emulierte Region</string> 141 <string name="emulated_region">Emulierte Region</string>
124 <string name="emulated_language">Emulierte Sprache</string> 142 <string name="emulated_language">Emulierte Sprache</string>
125 <string name="select_rtc_date">RTC-Datum auswählen</string> 143 <string name="select_rtc_date">RTC-Datum auswählen</string>
126 <string name="select_rtc_time">RTC-Zeit auswählen</string> 144 <string name="select_rtc_time">RTC-Zeit auswählen</string>
127 <string name="use_custom_rtc">Benutzerdefinierte RTC aktivieren</string> 145 <string name="use_custom_rtc">Benutzerdefinierte Echtzeituhr</string>
128 <string name="use_custom_rtc_description">Mit dieser Einstellung kann eine benutzerdefinierte Echtzeituhr unabhängig von der aktuellen Systemzeit verwendet werden.</string>
129 <string name="set_custom_rtc">Benutzerdefinierte RTC einstellen</string>
130
131 <!-- Graphics settings strings --> 146 <!-- Graphics settings strings -->
132 <string name="renderer_api">API</string>
133 <string name="renderer_accuracy">Genauigkeitsstufe</string> 147 <string name="renderer_accuracy">Genauigkeitsstufe</string>
134 <string name="renderer_resolution">Auflösung</string>
135 <string name="renderer_vsync">VSync-Modus</string> 148 <string name="renderer_vsync">VSync-Modus</string>
149 <string name="renderer_screen_layout">Orientierung</string>
136 <string name="renderer_aspect_ratio">Seitenverhältnis</string> 150 <string name="renderer_aspect_ratio">Seitenverhältnis</string>
137 <string name="renderer_scaling_filter">Fensteranpassungsfilter</string> 151 <string name="renderer_scaling_filter">Fensteranpassungsfilter</string>
138 <string name="renderer_anti_aliasing">Kantenglättungs-Methode</string>
139 <string name="renderer_force_max_clock">Maximale Taktfrequenz erzwingen (nur Adreno)</string> 152 <string name="renderer_force_max_clock">Maximale Taktfrequenz erzwingen (nur Adreno)</string>
140 <string name="renderer_force_max_clock_description">Erzwingt den Betrieb der GPU mit der maximal möglichen Taktfrequenz (Temperaturbeschränkungen werden weiterhin angewendet).</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>
141 <string name="renderer_asynchronous_shaders">Asynchrone Shader nutzen</string> 154 <string name="renderer_asynchronous_shaders">Asynchrone Shader nutzen</string>
142 <string name="renderer_asynchronous_shaders_description">Kompiliert Shader asynchron, was Ruckler reduziert, aber zu Glitches führen kann.</string> 155 <!-- Debug settings strings -->
143 <string name="renderer_debug">Grafik-Debugging aktivieren</string> 156 <string name="cpu">CPU</string>
144 <string name="renderer_debug_description">Wenn aktiviert, schaltet die Grafik-API in einen langsameren Debugging-Modus.</string> 157 <string name="cpu_debug_mode">CPU Debugging</string>
145 <string name="use_disk_shader_cache">Nutze Festplatten-Shader-Cache</string> 158 <string name="gpu">GPU</string>
146 <string name="use_disk_shader_cache_description">Ruckeln wird durch das Speichern und Laden von generierten Shadern auf der Festplatte reduziert.</string> 159 <string name="renderer_api">API</string>
147 160 <string name="renderer_debug">Graphik-Debugging</string>
148 <!-- Audio settings strings -->
149 <string name="audio_volume">Lautstärke</string> 161 <string name="audio_volume">Lautstärke</string>
150 <string name="audio_volume_description">Legt die Lautstärke der Audioausgabe fest.</string> 162 <string name="audio_volume_description">Legt die Lautstärke der Audioausgabe fest.</string>
151 163
@@ -154,14 +166,22 @@
154 <string name="ini_saved">Einstellungen gespeichert</string> 166 <string name="ini_saved">Einstellungen gespeichert</string>
155 <string name="gameid_saved">Einstellungen für %1$s gespeichert</string> 167 <string name="gameid_saved">Einstellungen für %1$s gespeichert</string>
156 <string name="error_saving">Fehler beim Speichern von %1$s.ini: %2$s</string> 168 <string name="error_saving">Fehler beim Speichern von %1$s.ini: %2$s</string>
169 <string name="unimplemented_menu">Unimplementiertes Menü</string>
157 <string name="loading">Lädt...</string> 170 <string name="loading">Lädt...</string>
158 <string name="reset_setting_confirmation">Möchtest du diese Einstellung auf den Standardwert zurücksetzen?</string> 171 <string name="reset_setting_confirmation">Möchtest du diese Einstellung auf den Standardwert zurücksetzen?</string>
159 <string name="reset_to_default">Auf Standard zurücksetzen</string> 172 <string name="reset_to_default">Auf Standard zurücksetzen</string>
160 <string name="reset_all_settings">Alle Einstellungen zurücksetzen?</string> 173 <string name="reset_all_settings">Alle Einstellungen zurücksetzen?</string>
161 <string name="reset_all_settings_description">Alle erweiterten Einstellungen werden auf ihren Standardwert zurückgesetzt. Dies kann nicht rückgängig gemacht werden.</string>
162 <string name="settings_reset">Einstellungen zurückgesetzt</string> 174 <string name="settings_reset">Einstellungen zurückgesetzt</string>
163 <string name="close">Schließen</string> 175 <string name="close">Schließen</string>
164 <string name="learn_more">Mehr erfahren</string> 176 <string name="learn_more">Mehr erfahren</string>
177 <string name="auto">Auto</string>
178 <string name="submit">Absenden</string>
179 <string name="string_null">Null</string>
180 <string name="string_import">Importieren</string>
181 <string name="export">Exportieren</string>
182 <string name="export_failed">Export fehlgeschlagen</string>
183 <string name="import_failed">Import fehlgeschlagen</string>
184 <string name="cancelling">Abbrechen</string>
165 185
166 <!-- GPU driver installation --> 186 <!-- GPU driver installation -->
167 <string name="select_gpu_driver">GPU-Treiber auswählen</string> 187 <string name="select_gpu_driver">GPU-Treiber auswählen</string>
@@ -169,6 +189,7 @@
169 <string name="select_gpu_driver_install">Installieren</string> 189 <string name="select_gpu_driver_install">Installieren</string>
170 <string name="select_gpu_driver_default">Standard</string> 190 <string name="select_gpu_driver_default">Standard</string>
171 <string name="select_gpu_driver_use_default">Standard GPU-Treiber wird verwendet</string> 191 <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>
172 <string name="system_gpu_driver">System GPU-Treiber</string> 193 <string name="system_gpu_driver">System GPU-Treiber</string>
173 <string name="installing_driver">Treiber wird installiert...</string> 194 <string name="installing_driver">Treiber wird installiert...</string>
174 195
@@ -179,6 +200,7 @@
179 <string name="preferences_graphics">Grafik</string> 200 <string name="preferences_graphics">Grafik</string>
180 <string name="preferences_audio">Audio</string> 201 <string name="preferences_audio">Audio</string>
181 <string name="preferences_theme">Theme und Farbe</string> 202 <string name="preferences_theme">Theme und Farbe</string>
203 <string name="preferences_debug">Debug</string>
182 204
183 <!-- ROM loading errors --> 205 <!-- ROM loading errors -->
184 <string name="loader_error_encrypted">Das ROM ist verschlüsselt</string> 206 <string name="loader_error_encrypted">Das ROM ist verschlüsselt</string>
@@ -192,22 +214,15 @@
192 <string name="emulation_exit">Emulation beenden</string> 214 <string name="emulation_exit">Emulation beenden</string>
193 <string name="emulation_done">Fertig</string> 215 <string name="emulation_done">Fertig</string>
194 <string name="emulation_fps_counter">FPS Zähler</string> 216 <string name="emulation_fps_counter">FPS Zähler</string>
195 <string name="emulation_toggle_controls">Steuerung umschalten</string>
196 <string name="emulation_rel_stick_center">Relative Stick-Mitte</string>
197 <string name="emulation_dpad_slide">DPad Slide</string>
198 <string name="emulation_haptics">Haptik</string>
199 <string name="emulation_show_overlay">Overlay anzeigen</string>
200 <string name="emulation_toggle_all">Alle umschalten</string> 217 <string name="emulation_toggle_all">Alle umschalten</string>
201 <string name="emulation_control_adjust">Overlay anpassen</string> 218 <string name="emulation_control_adjust">Overlay anpassen</string>
202 <string name="emulation_control_scale">Größe</string> 219 <string name="emulation_control_scale">Größe</string>
203 <string name="emulation_control_opacity">Transparenz</string> 220 <string name="emulation_control_opacity">Transparenz</string>
204 <string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string> 221 <string name="emulation_touch_overlay_reset">Overlay zurücksetzen</string>
205 <string name="emulation_touch_overlay_edit">Overlay bearbeiten</string> 222 <string name="emulation_touch_overlay_edit">Overlay bearbeiten</string>
206 <string name="emulation_pause">Emulation pausieren</string>
207 <string name="emulation_unpause">Emulation fortsetzen</string>
208 <string name="emulation_input_overlay">Overlay-Optionen</string> 223 <string name="emulation_input_overlay">Overlay-Optionen</string>
209 224
210 <string name="load_settings">Lädt Einstellungen...</string> 225 <string name="load_settings">Lade Einstellungen...</string>
211 226
212 <!-- Software keyboard --> 227 <!-- Software keyboard -->
213 <string name="software_keyboard">Software-Tastatur</string> 228 <string name="software_keyboard">Software-Tastatur</string>
@@ -221,7 +236,7 @@
221 <string name="fatal_error">Schwerwiegender Fehler</string> 236 <string name="fatal_error">Schwerwiegender Fehler</string>
222 <string name="fatal_error_message">Ein schwerwiegender Fehler ist aufgetreten. Einzelheiten wurden im Log protokolliert.\nDas Fortsetzen der Emulation kann zu Abstürzen und Bugs führen.</string> 237 <string name="fatal_error_message">Ein schwerwiegender Fehler ist aufgetreten. Einzelheiten wurden im Log protokolliert.\nDas Fortsetzen der Emulation kann zu Abstürzen und Bugs führen.</string>
223 <string name="performance_warning">Das Deaktivieren dieser Einstellung führt zu erheblichen Leistungsverlusten! Für ein optimales Erlebnis wird empfohlen, sie aktiviert zu lassen.</string> 238 <string name="performance_warning">Das Deaktivieren dieser Einstellung führt zu erheblichen Leistungsverlusten! Für ein optimales Erlebnis wird empfohlen, sie aktiviert zu lassen.</string>
224 239 <string name="memory_formatted">%1$s %2$s</string>
225 <!-- Region Names --> 240 <!-- Region Names -->
226 <string name="region_japan">Japan</string> 241 <string name="region_japan">Japan</string>
227 <string name="region_usa">USA</string> 242 <string name="region_usa">USA</string>
@@ -231,6 +246,15 @@
231 <string name="region_korea">Korea</string> 246 <string name="region_korea">Korea</string>
232 <string name="region_taiwan">Taiwan</string> 247 <string name="region_taiwan">Taiwan</string>
233 248
249 <!-- Memory Sizes -->
250 <string name="memory_byte">Byte</string>
251 <string name="memory_kilobyte">KB</string>
252 <string name="memory_megabyte">MB</string>
253 <string name="memory_gigabyte">GB</string>
254 <string name="memory_terabyte">TB</string>
255 <string name="memory_petabyte">PB</string>
256 <string name="memory_exabyte">EB</string>
257
234 <!-- Renderer APIs --> 258 <!-- Renderer APIs -->
235 <string name="renderer_vulkan">Vulkan</string> 259 <string name="renderer_vulkan">Vulkan</string>
236 <string name="renderer_none">Keiner</string> 260 <string name="renderer_none">Keiner</string>
@@ -267,12 +291,15 @@
267 <string name="anti_aliasing_fxaa">FXAA</string> 291 <string name="anti_aliasing_fxaa">FXAA</string>
268 <string name="anti_aliasing_smaa">SMAA</string> 292 <string name="anti_aliasing_smaa">SMAA</string>
269 293
294 <string name="screen_layout_portrait">Portrait</string>
295 <string name="screen_layout_auto">Auto</string>
296
270 <!-- Aspect Ratios --> 297 <!-- Aspect Ratios -->
271 <string name="ratio_default">Standard (16:9)</string> 298 <string name="ratio_default">Standard (16:9)</string>
272 <string name="ratio_force_four_three">4:3 erzwingen</string> 299 <string name="ratio_force_four_three">4:3 erzwingen</string>
273 <string name="ratio_force_twenty_one_nine">21:9 erzwingen</string> 300 <string name="ratio_force_twenty_one_nine">21:9 erzwingen</string>
274 <string name="ratio_force_sixteen_ten">Erzwinge 16:10</string> 301 <string name="ratio_force_sixteen_ten">Erzwinge 16:10</string>
275 <string name="ratio_stretch">Auf Fenster anpassen</string> 302 <string name="ratio_stretch">Auf Bildschirmgröße anpsassen</string>
276 303
277 <!-- CPU Accuracy --> 304 <!-- CPU Accuracy -->
278 <string name="cpu_accuracy_accurate">Akkurat</string> 305 <string name="cpu_accuracy_accurate">Akkurat</string>
@@ -280,9 +307,9 @@
280 <string name="cpu_accuracy_paranoid">Paranoid (Langsam)</string> 307 <string name="cpu_accuracy_paranoid">Paranoid (Langsam)</string>
281 308
282 <!-- Gamepad Buttons --> 309 <!-- Gamepad Buttons -->
283 <string name="gamepad_d_pad">Steuerkreuz</string> 310 <string name="gamepad_d_pad">D-Pad</string>
284 <string name="gamepad_left_stick">Linker Analogstick</string> 311 <string name="gamepad_left_stick">Linker Stick</string>
285 <string name="gamepad_right_stick">Rechter Analogstick</string> 312 <string name="gamepad_right_stick">Rechter Stick</string>
286 <string name="gamepad_home">Home</string> 313 <string name="gamepad_home">Home</string>
287 <string name="gamepad_screenshot">Screenshot</string> 314 <string name="gamepad_screenshot">Screenshot</string>
288 315
@@ -291,18 +318,30 @@
291 <string name="building_shaders">Shader werden erstellt</string> 318 <string name="building_shaders">Shader werden erstellt</string>
292 319
293 <!-- Theme options --> 320 <!-- Theme options -->
294 <string name="change_app_theme">App-Theme ändern</string> 321 <string name="change_app_theme">App-Thema ändern</string>
295 <string name="theme_default">Standard</string> 322 <string name="theme_default">Standard</string>
296 <string name="theme_material_you">Material You</string> 323 <string name="theme_material_you">Material You</string>
297 324
298 <!-- Theme Modes --> 325 <!-- Theme Modes -->
299 <string name="change_theme_mode">Theme-Modus ändern</string> 326 <string name="change_theme_mode">Themen-Modus ändern</string>
300 <string name="theme_mode_follow_system">System folgen</string> 327 <string name="theme_mode_follow_system">System folgen</string>
301 <string name="theme_mode_light">Hell</string> 328 <string name="theme_mode_light">Hell</string>
302 <string name="theme_mode_dark">Dunkel</string> 329 <string name="theme_mode_dark">Dunkel</string>
303 330
331 <!-- Audio output engines -->
332 <string name="cubeb">cubeb</string>
333
304 <!-- Black backgrounds theme --> 334 <!-- Black backgrounds theme -->
305 <string name="use_black_backgrounds">Schwarze Hintergünde verwenden</string> 335 <string name="use_black_backgrounds">Schwarze Hintergründe</string>
306 <string name="use_black_backgrounds_description">Bei Verwendung des dunklen Themes, schwarze Hintergründe verwenden.</string> 336 <string name="use_black_backgrounds_description">Bei Verwendung des dunklen Themes, schwarze Hintergründe verwenden.</string>
307 337
308</resources> 338 <!-- Picture-In-Picture -->
339 <string name="picture_in_picture">Bild im Bild</string>
340 <string name="pause">Pause</string>
341 <string name="mute">Stummschalten</string>
342 <string name="unmute">Ton aktivieren</string>
343
344 <!-- Licenses screen strings -->
345 <string name="licenses">Lizenzen</string>
346 <string name="license_fidelityfx_fsr_description">Hochwertiges Upscaling von AMD</string>
347 </resources>
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 e5bdd5889..103ac6e65 100644
--- a/src/android/app/src/main/res/values-es/strings.xml
+++ b/src/android/app/src/main/res/values-es/strings.xml
@@ -1,7 +1,7 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Este software ejecuta juegos para la videoconsola Nintendo Switch. Los videojuegos o keys 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 esta ejecutándose</string>
@@ -25,6 +25,7 @@
25 <string name="back">Atrás</string> 25 <string name="back">Atrás</string>
26 <string name="add_games">Añadir Juegos</string> 26 <string name="add_games">Añadir Juegos</string>
27 <string name="add_games_description">Selecciona la carpeta de juegos</string> 27 <string name="add_games_description">Selecciona la carpeta de juegos</string>
28 <string name="step_complete">¡Completado!</string>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">Juegos</string> 31 <string name="home_games">Juegos</string>
@@ -37,7 +38,8 @@
37 <string name="add_games_warning">¿Omitir la selección de la carpeta de juegos?</string> 38 <string name="add_games_warning">¿Omitir la selección de la carpeta de juegos?</string>
38 <string name="add_games_warning_description">No se mostrará ningún juego si no se ha seleccionado una 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>
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">Buscar Juegos</string> 41 <string name="home_search_games">Buscar juegos</string>
42 <string name="search_settings">Buscar configuración</string>
41 <string name="games_dir_selected">Directorio de juegos seleccionado</string> 43 <string name="games_dir_selected">Directorio de juegos seleccionado</string>
42 <string name="install_prod_keys">Instalar prod.keys</string> 44 <string name="install_prod_keys">Instalar prod.keys</string>
43 <string name="install_prod_keys_description">Requerido para descifrar juegos</string> 45 <string name="install_prod_keys_description">Requerido para descifrar juegos</string>
@@ -58,15 +60,18 @@
58 <string name="warning_cancel">Cancelar</string> 60 <string name="warning_cancel">Cancelar</string>
59 <string name="install_amiibo_keys">Instalar clave de Amiiboo</string> 61 <string name="install_amiibo_keys">Instalar clave de Amiiboo</string>
60 <string name="install_amiibo_keys_description">Necesario para usar Amiibo en el juego</string> 62 <string name="install_amiibo_keys_description">Necesario para usar Amiibo en el juego</string>
61 <string name="invalid_keys_file">Archivo de claves inválido seleccionado</string> 63 <string name="invalid_keys_file">Archivo de claves seleccionado inválido</string>
62 <string name="install_keys_success">Claves instaladas correctamente</string> 64 <string name="install_keys_success">Claves instaladas correctamente</string>
63 <string name="reading_keys_failure">Error al leer las claves de cifrado</string> 65 <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_amiibo_keys_failure_extension_description">Compruebe que el archivo de claves tenga una extensión .bin y pruebe otra vez.</string>
64 <string name="invalid_keys_error">Claves de cifrado no válidas</string> 68 <string name="invalid_keys_error">Claves de cifrado no válidas</string>
65 <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>
66 <string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string> 70 <string name="install_keys_failure_description">El archivo seleccionado es incorrecto o está corrupto. Vuelva a redumpear sus claves.</string>
67 <string name="install_gpu_driver">Instalar driver de GPU</string> 71 <string name="install_gpu_driver">Instalar driver de GPU</string>
68 <string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string> 72 <string name="install_gpu_driver_description">Instale drivers alternativos para obtener un rendimiento o una precisión potencialmente mejores</string>
69 <string name="advanced_settings">Opciones avanzadas</string> 73 <string name="advanced_settings">Opciones avanzadas</string>
74 <string name="advanced_settings_game">Configuración avanzada: %1$s</string>
70 <string name="settings_description">Configurar las opciones del emulador</string> 75 <string name="settings_description">Configurar las opciones del emulador</string>
71 <string name="search_recently_played">Jugado recientemente</string> 76 <string name="search_recently_played">Jugado recientemente</string>
72 <string name="search_recently_added">Añadido recientemente</string> 77 <string name="search_recently_added">Añadido recientemente</string>
@@ -86,6 +91,33 @@
86 <string name="save_file_invalid_zip_structure_description">El nombre de la primera subcarpeta debe ser el Title ID del juego.</string> 91 <string name="save_file_invalid_zip_structure_description">El nombre de la primera subcarpeta debe ser el Title ID del juego.</string>
87 <string name="import_saves">Importar</string> 92 <string name="import_saves">Importar</string>
88 <string name="export_saves">Exportar</string> 93 <string name="export_saves">Exportar</string>
94 <string name="install_firmware">Instalar firmware</string>
95 <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>
97 <string name="firmware_installed_success">Firmware instalado con éxito</string>
98 <string name="firmware_installed_failure">Falló 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>
100 <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>
102 <string name="share_log_missing">No se encontró ningún archivo de registro</string>
103 <string name="install_game_content">Instalar contenido de juego</string>
104 <string name="install_game_content_description">Instalar actualizaciones o DLC</string>
105 <string name="installing_game_content">Instalando contenido...</string>
106 <string name="install_game_content_failure">Error instalando archivo(s) a la NAND</string>
107 <string name="install_game_content_failure_description">Asegúrese de que el/los contenido(s) son válidos y que el archivo prod.keys esté instalado.</string>
108 <string name="install_game_content_failure_base">La instalación de los juegos base no está permitida para así evitar posibles conflictos.</string>
109 <string name="install_game_content_failure_file_extension">Sólo hay soporte para el contenido en NSP y XCI. Asegúrese de que el/los contenido(s) son válidos.</string>
110 <string name="install_game_content_failed_count">%1$d error(es) de instalación</string>
111 <string name="install_game_content_success">Contenido(s) de juego instalado/s con éxito</string>
112 <string name="install_game_content_success_install">%1$d instalado con éxito</string>
113 <string name="install_game_content_success_overwrite">%1$d sobreescrito con éxito</string>
114 <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 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>
117 <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>
119 <string name="share_save_file">Compartir archivo de guardado</string>
120 <string name="export_save_failed">La exportación del guardado falló</string>
89 121
90 <!-- About screen strings --> 122 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia no es real</string> 123 <string name="gaia_is_not_real">Gaia no es real</string>
@@ -94,7 +126,18 @@
94 <string name="contributors">Contribuidores</string> 126 <string name="contributors">Contribuidores</string>
95 <string name="contributors_description">Hecho con \u2764 del equipo yuzu</string> 127 <string name="contributors_description">Hecho con \u2764 del equipo yuzu</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">Proyectos que hacen que yuzu para Android sea una realidad</string>
97 <string name="build">Versión</string> 130 <string name="build">Versión</string>
131 <string name="user_data">Datos de usuario</string>
132 <string name="user_data_description">Importa/exporta todos los datos de usuario.\n\nCuando se importen los datos de usuario, ¡los demás datos de usuario existentes serán borrados!</string>
133 <string name="exporting_user_data">Exportando datos de usuario...</string>
134 <string name="importing_user_data">Importando datos de usuario...</string>
135 <string name="import_user_data">Importar datos de usuario</string>
136 <string name="invalid_yuzu_backup">Backup de válido</string>
137 <string name="user_data_export_success">Datos de usuario exportados con éxito</string>
138 <string name="user_data_import_success">Datos de usuario importados con éxito</string>
139 <string name="user_data_export_cancelled">Exportación cancelada</string>
140 <string name="user_data_import_failed_description">Asegúrese de que las carpetas de datos de usuario estén en la raíz de la carpeta del zip y contengan un archivo config en config/config.ini e inténtelo de nuevo.</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 141 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 142 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 143 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -114,41 +157,53 @@
114 <string name="are_you_interested">¿Estás interesado?</string> 157 <string name="are_you_interested">¿Estás interesado?</string>
115 158
116 <!-- General settings strings --> 159 <!-- General settings strings -->
117 <string name="frame_limit_enable">Activar limite de velocidad</string> 160 <string name="frame_limit_enable">Limitar velocidad</string>
118 <string name="frame_limit_enable_description">Cuando está habilitado, la velocidad de emulación se limitará a un porcentaje específico de la velocidad normal.</string> 161 <string name="frame_limit_enable_description">Limita la velocidad de emulación a un porcentaje específico de la velocidad normal.</string>
119 <string name="frame_limit_slider">Limitar porcentaje de velocidad</string> 162 <string name="frame_limit_slider">Limitar porcentaje de velocidad</string>
120 <string name="frame_limit_slider_description">Especifica el porcentaje para limitar la velocidad de emulación. Con el valor predeterminado del 100 %, la emulación se limitará a la velocidad normal. Valores más altos o más bajos aumentarán o disminuirán el límite 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>
121 <string name="cpu_accuracy">Precisión de CPU</string> 164 <string name="cpu_accuracy">Precisión de CPU</string>
165 <string name="value_with_units">%1$s%2$s</string>
122 166
123 <!-- System settings strings --> 167 <!-- System settings strings -->
124 <string name="use_docked_mode">Modo sobremesa</string> 168 <string name="use_docked_mode">Modo Sobremesa</string>
125 <string name="use_docked_mode_description">Emula en modo sobremesa, lo que aumenta la resolución perjudicando el rendimiento.</string> 169 <string name="use_docked_mode_description">Incrementa la resolución al coste de reducir el rendimiento. El Modo Portátil es usado cuando está desactivado, reduciendo la resolución y mejorando así el rendimiento.</string>
126 <string name="emulated_region">Región emulada</string> 170 <string name="emulated_region">Región emulada</string>
127 <string name="emulated_language">Idioma emulado</string> 171 <string name="emulated_language">Idioma emulado</string>
128 <string name="select_rtc_date">Seleccionar Fecha RTC</string> 172 <string name="select_rtc_date">Seleccionar fecha RTC</string>
129 <string name="select_rtc_time">Seleccionar Tiempo RTC</string> 173 <string name="select_rtc_time">Seleccionar tiempo RTC</string>
130 <string name="use_custom_rtc">Habilitar RTC Personalizado</string> 174 <string name="use_custom_rtc">RTC personalizado</string>
131 <string name="use_custom_rtc_description">Esta configuración le permite configurar un reloj de tiempo real personalizado diferente a la hora actual de su sistema</string> 175 <string name="use_custom_rtc_description">Te permite tener un reloj personalizado en tiempo real diferente del tiempo del propio sistema.</string>
132 <string name="set_custom_rtc">Establecer RTC Personalizado</string> 176 <string name="set_custom_rtc">Configurar RTC personalizado</string>
133 177
134 <!-- Graphics settings strings --> 178 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Nivel de precisión</string> 179 <string name="renderer_accuracy">Nivel de precisión</string>
137 <string name="renderer_resolution">Resolución</string> 180 <string name="renderer_resolution">Resolución (Portátil/Sobremesa)</string>
138 <string name="renderer_vsync">Modo VSync</string> 181 <string name="renderer_vsync">Modo VSync</string>
182 <string name="renderer_screen_layout">Orientación</string>
139 <string name="renderer_aspect_ratio">Relación de aspecto</string> 183 <string name="renderer_aspect_ratio">Relación de aspecto</string>
140 <string name="renderer_scaling_filter">Filtro de adaptación de ventana</string> 184 <string name="renderer_scaling_filter">Filtro de adaptación de ventana</string>
141 <string name="renderer_anti_aliasing">Metodo Anti Aliasing</string> 185 <string name="renderer_anti_aliasing">Método anti-aliasing</string>
142 <string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string> 186 <string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string>
143 <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> 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>
144 <string name="renderer_asynchronous_shaders">Usar shaders asíncronos</string> 188 <string name="renderer_asynchronous_shaders">Usar shaders asíncronos</string>
145 <string name="renderer_asynchronous_shaders_description">Compila shaders de forma asincrónica, lo que reducirá los parones pero puede introducir fallos.</string> 189 <string name="renderer_asynchronous_shaders_description">Compila shaders de manera asíncrona, reduciendo los parones, pero puede introducir fallos.</string>
146 <string name="renderer_debug">Habilitar la depuración de gráficos</string> 190 <string name="renderer_reactive_flushing">Usar limpieza reactiva</string>
147 <string name="renderer_debug_description">Cuando esté marcado, la API de gráficos entra en un modo de depuración más lento.</string> 191 <string name="renderer_reactive_flushing_description">Mejora la precisión de renderizado en algunos juegos, pero reduce el rendimiento.</string>
148 <string name="use_disk_shader_cache">Usar caché de shaders en disco</string> 192 <string name="use_disk_shader_cache">Caché de shaders en disco</string>
149 <string name="use_disk_shader_cache_description">Reduzca los parones almacenando y cargando shaders generados en el disco.</string> 193 <string name="use_disk_shader_cache_description">Reduce los parones almacenando y cargando shaders generados.</string>
194
195 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">Depuración de CPU</string>
198 <string name="cpu_debug_mode_description">Pone la CPU en un modo de depuración lento.</string>
199 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string>
201 <string name="renderer_debug">Depuración de gráficos</string>
202 <string name="renderer_debug_description">Configura la API gráfica a un modo de depuración lento.</string>
203 <string name="fastmem">Fastmem</string>
150 204
151 <!-- Audio settings strings --> 205 <!-- Audio settings strings -->
206 <string name="audio_output_engine">Motor de salida</string>
152 <string name="audio_volume">Volumen</string> 207 <string name="audio_volume">Volumen</string>
153 <string name="audio_volume_description">Especifica el volumen de la salida de audio.</string> 208 <string name="audio_volume_description">Especifica el volumen de la salida de audio.</string>
154 209
@@ -157,14 +212,24 @@
157 <string name="ini_saved">Configuración guardada</string> 212 <string name="ini_saved">Configuración guardada</string>
158 <string name="gameid_saved">Configuración guardada para %1$s</string> 213 <string name="gameid_saved">Configuración guardada para %1$s</string>
159 <string name="error_saving">Error guardando %1$s.ini: %2$s</string> 214 <string name="error_saving">Error guardando %1$s.ini: %2$s</string>
215 <string name="unimplemented_menu">Menú sin implementar</string>
160 <string name="loading">Cargando...</string> 216 <string name="loading">Cargando...</string>
217 <string name="shutting_down">Saliendo...</string>
161 <string name="reset_setting_confirmation">¿Desea restablecer esta configuración a su valor predeterminado?</string> 218 <string name="reset_setting_confirmation">¿Desea restablecer esta configuración a su valor predeterminado?</string>
162 <string name="reset_to_default">Restablecer a predeterminado</string> 219 <string name="reset_to_default">Restablecer a predeterminado</string>
163 <string name="reset_all_settings">¿Restablecer todas las configuraciones?</string> 220 <string name="reset_all_settings">¿Restablecer todas las configuraciones?</string>
164 <string name="reset_all_settings_description">Todas las configuraciones avanzadas se restablecerán a su configuración predeterminada. Esto no se puede deshacer.</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>
165 <string name="settings_reset">Reiniciar la configuracion</string> 222 <string name="settings_reset">Reiniciar la configuracion</string>
166 <string name="close">Cerrar</string> 223 <string name="close">Cerrar</string>
167 <string name="learn_more">Más información</string> 224 <string name="learn_more">Saber más</string>
225 <string name="auto">Auto</string>
226 <string name="submit">Enviar</string>
227 <string name="string_null">Null</string>
228 <string name="string_import">Importar</string>
229 <string name="export">Exportar</string>
230 <string name="export_failed">La exportación falló</string>
231 <string name="import_failed">La importación falló</string>
232 <string name="cancelling">Cancelando</string>
168 233
169 <!-- GPU driver installation --> 234 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Seleccionar driver GPU</string> 235 <string name="select_gpu_driver">Seleccionar driver GPU</string>
@@ -172,6 +237,7 @@
172 <string name="select_gpu_driver_install">Instalar</string> 237 <string name="select_gpu_driver_install">Instalar</string>
173 <string name="select_gpu_driver_default">Predeterminado</string> 238 <string name="select_gpu_driver_default">Predeterminado</string>
174 <string name="select_gpu_driver_use_default">Usando el driver de GPU por defecto </string> 239 <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>
175 <string name="system_gpu_driver">Driver GPU del sistema</string> 241 <string name="system_gpu_driver">Driver GPU del sistema</string>
176 <string name="installing_driver">Instalando driver...</string> 242 <string name="installing_driver">Instalando driver...</string>
177 243
@@ -182,10 +248,11 @@
182 <string name="preferences_graphics">Gráficos</string> 248 <string name="preferences_graphics">Gráficos</string>
183 <string name="preferences_audio">Audio</string> 249 <string name="preferences_audio">Audio</string>
184 <string name="preferences_theme">Tema y color</string> 250 <string name="preferences_theme">Tema y color</string>
251 <string name="preferences_debug">Depuración</string>
185 252
186 <!-- ROM loading errors --> 253 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">Su ROM está encriptada</string> 254 <string name="loader_error_encrypted">Su ROM está encriptada</string>
188 <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-cartridge-games\">cartuchos de juegos</a> o <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">titulos instalados</a>.]]></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>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[Por favor, compruebe que su archivo <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> está instalado, para que los juegos sean descifrados.]]></string> 256 <string name="loader_error_encrypted_keys_description"><![CDATA[Por favor, compruebe que su archivo <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> está instalado, para que los juegos sean descifrados.]]></string>
190 <string name="loader_error_video_core">Ocurrió un error al inicializar el núcleo de video, posiblemente debido a una incompatibilidad con el driver seleccionado</string> 257 <string name="loader_error_video_core">Ocurrió un error al inicializar el núcleo de video, posiblemente debido a una incompatibilidad con el driver seleccionado</string>
191 <string name="loader_error_video_core_description">Esto suele deberse a un driver de GPU incompatible. La instalación de un controlador de GPU personalizado puede resolver este problema.</string> 258 <string name="loader_error_video_core_description">Esto suele deberse a un driver de GPU incompatible. La instalación de un controlador de GPU personalizado puede resolver este problema.</string>
@@ -196,25 +263,25 @@
196 <string name="emulation_exit">Salir de la emulación</string> 263 <string name="emulation_exit">Salir de la emulación</string>
197 <string name="emulation_done">Hecho</string> 264 <string name="emulation_done">Hecho</string>
198 <string name="emulation_fps_counter">Contador de FPS</string> 265 <string name="emulation_fps_counter">Contador de FPS</string>
199 <string name="emulation_toggle_controls">Alternar Controles</string> 266 <string name="emulation_toggle_controls">Alternar controles</string>
200 <string name="emulation_rel_stick_center">Centro Relativo del Stick</string> 267 <string name="emulation_rel_stick_center">Centro relativo del stick</string>
201 <string name="emulation_dpad_slide">Deslizamiento de la Cruceta</string> 268 <string name="emulation_dpad_slide">Deslizamiento de la cruceta</string>
202 <string name="emulation_haptics">Hápticos</string> 269 <string name="emulation_haptics">Toques hápticos</string>
203 <string name="emulation_show_overlay">Mostrar pantalla</string> 270 <string name="emulation_show_overlay">Mostrar overlay</string>
204 <string name="emulation_toggle_all">Alternar Todo</string> 271 <string name="emulation_toggle_all">Alternar todo</string>
205 <string name="emulation_control_adjust">Ajustar pantalla</string> 272 <string name="emulation_control_adjust">Ajustar overlay</string>
206 <string name="emulation_control_scale">Escala</string> 273 <string name="emulation_control_scale">Escala</string>
207 <string name="emulation_control_opacity">Opacidad</string> 274 <string name="emulation_control_opacity">Opacidad</string>
208 <string name="emulation_touch_overlay_reset">Reiniciar pantalla</string> 275 <string name="emulation_touch_overlay_reset">Reiniciar overlay</string>
209 <string name="emulation_touch_overlay_edit">Editar pantalla</string> 276 <string name="emulation_touch_overlay_edit">Editar overlay</string>
210 <string name="emulation_pause">Pausar Emulación</string> 277 <string name="emulation_pause">Pausar emulación</string>
211 <string name="emulation_unpause">Reanudar Emulación</string> 278 <string name="emulation_unpause">Despausar emulación</string>
212 <string name="emulation_input_overlay">Opciones de pantalla </string> 279 <string name="emulation_input_overlay">Opciones de overlay</string>
213 280
214 <string name="load_settings">Cargando configuración...</string> 281 <string name="load_settings">Cargando configuración...</string>
215 282
216 <!-- Software keyboard --> 283 <!-- Software keyboard -->
217 <string name="software_keyboard">Software del teclado</string> 284 <string name="software_keyboard">Teclado de software</string>
218 285
219 <!-- Errors and warnings --> 286 <!-- Errors and warnings -->
220 <string name="abort_button">Abortar</string> 287 <string name="abort_button">Abortar</string>
@@ -226,6 +293,9 @@
226 <string name="fatal_error">Error fatal</string> 293 <string name="fatal_error">Error fatal</string>
227 <string name="fatal_error_message">Ocurrió un error fatal. Consulte el registro para obtener más detalles.\nContinuar con la emulación puede provocar bloqueos y errores.</string> 294 <string name="fatal_error_message">Ocurrió un error fatal. Consulte el registro para obtener más detalles.\nContinuar con la emulación puede provocar bloqueos y errores.</string>
228 <string name="performance_warning">¡Desactivar esta configuración reducirá significativamente el rendimiento de la emulación! Para obtener la mejor experiencia, se recomienda dejar esta configuración habilitada.</string> 295 <string name="performance_warning">¡Desactivar esta configuración reducirá significativamente el rendimiento de la emulación! Para obtener la mejor experiencia, se recomienda dejar esta configuración habilitada.</string>
296 <string name="device_memory_inadequate">RAM de dispositivo: %1$s\nRecomendado: %2$s</string>
297 <string name="memory_formatted">%1$s %2$s</string>
298 <string name="no_game_present">¡No hay ningún juego ejecutable presente!</string>
229 299
230 <!-- Region Names --> 300 <!-- Region Names -->
231 <string name="region_japan">Japón</string> 301 <string name="region_japan">Japón</string>
@@ -236,7 +306,14 @@
236 <string name="region_korea">Corea</string> 306 <string name="region_korea">Corea</string>
237 <string name="region_taiwan">Taiwán</string> 307 <string name="region_taiwan">Taiwán</string>
238 308
239 <!-- Language Names --> 309 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string>
311 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string>
314 <string name="memory_terabyte">TB</string>
315 <string name="memory_petabyte">PB</string>
316 <string name="memory_exabyte">EB</string>
240 317
241 <!-- Renderer APIs --> 318 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 319 <string name="renderer_vulkan">Vulkan</string>
@@ -274,6 +351,11 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 351 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 352 <string name="anti_aliasing_smaa">SMAA</string>
276 353
354 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">Paisaje</string>
356 <string name="screen_layout_portrait">Retrato</string>
357 <string name="screen_layout_auto">Auto</string>
358
277 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
278 <string name="ratio_default">Predeterminado (16:9)</string> 360 <string name="ratio_default">Predeterminado (16:9)</string>
279 <string name="ratio_force_four_three">Forzar 4:3</string> 361 <string name="ratio_force_four_three">Forzar 4:3</string>
@@ -298,7 +380,7 @@
298 <string name="building_shaders">Construyendo shaders</string> 380 <string name="building_shaders">Construyendo shaders</string>
299 381
300 <!-- Theme options --> 382 <!-- Theme options -->
301 <string name="change_app_theme">Cambiar Tema</string> 383 <string name="change_app_theme">Cambiar tema</string>
302 <string name="theme_default">Predeterminado</string> 384 <string name="theme_default">Predeterminado</string>
303 <string name="theme_material_you">Material You</string> 385 <string name="theme_material_you">Material You</string>
304 386
@@ -308,8 +390,22 @@
308 <string name="theme_mode_light">Claro</string> 390 <string name="theme_mode_light">Claro</string>
309 <string name="theme_mode_dark">Oscuro</string> 391 <string name="theme_mode_dark">Oscuro</string>
310 392
393 <!-- Audio output engines -->
394 <string name="cubeb">cubeb</string>
395
311 <!-- Black backgrounds theme --> 396 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">Usar Fondos Negros</string> 397 <string name="use_black_backgrounds">Fondos oscuros</string>
313 <string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string> 398 <string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string>
314 399
315</resources> 400 <!-- Picture-In-Picture -->
401 <string name="picture_in_picture">Picture in Picture</string>
402 <string name="picture_in_picture_description">Minimizar ventana cuando esté en segundo plano</string>
403 <string name="pause">Pausar</string>
404 <string name="play">Jugar</string>
405 <string name="mute">Mutear</string>
406 <string name="unmute">Desmutear</string>
407
408 <!-- Licenses screen strings -->
409 <string name="licenses">Licencias</string>
410 <string name="license_fidelityfx_fsr_description">Upscaling de alta calidad de AMD</string>
411 </resources>
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 1e02828aa..5a827c50b 100644
--- a/src/android/app/src/main/res/values-fr/strings.xml
+++ b/src/android/app/src/main/res/values-fr/strings.xml
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Ce logiciel exécutera des jeux pour la console de jeu Nintendo Switch. Aucun jeux ou clés n\'est inclus.&lt;br /&gt;&lt;br /&gt;Avant de commencer, veuillez localiser votre fichier <![CDATA[<b> prod.keys </b>]]> sur le stockage de votre appareil.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">En savoir plus</a>]]></string> 4 <string name="app_disclaimer">Ce logiciel exécutera des jeux pour la console de jeu Nintendo Switch. Aucun jeux ou clés n\'est inclus.&lt;br /&gt;&lt;br /&gt;Avant de commencer, veuillez localiser votre fichier <![CDATA[<b> prod.keys </b>]]> sur le stockage de votre appareil.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">En savoir plus</a>]]></string>
5 <string name="emulation_notification_channel_name">L\'émulation est active</string> 5 <string name="emulation_notification_channel_name">L\'émulation est active</string>
@@ -19,12 +19,13 @@
19 <string name="games">Jeux</string> 19 <string name="games">Jeux</string>
20 <string name="games_description">Sélectionnez votre dossier &lt;b>de Jeux&lt;/b> avec le bouton ci-dessous.</string> 20 <string name="games_description">Sélectionnez votre dossier &lt;b>de Jeux&lt;/b> avec le bouton ci-dessous.</string>
21 <string name="done">Terminé</string> 21 <string name="done">Terminé</string>
22 <string name="done_description">Vous êtes prêt.\nProfitez de vos jeux !</string> 22 <string name="done_description">Vous êtes prêt.\nProfitez de vos jeux !</string>
23 <string name="text_continue">Continuer</string> 23 <string name="text_continue">Continuer</string>
24 <string name="next">Suivant</string> 24 <string name="next">Suivant</string>
25 <string name="back">Retour</string> 25 <string name="back">Retour</string>
26 <string name="add_games">Ajouter des jeux</string> 26 <string name="add_games">Ajouter des jeux</string>
27 <string name="add_games_description">Sélectionner votre dossier de jeux</string> 27 <string name="add_games_description">Sélectionner le dossier des jeux</string>
28 <string name="step_complete">Terminé !</string>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">Jeux</string> 31 <string name="home_games">Jeux</string>
@@ -32,12 +33,13 @@
32 <string name="home_settings">Paramètres</string> 33 <string name="home_settings">Paramètres</string>
33 <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>
34 <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>
35 <string name="select_games_folder">Sélectionner le dossier de jeux</string> 36 <string name="select_games_folder">Sélectionner le dossier des jeux</string>
36 <string name="select_games_folder_description">Permet à yuzu de remplir la liste des jeux</string> 37 <string name="select_games_folder_description">Permet à yuzu de remplir la liste des jeux</string>
37 <string name="add_games_warning">Ne pas sélectionner le dossier des jeux ?</string> 38 <string name="add_games_warning">Ne pas sélectionner le dossier des jeux ?</string>
38 <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> 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>
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">Rechercher des jeux</string> 41 <string name="home_search_games">Rechercher des jeux</string>
42 <string name="search_settings">Rechercher un paramètre</string>
41 <string name="games_dir_selected">Répertoire de jeux sélectionné</string> 43 <string name="games_dir_selected">Répertoire de jeux sélectionné</string>
42 <string name="install_prod_keys">Installer prod.keys</string> 44 <string name="install_prod_keys">Installer prod.keys</string>
43 <string name="install_prod_keys_description">Nécessaire pour décrypter les jeux commerciaux.</string> 45 <string name="install_prod_keys_description">Nécessaire pour décrypter les jeux commerciaux.</string>
@@ -46,7 +48,7 @@
46 <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>
47 <string name="notifications">Notifications</string> 49 <string name="notifications">Notifications</string>
48 <string name="notifications_description">Accordez l\'autorisation de notification avec le bouton ci-dessous.</string> 50 <string name="notifications_description">Accordez l\'autorisation de notification avec le bouton ci-dessous.</string>
49 <string name="give_permission">Donner la permission</string> 51 <string name="give_permission">Accorder la permission</string>
50 <string name="notification_warning">Ne pas accorder la permission de notification ?</string> 52 <string name="notification_warning">Ne pas accorder la permission de notification ?</string>
51 <string name="notification_warning_description">yuzu ne pourra pas vous communiquer d\'informations importantes.</string> 53 <string name="notification_warning_description">yuzu ne pourra pas vous communiquer d\'informations importantes.</string>
52 <string name="permission_denied">Permission refusée</string> 54 <string name="permission_denied">Permission refusée</string>
@@ -61,12 +63,15 @@
61 <string name="invalid_keys_file">Fichier de clés sélectionné invalide</string> 63 <string name="invalid_keys_file">Fichier de clés sélectionné invalide</string>
62 <string name="install_keys_success">Clés installées avec succès</string> 64 <string name="install_keys_success">Clés installées avec succès</string>
63 <string name="reading_keys_failure">Erreur lors de la lecture des clés de chiffrement</string> 65 <string name="reading_keys_failure">Erreur lors de la lecture des clés de chiffrement</string>
66 <string name="install_prod_keys_failure_extension_description">Vérifiez que votre fichier de clés a une extension .keys et réessayez.</string>
67 <string name="install_amiibo_keys_failure_extension_description">Vérifiez que votre fichier de clés a une extension .bin et réessayez.</string>
64 <string name="invalid_keys_error">Clés de chiffrement invalides</string> 68 <string name="invalid_keys_error">Clés de chiffrement invalides</string>
65 <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>
66 <string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string> 70 <string name="install_keys_failure_description">Le fichier sélectionné est incorrect ou corrompu. Veuillez dumper à nouveau vos clés.</string>
67 <string name="install_gpu_driver">Installer le pilote du GPU</string> 71 <string name="install_gpu_driver">Installer le pilote du GPU</string>
68 <string name="install_gpu_driver_description">Installez des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string> 72 <string name="install_gpu_driver_description">Installer des pilotes alternatifs pour des performances ou une précision potentiellement meilleures</string>
69 <string name="advanced_settings">Paramètres avancés</string> 73 <string name="advanced_settings">Paramètres avancés</string>
74 <string name="advanced_settings_game">Paramètres avancés : %1$s</string>
70 <string name="settings_description">Configurer les paramètres de l\'émulateur</string> 75 <string name="settings_description">Configurer les paramètres de l\'émulateur</string>
71 <string name="search_recently_played">Joué récemment</string> 76 <string name="search_recently_played">Joué récemment</string>
72 <string name="search_recently_added">Ajouté récemment</string> 77 <string name="search_recently_added">Ajouté récemment</string>
@@ -86,6 +91,33 @@
86 <string name="save_file_invalid_zip_structure_description">Le nom du premier sous-dossier doit être l\'identifiant du titre du jeu.</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>
87 <string name="import_saves">Importer</string> 92 <string name="import_saves">Importer</string>
88 <string name="export_saves">Exporter</string> 93 <string name="export_saves">Exporter</string>
94 <string name="install_firmware">Installer le firmware</string>
95 <string name="install_firmware_description">Le firmware doit être dans une archive ZIP et est nécessaire pour démarrer certains jeux.</string>
96 <string name="firmware_installing">Installation du firmware</string>
97 <string name="firmware_installed_success">Firmware installé avec succès</string>
98 <string name="firmware_installed_failure">L\'installation du firmware a échoué</string>
99 <string name="firmware_installed_failure_description">Assurez-vous que les fichiers NCA du firmware se trouvent à la racine du fichier ZIP, puis réessayez.</string>
100 <string name="share_log">Partager les logs de débogage</string>
101 <string name="share_log_description">Partagez le fichier de log de yuzu pour déboguer les problèmes.</string>
102 <string name="share_log_missing">Aucun fichier de log trouvé</string>
103 <string name="install_game_content">Installer le contenu du jeu</string>
104 <string name="install_game_content_description">Installer une mise à jour ou un DLC</string>
105 <string name="installing_game_content">Installation du contenu en cours...</string>
106 <string name="install_game_content_failure">Erreur lors de l\'installation du fichier dans la NAND</string>
107 <string name="install_game_content_failure_description">Veuillez vous assurer que le contenu est valide et que le fichier prod.keys est installé.</string>
108 <string name="install_game_content_failure_base">L\'installation de jeux de base n\'est pas autorisée afin d\'éviter d\'éventuels conflits.</string>
109 <string name="install_game_content_failure_file_extension">Seuls les contenus NSP et XCI sont pris en charge. Veuillez vérifier que le contenu du jeu est valide.</string>
110 <string name="install_game_content_failed_count">%1$d erreur(s) d\'installation</string>
111 <string name="install_game_content_success">Contenu du jeu installé avec succès</string>
112 <string name="install_game_content_success_install">%1$d installé avec succès</string>
113 <string name="install_game_content_success_overwrite">%1$d écrasé avec succès</string>
114 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
115 <string name="custom_driver_not_supported">Pilotes personnalisés non supporté</string>
116 <string name="custom_driver_not_supported_description">Le chargement des pilotes personnalisés ne sont pas actuellement pris en charge pour ce périphérique. Vérifiez à nouveau cette option à l\'avenir pour voir si la prise en charge a été ajoutée !</string>
117 <string name="manage_yuzu_data">Gérer les données de yuzu</string>
118 <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>
120 <string name="export_save_failed">Échec de l\'exportation de la sauvegarde</string>
89 121
90 <!-- About screen strings --> 122 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia n\'est pas réel</string> 123 <string name="gaia_is_not_real">Gaia n\'est pas réel</string>
@@ -94,7 +126,18 @@
94 <string name="contributors">Contributeurs</string> 126 <string name="contributors">Contributeurs</string>
95 <string name="contributors_description">Fait avec \u2764 de l\'équipe yuzu</string> 127 <string name="contributors_description">Fait avec \u2764 de l\'équipe yuzu</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">Des projets qui rendent possible yuzu pour Android</string>
97 <string name="build">Build</string> 130 <string name="build">Build</string>
131 <string name="user_data">Données utilisateur</string>
132 <string name="user_data_description">Importer/exporter toutes les données de l\'application.\n\nLors de l\'importation des données utilisateur, toutes les données utilisateur existantes seront supprimées !</string>
133 <string name="exporting_user_data">Exportation des données utilisateur...</string>
134 <string name="importing_user_data">Importation des données utilisateur...</string>
135 <string name="import_user_data">Importer des données utilisateur</string>
136 <string name="invalid_yuzu_backup">Backup yuzu invalide</string>
137 <string name="user_data_export_success">Les données utilisateur ont été exportés avec succès</string>
138 <string name="user_data_import_success">Les données utilisateur ont été importées avec succès</string>
139 <string name="user_data_export_cancelled">Exportation annulée</string>
140 <string name="user_data_import_failed_description">Assurez-vous que les dossiers de données utilisateur se trouvent à la racine du dossier ZIP et contiennent un fichier de configuration à config/config.ini, puis réessayez.</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 141 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 142 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 143 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -114,64 +157,87 @@
114 <string name="are_you_interested">Es tu intéressé ?</string> 157 <string name="are_you_interested">Es tu intéressé ?</string>
115 158
116 <!-- General settings strings --> 159 <!-- General settings strings -->
117 <string name="frame_limit_enable">Activer la vitesse limite</string> 160 <string name="frame_limit_enable">Limitation de vitesse</string>
118 <string name="frame_limit_enable_description">Lorsqu\'elle est activée, la vitesse d\'émulation sera limitée à un pourcentage spécifié de la vitesse normale.</string> 161 <string name="frame_limit_enable_description">Limiter la vitesse d\'émulation à un pourcentage spécifié de la vitesse normale</string>
119 <string name="frame_limit_slider">Limite en pourcentage de vitesse</string> 162 <string name="frame_limit_slider">Limite en pourcentage de vitesse</string>
120 <string name="frame_limit_slider_description">Spécifie le pourcentage pour limiter la vitesse d\'émulation. Avec la valeur par défaut de 100%, l\'émulation sera limitée à la vitesse normale. Des valeurs supérieures ou inférieures augmenteront ou diminueront la limite 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>
121 <string name="cpu_accuracy">Précision du CPU</string> 164 <string name="cpu_accuracy">Précision du CPU</string>
165 <string name="value_with_units">%1$s%2$s</string>
122 166
123 <!-- System settings strings --> 167 <!-- System settings strings -->
124 <string name="use_docked_mode">Mode TV</string> 168 <string name="use_docked_mode">Mode TV</string>
125 <string name="use_docked_mode_description">Émuler en mode TV augmente la résolution au détriment des performances.</string> 169 <string name="use_docked_mode_description">Augmenter la résolution, ce qui diminue les performances. Le mode portable est utilisé lorsque la fonction est désactivée, ce qui réduit la résolution et améliore les performances.</string>
126 <string name="emulated_region">Région émulée</string> 170 <string name="emulated_region">Région émulée</string>
127 <string name="emulated_language">Langue émulée</string> 171 <string name="emulated_language">Langue émulée</string>
128 <string name="select_rtc_date">Sélectionner la date RTC</string> 172 <string name="select_rtc_date">Sélectionner la date RTC</string>
129 <string name="select_rtc_time">Sélectionner l\'heure RTC</string> 173 <string name="select_rtc_time">Sélectionner l\'heure RTC</string>
130 <string name="use_custom_rtc">Activer l\'horloge RTC personnalisée</string> 174 <string name="use_custom_rtc">RTC personnalisé</string>
131 <string name="use_custom_rtc_description">Ce paramètre vous permet de définir une horloge en temps réel personnalisée distincte de l\'heure actuelle de votre système.</string> 175 <string name="use_custom_rtc_description">Vous permet de définir une horloge en temps réel personnalisée distincte de l\'heure actuelle de votre système.</string>
132 <string name="set_custom_rtc">Définir l\'horloge RTC personnalisée</string> 176 <string name="set_custom_rtc">Définir l\'horloge RTC personnalisée</string>
133 177
134 <!-- Graphics settings strings --> 178 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Niveau de précision</string> 179 <string name="renderer_accuracy">Niveau de précision</string>
137 <string name="renderer_resolution">Résolution</string> 180 <string name="renderer_resolution">Résolution (Mode Portable/Mode TV)</string>
138 <string name="renderer_vsync">Mode VSync</string> 181 <string name="renderer_vsync">Mode VSync</string>
182 <string name="renderer_screen_layout">Orientation</string>
139 <string name="renderer_aspect_ratio">Format</string> 183 <string name="renderer_aspect_ratio">Format</string>
140 <string name="renderer_scaling_filter">Filtre de fenêtre adaptatif</string> 184 <string name="renderer_scaling_filter">Filtre de fenêtre adaptatif</string>
141 <string name="renderer_anti_aliasing">Méthode d\'anticrénelage :</string> 185 <string name="renderer_anti_aliasing">Méthode d\'anticrénelage</string>
142 <string name="renderer_force_max_clock">Forcer la fréquence d\'horloge maximale (Adreno uniquement)</string> 186 <string name="renderer_force_max_clock">Forcer les fréquences maximales (Adreno uniquement)</string>
143 <string name="renderer_force_max_clock_description">Force le GPU à fonctionner au maximum d\'horloges possibles (les contraintes thermiques seront toujours appliquées).</string> 187 <string name="renderer_force_max_clock_description">Forcer le GPU à fonctionner à ses fréquences maximales possibles (les contraintes thermiques seront toujours appliquées).</string>
144 <string name="renderer_asynchronous_shaders">Utiliser les shaders asynchrones</string> 188 <string name="renderer_asynchronous_shaders">Utiliser les shaders asynchrones</string>
145 <string name="renderer_asynchronous_shaders_description">Compile les shaders de manière asynchrone, ce qui réduira les saccades mais peut entraîner des problèmes visuels.</string> 189 <string name="renderer_asynchronous_shaders_description">Compile les shaders de manière asynchrone, réduisant les saccades mais pouvant entraîner des problèmes visuels.</string>
146 <string name="renderer_debug">Activer le débogage des graphismes</string> 190 <string name="renderer_reactive_flushing">Utiliser le vidage réactif</string>
147 <string name="renderer_debug_description">Lorsque cette case est cochée, l\'API graphique entre dans un mode de débogage plus lent.</string> 191 <string name="renderer_reactive_flushing_description">Améliore la précision du rendu dans certains jeux au détriment des performances.</string>
148 <string name="use_disk_shader_cache">Utiliser les shader cache de disque</string> 192 <string name="use_disk_shader_cache">Utiliser les shader cache</string>
149 <string name="use_disk_shader_cache_description">Réduire les saccades en stockant et en chargeant les shaders générés sur le disque.</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>
194
195 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">Débogage du CPU</string>
198 <string name="cpu_debug_mode_description">Place le CPU en mode lent de débogage.</string>
199 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string>
201 <string name="renderer_debug">Débogage des graphismes</string>
202 <string name="renderer_debug_description">Définit l\'API graphique en mode de débogage lent.</string>
203 <string name="fastmem">Fastmem</string>
150 204
151 <!-- Audio settings strings --> 205 <!-- Audio settings strings -->
206 <string name="audio_output_engine">Moteur de sortie</string>
152 <string name="audio_volume">Volume</string> 207 <string name="audio_volume">Volume</string>
153 <string name="audio_volume_description">Spécifie le volume de la sortie audio.</string> 208 <string name="audio_volume_description">Spécifier le volume de la sortie audio.</string>
154 209
155 <!-- Miscellaneous --> 210 <!-- Miscellaneous -->
156 <string name="slider_default">Défaut</string> 211 <string name="slider_default">Par défaut</string>
157 <string name="ini_saved">Paramètres enregistrés</string> 212 <string name="ini_saved">Paramètres enregistrés</string>
158 <string name="gameid_saved">Paramètres enregistrés pour %1$s</string> 213 <string name="gameid_saved">Paramètres enregistrés pour %1$s</string>
159 <string name="error_saving">Erreur lors de l\'enregistrement de %1$s.ini: %2$s</string> 214 <string name="error_saving">Erreur lors de l\'enregistrement de %1$s.ini: %2$s</string>
215 <string name="unimplemented_menu">Menu non implémenté</string>
160 <string name="loading">Chargement...</string> 216 <string name="loading">Chargement...</string>
161 <string name="reset_setting_confirmation">Voulez-vous réinitialiser ce paramètre à sa valeur par défaut ?</string> 217 <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>
162 <string name="reset_to_default">Réinitialiser par défaut</string> 219 <string name="reset_to_default">Réinitialiser par défaut</string>
163 <string name="reset_all_settings">Réinitialiser tous les réglages ?</string> 220 <string name="reset_all_settings">Réinitialiser tous les réglages ?</string>
164 <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> 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>
165 <string name="settings_reset">Paramètres réinitialisés</string> 222 <string name="settings_reset">Paramètres réinitialisés</string>
166 <string name="close">Fermer</string> 223 <string name="close">Fermer</string>
167 <string name="learn_more">Plus d\'informations</string> 224 <string name="learn_more">En savoir plus</string>
225 <string name="auto">Auto</string>
226 <string name="submit">Soumettre</string>
227 <string name="string_null">Nul</string>
228 <string name="string_import">Importer</string>
229 <string name="export">Exporter</string>
230 <string name="export_failed">L\'exportation a échoué</string>
231 <string name="import_failed">L\'importation a échoué</string>
232 <string name="cancelling">Annulation</string>
168 233
169 <!-- GPU driver installation --> 234 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Sélectionner le pilote du GPU</string> 235 <string name="select_gpu_driver">Sélectionner le pilote du GPU</string>
171 <string name="select_gpu_driver_title">Souhaitez vous remplacer votre pilote actuel ?</string> 236 <string name="select_gpu_driver_title">Souhaitez vous remplacer votre pilote actuel ?</string>
172 <string name="select_gpu_driver_install">Installer</string> 237 <string name="select_gpu_driver_install">Installer</string>
173 <string name="select_gpu_driver_default">Défaut</string> 238 <string name="select_gpu_driver_default">Par défaut</string>
174 <string name="select_gpu_driver_use_default">Utilisation du pilote de GPU par défaut</string> 239 <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>
175 <string name="system_gpu_driver">Pilote du GPU du système</string> 241 <string name="system_gpu_driver">Pilote du GPU du système</string>
176 <string name="installing_driver">Installation du pilote...</string> 242 <string name="installing_driver">Installation du pilote...</string>
177 243
@@ -182,13 +248,14 @@
182 <string name="preferences_graphics">Vidéo</string> 248 <string name="preferences_graphics">Vidéo</string>
183 <string name="preferences_audio">Audio</string> 249 <string name="preferences_audio">Audio</string>
184 <string name="preferences_theme">Thème et couleur</string> 250 <string name="preferences_theme">Thème et couleur</string>
251 <string name="preferences_debug">Débogage</string>
185 252
186 <!-- ROM loading errors --> 253 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">Votre ROM est cryptée</string> 254 <string name="loader_error_encrypted">Votre ROM est cryptée</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[Veuillez suivre les guides pour redumper vos <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">cartouches de jeu</a> ou <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">titres installés</a>.]]></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>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[Veuillez vous assurer que votre fichier <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> est installé pour que les jeux puissent être déchiffrés.]]></string> 256 <string name="loader_error_encrypted_keys_description"><![CDATA[Veuillez vous assurer que votre fichier <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> est installé pour que les jeux puissent être déchiffrés.]]></string>
190 <string name="loader_error_video_core">Une erreur s\'est produite lors de l\'initialisation du noyau vidéo</string> 257 <string name="loader_error_video_core">Une erreur s\'est produite lors de l\'initialisation du noyau vidéo</string>
191 <string name="loader_error_video_core_description">Cela est généralement dû à un pilote du GPU incompatible. L\'installation d\'un pilote du GPU personnalisé peut résoudre ce problème.</string> 258 <string name="loader_error_video_core_description">Cela est généralement dû à un pilote GPU incompatible. L\'installation d\'un pilote GPU personnalisé peut résoudre ce problème.</string>
192 <string name="loader_error_invalid_format">Impossible de charger la ROM</string> 259 <string name="loader_error_invalid_format">Impossible de charger la ROM</string>
193 <string name="loader_error_file_not_found">Le fichier ROM n\'existe pas</string> 260 <string name="loader_error_file_not_found">Le fichier ROM n\'existe pas</string>
194 261
@@ -198,8 +265,8 @@
198 <string name="emulation_fps_counter">Compteur FPS</string> 265 <string name="emulation_fps_counter">Compteur FPS</string>
199 <string name="emulation_toggle_controls">Activer/Désactiver les contrôles</string> 266 <string name="emulation_toggle_controls">Activer/Désactiver les contrôles</string>
200 <string name="emulation_rel_stick_center">Centre du stick relatif</string> 267 <string name="emulation_rel_stick_center">Centre du stick relatif</string>
201 <string name="emulation_dpad_slide">Glissement du DPad</string> 268 <string name="emulation_dpad_slide">Glissement du D-pad</string>
202 <string name="emulation_haptics">Haptique</string> 269 <string name="emulation_haptics">Toucher haptique</string>
203 <string name="emulation_show_overlay">Afficher l\'overlay</string> 270 <string name="emulation_show_overlay">Afficher l\'overlay</string>
204 <string name="emulation_toggle_all">Tout basculer</string> 271 <string name="emulation_toggle_all">Tout basculer</string>
205 <string name="emulation_control_adjust">Ajuster l\'overlay</string> 272 <string name="emulation_control_adjust">Ajuster l\'overlay</string>
@@ -225,7 +292,10 @@
225 <string name="save_load_error">Erreur de sauvegarde/chargement</string> 292 <string name="save_load_error">Erreur de sauvegarde/chargement</string>
226 <string name="fatal_error">Erreur fatale</string> 293 <string name="fatal_error">Erreur fatale</string>
227 <string name="fatal_error_message">Une erreur fatale s\'est produite. Consultez les logs pour plus de détails.\nContinuer l\'émulation peut entraîner des plantages et des bogues.</string> 294 <string name="fatal_error_message">Une erreur fatale s\'est produite. Consultez les logs pour plus de détails.\nContinuer l\'émulation peut entraîner des plantages et des bogues.</string>
228 <string name="performance_warning">La désactivation de ce paramètre réduira considérablement les performances d\'émulation ! Pour une expérience optimale, il est recommandé de laisser ce paramètre activé.</string> 295 <string name="performance_warning">La désactivation de ce paramètre réduira considérablement les performances d\'émulation ! Pour une expérience optimale, il est recommandé de laisser ce paramètre activé.</string>
296 <string name="device_memory_inadequate">Mémoire RAM de l\'appareil : %1$s\nRecommandé : %2$s</string>
297 <string name="memory_formatted">%1$s %2$s</string>
298 <string name="no_game_present">Aucun jeu démarreable présent !</string>
229 299
230 <!-- Region Names --> 300 <!-- Region Names -->
231 <string name="region_japan">Japon</string> 301 <string name="region_japan">Japon</string>
@@ -236,7 +306,14 @@
236 <string name="region_korea">Corée</string> 306 <string name="region_korea">Corée</string>
237 <string name="region_taiwan">Taïwan</string> 307 <string name="region_taiwan">Taïwan</string>
238 308
239 <!-- Language Names --> 309 <!-- Memory Sizes -->
310 <string name="memory_byte">Octet</string>
311 <string name="memory_kilobyte">Ko</string>
312 <string name="memory_megabyte">Mo</string>
313 <string name="memory_gigabyte">GB</string>
314 <string name="memory_terabyte">To</string>
315 <string name="memory_petabyte">Po</string>
316 <string name="memory_exabyte">Eo</string>
240 317
241 <!-- Renderer APIs --> 318 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 319 <string name="renderer_vulkan">Vulkan</string>
@@ -274,6 +351,11 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 351 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 352 <string name="anti_aliasing_smaa">SMAA</string>
276 353
354 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">Paysage</string>
356 <string name="screen_layout_portrait">Portrait</string>
357 <string name="screen_layout_auto">Auto</string>
358
277 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
278 <string name="ratio_default">Par défaut (16:9)</string> 360 <string name="ratio_default">Par défaut (16:9)</string>
279 <string name="ratio_force_four_three">Forcer le 4:3</string> 361 <string name="ratio_force_four_three">Forcer le 4:3</string>
@@ -288,8 +370,8 @@
288 370
289 <!-- Gamepad Buttons --> 371 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">Pavé directionnel</string> 372 <string name="gamepad_d_pad">Pavé directionnel</string>
291 <string name="gamepad_left_stick">Stick Gauche</string> 373 <string name="gamepad_left_stick">Stick gauche</string>
292 <string name="gamepad_right_stick">Stick Droit</string> 374 <string name="gamepad_right_stick">Stick droit</string>
293 <string name="gamepad_home">Home</string> 375 <string name="gamepad_home">Home</string>
294 <string name="gamepad_screenshot">Capture d\'écran</string> 376 <string name="gamepad_screenshot">Capture d\'écran</string>
295 377
@@ -299,7 +381,7 @@
299 381
300 <!-- Theme options --> 382 <!-- Theme options -->
301 <string name="change_app_theme">Changer le thème de l\'application</string> 383 <string name="change_app_theme">Changer le thème de l\'application</string>
302 <string name="theme_default">Défaut</string> 384 <string name="theme_default">Par défaut</string>
303 <string name="theme_material_you">Material You</string> 385 <string name="theme_material_you">Material You</string>
304 386
305 <!-- Theme Modes --> 387 <!-- Theme Modes -->
@@ -308,8 +390,22 @@
308 <string name="theme_mode_light">Lumineux</string> 390 <string name="theme_mode_light">Lumineux</string>
309 <string name="theme_mode_dark">Sombre</string> 391 <string name="theme_mode_dark">Sombre</string>
310 392
311 <!-- Black backgrounds theme --> 393 <!-- Audio output engines -->
312 <string name="use_black_backgrounds">Utiliser des arrière-plans noirs</string> 394 <string name="cubeb">cubeb</string>
313 <string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer des arrière-plans noirs.</string>
314 395
315</resources> 396 <!-- Black backgrounds theme -->
397 <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>
399
400 <!-- Picture-In-Picture -->
401 <string name="picture_in_picture">Lecteur réduit</string>
402 <string name="picture_in_picture_description">Réduire la fenêtre lorsqu\'elle est placée en arrière-plan</string>
403 <string name="pause">Pause</string>
404 <string name="play">Jouer</string>
405 <string name="mute">Couper le son</string>
406 <string name="unmute">Remettre le son</string>
407
408 <!-- Licenses screen strings -->
409 <string name="licenses">Licences</string>
410 <string name="license_fidelityfx_fsr_description">Mise à l\'échelle de haute qualité par AMD.</string>
411 </resources>
diff --git a/src/android/app/src/main/res/values-he/strings.xml b/src/android/app/src/main/res/values-he/strings.xml
new file mode 100644
index 000000000..0af78a57c
--- /dev/null
+++ b/src/android/app/src/main/res/values-he/strings.xml
@@ -0,0 +1,367 @@
1<?xml version="1.0" encoding="utf-8"?>
2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3
4 <string name="app_disclaimer">התוכנה תריץ ×ž×©×—×§×™× ×œ×§×•× ×¡×•×œ×ª ×” Nintendo Switch. ××£ משחק ×ו ×§×‘×¦×™× ×‘×¢×œ×™ זכויות ×™×•×¦×¨×™× × ×›×œ×œ×™×.&lt;br /&gt;&lt;br /&gt; לפני ש×ת/×” מתחיל בבקשה ×ž×¦× ×ת קובץ <![CDATA[<b>prod.keys</b>]]> על המכשיר.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">×§×¨× ×¢×•×“</a>]]></string>
5 <string name="emulation_notification_channel_name">×מולציה פעילה</string>
6 <string name="emulation_notification_channel_description">מציג התר××” מתמשכת ×›×שר ×”×מולציה פועלת.</string>
7 <string name="emulation_notification_running">yuzu רץ</string>
8 <string name="notice_notification_channel_name">התר×ות ותקלות</string>
9 <string name="notice_notification_channel_description">מציג התר×ות ×›×שר משהו הולך ×œ× ×›×©×•×¨×”.</string>
10 <string name="notification_permission_not_granted">הרש×ות התר×ות ×œ× × ×™×ª× ×”!</string>
11
12 <!-- Setup strings -->
13 <string name="welcome">×‘×¨×•×›×™× ×”×‘××™×!</string>
14 <string name="welcome_description">למד ×יך להפעיל &lt;b>yuzu&lt;/b> וקפוץ ישר ל×מולציה.</string>
15 <string name="get_started">כדי להתחיל</string>
16 <string name="keys">מפתחות</string>
17 <string name="keys_description">בחר ×ת קובץ ×” &lt;b>prod.keys&lt;/b> שלך ×¢× ×”×›×¤×ª×•×¨ למטה.</string>
18 <string name="select_keys">בחר מפתחות</string>
19 <string name="games">משחקי×</string>
20 <string name="games_description">בחר ×ת התיקיית ×” &lt;b>Games&lt;/b> שלך ×¢× ×”×›×¤×ª×•×¨ למטה.</string>
21 <string name="done">סיו×</string>
22 <string name="done_description">×ת/×” מוכן. \nתהנה/×™ ×ž×”×ž×©×—×§×™× ×©×œ×š </string>
23 <string name="text_continue">המשך</string>
24 <string name="next">הב×</string>
25 <string name="back">×חורה</string>
26 <string name="add_games">הוסף משחקי×</string>
27 <string name="add_games_description">בחר/×™ ×ת תיקיית ×”×ž×©×—×§×™× ×©×œ×š</string>
28 <string name="step_complete">הושל×!</string>
29
30 <!-- Home strings -->
31 <string name="home_games">משחקי×</string>
32 <string name="home_search">חפש</string>
33 <string name="home_settings">הגדרות</string>
34 <string name="empty_gamelist">×œ× × ×ž×¦×ו ×§×‘×¦×™× ×ו לנבחרה ספריית ×§×‘×¦×™× ×‘×™× ×ª×™×™×.</string>
35 <string name="search_and_filter_games">חפש וסנן משחקי×</string>
36 <string name="select_games_folder">בחר תיקיית משחקי×</string>
37 <string name="select_games_folder_description">×פשר ל yuzu ל×כלס ×ת רשימת המשחקי×</string>
38 <string name="add_games_warning">לדלג על בחירת תיקיית המשחקי×?</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>
41 <string name="home_search_games">חפש משחקי×</string>
42 <string name="search_settings">חפש בהגדרות</string>
43 <string name="games_dir_selected">ספריית ×ž×©×—×§×™× × ×‘×—×¨×”</string>
44 <string name="install_prod_keys">התקן prod.keys</string>
45 <string name="install_prod_keys_description">הכרחי בכדי לפענח משחקי×</string>
46 <string name="install_prod_keys_warning">לדלג על הוספת מפתחות?</string>
47 <string name="install_prod_keys_warning_description">מפתחות ×—×•×§×™×™× ×”×›×¨×—×™×™× ×›×“×™ לשחק במשחקי×. רק ×פליקציות פירטיות יפעלו ×× ×ª×ž×©×™×š.</string>
48 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
49 <string name="notifications">התר×ות</string>
50 <string name="notifications_description">תן גישה להתר×ות ×¢× ×”×›×¤×ª×•×¨ למטה.</string>
51 <string name="give_permission">תן הרש××”</string>
52 <string name="notification_warning">דלג על מתן הרש××” להתר×ות?</string>
53 <string name="notification_warning_description">yuzu ×œ× ×™×•×›×œ להתריע לך על מידע חשוב.</string>
54 <string name="permission_denied">הרש××” נדחתה</string>
55 <string name="permission_denied_description">×ת/×” דיחת ×ת ההרש××” יותר מדי ×¤×¢×ž×™× ×•×¢×›×©×™×• ×ת/×” צריך/×” לתת גישה ב×ופן ידני בהגדרות.</string>
56 <string name="about">×ודות</string>
57 <string name="about_description">מספר גירסה, ×§×¨×“×™×˜×™× ×•×¢×•×“</string>
58 <string name="warning_help">עזרה</string>
59 <string name="warning_skip">דלג</string>
60 <string name="warning_cancel">ביטול</string>
61 <string name="install_amiibo_keys">התקן מפתחות Amiibo</string>
62 <string name="install_amiibo_keys_description">נחוץ כדי להשתמש ב Amiibo במשחק</string>
63 <string name="invalid_keys_file">קובץ מפתחות ×œ× ×—×•×§×™ נבחר</string>
64 <string name="install_keys_success">מפתחות הותקנו בהצלחה</string>
65 <string name="reading_keys_failure">שגי××” בקרי×ת מפתחות ההצפנה</string>
66 <string name="install_prod_keys_failure_extension_description">×•×“× ×©×œ×§×•×‘×¥ המפתחות שלך יש סיומת של key. ונסה/×™ שוב.</string>
67 <string name="install_amiibo_keys_failure_extension_description">וד×/×™ שלקובץ המפתחות שלך יש סיומת של bin. ונסה/×™ שוב.</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>
70 <string name="install_keys_failure_description">קבוץ שנבחר מושחת ×ו ×œ× × ×›×•×Ÿ. בבקשה ×”×•×¦× ×ž×—×“×© ×ת המפתחות שלך.</string>
71 <string name="install_gpu_driver">התקן דרייבר למעבד הגרפי</string>
72 <string name="install_gpu_driver_description">התקן ×“×¨×™×™×‘×¨×™× ××—×¨×™× ×‘×©×‘×™×œ סיכוי ×œ×‘×™×¦×•×¢×™× ×ו דיוק ×’×‘×•×”×”×™× ×™×•×ª×¨</string>
73 <string name="advanced_settings">הגדרות מתקדמות</string>
74 <string name="advanced_settings_game">הגדרות מתקדמות: %1$s</string>
75 <string name="settings_description">הדר ×ת הגדרות ×”×מולטור</string>
76 <string name="search_recently_played">שוחק ל×חרונה</string>
77 <string name="search_recently_added">הוסף ל×חרונה</string>
78 <string name="search_retail">קמעונ××™</string>
79 <string name="search_homebrew">Homebrew</string>
80 <string name="open_user_folder">פתח ×ת תיקיית yuzu </string>
81 <string name="open_user_folder_description">× ×” ל ×ת ×”×§×‘×¦×™× ×”×¤× ×™×ž×™×™×Ÿ של yuzu</string>
82 <string name="theme_and_color_description">ערוך ×ת נר×ות ×”×פליקציה</string>
83 <string name="no_file_manager">×œ× × ×ž×¦× ×ž× ×”×œ קבצי×</string>
84 <string name="notification_no_directory_link">×œ× ×™×›×•×œ לפתוח ×ת ספריית yuzu</string>
85 <string name="notification_no_directory_link_description">בבקשה ×ž×§× ×ת תיקיית המשתמש בפנל הצידי של מנהל ×”×§×‘×¦×™× ×‘×ופן ידני.</string>
86 <string name="manage_save_data">נהל מידע שמור</string>
87 <string name="manage_save_data_description">מידע שמור ×œ× × ×ž×¦×. בבקשה בחר/×™ ×ופציה מלמטה</string>
88 <string name="import_export_saves_description">×™×‘× ×ו ×™×¦× ×§×‘×¦×™ שמירה</string>
89 <string name="save_file_imported_success">×™×•×‘× ×‘×”×¦×œ×—×”</string>
90 <string name="save_file_invalid_zip_structure">מבנה ספריית השמירות ×œ× ×—×•×§×™</string>
91 <string name="save_file_invalid_zip_structure_description">התת תיקייה הר×שונה חייב להיות ×” title ID של המשחק</string>
92 <string name="import_saves">ייבו×</string>
93 <string name="export_saves">ייצו×</string>
94 <string name="install_firmware">התקן firmware</string>
95 <string name="install_firmware_description">×” frimware חייב להיות בקובץ zip ×•×”×•× ×”×›×¨×—×™ להפעלת חלק מהמשחקי×</string>
96 <string name="firmware_installing">מתקין frimware</string>
97 <string name="firmware_installed_success">ה frimware הותקן בהצלחה</string>
98 <string name="firmware_installed_failure">התקנת ה frimware נכשלה</string>
99 <string name="firmware_installed_failure_description">×•×“× ×©×§×‘×¦×™ ×” firmware nca נמצ××™× ×‘×©×•×¨×© ×” zip ונסה שוב.</string>
100 <string name="share_log">שתף ×ת יומני ×”×¨×™×©×•× ×©×œ מיפוי הב××’×™×</string>
101 <string name="share_log_description">שתף ×ת קובץ יומני ×”×¨×™×©×•× ×©×œ yuzu בכדי לתקן בעיות</string>
102 <string name="share_log_missing">×œ× × ×ž×¦× ×§×•×‘×¥ יומן רישו×</string>
103 <string name="install_game_content">התקן תוכן משחק</string>
104 <string name="install_game_content_description">התקן עדכוני משחק ×ו DLC</string>
105 <string name="installing_game_content">מתקין תוכן...</string>
106 <string name="install_game_content_failure">תקלה בהתקנת הקובץ (×ו קבצי×) ל NAND</string>
107 <string name="install_game_content_failure_description">בבקשה ×•×“× ×©×”×ª×•×›×Ÿ (×ו תכני×) ×—×•×§×™×™× ×•×©×§×•×‘×¥ ×” prod.keys מותקן.</string>
108 <string name="install_game_content_failure_base">התקנת משחק בסיס נדחת בכדי להימנע ×ž×§×•× ×¤×œ×™×§×˜×™× ×פשריי×.</string>
109 <string name="install_game_content_failure_file_extension">רק קבצי NSP ו XCI נתמכי×. בבקשה ×•×“× ×©×ª×•×›×Ÿ (×ו תכני×) המשחק חוקי.</string>
110 <string name="install_game_content_failed_count">%1$dבעיה (בעיות) התקנה</string>
111 <string name="install_game_content_success">תוכן (×ו תכני) המשחק הותקנו בהצלחה</string>
112 <string name="install_game_content_success_install">%1$d הותקן בהצלחה</string>
113 <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>
115 <string name="custom_driver_not_supported">×“×¨×™×™×‘×¨×™× ×ž×•×ª××ž×™× ×ישית ×œ× × ×ª×ž×›×™×</string>
116 <string name="custom_driver_not_supported_description">הטענת ×“×¨×™×™×‘×™× ×ž×•×ª××ž×™× ×ישית ×œ× × ×ª×ž×š כרגע על מכשיר ×–×”. \nבבקשה בדוק ×ופציה זו בעתיד בכדי לר×ות ×× × ×•×¡×¤×” תמיכה!</string>
117 <string name="manage_yuzu_data">נהל ×ת המידע של yuzu</string>
118 <string name="manage_yuzu_data_description">יב×/×™×¦× firmware, keys, מידע של משתמש ועוד!</string>
119 <string name="share_save_file">שתף קובץ שמירה</string>
120 <string name="export_save_failed">נכשל ×‘×™×™×¦×•× ×©×ž×™×¨×”</string>
121
122 <!-- About screen strings -->
123 <string name="gaia_is_not_real">Gaia ×œ× ×מיתית</string>
124 <string name="copied_to_clipboard">הועתק ללוח</string>
125 <string name="about_app_description">×מולטור Switch ×¢× ×§×•×“ פתוח</string>
126 <string name="contributors">תורמי×</string>
127 <string name="contributors_description">נוצר ×¢× \u2764 מקבוצת yuzu</string>
128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">×¤×¨×•×™×™×§×˜×™× ×©×”×•×¤×›×™× ×ת yuzu ל Android ×פשרי</string>
130 <string name="build">גרסה</string>
131 <string name="user_data">נתוני משתמש</string>
132 <string name="user_data_description">יב×/×™×¦× ×ת כל נתוני ×”×פליקציה.\n\n×›×שר מייב××™× ×ת נתוני המשתמש, כל נתוני המשתמש ×”×§×™×™×ž×™× ×™×ž×—×§×•!</string>
133 <string name="exporting_user_data">×ž×™×™×¦× × ×ª×•× ×™ משתמש...</string>
134 <string name="importing_user_data">×ž×™×™×‘× × ×ª×•× ×™ משתמש...</string>
135 <string name="import_user_data">×™×‘× × ×ª×•× ×™ משתמש</string>
136 <string name="invalid_yuzu_backup">גיבוי yuzu ×œ× ×—×•×§×™</string>
137 <string name="user_data_export_success">נתוני משתמש יוצ×ו בהצלחה</string>
138 <string name="user_data_import_success">נתוני משתמש יוב×ו בהצלחה</string>
139 <string name="user_data_export_cancelled">×™×™×¦×•× ×‘×•×˜×œ</string>
140 <string name="user_data_import_failed_description">×•×“× ×©× ×ª×•× ×™ המשתמש נמצ××™× ×‘×©×•×¨×© קובץ ×” zip ×•×©×”×•× ×ž×›×™×œ קובץ סידור ב config/config.ini ונסה שוב.</string>
141 <string name="support_link">https://discord.gg/u77vRWY</string>
142 <string name="website_link">https://yuzu-emu.org/</string>
143 <string name="github_link">https://github.com/yuzu-emu</string>
144
145 <!-- Early access upgrade strings -->
146 <string name="early_access">גישה מוקדמת</string>
147 <string name="get_early_access">קבל גישה מוקדמת</string>
148 <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">תכונות חותכות קצה, גישה מוקדמת לעדכוני×, ועוד</string>
150 <string name="early_access_benefits">יתרונות של גישה מקודמת</string>
151 <string name="cutting_edge_features">תכונות חותכות קצה</string>
152 <string name="early_access_updates">גישה מוקדמת לעדכוני×</string>
153 <string name="no_manual_installation">×œ×œ× ×”×ª×§× ×” ידנית</string>
154 <string name="prioritized_support">תמיכה בעדיפות</string>
155 <string name="helping_game_preservation">עוזר בשמירת משחקי×</string>
156 <string name="our_eternal_gratitude">התודה ×”×ינסופית שלנו</string>
157 <string name="are_you_interested">×תה מעוניין?</string>
158
159 <!-- General settings strings -->
160 <string name="frame_limit_enable">הגבל מהירות</string>
161 <string name="frame_limit_enable_description">מגביל ×ת מהירות ×”×מולציה ל×חוז מהירות המבוקש מהמהירות הרגילה.</string>
162 <string name="frame_limit_slider">הגבל ×ת ×חוז המהירות</string>
163 <string name="frame_limit_slider_description">מדייק ×ת ×חוז מהירות ×”×מולציה. 100% ×–×” מהירות רגילה. ×¢×¨×›×™× ×’×“×•×œ×™× ×ו ×§×˜× ×™× ×™×יצו ×ו ×™×טו ×ת מהירות ×”×מולציה.</string>
164 <string name="cpu_accuracy">דיוק המעבד</string>
165 <string name="value_with_units">%1$s%2$s</string>
166
167 <!-- System settings strings -->
168 <string name="use_docked_mode">מצב עגינה</string>
169 <string name="use_docked_mode_description">מעלה ×ת הרזולוציה, פוגע בביצועי×. משתמש במצב נייד ×›×שר מנוטרל, מפחית ×ת הרזולוציה ומעלה ×ת הביצועי×.</string>
170 <string name="emulated_region">×זור ×מולציה</string>
171 <string name="emulated_language">שפת ×מולציה</string>
172 <string name="select_rtc_date">בחר ת×ריך RTC</string>
173 <string name="select_rtc_time">בחר זמן RTC</string>
174 <string name="use_custom_rtc">RTC מות×× ×ישית</string>
175 <string name="use_custom_rtc_description">מ×פשר לך לקבוע שעון זמן ×מת נפרד משעון המערכת שלך.</string>
176 <string name="set_custom_rtc">קבע RTC מות×× ×ישית</string>
177
178 <!-- Graphics settings strings -->
179 <string name="renderer_accuracy">רמת דיוק</string>
180 <string name="renderer_resolution">רזולוציה (מעוגן/נייד)</string>
181 <string name="renderer_vsync">מצב VSync</string>
182 <string name="renderer_screen_layout">כיוון</string>
183 <string name="renderer_aspect_ratio">יחס רוחב גובה</string>
184 <string name="renderer_scaling_filter">פילטר מת×× ×—×œ×•×Ÿ</string>
185 <string name="renderer_anti_aliasing">שיטת Anti-aliasing</string>
186 <string name="renderer_force_max_clock">החזק מהירות שעון מקסימלית (רק ל Adreno)</string>
187 <string name="renderer_force_max_clock_description">מכריח לדחוף ×ת מהירויות המעבד הגרפי ×œ×ž×§×¡×™×ž×•× (הגבלות ×—×•× ×™×ž×©×™×›×• לתפקד).</string>
188 <string name="renderer_reactive_flushing_description">משפר ×ת הדיוק של ×”×מולציה ×‘×ž×©×—×§×™× ×ž×¡×•×™×™×ž×™× ×‘×ž×—×™×¨ של ביצועי×.</string>
189 <!-- Debug settings strings -->
190 <string name="cpu">מעבד</string>
191 <string name="cpu_debug_mode_description">מכניס ×ת המעבד למצב דיב××’ ×יטי</string>
192 <string name="gpu">מעבד גרפי</string>
193 <!-- Audio settings strings -->
194 <string name="audio_output_engine">מנוע פלט</string>
195 <string name="audio_volume">עוצמת שמע</string>
196 <!-- Miscellaneous -->
197 <string name="slider_default">ברירת מחדל</string>
198 <string name="ini_saved">הגדרות שמורות</string>
199 <string name="gameid_saved">הגדרות שמורות עבור %1$s</string>
200 <string name="error_saving">תקלה בשמירת %1$s.ini: %2$s</string>
201 <string name="loading">טוען...</string>
202 <string name="shutting_down">כיבוי...</string>
203 <string name="reset_setting_confirmation">×תה מעוניין ל×פס ×ת ההגדרה הזו חזרה לברירת המחדל?</string>
204 <string name="reset_to_default">×פס לברירת המחדל</string>
205 <string name="reset_all_settings">ל×פס ×ת כל ההגדרות?</string>
206 <string name="reset_all_settings_description">כל ההגדרות המתקדמות ×™×ופסו לברירת המחדל. ×œ× × ×™×ª×Ÿ לבטל פעולה זו.</string>
207 <string name="settings_reset">×פס הגדרות</string>
208 <string name="close">סגור</string>
209 <string name="learn_more">למד עוד</string>
210 <string name="auto">×וטומטי</string>
211 <string name="submit">שלח</string>
212 <string name="string_import">ייבו×</string>
213 <string name="export">ייצו×</string>
214 <string name="export_failed">×™×™×¦×•× × ×›×©×œ</string>
215 <string name="import_failed">×™×™×‘×•× × ×›×©×œ</string>
216 <string name="cancelling">מבטל</string>
217
218 <!-- GPU driver installation -->
219 <string name="select_gpu_driver">בחר דרייבר למעבד הגרפי</string>
220 <string name="select_gpu_driver_title">×תה מעוניין להחליף ×ת הדרייבר של המעבד הגרפי שלך?</string>
221 <string name="select_gpu_driver_install">התקן</string>
222 <string name="select_gpu_driver_default">ברירת מחדל</string>
223 <string name="select_gpu_driver_use_default">משתמש בדרייבר ברירת המחדל של המעבד הגרפי</string>
224 <string name="select_gpu_driver_error">דרייבר ×œ× ×—×•×§×™ נבחר, משתמש בברירת המחדל של המערכת!</string>
225 <string name="system_gpu_driver">דרייבר של המעבד הגרפי של המערכת</string>
226 <string name="installing_driver">מתקין דרייבר...</string>
227
228 <!-- Preferences Screen -->
229 <string name="preferences_settings">הגדרות</string>
230 <string name="preferences_general">כללי</string>
231 <string name="preferences_system">מערכת</string>
232 <string name="preferences_graphics">גרפיקה</string>
233 <string name="preferences_audio">שמע</string>
234 <string name="preferences_theme">צבע ונוש×</string>
235 <!-- ROM loading errors -->
236 <string name="loader_error_encrypted">המשחק שלך מוצפן</string>
237 <string name="loader_error_invalid_format">×ין ×פשרות לטעון ×ת המשחק</string>
238 <string name="loader_error_file_not_found">קובץ המשחק ×œ× ×§×™×™×</string>
239
240 <!-- Emulation Menu -->
241 <string name="emulation_exit">×¦× ×ž×”×מולציה</string>
242 <string name="emulation_done">סיו×</string>
243 <string name="emulation_fps_counter">סופר FPS</string>
244 <string name="emulation_control_scale">קנה מידה</string>
245 <string name="emulation_control_opacity">שקיפות</string>
246 <string name="emulation_pause">עצור ×מולציה</string>
247 <string name="emulation_unpause">המשך ×מולציה</string>
248 <string name="load_settings">טוען הגדרות...</string>
249
250 <!-- Software keyboard -->
251 <string name="software_keyboard">מקלדת תוכנה</string>
252
253 <!-- Errors and warnings -->
254 <string name="abort_button">×ודות</string>
255 <string name="continue_button">המשך</string>
256 <string name="system_archive_not_found">×רכיון מערכת ×œ× × ×ž×¦×</string>
257 <string name="system_archive_not_found_message">%s חסר. בבקשה ×”×•×¦× ×ª× ×רכיוני המערכת שלך./nהמשכת ×”×מולציה עלולה ×œ×’×¨×•× ×œ×§×¨×™×¡×•×ª וב××’×™×.</string>
258 <string name="system_archive_general">×רכיון מערכת</string>
259 <string name="save_load_error">בעיית שמירה/טעינה</string>
260 <string name="fatal_error">שגי××” חמורה</string>
261 <string name="device_memory_inadequate">RAM המכשיר: %1$s/nמומלץ: %2$s</string>
262 <string name="memory_formatted">%1$s%2$s</string>
263 <string name="no_game_present">×ין משחק שניתן להריץ!</string>
264
265 <!-- Region Names -->
266 <string name="region_japan">יפן</string>
267 <string name="region_usa">×רה״ב</string>
268 <string name="region_europe">×ירופה</string>
269 <string name="region_australia">×וסטרליה</string>
270 <string name="region_china">סין</string>
271 <string name="region_korea">קורי××”</string>
272 <string name="region_taiwan">טייוו×ן</string>
273
274 <!-- Memory Sizes -->
275 <string name="memory_byte">בייט</string>
276 <string name="memory_kilobyte">KB</string>
277 <string name="memory_megabyte">MB</string>
278 <string name="memory_gigabyte">GB</string>
279 <string name="memory_terabyte">TB</string>
280 <string name="memory_petabyte">PB</string>
281 <string name="memory_exabyte">EB</string>
282
283 <!-- Renderer APIs -->
284 <string name="renderer_vulkan">Vulkan</string>
285 <string name="renderer_none">×ין ×©×•× ×“×‘×¨</string>
286
287 <!-- Renderer Accuracy -->
288 <string name="renderer_accuracy_normal">רגיל</string>
289 <string name="renderer_accuracy_high">גבוה</string>
290 <string name="renderer_accuracy_extreme">××§×¡×˜×¨×™× (×יטי)</string>
291
292 <!-- Resolutions -->
293 <string name="resolution_half">0.5X (360p/540p)</string>
294 <string name="resolution_three_quarter">0.75X (540p/810p)</string>
295 <string name="resolution_one">1X (720p/1080p)</string>
296 <string name="resolution_two">2X (1440p/2160p) (×יטי)</string>
297 <string name="resolution_three">3X (2160p/3240p) (×יטי)</string>
298 <string name="resolution_four">4X (2880p/4320p) (×יטי)</string>
299
300 <string name="renderer_vsync_mailbox">תיבת דו×ר</string>
301 <string name="renderer_vsync_fifo">FIFO (On)</string>
302 <string name="renderer_vsync_fifo_relaxed">FIFO נינוח</string>
303
304 <!-- Scaling Filters -->
305 <string name="scaling_filter_nearest_neighbor">השכן הקרוב ביותר</string>
306 <string name="scaling_filter_scale_force">ScaleForce</string>
307 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string>
308
309 <!-- Anti-Aliasing -->
310 <string name="anti_aliasing_none">×ין ×©×•× ×“×‘×¨</string>
311 <string name="anti_aliasing_fxaa">FXAA</string>
312 <string name="anti_aliasing_smaa">SMAA</string>
313
314 <!-- Screen Layouts -->
315 <string name="screen_layout_landscape">לרוחב</string>
316 <string name="screen_layout_portrait">ל×ורך</string>
317 <string name="screen_layout_auto">×וטומטי</string>
318
319 <!-- Aspect Ratios -->
320 <string name="ratio_default">ברירת מחדל (16:9)</string>
321 <string name="ratio_force_four_three">הכרח 4:3</string>
322 <string name="ratio_force_twenty_one_nine">הכרח 21:9</string>
323 <string name="ratio_force_sixteen_ten">הכרח 16:10</string>
324 <string name="ratio_stretch">הרחב לגודל המסך</string>
325
326 <!-- CPU Accuracy -->
327 <string name="cpu_accuracy_accurate">מדויק</string>
328 <string name="cpu_accuracy_unsafe">×œ× ×‘×˜×•×—</string>
329 <string name="cpu_accuracy_paranoid">פר×נו×ידי (×יטי)</string>
330
331 <!-- Gamepad Buttons -->
332 <string name="gamepad_d_pad">D-pad</string>
333 <string name="gamepad_left_stick">ג׳ויסטיק שמ×לי</string>
334 <string name="gamepad_right_stick">ג׳ויסטיק ימני</string>
335 <string name="gamepad_home">בית</string>
336 <string name="gamepad_screenshot">×¦×™×œ×•× ×ž×¡×š</string>
337
338 <!-- Theme options -->
339 <string name="change_app_theme">שנה ×ת × ×•×©× ×”×פליקצייה</string>
340 <string name="theme_default">ברירת מחדל</string>
341 <string name="theme_material_you">חומר ×תה/מ×טירי×ל יו</string>
342
343 <!-- Theme Modes -->
344 <string name="change_theme_mode">שנה ×ת מצב הנוש×</string>
345 <string name="theme_mode_follow_system">עקוב ×חרי המערכת</string>
346 <string name="theme_mode_light">בהיר</string>
347 <string name="theme_mode_dark">×›×”×”</string>
348
349 <!-- Audio output engines -->
350 <string name="cubeb">cubeb</string>
351
352 <!-- Black backgrounds theme -->
353 <string name="use_black_backgrounds">×¨×§×¢×™× ×©×—×•×¨×™×</string>
354 <string name="use_black_backgrounds_description">×›×©×ž×ª×©×ž×©×™× ×‘×ž×¦×‘ ×›×”×”, ×©× ×¨×§×¢×™× ×©×—×•×¨×™×.</string>
355
356 <!-- Picture-In-Picture -->
357 <string name="picture_in_picture">תמונה בתוך תמונה</string>
358 <string name="picture_in_picture_description">הקטן ×ת החלון ×›×שר × ×ž×¦× ×‘×¨×§×¢</string>
359 <string name="pause">עצור</string>
360 <string name="play">שחק</string>
361 <string name="mute">השתק</string>
362 <string name="unmute">בטל השתקה</string>
363
364 <!-- Licenses screen strings -->
365 <string name="licenses">רישיונות</string>
366 <string name="license_fidelityfx_fsr_description">×פסקיילינג ב×יכות גבוהה מ AMD</string>
367 </resources>
diff --git a/src/android/app/src/main/res/values-hu/strings.xml b/src/android/app/src/main/res/values-hu/strings.xml
new file mode 100644
index 000000000..6563ba288
--- /dev/null
+++ b/src/android/app/src/main/res/values-hu/strings.xml
@@ -0,0 +1,402 @@
1<?xml version="1.0" encoding="utf-8"?>
2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3
4 <string name="app_disclaimer">Ez a szoftver Nintendo Switch játékkonzolhoz készült játékokat futtat. Nem tartalmaz játékokat vagy kulcsokat. .&lt;br /&gt;&lt;br /&gt;Mielőtt hozzákezdenél, kérjük, válaszd ki a <![CDATA[<b>prod.keys</b>]]> fájl helyét a készülék tárhelyén&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Tudj meg többet</a>]]></string>
5 <string name="emulation_notification_channel_name">Emuláció aktív</string>
6 <string name="emulation_notification_channel_description">Ãllandó értesítést jelenít meg, amíg az emuláció fut.</string>
7 <string name="emulation_notification_running">A yuzu fut</string>
8 <string name="notice_notification_channel_name">Megjegyzések és hibák</string>
9 <string name="notice_notification_channel_description">Értesítések megjelenítése, ha valami rosszul sül el.</string>
10 <string name="notification_permission_not_granted">Nincs engedély az értesítés megjelenítéséhez!</string>
11
12 <!-- Setup strings -->
13 <string name="welcome">Üdvözöljük!</string>
14 <string name="welcome_description">Ismerkedj meg a &lt;b>yuzu&lt;/b> beállításával és ugorj bele az emulációba.</string>
15 <string name="get_started">Vágjunk bele</string>
16 <string name="keys">Kulcsok</string>
17 <string name="keys_description">Válaszd ki a(z) &lt;b>prod.keys&lt;/b> fájlodat az alábbi gombbal.</string>
18 <string name="select_keys">Kulcsok kiválasztása</string>
19 <string name="games">Játékok</string>
20 <string name="games_description">
21Válaszd ki a(z) &lt;b>Games&lt;/b> mappát az alábbi gombbal.</string>
22 <string name="done">Kész</string>
23 <string name="done_description">Minden kész.\nJó szórakozást!</string>
24 <string name="text_continue">Folytatás</string>
25 <string name="next">Következő</string>
26 <string name="back">Vissza</string>
27 <string name="add_games">Játékok hozzáadása</string>
28 <string name="add_games_description">Játékaid mappa kiválasztása</string>
29 <string name="step_complete">Kész!</string>
30
31 <!-- Home strings -->
32 <string name="home_games">Játékok</string>
33 <string name="home_search">Keresés</string>
34 <string name="home_settings">Beállítások</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>
37 <string name="select_games_folder">Játékmappa kiválasztása</string>
38 <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_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
41 <string name="home_search_games">Játékok keresése</string>
42 <string name="search_settings">Beállítások keresése</string>
43 <string name="games_dir_selected">Játékok könyvtár kiválasztva</string>
44 <string name="install_prod_keys">prod.keys telepítése</string>
45 <string name="install_prod_keys_description">Kiskereskedelmi játékok dekódolásához szükséges</string>
46 <string name="install_prod_keys_warning">Kihagyod a kulcsok hozzáadását?</string>
47 <string name="install_prod_keys_warning_description">A kiskereskedelmi játékok emulálásához érvényes kulcsokra van szükség. Csak a homebrew alkalmazások fognak működni, ha folytatod.</string>
48 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
49 <string name="notifications">Értesítések</string>
50 <string name="notifications_description">Értesítési engedélyek megadása az alábbi gombbal.</string>
51 <string name="give_permission">Engedély megadása</string>
52 <string name="notification_warning">Kihagyod az értesítési engedély megadását?</string>
53 <string name="notification_warning_description">yuzu nem fog tudni értesíteni a fontos imformációkról</string>
54 <string name="permission_denied">Engedély megtagadva</string>
55 <string name="permission_denied_description">Túl gyakran utasítottad el a hozzáférést, így manuálisan kell jóváhagynod a rendszer beállításokban.</string>
56 <string name="about">A programról</string>
57 <string name="about_description">Build verzió, készítők, és még több</string>
58 <string name="warning_help">Segítség</string>
59 <string name="warning_skip">Kihagyás</string>
60 <string name="warning_cancel">Mégse</string>
61 <string name="install_amiibo_keys">Amiibo kulcsok telepítése</string>
62 <string name="install_amiibo_keys_description">Amiibo használata szükséges a játékhoz</string>
63 <string name="invalid_keys_file">Érvénytelen titkosítófájlok kiválasztva</string>
64 <string name="install_keys_success">Kulcsok sikeresen telepítve</string>
65 <string name="reading_keys_failure">Hiba történt a titkosítókulcsok olvasása során</string>
66 <string name="install_prod_keys_failure_extension_description">Győződj meg róla, hogy a titkosító fájlod .keys kiterjesztéssel rendelkezik, majd próbáld újra.</string>
67 <string name="install_amiibo_keys_failure_extension_description">Győződj meg róla, hogy a titkosító fájlod .bin kiterjesztéssel rendelkezik, majd próbáld újra.</string>
68 <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="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_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>
73 <string name="advanced_settings">Haladó beállítások</string>
74 <string name="advanced_settings_game">Haladó beállítások: %1$s</string>
75 <string name="settings_description">Emulátorbeállítások konfigurálása</string>
76 <string name="search_recently_played">Nemrég játszva</string>
77 <string name="search_recently_added">Nemrég hozzáadva</string>
78 <string name="search_retail">Kiskereskedelmi</string>
79 <string name="open_user_folder">yuzu mappa megnyitása</string>
80 <string name="open_user_folder_description">yuzu belső fájljainak kezelése</string>
81 <string name="theme_and_color_description">Az alkalmazás megjelenésének módosítása</string>
82 <string name="no_file_manager">Nem található fájlkezelő</string>
83 <string name="notification_no_directory_link">Nem sikerült megnyitni a yuzu könyvtárat</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>
85 <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>
87 <string name="import_export_saves_description">Mentési fájlok importálás vagy exportálása</string>
88 <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>
90 <string name="save_file_invalid_zip_structure_description">Az első almappa neve a játék azonosítója kell, hogy legyen.</string>
91 <string name="import_saves">Importálás</string>
92 <string name="export_saves">Exportálás</string>
93 <string name="install_firmware">Firmware telepítés</string>
94 <string name="install_firmware_description">A firmwarenek ZIP archívumban kell lennie, és szükséges a játékok indításához</string>
95 <string name="firmware_installing">Firmware telepítése</string>
96 <string name="firmware_installed_success">Firmware sikeresen telepítve</string>
97 <string name="firmware_installed_failure">Firmware telepítése sikertelen</string>
98 <string name="firmware_installed_failure_description">Győződj meg róla, hogy a firmware nca fájlok a zip gyökerénél vannak, és próbáld meg újra.</string>
99 <string name="share_log">Hibakereső logok megosztása</string>
100 <string name="share_log_description">A yuzu naplófájl megosztása a problémák elhárításához</string>
101 <string name="share_log_missing">Nem található log fájl</string>
102 <string name="install_game_content">Játéktartalom telepítése</string>
103 <string name="install_game_content_description">Játékfrissítések vagy DLC telepítése</string>
104 <string name="installing_game_content">Tartalom telepítése...</string>
105 <string name="install_game_content_failure">Hiba történt a fájl(ok) NAND-ra telepítése közben</string>
106 <string name="install_game_content_failure_description">Győződj meg róla, hogy a tartalom valós, és a prod.keys fájl telepítve van.</string>
107 <string name="install_game_content_failure_base">Az alapjátékok telepítése nem engedélyezett az esetleges konfliktusok elkerülése érdekében.</string>
108 <string name="install_game_content_failure_file_extension">Csak NSP és XCI tartalom támogatott. Győződj meg róla, hogy a játéktartalom érvényes.</string>
109 <string name="install_game_content_failed_count">%1$d telepítési hiba</string>
110 <string name="install_game_content_success">Játéktartalom sikeresen telepítve</string>
111 <string name="install_game_content_success_install">%1$d sikeresen telepítve</string>
112 <string name="install_game_content_success_overwrite">%1$d sikeresen felülírva</string>
113 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
114 <string name="custom_driver_not_supported">Egyéni illesztőprogramok nem támogatottak</string>
115 <string name="custom_driver_not_supported_description">Egyéni illesztőprogram telepítése jelenleg nem támogatott ezen az eszközön.\nNézz vissza később, hátha hozzáadtuk a támogatását!</string>
116 <string name="manage_yuzu_data">yuzu adatok kezelése</string>
117 <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>
119 <string name="export_save_failed">A mentés exportálása sikertelen</string>
120
121 <!-- About screen strings -->
122 <string name="gaia_is_not_real">Gaia nem valódi</string>
123 <string name="copied_to_clipboard">Másolva a vágólapra</string>
124 <string name="about_app_description">Egy nyílt forráskódú Switch emulátor</string>
125 <string name="contributors">Hozzájárulók</string>
126 <string name="contributors_description">\u2764 által készítve a yuzu csapattól</string>
127 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
128 <string name="licenses_description">Projektek, amik nélkül a yuzu nem jöhetett volna létre Androidra</string>
129 <string name="user_data">Felhasználói adatok</string>
130 <string name="user_data_description">Az összes alkalmazásadat importálása/exportálása.\n\nA felhasználói adatok importálásakor az összes meglévő felhasználói adat törlődik!</string>
131 <string name="exporting_user_data">Felhasználói adatok exportálása...</string>
132 <string name="importing_user_data">Felhasználói adatok importálása...</string>
133 <string name="import_user_data">Felhasználói adatok importálása</string>
134 <string name="invalid_yuzu_backup">Érvénytelen yuzu biztonsági másolat</string>
135 <string name="user_data_export_success">Felhasználói adatok sikeresen exportálva</string>
136 <string name="user_data_import_success">Felhasználói adatok sikeresen importálva</string>
137 <string name="user_data_export_cancelled">Exportálás megszakítva</string>
138 <string name="user_data_import_failed_description">Ellenőrizd, hogy a felhasználói adatok mappái a zip mappa gyökerében vannak, és tartalmaznak egy konfig fájlt a config/config.ini címen, majd próbáld meg újra.</string>
139 <string name="support_link">https://discord.gg/u77vRWY</string>
140 <string name="website_link">https://yuzu-emu.org/</string>
141 <string name="github_link">https://github.com/yuzu-emu</string>
142
143 <!-- Early access upgrade strings -->
144 <string name="early_access">Korai hozzáférés</string>
145 <string name="get_early_access">Szerezz korai hozzáférést</string>
146 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
147 <string name="get_early_access_description">Legújabb funkciók, korai hozzáférés a frissítésekhez, és sok más</string>
148 <string name="early_access_benefits">Korai hozzáférés előnyei</string>
149 <string name="cutting_edge_features">Legújabb funkciók</string>
150 <string name="early_access_updates">Korai hozzáférés a frissítésekhez</string>
151 <string name="no_manual_installation">Automatikus telepítések</string>
152 <string name="prioritized_support">Priorizált támogatás</string>
153 <string name="our_eternal_gratitude">Valamint az örök hálánk</string>
154 <string name="are_you_interested">Érdekel a dolog?</string>
155
156 <!-- General settings strings -->
157 <string name="frame_limit_enable">Sebességkorlát</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>
159 <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>
161 <string name="cpu_accuracy">CPU pontosság</string>
162 <string name="value_with_units">%1$s%2$s</string>
163
164 <!-- System settings strings -->
165 <string name="use_docked_mode">Dokkolt mód</string>
166 <string name="use_docked_mode_description">Növeli a felbontást, de csökkenti a teljesítményt. Kikapcsolás esetén a Kézi mód van használatban, ami kisebb felbontást, de nagyobb teljesítményt eredményez.</string>
167 <string name="emulated_region">Emulált régió</string>
168 <string name="emulated_language">Emulált nyelv</string>
169 <string name="select_rtc_date">Válassz RTC dátumot</string>
170 <string name="select_rtc_time">Válassz RTC időt</string>
171 <string name="use_custom_rtc">Egyéni RTC</string>
172 <string name="use_custom_rtc_description">Megadhatsz egy valós idejű órát, amely eltér a rendszer által használt órától.</string>
173 <string name="set_custom_rtc">Egyéni RTC beállítása</string>
174
175 <!-- Graphics settings strings -->
176 <string name="renderer_accuracy">Pontosság szintje</string>
177 <string name="renderer_resolution">Felbontás (Kézi/Dockolt)</string>
178 <string name="renderer_vsync">VSync mód</string>
179 <string name="renderer_screen_layout">Orientáció</string>
180 <string name="renderer_aspect_ratio">Képarány</string>
181 <string name="renderer_scaling_filter">Ablakhoz alkalmazkodó szűrő</string>
182 <string name="renderer_anti_aliasing">Élsimítási módszer</string>
183 <string name="renderer_force_max_clock">Maximum órajel kényszerítése (csak Adreno)</string>
184 <string name="renderer_force_max_clock_description">Kényszeríti a GPU-t a lehető legnagyobb órajelen működésre (a hőmérséklet korlátozások továbbra is érvényben maradnak).</string>
185 <string name="renderer_asynchronous_shaders">Aszinkron árnyékolók használata</string>
186 <string name="renderer_asynchronous_shaders_description">Aszinkron módon fordítja az árnyékolókat, ami csökkenti az akadozást, de hibákat okozhat.</string>
187 <string name="renderer_reactive_flushing">Reaktív ürítés használata</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>
189 <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>
191
192 <!-- Debug settings strings -->
193 <string name="cpu">CPU</string>
194 <string name="cpu_debug_mode">CPU hibakeresés</string>
195 <string name="cpu_debug_mode_description">Lassú hibakereső módba állítja a CPU-t.</string>
196 <string name="gpu">GPU</string>
197 <string name="renderer_api">API</string>
198 <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>
200 <!-- Audio settings strings -->
201 <string name="audio_output_engine">Kimeneti rendszer</string>
202 <string name="audio_volume">Hangerő</string>
203 <string name="audio_volume_description">Hangkimenet hangerejének megadása</string>
204
205 <!-- Miscellaneous -->
206 <string name="slider_default">Alapértelmezett</string>
207 <string name="ini_saved">Beállítások elmentve</string>
208 <string name="gameid_saved">Beállítások elmentve a következőhöz: %1$s</string>
209 <string name="error_saving">Mentési hiba%1$s .ini: %2$s</string>
210 <string name="unimplemented_menu">Nem implementált menü</string>
211 <string name="loading">Betöltés...</string>
212 <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>
214 <string name="reset_to_default">Alaphelyzetbe állítás</string>
215 <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>
217 <string name="settings_reset">Beállítások alaphelyzetbe állítva</string>
218 <string name="close">Bezárás</string>
219 <string name="learn_more">Tudj meg többet</string>
220 <string name="auto">Automatikus</string>
221 <string name="submit">Küldés</string>
222 <string name="string_null">Nulla</string>
223 <string name="string_import">Importálás</string>
224 <string name="export">Exportálás</string>
225 <string name="export_failed">Exportálás sikertelen</string>
226 <string name="import_failed">Importálás sikertelen</string>
227 <string name="cancelling">Megszakítás</string>
228
229 <!-- GPU driver installation -->
230 <string name="select_gpu_driver">Válassz GPU illesztőprogramot</string>
231 <string name="select_gpu_driver_title">Szeretnéd lecserélni a jelenlegi GPU illesztőprogramot?</string>
232 <string name="select_gpu_driver_install">Telepítés</string>
233 <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>
235 <string name="select_gpu_driver_error">Érvénytelen driver kiválasztva, a rendszer alapértelmezett lesz használva!</string>
236 <string name="system_gpu_driver">Rendszer GPU illesztőprogram</string>
237 <string name="installing_driver">Illesztőprogram telepítése...</string>
238
239 <!-- Preferences Screen -->
240 <string name="preferences_settings">Beállítások</string>
241 <string name="preferences_general">Ãltalános</string>
242 <string name="preferences_system">Rendszer</string>
243 <string name="preferences_graphics">Grafika</string>
244 <string name="preferences_audio">Hang</string>
245 <string name="preferences_theme">Téma és színek</string>
246 <string name="preferences_debug">Hibakeresés</string>
247
248 <!-- ROM loading errors -->
249 <string name="loader_error_encrypted">ROM titkosítva</string>
250 <string name="loader_error_encrypted_keys_description"><![CDATA[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 telepítve van, hogy a játékok visszafejthetők legyenek.]]></string>
251 <string name="loader_error_video_core">Hiba lépett fel a videómag inicializása során</string>
252 <string name="loader_error_video_core_description">Ezt általában egy nem kompatibilis GPU illesztő okozza. Egyéni GPU illesztőprogram telepítése megoldhatja a problémát.</string>
253 <string name="loader_error_invalid_format">Nem sikerült betölteni a ROM-ot</string>
254 <string name="loader_error_file_not_found">ROM fájl nem létezik</string>
255
256 <!-- Emulation Menu -->
257 <string name="emulation_exit">Emuláció bezárása</string>
258 <string name="emulation_done">Kész</string>
259 <string name="emulation_fps_counter">FPS számláló</string>
260 <string name="emulation_toggle_controls">Irányítás átkapcsolása</string>
261 <string name="emulation_dpad_slide">D-pad csúsztatása</string>
262 <string name="emulation_haptics">Érintés haptikája</string>
263 <string name="emulation_show_overlay">Ãtfedés mutatása</string>
264 <string name="emulation_toggle_all">Össze átkapcsolása</string>
265 <string name="emulation_control_adjust">Ãtfedés testreszabása</string>
266 <string name="emulation_control_scale">Skálázás</string>
267 <string name="emulation_control_opacity">Ãtlátszóság</string>
268 <string name="emulation_touch_overlay_reset">Ãtfedés visszaállítása</string>
269 <string name="emulation_touch_overlay_edit">Ãtfedés módosítása</string>
270 <string name="emulation_pause">Emuláció szünetelése</string>
271 <string name="emulation_unpause">Emuláció folytatása</string>
272 <string name="emulation_input_overlay">Ãtfedés beállításai</string>
273
274 <string name="load_settings">Beállítások betöltése...</string>
275
276 <!-- Software keyboard -->
277 <string name="software_keyboard">Szoftver billenytűzet</string>
278
279 <!-- Errors and warnings -->
280 <string name="abort_button">Megszakítás</string>
281 <string name="continue_button">Folytatás</string>
282 <string name="system_archive_not_found">Nem található rendszerarchívum</string>
283 <string name="system_archive_not_found_message">%s hiányzik. Kérjük, mentsd ki a rendszerarchívumaidat.\nAz emuláció folytatása összeomlásokhoz és hibákhoz vezethet.</string>
284 <string name="system_archive_general">Egy rendszerarchívum</string>
285 <string name="save_load_error">Mentési/betöltési hiba</string>
286 <string name="fatal_error">Végzetes hiba</string>
287 <string name="fatal_error_message">Végzetes hiba történt. Ellenőrizd a logot a részletekért.\nAz emuláció folytatása összeomlást és hibákat eredményzhet.</string>
288 <string name="performance_warning">Ennek a beállításnak a kikapcsolása jelentős mértékben csökkenti a teljesítményt! A legjobb élmény érdekében javasolt a beállítás bekapcsolva tartása.</string>
289 <string name="device_memory_inadequate">Eszköz RAM: %1$s\nAjánlott: %2$s</string>
290 <string name="memory_formatted">%1$s %2$s</string>
291 <string name="no_game_present">Nincs indítható játék!</string>
292
293 <!-- Region Names -->
294 <string name="region_japan">Japán</string>
295 <string name="region_usa">USA</string>
296 <string name="region_europe">Európa</string>
297 <string name="region_australia">Ausztrália</string>
298 <string name="region_china">Kína</string>
299 <string name="region_korea">Korea</string>
300 <string name="region_taiwan">Tajvan</string>
301
302 <!-- Memory Sizes -->
303 <string name="memory_byte">Bájt</string>
304 <string name="memory_kilobyte">KB</string>
305 <string name="memory_megabyte">MB</string>
306 <string name="memory_gigabyte">GB</string>
307 <string name="memory_terabyte">TB</string>
308 <string name="memory_petabyte">PB</string>
309 <string name="memory_exabyte">EB</string>
310
311 <!-- Renderer APIs -->
312 <string name="renderer_vulkan">Vulkan</string>
313 <string name="renderer_none">Nincs</string>
314
315 <!-- Renderer Accuracy -->
316 <string name="renderer_accuracy_normal">Normál</string>
317 <string name="renderer_accuracy_high">Magas</string>
318 <string name="renderer_accuracy_extreme">Extrém (Lassú)</string>
319
320 <!-- Resolutions -->
321 <string name="resolution_half">0.5X (360p/540p)</string>
322 <string name="resolution_three_quarter">0.75X (540p/810p)</string>
323 <string name="resolution_one">1X (720p/1080p)</string>
324 <string name="resolution_two">2X (1440p/2160p) (Lassú)</string>
325 <string name="resolution_three">3X (2160p/3240p) (Lassú)</string>
326 <string name="resolution_four">4X (2880p/4320p) (Lassú)</string>
327
328 <!-- Renderer VSync -->
329 <string name="renderer_vsync_immediate">Azonnali (Ki)</string>
330 <string name="renderer_vsync_mailbox">Postaláda</string>
331 <string name="renderer_vsync_fifo">FIFO (Be)</string>
332 <string name="renderer_vsync_fifo_relaxed">FIFO Relaxált</string>
333
334 <!-- Scaling Filters -->
335 <string name="scaling_filter_nearest_neighbor">Legközelebbi szomszéd</string>
336 <string name="scaling_filter_bilinear">Bilineáris</string>
337 <string name="scaling_filter_bicubic">Bikubikus</string>
338 <string name="scaling_filter_gaussian">Gauss-féle</string>
339 <string name="scaling_filter_scale_force">ScaleForce</string>
340 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string>
341
342 <!-- Anti-Aliasing -->
343 <string name="anti_aliasing_none">Nincs</string>
344 <string name="anti_aliasing_fxaa">FXAA</string>
345 <string name="anti_aliasing_smaa">SMAA</string>
346
347 <!-- Screen Layouts -->
348 <string name="screen_layout_landscape">Fekvő</string>
349 <string name="screen_layout_portrait">Ãlló</string>
350 <string name="screen_layout_auto">Automatikus</string>
351
352 <!-- Aspect Ratios -->
353 <string name="ratio_default">Alapértelmezett (16:9)</string>
354 <string name="ratio_force_four_three">4:3 kényszerítése</string>
355 <string name="ratio_force_twenty_one_nine">21:9 kényszerítése</string>
356 <string name="ratio_force_sixteen_ten">16:10 kényszerítése</string>
357 <string name="ratio_stretch">Ablakhoz nyújtás</string>
358
359 <!-- CPU Accuracy -->
360 <string name="cpu_accuracy_accurate">Pontos</string>
361 <string name="cpu_accuracy_unsafe">Nem biztonságos</string>
362 <string name="cpu_accuracy_paranoid">Paranoid (Lassú)</string>
363
364 <!-- Gamepad Buttons -->
365 <string name="gamepad_d_pad">D-pad</string>
366 <string name="gamepad_left_stick">Bal kar</string>
367 <string name="gamepad_right_stick">Jobb kar</string>
368 <string name="gamepad_home">Home</string>
369 <string name="gamepad_screenshot">Képernyőmentés</string>
370
371 <!-- Disk shader cache -->
372 <string name="preparing_shaders">Ãrnyékolók elÅ‘készítése</string>
373 <string name="building_shaders">Ãrnyékolók létrehozása</string>
374
375 <!-- Theme options -->
376 <string name="change_app_theme">Alkalmazás témájának módosítása</string>
377 <string name="theme_default">Alapértelmezett</string>
378 <!-- Theme Modes -->
379 <string name="change_theme_mode">Téma váltása</string>
380 <string name="theme_mode_follow_system">Rendszerbeállítások használata</string>
381 <string name="theme_mode_light">Világos</string>
382 <string name="theme_mode_dark">Sötét</string>
383
384 <!-- Audio output engines -->
385 <string name="cubeb">cubeb</string>
386
387 <!-- Black backgrounds theme -->
388 <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>
390
391 <!-- Picture-In-Picture -->
392 <string name="picture_in_picture">Kép a képben</string>
393 <string name="picture_in_picture_description">Ablak minimalizálása, amikor háttérbe kerül</string>
394 <string name="pause">Szünet</string>
395 <string name="play">Lejátszás</string>
396 <string name="mute">Némítás</string>
397 <string name="unmute">Némítás feloldása</string>
398
399 <!-- Licenses screen strings -->
400 <string name="licenses">Licenszek</string>
401 <string name="license_fidelityfx_fsr_description">Magas minőségű felskálázás az AMD-től</string>
402 </resources>
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 09c9345b0..5afebb4c4 100644
--- a/src/android/app/src/main/res/values-it/strings.xml
+++ b/src/android/app/src/main/res/values-it/strings.xml
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Questo software permette di giocare ai giochi della console Nintendo Switch. Nessun gioco o chiave è inclusa.&lt;br /&gt;&lt;br /&gt;Prima di iniziare, perfavore individua il file <![CDATA[<b>prod.keys </b>]]> nella memoria del tuo dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Scopri di più</a>]]></string> 4 <string name="app_disclaimer">Questo software permette di giocare ai giochi della console Nintendo Switch. Nessun gioco o chiave è inclusa.&lt;br /&gt;&lt;br /&gt;Prima di iniziare, perfavore individua il file <![CDATA[<b>prod.keys </b>]]> nella memoria del tuo dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Scopri di più</a>]]></string>
5 <string name="emulation_notification_channel_name">L\'emulatore è attivo</string> 5 <string name="emulation_notification_channel_name">L\'emulatore è attivo</string>
@@ -13,9 +13,9 @@
13 <string name="welcome">Benvenuto!</string> 13 <string name="welcome">Benvenuto!</string>
14 <string name="welcome_description">Scopri come configurare &lt;b>yuzu&lt;/b> e passare all\'emulazione.</string> 14 <string name="welcome_description">Scopri come configurare &lt;b>yuzu&lt;/b> e passare all\'emulazione.</string>
15 <string name="get_started">Iniziare</string> 15 <string name="get_started">Iniziare</string>
16 <string name="keys">Pulsanti</string> 16 <string name="keys">Chiavi</string>
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">Selezione Pulsanti</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 &lt;b>Games&lt;/b> con il pulsante in basso.</string>
21 <string name="done">Fatto</string> 21 <string name="done">Fatto</string>
@@ -25,6 +25,7 @@
25 <string name="back">Indietro</string> 25 <string name="back">Indietro</string>
26 <string name="add_games">Aggiungi giochi</string> 26 <string name="add_games">Aggiungi giochi</string>
27 <string name="add_games_description">Seleziona la cartella dei giochi</string> 27 <string name="add_games_description">Seleziona la cartella dei giochi</string>
28 <string name="step_complete">Completato!</string>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">Giochi</string> 31 <string name="home_games">Giochi</string>
@@ -38,6 +39,7 @@
38 <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>
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">Cerca giochi</string> 41 <string name="home_search_games">Cerca giochi</string>
42 <string name="search_settings">Cerca impostazione</string>
41 <string name="games_dir_selected">Cartella dei giochi selezionata</string> 43 <string name="games_dir_selected">Cartella dei giochi selezionata</string>
42 <string name="install_prod_keys">Installa prod.keys</string> 44 <string name="install_prod_keys">Installa prod.keys</string>
43 <string name="install_prod_keys_description">Necessario per decrittografare i giochi</string> 45 <string name="install_prod_keys_description">Necessario per decrittografare i giochi</string>
@@ -61,15 +63,18 @@
61 <string name="invalid_keys_file">Selezionate chiavi non valide</string> 63 <string name="invalid_keys_file">Selezionate chiavi non valide</string>
62 <string name="install_keys_success">Chiavi installate correttamente</string> 64 <string name="install_keys_success">Chiavi installate correttamente</string>
63 <string name="reading_keys_failure">Errore durante la lettura delle chiavi di crittografia</string> 65 <string name="reading_keys_failure">Errore durante la lettura delle chiavi di crittografia</string>
66 <string name="install_prod_keys_failure_extension_description">Controlla che le tue chiavi abbiano l\'estensione .keys e prova di nuovo.</string>
67 <string name="install_amiibo_keys_failure_extension_description">Controlla che le tue chiavi abbiano l\'estensione .bin e prova di nuovo</string>
64 <string name="invalid_keys_error">Chiavi di crittografia non valide</string> 68 <string name="invalid_keys_error">Chiavi di crittografia non valide</string>
65 <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>
66 <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>
67 <string name="install_gpu_driver">Installa i driver GPU</string> 71 <string name="install_gpu_driver">Installa i driver GPU</string>
68 <string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string> 72 <string name="install_gpu_driver_description">Installa driver alternativi per potenziali prestazioni migliori o accuratezza.</string>
69 <string name="advanced_settings">Impostazioni avanzate</string> 73 <string name="advanced_settings">Impostazioni avanzate</string>
74 <string name="advanced_settings_game">Impostazioni Avanzate: %1$s</string>
70 <string name="settings_description">Configura le impostazioni dell\'emulatore</string> 75 <string name="settings_description">Configura le impostazioni dell\'emulatore</string>
71 <string name="search_recently_played">Giocato recentemente</string> 76 <string name="search_recently_played">Giocati recentemente</string>
72 <string name="search_recently_added">Aggiunto recentemente</string> 77 <string name="search_recently_added">Aggiunti recentemente</string>
73 <string name="search_retail">Rivenditore</string> 78 <string name="search_retail">Rivenditore</string>
74 <string name="search_homebrew">Homebrew</string> 79 <string name="search_homebrew">Homebrew</string>
75 <string name="open_user_folder">Apri la cartella di yuzu</string> 80 <string name="open_user_folder">Apri la cartella di yuzu</string>
@@ -86,6 +91,33 @@
86 <string name="save_file_invalid_zip_structure_description">La prima sotto cartella <b>deve</b> chiamarsi come l\'ID del titolo del gioco.</string> 91 <string name="save_file_invalid_zip_structure_description">La prima sotto cartella <b>deve</b> chiamarsi come l\'ID del titolo del gioco.</string>
87 <string name="import_saves">Importa</string> 92 <string name="import_saves">Importa</string>
88 <string name="export_saves">Esporta</string> 93 <string name="export_saves">Esporta</string>
94 <string name="install_firmware">Installa firmware</string>
95 <string name="install_firmware_description">Il firmware deve essere in un archivio ZIP ed è necessario per avviare alcuni giochi</string>
96 <string name="firmware_installing">Installando il firmware</string>
97 <string name="firmware_installed_success">Firmware installato con successo</string>
98 <string name="firmware_installed_failure">L\'installazione del firmware è fallita</string>
99 <string name="firmware_installed_failure_description">Accertati che i file .nca del firmware siano contenuti direttamente nella radice dello .zip e riprova.</string>
100 <string name="share_log">Condividi log di debug</string>
101 <string name="share_log_description">Condividi i log di yuzu per ricevere supporto</string>
102 <string name="share_log_missing">Nessun file di log trovato</string>
103 <string name="install_game_content">Installa contenuti di gioco</string>
104 <string name="install_game_content_description">Installa aggiornamenti o DLC</string>
105 <string name="installing_game_content">Installazione dei contenuti...</string>
106 <string name="install_game_content_failure">Errore durante l\'installazione del contenuto in NAND.</string>
107 <string name="install_game_content_failure_description">Accertati che i contenuti da installare siano validi e che le prod.keys siano presenti.</string>
108 <string name="install_game_content_failure_base">Installare i giochi base in NAND non è permesso, perché potrebbe causare dei conflitti con altri tipi di contenuti(Aggiornamenti e DLC)</string>
109 <string name="install_game_content_failure_file_extension">Solo i tipi NSP e XCI sono supportati. Verifica che i contenuti di gioco siano validi.</string>
110 <string name="install_game_content_failed_count">Errori di installazione: %1$d</string>
111 <string name="install_game_content_success">Contenuto/i di gioco installato/i con successo.</string>
112 <string name="install_game_content_success_install">%1$dinstallato con successo.</string>
113 <string name="install_game_content_success_overwrite">%1$dsovrascritto con successo</string>
114 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
115 <string name="custom_driver_not_supported">I driver personalizzati non sono supportati.</string>
116 <string name="custom_driver_not_supported_description">I driver personalizzati non sono attualmente supportati su questo dispositivo.\n Ricontrolla in futuro.</string>
117 <string name="manage_yuzu_data">Gestisci i dati di Yuzu</string>
118 <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="export_save_failed">Errore durante l\'esportazione del salvataggio</string>
89 121
90 <!-- About screen strings --> 122 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia non è reale</string> 123 <string name="gaia_is_not_real">Gaia non è reale</string>
@@ -94,7 +126,18 @@
94 <string name="contributors">Collaboratori</string> 126 <string name="contributors">Collaboratori</string>
95 <string name="contributors_description">Realizzato con \u2764 dal team yuzu</string> 127 <string name="contributors_description">Realizzato con \u2764 dal team yuzu</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">Progetti che rendono yuzu per Android possibile</string>
97 <string name="build">Compilazione</string> 130 <string name="build">Compilazione</string>
131 <string name="user_data">Dati Utente</string>
132 <string name="user_data_description">Importa/Esporta tutti i dati dell\'applicazione.\n\nDurante l\'importazione dei Dati Utente, quelli già esistenti verranno ELIMINATI.</string>
133 <string name="exporting_user_data">Esportazione dei Dati Utente...</string>
134 <string name="importing_user_data">Importazione dei Dati Utente...</string>
135 <string name="import_user_data">Importa i Dati Utente</string>
136 <string name="invalid_yuzu_backup">Backup di Yuzu Invalido</string>
137 <string name="user_data_export_success">Dati Utente esportati con successo</string>
138 <string name="user_data_import_success">Dati Utente importati con successo.</string>
139 <string name="user_data_export_cancelled">Esportazione annullata</string>
140 <string name="user_data_import_failed_description">Assicurati che la cartella dei Dati dell\'utente stiano nella radice del file.zip e che sia presente una cartella config in config/config.ini, poi, riprova.</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 141 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 142 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 143 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -114,41 +157,53 @@
114 <string name="are_you_interested">Sei interessato?</string> 157 <string name="are_you_interested">Sei interessato?</string>
115 158
116 <!-- General settings strings --> 159 <!-- General settings strings -->
117 <string name="frame_limit_enable">Abilita il limite di velocità</string> 160 <string name="frame_limit_enable">Limita velocità</string>
118 <string name="frame_limit_enable_description">Quando abilitato, la velocità di emulazione verrà limitata a una specifica percentuale della velocità normale.</string> 161 <string name="frame_limit_enable_description">Limita la velocità dell\'emulazione a una specifica percentuale della velocità normale.</string>
119 <string name="frame_limit_slider">Limite velocità percentuale</string> 162 <string name="frame_limit_slider">Limite velocità percentuale</string>
120 <string name="frame_limit_slider_description">Specifica la percentuale del limite della velocità di emulazione. Con quella preimpostata al 100% l\'emulazione verrà limitata alla velocità normale. Valori più alti o bassi aumenteranno o diminuiranno il limite di velocità.</string> 163 <string name="frame_limit_slider_description">Specifica la percentuale per limitare la velocità di emulazione. 100% è la velocità normale. Valori maggiori o minori aumenteranno o diminuiranno il limite di velocità</string>
121 <string name="cpu_accuracy">Accuratezza della CPU</string> 164 <string name="cpu_accuracy">Accuratezza della CPU</string>
165 <string name="value_with_units">%1$s%2$s</string>
122 166
123 <!-- System settings strings --> 167 <!-- System settings strings -->
124 <string name="use_docked_mode">Modalità docked</string> 168 <string name="use_docked_mode">Modalità Docked</string>
125 <string name="use_docked_mode_description">Emula in modalità docked, questo aumenta la risoluzione a spese delle performance.</string> 169 <string name="use_docked_mode_description">Aumenta la risoluzione, diminuendo le performance. La modalità portatile è usata quando disabilitato, diminuendo la risoluzione e aumentando le performance.</string>
126 <string name="emulated_region">Regione emulata</string> 170 <string name="emulated_region">Regione emulata</string>
127 <string name="emulated_language">Lingua emulata</string> 171 <string name="emulated_language">Lingua emulata</string>
128 <string name="select_rtc_date">Seleziona la data dall\'orologio in tempo reale</string> 172 <string name="select_rtc_date">Imposta la data </string>
129 <string name="select_rtc_time">Seleziona il tempo dall\'orologio in tempo reale</string> 173 <string name="select_rtc_time">Imposta l\'ora, i minuti e i secondi.</string>
130 <string name="use_custom_rtc">Abilità l\'orologio in tempo reale personalizzato</string> 174 <string name="use_custom_rtc">RTC Personalizzato</string>
131 <string name="use_custom_rtc_description">Questa impostazione ti permette di impostare un orologio in tempo reale personalizzato separato da quello del tuo sistema corrente.</string> 175 <string name="use_custom_rtc_description">Ti permette di impostare un orologio in tempo reale personalizzato, completamente separato da quello di sistema.</string>
132 <string name="set_custom_rtc">Imposta l\'orologio in tempo reale personalizzato</string> 176 <string name="set_custom_rtc">Imposta un orologio in tempo reale personalizzato</string>
133 177
134 <!-- Graphics settings strings --> 178 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Livello di accuratezza</string> 179 <string name="renderer_accuracy">Livello di accuratezza</string>
137 <string name="renderer_resolution">Risoluzione</string> 180 <string name="renderer_resolution">Risoluzione (Portatile/Docked)</string>
138 <string name="renderer_vsync">Modalità VSync</string> 181 <string name="renderer_vsync">Modalità VSync</string>
139 <string name="renderer_aspect_ratio">Rapporto d\'aspetto</string> 182 <string name="renderer_screen_layout">Orientamento</string>
140 <string name="renderer_scaling_filter">Filtro di adattamento alla finestra</string> 183 <string name="renderer_aspect_ratio">Rapporto d\'aspetto: </string>
184 <string name="renderer_scaling_filter">Filtro adattivo della finestra </string>
141 <string name="renderer_anti_aliasing">Metodo di anti-aliasing</string> 185 <string name="renderer_anti_aliasing">Metodo di anti-aliasing</string>
142 <string name="renderer_force_max_clock">Forza clock massimi (solo Adreno)</string> 186 <string name="renderer_force_max_clock">Forza clock massimi (solo Adreno)</string>
143 <string name="renderer_force_max_clock_description">Forza la GPU a girare col massimo clock possibile (i vincoli alla temperatura saranno comunque applicati)</string> 187 <string name="renderer_force_max_clock_description">Forza la GPU a girare col massimo clock possibile (i vincoli alla temperatura saranno comunque applicati)</string>
144 <string name="renderer_asynchronous_shaders">Usa shaders asincrone</string> 188 <string name="renderer_asynchronous_shaders">Usa shaders asincrone</string>
145 <string name="renderer_asynchronous_shaders_description">Compila le shaders asincronamente, questo riduce lo shutter ma potrebbe introdurre dei glitch. </string> 189 <string name="renderer_asynchronous_shaders_description">Compila le shader in modo asincrone, riducendo lo stutter. Può causare glitch grafici.</string>
146 <string name="renderer_debug">Abilità il debug grafico</string> 190 <string name="renderer_reactive_flushing">Abilita il Reactive Flushing</string>
147 <string name="renderer_debug_description">Quando l\'opzione è selezionata, l\'API grafica entra in una modalità di debug più lenta</string> 191 <string name="renderer_reactive_flushing_description">Migliora l\'accuratezza della grafica in alcuni giochi, al costo delle performance.</string>
148 <string name="use_disk_shader_cache">Usa cache shader su disco</string> 192 <string name="use_disk_shader_cache">Usa la cache delle shader</string>
149 <string name="use_disk_shader_cache_description">Riduce lo stuttering salvando e caricando le shader generate sul disco.</string> 193 <string name="use_disk_shader_cache_description">Riduce lo stuttering caricando le shader già compilate all\'avvio.</string>
194
195 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">Debug della CPU</string>
198 <string name="cpu_debug_mode_description">Imposta la CPU in modalità Debug (Più lento)</string>
199 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string>
201 <string name="renderer_debug">Debug GPU</string>
202 <string name="renderer_debug_description">Imposta l\'API grafica in uno stato dedicato al Debugging. Impatta di molto sulle performance.</string>
203 <string name="fastmem">Fastmem</string>
150 204
151 <!-- Audio settings strings --> 205 <!-- Audio settings strings -->
206 <string name="audio_output_engine">Motore di Output</string>
152 <string name="audio_volume">Volume</string> 207 <string name="audio_volume">Volume</string>
153 <string name="audio_volume_description">Specifica il volume dell\'audio in uscita.</string> 208 <string name="audio_volume_description">Specifica il volume dell\'audio in uscita.</string>
154 209
@@ -157,14 +212,24 @@
157 <string name="ini_saved">Impostazioni salvate</string> 212 <string name="ini_saved">Impostazioni salvate</string>
158 <string name="gameid_saved">Impostazioni salvate per %1$s</string> 213 <string name="gameid_saved">Impostazioni salvate per %1$s</string>
159 <string name="error_saving">Errore nel salvare %1$s.ini %2$s</string> 214 <string name="error_saving">Errore nel salvare %1$s.ini %2$s</string>
215 <string name="unimplemented_menu">Menu non implementato</string>
160 <string name="loading">Caricamento…</string> 216 <string name="loading">Caricamento…</string>
217 <string name="shutting_down">Spegnimento...</string>
161 <string name="reset_setting_confirmation">Vuoi ripristinare queste impostazioni al loro valore originale?</string> 218 <string name="reset_setting_confirmation">Vuoi ripristinare queste impostazioni al loro valore originale?</string>
162 <string name="reset_to_default">Riportare alle impostazioni originali</string> 219 <string name="reset_to_default">Riportare alle impostazioni originali</string>
163 <string name="reset_all_settings">Resettare tutte le impostazioni?</string> 220 <string name="reset_all_settings">Resettare tutte le impostazioni?</string>
164 <string name="reset_all_settings_description">Tutte le Impostazioni Avanzate saranno ripristinate a quelle originali. Questa operazione non è reversibile</string> 221 <string name="reset_all_settings_description">Le impostazione avanzate verranno completamente reimpostate. Questa operazione è IRREVERSIBILE.</string>
165 <string name="settings_reset">Reimposta le impostazioni</string> 222 <string name="settings_reset">Reimposta le impostazioni</string>
166 <string name="close">Chiudi</string> 223 <string name="close">Chiudi</string>
167 <string name="learn_more">Per saperne di più</string> 224 <string name="learn_more">Per saperne di più</string>
225 <string name="auto">Automatico</string>
226 <string name="submit">Invia</string>
227 <string name="string_null">Nullo</string>
228 <string name="string_import">Importa</string>
229 <string name="export">Esporta</string>
230 <string name="export_failed">Esportazione Fallita</string>
231 <string name="import_failed">Importazione Fallita</string>
232 <string name="cancelling">Cancellazione</string>
168 233
169 <!-- GPU driver installation --> 234 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Seleziona il driver della GPU</string> 235 <string name="select_gpu_driver">Seleziona il driver della GPU</string>
@@ -172,6 +237,7 @@
172 <string name="select_gpu_driver_install">Installa</string> 237 <string name="select_gpu_driver_install">Installa</string>
173 <string name="select_gpu_driver_default">Predefinito</string> 238 <string name="select_gpu_driver_default">Predefinito</string>
174 <string name="select_gpu_driver_use_default">Utilizza il driver predefinito della GPU.</string> 239 <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>
175 <string name="system_gpu_driver">Driver GPU del sistema</string> 241 <string name="system_gpu_driver">Driver GPU del sistema</string>
176 <string name="installing_driver">Installando i driver...</string> 242 <string name="installing_driver">Installando i driver...</string>
177 243
@@ -182,10 +248,11 @@
182 <string name="preferences_graphics">Grafica</string> 248 <string name="preferences_graphics">Grafica</string>
183 <string name="preferences_audio">Audio</string> 249 <string name="preferences_audio">Audio</string>
184 <string name="preferences_theme">Tema e colori</string> 250 <string name="preferences_theme">Tema e colori</string>
251 <string name="preferences_debug">Debug</string>
185 252
186 <!-- ROM loading errors --> 253 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">La tua ROM è criptata</string> 254 <string name="loader_error_encrypted">La tua ROM è criptata</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[Per favore segui la guida per eseguire il dump della <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">cartuccia di gioco</a> o i <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">titoli installati</a>.]]></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>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[Per favore assicurati che il file <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> sia installato in modo che i giochi possano essere decrittati.]]></string> 256 <string name="loader_error_encrypted_keys_description"><![CDATA[Per favore assicurati che il file <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> sia installato in modo che i giochi possano essere decrittati.]]></string>
190 <string name="loader_error_video_core">È stato riscontrato un errore nell\'inizializzazione del core video</string> 257 <string name="loader_error_video_core">È stato riscontrato un errore nell\'inizializzazione del core video</string>
191 <string name="loader_error_video_core_description">Questo è causato solitamente dal driver incompatibile di una GPU. L\'installazione di driver GPU personalizzati potrebbe risolvere questo problema.</string> 258 <string name="loader_error_video_core_description">Questo è causato solitamente dal driver incompatibile di una GPU. L\'installazione di driver GPU personalizzati potrebbe risolvere questo problema.</string>
@@ -193,28 +260,28 @@
193 <string name="loader_error_file_not_found">Il file della ROM non esiste</string> 260 <string name="loader_error_file_not_found">Il file della ROM non esiste</string>
194 261
195 <!-- Emulation Menu --> 262 <!-- Emulation Menu -->
196 <string name="emulation_exit">Uscire dall\'emulazione</string> 263 <string name="emulation_exit">Arresta emulazione</string>
197 <string name="emulation_done">Fatto</string> 264 <string name="emulation_done">Fatto</string>
198 <string name="emulation_fps_counter">Contatore degli FPS</string> 265 <string name="emulation_fps_counter">Contatore FPS</string>
199 <string name="emulation_toggle_controls">Controlli a interruttore</string> 266 <string name="emulation_toggle_controls">Controlli a interruttore</string>
200 <string name="emulation_rel_stick_center">Centro relativo degli Stick</string> 267 <string name="emulation_rel_stick_center">Centro relativo degli Stick</string>
201 <string name="emulation_dpad_slide">Slittamento del Pad Direzionale</string> 268 <string name="emulation_dpad_slide">DPad A Scorrimento</string>
202 <string name="emulation_haptics">Aptico</string> 269 <string name="emulation_haptics">Feedback Aptico</string>
203 <string name="emulation_show_overlay">Mostra Overlay</string> 270 <string name="emulation_show_overlay">Mostra l\'Overlay</string>
204 <string name="emulation_toggle_all">Attiva/disattiva tutto</string> 271 <string name="emulation_toggle_all">Attiva/Disattiva tutto</string>
205 <string name="emulation_control_adjust">Aggiusta Overlay</string> 272 <string name="emulation_control_adjust">Modifica l\'Overlay</string>
206 <string name="emulation_control_scale">Scala</string> 273 <string name="emulation_control_scale">Scala</string>
207 <string name="emulation_control_opacity">Opacità</string> 274 <string name="emulation_control_opacity">Opacità</string>
208 <string name="emulation_touch_overlay_reset">Reimposta Overlay</string> 275 <string name="emulation_touch_overlay_reset">Reimposta l\'Overlay</string>
209 <string name="emulation_touch_overlay_edit">Modifica Overlay</string> 276 <string name="emulation_touch_overlay_edit">Modifica l\'Overlay</string>
210 <string name="emulation_pause">Metti in pausa l\'emulazione</string> 277 <string name="emulation_pause">Sospendi l\'emulazione</string>
211 <string name="emulation_unpause">Riprendi Emulazione</string> 278 <string name="emulation_unpause">Riprendi l\'emulazione</string>
212 <string name="emulation_input_overlay">Impostazioni Overlay</string> 279 <string name="emulation_input_overlay">Opzioni overlay</string>
213 280
214 <string name="load_settings">Caricamento delle impostazioni...</string> 281 <string name="load_settings">Carico le impostazioni...</string>
215 282
216 <!-- Software keyboard --> 283 <!-- Software keyboard -->
217 <string name="software_keyboard">Tastiera software</string> 284 <string name="software_keyboard">Tastiera Software</string>
218 285
219 <!-- Errors and warnings --> 286 <!-- Errors and warnings -->
220 <string name="abort_button">Interrompi</string> 287 <string name="abort_button">Interrompi</string>
@@ -226,6 +293,9 @@
226 <string name="fatal_error">Errore Fatale</string> 293 <string name="fatal_error">Errore Fatale</string>
227 <string name="fatal_error_message">Un errore fatale è accaduto. Controlla i log per i dettagli.\nContinuare ad emulare potrebbe portare bug o causare crash.</string> 294 <string name="fatal_error_message">Un errore fatale è accaduto. Controlla i log per i dettagli.\nContinuare ad emulare potrebbe portare bug o causare crash.</string>
228 <string name="performance_warning">Disattivare questa impostazione può ridurre significativamente le performance di emulazione! Per una migliore esperienza, è consigliato lasciare questa impostazione attivata.</string> 295 <string name="performance_warning">Disattivare questa impostazione può ridurre significativamente le performance di emulazione! Per una migliore esperienza, è consigliato lasciare questa impostazione attivata.</string>
296 <string name="device_memory_inadequate">RAM Totale:%1$s\nRaccomandati: %2$s</string>
297 <string name="memory_formatted">%1$s%2$s</string>
298 <string name="no_game_present">Non è presente alcun gioco avviabile.</string>
229 299
230 <!-- Region Names --> 300 <!-- Region Names -->
231 <string name="region_japan">Giappone</string> 301 <string name="region_japan">Giappone</string>
@@ -236,7 +306,14 @@
236 <string name="region_korea">Corea</string> 306 <string name="region_korea">Corea</string>
237 <string name="region_taiwan">Taiwan</string> 307 <string name="region_taiwan">Taiwan</string>
238 308
239 <!-- Language Names --> 309 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string>
311 <string name="memory_kilobyte">Kb</string>
312 <string name="memory_megabyte">Mb</string>
313 <string name="memory_gigabyte">GB</string>
314 <string name="memory_terabyte">Tb</string>
315 <string name="memory_petabyte">Pb</string>
316 <string name="memory_exabyte">Eb</string>
240 317
241 <!-- Renderer APIs --> 318 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 319 <string name="renderer_vulkan">Vulkan</string>
@@ -274,12 +351,17 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 351 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 352 <string name="anti_aliasing_smaa">SMAA</string>
276 353
354 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">Layout Orizzontale</string>
356 <string name="screen_layout_portrait">Layout Verticale</string>
357 <string name="screen_layout_auto">Automatico</string>
358
277 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
278 <string name="ratio_default">Predefinito (16:9)</string> 360 <string name="ratio_default">Predefinito (16:9)</string>
279 <string name="ratio_force_four_three">Forza 4:3</string> 361 <string name="ratio_force_four_three">Forza 4:3</string>
280 <string name="ratio_force_twenty_one_nine">Forza 21:9</string> 362 <string name="ratio_force_twenty_one_nine">Forza 21:9</string>
281 <string name="ratio_force_sixteen_ten">Forza 16:10</string> 363 <string name="ratio_force_sixteen_ten">Forza 16:10</string>
282 <string name="ratio_stretch">Allunga a finestra</string> 364 <string name="ratio_stretch">Adatta alla finestra</string>
283 365
284 <!-- CPU Accuracy --> 366 <!-- CPU Accuracy -->
285 <string name="cpu_accuracy_accurate">Accurata</string> 367 <string name="cpu_accuracy_accurate">Accurata</string>
@@ -287,9 +369,9 @@
287 <string name="cpu_accuracy_paranoid">Paranoico (Lento)</string> 369 <string name="cpu_accuracy_paranoid">Paranoico (Lento)</string>
288 370
289 <!-- Gamepad Buttons --> 371 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">D-Pad</string> 372 <string name="gamepad_d_pad">D-pad</string>
291 <string name="gamepad_left_stick">Levetta sinistra</string> 373 <string name="gamepad_left_stick">Analogico sinistro</string>
292 <string name="gamepad_right_stick">Levetta destra</string> 374 <string name="gamepad_right_stick">Analogico destro</string>
293 <string name="gamepad_home">Home</string> 375 <string name="gamepad_home">Home</string>
294 <string name="gamepad_screenshot">Screenshot</string> 376 <string name="gamepad_screenshot">Screenshot</string>
295 377
@@ -298,7 +380,7 @@
298 <string name="building_shaders">Costruendo gli shaders</string> 380 <string name="building_shaders">Costruendo gli shaders</string>
299 381
300 <!-- Theme options --> 382 <!-- Theme options -->
301 <string name="change_app_theme">Cambia il tema dell\'app</string> 383 <string name="change_app_theme">Cambia tema dell\'app</string>
302 <string name="theme_default">Predefinito</string> 384 <string name="theme_default">Predefinito</string>
303 <string name="theme_material_you">Material You</string> 385 <string name="theme_material_you">Material You</string>
304 386
@@ -308,8 +390,22 @@
308 <string name="theme_mode_light">Chiaro</string> 390 <string name="theme_mode_light">Chiaro</string>
309 <string name="theme_mode_dark">Scuro</string> 391 <string name="theme_mode_dark">Scuro</string>
310 392
393 <!-- Audio output engines -->
394 <string name="cubeb">cubeb</string>
395
311 <!-- Black backgrounds theme --> 396 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">Usa sfondi neri</string> 397 <string name="use_black_backgrounds">Sfondi neri</string>
313 <string name="use_black_backgrounds_description">Quando utilizzi il tema scuro, applica sfondi neri.</string> 398 <string name="use_black_backgrounds_description">Quando utilizzi il tema scuro, applica sfondi neri.</string>
314 399
315</resources> 400 <!-- Picture-In-Picture -->
401 <string name="picture_in_picture">Picture in Picture</string>
402 <string name="picture_in_picture_description">Minimizza la finestra quando viene impostata in background</string>
403 <string name="pause">Pausa</string>
404 <string name="play">Gioca</string>
405 <string name="mute">Silenzia</string>
406 <string name="unmute">Riattiva</string>
407
408 <!-- Licenses screen strings -->
409 <string name="licenses">Licenze</string>
410 <string name="license_fidelityfx_fsr_description">Upscaling di alta qualità da parte di AMD</string>
411 </resources>
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 a0ea78bef..3be4e7d26 100644
--- a/src/android/app/src/main/res/values-ja/strings.xml
+++ b/src/android/app/src/main/res/values-ja/strings.xml
@@ -1,11 +1,12 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">ã“ã®ã‚½ãƒ•トウェアã¯ã€Nintendo Switch用ã®ã‚²ãƒ¼ãƒ ã‚’実行ã—ã¾ã™ã€‚ ゲームソフトやキーã¯å«ã¾ã‚Œã¾ã›ã‚“。&lt;br /&gt;&lt;br /&gt;事å‰ã«ã€ <![CDATA[<b> prod.keys </b>]]> ファイルをデãƒã‚¤ã‚¹ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã«é…ç½®ã—ã¦ãŠã„ã¦ãã ã•ã„。&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">詳細</a>]]></string> 4 <string name="app_disclaimer">ã“ã®ã‚½ãƒ•トウェアã§ã¯ã€Nintendo Switchã®ã‚²ãƒ¼ãƒ ã‚’実行ã§ãã¾ã™ã€‚ ゲームソフトやキーã¯å«ã¾ã‚Œã¾ã›ã‚“。&lt;br /&gt;&lt;br /&gt;事å‰ã«ã€ <![CDATA[<b> prod.keys </b>]]> ファイルをストレージã«é…ç½®ã—ã¦ãŠã„ã¦ãã ã•ã„。&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">詳細</a>]]></string>
5 <string name="emulation_notification_channel_name">ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒæœ‰åйã§ã™</string> 5 <string name="emulation_notification_channel_name">ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ãŒæœ‰åйã§ã™</string>
6 <string name="emulation_notification_channel_description">エミュレーションã®å®Ÿè¡Œä¸­ã«å¸¸è¨­é€šçŸ¥ã‚’表示ã—ã¾ã™ã€‚</string> 6 <string name="emulation_notification_channel_description">エミュレーションã®å®Ÿè¡Œä¸­ã«å¸¸è¨­é€šçŸ¥ã‚’表示ã—ã¾ã™ã€‚</string>
7 <string name="emulation_notification_running">yuzu ã¯å®Ÿè¡Œä¸­ã§ã™</string> 7 <string name="emulation_notification_running">yuzu ã¯å®Ÿè¡Œä¸­ã§ã™</string>
8 <string name="notice_notification_channel_description">å•題ãŒç™ºç”Ÿã—ãŸã¨ãã«é€šçŸ¥ã‚’表示ã—ã¾ã™ã€‚</string> 8 <string name="notice_notification_channel_name">通知ã¨ã‚¨ãƒ©ãƒ¼</string>
9 <string name="notice_notification_channel_description">å•題ã®ç™ºç”Ÿæ™‚ã«é€šçŸ¥ã‚’表示ã—ã¾ã™ã€‚</string>
9 <string name="notification_permission_not_granted">通知ãŒè¨±å¯ã•れã¦ã„ã¾ã›ã‚“!</string> 10 <string name="notification_permission_not_granted">通知ãŒè¨±å¯ã•れã¦ã„ã¾ã›ã‚“!</string>
10 11
11 <!-- Setup strings --> 12 <!-- Setup strings -->
@@ -16,7 +17,7 @@
16 <string name="keys_description">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰ &lt;b>prod.keys&lt;/b> ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。</string> 17 <string name="keys_description">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰ &lt;b>prod.keys&lt;/b> ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。</string>
17 <string name="select_keys">ã‚­ãƒ¼ã‚’é¸æŠž</string> 18 <string name="select_keys">ã‚­ãƒ¼ã‚’é¸æŠž</string>
18 <string name="games">ゲーム</string> 19 <string name="games">ゲーム</string>
19 <string name="games_description">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰&lt;b>ゲーム&lt;/b>ãŒã‚ã‚‹ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¦ãã ã•ã„。</string> 20 <string name="games_description">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰&lt;b>ゲーム&lt;/b>ã®ã‚ã‚‹ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¦ãã ã•ã„。</string>
20 <string name="done">完了</string> 21 <string name="done">完了</string>
21 <string name="done_description">準備ãŒå®Œäº†ã—ã¾ã—ãŸã€‚\nã‚²ãƒ¼ãƒ ã‚’ãŠæ¥½ã—ã¿ãã ã•ã„!</string> 22 <string name="done_description">準備ãŒå®Œäº†ã—ã¾ã—ãŸã€‚\nã‚²ãƒ¼ãƒ ã‚’ãŠæ¥½ã—ã¿ãã ã•ã„!</string>
22 <string name="text_continue">続行</string> 23 <string name="text_continue">続行</string>
@@ -24,48 +25,53 @@
24 <string name="back">戻る</string> 25 <string name="back">戻る</string>
25 <string name="add_games">ゲームを追加</string> 26 <string name="add_games">ゲームを追加</string>
26 <string name="add_games_description">ã‚²ãƒ¼ãƒ ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠž</string> 27 <string name="add_games_description">ã‚²ãƒ¼ãƒ ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠž</string>
28 <string name="step_complete">完了!</string>
27 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>
31 <string name="home_settings">設定</string> 33 <string name="home_settings">設定</string>
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="select_games_folder_description">ゲームをyuzuã®ã‚²ãƒ¼ãƒ ãƒªã‚¹ãƒˆã«è¿½åŠ ã—ã¾ã™</string>
36 <string name="add_games_warning">ゲームフォルダã®é¸æŠžã‚’スキップã—ã¾ã™ã‹?</string> 38 <string name="add_games_warning">ゲームフォルダã®é¸æŠžã‚’スキップã—ã¾ã™ã‹?</string>
37 <string name="add_games_warning_description">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ãªã„å ´åˆã€ã‚²ãƒ¼ãƒ ã¯ã‚²ãƒ¼ãƒ ãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•れã¾ã›ã‚“。</string> 39 <string name="add_games_warning_description">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ãªã„ã¨ã€ã‚²ãƒ¼ãƒ ãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•れã¾ã›ã‚“。</string>
38 <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>
39 <string name="home_search_games">ゲームを検索</string> 41 <string name="home_search_games">ゲームを検索</string>
40 <string name="games_dir_selected">ゲームディレクトリãŒé¸æŠžã•れã¾ã—ãŸ</string> 42 <string name="search_settings">検索設定</string>
41 <string name="install_prod_keys">prod.keys をインストール</string> 43 <string name="games_dir_selected">ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¾ã—ãŸ</string>
42 <string name="install_prod_keys_description">ゲームã®å¾©å·åŒ–ã«å¿…è¦</string> 44 <string name="install_prod_keys">prod.keys</string>
45 <string name="install_prod_keys_description">製å“版ゲームã®å¾©å·åŒ–ã«å¿…è¦ã§ã™</string>
43 <string name="install_prod_keys_warning">キーã®è¿½åŠ ã‚’ã‚¹ã‚­ãƒƒãƒ—ã—ã¾ã™ã‹ï¼Ÿ</string> 46 <string name="install_prod_keys_warning">キーã®è¿½åŠ ã‚’ã‚¹ã‚­ãƒƒãƒ—ã—ã¾ã™ã‹ï¼Ÿ</string>
44 <string name="install_prod_keys_warning_description">製å“版ゲームã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã«ã¯ã€æœ‰åйãªã‚­ãƒ¼ãŒå¿…è¦ã§ã™ã€‚続行ã™ã‚‹ã¨è‡ªä½œã‚¢ãƒ—リã—ã‹æ©Ÿèƒ½ã—ã¾ã›ã‚“。</string> 47 <string name="install_prod_keys_warning_description">製å“版ゲームã®ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã«ã¯ã€æœ‰åйãªã‚­ãƒ¼ãŒå¿…è¦ã§ã™ã€‚続行ã™ã‚‹ã¨è‡ªä½œã‚¢ãƒ—リã—ã‹æ©Ÿèƒ½ã—ã¾ã›ã‚“。</string>
45 <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>
46 <string name="notifications">通知</string> 49 <string name="notifications">通知</string>
47 <string name="notifications_description">下ã®ãƒœã‚¿ãƒ³ã§é€šçŸ¥ã®æ¨©é™ã‚’許å¯ã—ã¦ãã ã•ã„。</string> 50 <string name="notifications_description">下ã®ãƒœã‚¿ãƒ³ã§é€šçŸ¥ã‚’許å¯ã—ã¦ãã ã•ã„。</string>
48 <string name="give_permission">許å¯</string> 51 <string name="give_permission">許å¯</string>
49 <string name="notification_warning">通知ã®è¨±å¯ã‚’スキップã—ã¾ã™ã‹ï¼Ÿ</string> 52 <string name="notification_warning">通知ã®è¨±å¯ã‚’スキップã—ã¾ã™ã‹ï¼Ÿ</string>
50 <string name="notification_warning_description">yuzuã¯é‡è¦ãªãŠçŸ¥ã‚‰ã›ã‚’通知ã§ãã¾ã›ã‚“。</string> 53 <string name="notification_warning_description">yuzuã¯é‡è¦ãªãŠçŸ¥ã‚‰ã›ã‚’通知ã§ãã¾ã›ã‚“。</string>
51 <string name="permission_denied">権é™ãŒæ‹’å¦ã•れã¾ã—ãŸ</string> 54 <string name="permission_denied">権é™ãŒæ‹’å¦ã•れã¾ã—ãŸ</string>
52 <string name="permission_denied_description">ã“ã®æ¨©é™ã‚’複数回拒å¦ã—ãŸãŸã‚ã€ã‚·ã‚¹ãƒ†ãƒ è¨­å®šã§æ‰‹å‹•ã§è¨±å¯ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚</string> 55 <string name="permission_denied_description">ã“ã®æ¨©é™ã‚’複数回拒å¦ã—ãŸãŸã‚ã€è¨­å®šã‹ã‚‰æ‰‹å‹•ã§è¨±å¯ã™ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚</string>
53 <string name="about">情報</string> 56 <string name="about">情報</string>
54 <string name="about_description">ビルドãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆãªã©</string> 57 <string name="about_description">ビルドãƒãƒ¼ã‚¸ãƒ§ãƒ³ã€ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆãªã©</string>
55 <string name="warning_help">ヘルプ</string> 58 <string name="warning_help">ヘルプ</string>
56 <string name="warning_skip">スキップ</string> 59 <string name="warning_skip">スキップ</string>
57 <string name="warning_cancel">キャンセル</string> 60 <string name="warning_cancel">キャンセル</string>
58 <string name="install_amiibo_keys">Amiibo キーをインストール</string> 61 <string name="install_amiibo_keys">Amiibo</string>
59 <string name="install_amiibo_keys_description">ゲーム内ã§ã® Amiibo ã®ä½¿ç”¨ã«å¿…è¦</string> 62 <string name="install_amiibo_keys_description">ゲーム内ã§ã® Amiibo ã®ä½¿ç”¨ã«å¿…è¦ã§ã™</string>
60 <string name="invalid_keys_file">無効ãªã‚­ãƒ¼ãƒ•ァイルãŒé¸æŠžã•れã¾ã—ãŸ</string> 63 <string name="invalid_keys_file">無効ãªã‚­ãƒ¼ãƒ•ァイルã§ã</string>
61 <string name="install_keys_success">正常ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¾ã—ãŸ</string> 64 <string name="install_keys_success">正常ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¾ã—ãŸ</string>
62 <string name="reading_keys_failure">æš—å·åŒ–キーã®èª­ã¿å–りエラー</string> 65 <string name="reading_keys_failure">æš—å·åŒ–キーã®èª­ã¿è¾¼ã¿å¤±æ•—</string>
63 <string name="invalid_keys_error">æš—å·åŒ–キーãŒç„¡åйã§ã™</string> 66 <string name="install_prod_keys_failure_extension_description">ã‚­ãƒ¼ã®æ‹¡å¼µå­ãŒ.keysã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã€å†åº¦ãŠè©¦ã—ãã ã•ã„。</string>
67 <string name="install_amiibo_keys_failure_extension_description">ã‚­ãƒ¼ã®æ‹¡å¼µå­ãŒ.binã§ã‚ã‚‹ã“ã¨ã‚’確èªã—ã€å†åº¦ãŠè©¦ã—ãã ã•ã„。</string>
68 <string name="invalid_keys_error">æš—å·åŒ–キーãŒç„¡åй</string>
64 <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>
65 <string name="install_keys_failure_description">é¸æŠžã•れãŸãƒ•ァイルãŒä¸æ­£ã¾ãŸã¯ç ´æã—ã¦ã„ã¾ã™ã€‚キーをå†ãƒ€ãƒ³ãƒ—ã—ã¦ãã ã•ã„。</string> 70 <string name="install_keys_failure_description">ファイルãŒé–“é•ã£ã¦ã„ã‚‹ã‹ç ´æã—ã¦ã„ã¾ã™ã€‚キーをå†ãƒ€ãƒ³ãƒ—ã—ã¦ãã ã•ã„。</string>
66 <string name="install_gpu_driver">GPUドライãƒãƒ¼ã‚’インストール</string> 71 <string name="install_gpu_driver">GPUドライãƒãƒ¼</string>
67 <string name="install_gpu_driver_description">代替ドライãƒãƒ¼ã‚’インストールã—ã¦ãƒ‘フォーマンスや精度をå‘上ã•ã›ã¾ã™</string> 72 <string name="install_gpu_driver_description">代替ドライãƒãƒ¼ã‚’インストールã—ã¦ãƒ‘フォーマンスや精度をå‘上ã•ã›ã¾ã™</string>
68 <string name="advanced_settings">高度ãªè¨­å®š</string> 73 <string name="advanced_settings">高度ãªè¨­å®š</string>
74 <string name="advanced_settings_game">高度ãªè¨­å®š: %1$s</string>
69 <string name="settings_description">エミュレーターã®è¨­å®šã‚’æ§‹æˆã—ã¾ã™</string> 75 <string name="settings_description">エミュレーターã®è¨­å®šã‚’æ§‹æˆã—ã¾ã™</string>
70 <string name="search_recently_played">最近プレイã—ãŸ</string> 76 <string name="search_recently_played">最近プレイã—ãŸ</string>
71 <string name="search_recently_added">最近追加ã•れãŸ</string> 77 <string name="search_recently_added">最近追加ã•れãŸ</string>
@@ -77,15 +83,34 @@
77 <string name="no_file_manager">ファイルマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ</string> 83 <string name="no_file_manager">ファイルマãƒãƒ¼ã‚¸ãƒ£ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ</string>
78 <string name="notification_no_directory_link">yuzuã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é–‹ã‘ã¾ã›ã‚“</string> 84 <string name="notification_no_directory_link">yuzuã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’é–‹ã‘ã¾ã›ã‚“</string>
79 <string name="notification_no_directory_link_description">ファイルマãƒãƒ¼ã‚¸ãƒ£ã®ã‚µã‚¤ãƒ‰ãƒ‘ãƒãƒ«ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ•ã‚©ãƒ«ãƒ€ã‚’æ‰‹å‹•ã§æŽ¢ã—ã¦ãã ã•ã„。</string> 85 <string name="notification_no_directory_link_description">ファイルマãƒãƒ¼ã‚¸ãƒ£ã®ã‚µã‚¤ãƒ‰ãƒ‘ãƒãƒ«ã§ãƒ¦ãƒ¼ã‚¶ãƒ¼ãƒ•ã‚©ãƒ«ãƒ€ã‚’æ‰‹å‹•ã§æŽ¢ã—ã¦ãã ã•ã„。</string>
80 <string name="manage_save_data">セーブデータを管ç†</string> 86 <string name="manage_save_data">セーブデータ</string>
81 <string name="manage_save_data_description">セーブデータãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚以下ã®ã‚ªãƒ—ションã‹ã‚‰é¸æŠžã—ã¦ãã ã•ã„。</string> 87 <string name="manage_save_data_description">セーブデータãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸã€‚æ“ä½œã‚’é¸æŠžã—ã¦ãã ã•ã„。</string>
82 <string name="import_export_saves_description">セーブファイルをインãƒãƒ¼ãƒˆ/エクスãƒãƒ¼ãƒˆ</string> 88 <string name="import_export_saves_description">セーブファイルをインãƒãƒ¼ãƒˆ/エクスãƒãƒ¼ãƒˆ</string>
83 <string name="save_file_imported_success">インãƒãƒ¼ãƒˆãŒå®Œäº†ã—ã¾ã—ãŸ</string> 89 <string name="save_file_imported_success">インãƒãƒ¼ãƒˆãŒå®Œäº†ã—ã¾ã—ãŸ</string>
84 <string name="save_file_invalid_zip_structure">セーブデータã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªæ§‹é€ ãŒç„¡åйã§ã™</string> 90 <string name="save_file_invalid_zip_structure">セーブデータã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªæ§‹é€ ãŒç„¡åй</string>
85 <string name="save_file_invalid_zip_structure_description">最åˆã®ã‚µãƒ–フォルダåã¯ã€ã‚²ãƒ¼ãƒ ã®ã‚¿ã‚¤ãƒˆãƒ«IDã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚</string> 91 <string name="save_file_invalid_zip_structure_description">最åˆã®ã‚µãƒ–フォルダåã¯ã€ã‚²ãƒ¼ãƒ ã®ã‚¿ã‚¤ãƒˆãƒ«IDã§ã‚ã‚‹å¿…è¦ãŒã‚りã¾ã™ã€‚</string>
86 <string name="import_saves">インãƒãƒ¼ãƒˆ</string> 92 <string name="import_saves">インãƒãƒ¼ãƒˆ</string>
87 <string name="export_saves">エクスãƒãƒ¼ãƒˆ</string> 93 <string name="export_saves">エクスãƒãƒ¼ãƒˆ</string>
88 94 <string name="install_firmware">ファームウェア</string>
95 <string name="install_firmware_description">ファームウェアã¯ZIPアーカイブã§ã‚ã‚‹å¿…è¦ãŒã‚りã€ä¸€éƒ¨ã®ã‚²ãƒ¼ãƒ ã‚’èµ·å‹•ã™ã‚‹ã®ã«å¿…è¦ã§ã™</string>
96 <string name="firmware_installing">ファームウェアをインストール中</string>
97 <string name="firmware_installed_success">インストールãŒå®Œäº†ã—ã¾ã—ãŸ</string>
98 <string name="firmware_installed_failure">インストール失敗</string>
99 <string name="share_log">デãƒãƒƒã‚°ãƒ­ã‚°</string>
100 <string name="share_log_description">yuzuã®ãƒ­ã‚°ãƒ•ァイルを共有ã—ã¦å•題をデãƒãƒƒã‚°ã—ã¾ã™</string>
101 <string name="share_log_missing">ログãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</string>
102 <string name="install_game_content">追加コンテンツ</string>
103 <string name="install_game_content_description">更新データやDLCをインストールã—ã¾ã™</string>
104 <string name="installing_game_content">コンテンツをインストール中...</string>
105 <string name="install_game_content_failure_file_extension">NSPã¨XCIå½¢å¼ã®ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ã®ã¿ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã™ã€‚ã‚²ãƒ¼ãƒ ã‚³ãƒ³ãƒ†ãƒ³ãƒ„ãŒæœ‰åйãªã‚‚ã®ã§ã‚ã‚‹ã‹ã”確èªãã ã•ã„。</string>
106 <string name="install_game_content_failed_count">%1$d ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã‚¨ãƒ©ãƒ¼</string>
107 <string name="install_game_content_success">ゲームコンテンツã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«æˆåŠŸã—ã¾ã—ãŸ</string>
108 <string name="install_game_content_success_install">%1$d ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã«æˆåŠŸã—ã¾ã—ãŸ</string>
109 <string name="install_game_content_success_overwrite">%1$d ã®ä¸Šæ›¸ãã«æˆåŠŸã—ã¾ã—ãŸ</string>
110 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
111 <string name="custom_driver_not_supported">カスタムドライãƒã¯ã‚µãƒãƒ¼ãƒˆã•れã¦ã„ã¾ã›ã‚“</string>
112 <string name="manage_yuzu_data">yuzu データを管ç†</string>
113 <string name="share_save_file">セーブファイルを共有</string>
89 <!-- About screen strings --> 114 <!-- About screen strings -->
90 <string name="gaia_is_not_real">ガイアã¯å®Ÿåœ¨ã—ãªã„</string> 115 <string name="gaia_is_not_real">ガイアã¯å®Ÿåœ¨ã—ãªã„</string>
91 <string name="copied_to_clipboard">クリップボードã«ã‚³ãƒ”ーã—ã¾ã—ãŸ</string> 116 <string name="copied_to_clipboard">クリップボードã«ã‚³ãƒ”ーã—ã¾ã—ãŸ</string>
@@ -93,7 +118,15 @@
93 <string name="contributors">貢献者</string> 118 <string name="contributors">貢献者</string>
94 <string name="contributors_description">yuzuãƒãƒ¼ãƒ ã®\u2764ã§ä½œã‚‰ã‚ŒãŸ</string> 119 <string name="contributors_description">yuzuãƒãƒ¼ãƒ ã®\u2764ã§ä½œã‚‰ã‚ŒãŸ</string>
95 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 120 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
121 <string name="licenses_description">yuzu for Androidã®ä½œæˆã‚’å¯èƒ½ã«ã—ãŸãƒ—ロジェクト</string>
96 <string name="build">ビルド</string> 122 <string name="build">ビルド</string>
123 <string name="user_data">ユーザデータ</string>
124 <string name="exporting_user_data">ユーザデータをエクスãƒãƒ¼ãƒˆä¸­...</string>
125 <string name="importing_user_data">ユーザデータをインãƒãƒ¼ãƒˆä¸­...</string>
126 <string name="import_user_data">ユーザデータをインãƒãƒ¼ãƒˆ</string>
127 <string name="user_data_export_success">ユーザデータã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã«æˆåŠŸã—ã¾ã—ãŸ</string>
128 <string name="user_data_import_success">ユーザデータã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆã«æˆåŠŸã—ã¾ã—ãŸ</string>
129 <string name="user_data_export_cancelled">エクスãƒãƒ¼ãƒˆã‚’キャンセルã—ã¾ã—ãŸ</string>
97 <string name="support_link">https://discord.gg/u77vRWY</string> 130 <string name="support_link">https://discord.gg/u77vRWY</string>
98 <string name="website_link">https://yuzu-emu.org/</string> 131 <string name="website_link">https://yuzu-emu.org/</string>
99 <string name="github_link">https://github.com/yuzu-emu</string> 132 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -105,72 +138,91 @@
105 <string name="get_early_access_description">æœ€å…ˆç«¯ã®æ©Ÿèƒ½ã€ã‚¢ãƒƒãƒ—ãƒ‡ãƒ¼ãƒˆã®æ—©æœŸã‚¢ã‚¯ã‚»ã‚¹ãªã©</string> 138 <string name="get_early_access_description">æœ€å…ˆç«¯ã®æ©Ÿèƒ½ã€ã‚¢ãƒƒãƒ—ãƒ‡ãƒ¼ãƒˆã®æ—©æœŸã‚¢ã‚¯ã‚»ã‚¹ãªã©</string>
106 <string name="early_access_benefits">早期アクセスã®ãƒ¡ãƒªãƒƒãƒˆ</string> 139 <string name="early_access_benefits">早期アクセスã®ãƒ¡ãƒªãƒƒãƒˆ</string>
107 <string name="cutting_edge_features">æœ€å…ˆç«¯ã®æ©Ÿèƒ½</string> 140 <string name="cutting_edge_features">æœ€å…ˆç«¯ã®æ©Ÿèƒ½</string>
108 <string name="early_access_updates">ã‚¢ãƒƒãƒ—ãƒ‡ãƒ¼ãƒˆã®æ—©æœŸã‚¢ã‚¯ã‚»ã‚¹</string> 141 <string name="early_access_updates">アップデートã¸ã®æ—©æœŸã‚¢ã‚¯ã‚»ã‚¹</string>
109 <string name="no_manual_installation">手動インストールãŒä¸è¦</string> 142 <string name="no_manual_installation">手動インストールãŒä¸è¦</string>
110 <string name="prioritized_support">優先的ãªã‚µãƒãƒ¼ãƒˆ</string> 143 <string name="prioritized_support">優先サãƒãƒ¼ãƒˆ</string>
111 <string name="helping_game_preservation">ゲームã®ä¿å­˜ã«è²¢çŒ®</string> 144 <string name="helping_game_preservation">ゲームã®ä¿å­˜ã«è²¢çŒ®</string>
112 <string name="our_eternal_gratitude">ç§ãŸã¡ã®æ°¸é ã®æ„Ÿè¬</string> 145 <string name="our_eternal_gratitude">ç§ãŸã¡ã‹ã‚‰æ°¸é ã®æ„Ÿè¬</string>
113 <string name="are_you_interested">興味ãŒã‚りã¾ã™ã‹ï¼Ÿ</string> 146 <string name="are_you_interested">興味ãŒã‚りã¾ã™ã‹ï¼Ÿ</string>
114 147
115 <!-- General settings strings --> 148 <!-- General settings strings -->
116 <string name="frame_limit_enable">速度制é™ã‚’有効化</string> 149 <string name="frame_limit_enable">エミュレーション速度を制é™</string>
117 <string name="frame_limit_enable_description">有効ã«ã™ã‚‹ã¨ã€ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³é€Ÿåº¦ãŒä»»æ„ã®å‰²åˆã«åˆ¶é™ã•れã¾ã™ã€‚</string> 150 <string name="frame_limit_enable_description">エミュレーション速度を指定ã—ãŸå‰²åˆã«åˆ¶é™ã—ã¾ã™ã€‚</string>
118 <string name="frame_limit_slider">エミュレーション速度ã®åˆ¶é™</string> 151 <string name="frame_limit_slider">エミュレーション速度</string>
119 <string name="frame_limit_slider_description">エミュレーション速度を制é™ã™ã‚‹å‰²åˆã‚’指定ã—ã¾ã™ã€‚デフォルトã®100%ã§ã¯ã€ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã¯é€šå¸¸ã®é€Ÿåº¦ã«åˆ¶é™ã•れã¾ã™ã€‚値ãŒé«˜ã„ã¾ãŸã¯ä½Žã„ã»ã©ã€é€Ÿåº¦åˆ¶é™ãŒå¢—加ã¾ãŸã¯æ¸›å°‘ã—ã¾ã™ã€‚</string> 152 <string name="frame_limit_slider_description">エミュレーション速度を制é™ã™ã‚‹ãƒ‘ーセンテージを指定ã—ã¾ã™ã€‚100%ã¯é€šå¸¸é€Ÿåº¦ã§ã™ã€‚値ã®å¢—減ã§é€Ÿåº¦ã‚‚増減ã—ã¾ã™ã€‚</string>
120 <string name="cpu_accuracy">CPU精度</string> 153 <string name="cpu_accuracy">CPU精度</string>
121
122 <!-- System settings strings --> 154 <!-- System settings strings -->
123 <string name="use_docked_mode">TVモード</string> 155 <string name="use_docked_mode">TVモード</string>
124 <string name="use_docked_mode_description">TVモードã§ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ãƒˆã—ã¾ã™ã€‚パフォーマンスãŒçŠ ç‰²ã«ãªã‚Šã¾ã™ãŒã€è§£åƒåº¦ãŒå‘上ã—ã¾ã™ã€‚</string> 156 <string name="use_docked_mode_description">高解åƒåº¦ã€ä½Žãƒ‘フォーマンス。無効時ã«ã¯æºå¸¯ãƒ¢ãƒ¼ãƒ‰ãŒä½¿ç”¨ã•れã¾ã™ï¼ˆä½Žè§£åƒåº¦ã€é«˜ãƒ‘フォーマンス)。</string>
125 <string name="emulated_region">地域</string> 157 <string name="emulated_region">地域</string>
126 <string name="emulated_language">言語</string> 158 <string name="emulated_language">言語</string>
127 <string name="select_rtc_date">RTCã®æ—¥ä»˜ã‚’é¸æŠž</string> 159 <string name="select_rtc_date">RTCã®æ—¥ä»˜ã‚’é¸æŠž</string>
128 <string name="select_rtc_time">RTCã®æ™‚åˆ»ã‚’é¸æŠž</string> 160 <string name="select_rtc_time">RTCã®æ™‚åˆ»ã‚’é¸æŠž</string>
129 <string name="use_custom_rtc">カスタムRTC</string> 161 <string name="use_custom_rtc">カスタム RTC</string>
130 <string name="use_custom_rtc_description">ç¾åœ¨ã®ã‚·ã‚¹ãƒ†ãƒ æ™‚é–“ã¨ã¯åˆ¥ã«ã‚«ã‚¹ã‚¿ãƒ ã®ãƒªã‚¢ãƒ«ã‚¿ã‚¤ãƒ ã‚¯ãƒ­ãƒƒã‚¯ã‚’設定ã§ãã¾ã™ã€‚</string> 162 <string name="use_custom_rtc_description">ç¾åœ¨ã®ã‚·ã‚¹ãƒ†ãƒ æ™‚é–“ã¨ã¯åˆ¥ã«ã€ä»»æ„ã®ãƒªã‚¢ãƒ«ã‚¿ã‚¤ãƒ ã‚¯ãƒ­ãƒƒã‚¯ã‚’設定ã§ãã¾ã™ã€‚</string>
131 <string name="set_custom_rtc">カスタムRTCを設定</string> 163 <string name="set_custom_rtc">カスタムRTCを設定</string>
132 164
133 <!-- Graphics settings strings --> 165 <!-- Graphics settings strings -->
134 <string name="renderer_api">API</string>
135 <string name="renderer_accuracy">精度</string> 166 <string name="renderer_accuracy">精度</string>
136 <string name="renderer_resolution">è§£åƒåº¦</string> 167 <string name="renderer_resolution">è§£åƒåº¦ï¼ˆæºå¸¯ãƒ¢ãƒ¼ãƒ‰/TVモード)</string>
137 <string name="renderer_vsync">åž‚ç›´åŒæœŸãƒ¢ãƒ¼ãƒ‰</string> 168 <string name="renderer_vsync">åž‚ç›´åŒæœŸãƒ¢ãƒ¼ãƒ‰</string>
169 <string name="renderer_screen_layout">ç”»é¢ã®å‘ã</string>
138 <string name="renderer_aspect_ratio">アスペクト比</string> 170 <string name="renderer_aspect_ratio">アスペクト比</string>
139 <string name="renderer_scaling_filter">ウィンドウé©å¿œãƒ•ィルター</string> 171 <string name="renderer_scaling_filter">ウィンドウé©å¿œãƒ•ィルター</string>
140 <string name="renderer_anti_aliasing">アンãƒã‚¨ã‚¤ãƒªã‚¢ã‚¹æ–¹å¼</string> 172 <string name="renderer_anti_aliasing">アンãƒã‚¨ã‚¤ãƒªã‚¢ã‚¹æ–¹å¼</string>
141 <string name="renderer_force_max_clock">最大クロックを強制 (Adrenoã®ã¿)</string> 173 <string name="renderer_force_max_clock">最大クロックを強制 (Adrenoã®ã¿)</string>
142 <string name="renderer_force_max_clock_description">GPUã‚’å¯èƒ½ãªé™ã‚Šæœ€å¤§ã‚¯ãƒ­ãƒƒã‚¯ã§å‹•作ã•ã›ã¾ã™ (éŽç†±åˆ¶é™ã¯å¼•ãç¶šãé©ç”¨ã•れã¾ã™)。</string> 174 <string name="renderer_force_max_clock_description">GPUを最大é™å¯èƒ½ãªå‘¨æ³¢æ•°ã§å‹•作ã•ã›ã¾ã™ (éŽç†±åˆ¶é™ã¯å¼•ãç¶šãé©ç”¨ã•れã¾ã™)。</string>
143 <string name="renderer_asynchronous_shaders">éžåŒæœŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼</string> 175 <string name="renderer_asynchronous_shaders">éžåŒæœŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼</string>
144 <string name="renderer_asynchronous_shaders_description">シェーダーをéžåŒæœŸã§ã‚³ãƒ³ãƒ‘イルã—ã¾ã™ã€‚コマè½ã¡ãŒè»½æ¸›ã•れã¾ã™ãŒã€ä¸å…·åˆãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string> 176 <string name="renderer_asynchronous_shaders_description">シェーダーをéžåŒæœŸã§ã‚³ãƒ³ãƒ‘イルã—ã¾ã™ã€‚コマè½ã¡ãŒè»½æ¸›ã•れã¾ã™ãŒã€ä¸å…·åˆãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string>
177 <string name="renderer_reactive_flushing">峿™‚書ãè¾¼ã¿</string>
178 <string name="renderer_reactive_flushing_description">一部ã®ã‚²ãƒ¼ãƒ ã«ãŠã„ã¦ã€ãƒ‘フォーマンスを犠牲ã«ã—ãªãŒã‚‰ã‚‚ã€ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ç²¾åº¦ã‚’å‘上ã•ã›ã¾ã™ã€‚</string>
179 <string name="use_disk_shader_cache">ディスクシェーダーキャッシュ</string>
180 <string name="use_disk_shader_cache_description">生æˆã—ãŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã‚’端末ã«ä¿å­˜ã—ã¦èª­ã¿è¾¼ã¿ã€ã‚³ãƒžè½ã¡ã‚’軽減ã—ã¾ã™ã€‚</string>
181
182 <!-- Debug settings strings -->
183 <string name="cpu">CPU</string>
184 <string name="cpu_debug_mode">CPU デãƒãƒƒã‚®ãƒ³ã‚°</string>
185 <string name="gpu">GPU</string>
186 <string name="renderer_api">API</string>
145 <string name="renderer_debug">グラフィックデãƒãƒƒã‚°</string> 187 <string name="renderer_debug">グラフィックデãƒãƒƒã‚°</string>
146 <string name="renderer_debug_description">オンã«ã™ã‚‹ã¨ã€ã‚°ãƒ©ãƒ•ィックAPI ã¯ä½Žé€Ÿã®ãƒ‡ãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚Šã¾ã™ã€‚</string> 188 <string name="renderer_debug_description">グラフィックAPIを低速デãƒãƒƒã‚°ãƒ¢ãƒ¼ãƒ‰ã«è¨­å®šã—ã¾ã™ã€‚</string>
147 <string name="use_disk_shader_cache">シェーダーキャッシュを使用</string> 189 <string name="fastmem">Fastmem</string>
148 <string name="use_disk_shader_cache_description">生æˆã—ãŸã‚·ã‚§ãƒ¼ãƒ€ãƒ¼ã‚’ディスクã«ä¿å­˜ã—ã¦èª­ã¿è¾¼ã‚€ã“ã¨ã§ã€ã‚³ãƒžè½ã¡ã‚’軽減ã—ã¾ã™ã€‚</string>
149 190
150 <!-- Audio settings strings --> 191 <!-- Audio settings strings -->
192 <string name="audio_output_engine">出力エンジン</string>
151 <string name="audio_volume">音é‡</string> 193 <string name="audio_volume">音é‡</string>
152 <string name="audio_volume_description">オーディオ出力ã®éŸ³é‡ã‚’指定ã—ã¾ã™</string> 194 <string name="audio_volume_description">オーディオ出力ã®éŸ³é‡ã‚’指定ã—ã¾ã™</string>
153 195
154 <!-- Miscellaneous --> 196 <!-- Miscellaneous -->
155 <string name="slider_default">デフォルト</string> 197 <string name="slider_default">デフォルト</string>
156 <string name="ini_saved">設定をä¿å­˜ã—ã¾ã—ãŸ</string> 198 <string name="ini_saved">設定をä¿å­˜ã—ã¾ã—ãŸ</string>
157 <string name="gameid_saved">%1$sã®è¨­å®šã‚’ä¿å­˜ã—ã¾ã—ãŸ</string> 199 <string name="gameid_saved">%1$s ã®è¨­å®šã‚’ä¿å­˜ã—ã¾ã—ãŸ</string>
158 <string name="error_saving">%1$s.ini ã®ä¿å­˜ã‚¨ãƒ©ãƒ¼: %2$s</string> 200 <string name="error_saving">%1$s.ini ã®ä¿å­˜ã‚¨ãƒ©ãƒ¼: %2$s</string>
201 <string name="unimplemented_menu">未実装ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼</string>
159 <string name="loading">読ã¿è¾¼ã¿ä¸­â€¦</string> 202 <string name="loading">読ã¿è¾¼ã¿ä¸­â€¦</string>
203 <string name="shutting_down">終了中...</string>
160 <string name="reset_setting_confirmation">ã“ã®è¨­å®šã‚’åˆæœŸå€¤ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã™ã‹?</string> 204 <string name="reset_setting_confirmation">ã“ã®è¨­å®šã‚’åˆæœŸå€¤ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã™ã‹?</string>
161 <string name="reset_to_default">åˆæœŸè¨­å®šã«æˆ»ã™</string> 205 <string name="reset_to_default">åˆæœŸè¨­å®šã«æˆ»ã™</string>
162 <string name="reset_all_settings">ã™ã¹ã¦ã®è¨­å®šã‚’リセットã—ã¾ã™ã‹ï¼Ÿ</string> 206 <string name="reset_all_settings">ã™ã¹ã¦ã®è¨­å®šã‚’リセットã—ã¾ã™ã‹ï¼Ÿ</string>
163 <string name="reset_all_settings_description">ã™ã¹ã¦ã®è©³ç´°è¨­å®šãŒåˆæœŸè¨­å®šã«æˆ»ã•れã¾ã™ã€‚ã“ã®æ“作ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。</string> 207 <string name="reset_all_settings_description">ã™ã¹ã¦ã®è©³ç´°è¨­å®šãŒåˆæœŸå€¤ã«æˆ»ã•れã¾ã™ã€‚ã“ã®æ“作ã¯å…ƒã«æˆ»ã›ã¾ã›ã‚“。</string>
164 <string name="settings_reset">設定をリセットã—ã¾ã—ãŸ</string> 208 <string name="settings_reset">設定をリセットã—ã¾ã—ãŸ</string>
165 <string name="close">é–‰ã˜ã‚‹</string> 209 <string name="close">é–‰ã˜ã‚‹</string>
166 <string name="learn_more">詳細情報</string> 210 <string name="learn_more">詳細情報</string>
211 <string name="auto">自動</string>
212 <string name="submit">é€ä¿¡</string>
213 <string name="string_import">インãƒãƒ¼ãƒˆ</string>
214 <string name="export">エクスãƒãƒ¼ãƒˆ</string>
215 <string name="export_failed">エクスãƒãƒ¼ãƒˆå¤±æ•—</string>
216 <string name="import_failed">インãƒãƒ¼ãƒˆå¤±æ•—</string>
217 <string name="cancelling">キャンセル中</string>
167 218
168 <!-- GPU driver installation --> 219 <!-- GPU driver installation -->
169 <string name="select_gpu_driver">GPUドライãƒã‚’é¸æŠž</string> 220 <string name="select_gpu_driver">GPUドライãƒã‚’é¸æŠž</string>
170 <string name="select_gpu_driver_title">ç¾åœ¨ã®GPUドライãƒãƒ¼ã‚’ç½®ãæ›ãˆã¾ã™ã‹ï¼Ÿ</string> 221 <string name="select_gpu_driver_title">ç¾åœ¨ã®GPUドライãƒã‚’ç½®ãæ›ãˆã¾ã™ã‹ï¼Ÿ</string>
171 <string name="select_gpu_driver_install">インストール</string> 222 <string name="select_gpu_driver_install">インストール</string>
172 <string name="select_gpu_driver_default">デフォルト</string> 223 <string name="select_gpu_driver_default">デフォルト</string>
173 <string name="select_gpu_driver_use_default">デフォルトã®GPUドライãƒãƒ¼ã‚’使用ã—ã¾ã™</string> 224 <string name="select_gpu_driver_use_default">デフォルトã®ãƒ‰ãƒ©ã‚¤ãƒã‚’使用ã—ã¾ã™</string>
225 <string name="select_gpu_driver_error">é¸æŠžã•れãŸãƒ‰ãƒ©ã‚¤ãƒãŒç„¡åйã€ã‚·ã‚¹ãƒ†ãƒ ã®ãƒ‡ãƒ•ォルトを使用ã—ã¾ã™!</string>
174 <string name="system_gpu_driver">システムã®GPUドライãƒ</string> 226 <string name="system_gpu_driver">システムã®GPUドライãƒ</string>
175 <string name="installing_driver">インストール中…</string> 227 <string name="installing_driver">インストール中…</string>
176 228
@@ -181,33 +233,34 @@
181 <string name="preferences_graphics">グラフィック</string> 233 <string name="preferences_graphics">グラフィック</string>
182 <string name="preferences_audio">サウンド</string> 234 <string name="preferences_audio">サウンド</string>
183 <string name="preferences_theme">テーマã¨è‰²</string> 235 <string name="preferences_theme">テーマã¨è‰²</string>
236 <string name="preferences_debug">デãƒãƒƒã‚°</string>
184 237
185 <!-- ROM loading errors --> 238 <!-- ROM loading errors -->
186 <string name="loader_error_encrypted">ROMãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™</string> 239 <string name="loader_error_encrypted">ROMãŒæš—å·åŒ–ã•れã¦ã„ã¾ã™</string>
187 <string name="loader_error_encrypted_roms_description"><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">ゲームカートリッジ</a>ã‚„<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">インストール済ã¿ã®ã‚¿ã‚¤ãƒˆãƒ«</a>ã‚’å†åº¦ãƒ€ãƒ³ãƒ—ã™ã‚‹ãŸã‚ã®ã‚¬ã‚¤ãƒ‰ã«å¾“ã£ã¦ãã ã•ã„。]]></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>
188 <string name="loader_error_encrypted_keys_description"><![CDATA[ゲームを復å·åŒ–ã™ã‚‹ãŸã‚ã« <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> ファイルãŒã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã•れã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。]]></string>
189 <string name="loader_error_video_core">ビデオコアã®åˆæœŸåŒ–中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ</string> 241 <string name="loader_error_video_core">ビデオコアã®åˆæœŸåŒ–中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ</string>
190 <string name="loader_error_video_core_description">ã“れã¯é€šå¸¸ã€äº’æ›æ€§ã®ãªã„GPUドライãƒãƒ¼ãŒåŽŸå› ã§ç™ºç”Ÿã—ã¾ã™ã€‚ カスタムGPUドライãƒãƒ¼ã‚’インストールã™ã‚‹ã¨ã€å•題ãŒè§£æ±ºã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string> 242 <string name="loader_error_video_core_description">ã“れã¯é€šå¸¸ã€äº’æ›æ€§ã®ãªã„GPUドライãƒãƒ¼ãŒåŽŸå› ã§ç™ºç”Ÿã—ã¾ã™ã€‚ カスタムGPUドライãƒãƒ¼ã‚’インストールã™ã‚‹ã¨ã€å•題ãŒè§£æ±ºã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string>
191 <string name="loader_error_invalid_format">ROMã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ</string> 243 <string name="loader_error_invalid_format">ROMã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ</string>
192 <string name="loader_error_file_not_found">ROMファイルãŒå­˜åœ¨ã—ã¾ã›ã‚“</string> 244 <string name="loader_error_file_not_found">ROMファイルãŒå­˜åœ¨ã—ã¾ã›ã‚“</string>
193 245
194 <!-- Emulation Menu --> 246 <!-- Emulation Menu -->
195 <string name="emulation_exit">エミュレーションを終了</string> 247 <string name="emulation_exit">終了</string>
196 <string name="emulation_done">完了</string> 248 <string name="emulation_done">完了</string>
197 <string name="emulation_fps_counter">FPSカウンター</string> 249 <string name="emulation_fps_counter">FPSカウンター</string>
198 <string name="emulation_toggle_controls">コントロールを切り替ãˆ</string> 250 <string name="emulation_toggle_controls">ボタンã®è¡¨ç¤ºè¨­å®š</string>
199 <string name="emulation_dpad_slide">å字キーã®ã‚¹ãƒ©ã‚¤ãƒ‰æ“作</string> 251 <string name="emulation_rel_stick_center">スティックを固定ã—ãªã„</string>
200 <string name="emulation_haptics">振動</string> 252 <string name="emulation_dpad_slide">å字キーをスライドæ“作</string>
201 <string name="emulation_show_overlay">オーãƒãƒ¼ãƒ¬ã‚¤ã‚’表示</string> 253 <string name="emulation_haptics">ã‚¿ãƒƒãƒæŒ¯å‹•</string>
202 <string name="emulation_toggle_all">ã™ã¹ã¦é¸æŠž</string> 254 <string name="emulation_show_overlay">ボタンを表示</string>
203 <string name="emulation_control_adjust">オーãƒãƒ¼ãƒ¬ã‚¤ã‚’調整</string> 255 <string name="emulation_toggle_all">ã™ã¹ã¦åˆ‡æ›¿</string>
256 <string name="emulation_control_adjust">見ãŸç›®ã‚’調整</string>
204 <string name="emulation_control_scale">大ãã•</string> 257 <string name="emulation_control_scale">大ãã•</string>
205 <string name="emulation_control_opacity">ä¸é€æ˜Žåº¦</string> 258 <string name="emulation_control_opacity">ä¸é€æ˜Žåº¦</string>
206 <string name="emulation_touch_overlay_reset">リセット</string> 259 <string name="emulation_touch_overlay_reset">リセット</string>
207 <string name="emulation_touch_overlay_edit">オーãƒãƒ¼ãƒ¬ã‚¤ã‚’編集</string> 260 <string name="emulation_touch_overlay_edit">ä½ç½®ã‚’編集</string>
208 <string name="emulation_pause">ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ä¸€æ™‚åœæ­¢</string> 261 <string name="emulation_pause">ä¸€æ™‚åœæ­¢</string>
209 <string name="emulation_unpause">エミュレーションをå†é–‹</string> 262 <string name="emulation_unpause">å†é–‹</string>
210 <string name="emulation_input_overlay">オーãƒãƒ¼ãƒ¬ã‚¤ã‚ªãƒ—ション</string> 263 <string name="emulation_input_overlay">表示オプション</string>
211 264
212 <string name="load_settings">設定をロード中…</string> 265 <string name="load_settings">設定をロード中…</string>
213 266
@@ -220,10 +273,13 @@
220 <string name="system_archive_not_found">システムアーカイブãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</string> 273 <string name="system_archive_not_found">システムアーカイブãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“</string>
221 <string name="system_archive_not_found_message">%s ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。システムアーカイブをダンプã—ã¦ãã ã•ã„。\nエミュレーションを続行ã™ã‚‹ã¨ã€ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚„ãƒã‚°ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string> 274 <string name="system_archive_not_found_message">%s ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。システムアーカイブをダンプã—ã¦ãã ã•ã„。\nエミュレーションを続行ã™ã‚‹ã¨ã€ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚„ãƒã‚°ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string>
222 <string name="system_archive_general">システムアーカイブ</string> 275 <string name="system_archive_general">システムアーカイブ</string>
223 <string name="save_load_error">セーブ/ロード エラー</string> 276 <string name="save_load_error">セーブ/ロードエラー</string>
224 <string name="fatal_error">致命的ãªã‚¨ãƒ©ãƒ¼</string> 277 <string name="fatal_error">致命的ãªã‚¨ãƒ©ãƒ¼</string>
225 <string name="fatal_error_message">致命的ãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚詳細ã¯ãƒ­ã‚°ã‚’確èªã—ã¦ãã ã•ã„。\nエミュレーションを続行ã™ã‚‹ã¨ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚„ãƒã‚°ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string> 278 <string name="fatal_error_message">致命的ãªã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚詳細ã¯ãƒ­ã‚°ã‚’確èªã—ã¦ãã ã•ã„。\nエミュレーションを続行ã™ã‚‹ã¨ã‚¯ãƒ©ãƒƒã‚·ãƒ¥ã‚„ãƒã‚°ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚</string>
226 <string name="performance_warning">ã“ã®è¨­å®šã‚’オフã«ã™ã‚‹ã¨ã€ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®ãƒ‘フォーマンスãŒè‘—ã—ã低下ã—ã¾ã™ï¼æœ€é«˜ã®ä½“験を得るãŸã‚ã«ã¯ã€ã“ã®è¨­å®šã‚’有効ã«ã—ã¦ãŠãã“ã¨ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚</string> 279 <string name="performance_warning">ã“ã®è¨­å®šã‚’オフã«ã™ã‚‹ã¨ã€ã‚¨ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³ã®ãƒ‘フォーマンスãŒè‘—ã—ã低下ã—ã¾ã™ï¼æœ€é«˜ã®ä½“験を得るãŸã‚ã«ã¯ã€ã“ã®è¨­å®šã‚’有効ã«ã—ã¦ãŠãã“ã¨ã‚’推奨ã—ã¾ã™ã€‚</string>
280 <string name="device_memory_inadequate">デãƒã‚¤ã‚¹ RAM: %1$s\n推奨: %2$s</string>
281 <string name="memory_formatted">%1$s %2$s</string>
282 <string name="no_game_present">èµ·å‹•ã§ãるゲームãŒã‚りã¾ã›ã‚“!</string>
227 283
228 <!-- Region Names --> 284 <!-- Region Names -->
229 <string name="region_japan">日本</string> 285 <string name="region_japan">日本</string>
@@ -234,7 +290,14 @@
234 <string name="region_korea">韓国</string> 290 <string name="region_korea">韓国</string>
235 <string name="region_taiwan">å°æ¹¾</string> 291 <string name="region_taiwan">å°æ¹¾</string>
236 292
237 <!-- Language Names --> 293 <!-- Memory Sizes -->
294 <string name="memory_byte">Byte</string>
295 <string name="memory_kilobyte">KB</string>
296 <string name="memory_megabyte">MB</string>
297 <string name="memory_gigabyte">GB</string>
298 <string name="memory_terabyte">TB</string>
299 <string name="memory_petabyte">PB</string>
300 <string name="memory_exabyte">EB</string>
238 301
239 <!-- Renderer APIs --> 302 <!-- Renderer APIs -->
240 <string name="renderer_vulkan">Vulkan</string> 303 <string name="renderer_vulkan">Vulkan</string>
@@ -242,7 +305,7 @@
242 305
243 <!-- Renderer Accuracy --> 306 <!-- Renderer Accuracy -->
244 <string name="renderer_accuracy_normal">標準</string> 307 <string name="renderer_accuracy_normal">標準</string>
245 <string name="renderer_accuracy_high">高ã„</string> 308 <string name="renderer_accuracy_high">高</string>
246 <string name="renderer_accuracy_extreme">最高 (低速)</string> 309 <string name="renderer_accuracy_extreme">最高 (低速)</string>
247 310
248 <!-- Resolutions --> 311 <!-- Resolutions -->
@@ -272,12 +335,17 @@
272 <string name="anti_aliasing_fxaa">FXAA</string> 335 <string name="anti_aliasing_fxaa">FXAA</string>
273 <string name="anti_aliasing_smaa">SMAA</string> 336 <string name="anti_aliasing_smaa">SMAA</string>
274 337
338 <!-- Screen Layouts -->
339 <string name="screen_layout_landscape">横長</string>
340 <string name="screen_layout_portrait">縦長</string>
341 <string name="screen_layout_auto">自動</string>
342
275 <!-- Aspect Ratios --> 343 <!-- Aspect Ratios -->
276 <string name="ratio_default">デフォルト (16:9)</string> 344 <string name="ratio_default">デフォルト (16:9)</string>
277 <string name="ratio_force_four_three">強制 4:3</string> 345 <string name="ratio_force_four_three">強制 4:3</string>
278 <string name="ratio_force_twenty_one_nine">強制 21:9</string> 346 <string name="ratio_force_twenty_one_nine">強制 21:9</string>
279 <string name="ratio_force_sixteen_ten">強制 16:10</string> 347 <string name="ratio_force_sixteen_ten">強制 16:10</string>
280 <string name="ratio_stretch">ウィンドウã«åˆã‚ã›ã‚‹</string> 348 <string name="ratio_stretch">ç”»é¢ã«åˆã‚ã›ã‚‹</string>
281 349
282 <!-- CPU Accuracy --> 350 <!-- CPU Accuracy -->
283 <string name="cpu_accuracy_accurate">正確</string> 351 <string name="cpu_accuracy_accurate">正確</string>
@@ -289,7 +357,7 @@
289 <string name="gamepad_left_stick">Lスティック</string> 357 <string name="gamepad_left_stick">Lスティック</string>
290 <string name="gamepad_right_stick">Rスティック</string> 358 <string name="gamepad_right_stick">Rスティック</string>
291 <string name="gamepad_home">HOMEボタン</string> 359 <string name="gamepad_home">HOMEボタン</string>
292 <string name="gamepad_screenshot">スクリーンショット</string> 360 <string name="gamepad_screenshot">キャãƒãƒãƒ£ãƒ¼ãƒœã‚¿ãƒ³</string>
293 361
294 <!-- Disk shader cache --> 362 <!-- Disk shader cache -->
295 <string name="preparing_shaders">シェーダーを準備ã—ã¦ã„ã¾ã™</string> 363 <string name="preparing_shaders">シェーダーを準備ã—ã¦ã„ã¾ã™</string>
@@ -306,8 +374,22 @@
306 <string name="theme_mode_light">ライト</string> 374 <string name="theme_mode_light">ライト</string>
307 <string name="theme_mode_dark">ダーク</string> 375 <string name="theme_mode_dark">ダーク</string>
308 376
309 <!-- Black backgrounds theme --> 377 <!-- Audio output engines -->
310 <string name="use_black_backgrounds">黒色ã®èƒŒæ™¯ã‚’使用</string> 378 <string name="cubeb">cubeb</string>
311 <string name="use_black_backgrounds_description">ダークテーマã®ä½¿ç”¨æ™‚ã¯ã€é»’色ã®èƒŒæ™¯ã‚’有効ã«ã—ã¦ãã ã•ã„。</string>
312 379
313</resources> 380 <!-- Black backgrounds theme -->
381 <string name="use_black_backgrounds">完全ãªé»’を使用</string>
382 <string name="use_black_backgrounds_description">ダークテーマã®èƒŒæ™¯è‰²ã«é»’ãŒé©ç”¨ã•れã¾ã™ã€‚</string>
383
384 <!-- Picture-In-Picture -->
385 <string name="picture_in_picture">ピクãƒãƒ£ãƒ¼ã‚¤ãƒ³ãƒ”クãƒãƒ£ãƒ¼</string>
386 <string name="picture_in_picture_description">ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰æ™‚ã«ã‚¦ã‚¤ãƒ³ãƒ‰ã‚¦ã‚’最å°åŒ–ã™ã‚‹</string>
387 <string name="pause">中断</string>
388 <string name="play">プレイ</string>
389 <string name="mute">消音</string>
390 <string name="unmute">消音解除</string>
391
392 <!-- Licenses screen strings -->
393 <string name="licenses">ライセンス</string>
394 <string name="license_fidelityfx_fsr_description">AMDã®é«˜å“質アップスケーリング</string>
395 </resources>
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 214f95706..1b9160a23 100644
--- a/src/android/app/src/main/res/values-ko/strings.xml
+++ b/src/android/app/src/main/res/values-ko/strings.xml
@@ -1,9 +1,9 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">ì´ ì†Œí”„íŠ¸ì›¨ì–´ëŠ” 닌í…ë„ ìŠ¤ìœ„ì¹˜ 게임 콘솔용 ê²Œìž„ì„ ì‹¤í–‰í•©ë‹ˆë‹¤. 게임 타ì´í‹€ì´ë‚˜ keys는 í¬í•¨ë˜ì–´ 있지 않습니다.&lt;br /&gt;&lt;br /&gt;시작하기 ì „ì— ìž¥ì¹˜ 저장소ì—서 <![CDATA[<b> prod.keys </b>]]> 파ì¼ì„ 찾아주세요.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">ìžì„¸ížˆ 알아보기</a>]]></string> 4 <string name="app_disclaimer">ì´ ì†Œí”„íŠ¸ì›¨ì–´ëŠ” Nintendo Switch ê²Œìž„ì„ ì‹¤í–‰í•©ë‹ˆë‹¤. 게임 타ì´í‹€ì´ë‚˜ 키는 í¬í•¨ë˜ì–´ 있지 않습니다.&lt;br /&gt;&lt;br /&gt;시작하기 ì „ì— ìž¥ì¹˜ 저장소ì—서 <![CDATA[<b> prod.keys </b>]]> 파ì¼ì„ 찾아주세요.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">ìžì„¸ížˆ 알아보기</a>]]></string>
5 <string name="emulation_notification_channel_name">ì—뮬레ì´ì…˜ì´ 활성화ë¨</string> 5 <string name="emulation_notification_channel_name">ì—뮬레ì´ì…˜ì´ 활성화ë¨</string>
6 <string name="emulation_notification_channel_description">ì—뮬레ì´ì…˜ì´ 실행 ì¤‘ì¼ ë•Œ ì˜êµ¬ ì•Œë¦¼ì„ í‘œì‹œí•©ë‹ˆë‹¤.</string> 6 <string name="emulation_notification_channel_description">ì—뮬레ì´ì…˜ì´ 실행 ì¤‘ì¼ ë•Œ ì§€ì†ì ìœ¼ë¡œ ì•Œë¦¼ì„ í‘œì‹œí•©ë‹ˆë‹¤.</string>
7 <string name="emulation_notification_running">yuzu가 실행 중입니다.</string> 7 <string name="emulation_notification_running">yuzu가 실행 중입니다.</string>
8 <string name="notice_notification_channel_name">알림 ë° ì˜¤ë¥˜</string> 8 <string name="notice_notification_channel_name">알림 ë° ì˜¤ë¥˜</string>
9 <string name="notice_notification_channel_description">문제가 ë°œìƒí•˜ë©´ ì•Œë¦¼ì„ í‘œì‹œí•©ë‹ˆë‹¤.</string> 9 <string name="notice_notification_channel_description">문제가 ë°œìƒí•˜ë©´ ì•Œë¦¼ì„ í‘œì‹œí•©ë‹ˆë‹¤.</string>
@@ -11,26 +11,25 @@
11 11
12 <!-- Setup strings --> 12 <!-- Setup strings -->
13 <string name="welcome">환ì˜í•©ë‹ˆë‹¤!</string> 13 <string name="welcome">환ì˜í•©ë‹ˆë‹¤!</string>
14 <string name="welcome_description">&lt;b>yuzu&lt;/b> 를 설정하고 ì—뮬레ì´ì…˜ìœ¼ë¡œ ì´ë™í•˜ëŠ” ë°©ë²•ì„ ì•Œì•„ë³´ì„¸ìš”.</string> 14 <string name="welcome_description">&lt;b>yuzu&lt;/b>를 설정하고 ì—뮬레ì´ì…˜ì„ 시작하세요.</string>
15 <string name="get_started">시작하기</string> 15 <string name="get_started">시작하기</string>
16 <string name="keys">Keys</string> 16 <string name="keys">키 설정</string>
17 <string name="keys_description">아래 버튼ì 사용하여 &lt;b>prod.keys&lt;/b> 파ì¼ì„ ì„ íƒí•©ë‹ˆë‹¤.</string> 17 <string name="keys_description">아래 버튼으로 &lt;b>prod.keys&lt;/b> 파ì¼ì„ ì„ íƒí•©ë‹ˆë‹¤.</string>
18 <string name="select_keys">keys ì„ íƒ</string> 18 <string name="select_keys">키 ì„ íƒ</string>
19 <string name="games">게임</string> 19 <string name="games">게임</string>
20 <string name="games_description">아래 버튼으로 &lt;b>게임&lt;/b> í´ë”를 ì„ íƒí•©ë‹ˆë‹¤.</string> 20 <string name="games_description">아래 버튼으로 &lt;b>게임&lt;/b> í´ë”를 ì„ íƒí•©ë‹ˆë‹¤.</string>
21 <string name="done">완료</string> 21 <string name="done">완료</string>
22 <string name="done_description">모든 준비가 완료ë˜ì—ˆìŠµë‹ˆë‹¤.\nê²Œìž„ì„ ì¦ê¸°ì„¸ìš”!</string> 22 <string name="done_description">모ë 준비ë˜ì—ˆìŠµë‹ˆë‹¤.\nê²Œìž„ì„ ì¦ê¸°ì„¸ìš”!</string>
23 <string name="text_continue">계ì†</string> 23 <string name="text_continue">계ì†</string>
24 <string name="next">다ìŒ</string> 24 <string name="next">다ìŒ</string>
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
29 <!-- Home strings --> 28 <!-- Home strings -->
30 <string name="home_games">게임</string> 29 <string name="home_games">게임</string>
31 <string name="home_search">검색</string> 30 <string name="home_search">검색</string>
32 <string name="home_settings">설정</string> 31 <string name="home_settings">설정</string>
33 <string name="empty_gamelist">파ì¼ì„ ì°¾ì„ ìˆ˜ 없거나 ì•„ì§ ê²Œìž„ 디렉토리를 ì„ íƒí•˜ì§€ 않았습니다.</string> 32 <string name="empty_gamelist">파ì¼ì„ ì°¾ì„ ìˆ˜ 없거나 ì•„ì§ ê²Œìž„ 디렉터리를 ì„ íƒí•˜ì§€ 않았습니다.</string>
34 <string name="search_and_filter_games">게임 검색 ë° í•„í„°ë§</string> 33 <string name="search_and_filter_games">게임 검색 ë° í•„í„°ë§</string>
35 <string name="select_games_folder">게임 í´ë” ì„ íƒ</string> 34 <string name="select_games_folder">게임 í´ë” ì„ íƒ</string>
36 <string name="select_games_folder_description">yuzuê°€ 게임 목ë¡ì„ 채울 수 있ë„ë¡ í—ˆìš©</string> 35 <string name="select_games_folder_description">yuzuê°€ 게임 목ë¡ì„ 채울 수 있ë„ë¡ í—ˆìš©</string>
@@ -38,140 +37,160 @@
38 <string name="add_games_warning_description">í´ë”를 ì„ íƒí•˜ì§€ 않으면 게임 목ë¡ì— ê²Œìž„ì´ í‘œì‹œë˜ì§€ 않습니다.</string> 37 <string name="add_games_warning_description">í´ë”를 ì„ íƒí•˜ì§€ 않으면 게임 목ë¡ì— ê²Œìž„ì´ í‘œì‹œë˜ì§€ 않습니다.</string>
39 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 38 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
40 <string name="home_search_games">게임 검색</string> 39 <string name="home_search_games">게임 검색</string>
41 <string name="games_dir_selected">게임 디렉터리 ì„ íƒ</string> 40 <string name="games_dir_selected">게임 디렉터리를 설ì í–ˆìŠµë‹ˆë‹¤.</string>
42 <string name="install_prod_keys">prod.keys 설치</string> 41 <string name="install_prod_keys">prod.keys 설치</string>
43 <string name="install_prod_keys_description">íŒë§¤ìš© 게임 암호 í•´ë…ì— ìš”êµ¬</string> 42 <string name="install_prod_keys_description">패키지 게임 암호 í•´ë…ì— í•„ìš”</string>
44 <string name="install_prod_keys_warning">keys 추가를 건너뛰겠습니까?</string> 43 <string name="install_prod_keys_warning">키 추가를 건너뛰겠습니까?</string>
45 <string name="install_prod_keys_warning_description">ì •í’ˆ ê²Œìž„ì„ ì—뮬레ì´íŠ¸í•˜ë ¤ë©´ 유효한 keysê°€ 필요합니다. 계ì†í•˜ë©´ ìžì²´ 제작 앱만 ìž‘ë™í•©ë‹ˆë‹¤.</string> 44 <string name="install_prod_keys_warning_description">패키지 ê²Œìž„ì„ ì—뮬레ì´íŠ¸í•˜ë ¤ë©´ 유효한 키 ê°’ì´ í•„ìš”í•©ë‹ˆë‹¤. ì´ ë‹¨ê³„ë¥¼ 건너뛰면 홈브류 게임만 실행할 수 있습니다.</string>
46 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string> 45 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
47 <string name="notifications">알림</string> 46 <string name="notifications">알림</string>
48 <string name="notifications_description">아래 버튼으로 알림 ê¶Œí•œì„ ë¶€ì—¬í•©ë‹ˆë‹¤.</string> 47 <string name="notifications_description">아래 버튼으로 알림 ê¶Œí•œì„ ë¶€ì—¬í•©ë‹ˆë‹¤.</string>
49 <string name="give_permission">ê¶Œíœ ë¶€ì—¬</string> 48 <string name="give_permission">ìŒë¦¼ 켜기</string>
50 <string name="notification_warning">알림 권한 부여를 건너뛰겠습니까?</string> 49 <string name="notification_warning">알림ì ë„겠습니까?</string>
51 <string name="notification_warning_description">yuzu는 중요한 정보를 알려드리지 않습니다.</string> 50 <string name="notification_warning_description">yuzu가 중요한 정보를 알려드리지 않습니다.</string>
52 <string name="permission_denied">권한 ê±°ë¶€ë¨</string> 51 <string name="permission_denied">권한 ê±°ë¶€ë¨</string>
53 <string name="permission_denied_description">ì´ ê¶Œí•œì„ ë„ˆë¬´ ë§Žì´ ê±°ë¶€í–ˆìœ¼ë¯€ë¡œ ì´ì œ 시스템 설정ì—서 수ë™ìœ¼ë¡œ ê¶Œí•œì„ ë¶€ì—¬í•´ì•¼ 합니다.</string> 52 <string name="permission_denied_description">권한 í—ˆìš©ì„ ë„ˆë¬´ ë§Žì´ ê±°ë¶€í•˜ì—¬ 시스템 설정ì—서 수ë™ìœ¼ë¡œ ê¶Œí•œì„ ë¶€ì—¬í•´ì•¼ 합니다.</string>
54 <string name="about">ì •ë³´</string> 53 <string name="about">ì •ë³´</string>
55 <string name="about_description">빌드 버전, í¬ë ˆë”§ 등</string> 54 <string name="about_description">빌드 버전, í¬ë ˆë”§ 등</string>
56 <string name="warning_help">ë„움ë§</string> 55 <string name="warning_help">ë„움ë§</string>
57 <string name="warning_skip">건너뛰기</string> 56 <string name="warning_skip">건너뛰기</string>
58 <string name="warning_cancel">취소</string> 57 <string name="warning_cancel">취소</string>
59 <string name="install_amiibo_keys">Amiibo keys 설치</string> 58 <string name="install_amiibo_keys">amiibo 키 설치</string>
60 <string name="install_amiibo_keys_description">게임ì—서 아미보 사용 시 í•„ìš”</string> 59 <string name="install_amiibo_keys_description">게임ì—서 amiibo 사용 시 í•„ìš”</string>
61 <string name="invalid_keys_file">ìž˜ëª»ëœ keys íŒŒì¼ ì„ íƒ</string> 60 <string name="invalid_keys_file">ìž˜ëª»ëœ í‚¤ 파ì¼ì´ ì„ íƒë¨</string>
62 <string name="install_keys_success">keysê°€ 성공ì ìœ¼ë¡œ 설치ë¨</string> 61 <string name="install_keys_success">키 ê°’ì„ ì„¤ì¹˜í–ˆìŠµë‹ˆë‹¤.</string>
63 <string name="reading_keys_failure">암호화 keys ì½ê¸° 오류</string> 62 <string name="reading_keys_failure">암호화 키 ì½ê¸° 오류</string>
64 <string name="invalid_keys_error">ìž˜ëª»ëœ ì•”í˜¸í™” keys</string> 63 <string name="install_prod_keys_failure_extension_description">키 파ì¼ì˜ 확장ìžê°€ .keysì¸ì§€ 확ì¸í•˜ê³  다시 시ë„하세요.</string>
64 <string name="install_amiibo_keys_failure_extension_description">키 파ì¼ì˜ 확장ìžê°€ .binì¸ì§€ 확ì¸í•˜ê³  다시 시ë„하세요.</string>
65 <string name="invalid_keys_error">암호화 키가 올바르지 않ìŒ</string>
65 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
66 <string name="install_keys_failure_description">ì„ íƒí•œ 파ì¼ì´ 잘못ë˜ì—ˆê±°ë‚˜ ì†ìƒë˜ì—ˆìŠµë‹ˆë‹¤. keys를 다시 ë¤í”„하세요.</string> 67 <string name="install_keys_failure_description">ì„ íƒí•œ 파ì¼ì´ 잘못ë˜ì—ˆê±°ë‚˜ ì†ìƒë˜ì—ˆìŠµë‹ˆë‹¤. 키를 다시 ë¤í”„하세요.</string>
67 <string name="install_gpu_driver">GPU 드ë¼ì´ë²„ 설치</string> 68 <string name="install_gpu_driver">GPU 드ë¼ì´ë²„ 설치</string>
68 <string name="install_gpu_driver_description">잠재ì ìœ¼ë¡œ ë” ë‚˜ì€ ì„±ëŠ¥ ë˜ëŠ” ì •í™•ì„±ì„ ìœ„í•´ 대체 드ë¼ì´ë²„를 설치하세요.</string> 69 <string name="install_gpu_driver_description">잠재ì ìœ¼ë¡œ ë” ë‚˜ì€ ì„±ëŠ¥ ë˜ëŠ” ì •í™•ì„±ì„ ìœ„í•´ 대체 드ë¼ì´ë²„를 설치하세요.</string>
69 <string name="advanced_settings">고급 설정</string> 70 <string name="advanced_settings">고급 설정</string>
70 <string name="settings_description">ì—뮬레ì´í„° 설정 구성</string> 71 <string name="settings_description">ì—뮬레ì´í„° 설정 구성</string>
71 <string name="search_recently_played">최근 플레ì´í•œ 게임</string> 72 <string name="search_recently_played">최근 플레ì´</string>
72 <string name="search_recently_added">최근 추가한 게임</string> 73 <string name="search_recently_added">최근 추가</string>
73 <string name="search_retail">íŒë§¤ìš©</string> 74 <string name="search_retail">패키지</string>
74 <string name="search_homebrew">홈브류</string> 75 <string name="search_homebrew">홈브류</string>
75 <string name="open_user_folder">yuzu í´ë” 열기</string> 76 <string name="open_user_folder">yuzu í´ë” 열기</string>
76 <string name="open_user_folder_description">yuzuì˜ ë‚´ë¶€ íŒŒì¼ ê´€ë¦¬</string> 77 <string name="open_user_folder_description">yuzuì˜ ë‚´ë¶€ íŒŒì¼ ê´€ë¦¬</string>
77 <string name="theme_and_color_description">앱 모양 수정</string> 78 <string name="theme_and_color_description">앱 ë””ìžì¸ 편집</string>
78 <string name="no_file_manager">íŒŒì¼ ê´€ë¦¬ìžë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string> 79 <string name="no_file_manager">íŒŒì¼ ê´€ë¦¬ìžë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string>
79 <string name="notification_no_directory_link">yuzu 디렉토리를 ì—´ 수 ì—†ìŒ</string> 80 <string name="notification_no_directory_link">yuzu 디렉터리를 ì—´ 수 ì—†ìŒ</string>
80 <string name="notification_no_directory_link_description">íŒŒì¼ ê´€ë¦¬ìžì˜ 사ì´ë“œ 패ë„ì—서 ì‚¬ìš©ìž í´ë”를 수ë™ìœ¼ë¡œ 찾아주세요.</string> 81 <string name="notification_no_directory_link_description">íŒŒì¼ ê´€ë¦¬ìžì˜ 사ì´ë“œ 패ë„ì—서 ì‚¬ìš©ìž í´ë”를 수ë™ìœ¼ë¡œ 찾아주세요.</string>
81 <string name="manage_save_data">저장 ë°ì´í„° 관리</string> 82 <string name="manage_save_data">저장 ë°ì´í„° 관리</string>
82 <string name="manage_save_data_description">ë°ì´í„°ë¥¼ 저장했습니다. 아래ì—서 ì˜µì…˜ì„ ì„ íƒí•˜ì„¸ìš”.</string> 83 <string name="manage_save_data_description">저장 ë°ì´í„°ë¥¼ 발견했습니다. 아래ì—서 ì˜µì…˜ì„ ì„ íƒí•˜ì„¸ìš”.</string>
83 <string name="import_export_saves_description">저장 íŒŒì¼ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string> 84 <string name="import_export_saves_description">저장 íŒŒì¼ ê°€ì ¸ì˜¤ê¸° ë˜ëŠ” 내보내기</string>
84 <string name="save_file_imported_success">ê°ì ¸ì˜¤ê¸° 성공</string> 85 <string name="save_file_imported_success">ë°ì´í„°ë¥¼ 불러왔습니다.</string>
85 <string name="save_file_invalid_zip_structure">저장 디렉터리 구조가 잘못ë¨</string> 86 <string name="save_file_invalid_zip_structure">올바르지 ì•Šì€ ì €ìž¥ 디렉터리 구조</string>
86 <string name="save_file_invalid_zip_structure_description">첫 번째 하위 í´ë” ì´ë¦„ì€ ê²Œìž„ì˜ íƒ€ì´í‹€ ID여야 합니다.</string> 87 <string name="save_file_invalid_zip_structure_description">첫 번째 하위 í´ë” ì´ë¦„ì€ ê²Œìž„ì˜ íƒ€ì´í‹€ ID여야 합니다.</string>
87 <string name="import_saves">가져오기</string> 88 <string name="import_saves">가져오기</string>
88 <string name="export_saves">내보내기</string> 89 <string name="export_saves">내보내기</string>
89 90 <string name="install_firmware">펌웨어 설치</string>
91 <string name="install_firmware_description">펌웨어는 ZIP 파ì¼ì´ë©° ì¼ë¶€ ê²Œìž„ì„ ë¶€íŒ…í•˜ëŠ” ë° í•„ìš”í•©ë‹ˆë‹¤.</string>
92 <string name="firmware_installing">펌웨어 설치</string>
93 <string name="firmware_installed_success">펌웨어를 설치했습니다.</string>
94 <string name="firmware_installed_failure">펌웨어 설치 실패</string>
95 <string name="share_log">디버그 로그 공유</string>
96 <string name="share_log_description">yuzuì˜ ë¡œê·¸ 파ì¼ì„ 공유하여 문제 디버깅하기</string>
97 <string name="share_log_missing">로그 파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다.</string>
98 <string name="install_game_content">게임 콘í…츠 설치</string>
99 <string name="install_game_content_description">게임 ì—…ë°ì´íЏ ë˜ëŠ” DLC 설치</string>
100 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
90 <!-- About screen strings --> 101 <!-- About screen strings -->
91 <string name="gaia_is_not_real">ê°€ì´ì•„는 진짜가 아님</string> 102 <string name="gaia_is_not_real">ê°€ì´ì•„는 진짜가 아님</string>
92 <string name="copied_to_clipboard">í´ë¦½ë³´ë“œì— 복사</string> 103 <string name="copied_to_clipboard">í´ë¦½ë³´ë“œì— 복사ë˜ì—ˆìŠµë‹ˆë‹¤.</string>
93 <string name="about_app_description">오픈 소스 스위치 ì—뮬레ì´í„°</string> 104 <string name="about_app_description">오픈 소스 Switch ì—뮬레ì´í„°</string>
94 <string name="contributors">기여ìž</string> 105 <string name="contributors">기여ìž</string>
95 <string name="contributors_description">yuzu íŒ€ì˜ \u2764로 제작</string> 106 <string name="contributors_description">yuzu íŒ€ì˜ \u2764로 제작</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 107 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
108 <string name="licenses_description">Androidìš© yuzu를 가능하게 하는 프로ì íЏ</string>
97 <string name="build">빌드</string> 109 <string name="build">빌드</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 110 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 111 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 112 <string name="github_link">https://github.com/yuzu-emu</string>
101 113
102 <!-- Early access upgrade strings --> 114 <!-- Early access upgrade strings -->
103 <string name="early_access">미리 ì²´í—˜í˜ê¸°</string> 115 <string name="early_access">앞서 해보기</string>
104 <string name="get_early_access">미리 ì²´í—˜í˜ê¸° ì‹ ì²­</string> 116 <string name="get_early_access">앞서 해보기 ì‹ ì²­</string>
105 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string> 117 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
106 <string name="get_early_access_description">ìµœì²¨ë¨ ê¸°ëŠ¥, 미리 체험하기 ì—…ë°ì´íЏ 등</string> 118 <string name="get_early_access_description">최신 기능, ì—…ë°ì´íЏ 미리 ì²´í—˜ 등</string>
107 <string name="early_access_benefits">미리 ì²´í—˜í˜ê¸° 혜íƒ</string> 119 <string name="early_access_benefits">앞서 해보기 혜íƒ</string>
108 <string name="cutting_edge_features">ìµœì²¨ë¨ ê¸°ëŠ¥</string> 120 <string name="cutting_edge_features">최신 기능</string>
109 <string name="early_access_updates">미리 체험하기 ì—…ë°ì´íЏ</string> 121 <string name="early_access_updates">ì—…ë°ì´íЏ 미리 ì²´í—˜</string>
110 <string name="no_manual_installation">ìˆ˜ë™ ì„¤ì¹˜ 불필요</string> 122 <string name="no_manual_installation">ìˆ˜ë™ ì„¤ì¹˜ 불필요</string>
111 <string name="prioritized_support">ìš°ì„  ì§€ì›</string> 123 <string name="prioritized_support">ìš°ì„  ì§€ì›</string>
112 <string name="helping_game_preservation">게임 ë³´ì¡´ ë„ì€ì£¼ê¸°</string> 124 <string name="helping_game_preservation">게임 ë³´ì¡´ ì§€ì</string>
113 <string name="our_eternal_gratitude">ì˜ì›í•œ ê°ì‚¬ì˜ 마ìŒì„ 전합니다</string> 125 <string name="our_eternal_gratitude">ìš°ë¦¬ì˜ ì˜ì›í•œ ê°ì‚¬ì˜ 마ìŒ</string>
114 <string name="are_you_interested">관심 있으세요?</string> 126 <string name="are_you_interested">관심 있으세요?</string>
115 127
116 <!-- General settings strings --> 128 <!-- General settings strings -->
117 <string name="frame_limit_enable">제한 ì†ë„ 활성화</string> 129 <string name="frame_limit_enable">ì†ë„ 제한</string>
118 <string name="frame_limit_enable_description">활성화하면 ì—뮬레ì´ì…˜ ì†ë„ê°€ ì •ìƒ ì†ë„ì˜ ì§€ì •ëœ ë¹„ìœ¨ë¡œ 제한ë©ë‹ˆë‹¤.</string> 130 <string name="frame_limit_enable_description">ì—뮬레ì´ì…˜ ì†ë„를 ì •ìƒ ì†ë„ì˜ ì§€ì •ëœ ë¹„ìœ¨ë¡œ 제한합니다.</string>
119 <string name="frame_limit_slider">ì†ë„ 제한 비율</string> 131 <string name="frame_limit_slider">ì†ë„ 제한 비율</string>
120 <string name="frame_limit_slider_description">ì—뮬레ì´ì…˜ ì†ë„를 제한할 ë¹„ìœ¨ì„ ì§€ì •í•©ë‹ˆë‹¤. ê¸°ë³¸ê°’ì¸ 100%로 설정하면 ì—뮬레ì´ì…˜ì´ ì •ìƒ ì†ë„로 제한ë©ë‹ˆë‹¤. ê°’ì´ ë†’ê±°ë‚˜ 낮으면 ì†ë„ ì œí•œì´ ì¦ê°€í•˜ê±°ë‚˜ ê°ì†Œí•©ë‹ˆë‹¤.</string> 132 <string name="frame_limit_slider_description">ì—뮬레ì´ì…˜ ì†ë„ì˜ ì œí•œ ë¹„ìœ¨ì„ ì§€ì •í•©ë‹ˆë‹¤. 100%ê°€ ì •ìƒ ì†ë„입니다. ê°’ì´ ë†’ê±°ë‚˜ 낮으면 ì†ë„ ì œí•œì´ ì¦ê°€í•˜ê±°ë‚˜ ê°ì†Œí•©ë‹ˆë‹¤.</string>
121 <string name="cpu_accuracy">CPU 정확ë„</string> 133 <string name="cpu_accuracy">CPU 정확ë„</string>
122
123 <!-- System settings strings --> 134 <!-- System settings strings -->
124 <string name="use_docked_mode">ë„킹 모드</string> 135 <string name="use_docked_mode">ë 모드</string>
125 <string name="use_docked_mode_description">ë„킹 모드ì—서 ì—뮬레ì´ì…˜í•˜ë©´ ì„±ëŠ¥ì´ ì €í•˜ë˜ëŠ” 대신 í•´ìƒë„ê°€ í–¥ìƒë©ë‹ˆë‹¤.</string> 136 <string name="use_docked_mode_description">í•´ìƒë„를 높ì´ë©° ì„±ëŠ¥ì´ ì €í•˜ë©ë‹ˆë‹¤. 비활성화시 휴대 모드가 사용ë˜ë©° í•´ìƒë„는 낮아지고 ì„±ëŠ¥ì€ í–¥ìƒë©ë‹ˆë‹¤.</string>
126 <string name="emulated_region">ì—뮬레ì´íŠ¸ëœ ì§€ì—­</string> 137 <string name="emulated_region">ì—뮬레ì´íЏ 지역</string>
127 <string name="emulated_language">ì—뮬레ì´íŠ¸ëœ ì–¸ì–´</string> 138 <string name="emulated_language">ì—뮬레ì´íЏ 언어</string>
128 <string name="select_rtc_date">RTC ë‚ ì§œ ì„ íƒ</string> 139 <string name="select_rtc_date">RTC ë‚ ì§œ ì„ íƒ</string>
129 <string name="select_rtc_time">RTC 시간 ì„ íƒ</string> 140 <string name="select_rtc_time">RTC 시간 ì„ íƒ</string>
130 <string name="use_custom_rtc">커스텀 RTC 활성화</string> 141 <string name="use_custom_rtc">ì‚¬ìš©ìž ì§ì • RTC</string>
131 <string name="use_custom_rtc_description">ì´ ì„¤ì •ì„ ì‚¬ìš©í•˜ë©´ 현재 시스템 시간과 별ë„로 ì‚¬ìš©ìž ì§€ì • 실시간 시계를 설정할 수 있ìŒ</string> 142 <string name="use_custom_rtc_description">현재 시스템 시간과 별ë„로 ì‚¬ìš©ìž ì§€ì • 실시간 시계를 설정할 수 있습니다.</string>
132 <string name="set_custom_rtc">커스텀 RTC 설정</string> 143 <string name="set_custom_rtc">ì‚¬ìš©ìž ì§ì • RTC 설정</string>
133 144
134 <!-- Graphics settings strings --> 145 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">ì •í™•ë„ ìˆ˜ì¤€</string> 146 <string name="renderer_accuracy">ì •í™•ë„ ìˆ˜ì¤€</string>
137 <string name="renderer_resolution">í•´ìƒë„</string> 147 <string name="renderer_resolution">í•´ìƒë„ (휴대 모드/ë… ëª¨ë“œ)</string>
138 <string name="renderer_vsync">수ì§ë™ê¸°í™” 모드</string> 148 <string name="renderer_vsync">수ì§ë™ê¸°í™” 모드</string>
139 <string name="renderer_aspect_ratio">화면비</string> 149 <string name="renderer_aspect_ratio">화면비</string>
140 <string name="renderer_scaling_filter">ì°½ ì ì‘ í•„í„°</string> 150 <string name="renderer_scaling_filter">윈ë„ìš° ì ì‘ í•„í„°</string>
141 <string name="renderer_anti_aliasing">안티-ì—ì¼ë¦¬ì–´ì‹± 방법</string> 151 <string name="renderer_anti_aliasing">안티ì—ì¼ë¦¬ì–´ì‹± 방법</string>
142 <string name="renderer_force_max_clock">최대 í´ëŸ­ ê°•ì œ 설정 (아드레노만 해당)</string> 152 <string name="renderer_force_max_clock">최대 í´ëŸ­ ê°•ì œ 설정 (아드레노 ì „ìš©)</string>
143 <string name="renderer_force_max_clock_description">GPUê°€ 가능한 최대 í´ëŸ­ìœ¼ë¡œ 실행ë˜ë„ë¡ ê°•ì œí•©ë‹ˆë‹¤ (ì—´ 제약 ì¡°ê±´ì€ ì—¬ì „ížˆ ì ìš©ë©ë‹ˆë‹¤).</string> 153 <string name="renderer_force_max_clock_description">GPUê°€ 가능한 최대 í´ëŸ­ìœ¼ë¡œ 실행ë˜ë„ë¡ ê°•ì œí•©ë‹ˆë‹¤ (ì—´ 제약 ì¡°ê±´ì€ ì—¬ì „ížˆ ì ìš©ë©ë‹ˆë‹¤).</string>
144 <string name="renderer_asynchronous_shaders">비ë™ê¸° ì…°ì´ë” 사용</string> 154 <string name="renderer_asynchronous_shaders">비ë™ê¸° ì…°ì´ë” 사용</string>
145 <string name="renderer_asynchronous_shaders_description">ì…°ì´ë”를 비ë™ê¸°ì‹ìœ¼ë¡œ 컴파ì¼í•˜ë¯€ë¡œ ëŠê¹€ 현ìƒì´ 줄어들지만 글리치가 ë°œìƒí•  수 있습니다.</string> 155 <string name="renderer_asynchronous_shaders_description">ì…°ì´ë”를 비ë™ê¸°ì‹ìœ¼ë¡œ 컴파ì¼í•˜ì—¬ ëŠê¹€ 현ìƒì„ 줄ì´ì§€ë§Œ 글리치가 ë°œìƒí•  수 있습니다.</string>
146 <string name="renderer_debug">그래픽 디버깅 활성화</string> 156 <string name="renderer_reactive_flushing">ë°˜ì‘형 플러싱 사용</string>
147 <string name="renderer_debug_description">ì´ ì˜µì…˜ì„ ì„ íƒí•˜ë©´ 그래픽 APIê°€ ëŠë¦° 디버깅 모드로 전환ë©ë‹ˆë‹¤.</string> 157 <string name="renderer_reactive_flushing_description">ì¼ë¶€ 게임ì—서 성능 저하를 ê°ìˆ˜í•˜ê³  ë Œë”ë§ ì •í™•ë„를 í–¥ìƒí•©ë‹ˆë‹¤.</string>
148 <string name="use_disk_shader_cache">ë””ìŠ¤í¬ ì…°ì´ë” ìºì‹œ 사용</string> 158 <string name="use_disk_shader_cache">ë””ìŠ¤í¬ ì…°ì´ë” ìºì‹œ</string>
149 <string name="use_disk_shader_cache_description">ìƒì„±ëœ ì…°ì´ë”를 디스í¬ì— 저장하고 불러오기하여 ëŠê¹€ 현ìƒì„ 줄입니다.</string> 159 <string name="use_disk_shader_cache_description">ìƒì„±ëœ ì…°ì´ë”를 ë¡œì»¬ì— ì €ìž¥í•˜ê³  로드하여 ëŠê¹€ 현ìƒì„ 줄입니다.</string>
150 160
151 <!-- Audio settings strings --> 161 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string>
163 <string name="renderer_api">API</string>
164 <string name="renderer_debug">그래픽 디버깅</string>
165 <string name="renderer_debug_description">그래픽 API를 ëŠë¦° 디버깅 모드로 설정합니다.</string>
152 <string name="audio_volume">볼륨</string> 166 <string name="audio_volume">볼륨</string>
153 <string name="audio_volume_description">오디오 ì¶œë ¥ì˜ ë³¼ë¥¨ì„ ì§€ì •í•©ë‹ˆë‹¤.</string> 167 <string name="audio_volume_description">오디오 ì¶œë ¥ì˜ ë³¼ë¥¨ì„ ì§€ì •í•©ë‹ˆë‹¤.</string>
154 168
155 <!-- Miscellaneous --> 169 <!-- Miscellaneous -->
156 <string name="slider_default">기본값</string> 170 <string name="slider_default">기본값</string>
157 <string name="ini_saved">ì €ìž¥ëœ ì„¤ì •</string> 171 <string name="ini_saved">ì„¤ì •ì´ ì €ìž¥ë˜ì—ˆìŠµë‹ˆë‹¤.</string>
158 <string name="gameid_saved">%1$s를 ìœí•´ ì €ìž¥ëœ ì„¤ì •</string> 172 <string name="gameid_saved">%1$s ì ìš© 설ì ì´ 저장ë˜ì—ˆìŠµë‹ˆë‹¤.</string>
159 <string name="error_saving">%1$s.ini 저장 중 오류: %2$s</string> 173 <string name="error_saving">%1$s.ini 저장 중 오류 ë°œìƒ: %2$s</string>
160 <string name="loading">불러오기 중...</string> 174 <string name="loading">불러오는 중...</string>
161 <string name="reset_setting_confirmation">ì´ ì„¤ì •ì„ ê¸°ë³¸ê°’ìœ¼ë¡œ ë˜ëŒë¦¬ê² ìŠµë‹ˆê¹Œ?</string> 175 <string name="reset_setting_confirmation">ì´ ì„¤ì •ì„ ê¸°ë³¸ê°’ìœ¼ë¡œ 재설정하겠습니까?</string>
162 <string name="reset_to_default">기본값으로 재설정</string> 176 <string name="reset_to_default">기본값으로 재설정</string>
163 <string name="reset_all_settings">모든 ì„¤ì •ì„ ì´ˆê¸°í™”í•˜ê² ìŠµë‹ˆê¹Œ?</string> 177 <string name="reset_all_settings">모든 ì„¤ì •ì„ ì´ˆê¸°í™”í•˜ê² ìŠµë‹ˆê¹Œ?</string>
164 <string name="reset_all_settings_description">모든 고급 ì„¤ì •ì´ ê¸°ë³¸ 구성으로 재설정ë©ë‹ˆë‹¤. ì´ ì„¤ì •ì€ ë˜ëŒë¦´ 수 없습니다.</string> 178 <string name="reset_all_settings_description">모든 고급 ì„¤ì •ì´ ê¸°ë³¸ 구성으로 재설정ë©ë‹ˆë‹¤. ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다.</string>
165 <string name="settings_reset">설정 초기화</string> 179 <string name="settings_reset">설정 초기화</string>
166 <string name="close">닫기</string> 180 <string name="close">닫기</string>
167 <string name="learn_more">ìžì„¸ížˆ 알아보기</string> 181 <string name="learn_more">ìžì„¸ížˆ</string>
168 182 <string name="auto">ìžë™</string>
183 <string name="submit">제출</string>
184 <string name="string_null">Null</string>
185 <string name="string_import">가져오기</string>
186 <string name="export">내보내기</string>
169 <!-- GPU driver installation --> 187 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">GPU 드ë¼ì´ë²„ ì„ íƒ</string> 188 <string name="select_gpu_driver">GPU 드ë¼ì´ë²„ ì„ íƒ</string>
171 <string name="select_gpu_driver_title">현재 사용 ì¤‘ì¸ GPU 드ë¼ì´ë²„를 êµì²´í•˜ê² ìŠµë‹ˆê¹Œ?</string> 189 <string name="select_gpu_driver_title">현재 ì‚¬ìš©ì¤‘ì¸ GPU 드ë¼ì´ë²„를 변경하겠습니까?</string>
172 <string name="select_gpu_driver_install">설치</string> 190 <string name="select_gpu_driver_install">설치</string>
173 <string name="select_gpu_driver_default">기본값</string> 191 <string name="select_gpu_driver_default">기본값</string>
174 <string name="select_gpu_driver_use_default">기본 GPU 드ë¼ì´ë²„ 사용</string> 192 <string name="select_gpu_driver_use_default">기본 GPU 드ë¼ì´ë²„를 사용합니다.</string>
193 <string name="select_gpu_driver_error">ìž˜ëª»ëœ ë“œë¼ì´ë¸Œê°€ ì„ íƒë˜ì—ˆìŠµë‹ˆë‹¤. 시스템 ê¸°ë³¸ê°’ì„ ì‚¬ìš©í•©ë‹ˆë‹¤.</string>
175 <string name="system_gpu_driver">시스템 GPU 드ë¼ì´ë²„</string> 194 <string name="system_gpu_driver">시스템 GPU 드ë¼ì´ë²„</string>
176 <string name="installing_driver">드ë¼ì´ë²„ 설치 중...</string> 195 <string name="installing_driver">드ë¼ì´ë²„ 설치 중...</string>
177 196
@@ -182,51 +201,50 @@
182 <string name="preferences_graphics">그래픽</string> 201 <string name="preferences_graphics">그래픽</string>
183 <string name="preferences_audio">오디오</string> 202 <string name="preferences_audio">오디오</string>
184 <string name="preferences_theme">테마 ë° ìƒ‰ìƒ</string> 203 <string name="preferences_theme">테마 ë° ìƒ‰ìƒ</string>
204 <string name="preferences_debug">디버그</string>
185 205
186 <!-- ROM loading errors --> 206 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">ë¡¬ì´ ì•”í˜¸í™”ë˜ì—ˆìŒ</string> 207 <string name="loader_error_encrypted">롬 파ì¼ì´ 암호화ë˜ì–´ìžˆìŒ</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[ê°€ì´ë“œì— ë”°ë¼ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">게임 카트리지</a> ë˜ëŠ” <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-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>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[Pê²Œìž„ì„ í•´ë…í•  수 있ë„ë¡ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> 파ì¼ì´ 설치ë˜ì–´ 있는지 확ì¸í•˜ì„¸ìš”.]]></string>
190 <string name="loader_error_video_core">비디오 코어를 초기화하는 ë™ì•ˆ 오류 ë°œìƒ</string> 209 <string name="loader_error_video_core">비디오 코어를 초기화하는 ë™ì•ˆ 오류 ë°œìƒ</string>
191 <string name="loader_error_video_core_description">ì´ ë¬¸ì œëŠ” ì¼ë°˜ì ìœ¼ë¡œ 호환ë˜ì§€ 않는 GPU 드ë¼ì´ë²„로 ì¸í•´ ë°œìƒí•©ë‹ˆë‹¤. ì‚¬ìš©ìž ì§€ì • GPU 드ë¼ì´ë²„를 설치하면 ì´ ë¬¸ì œê°€ í•´ê²°ë  ìˆ˜ 있습니다.</string> 210 <string name="loader_error_video_core_description">ì¼ë°˜ì ìœ¼ë¡œ ì´ ë¬¸ì œëŠ” 호환ë˜ì§€ 않는 GPU 드ë¼ì´ë²„로 ì¸í•´ ë°œìƒí•©ë‹ˆë‹¤. ì‚¬ìš©ìž ì§€ì • GPU 드ë¼ì´ë²„를 설치하면 ì´ ë¬¸ì œê°€ í•´ê²°ë  ìˆ˜ 있습니다.</string>
192 <string name="loader_error_invalid_format">ë¡¬ì„ ë¶ˆëŸ¬ì˜¬ 수 ì—†ìŒ</string> 211 <string name="loader_error_invalid_format">롬 파ì¼ì„ 불러올 수 ì—†ìŒ</string>
193 <string name="loader_error_file_not_found">롬 파ì¼ì´ 존재하지 않ìŒ</string> 212 <string name="loader_error_file_not_found">롬 파ì¼ì´ 존재하지 않ìŒ</string>
194 213
195 <!-- Emulation Menu --> 214 <!-- Emulation Menu -->
196 <string name="emulation_exit">ì—뮬레ì´ì…˜ 종료</string> 215 <string name="emulation_exit">ì—뮬레ì´ì…˜ 종료</string>
197 <string name="emulation_done">완료</string> 216 <string name="emulation_done">완료</string>
198 <string name="emulation_fps_counter">FPS 카운터</string> 217 <string name="emulation_fps_counter">FPS 표시</string>
199 <string name="emulation_toggle_controls">í† ê¸ ì œì–´</string> 218 <string name="emulation_toggle_controls">컨트롤러 ì íƒ</string>
200 <string name="emulation_rel_stick_center">ìƒëŒ€ 스틱 센터</string> 219 <string name="emulation_rel_stick_center">ìŠ¤í‹±ì˜ ì¤‘ì‹¬ ì´ë™</string>
201 <string name="emulation_dpad_slide">ì‹­ìžíŒ¨ë“œ 슬ë¼ì´ë“œ</string> 220 <string name="emulation_dpad_slide">ì‹­ìží‚¤ 슬ë¼ì´ë“œ</string>
202 <string name="emulation_haptics">햅틱</string> 221 <string name="emulation_haptics">터치 햅틱</string>
203 <string name="emulation_show_overlay">ì˜¤ë²„ë ˆì´ í‘œì‹œ</string> 222 <string name="emulation_show_overlay">컨트롤러 표시</string>
204 <string name="emulation_toggle_all">ëª¨ë‘ í† ê¸€</string> 223 <string name="emulation_toggle_all">ëª¨ë‘ ì„ íƒ</string>
205 <string name="emulation_control_adjust">ì˜¤ë²„ë ˆì´ ì¡°ì •</string> 224 <string name="emulation_control_adjust">컨트롤러 ì¡°ì •</string>
206 <string name="emulation_control_scale">스케ì¼</string> 225 <string name="emulation_control_scale">í¬ê¸°</string>
207 <string name="emulation_control_opacity">불투명ë„</string> 226 <string name="emulation_control_opacity">불투명ë„</string>
208 <string name="emulation_touch_overlay_reset">ì˜¤ë²„ë ˆì´ ìž¬ì„¤ì •</string> 227 <string name="emulation_touch_overlay_reset">컨트롤러 설정 초기화</string>
209 <string name="emulation_touch_overlay_edit">오ë²ë ˆì´ 편집</string> 228 <string name="emulation_touch_overlay_edit">컨트롤러 위치 편집</string>
210 <string name="emulation_pause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지</string> 229 <string name="emulation_pause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지</string>
211 <string name="emulation_unpause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지 í•´ì œ</string> 230 <string name="emulation_unpause">ì—뮬레ì´ì…˜ ì¼ì‹œ 중지 í•´ì œ</string>
212 <string name="emulation_input_overlay">ì˜¤ë²„ë ˆì´ ì˜µì…˜</string> 231 <string name="emulation_input_overlay">화면 ì˜¤ë²„ë ˆì´ ì„¤ì •</string>
213 232
214 <string name="load_settings">설정 불러오기 중...</string> 233 <string name="load_settings">설정 불러오는 중...</string>
215 234
216 <!-- Software keyboard --> 235 <!-- Software keyboard -->
217 <string name="software_keyboard">ê°€ìƒ í‚¤ë³´ë“œ</string> 236 <string name="software_keyboard">소프트웨어 키보드</string>
218 237
219 <!-- Errors and warnings --> 238 <!-- Errors and warnings -->
220 <string name="abort_button">정보</string> 239 <string name="abort_button">중단</string>
221 <string name="continue_button">계ì†</string> 240 <string name="continue_button">계ì†</string>
222 <string name="system_archive_not_found">시스템 ì•„ì¹´ì´ë¸Œë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string> 241 <string name="system_archive_not_found">시스템 ì•„ì¹´ì´ë¸Œë¥¼ ì°¾ì„ ìˆ˜ ì—†ìŒ</string>
223 <string name="system_archive_not_found_message">%sê°€ 누ë½ë˜ì—ˆìŠµë‹ˆë‹¤. 시스템 ì•„ì¹´ì´ë¸Œë¥¼ ë¤í”„하세요.\nì—뮬레ì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí•  수 있습니다.</string> 242 <string name="system_archive_not_found_message">%sê°€ 누ë½ë˜ì—ˆìŠµë‹ˆë‹¤. 시스템 ì•„ì¹´ì´ë¸Œë¥¼ ë¤í”„하세요.\nì—뮬레ì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí•  수 있습니다.</string>
224 <string name="system_archive_general">시스템 ì•„ì¹´ì´ë¸Œ</string> 243 <string name="system_archive_general">시스템 ì•„ì¹´ì´ë¸Œ</string>
225 <string name="save_load_error">저장하기/불러오기 오류</string> 244 <string name="save_load_error">저장하기/불러오기 오류</string>
226 <string name="fatal_error">치명ì ì¸ 오류</string> 245 <string name="fatal_error">ì¹˜ëª…ì  ì˜¤ë¥˜</string>
227 <string name="fatal_error_message">치명ì ì¸ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¡œê·¸ë¥¼ 확ì¸í•˜ì‹­ì‹œì˜¤.\nì—뮬레ì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí•  수 있습니다.</string> 246 <string name="fatal_error_message">ì¹˜ëª…ì  ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¡œê·¸ë¥¼ 확ì¸í•˜ì‹­ì‹œì˜¤.\nì—뮬레ì´ì…˜ì„ 계ì†í•˜ë©´ ì¶©ëŒ ë° ë²„ê·¸ê°€ ë°œìƒí•  수 있습니다.</string>
228 <string name="performance_warning">ì´ ì„¤ì •ì„ ë„ë©´ ì—뮬레ì´ì…˜ ì„±ëŠ¥ì´ í¬ê²Œ 저하ë©ë‹ˆë‹¤! 최ìƒì˜ í™˜ê²½ì„ ìœ„í•´ ì´ ì„¤ì •ì„ í™œì„±í™”ëœ ìƒíƒœë¡œ ë‘는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</string> 247 <string name="performance_warning">ì´ ì„¤ì •ì„ ë„ë©´ ì—뮬레ì´ì…˜ ì„±ëŠ¥ì´ í¬ê²Œ 저하ë©ë‹ˆë‹¤! 최ìƒì˜ í™˜ê²½ì„ ìœ„í•´ ì´ ì„¤ì •ì„ í™œì„±í™”ëœ ìƒíƒœë¡œ ë‘는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤.</string>
229
230 <!-- Region Names --> 248 <!-- Region Names -->
231 <string name="region_japan">ì¼ë³¸</string> 249 <string name="region_japan">ì¼ë³¸</string>
232 <string name="region_usa">미국</string> 250 <string name="region_usa">미국</string>
@@ -234,12 +252,11 @@
234 <string name="region_australia">호주</string> 252 <string name="region_australia">호주</string>
235 <string name="region_china">중국</string> 253 <string name="region_china">중국</string>
236 <string name="region_korea">대한민국</string> 254 <string name="region_korea">대한민국</string>
237 <string name="region_taiwan">타ì´ì™„</string> 255 <string name="region_taiwan">대만</string>
238
239 <!-- Language Names -->
240 256
257 <string name="memory_gigabyte">ì˜êµ­ 하계 표준시(GB)</string>
241 <!-- Renderer APIs --> 258 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">불칸</string> 259 <string name="renderer_vulkan">Vulcan</string>
243 <string name="renderer_none">ì—†ìŒ</string> 260 <string name="renderer_none">ì—†ìŒ</string>
244 261
245 <!-- Renderer Accuracy --> 262 <!-- Renderer Accuracy -->
@@ -256,17 +273,17 @@
256 <string name="resolution_four">4X (2880p/4320p) (ëŠë¦¼)</string> 273 <string name="resolution_four">4X (2880p/4320p) (ëŠë¦¼)</string>
257 274
258 <!-- Renderer VSync --> 275 <!-- Renderer VSync -->
259 <string name="renderer_vsync_immediate">즉시 (ë)</string> 276 <string name="renderer_vsync_immediate">ì¦‰ê° í‘œì‹œ (ë„기)</string>
260 <string name="renderer_vsync_mailbox">ë©”ì¼ë°•스</string> 277 <string name="renderer_vsync_mailbox">ë©”ì¼ë°•스</string>
261 <string name="renderer_vsync_fifo">FIFO (켬)</string> 278 <string name="renderer_vsync_fifo">FIFO (켜기)</string>
262 <string name="renderer_vsync_fifo_relaxed">FIFO 릴랙스</string> 279 <string name="renderer_vsync_fifo_relaxed">FIFO Relaxed</string>
263 280
264 <!-- Scaling Filters --> 281 <!-- Scaling Filters -->
265 <string name="scaling_filter_nearest_neighbor">가장 가까운 ì´ì›ƒ</string> 282 <string name="scaling_filter_nearest_neighbor">최근접 ë³´ê°„</string>
266 <string name="scaling_filter_bilinear">ì´ì¤‘선형</string> 283 <string name="scaling_filter_bilinear">ìŒì„ í˜• ë³´ê°„</string>
267 <string name="scaling_filter_bicubic">고등차수보간</string> 284 <string name="scaling_filter_bicubic">ìŒìž…ë°© ë³´ê°„</string>
268 <string name="scaling_filter_gaussian">가우시안</string> 285 <string name="scaling_filter_gaussian">가우시안</string>
269 <string name="scaling_filter_scale_force">스케ì¼í¬ìФ</string> 286 <string name="scaling_filter_scale_force">ScaleForce</string>
270 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ 초고해ìƒë„</string> 287 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ 초고해ìƒë„</string>
271 288
272 <!-- Anti-Aliasing --> 289 <!-- Anti-Aliasing -->
@@ -274,27 +291,29 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 291 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 292 <string name="anti_aliasing_smaa">SMAA</string>
276 293
294 <string name="screen_layout_auto">ìžë™</string>
295
277 <!-- Aspect Ratios --> 296 <!-- Aspect Ratios -->
278 <string name="ratio_default">기본 (16:9)</string> 297 <string name="ratio_default">기본 (16:9)</string>
279 <string name="ratio_force_four_three">강제 4:3</string> 298 <string name="ratio_force_four_three">강제 4:3</string>
280 <string name="ratio_force_twenty_one_nine">강제 21:9</string> 299 <string name="ratio_force_twenty_one_nine">강제 21:9</string>
281 <string name="ratio_force_sixteen_ten">강제 16:10</string> 300 <string name="ratio_force_sixteen_ten">강제 16:10</string>
282 <string name="ratio_stretch">ì°½ì— ë§žê²Œ 늘림</string> 301 <string name="ratio_stretch">í™”ë©´ì— ë§žì¶¤</string>
283 302
284 <!-- CPU Accuracy --> 303 <!-- CPU Accuracy -->
285 <string name="cpu_accuracy_accurate">정확함</string> 304 <string name="cpu_accuracy_accurate">정확함</string>
286 <string name="cpu_accuracy_unsafe">안전하지 않ìŒ</string> 305 <string name="cpu_accuracy_unsafe">최ì í™” (안전하지 않ìŒ)</string>
287 <string name="cpu_accuracy_paranoid">편ì§ì¦ (ëŠë¦¼)</string> 306 <string name="cpu_accuracy_paranoid">최ì í™”하ì§ì•ŠìŒ (ëŠë¦¼)</string>
288 307
289 <!-- Gamepad Buttons --> 308 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">ì‹­ìžíŒ¨ë“œ</string> 309 <string name="gamepad_d_pad">ì‹­ìží‚¤</string>
291 <string name="gamepad_left_stick">L 스틱</string> 310 <string name="gamepad_left_stick">L 스틱</string>
292 <string name="gamepad_right_stick">R 스틱</string> 311 <string name="gamepad_right_stick">R 스틱</string>
293 <string name="gamepad_home">홈</string> 312 <string name="gamepad_home">홈</string>
294 <string name="gamepad_screenshot">스í¬ë¦°ìƒ·</string> 313 <string name="gamepad_screenshot">스í¬ë¦°ìƒ·</string>
295 314
296 <!-- Disk shader cache --> 315 <!-- Disk shader cache -->
297 <string name="preparing_shaders">ì…°ì´ë” 준비하기</string> 316 <string name="preparing_shaders">ì…°ì´ë” 준비하는 중</string>
298 <string name="building_shaders">ì…°ì´ë” 빌드 중</string> 317 <string name="building_shaders">ì…°ì´ë” 빌드 중</string>
299 318
300 <!-- Theme options --> 319 <!-- Theme options -->
@@ -303,13 +322,19 @@
303 <string name="theme_material_you">Material You</string> 322 <string name="theme_material_you">Material You</string>
304 323
305 <!-- Theme Modes --> 324 <!-- Theme Modes -->
306 <string name="change_theme_mode">테마 모드 변경</string> 325 <string name="change_theme_mode">ë‹¤í¬ ëª¨ë“œ 설정</string>
307 <string name="theme_mode_follow_system">팔로우 시스템</string> 326 <string name="theme_mode_follow_system">시스템 값 사용</string>
308 <string name="theme_mode_light">ë°ìŒ</string> 327 <string name="theme_mode_light">ë¼ì´íЏ 모드</string>
309 <string name="theme_mode_dark">ì–´ë‘움</string> 328 <string name="theme_mode_dark">ë‹¤í¬ ëª¨ë“œ</string>
310 329
311 <!-- Black backgrounds theme --> 330 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">ê²€ì€ìƒ‰ ë°°ê²½ 사용</string> 331 <string name="use_black_backgrounds">검정 ë°°ê²½</string>
313 <string name="use_black_backgrounds_description">ì–´ë‘ìš´ 테마를 사용할 때는 ê²€ì€ìƒ‰ ë°°ê²½ì„ ì ìš©í•©ë‹ˆë‹¤.</string> 332 <string name="use_black_backgrounds_description">ì–´ë‘ìš´ 테마를 사용할 때는 검정 ë°°ê²½ì„ ì ìš©í•©ë‹ˆë‹¤.</string>
333
334 <string name="mute">ìŒì†Œê±°</string>
335 <string name="unmute">ìŒì†Œê±° í•´ì œ</string>
314 336
315</resources> 337 <!-- Licenses screen strings -->
338 <string name="licenses">ë¼ì´ì„¼ìФ</string>
339 <string name="license_fidelityfx_fsr_description">AMDì˜ ê³ í’ˆì§ˆ 업스케ì¼ë§</string>
340 </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 5443cef42..3162a9d41 100644
--- a/src/android/app/src/main/res/values-nb/strings.xml
+++ b/src/android/app/src/main/res/values-nb/strings.xml
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Denne programvaren vil kjøre spill for Nintendo Switch-spillkonsollen. Ingen spilltitler eller nøkler er inkludert.&lt;br /&gt;&lt;br /&gt;Før du begynner, må du finne <![CDATA[<b> prod.keys </b>]]> filen din på enhetslagringen.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Lær mer</a>]]></string> 4 <string name="app_disclaimer">Denne programvaren vil kjøre spill for Nintendo Switch-spillkonsollen. Ingen spilltitler eller nøkler er inkludert.&lt;br /&gt;&lt;br /&gt;Før du begynner, må du finne <![CDATA[<b> prod.keys </b>]]> filen din på enhetslagringen.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Lær mer</a>]]></string>
5 <string name="emulation_notification_channel_name">Emulering er aktiv</string> 5 <string name="emulation_notification_channel_name">Emulering er aktiv</string>
@@ -25,7 +25,6 @@
25 <string name="back">Tilbake</string> 25 <string name="back">Tilbake</string>
26 <string name="add_games">Legg til spill</string> 26 <string name="add_games">Legg til spill</string>
27 <string name="add_games_description">Velg din spillmappe</string> 27 <string name="add_games_description">Velg din spillmappe</string>
28
29 <!-- Home strings --> 28 <!-- Home strings -->
30 <string name="home_games">Spill</string> 29 <string name="home_games">Spill</string>
31 <string name="home_search">Søk</string> 30 <string name="home_search">Søk</string>
@@ -37,7 +36,7 @@
37 <string name="add_games_warning">Hoppe over valg av spillmappe?</string> 36 <string name="add_games_warning">Hoppe over valg av spillmappe?</string>
38 <string name="add_games_warning_description">Spill vises ikke i Spill-listen hvis en mappe ikke er valgt.</string> 37 <string name="add_games_warning_description">Spill vises ikke i Spill-listen hvis en mappe ikke er valgt.</string>
39 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string> 38 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
40 <string name="home_search_games">Søk i spill</string> 39 <string name="home_search_games">Søk i spill|</string>
41 <string name="games_dir_selected">Spillkatalogen er valgt</string> 40 <string name="games_dir_selected">Spillkatalogen er valgt</string>
42 <string name="install_prod_keys">Installer prod.keys</string> 41 <string name="install_prod_keys">Installer prod.keys</string>
43 <string name="install_prod_keys_description">Nødvendig for å dekryptere spill</string> 42 <string name="install_prod_keys_description">Nødvendig for å dekryptere spill</string>
@@ -61,6 +60,8 @@
61 <string name="invalid_keys_file">Ugyldig nøkkelfil valgt</string> 60 <string name="invalid_keys_file">Ugyldig nøkkelfil valgt</string>
62 <string name="install_keys_success">Nøkler vellykket installert</string> 61 <string name="install_keys_success">Nøkler vellykket installert</string>
63 <string name="reading_keys_failure">Feil ved lesing av krypteringsnøkler</string> 62 <string name="reading_keys_failure">Feil ved lesing av krypteringsnøkler</string>
63 <string name="install_prod_keys_failure_extension_description">Kontroller at nøkkelfilen har filtypen .keys, og prøv igjen.</string>
64 <string name="install_amiibo_keys_failure_extension_description">Kontroller at nøkkelfilen har filtypen .bin, og prøv igjen.</string>
64 <string name="invalid_keys_error">Ugyldige krypteringsnøkler</string> 65 <string name="invalid_keys_error">Ugyldige krypteringsnøkler</string>
65 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
66 <string name="install_keys_failure_description">Den valgte filen er feil eller ødelagt. Vennligst dump nøklene på nytt.</string> 67 <string name="install_keys_failure_description">Den valgte filen er feil eller ødelagt. Vennligst dump nøklene på nytt.</string>
@@ -86,7 +87,17 @@
86 <string name="save_file_invalid_zip_structure_description">Det første undermappenavnet må være spillets tittel-ID.</string> 87 <string name="save_file_invalid_zip_structure_description">Det første undermappenavnet må være spillets tittel-ID.</string>
87 <string name="import_saves">Importer</string> 88 <string name="import_saves">Importer</string>
88 <string name="export_saves">Eksporter</string> 89 <string name="export_saves">Eksporter</string>
89 90 <string name="install_firmware">Installer fastvare</string>
91 <string name="install_firmware_description">Fastvaren må være i et ZIP-arkiv og er nødvendig for å starte noen spill.</string>
92 <string name="firmware_installing">Installering av fastvare</string>
93 <string name="firmware_installed_success">Fastvaren er vellykket installert</string>
94 <string name="firmware_installed_failure">Installasjon av fastvare mislyktes</string>
95 <string name="share_log">Del feilsøkingslogger</string>
96 <string name="share_log_description">Del yuzus loggfil for å feilsøke problemer</string>
97 <string name="share_log_missing">Ingen loggfil funnet</string>
98 <string name="install_game_content">Installer spillinnhold</string>
99 <string name="install_game_content_description">Installer spilloppdateringer eller DLC</string>
100 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
90 <!-- About screen strings --> 101 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia er ikke ekte</string> 102 <string name="gaia_is_not_real">Gaia er ikke ekte</string>
92 <string name="copied_to_clipboard">Kopiert til utklippstavlen</string> 103 <string name="copied_to_clipboard">Kopiert til utklippstavlen</string>
@@ -94,6 +105,7 @@
94 <string name="contributors">Bidragsytere</string> 105 <string name="contributors">Bidragsytere</string>
95 <string name="contributors_description">Laget med \u2764 fra yuzu-teamet</string> 106 <string name="contributors_description">Laget med \u2764 fra yuzu-teamet</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 107 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
108 <string name="licenses_description">Prosjekter som gjør yuzu for Android mulig</string>
97 <string name="build">Bygg</string> 109 <string name="build">Bygg</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 110 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 111 <string name="website_link">https://yuzu-emu.org/</string>
@@ -114,41 +126,43 @@
114 <string name="are_you_interested">Er du interessert?</string> 126 <string name="are_you_interested">Er du interessert?</string>
115 127
116 <!-- General settings strings --> 128 <!-- General settings strings -->
117 <string name="frame_limit_enable">Aktiver hastighetsbegrensning</string> 129 <string name="frame_limit_enable">Begrense hastigheten</string>
118 <string name="frame_limit_enable_description">NÃ¥r aktivert, begrenses emuleringshastigheten til en angitt prosentandel av normal hastighet.</string> 130 <string name="frame_limit_enable_description">Begrenser emuleringshastigheten til en spesifisert prosentandel av normal hastighet.</string>
119 <string name="frame_limit_slider">Hastighetsbegrensning i prosent</string> 131 <string name="frame_limit_slider">Hastighetsbegrensning i prosent</string>
120 <string name="frame_limit_slider_description">Angir prosentandelen som skal begrense emuleringshastigheten. Med standardverdien 100 % vil emuleringen være begrenset til normal hastighet. Høyere eller lavere verdier vil øke eller redusere hastighetsbegrensningen.</string> 132 <string name="frame_limit_slider_description">Angir prosentandelen som skal begrense emuleringshastigheten. 100 % er normal hastighet. Høyere eller lavere verdier vil øke eller redusere hastighetsgrensen.</string>
121 <string name="cpu_accuracy">CPU-nøyaktighet</string> 133 <string name="cpu_accuracy">CPU-nøyaktighet</string>
122
123 <!-- System settings strings --> 134 <!-- System settings strings -->
124 <string name="use_docked_mode">Dokket modus</string> 135 <string name="use_docked_mode">Dokket modus</string>
125 <string name="use_docked_mode_description">Emulerer i dokket modus, noe som øker oppløsningen på bekostning av ytelsen.</string> 136 <string name="use_docked_mode_description">Øker oppløsningen, men reduserer ytelsen. Håndholdt modus brukes når den er deaktivert, noe som reduserer oppløsningen og øker ytelsen.</string>
126 <string name="emulated_region">Emulert region</string> 137 <string name="emulated_region">Emulert region</string>
127 <string name="emulated_language">Emulert språk</string> 138 <string name="emulated_language">Emulert språk</string>
128 <string name="select_rtc_date">Velg RTC-dato</string> 139 <string name="select_rtc_date">Velg RTC-dato</string>
129 <string name="select_rtc_time">Velg RTC-tid</string> 140 <string name="select_rtc_time">Velg RTC-tid</string>
130 <string name="use_custom_rtc">Aktiver egendefinert RTC</string> 141 <string name="use_custom_rtc">Tilpasset Sannhetstidsklokke</string>
131 <string name="use_custom_rtc_description">Med denne innstillingen kan du stille inn en egendefinert sanntidsklokke som er atskilt fra gjeldende systemtid.</string> 142 <string name="use_custom_rtc_description">Gjør det mulig å stille inn en egendefinert sanntidsklokke separat fra den gjeldende systemtiden.</string>
132 <string name="set_custom_rtc">Angi egendefinert RTC</string> 143 <string name="set_custom_rtc">Angi tilpasset RTC</string>
133 144
134 <!-- Graphics settings strings --> 145 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Nøyaktighetsnivå</string> 146 <string name="renderer_accuracy">Nøyaktighetsnivå</string>
137 <string name="renderer_resolution">Oppløsning</string> 147 <string name="renderer_resolution">Oppløsning (håndholdt/dokket)</string>
138 <string name="renderer_vsync">VSync-modus</string> 148 <string name="renderer_vsync">VSync-modus</string>
139 <string name="renderer_aspect_ratio">Størrelsesforhold</string> 149 <string name="renderer_aspect_ratio">Størrelsesforhold</string>
140 <string name="renderer_scaling_filter">Filter for vindustilpasning</string> 150 <string name="renderer_scaling_filter">Filter for vindustilpasning</string>
141 <string name="renderer_anti_aliasing">Anti-Aliasing-metode</string> 151 <string name="renderer_anti_aliasing">Anti-aliasing-metode</string>
142 <string name="renderer_force_max_clock">Tving fram maksimal klokkefrekvens (kun Adreno)</string> 152 <string name="renderer_force_max_clock">Tving fram maksimal klokkefrekvens (kun Adreno)</string>
143 <string name="renderer_force_max_clock_description">Tvinger GPU-en til å kjøre med maksimal klokkefrekvens (termiske begrensninger vil fortsatt gjelde).</string> 153 <string name="renderer_force_max_clock_description">Tvinger GPU-en til å kjøre med maksimal klokkefrekvens (termiske begrensninger vil fortsatt gjelde).</string>
144 <string name="renderer_asynchronous_shaders">Bruk asynkrone shaders</string> 154 <string name="renderer_asynchronous_shaders">Bruk asynkrone shaders</string>
145 <string name="renderer_asynchronous_shaders_description">Kompilerer shaders asynkront, noe som reduserer hakkingen, men kan føre til feil.</string> 155 <string name="renderer_asynchronous_shaders_description">Kompilerer shaders asynkront, noe som reduserer hakking, men kan føre til feil.</string>
146 <string name="renderer_debug">Aktiver feilsøking av grafikk</string> 156 <string name="renderer_reactive_flushing">Bruk reaktiv spyling</string>
147 <string name="renderer_debug_description">Når dette er merket av, går grafikk-API-et inn i en langsommere feilsøkingsmodus.</string> 157 <string name="renderer_reactive_flushing_description">Forbedrer gjengivelsesnøyaktigheten i enkelte spill på bekostning av ytelsen.</string>
148 <string name="use_disk_shader_cache">Bruk disk shader-cache</string> 158 <string name="use_disk_shader_cache">Disk shader-hurtigbuffer</string>
149 <string name="use_disk_shader_cache_description">Reduser hakking ved å lagre og laste inn genererte shaders på disken.</string> 159 <string name="use_disk_shader_cache_description">Reduserer hakking ved å lagre og laste inn genererte shaders lokalt.</string>
150 160
151 <!-- Audio settings strings --> 161 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string>
163 <string name="renderer_api">API</string>
164 <string name="renderer_debug">Feilsøking av grafikk</string>
165 <string name="renderer_debug_description">Setter grafikk-API-et til en langsom feilsøkingsmodus.</string>
152 <string name="audio_volume">Volum</string> 166 <string name="audio_volume">Volum</string>
153 <string name="audio_volume_description">Angir volumet på lydutgangen.</string> 167 <string name="audio_volume_description">Angir volumet på lydutgangen.</string>
154 168
@@ -164,14 +178,19 @@
164 <string name="reset_all_settings_description">Alle avanserte innstillinger tilbakestilles til standardkonfigurasjonen. Dette kan ikke angres.</string> 178 <string name="reset_all_settings_description">Alle avanserte innstillinger tilbakestilles til standardkonfigurasjonen. Dette kan ikke angres.</string>
165 <string name="settings_reset">Tilbakestilling av innstillinger</string> 179 <string name="settings_reset">Tilbakestilling av innstillinger</string>
166 <string name="close">Lukk</string> 180 <string name="close">Lukk</string>
167 <string name="learn_more">Lær Mer</string> 181 <string name="learn_more">Lær mer</string>
168 182 <string name="auto">Auto</string>
183 <string name="submit">Send inn</string>
184 <string name="string_null">Null</string>
185 <string name="string_import">Importer</string>
186 <string name="export">Eksporter</string>
169 <!-- GPU driver installation --> 187 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Velg GPU-driver</string> 188 <string name="select_gpu_driver">Velg GPU-driver</string>
171 <string name="select_gpu_driver_title">Ønsker du å bytte ut din nåværende GPU-driver?</string> 189 <string name="select_gpu_driver_title">Ønsker du å bytte ut din nåværende GPU-driver?</string>
172 <string name="select_gpu_driver_install">Installer</string> 190 <string name="select_gpu_driver_install">Installer</string>
173 <string name="select_gpu_driver_default">Standard</string> 191 <string name="select_gpu_driver_default">Standard</string>
174 <string name="select_gpu_driver_use_default">Bruk av standard GPU-driver</string> 192 <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>
175 <string name="system_gpu_driver">Systemets GPU-driver</string> 194 <string name="system_gpu_driver">Systemets GPU-driver</string>
176 <string name="installing_driver">Installerer driver...</string> 195 <string name="installing_driver">Installerer driver...</string>
177 196
@@ -182,10 +201,10 @@
182 <string name="preferences_graphics">Grafikk</string> 201 <string name="preferences_graphics">Grafikk</string>
183 <string name="preferences_audio">Lyd</string> 202 <string name="preferences_audio">Lyd</string>
184 <string name="preferences_theme">Tema og farge</string> 203 <string name="preferences_theme">Tema og farge</string>
204 <string name="preferences_debug">Feilsøk</string>
185 205
186 <!-- ROM loading errors --> 206 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">ROM-en din er kryptert</string> 207 <string name="loader_error_encrypted">ROM-en din er kryptert</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[Følg veiledningene for å redumpe dine <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">spillkassetter</a> eller <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">installerte titler</a>.]]></string>
189 <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> 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>
190 <string name="loader_error_video_core">Det oppstod en feil ved initialisering av videokjernen</string> 209 <string name="loader_error_video_core">Det oppstod en feil ved initialisering av videokjernen</string>
191 <string name="loader_error_video_core_description">Dette skyldes vanligvis en inkompatibel GPU-driver. Installering av en tilpasset GPU-driver kan løse problemet.</string> 210 <string name="loader_error_video_core_description">Dette skyldes vanligvis en inkompatibel GPU-driver. Installering av en tilpasset GPU-driver kan løse problemet.</string>
@@ -196,25 +215,25 @@
196 <string name="emulation_exit">Avslutt emulering</string> 215 <string name="emulation_exit">Avslutt emulering</string>
197 <string name="emulation_done">Ferdig</string> 216 <string name="emulation_done">Ferdig</string>
198 <string name="emulation_fps_counter">FPS-teller</string> 217 <string name="emulation_fps_counter">FPS-teller</string>
199 <string name="emulation_toggle_controls">Veksle kontroller</string> 218 <string name="emulation_toggle_controls">Veksle mellom kontrollene</string>
200 <string name="emulation_rel_stick_center">Relativt senter for stikken</string> 219 <string name="emulation_rel_stick_center">Relativt pinnesenter</string>
201 <string name="emulation_dpad_slide">DPad-skyveplate</string> 220 <string name="emulation_dpad_slide">D-pad-skyving</string>
202 <string name="emulation_haptics">Haptikk</string> 221 <string name="emulation_haptics">Berøringshaptikk</string>
203 <string name="emulation_show_overlay">Vis overlegg</string> 222 <string name="emulation_show_overlay">Vis overlegg</string>
204 <string name="emulation_toggle_all">Slå av alt</string> 223 <string name="emulation_toggle_all">Veksle mellom alle</string>
205 <string name="emulation_control_adjust">Juster overlegg</string> 224 <string name="emulation_control_adjust">Juster overlegg</string>
206 <string name="emulation_control_scale">Skaler</string> 225 <string name="emulation_control_scale">Skaler</string>
207 <string name="emulation_control_opacity">Gjennomsiktighet</string> 226 <string name="emulation_control_opacity">Gjennomsiktighet</string>
208 <string name="emulation_touch_overlay_reset">Tilbakestill overlegg</string> 227 <string name="emulation_touch_overlay_reset">Tilbakestill overlegg</string>
209 <string name="emulation_touch_overlay_edit">Rediger overlegg</string> 228 <string name="emulation_touch_overlay_edit">Rediger overlegg</string>
210 <string name="emulation_pause">Pause Emulering</string> 229 <string name="emulation_pause">Pause emulering</string>
211 <string name="emulation_unpause">Opphev pausing av emulering</string> 230 <string name="emulation_unpause">Ta emuleringen ut av pause</string>
212 <string name="emulation_input_overlay">Alternativer for overlegg</string> 231 <string name="emulation_input_overlay">Overlay-alternativer</string>
213 232
214 <string name="load_settings">Laster inn innstillinger...</string> 233 <string name="load_settings">Laster inn innstillinger...</string>
215 234
216 <!-- Software keyboard --> 235 <!-- Software keyboard -->
217 <string name="software_keyboard">Programvare Tastatur</string> 236 <string name="software_keyboard">Programvaretastatur</string>
218 237
219 <!-- Errors and warnings --> 238 <!-- Errors and warnings -->
220 <string name="abort_button">Avbryt</string> 239 <string name="abort_button">Avbryt</string>
@@ -226,7 +245,6 @@
226 <string name="fatal_error">Fatal Feil</string> 245 <string name="fatal_error">Fatal Feil</string>
227 <string name="fatal_error_message">Det oppstod en fatal feil. Sjekk loggen for mer informasjon.\nFortsatt emulering kan føre til krasj og feil.</string> 246 <string name="fatal_error_message">Det oppstod en fatal feil. Sjekk loggen for mer informasjon.\nFortsatt emulering kan føre til krasj og feil.</string>
228 <string name="performance_warning">Hvis du slår av denne innstillingen, reduseres emuleringsytelsen betydelig! Vi anbefaler at du lar denne innstillingen være aktivert for å få den beste opplevelsen.</string> 247 <string name="performance_warning">Hvis du slår av denne innstillingen, reduseres emuleringsytelsen betydelig! Vi anbefaler at du lar denne innstillingen være aktivert for å få den beste opplevelsen.</string>
229
230 <!-- Region Names --> 248 <!-- Region Names -->
231 <string name="region_japan">Japan</string> 249 <string name="region_japan">Japan</string>
232 <string name="region_usa">USA</string> 250 <string name="region_usa">USA</string>
@@ -236,8 +254,7 @@
236 <string name="region_korea">Korea</string> 254 <string name="region_korea">Korea</string>
237 <string name="region_taiwan">Taiwan</string> 255 <string name="region_taiwan">Taiwan</string>
238 256
239 <!-- Language Names --> 257 <string name="memory_gigabyte">GB</string>
240
241 <!-- Renderer APIs --> 258 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 259 <string name="renderer_vulkan">Vulkan</string>
243 <string name="renderer_none">Ingen</string> 260 <string name="renderer_none">Ingen</string>
@@ -274,12 +291,14 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 291 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 292 <string name="anti_aliasing_smaa">SMAA</string>
276 293
294 <string name="screen_layout_auto">Auto</string>
295
277 <!-- Aspect Ratios --> 296 <!-- Aspect Ratios -->
278 <string name="ratio_default">Standard (16:9)</string> 297 <string name="ratio_default">Standard (16:9)</string>
279 <string name="ratio_force_four_three">Tving 4:3</string> 298 <string name="ratio_force_four_three">Tving 4:3</string>
280 <string name="ratio_force_twenty_one_nine">Tving 21:9</string> 299 <string name="ratio_force_twenty_one_nine">Tving 21:9</string>
281 <string name="ratio_force_sixteen_ten">Tving 16:10</string> 300 <string name="ratio_force_sixteen_ten">Tving 16:10</string>
282 <string name="ratio_stretch">Strekk til Vindu</string> 301 <string name="ratio_stretch">Strekk til vindu</string>
283 302
284 <!-- CPU Accuracy --> 303 <!-- CPU Accuracy -->
285 <string name="cpu_accuracy_accurate">Nøyaktig</string> 304 <string name="cpu_accuracy_accurate">Nøyaktig</string>
@@ -287,9 +306,9 @@
287 <string name="cpu_accuracy_paranoid">Paranoid (Langsom)</string> 306 <string name="cpu_accuracy_paranoid">Paranoid (Langsom)</string>
288 307
289 <!-- Gamepad Buttons --> 308 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">D-Pad</string> 309 <string name="gamepad_d_pad">D-pad</string>
291 <string name="gamepad_left_stick">Venstre Pinne</string> 310 <string name="gamepad_left_stick">Venstre spak</string>
292 <string name="gamepad_right_stick">Høyre Pinne</string> 311 <string name="gamepad_right_stick">Høyre spak</string>
293 <string name="gamepad_home">Hjem</string> 312 <string name="gamepad_home">Hjem</string>
294 <string name="gamepad_screenshot">Skjermbilde</string> 313 <string name="gamepad_screenshot">Skjermbilde</string>
295 314
@@ -298,7 +317,7 @@
298 <string name="building_shaders">Bygging av shaders</string> 317 <string name="building_shaders">Bygging av shaders</string>
299 318
300 <!-- Theme options --> 319 <!-- Theme options -->
301 <string name="change_app_theme">Endre appens tema</string> 320 <string name="change_app_theme">Endre app-tema</string>
302 <string name="theme_default">Standard</string> 321 <string name="theme_default">Standard</string>
303 <string name="theme_material_you">Material You</string> 322 <string name="theme_material_you">Material You</string>
304 323
@@ -309,7 +328,13 @@
309 <string name="theme_mode_dark">Mørk</string> 328 <string name="theme_mode_dark">Mørk</string>
310 329
311 <!-- Black backgrounds theme --> 330 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">Bruk svart bakgrunn</string> 331 <string name="use_black_backgrounds">Svart bakgrunn</string>
313 <string name="use_black_backgrounds_description">Bruk svart bakgrunn når du bruker det mørke temaet.</string> 332 <string name="use_black_backgrounds_description">Bruk svart bakgrunn når du bruker det mørke temaet.</string>
314 333
315</resources> 334 <string name="mute">Lydløs</string>
335 <string name="unmute">Slå på lyden</string>
336
337 <!-- Licenses screen strings -->
338 <string name="licenses">Lisenser</string>
339 <string name="license_fidelityfx_fsr_description">Oppskalering av høy kvalitet fra AMD</string>
340 </resources>
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 899e233d0..f4d9920c2 100644
--- a/src/android/app/src/main/res/values-pl/strings.xml
+++ b/src/android/app/src/main/res/values-pl/strings.xml
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">To oprogramowanie umożliwia uruchomienie gier z konsoli Nintendo Switch. Nie zawiera gier ani wymaganych kluczy.&lt;br /&gt;&lt;br /&gt;Zanim zaczniesz, wybierz plik kluczy <![CDATA[<b> prod.keys </b>]]> z katalogu w pamięci masowej.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Dowiedz się więcej</a>]]></string> 4 <string name="app_disclaimer">To oprogramowanie umożliwia uruchomienie gier z konsoli Nintendo Switch. Nie zawiera gier ani wymaganych kluczy.&lt;br /&gt;&lt;br /&gt;Zanim zaczniesz, wybierz plik kluczy <![CDATA[<b> prod.keys </b>]]> z katalogu w pamięci masowej.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Dowiedz się więcej</a>]]></string>
5 <string name="emulation_notification_channel_name">Emulacja jest uruchomiona</string> 5 <string name="emulation_notification_channel_name">Emulacja jest uruchomiona</string>
@@ -25,7 +25,6 @@
25 <string name="back">Wstecz</string> 25 <string name="back">Wstecz</string>
26 <string name="add_games">Dodaj gry</string> 26 <string name="add_games">Dodaj gry</string>
27 <string name="add_games_description">Wybierz folder zawierajÄ…cy Twoje gry</string> 27 <string name="add_games_description">Wybierz folder zawierajÄ…cy Twoje gry</string>
28
29 <!-- Home strings --> 28 <!-- Home strings -->
30 <string name="home_games">Gry</string> 29 <string name="home_games">Gry</string>
31 <string name="home_search">Szukaj</string> 30 <string name="home_search">Szukaj</string>
@@ -61,6 +60,8 @@
61 <string name="invalid_keys_file">Wybrano niepoprawne klucze</string> 60 <string name="invalid_keys_file">Wybrano niepoprawne klucze</string>
62 <string name="install_keys_success">Klucze zainstalowane pomyślnie</string> 61 <string name="install_keys_success">Klucze zainstalowane pomyślnie</string>
63 <string name="reading_keys_failure">Błąd podczas odczytu kluczy</string> 62 <string name="reading_keys_failure">Błąd podczas odczytu kluczy</string>
63 <string name="install_prod_keys_failure_extension_description">Upewnij się że twoje klucze mają rozszerzenie .keys i spróbuj ponownie.</string>
64 <string name="install_amiibo_keys_failure_extension_description">Upewnij się że twoje klucze mają rozszerzenie .bin i spróbuj ponownie.</string>
64 <string name="invalid_keys_error">Niepoprawne klucze</string> 65 <string name="invalid_keys_error">Niepoprawne klucze</string>
65 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
66 <string name="install_keys_failure_description">Wybrany plik jest niepoprawny lub uszkodzony. Zrzuć ponownie swoje klucze.</string> 67 <string name="install_keys_failure_description">Wybrany plik jest niepoprawny lub uszkodzony. Zrzuć ponownie swoje klucze.</string>
@@ -86,7 +87,17 @@
86 <string name="save_file_invalid_zip_structure_description">Pierwszy podkatalog musi zawierać w nazwie numer ID tytułu gry.</string> 87 <string name="save_file_invalid_zip_structure_description">Pierwszy podkatalog musi zawierać w nazwie numer ID tytułu gry.</string>
87 <string name="import_saves">Importuj</string> 88 <string name="import_saves">Importuj</string>
88 <string name="export_saves">Eksportuj</string> 89 <string name="export_saves">Eksportuj</string>
89 90 <string name="install_firmware">Zainstaluj firmware</string>
91 <string name="install_firmware_description">Firmware musi być w postaci archiwum ZIP, niektóre gry wymagają go do uruchomienia/prawidłowego działania</string>
92 <string name="firmware_installing">InstalujÄ™ firmware</string>
93 <string name="firmware_installed_success">Zainstalowano pomyślnie</string>
94 <string name="firmware_installed_failure">Błąd podczas instalacji firmware</string>
95 <string name="share_log">Udostępnij logi debugowania</string>
96 <string name="share_log_description">Podziel się logami yuzu, pomoże to twórcom w poprawie działania emulatora</string>
97 <string name="share_log_missing">Nie znaleziono plików logów</string>
98 <string name="install_game_content">Zainstaluj zawartość gry</string>
99 <string name="install_game_content_description">Zainstaluj aktualizacjÄ™ gry lub dodatek DLC</string>
100 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
90 <!-- About screen strings --> 101 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia isn\'t real</string> 102 <string name="gaia_is_not_real">Gaia isn\'t real</string>
92 <string name="copied_to_clipboard">Skopiowano do schowka</string> 103 <string name="copied_to_clipboard">Skopiowano do schowka</string>
@@ -94,6 +105,7 @@
94 <string name="contributors">Współtwórcy</string> 105 <string name="contributors">Współtwórcy</string>
95 <string name="contributors_description">Stworzone z \u2764 przez zespół yuzu</string> 106 <string name="contributors_description">Stworzone z \u2764 przez zespół yuzu</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 107 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
108 <string name="licenses_description">Projekty dzięki którym yuzu mógł zostać stworzony</string>
97 <string name="build">Wersja</string> 109 <string name="build">Wersja</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 110 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 111 <string name="website_link">https://yuzu-emu.org/</string>
@@ -114,27 +126,25 @@
114 <string name="are_you_interested">JesteÅ› zainteresowany?</string> 126 <string name="are_you_interested">JesteÅ› zainteresowany?</string>
115 127
116 <!-- General settings strings --> 128 <!-- General settings strings -->
117 <string name="frame_limit_enable">Włącz limit szybkości emulacji</string> 129 <string name="frame_limit_enable">Limit szybkość</string>
118 <string name="frame_limit_enable_description">Włącz, aby ustawić procentowy limit szybkości emulacji</string> 130 <string name="frame_limit_enable_description">Włącz, aby ustawić procentowy limit szybkości emulacji</string>
119 <string name="frame_limit_slider">Procentowy limit szybkości emulacji</string> 131 <string name="frame_limit_slider">Procentowy limit szybkości emulacji</string>
120 <string name="frame_limit_slider_description">Określa limit szybkości emulacji gier. Domyślna wartość 100% oznacza normalną szybkość z jaką działa gra. Wartości niższe lub wyższe zmniejszą lub zwiększą limit szybkości.</string> 132 <string name="frame_limit_slider_description">Określa limit szybkości emulacji gier. Domyślna wartość 100% oznacza normalną szybkość z jaką działa gra. Wartości niższe lub wyższe zmniejszą lub zwiększą limit szybkości.</string>
121 <string name="cpu_accuracy">Dokładność procesora CPU</string> 133 <string name="cpu_accuracy">Dokładność procesora CPU</string>
122
123 <!-- System settings strings --> 134 <!-- System settings strings -->
124 <string name="use_docked_mode">Tryb zadokowany</string> 135 <string name="use_docked_mode">Tryb zadokowany</string>
125 <string name="use_docked_mode_description">Emulacja w trybie stacji dokującej, zwiększa rozdzielczość kosztem wydajności.</string> 136 <string name="use_docked_mode_description">Zwiększa rozdzielczość kosztem wydajności. Kiedy wyłączone, używany jest tryb Handheld, który obniża rozdzielczość i dzięki temu zwiększa wydajność.</string>
126 <string name="emulated_region">Region emulacji</string> 137 <string name="emulated_region">Region emulacji</string>
127 <string name="emulated_language">Język emulacji</string> 138 <string name="emulated_language">Język emulacji</string>
128 <string name="select_rtc_date">Ustaw datÄ™ RTC</string> 139 <string name="select_rtc_date">Ustaw datÄ™ RTC</string>
129 <string name="select_rtc_time">Ustaw czas RTC</string> 140 <string name="select_rtc_time">Ustaw czas RTC</string>
130 <string name="use_custom_rtc">Włącz niestandardowy zegar RTC</string> 141 <string name="use_custom_rtc">Niestandardowy RTC</string>
131 <string name="use_custom_rtc_description">Ta opcja pozwala na wybranie własnych ustawień czasu używanych w czasie emulacji, innych niż czas systemu Android.</string> 142 <string name="use_custom_rtc_description">Ta opcja pozwala na wybranie własnych ustawień czasu używanych w czasie emulacji, innych niż czas systemu Android.</string>
132 <string name="set_custom_rtc">Ustaw niestandardowy czas RTC</string> 143 <string name="set_custom_rtc">Ustaw niestandardowy czas RTC</string>
133 144
134 <!-- Graphics settings strings --> 145 <!-- Graphics settings strings -->
135 <string name="renderer_api">Interfejs graficzny</string>
136 <string name="renderer_accuracy">Poziom precyzji emulacji</string> 146 <string name="renderer_accuracy">Poziom precyzji emulacji</string>
137 <string name="renderer_resolution">Rozdzielczość</string> 147 <string name="renderer_resolution">Rozdzielczość (Handheld/Zadokowany)</string>
138 <string name="renderer_vsync">Synchronizacja pionowa VSync</string> 148 <string name="renderer_vsync">Synchronizacja pionowa VSync</string>
139 <string name="renderer_aspect_ratio">Proporcje ekranu</string> 149 <string name="renderer_aspect_ratio">Proporcje ekranu</string>
140 <string name="renderer_scaling_filter">Filtr adaptacji rozdzielczości</string> 150 <string name="renderer_scaling_filter">Filtr adaptacji rozdzielczości</string>
@@ -143,12 +153,16 @@
143 <string name="renderer_force_max_clock_description">Wymusza uruchomienie maksymalnego taktowania układu graficznego (zabezpieczenia termiczne będą dalej aktywne).</string> 153 <string name="renderer_force_max_clock_description">Wymusza uruchomienie maksymalnego taktowania układu graficznego (zabezpieczenia termiczne będą dalej aktywne).</string>
144 <string name="renderer_asynchronous_shaders">Wyłącz synchronizację shaderów</string> 154 <string name="renderer_asynchronous_shaders">Wyłącz synchronizację shaderów</string>
145 <string name="renderer_asynchronous_shaders_description">Kompiluj oświetlenie bez synchronizacji, poprawi wydajność ale może powodować błędy.</string> 155 <string name="renderer_asynchronous_shaders_description">Kompiluj oświetlenie bez synchronizacji, poprawi wydajność ale może powodować błędy.</string>
146 <string name="renderer_debug">Włącz debugowanie grafiki</string> 156 <string name="renderer_reactive_flushing">Użyj spłukiwania reaktywnego - reactive flushing</string>
147 <string name="renderer_debug_description">Kiedy włączone, interfejs graficzny korzysta z wolnego trybu debugowania błędów.</string> 157 <string name="renderer_reactive_flushing_description">Poprawia jakość renderowania w kilku grach, kosztem wydajności.</string>
148 <string name="use_disk_shader_cache">Użyj pamięci podręcznej shaderów na dysku</string> 158 <string name="use_disk_shader_cache">Pamięć podręczna shaderów</string>
149 <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>
150 160
151 <!-- Audio settings strings --> 161 <!-- Debug settings strings -->
162 <string name="cpu">CPU</string>
163 <string name="renderer_api">Interfejs graficzny</string>
164 <string name="renderer_debug">Debugowanie grafiki</string>
165 <string name="renderer_debug_description">Kiedy włączone, interfejs graficzny korzysta z wolnego trybu debugowania błędów.</string>
152 <string name="audio_volume">Głośność</string> 166 <string name="audio_volume">Głośność</string>
153 <string name="audio_volume_description">Ustala poziom głośności wyjścia dźwięku.</string> 167 <string name="audio_volume_description">Ustala poziom głośności wyjścia dźwięku.</string>
154 168
@@ -161,17 +175,21 @@
161 <string name="reset_setting_confirmation">Przywrócić wartość tego ustawienia do wartości domyślnej?</string> 175 <string name="reset_setting_confirmation">Przywrócić wartość tego ustawienia do wartości domyślnej?</string>
162 <string name="reset_to_default">Przywróć ustawienia domyślne</string> 176 <string name="reset_to_default">Przywróć ustawienia domyślne</string>
163 <string name="reset_all_settings">Przywrócić WSZYSTKIE ustawienia?</string> 177 <string name="reset_all_settings">Przywrócić WSZYSTKIE ustawienia?</string>
164 <string name="reset_all_settings_description">Wszystkie zaawansowane opcje zostaną przywrócone do wartości domyślnych. Czynności nie będzie można cofnąć.</string> 178 <string name="reset_all_settings_description">Wszystkie zaawansowane opcje zostaną przywrócone do wartości domyślnych. Czynności nie będzie można cofnąć</string>
165 <string name="settings_reset">Reset ustawień</string> 179 <string name="settings_reset">Reset ustawień</string>
166 <string name="close">Zamknij</string> 180 <string name="close">Zamknij</string>
167 <string name="learn_more">Dowiedz się więcej</string> 181 <string name="learn_more">Dowiedz się więcej</string>
168 182 <string name="auto">Automatyczny</string>
183 <string name="submit">Zatwierdź</string>
184 <string name="string_import">Importuj</string>
185 <string name="export">Eksportuj</string>
169 <!-- GPU driver installation --> 186 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Wybierz sterownik GPU </string> 187 <string name="select_gpu_driver">Wybierz sterownik GPU </string>
171 <string name="select_gpu_driver_title">Chcesz zastąpić obecny sterownik układu graficznego?</string> 188 <string name="select_gpu_driver_title">Chcesz zastąpić obecny sterownik układu graficznego?</string>
172 <string name="select_gpu_driver_install">Zainstaluj</string> 189 <string name="select_gpu_driver_install">Zainstaluj</string>
173 <string name="select_gpu_driver_default">Domyślne</string> 190 <string name="select_gpu_driver_default">Domyślne</string>
174 <string name="select_gpu_driver_use_default">Aktywny domyślny sterownik GPU</string> 191 <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>
175 <string name="system_gpu_driver">Systemowy sterownik GPU</string> 193 <string name="system_gpu_driver">Systemowy sterownik GPU</string>
176 <string name="installing_driver">Instalowanie sterownika...</string> 194 <string name="installing_driver">Instalowanie sterownika...</string>
177 195
@@ -182,10 +200,10 @@
182 <string name="preferences_graphics">Grafika</string> 200 <string name="preferences_graphics">Grafika</string>
183 <string name="preferences_audio">Dźwięk</string> 201 <string name="preferences_audio">Dźwięk</string>
184 <string name="preferences_theme">Motyw i kolor</string> 202 <string name="preferences_theme">Motyw i kolor</string>
203 <string name="preferences_debug">Debug</string>
185 204
186 <!-- ROM loading errors --> 205 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">Twój ROM jest zakodowany</string> 206 <string name="loader_error_encrypted">Twój ROM jest zakodowany</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[Użyj przewodnika aby wykonać zrzuty <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">kardridży</a> lub <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">zainstalowanych gier</a>.]]></string>
189 <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> 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>
190 <string name="loader_error_video_core">Błąd inicjacji podsystemu graficznego</string> 208 <string name="loader_error_video_core">Błąd inicjacji podsystemu graficznego</string>
191 <string name="loader_error_video_core_description">Zazwyczaj spowodowane niekompatybilnym sterownikiem GPU, instalacja niestandardowego sterownika może rozwiązać ten problem.</string> 209 <string name="loader_error_video_core_description">Zazwyczaj spowodowane niekompatybilnym sterownikiem GPU, instalacja niestandardowego sterownika może rozwiązać ten problem.</string>
@@ -198,23 +216,23 @@
198 <string name="emulation_fps_counter">Licznik FPS</string> 216 <string name="emulation_fps_counter">Licznik FPS</string>
199 <string name="emulation_toggle_controls">Wybierz przyciski</string> 217 <string name="emulation_toggle_controls">Wybierz przyciski</string>
200 <string name="emulation_rel_stick_center">Wycentruj gałki</string> 218 <string name="emulation_rel_stick_center">Wycentruj gałki</string>
201 <string name="emulation_dpad_slide">Ruchomy DPad</string> 219 <string name="emulation_dpad_slide">Ruchomy D-pad</string>
202 <string name="emulation_haptics">Wibracje haptyczne</string> 220 <string name="emulation_haptics">Wibracje haptyczne</string>
203 <string name="emulation_show_overlay">Pokaż przyciski</string> 221 <string name="emulation_show_overlay">Pokaż przyciski</string>
204 <string name="emulation_toggle_all">Zaznacz wszystkie</string> 222 <string name="emulation_toggle_all">Włącz wszystkie</string>
205 <string name="emulation_control_adjust">Dostosuj nakładkę</string> 223 <string name="emulation_control_adjust">Dostosuj nakładkę</string>
206 <string name="emulation_control_scale">Skala</string> 224 <string name="emulation_control_scale">Skala</string>
207 <string name="emulation_control_opacity">Przeźroczystość</string> 225 <string name="emulation_control_opacity">Przeźroczystość</string>
208 <string name="emulation_touch_overlay_reset">Resetuj</string> 226 <string name="emulation_touch_overlay_reset">Resetuj nakładkę</string>
209 <string name="emulation_touch_overlay_edit">Edytuj nakładkę</string> 227 <string name="emulation_touch_overlay_edit">Edytuj nakładkę</string>
210 <string name="emulation_pause">Wstrzymaj emulacjÄ™</string> 228 <string name="emulation_pause">Wstrzymaj emulacjÄ™</string>
211 <string name="emulation_unpause">Wznów emulację</string> 229 <string name="emulation_unpause">Wznów emulację</string>
212 <string name="emulation_input_overlay">Opcje nakładki</string> 230 <string name="emulation_input_overlay">Opcje nakładki</string>
213 231
214 <string name="load_settings">Wczytywanie ustawień...</string> 232 <string name="load_settings">Wczytuję ustawienia...</string>
215 233
216 <!-- Software keyboard --> 234 <!-- Software keyboard -->
217 <string name="software_keyboard">Klawiatura systemowa</string> 235 <string name="software_keyboard">Klawiatura programowa</string>
218 236
219 <!-- Errors and warnings --> 237 <!-- Errors and warnings -->
220 <string name="abort_button">Przerwij</string> 238 <string name="abort_button">Przerwij</string>
@@ -226,7 +244,6 @@
226 <string name="fatal_error">Błąd krytyczny</string> 244 <string name="fatal_error">Błąd krytyczny</string>
227 <string name="fatal_error_message">Wystąpił błąd krytyczny. Szczegóły znajdziesz w pliku log.\nKontynuowanie może spowodować błędy lub przerwanie emulacji. </string> 245 <string name="fatal_error_message">Wystąpił błąd krytyczny. Szczegóły znajdziesz w pliku log.\nKontynuowanie może spowodować błędy lub przerwanie emulacji. </string>
228 <string name="performance_warning">Wyłączenie tej opcji znacząco ograniczy wydajność! Dla najlepszego doświadczenia, zaleca się zostawienie tej opcji włączonej.</string> 246 <string name="performance_warning">Wyłączenie tej opcji znacząco ograniczy wydajność! Dla najlepszego doświadczenia, zaleca się zostawienie tej opcji włączonej.</string>
229
230 <!-- Region Names --> 247 <!-- Region Names -->
231 <string name="region_japan">Japonia</string> 248 <string name="region_japan">Japonia</string>
232 <string name="region_usa">USA</string> 249 <string name="region_usa">USA</string>
@@ -236,8 +253,7 @@
236 <string name="region_korea">Korea</string> 253 <string name="region_korea">Korea</string>
237 <string name="region_taiwan">Tajwan</string> 254 <string name="region_taiwan">Tajwan</string>
238 255
239 <!-- Language Names --> 256 <string name="memory_gigabyte">GB</string>
240
241 <!-- Renderer APIs --> 257 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 258 <string name="renderer_vulkan">Vulkan</string>
243 <string name="renderer_none">Żadny</string> 259 <string name="renderer_none">Żadny</string>
@@ -274,12 +290,14 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 290 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 291 <string name="anti_aliasing_smaa">SMAA</string>
276 292
293 <string name="screen_layout_auto">Automatyczny</string>
294
277 <!-- Aspect Ratios --> 295 <!-- Aspect Ratios -->
278 <string name="ratio_default">Domyślne (16:9)</string> 296 <string name="ratio_default">Domyślne (16:9)</string>
279 <string name="ratio_force_four_three">WymuÅ› 4:3</string> 297 <string name="ratio_force_four_three">WymuÅ› 4:3</string>
280 <string name="ratio_force_twenty_one_nine">WymuÅ› 21:9</string> 298 <string name="ratio_force_twenty_one_nine">WymuÅ› 21:9</string>
281 <string name="ratio_force_sixteen_ten">WymuÅ› 16:10</string> 299 <string name="ratio_force_sixteen_ten">WymuÅ› 16:10</string>
282 <string name="ratio_stretch">RozciÄ…gnij do Okna</string> 300 <string name="ratio_stretch">RozciÄ…gnij do okna</string>
283 301
284 <!-- CPU Accuracy --> 302 <!-- CPU Accuracy -->
285 <string name="cpu_accuracy_accurate">Dokładny</string> 303 <string name="cpu_accuracy_accurate">Dokładny</string>
@@ -287,7 +305,7 @@
287 <string name="cpu_accuracy_paranoid">Paranoid (Wolny)</string> 305 <string name="cpu_accuracy_paranoid">Paranoid (Wolny)</string>
288 306
289 <!-- Gamepad Buttons --> 307 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">D-Pad</string> 308 <string name="gamepad_d_pad">D-pad</string>
291 <string name="gamepad_left_stick">Lewa gałka</string> 309 <string name="gamepad_left_stick">Lewa gałka</string>
292 <string name="gamepad_right_stick">Prawa gałka</string> 310 <string name="gamepad_right_stick">Prawa gałka</string>
293 <string name="gamepad_home">Home</string> 311 <string name="gamepad_home">Home</string>
@@ -298,18 +316,21 @@
298 <string name="building_shaders">Budowanie shaderów</string> 316 <string name="building_shaders">Budowanie shaderów</string>
299 317
300 <!-- Theme options --> 318 <!-- Theme options -->
301 <string name="change_app_theme">Zmień motyw aplikacji</string> 319 <string name="change_app_theme">Ustaw motyw aplikacji</string>
302 <string name="theme_default">Domyślny</string> 320 <string name="theme_default">Domyślny</string>
303 <string name="theme_material_you">Material You</string> 321 <string name="theme_material_you">Material You</string>
304 322
305 <!-- Theme Modes --> 323 <!-- Theme Modes -->
306 <string name="change_theme_mode">Zmiana trybu motywu</string> 324 <string name="change_theme_mode">Zmień tryb motywu</string>
307 <string name="theme_mode_follow_system">Podążaj za systemowym</string> 325 <string name="theme_mode_follow_system">Podążaj za systemowym</string>
308 <string name="theme_mode_light">Jasny</string> 326 <string name="theme_mode_light">Jasny</string>
309 <string name="theme_mode_dark">Ciemny</string> 327 <string name="theme_mode_dark">Ciemny</string>
310 328
311 <!-- Black backgrounds theme --> 329 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">Używaj czarnego tła</string> 330 <string name="use_black_backgrounds">Czarne tła</string>
313 <string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string> 331 <string name="use_black_backgrounds_description">Kiedy używany ciemny motyw, tła zostają zastąpione czernią.</string>
314 332
315</resources> 333 <!-- Licenses screen strings -->
334 <string name="licenses">Licencje</string>
335 <string name="license_fidelityfx_fsr_description">Rozciąganie wysokiej jakości od AMD</string>
336 </resources>
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 caa095364..8888fc750 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,30 +1,31 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Este software corre jogos para a consola Nintendo Switch. Não estão incluídas nem jogos ou chaves. &lt;br /&gt;&lt;br /&gt;Antes de começares, por favor localiza o ficheiro <![CDATA[1 prod.keys 1]]> no armazenamento do teu dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[2Learn more2]]></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[1 prod.keys 1]]> no armazenamento de seu dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[2Saiba mais2]]></string>
5 <string name="emulation_notification_channel_name">Emulação está Ativa</string> 5 <string name="emulation_notification_channel_name">Emulação está Ativa</string>
6 <string name="emulation_notification_channel_description">Mostra uma notificação permanente enquanto a emulação está a correr.</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">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 quendo algo corre mal.</string> 9 <string name="notice_notification_channel_description">Mostra notificações quando algo dá errado.</string>
10 <string name="notification_permission_not_granted">Permissões de notificação não permitidas </string> 10 <string name="notification_permission_not_granted">Acesso às notificações não concedido!</string>
11 11
12 <!-- Setup strings --> 12 <!-- Setup strings -->
13 <string name="welcome">Bemvindo! </string> 13 <string name="welcome">Bem-vindo! </string>
14 <string name="welcome_description">Aprende como configurar &lt;b>yuzu&lt;/b> e arranca a emulação.</string> 14 <string name="welcome_description">Aprenda como configurar o &lt;b>yuzu&lt;/b> e mergulhe na emulação.</string>
15 <string name="get_started">Começa</string> 15 <string name="get_started">Primeiros passos</string>
16 <string name="keys">Chaves</string> 16 <string name="keys">Keys</string>
17 <string name="keys_description">Seleciona o teu ficheiro &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">Seleciona as Chaves</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 a tua pasta &lt;b>Games&lt;/b> com o botão abaixo.</string> 20 <string name="games_description">Seleciona 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.\nDisfruta dos teus 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>
24 <string name="next">Próximo</string> 24 <string name="next">Próximo</string>
25 <string name="back">Voltar</string> 25 <string name="back">Voltar</string>
26 <string name="add_games">Adiciona Jogos</string> 26 <string name="add_games">Adicionar Jogos</string>
27 <string name="add_games_description">Seleciona a tua pasta de Jogos</string> 27 <string name="add_games_description">Selecione sua pasta de Jogos</string>
28 <string name="step_complete">Completo!</string>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">Jogos</string> 31 <string name="home_games">Jogos</string>
@@ -37,7 +38,8 @@
37 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> 38 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string>
38 <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> 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>
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">Procurar Jogos</string> 41 <string name="home_search_games">Procurar jogos</string>
42 <string name="search_settings">Procurar nas definições</string>
41 <string name="games_dir_selected">Pasta de Jogos selecionada</string> 43 <string name="games_dir_selected">Pasta de Jogos selecionada</string>
42 <string name="install_prod_keys">Instala prod.keys</string> 44 <string name="install_prod_keys">Instala prod.keys</string>
43 <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string> 45 <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string>
@@ -61,15 +63,18 @@
61 <string name="invalid_keys_file">Ficheiro de chaves inválido</string> 63 <string name="invalid_keys_file">Ficheiro de chaves inválido</string>
62 <string name="install_keys_success">Chaves instaladas com sucesso</string> 64 <string name="install_keys_success">Chaves instaladas com sucesso</string>
63 <string name="reading_keys_failure">Erro ao ler chaves de encriptação</string> 65 <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_amiibo_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .bin e tente novamente.</string>
64 <string name="invalid_keys_error">Chaves de encriptação inválidas</string> 68 <string name="invalid_keys_error">Chaves de encriptação inválidas</string>
65 <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>
66 <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string> 70 <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string>
67 <string name="install_gpu_driver">Instala driver para GPU</string> 71 <string name="install_gpu_driver">Instala driver para GPU</string>
68 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> 72 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string>
69 <string name="advanced_settings">Definições avançadas</string> 73 <string name="advanced_settings">Definições avançadas</string>
74 <string name="advanced_settings_game">Definições avançadas: %1$s</string>
70 <string name="settings_description">Configura definições do emulador</string> 75 <string name="settings_description">Configura definições do emulador</string>
71 <string name="search_recently_played">Jogos recentes</string> 76 <string name="search_recently_played">Jogado recentemente</string>
72 <string name="search_recently_added">Adicionados recentemente</string> 77 <string name="search_recently_added">Adicionado recentemente</string>
73 <string name="search_retail">Jogos comerciais</string> 78 <string name="search_retail">Jogos comerciais</string>
74 <string name="search_homebrew">Homebrew</string> 79 <string name="search_homebrew">Homebrew</string>
75 <string name="open_user_folder">Abre a pasta Yuzu</string> 80 <string name="open_user_folder">Abre a pasta Yuzu</string>
@@ -86,6 +91,33 @@
86 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string> 91 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string>
87 <string name="import_saves">Importar</string> 92 <string name="import_saves">Importar</string>
88 <string name="export_saves">Exportar</string> 93 <string name="export_saves">Exportar</string>
94 <string name="install_firmware">Instalar firmware</string>
95 <string name="install_firmware_description">O firmware deve estar em um arquivo ZIP e é necessário para iniciar alguns jogos.</string>
96 <string name="firmware_installing">Instalando firmware</string>
97 <string name="firmware_installed_success">Firmware instalado com sucesso.</string>
98 <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>
100 <string name="share_log">Compartilhe registros de debug.</string>
101 <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>
103 <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>
105 <string name="installing_game_content">A instalar conteúdo...</string>
106 <string name="install_game_content_failure">Erro ao instalar ficheiro(s) para 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>
108 <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>
110 <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>
112 <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>
114 <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>
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>
117 <string name="manage_yuzu_data">Administrar dados yuzu</string>
118 <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>
120 <string name="export_save_failed">Erro ao exportar dados guardados</string>
89 121
90 <!-- About screen strings --> 122 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia não é real</string> 123 <string name="gaia_is_not_real">Gaia não é real</string>
@@ -94,7 +126,18 @@
94 <string name="contributors">Contribuidores</string> 126 <string name="contributors">Contribuidores</string>
95 <string name="contributors_description">Feito com \u2764 da equipa do Yuzu</string> 127 <string name="contributors_description">Feito com \u2764 da equipa do Yuzu</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 128 <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>
97 <string name="build">Versão</string> 130 <string name="build">Versão</string>
131 <string name="user_data">Dado de utilizados</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>
133 <string name="exporting_user_data">A exportar dados de utilizados...</string>
134 <string name="importing_user_data">A importar dados de utilizador...</string>
135 <string name="import_user_data">Importar dados de utilizados...</string>
136 <string name="invalid_yuzu_backup">Backup yuzu inválido</string>
137 <string name="user_data_export_success">Dados de utilizados exportados com sucesso</string>
138 <string name="user_data_import_success">Dados de utilizador importado com sucesso</string>
139 <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>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 141 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 142 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 143 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -114,41 +157,53 @@
114 <string name="are_you_interested">Estás interessado?</string> 157 <string name="are_you_interested">Estás interessado?</string>
115 158
116 <!-- General settings strings --> 159 <!-- General settings strings -->
117 <string name="frame_limit_enable">Ativar limite de velocidade</string> 160 <string name="frame_limit_enable">Limite de velocidade</string>
118 <string name="frame_limit_enable_description">Quando ativada, a velocidade da emulação será limitada à percentagem definida da velocidade normal.</string> 161 <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
119 <string name="frame_limit_slider">Percentagem do limite de velocidade</string> 162 <string name="frame_limit_slider">Percentagem do limite de velocidade</string>
120 <string name="frame_limit_slider_description">Especifica o limite da percentagem da velocidade da emulação. Com a velocidade por defeito a 100% a emulação será limitada à velocidade normal. Valores maiores ou menores aumentarão ou diminuirão o 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>
121 <string name="cpu_accuracy">Precisão do CPU</string> 164 <string name="cpu_accuracy">Precisão do CPU</string>
165 <string name="value_with_units">%1$s%2$s</string>
122 166
123 <!-- System settings strings --> 167 <!-- System settings strings -->
124 <string name="use_docked_mode">Modo ancorado</string> 168 <string name="use_docked_mode">Modo Ancorado</string>
125 <string name="use_docked_mode_description">Emula em modo ancorado, que aumenta a resolução ás custas da performance.</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>
126 <string name="emulated_region">Região da emulação</string> 170 <string name="emulated_region">Região da emulação</string>
127 <string name="emulated_language">Idioma da emulação</string> 171 <string name="emulated_language">Idioma da emulação</string>
128 <string name="select_rtc_date">Seleciona a data RTC</string> 172 <string name="select_rtc_date">Selecione a data do sistema</string>
129 <string name="select_rtc_time">Seleciona a hora RTC</string> 173 <string name="select_rtc_time">Selecione a hora do sistema</string>
130 <string name="use_custom_rtc">Ativa RTC personalizado</string> 174 <string name="use_custom_rtc">Data e hora personalizada</string>
131 <string name="use_custom_rtc_description">Esta configuração permite definir um RTC personalizado diferente da hora atual do sistema</string> 175 <string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string>
132 <string name="set_custom_rtc">Define RTC personalizado</string> 176 <string name="set_custom_rtc">Defina um relógio em tempo real personalizado</string>
133 177
134 <!-- Graphics settings strings --> 178 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Nível de precisão</string> 179 <string name="renderer_accuracy">Nível de precisão</string>
137 <string name="renderer_resolution">Resolução</string> 180 <string name="renderer_resolution">Resolução (Portátil/Ancorado)</string>
138 <string name="renderer_vsync">Modo VSync</string> 181 <string name="renderer_vsync">Modo VSync</string>
139 <string name="renderer_aspect_ratio">Proporção do ecrã</string> 182 <string name="renderer_screen_layout">Oriantação</string>
183 <string name="renderer_aspect_ratio">Proporção da tela</string>
140 <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string> 184 <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
141 <string name="renderer_anti_aliasing">Método de Anti-Aliasing </string> 185 <string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string>
142 <string name="renderer_force_max_clock">Força velocidade máxima (Adreno only)</string> 186 <string name="renderer_force_max_clock">Força velocidade máxima (Adreno only)</string>
143 <string name="renderer_force_max_clock_description">Força o GPU a correr à velocidade máxima (restrições térmicas serão aplicadas)</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>
144 <string name="renderer_asynchronous_shaders">Usa shaders assíncronos </string> 188 <string name="renderer_asynchronous_shaders">Usa shaders assíncronos </string>
145 <string name="renderer_asynchronous_shaders_description">Compila shaders assincronamente, que aumentará a fluidez, mas poderá causar falhas.</string> 189 <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>
191 <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>
193 <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string>
194
195 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">Depuração da CPU</string>
198 <string name="cpu_debug_mode_description">Coloca a CPU em um modo de depuração lento.</string>
199 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string>
146 <string name="renderer_debug">Ativar depuração de gráficos</string> 201 <string name="renderer_debug">Ativar depuração de gráficos</string>
147 <string name="renderer_debug_description">Quando selecionado, a API gráfica entra num modo de depuração mais lento.</string> 202 <string name="renderer_debug_description">Quando selecionado, a API gráfica entra num modo de depuração mais lento.</string>
148 <string name="use_disk_shader_cache">Usar cache de shaders em disco</string> 203 <string name="fastmem">Fastmem</string>
149 <string name="use_disk_shader_cache_description">Aumenta a fluidez ao guardar e carregar shaders gerados para o armazenamento.</string>
150 204
151 <!-- Audio settings strings --> 205 <!-- Audio settings strings -->
206 <string name="audio_output_engine">Motor de saída</string>
152 <string name="audio_volume">Volume</string> 207 <string name="audio_volume">Volume</string>
153 <string name="audio_volume_description">Especifica o volume de saída.</string> 208 <string name="audio_volume_description">Especifica o volume de saída.</string>
154 209
@@ -157,14 +212,24 @@
157 <string name="ini_saved">Definições guardadas</string> 212 <string name="ini_saved">Definições guardadas</string>
158 <string name="gameid_saved">Definições guardadas para %1$s</string> 213 <string name="gameid_saved">Definições guardadas para %1$s</string>
159 <string name="error_saving">Erro ao guardar %1$s.ini: %2$s</string> 214 <string name="error_saving">Erro ao guardar %1$s.ini: %2$s</string>
215 <string name="unimplemented_menu">Menu não implementado</string>
160 <string name="loading">A carregar...</string> 216 <string name="loading">A carregar...</string>
217 <string name="shutting_down">A desligar...</string>
161 <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string> 218 <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string>
162 <string name="reset_to_default">Reverter para padrão</string> 219 <string name="reset_to_default">Reverter para padrão</string>
163 <string name="reset_all_settings">Redefinir todas as definições?</string> 220 <string name="reset_all_settings">Redefinir todas as definições?</string>
164 <string name="reset_all_settings_description">Todas as definições avançadas serão redefinidas para as definições padrão. Isto não pode ser revertido.</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>
165 <string name="settings_reset">Redefinir definições</string> 222 <string name="settings_reset">Redefinir definições</string>
166 <string name="close">Fechar</string> 223 <string name="close">Fechar</string>
167 <string name="learn_more">Saiba mais</string> 224 <string name="learn_more">Saiba mais</string>
225 <string name="auto">Automático</string>
226 <string name="submit">Enviar</string>
227 <string name="string_null">Nenhum (desativado)</string>
228 <string name="string_import">Importar</string>
229 <string name="export">Exportar</string>
230 <string name="export_failed">Exportação falhada</string>
231 <string name="import_failed">IMportação falhada</string>
232 <string name="cancelling">A cancelar</string>
168 233
169 <!-- GPU driver installation --> 234 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Seleciona a driver para o GPU</string> 235 <string name="select_gpu_driver">Seleciona a driver para o GPU</string>
@@ -172,6 +237,7 @@
172 <string name="select_gpu_driver_install">Instalar</string> 237 <string name="select_gpu_driver_install">Instalar</string>
173 <string name="select_gpu_driver_default">Padrão</string> 238 <string name="select_gpu_driver_default">Padrão</string>
174 <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string> 239 <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>
175 <string name="system_gpu_driver">Driver do GPU padrão</string> 241 <string name="system_gpu_driver">Driver do GPU padrão</string>
176 <string name="installing_driver">A instalar o Driver...</string> 242 <string name="installing_driver">A instalar o Driver...</string>
177 243
@@ -182,10 +248,11 @@
182 <string name="preferences_graphics">Gráficos</string> 248 <string name="preferences_graphics">Gráficos</string>
183 <string name="preferences_audio">Ãudio</string> 249 <string name="preferences_audio">Ãudio</string>
184 <string name="preferences_theme">Cor e tema.</string> 250 <string name="preferences_theme">Cor e tema.</string>
251 <string name="preferences_debug">Depuração</string>
185 252
186 <!-- ROM loading errors --> 253 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">A tua ROM está encriptada</string> 254 <string name="loader_error_encrypted">A tua ROM está encriptada</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor segue os guias para fazer redump das tuas<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">Cartidges de Jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">Jogos Instalados</a>.]]></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>
189 <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> 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>
190 <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vídeo.</string> 257 <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vídeo.</string>
191 <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> 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>
@@ -193,25 +260,25 @@
193 <string name="loader_error_file_not_found">O ficheiro da ROM não existe</string> 260 <string name="loader_error_file_not_found">O ficheiro da ROM não existe</string>
194 261
195 <!-- Emulation Menu --> 262 <!-- Emulation Menu -->
196 <string name="emulation_exit">Sair da emulação</string> 263 <string name="emulation_exit">Parar emulação</string>
197 <string name="emulation_done">Feito</string> 264 <string name="emulation_done">Feito</string>
198 <string name="emulation_fps_counter">Contador de FPS</string> 265 <string name="emulation_fps_counter">Contador de FPS</string>
199 <string name="emulation_toggle_controls">Alterar Controlos</string> 266 <string name="emulation_toggle_controls">Alterar controles</string>
200 <string name="emulation_rel_stick_center">Centro do Analógico Relativo</string> 267 <string name="emulation_rel_stick_center">Centro Relativo de Analógico</string>
201 <string name="emulation_dpad_slide">Deslizar do DPad</string> 268 <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string>
202 <string name="emulation_haptics">Hápticos </string> 269 <string name="emulation_haptics">Vibração ao tocar</string>
203 <string name="emulation_show_overlay">Mostrar sobreposição </string> 270 <string name="emulation_show_overlay">Mostrar overlay</string>
204 <string name="emulation_toggle_all">Alterar todos</string> 271 <string name="emulation_toggle_all">Marcar/Desmarcar tudo</string>
205 <string name="emulation_control_adjust">Ajustar a sobreposição </string> 272 <string name="emulation_control_adjust">Ajustar overlay</string>
206 <string name="emulation_control_scale">Escala</string> 273 <string name="emulation_control_scale">Escala</string>
207 <string name="emulation_control_opacity">Opacidade</string> 274 <string name="emulation_control_opacity">Opacidade</string>
208 <string name="emulation_touch_overlay_reset">Redefinir Sobreposição </string> 275 <string name="emulation_touch_overlay_reset">Restaurar overlay padrão</string>
209 <string name="emulation_touch_overlay_edit">Editar sobreposição </string> 276 <string name="emulation_touch_overlay_edit">Editar overlay</string>
210 <string name="emulation_pause">Pausa emulação</string> 277 <string name="emulation_pause">Pausar emulação</string>
211 <string name="emulation_unpause">Retomar emulação</string> 278 <string name="emulation_unpause">Retomar emulação</string>
212 <string name="emulation_input_overlay">Opções de sobreposição </string> 279 <string name="emulation_input_overlay">Opções de overlay</string>
213 280
214 <string name="load_settings">Configurações a carregar...</string> 281 <string name="load_settings">Carregando configurações...</string>
215 282
216 <!-- Software keyboard --> 283 <!-- Software keyboard -->
217 <string name="software_keyboard">Teclado de software</string> 284 <string name="software_keyboard">Teclado de software</string>
@@ -226,6 +293,9 @@
226 <string name="fatal_error">Erro fatal</string> 293 <string name="fatal_error">Erro fatal</string>
227 <string name="fatal_error_message">Ocorreu um erro fatal. Verifica o teu registro para detalhes. \nContinuar a emulação pode causar erros.</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>
228 <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> 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>
296 <string name="device_memory_inadequate">RAM do dispositivo: %1$s\nRecommended: %2$s</string>
297 <string name="memory_formatted">%1$s %2$s</string>
298 <string name="no_game_present">Nenhum jogo inicializável presente!</string>
229 299
230 <!-- Region Names --> 300 <!-- Region Names -->
231 <string name="region_japan">Japão</string> 301 <string name="region_japan">Japão</string>
@@ -236,7 +306,14 @@
236 <string name="region_korea">Coréia</string> 306 <string name="region_korea">Coréia</string>
237 <string name="region_taiwan">Taiwan</string> 307 <string name="region_taiwan">Taiwan</string>
238 308
239 <!-- Language Names --> 309 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string>
311 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string>
314 <string name="memory_terabyte">TB</string>
315 <string name="memory_petabyte">PB</string>
316 <string name="memory_exabyte">EB</string>
240 317
241 <!-- Renderer APIs --> 318 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulcano</string> 319 <string name="renderer_vulkan">Vulcano</string>
@@ -274,12 +351,17 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 351 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 352 <string name="anti_aliasing_smaa">SMAA</string>
276 353
354 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">Landscape</string>
356 <string name="screen_layout_portrait">Portrait</string>
357 <string name="screen_layout_auto">Automático</string>
358
277 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
278 <string name="ratio_default">Padrão (16:9)</string> 360 <string name="ratio_default">Padrão (16:9)</string>
279 <string name="ratio_force_four_three">Forçar 4:3</string> 361 <string name="ratio_force_four_three">Forçar 4:3</string>
280 <string name="ratio_force_twenty_one_nine">Forçar 21:9</string> 362 <string name="ratio_force_twenty_one_nine">Forçar 21:9</string>
281 <string name="ratio_force_sixteen_ten">Forçar 16:10</string> 363 <string name="ratio_force_sixteen_ten">Forçar 16:10</string>
282 <string name="ratio_stretch">Esticar para a janela</string> 364 <string name="ratio_stretch">Esticar à janela</string>
283 365
284 <!-- CPU Accuracy --> 366 <!-- CPU Accuracy -->
285 <string name="cpu_accuracy_accurate">Preciso</string> 367 <string name="cpu_accuracy_accurate">Preciso</string>
@@ -287,7 +369,7 @@
287 <string name="cpu_accuracy_paranoid">Paranoid (Lento)</string> 369 <string name="cpu_accuracy_paranoid">Paranoid (Lento)</string>
288 370
289 <!-- Gamepad Buttons --> 371 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">D-pad</string> 372 <string name="gamepad_d_pad">Botões Direcionais</string>
291 <string name="gamepad_left_stick">Analógico esquerdo</string> 373 <string name="gamepad_left_stick">Analógico esquerdo</string>
292 <string name="gamepad_right_stick">Analógico direito</string> 374 <string name="gamepad_right_stick">Analógico direito</string>
293 <string name="gamepad_home">Botão Home</string> 375 <string name="gamepad_home">Botão Home</string>
@@ -298,18 +380,32 @@
298 <string name="building_shaders">A criar shaders</string> 380 <string name="building_shaders">A criar shaders</string>
299 381
300 <!-- Theme options --> 382 <!-- Theme options -->
301 <string name="change_app_theme">Muda o Tema da App</string> 383 <string name="change_app_theme">Mudar o tema do aplicativo</string>
302 <string name="theme_default">Padrão</string> 384 <string name="theme_default">Padrão</string>
303 <string name="theme_material_you">Material You</string> 385 <string name="theme_material_you">Material You</string>
304 386
305 <!-- Theme Modes --> 387 <!-- Theme Modes -->
306 <string name="change_theme_mode">Altera o Modo do Tema</string> 388 <string name="change_theme_mode">Alterar o tema</string>
307 <string name="theme_mode_follow_system">Igual ao Sistema</string> 389 <string name="theme_mode_follow_system">Igual ao Sistema</string>
308 <string name="theme_mode_light">Claro</string> 390 <string name="theme_mode_light">Claro</string>
309 <string name="theme_mode_dark">Escuro</string> 391 <string name="theme_mode_dark">Escuro</string>
310 392
393 <!-- Audio output engines -->
394 <string name="cubeb">cubeb</string>
395
311 <!-- Black backgrounds theme --> 396 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">Usa Fundos Negros</string> 397 <string name="use_black_backgrounds">Plano de fundo preto</string>
313 <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string> 398 <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string>
314 399
315</resources> 400 <!-- Picture-In-Picture -->
401 <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>
403 <string name="pause">Pausa</string>
404 <string name="play">Correr</string>
405 <string name="mute">Mudo</string>
406 <string name="unmute">Unmute</string>
407
408 <!-- Licenses screen strings -->
409 <string name="licenses">Licenças</string>
410 <string name="license_fidelityfx_fsr_description">Upscaling de alta qualidade da AMD</string>
411 </resources>
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 0a1a47fbb..6afea9b03 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
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Este software corre jogos para a consola Nintendo Switch. Não estão incluídas nem jogos ou chaves. &lt;br /&gt;&lt;br /&gt;Antes de começares, por favor localiza o ficheiro <![CDATA[1 prod.keys 1]]> no armazenamento do teu dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[2Learn more2]]></string> 4 <string name="app_disclaimer">Este software corre jogos para a consola Nintendo Switch. Não estão incluídas nem jogos ou chaves. &lt;br /&gt;&lt;br /&gt;Antes de começares, por favor localiza o ficheiro <![CDATA[1 prod.keys 1]]> no armazenamento do teu dispositivo.&lt;br /&gt;&lt;br /&gt;<![CDATA[2Learn more2]]></string>
5 <string name="emulation_notification_channel_name">Emulação está Ativa</string> 5 <string name="emulation_notification_channel_name">Emulação está Ativa</string>
@@ -25,6 +25,7 @@
25 <string name="back">Voltar</string> 25 <string name="back">Voltar</string>
26 <string name="add_games">Adiciona Jogos</string> 26 <string name="add_games">Adiciona Jogos</string>
27 <string name="add_games_description">Seleciona a tua pasta de Jogos</string> 27 <string name="add_games_description">Seleciona a tua pasta de Jogos</string>
28 <string name="step_complete">Completo!</string>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">Jogos</string> 31 <string name="home_games">Jogos</string>
@@ -37,7 +38,8 @@
37 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string> 38 <string name="add_games_warning">Ignorar a seleção da pasta de jogos?</string>
38 <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> 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>
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">Procurar Jogos</string> 41 <string name="home_search_games">Procurar jogos</string>
42 <string name="search_settings">Procurar nas definições</string>
41 <string name="games_dir_selected">Pasta de Jogos selecionada</string> 43 <string name="games_dir_selected">Pasta de Jogos selecionada</string>
42 <string name="install_prod_keys">Instala prod.keys</string> 44 <string name="install_prod_keys">Instala prod.keys</string>
43 <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string> 45 <string name="install_prod_keys_description">Necessário para desencriptar jogos comerciais</string>
@@ -61,15 +63,18 @@
61 <string name="invalid_keys_file">Ficheiro de chaves inválido</string> 63 <string name="invalid_keys_file">Ficheiro de chaves inválido</string>
62 <string name="install_keys_success">Chaves instaladas com sucesso</string> 64 <string name="install_keys_success">Chaves instaladas com sucesso</string>
63 <string name="reading_keys_failure">Erro ao ler chaves de encriptação</string> 65 <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_amiibo_keys_failure_extension_description">Verifique se seu arquivo keys possui a extensão .bin e tente novamente.</string>
64 <string name="invalid_keys_error">Chaves de encriptação inválidas</string> 68 <string name="invalid_keys_error">Chaves de encriptação inválidas</string>
65 <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>
66 <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string> 70 <string name="install_keys_failure_description">O ficheiro selecionado está corrompido. Por favor recarrega as tuas chaves.</string>
67 <string name="install_gpu_driver">Instala driver para GPU</string> 71 <string name="install_gpu_driver">Instala driver para GPU</string>
68 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string> 72 <string name="install_gpu_driver_description">Instala drivers alternativos para desempenho ou precisão potencialmente melhores</string>
69 <string name="advanced_settings">Configurações avançadas</string> 73 <string name="advanced_settings">Configurações avançadas</string>
74 <string name="advanced_settings_game">Definições avançadas: %1$s</string>
70 <string name="settings_description">Configura configurações do emulador</string> 75 <string name="settings_description">Configura configurações do emulador</string>
71 <string name="search_recently_played">Jogos recentes</string> 76 <string name="search_recently_played">Jogado recentemente</string>
72 <string name="search_recently_added">Adicionados recentemente</string> 77 <string name="search_recently_added">Adicionado recentemente</string>
73 <string name="search_retail">Jogos comerciais</string> 78 <string name="search_retail">Jogos comerciais</string>
74 <string name="search_homebrew">Homebrew</string> 79 <string name="search_homebrew">Homebrew</string>
75 <string name="open_user_folder">Abre a pasta Yuzu</string> 80 <string name="open_user_folder">Abre a pasta Yuzu</string>
@@ -86,6 +91,33 @@
86 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string> 91 <string name="save_file_invalid_zip_structure_description">O nome da primeira sub pasta tem de ser a ID do jogo.</string>
87 <string name="import_saves">Importar</string> 92 <string name="import_saves">Importar</string>
88 <string name="export_saves">Exportar</string> 93 <string name="export_saves">Exportar</string>
94 <string name="install_firmware">Instalar firmware</string>
95 <string name="install_firmware_description">O firmware deve estar em um arquivo ZIP e é necessário para iniciar alguns jogos.</string>
96 <string name="firmware_installing">Instalando firmware</string>
97 <string name="firmware_installed_success">Firmware instalado com sucesso.</string>
98 <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>
100 <string name="share_log">Compartilhe registros de debug.</string>
101 <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>
103 <string name="install_game_content">Instalar conteúdo adicional</string>
104 <string name="install_game_content_description">Instale atualizações de jogos ou DLC</string>
105 <string name="installing_game_content">A instalar conteúdo...</string>
106 <string name="install_game_content_failure">Erro ao instalar ficheiro(s) para 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>
108 <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>
110 <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>
112 <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>
114 <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>
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>
117 <string name="manage_yuzu_data">Administrar dados yuzu</string>
118 <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>
120 <string name="export_save_failed">Erro ao exportar dados guardados</string>
89 121
90 <!-- About screen strings --> 122 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia não é real</string> 123 <string name="gaia_is_not_real">Gaia não é real</string>
@@ -94,7 +126,18 @@
94 <string name="contributors">Contribuidores</string> 126 <string name="contributors">Contribuidores</string>
95 <string name="contributors_description">Feito com \u2764 da equipa do Yuzu</string> 127 <string name="contributors_description">Feito com \u2764 da equipa do Yuzu</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 128 <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>
97 <string name="build">Versão</string> 130 <string name="build">Versão</string>
131 <string name="user_data">Dado de utilizados</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>
133 <string name="exporting_user_data">A exportar dados de utilizados...</string>
134 <string name="importing_user_data">A importar dados de utilizador...</string>
135 <string name="import_user_data">Importar dados de utilizados...</string>
136 <string name="invalid_yuzu_backup">Backup yuzu inválido</string>
137 <string name="user_data_export_success">Dados de utilizados exportados com sucesso</string>
138 <string name="user_data_import_success">Dados de utilizador importado com sucesso</string>
139 <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>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 141 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 142 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 143 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -114,41 +157,53 @@
114 <string name="are_you_interested">Estás interessado?</string> 157 <string name="are_you_interested">Estás interessado?</string>
115 158
116 <!-- General settings strings --> 159 <!-- General settings strings -->
117 <string name="frame_limit_enable">Ativar limite de velocidade</string> 160 <string name="frame_limit_enable">Limite de velocidade</string>
118 <string name="frame_limit_enable_description">Quando ativada, a velocidade da emulação será limitada à percentagem definida da velocidade normal.</string> 161 <string name="frame_limit_enable_description">Limita a velocidade da emulação a uma porcentagem específica da velocidade normal.</string>
119 <string name="frame_limit_slider">Percentagem do limite de velocidade</string> 162 <string name="frame_limit_slider">Percentagem do limite de velocidade</string>
120 <string name="frame_limit_slider_description">Especifica o limite da percentagem da velocidade da emulação. Com a velocidade por defeito a 100% a emulação será limitada à velocidade normal. Valores maiores ou menores aumentarão ou diminuirão o 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>
121 <string name="cpu_accuracy">Precisão do CPU</string> 164 <string name="cpu_accuracy">Precisão do CPU</string>
165 <string name="value_with_units">%1$s%2$s</string>
122 166
123 <!-- System settings strings --> 167 <!-- System settings strings -->
124 <string name="use_docked_mode">Modo ancorado</string> 168 <string name="use_docked_mode">Modo Ancorado</string>
125 <string name="use_docked_mode_description">Emula em modo ancorado, que aumenta a resolução ás custas da performance.</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>
126 <string name="emulated_region">Região da emulação</string> 170 <string name="emulated_region">Região da emulação</string>
127 <string name="emulated_language">Idioma da emulação</string> 171 <string name="emulated_language">Idioma da emulação</string>
128 <string name="select_rtc_date">Seleciona a data RTC</string> 172 <string name="select_rtc_date">Selecione a data do sistema</string>
129 <string name="select_rtc_time">Seleciona a hora RTC</string> 173 <string name="select_rtc_time">Selecione a hora do sistema</string>
130 <string name="use_custom_rtc">Ativa RTC personalizado</string> 174 <string name="use_custom_rtc">RTC personalizado</string>
131 <string name="use_custom_rtc_description">Esta configuração permite definir um RTC personalizado diferente da hora atual do sistema</string> 175 <string name="use_custom_rtc_description">Permite a você configurar um relógio em tempo real separado do relógio do seu dispositivo.</string>
132 <string name="set_custom_rtc">Define RTC personalizado</string> 176 <string name="set_custom_rtc">Defina um relógio em tempo real personalizado</string>
133 177
134 <!-- Graphics settings strings --> 178 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Nível de precisão</string> 179 <string name="renderer_accuracy">Nível de precisão</string>
137 <string name="renderer_resolution">Resolução</string> 180 <string name="renderer_resolution">Resolução (Portátil/Ancorado)</string>
138 <string name="renderer_vsync">Modo VSync</string> 181 <string name="renderer_vsync">Modo VSync</string>
139 <string name="renderer_aspect_ratio">Proporção do ecrã</string> 182 <string name="renderer_screen_layout">Oriantação</string>
183 <string name="renderer_aspect_ratio">Proporção da tela</string>
140 <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string> 184 <string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
141 <string name="renderer_anti_aliasing">Método de Anti-Aliasing </string> 185 <string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string>
142 <string name="renderer_force_max_clock">Força velocidade máxima (Adreno only)</string> 186 <string name="renderer_force_max_clock">Força velocidade máxima (Adreno only)</string>
143 <string name="renderer_force_max_clock_description">Força o GPU a correr à velocidade máxima (restrições térmicas serão aplicadas)</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>
144 <string name="renderer_asynchronous_shaders">Usa shaders assíncronos </string> 188 <string name="renderer_asynchronous_shaders">Usa shaders assíncronos </string>
145 <string name="renderer_asynchronous_shaders_description">Compila shaders assincronamente, que aumentará a fluidez, mas poderá causar falhas.</string> 189 <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>
191 <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>
193 <string name="use_disk_shader_cache_description">Reduz travamentos ao armazenar e carregar localmente os shaders.</string>
194
195 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">Depuração da CPU</string>
198 <string name="cpu_debug_mode_description">Coloca a CPU em um modo de depuração lento.</string>
199 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string>
146 <string name="renderer_debug">Ativar depuração de gráficos</string> 201 <string name="renderer_debug">Ativar depuração de gráficos</string>
147 <string name="renderer_debug_description">Quando selecionado, a API gráfica entra num modo de depuração mais lento.</string> 202 <string name="renderer_debug_description">Quando selecionado, a API gráfica entra num modo de depuração mais lento.</string>
148 <string name="use_disk_shader_cache">Usar cache do disk shader</string> 203 <string name="fastmem">Fastmem</string>
149 <string name="use_disk_shader_cache_description">Aumenta a fluidez ao guardar e carregar shaders gerados para o armazenamento.</string>
150 204
151 <!-- Audio settings strings --> 205 <!-- Audio settings strings -->
206 <string name="audio_output_engine">Motor de saída</string>
152 <string name="audio_volume">Volume</string> 207 <string name="audio_volume">Volume</string>
153 <string name="audio_volume_description">Especifica o volume de saída.</string> 208 <string name="audio_volume_description">Especifica o volume de saída.</string>
154 209
@@ -157,14 +212,24 @@
157 <string name="ini_saved">Configurações guardadas</string> 212 <string name="ini_saved">Configurações guardadas</string>
158 <string name="gameid_saved">Configurações guardadas para %1$s</string> 213 <string name="gameid_saved">Configurações guardadas para %1$s</string>
159 <string name="error_saving">Erro ao guardar %1$s.ini: %2$s</string> 214 <string name="error_saving">Erro ao guardar %1$s.ini: %2$s</string>
215 <string name="unimplemented_menu">Menu não implementado</string>
160 <string name="loading">A carregar...</string> 216 <string name="loading">A carregar...</string>
217 <string name="shutting_down">A desligar...</string>
161 <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string> 218 <string name="reset_setting_confirmation">Queres reverter esta definição para os valores padrão?</string>
162 <string name="reset_to_default">Reverter para padrão</string> 219 <string name="reset_to_default">Reverter para padrão</string>
163 <string name="reset_all_settings">Redefinir todas as configurações?</string> 220 <string name="reset_all_settings">Redefinir todas as configurações?</string>
164 <string name="reset_all_settings_description">Todas as configurações avançadas serão redefinidas para as definições padrão. Isto não pode ser revertido.</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>
165 <string name="settings_reset">Redefinir configurações </string> 222 <string name="settings_reset">Redefinir configurações </string>
166 <string name="close">Fechar</string> 223 <string name="close">Fechar</string>
167 <string name="learn_more">Saber Mais</string> 224 <string name="learn_more">Saber mais</string>
225 <string name="auto">Automático</string>
226 <string name="submit">Enviar</string>
227 <string name="string_null">Nenhum (desativado)</string>
228 <string name="string_import">Importar</string>
229 <string name="export">Exportar</string>
230 <string name="export_failed">Exportação falhada</string>
231 <string name="import_failed">IMportação falhada</string>
232 <string name="cancelling">A cancelar</string>
168 233
169 <!-- GPU driver installation --> 234 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Seleciona a driver para o GPU</string> 235 <string name="select_gpu_driver">Seleciona a driver para o GPU</string>
@@ -172,6 +237,7 @@
172 <string name="select_gpu_driver_install">Instalar</string> 237 <string name="select_gpu_driver_install">Instalar</string>
173 <string name="select_gpu_driver_default">Padrão</string> 238 <string name="select_gpu_driver_default">Padrão</string>
174 <string name="select_gpu_driver_use_default">Usar o driver padrão do GPU</string> 239 <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>
175 <string name="system_gpu_driver">Driver do GPU padrão</string> 241 <string name="system_gpu_driver">Driver do GPU padrão</string>
176 <string name="installing_driver">A instalar o Driver...</string> 242 <string name="installing_driver">A instalar o Driver...</string>
177 243
@@ -182,10 +248,11 @@
182 <string name="preferences_graphics">Gráficos</string> 248 <string name="preferences_graphics">Gráficos</string>
183 <string name="preferences_audio">Audio</string> 249 <string name="preferences_audio">Audio</string>
184 <string name="preferences_theme">Cor e tema.</string> 250 <string name="preferences_theme">Cor e tema.</string>
251 <string name="preferences_debug">Depurar</string>
185 252
186 <!-- ROM loading errors --> 253 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">A tua ROM está encriptada</string> 254 <string name="loader_error_encrypted">A tua ROM está encriptada</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[Por favor segue os guias para fazer redump das tuas<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">Cartidges de Jogo</a> or <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">Jogos Instalados</a>.]]></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>
189 <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> 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>
190 <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vídeo.</string> 257 <string name="loader_error_video_core">Ocorreu um erro ao iniciar o núcleo de vídeo.</string>
191 <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> 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>
@@ -193,28 +260,28 @@
193 <string name="loader_error_file_not_found">O ficheiro da ROM não existe</string> 260 <string name="loader_error_file_not_found">O ficheiro da ROM não existe</string>
194 261
195 <!-- Emulation Menu --> 262 <!-- Emulation Menu -->
196 <string name="emulation_exit">Sair da emulação</string> 263 <string name="emulation_exit">Parar emulação</string>
197 <string name="emulation_done">Feito</string> 264 <string name="emulation_done">Feito</string>
198 <string name="emulation_fps_counter">Contador de FPS</string> 265 <string name="emulation_fps_counter">Contador de FPS</string>
199 <string name="emulation_toggle_controls">Alterar Controlos</string> 266 <string name="emulation_toggle_controls">Alterar controles</string>
200 <string name="emulation_rel_stick_center">Centro do Analógico Relativo</string> 267 <string name="emulation_rel_stick_center">Centro Relativo de Analógico</string>
201 <string name="emulation_dpad_slide">Deslizar do DPad</string> 268 <string name="emulation_dpad_slide">Deslizamento dos Botões Direcionais</string>
202 <string name="emulation_haptics">Hápticos </string> 269 <string name="emulation_haptics">Vibração ao tocar</string>
203 <string name="emulation_show_overlay">Mostrar sobreposição </string> 270 <string name="emulation_show_overlay">Mostrar overlay</string>
204 <string name="emulation_toggle_all">Alterar todos</string> 271 <string name="emulation_toggle_all">Marcar/Desmarcar tudo</string>
205 <string name="emulation_control_adjust">Ajustar a sobreposição </string> 272 <string name="emulation_control_adjust">Ajustar overlay</string>
206 <string name="emulation_control_scale">Escala</string> 273 <string name="emulation_control_scale">Escala</string>
207 <string name="emulation_control_opacity">Opacidade</string> 274 <string name="emulation_control_opacity">Opacidade</string>
208 <string name="emulation_touch_overlay_reset">Redefinir Sobreposição </string> 275 <string name="emulation_touch_overlay_reset">Restaurar overlay padrão</string>
209 <string name="emulation_touch_overlay_edit">Editar sobreposição </string> 276 <string name="emulation_touch_overlay_edit">Editar overlay</string>
210 <string name="emulation_pause">Pausa emulação</string> 277 <string name="emulation_pause">Pausar emulação</string>
211 <string name="emulation_unpause">Retomar emulação</string> 278 <string name="emulation_unpause">Despausar emulação</string>
212 <string name="emulation_input_overlay">Opções de sobreposição </string> 279 <string name="emulation_input_overlay">Opções de overlay</string>
213 280
214 <string name="load_settings">Configurações a carregar...</string> 281 <string name="load_settings">Carregando configurações...</string>
215 282
216 <!-- Software keyboard --> 283 <!-- Software keyboard -->
217 <string name="software_keyboard">Teclado de Software</string> 284 <string name="software_keyboard">Teclado de software</string>
218 285
219 <!-- Errors and warnings --> 286 <!-- Errors and warnings -->
220 <string name="abort_button">Abortar</string> 287 <string name="abort_button">Abortar</string>
@@ -226,6 +293,9 @@
226 <string name="fatal_error">Erro fatal</string> 293 <string name="fatal_error">Erro fatal</string>
227 <string name="fatal_error_message">Ocorreu um erro fatal. Verifica o teu registro para detalhes. \nContinuar a emulação pode causar erros.</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>
228 <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> 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>
296 <string name="device_memory_inadequate">RAM do dispositivo: %1$s\nRecommended: %2$s</string>
297 <string name="memory_formatted">%1$s %2$s</string>
298 <string name="no_game_present">Nenhum jogo inicializável presente!</string>
229 299
230 <!-- Region Names --> 300 <!-- Region Names -->
231 <string name="region_japan">Japão</string> 301 <string name="region_japan">Japão</string>
@@ -236,7 +306,14 @@
236 <string name="region_korea">Coreia</string> 306 <string name="region_korea">Coreia</string>
237 <string name="region_taiwan">Taiwan</string> 307 <string name="region_taiwan">Taiwan</string>
238 308
239 <!-- Language Names --> 309 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string>
311 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string>
314 <string name="memory_terabyte">TB</string>
315 <string name="memory_petabyte">PB</string>
316 <string name="memory_exabyte">EB</string>
240 317
241 <!-- Renderer APIs --> 318 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulcano</string> 319 <string name="renderer_vulkan">Vulcano</string>
@@ -274,12 +351,17 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 351 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 352 <string name="anti_aliasing_smaa">SMAA</string>
276 353
354 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">Landscape</string>
356 <string name="screen_layout_portrait">Portrait</string>
357 <string name="screen_layout_auto">Automático</string>
358
277 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
278 <string name="ratio_default">Padrão (16:9)</string> 360 <string name="ratio_default">Padrão (16:9)</string>
279 <string name="ratio_force_four_three">Forçar 4:3</string> 361 <string name="ratio_force_four_three">Forçar 4:3</string>
280 <string name="ratio_force_twenty_one_nine">Forçar 21:9</string> 362 <string name="ratio_force_twenty_one_nine">Forçar 21:9</string>
281 <string name="ratio_force_sixteen_ten">Forçar 16:10</string> 363 <string name="ratio_force_sixteen_ten">Forçar 16:10</string>
282 <string name="ratio_stretch">Esticar à Janela</string> 364 <string name="ratio_stretch">Esticar à janela</string>
283 365
284 <!-- CPU Accuracy --> 366 <!-- CPU Accuracy -->
285 <string name="cpu_accuracy_accurate">Preciso</string> 367 <string name="cpu_accuracy_accurate">Preciso</string>
@@ -287,9 +369,9 @@
287 <string name="cpu_accuracy_paranoid">Paranoid (Lento)</string> 369 <string name="cpu_accuracy_paranoid">Paranoid (Lento)</string>
288 370
289 <!-- Gamepad Buttons --> 371 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">D-Pad</string> 372 <string name="gamepad_d_pad">Botões Direcionais</string>
291 <string name="gamepad_left_stick">Analógico Esquerdo</string> 373 <string name="gamepad_left_stick">Analógico esquerdo</string>
292 <string name="gamepad_right_stick">Analógico Direito</string> 374 <string name="gamepad_right_stick">Analógico direito</string>
293 <string name="gamepad_home">Home</string> 375 <string name="gamepad_home">Home</string>
294 <string name="gamepad_screenshot">Captura de ecrã</string> 376 <string name="gamepad_screenshot">Captura de ecrã</string>
295 377
@@ -298,18 +380,32 @@
298 <string name="building_shaders">A criar shaders</string> 380 <string name="building_shaders">A criar shaders</string>
299 381
300 <!-- Theme options --> 382 <!-- Theme options -->
301 <string name="change_app_theme">Muda o Tema da App</string> 383 <string name="change_app_theme">Mudar o tema do aplicativo</string>
302 <string name="theme_default">Padrão</string> 384 <string name="theme_default">Padrão</string>
303 <string name="theme_material_you">Material You</string> 385 <string name="theme_material_you">Material You</string>
304 386
305 <!-- Theme Modes --> 387 <!-- Theme Modes -->
306 <string name="change_theme_mode">Altera o Modo do Tema</string> 388 <string name="change_theme_mode">Alterar o tema</string>
307 <string name="theme_mode_follow_system">Igual ao Sistema</string> 389 <string name="theme_mode_follow_system">Igual ao Sistema</string>
308 <string name="theme_mode_light">Claro</string> 390 <string name="theme_mode_light">Claro</string>
309 <string name="theme_mode_dark">Escuro</string> 391 <string name="theme_mode_dark">Escuro</string>
310 392
393 <!-- Audio output engines -->
394 <string name="cubeb">cubeb</string>
395
311 <!-- Black backgrounds theme --> 396 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">Usa Fundos Escuros</string> 397 <string name="use_black_backgrounds">Plano de fundo preto</string>
313 <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string> 398 <string name="use_black_backgrounds_description">Quando usar tema escuro, aplicar fundos escuros</string>
314 399
315</resources> 400 <!-- Picture-In-Picture -->
401 <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>
403 <string name="pause">Pausa</string>
404 <string name="play">Correr</string>
405 <string name="mute">Mute</string>
406 <string name="unmute">Unmute</string>
407
408 <!-- Licenses screen strings -->
409 <string name="licenses">Licenças</string>
410 <string name="license_fidelityfx_fsr_description">Upscaling de alta qualidade da AMD</string>
411 </resources>
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 0bef035d6..c614257a8 100644
--- a/src/android/app/src/main/res/values-ru/strings.xml
+++ b/src/android/app/src/main/res/values-ru/strings.xml
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Это программное обеÑпечение позволÑет запуÑкать игры Ð´Ð»Ñ Ð¸Ð³Ñ€Ð¾Ð²Ð¾Ð¹ конÑоли Nintendo Switch. Мы не предоÑтавлÑем Ñами игры или ключи.&lt;br /&gt;&lt;br /&gt;Перед началом работы найдите файл <![CDATA[<b> prod.keys </b>]]> в хранилище уÑтройÑтва..&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Узнать больше</a>]]></string> 4 <string name="app_disclaimer">Это программное обеÑпечение позволÑет запуÑкать игры Ð´Ð»Ñ Ð¸Ð³Ñ€Ð¾Ð²Ð¾Ð¹ конÑоли Nintendo Switch. Мы не предоÑтавлÑем Ñами игры или ключи.&lt;br /&gt;&lt;br /&gt;Перед началом работы найдите файл <![CDATA[<b> prod.keys </b>]]> в хранилище уÑтройÑтва..&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Узнать больше</a>]]></string>
5 <string name="emulation_notification_channel_name">ЭмулÑÑ†Ð¸Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð°</string> 5 <string name="emulation_notification_channel_name">ЭмулÑÑ†Ð¸Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð°</string>
@@ -7,7 +7,7 @@
7 <string name="emulation_notification_running">yuzu запущен</string> 7 <string name="emulation_notification_running">yuzu запущен</string>
8 <string name="notice_notification_channel_name">Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ ошибки</string> 8 <string name="notice_notification_channel_name">Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¸ ошибки</string>
9 <string name="notice_notification_channel_description">Показывать уведомлениÑ, когда что-то пошло не так</string> 9 <string name="notice_notification_channel_description">Показывать уведомлениÑ, когда что-то пошло не так</string>
10 <string name="notification_permission_not_granted">Ð’Ñ‹ не предоÑтавили разрешение уведомлений!</string> 10 <string name="notification_permission_not_granted">Ð’Ñ‹ не предоÑтавили разрешение на уведомлениÑ!</string>
11 11
12 <!-- Setup strings --> 12 <!-- Setup strings -->
13 <string name="welcome">Добро пожаловать!</string> 13 <string name="welcome">Добро пожаловать!</string>
@@ -25,6 +25,7 @@
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>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">Игры</string> 31 <string name="home_games">Игры</string>
@@ -38,6 +39,7 @@
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>
42 <string name="search_settings">ÐаÑтройки поиÑка</string>
41 <string name="games_dir_selected">Выбрана папка Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string> 43 <string name="games_dir_selected">Выбрана папка Ñ Ð¸Ð³Ñ€Ð°Ð¼Ð¸</string>
42 <string name="install_prod_keys">УÑтановить prod.keys</string> 44 <string name="install_prod_keys">УÑтановить prod.keys</string>
43 <string name="install_prod_keys_description">ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ñшифровки розничных игр</string> 45 <string name="install_prod_keys_description">ТребуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ñшифровки розничных игр</string>
@@ -61,14 +63,17 @@
61 <string name="invalid_keys_file">Выбран неверный файл ключей</string> 63 <string name="invalid_keys_file">Выбран неверный файл ключей</string>
62 <string name="install_keys_success">Ключи уÑпешно уÑтановлены</string> 64 <string name="install_keys_success">Ключи уÑпешно уÑтановлены</string>
63 <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>
64 <string name="invalid_keys_error">Ðеверные ключи шифрованиÑ</string> 68 <string name="invalid_keys_error">Ðеверные ключи шифрованиÑ</string>
65 <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>
66 <string name="install_keys_failure_description">Выбранный файл неверен или поврежден. ПожалуйÑта, пере-дампите ваши ключи.</string> 70 <string name="install_keys_failure_description">Выбранный файл неверен или поврежден. ПожалуйÑта, пере-дампите ваши ключи.</string>
67 <string name="install_gpu_driver">УÑтановить драйвер ГП</string> 71 <string name="install_gpu_driver">УÑтановить драйвер ГП</string>
68 <string name="install_gpu_driver_description">УÑтановите альтернативные драйверы Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾ лучшей производительноÑти и/или точноÑти</string> 72 <string name="install_gpu_driver_description">УÑтановите альтернативные драйверы Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ð¸Ð°Ð»ÑŒÐ½Ð¾ лучшей производительноÑти и/или точноÑти</string>
69 <string name="advanced_settings">РаÑширенные наÑтройки</string> 73 <string name="advanced_settings">РаÑширенные наÑтройки</string>
74 <string name="advanced_settings_game">РаÑширенные наÑтройки: %1$s</string>
70 <string name="settings_description">ÐаÑтройка параметров ÑмулÑтора</string> 75 <string name="settings_description">ÐаÑтройка параметров ÑмулÑтора</string>
71 <string name="search_recently_played">Ðедавно Ñыграно</string> 76 <string name="search_recently_played">Ðедавно Ñыгранные</string>
72 <string name="search_recently_added">Ðедавно добавлено</string> 77 <string name="search_recently_added">Ðедавно добавлено</string>
73 <string name="search_retail">Розничные</string> 78 <string name="search_retail">Розничные</string>
74 <string name="search_homebrew">Homebrew</string> 79 <string name="search_homebrew">Homebrew</string>
@@ -86,6 +91,34 @@
86 <string name="save_file_invalid_zip_structure_description">Ðазвание первой вложенной папки должно быть идентификатором игры.</string> 91 <string name="save_file_invalid_zip_structure_description">Ðазвание первой вложенной папки должно быть идентификатором игры.</string>
87 <string name="import_saves">Импорт</string> 92 <string name="import_saves">Импорт</string>
88 <string name="export_saves">ЭкÑпорт</string> 93 <string name="export_saves">ЭкÑпорт</string>
94 <string name="install_firmware">УÑтановить прошивку</string>
95 <string name="install_firmware_description">Прошивка должна находитьÑÑ Ð² ZIP-архиве и необходима Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ некоторых игр</string>
96 <string name="firmware_installing">УÑтановка прошивки</string>
97 <string name="firmware_installed_success">Прошивка уÑпешно уÑтановлена</string>
98 <string name="firmware_installed_failure">Ðе удалоÑÑŒ уÑтановить прошивку</string>
99 <string name="firmware_installed_failure_description">УбедитеÑÑŒ что файлы прошивки nca находÑÑ‚ÑÑ Ð² корне zip-архива и повторите попытку.</string>
100 <string name="share_log">ПоделитьÑÑ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð¾Ð¼ отладки</string>
101 <string name="share_log_description">ПоделитьÑÑ Ð¶ÑƒÑ€Ð½Ð°Ð»Ð¾Ð¼ отладки yuzu Ð´Ð»Ñ ÑƒÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼</string>
102 <string name="share_log_missing">Файл журнала не найден</string>
103 <string name="install_game_content">УÑтановить игровой контент</string>
104 <string name="install_game_content_description">УÑтановить Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð³Ñ€Ñ‹ или дополнений</string>
105 <string name="installing_game_content">УÑтановка контента...</string>
106 <string name="install_game_content_failure">Ошибка уÑтановки файл(ов) в NAND.</string>
107 <string name="install_game_content_failure_description">УбедитеÑÑŒ что Ñодержимое допуÑтимо и что файл prod.keys уÑтановлен.</string>
108 <string name="install_game_content_failure_base">УÑтановка базовых игр запрещена во избежание возможных конфликтов.</string>
109 <string name="install_game_content_failure_file_extension">ПоддерживаетÑÑ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ контент NSP и XCI. ПожалуйÑта убедитеÑÑŒ что игровой контент дейÑтвителен.</string>
110 <string name="install_game_content_failed_count">%1$d ошибка уÑтановки</string>
111 <string name="install_game_content_success">Игровой контент уÑпешно уÑтановлен</string>
112 <string name="install_game_content_success_install">%1$d УÑпешно уÑтановлено</string>
113 <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>
115 <string name="custom_driver_not_supported">ПользовательÑкие драйверы не поддерживаютÑÑ</string>
116 <string name="custom_driver_not_supported_description">Загрузка пользовательÑкого драйвера в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½Ðµ поддерживаетÑÑ Ð´Ð»Ñ Ñтого уÑтройÑтва.\nПроверьте Ñтот параметр еще раз в будущем чтобы узнать была ли добавлена ​​поддержка!
117 </string>
118 <string name="manage_yuzu_data">Управление данными yuzu</string>
119 <string name="manage_yuzu_data_description">Импортируйте/ÑкÑпортируйте прошивку, ключи, пользовательÑкие данные и многое другое!</string>
120 <string name="share_save_file">ПоделитьÑÑ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ ÑохранениÑ</string>
121 <string name="export_save_failed">Ðе удалоÑÑŒ ÑкÑпортировать Ñохранение</string>
89 122
90 <!-- About screen strings --> 123 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia не ÑущеÑтвует</string> 124 <string name="gaia_is_not_real">Gaia не ÑущеÑтвует</string>
@@ -94,7 +127,18 @@
94 <string name="contributors">Контрибьюторы</string> 127 <string name="contributors">Контрибьюторы</string>
95 <string name="contributors_description">Сделано Ñ \u2764 от команды yuzu</string> 128 <string name="contributors_description">Сделано Ñ \u2764 от команды yuzu</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 129 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
130 <string name="licenses_description">Проекты, которые Ñделали yuzu Ð´Ð»Ñ Android возможным</string>
97 <string name="build">Сборка</string> 131 <string name="build">Сборка</string>
132 <string name="user_data">Данные пользователÑ</string>
133 <string name="user_data_description">Импортируйте/ÑкÑпортируйте вÑе данные приложениÑ.\n\nПри импорте пользовательÑких данных вÑе ÑущеÑтвующие пользовательÑкие данные будут удалены!</string>
134 <string name="exporting_user_data">ЭкÑпорт пользовательÑких данных…</string>
135 <string name="importing_user_data">Импорт пользовательÑких данных…</string>
136 <string name="import_user_data">Импортировать пользовательÑкие данные</string>
137 <string name="invalid_yuzu_backup">ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñ€ÐµÐ·ÐµÑ€Ð²Ð½Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ yuzu</string>
138 <string name="user_data_export_success">ПользовательÑкие данные уÑпешно ÑкÑпортированы</string>
139 <string name="user_data_import_success">ПользовательÑкие данные уÑпешно импортированы</string>
140 <string name="user_data_export_cancelled">ЭкÑпорт отменен</string>
141 <string name="user_data_import_failed_description">УбедитеÑÑŒ что папки пользовательÑких данных находÑÑ‚ÑÑ Ð² корне zip-папки и Ñодержат файл конфигурации config/config.ini и повторите попытку.</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 142 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 143 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 144 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -114,41 +158,51 @@
114 <string name="are_you_interested">Ð’Ñ‹ заинтереÑованы?</string> 158 <string name="are_you_interested">Ð’Ñ‹ заинтереÑованы?</string>
115 159
116 <!-- General settings strings --> 160 <!-- General settings strings -->
117 <string name="frame_limit_enable">Ðключить ограничение ÑкороÑти</string> 161 <string name="frame_limit_enable">Ограничить ÑкороÑть</string>
118 <string name="frame_limit_enable_description">ЕÑли Ñта Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð°, ÑкороÑть ÑмулÑции будет ограничена указанным процентом от нормальной ÑкороÑти.</string> 162 <string name="frame_limit_enable_description">Ограничивает ÑкороÑть ÑмулÑции указанным процентом от нормальной ÑкороÑти.</string>
119 <string name="frame_limit_slider">Ограничение процента cкороÑти</string> 163 <string name="frame_limit_slider">Ограничение процента cкороÑти</string>
120 <string name="frame_limit_slider_description">Указывает процент Ð´Ð»Ñ Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ ÑкороÑти ÑмулÑции. При значении по умолчанию 100% ÑмулÑÑ†Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ ограничена нормальной ÑкороÑтью. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ‹ÑˆÐµ или ниже будут увеличивать или уменьшать ограничение ÑкороÑти.</string> 164 <string name="frame_limit_slider_description">Указывает процент Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ ÑкороÑти ÑмулÑции. 100% - Ñто Ð½Ð¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÑкороÑть. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐµ или меньше увеличивают или уменьшают ограничение ÑкороÑти.</string>
121 <string name="cpu_accuracy">ТочноÑть ЦП</string> 165 <string name="cpu_accuracy">ТочноÑть ЦП</string>
166 <string name="value_with_units">%1$s%2$s</string>
122 167
123 <!-- System settings strings --> 168 <!-- System settings strings -->
124 <string name="use_docked_mode">Режим док-Ñтанции</string> 169 <string name="use_docked_mode">Режим док-Ñтанции</string>
125 <string name="use_docked_mode_description">ЭмулÑÑ†Ð¸Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ð° док-Ñтанции, что увеличивает разрешение за Ñчет ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти.</string> 170 <string name="use_docked_mode_description">Увеличивает разрешение, ÑÐ½Ð¸Ð¶Ð°Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñть. Портативный режим иÑпользуетÑÑ Ð¿Ñ€Ð¸ отключении, ÑÐ½Ð¸Ð¶Ð°Ñ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ðµ и Ð¿Ð¾Ð²Ñ‹ÑˆÐ°Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñть.</string>
126 <string name="emulated_region">Эмулируемый регион</string> 171 <string name="emulated_region">Регион конÑоли</string>
127 <string name="emulated_language">ЭмулируемÑй Ñзык</string> 172 <string name="emulated_language">ЯзÑк конÑоли</string>
128 <string name="select_rtc_date">Выберите дату RTC</string> 173 <string name="select_rtc_date">Выберите дату RTC</string>
129 <string name="select_rtc_time">Выберите Ð²Ñ€ÐµÐ¼Ñ RTC</string> 174 <string name="select_rtc_time">Выберите Ð²Ñ€ÐµÐ¼Ñ RTC</string>
130 <string name="use_custom_rtc">Ðключить пользовательÑкий RTC</string> 175 <string name="use_custom_rtc">ПользовательÑкий RTC</string>
131 <string name="use_custom_rtc_description">Этот параметр позволÑет уÑтановить пользовательÑкие чаÑÑ‹ реального времени отдельно от текущего ÑиÑтемного времени</string> 176 <string name="use_custom_rtc_description">ПозволÑет уÑтановить пользовательÑкие чаÑÑ‹ реального времени отдельно от текущего ÑиÑтемного времени.</string>
132 <string name="set_custom_rtc">УÑтановить пользовательÑкий RTC</string> 177 <string name="set_custom_rtc">УÑтановить пользовательÑкий RTC</string>
133 178
134 <!-- Graphics settings strings --> 179 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Уровень точноÑти</string> 180 <string name="renderer_accuracy">Уровень точноÑти</string>
137 <string name="renderer_resolution">Разрешение</string> 181 <string name="renderer_resolution">Разрешение (портативное/в док-Ñтанции)</string>
138 <string name="renderer_vsync">Режим верт. Ñинхронизации</string> 182 <string name="renderer_vsync">Режим верт. Ñинхронизации</string>
183 <string name="renderer_screen_layout">ОриентациÑ</string>
139 <string name="renderer_aspect_ratio">Соотношение Ñторон</string> 184 <string name="renderer_aspect_ratio">Соотношение Ñторон</string>
140 <string name="renderer_scaling_filter">Фильтр адаптации окна</string> 185 <string name="renderer_scaling_filter">Фильтр адаптации окна</string>
141 <string name="renderer_anti_aliasing">Метод ÑглаживаниÑ</string> 186 <string name="renderer_anti_aliasing">Метод ÑглаживаниÑ</string>
142 <string name="renderer_force_max_clock">Принудительно заÑтавить макÑимальную тактовую чаÑтоту (только Ð´Ð»Ñ Adreno)</string> 187 <string name="renderer_force_max_clock">Принудительно заÑтавить макÑимальную тактовую чаÑтоту (только Ð´Ð»Ñ Adreno)</string>
143 <string name="renderer_force_max_clock_description">ЗаÑтавлÑет ГП работать на макÑимально возможных тактовых чаÑтотах (тепловые Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñе равно будут применÑтьÑÑ).</string> 188 <string name="renderer_force_max_clock_description">ЗаÑтавлÑет ГП работать на макÑимально возможных тактовых чаÑтотах (тепловые Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñе равно будут применÑтьÑÑ).</string>
144 <string name="renderer_asynchronous_shaders">ИÑпользовать аÑинхронные шейдеры</string> 189 <string name="renderer_asynchronous_shaders">ИÑпользовать аÑинхронные шейдеры</string>
145 <string name="renderer_asynchronous_shaders_description">Компилирует шейдеры аÑинхронно, что уменьшает завиÑаниÑ, но может взамен предоÑтавить визуальные баги.</string> 190 <string name="renderer_asynchronous_shaders_description">КомпилÑÑ†Ð¸Ñ ÑˆÐµÐ¹Ð´ÐµÑ€Ð¾Ð² проиÑходит аÑинхронно, что уменьшает завиÑаниÑ, но может привеÑти к поÑвлению багов.</string>
146 <string name="renderer_debug">Включить отладку графики</string> 191 <string name="renderer_reactive_flushing">Ð ÐµÐ°ÐºÑ‚Ð¸Ð²Ð½Ð°Ñ Ð¾Ñ‡Ð¸Ñтка</string>
147 <string name="renderer_debug_description">ЕÑли включено, графичеÑкий API переходит в более медленный режим отладки</string> 192 <string name="renderer_reactive_flushing_description">Повышение точноÑти рендеринга в некоторых играх за Ñчет ÑÐ½Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти.</string>
148 <string name="use_disk_shader_cache">ИÑпользовать кÑш шейдеров на диÑке</string> 193 <string name="use_disk_shader_cache">КÑш шейдеров на диÑке</string>
149 <string name="use_disk_shader_cache_description">Уменьшение завиÑаний за Ñчет Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸ загрузки Ñгенерированных шейдеров на хранилище.</string> 194 <string name="use_disk_shader_cache_description">Уменьшение завиÑаний за Ñчет Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¸ загрузки Ñгенерированных шейдеров.</string>
195
196 <!-- Debug settings strings -->
197 <string name="cpu">ЦП</string>
198 <string name="cpu_debug_mode">Отладка ЦП</string>
199 <string name="cpu_debug_mode_description">Переводит ЦП в режим медленной отладки.</string>
200 <string name="gpu">графичеÑкий процеÑÑор</string>
201 <string name="renderer_api">API</string>
202 <string name="renderer_debug">Отладка графики</string>
203 <string name="renderer_debug_description">Переводит графичеÑкий API в режим медленной отладки.</string>
204 <string name="fastmem">Fastmem</string>
150 205
151 <!-- Audio settings strings -->
152 <string name="audio_volume">ГромкоÑть</string> 206 <string name="audio_volume">ГромкоÑть</string>
153 <string name="audio_volume_description">Задает громкоÑть аудиовыхода.</string> 207 <string name="audio_volume_description">Задает громкоÑть аудиовыхода.</string>
154 208
@@ -157,7 +211,9 @@
157 <string name="ini_saved">Сохраненные наÑтройки</string> 211 <string name="ini_saved">Сохраненные наÑтройки</string>
158 <string name="gameid_saved">ÐаÑтройки Ñохранены Ð´Ð»Ñ %1$s</string> 212 <string name="gameid_saved">ÐаÑтройки Ñохранены Ð´Ð»Ñ %1$s</string>
159 <string name="error_saving">Ошибка ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ %1$s.ini: %2$s</string> 213 <string name="error_saving">Ошибка ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ %1$s.ini: %2$s</string>
214 <string name="unimplemented_menu">Ðереализованное меню</string>
160 <string name="loading">Загрузка...</string> 215 <string name="loading">Загрузка...</string>
216 <string name="shutting_down">Выключение…</string>
161 <string name="reset_setting_confirmation">Хотите ли вы вернуть Ñтот параметр к значению по умолчанию?</string> 217 <string name="reset_setting_confirmation">Хотите ли вы вернуть Ñтот параметр к значению по умолчанию?</string>
162 <string name="reset_to_default">Ð¡Ð±Ñ€Ð¾Ñ Ðº наÑтройкам по умолчанию</string> 218 <string name="reset_to_default">Ð¡Ð±Ñ€Ð¾Ñ Ðº наÑтройкам по умолчанию</string>
163 <string name="reset_all_settings">СброÑить вÑе наÑтройки?</string> 219 <string name="reset_all_settings">СброÑить вÑе наÑтройки?</string>
@@ -165,6 +221,14 @@
165 <string name="settings_reset">ÐаÑтройки Ñброшены</string> 221 <string name="settings_reset">ÐаÑтройки Ñброшены</string>
166 <string name="close">Закрыть</string> 222 <string name="close">Закрыть</string>
167 <string name="learn_more">Узнать больше</string> 223 <string name="learn_more">Узнать больше</string>
224 <string name="auto">Ðвто</string>
225 <string name="submit">Отправить</string>
226 <string name="string_null">Null</string>
227 <string name="string_import">Импорт</string>
228 <string name="export">ЭкÑпорт</string>
229 <string name="export_failed">Ошибка ÑкÑпорта</string>
230 <string name="import_failed">Ошибка импортированиÑ</string>
231 <string name="cancelling">ОтменÑÑŽ</string>
168 232
169 <!-- GPU driver installation --> 233 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Выбрать драйвер ГП</string> 234 <string name="select_gpu_driver">Выбрать драйвер ГП</string>
@@ -172,6 +236,7 @@
172 <string name="select_gpu_driver_install">УÑтановить</string> 236 <string name="select_gpu_driver_install">УÑтановить</string>
173 <string name="select_gpu_driver_default">По умолчанию</string> 237 <string name="select_gpu_driver_default">По умолчанию</string>
174 <string name="select_gpu_driver_use_default">ИÑпользуетÑÑ Ñтандартный драйвер ГП </string> 238 <string name="select_gpu_driver_use_default">ИÑпользуетÑÑ Ñтандартный драйвер ГП </string>
239 <string name="select_gpu_driver_error">Выбран неверный драйвер, иÑпользуетÑÑ Ñтандартный ÑиÑтемный!</string>
175 <string name="system_gpu_driver">СиÑтемный драйвер ГП</string> 240 <string name="system_gpu_driver">СиÑтемный драйвер ГП</string>
176 <string name="installing_driver">УÑтановка драйвера...</string> 241 <string name="installing_driver">УÑтановка драйвера...</string>
177 242
@@ -182,10 +247,11 @@
182 <string name="preferences_graphics">Графика</string> 247 <string name="preferences_graphics">Графика</string>
183 <string name="preferences_audio">Ðудио</string> 248 <string name="preferences_audio">Ðудио</string>
184 <string name="preferences_theme">Тема и цвет</string> 249 <string name="preferences_theme">Тема и цвет</string>
250 <string name="preferences_debug">Отладка</string>
185 251
186 <!-- ROM loading errors --> 252 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">Ваш ROM зашифрованный</string> 253 <string name="loader_error_encrypted">Ваш ROM зашифрованный</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[ПожалуйÑта, Ñледуйте инÑтрукциÑм, чтобы пере-дампить ваши <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">игровые картриджи</a> или <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">уÑтановленные игры</a>.]]></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>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[ПожалуйÑта, убедитеÑÑŒ, что ваш файл <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> уÑтановлен, чтобы игры можно было раÑшифровать.]]></string> 255 <string name="loader_error_encrypted_keys_description"><![CDATA[ПожалуйÑта, убедитеÑÑŒ, что ваш файл <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> уÑтановлен, чтобы игры можно было раÑшифровать.]]></string>
190 <string name="loader_error_video_core">Произошла ошибка при инициализации видеоÑдра.</string> 256 <string name="loader_error_video_core">Произошла ошибка при инициализации видеоÑдра.</string>
191 <string name="loader_error_video_core_description">Обычно Ñто вызвано неÑовмеÑтимым драйвером ГП. УÑтановка пользовательÑкого драйвера ГП может решить Ñту проблему.</string> 257 <string name="loader_error_video_core_description">Обычно Ñто вызвано неÑовмеÑтимым драйвером ГП. УÑтановка пользовательÑкого драйвера ГП может решить Ñту проблему.</string>
@@ -199,17 +265,17 @@
199 <string name="emulation_toggle_controls">Переключение управлениÑ</string> 265 <string name="emulation_toggle_controls">Переключение управлениÑ</string>
200 <string name="emulation_rel_stick_center">ОтноÑительный центр Ñтика</string> 266 <string name="emulation_rel_stick_center">ОтноÑительный центр Ñтика</string>
201 <string name="emulation_dpad_slide">Слайд креÑтовиной</string> 267 <string name="emulation_dpad_slide">Слайд креÑтовиной</string>
202 <string name="emulation_haptics">Ð¢Ð°ÐºÑ‚Ð¸Ð»ÑŒÐ½Ð°Ñ Ð¾Ð±Ñ€Ð°Ñ‚Ð½Ð°Ñ ÑвÑзь</string> 268 <string name="emulation_haptics">ÐžÐ±Ñ€Ð°Ñ‚Ð½Ð°Ñ ÑвÑзь от нажатий</string>
203 <string name="emulation_show_overlay">Показать оверлей</string> 269 <string name="emulation_show_overlay">Показать оверлей</string>
204 <string name="emulation_toggle_all">Переключить вÑÑ‘</string> 270 <string name="emulation_toggle_all">Переключить вÑÑ‘</string>
205 <string name="emulation_control_adjust">ÐаÑтроить оверлей</string> 271 <string name="emulation_control_adjust">Регулировка оверлеÑ</string>
206 <string name="emulation_control_scale">МаÑштаб</string> 272 <string name="emulation_control_scale">МаÑштаб</string>
207 <string name="emulation_control_opacity">ÐепрозрачноÑть</string> 273 <string name="emulation_control_opacity">ÐепрозрачноÑть</string>
208 <string name="emulation_touch_overlay_reset">СброÑить оверлей</string> 274 <string name="emulation_touch_overlay_reset">СброÑить оверлей</string>
209 <string name="emulation_touch_overlay_edit">Изменить оверлей</string> 275 <string name="emulation_touch_overlay_edit">Редактировать оверлей</string>
210 <string name="emulation_pause">Пауза ÑмулÑции</string> 276 <string name="emulation_pause">Пауза ÑмулÑции</string>
211 <string name="emulation_unpause">Возобновление ÑмулÑции</string> 277 <string name="emulation_unpause">Возобновить ÑмулÑцию</string>
212 <string name="emulation_input_overlay">ÐаÑтройки оверлеÑ</string> 278 <string name="emulation_input_overlay">ÐаÑтройка оверлеÑ</string>
213 279
214 <string name="load_settings">Загрузка наÑтроек...</string> 280 <string name="load_settings">Загрузка наÑтроек...</string>
215 281
@@ -226,6 +292,9 @@
226 <string name="fatal_error">Ð¤Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°</string> 292 <string name="fatal_error">Ð¤Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°</string>
227 <string name="fatal_error_message">Произошла Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Проверьте журнал Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информации.\nПродолжение ÑмулÑции может привеÑти к ÑбоÑм и ошибкам.</string> 293 <string name="fatal_error_message">Произошла Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¾ÑˆÐ¸Ð±ÐºÐ°. Проверьте журнал Ð´Ð»Ñ Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информации.\nПродолжение ÑмулÑции может привеÑти к ÑбоÑм и ошибкам.</string>
228 <string name="performance_warning">Отключение Ñтой наÑтройки значительно Ñнизит производительноÑть ÑмулÑции! Ð”Ð»Ñ Ð´Ð¾ÑÑ‚Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð½Ð°Ð¸Ð»ÑƒÑ‡ÑˆÐ¸Ñ… результатов рекомендуетÑÑ Ð¾Ñтавить Ñту наÑтройку включенной.</string> 294 <string name="performance_warning">Отключение Ñтой наÑтройки значительно Ñнизит производительноÑть ÑмулÑции! Ð”Ð»Ñ Ð´Ð¾ÑÑ‚Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð½Ð°Ð¸Ð»ÑƒÑ‡ÑˆÐ¸Ñ… результатов рекомендуетÑÑ Ð¾Ñтавить Ñту наÑтройку включенной.</string>
295 <string name="device_memory_inadequate">ÐžÐ¿ÐµÑ€Ð°Ñ‚Ð¸Ð²Ð½Ð°Ñ Ð¿Ð°Ð¼Ñть уÑтройÑтва: %1$s\nРекомендовано: %2$s</string>
296 <string name="memory_formatted">%1$s%2$s</string>
297 <string name="no_game_present">Загрузочной игры нету!</string>
229 298
230 <!-- Region Names --> 299 <!-- Region Names -->
231 <string name="region_japan">ЯпониÑ</string> 300 <string name="region_japan">ЯпониÑ</string>
@@ -236,7 +305,14 @@
236 <string name="region_korea">КореÑ</string> 305 <string name="region_korea">КореÑ</string>
237 <string name="region_taiwan">Тайвань</string> 306 <string name="region_taiwan">Тайвань</string>
238 307
239 <!-- Language Names --> 308 <!-- Memory Sizes -->
309 <string name="memory_byte">Байт</string>
310 <string name="memory_kilobyte">КБ</string>
311 <string name="memory_megabyte">МБ</string>
312 <string name="memory_gigabyte">GB</string>
313 <string name="memory_terabyte">ТБ</string>
314 <string name="memory_petabyte">ПБ</string>
315 <string name="memory_exabyte">ЕВ</string>
240 316
241 <!-- Renderer APIs --> 317 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 318 <string name="renderer_vulkan">Vulkan</string>
@@ -274,6 +350,11 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 350 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 351 <string name="anti_aliasing_smaa">SMAA</string>
276 352
353 <!-- Screen Layouts -->
354 <string name="screen_layout_landscape">Пейзаж</string>
355 <string name="screen_layout_portrait">Портрет</string>
356 <string name="screen_layout_auto">Ðвто</string>
357
277 <!-- Aspect Ratios --> 358 <!-- Aspect Ratios -->
278 <string name="ratio_default">Стандартное (16:9)</string> 359 <string name="ratio_default">Стандартное (16:9)</string>
279 <string name="ratio_force_four_three">ЗаÑтавить 4:3</string> 360 <string name="ratio_force_four_three">ЗаÑтавить 4:3</string>
@@ -288,8 +369,8 @@
288 369
289 <!-- Gamepad Buttons --> 370 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">КреÑтовина</string> 371 <string name="gamepad_d_pad">КреÑтовина</string>
291 <string name="gamepad_left_stick">Левый мини-джойÑтик</string> 372 <string name="gamepad_left_stick">Левый Ñтик</string>
292 <string name="gamepad_right_stick">Правый мини-джойÑтик</string> 373 <string name="gamepad_right_stick">Правый Ñтик</string>
293 <string name="gamepad_home">Home</string> 374 <string name="gamepad_home">Home</string>
294 <string name="gamepad_screenshot">Скриншот</string> 375 <string name="gamepad_screenshot">Скриншот</string>
295 376
@@ -298,18 +379,32 @@
298 <string name="building_shaders">ПоÑтройка шейдеров</string> 379 <string name="building_shaders">ПоÑтройка шейдеров</string>
299 380
300 <!-- Theme options --> 381 <!-- Theme options -->
301 <string name="change_app_theme">Изменить тему приложениÑ</string> 382 <string name="change_app_theme">Сменить тему</string>
302 <string name="theme_default">По умолчанию</string> 383 <string name="theme_default">По умолчанию</string>
303 <string name="theme_material_you">Material You</string> 384 <string name="theme_material_you">Material You</string>
304 385
305 <!-- Theme Modes --> 386 <!-- Theme Modes -->
306 <string name="change_theme_mode">Изменить режим темы</string> 387 <string name="change_theme_mode">Сменить режим темы</string>
307 <string name="theme_mode_follow_system">СиÑтемнаÑ</string> 388 <string name="theme_mode_follow_system">СиÑтемнаÑ</string>
308 <string name="theme_mode_light">СветлаÑ</string> 389 <string name="theme_mode_light">СветлаÑ</string>
309 <string name="theme_mode_dark">ТемнаÑ</string> 390 <string name="theme_mode_dark">ТемнаÑ</string>
310 391
392 <!-- Audio output engines -->
393 <string name="cubeb">cubeb</string>
394
311 <!-- Black backgrounds theme --> 395 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">ИÑпользовать черный фон</string> 396 <string name="use_black_backgrounds">ЧÑрный фон</string>
313 <string name="use_black_backgrounds_description">При иÑпользовании темной темы применÑйте черный фон.</string> 397 <string name="use_black_backgrounds_description">При иÑпользовании темной темы применÑйте черный фон.</string>
314 398
315</resources> 399 <!-- Picture-In-Picture -->
400 <string name="picture_in_picture">Картинка в картинке</string>
401 <string name="picture_in_picture_description">Свернуть окно при размещении в фоновом режиме</string>
402 <string name="pause">Пауза</string>
403 <string name="play">Играть</string>
404 <string name="mute">Выключить звук</string>
405 <string name="unmute">Включить звук</string>
406
407 <!-- Licenses screen strings -->
408 <string name="licenses">Лицензии</string>
409 <string name="license_fidelityfx_fsr_description">Ð’Ñ‹ÑококачеÑтвенное маÑштабирование от AMD</string>
410 </resources>
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 5b789ee98..34809dbb8 100644
--- a/src/android/app/src/main/res/values-uk/strings.xml
+++ b/src/android/app/src/main/res/values-uk/strings.xml
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">Це програмне Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” запуÑкати ігри Ð´Ð»Ñ Ñ–Ð³Ñ€Ð¾Ð²Ð¾Ñ— конÑолі Nintendo Switch. Ми не надаємо Ñамі ігри або ключі.&lt;br /&gt;&lt;br /&gt;Перед початком роботи знайдіть ваш файл <![CDATA[<b> prod.keys </b>]]> у Ñховищі приÑтрою.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ</a>]]></string> 4 <string name="app_disclaimer">Це програмне Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” запуÑкати ігри Ð´Ð»Ñ Ñ–Ð³Ñ€Ð¾Ð²Ð¾Ñ— конÑолі Nintendo Switch. Ми не надаємо Ñамі ігри або ключі.&lt;br /&gt;&lt;br /&gt;Перед початком роботи знайдіть ваш файл <![CDATA[<b> prod.keys </b>]]> у Ñховищі приÑтрою.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ</a>]]></string>
5 <string name="emulation_notification_channel_name">ЕмулÑÑ†Ñ–Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð°</string> 5 <string name="emulation_notification_channel_name">ЕмулÑÑ†Ñ–Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð°</string>
@@ -25,7 +25,6 @@
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
29 <!-- Home strings --> 28 <!-- Home strings -->
30 <string name="home_games">Ігри</string> 29 <string name="home_games">Ігри</string>
31 <string name="home_search">Пошук</string> 30 <string name="home_search">Пошук</string>
@@ -61,6 +60,7 @@
61 <string name="invalid_keys_file">Вибрано неправильний файл ключів</string> 60 <string name="invalid_keys_file">Вибрано неправильний файл ключів</string>
62 <string name="install_keys_success">Ключі уÑпішно вÑтановлено</string> 61 <string name="install_keys_success">Ключі уÑпішно вÑтановлено</string>
63 <string name="reading_keys_failure">Помилка під Ñ‡Ð°Ñ Ð·Ñ‡Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² шифруваннÑ</string> 62 <string name="reading_keys_failure">Помилка під Ñ‡Ð°Ñ Ð·Ñ‡Ð¸Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² шифруваннÑ</string>
63 <string name="install_prod_keys_failure_extension_description">ПереконайтеÑÑ, що файл ключів має Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ .keys, Ñ– повторіть Ñпробу.</string>
64 <string name="invalid_keys_error">Ðевірні ключі шифруваннÑ</string> 64 <string name="invalid_keys_error">Ðевірні ключі шифруваннÑ</string>
65 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 65 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
66 <string name="install_keys_failure_description">Обраний файл невірний або пошкоджений. Будь лаÑка, пере-дампіть ваші ключі.</string> 66 <string name="install_keys_failure_description">Обраний файл невірний або пошкоджений. Будь лаÑка, пере-дампіть ваші ключі.</string>
@@ -68,8 +68,6 @@
68 <string name="install_gpu_driver_description">Ð’Ñтановіть альтернативні драйвери Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ кращої продуктивноÑті та/або точноÑті</string> 68 <string name="install_gpu_driver_description">Ð’Ñтановіть альтернативні драйвери Ð´Ð»Ñ Ð¿Ð¾Ñ‚ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ кращої продуктивноÑті та/або точноÑті</string>
69 <string name="advanced_settings">Розширені налаштуваннÑ</string> 69 <string name="advanced_settings">Розширені налаштуваннÑ</string>
70 <string name="settings_description">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ–Ð² емулÑтора</string> 70 <string name="settings_description">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð°Ñ€Ð°Ð¼ÐµÑ‚Ñ€Ñ–Ð² емулÑтора</string>
71 <string name="search_recently_played">Ðещодавно зіграно</string>
72 <string name="search_recently_added">Ðещодавно додано</string>
73 <string name="search_retail">Роздрібні</string> 71 <string name="search_retail">Роздрібні</string>
74 <string name="search_homebrew">Homebrew</string> 72 <string name="search_homebrew">Homebrew</string>
75 <string name="open_user_folder">Відкрити папку yuzu</string> 73 <string name="open_user_folder">Відкрити папку yuzu</string>
@@ -86,7 +84,6 @@
86 <string name="save_file_invalid_zip_structure_description">Ðазва першої вкладеної папки має бути ідентифікатором гри.</string> 84 <string name="save_file_invalid_zip_structure_description">Ðазва першої вкладеної папки має бути ідентифікатором гри.</string>
87 <string name="import_saves">Імпорт</string> 85 <string name="import_saves">Імпорт</string>
88 <string name="export_saves">ЕкÑпорт</string> 86 <string name="export_saves">ЕкÑпорт</string>
89
90 <!-- About screen strings --> 87 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia не Ñ–Ñнує</string> 88 <string name="gaia_is_not_real">Gaia не Ñ–Ñнує</string>
92 <string name="copied_to_clipboard">Скопійовано в буфер обміну</string> 89 <string name="copied_to_clipboard">Скопійовано в буфер обміну</string>
@@ -113,42 +110,20 @@
113 <string name="our_eternal_gratitude">Ðаша неÑкінченна вдÑчніÑть</string> 110 <string name="our_eternal_gratitude">Ðаша неÑкінченна вдÑчніÑть</string>
114 <string name="are_you_interested">Ви зацікавлені?</string> 111 <string name="are_you_interested">Ви зацікавлені?</string>
115 112
116 <!-- General settings strings -->
117 <string name="frame_limit_enable">Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾Ñті</string>
118 <string name="frame_limit_enable_description">Якщо цю функцію ввімкнено, швидкіÑть емулÑції буде обмежена зазначеним відÑотком від нормальної швидкоÑті.</string>
119 <string name="frame_limit_slider">ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñотка швидкоÑті</string> 113 <string name="frame_limit_slider">ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ñотка швидкоÑті</string>
120 <string name="frame_limit_slider_description">Вказує відÑоток Ð´Ð»Ñ Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾Ñті емулÑції. При значенні за замовчуваннÑм 100% емулÑÑ†Ñ–Ñ Ð±ÑƒÐ´Ðµ обмежена нормальною швидкіÑтю. Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð²Ð¸Ñ‰Ðµ або нижче збільшуватимуть або зменшуватимуть Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾Ñті.</string>
121 <string name="cpu_accuracy">ТочніÑть ЦП</string> 114 <string name="cpu_accuracy">ТочніÑть ЦП</string>
122
123 <!-- System settings strings -->
124 <string name="use_docked_mode">Режим док-Ñтанції</string>
125 <string name="use_docked_mode_description">ЕмулÑÑ†Ñ–Ñ Ñ€ÐµÐ¶Ð¸Ð¼Ñƒ док-Ñтанції, що збільшує роздільну здатніÑть за рахунок Ð·Ð½Ð¸Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ð¸Ð²Ð½Ð¾Ñті.</string>
126 <string name="emulated_region">Емульований регіон</string> 115 <string name="emulated_region">Емульований регіон</string>
127 <string name="emulated_language">Емульована мова</string> 116 <string name="emulated_language">Емульована мова</string>
128 <string name="select_rtc_date">Оберіть дату RTC</string> 117 <string name="use_custom_rtc">КориÑтувацький RTC</string>
129 <string name="select_rtc_time">Оберіть Ñ‡Ð°Ñ RTC</string>
130 <string name="use_custom_rtc">Увімкнути кориÑтувацький RTC</string>
131 <string name="use_custom_rtc_description">Цей параметр дає змогу вÑтановити кориÑтувацький годинник реального чаÑу окремо від поточного ÑиÑтемного чаÑу</string>
132 <string name="set_custom_rtc">Ð’Ñтановити кориÑтувацький RTC</string>
133
134 <!-- Graphics settings strings --> 118 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">Рівень точноÑті</string> 119 <string name="renderer_accuracy">Рівень точноÑті</string>
137 <string name="renderer_resolution">Роздільна здатніÑть</string>
138 <string name="renderer_vsync">Режим верт. Ñинхронізації</string> 120 <string name="renderer_vsync">Режим верт. Ñинхронізації</string>
139 <string name="renderer_aspect_ratio">Ð¡Ð¿Ñ–Ð²Ð²Ñ–Ð´Ð½Ð¾ÑˆÐµÐ½Ð½Ñ Ñторін</string>
140 <string name="renderer_scaling_filter">Фільтр адаптації вікна</string>
141 <string name="renderer_anti_aliasing">Метод згладжуваннÑ</string>
142 <string name="renderer_force_max_clock">ПримуÑово змуÑити макÑимальну тактову чаÑтоту (тільки Ð´Ð»Ñ Adreno)</string> 121 <string name="renderer_force_max_clock">ПримуÑово змуÑити макÑимальну тактову чаÑтоту (тільки Ð´Ð»Ñ Adreno)</string>
143 <string name="renderer_force_max_clock_description">Змушує ГП працювати на макÑимально можливих тактових чаÑтотах (теплові Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ñе одно будуть заÑтоÑовуватиÑÑ).</string> 122 <string name="renderer_force_max_clock_description">Змушує ГП працювати на макÑимально можливих тактових чаÑтотах (теплові Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ñе одно будуть заÑтоÑовуватиÑÑ).</string>
144 <string name="renderer_asynchronous_shaders">ВикориÑтовувати аÑинхронні шейдери</string> 123 <string name="renderer_asynchronous_shaders">ВикориÑтовувати аÑинхронні шейдери</string>
145 <string name="renderer_asynchronous_shaders_description">Компілює шейдери аÑинхронно, що зменшує завиÑаннÑ, але може натоміÑть надати візуальні баги.</string> 124 <!-- Debug settings strings -->
146 <string name="renderer_debug">Увімкнути Ð½Ð°Ð»Ð°Ð³Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð³Ñ€Ð°Ñ„Ñ–ÐºÐ¸</string> 125 <string name="cpu">ЦП</string>
147 <string name="renderer_debug_description">Якщо увімкнено, графічний API переходить у повільніший режим налагодженнÑ</string> 126 <string name="renderer_api">API</string>
148 <string name="use_disk_shader_cache">ВикориÑтовувати кеш шейдерів на диÑку</string>
149 <string name="use_disk_shader_cache_description">Ð—Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ Ð·Ð°Ð²Ð¸Ñань завдÑки зберіганню та завантаженню згенерованих шейдерів на Ñховище.</string>
150
151 <!-- Audio settings strings -->
152 <string name="audio_volume">ГучніÑть</string> 127 <string name="audio_volume">ГучніÑть</string>
153 <string name="audio_volume_description">Вказує гучніÑть аудіовиходу.</string> 128 <string name="audio_volume_description">Вказує гучніÑть аудіовиходу.</string>
154 129
@@ -161,17 +136,20 @@
161 <string name="reset_setting_confirmation">Чи хочете ви повернути цей параметр до Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм?</string> 136 <string name="reset_setting_confirmation">Чи хочете ви повернути цей параметр до Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм?</string>
162 <string name="reset_to_default">Ð¡ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð´Ð¾ налаштувань за замовчуваннÑм</string> 137 <string name="reset_to_default">Ð¡ÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ð´Ð¾ налаштувань за замовчуваннÑм</string>
163 <string name="reset_all_settings">Скинути вÑÑ– налаштуваннÑ</string> 138 <string name="reset_all_settings">Скинути вÑÑ– налаштуваннÑ</string>
164 <string name="reset_all_settings_description">УÑÑ– додаткові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ Ñкинуто до Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð° замовчуваннÑм. Це неможливо ÑкаÑувати.</string>
165 <string name="settings_reset">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñкинуто</string> 139 <string name="settings_reset">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñкинуто</string>
166 <string name="close">Закрити</string> 140 <string name="close">Закрити</string>
167 <string name="learn_more">ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ</string> 141 <string name="learn_more">ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ</string>
168 142 <string name="auto">Ðвто</string>
143 <string name="string_null">Null</string>
144 <string name="string_import">Імпорт</string>
145 <string name="export">ЕкÑпорт</string>
169 <!-- GPU driver installation --> 146 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">Вибрати драйвер ГП</string> 147 <string name="select_gpu_driver">Вибрати драйвер ГП</string>
171 <string name="select_gpu_driver_title">Хочете замінити поточний драйвер ГП?</string> 148 <string name="select_gpu_driver_title">Хочете замінити поточний драйвер ГП?</string>
172 <string name="select_gpu_driver_install">Ð’Ñтановити</string> 149 <string name="select_gpu_driver_install">Ð’Ñтановити</string>
173 <string name="select_gpu_driver_default">За замовчуваннÑм</string> 150 <string name="select_gpu_driver_default">За замовчуваннÑм</string>
174 <string name="select_gpu_driver_use_default">ВикориÑтовуєтьÑÑ Ñтандартний драйвер ГП</string> 151 <string name="select_gpu_driver_use_default">ВикориÑтовуєтьÑÑ Ñтандартний драйвер ГП</string>
152 <string name="select_gpu_driver_error">Обрано неправильний драйвер, викориÑтовуєтьÑÑ Ñтандартний ÑиÑтемний!</string>
175 <string name="system_gpu_driver">СиÑтемний драйвер ГП</string> 153 <string name="system_gpu_driver">СиÑтемний драйвер ГП</string>
176 <string name="installing_driver">Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð°...</string> 154 <string name="installing_driver">Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ñ€Ð°Ð¹Ð²ÐµÑ€Ð°...</string>
177 155
@@ -182,40 +160,19 @@
182 <string name="preferences_graphics">Графіка</string> 160 <string name="preferences_graphics">Графіка</string>
183 <string name="preferences_audio">Ðудіо</string> 161 <string name="preferences_audio">Ðудіо</string>
184 <string name="preferences_theme">Тема і колір</string> 162 <string name="preferences_theme">Тема і колір</string>
163 <string name="preferences_debug">ÐалагодженнÑ</string>
185 164
186 <!-- ROM loading errors --> 165 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">Ваш ROM зашифрований</string> 166 <string name="loader_error_encrypted">Ваш ROM зашифрований</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[Будь лаÑка, дотримуйтеÑÑŒ інÑтрукцій, щоб пере-дампити ваші <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">ігрові картриджі</a> або <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">вÑтановлені ігри</a>.]]></string>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[Будь лаÑка, переконайтеÑÑ, що ваш файл <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> вÑтановлено, щоб ігри можна було розшифрувати.]]></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>
190 <string name="loader_error_video_core">СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ— відеоÑдра.</string> 168 <string name="loader_error_video_core">СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ— відеоÑдра.</string>
191 <string name="loader_error_video_core_description">Зазвичай це Ñпричинено неÑуміÑним драйвером ГП. Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувацького драйвера ГП може вирішити цю проблему.</string> 169 <string name="loader_error_video_core_description">Зазвичай це Ñпричинено неÑуміÑним драйвером ГП. Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувацького драйвера ГП може вирішити цю проблему.</string>
192 <string name="loader_error_invalid_format">Ðе вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити ROM</string> 170 <string name="loader_error_invalid_format">Ðе вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити ROM</string>
193 <string name="loader_error_file_not_found">Файл ROM не Ñ–Ñнує</string> 171 <string name="loader_error_file_not_found">Файл ROM не Ñ–Ñнує</string>
194 172
195 <!-- Emulation Menu -->
196 <string name="emulation_exit">Вихід з емулÑції</string>
197 <string name="emulation_done">Готово</string> 173 <string name="emulation_done">Готово</string>
198 <string name="emulation_fps_counter">Лічильник FPS</string>
199 <string name="emulation_toggle_controls">ÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ</string>
200 <string name="emulation_rel_stick_center">ВідноÑний центр Ñтіка</string>
201 <string name="emulation_dpad_slide">Слайд хреÑтовиною</string>
202 <string name="emulation_haptics">Тактильний зворотний зв\'Ñзок</string>
203 <string name="emulation_show_overlay">Показати оверлей</string>
204 <string name="emulation_toggle_all">Перемкнути вÑе</string>
205 <string name="emulation_control_adjust">Ðалаштувати оверлей</string>
206 <string name="emulation_control_scale">МаÑштаб</string> 174 <string name="emulation_control_scale">МаÑштаб</string>
207 <string name="emulation_control_opacity">ÐепрозоріÑть</string> 175 <string name="emulation_control_opacity">ÐепрозоріÑть</string>
208 <string name="emulation_touch_overlay_reset">Скинути оверлей</string>
209 <string name="emulation_touch_overlay_edit">Змінити оверлей</string>
210 <string name="emulation_pause">Пауза емулÑції</string>
211 <string name="emulation_unpause">Ð’Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»Ñції</string>
212 <string name="emulation_input_overlay">ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð²ÐµÑ€Ð»ÐµÑ</string>
213
214 <string name="load_settings">Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ...</string>
215
216 <!-- Software keyboard -->
217 <string name="software_keyboard">Віртуальна клавіатура</string>
218
219 <!-- Errors and warnings --> 176 <!-- Errors and warnings -->
220 <string name="abort_button">Перервати</string> 177 <string name="abort_button">Перервати</string>
221 <string name="continue_button">Продовжити</string> 178 <string name="continue_button">Продовжити</string>
@@ -226,7 +183,6 @@
226 <string name="fatal_error">Фатальна помилка</string> 183 <string name="fatal_error">Фатальна помилка</string>
227 <string name="fatal_error_message">СталаÑÑ Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð° помилка. Перевірте журнал Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾ÐºÐ»Ð°Ð´Ð½Ð¾Ñ— інформації.\nÐŸÑ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»Ñції може призвеÑти до збоїв Ñ– помилок.</string> 184 <string name="fatal_error_message">СталаÑÑ Ñ„Ð°Ñ‚Ð°Ð»ÑŒÐ½Ð° помилка. Перевірте журнал Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾ÐºÐ»Ð°Ð´Ð½Ð¾Ñ— інформації.\nÐŸÑ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»Ñції може призвеÑти до збоїв Ñ– помилок.</string>
228 <string name="performance_warning">Ð’Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð½Ð°Ñ‡Ð½Ð¾ знизить продуктивніÑть емулÑції! Ð”Ð»Ñ Ð´Ð¾ÑÑÐ³Ð½ÐµÐ½Ð½Ñ Ð½Ð°Ð¹ÐºÑ€Ð°Ñ‰Ð¸Ñ… результатів рекомендуєтьÑÑ Ð·Ð°Ð»Ð¸ÑˆÐ¸Ñ‚Ð¸ це Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¸Ð¼.</string> 185 <string name="performance_warning">Ð’Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð½Ð°Ñ‡Ð½Ð¾ знизить продуктивніÑть емулÑції! Ð”Ð»Ñ Ð´Ð¾ÑÑÐ³Ð½ÐµÐ½Ð½Ñ Ð½Ð°Ð¹ÐºÑ€Ð°Ñ‰Ð¸Ñ… результатів рекомендуєтьÑÑ Ð·Ð°Ð»Ð¸ÑˆÐ¸Ñ‚Ð¸ це Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¸Ð¼.</string>
229
230 <!-- Region Names --> 186 <!-- Region Names -->
231 <string name="region_japan">ЯпоніÑ</string> 187 <string name="region_japan">ЯпоніÑ</string>
232 <string name="region_usa">СШÐ</string> 188 <string name="region_usa">СШÐ</string>
@@ -236,8 +192,7 @@
236 <string name="region_korea">КореÑ</string> 192 <string name="region_korea">КореÑ</string>
237 <string name="region_taiwan">Тайвань</string> 193 <string name="region_taiwan">Тайвань</string>
238 194
239 <!-- Language Names --> 195 <string name="memory_gigabyte">GB</string>
240
241 <!-- Renderer APIs --> 196 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 197 <string name="renderer_vulkan">Vulkan</string>
243 <string name="renderer_none">Вимкнено</string> 198 <string name="renderer_none">Вимкнено</string>
@@ -274,22 +229,18 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 229 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 230 <string name="anti_aliasing_smaa">SMAA</string>
276 231
232 <string name="screen_layout_auto">Ðвто</string>
233
277 <!-- Aspect Ratios --> 234 <!-- Aspect Ratios -->
278 <string name="ratio_default">За замовчуваннÑм (16:9)</string> 235 <string name="ratio_default">За замовчуваннÑм (16:9)</string>
279 <string name="ratio_force_four_three">ЗмуÑити 4:3</string> 236 <string name="ratio_force_four_three">ЗмуÑити 4:3</string>
280 <string name="ratio_force_twenty_one_nine">ЗмуÑити 21:9</string> 237 <string name="ratio_force_twenty_one_nine">ЗмуÑити 21:9</string>
281 <string name="ratio_force_sixteen_ten">ЗмуÑити 16:10</string> 238 <string name="ratio_force_sixteen_ten">ЗмуÑити 16:10</string>
282 <string name="ratio_stretch">РозтÑгнути до вікна</string>
283
284 <!-- CPU Accuracy --> 239 <!-- CPU Accuracy -->
285 <string name="cpu_accuracy_accurate">Точно</string> 240 <string name="cpu_accuracy_accurate">Точно</string>
286 <string name="cpu_accuracy_unsafe">Ðебезпечно</string> 241 <string name="cpu_accuracy_unsafe">Ðебезпечно</string>
287 <string name="cpu_accuracy_paranoid">Параноїк (повільно)</string> 242 <string name="cpu_accuracy_paranoid">Параноїк (повільно)</string>
288 243
289 <!-- Gamepad Buttons -->
290 <string name="gamepad_d_pad">Кнопки напрÑмків</string>
291 <string name="gamepad_left_stick">Лівий міні-джойÑтик</string>
292 <string name="gamepad_right_stick">Правий міні-джойÑтик</string>
293 <string name="gamepad_home">Home</string> 244 <string name="gamepad_home">Home</string>
294 <string name="gamepad_screenshot">Знімок екрану</string> 245 <string name="gamepad_screenshot">Знімок екрану</string>
295 246
@@ -297,19 +248,16 @@
297 <string name="preparing_shaders">Підготовка шейдерів</string> 248 <string name="preparing_shaders">Підготовка шейдерів</string>
298 <string name="building_shaders">Побудова шейдерів</string> 249 <string name="building_shaders">Побудова шейдерів</string>
299 250
300 <!-- Theme options -->
301 <string name="change_app_theme">Змінити тему заÑтоÑунку</string>
302 <string name="theme_default">За замовчуваннÑм</string> 251 <string name="theme_default">За замовчуваннÑм</string>
303 <string name="theme_material_you">Material You</string> 252 <string name="theme_material_you">Material You</string>
304 253
305 <!-- Theme Modes -->
306 <string name="change_theme_mode">Змінити режим теми</string>
307 <string name="theme_mode_follow_system">СиÑтемна</string> 254 <string name="theme_mode_follow_system">СиÑтемна</string>
308 <string name="theme_mode_light">Світла</string> 255 <string name="theme_mode_light">Світла</string>
309 <string name="theme_mode_dark">Темна</string> 256 <string name="theme_mode_dark">Темна</string>
310 257
311 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">ВикориÑтовувати чорне тло</string>
313 <string name="use_black_backgrounds_description">У разі викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— теми заÑтоÑовуйте чорне тло.</string> 258 <string name="use_black_backgrounds_description">У разі викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¼Ð½Ð¾Ñ— теми заÑтоÑовуйте чорне тло.</string>
314 259
315</resources> 260 <string name="mute">Вимкнути звук</string>
261 <string name="unmute">Увімкнути звук</string>
262
263 </resources>
diff --git a/src/android/app/src/main/res/values-vi/strings.xml b/src/android/app/src/main/res/values-vi/strings.xml
new file mode 100644
index 000000000..f977db3a2
--- /dev/null
+++ b/src/android/app/src/main/res/values-vi/strings.xml
@@ -0,0 +1,340 @@
1<?xml version="1.0" encoding="utf-8"?>
2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3
4 <string name="app_disclaimer">Phần má»m này sẽ chạy các game cho máy chÆ¡i game Nintendo Switch. Không có title games hoặc keys được bao gồm.&lt;br /&gt;&lt;br /&gt;Trước khi bạn bắt đầu, hãy tìm tập tin <![CDATA[<b> prod.keys </b>]]> trên bá»™ nhá»› thiết bị cá»§a bạn.&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Tìm hiểu thêm</a>]]></string>
5 <string name="emulation_notification_channel_name">Giả lập đang chạy</string>
6 <string name="emulation_notification_channel_description">Hiển thị thông báo liên tục khi giả lập đang chạy.</string>
7 <string name="emulation_notification_running">yuzu đang chạy</string>
8 <string name="notice_notification_channel_name">Thông báo và lỗi</string>
9 <string name="notice_notification_channel_description">Hiển thị thông báo khi có sự cố xảy ra.</string>
10 <string name="notification_permission_not_granted">Ứng dụng không được cấp quyá»n thông báo!</string>
11
12 <!-- Setup strings -->
13 <string name="welcome">Chào mừng!</string>
14 <string name="welcome_description">Tìm hiểu cách cài đặt &lt;b>yuzu&lt;/b> và bắt đầu giả lập.</string>
15 <string name="get_started">Bắt đầu</string>
16 <string name="keys">Keys</string>
17 <string name="keys_description">Chá»n tệp &lt;b>prod.keys&lt;/b> cá»§a bạn bằng nút bên dưới.</string>
18 <string name="select_keys">Chá»n Keys</string>
19 <string name="games">Game</string>
20 <string name="games_description">Chá»n thư mục &lt;b>Game&lt;/b> cá»§a bạn bằng nút bên dưới.</string>
21 <string name="done">Hoàn thành</string>
22 <string name="done_description">Tất cả đã hoàn tất.\nHãy tận hưởng các game của bạn!</string>
23 <string name="text_continue">Tiếp tục</string>
24 <string name="next">Tiếp theo</string>
25 <string name="back">Trở lại</string>
26 <string name="add_games">Thêm Game</string>
27 <string name="add_games_description">Chá»n thư mục game cá»§a bạn</string>
28 <!-- Home strings -->
29 <string name="home_games">Game</string>
30 <string name="home_search">Tìm kiếm</string>
31 <string name="home_settings">Cài đặt</string>
32 <string name="empty_gamelist">Không tìm thấy tập tin hoặc chưa có thư mục game nào được chá»n.</string>
33 <string name="search_and_filter_games">Tìm và lá»c game</string>
34 <string name="select_games_folder">Chá»n thư mục game</string>
35 <string name="select_games_folder_description">Cho phép yuzu thêm vào danh sách game</string>
36 <string name="add_games_warning">Bá» qua việc lá»±a chá»n thư mục game?</string>
37 <string name="add_games_warning_description">Game sẽ không hiển thị trong danh sách nếu má»™t thư mục không được chá»n.</string>
38 <string name="add_games_warning_help">https://yuzu-emu.org/help/quickstart/#dumping-games</string>
39 <string name="home_search_games">Tìm kiếm game</string>
40 <string name="games_dir_selected">Thư mục game đã được chá»n</string>
41 <string name="install_prod_keys">Cài đặt prod.keys</string>
42 <string name="install_prod_keys_description">Yêu cầu để giải mã các game bán lẻ</string>
43 <string name="install_prod_keys_warning">BỠqua việc thêm keys?</string>
44 <string name="install_prod_keys_warning_description">Cần có keys hợp lệ để giả lập các game bán lẻ. Chỉ có các ứng dụng homebrew có thể vận hành nếu bạn tiếp tục.</string>
45 <string name="install_prod_keys_warning_help">https://yuzu-emu.org/help/quickstart/#guide-introduction</string>
46 <string name="notifications">Thông báo</string>
47 <string name="notifications_description">Cấp quyá»n thông báo bằng nút bên dưới.</string>
48 <string name="give_permission">Cấp quyá»n</string>
49 <string name="notification_warning">Bá» qua việc cấp quyá»n thông báo?</string>
50 <string name="notification_warning_description">yuzu sẽ không thể gá»­i những thông báo quan trá»ng đến bạn.</string>
51 <string name="permission_denied">Äã từ chối cấp quyá»n</string>
52 <string name="permission_denied_description">Bạn từ chối cấp quyá»n này quá nhiá»u lần và giá» bạn phải cấp quyá»n thá»§ công trong cài đặt máy.</string>
53 <string name="about">Thông tin</string>
54 <string name="about_description">Phiên bản, đóng góp và những thứ khác</string>
55 <string name="warning_help">Trợ giúp</string>
56 <string name="warning_skip">Bá» qua</string>
57 <string name="warning_cancel">Há»§y bá»</string>
58 <string name="install_amiibo_keys">Cài đặt keys Amiibo</string>
59 <string name="install_amiibo_keys_description">Cần thiết để dùng Amiibo trong game</string>
60 <string name="invalid_keys_file">Tệp keys không hợp lệ đã được chá»n</string>
61 <string name="install_keys_success">Cài đặt keys thành công</string>
62 <string name="reading_keys_failure">Lá»—i Ä‘á»c keys mã hóa</string>
63 <string name="install_prod_keys_failure_extension_description">Xác minh rằng tệp keys của bạn có đuôi .keys và thử lại.</string>
64 <string name="install_amiibo_keys_failure_extension_description">Xác minh rằng tệp keys của bạn có đuôi .bin và thử lại.</string>
65 <string name="invalid_keys_error">Keys mã hoá không hợp lệ</string>
66 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
67 <string name="install_keys_failure_description">Tệp đã chá»n sai hoặc há»ng. Vui lòng trích xuất lại keys cá»§a bạn.</string>
68 <string name="install_gpu_driver">Cài đặt driver GPU</string>
69 <string name="install_gpu_driver_description">Cài đặt driver thay thế để có thể có hiệu suất tốt và chính xác hơn</string>
70 <string name="advanced_settings">Cài đặt nâng cao</string>
71 <string name="settings_description">Cấu hình cài đặt giả lập</string>
72 <string name="search_recently_played">Äã chÆ¡i gần đây</string>
73 <string name="search_recently_added">Äã thêm gần đây</string>
74 <string name="search_retail">Bán lẻ</string>
75 <string name="search_homebrew">Homebrew</string>
76 <string name="open_user_folder">Mở thư mục yuzu</string>
77 <string name="open_user_folder_description">Quản lý tệp nội bộ của yuzu</string>
78 <string name="theme_and_color_description">Thay đổi giao diện ứng dụng</string>
79 <string name="no_file_manager">Không tìm thấy trình quản lý tập tin</string>
80 <string name="notification_no_directory_link">Không thể mở thư mục yuzu</string>
81 <string name="notification_no_directory_link_description">Vui lòng xác định thư mục ngưá»i dùng vá»›i bảng Ä‘iá»u khiển bên cá»§a trình quản lý tệp thá»§ công.</string>
82 <string name="manage_save_data">Quản lý dữ liệu save</string>
83 <string name="manage_save_data_description">Äã tìm thấy dữ liệu save. Vui lòng chá»n má»™t tuỳ chá»n bên dưới.</string>
84 <string name="import_export_saves_description">Nhập hoặc xuất tệp save</string>
85 <string name="save_file_imported_success">Nhập thành công</string>
86 <string name="save_file_invalid_zip_structure">Cấu trúc thư mục save không hợp lệ</string>
87 <string name="save_file_invalid_zip_structure_description">Tên thư mục con đầu tiên phải là ID title của game.</string>
88 <string name="import_saves">Nhập</string>
89 <string name="export_saves">Xuất</string>
90 <string name="install_firmware">Cài đặt firmware</string>
91 <string name="install_firmware_description">Firmware phải được đặt trong một tập tin nén ZIP và cần thiết để khởi chạy một số game</string>
92 <string name="firmware_installing">Äang cài đặt firmware</string>
93 <string name="firmware_installed_success">Cài đặt firmware thành công</string>
94 <string name="firmware_installed_failure">Cài đặt firmware thất bại</string>
95 <string name="share_log">Chia sẻ nhật ký gỡ lỗi</string>
96 <string name="share_log_description">Chia sẻ tập tin nhật ký cá»§a yuzu để gỡ lá»—i vấn Ä‘á»</string>
97 <string name="share_log_missing">Không tìm thấy tập tin nhật ký</string>
98 <string name="install_game_content">Cài đặt nội dung game</string>
99 <string name="install_game_content_description">Cài đặt cập nhật game hoặc DLC</string>
100 <string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
101 <!-- About screen strings -->
102 <string name="gaia_is_not_real">Gaia không có thật</string>
103 <string name="copied_to_clipboard">Äã sao chép vào bá»™ nhá»› tạm</string>
104 <string name="about_app_description">Một giả lập Switch mã nguồn mở</string>
105 <string name="contributors">Ngưá»i đóng góp</string>
106 <string name="contributors_description">ÄÆ°á»£c làm vá»›i \u2764 từ nhóm yuzu</string>
107 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
108 <string name="licenses_description">Các dá»± án làm cho yuzu trên Android trở thành Ä‘iá»u có thể</string>
109 <string name="build">Dá»±ng</string>
110 <string name="support_link">https://discord.gg/u77vRWY</string>
111 <string name="website_link">https://yuzu-emu.org/</string>
112 <string name="github_link">https://github.com/yuzu-emu</string>
113
114 <!-- Early access upgrade strings -->
115 <string name="early_access">Early Access</string>
116 <string name="get_early_access">Tải Early Access</string>
117 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
118 <string name="get_early_access_description">Các tính năng tiên tiến, truy cập sá»›m các bản cập nhật và nhiá»u hÆ¡n nữa</string>
119 <string name="early_access_benefits">Lợi ích của Early Access</string>
120 <string name="cutting_edge_features">Tính năng tiên tiến</string>
121 <string name="early_access_updates">Truy cập sớm các bản cập nhật</string>
122 <string name="no_manual_installation">Không có cài đặt thủ công</string>
123 <string name="prioritized_support">Ưu tiên hỗ trợ</string>
124 <string name="helping_game_preservation">Hỗ trợ bảo tồn game</string>
125 <string name="our_eternal_gratitude">Sự biết ơn vô hạn của chúng tôi</string>
126 <string name="are_you_interested">Bạn có thấy hứng thú không?</string>
127
128 <!-- General settings strings -->
129 <string name="frame_limit_enable">Giới hạn tốc độ</string>
130 <string name="frame_limit_enable_description">Giá»›i hạn tốc độ giả lập ở má»™t phần trăm cụ thể cá»§a tốc độ bình thưá»ng.</string>
131 <string name="frame_limit_slider">Giới hạn phần trăm tốc độ</string>
132 <string name="frame_limit_slider_description">Xác định phần trăm để giá»›i hạn tốc độ giả lập. 100% là tốc độ bình thưá»ng. Giá trị cao hÆ¡n hoặc thấp hÆ¡n sẽ tăng hoặc giảm giá»›i hạn tốc độ.</string>
133 <string name="cpu_accuracy">Äá»™ chính xác CPU</string>
134 <!-- System settings strings -->
135 <string name="use_docked_mode">Chế độ docked</string>
136 <string name="use_docked_mode_description">Tăng độ phân giải, giảm hiệu suất. Chế độ handheld được sử dụng khi tắt, giảm độ phân giải và tăng hiệu suất.</string>
137 <string name="emulated_region">Khu vực giả lập</string>
138 <string name="emulated_language">Ngôn ngữ giả lập</string>
139 <string name="select_rtc_date">Chá»n ngày RTC</string>
140 <string name="select_rtc_time">Chá»n giá» RTC</string>
141 <string name="use_custom_rtc">RTC tuỳ chỉnh</string>
142 <string name="use_custom_rtc_description">Cho phép bạn thiết lập má»™t đồng hồ thá»i gian thá»±c tùy chỉnh riêng biệt so vá»›i thá»i gian hệ thống hiện tại.</string>
143 <string name="set_custom_rtc">Thiết lập RTC tùy chỉnh</string>
144
145 <!-- Graphics settings strings -->
146 <string name="renderer_accuracy">Mức độ chính xác</string>
147 <string name="renderer_resolution">Äá»™ phân giải (Handheld/Docked)</string>
148 <string name="renderer_vsync">Chế độ VSync</string>
149 <string name="renderer_aspect_ratio">Tỉ lệ khung hình</string>
150 <string name="renderer_scaling_filter">Bá»™ lá»c Ä‘iá»u chỉnh cá»­a sổ</string>
151 <string name="renderer_anti_aliasing">Phương pháp khử răng cưa</string>
152 <string name="renderer_force_max_clock">Buộc chạy ở xung nhịp tối đa (chỉ cho Adreno)</string>
153 <string name="renderer_force_max_clock_description">Buộc GPU hoạt động ở xung nhịp tối đa có thể (ràng buộc nhiệt độ vẫn sẽ được áp dụng).</string>
154 <string name="renderer_asynchronous_shaders">Dùng các shader bất đồng bộ</string>
155 <string name="renderer_asynchronous_shaders_description">Biên dịch các shader bất đồng bộ, giảm tình trạng giật lag nhưng có thể gây ra các lỗi.</string>
156 <string name="renderer_reactive_flushing">Dùng xả tương ứng</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>
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 -->
162 <string name="cpu">CPU</string>
163 <string name="renderer_api">API</string>
164 <string name="renderer_debug">Gỡ lỗi đồ hoạ</string>
165 <string name="renderer_debug_description">Äặt API đồ há»a vào chế độ gỡ lá»—i chậm.</string>
166 <string name="audio_volume">Âm lượng</string>
167 <string name="audio_volume_description">Xác định âm lượng của đầu ra âm thanh.</string>
168
169 <!-- Miscellaneous -->
170 <string name="slider_default">Mặc định</string>
171 <string name="ini_saved">Cài đặt đã lưu</string>
172 <string name="gameid_saved">Cài đặt đã lưu cho %1$s</string>
173 <string name="error_saving">Lỗi khi lưu %1$s.ini: %2$s</string>
174 <string name="loading">Äang tải...</string>
175 <string name="reset_setting_confirmation">Bạn có muốn đặt lại cài đặt này vỠgiá trị mặc định không?</string>
176 <string name="reset_to_default">Äặt lại vá» mặc định</string>
177 <string name="reset_all_settings">Bạn có muốn đặt lại tất cả các cài đặt vỠgiá trị mặc định không?</string>
178 <string name="reset_all_settings_description">Tất cả các cài đặt nâng cao sẽ được đặt lại vá» cấu hình mặc định. Äiá»u này không thể hoàn tác.</string>
179 <string name="settings_reset">Cài đặt đã được đặt lại</string>
180 <string name="close">Äóng</string>
181 <string name="learn_more">Tìm hiểu thêm</string>
182 <string name="auto">Tự động</string>
183 <string name="submit">Gá»­i</string>
184 <string name="string_null">Null</string>
185 <string name="string_import">Nhập</string>
186 <string name="export">Xuất</string>
187 <!-- GPU driver installation -->
188 <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>
190 <string name="select_gpu_driver_install">Cài đặt</string>
191 <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>
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>
195 <string name="installing_driver">Äang cài đặt driver...</string>
196
197 <!-- Preferences Screen -->
198 <string name="preferences_settings">Cài đặt</string>
199 <string name="preferences_general">Chung</string>
200 <string name="preferences_system">Hệ thống</string>
201 <string name="preferences_graphics">Äồ hoạ</string>
202 <string name="preferences_audio">Âm thanh</string>
203 <string name="preferences_theme">Chủ đỠvà màu sắc</string>
204 <string name="preferences_debug">Gỡ lỗi</string>
205
206 <!-- ROM loading errors -->
207 <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>
209 <string name="loader_error_video_core">Äã xảy ra lá»—i khi khởi tạo lõi video</string>
210 <string name="loader_error_video_core_description">Việc này thưá»ng do driver GPU không tương thích. Cài đặt má»™t driver GPU tùy chỉnh có thể giải quyết vấn đỠnày.</string>
211 <string name="loader_error_invalid_format">Không thể nạp ROM</string>
212 <string name="loader_error_file_not_found">Tệp ROM không tồn tại</string>
213
214 <!-- Emulation Menu -->
215 <string name="emulation_exit">Thoát giả lập</string>
216 <string name="emulation_done">Hoàn thành</string>
217 <string name="emulation_fps_counter">Bộ đếm FPS</string>
218 <string name="emulation_toggle_controls">Chuyển đổi Ä‘iá»u khiển</string>
219 <string name="emulation_rel_stick_center">Trung tâm nút cần xoay tương đối</string>
220 <string name="emulation_dpad_slide">Trượt D-pad</string>
221 <string name="emulation_haptics">Chạm haptics</string>
222 <string name="emulation_show_overlay">Hiện lớp phủ</string>
223 <string name="emulation_toggle_all">Chuyển đổi tất cả</string>
224 <string name="emulation_control_adjust">Äiá»u chỉnh lá»›p phá»§</string>
225 <string name="emulation_control_scale">Tỉ lệ thu phóng</string>
226 <string name="emulation_control_opacity">Äá»™ má»</string>
227 <string name="emulation_touch_overlay_reset">Äặt lại lá»›p phá»§</string>
228 <string name="emulation_touch_overlay_edit">Chỉnh sửa lớp phủ</string>
229 <string name="emulation_pause">Tạm đừng giả lập</string>
230 <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>
232
233 <string name="load_settings">Äang tải cài đặt...</string>
234
235 <!-- Software keyboard -->
236 <string name="software_keyboard">Bàn phím má»m</string>
237
238 <!-- Errors and warnings -->
239 <string name="abort_button">Há»§y bá»</string>
240 <string name="continue_button">Tiếp tục</string>
241 <string name="system_archive_not_found">Không tìm thấy bản lưu trữ của hệ thống</string>
242 <string name="system_archive_not_found_message">%s bị thiếu. Vui lòng trích xuất các bản lưu trữ hệ thống của bạn.\nNếu chạy tiếp giả lập có thể bị crash và lỗi.</string>
243 <string name="system_archive_general">Một bản lưu trữ của hệ thống</string>
244 <string name="save_load_error">Lỗi Lưu/Tải</string>
245 <string name="fatal_error">Lá»—i nghiêm trá»ng</string>
246 <string name="fatal_error_message">Äã xảy ra lá»—i nghiêm trá»ng. Kiểm tra nhật ký để biết thêm chi tiết.\nNếu chạy tiếp giả lập có thể bị crash và lá»—i.</string>
247 <string name="performance_warning">Tắt cài đặt này sẽ làm giảm đáng kể hiệu suất giả lập! Äể có trải nghiệm tốt nhất, bạn nên bật cài đặt này.</string>
248 <!-- Region Names -->
249 <string name="region_japan">Nhật Bản</string>
250 <string name="region_usa">Hoa Kỳ</string>
251 <string name="region_europe">Châu Âu</string>
252 <string name="region_australia">Úc</string>
253 <string name="region_china">Trung Quốc</string>
254 <string name="region_korea">Hàn Quốc</string>
255 <string name="region_taiwan">Äài Loan</string>
256
257 <string name="memory_gigabyte">GB</string>
258 <!-- Renderer APIs -->
259 <string name="renderer_vulkan">Vulkan</string>
260 <string name="renderer_none">Không có</string>
261
262 <!-- Renderer Accuracy -->
263 <string name="renderer_accuracy_normal">Bình thưá»ng</string>
264 <string name="renderer_accuracy_high">Cao</string>
265 <string name="renderer_accuracy_extreme">Cực đại (Chậm)</string>
266
267 <!-- Resolutions -->
268 <string name="resolution_half">0.5X (360p/540p)</string>
269 <string name="resolution_three_quarter">0.75X (540p/810p)</string>
270 <string name="resolution_one">1X (720p/1080p)</string>
271 <string name="resolution_two">2X (1440p/2160p) (Chậm)</string>
272 <string name="resolution_three">3X (2160p/3240p) (Chậm)</string>
273 <string name="resolution_four">4X (2880p/4320p) (Chậm)</string>
274
275 <!-- Renderer VSync -->
276 <string name="renderer_vsync_immediate">Immediate (Tắt)</string>
277 <string name="renderer_vsync_mailbox">Mailbox</string>
278 <string name="renderer_vsync_fifo">FIFO (Bật)</string>
279 <string name="renderer_vsync_fifo_relaxed">FIFO Relaxed</string>
280
281 <!-- Scaling Filters -->
282 <string name="scaling_filter_nearest_neighbor">Nearest Neighbor</string>
283 <string name="scaling_filter_bilinear">Bilinear</string>
284 <string name="scaling_filter_bicubic">Bicubic</string>
285 <string name="scaling_filter_gaussian">Gaussian</string>
286 <string name="scaling_filter_scale_force">ScaleForce</string>
287 <string name="scaling_filter_fsr">AMD FidelityFXâ„¢ Super Resolution</string>
288
289 <!-- Anti-Aliasing -->
290 <string name="anti_aliasing_none">Không có</string>
291 <string name="anti_aliasing_fxaa">FXAA</string>
292 <string name="anti_aliasing_smaa">SMAA</string>
293
294 <string name="screen_layout_auto">Tự động</string>
295
296 <!-- Aspect Ratios -->
297 <string name="ratio_default">Mặc định (16:9)</string>
298 <string name="ratio_force_four_three">Dùng 4:3</string>
299 <string name="ratio_force_twenty_one_nine">Dùng 21:9</string>
300 <string name="ratio_force_sixteen_ten">Dùng 16:10</string>
301 <string name="ratio_stretch">Mở rộng đến cửa sổ</string>
302
303 <!-- CPU Accuracy -->
304 <string name="cpu_accuracy_accurate">Chính xác</string>
305 <string name="cpu_accuracy_unsafe">Không an toàn</string>
306 <string name="cpu_accuracy_paranoid">Paranoid (Chậm)</string>
307
308 <!-- Gamepad Buttons -->
309 <string name="gamepad_d_pad">D-pad</string>
310 <string name="gamepad_left_stick">Cần trái</string>
311 <string name="gamepad_right_stick">Cần phải</string>
312 <string name="gamepad_home">Home</string>
313 <string name="gamepad_screenshot">Ảnh chụp màn hình</string>
314
315 <!-- Disk shader cache -->
316 <string name="preparing_shaders">Äang chuẩn bị shader</string>
317 <string name="building_shaders">Äang đựng shader</string>
318
319 <!-- Theme options -->
320 <string name="change_app_theme">Thay đổi chủ đỠứng dụng</string>
321 <string name="theme_default">Mặc định</string>
322 <string name="theme_material_you">Material You</string>
323
324 <!-- Theme Modes -->
325 <string name="change_theme_mode">Thay đổi chá»§ Ä‘á»</string>
326 <string name="theme_mode_follow_system">Theo hệ thống</string>
327 <string name="theme_mode_light">Sáng</string>
328 <string name="theme_mode_dark">Tối</string>
329
330 <!-- Black backgrounds theme -->
331 <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>
333
334 <string name="mute">Tắt tiếng</string>
335 <string name="unmute">Bật tiếng</string>
336
337 <!-- Licenses screen strings -->
338 <string name="licenses">Giấy phép</string>
339 <string name="license_fidelityfx_fsr_description">Upscaling chất lượng cao từ AMD</string>
340 </resources>
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 c0e885751..13455564f 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
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">此软件å¯ä»¥è¿è¡Œ Nintendo Switch 游æˆï¼Œä½†ä¸åŒ…å«ä»»ä½•游æˆå’Œå¯†é’¥æ–‡ä»¶ã€‚&lt;br /&gt;&lt;br /&gt;在开始å‰ï¼Œè¯·æ‰¾åˆ°æ”¾ç½®äºŽè®¾å¤‡å­˜å‚¨ä¸­çš„ <![CDATA[<b> prod.keys </b>]]> 文件。&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">了解更多</a>]]></string> 4 <string name="app_disclaimer">此软件å¯ä»¥è¿è¡Œ Nintendo Switch 游æˆï¼Œä½†ä¸åŒ…å«ä»»ä½•游æˆå’Œå¯†é’¥æ–‡ä»¶ã€‚&lt;br /&gt;&lt;br /&gt;在开始å‰ï¼Œè¯·æ‰¾åˆ°æ”¾ç½®äºŽè®¾å¤‡å­˜å‚¨ä¸­çš„ <![CDATA[<b> prod.keys </b>]]> 文件。&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">了解更多</a>]]></string>
5 <string name="emulation_notification_channel_name">正在进行模拟</string> 5 <string name="emulation_notification_channel_name">正在进行模拟</string>
@@ -17,7 +17,7 @@
17 <string name="keys_description">使用下方的按钮æ¥é€‰æ‹©ä½ çš„ &lt;b>prod.keys&lt;/b> 文件。</string> 17 <string name="keys_description">使用下方的按钮æ¥é€‰æ‹©ä½ çš„ &lt;b>prod.keys&lt;/b> 文件。</string>
18 <string name="select_keys">选择密钥文件</string> 18 <string name="select_keys">选择密钥文件</string>
19 <string name="games">游æˆ</string> 19 <string name="games">游æˆ</string>
20 <string name="games_description">使用下方的按钮选择你的 &lt;b>游æˆ&lt;/b> 文件夹。</string> 20 <string name="games_description">使用下方的按钮选择你的&lt;b>游æˆ&lt;/b>文件夹。</string>
21 <string name="done">完æˆ</string> 21 <string name="done">完æˆ</string>
22 <string name="done_description">你完æˆäº†å…¨éƒ¨è®¾ç½®ã€‚\n玩的开心ï¼</string> 22 <string name="done_description">你完æˆäº†å…¨éƒ¨è®¾ç½®ã€‚\n玩的开心ï¼</string>
23 <string name="text_continue">ç»§ç»­</string> 23 <string name="text_continue">ç»§ç»­</string>
@@ -25,6 +25,7 @@
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>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">游æˆ</string> 31 <string name="home_games">游æˆ</string>
@@ -38,6 +39,7 @@
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>
42 <string name="search_settings">æœç´¢è®¾ç½®</string>
41 <string name="games_dir_selected">å·²é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹</string> 43 <string name="games_dir_selected">å·²é€‰æ‹©æ¸¸æˆæ–‡ä»¶å¤¹</string>
42 <string name="install_prod_keys">安装 prod.keys 文件</string> 44 <string name="install_prod_keys">安装 prod.keys 文件</string>
43 <string name="install_prod_keys_description">需è¦å¯†é’¥æ–‡ä»¶æ¥è§£å¯†æ¸¸æˆ</string> 45 <string name="install_prod_keys_description">需è¦å¯†é’¥æ–‡ä»¶æ¥è§£å¯†æ¸¸æˆ</string>
@@ -61,12 +63,15 @@
61 <string name="invalid_keys_file">选择的密钥文件无效</string> 63 <string name="invalid_keys_file">选择的密钥文件无效</string>
62 <string name="install_keys_success">密钥文件已æˆåŠŸå®‰è£…</string> 64 <string name="install_keys_success">密钥文件已æˆåŠŸå®‰è£…</string>
63 <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>
64 <string name="invalid_keys_error">无效的加密密钥</string> 68 <string name="invalid_keys_error">无效的加密密钥</string>
65 <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>
66 <string name="install_keys_failure_description">é€‰æ‹©çš„å¯†é’¥æ–‡ä»¶ä¸æ­£ç¡®æˆ–å·²æŸåã€‚è¯·é‡æ–°è½¬å‚¨å¯†é’¥æ–‡ä»¶ã€‚</string> 70 <string name="install_keys_failure_description">é€‰æ‹©çš„å¯†é’¥æ–‡ä»¶ä¸æ­£ç¡®æˆ–å·²æŸåã€‚è¯·é‡æ–°è½¬å‚¨å¯†é’¥æ–‡ä»¶ã€‚</string>
67 <string name="install_gpu_driver">安装 GPU 驱动</string> 71 <string name="install_gpu_driver">安装 GPU 驱动</string>
68 <string name="install_gpu_driver_description">安装替代的驱动程åºä»¥èŽ·å¾—æ›´å¥½çš„æ€§èƒ½å’Œç²¾åº¦</string> 72 <string name="install_gpu_driver_description">安装替代的驱动程åºä»¥èŽ·å¾—æ›´å¥½çš„æ€§èƒ½å’Œç²¾åº¦</string>
69 <string name="advanced_settings">高级选项</string> 73 <string name="advanced_settings">高级选项</string>
74 <string name="advanced_settings_game">高级选项: %1$s</string>
70 <string name="settings_description">更改模拟器设置</string> 75 <string name="settings_description">更改模拟器设置</string>
71 <string name="search_recently_played">最近游玩</string> 76 <string name="search_recently_played">最近游玩</string>
72 <string name="search_recently_added">最近添加</string> 77 <string name="search_recently_added">最近添加</string>
@@ -86,6 +91,33 @@
86 <string name="save_file_invalid_zip_structure_description">ç¬¬ä¸€ä¸ªå­æ–‡ä»¶å¤¹åç§°å¿…é¡»ä¸ºå½“å‰æ¸¸æˆçš„ ID。</string> 91 <string name="save_file_invalid_zip_structure_description">ç¬¬ä¸€ä¸ªå­æ–‡ä»¶å¤¹åç§°å¿…é¡»ä¸ºå½“å‰æ¸¸æˆçš„ ID。</string>
87 <string name="import_saves">导入</string> 92 <string name="import_saves">导入</string>
88 <string name="export_saves">导出</string> 93 <string name="export_saves">导出</string>
94 <string name="install_firmware">安装固件</string>
95 <string name="install_firmware_description">固件文件必须为 zip æ ¼å¼ï¼Œå¯åЍæŸäº›æ¸¸æˆæ—¶å¿…需</string>
96 <string name="firmware_installing">正在安装固件</string>
97 <string name="firmware_installed_success">固件已æˆåŠŸå®‰è£…</string>
98 <string name="firmware_installed_failure">固件安装失败</string>
99 <string name="firmware_installed_failure_description">请确ä¿å›ºä»¶ nca 文件ä½äºŽ zip 压缩包的根目录,然åŽé‡è¯•。</string>
100 <string name="share_log">分享调试日志</string>
101 <string name="share_log_description">分享 yuzu 日志文件以便调试</string>
102 <string name="share_log_missing">未找到日志文件</string>
103 <string name="install_game_content">安装游æˆé™„加内容</string>
104 <string name="install_game_content_description">å®‰è£…æ¸¸æˆæ›´æ–°åŠ DLC</string>
105 <string name="installing_game_content">安装中...</string>
106 <string name="install_game_content_failure">å‘ NAND 安装文件时失败</string>
107 <string name="install_game_content_failure_description">请确ä¿é™„加内容的有效性,并且 prod.keys 密钥文件已安装。</string>
108 <string name="install_game_content_failure_base">为é¿å…产生冲çªï¼Œæ­¤åŠŸèƒ½ä¸èƒ½ç”¨äºŽå®‰è£…æ¸¸æˆæœ¬ä½“。</string>
109 <string name="install_game_content_failure_file_extension">åªæœ‰ NSP 或 XCI æ ¼å¼çš„附加内容å¯ä»¥å®‰è£…ã€‚è¯·ç¡®ä¿æ‚¨çš„æ¸¸æˆé™„加内容是有效的。</string>
110 <string name="install_game_content_failed_count">%1$d 安装出错</string>
111 <string name="install_game_content_success">游æˆé™„加内容已æˆåŠŸå®‰è£…</string>
112 <string name="install_game_content_success_install">%1$d 安装æˆåŠŸ</string>
113 <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>
115 <string name="custom_driver_not_supported">䏿”¯æŒè‡ªå®šä¹‰é©±åЍ</string>
116 <string name="custom_driver_not_supported_description">æ­¤è®¾å¤‡ä¸æ”¯æŒè‡ªå®šä¹‰é©±åŠ¨ã€‚\n请之åŽå†è®¿é—®æ­¤é¡¹ï¼ŒæŸ¥çœ‹æ˜¯å¦å·²ä¸ºæ­¤è®¾å¤‡æ·»åŠ æ”¯æŒã€‚</string>
117 <string name="manage_yuzu_data">ç®¡ç† yuzu æ•°æ®</string>
118 <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string>
119 <string name="share_save_file">分享存档文件</string>
120 <string name="export_save_failed">导出存档文件失败</string>
89 121
90 <!-- About screen strings --> 122 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia ä¸çœŸå®ž</string> 123 <string name="gaia_is_not_real">Gaia ä¸çœŸå®ž</string>
@@ -94,14 +126,25 @@
94 <string name="contributors">贡献者</string> 126 <string name="contributors">贡献者</string>
95 <string name="contributors_description">使用æ¥è‡ª yuzu 团队的 \u2764 制作</string> 127 <string name="contributors_description">使用æ¥è‡ª yuzu 团队的 \u2764 制作</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">Android 版 yuzu 离ä¸å¼€è¿™äº›é¡¹ç›®çš„æ”¯æŒ</string>
97 <string name="build">构建版本</string> 130 <string name="build">构建版本</string>
131 <string name="user_data">用户数æ®</string>
132 <string name="user_data_description">导入/å¯¼å‡ºåº”ç”¨ç¨‹åºæ‰€æœ‰æ•°æ®ã€‚\n\nå¯¼å…¥ç”¨æˆ·æ•°æ®æ—¶ï¼Œå°†åˆ é™¤å½“剿‰€æœ‰çš„用户数æ®ï¼</string>
133 <string name="exporting_user_data">正在导出用户数æ®...</string>
134 <string name="importing_user_data">正在导入用户数æ®...</string>
135 <string name="import_user_data">导入用户数æ®</string>
136 <string name="invalid_yuzu_backup">无效的 yuzu 备份</string>
137 <string name="user_data_export_success">å¯¼å‡ºç”¨æˆ·æ•°æ®æˆåŠŸ</string>
138 <string name="user_data_import_success">å¯¼å…¥ç”¨æˆ·æ•°æ®æˆåŠŸ</string>
139 <string name="user_data_export_cancelled">已喿¶ˆå¯¼å‡ºæ•°æ®</string>
140 <string name="user_data_import_failed_description">请确ä¿ç”¨æˆ·æ•°æ®æ–‡ä»¶å¤¹ä½äºŽ zip 压缩包的根目录,并在 config/config.ini 路径中包å«é…置文件,然åŽé‡è¯•。</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 141 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 142 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 143 <string name="github_link">https://github.com/yuzu-emu</string>
101 144
102 <!-- Early access upgrade strings --> 145 <!-- Early access upgrade strings -->
103 <string name="early_access">抢先体验</string> 146 <string name="early_access">抢先体验</string>
104 <string name="get_early_access">å–得抢先体验</string> 147 <string name="get_early_access">èŽ·å–æŠ¢å…ˆä½“éªŒï¼</string>
105 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string> 148 <string name="play_store_link">https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea</string>
106 <string name="get_early_access_description">æœ€æ–°çš„åŠŸèƒ½ã€æŠ¢å…ˆæ›´æ–°ã€ä»¥åŠæ›´å¤š</string> 149 <string name="get_early_access_description">æœ€æ–°çš„åŠŸèƒ½ã€æŠ¢å…ˆæ›´æ–°ã€ä»¥åŠæ›´å¤š</string>
107 <string name="early_access_benefits">抢先体验的æƒç›Š</string> 150 <string name="early_access_benefits">抢先体验的æƒç›Š</string>
@@ -109,33 +152,34 @@
109 <string name="early_access_updates">抢先更新</string> 152 <string name="early_access_updates">抢先更新</string>
110 <string name="no_manual_installation">无需手动安装</string> 153 <string name="no_manual_installation">无需手动安装</string>
111 <string name="prioritized_support">优先支æŒ</string> 154 <string name="prioritized_support">优先支æŒ</string>
112 <string name="helping_game_preservation">帮助ä¿ç•™æ¸¸æˆ</string> 155 <string name="helping_game_preservation">帮助ä¿ç•™æ¸¸çŽ©åŽ†å²</string>
113 <string name="our_eternal_gratitude">我们真诚的感激</string> 156 <string name="our_eternal_gratitude">我们真诚的感激</string>
114 <string name="are_you_interested">您对此感兴趣å—?</string> 157 <string name="are_you_interested">您对此感兴趣å—?</string>
115 158
116 <!-- General settings strings --> 159 <!-- General settings strings -->
117 <string name="frame_limit_enable">å¯ç”¨è¿è¡Œé€Ÿåº¦é™åˆ¶</string> 160 <string name="frame_limit_enable">è¿è¡Œé€Ÿåº¦é™åˆ¶</string>
118 <string name="frame_limit_enable_description">å¯ç”¨åŽï¼Œæ¨¡æ‹Ÿé€Ÿåº¦å°†é™åˆ¶åœ¨æ­£å¸¸è¿è¡Œé€Ÿåº¦çš„æŒ‡å®šç™¾åˆ†æ¯”。</string> 161 <string name="frame_limit_enable_description">å°†è¿è¡Œé€Ÿåº¦é™åˆ¶ä¸ºæ­£å¸¸é€Ÿåº¦çš„æŒ‡å®šç™¾åˆ†æ¯”。</string>
119 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> 162 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string>
120 <string name="frame_limit_slider_description">指定é™åˆ¶æ¨¡æ‹Ÿé€Ÿåº¦çš„百分比。预设为 100%,此时模拟速度将被é™åˆ¶ä¸ºæ ‡å‡†é€Ÿåº¦ã€‚更高或更低的值将增加或é™ä½Žé€Ÿåº¦é™åˆ¶ä¸Šé™ã€‚</string> 163 <string name="frame_limit_slider_description">指定é™åˆ¶è¿è¡Œé€Ÿåº¦çš„百分比。100% 为正常速度。更高或更低的值将增加或é™ä½Žé€Ÿåº¦é™åˆ¶ä¸Šé™ã€‚</string>
121 <string name="cpu_accuracy">CPU 精度</string> 164 <string name="cpu_accuracy">CPU 精度</string>
165 <string name="value_with_units">%1$s%2$s</string>
122 166
123 <!-- System settings strings --> 167 <!-- System settings strings -->
124 <string name="use_docked_mode">主机模å¼</string> 168 <string name="use_docked_mode">主机模å¼</string>
125 <string name="use_docked_mode_description">以主机模å¼è¿›è¡Œæ¨¡æ‹Ÿï¼Œç‰ºç‰²æ€§èƒ½å¹¶æé«˜ç”»é¢åˆ†è¾¨çŽ‡ã€‚</string> 169 <string name="use_docked_mode_description">æé«˜åˆ†è¾¨çŽ‡ï¼Œä½†é™ä½Žæ€§èƒ½ã€‚ç¦ç”¨æ­¤é¡¹æ—¶ä½¿ç”¨æŽŒæœºæ¨¡å¼ï¼Œé™ä½Žåˆ†è¾¨çއ并æé«˜æ€§èƒ½ã€‚</string>
126 <string name="emulated_region">模拟区域</string> 170 <string name="emulated_region">模拟区域</string>
127 <string name="emulated_language">模拟语言</string> 171 <string name="emulated_language">模拟语言</string>
128 <string name="select_rtc_date">选择日期</string> 172 <string name="select_rtc_date">选择日期</string>
129 <string name="select_rtc_time">选择时间</string> 173 <string name="select_rtc_time">选择时间</string>
130 <string name="use_custom_rtc">å¯ç”¨è‡ªå®šä¹‰ç³»ç»Ÿæ—¶é’Ÿ</string> 174 <string name="use_custom_rtc">自定义系统时间</string>
131 <string name="use_custom_rtc_description">此选项å…许您设置与目å‰ç³»ç»Ÿæ—¶é—´ç›¸ç‹¬ç«‹çš„自定义系统时钟</string> 175 <string name="use_custom_rtc_description">此选项å…许您设置与目å‰ç³»ç»Ÿæ—¶é—´ç›¸ç‹¬ç«‹çš„自定义系统时钟。</string>
132 <string name="set_custom_rtc">设置自定义系统时钟</string> 176 <string name="set_custom_rtc">设置自定义系统时间</string>
133 177
134 <!-- Graphics settings strings --> 178 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">精度等级</string> 179 <string name="renderer_accuracy">精度等级</string>
137 <string name="renderer_resolution">分辨率</string> 180 <string name="renderer_resolution">分辨率 (掌机模å¼/主机模å¼)</string>
138 <string name="renderer_vsync">åž‚ç›´åŒæ­¥æ¨¡å¼</string> 181 <string name="renderer_vsync">åž‚ç›´åŒæ­¥æ¨¡å¼</string>
182 <string name="renderer_screen_layout">å±å¹•æ–¹å‘</string>
139 <string name="renderer_aspect_ratio">å±å¹•纵横比</string> 183 <string name="renderer_aspect_ratio">å±å¹•纵横比</string>
140 <string name="renderer_scaling_filter">çª—å£æ»¤é•œ</string> 184 <string name="renderer_scaling_filter">çª—å£æ»¤é•œ</string>
141 <string name="renderer_anti_aliasing">抗锯齿方å¼</string> 185 <string name="renderer_anti_aliasing">抗锯齿方å¼</string>
@@ -143,12 +187,23 @@
143 <string name="renderer_force_max_clock_description">强制 GPU 以最大时钟è¿è¡Œ (ä»è¢«æ¸©æŽ§é™åˆ¶)。</string> 187 <string name="renderer_force_max_clock_description">强制 GPU 以最大时钟è¿è¡Œ (ä»è¢«æ¸©æŽ§é™åˆ¶)。</string>
144 <string name="renderer_asynchronous_shaders">使用异步ç€è‰²å™¨</string> 188 <string name="renderer_asynchronous_shaders">使用异步ç€è‰²å™¨</string>
145 <string name="renderer_asynchronous_shaders_description">异步编译ç€è‰²å™¨ï¼Œå‡å°‘å¡é¡¿ï¼Œä½†å¯èƒ½å¼•入故障。</string> 189 <string name="renderer_asynchronous_shaders_description">异步编译ç€è‰²å™¨ï¼Œå‡å°‘å¡é¡¿ï¼Œä½†å¯èƒ½å¼•入故障。</string>
146 <string name="renderer_debug">å¯ç”¨å›¾å½¢è°ƒè¯•</string> 190 <string name="renderer_reactive_flushing">å¯ç”¨å应性刷新</string>
147 <string name="renderer_debug_description">å¯ç”¨æ—¶ï¼Œå›¾å½¢ API 将进入较慢的调试模å¼ã€‚</string> 191 <string name="renderer_reactive_flushing_description">牺牲性能,æé«˜æŸäº›æ¸¸æˆçš„æ¸²æŸ“精度。</string>
148 <string name="use_disk_shader_cache">使用ç£ç›˜ç€è‰²å™¨ç¼“å­˜</string> 192 <string name="use_disk_shader_cache">ç£ç›˜ç€è‰²å™¨ç¼“å­˜</string>
149 <string name="use_disk_shader_cache_description">将生æˆçš„ç€è‰²å™¨ç¼“存于ç£ç›˜ä¸­å¹¶è¿›è¡Œè¯»å–以å‡å°‘å¡é¡¿ã€‚</string> 193 <string name="use_disk_shader_cache_description">将生æˆçš„ç€è‰²å™¨ç¼“存于ç£ç›˜ä¸­å¹¶è¿›è¡Œè¯»å–,以å‡å°‘å¡é¡¿ã€‚</string>
194
195 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">CPU 调试</string>
198 <string name="cpu_debug_mode_description">å°† CPU 设置为较慢的调试模å¼ã€‚</string>
199 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string>
201 <string name="renderer_debug">图形调试</string>
202 <string name="renderer_debug_description">将图形 API 设置为较慢的调试模å¼ã€‚</string>
203 <string name="fastmem">Fastmem</string>
150 204
151 <!-- Audio settings strings --> 205 <!-- Audio settings strings -->
206 <string name="audio_output_engine">输出引擎</string>
152 <string name="audio_volume">音é‡</string> 207 <string name="audio_volume">音é‡</string>
153 <string name="audio_volume_description">指定输出的音é‡ã€‚</string> 208 <string name="audio_volume_description">指定输出的音é‡ã€‚</string>
154 209
@@ -157,7 +212,9 @@
157 <string name="ini_saved">å·²ä¿å­˜è®¾ç½®</string> 212 <string name="ini_saved">å·²ä¿å­˜è®¾ç½®</string>
158 <string name="gameid_saved">å·²ä¿å­˜ %1$s 的设置</string> 213 <string name="gameid_saved">å·²ä¿å­˜ %1$s 的设置</string>
159 <string name="error_saving">ä¿å­˜ %1$s.ini 时出错: %2$s</string> 214 <string name="error_saving">ä¿å­˜ %1$s.ini 时出错: %2$s</string>
215 <string name="unimplemented_menu">未生效èœå•</string>
160 <string name="loading">加载中…</string> 216 <string name="loading">加载中…</string>
217 <string name="shutting_down">正在关闭…</string>
161 <string name="reset_setting_confirmation">您è¦å°†æ­¤è®¾å®šé‡è®¾ä¸ºé»˜è®¤å€¼å—?</string> 218 <string name="reset_setting_confirmation">您è¦å°†æ­¤è®¾å®šé‡è®¾ä¸ºé»˜è®¤å€¼å—?</string>
162 <string name="reset_to_default">æ¢å¤é»˜è®¤</string> 219 <string name="reset_to_default">æ¢å¤é»˜è®¤</string>
163 <string name="reset_all_settings">é‡ç½®æ‰€æœ‰è®¾ç½®é¡¹ï¼Ÿ</string> 220 <string name="reset_all_settings">é‡ç½®æ‰€æœ‰è®¾ç½®é¡¹ï¼Ÿ</string>
@@ -165,6 +222,14 @@
165 <string name="settings_reset">é‡è®¾è®¾ç½®é¡¹</string> 222 <string name="settings_reset">é‡è®¾è®¾ç½®é¡¹</string>
166 <string name="close">关闭</string> 223 <string name="close">关闭</string>
167 <string name="learn_more">了解更多</string> 224 <string name="learn_more">了解更多</string>
225 <string name="auto">自动</string>
226 <string name="submit">æäº¤</string>
227 <string name="string_null">æ— </string>
228 <string name="string_import">导入</string>
229 <string name="export">导出</string>
230 <string name="export_failed">导出失败</string>
231 <string name="import_failed">导入失败</string>
232 <string name="cancelling">å–æ¶ˆä¸­</string>
168 233
169 <!-- GPU driver installation --> 234 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">选择 GPU 驱动程åº</string> 235 <string name="select_gpu_driver">选择 GPU 驱动程åº</string>
@@ -172,6 +237,7 @@
172 <string name="select_gpu_driver_install">安装</string> 237 <string name="select_gpu_driver_install">安装</string>
173 <string name="select_gpu_driver_default">系统默认</string> 238 <string name="select_gpu_driver_default">系统默认</string>
174 <string name="select_gpu_driver_use_default">使用默认 GPU 驱动程åº</string> 239 <string name="select_gpu_driver_use_default">使用默认 GPU 驱动程åº</string>
240 <string name="select_gpu_driver_error">é€‰æ‹©çš„é©±åŠ¨ç¨‹åºæ— æ•ˆï¼Œå°†ä½¿ç”¨ç³»ç»Ÿé»˜è®¤çš„驱动程åºï¼</string>
175 <string name="system_gpu_driver">系统 GPU 驱动程åº</string> 241 <string name="system_gpu_driver">系统 GPU 驱动程åº</string>
176 <string name="installing_driver">正在安装驱动程åºâ€¦</string> 242 <string name="installing_driver">正在安装驱动程åºâ€¦</string>
177 243
@@ -182,10 +248,11 @@
182 <string name="preferences_graphics">图形</string> 248 <string name="preferences_graphics">图形</string>
183 <string name="preferences_audio">声音</string> 249 <string name="preferences_audio">声音</string>
184 <string name="preferences_theme">主题和色彩</string> 250 <string name="preferences_theme">主题和色彩</string>
251 <string name="preferences_debug">调试</string>
185 252
186 <!-- ROM loading errors --> 253 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">您的 ROM 已加密</string> 254 <string name="loader_error_encrypted">您的 ROM 已加密</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[请å‚考指å—釿–°è½¬å‚¨ä½ çš„<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">游æˆå¡å¸¦</a>或<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">已安装的游æˆ</a>。]]></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>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[è¯·ç¡®ä¿ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</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>
190 <string name="loader_error_video_core">åˆå§‹åŒ–视频核心时å‘生错误</string> 257 <string name="loader_error_video_core">åˆå§‹åŒ–视频核心时å‘生错误</string>
191 <string name="loader_error_video_core_description">这通常由ä¸å…¼å®¹çš„ GPU 驱动程åºé€ æˆï¼Œå®‰è£…自定义 GPU 驱动程åºå¯èƒ½è§£å†³æ­¤é—®é¢˜ã€‚</string> 258 <string name="loader_error_video_core_description">这通常由ä¸å…¼å®¹çš„ GPU 驱动程åºé€ æˆï¼Œå®‰è£…自定义 GPU 驱动程åºå¯èƒ½è§£å†³æ­¤é—®é¢˜ã€‚</string>
@@ -226,6 +293,9 @@
226 <string name="fatal_error">致命错误</string> 293 <string name="fatal_error">致命错误</string>
227 <string name="fatal_error_message">å‘生致命错误,请查阅日志获å–详细信æ¯ã€‚\n继续模拟å¯èƒ½ä¼šé€ æˆå´©æºƒå’Œé”™è¯¯ã€‚</string> 294 <string name="fatal_error_message">å‘生致命错误,请查阅日志获å–详细信æ¯ã€‚\n继续模拟å¯èƒ½ä¼šé€ æˆå´©æºƒå’Œé”™è¯¯ã€‚</string>
228 <string name="performance_warning">关闭此项会显著é™ä½Žæ¨¡æ‹Ÿæ€§èƒ½ï¼å»ºè®®æ‚¨å°†æ­¤é¡¹ä¿æŒä¸ºå¯ç”¨çжæ€ã€‚</string> 295 <string name="performance_warning">关闭此项会显著é™ä½Žæ¨¡æ‹Ÿæ€§èƒ½ï¼å»ºè®®æ‚¨å°†æ­¤é¡¹ä¿æŒä¸ºå¯ç”¨çжæ€ã€‚</string>
296 <string name="device_memory_inadequate">设备 RAM: %1$s\n推è RAM: %2$s</string>
297 <string name="memory_formatted">%1$s%2$s</string>
298 <string name="no_game_present">当剿²¡æœ‰å¯å¯åŠ¨çš„æ¸¸æˆï¼</string>
229 299
230 <!-- Region Names --> 300 <!-- Region Names -->
231 <string name="region_japan">日本</string> 301 <string name="region_japan">日本</string>
@@ -236,7 +306,14 @@
236 <string name="region_korea">韩国</string> 306 <string name="region_korea">韩国</string>
237 <string name="region_taiwan">䏭国尿¹¾</string> 307 <string name="region_taiwan">䏭国尿¹¾</string>
238 308
239 <!-- Language Names --> 309 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string>
311 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">GB</string>
314 <string name="memory_terabyte">TB</string>
315 <string name="memory_petabyte">PB</string>
316 <string name="memory_exabyte">EB</string>
240 317
241 <!-- Renderer APIs --> 318 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 319 <string name="renderer_vulkan">Vulkan</string>
@@ -274,6 +351,11 @@
274 <string name="anti_aliasing_fxaa">快速近似抗锯齿</string> 351 <string name="anti_aliasing_fxaa">快速近似抗锯齿</string>
275 <string name="anti_aliasing_smaa">å­åƒç´ å½¢æ€å­¦æŠ—锯齿</string> 352 <string name="anti_aliasing_smaa">å­åƒç´ å½¢æ€å­¦æŠ—锯齿</string>
276 353
354 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">横å‘大å±</string>
356 <string name="screen_layout_portrait">纵å‘å±å¹•</string>
357 <string name="screen_layout_auto">自动</string>
358
277 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
278 <string name="ratio_default">默认 (16:9)</string> 360 <string name="ratio_default">默认 (16:9)</string>
279 <string name="ratio_force_four_three">强制 4:3</string> 361 <string name="ratio_force_four_three">强制 4:3</string>
@@ -303,13 +385,27 @@
303 <string name="theme_material_you">Material You</string> 385 <string name="theme_material_you">Material You</string>
304 386
305 <!-- Theme Modes --> 387 <!-- Theme Modes -->
306 <string name="change_theme_mode">主题模å¼</string> 388 <string name="change_theme_mode">更改主题模å¼</string>
307 <string name="theme_mode_follow_system">è·Ÿéšç³»ç»Ÿ</string> 389 <string name="theme_mode_follow_system">è·Ÿéšç³»ç»Ÿ</string>
308 <string name="theme_mode_light">浅色</string> 390 <string name="theme_mode_light">浅色</string>
309 <string name="theme_mode_dark">深色</string> 391 <string name="theme_mode_dark">深色</string>
310 392
393 <!-- Audio output engines -->
394 <string name="cubeb">cubeb</string>
395
311 <!-- Black backgrounds theme --> 396 <!-- Black backgrounds theme -->
312 <string name="use_black_backgrounds">使用黑色背景</string> 397 <string name="use_black_backgrounds">使用黑色背景</string>
313 <string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string> 398 <string name="use_black_backgrounds_description">使用深色主题时,套用黑色背景。</string>
314 399
315</resources> 400 <!-- Picture-In-Picture -->
401 <string name="picture_in_picture">画中画</string>
402 <string name="picture_in_picture_description">模拟器ä½äºŽåŽå°æ—¶æœ€å°åŒ–窗å£</string>
403 <string name="pause">æš‚åœ</string>
404 <string name="play">开始</string>
405 <string name="mute">é™éŸ³</string>
406 <string name="unmute">å–æ¶ˆé™éŸ³</string>
407
408 <!-- Licenses screen strings -->
409 <string name="licenses">许å¯è¯</string>
410 <string name="license_fidelityfx_fsr_description">æ¥è‡ª AMD 的高å“质画质å‡çº§</string>
411 </resources>
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 4a21bf893..b8f468c68 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
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<resources> 2<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
3 3
4 <string name="app_disclaimer">此軟體å¯ä»¥åŸ·è¡Œ Nintendo Switch ä¸»æ©ŸéŠæˆ²ï¼Œä½†ä¸åŒ…å«ä»»ä½•éŠæˆ²å’Œé‡‘鑰。&lt;br /&gt;&lt;br /&gt;在您開始å‰ï¼Œè«‹æ‰¾åˆ°æ”¾ç½®æ–¼æ‚¨çš„è£ç½®å„²å­˜ç©ºé–“çš„ <![CDATA[<b> prod.keys </b>]]> 檔案。&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">深入瞭解</a>]]></string> 4 <string name="app_disclaimer">此軟體å¯ä»¥åŸ·è¡Œ Nintendo Switch ä¸»æ©ŸéŠæˆ²ï¼Œä½†ä¸åŒ…å«ä»»ä½•éŠæˆ²å’Œé‡‘鑰。&lt;br /&gt;&lt;br /&gt;在您開始å‰ï¼Œè«‹æ‰¾åˆ°æ”¾ç½®æ–¼æ‚¨çš„è£ç½®å„²å­˜ç©ºé–“çš„ <![CDATA[<b> prod.keys </b>]]> 檔案。&lt;br /&gt;&lt;br /&gt;<![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">深入瞭解</a>]]></string>
5 <string name="emulation_notification_channel_name">模擬進行中</string> 5 <string name="emulation_notification_channel_name">模擬進行中</string>
@@ -25,6 +25,7 @@
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>
28 29
29 <!-- Home strings --> 30 <!-- Home strings -->
30 <string name="home_games">éŠæˆ²</string> 31 <string name="home_games">éŠæˆ²</string>
@@ -33,11 +34,12 @@
33 <string name="empty_gamelist">找ä¸åˆ°æª”案,或者尚未é¸å–éŠæˆ²ç›®éŒ„。</string> 34 <string name="empty_gamelist">找ä¸åˆ°æª”案,或者尚未é¸å–éŠæˆ²ç›®éŒ„。</string>
34 <string name="search_and_filter_games">æœå°‹ä¸¦ç¯©é¸éŠæˆ²</string> 35 <string name="search_and_filter_games">æœå°‹ä¸¦ç¯©é¸éŠæˆ²</string>
35 <string name="select_games_folder">é¸å–éŠæˆ²è³‡æ–™å¤¾</string> 36 <string name="select_games_folder">é¸å–éŠæˆ²è³‡æ–™å¤¾</string>
36 <string name="select_games_folder_description">一律å…許 yuzu å¡«å…¥éŠæˆ²æ¸…å–®</string> 37 <string name="select_games_folder_description">å…許 yuzu å¡«å…¥éŠæˆ²æ¸…å–®</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>
42 <string name="search_settings">æœç´¢è®¾ç½®</string>
41 <string name="games_dir_selected">éŠæˆ²ç›®éŒ„å·²é¸å–</string> 43 <string name="games_dir_selected">éŠæˆ²ç›®éŒ„å·²é¸å–</string>
42 <string name="install_prod_keys">å®‰è£ prod.keys</string> 44 <string name="install_prod_keys">å®‰è£ prod.keys</string>
43 <string name="install_prod_keys_description">需è¦è§£å¯†é›¶å”®éŠæˆ²</string> 45 <string name="install_prod_keys_description">需è¦è§£å¯†é›¶å”®éŠæˆ²</string>
@@ -60,13 +62,16 @@
60 <string name="install_amiibo_keys_description">需è¦åœ¨éŠæˆ²ä¸­ä½¿ç”¨ Amiibo</string> 62 <string name="install_amiibo_keys_description">需è¦åœ¨éŠæˆ²ä¸­ä½¿ç”¨ Amiibo</string>
61 <string name="invalid_keys_file">無效的金鑰檔案已é¸å–</string> 63 <string name="invalid_keys_file">無效的金鑰檔案已é¸å–</string>
62 <string name="install_keys_success">金鑰已æˆåŠŸå®‰è£</string> 64 <string name="install_keys_success">金鑰已æˆåŠŸå®‰è£</string>
63 <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>
64 <string name="invalid_keys_error">無效的加密金鑰</string> 68 <string name="invalid_keys_error">無效的加密金鑰</string>
65 <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>
66 <string name="install_keys_failure_description">é¸å–çš„æª”æ¡ˆä¸æ­£ç¢ºæˆ–å·²ææ¯€ï¼Œè«‹é‡æ–°å‚¾å°æ‚¨çš„金鑰。</string> 70 <string name="install_keys_failure_description">é¸å–çš„æª”æ¡ˆä¸æ­£ç¢ºæˆ–å·²ææ¯€ï¼Œè«‹é‡æ–°å‚¾å°æ‚¨çš„金鑰。</string>
67 <string name="install_gpu_driver">å®‰è£ GPU 驅動程å¼</string> 71 <string name="install_gpu_driver">å®‰è£ GPU 驅動程å¼</string>
68 <string name="install_gpu_driver_description">å®‰è£æ›¿ä»£é©…動程å¼ä»¥å–得潛在的更佳效能或準確度</string> 72 <string name="install_gpu_driver_description">å®‰è£æ›¿ä»£é©…動程å¼ä»¥å–得潛在的更佳效能或準確度</string>
69 <string name="advanced_settings">進階設定</string> 73 <string name="advanced_settings">進階設定</string>
74 <string name="advanced_settings_game">高级选项: %1$s</string>
70 <string name="settings_description">進行模擬器設定</string> 75 <string name="settings_description">進行模擬器設定</string>
71 <string name="search_recently_played">最近éŠçŽ©</string> 76 <string name="search_recently_played">最近éŠçŽ©</string>
72 <string name="search_recently_added">最近新增</string> 77 <string name="search_recently_added">最近新增</string>
@@ -86,6 +91,33 @@
86 <string name="save_file_invalid_zip_structure_description">首個å­è³‡æ–™å¤¾åç¨±å¿…é ˆç‚ºéŠæˆ²æ¨™é¡Œ ID。</string> 91 <string name="save_file_invalid_zip_structure_description">首個å­è³‡æ–™å¤¾åç¨±å¿…é ˆç‚ºéŠæˆ²æ¨™é¡Œ ID。</string>
87 <string name="import_saves">匯入</string> 92 <string name="import_saves">匯入</string>
88 <string name="export_saves">匯出</string> 93 <string name="export_saves">匯出</string>
94 <string name="install_firmware">安è£éŸŒé«”</string>
95 <string name="install_firmware_description">韌體必須為 ZIP å°å­˜æª”ï¼Œå°‡æœƒç”¨æ–¼éƒ¨åˆ†éŠæˆ²çš„啟動</string>
96 <string name="firmware_installing">正在安è£éŸŒé«”</string>
97 <string name="firmware_installed_success">韌體已æˆåŠŸå®‰è£</string>
98 <string name="firmware_installed_failure">韌體安è£å¤±æ•—</string>
99 <string name="firmware_installed_failure_description">请确ä¿å›ºä»¶ nca 文件ä½äºŽ zip 压缩包的根目录,然åŽé‡è¯•。</string>
100 <string name="share_log">分享åµéŒ¯è¨˜éŒ„</string>
101 <string name="share_log_description">分享 yuzu 的記錄檔以便å°ç›¸é—œå•題進行åµéŒ¯</string>
102 <string name="share_log_missing">找ä¸åˆ°è¨˜éŒ„檔</string>
103 <string name="install_game_content">安è£éŠæˆ²å…§å®¹</string>
104 <string name="install_game_content_description">安è£éŠæˆ²æ›´æ–°æˆ– DLC</string>
105 <string name="installing_game_content">安装中...</string>
106 <string name="install_game_content_failure">å‘ NAND 安装文件时失败</string>
107 <string name="install_game_content_failure_description">请确ä¿é™„加内容的有效性,并且 prod.keys 密钥文件已安装。</string>
108 <string name="install_game_content_failure_base">为é¿å…产生冲çªï¼Œæ­¤åŠŸèƒ½ä¸èƒ½ç”¨äºŽå®‰è£…æ¸¸æˆæœ¬ä½“。</string>
109 <string name="install_game_content_failure_file_extension">åªæœ‰ NSP 或 XCI æ ¼å¼çš„附加内容å¯ä»¥å®‰è£…ã€‚è¯·ç¡®ä¿æ‚¨çš„æ¸¸æˆé™„加内容是有效的。</string>
110 <string name="install_game_content_failed_count">%1$d 安装出错</string>
111 <string name="install_game_content_success">游æˆé™„加内容已æˆåŠŸå®‰è£…</string>
112 <string name="install_game_content_success_install">%1$d 安装æˆåŠŸ</string>
113 <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>
115 <string name="custom_driver_not_supported">䏿”¯æŒè‡ªå®šä¹‰é©±åЍ</string>
116 <string name="custom_driver_not_supported_description">æ­¤è®¾å¤‡ä¸æ”¯æŒè‡ªå®šä¹‰é©±åŠ¨ã€‚\n请之åŽå†è®¿é—®æ­¤é¡¹ï¼ŒæŸ¥çœ‹æ˜¯å¦å·²ä¸ºæ­¤è®¾å¤‡æ·»åŠ æ”¯æŒã€‚</string>
117 <string name="manage_yuzu_data">ç®¡ç† yuzu æ•°æ®</string>
118 <string name="manage_yuzu_data_description">导入/导出固件ã€å¯†é’¥ã€ç”¨æˆ·æ•°æ®åŠå…¶ä»–。</string>
119 <string name="share_save_file">分享存档文件</string>
120 <string name="export_save_failed">导出存档文件失败</string>
89 121
90 <!-- About screen strings --> 122 <!-- About screen strings -->
91 <string name="gaia_is_not_real">Gaia ä¸çœŸå¯¦</string> 123 <string name="gaia_is_not_real">Gaia ä¸çœŸå¯¦</string>
@@ -94,7 +126,18 @@
94 <string name="contributors">åƒèˆ‡è€…</string> 126 <string name="contributors">åƒèˆ‡è€…</string>
95 <string name="contributors_description">使用來自 yuzu 團隊的 \u2764 製作</string> 127 <string name="contributors_description">使用來自 yuzu 團隊的 \u2764 製作</string>
96 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string> 128 <string name="contributors_link">https://github.com/yuzu-emu/yuzu/graphs/contributors</string>
129 <string name="licenses_description">這些專案使 yuzu Android 版æˆç‚ºå¯èƒ½</string>
97 <string name="build">組建</string> 130 <string name="build">組建</string>
131 <string name="user_data">用户数æ®</string>
132 <string name="user_data_description">导入/å¯¼å‡ºåº”ç”¨ç¨‹åºæ‰€æœ‰æ•°æ®ã€‚\n\nå¯¼å…¥ç”¨æˆ·æ•°æ®æ—¶ï¼Œå°†åˆ é™¤å½“剿‰€æœ‰çš„用户数æ®ï¼</string>
133 <string name="exporting_user_data">正在导出用户数æ®...</string>
134 <string name="importing_user_data">正在导入用户数æ®...</string>
135 <string name="import_user_data">导入用户数æ®</string>
136 <string name="invalid_yuzu_backup">无效的 yuzu 备份</string>
137 <string name="user_data_export_success">å¯¼å‡ºç”¨æˆ·æ•°æ®æˆåŠŸ</string>
138 <string name="user_data_import_success">å¯¼å…¥ç”¨æˆ·æ•°æ®æˆåŠŸ</string>
139 <string name="user_data_export_cancelled">已喿¶ˆå¯¼å‡ºæ•°æ®</string>
140 <string name="user_data_import_failed_description">请确ä¿ç”¨æˆ·æ•°æ®æ–‡ä»¶å¤¹ä½äºŽ zip 压缩包的根目录,并在 config/config.ini 路径中包å«é…置文件,然åŽé‡è¯•。</string>
98 <string name="support_link">https://discord.gg/u77vRWY</string> 141 <string name="support_link">https://discord.gg/u77vRWY</string>
99 <string name="website_link">https://yuzu-emu.org/</string> 142 <string name="website_link">https://yuzu-emu.org/</string>
100 <string name="github_link">https://github.com/yuzu-emu</string> 143 <string name="github_link">https://github.com/yuzu-emu</string>
@@ -114,28 +157,29 @@
114 <string name="are_you_interested">æ‚¨ä»æ„Ÿèˆˆè¶£å—Žï¼Ÿ</string> 157 <string name="are_you_interested">æ‚¨ä»æ„Ÿèˆˆè¶£å—Žï¼Ÿ</string>
115 158
116 <!-- General settings strings --> 159 <!-- General settings strings -->
117 <string name="frame_limit_enable">啟用é™åˆ¶é€Ÿåº¦</string> 160 <string name="frame_limit_enable">é™åˆ¶é€Ÿåº¦</string>
118 <string name="frame_limit_enable_description">若啟用,模擬速度將會é™åˆ¶åœ¨æ¨™æº–速度的指定百分比。</string> 161 <string name="frame_limit_enable_description">將模擬速度é™åˆ¶åœ¨æ¨™æº–速度的指定百分比。</string>
119 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string> 162 <string name="frame_limit_slider">é™åˆ¶é€Ÿåº¦ç™¾åˆ†æ¯”</string>
120 <string name="frame_limit_slider_description">指定é™åˆ¶æ¨¡æ“¬é€Ÿåº¦çš„百分比。é è¨­ç‚º 100%,模擬速度將被é™åˆ¶ç‚ºæ¨™æº–速度。更高或更低的值將會增加或減少速度é™åˆ¶ã€‚</string> 163 <string name="frame_limit_slider_description">指定é™åˆ¶æ¨¡æ“¬é€Ÿåº¦çš„百分比。100% 為標準速度,更高或更低的值將會增加或減少速度é™åˆ¶ã€‚</string>
121 <string name="cpu_accuracy">CPU 準確度</string> 164 <string name="cpu_accuracy">CPU 準確度</string>
165 <string name="value_with_units">%1$s%2$s</string>
122 166
123 <!-- System settings strings --> 167 <!-- System settings strings -->
124 <string name="use_docked_mode">底座模å¼</string> 168 <string name="use_docked_mode">底座模å¼</string>
125 <string name="use_docked_mode_description">ä»¥åº•åº§æ¨¡å¼æ¨¡æ“¬ï¼Œä»¥çŠ§ç‰²æ•ˆèƒ½çš„ä»£åƒ¹æé«˜è§£æžåº¦ã€‚</string> 169 <string name="use_docked_mode_description">æé«˜è§£æžåº¦ï¼Œé™ä½Žæ•ˆèƒ½ã€‚åœç”¨å¾Œå°‡æœƒä½¿ç”¨æ‰‹ææ¨¡å¼ï¼Œæœƒé™ä½Žè§£æžåº¦ä¸¦æé«˜æ•ˆèƒ½ã€‚</string>
126 <string name="emulated_region">模擬å€åŸŸ</string> 170 <string name="emulated_region">模擬å€åŸŸ</string>
127 <string name="emulated_language">模擬語言</string> 171 <string name="emulated_language">模擬語言</string>
128 <string name="select_rtc_date">é¸å– RTC 日期</string> 172 <string name="select_rtc_date">é¸å– RTC 日期</string>
129 <string name="select_rtc_time">é¸å– RTC 時間</string> 173 <string name="select_rtc_time">é¸å– RTC 時間</string>
130 <string name="use_custom_rtc">啟用自訂 RTC</string> 174 <string name="use_custom_rtc">自訂 RTC</string>
131 <string name="use_custom_rtc_description">此設定å…許您設定與您的目å‰ç³»çµ±æ™‚間相互ç¨ç«‹çš„è‡ªè¨‚å³æ™‚時é˜</string> 175 <string name="use_custom_rtc_description">å…許您設定與您的目å‰ç³»çµ±æ™‚間相互ç¨ç«‹çš„è‡ªè¨‚å³æ™‚時é˜ã€‚</string>
132 <string name="set_custom_rtc">設定自訂 RTC</string> 176 <string name="set_custom_rtc">設定自訂 RTC</string>
133 177
134 <!-- Graphics settings strings --> 178 <!-- Graphics settings strings -->
135 <string name="renderer_api">API</string>
136 <string name="renderer_accuracy">準確度層級</string> 179 <string name="renderer_accuracy">準確度層級</string>
137 <string name="renderer_resolution">è§£æžåº¦</string> 180 <string name="renderer_resolution">è§£æžåº¦ (手æ/底座)</string>
138 <string name="renderer_vsync">VSync 模å¼</string> 181 <string name="renderer_vsync">VSync 模å¼</string>
182 <string name="renderer_screen_layout">å±å¹•æ–¹å‘</string>
139 <string name="renderer_aspect_ratio">長寬比</string> 183 <string name="renderer_aspect_ratio">長寬比</string>
140 <string name="renderer_scaling_filter">è¦–çª—é©æ‡‰éŽæ¿¾å™¨</string> 184 <string name="renderer_scaling_filter">è¦–çª—é©æ‡‰éŽæ¿¾å™¨</string>
141 <string name="renderer_anti_aliasing">消除鋸齒方法</string> 185 <string name="renderer_anti_aliasing">消除鋸齒方法</string>
@@ -143,12 +187,23 @@
143 <string name="renderer_force_max_clock_description">強制 GPU 以最大å¯èƒ½æ™‚脈執行 (熱溫é™åˆ¶ä»è¢«å¥—用)。</string> 187 <string name="renderer_force_max_clock_description">強制 GPU 以最大å¯èƒ½æ™‚脈執行 (熱溫é™åˆ¶ä»è¢«å¥—用)。</string>
144 <string name="renderer_asynchronous_shaders">使用éžåŒæ­¥è‘—色器</string> 188 <string name="renderer_asynchronous_shaders">使用éžåŒæ­¥è‘—色器</string>
145 <string name="renderer_asynchronous_shaders_description">éžåŒæ­¥ç·¨è­¯è‘—色器,將會減少間斷,但å¯èƒ½æœƒå¼•入故障。</string> 189 <string name="renderer_asynchronous_shaders_description">éžåŒæ­¥ç·¨è­¯è‘—色器,將會減少間斷,但å¯èƒ½æœƒå¼•入故障。</string>
146 <string name="renderer_debug">啟用圖形åµéŒ¯</string> 190 <string name="renderer_reactive_flushing">ä½¿ç”¨é‡æ–°å•Ÿç”¨æŽ’清</string>
147 <string name="renderer_debug_description">æ ¸å–æ™‚,åœå½¢ API 將會進入慢速åµéŒ¯æ¨¡å¼ã€‚</string> 191 <string name="renderer_reactive_flushing_description">犧牲效能,以改å–éƒ¨åˆ†éŠæˆ²çš„轉譯準確度。</string>
148 <string name="use_disk_shader_cache">使用ç£ç¢Ÿè‘—色器快å–</string> 192 <string name="use_disk_shader_cache">ç£ç¢Ÿè‘—色器快å–</string>
149 <string name="use_disk_shader_cache_description">é€éŽå°‡ç”¢ç”Ÿçš„著色器儲存並載入至ç£ç¢Ÿï¼Œæ¸›å°‘中斷。</string> 193 <string name="use_disk_shader_cache_description">é€éŽå°‡ç”¢ç”Ÿçš„著色器儲存並載入至ç£ç¢Ÿï¼Œæ¸›å°‘中斷。</string>
150 194
195 <!-- Debug settings strings -->
196 <string name="cpu">CPU</string>
197 <string name="cpu_debug_mode">CPU 调试</string>
198 <string name="cpu_debug_mode_description">å°† CPU 设置为较慢的调试模å¼ã€‚</string>
199 <string name="gpu">GPU</string>
200 <string name="renderer_api">API</string>
201 <string name="renderer_debug">圖形åµéŒ¯</string>
202 <string name="renderer_debug_description">將圖形 API 設為慢速åµéŒ¯æ¨¡å¼ã€‚</string>
203 <string name="fastmem">Fastmem</string>
204
151 <!-- Audio settings strings --> 205 <!-- Audio settings strings -->
206 <string name="audio_output_engine">输出引擎</string>
152 <string name="audio_volume">音é‡</string> 207 <string name="audio_volume">音é‡</string>
153 <string name="audio_volume_description">指定音訊輸出音é‡ã€‚</string> 208 <string name="audio_volume_description">指定音訊輸出音é‡ã€‚</string>
154 209
@@ -157,7 +212,9 @@
157 <string name="ini_saved">已儲存設定</string> 212 <string name="ini_saved">已儲存設定</string>
158 <string name="gameid_saved">已儲存 %1$s 設定</string> 213 <string name="gameid_saved">已儲存 %1$s 設定</string>
159 <string name="error_saving">儲存 %1$s 時發生錯誤 ini: %2$s</string> 214 <string name="error_saving">儲存 %1$s 時發生錯誤 ini: %2$s</string>
215 <string name="unimplemented_menu">未生效èœå•</string>
160 <string name="loading">正在載入…</string> 216 <string name="loading">正在載入…</string>
217 <string name="shutting_down">正在关闭…</string>
161 <string name="reset_setting_confirmation">è¦å°‡æ­¤è¨­å®šé‡è¨­å›žé è¨­å€¼å—Žï¼Ÿ</string> 218 <string name="reset_setting_confirmation">è¦å°‡æ­¤è¨­å®šé‡è¨­å›žé è¨­å€¼å—Žï¼Ÿ</string>
162 <string name="reset_to_default">é‡è¨­ç‚ºé è¨­å€¼</string> 219 <string name="reset_to_default">é‡è¨­ç‚ºé è¨­å€¼</string>
163 <string name="reset_all_settings">é‡è¨­æ‰€æœ‰è¨­å®šï¼Ÿ</string> 220 <string name="reset_all_settings">é‡è¨­æ‰€æœ‰è¨­å®šï¼Ÿ</string>
@@ -165,6 +222,14 @@
165 <string name="settings_reset">設定已é‡è¨­</string> 222 <string name="settings_reset">設定已é‡è¨­</string>
166 <string name="close">關閉</string> 223 <string name="close">關閉</string>
167 <string name="learn_more">深入瞭解</string> 224 <string name="learn_more">深入瞭解</string>
225 <string name="auto">自動</string>
226 <string name="submit">æäº¤</string>
227 <string name="string_null">ç„¡</string>
228 <string name="string_import">匯入</string>
229 <string name="export">匯出</string>
230 <string name="export_failed">导出失败</string>
231 <string name="import_failed">导入失败</string>
232 <string name="cancelling">å–æ¶ˆä¸­</string>
168 233
169 <!-- GPU driver installation --> 234 <!-- GPU driver installation -->
170 <string name="select_gpu_driver">é¸å– GPU 驅動程å¼</string> 235 <string name="select_gpu_driver">é¸å– GPU 驅動程å¼</string>
@@ -172,6 +237,7 @@
172 <string name="select_gpu_driver_install">安è£</string> 237 <string name="select_gpu_driver_install">安è£</string>
173 <string name="select_gpu_driver_default">é è¨­</string> 238 <string name="select_gpu_driver_default">é è¨­</string>
174 <string name="select_gpu_driver_use_default">使用é è¨­ GPU 驅動程å¼</string> 239 <string name="select_gpu_driver_use_default">使用é è¨­ GPU 驅動程å¼</string>
240 <string name="select_gpu_driver_error">é¸å–的驅動程å¼ç„¡æ•ˆï¼Œå°‡ä½¿ç”¨ç³»çµ±é è¨­é©…動程å¼ï¼</string>
175 <string name="system_gpu_driver">系統 GPU 驅動程å¼</string> 241 <string name="system_gpu_driver">系統 GPU 驅動程å¼</string>
176 <string name="installing_driver">正在安è£é©…動程å¼â€¦</string> 242 <string name="installing_driver">正在安è£é©…動程å¼â€¦</string>
177 243
@@ -182,10 +248,11 @@
182 <string name="preferences_graphics">圖形</string> 248 <string name="preferences_graphics">圖形</string>
183 <string name="preferences_audio">音訊</string> 249 <string name="preferences_audio">音訊</string>
184 <string name="preferences_theme">主題和色彩</string> 250 <string name="preferences_theme">主題和色彩</string>
251 <string name="preferences_debug">åµéŒ¯</string>
185 252
186 <!-- ROM loading errors --> 253 <!-- ROM loading errors -->
187 <string name="loader_error_encrypted">您的 ROM 已加密</string> 254 <string name="loader_error_encrypted">您的 ROM 已加密</string>
188 <string name="loader_error_encrypted_roms_description"><![CDATA[è«‹ä¾å¾ªæŒ‡å—釿–°å‚¾å°æ‚¨çš„<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games\">éŠæˆ²å¡åŒ£</a>或<a href=\"https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop\">å®‰è£æ¨™é¡Œ</a>。]]></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>
189 <string name="loader_error_encrypted_keys_description"><![CDATA[è«‹ç¢ºä¿æ‚¨çš„ <a href=\"https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</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>
190 <string name="loader_error_video_core">åˆå§‹åŒ–視訊核心時發生錯誤</string> 257 <string name="loader_error_video_core">åˆå§‹åŒ–視訊核心時發生錯誤</string>
191 <string name="loader_error_video_core_description">這經常由ä¸ç›¸å®¹çš„ GPU 驅動程å¼é€ æˆï¼Œå®‰è£è‡ªè¨‚ GPU 驅動程å¼å¯èƒ½æœƒè§£æ±ºæ­¤å•題。</string> 258 <string name="loader_error_video_core_description">這經常由ä¸ç›¸å®¹çš„ GPU 驅動程å¼é€ æˆï¼Œå®‰è£è‡ªè¨‚ GPU 驅動程å¼å¯èƒ½æœƒè§£æ±ºæ­¤å•題。</string>
@@ -219,13 +286,16 @@
219 <!-- Errors and warnings --> 286 <!-- Errors and warnings -->
220 <string name="abort_button">中止</string> 287 <string name="abort_button">中止</string>
221 <string name="continue_button">繼續</string> 288 <string name="continue_button">繼續</string>
222 <string name="system_archive_not_found">找ä¸åˆ°ç³»çµ±æª”案</string> 289 <string name="system_archive_not_found">找ä¸åˆ°ç³»çµ±å°å­˜</string>
223 <string name="system_archive_not_found_message">%s éºå¤±ï¼Œè«‹å‚¾å°æ‚¨çš„系統å°å­˜ã€‚\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string> 290 <string name="system_archive_not_found_message">%s éºå¤±ï¼Œè«‹å‚¾å°æ‚¨çš„系統å°å­˜ã€‚\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string>
224 <string name="system_archive_general">系統å°å­˜</string> 291 <string name="system_archive_general">系統å°å­˜</string>
225 <string name="save_load_error">儲存/載入發生錯誤</string> 292 <string name="save_load_error">儲存/載入發生錯誤</string>
226 <string name="fatal_error">åš´é‡éŒ¯èª¤</string> 293 <string name="fatal_error">åš´é‡éŒ¯èª¤</string>
227 <string name="fatal_error_message">發生嚴é‡éŒ¯èª¤ï¼Œæª¢æŸ¥è¨˜éŒ„以å–得詳細資訊。\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string> 294 <string name="fatal_error_message">發生嚴é‡éŒ¯èª¤ï¼Œæª¢æŸ¥è¨˜éŒ„以å–得詳細資訊。\n繼續模擬å¯èƒ½æœƒé€ æˆç•¶æ©Ÿå’ŒéŒ¯èª¤ã€‚</string>
228 <string name="performance_warning">關閉此設定會顯著é™ä½Žæ¨¡æ“¬æ•ˆèƒ½ï¼å¦‚éœ€æœ€ä½³é«”é©—ï¼Œå»ºè­°æ‚¨å°‡æ­¤è¨­å®šä¿æŒç‚ºå•Ÿç”¨ç‹€æ…‹ã€‚</string> 295 <string name="performance_warning">關閉此設定會顯著é™ä½Žæ¨¡æ“¬æ•ˆèƒ½ï¼å¦‚éœ€æœ€ä½³é«”é©—ï¼Œå»ºè­°æ‚¨å°‡æ­¤è¨­å®šä¿æŒç‚ºå•Ÿç”¨ç‹€æ…‹ã€‚</string>
296 <string name="device_memory_inadequate">设备 RAM: %1$s\n推è RAM: %2$s</string>
297 <string name="memory_formatted">%1$s%2$s</string>
298 <string name="no_game_present">当剿²¡æœ‰å¯å¯åŠ¨çš„æ¸¸æˆï¼</string>
229 299
230 <!-- Region Names --> 300 <!-- Region Names -->
231 <string name="region_japan">日本</string> 301 <string name="region_japan">日本</string>
@@ -236,7 +306,14 @@
236 <string name="region_korea">å—韓</string> 306 <string name="region_korea">å—韓</string>
237 <string name="region_taiwan">å°ç£</string> 307 <string name="region_taiwan">å°ç£</string>
238 308
239 <!-- Language Names --> 309 <!-- Memory Sizes -->
310 <string name="memory_byte">Byte</string>
311 <string name="memory_kilobyte">KB</string>
312 <string name="memory_megabyte">MB</string>
313 <string name="memory_gigabyte">英國</string>
314 <string name="memory_terabyte">TB</string>
315 <string name="memory_petabyte">PB</string>
316 <string name="memory_exabyte">EB</string>
240 317
241 <!-- Renderer APIs --> 318 <!-- Renderer APIs -->
242 <string name="renderer_vulkan">Vulkan</string> 319 <string name="renderer_vulkan">Vulkan</string>
@@ -274,14 +351,20 @@
274 <string name="anti_aliasing_fxaa">FXAA</string> 351 <string name="anti_aliasing_fxaa">FXAA</string>
275 <string name="anti_aliasing_smaa">SMAA</string> 352 <string name="anti_aliasing_smaa">SMAA</string>
276 353
354 <!-- Screen Layouts -->
355 <string name="screen_layout_landscape">横å‘大å±</string>
356 <string name="screen_layout_portrait">纵å‘å±å¹•</string>
357 <string name="screen_layout_auto">自動</string>
358
277 <!-- Aspect Ratios --> 359 <!-- Aspect Ratios -->
278 <string name="ratio_default">é è¨­ (16:9)</string> 360 <string name="ratio_default">é è¨­ (16:9)</string>
279 <string name="ratio_force_four_three">強制 4:3</string> 361 <string name="ratio_force_four_three">強制 4:3</string>
280 <string name="ratio_force_twenty_one_nine">強制 21:9</string> 362 <string name="ratio_force_twenty_one_nine">強制 21:9</string>
281 <string name="ratio_force_sixteen_ten">強制 16:10</string> 363 <string name="ratio_force_sixteen_ten">強制 16:10</string>
282 <string name="ratio_stretch">延伸視窗</string> 364 <string name="ratio_stretch">延展視窗</string>
283 365
284 <!-- CPU Accuracy --> 366 <!-- CPU Accuracy -->
367 <string name="cpu_accuracy_accurate">高精度</string>
285 <string name="cpu_accuracy_unsafe">低精度</string> 368 <string name="cpu_accuracy_unsafe">低精度</string>
286 <string name="cpu_accuracy_paranoid">ä¸åˆç† (æ…¢)</string> 369 <string name="cpu_accuracy_paranoid">ä¸åˆç† (æ…¢)</string>
287 370
@@ -307,8 +390,22 @@
307 <string name="theme_mode_light">淺色</string> 390 <string name="theme_mode_light">淺色</string>
308 <string name="theme_mode_dark">深色</string> 391 <string name="theme_mode_dark">深色</string>
309 392
393 <!-- Audio output engines -->
394 <string name="cubeb">cubeb</string>
395
310 <!-- Black backgrounds theme --> 396 <!-- Black backgrounds theme -->
311 <string name="use_black_backgrounds">使用黑色背景</string> 397 <string name="use_black_backgrounds">黑色背景</string>
312 <string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string> 398 <string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string>
313 399
314</resources> 400 <!-- Picture-In-Picture -->
401 <string name="picture_in_picture">画中画</string>
402 <string name="picture_in_picture_description">模拟器ä½äºŽåŽå°æ—¶æœ€å°åŒ–窗å£</string>
403 <string name="pause">æš‚åœ</string>
404 <string name="play">开始</string>
405 <string name="mute">éœéŸ³</string>
406 <string name="unmute">å–æ¶ˆéœéŸ³</string>
407
408 <!-- Licenses screen strings -->
409 <string name="licenses">授權</string>
410 <string name="license_fidelityfx_fsr_description">來自 AMD çš„å‡ç´šåœ–åƒå“質</string>
411 </resources>
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml
index 9e4854221..c551a6106 100644
--- a/src/android/app/src/main/res/values/strings.xml
+++ b/src/android/app/src/main/res/values/strings.xml
@@ -72,7 +72,7 @@
72 <string name="invalid_keys_error">Invalid encryption keys</string> 72 <string name="invalid_keys_error">Invalid encryption keys</string>
73 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string> 73 <string name="dumping_keys_quickstart_link">https://yuzu-emu.org/help/quickstart/#dumping-decryption-keys</string>
74 <string name="install_keys_failure_description">The selected file is incorrect or corrupt. Please redump your keys.</string> 74 <string name="install_keys_failure_description">The selected file is incorrect or corrupt. Please redump your keys.</string>
75 <string name="gpu_driver_manager">GPU Driver Manager</string> 75 <string name="gpu_driver_manager">GPU driver manager</string>
76 <string name="install_gpu_driver">Install GPU driver</string> 76 <string name="install_gpu_driver">Install GPU driver</string>
77 <string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string> 77 <string name="install_gpu_driver_description">Install alternative drivers for potentially better performance or accuracy</string>
78 <string name="advanced_settings">Advanced settings</string> 78 <string name="advanced_settings">Advanced settings</string>
@@ -124,6 +124,24 @@
124 <string name="share_save_file">Share save file</string> 124 <string name="share_save_file">Share save file</string>
125 <string name="export_save_failed">Failed to export save</string> 125 <string name="export_save_failed">Failed to export save</string>
126 126
127 <!-- Applet launcher strings -->
128 <string name="applets">Applet launcher</string>
129 <string name="applets_description">Launch system applets using installed firmware</string>
130 <string name="applets_error_firmware">Firmware not installed</string>
131 <string name="applets_error_applet">Applet not available</string>
132 <string name="applets_error_description"><![CDATA[Please ensure your <a href="https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys">prod.keys</a> file and <a href="https://yuzu-emu.org/help/quickstart/#dumping-system-firmware">firmware</a> are installed and try again.]]></string>
133 <string name="album_applet">Album</string>
134 <string name="album_applet_description">See images stored in the user screenshots folder with the system photo viewer</string>
135 <string name="mii_edit_applet">Mii edit</string>
136 <string name="mii_edit_applet_description">View and edit Miis with the system editor</string>
137 <string name="cabinet_applet">Cabinet</string>
138 <string name="cabinet_applet_description">Edit and delete data stored on amiibo</string>
139 <string name="cabinet_launcher">Cabinet launcher</string>
140 <string name="cabinet_nickname_and_owner">Nickname and owner settings</string>
141 <string name="cabinet_game_data_eraser">Game data eraser</string>
142 <string name="cabinet_restorer">Restorer</string>
143 <string name="cabinet_formatter">Formatter</string>
144
127 <!-- About screen strings --> 145 <!-- About screen strings -->
128 <string name="gaia_is_not_real">Gaia isn\'t real</string> 146 <string name="gaia_is_not_real">Gaia isn\'t real</string>
129 <string name="copied_to_clipboard">Copied to clipboard</string> 147 <string name="copied_to_clipboard">Copied to clipboard</string>
diff --git a/src/android/app/src/main/res/xml/locales_config.xml b/src/android/app/src/main/res/xml/locales_config.xml
deleted file mode 100644
index 51b88d9dc..000000000
--- a/src/android/app/src/main/res/xml/locales_config.xml
+++ /dev/null
@@ -1,17 +0,0 @@
1<?xml version="1.0" encoding="utf-8"?>
2<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
3 <locale android:name="en" /> <!-- English (default) -->
4 <locale android:name="de" /> <!-- German -->
5 <locale android:name="es" /> <!-- Spanish -->
6 <locale android:name="fr" /> <!-- French -->
7 <locale android:name="it" /> <!-- Italian -->
8 <locale android:name="ja" /> <!-- Japanese -->
9 <locale android:name="nb" /> <!-- Norwegian Bokmal -->
10 <locale android:name="pl" /> <!-- Polish -->
11 <locale android:name="pt-rBR" /> <!-- Portuguese (Brazil) -->
12 <locale android:name="pt-RPT" /> <!-- Portuguese (Portugal) -->
13 <locale android:name="ru" /> <!-- Russian -->
14 <locale android:name="uk" /> <!-- Ukranian -->
15 <locale android:name="zh-rCN" /> <!-- Chinese (China) -->
16 <locale android:name="zh-rTW" /> <!-- Chinese (Taiwan) -->
17</locale-config>
diff --git a/src/audio_core/adsp/apps/opus/opus_decode_object.cpp b/src/audio_core/adsp/apps/opus/opus_decode_object.cpp
index 2c16d3769..e2b9eb566 100644
--- a/src/audio_core/adsp/apps/opus/opus_decode_object.cpp
+++ b/src/audio_core/adsp/apps/opus/opus_decode_object.cpp
@@ -1,107 +1,107 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "audio_core/adsp/apps/opus/opus_decode_object.h" 4#include "audio_core/adsp/apps/opus/opus_decode_object.h"
5#include "common/assert.h" 5#include "common/assert.h"
6 6
7namespace AudioCore::ADSP::OpusDecoder { 7namespace AudioCore::ADSP::OpusDecoder {
8namespace { 8namespace {
9bool IsValidChannelCount(u32 channel_count) { 9bool IsValidChannelCount(u32 channel_count) {
10 return channel_count == 1 || channel_count == 2; 10 return channel_count == 1 || channel_count == 2;
11} 11}
12} // namespace 12} // namespace
13 13
14u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) { 14u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) {
15 if (!IsValidChannelCount(channel_count)) { 15 if (!IsValidChannelCount(channel_count)) {
16 return 0; 16 return 0;
17 } 17 }
18 return static_cast<u32>(sizeof(OpusDecodeObject)) + opus_decoder_get_size(channel_count); 18 return static_cast<u32>(sizeof(OpusDecodeObject)) + opus_decoder_get_size(channel_count);
19} 19}
20 20
21OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) { 21OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) {
22 auto* new_decoder = reinterpret_cast<OpusDecodeObject*>(buffer); 22 auto* new_decoder = reinterpret_cast<OpusDecodeObject*>(buffer);
23 auto* comparison = reinterpret_cast<OpusDecodeObject*>(buffer2); 23 auto* comparison = reinterpret_cast<OpusDecodeObject*>(buffer2);
24 24
25 if (new_decoder->magic == DecodeObjectMagic) { 25 if (new_decoder->magic == DecodeObjectMagic) {
26 if (!new_decoder->initialized || 26 if (!new_decoder->initialized ||
27 (new_decoder->initialized && new_decoder->self == comparison)) { 27 (new_decoder->initialized && new_decoder->self == comparison)) {
28 new_decoder->state_valid = true; 28 new_decoder->state_valid = true;
29 } 29 }
30 } else { 30 } else {
31 new_decoder->initialized = false; 31 new_decoder->initialized = false;
32 new_decoder->state_valid = true; 32 new_decoder->state_valid = true;
33 } 33 }
34 return *new_decoder; 34 return *new_decoder;
35} 35}
36 36
37s32 OpusDecodeObject::InitializeDecoder(u32 sample_rate, u32 channel_count) { 37s32 OpusDecodeObject::InitializeDecoder(u32 sample_rate, u32 channel_count) {
38 if (!state_valid) { 38 if (!state_valid) {
39 return OPUS_INVALID_STATE; 39 return OPUS_INVALID_STATE;
40 } 40 }
41 41
42 if (initialized) { 42 if (initialized) {
43 return OPUS_OK; 43 return OPUS_OK;
44 } 44 }
45 45
46 // Unfortunately libopus does not expose the OpusDecoder struct publicly, so we can't include 46 // Unfortunately libopus does not expose the OpusDecoder struct publicly, so we can't include
47 // it in this class. Nintendo does not allocate memory, which is why we have a workbuffer 47 // it in this class. Nintendo does not allocate memory, which is why we have a workbuffer
48 // provided. 48 // provided.
49 // We could use _create and have libopus allocate it for us, but then we have to separately 49 // We could use _create and have libopus allocate it for us, but then we have to separately
50 // track which decoder is being used between this and multistream in order to call the correct 50 // track which decoder is being used between this and multistream in order to call the correct
51 // destroy from the host side. 51 // destroy from the host side.
52 // This is a bit cringe, but is safe as these objects are only ever initialized inside the given 52 // This is a bit cringe, but is safe as these objects are only ever initialized inside the given
53 // workbuffer, and GetWorkBufferSize will guarantee there's enough space to follow. 53 // workbuffer, and GetWorkBufferSize will guarantee there's enough space to follow.
54 decoder = (LibOpusDecoder*)(this + 1); 54 decoder = (LibOpusDecoder*)(this + 1);
55 s32 ret = opus_decoder_init(decoder, sample_rate, channel_count); 55 s32 ret = opus_decoder_init(decoder, sample_rate, channel_count);
56 if (ret == OPUS_OK) { 56 if (ret == OPUS_OK) {
57 magic = DecodeObjectMagic; 57 magic = DecodeObjectMagic;
58 initialized = true; 58 initialized = true;
59 state_valid = true; 59 state_valid = true;
60 self = this; 60 self = this;
61 final_range = 0; 61 final_range = 0;
62 } 62 }
63 return ret; 63 return ret;
64} 64}
65 65
66s32 OpusDecodeObject::Shutdown() { 66s32 OpusDecodeObject::Shutdown() {
67 if (!state_valid) { 67 if (!state_valid) {
68 return OPUS_INVALID_STATE; 68 return OPUS_INVALID_STATE;
69 } 69 }
70 70
71 if (initialized) { 71 if (initialized) {
72 magic = 0x0; 72 magic = 0x0;
73 initialized = false; 73 initialized = false;
74 state_valid = false; 74 state_valid = false;
75 self = nullptr; 75 self = nullptr;
76 final_range = 0; 76 final_range = 0;
77 decoder = nullptr; 77 decoder = nullptr;
78 } 78 }
79 return OPUS_OK; 79 return OPUS_OK;
80} 80}
81 81
82s32 OpusDecodeObject::ResetDecoder() { 82s32 OpusDecodeObject::ResetDecoder() {
83 return opus_decoder_ctl(decoder, OPUS_RESET_STATE); 83 return opus_decoder_ctl(decoder, OPUS_RESET_STATE);
84} 84}
85 85
86s32 OpusDecodeObject::Decode(u32& out_sample_count, u64 output_data, u64 output_data_size, 86s32 OpusDecodeObject::Decode(u32& out_sample_count, u64 output_data, u64 output_data_size,
87 u64 input_data, u64 input_data_size) { 87 u64 input_data, u64 input_data_size) {
88 ASSERT(initialized); 88 ASSERT(initialized);
89 out_sample_count = 0; 89 out_sample_count = 0;
90 90
91 if (!state_valid) { 91 if (!state_valid) {
92 return OPUS_INVALID_STATE; 92 return OPUS_INVALID_STATE;
93 } 93 }
94 94
95 auto ret_code_or_samples = opus_decode( 95 auto ret_code_or_samples = opus_decode(
96 decoder, reinterpret_cast<const u8*>(input_data), static_cast<opus_int32>(input_data_size), 96 decoder, reinterpret_cast<const u8*>(input_data), static_cast<opus_int32>(input_data_size),
97 reinterpret_cast<opus_int16*>(output_data), static_cast<opus_int32>(output_data_size), 0); 97 reinterpret_cast<opus_int16*>(output_data), static_cast<opus_int32>(output_data_size), 0);
98 98
99 if (ret_code_or_samples < OPUS_OK) { 99 if (ret_code_or_samples < OPUS_OK) {
100 return ret_code_or_samples; 100 return ret_code_or_samples;
101 } 101 }
102 102
103 out_sample_count = ret_code_or_samples; 103 out_sample_count = ret_code_or_samples;
104 return opus_decoder_ctl(decoder, OPUS_GET_FINAL_RANGE_REQUEST, &final_range); 104 return opus_decoder_ctl(decoder, OPUS_GET_FINAL_RANGE_REQUEST, &final_range);
105} 105}
106 106
107} // namespace AudioCore::ADSP::OpusDecoder 107} // namespace AudioCore::ADSP::OpusDecoder
diff --git a/src/audio_core/adsp/apps/opus/opus_decoder.cpp b/src/audio_core/adsp/apps/opus/opus_decoder.cpp
index 2084de128..75f0fb9ad 100644
--- a/src/audio_core/adsp/apps/opus/opus_decoder.cpp
+++ b/src/audio_core/adsp/apps/opus/opus_decoder.cpp
@@ -30,9 +30,9 @@ bool IsValidMultiStreamChannelCount(u32 channel_count) {
30 return channel_count <= OpusStreamCountMax; 30 return channel_count <= OpusStreamCountMax;
31} 31}
32 32
33bool IsValidMultiStreamStreamCounts(s32 total_stream_count, s32 sterero_stream_count) { 33bool IsValidMultiStreamStreamCounts(s32 total_stream_count, s32 stereo_stream_count) {
34 return IsValidMultiStreamChannelCount(total_stream_count) && total_stream_count > 0 && 34 return IsValidMultiStreamChannelCount(total_stream_count) && total_stream_count > 0 &&
35 sterero_stream_count > 0 && sterero_stream_count <= total_stream_count; 35 stereo_stream_count >= 0 && stereo_stream_count <= total_stream_count;
36} 36}
37} // namespace 37} // namespace
38 38
diff --git a/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp b/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp
index f6d362e68..7f1ed0450 100644
--- a/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp
+++ b/src/audio_core/adsp/apps/opus/opus_multistream_decode_object.cpp
@@ -1,111 +1,111 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "audio_core/adsp/apps/opus/opus_multistream_decode_object.h" 4#include "audio_core/adsp/apps/opus/opus_multistream_decode_object.h"
5#include "common/assert.h" 5#include "common/assert.h"
6 6
7namespace AudioCore::ADSP::OpusDecoder { 7namespace AudioCore::ADSP::OpusDecoder {
8 8
9namespace { 9namespace {
10bool IsValidChannelCount(u32 channel_count) { 10bool IsValidChannelCount(u32 channel_count) {
11 return channel_count == 1 || channel_count == 2; 11 return channel_count == 1 || channel_count == 2;
12} 12}
13 13
14bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) { 14bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) {
15 return total_stream_count > 0 && stereo_stream_count > 0 && 15 return total_stream_count > 0 && stereo_stream_count > 0 &&
16 stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count); 16 stereo_stream_count <= total_stream_count && IsValidChannelCount(total_stream_count);
17} 17}
18} // namespace 18} // namespace
19 19
20u32 OpusMultiStreamDecodeObject::GetWorkBufferSize(u32 total_stream_count, 20u32 OpusMultiStreamDecodeObject::GetWorkBufferSize(u32 total_stream_count,
21 u32 stereo_stream_count) { 21 u32 stereo_stream_count) {
22 if (IsValidStreamCounts(total_stream_count, stereo_stream_count)) { 22 if (IsValidStreamCounts(total_stream_count, stereo_stream_count)) {
23 return static_cast<u32>(sizeof(OpusMultiStreamDecodeObject)) + 23 return static_cast<u32>(sizeof(OpusMultiStreamDecodeObject)) +
24 opus_multistream_decoder_get_size(total_stream_count, stereo_stream_count); 24 opus_multistream_decoder_get_size(total_stream_count, stereo_stream_count);
25 } 25 }
26 return 0; 26 return 0;
27} 27}
28 28
29OpusMultiStreamDecodeObject& OpusMultiStreamDecodeObject::Initialize(u64 buffer, u64 buffer2) { 29OpusMultiStreamDecodeObject& OpusMultiStreamDecodeObject::Initialize(u64 buffer, u64 buffer2) {
30 auto* new_decoder = reinterpret_cast<OpusMultiStreamDecodeObject*>(buffer); 30 auto* new_decoder = reinterpret_cast<OpusMultiStreamDecodeObject*>(buffer);
31 auto* comparison = reinterpret_cast<OpusMultiStreamDecodeObject*>(buffer2); 31 auto* comparison = reinterpret_cast<OpusMultiStreamDecodeObject*>(buffer2);
32 32
33 if (new_decoder->magic == DecodeMultiStreamObjectMagic) { 33 if (new_decoder->magic == DecodeMultiStreamObjectMagic) {
34 if (!new_decoder->initialized || 34 if (!new_decoder->initialized ||
35 (new_decoder->initialized && new_decoder->self == comparison)) { 35 (new_decoder->initialized && new_decoder->self == comparison)) {
36 new_decoder->state_valid = true; 36 new_decoder->state_valid = true;
37 } 37 }
38 } else { 38 } else {
39 new_decoder->initialized = false; 39 new_decoder->initialized = false;
40 new_decoder->state_valid = true; 40 new_decoder->state_valid = true;
41 } 41 }
42 return *new_decoder; 42 return *new_decoder;
43} 43}
44 44
45s32 OpusMultiStreamDecodeObject::InitializeDecoder(u32 sample_rate, u32 total_stream_count, 45s32 OpusMultiStreamDecodeObject::InitializeDecoder(u32 sample_rate, u32 total_stream_count,
46 u32 channel_count, u32 stereo_stream_count, 46 u32 channel_count, u32 stereo_stream_count,
47 u8* mappings) { 47 u8* mappings) {
48 if (!state_valid) { 48 if (!state_valid) {
49 return OPUS_INVALID_STATE; 49 return OPUS_INVALID_STATE;
50 } 50 }
51 51
52 if (initialized) { 52 if (initialized) {
53 return OPUS_OK; 53 return OPUS_OK;
54 } 54 }
55 55
56 // See OpusDecodeObject::InitializeDecoder for an explanation of this 56 // See OpusDecodeObject::InitializeDecoder for an explanation of this
57 decoder = (LibOpusMSDecoder*)(this + 1); 57 decoder = (LibOpusMSDecoder*)(this + 1);
58 s32 ret = opus_multistream_decoder_init(decoder, sample_rate, channel_count, total_stream_count, 58 s32 ret = opus_multistream_decoder_init(decoder, sample_rate, channel_count, total_stream_count,
59 stereo_stream_count, mappings); 59 stereo_stream_count, mappings);
60 if (ret == OPUS_OK) { 60 if (ret == OPUS_OK) {
61 magic = DecodeMultiStreamObjectMagic; 61 magic = DecodeMultiStreamObjectMagic;
62 initialized = true; 62 initialized = true;
63 state_valid = true; 63 state_valid = true;
64 self = this; 64 self = this;
65 final_range = 0; 65 final_range = 0;
66 } 66 }
67 return ret; 67 return ret;
68} 68}
69 69
70s32 OpusMultiStreamDecodeObject::Shutdown() { 70s32 OpusMultiStreamDecodeObject::Shutdown() {
71 if (!state_valid) { 71 if (!state_valid) {
72 return OPUS_INVALID_STATE; 72 return OPUS_INVALID_STATE;
73 } 73 }
74 74
75 if (initialized) { 75 if (initialized) {
76 magic = 0x0; 76 magic = 0x0;
77 initialized = false; 77 initialized = false;
78 state_valid = false; 78 state_valid = false;
79 self = nullptr; 79 self = nullptr;
80 final_range = 0; 80 final_range = 0;
81 decoder = nullptr; 81 decoder = nullptr;
82 } 82 }
83 return OPUS_OK; 83 return OPUS_OK;
84} 84}
85 85
86s32 OpusMultiStreamDecodeObject::ResetDecoder() { 86s32 OpusMultiStreamDecodeObject::ResetDecoder() {
87 return opus_multistream_decoder_ctl(decoder, OPUS_RESET_STATE); 87 return opus_multistream_decoder_ctl(decoder, OPUS_RESET_STATE);
88} 88}
89 89
90s32 OpusMultiStreamDecodeObject::Decode(u32& out_sample_count, u64 output_data, 90s32 OpusMultiStreamDecodeObject::Decode(u32& out_sample_count, u64 output_data,
91 u64 output_data_size, u64 input_data, u64 input_data_size) { 91 u64 output_data_size, u64 input_data, u64 input_data_size) {
92 ASSERT(initialized); 92 ASSERT(initialized);
93 out_sample_count = 0; 93 out_sample_count = 0;
94 94
95 if (!state_valid) { 95 if (!state_valid) {
96 return OPUS_INVALID_STATE; 96 return OPUS_INVALID_STATE;
97 } 97 }
98 98
99 auto ret_code_or_samples = opus_multistream_decode( 99 auto ret_code_or_samples = opus_multistream_decode(
100 decoder, reinterpret_cast<const u8*>(input_data), static_cast<opus_int32>(input_data_size), 100 decoder, reinterpret_cast<const u8*>(input_data), static_cast<opus_int32>(input_data_size),
101 reinterpret_cast<opus_int16*>(output_data), static_cast<opus_int32>(output_data_size), 0); 101 reinterpret_cast<opus_int16*>(output_data), static_cast<opus_int32>(output_data_size), 0);
102 102
103 if (ret_code_or_samples < OPUS_OK) { 103 if (ret_code_or_samples < OPUS_OK) {
104 return ret_code_or_samples; 104 return ret_code_or_samples;
105 } 105 }
106 106
107 out_sample_count = ret_code_or_samples; 107 out_sample_count = ret_code_or_samples;
108 return opus_multistream_decoder_ctl(decoder, OPUS_GET_FINAL_RANGE_REQUEST, &final_range); 108 return opus_multistream_decoder_ctl(decoder, OPUS_GET_FINAL_RANGE_REQUEST, &final_range);
109} 109}
110 110
111} // namespace AudioCore::ADSP::OpusDecoder 111} // namespace AudioCore::ADSP::OpusDecoder
diff --git a/src/audio_core/opus/decoder.cpp b/src/audio_core/opus/decoder.cpp
index 5b23fce14..c6fd45f47 100644
--- a/src/audio_core/opus/decoder.cpp
+++ b/src/audio_core/opus/decoder.cpp
@@ -1,179 +1,179 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "audio_core/opus/decoder.h" 4#include "audio_core/opus/decoder.h"
5#include "audio_core/opus/hardware_opus.h" 5#include "audio_core/opus/hardware_opus.h"
6#include "audio_core/opus/parameters.h" 6#include "audio_core/opus/parameters.h"
7#include "common/alignment.h" 7#include "common/alignment.h"
8#include "common/swap.h" 8#include "common/swap.h"
9#include "core/core.h" 9#include "core/core.h"
10 10
11namespace AudioCore::OpusDecoder { 11namespace AudioCore::OpusDecoder {
12using namespace Service::Audio; 12using namespace Service::Audio;
13namespace { 13namespace {
14OpusPacketHeader ReverseHeader(OpusPacketHeader header) { 14OpusPacketHeader ReverseHeader(OpusPacketHeader header) {
15 OpusPacketHeader out; 15 OpusPacketHeader out;
16 out.size = Common::swap32(header.size); 16 out.size = Common::swap32(header.size);
17 out.final_range = Common::swap32(header.final_range); 17 out.final_range = Common::swap32(header.final_range);
18 return out; 18 return out;
19} 19}
20} // namespace 20} // namespace
21 21
22OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_) 22OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_)
23 : system{system_}, hardware_opus{hardware_opus_} {} 23 : system{system_}, hardware_opus{hardware_opus_} {}
24 24
25OpusDecoder::~OpusDecoder() { 25OpusDecoder::~OpusDecoder() {
26 if (decode_object_initialized) { 26 if (decode_object_initialized) {
27 hardware_opus.ShutdownDecodeObject(shared_buffer.get(), shared_buffer_size); 27 hardware_opus.ShutdownDecodeObject(shared_buffer.get(), shared_buffer_size);
28 } 28 }
29} 29}
30 30
31Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, 31Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
32 u64 transfer_memory_size) { 32 u64 transfer_memory_size) {
33 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 33 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
34 shared_buffer_size = transfer_memory_size; 34 shared_buffer_size = transfer_memory_size;
35 shared_buffer = std::make_unique<u8[]>(shared_buffer_size); 35 shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
36 shared_memory_mapped = true; 36 shared_memory_mapped = true;
37 37
38 buffer_size = 38 buffer_size =
39 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); 39 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16);
40 40
41 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; 41 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size};
42 size_t in_data_size{0x600u}; 42 size_t in_data_size{0x600u};
43 in_data = {out_data.data() - in_data_size, in_data_size}; 43 in_data = {out_data.data() - in_data_size, in_data_size};
44 44
45 ON_RESULT_FAILURE { 45 ON_RESULT_FAILURE {
46 if (shared_memory_mapped) { 46 if (shared_memory_mapped) {
47 shared_memory_mapped = false; 47 shared_memory_mapped = false;
48 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); 48 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size)));
49 } 49 }
50 }; 50 };
51 51
52 R_TRY(hardware_opus.InitializeDecodeObject(params.sample_rate, params.channel_count, 52 R_TRY(hardware_opus.InitializeDecodeObject(params.sample_rate, params.channel_count,
53 shared_buffer.get(), shared_buffer_size)); 53 shared_buffer.get(), shared_buffer_size));
54 54
55 sample_rate = params.sample_rate; 55 sample_rate = params.sample_rate;
56 channel_count = params.channel_count; 56 channel_count = params.channel_count;
57 use_large_frame_size = params.use_large_frame_size; 57 use_large_frame_size = params.use_large_frame_size;
58 decode_object_initialized = true; 58 decode_object_initialized = true;
59 R_SUCCEED(); 59 R_SUCCEED();
60} 60}
61 61
62Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params, 62Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params,
63 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) { 63 Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size) {
64 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 64 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
65 shared_buffer_size = transfer_memory_size; 65 shared_buffer_size = transfer_memory_size;
66 shared_buffer = std::make_unique<u8[]>(shared_buffer_size); 66 shared_buffer = std::make_unique<u8[]>(shared_buffer_size);
67 shared_memory_mapped = true; 67 shared_memory_mapped = true;
68 68
69 buffer_size = 69 buffer_size =
70 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16); 70 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 16);
71 71
72 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size}; 72 out_data = {shared_buffer.get() + shared_buffer_size - buffer_size, buffer_size};
73 size_t in_data_size{Common::AlignUp(1500ull * params.total_stream_count, 64u)}; 73 size_t in_data_size{Common::AlignUp(1500ull * params.total_stream_count, 64u)};
74 in_data = {out_data.data() - in_data_size, in_data_size}; 74 in_data = {out_data.data() - in_data_size, in_data_size};
75 75
76 ON_RESULT_FAILURE { 76 ON_RESULT_FAILURE {
77 if (shared_memory_mapped) { 77 if (shared_memory_mapped) {
78 shared_memory_mapped = false; 78 shared_memory_mapped = false;
79 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size))); 79 ASSERT(R_SUCCEEDED(hardware_opus.UnmapMemory(shared_buffer.get(), shared_buffer_size)));
80 } 80 }
81 }; 81 };
82 82
83 R_TRY(hardware_opus.InitializeMultiStreamDecodeObject( 83 R_TRY(hardware_opus.InitializeMultiStreamDecodeObject(
84 params.sample_rate, params.channel_count, params.total_stream_count, 84 params.sample_rate, params.channel_count, params.total_stream_count,
85 params.stereo_stream_count, params.mappings.data(), shared_buffer.get(), 85 params.stereo_stream_count, params.mappings.data(), shared_buffer.get(),
86 shared_buffer_size)); 86 shared_buffer_size));
87 87
88 sample_rate = params.sample_rate; 88 sample_rate = params.sample_rate;
89 channel_count = params.channel_count; 89 channel_count = params.channel_count;
90 total_stream_count = params.total_stream_count; 90 total_stream_count = params.total_stream_count;
91 stereo_stream_count = params.stereo_stream_count; 91 stereo_stream_count = params.stereo_stream_count;
92 use_large_frame_size = params.use_large_frame_size; 92 use_large_frame_size = params.use_large_frame_size;
93 decode_object_initialized = true; 93 decode_object_initialized = true;
94 R_SUCCEED(); 94 R_SUCCEED();
95} 95}
96 96
97Result OpusDecoder::DecodeInterleaved(u32* out_data_size, u64* out_time_taken, 97Result OpusDecoder::DecodeInterleaved(u32* out_data_size, u64* out_time_taken,
98 u32* out_sample_count, std::span<const u8> input_data, 98 u32* out_sample_count, std::span<const u8> input_data,
99 std::span<u8> output_data, bool reset) { 99 std::span<u8> output_data, bool reset) {
100 u32 out_samples; 100 u32 out_samples;
101 u64 time_taken{}; 101 u64 time_taken{};
102 102
103 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); 103 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall);
104 104
105 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())}; 105 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
106 OpusPacketHeader header{ReverseHeader(*header_p)}; 106 OpusPacketHeader header{ReverseHeader(*header_p)};
107 107
108 R_UNLESS(in_data.size_bytes() >= header.size && 108 R_UNLESS(in_data.size_bytes() >= header.size &&
109 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), 109 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(),
110 ResultBufferTooSmall); 110 ResultBufferTooSmall);
111 111
112 if (!shared_memory_mapped) { 112 if (!shared_memory_mapped) {
113 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); 113 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size));
114 shared_memory_mapped = true; 114 shared_memory_mapped = true;
115 } 115 }
116 116
117 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); 117 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size);
118 118
119 R_TRY(hardware_opus.DecodeInterleaved(out_samples, out_data.data(), out_data.size_bytes(), 119 R_TRY(hardware_opus.DecodeInterleaved(out_samples, out_data.data(), out_data.size_bytes(),
120 channel_count, in_data.data(), header.size, 120 channel_count, in_data.data(), header.size,
121 shared_buffer.get(), time_taken, reset)); 121 shared_buffer.get(), time_taken, reset));
122 122
123 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); 123 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16));
124 124
125 *out_data_size = header.size + sizeof(OpusPacketHeader); 125 *out_data_size = header.size + sizeof(OpusPacketHeader);
126 *out_sample_count = out_samples; 126 *out_sample_count = out_samples;
127 if (out_time_taken) { 127 if (out_time_taken) {
128 *out_time_taken = time_taken / 1000; 128 *out_time_taken = time_taken / 1000;
129 } 129 }
130 R_SUCCEED(); 130 R_SUCCEED();
131} 131}
132 132
133Result OpusDecoder::SetContext([[maybe_unused]] std::span<const u8> context) { 133Result OpusDecoder::SetContext([[maybe_unused]] std::span<const u8> context) {
134 R_SUCCEED_IF(shared_memory_mapped); 134 R_SUCCEED_IF(shared_memory_mapped);
135 shared_memory_mapped = true; 135 shared_memory_mapped = true;
136 R_RETURN(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); 136 R_RETURN(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size));
137} 137}
138 138
139Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, 139Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken,
140 u32* out_sample_count, 140 u32* out_sample_count,
141 std::span<const u8> input_data, 141 std::span<const u8> input_data,
142 std::span<u8> output_data, bool reset) { 142 std::span<u8> output_data, bool reset) {
143 u32 out_samples; 143 u32 out_samples;
144 u64 time_taken{}; 144 u64 time_taken{};
145 145
146 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall); 146 R_UNLESS(input_data.size_bytes() > sizeof(OpusPacketHeader), ResultInputDataTooSmall);
147 147
148 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())}; 148 auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
149 OpusPacketHeader header{ReverseHeader(*header_p)}; 149 OpusPacketHeader header{ReverseHeader(*header_p)};
150 150
151 LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}", 151 LOG_ERROR(Service_Audio, "header size 0x{:X} input data size 0x{:X} in_data size 0x{:X}",
152 header.size, input_data.size_bytes(), in_data.size_bytes()); 152 header.size, input_data.size_bytes(), in_data.size_bytes());
153 153
154 R_UNLESS(in_data.size_bytes() >= header.size && 154 R_UNLESS(in_data.size_bytes() >= header.size &&
155 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(), 155 header.size + sizeof(OpusPacketHeader) <= input_data.size_bytes(),
156 ResultBufferTooSmall); 156 ResultBufferTooSmall);
157 157
158 if (!shared_memory_mapped) { 158 if (!shared_memory_mapped) {
159 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size)); 159 R_TRY(hardware_opus.MapMemory(shared_buffer.get(), shared_buffer_size));
160 shared_memory_mapped = true; 160 shared_memory_mapped = true;
161 } 161 }
162 162
163 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size); 163 std::memcpy(in_data.data(), input_data.data() + sizeof(OpusPacketHeader), header.size);
164 164
165 R_TRY(hardware_opus.DecodeInterleavedForMultiStream( 165 R_TRY(hardware_opus.DecodeInterleavedForMultiStream(
166 out_samples, out_data.data(), out_data.size_bytes(), channel_count, in_data.data(), 166 out_samples, out_data.data(), out_data.size_bytes(), channel_count, in_data.data(),
167 header.size, shared_buffer.get(), time_taken, reset)); 167 header.size, shared_buffer.get(), time_taken, reset));
168 168
169 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16)); 169 std::memcpy(output_data.data(), out_data.data(), out_samples * channel_count * sizeof(s16));
170 170
171 *out_data_size = header.size + sizeof(OpusPacketHeader); 171 *out_data_size = header.size + sizeof(OpusPacketHeader);
172 *out_sample_count = out_samples; 172 *out_sample_count = out_samples;
173 if (out_time_taken) { 173 if (out_time_taken) {
174 *out_time_taken = time_taken / 1000; 174 *out_time_taken = time_taken / 1000;
175 } 175 }
176 R_SUCCEED(); 176 R_SUCCEED();
177} 177}
178 178
179} // namespace AudioCore::OpusDecoder 179} // namespace AudioCore::OpusDecoder
diff --git a/src/audio_core/opus/decoder.h b/src/audio_core/opus/decoder.h
index d08d8a4a4..fd728958a 100644
--- a/src/audio_core/opus/decoder.h
+++ b/src/audio_core/opus/decoder.h
@@ -1,53 +1,53 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include <span> 6#include <span>
7 7
8#include "audio_core/opus/parameters.h" 8#include "audio_core/opus/parameters.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/hle/kernel/k_transfer_memory.h" 10#include "core/hle/kernel/k_transfer_memory.h"
11#include "core/hle/service/audio/errors.h" 11#include "core/hle/service/audio/errors.h"
12 12
13namespace Core { 13namespace Core {
14class System; 14class System;
15} 15}
16 16
17namespace AudioCore::OpusDecoder { 17namespace AudioCore::OpusDecoder {
18class HardwareOpus; 18class HardwareOpus;
19 19
20class OpusDecoder { 20class OpusDecoder {
21public: 21public:
22 explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_); 22 explicit OpusDecoder(Core::System& system, HardwareOpus& hardware_opus_);
23 ~OpusDecoder(); 23 ~OpusDecoder();
24 24
25 Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, 25 Result Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory,
26 u64 transfer_memory_size); 26 u64 transfer_memory_size);
27 Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory, 27 Result Initialize(OpusMultiStreamParametersEx& params, Kernel::KTransferMemory* transfer_memory,
28 u64 transfer_memory_size); 28 u64 transfer_memory_size);
29 Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count, 29 Result DecodeInterleaved(u32* out_data_size, u64* out_time_taken, u32* out_sample_count,
30 std::span<const u8> input_data, std::span<u8> output_data, bool reset); 30 std::span<const u8> input_data, std::span<u8> output_data, bool reset);
31 Result SetContext([[maybe_unused]] std::span<const u8> context); 31 Result SetContext([[maybe_unused]] std::span<const u8> context);
32 Result DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, 32 Result DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken,
33 u32* out_sample_count, std::span<const u8> input_data, 33 u32* out_sample_count, std::span<const u8> input_data,
34 std::span<u8> output_data, bool reset); 34 std::span<u8> output_data, bool reset);
35 35
36private: 36private:
37 Core::System& system; 37 Core::System& system;
38 HardwareOpus& hardware_opus; 38 HardwareOpus& hardware_opus;
39 std::unique_ptr<u8[]> shared_buffer{}; 39 std::unique_ptr<u8[]> shared_buffer{};
40 u64 shared_buffer_size; 40 u64 shared_buffer_size;
41 std::span<u8> in_data{}; 41 std::span<u8> in_data{};
42 std::span<u8> out_data{}; 42 std::span<u8> out_data{};
43 u64 buffer_size{}; 43 u64 buffer_size{};
44 s32 sample_rate{}; 44 s32 sample_rate{};
45 s32 channel_count{}; 45 s32 channel_count{};
46 bool use_large_frame_size{false}; 46 bool use_large_frame_size{false};
47 s32 total_stream_count{}; 47 s32 total_stream_count{};
48 s32 stereo_stream_count{}; 48 s32 stereo_stream_count{};
49 bool shared_memory_mapped{false}; 49 bool shared_memory_mapped{false};
50 bool decode_object_initialized{false}; 50 bool decode_object_initialized{false};
51}; 51};
52 52
53} // namespace AudioCore::OpusDecoder 53} // namespace AudioCore::OpusDecoder
diff --git a/src/audio_core/opus/decoder_manager.cpp b/src/audio_core/opus/decoder_manager.cpp
index 4a5382973..1464880a1 100644
--- a/src/audio_core/opus/decoder_manager.cpp
+++ b/src/audio_core/opus/decoder_manager.cpp
@@ -1,102 +1,102 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "audio_core/adsp/apps/opus/opus_decoder.h" 4#include "audio_core/adsp/apps/opus/opus_decoder.h"
5#include "audio_core/opus/decoder_manager.h" 5#include "audio_core/opus/decoder_manager.h"
6#include "common/alignment.h" 6#include "common/alignment.h"
7#include "core/core.h" 7#include "core/core.h"
8 8
9namespace AudioCore::OpusDecoder { 9namespace AudioCore::OpusDecoder {
10using namespace Service::Audio; 10using namespace Service::Audio;
11 11
12namespace { 12namespace {
13bool IsValidChannelCount(u32 channel_count) { 13bool IsValidChannelCount(u32 channel_count) {
14 return channel_count == 1 || channel_count == 2; 14 return channel_count == 1 || channel_count == 2;
15} 15}
16 16
17bool IsValidMultiStreamChannelCount(u32 channel_count) { 17bool IsValidMultiStreamChannelCount(u32 channel_count) {
18 return channel_count > 0 && channel_count <= OpusStreamCountMax; 18 return channel_count > 0 && channel_count <= OpusStreamCountMax;
19} 19}
20 20
21bool IsValidSampleRate(u32 sample_rate) { 21bool IsValidSampleRate(u32 sample_rate) {
22 return sample_rate == 8'000 || sample_rate == 12'000 || sample_rate == 16'000 || 22 return sample_rate == 8'000 || sample_rate == 12'000 || sample_rate == 16'000 ||
23 sample_rate == 24'000 || sample_rate == 48'000; 23 sample_rate == 24'000 || sample_rate == 48'000;
24} 24}
25 25
26bool IsValidStreamCount(u32 channel_count, u32 total_stream_count, u32 stereo_stream_count) { 26bool IsValidStreamCount(u32 channel_count, u32 total_stream_count, u32 stereo_stream_count) {
27 return total_stream_count > 0 && stereo_stream_count > 0 && 27 return total_stream_count > 0 && static_cast<s32>(stereo_stream_count) >= 0 &&
28 stereo_stream_count <= total_stream_count && 28 stereo_stream_count <= total_stream_count &&
29 total_stream_count + stereo_stream_count <= channel_count; 29 total_stream_count + stereo_stream_count <= channel_count;
30} 30}
31 31
32} // namespace 32} // namespace
33 33
34OpusDecoderManager::OpusDecoderManager(Core::System& system_) 34OpusDecoderManager::OpusDecoderManager(Core::System& system_)
35 : system{system_}, hardware_opus{system} { 35 : system{system_}, hardware_opus{system} {
36 for (u32 i = 0; i < MaxChannels; i++) { 36 for (u32 i = 0; i < MaxChannels; i++) {
37 required_workbuffer_sizes[i] = hardware_opus.GetWorkBufferSize(1 + i); 37 required_workbuffer_sizes[i] = hardware_opus.GetWorkBufferSize(1 + i);
38 } 38 }
39} 39}
40 40
41Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) { 41Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) {
42 OpusParametersEx ex{ 42 OpusParametersEx ex{
43 .sample_rate = params.sample_rate, 43 .sample_rate = params.sample_rate,
44 .channel_count = params.channel_count, 44 .channel_count = params.channel_count,
45 .use_large_frame_size = false, 45 .use_large_frame_size = false,
46 }; 46 };
47 R_RETURN(GetWorkBufferSizeExEx(ex, out_size)); 47 R_RETURN(GetWorkBufferSizeExEx(ex, out_size));
48} 48}
49 49
50Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) { 50Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) {
51 R_RETURN(GetWorkBufferSizeExEx(params, out_size)); 51 R_RETURN(GetWorkBufferSizeExEx(params, out_size));
52} 52}
53 53
54Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) { 54Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) {
55 R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount); 55 R_UNLESS(IsValidChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
56 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); 56 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
57 57
58 auto work_buffer_size{required_workbuffer_sizes[params.channel_count - 1]}; 58 auto work_buffer_size{required_workbuffer_sizes[params.channel_count - 1]};
59 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 59 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
60 work_buffer_size += 60 work_buffer_size +=
61 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64); 61 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64);
62 out_size = work_buffer_size + 0x600; 62 out_size = work_buffer_size + 0x600;
63 R_SUCCEED(); 63 R_SUCCEED();
64} 64}
65 65
66Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, 66Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params,
67 u64& out_size) { 67 u64& out_size) {
68 OpusMultiStreamParametersEx ex{ 68 OpusMultiStreamParametersEx ex{
69 .sample_rate = params.sample_rate, 69 .sample_rate = params.sample_rate,
70 .channel_count = params.channel_count, 70 .channel_count = params.channel_count,
71 .total_stream_count = params.total_stream_count, 71 .total_stream_count = params.total_stream_count,
72 .stereo_stream_count = params.stereo_stream_count, 72 .stereo_stream_count = params.stereo_stream_count,
73 .use_large_frame_size = false, 73 .use_large_frame_size = false,
74 .mappings = {}, 74 .mappings = {},
75 }; 75 };
76 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size)); 76 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(ex, out_size));
77} 77}
78 78
79Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, 79Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params,
80 u64& out_size) { 80 u64& out_size) {
81 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size)); 81 R_RETURN(GetWorkBufferSizeForMultiStreamExEx(params, out_size));
82} 82}
83 83
84Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, 84Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params,
85 u64& out_size) { 85 u64& out_size) {
86 R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount); 86 R_UNLESS(IsValidMultiStreamChannelCount(params.channel_count), ResultInvalidOpusChannelCount);
87 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate); 87 R_UNLESS(IsValidSampleRate(params.sample_rate), ResultInvalidOpusSampleRate);
88 R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count, 88 R_UNLESS(IsValidStreamCount(params.channel_count, params.total_stream_count,
89 params.stereo_stream_count), 89 params.stereo_stream_count),
90 ResultInvalidOpusSampleRate); 90 ResultInvalidOpusSampleRate);
91 91
92 auto work_buffer_size{hardware_opus.GetWorkBufferSizeForMultiStream( 92 auto work_buffer_size{hardware_opus.GetWorkBufferSizeForMultiStream(
93 params.total_stream_count, params.stereo_stream_count)}; 93 params.total_stream_count, params.stereo_stream_count)};
94 auto frame_size{params.use_large_frame_size ? 5760 : 1920}; 94 auto frame_size{params.use_large_frame_size ? 5760 : 1920};
95 work_buffer_size += Common::AlignUp(1500 * params.total_stream_count, 64); 95 work_buffer_size += Common::AlignUp(1500 * params.total_stream_count, 64);
96 work_buffer_size += 96 work_buffer_size +=
97 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64); 97 Common::AlignUp((frame_size * params.channel_count) / (48'000 / params.sample_rate), 64);
98 out_size = work_buffer_size; 98 out_size = work_buffer_size;
99 R_SUCCEED(); 99 R_SUCCEED();
100} 100}
101 101
102} // namespace AudioCore::OpusDecoder 102} // namespace AudioCore::OpusDecoder
diff --git a/src/audio_core/opus/decoder_manager.h b/src/audio_core/opus/decoder_manager.h
index 466e1967b..70ebc4bab 100644
--- a/src/audio_core/opus/decoder_manager.h
+++ b/src/audio_core/opus/decoder_manager.h
@@ -1,38 +1,38 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include "audio_core/opus/hardware_opus.h" 6#include "audio_core/opus/hardware_opus.h"
7#include "audio_core/opus/parameters.h" 7#include "audio_core/opus/parameters.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/hle/service/audio/errors.h" 9#include "core/hle/service/audio/errors.h"
10 10
11namespace Core { 11namespace Core {
12class System; 12class System;
13} 13}
14 14
15namespace AudioCore::OpusDecoder { 15namespace AudioCore::OpusDecoder {
16 16
17class OpusDecoderManager { 17class OpusDecoderManager {
18public: 18public:
19 OpusDecoderManager(Core::System& system); 19 OpusDecoderManager(Core::System& system);
20 20
21 HardwareOpus& GetHardwareOpus() { 21 HardwareOpus& GetHardwareOpus() {
22 return hardware_opus; 22 return hardware_opus;
23 } 23 }
24 24
25 Result GetWorkBufferSize(OpusParameters& params, u64& out_size); 25 Result GetWorkBufferSize(OpusParameters& params, u64& out_size);
26 Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size); 26 Result GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size);
27 Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size); 27 Result GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size);
28 Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size); 28 Result GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, u64& out_size);
29 Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size); 29 Result GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, u64& out_size);
30 Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size); 30 Result GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, u64& out_size);
31 31
32private: 32private:
33 Core::System& system; 33 Core::System& system;
34 HardwareOpus hardware_opus; 34 HardwareOpus hardware_opus;
35 std::array<u64, MaxChannels> required_workbuffer_sizes{}; 35 std::array<u64, MaxChannels> required_workbuffer_sizes{};
36}; 36};
37 37
38} // namespace AudioCore::OpusDecoder 38} // namespace AudioCore::OpusDecoder
diff --git a/src/audio_core/opus/hardware_opus.cpp b/src/audio_core/opus/hardware_opus.cpp
index d6544dcb0..5ff71ab2d 100644
--- a/src/audio_core/opus/hardware_opus.cpp
+++ b/src/audio_core/opus/hardware_opus.cpp
@@ -1,241 +1,241 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <array> 4#include <array>
5 5
6#include "audio_core/audio_core.h" 6#include "audio_core/audio_core.h"
7#include "audio_core/opus/hardware_opus.h" 7#include "audio_core/opus/hardware_opus.h"
8#include "core/core.h" 8#include "core/core.h"
9 9
10namespace AudioCore::OpusDecoder { 10namespace AudioCore::OpusDecoder {
11namespace { 11namespace {
12using namespace Service::Audio; 12using namespace Service::Audio;
13 13
14static constexpr Result ResultCodeFromLibOpusErrorCode(u64 error_code) { 14static constexpr Result ResultCodeFromLibOpusErrorCode(u64 error_code) {
15 s32 error{static_cast<s32>(error_code)}; 15 s32 error{static_cast<s32>(error_code)};
16 ASSERT(error <= OPUS_OK); 16 ASSERT(error <= OPUS_OK);
17 switch (error) { 17 switch (error) {
18 case OPUS_ALLOC_FAIL: 18 case OPUS_ALLOC_FAIL:
19 R_THROW(ResultLibOpusAllocFail); 19 R_THROW(ResultLibOpusAllocFail);
20 case OPUS_INVALID_STATE: 20 case OPUS_INVALID_STATE:
21 R_THROW(ResultLibOpusInvalidState); 21 R_THROW(ResultLibOpusInvalidState);
22 case OPUS_UNIMPLEMENTED: 22 case OPUS_UNIMPLEMENTED:
23 R_THROW(ResultLibOpusUnimplemented); 23 R_THROW(ResultLibOpusUnimplemented);
24 case OPUS_INVALID_PACKET: 24 case OPUS_INVALID_PACKET:
25 R_THROW(ResultLibOpusInvalidPacket); 25 R_THROW(ResultLibOpusInvalidPacket);
26 case OPUS_INTERNAL_ERROR: 26 case OPUS_INTERNAL_ERROR:
27 R_THROW(ResultLibOpusInternalError); 27 R_THROW(ResultLibOpusInternalError);
28 case OPUS_BUFFER_TOO_SMALL: 28 case OPUS_BUFFER_TOO_SMALL:
29 R_THROW(ResultBufferTooSmall); 29 R_THROW(ResultBufferTooSmall);
30 case OPUS_BAD_ARG: 30 case OPUS_BAD_ARG:
31 R_THROW(ResultLibOpusBadArg); 31 R_THROW(ResultLibOpusBadArg);
32 case OPUS_OK: 32 case OPUS_OK:
33 R_RETURN(ResultSuccess); 33 R_RETURN(ResultSuccess);
34 } 34 }
35 UNREACHABLE(); 35 UNREACHABLE();
36} 36}
37 37
38} // namespace 38} // namespace
39 39
40HardwareOpus::HardwareOpus(Core::System& system_) 40HardwareOpus::HardwareOpus(Core::System& system_)
41 : system{system_}, opus_decoder{system.AudioCore().ADSP().OpusDecoder()} { 41 : system{system_}, opus_decoder{system.AudioCore().ADSP().OpusDecoder()} {
42 opus_decoder.SetSharedMemory(shared_memory); 42 opus_decoder.SetSharedMemory(shared_memory);
43} 43}
44 44
45u64 HardwareOpus::GetWorkBufferSize(u32 channel) { 45u64 HardwareOpus::GetWorkBufferSize(u32 channel) {
46 if (!opus_decoder.IsRunning()) { 46 if (!opus_decoder.IsRunning()) {
47 return 0; 47 return 0;
48 } 48 }
49 std::scoped_lock l{mutex}; 49 std::scoped_lock l{mutex};
50 shared_memory.host_send_data[0] = channel; 50 shared_memory.host_send_data[0] = channel;
51 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::GetWorkBufferSize); 51 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::GetWorkBufferSize);
52 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 52 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
53 if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeOK) { 53 if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeOK) {
54 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 54 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
55 ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg); 55 ADSP::OpusDecoder::Message::GetWorkBufferSizeOK, msg);
56 return 0; 56 return 0;
57 } 57 }
58 return shared_memory.dsp_return_data[0]; 58 return shared_memory.dsp_return_data[0];
59} 59}
60 60
61u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) { 61u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) {
62 std::scoped_lock l{mutex}; 62 std::scoped_lock l{mutex};
63 shared_memory.host_send_data[0] = total_stream_count; 63 shared_memory.host_send_data[0] = total_stream_count;
64 shared_memory.host_send_data[1] = stereo_stream_count; 64 shared_memory.host_send_data[1] = stereo_stream_count;
65 opus_decoder.Send(ADSP::Direction::DSP, 65 opus_decoder.Send(ADSP::Direction::DSP,
66 ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStream); 66 ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStream);
67 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 67 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
68 if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK) { 68 if (msg != ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK) {
69 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 69 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
70 ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg); 70 ADSP::OpusDecoder::Message::GetWorkBufferSizeForMultiStreamOK, msg);
71 return 0; 71 return 0;
72 } 72 }
73 return shared_memory.dsp_return_data[0]; 73 return shared_memory.dsp_return_data[0];
74} 74}
75 75
76Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, 76Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
77 u64 buffer_size) { 77 u64 buffer_size) {
78 std::scoped_lock l{mutex}; 78 std::scoped_lock l{mutex};
79 shared_memory.host_send_data[0] = (u64)buffer; 79 shared_memory.host_send_data[0] = (u64)buffer;
80 shared_memory.host_send_data[1] = buffer_size; 80 shared_memory.host_send_data[1] = buffer_size;
81 shared_memory.host_send_data[2] = sample_rate; 81 shared_memory.host_send_data[2] = sample_rate;
82 shared_memory.host_send_data[3] = channel_count; 82 shared_memory.host_send_data[3] = channel_count;
83 83
84 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::InitializeDecodeObject); 84 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::InitializeDecodeObject);
85 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 85 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
86 if (msg != ADSP::OpusDecoder::Message::InitializeDecodeObjectOK) { 86 if (msg != ADSP::OpusDecoder::Message::InitializeDecodeObjectOK) {
87 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 87 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
88 ADSP::OpusDecoder::Message::InitializeDecodeObjectOK, msg); 88 ADSP::OpusDecoder::Message::InitializeDecodeObjectOK, msg);
89 R_THROW(ResultInvalidOpusDSPReturnCode); 89 R_THROW(ResultInvalidOpusDSPReturnCode);
90 } 90 }
91 91
92 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); 92 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0]));
93} 93}
94 94
95Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, 95Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
96 u32 total_stream_count, 96 u32 total_stream_count,
97 u32 stereo_stream_count, void* mappings, 97 u32 stereo_stream_count, void* mappings,
98 void* buffer, u64 buffer_size) { 98 void* buffer, u64 buffer_size) {
99 std::scoped_lock l{mutex}; 99 std::scoped_lock l{mutex};
100 shared_memory.host_send_data[0] = (u64)buffer; 100 shared_memory.host_send_data[0] = (u64)buffer;
101 shared_memory.host_send_data[1] = buffer_size; 101 shared_memory.host_send_data[1] = buffer_size;
102 shared_memory.host_send_data[2] = sample_rate; 102 shared_memory.host_send_data[2] = sample_rate;
103 shared_memory.host_send_data[3] = channel_count; 103 shared_memory.host_send_data[3] = channel_count;
104 shared_memory.host_send_data[4] = total_stream_count; 104 shared_memory.host_send_data[4] = total_stream_count;
105 shared_memory.host_send_data[5] = stereo_stream_count; 105 shared_memory.host_send_data[5] = stereo_stream_count;
106 106
107 ASSERT(channel_count <= MaxChannels); 107 ASSERT(channel_count <= MaxChannels);
108 std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8)); 108 std::memcpy(shared_memory.channel_mapping.data(), mappings, channel_count * sizeof(u8));
109 109
110 opus_decoder.Send(ADSP::Direction::DSP, 110 opus_decoder.Send(ADSP::Direction::DSP,
111 ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObject); 111 ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObject);
112 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 112 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
113 if (msg != ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK) { 113 if (msg != ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK) {
114 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 114 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
115 ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK, msg); 115 ADSP::OpusDecoder::Message::InitializeMultiStreamDecodeObjectOK, msg);
116 R_THROW(ResultInvalidOpusDSPReturnCode); 116 R_THROW(ResultInvalidOpusDSPReturnCode);
117 } 117 }
118 118
119 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); 119 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0]));
120} 120}
121 121
122Result HardwareOpus::ShutdownDecodeObject(void* buffer, u64 buffer_size) { 122Result HardwareOpus::ShutdownDecodeObject(void* buffer, u64 buffer_size) {
123 std::scoped_lock l{mutex}; 123 std::scoped_lock l{mutex};
124 shared_memory.host_send_data[0] = (u64)buffer; 124 shared_memory.host_send_data[0] = (u64)buffer;
125 shared_memory.host_send_data[1] = buffer_size; 125 shared_memory.host_send_data[1] = buffer_size;
126 126
127 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::ShutdownDecodeObject); 127 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::ShutdownDecodeObject);
128 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 128 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
129 ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK, 129 ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK,
130 "Expected Opus shutdown code {}, got {}", 130 "Expected Opus shutdown code {}, got {}",
131 ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK, msg); 131 ADSP::OpusDecoder::Message::ShutdownDecodeObjectOK, msg);
132 132
133 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); 133 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0]));
134} 134}
135 135
136Result HardwareOpus::ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size) { 136Result HardwareOpus::ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size) {
137 std::scoped_lock l{mutex}; 137 std::scoped_lock l{mutex};
138 shared_memory.host_send_data[0] = (u64)buffer; 138 shared_memory.host_send_data[0] = (u64)buffer;
139 shared_memory.host_send_data[1] = buffer_size; 139 shared_memory.host_send_data[1] = buffer_size;
140 140
141 opus_decoder.Send(ADSP::Direction::DSP, 141 opus_decoder.Send(ADSP::Direction::DSP,
142 ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObject); 142 ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObject);
143 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 143 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
144 ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK, 144 ASSERT_MSG(msg == ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK,
145 "Expected Opus shutdown code {}, got {}", 145 "Expected Opus shutdown code {}, got {}",
146 ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK, msg); 146 ADSP::OpusDecoder::Message::ShutdownMultiStreamDecodeObjectOK, msg);
147 147
148 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0])); 148 R_RETURN(ResultCodeFromLibOpusErrorCode(shared_memory.dsp_return_data[0]));
149} 149}
150 150
151Result HardwareOpus::DecodeInterleaved(u32& out_sample_count, void* output_data, 151Result HardwareOpus::DecodeInterleaved(u32& out_sample_count, void* output_data,
152 u64 output_data_size, u32 channel_count, void* input_data, 152 u64 output_data_size, u32 channel_count, void* input_data,
153 u64 input_data_size, void* buffer, u64& out_time_taken, 153 u64 input_data_size, void* buffer, u64& out_time_taken,
154 bool reset) { 154 bool reset) {
155 std::scoped_lock l{mutex}; 155 std::scoped_lock l{mutex};
156 shared_memory.host_send_data[0] = (u64)buffer; 156 shared_memory.host_send_data[0] = (u64)buffer;
157 shared_memory.host_send_data[1] = (u64)input_data; 157 shared_memory.host_send_data[1] = (u64)input_data;
158 shared_memory.host_send_data[2] = input_data_size; 158 shared_memory.host_send_data[2] = input_data_size;
159 shared_memory.host_send_data[3] = (u64)output_data; 159 shared_memory.host_send_data[3] = (u64)output_data;
160 shared_memory.host_send_data[4] = output_data_size; 160 shared_memory.host_send_data[4] = output_data_size;
161 shared_memory.host_send_data[5] = 0; 161 shared_memory.host_send_data[5] = 0;
162 shared_memory.host_send_data[6] = reset; 162 shared_memory.host_send_data[6] = reset;
163 163
164 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::DecodeInterleaved); 164 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::DecodeInterleaved);
165 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 165 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
166 if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedOK) { 166 if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedOK) {
167 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 167 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
168 ADSP::OpusDecoder::Message::DecodeInterleavedOK, msg); 168 ADSP::OpusDecoder::Message::DecodeInterleavedOK, msg);
169 R_THROW(ResultInvalidOpusDSPReturnCode); 169 R_THROW(ResultInvalidOpusDSPReturnCode);
170 } 170 }
171 171
172 auto error_code{static_cast<s32>(shared_memory.dsp_return_data[0])}; 172 auto error_code{static_cast<s32>(shared_memory.dsp_return_data[0])};
173 if (error_code == OPUS_OK) { 173 if (error_code == OPUS_OK) {
174 out_sample_count = static_cast<u32>(shared_memory.dsp_return_data[1]); 174 out_sample_count = static_cast<u32>(shared_memory.dsp_return_data[1]);
175 out_time_taken = 1000 * shared_memory.dsp_return_data[2]; 175 out_time_taken = 1000 * shared_memory.dsp_return_data[2];
176 } 176 }
177 R_RETURN(ResultCodeFromLibOpusErrorCode(error_code)); 177 R_RETURN(ResultCodeFromLibOpusErrorCode(error_code));
178} 178}
179 179
180Result HardwareOpus::DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data, 180Result HardwareOpus::DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data,
181 u64 output_data_size, u32 channel_count, 181 u64 output_data_size, u32 channel_count,
182 void* input_data, u64 input_data_size, 182 void* input_data, u64 input_data_size,
183 void* buffer, u64& out_time_taken, 183 void* buffer, u64& out_time_taken,
184 bool reset) { 184 bool reset) {
185 std::scoped_lock l{mutex}; 185 std::scoped_lock l{mutex};
186 shared_memory.host_send_data[0] = (u64)buffer; 186 shared_memory.host_send_data[0] = (u64)buffer;
187 shared_memory.host_send_data[1] = (u64)input_data; 187 shared_memory.host_send_data[1] = (u64)input_data;
188 shared_memory.host_send_data[2] = input_data_size; 188 shared_memory.host_send_data[2] = input_data_size;
189 shared_memory.host_send_data[3] = (u64)output_data; 189 shared_memory.host_send_data[3] = (u64)output_data;
190 shared_memory.host_send_data[4] = output_data_size; 190 shared_memory.host_send_data[4] = output_data_size;
191 shared_memory.host_send_data[5] = 0; 191 shared_memory.host_send_data[5] = 0;
192 shared_memory.host_send_data[6] = reset; 192 shared_memory.host_send_data[6] = reset;
193 193
194 opus_decoder.Send(ADSP::Direction::DSP, 194 opus_decoder.Send(ADSP::Direction::DSP,
195 ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStream); 195 ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStream);
196 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 196 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
197 if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK) { 197 if (msg != ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK) {
198 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 198 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
199 ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK, msg); 199 ADSP::OpusDecoder::Message::DecodeInterleavedForMultiStreamOK, msg);
200 R_THROW(ResultInvalidOpusDSPReturnCode); 200 R_THROW(ResultInvalidOpusDSPReturnCode);
201 } 201 }
202 202
203 auto error_code{static_cast<s32>(shared_memory.dsp_return_data[0])}; 203 auto error_code{static_cast<s32>(shared_memory.dsp_return_data[0])};
204 if (error_code == OPUS_OK) { 204 if (error_code == OPUS_OK) {
205 out_sample_count = static_cast<u32>(shared_memory.dsp_return_data[1]); 205 out_sample_count = static_cast<u32>(shared_memory.dsp_return_data[1]);
206 out_time_taken = 1000 * shared_memory.dsp_return_data[2]; 206 out_time_taken = 1000 * shared_memory.dsp_return_data[2];
207 } 207 }
208 R_RETURN(ResultCodeFromLibOpusErrorCode(error_code)); 208 R_RETURN(ResultCodeFromLibOpusErrorCode(error_code));
209} 209}
210 210
211Result HardwareOpus::MapMemory(void* buffer, u64 buffer_size) { 211Result HardwareOpus::MapMemory(void* buffer, u64 buffer_size) {
212 std::scoped_lock l{mutex}; 212 std::scoped_lock l{mutex};
213 shared_memory.host_send_data[0] = (u64)buffer; 213 shared_memory.host_send_data[0] = (u64)buffer;
214 shared_memory.host_send_data[1] = buffer_size; 214 shared_memory.host_send_data[1] = buffer_size;
215 215
216 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::MapMemory); 216 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::MapMemory);
217 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 217 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
218 if (msg != ADSP::OpusDecoder::Message::MapMemoryOK) { 218 if (msg != ADSP::OpusDecoder::Message::MapMemoryOK) {
219 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 219 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
220 ADSP::OpusDecoder::Message::MapMemoryOK, msg); 220 ADSP::OpusDecoder::Message::MapMemoryOK, msg);
221 R_THROW(ResultInvalidOpusDSPReturnCode); 221 R_THROW(ResultInvalidOpusDSPReturnCode);
222 } 222 }
223 R_SUCCEED(); 223 R_SUCCEED();
224} 224}
225 225
226Result HardwareOpus::UnmapMemory(void* buffer, u64 buffer_size) { 226Result HardwareOpus::UnmapMemory(void* buffer, u64 buffer_size) {
227 std::scoped_lock l{mutex}; 227 std::scoped_lock l{mutex};
228 shared_memory.host_send_data[0] = (u64)buffer; 228 shared_memory.host_send_data[0] = (u64)buffer;
229 shared_memory.host_send_data[1] = buffer_size; 229 shared_memory.host_send_data[1] = buffer_size;
230 230
231 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::UnmapMemory); 231 opus_decoder.Send(ADSP::Direction::DSP, ADSP::OpusDecoder::Message::UnmapMemory);
232 auto msg = opus_decoder.Receive(ADSP::Direction::Host); 232 auto msg = opus_decoder.Receive(ADSP::Direction::Host);
233 if (msg != ADSP::OpusDecoder::Message::UnmapMemoryOK) { 233 if (msg != ADSP::OpusDecoder::Message::UnmapMemoryOK) {
234 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}", 234 LOG_ERROR(Service_Audio, "OpusDecoder returned invalid message. Expected {} got {}",
235 ADSP::OpusDecoder::Message::UnmapMemoryOK, msg); 235 ADSP::OpusDecoder::Message::UnmapMemoryOK, msg);
236 R_THROW(ResultInvalidOpusDSPReturnCode); 236 R_THROW(ResultInvalidOpusDSPReturnCode);
237 } 237 }
238 R_SUCCEED(); 238 R_SUCCEED();
239} 239}
240 240
241} // namespace AudioCore::OpusDecoder 241} // namespace AudioCore::OpusDecoder
diff --git a/src/audio_core/opus/hardware_opus.h b/src/audio_core/opus/hardware_opus.h
index 7013a6b40..b10184baa 100644
--- a/src/audio_core/opus/hardware_opus.h
+++ b/src/audio_core/opus/hardware_opus.h
@@ -1,45 +1,45 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include <mutex> 6#include <mutex>
7#include <opus.h> 7#include <opus.h>
8 8
9#include "audio_core/adsp/apps/opus/opus_decoder.h" 9#include "audio_core/adsp/apps/opus/opus_decoder.h"
10#include "audio_core/adsp/apps/opus/shared_memory.h" 10#include "audio_core/adsp/apps/opus/shared_memory.h"
11#include "audio_core/adsp/mailbox.h" 11#include "audio_core/adsp/mailbox.h"
12#include "core/hle/service/audio/errors.h" 12#include "core/hle/service/audio/errors.h"
13 13
14namespace AudioCore::OpusDecoder { 14namespace AudioCore::OpusDecoder {
15class HardwareOpus { 15class HardwareOpus {
16public: 16public:
17 HardwareOpus(Core::System& system); 17 HardwareOpus(Core::System& system);
18 18
19 u64 GetWorkBufferSize(u32 channel); 19 u64 GetWorkBufferSize(u32 channel);
20 u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count); 20 u64 GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count);
21 21
22 Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, 22 Result InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer,
23 u64 buffer_size); 23 u64 buffer_size);
24 Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, 24 Result InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count,
25 u32 totaL_stream_count, u32 stereo_stream_count, 25 u32 totaL_stream_count, u32 stereo_stream_count,
26 void* mappings, void* buffer, u64 buffer_size); 26 void* mappings, void* buffer, u64 buffer_size);
27 Result ShutdownDecodeObject(void* buffer, u64 buffer_size); 27 Result ShutdownDecodeObject(void* buffer, u64 buffer_size);
28 Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size); 28 Result ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size);
29 Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size, 29 Result DecodeInterleaved(u32& out_sample_count, void* output_data, u64 output_data_size,
30 u32 channel_count, void* input_data, u64 input_data_size, void* buffer, 30 u32 channel_count, void* input_data, u64 input_data_size, void* buffer,
31 u64& out_time_taken, bool reset); 31 u64& out_time_taken, bool reset);
32 Result DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data, 32 Result DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data,
33 u64 output_data_size, u32 channel_count, 33 u64 output_data_size, u32 channel_count,
34 void* input_data, u64 input_data_size, void* buffer, 34 void* input_data, u64 input_data_size, void* buffer,
35 u64& out_time_taken, bool reset); 35 u64& out_time_taken, bool reset);
36 Result MapMemory(void* buffer, u64 buffer_size); 36 Result MapMemory(void* buffer, u64 buffer_size);
37 Result UnmapMemory(void* buffer, u64 buffer_size); 37 Result UnmapMemory(void* buffer, u64 buffer_size);
38 38
39private: 39private:
40 Core::System& system; 40 Core::System& system;
41 std::mutex mutex; 41 std::mutex mutex;
42 ADSP::OpusDecoder::OpusDecoder& opus_decoder; 42 ADSP::OpusDecoder::OpusDecoder& opus_decoder;
43 ADSP::OpusDecoder::SharedMemory shared_memory; 43 ADSP::OpusDecoder::SharedMemory shared_memory;
44}; 44};
45} // namespace AudioCore::OpusDecoder 45} // namespace AudioCore::OpusDecoder
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 8a1861051..e216eb3de 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -120,6 +120,8 @@ add_library(common STATIC
120 socket_types.h 120 socket_types.h
121 spin_lock.cpp 121 spin_lock.cpp
122 spin_lock.h 122 spin_lock.h
123 stb.cpp
124 stb.h
123 steady_clock.cpp 125 steady_clock.cpp
124 steady_clock.h 126 steady_clock.h
125 stream.cpp 127 stream.cpp
@@ -208,6 +210,8 @@ if (MSVC)
208 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 210 /we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
209 /we4800 # Implicit conversion from 'type' to bool. Possible information loss 211 /we4800 # Implicit conversion from 'type' to bool. Possible information loss
210 ) 212 )
213else()
214 set_source_files_properties(stb.cpp PROPERTIES COMPILE_OPTIONS "-Wno-implicit-fallthrough;-Wno-missing-declarations;-Wno-missing-field-initializers")
211endif() 215endif()
212 216
213if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 217if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
@@ -223,7 +227,7 @@ endif()
223 227
224create_target_directory_groups(common) 228create_target_directory_groups(common)
225 229
226target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile Threads::Threads) 230target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
227target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) 231target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
228 232
229if (ANDROID) 233if (ANDROID)
diff --git a/src/common/arm64/native_clock.cpp b/src/common/arm64/native_clock.cpp
index 88fdba527..f437d7187 100644
--- a/src/common/arm64/native_clock.cpp
+++ b/src/common/arm64/native_clock.cpp
@@ -1,6 +1,9 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#ifdef ANDROID
5#include <sys/system_properties.h>
6#endif
4#include "common/arm64/native_clock.h" 7#include "common/arm64/native_clock.h"
5 8
6namespace Common::Arm64 { 9namespace Common::Arm64 {
@@ -65,7 +68,23 @@ bool NativeClock::IsNative() const {
65 68
66u64 NativeClock::GetHostCNTFRQ() { 69u64 NativeClock::GetHostCNTFRQ() {
67 u64 cntfrq_el0 = 0; 70 u64 cntfrq_el0 = 0;
68 asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0)); 71 std::string_view board{""};
72#ifdef ANDROID
73 char buffer[PROP_VALUE_MAX];
74 int len{__system_property_get("ro.product.board", buffer)};
75 board = std::string_view(buffer, static_cast<size_t>(len));
76#endif
77 if (board == "s5e9925") { // Exynos 2200
78 cntfrq_el0 = 25600000;
79 } else if (board == "exynos2100") { // Exynos 2100
80 cntfrq_el0 = 26000000;
81 } else if (board == "exynos9810") { // Exynos 9810
82 cntfrq_el0 = 26000000;
83 } else if (board == "s5e8825") { // Exynos 1280
84 cntfrq_el0 = 26000000;
85 } else {
86 asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
87 }
69 return cntfrq_el0; 88 return cntfrq_el0;
70} 89}
71 90
diff --git a/src/common/fs/fs_android.cpp b/src/common/fs/fs_android.cpp
index 298a79bac..1dd826a4a 100644
--- a/src/common/fs/fs_android.cpp
+++ b/src/common/fs/fs_android.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/fs/fs_android.h" 4#include "common/fs/fs_android.h"
5#include "common/string_util.h"
5 6
6namespace Common::FS::Android { 7namespace Common::FS::Android {
7 8
@@ -28,28 +29,35 @@ void RegisterCallbacks(JNIEnv* env, jclass clazz) {
28 env->GetJavaVM(&g_jvm); 29 env->GetJavaVM(&g_jvm);
29 native_library = clazz; 30 native_library = clazz;
30 31
32#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) \
33 F(JMethodID, JMethodName, Signature)
31#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ 34#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \
32 F(JMethodID, JMethodName, Signature) 35 F(JMethodID, JMethodName, Signature)
33#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \ 36#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \
34 F(JMethodID, JMethodName, Signature) 37 F(JMethodID, JMethodName, Signature)
35#define F(JMethodID, JMethodName, Signature) \ 38#define F(JMethodID, JMethodName, Signature) \
36 JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature); 39 JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature);
40 ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
37 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) 41 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
38 ANDROID_STORAGE_FUNCTIONS(FS) 42 ANDROID_STORAGE_FUNCTIONS(FS)
39#undef F 43#undef F
40#undef FS 44#undef FS
41#undef FR 45#undef FR
46#undef FH
42} 47}
43 48
44void UnRegisterCallbacks() { 49void UnRegisterCallbacks() {
50#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
45#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) 51#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
46#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) 52#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID)
47#define F(JMethodID) JMethodID = nullptr; 53#define F(JMethodID) JMethodID = nullptr;
54 ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
48 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) 55 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
49 ANDROID_STORAGE_FUNCTIONS(FS) 56 ANDROID_STORAGE_FUNCTIONS(FS)
50#undef F 57#undef F
51#undef FS 58#undef FS
52#undef FR 59#undef FR
60#undef FH
53} 61}
54 62
55bool IsContentUri(const std::string& path) { 63bool IsContentUri(const std::string& path) {
@@ -95,4 +103,29 @@ ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
95#undef F 103#undef F
96#undef FR 104#undef FR
97 105
106#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) \
107 F(FunctionName, JMethodID, Caller)
108#define F(FunctionName, JMethodID, Caller) \
109 std::string FunctionName(const std::string& filepath) { \
110 if (JMethodID == nullptr) { \
111 return 0; \
112 } \
113 auto env = GetEnvForThread(); \
114 jstring j_filepath = env->NewStringUTF(filepath.c_str()); \
115 jstring j_return = \
116 static_cast<jstring>(env->Caller(native_library, JMethodID, j_filepath)); \
117 if (!j_return) { \
118 return {}; \
119 } \
120 const jchar* jchars = env->GetStringChars(j_return, nullptr); \
121 const jsize length = env->GetStringLength(j_return); \
122 const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length); \
123 const std::string converted_string = Common::UTF16ToUTF8(string_view); \
124 env->ReleaseStringChars(j_return, jchars); \
125 return converted_string; \
126 }
127ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
128#undef F
129#undef FH
130
98} // namespace Common::FS::Android 131} // namespace Common::FS::Android
diff --git a/src/common/fs/fs_android.h b/src/common/fs/fs_android.h
index b441c2a12..2c9234313 100644
--- a/src/common/fs/fs_android.h
+++ b/src/common/fs/fs_android.h
@@ -17,19 +17,28 @@
17 "(Ljava/lang/String;)Z") \ 17 "(Ljava/lang/String;)Z") \
18 V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z") 18 V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z")
19 19
20#define ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(V) \
21 V(GetParentDirectory, get_parent_directory, CallStaticObjectMethod, "getParentDirectory", \
22 "(Ljava/lang/String;)Ljava/lang/String;") \
23 V(GetFilename, get_filename, CallStaticObjectMethod, "getFilename", \
24 "(Ljava/lang/String;)Ljava/lang/String;")
25
20namespace Common::FS::Android { 26namespace Common::FS::Android {
21 27
22static JavaVM* g_jvm = nullptr; 28static JavaVM* g_jvm = nullptr;
23static jclass native_library = nullptr; 29static jclass native_library = nullptr;
24 30
31#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
25#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) 32#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
26#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) 33#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID)
27#define F(JMethodID) static jmethodID JMethodID = nullptr; 34#define F(JMethodID) static jmethodID JMethodID = nullptr;
35ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
28ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) 36ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
29ANDROID_STORAGE_FUNCTIONS(FS) 37ANDROID_STORAGE_FUNCTIONS(FS)
30#undef F 38#undef F
31#undef FS 39#undef FS
32#undef FR 40#undef FR
41#undef FH
33 42
34enum class OpenMode { 43enum class OpenMode {
35 Read, 44 Read,
@@ -62,4 +71,10 @@ ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
62#undef F 71#undef F
63#undef FR 72#undef FR
64 73
74#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(FunctionName)
75#define F(FunctionName) std::string FunctionName(const std::string& filepath);
76ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
77#undef F
78#undef FH
79
65} // namespace Common::FS::Android 80} // namespace Common::FS::Android
diff --git a/src/common/fs/fs_paths.h b/src/common/fs/fs_paths.h
index 441c8af97..bcf447089 100644
--- a/src/common/fs/fs_paths.h
+++ b/src/common/fs/fs_paths.h
@@ -13,6 +13,7 @@
13#define AMIIBO_DIR "amiibo" 13#define AMIIBO_DIR "amiibo"
14#define CACHE_DIR "cache" 14#define CACHE_DIR "cache"
15#define CONFIG_DIR "config" 15#define CONFIG_DIR "config"
16#define CRASH_DUMPS_DIR "crash_dumps"
16#define DUMP_DIR "dump" 17#define DUMP_DIR "dump"
17#define KEYS_DIR "keys" 18#define KEYS_DIR "keys"
18#define LOAD_DIR "load" 19#define LOAD_DIR "load"
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp
index 0abd81a45..c3a81f9a9 100644
--- a/src/common/fs/path_util.cpp
+++ b/src/common/fs/path_util.cpp
@@ -119,6 +119,7 @@ public:
119 GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR); 119 GenerateYuzuPath(YuzuPath::AmiiboDir, yuzu_path / AMIIBO_DIR);
120 GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache); 120 GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache);
121 GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config); 121 GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config);
122 GenerateYuzuPath(YuzuPath::CrashDumpsDir, yuzu_path / CRASH_DUMPS_DIR);
122 GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR); 123 GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR);
123 GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR); 124 GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR);
124 GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR); 125 GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR);
@@ -400,6 +401,16 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se
400} 401}
401 402
402std::string_view GetParentPath(std::string_view path) { 403std::string_view GetParentPath(std::string_view path) {
404 if (path.empty()) {
405 return path;
406 }
407
408#ifdef ANDROID
409 if (path[0] != '/') {
410 std::string path_string{path};
411 return FS::Android::GetParentDirectory(path_string);
412 }
413#endif
403 const auto name_bck_index = path.rfind('\\'); 414 const auto name_bck_index = path.rfind('\\');
404 const auto name_fwd_index = path.rfind('/'); 415 const auto name_fwd_index = path.rfind('/');
405 std::size_t name_index; 416 std::size_t name_index;
diff --git a/src/common/fs/path_util.h b/src/common/fs/path_util.h
index 63801c924..2874ea738 100644
--- a/src/common/fs/path_util.h
+++ b/src/common/fs/path_util.h
@@ -15,6 +15,7 @@ enum class YuzuPath {
15 AmiiboDir, // Where Amiibo backups are stored. 15 AmiiboDir, // Where Amiibo backups are stored.
16 CacheDir, // Where cached filesystem data is stored. 16 CacheDir, // Where cached filesystem data is stored.
17 ConfigDir, // Where config files are stored. 17 ConfigDir, // Where config files are stored.
18 CrashDumpsDir, // Where crash dumps are stored.
18 DumpDir, // Where dumped data is stored. 19 DumpDir, // Where dumped data is stored.
19 KeysDir, // Where key files are stored. 20 KeysDir, // Where key files are stored.
20 LoadDir, // Where cheat/mod files are stored. 21 LoadDir, // Where cheat/mod files are stored.
diff --git a/src/common/nvidia_flags.cpp b/src/common/nvidia_flags.cpp
index 7ed7690ee..fa3747782 100644
--- a/src/common/nvidia_flags.cpp
+++ b/src/common/nvidia_flags.cpp
@@ -25,6 +25,7 @@ void ConfigureNvidiaEnvironmentFlags() {
25 25
26 void(_putenv(fmt::format("__GL_SHADER_DISK_CACHE_PATH={}", windows_path_string).c_str())); 26 void(_putenv(fmt::format("__GL_SHADER_DISK_CACHE_PATH={}", windows_path_string).c_str()));
27 void(_putenv("__GL_SHADER_DISK_CACHE_SKIP_CLEANUP=1")); 27 void(_putenv("__GL_SHADER_DISK_CACHE_SKIP_CLEANUP=1"));
28 void(_putenv("__GL_THREADED_OPTIMIZATIONS=1"));
28#endif 29#endif
29} 30}
30 31
diff --git a/src/common/settings.h b/src/common/settings.h
index 236e33bee..9317075f7 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -505,7 +505,6 @@ struct Values {
505 linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false}; 505 linkage, false, "use_auto_stub", Category::Debugging, Specialization::Default, false};
506 Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers", 506 Setting<bool> enable_all_controllers{linkage, false, "enable_all_controllers",
507 Category::Debugging}; 507 Category::Debugging};
508 Setting<bool> create_crash_dumps{linkage, false, "create_crash_dumps", Category::Debugging};
509 Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging}; 508 Setting<bool> perform_vulkan_check{linkage, true, "perform_vulkan_check", Category::Debugging};
510 509
511 // Miscellaneous 510 // Miscellaneous
diff --git a/src/common/stb.cpp b/src/common/stb.cpp
new file mode 100644
index 000000000..d3b16665d
--- /dev/null
+++ b/src/common/stb.cpp
@@ -0,0 +1,8 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#define STB_IMAGE_IMPLEMENTATION
5#define STB_IMAGE_RESIZE_IMPLEMENTATION
6#define STB_IMAGE_WRITE_IMPLEMENTATION
7
8#include "common/stb.h"
diff --git a/src/common/stb.h b/src/common/stb.h
new file mode 100644
index 000000000..e5c197c11
--- /dev/null
+++ b/src/common/stb.h
@@ -0,0 +1,8 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <stb_image.h>
7#include <stb_image_resize.h>
8#include <stb_image_write.h>
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 4c7aba3f5..72c481798 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -14,6 +14,10 @@
14#include <windows.h> 14#include <windows.h>
15#endif 15#endif
16 16
17#ifdef ANDROID
18#include <common/fs/fs_android.h>
19#endif
20
17namespace Common { 21namespace Common {
18 22
19/// Make a string lowercase 23/// Make a string lowercase
@@ -63,6 +67,14 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
63 if (full_path.empty()) 67 if (full_path.empty())
64 return false; 68 return false;
65 69
70#ifdef ANDROID
71 if (full_path[0] != '/') {
72 *_pPath = Common::FS::Android::GetParentDirectory(full_path);
73 *_pFilename = Common::FS::Android::GetFilename(full_path);
74 return true;
75 }
76#endif
77
66 std::size_t dir_end = full_path.find_last_of("/" 78 std::size_t dir_end = full_path.find_last_of("/"
67// windows needs the : included for something like just "C:" to be considered a directory 79// windows needs the : included for something like just "C:" to be considered a directory
68#ifdef _WIN32 80#ifdef _WIN32
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp
index 0c012f094..5e27dde58 100644
--- a/src/core/arm/arm_interface.cpp
+++ b/src/core/arm/arm_interface.cpp
@@ -86,9 +86,9 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt
86 86
87 std::map<std::string, Symbols::Symbols> symbols; 87 std::map<std::string, Symbols::Symbols> symbols;
88 for (const auto& module : modules) { 88 for (const auto& module : modules) {
89 symbols.insert_or_assign( 89 symbols.insert_or_assign(module.second,
90 module.second, Symbols::GetSymbols(module.first, system.ApplicationMemory(), 90 Symbols::GetSymbols(module.first, system.ApplicationMemory(),
91 system.ApplicationProcess()->Is64BitProcess())); 91 system.ApplicationProcess()->Is64Bit()));
92 } 92 }
93 93
94 for (auto& entry : out) { 94 for (auto& entry : out) {
diff --git a/src/core/core.cpp b/src/core/core.cpp
index d7e2efbd7..14d6c8c27 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -309,17 +309,10 @@ struct System::Impl {
309 309
310 telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); 310 telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
311 311
312 // Create a resource limit for the process.
313 const auto physical_memory_size =
314 kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application);
315 auto* resource_limit = Kernel::CreateResourceLimitForProcess(system, physical_memory_size);
316
317 // Create the process. 312 // Create the process.
318 auto main_process = Kernel::KProcess::Create(system.Kernel()); 313 auto main_process = Kernel::KProcess::Create(system.Kernel());
319 ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
320 Kernel::KProcess::ProcessType::Userland, resource_limit)
321 .IsSuccess());
322 Kernel::KProcess::Register(system.Kernel(), main_process); 314 Kernel::KProcess::Register(system.Kernel(), main_process);
315 kernel.AppendNewProcess(main_process);
323 kernel.MakeApplicationProcess(main_process); 316 kernel.MakeApplicationProcess(main_process);
324 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); 317 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
325 if (load_result != Loader::ResultStatus::Success) { 318 if (load_result != Loader::ResultStatus::Success) {
@@ -418,6 +411,7 @@ struct System::Impl {
418 services->KillNVNFlinger(); 411 services->KillNVNFlinger();
419 } 412 }
420 kernel.CloseServices(); 413 kernel.CloseServices();
414 kernel.ShutdownCores();
421 services.reset(); 415 services.reset();
422 service_manager.reset(); 416 service_manager.reset();
423 cheat_engine.reset(); 417 cheat_engine.reset();
@@ -429,7 +423,6 @@ struct System::Impl {
429 gpu_core.reset(); 423 gpu_core.reset();
430 host1x_core.reset(); 424 host1x_core.reset();
431 perf_stats.reset(); 425 perf_stats.reset();
432 kernel.ShutdownCores();
433 cpu_manager.Shutdown(); 426 cpu_manager.Shutdown();
434 debugger.reset(); 427 debugger.reset();
435 kernel.Shutdown(); 428 kernel.Shutdown();
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index a1589fecb..0e270eb50 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -258,20 +258,20 @@ private:
258 Kernel::KScopedSchedulerLock sl{system.Kernel()}; 258 Kernel::KScopedSchedulerLock sl{system.Kernel()};
259 259
260 // Put all threads to sleep on next scheduler round. 260 // Put all threads to sleep on next scheduler round.
261 for (auto* thread : ThreadList()) { 261 for (auto& thread : ThreadList()) {
262 thread->RequestSuspend(Kernel::SuspendType::Debug); 262 thread.RequestSuspend(Kernel::SuspendType::Debug);
263 } 263 }
264 } 264 }
265 265
266 void ResumeEmulation(Kernel::KThread* except = nullptr) { 266 void ResumeEmulation(Kernel::KThread* except = nullptr) {
267 // Wake up all threads. 267 // Wake up all threads.
268 for (auto* thread : ThreadList()) { 268 for (auto& thread : ThreadList()) {
269 if (thread == except) { 269 if (std::addressof(thread) == except) {
270 continue; 270 continue;
271 } 271 }
272 272
273 thread->SetStepState(Kernel::StepState::NotStepping); 273 thread.SetStepState(Kernel::StepState::NotStepping);
274 thread->Resume(Kernel::SuspendType::Debug); 274 thread.Resume(Kernel::SuspendType::Debug);
275 } 275 }
276 } 276 }
277 277
@@ -283,13 +283,17 @@ private:
283 } 283 }
284 284
285 void UpdateActiveThread() { 285 void UpdateActiveThread() {
286 const auto& threads{ThreadList()}; 286 auto& threads{ThreadList()};
287 if (std::find(threads.begin(), threads.end(), state->active_thread) == threads.end()) { 287 for (auto& thread : threads) {
288 state->active_thread = threads.front(); 288 if (std::addressof(thread) == state->active_thread) {
289 // Thread is still alive, no need to update.
290 return;
291 }
289 } 292 }
293 state->active_thread = std::addressof(threads.front());
290 } 294 }
291 295
292 const std::list<Kernel::KThread*>& ThreadList() { 296 Kernel::KProcess::ThreadList& ThreadList() {
293 return system.ApplicationProcess()->GetThreadList(); 297 return system.ApplicationProcess()->GetThreadList();
294 } 298 }
295 299
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index 2076aa8a2..6f5f5156b 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -109,7 +109,7 @@ static std::string EscapeXML(std::string_view data) {
109 109
110GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_) 110GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_)
111 : DebuggerFrontend(backend_), system{system_} { 111 : DebuggerFrontend(backend_), system{system_} {
112 if (system.ApplicationProcess()->Is64BitProcess()) { 112 if (system.ApplicationProcess()->Is64Bit()) {
113 arch = std::make_unique<GDBStubA64>(); 113 arch = std::make_unique<GDBStubA64>();
114 } else { 114 } else {
115 arch = std::make_unique<GDBStubA32>(); 115 arch = std::make_unique<GDBStubA32>();
@@ -446,10 +446,10 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
446// See osdbg_thread_local_region.os.horizon.hpp and osdbg_thread_type.os.horizon.hpp 446// See osdbg_thread_local_region.os.horizon.hpp and osdbg_thread_type.os.horizon.hpp
447 447
448static std::optional<std::string> GetNameFromThreadType32(Core::Memory::Memory& memory, 448static std::optional<std::string> GetNameFromThreadType32(Core::Memory::Memory& memory,
449 const Kernel::KThread* thread) { 449 const Kernel::KThread& thread) {
450 // Read thread type from TLS 450 // Read thread type from TLS
451 const VAddr tls_thread_type{memory.Read32(thread->GetTlsAddress() + 0x1fc)}; 451 const VAddr tls_thread_type{memory.Read32(thread.GetTlsAddress() + 0x1fc)};
452 const VAddr argument_thread_type{thread->GetArgument()}; 452 const VAddr argument_thread_type{thread.GetArgument()};
453 453
454 if (argument_thread_type && tls_thread_type != argument_thread_type) { 454 if (argument_thread_type && tls_thread_type != argument_thread_type) {
455 // Probably not created by nnsdk, no name available. 455 // Probably not created by nnsdk, no name available.
@@ -477,10 +477,10 @@ static std::optional<std::string> GetNameFromThreadType32(Core::Memory::Memory&
477} 477}
478 478
479static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory& memory, 479static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory& memory,
480 const Kernel::KThread* thread) { 480 const Kernel::KThread& thread) {
481 // Read thread type from TLS 481 // Read thread type from TLS
482 const VAddr tls_thread_type{memory.Read64(thread->GetTlsAddress() + 0x1f8)}; 482 const VAddr tls_thread_type{memory.Read64(thread.GetTlsAddress() + 0x1f8)};
483 const VAddr argument_thread_type{thread->GetArgument()}; 483 const VAddr argument_thread_type{thread.GetArgument()};
484 484
485 if (argument_thread_type && tls_thread_type != argument_thread_type) { 485 if (argument_thread_type && tls_thread_type != argument_thread_type) {
486 // Probably not created by nnsdk, no name available. 486 // Probably not created by nnsdk, no name available.
@@ -508,16 +508,16 @@ static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory&
508} 508}
509 509
510static std::optional<std::string> GetThreadName(Core::System& system, 510static std::optional<std::string> GetThreadName(Core::System& system,
511 const Kernel::KThread* thread) { 511 const Kernel::KThread& thread) {
512 if (system.ApplicationProcess()->Is64BitProcess()) { 512 if (system.ApplicationProcess()->Is64Bit()) {
513 return GetNameFromThreadType64(system.ApplicationMemory(), thread); 513 return GetNameFromThreadType64(system.ApplicationMemory(), thread);
514 } else { 514 } else {
515 return GetNameFromThreadType32(system.ApplicationMemory(), thread); 515 return GetNameFromThreadType32(system.ApplicationMemory(), thread);
516 } 516 }
517} 517}
518 518
519static std::string_view GetThreadWaitReason(const Kernel::KThread* thread) { 519static std::string_view GetThreadWaitReason(const Kernel::KThread& thread) {
520 switch (thread->GetWaitReasonForDebugging()) { 520 switch (thread.GetWaitReasonForDebugging()) {
521 case Kernel::ThreadWaitReasonForDebugging::Sleep: 521 case Kernel::ThreadWaitReasonForDebugging::Sleep:
522 return "Sleep"; 522 return "Sleep";
523 case Kernel::ThreadWaitReasonForDebugging::IPC: 523 case Kernel::ThreadWaitReasonForDebugging::IPC:
@@ -535,8 +535,8 @@ static std::string_view GetThreadWaitReason(const Kernel::KThread* thread) {
535 } 535 }
536} 536}
537 537
538static std::string GetThreadState(const Kernel::KThread* thread) { 538static std::string GetThreadState(const Kernel::KThread& thread) {
539 switch (thread->GetState()) { 539 switch (thread.GetState()) {
540 case Kernel::ThreadState::Initialized: 540 case Kernel::ThreadState::Initialized:
541 return "Initialized"; 541 return "Initialized";
542 case Kernel::ThreadState::Waiting: 542 case Kernel::ThreadState::Waiting:
@@ -604,7 +604,7 @@ void GDBStub::HandleQuery(std::string_view command) {
604 const auto& threads = system.ApplicationProcess()->GetThreadList(); 604 const auto& threads = system.ApplicationProcess()->GetThreadList();
605 std::vector<std::string> thread_ids; 605 std::vector<std::string> thread_ids;
606 for (const auto& thread : threads) { 606 for (const auto& thread : threads) {
607 thread_ids.push_back(fmt::format("{:x}", thread->GetThreadId())); 607 thread_ids.push_back(fmt::format("{:x}", thread.GetThreadId()));
608 } 608 }
609 SendReply(fmt::format("m{}", fmt::join(thread_ids, ","))); 609 SendReply(fmt::format("m{}", fmt::join(thread_ids, ",")));
610 } else if (command.starts_with("sThreadInfo")) { 610 } else if (command.starts_with("sThreadInfo")) {
@@ -616,14 +616,14 @@ void GDBStub::HandleQuery(std::string_view command) {
616 buffer += "<threads>"; 616 buffer += "<threads>";
617 617
618 const auto& threads = system.ApplicationProcess()->GetThreadList(); 618 const auto& threads = system.ApplicationProcess()->GetThreadList();
619 for (const auto* thread : threads) { 619 for (const auto& thread : threads) {
620 auto thread_name{GetThreadName(system, thread)}; 620 auto thread_name{GetThreadName(system, thread)};
621 if (!thread_name) { 621 if (!thread_name) {
622 thread_name = fmt::format("Thread {:d}", thread->GetThreadId()); 622 thread_name = fmt::format("Thread {:d}", thread.GetThreadId());
623 } 623 }
624 624
625 buffer += fmt::format(R"(<thread id="{:x}" core="{:d}" name="{}">{}</thread>)", 625 buffer += fmt::format(R"(<thread id="{:x}" core="{:d}" name="{}">{}</thread>)",
626 thread->GetThreadId(), thread->GetActiveCore(), 626 thread.GetThreadId(), thread.GetActiveCore(),
627 EscapeXML(*thread_name), GetThreadState(thread)); 627 EscapeXML(*thread_name), GetThreadState(thread));
628 } 628 }
629 629
@@ -850,10 +850,10 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
850} 850}
851 851
852Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { 852Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) {
853 const auto& threads{system.ApplicationProcess()->GetThreadList()}; 853 auto& threads{system.ApplicationProcess()->GetThreadList()};
854 for (auto* thread : threads) { 854 for (auto& thread : threads) {
855 if (thread->GetThreadId() == thread_id) { 855 if (thread.GetThreadId() == thread_id) {
856 return thread; 856 return std::addressof(thread);
857 } 857 }
858 } 858 }
859 859
diff --git a/src/core/file_sys/program_metadata.cpp b/src/core/file_sys/program_metadata.cpp
index 8e291ff67..763a44fee 100644
--- a/src/core/file_sys/program_metadata.cpp
+++ b/src/core/file_sys/program_metadata.cpp
@@ -104,16 +104,16 @@ Loader::ResultStatus ProgramMetadata::Reload(VirtualFile file) {
104} 104}
105 105
106/*static*/ ProgramMetadata ProgramMetadata::GetDefault() { 106/*static*/ ProgramMetadata ProgramMetadata::GetDefault() {
107 // Allow use of cores 0~3 and thread priorities 1~63. 107 // Allow use of cores 0~3 and thread priorities 16~63.
108 constexpr u32 default_thread_info_capability = 0x30007F7; 108 constexpr u32 default_thread_info_capability = 0x30043F7;
109 109
110 ProgramMetadata result; 110 ProgramMetadata result;
111 111
112 result.LoadManual( 112 result.LoadManual(
113 true /*is_64_bit*/, FileSys::ProgramAddressSpaceType::Is39Bit /*address_space*/, 113 true /*is_64_bit*/, FileSys::ProgramAddressSpaceType::Is39Bit /*address_space*/,
114 0x2c /*main_thread_prio*/, 0 /*main_thread_core*/, 0x00100000 /*main_thread_stack_size*/, 114 0x2c /*main_thread_prio*/, 0 /*main_thread_core*/, 0x100000 /*main_thread_stack_size*/,
115 0 /*title_id*/, 0xFFFFFFFFFFFFFFFF /*filesystem_permissions*/, 115 0 /*title_id*/, 0xFFFFFFFFFFFFFFFF /*filesystem_permissions*/, 0 /*system_resource_size*/,
116 0x1FE00000 /*system_resource_size*/, {default_thread_info_capability} /*capabilities*/); 116 {default_thread_info_capability} /*capabilities*/);
117 117
118 return result; 118 return result;
119} 119}
diff --git a/src/core/file_sys/program_metadata.h b/src/core/file_sys/program_metadata.h
index 9f8e74b13..76ee97d78 100644
--- a/src/core/file_sys/program_metadata.h
+++ b/src/core/file_sys/program_metadata.h
@@ -73,6 +73,9 @@ public:
73 u64 GetFilesystemPermissions() const; 73 u64 GetFilesystemPermissions() const;
74 u32 GetSystemResourceSize() const; 74 u32 GetSystemResourceSize() const;
75 const KernelCapabilityDescriptors& GetKernelCapabilities() const; 75 const KernelCapabilityDescriptors& GetKernelCapabilities() const;
76 const std::array<u8, 0x10>& GetName() const {
77 return npdm_header.application_name;
78 }
76 79
77 void Print() const; 80 void Print() const;
78 81
@@ -164,14 +167,14 @@ private:
164 u32_le unk_size_2; 167 u32_le unk_size_2;
165 }; 168 };
166 169
167 Header npdm_header; 170 Header npdm_header{};
168 AciHeader aci_header; 171 AciHeader aci_header{};
169 AcidHeader acid_header; 172 AcidHeader acid_header{};
170 173
171 FileAccessControl acid_file_access; 174 FileAccessControl acid_file_access{};
172 FileAccessHeader aci_file_access; 175 FileAccessHeader aci_file_access{};
173 176
174 KernelCapabilityDescriptors aci_kernel_capabilities; 177 KernelCapabilityDescriptors aci_kernel_capabilities{};
175}; 178};
176 179
177} // namespace FileSys 180} // namespace FileSys
diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp
index 1c580de57..1eb1f439a 100644
--- a/src/core/file_sys/romfs.cpp
+++ b/src/core/file_sys/romfs.cpp
@@ -35,13 +35,14 @@ struct RomFSHeader {
35static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); 35static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
36 36
37struct DirectoryEntry { 37struct DirectoryEntry {
38 u32_le parent;
38 u32_le sibling; 39 u32_le sibling;
39 u32_le child_dir; 40 u32_le child_dir;
40 u32_le child_file; 41 u32_le child_file;
41 u32_le hash; 42 u32_le hash;
42 u32_le name_length; 43 u32_le name_length;
43}; 44};
44static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size."); 45static_assert(sizeof(DirectoryEntry) == 0x18, "DirectoryEntry has incorrect size.");
45 46
46struct FileEntry { 47struct FileEntry {
47 u32_le parent; 48 u32_le parent;
@@ -64,25 +65,22 @@ std::pair<Entry, std::string> GetEntry(const VirtualFile& file, std::size_t offs
64 return {entry, string}; 65 return {entry, string};
65} 66}
66 67
67void ProcessFile(VirtualFile file, std::size_t file_offset, std::size_t data_offset, 68void ProcessFile(const VirtualFile& file, std::size_t file_offset, std::size_t data_offset,
68 u32 this_file_offset, std::shared_ptr<VectorVfsDirectory> parent) { 69 u32 this_file_offset, std::shared_ptr<VectorVfsDirectory>& parent) {
69 while (true) { 70 while (this_file_offset != ROMFS_ENTRY_EMPTY) {
70 auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset); 71 auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset);
71 72
72 parent->AddFile(std::make_shared<OffsetVfsFile>( 73 parent->AddFile(std::make_shared<OffsetVfsFile>(
73 file, entry.first.size, entry.first.offset + data_offset, entry.second)); 74 file, entry.first.size, entry.first.offset + data_offset, entry.second));
74 75
75 if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
76 break;
77
78 this_file_offset = entry.first.sibling; 76 this_file_offset = entry.first.sibling;
79 } 77 }
80} 78}
81 79
82void ProcessDirectory(VirtualFile file, std::size_t dir_offset, std::size_t file_offset, 80void ProcessDirectory(const VirtualFile& file, std::size_t dir_offset, std::size_t file_offset,
83 std::size_t data_offset, u32 this_dir_offset, 81 std::size_t data_offset, u32 this_dir_offset,
84 std::shared_ptr<VectorVfsDirectory> parent) { 82 std::shared_ptr<VectorVfsDirectory>& parent) {
85 while (true) { 83 while (this_dir_offset != ROMFS_ENTRY_EMPTY) {
86 auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset); 84 auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset);
87 auto current = std::make_shared<VectorVfsDirectory>( 85 auto current = std::make_shared<VectorVfsDirectory>(
88 std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, entry.second); 86 std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, entry.second);
@@ -97,14 +95,12 @@ void ProcessDirectory(VirtualFile file, std::size_t dir_offset, std::size_t file
97 } 95 }
98 96
99 parent->AddDirectory(current); 97 parent->AddDirectory(current);
100 if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
101 break;
102 this_dir_offset = entry.first.sibling; 98 this_dir_offset = entry.first.sibling;
103 } 99 }
104} 100}
105} // Anonymous namespace 101} // Anonymous namespace
106 102
107VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) { 103VirtualDir ExtractRomFS(VirtualFile file) {
108 RomFSHeader header{}; 104 RomFSHeader header{};
109 if (file->ReadObject(&header) != sizeof(RomFSHeader)) 105 if (file->ReadObject(&header) != sizeof(RomFSHeader))
110 return nullptr; 106 return nullptr;
@@ -113,27 +109,17 @@ VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) {
113 return nullptr; 109 return nullptr;
114 110
115 const u64 file_offset = header.file_meta.offset; 111 const u64 file_offset = header.file_meta.offset;
116 const u64 dir_offset = header.directory_meta.offset + 4; 112 const u64 dir_offset = header.directory_meta.offset;
117
118 auto root =
119 std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, std::vector<VirtualDir>{},
120 file->GetName(), file->GetContainingDirectory());
121
122 ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root);
123 113
124 VirtualDir out = std::move(root); 114 auto root_container = std::make_shared<VectorVfsDirectory>();
125 115
126 if (type == RomFSExtractionType::SingleDiscard) 116 ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root_container);
127 return out->GetSubdirectories().front();
128 117
129 while (out->GetSubdirectories().size() == 1 && out->GetFiles().empty()) { 118 if (auto root = root_container->GetSubdirectory(""); root) {
130 if (Common::ToLower(out->GetSubdirectories().front()->GetName()) == "data" && 119 return std::make_shared<CachedVfsDirectory>(std::move(root));
131 type == RomFSExtractionType::Truncated)
132 break;
133 out = out->GetSubdirectories().front();
134 } 120 }
135 121
136 return std::make_shared<CachedVfsDirectory>(std::move(out)); 122 return nullptr;
137} 123}
138 124
139VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) { 125VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h
index 5d7f0c2a8..b75ff1aad 100644
--- a/src/core/file_sys/romfs.h
+++ b/src/core/file_sys/romfs.h
@@ -7,16 +7,9 @@
7 7
8namespace FileSys { 8namespace FileSys {
9 9
10enum class RomFSExtractionType {
11 Full, // Includes data directory
12 Truncated, // Traverses into data directory
13 SingleDiscard, // Traverses into the first subdirectory of root
14};
15
16// Converts a RomFS binary blob to VFS Filesystem 10// Converts a RomFS binary blob to VFS Filesystem
17// Returns nullptr on failure 11// Returns nullptr on failure
18VirtualDir ExtractRomFS(VirtualFile file, 12VirtualDir ExtractRomFS(VirtualFile file);
19 RomFSExtractionType type = RomFSExtractionType::Truncated);
20 13
21// Converts a VFS filesystem into a RomFS binary 14// Converts a VFS filesystem into a RomFS binary
22// Returns nullptr on failure 15// Returns nullptr on failure
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 2af3f06fc..b08a71446 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -96,18 +96,7 @@ void EmulatedController::ReloadFromSettings() {
96 } 96 }
97 97
98 controller.color_values = {}; 98 controller.color_values = {};
99 controller.colors_state.fullkey = { 99 ReloadColorsFromSettings();
100 .body = GetNpadColor(player.body_color_left),
101 .button = GetNpadColor(player.button_color_left),
102 };
103 controller.colors_state.left = {
104 .body = GetNpadColor(player.body_color_left),
105 .button = GetNpadColor(player.button_color_left),
106 };
107 controller.colors_state.right = {
108 .body = GetNpadColor(player.body_color_right),
109 .button = GetNpadColor(player.button_color_right),
110 };
111 100
112 ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs); 101 ring_params[0] = Common::ParamPackage(Settings::values.ringcon_analogs);
113 102
@@ -128,6 +117,30 @@ void EmulatedController::ReloadFromSettings() {
128 ReloadInput(); 117 ReloadInput();
129} 118}
130 119
120void EmulatedController::ReloadColorsFromSettings() {
121 const auto player_index = NpadIdTypeToIndex(npad_id_type);
122 const auto& player = Settings::values.players.GetValue()[player_index];
123
124 // Avoid updating colors if overridden by physical controller
125 if (controller.color_values[LeftIndex].body != 0 &&
126 controller.color_values[RightIndex].body != 0) {
127 return;
128 }
129
130 controller.colors_state.fullkey = {
131 .body = GetNpadColor(player.body_color_left),
132 .button = GetNpadColor(player.button_color_left),
133 };
134 controller.colors_state.left = {
135 .body = GetNpadColor(player.body_color_left),
136 .button = GetNpadColor(player.button_color_left),
137 };
138 controller.colors_state.right = {
139 .body = GetNpadColor(player.body_color_right),
140 .button = GetNpadColor(player.button_color_right),
141 };
142}
143
131void EmulatedController::LoadDevices() { 144void EmulatedController::LoadDevices() {
132 // TODO(german77): Use more buttons to detect the correct device 145 // TODO(german77): Use more buttons to detect the correct device
133 const auto left_joycon = button_params[Settings::NativeButton::DRight]; 146 const auto left_joycon = button_params[Settings::NativeButton::DRight];
@@ -1091,30 +1104,30 @@ void EmulatedController::SetBattery(const Common::Input::CallbackStatus& callbac
1091 1104
1092 bool is_charging = false; 1105 bool is_charging = false;
1093 bool is_powered = false; 1106 bool is_powered = false;
1094 NpadBatteryLevel battery_level = 0; 1107 NpadBatteryLevel battery_level = NpadBatteryLevel::Empty;
1095 switch (controller.battery_values[index]) { 1108 switch (controller.battery_values[index]) {
1096 case Common::Input::BatteryLevel::Charging: 1109 case Common::Input::BatteryLevel::Charging:
1097 is_charging = true; 1110 is_charging = true;
1098 is_powered = true; 1111 is_powered = true;
1099 battery_level = 6; 1112 battery_level = NpadBatteryLevel::Full;
1100 break; 1113 break;
1101 case Common::Input::BatteryLevel::Medium: 1114 case Common::Input::BatteryLevel::Medium:
1102 battery_level = 6; 1115 battery_level = NpadBatteryLevel::High;
1103 break; 1116 break;
1104 case Common::Input::BatteryLevel::Low: 1117 case Common::Input::BatteryLevel::Low:
1105 battery_level = 4; 1118 battery_level = NpadBatteryLevel::Low;
1106 break; 1119 break;
1107 case Common::Input::BatteryLevel::Critical: 1120 case Common::Input::BatteryLevel::Critical:
1108 battery_level = 2; 1121 battery_level = NpadBatteryLevel::Critical;
1109 break; 1122 break;
1110 case Common::Input::BatteryLevel::Empty: 1123 case Common::Input::BatteryLevel::Empty:
1111 battery_level = 0; 1124 battery_level = NpadBatteryLevel::Empty;
1112 break; 1125 break;
1113 case Common::Input::BatteryLevel::None: 1126 case Common::Input::BatteryLevel::None:
1114 case Common::Input::BatteryLevel::Full: 1127 case Common::Input::BatteryLevel::Full:
1115 default: 1128 default:
1116 is_powered = true; 1129 is_powered = true;
1117 battery_level = 8; 1130 battery_level = NpadBatteryLevel::Full;
1118 break; 1131 break;
1119 } 1132 }
1120 1133
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index d4500583e..ea18c2343 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -253,6 +253,9 @@ public:
253 /// Overrides current mapped devices with the stored configuration and reloads all input devices 253 /// Overrides current mapped devices with the stored configuration and reloads all input devices
254 void ReloadFromSettings(); 254 void ReloadFromSettings();
255 255
256 /// Updates current colors with the ones stored in the configuration
257 void ReloadColorsFromSettings();
258
256 /// Saves the current mapped configuration 259 /// Saves the current mapped configuration
257 void SaveCurrentConfig(); 260 void SaveCurrentConfig();
258 261
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 00beb40dd..7ba75a50c 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -302,6 +302,15 @@ enum class TouchScreenModeForNx : u8 {
302 Heat2, 302 Heat2,
303}; 303};
304 304
305// This is nn::hid::system::NpadBatteryLevel
306enum class NpadBatteryLevel : u32 {
307 Empty,
308 Critical,
309 Low,
310 High,
311 Full,
312};
313
305// This is nn::hid::NpadStyleTag 314// This is nn::hid::NpadStyleTag
306struct NpadStyleTag { 315struct NpadStyleTag {
307 union { 316 union {
@@ -385,16 +394,12 @@ struct NpadGcTriggerState {
385}; 394};
386static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); 395static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size");
387 396
388// This is nn::hid::system::NpadBatteryLevel
389using NpadBatteryLevel = u32;
390static_assert(sizeof(NpadBatteryLevel) == 0x4, "NpadBatteryLevel is an invalid size");
391
392// This is nn::hid::system::NpadPowerInfo 397// This is nn::hid::system::NpadPowerInfo
393struct NpadPowerInfo { 398struct NpadPowerInfo {
394 bool is_powered{}; 399 bool is_powered{};
395 bool is_charging{}; 400 bool is_charging{};
396 INSERT_PADDING_BYTES(0x6); 401 INSERT_PADDING_BYTES(0x6);
397 NpadBatteryLevel battery_level{8}; 402 NpadBatteryLevel battery_level{NpadBatteryLevel::Full};
398}; 403};
399static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); 404static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
400 405
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
index 4cfdf4558..59364efa1 100644
--- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -8,7 +8,11 @@
8 8
9#include "core/hle/kernel/board/nintendo/nx/k_system_control.h" 9#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
10#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h" 10#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h"
11#include "core/hle/kernel/k_memory_manager.h"
12#include "core/hle/kernel/k_page_table.h"
11#include "core/hle/kernel/k_trace.h" 13#include "core/hle/kernel/k_trace.h"
14#include "core/hle/kernel/kernel.h"
15#include "core/hle/kernel/svc_results.h"
12 16
13namespace Kernel::Board::Nintendo::Nx { 17namespace Kernel::Board::Nintendo::Nx {
14 18
@@ -30,6 +34,8 @@ constexpr const std::size_t RequiredNonSecureSystemMemorySize =
30constexpr const std::size_t RequiredNonSecureSystemMemorySizeWithFatal = 34constexpr const std::size_t RequiredNonSecureSystemMemorySizeWithFatal =
31 RequiredNonSecureSystemMemorySize + impl::RequiredNonSecureSystemMemorySizeViFatal; 35 RequiredNonSecureSystemMemorySize + impl::RequiredNonSecureSystemMemorySizeViFatal;
32 36
37constexpr const std::size_t SecureAlignment = 128_KiB;
38
33namespace { 39namespace {
34 40
35using namespace Common::Literals; 41using namespace Common::Literals;
@@ -183,4 +189,57 @@ u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
183 return GenerateUniformRange(min, max, GenerateRandomU64); 189 return GenerateUniformRange(min, max, GenerateRandomU64);
184} 190}
185 191
192size_t KSystemControl::CalculateRequiredSecureMemorySize(size_t size, u32 pool) {
193 if (pool == static_cast<u32>(KMemoryManager::Pool::Applet)) {
194 return 0;
195 } else {
196 // return KSystemControlBase::CalculateRequiredSecureMemorySize(size, pool);
197 return size;
198 }
199}
200
201Result KSystemControl::AllocateSecureMemory(KernelCore& kernel, KVirtualAddress* out, size_t size,
202 u32 pool) {
203 // Applet secure memory is handled separately.
204 UNIMPLEMENTED_IF(pool == static_cast<u32>(KMemoryManager::Pool::Applet));
205
206 // Ensure the size is aligned.
207 const size_t alignment =
208 (pool == static_cast<u32>(KMemoryManager::Pool::System) ? PageSize : SecureAlignment);
209 R_UNLESS(Common::IsAligned(size, alignment), ResultInvalidSize);
210
211 // Allocate the memory.
212 const size_t num_pages = size / PageSize;
213 const KPhysicalAddress paddr = kernel.MemoryManager().AllocateAndOpenContinuous(
214 num_pages, alignment / PageSize,
215 KMemoryManager::EncodeOption(static_cast<KMemoryManager::Pool>(pool),
216 KMemoryManager::Direction::FromFront));
217 R_UNLESS(paddr != 0, ResultOutOfMemory);
218
219 // Ensure we don't leak references to the memory on error.
220 ON_RESULT_FAILURE {
221 kernel.MemoryManager().Close(paddr, num_pages);
222 };
223
224 // We succeeded.
225 *out = KPageTable::GetHeapVirtualAddress(kernel.MemoryLayout(), paddr);
226 R_SUCCEED();
227}
228
229void KSystemControl::FreeSecureMemory(KernelCore& kernel, KVirtualAddress address, size_t size,
230 u32 pool) {
231 // Applet secure memory is handled separately.
232 UNIMPLEMENTED_IF(pool == static_cast<u32>(KMemoryManager::Pool::Applet));
233
234 // Ensure the size is aligned.
235 const size_t alignment =
236 (pool == static_cast<u32>(KMemoryManager::Pool::System) ? PageSize : SecureAlignment);
237 ASSERT(Common::IsAligned(GetInteger(address), alignment));
238 ASSERT(Common::IsAligned(size, alignment));
239
240 // Close the secure region's pages.
241 kernel.MemoryManager().Close(KPageTable::GetHeapPhysicalAddress(kernel.MemoryLayout(), address),
242 size / PageSize);
243}
244
186} // namespace Kernel::Board::Nintendo::Nx 245} // namespace Kernel::Board::Nintendo::Nx
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
index b477e8193..ff1feec70 100644
--- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.h
@@ -4,6 +4,11 @@
4#pragma once 4#pragma once
5 5
6#include "core/hle/kernel/k_typed_address.h" 6#include "core/hle/kernel/k_typed_address.h"
7#include "core/hle/result.h"
8
9namespace Kernel {
10class KernelCore;
11}
7 12
8namespace Kernel::Board::Nintendo::Nx { 13namespace Kernel::Board::Nintendo::Nx {
9 14
@@ -25,8 +30,16 @@ public:
25 static std::size_t GetMinimumNonSecureSystemPoolSize(); 30 static std::size_t GetMinimumNonSecureSystemPoolSize();
26 }; 31 };
27 32
33 // Randomness.
28 static u64 GenerateRandomRange(u64 min, u64 max); 34 static u64 GenerateRandomRange(u64 min, u64 max);
29 static u64 GenerateRandomU64(); 35 static u64 GenerateRandomU64();
36
37 // Secure Memory.
38 static size_t CalculateRequiredSecureMemorySize(size_t size, u32 pool);
39 static Result AllocateSecureMemory(KernelCore& kernel, KVirtualAddress* out, size_t size,
40 u32 pool);
41 static void FreeSecureMemory(KernelCore& kernel, KVirtualAddress address, size_t size,
42 u32 pool);
30}; 43};
31 44
32} // namespace Kernel::Board::Nintendo::Nx 45} // namespace Kernel::Board::Nintendo::Nx
diff --git a/src/core/hle/kernel/k_capabilities.h b/src/core/hle/kernel/k_capabilities.h
index de766c811..ebd4eedb1 100644
--- a/src/core/hle/kernel/k_capabilities.h
+++ b/src/core/hle/kernel/k_capabilities.h
@@ -200,8 +200,8 @@ private:
200 200
201 RawCapabilityValue raw; 201 RawCapabilityValue raw;
202 BitField<0, 15, CapabilityType> id; 202 BitField<0, 15, CapabilityType> id;
203 BitField<15, 4, u32> major_version; 203 BitField<15, 4, u32> minor_version;
204 BitField<19, 13, u32> minor_version; 204 BitField<19, 13, u32> major_version;
205 }; 205 };
206 206
207 union HandleTable { 207 union HandleTable {
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index efbac0e6a..7633a51fb 100644
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -107,12 +107,12 @@ KConditionVariable::KConditionVariable(Core::System& system)
107 107
108KConditionVariable::~KConditionVariable() = default; 108KConditionVariable::~KConditionVariable() = default;
109 109
110Result KConditionVariable::SignalToAddress(KProcessAddress addr) { 110Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress addr) {
111 KThread* owner_thread = GetCurrentThreadPointer(m_kernel); 111 KThread* owner_thread = GetCurrentThreadPointer(kernel);
112 112
113 // Signal the address. 113 // Signal the address.
114 { 114 {
115 KScopedSchedulerLock sl(m_kernel); 115 KScopedSchedulerLock sl(kernel);
116 116
117 // Remove waiter thread. 117 // Remove waiter thread.
118 bool has_waiters{}; 118 bool has_waiters{};
@@ -133,7 +133,7 @@ Result KConditionVariable::SignalToAddress(KProcessAddress addr) {
133 133
134 // Write the value to userspace. 134 // Write the value to userspace.
135 Result result{ResultSuccess}; 135 Result result{ResultSuccess};
136 if (WriteToUser(m_kernel, addr, std::addressof(next_value))) [[likely]] { 136 if (WriteToUser(kernel, addr, std::addressof(next_value))) [[likely]] {
137 result = ResultSuccess; 137 result = ResultSuccess;
138 } else { 138 } else {
139 result = ResultInvalidCurrentMemory; 139 result = ResultInvalidCurrentMemory;
@@ -148,28 +148,28 @@ Result KConditionVariable::SignalToAddress(KProcessAddress addr) {
148 } 148 }
149} 149}
150 150
151Result KConditionVariable::WaitForAddress(Handle handle, KProcessAddress addr, u32 value) { 151Result KConditionVariable::WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr,
152 KThread* cur_thread = GetCurrentThreadPointer(m_kernel); 152 u32 value) {
153 ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(m_kernel); 153 KThread* cur_thread = GetCurrentThreadPointer(kernel);
154 ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel);
154 155
155 // Wait for the address. 156 // Wait for the address.
156 KThread* owner_thread{}; 157 KThread* owner_thread{};
157 { 158 {
158 KScopedSchedulerLock sl(m_kernel); 159 KScopedSchedulerLock sl(kernel);
159 160
160 // Check if the thread should terminate. 161 // Check if the thread should terminate.
161 R_UNLESS(!cur_thread->IsTerminationRequested(), ResultTerminationRequested); 162 R_UNLESS(!cur_thread->IsTerminationRequested(), ResultTerminationRequested);
162 163
163 // Read the tag from userspace. 164 // Read the tag from userspace.
164 u32 test_tag{}; 165 u32 test_tag{};
165 R_UNLESS(ReadFromUser(m_kernel, std::addressof(test_tag), addr), 166 R_UNLESS(ReadFromUser(kernel, std::addressof(test_tag), addr), ResultInvalidCurrentMemory);
166 ResultInvalidCurrentMemory);
167 167
168 // If the tag isn't the handle (with wait mask), we're done. 168 // If the tag isn't the handle (with wait mask), we're done.
169 R_SUCCEED_IF(test_tag != (handle | Svc::HandleWaitMask)); 169 R_SUCCEED_IF(test_tag != (handle | Svc::HandleWaitMask));
170 170
171 // Get the lock owner thread. 171 // Get the lock owner thread.
172 owner_thread = GetCurrentProcess(m_kernel) 172 owner_thread = GetCurrentProcess(kernel)
173 .GetHandleTable() 173 .GetHandleTable()
174 .GetObjectWithoutPseudoHandle<KThread>(handle) 174 .GetObjectWithoutPseudoHandle<KThread>(handle)
175 .ReleasePointerUnsafe(); 175 .ReleasePointerUnsafe();
diff --git a/src/core/hle/kernel/k_condition_variable.h b/src/core/hle/kernel/k_condition_variable.h
index 8c2f3ae51..2620c8e39 100644
--- a/src/core/hle/kernel/k_condition_variable.h
+++ b/src/core/hle/kernel/k_condition_variable.h
@@ -24,11 +24,12 @@ public:
24 explicit KConditionVariable(Core::System& system); 24 explicit KConditionVariable(Core::System& system);
25 ~KConditionVariable(); 25 ~KConditionVariable();
26 26
27 // Arbitration 27 // Arbitration.
28 Result SignalToAddress(KProcessAddress addr); 28 static Result SignalToAddress(KernelCore& kernel, KProcessAddress addr);
29 Result WaitForAddress(Handle handle, KProcessAddress addr, u32 value); 29 static Result WaitForAddress(KernelCore& kernel, Handle handle, KProcessAddress addr,
30 u32 value);
30 31
31 // Condition variable 32 // Condition variable.
32 void Signal(u64 cv_key, s32 count); 33 void Signal(u64 cv_key, s32 count);
33 Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout); 34 Result Wait(KProcessAddress addr, u64 key, u32 value, s64 timeout);
34 35
diff --git a/src/core/hle/kernel/k_interrupt_manager.cpp b/src/core/hle/kernel/k_interrupt_manager.cpp
index fe6a20168..22d79569a 100644
--- a/src/core/hle/kernel/k_interrupt_manager.cpp
+++ b/src/core/hle/kernel/k_interrupt_manager.cpp
@@ -22,7 +22,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) {
22 KScopedSchedulerLock sl{kernel}; 22 KScopedSchedulerLock sl{kernel};
23 23
24 // Pin the current thread. 24 // Pin the current thread.
25 process->PinCurrentThread(core_id); 25 process->PinCurrentThread();
26 26
27 // Set the interrupt flag for the thread. 27 // Set the interrupt flag for the thread.
28 GetCurrentThread(kernel).SetInterruptFlag(); 28 GetCurrentThread(kernel).SetInterruptFlag();
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index 637558e10..cdc5572d8 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -11,6 +11,7 @@
11#include "core/hle/kernel/initial_process.h" 11#include "core/hle/kernel/initial_process.h"
12#include "core/hle/kernel/k_memory_manager.h" 12#include "core/hle/kernel/k_memory_manager.h"
13#include "core/hle/kernel/k_page_group.h" 13#include "core/hle/kernel/k_page_group.h"
14#include "core/hle/kernel/k_page_table.h"
14#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
15#include "core/hle/kernel/svc_results.h" 16#include "core/hle/kernel/svc_results.h"
16 17
@@ -168,11 +169,37 @@ void KMemoryManager::Initialize(KVirtualAddress management_region, size_t manage
168} 169}
169 170
170Result KMemoryManager::InitializeOptimizedMemory(u64 process_id, Pool pool) { 171Result KMemoryManager::InitializeOptimizedMemory(u64 process_id, Pool pool) {
171 UNREACHABLE(); 172 const u32 pool_index = static_cast<u32>(pool);
173
174 // Lock the pool.
175 KScopedLightLock lk(m_pool_locks[pool_index]);
176
177 // Check that we don't already have an optimized process.
178 R_UNLESS(!m_has_optimized_process[pool_index], ResultBusy);
179
180 // Set the optimized process id.
181 m_optimized_process_ids[pool_index] = process_id;
182 m_has_optimized_process[pool_index] = true;
183
184 // Clear the management area for the optimized process.
185 for (auto* manager = this->GetFirstManager(pool, Direction::FromFront); manager != nullptr;
186 manager = this->GetNextManager(manager, Direction::FromFront)) {
187 manager->InitializeOptimizedMemory(m_system.Kernel());
188 }
189
190 R_SUCCEED();
172} 191}
173 192
174void KMemoryManager::FinalizeOptimizedMemory(u64 process_id, Pool pool) { 193void KMemoryManager::FinalizeOptimizedMemory(u64 process_id, Pool pool) {
175 UNREACHABLE(); 194 const u32 pool_index = static_cast<u32>(pool);
195
196 // Lock the pool.
197 KScopedLightLock lk(m_pool_locks[pool_index]);
198
199 // If the process was optimized, clear it.
200 if (m_has_optimized_process[pool_index] && m_optimized_process_ids[pool_index] == process_id) {
201 m_has_optimized_process[pool_index] = false;
202 }
176} 203}
177 204
178KPhysicalAddress KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, 205KPhysicalAddress KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, size_t align_pages,
@@ -207,7 +234,7 @@ KPhysicalAddress KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, siz
207 234
208 // Maintain the optimized memory bitmap, if we should. 235 // Maintain the optimized memory bitmap, if we should.
209 if (m_has_optimized_process[static_cast<size_t>(pool)]) { 236 if (m_has_optimized_process[static_cast<size_t>(pool)]) {
210 UNIMPLEMENTED(); 237 chosen_manager->TrackUnoptimizedAllocation(m_system.Kernel(), allocated_block, num_pages);
211 } 238 }
212 239
213 // Open the first reference to the pages. 240 // Open the first reference to the pages.
@@ -255,7 +282,8 @@ Result KMemoryManager::AllocatePageGroupImpl(KPageGroup* out, size_t num_pages,
255 282
256 // Maintain the optimized memory bitmap, if we should. 283 // Maintain the optimized memory bitmap, if we should.
257 if (unoptimized) { 284 if (unoptimized) {
258 UNIMPLEMENTED(); 285 cur_manager->TrackUnoptimizedAllocation(m_system.Kernel(), allocated_block,
286 pages_per_alloc);
259 } 287 }
260 288
261 num_pages -= pages_per_alloc; 289 num_pages -= pages_per_alloc;
@@ -358,8 +386,8 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
358 // Process part or all of the block. 386 // Process part or all of the block.
359 const size_t cur_pages = 387 const size_t cur_pages =
360 std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); 388 std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address));
361 any_new = 389 any_new = manager.ProcessOptimizedAllocation(m_system.Kernel(), cur_address,
362 manager.ProcessOptimizedAllocation(cur_address, cur_pages, fill_pattern); 390 cur_pages, fill_pattern);
363 391
364 // Advance. 392 // Advance.
365 cur_address += cur_pages * PageSize; 393 cur_address += cur_pages * PageSize;
@@ -382,7 +410,7 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
382 // Track some or all of the current pages. 410 // Track some or all of the current pages.
383 const size_t cur_pages = 411 const size_t cur_pages =
384 std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address)); 412 std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address));
385 manager.TrackOptimizedAllocation(cur_address, cur_pages); 413 manager.TrackOptimizedAllocation(m_system.Kernel(), cur_address, cur_pages);
386 414
387 // Advance. 415 // Advance.
388 cur_address += cur_pages * PageSize; 416 cur_address += cur_pages * PageSize;
@@ -427,17 +455,86 @@ size_t KMemoryManager::Impl::Initialize(KPhysicalAddress address, size_t size,
427 return total_management_size; 455 return total_management_size;
428} 456}
429 457
430void KMemoryManager::Impl::TrackUnoptimizedAllocation(KPhysicalAddress block, size_t num_pages) { 458void KMemoryManager::Impl::InitializeOptimizedMemory(KernelCore& kernel) {
431 UNREACHABLE(); 459 auto optimize_pa =
460 KPageTable::GetHeapPhysicalAddress(kernel.MemoryLayout(), m_management_region);
461 auto* optimize_map = kernel.System().DeviceMemory().GetPointer<u64>(optimize_pa);
462
463 std::memset(optimize_map, 0, CalculateOptimizedProcessOverheadSize(m_heap.GetSize()));
432} 464}
433 465
434void KMemoryManager::Impl::TrackOptimizedAllocation(KPhysicalAddress block, size_t num_pages) { 466void KMemoryManager::Impl::TrackUnoptimizedAllocation(KernelCore& kernel, KPhysicalAddress block,
435 UNREACHABLE(); 467 size_t num_pages) {
468 auto optimize_pa =
469 KPageTable::GetHeapPhysicalAddress(kernel.MemoryLayout(), m_management_region);
470 auto* optimize_map = kernel.System().DeviceMemory().GetPointer<u64>(optimize_pa);
471
472 // Get the range we're tracking.
473 size_t offset = this->GetPageOffset(block);
474 const size_t last = offset + num_pages - 1;
475
476 // Track.
477 while (offset <= last) {
478 // Mark the page as not being optimized-allocated.
479 optimize_map[offset / Common::BitSize<u64>()] &=
480 ~(u64(1) << (offset % Common::BitSize<u64>()));
481
482 offset++;
483 }
484}
485
486void KMemoryManager::Impl::TrackOptimizedAllocation(KernelCore& kernel, KPhysicalAddress block,
487 size_t num_pages) {
488 auto optimize_pa =
489 KPageTable::GetHeapPhysicalAddress(kernel.MemoryLayout(), m_management_region);
490 auto* optimize_map = kernel.System().DeviceMemory().GetPointer<u64>(optimize_pa);
491
492 // Get the range we're tracking.
493 size_t offset = this->GetPageOffset(block);
494 const size_t last = offset + num_pages - 1;
495
496 // Track.
497 while (offset <= last) {
498 // Mark the page as being optimized-allocated.
499 optimize_map[offset / Common::BitSize<u64>()] |=
500 (u64(1) << (offset % Common::BitSize<u64>()));
501
502 offset++;
503 }
436} 504}
437 505
438bool KMemoryManager::Impl::ProcessOptimizedAllocation(KPhysicalAddress block, size_t num_pages, 506bool KMemoryManager::Impl::ProcessOptimizedAllocation(KernelCore& kernel, KPhysicalAddress block,
439 u8 fill_pattern) { 507 size_t num_pages, u8 fill_pattern) {
440 UNREACHABLE(); 508 auto& device_memory = kernel.System().DeviceMemory();
509 auto optimize_pa =
510 KPageTable::GetHeapPhysicalAddress(kernel.MemoryLayout(), m_management_region);
511 auto* optimize_map = device_memory.GetPointer<u64>(optimize_pa);
512
513 // We want to return whether any pages were newly allocated.
514 bool any_new = false;
515
516 // Get the range we're processing.
517 size_t offset = this->GetPageOffset(block);
518 const size_t last = offset + num_pages - 1;
519
520 // Process.
521 while (offset <= last) {
522 // Check if the page has been optimized-allocated before.
523 if ((optimize_map[offset / Common::BitSize<u64>()] &
524 (u64(1) << (offset % Common::BitSize<u64>()))) == 0) {
525 // If not, it's new.
526 any_new = true;
527
528 // Fill the page.
529 auto* ptr = device_memory.GetPointer<u8>(m_heap.GetAddress());
530 std::memset(ptr + offset * PageSize, fill_pattern, PageSize);
531 }
532
533 offset++;
534 }
535
536 // Return the number of pages we processed.
537 return any_new;
441} 538}
442 539
443size_t KMemoryManager::Impl::CalculateManagementOverheadSize(size_t region_size) { 540size_t KMemoryManager::Impl::CalculateManagementOverheadSize(size_t region_size) {
diff --git a/src/core/hle/kernel/k_memory_manager.h b/src/core/hle/kernel/k_memory_manager.h
index 7e4b41319..c5a487af9 100644
--- a/src/core/hle/kernel/k_memory_manager.h
+++ b/src/core/hle/kernel/k_memory_manager.h
@@ -216,14 +216,14 @@ private:
216 m_heap.SetInitialUsedSize(reserved_size); 216 m_heap.SetInitialUsedSize(reserved_size);
217 } 217 }
218 218
219 void InitializeOptimizedMemory() { 219 void InitializeOptimizedMemory(KernelCore& kernel);
220 UNIMPLEMENTED();
221 }
222 220
223 void TrackUnoptimizedAllocation(KPhysicalAddress block, size_t num_pages); 221 void TrackUnoptimizedAllocation(KernelCore& kernel, KPhysicalAddress block,
224 void TrackOptimizedAllocation(KPhysicalAddress block, size_t num_pages); 222 size_t num_pages);
223 void TrackOptimizedAllocation(KernelCore& kernel, KPhysicalAddress block, size_t num_pages);
225 224
226 bool ProcessOptimizedAllocation(KPhysicalAddress block, size_t num_pages, u8 fill_pattern); 225 bool ProcessOptimizedAllocation(KernelCore& kernel, KPhysicalAddress block,
226 size_t num_pages, u8 fill_pattern);
227 227
228 constexpr Pool GetPool() const { 228 constexpr Pool GetPool() const {
229 return m_pool; 229 return m_pool;
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 217ccbae3..1d47bdf6b 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -82,14 +82,14 @@ public:
82 82
83using namespace Common::Literals; 83using namespace Common::Literals;
84 84
85constexpr size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceType as_type) { 85constexpr size_t GetAddressSpaceWidthFromType(Svc::CreateProcessFlag as_type) {
86 switch (as_type) { 86 switch (as_type) {
87 case FileSys::ProgramAddressSpaceType::Is32Bit: 87 case Svc::CreateProcessFlag::AddressSpace32Bit:
88 case FileSys::ProgramAddressSpaceType::Is32BitNoMap: 88 case Svc::CreateProcessFlag::AddressSpace32BitWithoutAlias:
89 return 32; 89 return 32;
90 case FileSys::ProgramAddressSpaceType::Is36Bit: 90 case Svc::CreateProcessFlag::AddressSpace64BitDeprecated:
91 return 36; 91 return 36;
92 case FileSys::ProgramAddressSpaceType::Is39Bit: 92 case Svc::CreateProcessFlag::AddressSpace64Bit:
93 return 39; 93 return 39;
94 default: 94 default:
95 ASSERT(false); 95 ASSERT(false);
@@ -105,7 +105,7 @@ KPageTable::KPageTable(Core::System& system_)
105 105
106KPageTable::~KPageTable() = default; 106KPageTable::~KPageTable() = default;
107 107
108Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, 108Result KPageTable::InitializeForProcess(Svc::CreateProcessFlag as_type, bool enable_aslr,
109 bool enable_das_merge, bool from_back, 109 bool enable_das_merge, bool from_back,
110 KMemoryManager::Pool pool, KProcessAddress code_addr, 110 KMemoryManager::Pool pool, KProcessAddress code_addr,
111 size_t code_size, KSystemResource* system_resource, 111 size_t code_size, KSystemResource* system_resource,
@@ -133,7 +133,7 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
133 ASSERT(code_addr + code_size - 1 <= end - 1); 133 ASSERT(code_addr + code_size - 1 <= end - 1);
134 134
135 // Adjust heap/alias size if we don't have an alias region 135 // Adjust heap/alias size if we don't have an alias region
136 if (as_type == FileSys::ProgramAddressSpaceType::Is32BitNoMap) { 136 if (as_type == Svc::CreateProcessFlag::AddressSpace32BitWithoutAlias) {
137 heap_region_size += alias_region_size; 137 heap_region_size += alias_region_size;
138 alias_region_size = 0; 138 alias_region_size = 0;
139 } 139 }
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index 3d64b6fb0..66f16faaf 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -63,7 +63,7 @@ public:
63 explicit KPageTable(Core::System& system_); 63 explicit KPageTable(Core::System& system_);
64 ~KPageTable(); 64 ~KPageTable();
65 65
66 Result InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, 66 Result InitializeForProcess(Svc::CreateProcessFlag as_type, bool enable_aslr,
67 bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, 67 bool enable_das_merge, bool from_back, KMemoryManager::Pool pool,
68 KProcessAddress code_addr, size_t code_size, 68 KProcessAddress code_addr, size_t code_size,
69 KSystemResource* system_resource, KResourceLimit* resource_limit, 69 KSystemResource* system_resource, KResourceLimit* resource_limit,
@@ -400,7 +400,7 @@ public:
400 constexpr size_t GetAliasCodeRegionSize() const { 400 constexpr size_t GetAliasCodeRegionSize() const {
401 return m_alias_code_region_end - m_alias_code_region_start; 401 return m_alias_code_region_end - m_alias_code_region_start;
402 } 402 }
403 size_t GetNormalMemorySize() { 403 size_t GetNormalMemorySize() const {
404 KScopedLightLock lk(m_general_lock); 404 KScopedLightLock lk(m_general_lock);
405 return GetHeapSize() + m_mapped_physical_memory_size; 405 return GetHeapSize() + m_mapped_physical_memory_size;
406 } 406 }
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 7fa34d693..1f4b0755d 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -1,515 +1,598 @@
1// SPDX-FileCopyrightText: 2015 Citra Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <algorithm>
5#include <bitset>
6#include <ctime>
7#include <memory>
8#include <random> 4#include <random>
9#include "common/alignment.h"
10#include "common/assert.h"
11#include "common/logging/log.h"
12#include "common/scope_exit.h" 5#include "common/scope_exit.h"
13#include "common/settings.h" 6#include "common/settings.h"
14#include "core/core.h" 7#include "core/core.h"
15#include "core/file_sys/program_metadata.h"
16#include "core/hle/kernel/code_set.h"
17#include "core/hle/kernel/k_memory_block_manager.h"
18#include "core/hle/kernel/k_page_table.h"
19#include "core/hle/kernel/k_process.h" 8#include "core/hle/kernel/k_process.h"
20#include "core/hle/kernel/k_resource_limit.h"
21#include "core/hle/kernel/k_scheduler.h"
22#include "core/hle/kernel/k_scoped_resource_reservation.h" 9#include "core/hle/kernel/k_scoped_resource_reservation.h"
23#include "core/hle/kernel/k_shared_memory.h" 10#include "core/hle/kernel/k_shared_memory.h"
24#include "core/hle/kernel/k_shared_memory_info.h" 11#include "core/hle/kernel/k_shared_memory_info.h"
25#include "core/hle/kernel/k_thread.h" 12#include "core/hle/kernel/k_thread_local_page.h"
26#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/k_thread_queue.h"
27#include "core/hle/kernel/svc_results.h" 14#include "core/hle/kernel/k_worker_task_manager.h"
28#include "core/memory.h"
29 15
30namespace Kernel { 16namespace Kernel {
31namespace {
32/**
33 * Sets up the primary application thread
34 *
35 * @param system The system instance to create the main thread under.
36 * @param owner_process The parent process for the main thread
37 * @param priority The priority to give the main thread
38 */
39void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
40 KProcessAddress stack_top) {
41 const KProcessAddress entry_point = owner_process.GetEntryPoint();
42 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
43
44 KThread* thread = KThread::Create(system.Kernel());
45 SCOPE_EXIT({ thread->Close(); });
46
47 ASSERT(KThread::InitializeUserThread(system, thread, entry_point, 0, stack_top, priority,
48 owner_process.GetIdealCoreId(),
49 std::addressof(owner_process))
50 .IsSuccess());
51
52 // Register 1 must be a handle to the main thread
53 Handle thread_handle{};
54 owner_process.GetHandleTable().Add(std::addressof(thread_handle), thread);
55
56 thread->GetContext32().cpu_registers[0] = 0;
57 thread->GetContext64().cpu_registers[0] = 0;
58 thread->GetContext32().cpu_registers[1] = thread_handle;
59 thread->GetContext64().cpu_registers[1] = thread_handle;
60
61 if (system.DebuggerEnabled()) {
62 thread->RequestSuspend(SuspendType::Debug);
63 }
64 17
65 // Run our thread. 18namespace {
66 void(thread->Run());
67}
68} // Anonymous namespace
69 19
70Result KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name, 20Result TerminateChildren(KernelCore& kernel, KProcess* process,
71 ProcessType type, KResourceLimit* res_limit) { 21 const KThread* thread_to_not_terminate) {
72 auto& kernel = system.Kernel(); 22 // Request that all children threads terminate.
23 {
24 KScopedLightLock proc_lk(process->GetListLock());
25 KScopedSchedulerLock sl(kernel);
26
27 if (thread_to_not_terminate != nullptr &&
28 process->GetPinnedThread(GetCurrentCoreId(kernel)) == thread_to_not_terminate) {
29 // NOTE: Here Nintendo unpins the current thread instead of the thread_to_not_terminate.
30 // This is valid because the only caller which uses non-nullptr as argument uses
31 // GetCurrentThreadPointer(), but it's still notable because it seems incorrect at
32 // first glance.
33 process->UnpinCurrentThread();
34 }
73 35
74 process->name = std::move(process_name); 36 auto& thread_list = process->GetThreadList();
75 process->m_resource_limit = res_limit; 37 for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
76 process->m_system_resource_address = 0; 38 if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) {
77 process->m_state = State::Created; 39 if (thread->GetState() != ThreadState::Terminated) {
78 process->m_program_id = 0; 40 thread->RequestTerminate();
79 process->m_process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() 41 }
80 : kernel.CreateNewUserProcessID(); 42 }
81 process->m_capabilities.InitializeForMetadatalessProcess(); 43 }
82 process->m_is_initialized = true; 44 }
83 45
84 std::mt19937 rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue() 46 // Wait for all children threads to terminate.
85 : static_cast<u32>(std::time(nullptr))); 47 while (true) {
86 std::uniform_int_distribution<u64> distribution; 48 // Get the next child.
87 std::generate(process->m_random_entropy.begin(), process->m_random_entropy.end(), 49 KThread* cur_child = nullptr;
88 [&] { return distribution(rng); }); 50 {
51 KScopedLightLock proc_lk(process->GetListLock());
52
53 auto& thread_list = process->GetThreadList();
54 for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
55 if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) {
56 if (thread->GetState() != ThreadState::Terminated) {
57 if (thread->Open()) {
58 cur_child = thread;
59 break;
60 }
61 }
62 }
63 }
64 }
89 65
90 kernel.AppendNewProcess(process); 66 // If we didn't find any non-terminated children, we're done.
67 if (cur_child == nullptr) {
68 break;
69 }
91 70
92 // Clear remaining fields. 71 // Terminate and close the thread.
93 process->m_num_running_threads = 0; 72 SCOPE_EXIT({ cur_child->Close(); });
94 process->m_is_signaled = false;
95 process->m_exception_thread = nullptr;
96 process->m_is_suspended = false;
97 process->m_schedule_count = 0;
98 process->m_is_handle_table_initialized = false;
99 process->m_is_hbl = false;
100 73
101 // Open a reference to the resource limit. 74 if (const Result terminate_result = cur_child->Terminate();
102 process->m_resource_limit->Open(); 75 ResultTerminationRequested == terminate_result) {
76 R_THROW(terminate_result);
77 }
78 }
103 79
104 R_SUCCEED(); 80 R_SUCCEED();
105} 81}
106 82
107void KProcess::DoWorkerTaskImpl() { 83class ThreadQueueImplForKProcessEnterUserException final : public KThreadQueue {
108 UNIMPLEMENTED(); 84private:
109} 85 KThread** m_exception_thread;
110
111KResourceLimit* KProcess::GetResourceLimit() const {
112 return m_resource_limit;
113}
114 86
115void KProcess::IncrementRunningThreadCount() { 87public:
116 ASSERT(m_num_running_threads.load() >= 0); 88 explicit ThreadQueueImplForKProcessEnterUserException(KernelCore& kernel, KThread** t)
117 ++m_num_running_threads; 89 : KThreadQueue(kernel), m_exception_thread(t) {}
118}
119 90
120void KProcess::DecrementRunningThreadCount() { 91 virtual void EndWait(KThread* waiting_thread, Result wait_result) override {
121 ASSERT(m_num_running_threads.load() > 0); 92 // Set the exception thread.
93 *m_exception_thread = waiting_thread;
122 94
123 if (const auto prev = m_num_running_threads--; prev == 1) { 95 // Invoke the base end wait handler.
124 // TODO(bunnei): Process termination to be implemented when multiprocess is supported. 96 KThreadQueue::EndWait(waiting_thread, wait_result);
125 } 97 }
126}
127 98
128u64 KProcess::GetTotalPhysicalMemoryAvailable() { 99 virtual void CancelWait(KThread* waiting_thread, Result wait_result,
129 const u64 capacity{m_resource_limit->GetFreeValue(LimitableResource::PhysicalMemoryMax) + 100 bool cancel_timer_task) override {
130 m_page_table.GetNormalMemorySize() + GetSystemResourceSize() + m_image_size + 101 // Remove the thread as a waiter on its mutex owner.
131 m_main_thread_stack_size}; 102 waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread);
132 if (const auto pool_size = m_kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); 103
133 capacity != pool_size) { 104 // Invoke the base cancel wait handler.
134 LOG_WARNING(Kernel, "capacity {} != application pool size {}", capacity, pool_size); 105 KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task);
135 }
136 if (capacity < m_memory_usage_capacity) {
137 return capacity;
138 } 106 }
139 return m_memory_usage_capacity; 107};
140}
141 108
142u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() { 109void GenerateRandom(std::span<u64> out_random) {
143 return this->GetTotalPhysicalMemoryAvailable() - this->GetSystemResourceSize(); 110 std::mt19937 rng(Settings::values.rng_seed_enabled ? Settings::values.rng_seed.GetValue()
111 : static_cast<u32>(std::time(nullptr)));
112 std::uniform_int_distribution<u64> distribution;
113 std::generate(out_random.begin(), out_random.end(), [&] { return distribution(rng); });
144} 114}
145 115
146u64 KProcess::GetTotalPhysicalMemoryUsed() { 116} // namespace
147 return m_image_size + m_main_thread_stack_size + m_page_table.GetNormalMemorySize() +
148 this->GetSystemResourceSize();
149}
150 117
151u64 KProcess::GetTotalPhysicalMemoryUsedWithoutSystemResource() { 118void KProcess::Finalize() {
152 return this->GetTotalPhysicalMemoryUsed() - this->GetSystemResourceSize(); 119 // Delete the process local region.
153} 120 this->DeleteThreadLocalRegion(m_plr_address);
154 121
155bool KProcess::ReleaseUserException(KThread* thread) { 122 // Get the used memory size.
156 KScopedSchedulerLock sl{m_kernel}; 123 const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize();
157 124
158 if (m_exception_thread == thread) { 125 // Finalize the page table.
159 m_exception_thread = nullptr; 126 m_page_table.Finalize();
160 127
161 // Remove waiter thread. 128 // Finish using our system resource.
162 bool has_waiters{}; 129 if (m_system_resource) {
163 if (KThread* next = thread->RemoveKernelWaiterByKey( 130 if (m_system_resource->IsSecureResource()) {
164 std::addressof(has_waiters), 131 // Finalize optimized memory. If memory wasn't optimized, this is a no-op.
165 reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread))); 132 m_kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
166 next != nullptr) {
167 next->EndWait(ResultSuccess);
168 } 133 }
169 134
170 KScheduler::SetSchedulerUpdateNeeded(m_kernel); 135 m_system_resource->Close();
171 136 m_system_resource = nullptr;
172 return true;
173 } else {
174 return false;
175 } 137 }
176}
177
178void KProcess::PinCurrentThread(s32 core_id) {
179 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
180 138
181 // Get the current thread. 139 // Free all shared memory infos.
182 KThread* cur_thread = 140 {
183 m_kernel.Scheduler(static_cast<std::size_t>(core_id)).GetSchedulerCurrentThread(); 141 auto it = m_shared_memory_list.begin();
142 while (it != m_shared_memory_list.end()) {
143 KSharedMemoryInfo* info = std::addressof(*it);
144 KSharedMemory* shmem = info->GetSharedMemory();
184 145
185 // If the thread isn't terminated, pin it. 146 while (!info->Close()) {
186 if (!cur_thread->IsTerminationRequested()) { 147 shmem->Close();
187 // Pin it. 148 }
188 this->PinThread(core_id, cur_thread); 149 shmem->Close();
189 cur_thread->Pin(core_id);
190 150
191 // An update is needed. 151 it = m_shared_memory_list.erase(it);
192 KScheduler::SetSchedulerUpdateNeeded(m_kernel); 152 KSharedMemoryInfo::Free(m_kernel, info);
153 }
193 } 154 }
194}
195 155
196void KProcess::UnpinCurrentThread(s32 core_id) { 156 // Our thread local page list must be empty at this point.
197 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); 157 ASSERT(m_partially_used_tlp_tree.empty());
198 158 ASSERT(m_fully_used_tlp_tree.empty());
199 // Get the current thread.
200 KThread* cur_thread =
201 m_kernel.Scheduler(static_cast<std::size_t>(core_id)).GetSchedulerCurrentThread();
202 159
203 // Unpin it. 160 // Release memory to the resource limit.
204 cur_thread->Unpin(); 161 if (m_resource_limit != nullptr) {
205 this->UnpinThread(core_id, cur_thread); 162 ASSERT(used_memory_size >= m_memory_release_hint);
163 m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, used_memory_size,
164 used_memory_size - m_memory_release_hint);
165 m_resource_limit->Close();
166 }
206 167
207 // An update is needed. 168 // Perform inherited finalization.
208 KScheduler::SetSchedulerUpdateNeeded(m_kernel); 169 KSynchronizationObject::Finalize();
209} 170}
210 171
211void KProcess::UnpinThread(KThread* thread) { 172Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit,
212 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); 173 bool is_real) {
213 174 // TODO: remove this special case
214 // Get the thread's core id. 175 if (is_real) {
215 const auto core_id = thread->GetActiveCore(); 176 // Create and clear the process local region.
177 R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address)));
178 this->GetMemory().ZeroBlock(m_plr_address, Svc::ThreadLocalRegionSize);
179 }
216 180
217 // Unpin it. 181 // Copy in the name from parameters.
218 this->UnpinThread(core_id, thread); 182 static_assert(sizeof(params.name) < sizeof(m_name));
219 thread->Unpin(); 183 std::memcpy(m_name.data(), params.name.data(), sizeof(params.name));
184 m_name[sizeof(params.name)] = 0;
185
186 // Set misc fields.
187 m_state = State::Created;
188 m_main_thread_stack_size = 0;
189 m_used_kernel_memory_size = 0;
190 m_ideal_core_id = 0;
191 m_flags = params.flags;
192 m_version = params.version;
193 m_program_id = params.program_id;
194 m_code_address = params.code_address;
195 m_code_size = params.code_num_pages * PageSize;
196 m_is_application = True(params.flags & Svc::CreateProcessFlag::IsApplication);
197
198 // Set thread fields.
199 for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
200 m_running_threads[i] = nullptr;
201 m_pinned_threads[i] = nullptr;
202 m_running_thread_idle_counts[i] = 0;
203 m_running_thread_switch_counts[i] = 0;
204 }
220 205
221 // An update is needed. 206 // Set max memory based on address space type.
222 KScheduler::SetSchedulerUpdateNeeded(m_kernel); 207 switch ((params.flags & Svc::CreateProcessFlag::AddressSpaceMask)) {
223} 208 case Svc::CreateProcessFlag::AddressSpace32Bit:
209 case Svc::CreateProcessFlag::AddressSpace64BitDeprecated:
210 case Svc::CreateProcessFlag::AddressSpace64Bit:
211 m_max_process_memory = m_page_table.GetHeapRegionSize();
212 break;
213 case Svc::CreateProcessFlag::AddressSpace32BitWithoutAlias:
214 m_max_process_memory = m_page_table.GetHeapRegionSize() + m_page_table.GetAliasRegionSize();
215 break;
216 default:
217 UNREACHABLE();
218 }
224 219
225Result KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] KProcessAddress address, 220 // Generate random entropy.
226 [[maybe_unused]] size_t size) { 221 GenerateRandom(m_entropy);
227 // Lock ourselves, to prevent concurrent access.
228 KScopedLightLock lk(m_state_lock);
229 222
230 // Try to find an existing info for the memory. 223 // Clear remaining fields.
231 KSharedMemoryInfo* shemen_info = nullptr; 224 m_num_running_threads = 0;
232 const auto iter = std::find_if( 225 m_num_process_switches = 0;
233 m_shared_memory_list.begin(), m_shared_memory_list.end(), 226 m_num_thread_switches = 0;
234 [shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; }); 227 m_num_fpu_switches = 0;
235 if (iter != m_shared_memory_list.end()) { 228 m_num_supervisor_calls = 0;
236 shemen_info = *iter; 229 m_num_ipc_messages = 0;
237 }
238 230
239 if (shemen_info == nullptr) { 231 m_is_signaled = false;
240 shemen_info = KSharedMemoryInfo::Allocate(m_kernel); 232 m_exception_thread = nullptr;
241 R_UNLESS(shemen_info != nullptr, ResultOutOfMemory); 233 m_is_suspended = false;
234 m_memory_release_hint = 0;
235 m_schedule_count = 0;
236 m_is_handle_table_initialized = false;
242 237
243 shemen_info->Initialize(shmem); 238 // Open a reference to our resource limit.
244 m_shared_memory_list.push_back(shemen_info); 239 m_resource_limit = res_limit;
245 } 240 m_resource_limit->Open();
246 241
247 // Open a reference to the shared memory and its info. 242 // We're initialized!
248 shmem->Open(); 243 m_is_initialized = true;
249 shemen_info->Open();
250 244
251 R_SUCCEED(); 245 R_SUCCEED();
252} 246}
253 247
254void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] KProcessAddress address, 248Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg,
255 [[maybe_unused]] size_t size) { 249 std::span<const u32> caps, KResourceLimit* res_limit,
256 // Lock ourselves, to prevent concurrent access. 250 KMemoryManager::Pool pool, bool immortal) {
257 KScopedLightLock lk(m_state_lock); 251 ASSERT(res_limit != nullptr);
252 ASSERT((params.code_num_pages * PageSize) / PageSize ==
253 static_cast<size_t>(params.code_num_pages));
254
255 // Set members.
256 m_memory_pool = pool;
257 m_is_default_application_system_resource = false;
258 m_is_immortal = immortal;
259
260 // Setup our system resource.
261 if (const size_t system_resource_num_pages = params.system_resource_num_pages;
262 system_resource_num_pages != 0) {
263 // Create a secure system resource.
264 KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel);
265 R_UNLESS(secure_resource != nullptr, ResultOutOfResource);
266
267 ON_RESULT_FAILURE {
268 secure_resource->Close();
269 };
270
271 // Initialize the secure resource.
272 R_TRY(secure_resource->Initialize(system_resource_num_pages * PageSize, res_limit,
273 m_memory_pool));
274
275 // Set our system resource.
276 m_system_resource = secure_resource;
277 } else {
278 // Use the system-wide system resource.
279 const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication);
280 m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource()
281 : m_kernel.GetSystemSystemResource());
258 282
259 KSharedMemoryInfo* shemen_info = nullptr; 283 m_is_default_application_system_resource = is_app;
260 const auto iter = std::find_if( 284
261 m_shared_memory_list.begin(), m_shared_memory_list.end(), 285 // Open reference to the system resource.
262 [shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; }); 286 m_system_resource->Open();
263 if (iter != m_shared_memory_list.end()) {
264 shemen_info = *iter;
265 } 287 }
266 288
267 ASSERT(shemen_info != nullptr); 289 // Ensure we clean up our secure resource, if we fail.
290 ON_RESULT_FAILURE {
291 m_system_resource->Close();
292 m_system_resource = nullptr;
293 };
268 294
269 if (shemen_info->Close()) { 295 // Setup page table.
270 m_shared_memory_list.erase(iter); 296 {
271 KSharedMemoryInfo::Free(m_kernel, shemen_info); 297 const auto as_type = params.flags & Svc::CreateProcessFlag::AddressSpaceMask;
298 const bool enable_aslr = True(params.flags & Svc::CreateProcessFlag::EnableAslr);
299 const bool enable_das_merge =
300 False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
301 R_TRY(m_page_table.InitializeForProcess(
302 as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address,
303 params.code_num_pages * PageSize, m_system_resource, res_limit, this->GetMemory()));
272 } 304 }
305 ON_RESULT_FAILURE_2 {
306 m_page_table.Finalize();
307 };
273 308
274 // Close a reference to the shared memory. 309 // Ensure we can insert the code region.
275 shmem->Close(); 310 R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize,
276} 311 KMemoryState::Code),
312 ResultInvalidMemoryRegion);
277 313
278void KProcess::RegisterThread(KThread* thread) { 314 // Map the code region.
279 KScopedLightLock lk{m_list_lock}; 315 R_TRY(m_page_table.MapPageGroup(params.code_address, pg, KMemoryState::Code,
316 KMemoryPermission::KernelRead));
280 317
281 m_thread_list.push_back(thread); 318 // Initialize capabilities.
282} 319 R_TRY(m_capabilities.InitializeForKip(caps, std::addressof(m_page_table)));
283 320
284void KProcess::UnregisterThread(KThread* thread) { 321 // Initialize the process id.
285 KScopedLightLock lk{m_list_lock}; 322 m_process_id = m_kernel.CreateNewUserProcessID();
323 ASSERT(InitialProcessIdMin <= m_process_id);
324 ASSERT(m_process_id <= InitialProcessIdMax);
286 325
287 m_thread_list.remove(thread); 326 // Initialize the rest of the process.
288} 327 R_TRY(this->Initialize(params, res_limit, true));
289 328
290u64 KProcess::GetFreeThreadCount() const { 329 // We succeeded!
291 if (m_resource_limit != nullptr) { 330 R_SUCCEED();
292 const auto current_value =
293 m_resource_limit->GetCurrentValue(LimitableResource::ThreadCountMax);
294 const auto limit_value = m_resource_limit->GetLimitValue(LimitableResource::ThreadCountMax);
295 return limit_value - current_value;
296 } else {
297 return 0;
298 }
299} 331}
300 332
301Result KProcess::Reset() { 333Result KProcess::Initialize(const Svc::CreateProcessParameter& params,
302 // Lock the process and the scheduler. 334 std::span<const u32> user_caps, KResourceLimit* res_limit,
303 KScopedLightLock lk(m_state_lock); 335 KMemoryManager::Pool pool) {
304 KScopedSchedulerLock sl{m_kernel}; 336 ASSERT(res_limit != nullptr);
305 337
306 // Validate that we're in a state that we can reset. 338 // Set members.
307 R_UNLESS(m_state != State::Terminated, ResultInvalidState); 339 m_memory_pool = pool;
308 R_UNLESS(m_is_signaled, ResultInvalidState); 340 m_is_default_application_system_resource = false;
341 m_is_immortal = false;
309 342
310 // Clear signaled. 343 // Get the memory sizes.
311 m_is_signaled = false; 344 const size_t code_num_pages = params.code_num_pages;
312 R_SUCCEED(); 345 const size_t system_resource_num_pages = params.system_resource_num_pages;
313} 346 const size_t code_size = code_num_pages * PageSize;
347 const size_t system_resource_size = system_resource_num_pages * PageSize;
314 348
315Result KProcess::SetActivity(ProcessActivity activity) { 349 // Reserve memory for our code resource.
316 // Lock ourselves and the scheduler. 350 KScopedResourceReservation memory_reservation(
317 KScopedLightLock lk{m_state_lock}; 351 res_limit, Svc::LimitableResource::PhysicalMemoryMax, code_size);
318 KScopedLightLock list_lk{m_list_lock}; 352 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
319 KScopedSchedulerLock sl{m_kernel};
320 353
321 // Validate our state. 354 // Setup our system resource.
322 R_UNLESS(m_state != State::Terminating, ResultInvalidState); 355 if (system_resource_num_pages != 0) {
323 R_UNLESS(m_state != State::Terminated, ResultInvalidState); 356 // Create a secure system resource.
357 KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel);
358 R_UNLESS(secure_resource != nullptr, ResultOutOfResource);
324 359
325 // Either pause or resume. 360 ON_RESULT_FAILURE {
326 if (activity == ProcessActivity::Paused) { 361 secure_resource->Close();
327 // Verify that we're not suspended. 362 };
328 R_UNLESS(!m_is_suspended, ResultInvalidState);
329 363
330 // Suspend all threads. 364 // Initialize the secure resource.
331 for (auto* thread : this->GetThreadList()) { 365 R_TRY(secure_resource->Initialize(system_resource_size, res_limit, m_memory_pool));
332 thread->RequestSuspend(SuspendType::Process); 366
333 } 367 // Set our system resource.
368 m_system_resource = secure_resource;
334 369
335 // Set ourselves as suspended.
336 this->SetSuspended(true);
337 } else { 370 } else {
338 ASSERT(activity == ProcessActivity::Runnable); 371 // Use the system-wide system resource.
372 const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication);
373 m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource()
374 : m_kernel.GetSystemSystemResource());
339 375
340 // Verify that we're suspended. 376 m_is_default_application_system_resource = is_app;
341 R_UNLESS(m_is_suspended, ResultInvalidState);
342 377
343 // Resume all threads. 378 // Open reference to the system resource.
344 for (auto* thread : this->GetThreadList()) { 379 m_system_resource->Open();
345 thread->Resume(SuspendType::Process); 380 }
346 }
347 381
348 // Set ourselves as resumed. 382 // Ensure we clean up our secure resource, if we fail.
349 this->SetSuspended(false); 383 ON_RESULT_FAILURE {
384 m_system_resource->Close();
385 m_system_resource = nullptr;
386 };
387
388 // Setup page table.
389 {
390 const auto as_type = params.flags & Svc::CreateProcessFlag::AddressSpaceMask;
391 const bool enable_aslr = True(params.flags & Svc::CreateProcessFlag::EnableAslr);
392 const bool enable_das_merge =
393 False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
394 R_TRY(m_page_table.InitializeForProcess(as_type, enable_aslr, enable_das_merge,
395 !enable_aslr, pool, params.code_address, code_size,
396 m_system_resource, res_limit, this->GetMemory()));
397 }
398 ON_RESULT_FAILURE_2 {
399 m_page_table.Finalize();
400 };
401
402 // Ensure we can insert the code region.
403 R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code),
404 ResultInvalidMemoryRegion);
405
406 // Map the code region.
407 R_TRY(m_page_table.MapPages(params.code_address, code_num_pages, KMemoryState::Code,
408 KMemoryPermission::KernelRead | KMemoryPermission::NotMapped));
409
410 // Initialize capabilities.
411 R_TRY(m_capabilities.InitializeForUser(user_caps, std::addressof(m_page_table)));
412
413 // Initialize the process id.
414 m_process_id = m_kernel.CreateNewUserProcessID();
415 ASSERT(ProcessIdMin <= m_process_id);
416 ASSERT(m_process_id <= ProcessIdMax);
417
418 // If we should optimize memory allocations, do so.
419 if (m_system_resource->IsSecureResource() &&
420 True(params.flags & Svc::CreateProcessFlag::OptimizeMemoryAllocation)) {
421 R_TRY(m_kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool));
350 } 422 }
351 423
424 // Initialize the rest of the process.
425 R_TRY(this->Initialize(params, res_limit, true));
426
427 // We succeeded, so commit our memory reservation.
428 memory_reservation.Commit();
352 R_SUCCEED(); 429 R_SUCCEED();
353} 430}
354 431
355Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, 432void KProcess::DoWorkerTaskImpl() {
356 bool is_hbl) { 433 // Terminate child threads.
357 m_program_id = metadata.GetTitleID(); 434 TerminateChildren(m_kernel, this, nullptr);
358 m_ideal_core = metadata.GetMainThreadCore();
359 m_is_64bit_process = metadata.Is64BitProgram();
360 m_system_resource_size = metadata.GetSystemResourceSize();
361 m_image_size = code_size;
362 m_is_hbl = is_hbl;
363 435
364 if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is39Bit) { 436 // Finalize the handle table, if we're not immortal.
365 // For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large. 437 if (!m_is_immortal && m_is_handle_table_initialized) {
366 // However, some (buggy) programs/libraries like skyline incorrectly depend on the 438 this->FinalizeHandleTable();
367 // existence of ASLR pages before the entry point, so we will adjust the load address
368 // to point to about 2GiB into the ASLR region.
369 m_code_address = 0x8000'0000;
370 } else {
371 // All other processes can be mapped at the beginning of the code region.
372 if (metadata.GetAddressSpaceType() == FileSys::ProgramAddressSpaceType::Is36Bit) {
373 m_code_address = 0x800'0000;
374 } else {
375 m_code_address = 0x20'0000;
376 }
377 } 439 }
378 440
379 KScopedResourceReservation memory_reservation( 441 // Finish termination.
380 m_resource_limit, LimitableResource::PhysicalMemoryMax, code_size + m_system_resource_size); 442 this->FinishTermination();
381 if (!memory_reservation.Succeeded()) { 443}
382 LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes",
383 code_size + m_system_resource_size);
384 R_RETURN(ResultLimitReached);
385 }
386 // Initialize process address space
387 if (const Result result{m_page_table.InitializeForProcess(
388 metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
389 this->GetEntryPoint(), code_size, std::addressof(m_kernel.GetAppSystemResource()),
390 m_resource_limit, m_kernel.System().ApplicationMemory())};
391 result.IsError()) {
392 R_RETURN(result);
393 }
394
395 // Map process code region
396 if (const Result result{m_page_table.MapProcessCode(this->GetEntryPoint(), code_size / PageSize,
397 KMemoryState::Code,
398 KMemoryPermission::None)};
399 result.IsError()) {
400 R_RETURN(result);
401 }
402
403 // Initialize process capabilities
404 const auto& caps{metadata.GetKernelCapabilities()};
405 if (const Result result{
406 m_capabilities.InitializeForUserProcess(caps.data(), caps.size(), m_page_table)};
407 result.IsError()) {
408 R_RETURN(result);
409 }
410
411 // Set memory usage capacity
412 switch (metadata.GetAddressSpaceType()) {
413 case FileSys::ProgramAddressSpaceType::Is32Bit:
414 case FileSys::ProgramAddressSpaceType::Is36Bit:
415 case FileSys::ProgramAddressSpaceType::Is39Bit:
416 m_memory_usage_capacity =
417 m_page_table.GetHeapRegionEnd() - m_page_table.GetHeapRegionStart();
418 break;
419 444
420 case FileSys::ProgramAddressSpaceType::Is32BitNoMap: 445Result KProcess::StartTermination() {
421 m_memory_usage_capacity = 446 // Finalize the handle table when we're done, if the process isn't immortal.
422 (m_page_table.GetHeapRegionEnd() - m_page_table.GetHeapRegionStart()) + 447 SCOPE_EXIT({
423 (m_page_table.GetAliasRegionEnd() - m_page_table.GetAliasRegionStart()); 448 if (!m_is_immortal) {
424 break; 449 this->FinalizeHandleTable();
450 }
451 });
425 452
426 default: 453 // Terminate child threads other than the current one.
427 ASSERT(false); 454 R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel)));
428 break; 455}
429 }
430 456
431 // Create TLS region 457void KProcess::FinishTermination() {
432 R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address))); 458 // Only allow termination to occur if the process isn't immortal.
433 memory_reservation.Commit(); 459 if (!m_is_immortal) {
460 // Release resource limit hint.
461 if (m_resource_limit != nullptr) {
462 m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize();
463 m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, 0,
464 m_memory_release_hint);
465 }
466
467 // Change state.
468 {
469 KScopedSchedulerLock sl(m_kernel);
470 this->ChangeState(State::Terminated);
471 }
434 472
435 R_RETURN(m_handle_table.Initialize(m_capabilities.GetHandleTableSize())); 473 // Close.
474 this->Close();
475 }
436} 476}
437 477
438void KProcess::Run(s32 main_thread_priority, u64 stack_size) { 478void KProcess::Exit() {
439 ASSERT(this->AllocateMainThreadStack(stack_size) == ResultSuccess); 479 // Determine whether we need to start terminating
440 m_resource_limit->Reserve(LimitableResource::ThreadCountMax, 1); 480 bool needs_terminate = false;
481 {
482 KScopedLightLock lk(m_state_lock);
483 KScopedSchedulerLock sl(m_kernel);
484
485 ASSERT(m_state != State::Created);
486 ASSERT(m_state != State::CreatedAttached);
487 ASSERT(m_state != State::Crashed);
488 ASSERT(m_state != State::Terminated);
489 if (m_state == State::Running || m_state == State::RunningAttached ||
490 m_state == State::DebugBreak) {
491 this->ChangeState(State::Terminating);
492 needs_terminate = true;
493 }
494 }
441 495
442 const std::size_t heap_capacity{m_memory_usage_capacity - 496 // If we need to start termination, do so.
443 (m_main_thread_stack_size + m_image_size)}; 497 if (needs_terminate) {
444 ASSERT(!m_page_table.SetMaxHeapSize(heap_capacity).IsError()); 498 this->StartTermination();
445 499
446 this->ChangeState(State::Running); 500 // Register the process as a work task.
501 m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this);
502 }
447 503
448 SetupMainThread(m_kernel.System(), *this, main_thread_priority, m_main_thread_stack_top); 504 // Exit the current thread.
505 GetCurrentThread(m_kernel).Exit();
449} 506}
450 507
451void KProcess::PrepareForTermination() { 508Result KProcess::Terminate() {
452 this->ChangeState(State::Terminating); 509 // Determine whether we need to start terminating.
510 bool needs_terminate = false;
511 {
512 KScopedLightLock lk(m_state_lock);
453 513
454 const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) { 514 // Check whether we're allowed to terminate.
455 for (auto* thread : in_thread_list) { 515 R_UNLESS(m_state != State::Created, ResultInvalidState);
456 if (thread->GetOwnerProcess() != this) 516 R_UNLESS(m_state != State::CreatedAttached, ResultInvalidState);
457 continue;
458 517
459 if (thread == GetCurrentThreadPointer(m_kernel)) 518 KScopedSchedulerLock sl(m_kernel);
460 continue;
461 519
462 // TODO(Subv): When are the other running/ready threads terminated? 520 if (m_state == State::Running || m_state == State::RunningAttached ||
463 ASSERT_MSG(thread->GetState() == ThreadState::Waiting, 521 m_state == State::Crashed || m_state == State::DebugBreak) {
464 "Exiting processes with non-waiting threads is currently unimplemented"); 522 this->ChangeState(State::Terminating);
523 needs_terminate = true;
524 }
525 }
465 526
466 thread->Exit(); 527 // If we need to terminate, do so.
528 if (needs_terminate) {
529 // Start termination.
530 if (R_SUCCEEDED(this->StartTermination())) {
531 // Finish termination.
532 this->FinishTermination();
533 } else {
534 // Register the process as a work task.
535 m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit,
536 this);
467 } 537 }
468 }; 538 }
469 539
470 stop_threads(m_kernel.System().GlobalSchedulerContext().GetThreadList()); 540 R_SUCCEED();
541}
471 542
472 this->DeleteThreadLocalRegion(m_plr_address); 543Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) {
473 m_plr_address = 0; 544 // Lock ourselves, to prevent concurrent access.
545 KScopedLightLock lk(m_state_lock);
474 546
475 if (m_resource_limit) { 547 // Try to find an existing info for the memory.
476 m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, 548 KSharedMemoryInfo* info = nullptr;
477 m_main_thread_stack_size + m_image_size); 549 for (auto it = m_shared_memory_list.begin(); it != m_shared_memory_list.end(); ++it) {
550 if (it->GetSharedMemory() == shmem) {
551 info = std::addressof(*it);
552 break;
553 }
478 } 554 }
479 555
480 this->ChangeState(State::Terminated); 556 // If we didn't find an info, create one.
481} 557 if (info == nullptr) {
558 // Allocate a new info.
559 info = KSharedMemoryInfo::Allocate(m_kernel);
560 R_UNLESS(info != nullptr, ResultOutOfResource);
482 561
483void KProcess::Finalize() { 562 // Initialize the info and add it to our list.
484 // Free all shared memory infos. 563 info->Initialize(shmem);
485 { 564 m_shared_memory_list.push_back(*info);
486 auto it = m_shared_memory_list.begin(); 565 }
487 while (it != m_shared_memory_list.end()) {
488 KSharedMemoryInfo* info = *it;
489 KSharedMemory* shmem = info->GetSharedMemory();
490 566
491 while (!info->Close()) { 567 // Open a reference to the shared memory and its info.
492 shmem->Close(); 568 shmem->Open();
493 } 569 info->Open();
494 570
495 shmem->Close(); 571 R_SUCCEED();
572}
496 573
497 it = m_shared_memory_list.erase(it); 574void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) {
498 KSharedMemoryInfo::Free(m_kernel, info); 575 // Lock ourselves, to prevent concurrent access.
576 KScopedLightLock lk(m_state_lock);
577
578 // Find an existing info for the memory.
579 KSharedMemoryInfo* info = nullptr;
580 auto it = m_shared_memory_list.begin();
581 for (; it != m_shared_memory_list.end(); ++it) {
582 if (it->GetSharedMemory() == shmem) {
583 info = std::addressof(*it);
584 break;
499 } 585 }
500 } 586 }
587 ASSERT(info != nullptr);
501 588
502 // Release memory to the resource limit. 589 // Close a reference to the info and its memory.
503 if (m_resource_limit != nullptr) { 590 if (info->Close()) {
504 m_resource_limit->Close(); 591 m_shared_memory_list.erase(it);
505 m_resource_limit = nullptr; 592 KSharedMemoryInfo::Free(m_kernel, info);
506 } 593 }
507 594
508 // Finalize the page table. 595 shmem->Close();
509 m_page_table.Finalize();
510
511 // Perform inherited finalization.
512 KSynchronizationObject::Finalize();
513} 596}
514 597
515Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { 598Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) {
@@ -518,7 +601,7 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) {
518 601
519 // See if we can get a region from a partially used TLP. 602 // See if we can get a region from a partially used TLP.
520 { 603 {
521 KScopedSchedulerLock sl{m_kernel}; 604 KScopedSchedulerLock sl(m_kernel);
522 605
523 if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) { 606 if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) {
524 tlr = it->Reserve(); 607 tlr = it->Reserve();
@@ -538,7 +621,9 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) {
538 // Allocate a new page. 621 // Allocate a new page.
539 tlp = KThreadLocalPage::Allocate(m_kernel); 622 tlp = KThreadLocalPage::Allocate(m_kernel);
540 R_UNLESS(tlp != nullptr, ResultOutOfMemory); 623 R_UNLESS(tlp != nullptr, ResultOutOfMemory);
541 auto tlp_guard = SCOPE_GUARD({ KThreadLocalPage::Free(m_kernel, tlp); }); 624 ON_RESULT_FAILURE {
625 KThreadLocalPage::Free(m_kernel, tlp);
626 };
542 627
543 // Initialize the new page. 628 // Initialize the new page.
544 R_TRY(tlp->Initialize(m_kernel, this)); 629 R_TRY(tlp->Initialize(m_kernel, this));
@@ -549,7 +634,7 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) {
549 634
550 // Insert into our tree. 635 // Insert into our tree.
551 { 636 {
552 KScopedSchedulerLock sl{m_kernel}; 637 KScopedSchedulerLock sl(m_kernel);
553 if (tlp->IsAllUsed()) { 638 if (tlp->IsAllUsed()) {
554 m_fully_used_tlp_tree.insert(*tlp); 639 m_fully_used_tlp_tree.insert(*tlp);
555 } else { 640 } else {
@@ -558,7 +643,6 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) {
558 } 643 }
559 644
560 // We succeeded! 645 // We succeeded!
561 tlp_guard.Cancel();
562 *out = tlr; 646 *out = tlr;
563 R_SUCCEED(); 647 R_SUCCEED();
564} 648}
@@ -568,7 +652,7 @@ Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
568 652
569 // Release the region. 653 // Release the region.
570 { 654 {
571 KScopedSchedulerLock sl{m_kernel}; 655 KScopedSchedulerLock sl(m_kernel);
572 656
573 // Try to find the page in the partially used list. 657 // Try to find the page in the partially used list.
574 auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize)); 658 auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize));
@@ -611,95 +695,213 @@ Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) {
611 R_SUCCEED(); 695 R_SUCCEED();
612} 696}
613 697
614bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { 698bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value) {
615 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { 699 if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
616 return wp.type == DebugWatchpointType::None; 700 return rl->Reserve(which, value);
617 })}; 701 } else {
702 return true;
703 }
704}
618 705
619 if (watch == m_watchpoints.end()) { 706bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout) {
620 return false; 707 if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
708 return rl->Reserve(which, value, timeout);
709 } else {
710 return true;
621 } 711 }
712}
622 713
623 watch->start_address = addr; 714void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value) {
624 watch->end_address = addr + size; 715 if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
625 watch->type = type; 716 rl->Release(which, value);
717 }
718}
626 719
627 for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size; 720void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint) {
628 page += PageSize) { 721 if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) {
629 m_debug_page_refcounts[page]++; 722 rl->Release(which, value, hint);
630 this->GetMemory().MarkRegionDebug(page, PageSize, true);
631 } 723 }
724}
632 725
633 return true; 726void KProcess::IncrementRunningThreadCount() {
727 ASSERT(m_num_running_threads.load() >= 0);
728
729 ++m_num_running_threads;
634} 730}
635 731
636bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { 732void KProcess::DecrementRunningThreadCount() {
637 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { 733 ASSERT(m_num_running_threads.load() > 0);
638 return wp.start_address == addr && wp.end_address == addr + size && wp.type == type;
639 })};
640 734
641 if (watch == m_watchpoints.end()) { 735 if (const auto prev = m_num_running_threads--; prev == 1) {
736 this->Terminate();
737 }
738}
739
740bool KProcess::EnterUserException() {
741 // Get the current thread.
742 KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
743 ASSERT(this == cur_thread->GetOwnerProcess());
744
745 // Check that we haven't already claimed the exception thread.
746 if (m_exception_thread == cur_thread) {
642 return false; 747 return false;
643 } 748 }
644 749
645 watch->start_address = 0; 750 // Create the wait queue we'll be using.
646 watch->end_address = 0; 751 ThreadQueueImplForKProcessEnterUserException wait_queue(m_kernel,
647 watch->type = DebugWatchpointType::None; 752 std::addressof(m_exception_thread));
648 753
649 for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size; 754 // Claim the exception thread.
650 page += PageSize) { 755 {
651 m_debug_page_refcounts[page]--; 756 // Lock the scheduler.
652 if (!m_debug_page_refcounts[page]) { 757 KScopedSchedulerLock sl(m_kernel);
653 this->GetMemory().MarkRegionDebug(page, PageSize, false); 758
759 // Check that we're not terminating.
760 if (cur_thread->IsTerminationRequested()) {
761 return false;
762 }
763
764 // If we don't have an exception thread, we can just claim it directly.
765 if (m_exception_thread == nullptr) {
766 m_exception_thread = cur_thread;
767 KScheduler::SetSchedulerUpdateNeeded(m_kernel);
768 return true;
654 } 769 }
770
771 // Otherwise, we need to wait until we don't have an exception thread.
772
773 // Add the current thread as a waiter on the current exception thread.
774 cur_thread->SetKernelAddressKey(
775 reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1);
776 m_exception_thread->AddWaiter(cur_thread);
777
778 // Wait to claim the exception thread.
779 cur_thread->BeginWait(std::addressof(wait_queue));
655 } 780 }
656 781
657 return true; 782 // If our wait didn't end due to thread termination, we succeeded.
783 return ResultTerminationRequested != cur_thread->GetWaitResult();
658} 784}
659 785
660void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { 786bool KProcess::LeaveUserException() {
661 const auto ReprotectSegment = [&](const CodeSet::Segment& segment, 787 return this->ReleaseUserException(GetCurrentThreadPointer(m_kernel));
662 Svc::MemoryPermission permission) { 788}
663 m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
664 };
665 789
666 this->GetMemory().WriteBlock(base_addr, code_set.memory.data(), code_set.memory.size()); 790bool KProcess::ReleaseUserException(KThread* thread) {
791 KScopedSchedulerLock sl(m_kernel);
667 792
668 ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute); 793 if (m_exception_thread == thread) {
669 ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read); 794 m_exception_thread = nullptr;
670 ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite); 795
796 // Remove waiter thread.
797 bool has_waiters;
798 if (KThread* next = thread->RemoveKernelWaiterByKey(
799 std::addressof(has_waiters),
800 reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1);
801 next != nullptr) {
802 next->EndWait(ResultSuccess);
803 }
804
805 KScheduler::SetSchedulerUpdateNeeded(m_kernel);
806
807 return true;
808 } else {
809 return false;
810 }
671} 811}
672 812
673bool KProcess::IsSignaled() const { 813void KProcess::RegisterThread(KThread* thread) {
674 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); 814 KScopedLightLock lk(m_list_lock);
675 return m_is_signaled; 815
816 m_thread_list.push_back(*thread);
676} 817}
677 818
678KProcess::KProcess(KernelCore& kernel) 819void KProcess::UnregisterThread(KThread* thread) {
679 : KAutoObjectWithSlabHeapAndContainer{kernel}, m_page_table{m_kernel.System()}, 820 KScopedLightLock lk(m_list_lock);
680 m_handle_table{m_kernel}, m_address_arbiter{m_kernel.System()},
681 m_condition_var{m_kernel.System()}, m_state_lock{m_kernel}, m_list_lock{m_kernel} {}
682 821
683KProcess::~KProcess() = default; 822 m_thread_list.erase(m_thread_list.iterator_to(*thread));
823}
824
825size_t KProcess::GetUsedUserPhysicalMemorySize() const {
826 const size_t norm_size = m_page_table.GetNormalMemorySize();
827 const size_t other_size = m_code_size + m_main_thread_stack_size;
828 const size_t sec_size = this->GetRequiredSecureMemorySizeNonDefault();
684 829
685void KProcess::ChangeState(State new_state) { 830 return norm_size + other_size + sec_size;
686 if (m_state == new_state) { 831}
687 return; 832
833size_t KProcess::GetTotalUserPhysicalMemorySize() const {
834 // Get the amount of free and used size.
835 const size_t free_size =
836 m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax);
837 const size_t max_size = m_max_process_memory;
838
839 // Determine used size.
840 // NOTE: This does *not* check this->IsDefaultApplicationSystemResource(), unlike
841 // GetUsedUserPhysicalMemorySize().
842 const size_t norm_size = m_page_table.GetNormalMemorySize();
843 const size_t other_size = m_code_size + m_main_thread_stack_size;
844 const size_t sec_size = this->GetRequiredSecureMemorySize();
845 const size_t used_size = norm_size + other_size + sec_size;
846
847 // NOTE: These function calls will recalculate, introducing a race...it is unclear why Nintendo
848 // does it this way.
849 if (used_size + free_size > max_size) {
850 return max_size;
851 } else {
852 return free_size + this->GetUsedUserPhysicalMemorySize();
688 } 853 }
854}
689 855
690 m_state = new_state; 856size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const {
691 m_is_signaled = true; 857 const size_t norm_size = m_page_table.GetNormalMemorySize();
692 this->NotifyAvailable(); 858 const size_t other_size = m_code_size + m_main_thread_stack_size;
859
860 return norm_size + other_size;
861}
862
863size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const {
864 // Get the amount of free and used size.
865 const size_t free_size =
866 m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax);
867 const size_t max_size = m_max_process_memory;
868
869 // Determine used size.
870 // NOTE: This does *not* check this->IsDefaultApplicationSystemResource(), unlike
871 // GetUsedUserPhysicalMemorySize().
872 const size_t norm_size = m_page_table.GetNormalMemorySize();
873 const size_t other_size = m_code_size + m_main_thread_stack_size;
874 const size_t sec_size = this->GetRequiredSecureMemorySize();
875 const size_t used_size = norm_size + other_size + sec_size;
876
877 // NOTE: These function calls will recalculate, introducing a race...it is unclear why Nintendo
878 // does it this way.
879 if (used_size + free_size > max_size) {
880 return max_size - this->GetRequiredSecureMemorySizeNonDefault();
881 } else {
882 return free_size + this->GetUsedNonSystemUserPhysicalMemorySize();
883 }
693} 884}
694 885
695Result KProcess::AllocateMainThreadStack(std::size_t stack_size) { 886Result KProcess::Run(s32 priority, size_t stack_size) {
887 // Lock ourselves, to prevent concurrent access.
888 KScopedLightLock lk(m_state_lock);
889
890 // Validate that we're in a state where we can initialize.
891 const auto state = m_state;
892 R_UNLESS(state == State::Created || state == State::CreatedAttached, ResultInvalidState);
893
894 // Place a tentative reservation of a thread for this process.
895 KScopedResourceReservation thread_reservation(this, Svc::LimitableResource::ThreadCountMax);
896 R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached);
897
696 // Ensure that we haven't already allocated stack. 898 // Ensure that we haven't already allocated stack.
697 ASSERT(m_main_thread_stack_size == 0); 899 ASSERT(m_main_thread_stack_size == 0);
698 900
699 // Ensure that we're allocating a valid stack. 901 // Ensure that we're allocating a valid stack.
700 stack_size = Common::AlignUp(stack_size, PageSize); 902 stack_size = Common::AlignUp(stack_size, PageSize);
701 // R_UNLESS(stack_size + image_size <= m_max_process_memory, ResultOutOfMemory); 903 R_UNLESS(stack_size + m_code_size <= m_max_process_memory, ResultOutOfMemory);
702 R_UNLESS(stack_size + m_image_size >= m_image_size, ResultOutOfMemory); 904 R_UNLESS(stack_size + m_code_size >= m_code_size, ResultOutOfMemory);
703 905
704 // Place a tentative reservation of memory for our new stack. 906 // Place a tentative reservation of memory for our new stack.
705 KScopedResourceReservation mem_reservation(this, Svc::LimitableResource::PhysicalMemoryMax, 907 KScopedResourceReservation mem_reservation(this, Svc::LimitableResource::PhysicalMemoryMax,
@@ -707,21 +909,359 @@ Result KProcess::AllocateMainThreadStack(std::size_t stack_size) {
707 R_UNLESS(mem_reservation.Succeeded(), ResultLimitReached); 909 R_UNLESS(mem_reservation.Succeeded(), ResultLimitReached);
708 910
709 // Allocate and map our stack. 911 // Allocate and map our stack.
912 KProcessAddress stack_top = 0;
710 if (stack_size) { 913 if (stack_size) {
711 KProcessAddress stack_bottom; 914 KProcessAddress stack_bottom;
712 R_TRY(m_page_table.MapPages(std::addressof(stack_bottom), stack_size / PageSize, 915 R_TRY(m_page_table.MapPages(std::addressof(stack_bottom), stack_size / PageSize,
713 KMemoryState::Stack, KMemoryPermission::UserReadWrite)); 916 KMemoryState::Stack, KMemoryPermission::UserReadWrite));
714 917
715 m_main_thread_stack_top = stack_bottom + stack_size; 918 stack_top = stack_bottom + stack_size;
716 m_main_thread_stack_size = stack_size; 919 m_main_thread_stack_size = stack_size;
717 } 920 }
718 921
922 // Ensure our stack is safe to clean up on exit.
923 ON_RESULT_FAILURE {
924 if (m_main_thread_stack_size) {
925 ASSERT(R_SUCCEEDED(m_page_table.UnmapPages(stack_top - m_main_thread_stack_size,
926 m_main_thread_stack_size / PageSize,
927 KMemoryState::Stack)));
928 m_main_thread_stack_size = 0;
929 }
930 };
931
932 // Set our maximum heap size.
933 R_TRY(m_page_table.SetMaxHeapSize(m_max_process_memory -
934 (m_main_thread_stack_size + m_code_size)));
935
936 // Initialize our handle table.
937 R_TRY(this->InitializeHandleTable(m_capabilities.GetHandleTableSize()));
938 ON_RESULT_FAILURE_2 {
939 this->FinalizeHandleTable();
940 };
941
942 // Create a new thread for the process.
943 KThread* main_thread = KThread::Create(m_kernel);
944 R_UNLESS(main_thread != nullptr, ResultOutOfResource);
945 SCOPE_EXIT({ main_thread->Close(); });
946
947 // Initialize the thread.
948 R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0,
949 stack_top, priority, m_ideal_core_id, this));
950
951 // Register the thread, and commit our reservation.
952 KThread::Register(m_kernel, main_thread);
953 thread_reservation.Commit();
954
955 // Add the thread to our handle table.
956 Handle thread_handle;
957 R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread));
958
959 // Set the thread arguments.
960 main_thread->GetContext32().cpu_registers[0] = 0;
961 main_thread->GetContext64().cpu_registers[0] = 0;
962 main_thread->GetContext32().cpu_registers[1] = thread_handle;
963 main_thread->GetContext64().cpu_registers[1] = thread_handle;
964
965 // Update our state.
966 this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached);
967 ON_RESULT_FAILURE_2 {
968 this->ChangeState(state);
969 };
970
971 // Suspend for debug, if we should.
972 if (m_kernel.System().DebuggerEnabled()) {
973 main_thread->RequestSuspend(SuspendType::Debug);
974 }
975
976 // Run our thread.
977 R_TRY(main_thread->Run());
978
979 // Open a reference to represent that we're running.
980 this->Open();
981
719 // We succeeded! Commit our memory reservation. 982 // We succeeded! Commit our memory reservation.
720 mem_reservation.Commit(); 983 mem_reservation.Commit();
721 984
722 R_SUCCEED(); 985 R_SUCCEED();
723} 986}
724 987
988Result KProcess::Reset() {
989 // Lock the process and the scheduler.
990 KScopedLightLock lk(m_state_lock);
991 KScopedSchedulerLock sl(m_kernel);
992
993 // Validate that we're in a state that we can reset.
994 R_UNLESS(m_state != State::Terminated, ResultInvalidState);
995 R_UNLESS(m_is_signaled, ResultInvalidState);
996
997 // Clear signaled.
998 m_is_signaled = false;
999 R_SUCCEED();
1000}
1001
1002Result KProcess::SetActivity(Svc::ProcessActivity activity) {
1003 // Lock ourselves and the scheduler.
1004 KScopedLightLock lk(m_state_lock);
1005 KScopedLightLock list_lk(m_list_lock);
1006 KScopedSchedulerLock sl(m_kernel);
1007
1008 // Validate our state.
1009 R_UNLESS(m_state != State::Terminating, ResultInvalidState);
1010 R_UNLESS(m_state != State::Terminated, ResultInvalidState);
1011
1012 // Either pause or resume.
1013 if (activity == Svc::ProcessActivity::Paused) {
1014 // Verify that we're not suspended.
1015 R_UNLESS(!m_is_suspended, ResultInvalidState);
1016
1017 // Suspend all threads.
1018 auto end = this->GetThreadList().end();
1019 for (auto it = this->GetThreadList().begin(); it != end; ++it) {
1020 it->RequestSuspend(SuspendType::Process);
1021 }
1022
1023 // Set ourselves as suspended.
1024 this->SetSuspended(true);
1025 } else {
1026 ASSERT(activity == Svc::ProcessActivity::Runnable);
1027
1028 // Verify that we're suspended.
1029 R_UNLESS(m_is_suspended, ResultInvalidState);
1030
1031 // Resume all threads.
1032 auto end = this->GetThreadList().end();
1033 for (auto it = this->GetThreadList().begin(); it != end; ++it) {
1034 it->Resume(SuspendType::Process);
1035 }
1036
1037 // Set ourselves as resumed.
1038 this->SetSuspended(false);
1039 }
1040
1041 R_SUCCEED();
1042}
1043
1044void KProcess::PinCurrentThread() {
1045 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
1046
1047 // Get the current thread.
1048 const s32 core_id = GetCurrentCoreId(m_kernel);
1049 KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
1050
1051 // If the thread isn't terminated, pin it.
1052 if (!cur_thread->IsTerminationRequested()) {
1053 // Pin it.
1054 this->PinThread(core_id, cur_thread);
1055 cur_thread->Pin(core_id);
1056
1057 // An update is needed.
1058 KScheduler::SetSchedulerUpdateNeeded(m_kernel);
1059 }
1060}
1061
1062void KProcess::UnpinCurrentThread() {
1063 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
1064
1065 // Get the current thread.
1066 const s32 core_id = GetCurrentCoreId(m_kernel);
1067 KThread* cur_thread = GetCurrentThreadPointer(m_kernel);
1068
1069 // Unpin it.
1070 cur_thread->Unpin();
1071 this->UnpinThread(core_id, cur_thread);
1072
1073 // An update is needed.
1074 KScheduler::SetSchedulerUpdateNeeded(m_kernel);
1075}
1076
1077void KProcess::UnpinThread(KThread* thread) {
1078 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
1079
1080 // Get the thread's core id.
1081 const auto core_id = thread->GetActiveCore();
1082
1083 // Unpin it.
1084 this->UnpinThread(core_id, thread);
1085 thread->Unpin();
1086
1087 // An update is needed.
1088 KScheduler::SetSchedulerUpdateNeeded(m_kernel);
1089}
1090
1091Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids,
1092 s32 max_out_count) {
1093 // TODO: use current memory reference
1094 auto& memory = m_kernel.System().ApplicationMemory();
1095
1096 // Lock the list.
1097 KScopedLightLock lk(m_list_lock);
1098
1099 // Iterate over the list.
1100 s32 count = 0;
1101 auto end = this->GetThreadList().end();
1102 for (auto it = this->GetThreadList().begin(); it != end; ++it) {
1103 // If we're within array bounds, write the id.
1104 if (count < max_out_count) {
1105 // Get the thread id.
1106 KThread* thread = std::addressof(*it);
1107 const u64 id = thread->GetId();
1108
1109 // Copy the id to userland.
1110 memory.Write64(out_thread_ids + count * sizeof(u64), id);
1111 }
1112
1113 // Increment the count.
1114 ++count;
1115 }
1116
1117 // We successfully iterated the list.
1118 *out_num_threads = count;
1119 R_SUCCEED();
1120}
1121
1122void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {}
1123
1124KProcess::KProcess(KernelCore& kernel)
1125 : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel.System()},
1126 m_state_lock{kernel}, m_list_lock{kernel}, m_cond_var{kernel.System()},
1127 m_address_arbiter{kernel.System()}, m_handle_table{kernel} {}
1128KProcess::~KProcess() = default;
1129
1130Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
1131 bool is_hbl) {
1132 // Create a resource limit for the process.
1133 const auto physical_memory_size =
1134 m_kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application);
1135 auto* res_limit =
1136 Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size);
1137
1138 // Ensure we maintain a clean state on exit.
1139 SCOPE_EXIT({ res_limit->Close(); });
1140
1141 // Declare flags and code address.
1142 Svc::CreateProcessFlag flag{};
1143 u64 code_address{};
1144
1145 // We are an application.
1146 flag |= Svc::CreateProcessFlag::IsApplication;
1147
1148 // If we are 64-bit, create as such.
1149 if (metadata.Is64BitProgram()) {
1150 flag |= Svc::CreateProcessFlag::Is64Bit;
1151 }
1152
1153 // Set the address space type and code address.
1154 switch (metadata.GetAddressSpaceType()) {
1155 case FileSys::ProgramAddressSpaceType::Is39Bit:
1156 flag |= Svc::CreateProcessFlag::AddressSpace64Bit;
1157
1158 // For 39-bit processes, the ASLR region starts at 0x800'0000 and is ~512GiB large.
1159 // However, some (buggy) programs/libraries like skyline incorrectly depend on the
1160 // existence of ASLR pages before the entry point, so we will adjust the load address
1161 // to point to about 2GiB into the ASLR region.
1162 code_address = 0x8000'0000;
1163 break;
1164 case FileSys::ProgramAddressSpaceType::Is36Bit:
1165 flag |= Svc::CreateProcessFlag::AddressSpace64BitDeprecated;
1166 code_address = 0x800'0000;
1167 break;
1168 case FileSys::ProgramAddressSpaceType::Is32Bit:
1169 flag |= Svc::CreateProcessFlag::AddressSpace32Bit;
1170 code_address = 0x20'0000;
1171 break;
1172 case FileSys::ProgramAddressSpaceType::Is32BitNoMap:
1173 flag |= Svc::CreateProcessFlag::AddressSpace32BitWithoutAlias;
1174 code_address = 0x20'0000;
1175 break;
1176 }
1177
1178 Svc::CreateProcessParameter params{
1179 .name = {},
1180 .version = {},
1181 .program_id = metadata.GetTitleID(),
1182 .code_address = code_address,
1183 .code_num_pages = static_cast<s32>(code_size / PageSize),
1184 .flags = flag,
1185 .reslimit = Svc::InvalidHandle,
1186 .system_resource_num_pages = static_cast<s32>(metadata.GetSystemResourceSize() / PageSize),
1187 };
1188
1189 // Set the process name.
1190 const auto& name = metadata.GetName();
1191 static_assert(sizeof(params.name) <= sizeof(name));
1192 std::memcpy(params.name.data(), name.data(), sizeof(params.name));
1193
1194 // Initialize for application process.
1195 R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit,
1196 KMemoryManager::Pool::Application));
1197
1198 // Assign remaining properties.
1199 m_is_hbl = is_hbl;
1200 m_ideal_core_id = metadata.GetMainThreadCore();
1201
1202 // We succeeded.
1203 R_SUCCEED();
1204}
1205
1206void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
1207 const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
1208 Svc::MemoryPermission permission) {
1209 m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
1210 };
1211
1212 this->GetMemory().WriteBlock(base_addr, code_set.memory.data(), code_set.memory.size());
1213
1214 ReprotectSegment(code_set.CodeSegment(), Svc::MemoryPermission::ReadExecute);
1215 ReprotectSegment(code_set.RODataSegment(), Svc::MemoryPermission::Read);
1216 ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite);
1217}
1218
1219bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) {
1220 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
1221 return wp.type == DebugWatchpointType::None;
1222 })};
1223
1224 if (watch == m_watchpoints.end()) {
1225 return false;
1226 }
1227
1228 watch->start_address = addr;
1229 watch->end_address = addr + size;
1230 watch->type = type;
1231
1232 for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
1233 page += PageSize) {
1234 m_debug_page_refcounts[page]++;
1235 this->GetMemory().MarkRegionDebug(page, PageSize, true);
1236 }
1237
1238 return true;
1239}
1240
1241bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) {
1242 const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) {
1243 return wp.start_address == addr && wp.end_address == addr + size && wp.type == type;
1244 })};
1245
1246 if (watch == m_watchpoints.end()) {
1247 return false;
1248 }
1249
1250 watch->start_address = 0;
1251 watch->end_address = 0;
1252 watch->type = DebugWatchpointType::None;
1253
1254 for (KProcessAddress page = Common::AlignDown(GetInteger(addr), PageSize); page < addr + size;
1255 page += PageSize) {
1256 m_debug_page_refcounts[page]--;
1257 if (!m_debug_page_refcounts[page]) {
1258 this->GetMemory().MarkRegionDebug(page, PageSize, false);
1259 }
1260 }
1261
1262 return true;
1263}
1264
725Core::Memory::Memory& KProcess::GetMemory() const { 1265Core::Memory::Memory& KProcess::GetMemory() const {
726 // TODO: per-process memory 1266 // TODO: per-process memory
727 return m_kernel.System().ApplicationMemory(); 1267 return m_kernel.System().ApplicationMemory();
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 146e07a57..f9f755afa 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -1,59 +1,23 @@
1// SPDX-FileCopyrightText: 2015 Citra Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
5 5
6#include <array>
7#include <cstddef>
8#include <list>
9#include <map> 6#include <map>
10#include <string> 7
8#include "core/hle/kernel/code_set.h"
11#include "core/hle/kernel/k_address_arbiter.h" 9#include "core/hle/kernel/k_address_arbiter.h"
12#include "core/hle/kernel/k_auto_object.h" 10#include "core/hle/kernel/k_capabilities.h"
13#include "core/hle/kernel/k_condition_variable.h" 11#include "core/hle/kernel/k_condition_variable.h"
14#include "core/hle/kernel/k_handle_table.h" 12#include "core/hle/kernel/k_handle_table.h"
15#include "core/hle/kernel/k_page_table.h" 13#include "core/hle/kernel/k_page_table.h"
16#include "core/hle/kernel/k_synchronization_object.h" 14#include "core/hle/kernel/k_page_table_manager.h"
15#include "core/hle/kernel/k_system_resource.h"
16#include "core/hle/kernel/k_thread.h"
17#include "core/hle/kernel/k_thread_local_page.h" 17#include "core/hle/kernel/k_thread_local_page.h"
18#include "core/hle/kernel/k_typed_address.h"
19#include "core/hle/kernel/k_worker_task.h"
20#include "core/hle/kernel/process_capability.h"
21#include "core/hle/kernel/slab_helpers.h"
22#include "core/hle/result.h"
23
24namespace Core {
25namespace Memory {
26class Memory;
27};
28
29class System;
30} // namespace Core
31
32namespace FileSys {
33class ProgramMetadata;
34}
35 18
36namespace Kernel { 19namespace Kernel {
37 20
38class KernelCore;
39class KResourceLimit;
40class KThread;
41class KSharedMemoryInfo;
42class TLSPage;
43
44struct CodeSet;
45
46enum class MemoryRegion : u16 {
47 APPLICATION = 1,
48 SYSTEM = 2,
49 BASE = 3,
50};
51
52enum class ProcessActivity : u32 {
53 Runnable,
54 Paused,
55};
56
57enum class DebugWatchpointType : u8 { 21enum class DebugWatchpointType : u8 {
58 None = 0, 22 None = 0,
59 Read = 1 << 0, 23 Read = 1 << 0,
@@ -72,9 +36,6 @@ class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWor
72 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); 36 KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
73 37
74public: 38public:
75 explicit KProcess(KernelCore& kernel);
76 ~KProcess() override;
77
78 enum class State { 39 enum class State {
79 Created = static_cast<u32>(Svc::ProcessState::Created), 40 Created = static_cast<u32>(Svc::ProcessState::Created),
80 CreatedAttached = static_cast<u32>(Svc::ProcessState::CreatedAttached), 41 CreatedAttached = static_cast<u32>(Svc::ProcessState::CreatedAttached),
@@ -86,470 +47,493 @@ public:
86 DebugBreak = static_cast<u32>(Svc::ProcessState::DebugBreak), 47 DebugBreak = static_cast<u32>(Svc::ProcessState::DebugBreak),
87 }; 48 };
88 49
89 enum : u64 { 50 using ThreadList = Common::IntrusiveListMemberTraits<&KThread::m_process_list_node>::ListType;
90 /// Lowest allowed process ID for a kernel initial process.
91 InitialKIPIDMin = 1,
92 /// Highest allowed process ID for a kernel initial process.
93 InitialKIPIDMax = 80,
94
95 /// Lowest allowed process ID for a userland process.
96 ProcessIDMin = 81,
97 /// Highest allowed process ID for a userland process.
98 ProcessIDMax = 0xFFFFFFFFFFFFFFFF,
99 };
100 51
101 // Used to determine how process IDs are assigned. 52 static constexpr size_t AslrAlignment = 2_MiB;
102 enum class ProcessType {
103 KernelInternal,
104 Userland,
105 };
106 53
107 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; 54public:
55 static constexpr u64 InitialProcessIdMin = 1;
56 static constexpr u64 InitialProcessIdMax = 0x50;
108 57
109 static Result Initialize(KProcess* process, Core::System& system, std::string process_name, 58 static constexpr u64 ProcessIdMin = InitialProcessIdMax + 1;
110 ProcessType type, KResourceLimit* res_limit); 59 static constexpr u64 ProcessIdMax = std::numeric_limits<u64>::max();
111 60
112 /// Gets a reference to the process' page table. 61private:
113 KPageTable& GetPageTable() { 62 using SharedMemoryInfoList = Common::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
114 return m_page_table; 63 using TLPTree =
115 } 64 Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
65 using TLPIterator = TLPTree::iterator;
116 66
117 /// Gets const a reference to the process' page table. 67private:
118 const KPageTable& GetPageTable() const { 68 KPageTable m_page_table;
119 return m_page_table; 69 std::atomic<size_t> m_used_kernel_memory_size{};
120 } 70 TLPTree m_fully_used_tlp_tree{};
71 TLPTree m_partially_used_tlp_tree{};
72 s32 m_ideal_core_id{};
73 KResourceLimit* m_resource_limit{};
74 KSystemResource* m_system_resource{};
75 size_t m_memory_release_hint{};
76 State m_state{};
77 KLightLock m_state_lock;
78 KLightLock m_list_lock;
79 KConditionVariable m_cond_var;
80 KAddressArbiter m_address_arbiter;
81 std::array<u64, 4> m_entropy{};
82 bool m_is_signaled{};
83 bool m_is_initialized{};
84 bool m_is_application{};
85 bool m_is_default_application_system_resource{};
86 bool m_is_hbl{};
87 std::array<char, 13> m_name{};
88 std::atomic<u16> m_num_running_threads{};
89 Svc::CreateProcessFlag m_flags{};
90 KMemoryManager::Pool m_memory_pool{};
91 s64 m_schedule_count{};
92 KCapabilities m_capabilities{};
93 u64 m_program_id{};
94 u64 m_process_id{};
95 KProcessAddress m_code_address{};
96 size_t m_code_size{};
97 size_t m_main_thread_stack_size{};
98 size_t m_max_process_memory{};
99 u32 m_version{};
100 KHandleTable m_handle_table;
101 KProcessAddress m_plr_address{};
102 KThread* m_exception_thread{};
103 ThreadList m_thread_list{};
104 SharedMemoryInfoList m_shared_memory_list{};
105 bool m_is_suspended{};
106 bool m_is_immortal{};
107 bool m_is_handle_table_initialized{};
108 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_running_threads{};
109 std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{};
110 std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_switch_counts{};
111 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_pinned_threads{};
112 std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> m_watchpoints{};
113 std::map<KProcessAddress, u64> m_debug_page_refcounts{};
114 std::atomic<s64> m_cpu_time{};
115 std::atomic<s64> m_num_process_switches{};
116 std::atomic<s64> m_num_thread_switches{};
117 std::atomic<s64> m_num_fpu_switches{};
118 std::atomic<s64> m_num_supervisor_calls{};
119 std::atomic<s64> m_num_ipc_messages{};
120 std::atomic<s64> m_num_ipc_replies{};
121 std::atomic<s64> m_num_ipc_receives{};
121 122
122 /// Gets a reference to the process' handle table. 123private:
123 KHandleTable& GetHandleTable() { 124 Result StartTermination();
124 return m_handle_table; 125 void FinishTermination();
125 }
126 126
127 /// Gets a const reference to the process' handle table. 127 void PinThread(s32 core_id, KThread* thread) {
128 const KHandleTable& GetHandleTable() const { 128 ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
129 return m_handle_table; 129 ASSERT(thread != nullptr);
130 ASSERT(m_pinned_threads[core_id] == nullptr);
131 m_pinned_threads[core_id] = thread;
130 } 132 }
131 133
132 /// Gets a reference to process's memory. 134 void UnpinThread(s32 core_id, KThread* thread) {
133 Core::Memory::Memory& GetMemory() const; 135 ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
134 136 ASSERT(thread != nullptr);
135 Result SignalToAddress(KProcessAddress address) { 137 ASSERT(m_pinned_threads[core_id] == thread);
136 return m_condition_var.SignalToAddress(address); 138 m_pinned_threads[core_id] = nullptr;
137 } 139 }
138 140
139 Result WaitForAddress(Handle handle, KProcessAddress address, u32 tag) { 141public:
140 return m_condition_var.WaitForAddress(handle, address, tag); 142 explicit KProcess(KernelCore& kernel);
141 } 143 ~KProcess() override;
142 144
143 void SignalConditionVariable(u64 cv_key, int32_t count) { 145 Result Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit,
144 return m_condition_var.Signal(cv_key, count); 146 bool is_real);
145 }
146 147
147 Result WaitConditionVariable(KProcessAddress address, u64 cv_key, u32 tag, s64 ns) { 148 Result Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg,
148 R_RETURN(m_condition_var.Wait(address, cv_key, tag, ns)); 149 std::span<const u32> caps, KResourceLimit* res_limit,
149 } 150 KMemoryManager::Pool pool, bool immortal);
151 Result Initialize(const Svc::CreateProcessParameter& params, std::span<const u32> user_caps,
152 KResourceLimit* res_limit, KMemoryManager::Pool pool);
153 void Exit();
150 154
151 Result SignalAddressArbiter(uint64_t address, Svc::SignalType signal_type, s32 value, 155 const char* GetName() const {
152 s32 count) { 156 return m_name.data();
153 R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count));
154 } 157 }
155 158
156 Result WaitAddressArbiter(uint64_t address, Svc::ArbitrationType arb_type, s32 value, 159 u64 GetProgramId() const {
157 s64 timeout) { 160 return m_program_id;
158 R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout));
159 } 161 }
160 162
161 KProcessAddress GetProcessLocalRegionAddress() const { 163 u64 GetProcessId() const {
162 return m_plr_address; 164 return m_process_id;
163 } 165 }
164 166
165 /// Gets the current status of the process
166 State GetState() const { 167 State GetState() const {
167 return m_state; 168 return m_state;
168 } 169 }
169 170
170 /// Gets the unique ID that identifies this particular process. 171 u64 GetCoreMask() const {
171 u64 GetProcessId() const { 172 return m_capabilities.GetCoreMask();
172 return m_process_id; 173 }
174 u64 GetPhysicalCoreMask() const {
175 return m_capabilities.GetPhysicalCoreMask();
176 }
177 u64 GetPriorityMask() const {
178 return m_capabilities.GetPriorityMask();
173 } 179 }
174 180
175 /// Gets the program ID corresponding to this process. 181 s32 GetIdealCoreId() const {
176 u64 GetProgramId() const { 182 return m_ideal_core_id;
177 return m_program_id; 183 }
184 void SetIdealCoreId(s32 core_id) {
185 m_ideal_core_id = core_id;
178 } 186 }
179 187
180 KProcessAddress GetEntryPoint() const { 188 bool CheckThreadPriority(s32 prio) const {
181 return m_code_address; 189 return ((1ULL << prio) & this->GetPriorityMask()) != 0;
182 } 190 }
183 191
184 /// Gets the resource limit descriptor for this process 192 u32 GetCreateProcessFlags() const {
185 KResourceLimit* GetResourceLimit() const; 193 return static_cast<u32>(m_flags);
194 }
186 195
187 /// Gets the ideal CPU core ID for this process 196 bool Is64Bit() const {
188 u8 GetIdealCoreId() const { 197 return True(m_flags & Svc::CreateProcessFlag::Is64Bit);
189 return m_ideal_core;
190 } 198 }
191 199
192 /// Checks if the specified thread priority is valid. 200 KProcessAddress GetEntryPoint() const {
193 bool CheckThreadPriority(s32 prio) const { 201 return m_code_address;
194 return ((1ULL << prio) & GetPriorityMask()) != 0;
195 } 202 }
196 203
197 /// Gets the bitmask of allowed cores that this process' threads can run on. 204 size_t GetMainStackSize() const {
198 u64 GetCoreMask() const { 205 return m_main_thread_stack_size;
199 return m_capabilities.GetCoreMask();
200 } 206 }
201 207
202 /// Gets the bitmask of allowed thread priorities. 208 KMemoryManager::Pool GetMemoryPool() const {
203 u64 GetPriorityMask() const { 209 return m_memory_pool;
204 return m_capabilities.GetPriorityMask();
205 } 210 }
206 211
207 /// Gets the amount of secure memory to allocate for memory management. 212 u64 GetRandomEntropy(size_t i) const {
208 u32 GetSystemResourceSize() const { 213 return m_entropy[i];
209 return m_system_resource_size;
210 } 214 }
211 215
212 /// Gets the amount of secure memory currently in use for memory management. 216 bool IsApplication() const {
213 u32 GetSystemResourceUsage() const { 217 return m_is_application;
214 // On hardware, this returns the amount of system resource memory that has
215 // been used by the kernel. This is problematic for Yuzu to emulate, because
216 // system resource memory is used for page tables -- and yuzu doesn't really
217 // have a way to calculate how much memory is required for page tables for
218 // the current process at any given time.
219 // TODO: Is this even worth implementing? Games may retrieve this value via
220 // an SDK function that gets used + available system resource size for debug
221 // or diagnostic purposes. However, it seems unlikely that a game would make
222 // decisions based on how much system memory is dedicated to its page tables.
223 // Is returning a value other than zero wise?
224 return 0;
225 } 218 }
226 219
227 /// Whether this process is an AArch64 or AArch32 process. 220 bool IsDefaultApplicationSystemResource() const {
228 bool Is64BitProcess() const { 221 return m_is_default_application_system_resource;
229 return m_is_64bit_process;
230 } 222 }
231 223
232 bool IsSuspended() const { 224 bool IsSuspended() const {
233 return m_is_suspended; 225 return m_is_suspended;
234 } 226 }
235
236 void SetSuspended(bool suspended) { 227 void SetSuspended(bool suspended) {
237 m_is_suspended = suspended; 228 m_is_suspended = suspended;
238 } 229 }
239 230
240 /// Gets the total running time of the process instance in ticks. 231 Result Terminate();
241 u64 GetCPUTimeTicks() const { 232
242 return m_total_process_running_time_ticks; 233 bool IsTerminated() const {
234 return m_state == State::Terminated;
243 } 235 }
244 236
245 /// Updates the total running time, adding the given ticks to it. 237 bool IsPermittedSvc(u32 svc_id) const {
246 void UpdateCPUTimeTicks(u64 ticks) { 238 return m_capabilities.IsPermittedSvc(svc_id);
247 m_total_process_running_time_ticks += ticks;
248 } 239 }
249 240
250 /// Gets the process schedule count, used for thread yielding 241 bool IsPermittedInterrupt(s32 interrupt_id) const {
251 s64 GetScheduledCount() const { 242 return m_capabilities.IsPermittedInterrupt(interrupt_id);
252 return m_schedule_count;
253 } 243 }
254 244
255 /// Increments the process schedule count, used for thread yielding. 245 bool IsPermittedDebug() const {
256 void IncrementScheduledCount() { 246 return m_capabilities.IsPermittedDebug();
257 ++m_schedule_count;
258 } 247 }
259 248
260 void IncrementRunningThreadCount(); 249 bool CanForceDebug() const {
261 void DecrementRunningThreadCount(); 250 return m_capabilities.CanForceDebug();
251 }
262 252
263 void SetRunningThread(s32 core, KThread* thread, u64 idle_count) { 253 bool IsHbl() const {
264 m_running_threads[core] = thread; 254 return m_is_hbl;
265 m_running_thread_idle_counts[core] = idle_count;
266 } 255 }
267 256
268 void ClearRunningThread(KThread* thread) { 257 Kernel::KMemoryManager::Direction GetAllocateOption() const {
269 for (size_t i = 0; i < m_running_threads.size(); ++i) { 258 // TODO: property of the KPageTableBase
270 if (m_running_threads[i] == thread) { 259 return KMemoryManager::Direction::FromFront;
271 m_running_threads[i] = nullptr;
272 }
273 }
274 } 260 }
275 261
276 [[nodiscard]] KThread* GetRunningThread(s32 core) const { 262 ThreadList& GetThreadList() {
277 return m_running_threads[core]; 263 return m_thread_list;
264 }
265 const ThreadList& GetThreadList() const {
266 return m_thread_list;
278 } 267 }
279 268
269 bool EnterUserException();
270 bool LeaveUserException();
280 bool ReleaseUserException(KThread* thread); 271 bool ReleaseUserException(KThread* thread);
281 272
282 [[nodiscard]] KThread* GetPinnedThread(s32 core_id) const { 273 KThread* GetPinnedThread(s32 core_id) const {
283 ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); 274 ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
284 return m_pinned_threads[core_id]; 275 return m_pinned_threads[core_id];
285 } 276 }
286 277
287 /// Gets 8 bytes of random data for svcGetInfo RandomEntropy 278 const Svc::SvcAccessFlagSet& GetSvcPermissions() const {
288 u64 GetRandomEntropy(std::size_t index) const { 279 return m_capabilities.GetSvcPermissions();
289 return m_random_entropy.at(index);
290 } 280 }
291 281
292 /// Retrieves the total physical memory available to this process in bytes. 282 KResourceLimit* GetResourceLimit() const {
293 u64 GetTotalPhysicalMemoryAvailable(); 283 return m_resource_limit;
294
295 /// Retrieves the total physical memory available to this process in bytes,
296 /// without the size of the personal system resource heap added to it.
297 u64 GetTotalPhysicalMemoryAvailableWithoutSystemResource();
298
299 /// Retrieves the total physical memory used by this process in bytes.
300 u64 GetTotalPhysicalMemoryUsed();
301
302 /// Retrieves the total physical memory used by this process in bytes,
303 /// without the size of the personal system resource heap added to it.
304 u64 GetTotalPhysicalMemoryUsedWithoutSystemResource();
305
306 /// Gets the list of all threads created with this process as their owner.
307 std::list<KThread*>& GetThreadList() {
308 return m_thread_list;
309 } 284 }
310 285
311 /// Registers a thread as being created under this process, 286 bool ReserveResource(Svc::LimitableResource which, s64 value);
312 /// adding it to this process' thread list. 287 bool ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout);
313 void RegisterThread(KThread* thread); 288 void ReleaseResource(Svc::LimitableResource which, s64 value);
289 void ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint);
314 290
315 /// Unregisters a thread from this process, removing it 291 KLightLock& GetStateLock() {
316 /// from this process' thread list. 292 return m_state_lock;
317 void UnregisterThread(KThread* thread); 293 }
294 KLightLock& GetListLock() {
295 return m_list_lock;
296 }
318 297
319 /// Retrieves the number of available threads for this process. 298 KPageTable& GetPageTable() {
320 u64 GetFreeThreadCount() const; 299 return m_page_table;
321 300 }
322 /// Clears the signaled state of the process if and only if it's signaled. 301 const KPageTable& GetPageTable() const {
323 /// 302 return m_page_table;
324 /// @pre The process must not be already terminated. If this is called on a 303 }
325 /// terminated process, then ResultInvalidState will be returned.
326 ///
327 /// @pre The process must be in a signaled state. If this is called on a
328 /// process instance that is not signaled, ResultInvalidState will be
329 /// returned.
330 Result Reset();
331 304
332 /** 305 KHandleTable& GetHandleTable() {
333 * Loads process-specifics configuration info with metadata provided 306 return m_handle_table;
334 * by an executable. 307 }
335 * 308 const KHandleTable& GetHandleTable() const {
336 * @param metadata The provided metadata to load process specific info from. 309 return m_handle_table;
337 * 310 }
338 * @returns ResultSuccess if all relevant metadata was able to be
339 * loaded and parsed. Otherwise, an error code is returned.
340 */
341 Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
342 bool is_hbl);
343 311
344 /** 312 size_t GetUsedUserPhysicalMemorySize() const;
345 * Starts the main application thread for this process. 313 size_t GetTotalUserPhysicalMemorySize() const;
346 * 314 size_t GetUsedNonSystemUserPhysicalMemorySize() const;
347 * @param main_thread_priority The priority for the main thread. 315 size_t GetTotalNonSystemUserPhysicalMemorySize() const;
348 * @param stack_size The stack size for the main thread in bytes.
349 */
350 void Run(s32 main_thread_priority, u64 stack_size);
351 316
352 /** 317 Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
353 * Prepares a process for termination by stopping all of its threads 318 void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size);
354 * and clearing any other resources.
355 */
356 void PrepareForTermination();
357 319
358 void LoadModule(CodeSet code_set, KProcessAddress base_addr); 320 Result CreateThreadLocalRegion(KProcessAddress* out);
321 Result DeleteThreadLocalRegion(KProcessAddress addr);
359 322
360 bool IsInitialized() const override { 323 KProcessAddress GetProcessLocalRegionAddress() const {
361 return m_is_initialized; 324 return m_plr_address;
362 } 325 }
363 326
364 static void PostDestroy(uintptr_t arg) {} 327 KThread* GetExceptionThread() const {
365 328 return m_exception_thread;
366 void Finalize() override;
367
368 u64 GetId() const override {
369 return GetProcessId();
370 } 329 }
371 330
372 bool IsHbl() const { 331 void AddCpuTime(s64 diff) {
373 return m_is_hbl; 332 m_cpu_time += diff;
333 }
334 s64 GetCpuTime() {
335 return m_cpu_time.load();
374 } 336 }
375 337
376 bool IsSignaled() const override; 338 s64 GetScheduledCount() const {
377 339 return m_schedule_count;
378 void DoWorkerTaskImpl(); 340 }
341 void IncrementScheduledCount() {
342 ++m_schedule_count;
343 }
379 344
380 Result SetActivity(ProcessActivity activity); 345 void IncrementRunningThreadCount();
346 void DecrementRunningThreadCount();
381 347
382 void PinCurrentThread(s32 core_id); 348 size_t GetRequiredSecureMemorySizeNonDefault() const {
383 void UnpinCurrentThread(s32 core_id); 349 if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
384 void UnpinThread(KThread* thread); 350 auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
351 return secure_system_resource->CalculateRequiredSecureMemorySize();
352 }
385 353
386 KLightLock& GetStateLock() { 354 return 0;
387 return m_state_lock;
388 } 355 }
389 356
390 Result AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); 357 size_t GetRequiredSecureMemorySize() const {
391 void RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size); 358 if (m_system_resource->IsSecureResource()) {
392 359 auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
393 /////////////////////////////////////////////////////////////////////////////////////////////// 360 return secure_system_resource->CalculateRequiredSecureMemorySize();
394 // Thread-local storage management 361 }
395
396 // Marks the next available region as used and returns the address of the slot.
397 [[nodiscard]] Result CreateThreadLocalRegion(KProcessAddress* out);
398 362
399 // Frees a used TLS slot identified by the given address 363 return 0;
400 Result DeleteThreadLocalRegion(KProcessAddress addr); 364 }
401 365
402 /////////////////////////////////////////////////////////////////////////////////////////////// 366 size_t GetTotalSystemResourceSize() const {
403 // Debug watchpoint management 367 if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
368 auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
369 return secure_system_resource->GetSize();
370 }
404 371
405 // Attempts to insert a watchpoint into a free slot. Returns false if none are available. 372 return 0;
406 bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); 373 }
407 374
408 // Attempts to remove the watchpoint specified by the given parameters. 375 size_t GetUsedSystemResourceSize() const {
409 bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type); 376 if (!this->IsDefaultApplicationSystemResource() && m_system_resource->IsSecureResource()) {
377 auto* secure_system_resource = static_cast<KSecureSystemResource*>(m_system_resource);
378 return secure_system_resource->GetUsedSize();
379 }
410 380
411 const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const { 381 return 0;
412 return m_watchpoints;
413 } 382 }
414 383
415 const std::string& GetName() { 384 void SetRunningThread(s32 core, KThread* thread, u64 idle_count, u64 switch_count) {
416 return name; 385 m_running_threads[core] = thread;
386 m_running_thread_idle_counts[core] = idle_count;
387 m_running_thread_switch_counts[core] = switch_count;
417 } 388 }
418 389
419private: 390 void ClearRunningThread(KThread* thread) {
420 void PinThread(s32 core_id, KThread* thread) { 391 for (size_t i = 0; i < m_running_threads.size(); ++i) {
421 ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); 392 if (m_running_threads[i] == thread) {
422 ASSERT(thread != nullptr); 393 m_running_threads[i] = nullptr;
423 ASSERT(m_pinned_threads[core_id] == nullptr); 394 }
424 m_pinned_threads[core_id] = thread; 395 }
425 } 396 }
426 397
427 void UnpinThread(s32 core_id, KThread* thread) { 398 const KSystemResource& GetSystemResource() const {
428 ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); 399 return *m_system_resource;
429 ASSERT(thread != nullptr);
430 ASSERT(m_pinned_threads[core_id] == thread);
431 m_pinned_threads[core_id] = nullptr;
432 } 400 }
433 401
434 void FinalizeHandleTable() { 402 const KMemoryBlockSlabManager& GetMemoryBlockSlabManager() const {
435 // Finalize the table. 403 return m_system_resource->GetMemoryBlockSlabManager();
436 m_handle_table.Finalize(); 404 }
437 405 const KBlockInfoManager& GetBlockInfoManager() const {
438 // Note that the table is finalized. 406 return m_system_resource->GetBlockInfoManager();
439 m_is_handle_table_initialized = false; 407 }
408 const KPageTableManager& GetPageTableManager() const {
409 return m_system_resource->GetPageTableManager();
440 } 410 }
441 411
442 void ChangeState(State new_state); 412 KThread* GetRunningThread(s32 core) const {
443 413 return m_running_threads[core];
444 /// Allocates the main thread stack for the process, given the stack size in bytes. 414 }
445 Result AllocateMainThreadStack(std::size_t stack_size); 415 u64 GetRunningThreadIdleCount(s32 core) const {
446 416 return m_running_thread_idle_counts[core];
447 /// Memory manager for this process 417 }
448 KPageTable m_page_table; 418 u64 GetRunningThreadSwitchCount(s32 core) const {
449 419 return m_running_thread_switch_counts[core];
450 /// Current status of the process 420 }
451 State m_state{};
452 421
453 /// The ID of this process 422 void RegisterThread(KThread* thread);
454 u64 m_process_id = 0; 423 void UnregisterThread(KThread* thread);
455 424
456 /// Title ID corresponding to the process 425 Result Run(s32 priority, size_t stack_size);
457 u64 m_program_id = 0;
458 426
459 /// Specifies additional memory to be reserved for the process's memory management by the 427 Result Reset();
460 /// system. When this is non-zero, secure memory is allocated and used for page table allocation
461 /// instead of using the normal global page tables/memory block management.
462 u32 m_system_resource_size = 0;
463 428
464 /// Resource limit descriptor for this process 429 void SetDebugBreak() {
465 KResourceLimit* m_resource_limit{}; 430 if (m_state == State::RunningAttached) {
431 this->ChangeState(State::DebugBreak);
432 }
433 }
466 434
467 KVirtualAddress m_system_resource_address{}; 435 void SetAttached() {
436 if (m_state == State::DebugBreak) {
437 this->ChangeState(State::RunningAttached);
438 }
439 }
468 440
469 /// The ideal CPU core for this process, threads are scheduled on this core by default. 441 Result SetActivity(Svc::ProcessActivity activity);
470 u8 m_ideal_core = 0;
471 442
472 /// Contains the parsed process capability descriptors. 443 void PinCurrentThread();
473 ProcessCapabilities m_capabilities; 444 void UnpinCurrentThread();
445 void UnpinThread(KThread* thread);
474 446
475 /// Whether or not this process is AArch64, or AArch32. 447 void SignalConditionVariable(uintptr_t cv_key, int32_t count) {
476 /// By default, we currently assume this is true, unless otherwise 448 return m_cond_var.Signal(cv_key, count);
477 /// specified by metadata provided to the process during loading. 449 }
478 bool m_is_64bit_process = true;
479 450
480 /// Total running time for the process in ticks. 451 Result WaitConditionVariable(KProcessAddress address, uintptr_t cv_key, u32 tag, s64 ns) {
481 std::atomic<u64> m_total_process_running_time_ticks = 0; 452 R_RETURN(m_cond_var.Wait(address, cv_key, tag, ns));
453 }
482 454
483 /// Per-process handle table for storing created object handles in. 455 Result SignalAddressArbiter(uintptr_t address, Svc::SignalType signal_type, s32 value,
484 KHandleTable m_handle_table; 456 s32 count) {
457 R_RETURN(m_address_arbiter.SignalToAddress(address, signal_type, value, count));
458 }
485 459
486 /// Per-process address arbiter. 460 Result WaitAddressArbiter(uintptr_t address, Svc::ArbitrationType arb_type, s32 value,
487 KAddressArbiter m_address_arbiter; 461 s64 timeout) {
462 R_RETURN(m_address_arbiter.WaitForAddress(address, arb_type, value, timeout));
463 }
488 464
489 /// The per-process mutex lock instance used for handling various 465 Result GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count);
490 /// forms of services, such as lock arbitration, and condition
491 /// variable related facilities.
492 KConditionVariable m_condition_var;
493 466
494 /// Address indicating the location of the process' dedicated TLS region. 467 static void Switch(KProcess* cur_process, KProcess* next_process);
495 KProcessAddress m_plr_address = 0;
496 468
497 /// Address indicating the location of the process's entry point. 469public:
498 KProcessAddress m_code_address = 0; 470 // Attempts to insert a watchpoint into a free slot. Returns false if none are available.
471 bool InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
499 472
500 /// Random values for svcGetInfo RandomEntropy 473 // Attempts to remove the watchpoint specified by the given parameters.
501 std::array<u64, RANDOM_ENTROPY_SIZE> m_random_entropy{}; 474 bool RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type);
502 475
503 /// List of threads that are running with this process as their owner. 476 const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const {
504 std::list<KThread*> m_thread_list; 477 return m_watchpoints;
478 }
505 479
506 /// List of shared memory that are running with this process as their owner. 480public:
507 std::list<KSharedMemoryInfo*> m_shared_memory_list; 481 Result LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
482 bool is_hbl);
508 483
509 /// Address of the top of the main thread's stack 484 void LoadModule(CodeSet code_set, KProcessAddress base_addr);
510 KProcessAddress m_main_thread_stack_top{};
511 485
512 /// Size of the main thread's stack 486 Core::Memory::Memory& GetMemory() const;
513 std::size_t m_main_thread_stack_size{};
514 487
515 /// Memory usage capacity for the process 488public:
516 std::size_t m_memory_usage_capacity{}; 489 // Overridden parent functions.
490 bool IsInitialized() const override {
491 return m_is_initialized;
492 }
517 493
518 /// Process total image size 494 static void PostDestroy(uintptr_t arg) {}
519 std::size_t m_image_size{};
520 495
521 /// Schedule count of this process 496 void Finalize() override;
522 s64 m_schedule_count{};
523 497
524 size_t m_memory_release_hint{}; 498 u64 GetIdImpl() const {
499 return this->GetProcessId();
500 }
501 u64 GetId() const override {
502 return this->GetIdImpl();
503 }
525 504
526 std::string name{}; 505 virtual bool IsSignaled() const override {
506 ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel));
507 return m_is_signaled;
508 }
527 509
528 bool m_is_signaled{}; 510 void DoWorkerTaskImpl();
529 bool m_is_suspended{};
530 bool m_is_immortal{};
531 bool m_is_handle_table_initialized{};
532 bool m_is_initialized{};
533 bool m_is_hbl{};
534 511
535 std::atomic<u16> m_num_running_threads{}; 512private:
513 void ChangeState(State new_state) {
514 if (m_state != new_state) {
515 m_state = new_state;
516 m_is_signaled = true;
517 this->NotifyAvailable();
518 }
519 }
536 520
537 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_running_threads{}; 521 Result InitializeHandleTable(s32 size) {
538 std::array<u64, Core::Hardware::NUM_CPU_CORES> m_running_thread_idle_counts{}; 522 // Try to initialize the handle table.
539 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> m_pinned_threads{}; 523 R_TRY(m_handle_table.Initialize(size));
540 std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> m_watchpoints{};
541 std::map<KProcessAddress, u64> m_debug_page_refcounts;
542 524
543 KThread* m_exception_thread{}; 525 // We succeeded, so note that we did.
526 m_is_handle_table_initialized = true;
527 R_SUCCEED();
528 }
544 529
545 KLightLock m_state_lock; 530 void FinalizeHandleTable() {
546 KLightLock m_list_lock; 531 // Finalize the table.
532 m_handle_table.Finalize();
547 533
548 using TLPTree = 534 // Note that the table is finalized.
549 Common::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>; 535 m_is_handle_table_initialized = false;
550 using TLPIterator = TLPTree::iterator; 536 }
551 TLPTree m_fully_used_tlp_tree;
552 TLPTree m_partially_used_tlp_tree;
553}; 537};
554 538
555} // namespace Kernel 539} // namespace Kernel
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index d8143c650..1bce63a56 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -190,7 +190,7 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {
190 if (m_state.should_count_idle) { 190 if (m_state.should_count_idle) {
191 if (highest_thread != nullptr) [[likely]] { 191 if (highest_thread != nullptr) [[likely]] {
192 if (KProcess* process = highest_thread->GetOwnerProcess(); process != nullptr) { 192 if (KProcess* process = highest_thread->GetOwnerProcess(); process != nullptr) {
193 process->SetRunningThread(m_core_id, highest_thread, m_state.idle_count); 193 process->SetRunningThread(m_core_id, highest_thread, m_state.idle_count, 0);
194 } 194 }
195 } else { 195 } else {
196 m_state.idle_count++; 196 m_state.idle_count++;
@@ -356,7 +356,7 @@ void KScheduler::SwitchThread(KThread* next_thread) {
356 const s64 tick_diff = cur_tick - prev_tick; 356 const s64 tick_diff = cur_tick - prev_tick;
357 cur_thread->AddCpuTime(m_core_id, tick_diff); 357 cur_thread->AddCpuTime(m_core_id, tick_diff);
358 if (cur_process != nullptr) { 358 if (cur_process != nullptr) {
359 cur_process->UpdateCPUTimeTicks(tick_diff); 359 cur_process->AddCpuTime(tick_diff);
360 } 360 }
361 m_last_context_switch_time = cur_tick; 361 m_last_context_switch_time = cur_tick;
362 362
diff --git a/src/core/hle/kernel/k_system_resource.cpp b/src/core/hle/kernel/k_system_resource.cpp
index e6c8d589a..07e92aa80 100644
--- a/src/core/hle/kernel/k_system_resource.cpp
+++ b/src/core/hle/kernel/k_system_resource.cpp
@@ -1,25 +1,100 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/core.h"
5#include "core/hle/kernel/k_scoped_resource_reservation.h"
4#include "core/hle/kernel/k_system_resource.h" 6#include "core/hle/kernel/k_system_resource.h"
5 7
6namespace Kernel { 8namespace Kernel {
7 9
8Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit, 10Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit,
9 KMemoryManager::Pool pool) { 11 KMemoryManager::Pool pool) {
10 // Unimplemented 12 // Set members.
11 UNREACHABLE(); 13 m_resource_limit = resource_limit;
14 m_resource_size = size;
15 m_resource_pool = pool;
16
17 // Determine required size for our secure resource.
18 const size_t secure_size = this->CalculateRequiredSecureMemorySize();
19
20 // Reserve memory for our secure resource.
21 KScopedResourceReservation memory_reservation(
22 m_resource_limit, Svc::LimitableResource::PhysicalMemoryMax, secure_size);
23 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
24
25 // Allocate secure memory.
26 R_TRY(KSystemControl::AllocateSecureMemory(m_kernel, std::addressof(m_resource_address),
27 m_resource_size, static_cast<u32>(m_resource_pool)));
28 ASSERT(m_resource_address != 0);
29
30 // Ensure we clean up the secure memory, if we fail past this point.
31 ON_RESULT_FAILURE {
32 KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size,
33 static_cast<u32>(m_resource_pool));
34 };
35
36 // Check that our allocation is bigger than the reference counts needed for it.
37 const size_t rc_size =
38 Common::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(m_resource_size), PageSize);
39 R_UNLESS(m_resource_size > rc_size, ResultOutOfMemory);
40
41 // Get resource pointer.
42 KPhysicalAddress resource_paddr =
43 KPageTable::GetHeapPhysicalAddress(m_kernel.MemoryLayout(), m_resource_address);
44 auto* resource =
45 m_kernel.System().DeviceMemory().GetPointer<KPageTableManager::RefCount>(resource_paddr);
46
47 // Initialize slab heaps.
48 m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size,
49 PageSize);
50 m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, resource);
51 m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
52 m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
53
54 // Initialize managers.
55 m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager),
56 std::addressof(m_page_table_heap));
57 m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager),
58 std::addressof(m_memory_block_heap));
59 m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager),
60 std::addressof(m_block_info_heap));
61
62 // Set our managers.
63 this->SetManagers(m_memory_block_slab_manager, m_block_info_manager, m_page_table_manager);
64
65 // Commit the memory reservation.
66 memory_reservation.Commit();
67
68 // Open reference to our resource limit.
69 m_resource_limit->Open();
70
71 // Set ourselves as initialized.
72 m_is_initialized = true;
73
74 R_SUCCEED();
12} 75}
13 76
14void KSecureSystemResource::Finalize() { 77void KSecureSystemResource::Finalize() {
15 // Unimplemented 78 // Check that we have no outstanding allocations.
16 UNREACHABLE(); 79 ASSERT(m_memory_block_slab_manager.GetUsed() == 0);
80 ASSERT(m_block_info_manager.GetUsed() == 0);
81 ASSERT(m_page_table_manager.GetUsed() == 0);
82
83 // Free our secure memory.
84 KSystemControl::FreeSecureMemory(m_kernel, m_resource_address, m_resource_size,
85 static_cast<u32>(m_resource_pool));
86
87 // Release the memory reservation.
88 m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax,
89 this->CalculateRequiredSecureMemorySize());
90
91 // Close reference to our resource limit.
92 m_resource_limit->Close();
17} 93}
18 94
19size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, 95size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size,
20 KMemoryManager::Pool pool) { 96 KMemoryManager::Pool pool) {
21 // Unimplemented 97 return KSystemControl::CalculateRequiredSecureMemorySize(size, static_cast<u32>(pool));
22 UNREACHABLE();
23} 98}
24 99
25} // namespace Kernel 100} // namespace Kernel
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 7df8fd7f7..a6deb50ec 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -122,16 +122,15 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress
122 case ThreadType::Main: 122 case ThreadType::Main:
123 ASSERT(arg == 0); 123 ASSERT(arg == 0);
124 [[fallthrough]]; 124 [[fallthrough]];
125 case ThreadType::HighPriority:
126 [[fallthrough]];
127 case ThreadType::Dummy:
128 [[fallthrough]];
129 case ThreadType::User: 125 case ThreadType::User:
130 ASSERT(((owner == nullptr) || 126 ASSERT(((owner == nullptr) ||
131 (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask())); 127 (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask()));
132 ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) || 128 ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) ||
133 (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask())); 129 (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask()));
134 break; 130 break;
131 case ThreadType::HighPriority:
132 case ThreadType::Dummy:
133 break;
135 case ThreadType::Kernel: 134 case ThreadType::Kernel:
136 UNIMPLEMENTED(); 135 UNIMPLEMENTED();
137 break; 136 break;
@@ -216,6 +215,7 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress
216 // Setup the TLS, if needed. 215 // Setup the TLS, if needed.
217 if (type == ThreadType::User) { 216 if (type == ThreadType::User) {
218 R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address))); 217 R_TRY(owner->CreateThreadLocalRegion(std::addressof(m_tls_address)));
218 owner->GetMemory().ZeroBlock(m_tls_address, Svc::ThreadLocalRegionSize);
219 } 219 }
220 220
221 m_parent = owner; 221 m_parent = owner;
@@ -403,7 +403,7 @@ void KThread::StartTermination() {
403 if (m_parent != nullptr) { 403 if (m_parent != nullptr) {
404 m_parent->ReleaseUserException(this); 404 m_parent->ReleaseUserException(this);
405 if (m_parent->GetPinnedThread(GetCurrentCoreId(m_kernel)) == this) { 405 if (m_parent->GetPinnedThread(GetCurrentCoreId(m_kernel)) == this) {
406 m_parent->UnpinCurrentThread(m_core_id); 406 m_parent->UnpinCurrentThread();
407 } 407 }
408 } 408 }
409 409
@@ -415,10 +415,6 @@ void KThread::StartTermination() {
415 m_parent->ClearRunningThread(this); 415 m_parent->ClearRunningThread(this);
416 } 416 }
417 417
418 // Signal.
419 m_signaled = true;
420 KSynchronizationObject::NotifyAvailable();
421
422 // Clear previous thread in KScheduler. 418 // Clear previous thread in KScheduler.
423 KScheduler::ClearPreviousThread(m_kernel, this); 419 KScheduler::ClearPreviousThread(m_kernel, this);
424 420
@@ -437,6 +433,13 @@ void KThread::FinishTermination() {
437 } 433 }
438 } 434 }
439 435
436 // Acquire the scheduler lock.
437 KScopedSchedulerLock sl{m_kernel};
438
439 // Signal.
440 m_signaled = true;
441 KSynchronizationObject::NotifyAvailable();
442
440 // Close the thread. 443 // Close the thread.
441 this->Close(); 444 this->Close();
442} 445}
@@ -820,7 +823,7 @@ void KThread::CloneFpuStatus() {
820 ASSERT(this->GetOwnerProcess() != nullptr); 823 ASSERT(this->GetOwnerProcess() != nullptr);
821 ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(m_kernel)); 824 ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(m_kernel));
822 825
823 if (this->GetOwnerProcess()->Is64BitProcess()) { 826 if (this->GetOwnerProcess()->Is64Bit()) {
824 // Clone FPSR and FPCR. 827 // Clone FPSR and FPCR.
825 ThreadContext64 cur_ctx{}; 828 ThreadContext64 cur_ctx{};
826 m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx); 829 m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
@@ -923,7 +926,7 @@ Result KThread::GetThreadContext3(Common::ScratchBuffer<u8>& out) {
923 926
924 // If we're not terminating, get the thread's user context. 927 // If we're not terminating, get the thread's user context.
925 if (!this->IsTerminationRequested()) { 928 if (!this->IsTerminationRequested()) {
926 if (m_parent->Is64BitProcess()) { 929 if (m_parent->Is64Bit()) {
927 // Mask away mode bits, interrupt bits, IL bit, and other reserved bits. 930 // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
928 auto context = GetContext64(); 931 auto context = GetContext64();
929 context.pstate &= 0xFF0FFE20; 932 context.pstate &= 0xFF0FFE20;
@@ -1174,6 +1177,9 @@ Result KThread::Run() {
1174 owner->IncrementRunningThreadCount(); 1177 owner->IncrementRunningThreadCount();
1175 } 1178 }
1176 1179
1180 // Open a reference, now that we're running.
1181 this->Open();
1182
1177 // Set our state and finish. 1183 // Set our state and finish.
1178 this->SetState(ThreadState::Runnable); 1184 this->SetState(ThreadState::Runnable);
1179 1185
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index d178c2453..e1f80b04f 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -721,6 +721,7 @@ private:
721 // For core KThread implementation 721 // For core KThread implementation
722 ThreadContext32 m_thread_context_32{}; 722 ThreadContext32 m_thread_context_32{};
723 ThreadContext64 m_thread_context_64{}; 723 ThreadContext64 m_thread_context_64{};
724 Common::IntrusiveListNode m_process_list_node;
724 Common::IntrusiveRedBlackTreeNode m_condvar_arbiter_tree_node{}; 725 Common::IntrusiveRedBlackTreeNode m_condvar_arbiter_tree_node{};
725 s32 m_priority{}; 726 s32 m_priority{};
726 using ConditionVariableThreadTreeTraits = 727 using ConditionVariableThreadTreeTraits =
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 24433d32b..4a1559291 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -101,35 +101,31 @@ struct KernelCore::Impl {
101 101
102 void InitializeCores() { 102 void InitializeCores() {
103 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 103 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
104 cores[core_id]->Initialize((*application_process).Is64BitProcess()); 104 cores[core_id]->Initialize((*application_process).Is64Bit());
105 system.ApplicationMemory().SetCurrentPageTable(*application_process, core_id); 105 system.ApplicationMemory().SetCurrentPageTable(*application_process, core_id);
106 } 106 }
107 } 107 }
108 108
109 void CloseApplicationProcess() { 109 void TerminateApplicationProcess() {
110 KProcess* old_process = application_process.exchange(nullptr); 110 application_process.load()->Terminate();
111 if (old_process == nullptr) {
112 return;
113 }
114
115 // old_process->Close();
116 // TODO: The process should be destroyed based on accurate ref counting after
117 // calling Close(). Adding a manual Destroy() call instead to avoid a memory leak.
118 old_process->Finalize();
119 old_process->Destroy();
120 } 111 }
121 112
122 void Shutdown() { 113 void Shutdown() {
123 is_shutting_down.store(true, std::memory_order_relaxed); 114 is_shutting_down.store(true, std::memory_order_relaxed);
124 SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); }); 115 SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); });
125 116
126 process_list.clear();
127
128 CloseServices(); 117 CloseServices();
129 118
119 auto* old_process = application_process.exchange(nullptr);
120 if (old_process) {
121 old_process->Close();
122 }
123
124 process_list.clear();
125
130 next_object_id = 0; 126 next_object_id = 0;
131 next_kernel_process_id = KProcess::InitialKIPIDMin; 127 next_kernel_process_id = KProcess::InitialProcessIdMin;
132 next_user_process_id = KProcess::ProcessIDMin; 128 next_user_process_id = KProcess::ProcessIdMin;
133 next_thread_id = 1; 129 next_thread_id = 1;
134 130
135 global_handle_table->Finalize(); 131 global_handle_table->Finalize();
@@ -176,8 +172,6 @@ struct KernelCore::Impl {
176 } 172 }
177 } 173 }
178 174
179 CloseApplicationProcess();
180
181 // Track kernel objects that were not freed on shutdown 175 // Track kernel objects that were not freed on shutdown
182 { 176 {
183 std::scoped_lock lk{registered_objects_lock}; 177 std::scoped_lock lk{registered_objects_lock};
@@ -344,6 +338,8 @@ struct KernelCore::Impl {
344 // Create the system page table managers. 338 // Create the system page table managers.
345 app_system_resource = std::make_unique<KSystemResource>(kernel); 339 app_system_resource = std::make_unique<KSystemResource>(kernel);
346 sys_system_resource = std::make_unique<KSystemResource>(kernel); 340 sys_system_resource = std::make_unique<KSystemResource>(kernel);
341 KAutoObject::Create(std::addressof(*app_system_resource));
342 KAutoObject::Create(std::addressof(*sys_system_resource));
347 343
348 // Set the managers for the system resources. 344 // Set the managers for the system resources.
349 app_system_resource->SetManagers(*app_memory_block_manager, *app_block_info_manager, 345 app_system_resource->SetManagers(*app_memory_block_manager, *app_block_info_manager,
@@ -792,8 +788,8 @@ struct KernelCore::Impl {
792 std::mutex registered_in_use_objects_lock; 788 std::mutex registered_in_use_objects_lock;
793 789
794 std::atomic<u32> next_object_id{0}; 790 std::atomic<u32> next_object_id{0};
795 std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin}; 791 std::atomic<u64> next_kernel_process_id{KProcess::InitialProcessIdMin};
796 std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin}; 792 std::atomic<u64> next_user_process_id{KProcess::ProcessIdMin};
797 std::atomic<u64> next_thread_id{1}; 793 std::atomic<u64> next_thread_id{1};
798 794
799 // Lists all processes that exist in the current session. 795 // Lists all processes that exist in the current session.
@@ -924,10 +920,6 @@ const KProcess* KernelCore::ApplicationProcess() const {
924 return impl->application_process; 920 return impl->application_process;
925} 921}
926 922
927void KernelCore::CloseApplicationProcess() {
928 impl->CloseApplicationProcess();
929}
930
931const std::vector<KProcess*>& KernelCore::GetProcessList() const { 923const std::vector<KProcess*>& KernelCore::GetProcessList() const {
932 return impl->process_list; 924 return impl->process_list;
933} 925}
@@ -1128,8 +1120,8 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name,
1128 std::function<void()> func) { 1120 std::function<void()> func) {
1129 // Make a new process. 1121 // Make a new process.
1130 KProcess* process = KProcess::Create(*this); 1122 KProcess* process = KProcess::Create(*this);
1131 ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland, 1123 ASSERT(R_SUCCEEDED(
1132 GetSystemResourceLimit()))); 1124 process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));
1133 1125
1134 // Ensure that we don't hold onto any extra references. 1126 // Ensure that we don't hold onto any extra references.
1135 SCOPE_EXIT({ process->Close(); }); 1127 SCOPE_EXIT({ process->Close(); });
@@ -1156,8 +1148,8 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function
1156 1148
1157 // Make a new process. 1149 // Make a new process.
1158 KProcess* process = KProcess::Create(*this); 1150 KProcess* process = KProcess::Create(*this);
1159 ASSERT(R_SUCCEEDED(KProcess::Initialize(process, System(), "", KProcess::ProcessType::Userland, 1151 ASSERT(R_SUCCEEDED(
1160 GetSystemResourceLimit()))); 1152 process->Initialize(Svc::CreateProcessParameter{}, GetSystemResourceLimit(), false)));
1161 1153
1162 // Ensure that we don't hold onto any extra references. 1154 // Ensure that we don't hold onto any extra references.
1163 SCOPE_EXIT({ process->Close(); }); 1155 SCOPE_EXIT({ process->Close(); });
@@ -1266,7 +1258,8 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
1266 1258
1267void KernelCore::SuspendApplication(bool suspended) { 1259void KernelCore::SuspendApplication(bool suspended) {
1268 const bool should_suspend{exception_exited || suspended}; 1260 const bool should_suspend{exception_exited || suspended};
1269 const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; 1261 const auto activity =
1262 should_suspend ? Svc::ProcessActivity::Paused : Svc::ProcessActivity::Runnable;
1270 1263
1271 // Get the application process. 1264 // Get the application process.
1272 KScopedAutoObject<KProcess> process = ApplicationProcess(); 1265 KScopedAutoObject<KProcess> process = ApplicationProcess();
@@ -1300,6 +1293,8 @@ void KernelCore::SuspendApplication(bool suspended) {
1300} 1293}
1301 1294
1302void KernelCore::ShutdownCores() { 1295void KernelCore::ShutdownCores() {
1296 impl->TerminateApplicationProcess();
1297
1303 KScopedSchedulerLock lk{*this}; 1298 KScopedSchedulerLock lk{*this};
1304 1299
1305 for (auto* thread : impl->shutdown_threads) { 1300 for (auto* thread : impl->shutdown_threads) {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index d5b08eeb5..d8086c0ea 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -134,9 +134,6 @@ public:
134 /// Retrieves a const pointer to the application process. 134 /// Retrieves a const pointer to the application process.
135 const KProcess* ApplicationProcess() const; 135 const KProcess* ApplicationProcess() const;
136 136
137 /// Closes the application process.
138 void CloseApplicationProcess();
139
140 /// Retrieves the list of processes. 137 /// Retrieves the list of processes.
141 const std::vector<KProcess*>& GetProcessList() const; 138 const std::vector<KProcess*>& GetProcessList() const;
142 139
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 871d541d4..b76683969 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -4426,7 +4426,7 @@ void Call(Core::System& system, u32 imm) {
4426 auto& kernel = system.Kernel(); 4426 auto& kernel = system.Kernel();
4427 kernel.EnterSVCProfile(); 4427 kernel.EnterSVCProfile();
4428 4428
4429 if (GetCurrentProcess(system.Kernel()).Is64BitProcess()) { 4429 if (GetCurrentProcess(system.Kernel()).Is64Bit()) {
4430 Call64(system, imm); 4430 Call64(system, imm);
4431 } else { 4431 } else {
4432 Call32(system, imm); 4432 Call32(system, imm);
diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp
index f99964028..ada998772 100644
--- a/src/core/hle/kernel/svc/svc_info.cpp
+++ b/src/core/hle/kernel/svc/svc_info.cpp
@@ -86,20 +86,19 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
86 R_SUCCEED(); 86 R_SUCCEED();
87 87
88 case InfoType::TotalMemorySize: 88 case InfoType::TotalMemorySize:
89 *result = process->GetTotalPhysicalMemoryAvailable(); 89 *result = process->GetTotalUserPhysicalMemorySize();
90 R_SUCCEED(); 90 R_SUCCEED();
91 91
92 case InfoType::UsedMemorySize: 92 case InfoType::UsedMemorySize:
93 *result = process->GetTotalPhysicalMemoryUsed(); 93 *result = process->GetUsedUserPhysicalMemorySize();
94 R_SUCCEED(); 94 R_SUCCEED();
95 95
96 case InfoType::SystemResourceSizeTotal: 96 case InfoType::SystemResourceSizeTotal:
97 *result = process->GetSystemResourceSize(); 97 *result = process->GetTotalSystemResourceSize();
98 R_SUCCEED(); 98 R_SUCCEED();
99 99
100 case InfoType::SystemResourceSizeUsed: 100 case InfoType::SystemResourceSizeUsed:
101 LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query system resource usage"); 101 *result = process->GetUsedSystemResourceSize();
102 *result = process->GetSystemResourceUsage();
103 R_SUCCEED(); 102 R_SUCCEED();
104 103
105 case InfoType::ProgramId: 104 case InfoType::ProgramId:
@@ -111,20 +110,29 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
111 R_SUCCEED(); 110 R_SUCCEED();
112 111
113 case InfoType::TotalNonSystemMemorySize: 112 case InfoType::TotalNonSystemMemorySize:
114 *result = process->GetTotalPhysicalMemoryAvailableWithoutSystemResource(); 113 *result = process->GetTotalNonSystemUserPhysicalMemorySize();
115 R_SUCCEED(); 114 R_SUCCEED();
116 115
117 case InfoType::UsedNonSystemMemorySize: 116 case InfoType::UsedNonSystemMemorySize:
118 *result = process->GetTotalPhysicalMemoryUsedWithoutSystemResource(); 117 *result = process->GetUsedNonSystemUserPhysicalMemorySize();
119 R_SUCCEED(); 118 R_SUCCEED();
120 119
121 case InfoType::IsApplication: 120 case InfoType::IsApplication:
122 LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application"); 121 LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application");
123 *result = true; 122 *result = process->IsApplication();
124 R_SUCCEED(); 123 R_SUCCEED();
125 124
126 case InfoType::FreeThreadCount: 125 case InfoType::FreeThreadCount:
127 *result = process->GetFreeThreadCount(); 126 if (KResourceLimit* resource_limit = process->GetResourceLimit();
127 resource_limit != nullptr) {
128 const auto current_value =
129 resource_limit->GetCurrentValue(Svc::LimitableResource::ThreadCountMax);
130 const auto limit_value =
131 resource_limit->GetLimitValue(Svc::LimitableResource::ThreadCountMax);
132 *result = limit_value - current_value;
133 } else {
134 *result = 0;
135 }
128 R_SUCCEED(); 136 R_SUCCEED();
129 137
130 default: 138 default:
@@ -161,7 +169,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
161 169
162 case InfoType::RandomEntropy: 170 case InfoType::RandomEntropy:
163 R_UNLESS(handle == 0, ResultInvalidHandle); 171 R_UNLESS(handle == 0, ResultInvalidHandle);
164 R_UNLESS(info_sub_id < KProcess::RANDOM_ENTROPY_SIZE, ResultInvalidCombination); 172 R_UNLESS(info_sub_id < 4, ResultInvalidCombination);
165 173
166 *result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id); 174 *result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id);
167 R_SUCCEED(); 175 R_SUCCEED();
diff --git a/src/core/hle/kernel/svc/svc_lock.cpp b/src/core/hle/kernel/svc/svc_lock.cpp
index 1d7bc4246..5f0833fcb 100644
--- a/src/core/hle/kernel/svc/svc_lock.cpp
+++ b/src/core/hle/kernel/svc/svc_lock.cpp
@@ -17,7 +17,7 @@ Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u3
17 R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory); 17 R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory);
18 R_UNLESS(Common::IsAligned(address, sizeof(u32)), ResultInvalidAddress); 18 R_UNLESS(Common::IsAligned(address, sizeof(u32)), ResultInvalidAddress);
19 19
20 R_RETURN(GetCurrentProcess(system.Kernel()).WaitForAddress(thread_handle, address, tag)); 20 R_RETURN(KConditionVariable::WaitForAddress(system.Kernel(), thread_handle, address, tag));
21} 21}
22 22
23/// Unlock a mutex 23/// Unlock a mutex
@@ -28,7 +28,7 @@ Result ArbitrateUnlock(Core::System& system, u64 address) {
28 R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory); 28 R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory);
29 R_UNLESS(Common::IsAligned(address, sizeof(u32)), ResultInvalidAddress); 29 R_UNLESS(Common::IsAligned(address, sizeof(u32)), ResultInvalidAddress);
30 30
31 R_RETURN(GetCurrentProcess(system.Kernel()).SignalToAddress(address)); 31 R_RETURN(KConditionVariable::SignalToAddress(system.Kernel(), address));
32} 32}
33 33
34Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag) { 34Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag) {
diff --git a/src/core/hle/kernel/svc/svc_physical_memory.cpp b/src/core/hle/kernel/svc/svc_physical_memory.cpp
index d3545f232..99330d02a 100644
--- a/src/core/hle/kernel/svc/svc_physical_memory.cpp
+++ b/src/core/hle/kernel/svc/svc_physical_memory.cpp
@@ -46,7 +46,7 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
46 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())}; 46 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
47 auto& page_table{current_process->GetPageTable()}; 47 auto& page_table{current_process->GetPageTable()};
48 48
49 if (current_process->GetSystemResourceSize() == 0) { 49 if (current_process->GetTotalSystemResourceSize() == 0) {
50 LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); 50 LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
51 R_THROW(ResultInvalidState); 51 R_THROW(ResultInvalidState);
52 } 52 }
@@ -95,7 +95,7 @@ Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
95 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())}; 95 KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
96 auto& page_table{current_process->GetPageTable()}; 96 auto& page_table{current_process->GetPageTable()};
97 97
98 if (current_process->GetSystemResourceSize() == 0) { 98 if (current_process->GetTotalSystemResourceSize() == 0) {
99 LOG_ERROR(Kernel_SVC, "System Resource Size is zero"); 99 LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
100 R_THROW(ResultInvalidState); 100 R_THROW(ResultInvalidState);
101 } 101 }
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 8ebc1bd1c..6c79cfd8d 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -132,7 +132,7 @@ void SynchronizePreemptionState(Core::System& system) {
132 GetCurrentThread(kernel).ClearInterruptFlag(); 132 GetCurrentThread(kernel).ClearInterruptFlag();
133 133
134 // Unpin the current thread. 134 // Unpin the current thread.
135 cur_process->UnpinCurrentThread(core_id); 135 cur_process->UnpinCurrentThread();
136 } 136 }
137} 137}
138 138
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 933b82e30..755fd62b5 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -85,10 +85,6 @@ Result StartThread(Core::System& system, Handle thread_handle) {
85 // Try to start the thread. 85 // Try to start the thread.
86 R_TRY(thread->Run()); 86 R_TRY(thread->Run());
87 87
88 // If we succeeded, persist a reference to the thread.
89 thread->Open();
90 system.Kernel().RegisterInUseObject(thread.GetPointerUnsafe());
91
92 R_SUCCEED(); 88 R_SUCCEED();
93} 89}
94 90
@@ -99,7 +95,6 @@ void ExitThread(Core::System& system) {
99 auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); 95 auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
100 system.GlobalSchedulerContext().RemoveThread(current_thread); 96 system.GlobalSchedulerContext().RemoveThread(current_thread);
101 current_thread->Exit(); 97 current_thread->Exit();
102 system.Kernel().UnregisterInUseObject(current_thread);
103} 98}
104 99
105/// Sleep the current thread 100/// Sleep the current thread
@@ -260,7 +255,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
260 255
261 auto list_iter = thread_list.cbegin(); 256 auto list_iter = thread_list.cbegin();
262 for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) { 257 for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) {
263 memory.Write64(out_thread_ids, (*list_iter)->GetThreadId()); 258 memory.Write64(out_thread_ids, list_iter->GetThreadId());
264 out_thread_ids += sizeof(u64); 259 out_thread_ids += sizeof(u64);
265 } 260 }
266 261
diff --git a/src/core/hle/kernel/svc_generator.py b/src/core/hle/kernel/svc_generator.py
index 7fcbb1ba1..5531faac6 100644
--- a/src/core/hle/kernel/svc_generator.py
+++ b/src/core/hle/kernel/svc_generator.py
@@ -592,7 +592,7 @@ void Call(Core::System& system, u32 imm) {
592 auto& kernel = system.Kernel(); 592 auto& kernel = system.Kernel();
593 kernel.EnterSVCProfile(); 593 kernel.EnterSVCProfile();
594 594
595 if (GetCurrentProcess(system.Kernel()).Is64BitProcess()) { 595 if (GetCurrentProcess(system.Kernel()).Is64Bit()) {
596 Call64(system, imm); 596 Call64(system, imm);
597 } else { 597 } else {
598 Call32(system, imm); 598 Call32(system, imm);
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h
index 251e6013c..50de02e36 100644
--- a/src/core/hle/kernel/svc_types.h
+++ b/src/core/hle/kernel/svc_types.h
@@ -604,13 +604,57 @@ enum class ProcessActivity : u32 {
604 Paused, 604 Paused,
605}; 605};
606 606
607enum class CreateProcessFlag : u32 {
608 // Is 64 bit?
609 Is64Bit = (1 << 0),
610
611 // What kind of address space?
612 AddressSpaceShift = 1,
613 AddressSpaceMask = (7 << AddressSpaceShift),
614 AddressSpace32Bit = (0 << AddressSpaceShift),
615 AddressSpace64BitDeprecated = (1 << AddressSpaceShift),
616 AddressSpace32BitWithoutAlias = (2 << AddressSpaceShift),
617 AddressSpace64Bit = (3 << AddressSpaceShift),
618
619 // Should JIT debug be done on crash?
620 EnableDebug = (1 << 4),
621
622 // Should ASLR be enabled for the process?
623 EnableAslr = (1 << 5),
624
625 // Is the process an application?
626 IsApplication = (1 << 6),
627
628 // 4.x deprecated: Should use secure memory?
629 DeprecatedUseSecureMemory = (1 << 7),
630
631 // 5.x+ Pool partition type.
632 PoolPartitionShift = 7,
633 PoolPartitionMask = (0xF << PoolPartitionShift),
634 PoolPartitionApplication = (0 << PoolPartitionShift),
635 PoolPartitionApplet = (1 << PoolPartitionShift),
636 PoolPartitionSystem = (2 << PoolPartitionShift),
637 PoolPartitionSystemNonSecure = (3 << PoolPartitionShift),
638
639 // 7.x+ Should memory allocation be optimized? This requires IsApplication.
640 OptimizeMemoryAllocation = (1 << 11),
641
642 // 11.x+ DisableDeviceAddressSpaceMerge.
643 DisableDeviceAddressSpaceMerge = (1 << 12),
644
645 // Mask of all flags.
646 All = Is64Bit | AddressSpaceMask | EnableDebug | EnableAslr | IsApplication |
647 PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge,
648};
649DECLARE_ENUM_FLAG_OPERATORS(CreateProcessFlag);
650
607struct CreateProcessParameter { 651struct CreateProcessParameter {
608 std::array<char, 12> name; 652 std::array<char, 12> name;
609 u32 version; 653 u32 version;
610 u64 program_id; 654 u64 program_id;
611 u64 code_address; 655 u64 code_address;
612 s32 code_num_pages; 656 s32 code_num_pages;
613 u32 flags; 657 CreateProcessFlag flags;
614 Handle reslimit; 658 Handle reslimit;
615 s32 system_resource_num_pages; 659 s32 system_resource_num_pages;
616}; 660};
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 1b1c8190e..f21553644 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -3,11 +3,13 @@
3 3
4#include <algorithm> 4#include <algorithm>
5#include <array> 5#include <array>
6
6#include "common/common_types.h" 7#include "common/common_types.h"
7#include "common/fs/file.h" 8#include "common/fs/file.h"
8#include "common/fs/path_util.h" 9#include "common/fs/path_util.h"
9#include "common/logging/log.h" 10#include "common/logging/log.h"
10#include "common/polyfill_ranges.h" 11#include "common/polyfill_ranges.h"
12#include "common/stb.h"
11#include "common/string_util.h" 13#include "common/string_util.h"
12#include "common/swap.h" 14#include "common/swap.h"
13#include "core/constants.h" 15#include "core/constants.h"
@@ -38,9 +40,36 @@ static std::filesystem::path GetImagePath(const Common::UUID& uuid) {
38 fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString()); 40 fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString());
39} 41}
40 42
41static constexpr u32 SanitizeJPEGSize(std::size_t size) { 43static void JPGToMemory(void* context, void* data, int len) {
44 std::vector<u8>* jpg_image = static_cast<std::vector<u8>*>(context);
45 unsigned char* jpg = static_cast<unsigned char*>(data);
46 jpg_image->insert(jpg_image->end(), jpg, jpg + len);
47}
48
49static void SanitizeJPEGImageSize(std::vector<u8>& image) {
42 constexpr std::size_t max_jpeg_image_size = 0x20000; 50 constexpr std::size_t max_jpeg_image_size = 0x20000;
43 return static_cast<u32>(std::min(size, max_jpeg_image_size)); 51 constexpr int profile_dimensions = 256;
52 int original_width, original_height, color_channels;
53
54 const auto plain_image =
55 stbi_load_from_memory(image.data(), static_cast<int>(image.size()), &original_width,
56 &original_height, &color_channels, STBI_rgb);
57
58 // Resize image to match 256*256
59 if (original_width != profile_dimensions || original_height != profile_dimensions) {
60 // Use vector instead of array to avoid overflowing the stack
61 std::vector<u8> out_image(profile_dimensions * profile_dimensions * STBI_rgb);
62 stbir_resize_uint8_srgb(plain_image, original_width, original_height, 0, out_image.data(),
63 profile_dimensions, profile_dimensions, 0, STBI_rgb, 0,
64 STBIR_FILTER_BOX);
65 image.clear();
66 if (!stbi_write_jpg_to_func(JPGToMemory, &image, profile_dimensions, profile_dimensions,
67 STBI_rgb, out_image.data(), 0)) {
68 LOG_ERROR(Service_ACC, "Failed to resize the user provided image.");
69 }
70 }
71
72 image.resize(std::min(image.size(), max_jpeg_image_size));
44} 73}
45 74
46class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> { 75class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> {
@@ -339,19 +368,20 @@ protected:
339 LOG_WARNING(Service_ACC, 368 LOG_WARNING(Service_ACC,
340 "Failed to load user provided image! Falling back to built-in backup..."); 369 "Failed to load user provided image! Falling back to built-in backup...");
341 ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG); 370 ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG);
342 rb.Push(SanitizeJPEGSize(Core::Constants::ACCOUNT_BACKUP_JPEG.size())); 371 rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
343 return; 372 return;
344 } 373 }
345 374
346 const u32 size = SanitizeJPEGSize(image.GetSize()); 375 std::vector<u8> buffer(image.GetSize());
347 std::vector<u8> buffer(size);
348 376
349 if (image.Read(buffer) != buffer.size()) { 377 if (image.Read(buffer) != buffer.size()) {
350 LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image."); 378 LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
351 } 379 }
352 380
381 SanitizeJPEGImageSize(buffer);
382
353 ctx.WriteBuffer(buffer); 383 ctx.WriteBuffer(buffer);
354 rb.Push<u32>(size); 384 rb.Push(static_cast<u32>(buffer.size()));
355 } 385 }
356 386
357 void GetImageSize(HLERequestContext& ctx) { 387 void GetImageSize(HLERequestContext& ctx) {
@@ -365,10 +395,18 @@ protected:
365 if (!image.IsOpen()) { 395 if (!image.IsOpen()) {
366 LOG_WARNING(Service_ACC, 396 LOG_WARNING(Service_ACC,
367 "Failed to load user provided image! Falling back to built-in backup..."); 397 "Failed to load user provided image! Falling back to built-in backup...");
368 rb.Push(SanitizeJPEGSize(Core::Constants::ACCOUNT_BACKUP_JPEG.size())); 398 rb.Push(static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()));
369 } else { 399 return;
370 rb.Push(SanitizeJPEGSize(image.GetSize()));
371 } 400 }
401
402 std::vector<u8> buffer(image.GetSize());
403
404 if (image.Read(buffer) != buffer.size()) {
405 LOG_ERROR(Service_ACC, "Failed to read all the bytes in the user provided image.");
406 }
407
408 SanitizeJPEGImageSize(buffer);
409 rb.Push(static_cast<u32>(buffer.size()));
372 } 410 }
373 411
374 void Store(HLERequestContext& ctx) { 412 void Store(HLERequestContext& ctx) {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 98765b81a..cc643ea09 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -23,6 +23,7 @@
23#include "core/hle/service/am/applets/applet_cabinet.h" 23#include "core/hle/service/am/applets/applet_cabinet.h"
24#include "core/hle/service/am/applets/applet_mii_edit_types.h" 24#include "core/hle/service/am/applets/applet_mii_edit_types.h"
25#include "core/hle/service/am/applets/applet_profile_select.h" 25#include "core/hle/service/am/applets/applet_profile_select.h"
26#include "core/hle/service/am/applets/applet_software_keyboard_types.h"
26#include "core/hle/service/am/applets/applet_web_browser.h" 27#include "core/hle/service/am/applets/applet_web_browser.h"
27#include "core/hle/service/am/applets/applets.h" 28#include "core/hle/service/am/applets/applets.h"
28#include "core/hle/service/am/idle.h" 29#include "core/hle/service/am/idle.h"
@@ -31,6 +32,7 @@
31#include "core/hle/service/apm/apm_controller.h" 32#include "core/hle/service/apm/apm_controller.h"
32#include "core/hle/service/apm/apm_interface.h" 33#include "core/hle/service/apm/apm_interface.h"
33#include "core/hle/service/bcat/backend/backend.h" 34#include "core/hle/service/bcat/backend/backend.h"
35#include "core/hle/service/caps/caps_su.h"
34#include "core/hle/service/caps/caps_types.h" 36#include "core/hle/service/caps/caps_types.h"
35#include "core/hle/service/filesystem/filesystem.h" 37#include "core/hle/service/filesystem/filesystem.h"
36#include "core/hle/service/ipc_helpers.h" 38#include "core/hle/service/ipc_helpers.h"
@@ -702,9 +704,17 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& c
702void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { 704void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) {
703 IPC::RequestParser rp{ctx}; 705 IPC::RequestParser rp{ctx};
704 706
705 const auto album_report_option = rp.PopEnum<Capture::AlbumReportOption>(); 707 const auto report_option = rp.PopEnum<Capture::AlbumReportOption>();
706 708
707 LOG_WARNING(Service_AM, "(STUBBED) called. album_report_option={}", album_report_option); 709 LOG_INFO(Service_AM, "called, report_option={}", report_option);
710
711 const auto screenshot_service =
712 system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>(
713 "caps:su");
714
715 if (screenshot_service) {
716 screenshot_service->CaptureAndSaveScreenshot(report_option);
717 }
708 718
709 IPC::ResponseBuilder rb{ctx, 2}; 719 IPC::ResponseBuilder rb{ctx, 2};
710 rb.Push(ResultSuccess); 720 rb.Push(ResultSuccess);
@@ -796,7 +806,9 @@ ILockAccessor::ILockAccessor(Core::System& system_)
796 lock_event = service_context.CreateEvent("ILockAccessor::LockEvent"); 806 lock_event = service_context.CreateEvent("ILockAccessor::LockEvent");
797} 807}
798 808
799ILockAccessor::~ILockAccessor() = default; 809ILockAccessor::~ILockAccessor() {
810 service_context.CloseEvent(lock_event);
811};
800 812
801void ILockAccessor::TryLock(HLERequestContext& ctx) { 813void ILockAccessor::TryLock(HLERequestContext& ctx) {
802 IPC::RequestParser rp{ctx}; 814 IPC::RequestParser rp{ctx};
@@ -909,7 +921,9 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
909 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); 921 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
910} 922}
911 923
912ICommonStateGetter::~ICommonStateGetter() = default; 924ICommonStateGetter::~ICommonStateGetter() {
925 service_context.CloseEvent(sleep_lock_event);
926};
913 927
914void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { 928void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) {
915 LOG_DEBUG(Service_AM, "called"); 929 LOG_DEBUG(Service_AM, "called");
@@ -1558,7 +1572,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
1558 {16, nullptr, "GetMainAppletStorageId"}, 1572 {16, nullptr, "GetMainAppletStorageId"},
1559 {17, nullptr, "GetCallerAppletIdentityInfoStack"}, 1573 {17, nullptr, "GetCallerAppletIdentityInfoStack"},
1560 {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, 1574 {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"},
1561 {19, nullptr, "GetDesirableKeyboardLayout"}, 1575 {19, &ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout, "GetDesirableKeyboardLayout"},
1562 {20, nullptr, "PopExtraStorage"}, 1576 {20, nullptr, "PopExtraStorage"},
1563 {25, nullptr, "GetPopExtraStorageEvent"}, 1577 {25, nullptr, "GetPopExtraStorageEvent"},
1564 {30, nullptr, "UnpopInData"}, 1578 {30, nullptr, "UnpopInData"},
@@ -1577,7 +1591,7 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
1577 {120, nullptr, "GetLaunchStorageInfoForDebug"}, 1591 {120, nullptr, "GetLaunchStorageInfoForDebug"},
1578 {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, 1592 {130, nullptr, "GetGpuErrorDetectedSystemEvent"},
1579 {140, nullptr, "SetApplicationMemoryReservation"}, 1593 {140, nullptr, "SetApplicationMemoryReservation"},
1580 {150, nullptr, "ShouldSetGpuTimeSliceManually"}, 1594 {150, &ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually, "ShouldSetGpuTimeSliceManually"},
1581 }; 1595 };
1582 // clang-format on 1596 // clang-format on
1583 RegisterHandlers(functions); 1597 RegisterHandlers(functions);
@@ -1592,6 +1606,9 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
1592 case Applets::AppletId::PhotoViewer: 1606 case Applets::AppletId::PhotoViewer:
1593 PushInShowAlbum(); 1607 PushInShowAlbum();
1594 break; 1608 break;
1609 case Applets::AppletId::SoftwareKeyboard:
1610 PushInShowSoftwareKeyboard();
1611 break;
1595 default: 1612 default:
1596 break; 1613 break;
1597 } 1614 }
@@ -1668,6 +1685,14 @@ void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext&
1668 rb.PushRaw(applet_info); 1685 rb.PushRaw(applet_info);
1669} 1686}
1670 1687
1688void ILibraryAppletSelfAccessor::GetDesirableKeyboardLayout(HLERequestContext& ctx) {
1689 LOG_WARNING(Service_AM, "(STUBBED) called");
1690
1691 IPC::ResponseBuilder rb{ctx, 3};
1692 rb.Push(ResultSuccess);
1693 rb.Push<u32>(0);
1694}
1695
1671void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { 1696void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) {
1672 const Service::Account::ProfileManager manager{}; 1697 const Service::Account::ProfileManager manager{};
1673 bool is_empty{true}; 1698 bool is_empty{true};
@@ -1687,6 +1712,14 @@ void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext&
1687 rb.Push(user_count); 1712 rb.Push(user_count);
1688} 1713}
1689 1714
1715void ILibraryAppletSelfAccessor::ShouldSetGpuTimeSliceManually(HLERequestContext& ctx) {
1716 LOG_WARNING(Service_AM, "(STUBBED) called");
1717
1718 IPC::ResponseBuilder rb{ctx, 2};
1719 rb.Push(ResultSuccess);
1720 rb.Push<u8>(0);
1721}
1722
1690void ILibraryAppletSelfAccessor::PushInShowAlbum() { 1723void ILibraryAppletSelfAccessor::PushInShowAlbum() {
1691 const Applets::CommonArguments arguments{ 1724 const Applets::CommonArguments arguments{
1692 .arguments_version = Applets::CommonArgumentVersion::Version3, 1725 .arguments_version = Applets::CommonArgumentVersion::Version3,
@@ -1755,6 +1788,61 @@ void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
1755 queue_data.emplace_back(std::move(argument_data)); 1788 queue_data.emplace_back(std::move(argument_data));
1756} 1789}
1757 1790
1791void ILibraryAppletSelfAccessor::PushInShowSoftwareKeyboard() {
1792 const Applets::CommonArguments arguments{
1793 .arguments_version = Applets::CommonArgumentVersion::Version3,
1794 .size = Applets::CommonArgumentSize::Version3,
1795 .library_version = static_cast<u32>(Applets::SwkbdAppletVersion::Version524301),
1796 .theme_color = Applets::ThemeColor::BasicBlack,
1797 .play_startup_sound = true,
1798 .system_tick = system.CoreTiming().GetClockTicks(),
1799 };
1800
1801 std::vector<char16_t> initial_string(0);
1802
1803 const Applets::SwkbdConfigCommon swkbd_config{
1804 .type = Applets::SwkbdType::Qwerty,
1805 .ok_text{},
1806 .left_optional_symbol_key{},
1807 .right_optional_symbol_key{},
1808 .use_prediction = false,
1809 .key_disable_flags{},
1810 .initial_cursor_position = Applets::SwkbdInitialCursorPosition::Start,
1811 .header_text{},
1812 .sub_text{},
1813 .guide_text{},
1814 .max_text_length = 500,
1815 .min_text_length = 0,
1816 .password_mode = Applets::SwkbdPasswordMode::Disabled,
1817 .text_draw_type = Applets::SwkbdTextDrawType::Box,
1818 .enable_return_button = true,
1819 .use_utf8 = false,
1820 .use_blur_background = true,
1821 .initial_string_offset{},
1822 .initial_string_length = static_cast<u32>(initial_string.size()),
1823 .user_dictionary_offset{},
1824 .user_dictionary_entries{},
1825 .use_text_check = false,
1826 };
1827
1828 Applets::SwkbdConfigNew swkbd_config_new{};
1829
1830 std::vector<u8> argument_data(sizeof(arguments));
1831 std::vector<u8> swkbd_data(sizeof(swkbd_config) + sizeof(swkbd_config_new));
1832 std::vector<u8> work_buffer(swkbd_config.initial_string_length * sizeof(char16_t));
1833
1834 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
1835 std::memcpy(swkbd_data.data(), &swkbd_config, sizeof(swkbd_config));
1836 std::memcpy(swkbd_data.data() + sizeof(swkbd_config), &swkbd_config_new,
1837 sizeof(Applets::SwkbdConfigNew));
1838 std::memcpy(work_buffer.data(), initial_string.data(),
1839 swkbd_config.initial_string_length * sizeof(char16_t));
1840
1841 queue_data.emplace_back(std::move(argument_data));
1842 queue_data.emplace_back(std::move(swkbd_data));
1843 queue_data.emplace_back(std::move(work_buffer));
1844}
1845
1758IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_) 1846IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_)
1759 : ServiceFramework{system_, "IAppletCommonFunctions"} { 1847 : ServiceFramework{system_, "IAppletCommonFunctions"} {
1760 // clang-format off 1848 // clang-format off
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 64b3f3fe2..8f8cb8a9e 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -347,11 +347,14 @@ private:
347 void GetLibraryAppletInfo(HLERequestContext& ctx); 347 void GetLibraryAppletInfo(HLERequestContext& ctx);
348 void ExitProcessAndReturn(HLERequestContext& ctx); 348 void ExitProcessAndReturn(HLERequestContext& ctx);
349 void GetCallerAppletIdentityInfo(HLERequestContext& ctx); 349 void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
350 void GetDesirableKeyboardLayout(HLERequestContext& ctx);
350 void GetMainAppletAvailableUsers(HLERequestContext& ctx); 351 void GetMainAppletAvailableUsers(HLERequestContext& ctx);
352 void ShouldSetGpuTimeSliceManually(HLERequestContext& ctx);
351 353
352 void PushInShowAlbum(); 354 void PushInShowAlbum();
353 void PushInShowCabinetData(); 355 void PushInShowCabinetData();
354 void PushInShowMiiEditData(); 356 void PushInShowMiiEditData();
357 void PushInShowSoftwareKeyboard();
355 358
356 std::deque<std::vector<u8>> queue_data; 359 std::deque<std::vector<u8>> queue_data;
357}; 360};
diff --git a/src/core/hle/service/am/applets/applet_cabinet.cpp b/src/core/hle/service/am/applets/applet_cabinet.cpp
index 19ed184e8..b379dadeb 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.cpp
+++ b/src/core/hle/service/am/applets/applet_cabinet.cpp
@@ -25,7 +25,9 @@ Cabinet::Cabinet(Core::System& system_, LibraryAppletMode applet_mode_,
25 service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent"); 25 service_context.CreateEvent("CabinetApplet:AvailabilityChangeEvent");
26} 26}
27 27
28Cabinet::~Cabinet() = default; 28Cabinet::~Cabinet() {
29 service_context.CloseEvent(availability_change_event);
30};
29 31
30void Cabinet::Initialize() { 32void Cabinet::Initialize() {
31 Applet::Initialize(); 33 Applet::Initialize();
diff --git a/src/core/hle/service/am/applets/applet_web_browser.cpp b/src/core/hle/service/am/applets/applet_web_browser.cpp
index 1c9a1dc29..b0ea2b381 100644
--- a/src/core/hle/service/am/applets/applet_web_browser.cpp
+++ b/src/core/hle/service/am/applets/applet_web_browser.cpp
@@ -330,8 +330,7 @@ void WebBrowser::ExtractOfflineRomFS() {
330 LOG_DEBUG(Service_AM, "Extracting RomFS to {}", 330 LOG_DEBUG(Service_AM, "Extracting RomFS to {}",
331 Common::FS::PathToUTF8String(offline_cache_dir)); 331 Common::FS::PathToUTF8String(offline_cache_dir));
332 332
333 const auto extracted_romfs_dir = 333 const auto extracted_romfs_dir = FileSys::ExtractRomFS(offline_romfs);
334 FileSys::ExtractRomFS(offline_romfs, FileSys::RomFSExtractionType::SingleDiscard);
335 334
336 const auto temp_dir = system.GetFilesystem()->CreateDirectory( 335 const auto temp_dir = system.GetFilesystem()->CreateDirectory(
337 Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite); 336 Common::FS::PathToUTF8String(offline_cache_dir), FileSys::Mode::ReadWrite);
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index f02bbc450..0bf2598b7 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -69,6 +69,30 @@ enum class AppletId : u32 {
69 MyPage = 0x1A, 69 MyPage = 0x1A,
70}; 70};
71 71
72enum class AppletProgramId : u64 {
73 QLaunch = 0x0100000000001000ull,
74 Auth = 0x0100000000001001ull,
75 Cabinet = 0x0100000000001002ull,
76 Controller = 0x0100000000001003ull,
77 DataErase = 0x0100000000001004ull,
78 Error = 0x0100000000001005ull,
79 NetConnect = 0x0100000000001006ull,
80 ProfileSelect = 0x0100000000001007ull,
81 SoftwareKeyboard = 0x0100000000001008ull,
82 MiiEdit = 0x0100000000001009ull,
83 Web = 0x010000000000100Aull,
84 Shop = 0x010000000000100Bull,
85 OverlayDisplay = 0x010000000000100Cull,
86 PhotoViewer = 0x010000000000100Dull,
87 Settings = 0x010000000000100Eull,
88 OfflineWeb = 0x010000000000100Full,
89 LoginShare = 0x0100000000001010ull,
90 WebAuth = 0x0100000000001011ull,
91 Starter = 0x0100000000001012ull,
92 MyPage = 0x0100000000001013ull,
93 MaxProgramId = 0x0100000000001FFFull,
94};
95
72enum class LibraryAppletMode : u32 { 96enum class LibraryAppletMode : u32 {
73 AllForeground = 0, 97 AllForeground = 0,
74 Background = 1, 98 Background = 1,
diff --git a/src/core/hle/service/caps/caps_manager.cpp b/src/core/hle/service/caps/caps_manager.cpp
index 9c9454b99..96b225d5f 100644
--- a/src/core/hle/service/caps/caps_manager.cpp
+++ b/src/core/hle/service/caps/caps_manager.cpp
@@ -2,13 +2,11 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <sstream> 4#include <sstream>
5#include <stb_image.h>
6#include <stb_image_resize.h>
7#include <stb_image_write.h>
8 5
9#include "common/fs/file.h" 6#include "common/fs/file.h"
10#include "common/fs/path_util.h" 7#include "common/fs/path_util.h"
11#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "common/stb.h"
12#include "core/core.h" 10#include "core/core.h"
13#include "core/hle/service/caps/caps_manager.h" 11#include "core/hle/service/caps/caps_manager.h"
14#include "core/hle/service/caps/caps_result.h" 12#include "core/hle/service/caps/caps_result.h"
@@ -230,12 +228,14 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail(
230 228
231Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, 229Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
232 const ScreenShotAttribute& attribute, 230 const ScreenShotAttribute& attribute,
233 std::span<const u8> image_data, u64 aruid) { 231 AlbumReportOption report_option, std::span<const u8> image_data,
234 return SaveScreenShot(out_entry, attribute, {}, image_data, aruid); 232 u64 aruid) {
233 return SaveScreenShot(out_entry, attribute, report_option, {}, image_data, aruid);
235} 234}
236 235
237Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, 236Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
238 const ScreenShotAttribute& attribute, 237 const ScreenShotAttribute& attribute,
238 AlbumReportOption report_option,
239 const ApplicationData& app_data, std::span<const u8> image_data, 239 const ApplicationData& app_data, std::span<const u8> image_data,
240 u64 aruid) { 240 u64 aruid) {
241 const u64 title_id = system.GetApplicationProcessProgramID(); 241 const u64 title_id = system.GetApplicationProcessProgramID();
@@ -409,6 +409,16 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p
409 return ResultSuccess; 409 return ResultSuccess;
410} 410}
411 411
412void AlbumManager::FlipVerticallyOnWrite(bool flip) {
413 stbi_flip_vertically_on_write(flip);
414}
415
416static void PNGToMemory(void* context, void* data, int len) {
417 std::vector<u8>* png_image = static_cast<std::vector<u8>*>(context);
418 unsigned char* png = static_cast<unsigned char*>(data);
419 png_image->insert(png_image->end(), png, png + len);
420}
421
412Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, 422Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image,
413 u64 title_id, const AlbumFileDateTime& date) const { 423 u64 title_id, const AlbumFileDateTime& date) const {
414 const auto screenshot_path = 424 const auto screenshot_path =
@@ -422,16 +432,12 @@ Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const
422 const Common::FS::IOFile db_file{file_path, Common::FS::FileAccessMode::Write, 432 const Common::FS::IOFile db_file{file_path, Common::FS::FileAccessMode::Write,
423 Common::FS::FileType::BinaryFile}; 433 Common::FS::FileType::BinaryFile};
424 434
425 s32 len; 435 std::vector<u8> png_image;
426 const u8* png = stbi_write_png_to_mem(image.data(), 0, 1280, 720, STBI_rgb_alpha, &len); 436 if (!stbi_write_png_to_func(PNGToMemory, &png_image, 1280, 720, STBI_rgb_alpha, image.data(),
427 437 0)) {
428 if (!png) {
429 return ResultFileCountLimit; 438 return ResultFileCountLimit;
430 } 439 }
431 440
432 std::vector<u8> png_image(len);
433 std::memcpy(png_image.data(), png, len);
434
435 if (db_file.Write(png_image) != png_image.size()) { 441 if (db_file.Write(png_image) != png_image.size()) {
436 return ResultFileCountLimit; 442 return ResultFileCountLimit;
437 } 443 }
diff --git a/src/core/hle/service/caps/caps_manager.h b/src/core/hle/service/caps/caps_manager.h
index 44d85117f..e20c70c7b 100644
--- a/src/core/hle/service/caps/caps_manager.h
+++ b/src/core/hle/service/caps/caps_manager.h
@@ -59,14 +59,17 @@ public:
59 const ScreenShotDecodeOption& decoder_options) const; 59 const ScreenShotDecodeOption& decoder_options) const;
60 60
61 Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, 61 Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
62 std::span<const u8> image_data, u64 aruid); 62 AlbumReportOption report_option, std::span<const u8> image_data,
63 Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
64 const ApplicationData& app_data, std::span<const u8> image_data,
65 u64 aruid); 63 u64 aruid);
64 Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
65 AlbumReportOption report_option, const ApplicationData& app_data,
66 std::span<const u8> image_data, u64 aruid);
66 Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry, 67 Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
67 const ScreenShotAttribute& attribute, const AlbumFileId& file_id, 68 const ScreenShotAttribute& attribute, const AlbumFileId& file_id,
68 std::span<const u8> image_data); 69 std::span<const u8> image_data);
69 70
71 void FlipVerticallyOnWrite(bool flip);
72
70private: 73private:
71 static constexpr std::size_t NandAlbumFileLimit = 1000; 74 static constexpr std::size_t NandAlbumFileLimit = 1000;
72 static constexpr std::size_t SdAlbumFileLimit = 10000; 75 static constexpr std::size_t SdAlbumFileLimit = 10000;
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp
index 1ba2b7972..eab023568 100644
--- a/src/core/hle/service/caps/caps_ss.cpp
+++ b/src/core/hle/service/caps/caps_ss.cpp
@@ -34,7 +34,7 @@ void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) {
34 IPC::RequestParser rp{ctx}; 34 IPC::RequestParser rp{ctx};
35 struct Parameters { 35 struct Parameters {
36 ScreenShotAttribute attribute{}; 36 ScreenShotAttribute attribute{};
37 u32 report_option{}; 37 AlbumReportOption report_option{};
38 INSERT_PADDING_BYTES(0x4); 38 INSERT_PADDING_BYTES(0x4);
39 u64 applet_resource_user_id{}; 39 u64 applet_resource_user_id{};
40 }; 40 };
@@ -49,13 +49,16 @@ void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) {
49 parameters.applet_resource_user_id); 49 parameters.applet_resource_user_id);
50 50
51 ApplicationAlbumEntry entry{}; 51 ApplicationAlbumEntry entry{};
52 const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer, 52 manager->FlipVerticallyOnWrite(false);
53 parameters.applet_resource_user_id); 53 const auto result =
54 manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option,
55 image_data_buffer, parameters.applet_resource_user_id);
54 56
55 IPC::ResponseBuilder rb{ctx, 10}; 57 IPC::ResponseBuilder rb{ctx, 10};
56 rb.Push(result); 58 rb.Push(result);
57 rb.PushRaw(entry); 59 rb.PushRaw(entry);
58} 60}
61
59void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) { 62void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) {
60 IPC::RequestParser rp{ctx}; 63 IPC::RequestParser rp{ctx};
61 struct Parameters { 64 struct Parameters {
@@ -83,6 +86,7 @@ void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) {
83 image_data_buffer.size(), thumbnail_image_data_buffer.size()); 86 image_data_buffer.size(), thumbnail_image_data_buffer.size());
84 87
85 ApplicationAlbumEntry entry{}; 88 ApplicationAlbumEntry entry{};
89 manager->FlipVerticallyOnWrite(false);
86 const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute, 90 const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute,
87 parameters.file_id, image_data_buffer); 91 parameters.file_id, image_data_buffer);
88 92
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp
index e85625ee4..296b07b00 100644
--- a/src/core/hle/service/caps/caps_su.cpp
+++ b/src/core/hle/service/caps/caps_su.cpp
@@ -2,10 +2,12 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/logging/log.h" 4#include "common/logging/log.h"
5#include "core/core.h"
5#include "core/hle/service/caps/caps_manager.h" 6#include "core/hle/service/caps/caps_manager.h"
6#include "core/hle/service/caps/caps_su.h" 7#include "core/hle/service/caps/caps_su.h"
7#include "core/hle/service/caps/caps_types.h" 8#include "core/hle/service/caps/caps_types.h"
8#include "core/hle/service/ipc_helpers.h" 9#include "core/hle/service/ipc_helpers.h"
10#include "video_core/renderer_base.h"
9 11
10namespace Service::Capture { 12namespace Service::Capture {
11 13
@@ -58,8 +60,10 @@ void IScreenShotApplicationService::SaveScreenShotEx0(HLERequestContext& ctx) {
58 parameters.applet_resource_user_id); 60 parameters.applet_resource_user_id);
59 61
60 ApplicationAlbumEntry entry{}; 62 ApplicationAlbumEntry entry{};
61 const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer, 63 manager->FlipVerticallyOnWrite(false);
62 parameters.applet_resource_user_id); 64 const auto result =
65 manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option,
66 image_data_buffer, parameters.applet_resource_user_id);
63 67
64 IPC::ResponseBuilder rb{ctx, 10}; 68 IPC::ResponseBuilder rb{ctx, 10};
65 rb.Push(result); 69 rb.Push(result);
@@ -88,13 +92,43 @@ void IScreenShotApplicationService::SaveScreenShotEx1(HLERequestContext& ctx) {
88 ApplicationAlbumEntry entry{}; 92 ApplicationAlbumEntry entry{};
89 ApplicationData app_data{}; 93 ApplicationData app_data{};
90 std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData)); 94 std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData));
95 manager->FlipVerticallyOnWrite(false);
91 const auto result = 96 const auto result =
92 manager->SaveScreenShot(entry, parameters.attribute, app_data, image_data_buffer, 97 manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option, app_data,
93 parameters.applet_resource_user_id); 98 image_data_buffer, parameters.applet_resource_user_id);
94 99
95 IPC::ResponseBuilder rb{ctx, 10}; 100 IPC::ResponseBuilder rb{ctx, 10};
96 rb.Push(result); 101 rb.Push(result);
97 rb.PushRaw(entry); 102 rb.PushRaw(entry);
98} 103}
99 104
105void IScreenShotApplicationService::CaptureAndSaveScreenshot(AlbumReportOption report_option) {
106 auto& renderer = system.Renderer();
107 Layout::FramebufferLayout layout =
108 Layout::DefaultFrameLayout(screenshot_width, screenshot_height);
109
110 const Capture::ScreenShotAttribute attribute{
111 .unknown_0{},
112 .orientation = Capture::AlbumImageOrientation::None,
113 .unknown_1{},
114 .unknown_2{},
115 };
116
117 renderer.RequestScreenshot(
118 image_data.data(),
119 [attribute, report_option, this](bool invert_y) {
120 // Convert from BGRA to RGBA
121 for (std::size_t i = 0; i < image_data.size(); i += bytes_per_pixel) {
122 const u8 temp = image_data[i];
123 image_data[i] = image_data[i + 2];
124 image_data[i + 2] = temp;
125 }
126
127 Capture::ApplicationAlbumEntry entry{};
128 manager->FlipVerticallyOnWrite(invert_y);
129 manager->SaveScreenShot(entry, attribute, report_option, image_data, {});
130 },
131 layout);
132}
133
100} // namespace Service::Capture 134} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h
index 89e71f506..21912e95f 100644
--- a/src/core/hle/service/caps/caps_su.h
+++ b/src/core/hle/service/caps/caps_su.h
@@ -10,6 +10,7 @@ class System;
10} 10}
11 11
12namespace Service::Capture { 12namespace Service::Capture {
13enum class AlbumReportOption : s32;
13class AlbumManager; 14class AlbumManager;
14 15
15class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> { 16class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> {
@@ -18,11 +19,19 @@ public:
18 std::shared_ptr<AlbumManager> album_manager); 19 std::shared_ptr<AlbumManager> album_manager);
19 ~IScreenShotApplicationService() override; 20 ~IScreenShotApplicationService() override;
20 21
22 void CaptureAndSaveScreenshot(AlbumReportOption report_option);
23
21private: 24private:
25 static constexpr std::size_t screenshot_width = 1280;
26 static constexpr std::size_t screenshot_height = 720;
27 static constexpr std::size_t bytes_per_pixel = 4;
28
22 void SetShimLibraryVersion(HLERequestContext& ctx); 29 void SetShimLibraryVersion(HLERequestContext& ctx);
23 void SaveScreenShotEx0(HLERequestContext& ctx); 30 void SaveScreenShotEx0(HLERequestContext& ctx);
24 void SaveScreenShotEx1(HLERequestContext& ctx); 31 void SaveScreenShotEx1(HLERequestContext& ctx);
25 32
33 std::array<u8, screenshot_width * screenshot_height * bytes_per_pixel> image_data;
34
26 std::shared_ptr<AlbumManager> manager; 35 std::shared_ptr<AlbumManager> manager;
27}; 36};
28 37
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index bc822f19e..21695bda2 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -1108,9 +1108,9 @@ Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
1108 shared_memory->sixaxis_dual_right_properties.raw = 0; 1108 shared_memory->sixaxis_dual_right_properties.raw = 0;
1109 shared_memory->sixaxis_left_properties.raw = 0; 1109 shared_memory->sixaxis_left_properties.raw = 0;
1110 shared_memory->sixaxis_right_properties.raw = 0; 1110 shared_memory->sixaxis_right_properties.raw = 0;
1111 shared_memory->battery_level_dual = 0; 1111 shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty;
1112 shared_memory->battery_level_left = 0; 1112 shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty;
1113 shared_memory->battery_level_right = 0; 1113 shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty;
1114 shared_memory->fullkey_color = { 1114 shared_memory->fullkey_color = {
1115 .attribute = ColorAttribute::NoController, 1115 .attribute = ColorAttribute::NoController,
1116 .fullkey = {}, 1116 .fullkey = {},
diff --git a/src/core/hle/service/hid/controllers/palma.cpp b/src/core/hle/service/hid/controllers/palma.cpp
index 14c67e454..73a2a2b91 100644
--- a/src/core/hle/service/hid/controllers/palma.cpp
+++ b/src/core/hle/service/hid/controllers/palma.cpp
@@ -19,7 +19,9 @@ Controller_Palma::Controller_Palma(Core::HID::HIDCore& hid_core_, u8* raw_shared
19 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent"); 19 operation_complete_event = service_context.CreateEvent("hid:PalmaOperationCompleteEvent");
20} 20}
21 21
22Controller_Palma::~Controller_Palma() = default; 22Controller_Palma::~Controller_Palma() {
23 service_context.CloseEvent(operation_complete_event);
24};
23 25
24void Controller_Palma::OnInit() {} 26void Controller_Palma::OnInit() {}
25 27
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 4d70006c1..1d4101be9 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1353,7 +1353,7 @@ void Hid::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx) {
1353void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) { 1353void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
1354 IPC::RequestParser rp{ctx}; 1354 IPC::RequestParser rp{ctx};
1355 struct Parameters { 1355 struct Parameters {
1356 bool unintended_home_button_input_protection; 1356 bool is_enabled;
1357 INSERT_PADDING_BYTES_NOINIT(3); 1357 INSERT_PADDING_BYTES_NOINIT(3);
1358 Core::HID::NpadIdType npad_id; 1358 Core::HID::NpadIdType npad_id;
1359 u64 applet_resource_user_id; 1359 u64 applet_resource_user_id;
@@ -1364,13 +1364,11 @@ void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
1364 1364
1365 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); 1365 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1366 const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled( 1366 const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
1367 parameters.unintended_home_button_input_protection, parameters.npad_id); 1367 parameters.is_enabled, parameters.npad_id);
1368 1368
1369 LOG_WARNING(Service_HID, 1369 LOG_DEBUG(Service_HID,
1370 "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," 1370 "(STUBBED) called, is_enabled={}, npad_id={}, applet_resource_user_id={}",
1371 "applet_resource_user_id={}", 1371 parameters.is_enabled, parameters.npad_id, parameters.applet_resource_user_id);
1372 parameters.unintended_home_button_input_protection, parameters.npad_id,
1373 parameters.applet_resource_user_id);
1374 1372
1375 IPC::ResponseBuilder rb{ctx, 2}; 1373 IPC::ResponseBuilder rb{ctx, 2};
1376 rb.Push(result); 1374 rb.Push(result);
@@ -2757,6 +2755,10 @@ public:
2757 joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent"); 2755 joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
2758 } 2756 }
2759 2757
2758 ~HidSys() {
2759 service_context.CloseEvent(joy_detach_event);
2760 };
2761
2760private: 2762private:
2761 void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) { 2763 void ApplyNpadSystemCommonPolicy(HLERequestContext& ctx) {
2762 LOG_WARNING(Service_HID, "called"); 2764 LOG_WARNING(Service_HID, "called");
diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.cpp b/src/core/hle/service/hid/hidbus/hidbus_base.cpp
index ee522c36e..8c44f93e8 100644
--- a/src/core/hle/service/hid/hidbus/hidbus_base.cpp
+++ b/src/core/hle/service/hid/hidbus/hidbus_base.cpp
@@ -13,7 +13,10 @@ HidbusBase::HidbusBase(Core::System& system_, KernelHelpers::ServiceContext& ser
13 : system(system_), service_context(service_context_) { 13 : system(system_), service_context(service_context_) {
14 send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent"); 14 send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent");
15} 15}
16HidbusBase::~HidbusBase() = default; 16
17HidbusBase::~HidbusBase() {
18 service_context.CloseEvent(send_command_async_event);
19};
17 20
18void HidbusBase::ActivateDevice() { 21void HidbusBase::ActivateDevice() {
19 if (is_activated) { 22 if (is_activated) {
diff --git a/src/core/hle/service/hid/ring_lifo.h b/src/core/hle/service/hid/ring_lifo.h
index 65eb7ea02..0816784e0 100644
--- a/src/core/hle/service/hid/ring_lifo.h
+++ b/src/core/hle/service/hid/ring_lifo.h
@@ -32,15 +32,15 @@ struct Lifo {
32 } 32 }
33 33
34 std::size_t GetPreviousEntryIndex() const { 34 std::size_t GetPreviousEntryIndex() const {
35 return static_cast<size_t>((buffer_tail + total_buffer_count - 1) % total_buffer_count); 35 return static_cast<size_t>((buffer_tail + max_buffer_size - 1) % max_buffer_size);
36 } 36 }
37 37
38 std::size_t GetNextEntryIndex() const { 38 std::size_t GetNextEntryIndex() const {
39 return static_cast<size_t>((buffer_tail + 1) % total_buffer_count); 39 return static_cast<size_t>((buffer_tail + 1) % max_buffer_size);
40 } 40 }
41 41
42 void WriteNextEntry(const State& new_state) { 42 void WriteNextEntry(const State& new_state) {
43 if (buffer_count < total_buffer_count - 1) { 43 if (buffer_count < static_cast<s64>(max_buffer_size) - 1) {
44 buffer_count++; 44 buffer_count++;
45 } 45 }
46 buffer_tail = GetNextEntryIndex(); 46 buffer_tail = GetNextEntryIndex();
diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp
index 6a313a03b..f51e63564 100644
--- a/src/core/hle/service/kernel_helpers.cpp
+++ b/src/core/hle/service/kernel_helpers.cpp
@@ -21,10 +21,8 @@ ServiceContext::ServiceContext(Core::System& system_, std::string name_)
21 21
22 // Create the process. 22 // Create the process.
23 process = Kernel::KProcess::Create(kernel); 23 process = Kernel::KProcess::Create(kernel);
24 ASSERT(Kernel::KProcess::Initialize(process, system_, std::move(name_), 24 ASSERT(R_SUCCEEDED(process->Initialize(Kernel::Svc::CreateProcessParameter{},
25 Kernel::KProcess::ProcessType::KernelInternal, 25 kernel.GetSystemResourceLimit(), false)));
26 kernel.GetSystemResourceLimit())
27 .IsSuccess());
28 26
29 // Register the process. 27 // Register the process.
30 Kernel::KProcess::Register(kernel, process); 28 Kernel::KProcess::Register(kernel, process);
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
index 2dbe29616..ed66f6f5b 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
@@ -41,7 +41,7 @@ bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk)
41s32 BufferQueueCore::GetMinUndequeuedBufferCountLocked(bool async) const { 41s32 BufferQueueCore::GetMinUndequeuedBufferCountLocked(bool async) const {
42 // If DequeueBuffer is allowed to error out, we don't have to add an extra buffer. 42 // If DequeueBuffer is allowed to error out, we don't have to add an extra buffer.
43 if (!use_async_buffer) { 43 if (!use_async_buffer) {
44 return max_acquired_buffer_count; 44 return 0;
45 } 45 }
46 46
47 if (dequeue_buffer_cannot_block || async) { 47 if (dequeue_buffer_cannot_block || async) {
@@ -52,7 +52,7 @@ s32 BufferQueueCore::GetMinUndequeuedBufferCountLocked(bool async) const {
52} 52}
53 53
54s32 BufferQueueCore::GetMinMaxBufferCountLocked(bool async) const { 54s32 BufferQueueCore::GetMinMaxBufferCountLocked(bool async) const {
55 return GetMinUndequeuedBufferCountLocked(async) + 1; 55 return GetMinUndequeuedBufferCountLocked(async);
56} 56}
57 57
58s32 BufferQueueCore::GetMaxBufferCountLocked(bool async) const { 58s32 BufferQueueCore::GetMaxBufferCountLocked(bool async) const {
@@ -61,7 +61,7 @@ s32 BufferQueueCore::GetMaxBufferCountLocked(bool async) const {
61 61
62 if (override_max_buffer_count != 0) { 62 if (override_max_buffer_count != 0) {
63 ASSERT(override_max_buffer_count >= min_buffer_count); 63 ASSERT(override_max_buffer_count >= min_buffer_count);
64 max_buffer_count = override_max_buffer_count; 64 return override_max_buffer_count;
65 } 65 }
66 66
67 // Any buffers that are dequeued by the producer or sitting in the queue waiting to be consumed 67 // Any buffers that are dequeued by the producer or sitting in the queue waiting to be consumed
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
index dc6917d5d..6e7a49658 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
@@ -134,7 +134,7 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, St
134 const s32 max_buffer_count = core->GetMaxBufferCountLocked(async); 134 const s32 max_buffer_count = core->GetMaxBufferCountLocked(async);
135 if (async && core->override_max_buffer_count) { 135 if (async && core->override_max_buffer_count) {
136 if (core->override_max_buffer_count < max_buffer_count) { 136 if (core->override_max_buffer_count < max_buffer_count) {
137 LOG_ERROR(Service_Nvnflinger, "async mode is invalid with buffer count override"); 137 *found = BufferQueueCore::INVALID_BUFFER_SLOT;
138 return Status::BadValue; 138 return Status::BadValue;
139 } 139 }
140 } 140 }
@@ -142,7 +142,8 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, St
142 // Free up any buffers that are in slots beyond the max buffer count 142 // Free up any buffers that are in slots beyond the max buffer count
143 for (s32 s = max_buffer_count; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) { 143 for (s32 s = max_buffer_count; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
144 ASSERT(slots[s].buffer_state == BufferState::Free); 144 ASSERT(slots[s].buffer_state == BufferState::Free);
145 if (slots[s].graphic_buffer != nullptr) { 145 if (slots[s].graphic_buffer != nullptr && slots[s].buffer_state == BufferState::Free &&
146 !slots[s].is_preallocated) {
146 core->FreeBufferLocked(s); 147 core->FreeBufferLocked(s);
147 *return_flags |= Status::ReleaseAllBuffers; 148 *return_flags |= Status::ReleaseAllBuffers;
148 } 149 }
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index a07c621d9..bebb45eae 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -66,7 +66,6 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
66 "ScreenComposition", 66 "ScreenComposition",
67 [this](std::uintptr_t, s64 time, 67 [this](std::uintptr_t, s64 time,
68 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { 68 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
69 { const auto lock_guard = Lock(); }
70 vsync_signal.Set(); 69 vsync_signal.Set();
71 return std::chrono::nanoseconds(GetNextTicks()); 70 return std::chrono::nanoseconds(GetNextTicks());
72 }); 71 });
@@ -99,6 +98,7 @@ Nvnflinger::~Nvnflinger() {
99 } 98 }
100 99
101 ShutdownLayers(); 100 ShutdownLayers();
101 vsync_thread = {};
102 102
103 if (nvdrv) { 103 if (nvdrv) {
104 nvdrv->Close(disp_fd); 104 nvdrv->Close(disp_fd);
@@ -106,6 +106,7 @@ Nvnflinger::~Nvnflinger() {
106} 106}
107 107
108void Nvnflinger::ShutdownLayers() { 108void Nvnflinger::ShutdownLayers() {
109 const auto lock_guard = Lock();
109 for (auto& display : displays) { 110 for (auto& display : displays) {
110 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { 111 for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
111 display.GetLayer(layer).Core().NotifyShutdown(); 112 display.GetLayer(layer).Core().NotifyShutdown();
@@ -229,16 +230,6 @@ VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) {
229 return display->FindLayer(layer_id); 230 return display->FindLayer(layer_id);
230} 231}
231 232
232const VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) const {
233 const auto* const display = FindDisplay(display_id);
234
235 if (display == nullptr) {
236 return nullptr;
237 }
238
239 return display->FindLayer(layer_id);
240}
241
242VI::Layer* Nvnflinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { 233VI::Layer* Nvnflinger::FindOrCreateLayer(u64 display_id, u64 layer_id) {
243 auto* const display = FindDisplay(display_id); 234 auto* const display = FindDisplay(display_id);
244 235
@@ -288,7 +279,6 @@ void Nvnflinger::Compose() {
288 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); 279 auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd);
289 ASSERT(nvdisp); 280 ASSERT(nvdisp);
290 281
291 guard->unlock();
292 Common::Rectangle<int> crop_rect{ 282 Common::Rectangle<int> crop_rect{
293 static_cast<int>(buffer.crop.Left()), static_cast<int>(buffer.crop.Top()), 283 static_cast<int>(buffer.crop.Left()), static_cast<int>(buffer.crop.Top()),
294 static_cast<int>(buffer.crop.Right()), static_cast<int>(buffer.crop.Bottom())}; 284 static_cast<int>(buffer.crop.Right()), static_cast<int>(buffer.crop.Bottom())};
@@ -299,7 +289,6 @@ void Nvnflinger::Compose() {
299 buffer.fence.fences, buffer.fence.num_fences); 289 buffer.fence.fences, buffer.fence.num_fences);
300 290
301 MicroProfileFlip(); 291 MicroProfileFlip();
302 guard->lock();
303 292
304 swap_interval = buffer.swap_interval; 293 swap_interval = buffer.swap_interval;
305 294
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index 14c783582..959d8b46b 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -117,9 +117,6 @@ private:
117 /// Finds the layer identified by the specified ID in the desired display. 117 /// Finds the layer identified by the specified ID in the desired display.
118 [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id); 118 [[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
119 119
120 /// Finds the layer identified by the specified ID in the desired display.
121 [[nodiscard]] const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const;
122
123 /// Finds the layer identified by the specified ID in the desired display, 120 /// Finds the layer identified by the specified ID in the desired display,
124 /// or creates the layer if it is not found. 121 /// or creates the layer if it is not found.
125 /// To be used when the system expects the specified ID to already exist. 122 /// To be used when the system expects the specified ID to already exist.
diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp
index 938330dd0..6a7fd72bc 100644
--- a/src/core/hle/service/pctl/pctl_module.cpp
+++ b/src/core/hle/service/pctl/pctl_module.cpp
@@ -141,6 +141,12 @@ public:
141 service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent"); 141 service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent");
142 } 142 }
143 143
144 ~IParentalControlService() {
145 service_context.CloseEvent(synchronization_event);
146 service_context.CloseEvent(unlinked_event);
147 service_context.CloseEvent(request_suspension_event);
148 };
149
144private: 150private:
145 bool CheckFreeCommunicationPermissionImpl() const { 151 bool CheckFreeCommunicationPermissionImpl() const {
146 if (states.temporary_unlocked) { 152 if (states.temporary_unlocked) {
diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp
index f9cf2dda3..d92499f05 100644
--- a/src/core/hle/service/pm/pm.cpp
+++ b/src/core/hle/service/pm/pm.cpp
@@ -37,7 +37,7 @@ std::optional<Kernel::KProcess*> SearchProcessList(
37void GetApplicationPidGeneric(HLERequestContext& ctx, 37void GetApplicationPidGeneric(HLERequestContext& ctx,
38 const std::vector<Kernel::KProcess*>& process_list) { 38 const std::vector<Kernel::KProcess*>& process_list) {
39 const auto process = SearchProcessList(process_list, [](const auto& proc) { 39 const auto process = SearchProcessList(process_list, [](const auto& proc) {
40 return proc->GetProcessId() == Kernel::KProcess::ProcessIDMin; 40 return proc->GetProcessId() == Kernel::KProcess::ProcessIdMin;
41 }); 41 });
42 42
43 IPC::ResponseBuilder rb{ctx, 4}; 43 IPC::ResponseBuilder rb{ctx, 4};
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 85849d5f3..dd652ca42 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -39,6 +39,18 @@ bool IsConnectionBased(Type type) {
39 } 39 }
40} 40}
41 41
42template <typename T>
43T GetValue(std::span<const u8> buffer) {
44 T t{};
45 std::memcpy(&t, buffer.data(), std::min(sizeof(T), buffer.size()));
46 return t;
47}
48
49template <typename T>
50void PutValue(std::span<u8> buffer, const T& t) {
51 std::memcpy(buffer.data(), &t, std::min(sizeof(T), buffer.size()));
52}
53
42} // Anonymous namespace 54} // Anonymous namespace
43 55
44void BSD::PollWork::Execute(BSD* bsd) { 56void BSD::PollWork::Execute(BSD* bsd) {
@@ -316,22 +328,12 @@ void BSD::SetSockOpt(HLERequestContext& ctx) {
316 const s32 fd = rp.Pop<s32>(); 328 const s32 fd = rp.Pop<s32>();
317 const u32 level = rp.Pop<u32>(); 329 const u32 level = rp.Pop<u32>();
318 const OptName optname = static_cast<OptName>(rp.Pop<u32>()); 330 const OptName optname = static_cast<OptName>(rp.Pop<u32>());
319 331 const auto optval = ctx.ReadBuffer();
320 const auto buffer = ctx.ReadBuffer();
321 const u8* optval = buffer.empty() ? nullptr : buffer.data();
322 size_t optlen = buffer.size();
323
324 std::array<u64, 2> values;
325 if ((optname == OptName::SNDTIMEO || optname == OptName::RCVTIMEO) && buffer.size() == 8) {
326 std::memcpy(values.data(), buffer.data(), sizeof(values));
327 optlen = sizeof(values);
328 optval = reinterpret_cast<const u8*>(values.data());
329 }
330 332
331 LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level, 333 LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level,
332 static_cast<u32>(optname), optlen); 334 static_cast<u32>(optname), optval.size());
333 335
334 BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval)); 336 BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
335} 337}
336 338
337void BSD::Shutdown(HLERequestContext& ctx) { 339void BSD::Shutdown(HLERequestContext& ctx) {
@@ -521,18 +523,19 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco
521 523
522std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, 524std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
523 s32 nfds, s32 timeout) { 525 s32 nfds, s32 timeout) {
524 if (write_buffer.size() < nfds * sizeof(PollFD)) { 526 if (nfds <= 0) {
525 return {-1, Errno::INVAL};
526 }
527
528 if (nfds == 0) {
529 // When no entries are provided, -1 is returned with errno zero 527 // When no entries are provided, -1 is returned with errno zero
530 return {-1, Errno::SUCCESS}; 528 return {-1, Errno::SUCCESS};
531 } 529 }
530 if (read_buffer.size() < nfds * sizeof(PollFD)) {
531 return {-1, Errno::INVAL};
532 }
533 if (write_buffer.size() < nfds * sizeof(PollFD)) {
534 return {-1, Errno::INVAL};
535 }
532 536
533 const size_t length = std::min(read_buffer.size(), write_buffer.size());
534 std::vector<PollFD> fds(nfds); 537 std::vector<PollFD> fds(nfds);
535 std::memcpy(fds.data(), read_buffer.data(), length); 538 std::memcpy(fds.data(), read_buffer.data(), nfds * sizeof(PollFD));
536 539
537 if (timeout >= 0) { 540 if (timeout >= 0) {
538 const s64 seconds = timeout / 1000; 541 const s64 seconds = timeout / 1000;
@@ -580,7 +583,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
580 for (size_t i = 0; i < num; ++i) { 583 for (size_t i = 0; i < num; ++i) {
581 fds[i].revents = Translate(host_pollfds[i].revents); 584 fds[i].revents = Translate(host_pollfds[i].revents);
582 } 585 }
583 std::memcpy(write_buffer.data(), fds.data(), length); 586 std::memcpy(write_buffer.data(), fds.data(), nfds * sizeof(PollFD));
584 587
585 return Translate(result); 588 return Translate(result);
586} 589}
@@ -608,8 +611,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
608 new_descriptor.is_connection_based = descriptor.is_connection_based; 611 new_descriptor.is_connection_based = descriptor.is_connection_based;
609 612
610 const SockAddrIn guest_addr_in = Translate(result.sockaddr_in); 613 const SockAddrIn guest_addr_in = Translate(result.sockaddr_in);
611 const size_t length = std::min(sizeof(guest_addr_in), write_buffer.size()); 614 PutValue(write_buffer, guest_addr_in);
612 std::memcpy(write_buffer.data(), &guest_addr_in, length);
613 615
614 return {new_fd, Errno::SUCCESS}; 616 return {new_fd, Errno::SUCCESS};
615} 617}
@@ -619,8 +621,7 @@ Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
619 return Errno::BADF; 621 return Errno::BADF;
620 } 622 }
621 ASSERT(addr.size() == sizeof(SockAddrIn)); 623 ASSERT(addr.size() == sizeof(SockAddrIn));
622 SockAddrIn addr_in; 624 auto addr_in = GetValue<SockAddrIn>(addr);
623 std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
624 625
625 return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); 626 return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
626} 627}
@@ -631,8 +632,7 @@ Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
631 } 632 }
632 633
633 UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn)); 634 UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn));
634 SockAddrIn addr_in; 635 auto addr_in = GetValue<SockAddrIn>(addr);
635 std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
636 636
637 return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in))); 637 return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
638} 638}
@@ -650,7 +650,7 @@ Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
650 650
651 ASSERT(write_buffer.size() >= sizeof(guest_addrin)); 651 ASSERT(write_buffer.size() >= sizeof(guest_addrin));
652 write_buffer.resize(sizeof(guest_addrin)); 652 write_buffer.resize(sizeof(guest_addrin));
653 std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); 653 PutValue(write_buffer, guest_addrin);
654 return Translate(bsd_errno); 654 return Translate(bsd_errno);
655} 655}
656 656
@@ -667,7 +667,7 @@ Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
667 667
668 ASSERT(write_buffer.size() >= sizeof(guest_addrin)); 668 ASSERT(write_buffer.size() >= sizeof(guest_addrin));
669 write_buffer.resize(sizeof(guest_addrin)); 669 write_buffer.resize(sizeof(guest_addrin));
670 std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); 670 PutValue(write_buffer, guest_addrin);
671 return Translate(bsd_errno); 671 return Translate(bsd_errno);
672} 672}
673 673
@@ -725,7 +725,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
725 optval.size() == sizeof(Errno), { return Errno::INVAL; }, 725 optval.size() == sizeof(Errno), { return Errno::INVAL; },
726 "Incorrect getsockopt option size"); 726 "Incorrect getsockopt option size");
727 optval.resize(sizeof(Errno)); 727 optval.resize(sizeof(Errno));
728 memcpy(optval.data(), &translated_pending_err, sizeof(Errno)); 728 PutValue(optval, translated_pending_err);
729 } 729 }
730 return Translate(getsockopt_err); 730 return Translate(getsockopt_err);
731 } 731 }
@@ -735,7 +735,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
735 } 735 }
736} 736}
737 737
738Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) { 738Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval) {
739 if (!IsFileDescriptorValid(fd)) { 739 if (!IsFileDescriptorValid(fd)) {
740 return Errno::BADF; 740 return Errno::BADF;
741 } 741 }
@@ -748,17 +748,15 @@ Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, con
748 Network::SocketBase* const socket = file_descriptors[fd]->socket.get(); 748 Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
749 749
750 if (optname == OptName::LINGER) { 750 if (optname == OptName::LINGER) {
751 ASSERT(optlen == sizeof(Linger)); 751 ASSERT(optval.size() == sizeof(Linger));
752 Linger linger; 752 auto linger = GetValue<Linger>(optval);
753 std::memcpy(&linger, optval, sizeof(linger));
754 ASSERT(linger.onoff == 0 || linger.onoff == 1); 753 ASSERT(linger.onoff == 0 || linger.onoff == 1);
755 754
756 return Translate(socket->SetLinger(linger.onoff != 0, linger.linger)); 755 return Translate(socket->SetLinger(linger.onoff != 0, linger.linger));
757 } 756 }
758 757
759 ASSERT(optlen == sizeof(u32)); 758 ASSERT(optval.size() == sizeof(u32));
760 u32 value; 759 auto value = GetValue<u32>(optval);
761 std::memcpy(&value, optval, sizeof(value));
762 760
763 switch (optname) { 761 switch (optname) {
764 case OptName::REUSEADDR: 762 case OptName::REUSEADDR:
@@ -862,7 +860,7 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess
862 } else { 860 } else {
863 ASSERT(addr.size() == sizeof(SockAddrIn)); 861 ASSERT(addr.size() == sizeof(SockAddrIn));
864 const SockAddrIn result = Translate(addr_in); 862 const SockAddrIn result = Translate(addr_in);
865 std::memcpy(addr.data(), &result, sizeof(result)); 863 PutValue(addr, result);
866 } 864 }
867 } 865 }
868 866
@@ -886,8 +884,7 @@ std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> mes
886 Network::SockAddrIn* p_addr_in = nullptr; 884 Network::SockAddrIn* p_addr_in = nullptr;
887 if (!addr.empty()) { 885 if (!addr.empty()) {
888 ASSERT(addr.size() == sizeof(SockAddrIn)); 886 ASSERT(addr.size() == sizeof(SockAddrIn));
889 SockAddrIn guest_addr_in; 887 auto guest_addr_in = GetValue<SockAddrIn>(addr);
890 std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in));
891 addr_in = Translate(guest_addr_in); 888 addr_in = Translate(guest_addr_in);
892 p_addr_in = &addr_in; 889 p_addr_in = &addr_in;
893 } 890 }
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index 161f22b9b..4f69d382c 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -163,7 +163,7 @@ private:
163 Errno ListenImpl(s32 fd, s32 backlog); 163 Errno ListenImpl(s32 fd, s32 backlog);
164 std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg); 164 std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg);
165 Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval); 165 Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval);
166 Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval); 166 Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval);
167 Errno ShutdownImpl(s32 fd, s32 how); 167 Errno ShutdownImpl(s32 fd, s32 how);
168 std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); 168 std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
169 std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, 169 std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp
index ed875d444..5d168cbc1 100644
--- a/src/core/reporter.cpp
+++ b/src/core/reporter.cpp
@@ -116,7 +116,7 @@ json GetProcessorStateDataAuto(Core::System& system) {
116 Core::ARM_Interface::ThreadContext64 context{}; 116 Core::ARM_Interface::ThreadContext64 context{};
117 arm.SaveContext(context); 117 arm.SaveContext(context);
118 118
119 return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32", 119 return GetProcessorStateData(process->Is64Bit() ? "AArch64" : "AArch32",
120 GetInteger(process->GetEntryPoint()), context.sp, context.pc, 120 GetInteger(process->GetEntryPoint()), context.sp, context.pc,
121 context.pstate, context.cpu_registers); 121 context.pstate, context.cpu_registers);
122} 122}
diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp
index cf51f3481..c9f903213 100644
--- a/src/input_common/helpers/joycon_driver.cpp
+++ b/src/input_common/helpers/joycon_driver.cpp
@@ -139,7 +139,7 @@ void JoyconDriver::InputThread(std::stop_token stop_token) {
139 input_thread_running = true; 139 input_thread_running = true;
140 140
141 // Max update rate is 5ms, ensure we are always able to read a bit faster 141 // Max update rate is 5ms, ensure we are always able to read a bit faster
142 constexpr int ThreadDelay = 2; 142 constexpr int ThreadDelay = 3;
143 std::vector<u8> buffer(MaxBufferSize); 143 std::vector<u8> buffer(MaxBufferSize);
144 144
145 while (!stop_token.stop_requested()) { 145 while (!stop_token.stop_requested()) {
@@ -163,6 +163,17 @@ void JoyconDriver::InputThread(std::stop_token stop_token) {
163 OnNewData(buffer); 163 OnNewData(buffer);
164 } 164 }
165 165
166 if (!vibration_queue.Empty()) {
167 VibrationValue vibration_value;
168 vibration_queue.Pop(vibration_value);
169 last_vibration_result = rumble_protocol->SendVibration(vibration_value);
170 }
171
172 // We can't keep up with vibrations. Start skipping.
173 while (vibration_queue.Size() > 6) {
174 vibration_queue.Pop();
175 }
176
166 std::this_thread::yield(); 177 std::this_thread::yield();
167 } 178 }
168 179
@@ -402,7 +413,8 @@ Common::Input::DriverResult JoyconDriver::SetVibration(const VibrationValue& vib
402 if (disable_input_thread) { 413 if (disable_input_thread) {
403 return Common::Input::DriverResult::HandleInUse; 414 return Common::Input::DriverResult::HandleInUse;
404 } 415 }
405 return rumble_protocol->SendVibration(vibration); 416 vibration_queue.Push(vibration);
417 return last_vibration_result;
406} 418}
407 419
408Common::Input::DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { 420Common::Input::DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) {
diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h
index 335e12cc3..5355780fb 100644
--- a/src/input_common/helpers/joycon_driver.h
+++ b/src/input_common/helpers/joycon_driver.h
@@ -9,6 +9,7 @@
9#include <span> 9#include <span>
10#include <thread> 10#include <thread>
11 11
12#include "common/threadsafe_queue.h"
12#include "input_common/helpers/joycon_protocol/joycon_types.h" 13#include "input_common/helpers/joycon_protocol/joycon_types.h"
13 14
14namespace Common::Input { 15namespace Common::Input {
@@ -152,6 +153,10 @@ private:
152 SerialNumber handle_serial_number{}; // Serial number type reported by hidapi 153 SerialNumber handle_serial_number{}; // Serial number type reported by hidapi
153 SupportedFeatures supported_features{}; 154 SupportedFeatures supported_features{};
154 155
156 /// Queue of vibration request to controllers
157 Common::Input::DriverResult last_vibration_result{Common::Input::DriverResult::Success};
158 Common::SPSCQueue<VibrationValue> vibration_queue;
159
155 // Thread related 160 // Thread related
156 mutable std::mutex mutex; 161 mutable std::mutex mutex;
157 std::jthread input_thread; 162 std::jthread input_thread;
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 9b2698fad..081a574e8 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -1067,8 +1067,7 @@ void BufferCache<P>::BindHostComputeTextureBuffers() {
1067 1067
1068template <class P> 1068template <class P>
1069void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) { 1069void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
1070 do { 1070 BufferOperations([&]() {
1071 channel_state->has_deleted_buffers = false;
1072 if (is_indexed) { 1071 if (is_indexed) {
1073 UpdateIndexBuffer(); 1072 UpdateIndexBuffer();
1074 } 1073 }
@@ -1082,14 +1081,16 @@ void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) {
1082 if (current_draw_indirect) { 1081 if (current_draw_indirect) {
1083 UpdateDrawIndirect(); 1082 UpdateDrawIndirect();
1084 } 1083 }
1085 } while (channel_state->has_deleted_buffers); 1084 });
1086} 1085}
1087 1086
1088template <class P> 1087template <class P>
1089void BufferCache<P>::DoUpdateComputeBuffers() { 1088void BufferCache<P>::DoUpdateComputeBuffers() {
1090 UpdateComputeUniformBuffers(); 1089 BufferOperations([&]() {
1091 UpdateComputeStorageBuffers(); 1090 UpdateComputeUniformBuffers();
1092 UpdateComputeTextureBuffers(); 1091 UpdateComputeStorageBuffers();
1092 UpdateComputeTextureBuffers();
1093 });
1093} 1094}
1094 1095
1095template <class P> 1096template <class P>
diff --git a/src/video_core/renderer_null/null_rasterizer.cpp b/src/video_core/renderer_null/null_rasterizer.cpp
index 65cd5aa06..4f1d5b548 100644
--- a/src/video_core/renderer_null/null_rasterizer.cpp
+++ b/src/video_core/renderer_null/null_rasterizer.cpp
@@ -3,6 +3,7 @@
3 3
4#include "common/alignment.h" 4#include "common/alignment.h"
5#include "core/memory.h" 5#include "core/memory.h"
6#include "video_core/control/channel_state.h"
6#include "video_core/host1x/host1x.h" 7#include "video_core/host1x/host1x.h"
7#include "video_core/memory_manager.h" 8#include "video_core/memory_manager.h"
8#include "video_core/renderer_null/null_rasterizer.h" 9#include "video_core/renderer_null/null_rasterizer.h"
@@ -99,8 +100,14 @@ bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config,
99} 100}
100void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, 101void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
101 const VideoCore::DiskResourceLoadCallback& callback) {} 102 const VideoCore::DiskResourceLoadCallback& callback) {}
102void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {} 103void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {
103void RasterizerNull::BindChannel(Tegra::Control::ChannelState& channel) {} 104 CreateChannel(channel);
104void RasterizerNull::ReleaseChannel(s32 channel_id) {} 105}
106void RasterizerNull::BindChannel(Tegra::Control::ChannelState& channel) {
107 BindToChannel(channel.bind_id);
108}
109void RasterizerNull::ReleaseChannel(s32 channel_id) {
110 EraseChannel(channel_id);
111}
105 112
106} // namespace Null 113} // namespace Null
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 804b95989..22bf8cc77 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -358,7 +358,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
358 .has_broken_spirv_subgroup_mask_vector_extract_dynamic = 358 .has_broken_spirv_subgroup_mask_vector_extract_dynamic =
359 driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY, 359 driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
360 .has_broken_robust = 360 .has_broken_robust =
361 device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Maxwell, 361 device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Pascal,
362 }; 362 };
363 363
364 host_info = Shader::HostTranslateInfo{ 364 host_info = Shader::HostTranslateInfo{
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 465eac37e..c0e8431e4 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -13,6 +13,7 @@
13#include "common/microprofile.h" 13#include "common/microprofile.h"
14#include "common/scope_exit.h" 14#include "common/scope_exit.h"
15#include "common/settings.h" 15#include "common/settings.h"
16#include "video_core/buffer_cache/buffer_cache.h"
16#include "video_core/control/channel_state.h" 17#include "video_core/control/channel_state.h"
17#include "video_core/engines/draw_manager.h" 18#include "video_core/engines/draw_manager.h"
18#include "video_core/engines/kepler_compute.h" 19#include "video_core/engines/kepler_compute.h"
@@ -81,7 +82,7 @@ VkViewport GetViewportState(const Device& device, const Maxwell& regs, size_t in
81 } 82 }
82 83
83 if (y_negate) { 84 if (y_negate) {
84 y += height; 85 y += conv(static_cast<f32>(regs.surface_clip.height));
85 height = -height; 86 height = -height;
86 } 87 }
87 88
@@ -285,6 +286,7 @@ void RasterizerVulkan::DrawTexture() {
285 286
286 query_cache.NotifySegment(true); 287 query_cache.NotifySegment(true);
287 288
289 std::scoped_lock l{texture_cache.mutex};
288 texture_cache.SynchronizeGraphicsDescriptors(); 290 texture_cache.SynchronizeGraphicsDescriptors();
289 texture_cache.UpdateRenderTargets(false); 291 texture_cache.UpdateRenderTargets(false);
290 292
@@ -921,9 +923,13 @@ void RasterizerVulkan::UpdateDynamicStates() {
921} 923}
922 924
923void RasterizerVulkan::HandleTransformFeedback() { 925void RasterizerVulkan::HandleTransformFeedback() {
926 static std::once_flag warn_unsupported;
927
924 const auto& regs = maxwell3d->regs; 928 const auto& regs = maxwell3d->regs;
925 if (!device.IsExtTransformFeedbackSupported()) { 929 if (!device.IsExtTransformFeedbackSupported()) {
926 LOG_ERROR(Render_Vulkan, "Transform feedbacks used but not supported"); 930 std::call_once(warn_unsupported, [&] {
931 LOG_ERROR(Render_Vulkan, "Transform feedbacks used but not supported");
932 });
927 return; 933 return;
928 } 934 }
929 query_cache.CounterEnable(VideoCommon::QueryType::StreamingByteCount, 935 query_cache.CounterEnable(VideoCommon::QueryType::StreamingByteCount,
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index d56558a83..daaea2979 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -190,7 +190,7 @@ void SetupDirtySpecialOps(Tables& tables) {
190void SetupDirtyViewportSwizzles(Tables& tables) { 190void SetupDirtyViewportSwizzles(Tables& tables) {
191 static constexpr size_t swizzle_offset = 6; 191 static constexpr size_t swizzle_offset = 6;
192 for (size_t index = 0; index < Regs::NumViewports; ++index) { 192 for (size_t index = 0; index < Regs::NumViewports; ++index) {
193 tables[0][OFF(viewport_transform) + index * NUM(viewport_transform[0]) + swizzle_offset] = 193 tables[1][OFF(viewport_transform) + index * NUM(viewport_transform[0]) + swizzle_offset] =
194 ViewportSwizzles; 194 ViewportSwizzles;
195 } 195 }
196} 196}
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index 81ef98f61..821f44f1a 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -147,6 +147,9 @@ bool Swapchain::AcquireNextImage() {
147 case VK_ERROR_OUT_OF_DATE_KHR: 147 case VK_ERROR_OUT_OF_DATE_KHR:
148 is_outdated = true; 148 is_outdated = true;
149 break; 149 break;
150 case VK_ERROR_SURFACE_LOST_KHR:
151 vk::Check(result);
152 break;
150 default: 153 default:
151 LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", vk::ToString(result)); 154 LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", vk::ToString(result));
152 break; 155 break;
@@ -180,6 +183,9 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
180 case VK_ERROR_OUT_OF_DATE_KHR: 183 case VK_ERROR_OUT_OF_DATE_KHR:
181 is_outdated = true; 184 is_outdated = true;
182 break; 185 break;
186 case VK_ERROR_SURFACE_LOST_KHR:
187 vk::Check(result);
188 break;
183 default: 189 default:
184 LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", vk::ToString(result)); 190 LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", vk::ToString(result));
185 break; 191 break;
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 34208ed74..33e1fb663 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -227,14 +227,14 @@ add_executable(yuzu
227 yuzu.rc 227 yuzu.rc
228) 228)
229 229
230if (WIN32 AND YUZU_CRASH_DUMPS) 230if (YUZU_CRASH_DUMPS)
231 target_sources(yuzu PRIVATE 231 target_sources(yuzu PRIVATE
232 mini_dump.cpp 232 breakpad.cpp
233 mini_dump.h 233 breakpad.h
234 ) 234 )
235 235
236 target_link_libraries(yuzu PRIVATE ${DBGHELP_LIBRARY}) 236 target_link_libraries(yuzu PRIVATE libbreakpad_client)
237 target_compile_definitions(yuzu PRIVATE -DYUZU_DBGHELP) 237 target_compile_definitions(yuzu PRIVATE YUZU_CRASH_DUMPS)
238endif() 238endif()
239 239
240if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 240if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index ca0e14fad..515cb7ce6 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -155,18 +155,27 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
155 UpdateBorderColor(i); 155 UpdateBorderColor(i);
156 156
157 connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) { 157 connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) {
158 if (checked) { 158 // Reconnect current controller if it was the last one checked
159 // Hide eventual error message about number of controllers 159 // (player number was reduced by more than one)
160 ui->labelError->setVisible(false); 160 const bool reconnect_first = !checked && i < player_groupboxes.size() - 1 &&
161 for (std::size_t index = 0; index <= i; ++index) { 161 player_groupboxes[i + 1]->isChecked();
162 connected_controller_checkboxes[index]->setChecked(checked); 162
163 } 163 // Ensures that connecting a controller changes the number of players
164 } else { 164 if (connected_controller_checkboxes[i]->isChecked() != checked) {
165 for (std::size_t index = i; index < NUM_PLAYERS; ++index) { 165 // Ensures that the players are always connected in sequential order
166 connected_controller_checkboxes[index]->setChecked(checked); 166 PropagatePlayerNumberChanged(i, checked, reconnect_first);
167 }
168 } 167 }
169 }); 168 });
169 connect(connected_controller_checkboxes[i], &QCheckBox::clicked, [this, i](bool checked) {
170 // Reconnect current controller if it was the last one checked
171 // (player number was reduced by more than one)
172 const bool reconnect_first = !checked &&
173 i < connected_controller_checkboxes.size() - 1 &&
174 connected_controller_checkboxes[i + 1]->isChecked();
175
176 // Ensures that the players are always connected in sequential order
177 PropagatePlayerNumberChanged(i, checked, reconnect_first);
178 });
170 179
171 connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged), 180 connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged),
172 [this, i](int) { 181 [this, i](int) {
@@ -668,6 +677,29 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
668 } 677 }
669} 678}
670 679
680void QtControllerSelectorDialog::PropagatePlayerNumberChanged(size_t player_index, bool checked,
681 bool reconnect_current) {
682 connected_controller_checkboxes[player_index]->setChecked(checked);
683 // Hide eventual error message about number of controllers
684 ui->labelError->setVisible(false);
685
686 if (checked) {
687 // Check all previous buttons when checked
688 if (player_index > 0) {
689 PropagatePlayerNumberChanged(player_index - 1, checked);
690 }
691 } else {
692 // Unchecked all following buttons when unchecked
693 if (player_index < connected_controller_checkboxes.size() - 1) {
694 PropagatePlayerNumberChanged(player_index + 1, checked);
695 }
696 }
697
698 if (reconnect_current) {
699 connected_controller_checkboxes[player_index]->setCheckState(Qt::Checked);
700 }
701}
702
671void QtControllerSelectorDialog::DisableUnsupportedPlayers() { 703void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
672 const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; 704 const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
673 705
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index 7f0673d06..e5372495d 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -100,6 +100,10 @@ private:
100 // Updates the console mode. 100 // Updates the console mode.
101 void UpdateDockedState(bool is_handheld); 101 void UpdateDockedState(bool is_handheld);
102 102
103 // Enable preceding controllers or disable following ones
104 void PropagatePlayerNumberChanged(size_t player_index, bool checked,
105 bool reconnect_current = false);
106
103 // Disables and disconnects unsupported players based on the given parameters. 107 // Disables and disconnects unsupported players based on the given parameters.
104 void DisableUnsupportedPlayers(); 108 void DisableUnsupportedPlayers();
105 109
diff --git a/src/yuzu/breakpad.cpp b/src/yuzu/breakpad.cpp
new file mode 100644
index 000000000..0f6a71ab0
--- /dev/null
+++ b/src/yuzu/breakpad.cpp
@@ -0,0 +1,77 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <algorithm>
5#include <ranges>
6
7#if defined(_WIN32)
8#include <client/windows/handler/exception_handler.h>
9#elif defined(__linux__)
10#include <client/linux/handler/exception_handler.h>
11#else
12#error Minidump creation not supported on this platform
13#endif
14
15#include "common/fs/fs_paths.h"
16#include "common/fs/path_util.h"
17#include "yuzu/breakpad.h"
18
19namespace Breakpad {
20
21static void PruneDumpDirectory(const std::filesystem::path& dump_path) {
22 // Code in this function should be exception-safe.
23 struct Entry {
24 std::filesystem::path path;
25 std::filesystem::file_time_type last_write_time;
26 };
27 std::vector<Entry> existing_dumps;
28
29 // Get existing entries.
30 std::error_code ec;
31 std::filesystem::directory_iterator dir(dump_path, ec);
32 for (auto& entry : dir) {
33 if (entry.is_regular_file()) {
34 existing_dumps.push_back(Entry{
35 .path = entry.path(),
36 .last_write_time = entry.last_write_time(ec),
37 });
38 }
39 }
40
41 // Sort descending by creation date.
42 std::ranges::stable_sort(existing_dumps, [](const auto& a, const auto& b) {
43 return a.last_write_time > b.last_write_time;
44 });
45
46 // Delete older dumps.
47 for (size_t i = 5; i < existing_dumps.size(); i++) {
48 std::filesystem::remove(existing_dumps[i].path, ec);
49 }
50}
51
52#if defined(__linux__)
53[[noreturn]] bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context,
54 bool succeeded) {
55 // Prevent time- and space-consuming core dumps from being generated, as we have
56 // already generated a minidump and a core file will not be useful anyway.
57 _exit(1);
58}
59#endif
60
61void InstallCrashHandler() {
62 // Write crash dumps to profile directory.
63 const auto dump_path = GetYuzuPath(Common::FS::YuzuPath::CrashDumpsDir);
64 PruneDumpDirectory(dump_path);
65
66#if defined(_WIN32)
67 // TODO: If we switch to MinGW builds for Windows, this needs to be wrapped in a C API.
68 static google_breakpad::ExceptionHandler eh{dump_path, nullptr, nullptr, nullptr,
69 google_breakpad::ExceptionHandler::HANDLER_ALL};
70#elif defined(__linux__)
71 static google_breakpad::MinidumpDescriptor descriptor{dump_path};
72 static google_breakpad::ExceptionHandler eh{descriptor, nullptr, DumpCallback,
73 nullptr, true, -1};
74#endif
75}
76
77} // namespace Breakpad
diff --git a/src/yuzu/breakpad.h b/src/yuzu/breakpad.h
new file mode 100644
index 000000000..0f911aa9c
--- /dev/null
+++ b/src/yuzu/breakpad.h
@@ -0,0 +1,10 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6namespace Breakpad {
7
8void InstallCrashHandler();
9
10}
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 74ec4f771..1589ba057 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: 2014 Citra Emulator Project 1// SPDX-FileCopyrightText: 2014 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
diff --git a/src/yuzu/configuration/configure_camera.h b/src/yuzu/configuration/configure_camera.h
index 9a90512b3..3d822da7b 100644
--- a/src/yuzu/configuration/configure_camera.h
+++ b/src/yuzu/configuration/configure_camera.h
@@ -1,4 +1,4 @@
1// Text : Copyright 2022 yuzu Emulator Project 1// Text : Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-3.0-or-later 2// SPDX-License-Identifier: GPL-3.0-or-later
3 3
4#pragma once 4#pragma once
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index b22fda746..ef421c754 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -27,16 +27,6 @@ ConfigureDebug::ConfigureDebug(const Core::System& system_, QWidget* parent)
27 27
28 connect(ui->toggle_gdbstub, &QCheckBox::toggled, 28 connect(ui->toggle_gdbstub, &QCheckBox::toggled,
29 [&]() { ui->gdbport_spinbox->setEnabled(ui->toggle_gdbstub->isChecked()); }); 29 [&]() { ui->gdbport_spinbox->setEnabled(ui->toggle_gdbstub->isChecked()); });
30
31 connect(ui->create_crash_dumps, &QCheckBox::stateChanged, [&](int) {
32 if (crash_dump_warning_shown) {
33 return;
34 }
35 QMessageBox::warning(this, tr("Restart Required"),
36 tr("yuzu is required to restart in order to apply this setting."),
37 QMessageBox::Ok, QMessageBox::Ok);
38 crash_dump_warning_shown = true;
39 });
40} 30}
41 31
42ConfigureDebug::~ConfigureDebug() = default; 32ConfigureDebug::~ConfigureDebug() = default;
@@ -89,13 +79,6 @@ void ConfigureDebug::SetConfiguration() {
89 ui->disable_web_applet->setEnabled(false); 79 ui->disable_web_applet->setEnabled(false);
90 ui->disable_web_applet->setText(tr("Web applet not compiled")); 80 ui->disable_web_applet->setText(tr("Web applet not compiled"));
91#endif 81#endif
92
93#ifdef YUZU_DBGHELP
94 ui->create_crash_dumps->setChecked(Settings::values.create_crash_dumps.GetValue());
95#else
96 ui->create_crash_dumps->setEnabled(false);
97 ui->create_crash_dumps->setText(tr("MiniDump creation not compiled"));
98#endif
99} 82}
100 83
101void ConfigureDebug::ApplyConfiguration() { 84void ConfigureDebug::ApplyConfiguration() {
@@ -107,7 +90,6 @@ void ConfigureDebug::ApplyConfiguration() {
107 Settings::values.enable_fs_access_log = ui->fs_access_log->isChecked(); 90 Settings::values.enable_fs_access_log = ui->fs_access_log->isChecked();
108 Settings::values.reporting_services = ui->reporting_services->isChecked(); 91 Settings::values.reporting_services = ui->reporting_services->isChecked();
109 Settings::values.dump_audio_commands = ui->dump_audio_commands->isChecked(); 92 Settings::values.dump_audio_commands = ui->dump_audio_commands->isChecked();
110 Settings::values.create_crash_dumps = ui->create_crash_dumps->isChecked();
111 Settings::values.quest_flag = ui->quest_flag->isChecked(); 93 Settings::values.quest_flag = ui->quest_flag->isChecked();
112 Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); 94 Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
113 Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); 95 Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 66b8b7459..76fe98924 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -471,13 +471,6 @@
471 </property> 471 </property>
472 </widget> 472 </widget>
473 </item> 473 </item>
474 <item row="4" column="0">
475 <widget class="QCheckBox" name="create_crash_dumps">
476 <property name="text">
477 <string>Create Minidump After Crash</string>
478 </property>
479 </widget>
480 </item>
481 <item row="3" column="0"> 474 <item row="3" column="0">
482 <widget class="QCheckBox" name="dump_audio_commands"> 475 <widget class="QCheckBox" name="dump_audio_commands">
483 <property name="toolTip"> 476 <property name="toolTip">
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 5a48e388b..02e23cce6 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -101,13 +101,13 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
101 ui->tabPlayer5, ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8, 101 ui->tabPlayer5, ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8,
102 }; 102 };
103 103
104 player_connected = { 104 connected_controller_checkboxes = {
105 ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected, 105 ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected,
106 ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected, 106 ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected,
107 ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, 107 ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected,
108 }; 108 };
109 109
110 std::array<QLabel*, 8> player_connected_labels = { 110 std::array<QLabel*, 8> connected_controller_labels = {
111 ui->label, ui->label_3, ui->label_4, ui->label_5, 111 ui->label, ui->label_3, ui->label_4, ui->label_5,
112 ui->label_6, ui->label_7, ui->label_8, ui->label_9, 112 ui->label_6, ui->label_7, ui->label_8, ui->label_9,
113 }; 113 };
@@ -115,30 +115,44 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
115 for (std::size_t i = 0; i < player_tabs.size(); ++i) { 115 for (std::size_t i = 0; i < player_tabs.size(); ++i) {
116 player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i])); 116 player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i]));
117 player_tabs[i]->layout()->addWidget(player_controllers[i]); 117 player_tabs[i]->layout()->addWidget(player_controllers[i]);
118 connect(player_connected[i], &QCheckBox::clicked, [this, i](int checked) { 118 connect(player_controllers[i], &ConfigureInputPlayer::Connected, [this, i](bool checked) {
119 // Ensures that the controllers are always connected in sequential order 119 // Ensures that connecting a controller changes the number of players
120 this->propagateMouseClickOnPlayers(i, checked, true); 120 if (connected_controller_checkboxes[i]->isChecked() != checked) {
121 // Ensures that the players are always connected in sequential order
122 PropagatePlayerNumberChanged(i, checked);
123 }
124 });
125 connect(connected_controller_checkboxes[i], &QCheckBox::clicked, [this, i](bool checked) {
126 // Reconnect current controller if it was the last one checked
127 // (player number was reduced by more than one)
128 const bool reconnect_first = !checked &&
129 i < connected_controller_checkboxes.size() - 1 &&
130 connected_controller_checkboxes[i + 1]->isChecked();
131
132 // Ensures that the players are always connected in sequential order
133 PropagatePlayerNumberChanged(i, checked, reconnect_first);
121 }); 134 });
122 connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, this, 135 connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, this,
123 &ConfigureInput::UpdateAllInputDevices); 136 &ConfigureInput::UpdateAllInputDevices);
124 connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this, 137 connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this,
125 &ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection); 138 &ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection);
126 connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) { 139 connect(connected_controller_checkboxes[i], &QCheckBox::stateChanged, [this, i](int state) {
140 // Keep activated controllers synced with the "Connected Controllers" checkboxes
127 player_controllers[i]->ConnectPlayer(state == Qt::Checked); 141 player_controllers[i]->ConnectPlayer(state == Qt::Checked);
128 }); 142 });
129 143
130 // Remove/hide all the elements that exceed max_players, if applicable. 144 // Remove/hide all the elements that exceed max_players, if applicable.
131 if (i >= max_players) { 145 if (i >= max_players) {
132 ui->tabWidget->removeTab(static_cast<int>(max_players)); 146 ui->tabWidget->removeTab(static_cast<int>(max_players));
133 player_connected[i]->hide(); 147 connected_controller_checkboxes[i]->hide();
134 player_connected_labels[i]->hide(); 148 connected_controller_labels[i]->hide();
135 } 149 }
136 } 150 }
137 // Only the first player can choose handheld mode so connect the signal just to player 1 151 // Only the first player can choose handheld mode so connect the signal just to player 1
138 connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged, 152 connect(player_controllers[0], &ConfigureInputPlayer::HandheldStateChanged,
139 [this](bool is_handheld) { UpdateDockedState(is_handheld); }); 153 [this](bool is_handheld) { UpdateDockedState(is_handheld); });
140 154
141 advanced = new ConfigureInputAdvanced(this); 155 advanced = new ConfigureInputAdvanced(hid_core, this);
142 ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced)); 156 ui->tabAdvanced->setLayout(new QHBoxLayout(ui->tabAdvanced));
143 ui->tabAdvanced->layout()->addWidget(advanced); 157 ui->tabAdvanced->layout()->addWidget(advanced);
144 158
@@ -175,28 +189,25 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
175 LoadConfiguration(); 189 LoadConfiguration();
176} 190}
177 191
178void ConfigureInput::propagateMouseClickOnPlayers(size_t player_index, bool checked, bool origin) { 192void ConfigureInput::PropagatePlayerNumberChanged(size_t player_index, bool checked,
179 // Origin has already been toggled 193 bool reconnect_current) {
180 if (!origin) { 194 connected_controller_checkboxes[player_index]->setChecked(checked);
181 player_connected[player_index]->setChecked(checked);
182 }
183 195
184 if (checked) { 196 if (checked) {
185 // Check all previous buttons when checked 197 // Check all previous buttons when checked
186 if (player_index > 0) { 198 if (player_index > 0) {
187 propagateMouseClickOnPlayers(player_index - 1, checked, false); 199 PropagatePlayerNumberChanged(player_index - 1, checked);
188 } 200 }
189 } else { 201 } else {
190 // Unchecked all following buttons when unchecked 202 // Unchecked all following buttons when unchecked
191 if (player_index < player_tabs.size() - 1) { 203 if (player_index < connected_controller_checkboxes.size() - 1) {
192 // Reconnect current player if it was the last one checked 204 PropagatePlayerNumberChanged(player_index + 1, checked);
193 // (player number was reduced by more than one)
194 if (origin && player_connected[player_index + 1]->checkState() == Qt::Checked) {
195 player_connected[player_index]->setCheckState(Qt::Checked);
196 }
197 propagateMouseClickOnPlayers(player_index + 1, checked, false);
198 } 205 }
199 } 206 }
207
208 if (reconnect_current) {
209 connected_controller_checkboxes[player_index]->setCheckState(Qt::Checked);
210 }
200} 211}
201 212
202QList<QWidget*> ConfigureInput::GetSubTabs() const { 213QList<QWidget*> ConfigureInput::GetSubTabs() const {
@@ -249,17 +260,17 @@ void ConfigureInput::LoadConfiguration() {
249} 260}
250 261
251void ConfigureInput::LoadPlayerControllerIndices() { 262void ConfigureInput::LoadPlayerControllerIndices() {
252 for (std::size_t i = 0; i < player_connected.size(); ++i) { 263 for (std::size_t i = 0; i < connected_controller_checkboxes.size(); ++i) {
253 if (i == 0) { 264 if (i == 0) {
254 auto* handheld = 265 auto* handheld =
255 system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); 266 system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
256 if (handheld->IsConnected()) { 267 if (handheld->IsConnected()) {
257 player_connected[i]->setChecked(true); 268 connected_controller_checkboxes[i]->setChecked(true);
258 continue; 269 continue;
259 } 270 }
260 } 271 }
261 const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(i); 272 const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(i);
262 player_connected[i]->setChecked(controller->IsConnected()); 273 connected_controller_checkboxes[i]->setChecked(controller->IsConnected());
263 } 274 }
264} 275}
265 276
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index abb7f7089..beb503dae 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: 2016 Citra Emulator Project 1// SPDX-FileCopyrightText: 2016 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
@@ -56,7 +56,9 @@ private:
56 void UpdateDockedState(bool is_handheld); 56 void UpdateDockedState(bool is_handheld);
57 void UpdateAllInputDevices(); 57 void UpdateAllInputDevices();
58 void UpdateAllInputProfiles(std::size_t player_index); 58 void UpdateAllInputProfiles(std::size_t player_index);
59 void propagateMouseClickOnPlayers(size_t player_index, bool origin, bool checked); 59 // Enable preceding controllers or disable following ones
60 void PropagatePlayerNumberChanged(size_t player_index, bool checked,
61 bool reconnect_current = false);
60 62
61 /// Load configuration settings. 63 /// Load configuration settings.
62 void LoadConfiguration(); 64 void LoadConfiguration();
@@ -71,7 +73,8 @@ private:
71 73
72 std::array<ConfigureInputPlayer*, 8> player_controllers; 74 std::array<ConfigureInputPlayer*, 8> player_controllers;
73 std::array<QWidget*, 8> player_tabs; 75 std::array<QWidget*, 8> player_tabs;
74 std::array<QCheckBox*, 8> player_connected; 76 // Checkboxes representing the "Connected Controllers".
77 std::array<QCheckBox*, 8> connected_controller_checkboxes;
75 ConfigureInputAdvanced* advanced; 78 ConfigureInputAdvanced* advanced;
76 79
77 Core::System& system; 80 Core::System& system;
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index 3cfd5d439..441cea3f6 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -4,11 +4,13 @@
4#include <QColorDialog> 4#include <QColorDialog>
5#include "common/settings.h" 5#include "common/settings.h"
6#include "core/core.h" 6#include "core/core.h"
7#include "core/hid/emulated_controller.h"
8#include "core/hid/hid_core.h"
7#include "ui_configure_input_advanced.h" 9#include "ui_configure_input_advanced.h"
8#include "yuzu/configuration/configure_input_advanced.h" 10#include "yuzu/configuration/configure_input_advanced.h"
9 11
10ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) 12ConfigureInputAdvanced::ConfigureInputAdvanced(Core::HID::HIDCore& hid_core_, QWidget* parent)
11 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputAdvanced>()) { 13 : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputAdvanced>()), hid_core{hid_core_} {
12 ui->setupUi(this); 14 ui->setupUi(this);
13 15
14 controllers_color_buttons = {{ 16 controllers_color_buttons = {{
@@ -123,6 +125,8 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
123 player.button_color_left = colors[1]; 125 player.button_color_left = colors[1];
124 player.body_color_right = colors[2]; 126 player.body_color_right = colors[2];
125 player.button_color_right = colors[3]; 127 player.button_color_right = colors[3];
128
129 hid_core.GetEmulatedControllerByIndex(player_idx)->ReloadColorsFromSettings();
126 } 130 }
127 131
128 Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked(); 132 Settings::values.debug_pad_enabled = ui->debug_enabled->isChecked();
diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h
index fc1230284..41f822c4a 100644
--- a/src/yuzu/configuration/configure_input_advanced.h
+++ b/src/yuzu/configuration/configure_input_advanced.h
@@ -14,11 +14,15 @@ namespace Ui {
14class ConfigureInputAdvanced; 14class ConfigureInputAdvanced;
15} 15}
16 16
17namespace Core::HID {
18class HIDCore;
19} // namespace Core::HID
20
17class ConfigureInputAdvanced : public QWidget { 21class ConfigureInputAdvanced : public QWidget {
18 Q_OBJECT 22 Q_OBJECT
19 23
20public: 24public:
21 explicit ConfigureInputAdvanced(QWidget* parent = nullptr); 25 explicit ConfigureInputAdvanced(Core::HID::HIDCore& hid_core_, QWidget* parent = nullptr);
22 ~ConfigureInputAdvanced() override; 26 ~ConfigureInputAdvanced() override;
23 27
24 void ApplyConfiguration(); 28 void ApplyConfiguration();
@@ -44,4 +48,6 @@ private:
44 48
45 std::array<std::array<QColor, 4>, 8> controllers_colors; 49 std::array<std::array<QColor, 4>, 8> controllers_colors;
46 std::array<std::array<QPushButton*, 4>, 8> controllers_color_buttons; 50 std::array<std::array<QPushButton*, 4>, 8> controllers_color_buttons;
51
52 Core::HID::HIDCore& hid_core;
47}; 53};
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index d4df43d73..fda09e925 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: 2016 Citra Emulator Project 1// SPDX-FileCopyrightText: 2016 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
@@ -75,7 +75,7 @@ public:
75 void ClearAll(); 75 void ClearAll();
76 76
77signals: 77signals:
78 /// Emitted when this controller is connected by the user. 78 /// Emitted when this controller is (dis)connected by the user.
79 void Connected(bool connected); 79 void Connected(bool connected);
80 /// Emitted when the Handheld mode is selected (undocked with dual joycons attached). 80 /// Emitted when the Handheld mode is selected (undocked with dual joycons attached).
81 void HandheldStateChanged(bool is_handheld); 81 void HandheldStateChanged(bool is_handheld);
@@ -183,9 +183,6 @@ private:
183 /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum. 183 /// Stores a pair of "Connected Controllers" combobox index and Controller Type enum.
184 std::vector<std::pair<int, Core::HID::NpadStyleIndex>> index_controller_type_pairs; 184 std::vector<std::pair<int, Core::HID::NpadStyleIndex>> index_controller_type_pairs;
185 185
186 static constexpr int PLAYER_COUNT = 8;
187 std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox;
188
189 /// This will be the the setting function when an input is awaiting configuration. 186 /// This will be the the setting function when an input is awaiting configuration.
190 std::optional<std::function<void(const Common::ParamPackage&)>> input_setter; 187 std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
191 188
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index 1a727f32c..cc2513001 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp
index a47089988..6d2219bf5 100644
--- a/src/yuzu/configuration/configure_profile_manager.cpp
+++ b/src/yuzu/configuration/configure_profile_manager.cpp
@@ -306,10 +306,10 @@ void ConfigureProfileManager::SetUserImage() {
306 return; 306 return;
307 } 307 }
308 308
309 // Some games crash when the profile image is too big. Resize any image bigger than 256x256 309 // Profile image must be 256x256
310 QImage image(image_path); 310 QImage image(image_path);
311 if (image.width() > 256 || image.height() > 256) { 311 if (image.width() != 256 || image.height() != 256) {
312 image = image.scaled(256, 256, Qt::KeepAspectRatio); 312 image = image.scaled(256, 256, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
313 if (!image.save(image_path)) { 313 if (!image.save(image_path)) {
314 QMessageBox::warning(this, tr("Error resizing user image"), 314 QMessageBox::warning(this, tr("Error resizing user image"),
315 tr("Unable to resize image")); 315 tr("Unable to resize image"));
diff --git a/src/yuzu/configuration/configure_ringcon.h b/src/yuzu/configuration/configure_ringcon.h
index b23c27906..6fd95e2b8 100644
--- a/src/yuzu/configuration/configure_ringcon.h
+++ b/src/yuzu/configuration/configure_ringcon.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
diff --git a/src/yuzu/configuration/configure_tas.h b/src/yuzu/configuration/configure_tas.h
index 4a6b0ba4e..a91891906 100644
--- a/src/yuzu/configuration/configure_tas.h
+++ b/src/yuzu/configuration/configure_tas.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h
index 034dc0d46..b6fdffdc8 100644
--- a/src/yuzu/configuration/configure_touchscreen_advanced.h
+++ b/src/yuzu/configuration/configure_touchscreen_advanced.h
@@ -1,4 +1,4 @@
1// SPDX-FileCopyrightText: 2016 Citra Emulator Project 1// SPDX-FileCopyrightText: 2016 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#pragma once 4#pragma once
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp
index 3fe448f27..1434b1a56 100644
--- a/src/yuzu/configuration/shared_translation.cpp
+++ b/src/yuzu/configuration/shared_translation.cpp
@@ -156,7 +156,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
156 // Ui General 156 // Ui General
157 INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", ""); 157 INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", "");
158 INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", ""); 158 INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", "");
159 INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", "");
160 INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", ""); 159 INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", "");
161 INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", ""); 160 INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", "");
162 INSERT(UISettings, controller_applet_disabled, "Disable controller applet", ""); 161 INSERT(UISettings, controller_applet_disabled, "Disable controller applet", "");
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 0783a2430..7049c57b6 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -127,7 +127,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
127 return list; 127 return list;
128 } 128 }
129 129
130 if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64BitProcess()) { 130 if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64Bit()) {
131 return list; 131 return list;
132 } 132 }
133 133
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 2bb1a0239..7e7d8e252 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -380,7 +380,6 @@ void GameList::UnloadController() {
380 380
381GameList::~GameList() { 381GameList::~GameList() {
382 UnloadController(); 382 UnloadController();
383 emit ShouldCancelWorker();
384} 383}
385 384
386void GameList::SetFilterFocus() { 385void GameList::SetFilterFocus() {
@@ -397,6 +396,10 @@ void GameList::ClearFilter() {
397 search_field->clear(); 396 search_field->clear();
398} 397}
399 398
399void GameList::WorkerEvent() {
400 current_worker->ProcessEvents(this);
401}
402
400void GameList::AddDirEntry(GameListDir* entry_items) { 403void GameList::AddDirEntry(GameListDir* entry_items) {
401 item_model->invisibleRootItem()->appendRow(entry_items); 404 item_model->invisibleRootItem()->appendRow(entry_items);
402 tree_view->setExpanded( 405 tree_view->setExpanded(
@@ -826,28 +829,21 @@ void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
826 tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size); 829 tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size);
827 tree_view->setColumnHidden(COLUMN_PLAY_TIME, !UISettings::values.show_play_time); 830 tree_view->setColumnHidden(COLUMN_PLAY_TIME, !UISettings::values.show_play_time);
828 831
829 // Before deleting rows, cancel the worker so that it is not using them 832 // Cancel any existing worker.
830 emit ShouldCancelWorker(); 833 current_worker.reset();
831 834
832 // Delete any rows that might already exist if we're repopulating 835 // Delete any rows that might already exist if we're repopulating
833 item_model->removeRows(0, item_model->rowCount()); 836 item_model->removeRows(0, item_model->rowCount());
834 search_field->clear(); 837 search_field->clear();
835 838
836 GameListWorker* worker = 839 current_worker = std::make_unique<GameListWorker>(vfs, provider, game_dirs, compatibility_list,
837 new GameListWorker(vfs, provider, game_dirs, compatibility_list, play_time_manager, system); 840 play_time_manager, system);
838 841
839 connect(worker, &GameListWorker::EntryReady, this, &GameList::AddEntry, Qt::QueuedConnection); 842 // Get events from the worker as data becomes available
840 connect(worker, &GameListWorker::DirEntryReady, this, &GameList::AddDirEntry, 843 connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameList::WorkerEvent,
841 Qt::QueuedConnection);
842 connect(worker, &GameListWorker::Finished, this, &GameList::DonePopulating,
843 Qt::QueuedConnection); 844 Qt::QueuedConnection);
844 // Use DirectConnection here because worker->Cancel() is thread-safe and we want it to
845 // cancel without delay.
846 connect(this, &GameList::ShouldCancelWorker, worker, &GameListWorker::Cancel,
847 Qt::DirectConnection);
848 845
849 QThreadPool::globalInstance()->start(worker); 846 QThreadPool::globalInstance()->start(current_worker.get());
850 current_worker = std::move(worker);
851} 847}
852 848
853void GameList::SaveInterfaceLayout() { 849void GameList::SaveInterfaceLayout() {
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 712570cea..563a3a35b 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -109,7 +109,6 @@ signals:
109 void BootGame(const QString& game_path, u64 program_id, std::size_t program_index, 109 void BootGame(const QString& game_path, u64 program_id, std::size_t program_index,
110 StartGameType type, AmLaunchType launch_type); 110 StartGameType type, AmLaunchType launch_type);
111 void GameChosen(const QString& game_path, const u64 title_id = 0); 111 void GameChosen(const QString& game_path, const u64 title_id = 0);
112 void ShouldCancelWorker();
113 void OpenFolderRequested(u64 program_id, GameListOpenTarget target, 112 void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
114 const std::string& game_path); 113 const std::string& game_path);
115 void OpenTransferableShaderCacheRequested(u64 program_id); 114 void OpenTransferableShaderCacheRequested(u64 program_id);
@@ -138,11 +137,16 @@ private slots:
138 void OnUpdateThemedIcons(); 137 void OnUpdateThemedIcons();
139 138
140private: 139private:
140 friend class GameListWorker;
141 void WorkerEvent();
142
141 void AddDirEntry(GameListDir* entry_items); 143 void AddDirEntry(GameListDir* entry_items);
142 void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent); 144 void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent);
143 void ValidateEntry(const QModelIndex& item);
144 void DonePopulating(const QStringList& watch_list); 145 void DonePopulating(const QStringList& watch_list);
145 146
147private:
148 void ValidateEntry(const QModelIndex& item);
149
146 void RefreshGameDirectory(); 150 void RefreshGameDirectory();
147 151
148 void ToggleFavorite(u64 program_id); 152 void ToggleFavorite(u64 program_id);
@@ -165,7 +169,7 @@ private:
165 QVBoxLayout* layout = nullptr; 169 QVBoxLayout* layout = nullptr;
166 QTreeView* tree_view = nullptr; 170 QTreeView* tree_view = nullptr;
167 QStandardItemModel* item_model = nullptr; 171 QStandardItemModel* item_model = nullptr;
168 GameListWorker* current_worker = nullptr; 172 std::unique_ptr<GameListWorker> current_worker;
169 QFileSystemWatcher* watcher = nullptr; 173 QFileSystemWatcher* watcher = nullptr;
170 ControllerNavigation* controller_navigation = nullptr; 174 ControllerNavigation* controller_navigation = nullptr;
171 CompatibilityList compatibility_list; 175 CompatibilityList compatibility_list;
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 077ced12b..69be21027 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -233,10 +233,53 @@ GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_,
233 const PlayTime::PlayTimeManager& play_time_manager_, 233 const PlayTime::PlayTimeManager& play_time_manager_,
234 Core::System& system_) 234 Core::System& system_)
235 : vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_}, 235 : vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_},
236 compatibility_list{compatibility_list_}, 236 compatibility_list{compatibility_list_}, play_time_manager{play_time_manager_}, system{
237 play_time_manager{play_time_manager_}, system{system_} {} 237 system_} {
238 // We want the game list to manage our lifetime.
239 setAutoDelete(false);
240}
241
242GameListWorker::~GameListWorker() {
243 this->disconnect();
244 stop_requested.store(true);
245 processing_completed.Wait();
246}
247
248void GameListWorker::ProcessEvents(GameList* game_list) {
249 while (true) {
250 std::function<void(GameList*)> func;
251 {
252 // Lock queue to protect concurrent modification.
253 std::scoped_lock lk(lock);
254
255 // If we can't pop a function, return.
256 if (queued_events.empty()) {
257 return;
258 }
259
260 // Pop a function.
261 func = std::move(queued_events.back());
262 queued_events.pop_back();
263 }
264
265 // Run the function.
266 func(game_list);
267 }
268}
269
270template <typename F>
271void GameListWorker::RecordEvent(F&& func) {
272 {
273 // Lock queue to protect concurrent modification.
274 std::scoped_lock lk(lock);
238 275
239GameListWorker::~GameListWorker() = default; 276 // Add the function into the front of the queue.
277 queued_events.emplace_front(std::move(func));
278 }
279
280 // Data now available.
281 emit DataAvailable();
282}
240 283
241void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { 284void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
242 using namespace FileSys; 285 using namespace FileSys;
@@ -284,9 +327,9 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
284 GetMetadataFromControlNCA(patch, *control, icon, name); 327 GetMetadataFromControlNCA(patch, *control, icon, name);
285 } 328 }
286 329
287 emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader, 330 auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
288 program_id, compatibility_list, play_time_manager, patch), 331 program_id, compatibility_list, play_time_manager, patch);
289 parent_dir); 332 RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
290 } 333 }
291} 334}
292 335
@@ -360,11 +403,12 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
360 const FileSys::PatchManager patch{id, system.GetFileSystemController(), 403 const FileSys::PatchManager patch{id, system.GetFileSystemController(),
361 system.GetContentProvider()}; 404 system.GetContentProvider()};
362 405
363 emit EntryReady(MakeGameListEntry(physical_name, name, 406 auto entry = MakeGameListEntry(
364 Common::FS::GetSize(physical_name), icon, 407 physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
365 *loader, id, compatibility_list, 408 id, compatibility_list, play_time_manager, patch);
366 play_time_manager, patch), 409
367 parent_dir); 410 RecordEvent(
411 [=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
368 } 412 }
369 } else { 413 } else {
370 std::vector<u8> icon; 414 std::vector<u8> icon;
@@ -376,11 +420,12 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
376 const FileSys::PatchManager patch{program_id, system.GetFileSystemController(), 420 const FileSys::PatchManager patch{program_id, system.GetFileSystemController(),
377 system.GetContentProvider()}; 421 system.GetContentProvider()};
378 422
379 emit EntryReady(MakeGameListEntry(physical_name, name, 423 auto entry = MakeGameListEntry(
380 Common::FS::GetSize(physical_name), icon, 424 physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
381 *loader, program_id, compatibility_list, 425 program_id, compatibility_list, play_time_manager, patch);
382 play_time_manager, patch), 426
383 parent_dir); 427 RecordEvent(
428 [=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
384 } 429 }
385 } 430 }
386 } else if (is_dir) { 431 } else if (is_dir) {
@@ -399,25 +444,34 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
399} 444}
400 445
401void GameListWorker::run() { 446void GameListWorker::run() {
447 watch_list.clear();
402 provider->ClearAllEntries(); 448 provider->ClearAllEntries();
403 449
450 const auto DirEntryReady = [&](GameListDir* game_list_dir) {
451 RecordEvent([=](GameList* game_list) { game_list->AddDirEntry(game_list_dir); });
452 };
453
404 for (UISettings::GameDir& game_dir : game_dirs) { 454 for (UISettings::GameDir& game_dir : game_dirs) {
455 if (stop_requested) {
456 break;
457 }
458
405 if (game_dir.path == QStringLiteral("SDMC")) { 459 if (game_dir.path == QStringLiteral("SDMC")) {
406 auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir); 460 auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
407 emit DirEntryReady(game_list_dir); 461 DirEntryReady(game_list_dir);
408 AddTitlesToGameList(game_list_dir); 462 AddTitlesToGameList(game_list_dir);
409 } else if (game_dir.path == QStringLiteral("UserNAND")) { 463 } else if (game_dir.path == QStringLiteral("UserNAND")) {
410 auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir); 464 auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
411 emit DirEntryReady(game_list_dir); 465 DirEntryReady(game_list_dir);
412 AddTitlesToGameList(game_list_dir); 466 AddTitlesToGameList(game_list_dir);
413 } else if (game_dir.path == QStringLiteral("SysNAND")) { 467 } else if (game_dir.path == QStringLiteral("SysNAND")) {
414 auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir); 468 auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
415 emit DirEntryReady(game_list_dir); 469 DirEntryReady(game_list_dir);
416 AddTitlesToGameList(game_list_dir); 470 AddTitlesToGameList(game_list_dir);
417 } else { 471 } else {
418 watch_list.append(game_dir.path); 472 watch_list.append(game_dir.path);
419 auto* const game_list_dir = new GameListDir(game_dir); 473 auto* const game_list_dir = new GameListDir(game_dir);
420 emit DirEntryReady(game_list_dir); 474 DirEntryReady(game_list_dir);
421 ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(), 475 ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(),
422 game_dir.deep_scan, game_list_dir); 476 game_dir.deep_scan, game_list_dir);
423 ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(), 477 ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(),
@@ -425,12 +479,6 @@ void GameListWorker::run() {
425 } 479 }
426 } 480 }
427 481
428 emit Finished(watch_list); 482 RecordEvent([=](GameList* game_list) { game_list->DonePopulating(watch_list); });
429 processing_completed.Set(); 483 processing_completed.Set();
430} 484}
431
432void GameListWorker::Cancel() {
433 this->disconnect();
434 stop_requested.store(true);
435 processing_completed.Wait();
436}
diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h
index 54dc05e30..d5990fcde 100644
--- a/src/yuzu/game_list_worker.h
+++ b/src/yuzu/game_list_worker.h
@@ -4,6 +4,7 @@
4#pragma once 4#pragma once
5 5
6#include <atomic> 6#include <atomic>
7#include <deque>
7#include <memory> 8#include <memory>
8#include <string> 9#include <string>
9 10
@@ -20,6 +21,7 @@ namespace Core {
20class System; 21class System;
21} 22}
22 23
24class GameList;
23class QStandardItem; 25class QStandardItem;
24 26
25namespace FileSys { 27namespace FileSys {
@@ -46,24 +48,22 @@ public:
46 /// Starts the processing of directory tree information. 48 /// Starts the processing of directory tree information.
47 void run() override; 49 void run() override;
48 50
49 /// Tells the worker that it should no longer continue processing. Thread-safe. 51public:
50 void Cancel();
51
52signals:
53 /** 52 /**
54 * The `EntryReady` signal is emitted once an entry has been prepared and is ready 53 * Synchronously processes any events queued by the worker.
55 * to be added to the game list. 54 *
56 * @param entry_items a list with `QStandardItem`s that make up the columns of the new 55 * AddDirEntry is called on the game list for every discovered directory.
57 * entry. 56 * AddEntry is called on the game list for every discovered program.
57 * DonePopulating is called on the game list when processing completes.
58 */ 58 */
59 void DirEntryReady(GameListDir* entry_items); 59 void ProcessEvents(GameList* game_list);
60 void EntryReady(QList<QStandardItem*> entry_items, GameListDir* parent_dir);
61 60
62 /** 61signals:
63 * After the worker has traversed the game directory looking for entries, this signal is 62 void DataAvailable();
64 * emitted with a list of folders that should be watched for changes as well. 63
65 */ 64private:
66 void Finished(QStringList watch_list); 65 template <typename F>
66 void RecordEvent(F&& func);
67 67
68private: 68private:
69 void AddTitlesToGameList(GameListDir* parent_dir); 69 void AddTitlesToGameList(GameListDir* parent_dir);
@@ -84,8 +84,11 @@ private:
84 84
85 QStringList watch_list; 85 QStringList watch_list;
86 86
87 Common::Event processing_completed; 87 std::mutex lock;
88 std::condition_variable cv;
89 std::deque<std::function<void(GameList*)>> queued_events;
88 std::atomic_bool stop_requested = false; 90 std::atomic_bool stop_requested = false;
91 Common::Event processing_completed;
89 92
90 Core::System& system; 93 Core::System& system;
91}; 94};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 1431cf2fe..ce0c71021 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -159,8 +159,8 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
159#include "yuzu/util/clickable_label.h" 159#include "yuzu/util/clickable_label.h"
160#include "yuzu/vk_device_info.h" 160#include "yuzu/vk_device_info.h"
161 161
162#ifdef YUZU_DBGHELP 162#ifdef YUZU_CRASH_DUMPS
163#include "yuzu/mini_dump.h" 163#include "yuzu/breakpad.h"
164#endif 164#endif
165 165
166using namespace Common::Literals; 166using namespace Common::Literals;
@@ -1072,7 +1072,7 @@ void GMainWindow::InitializeWidgets() {
1072 }); 1072 });
1073 volume_popup->layout()->addWidget(volume_slider); 1073 volume_popup->layout()->addWidget(volume_slider);
1074 1074
1075 volume_button = new QPushButton(); 1075 volume_button = new VolumeButton();
1076 volume_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); 1076 volume_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
1077 volume_button->setFocusPolicy(Qt::NoFocus); 1077 volume_button->setFocusPolicy(Qt::NoFocus);
1078 volume_button->setCheckable(true); 1078 volume_button->setCheckable(true);
@@ -1103,6 +1103,8 @@ void GMainWindow::InitializeWidgets() {
1103 context_menu.exec(volume_button->mapToGlobal(menu_location)); 1103 context_menu.exec(volume_button->mapToGlobal(menu_location));
1104 volume_button->repaint(); 1104 volume_button->repaint();
1105 }); 1105 });
1106 connect(volume_button, &VolumeButton::VolumeChanged, this, &GMainWindow::UpdateVolumeUI);
1107
1106 statusBar()->insertPermanentWidget(0, volume_button); 1108 statusBar()->insertPermanentWidget(0, volume_button);
1107 1109
1108 // setup AA button 1110 // setup AA button
@@ -1906,7 +1908,10 @@ void GMainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
1906void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, 1908void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index,
1907 StartGameType type, AmLaunchType launch_type) { 1909 StartGameType type, AmLaunchType launch_type) {
1908 LOG_INFO(Frontend, "yuzu starting..."); 1910 LOG_INFO(Frontend, "yuzu starting...");
1909 StoreRecentFile(filename); // Put the filename on top of the list 1911
1912 if (program_id > static_cast<u64>(Service::AM::Applets::AppletProgramId::MaxProgramId)) {
1913 StoreRecentFile(filename); // Put the filename on top of the list
1914 }
1910 1915
1911 // Save configurations 1916 // Save configurations
1912 UpdateUISettings(); 1917 UpdateUISettings();
@@ -2019,7 +2024,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
2019 std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())} 2024 std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())}
2020 .filename()); 2025 .filename());
2021 } 2026 }
2022 const bool is_64bit = system->Kernel().ApplicationProcess()->Is64BitProcess(); 2027 const bool is_64bit = system->Kernel().ApplicationProcess()->Is64Bit();
2023 const auto instruction_set_suffix = is_64bit ? tr("(64-bit)") : tr("(32-bit)"); 2028 const auto instruction_set_suffix = is_64bit ? tr("(64-bit)") : tr("(32-bit)");
2024 title_name = tr("%1 %2", "%1 is the title name. %2 indicates if the title is 64-bit or 32-bit") 2029 title_name = tr("%1 %2", "%1 is the title name. %2 indicates if the title is 64-bit or 32-bit")
2025 .arg(QString::fromStdString(title_name), instruction_set_suffix) 2030 .arg(QString::fromStdString(title_name), instruction_set_suffix)
@@ -2172,6 +2177,7 @@ void GMainWindow::ShutdownGame() {
2172 return; 2177 return;
2173 } 2178 }
2174 2179
2180 play_time_manager->Stop();
2175 OnShutdownBegin(); 2181 OnShutdownBegin();
2176 OnEmulationStopTimeExpired(); 2182 OnEmulationStopTimeExpired();
2177 OnEmulationStopped(); 2183 OnEmulationStopped();
@@ -2735,7 +2741,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
2735 return; 2741 return;
2736 } 2742 }
2737 2743
2738 const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); 2744 const auto extracted = FileSys::ExtractRomFS(romfs);
2739 if (extracted == nullptr) { 2745 if (extracted == nullptr) {
2740 failed(); 2746 failed();
2741 return; 2747 return;
@@ -2906,7 +2912,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
2906 2912
2907 const std::string game_file_name = std::filesystem::path(game_path).filename().string(); 2913 const std::string game_file_name = std::filesystem::path(game_path).filename().string();
2908 // Determine full paths for icon and shortcut 2914 // Determine full paths for icon and shortcut
2909#if defined(__linux__) || defined(__FreeBSD__) 2915#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
2910 const char* home = std::getenv("HOME"); 2916 const char* home = std::getenv("HOME");
2911 const std::filesystem::path home_path = (home == nullptr ? "~" : home); 2917 const std::filesystem::path home_path = (home == nullptr ? "~" : home);
2912 const char* xdg_data_home = std::getenv("XDG_DATA_HOME"); 2918 const char* xdg_data_home = std::getenv("XDG_DATA_HOME");
@@ -2963,7 +2969,7 @@ void GMainWindow::OnGameListCreateShortcut(u64 program_id, const std::string& ga
2963 2969
2964 QImage icon_data = 2970 QImage icon_data =
2965 QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size())); 2971 QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
2966#if defined(__linux__) || defined(__FreeBSD__) 2972#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
2967 // Convert and write the icon as a PNG 2973 // Convert and write the icon as a PNG
2968 if (!icon_data.save(QString::fromStdString(icon_path.string()))) { 2974 if (!icon_data.save(QString::fromStdString(icon_path.string()))) {
2969 LOG_ERROR(Frontend, "Could not write icon as PNG to file"); 2975 LOG_ERROR(Frontend, "Could not write icon as PNG to file");
@@ -3482,7 +3488,7 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
3482} 3488}
3483 3489
3484void GMainWindow::OnExit() { 3490void GMainWindow::OnExit() {
3485 OnStopGame(); 3491 ShutdownGame();
3486} 3492}
3487 3493
3488void GMainWindow::OnSaveConfig() { 3494void GMainWindow::OnSaveConfig() {
@@ -4002,7 +4008,7 @@ bool GMainWindow::CreateShortcut(const std::string& shortcut_path, const std::st
4002 const std::string& comment, const std::string& icon_path, 4008 const std::string& comment, const std::string& icon_path,
4003 const std::string& command, const std::string& arguments, 4009 const std::string& command, const std::string& arguments,
4004 const std::string& categories, const std::string& keywords) { 4010 const std::string& categories, const std::string& keywords) {
4005#if defined(__linux__) || defined(__FreeBSD__) 4011#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
4006 // This desktop file template was writing referencing 4012 // This desktop file template was writing referencing
4007 // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html 4013 // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
4008 std::string shortcut_contents{}; 4014 std::string shortcut_contents{};
@@ -4270,7 +4276,7 @@ void GMainWindow::OnToggleStatusBar() {
4270} 4276}
4271 4277
4272void GMainWindow::OnAlbum() { 4278void GMainWindow::OnAlbum() {
4273 constexpr u64 AlbumId = 0x010000000000100Dull; 4279 constexpr u64 AlbumId = static_cast<u64>(Service::AM::Applets::AppletProgramId::PhotoViewer);
4274 auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); 4280 auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
4275 if (!bis_system) { 4281 if (!bis_system) {
4276 QMessageBox::warning(this, tr("No firmware available"), 4282 QMessageBox::warning(this, tr("No firmware available"),
@@ -4293,7 +4299,7 @@ void GMainWindow::OnAlbum() {
4293} 4299}
4294 4300
4295void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { 4301void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
4296 constexpr u64 CabinetId = 0x0100000000001002ull; 4302 constexpr u64 CabinetId = static_cast<u64>(Service::AM::Applets::AppletProgramId::Cabinet);
4297 auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); 4303 auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
4298 if (!bis_system) { 4304 if (!bis_system) {
4299 QMessageBox::warning(this, tr("No firmware available"), 4305 QMessageBox::warning(this, tr("No firmware available"),
@@ -4317,7 +4323,7 @@ void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
4317} 4323}
4318 4324
4319void GMainWindow::OnMiiEdit() { 4325void GMainWindow::OnMiiEdit() {
4320 constexpr u64 MiiEditId = 0x0100000000001009ull; 4326 constexpr u64 MiiEditId = static_cast<u64>(Service::AM::Applets::AppletProgramId::MiiEdit);
4321 auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); 4327 auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
4322 if (!bis_system) { 4328 if (!bis_system) {
4323 QMessageBox::warning(this, tr("No firmware available"), 4329 QMessageBox::warning(this, tr("No firmware available"),
@@ -4845,7 +4851,12 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
4845} 4851}
4846 4852
4847bool GMainWindow::ConfirmClose() { 4853bool GMainWindow::ConfirmClose() {
4848 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { 4854 if (emu_thread == nullptr ||
4855 UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Never) {
4856 return true;
4857 }
4858 if (!system->GetExitLocked() &&
4859 UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Based_On_Game) {
4849 return true; 4860 return true;
4850 } 4861 }
4851 const auto text = tr("Are you sure you want to close yuzu?"); 4862 const auto text = tr("Are you sure you want to close yuzu?");
@@ -4950,7 +4961,7 @@ bool GMainWindow::ConfirmChangeGame() {
4950} 4961}
4951 4962
4952bool GMainWindow::ConfirmForceLockedExit() { 4963bool GMainWindow::ConfirmForceLockedExit() {
4953 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { 4964 if (emu_thread == nullptr) {
4954 return true; 4965 return true;
4955 } 4966 }
4956 const auto text = tr("The currently running application has requested yuzu to not exit.\n\n" 4967 const auto text = tr("The currently running application has requested yuzu to not exit.\n\n"
@@ -5126,6 +5137,32 @@ void GMainWindow::changeEvent(QEvent* event) {
5126 QWidget::changeEvent(event); 5137 QWidget::changeEvent(event);
5127} 5138}
5128 5139
5140void VolumeButton::wheelEvent(QWheelEvent* event) {
5141
5142 int num_degrees = event->angleDelta().y() / 8;
5143 int num_steps = (num_degrees / 15) * scroll_multiplier;
5144 // Stated in QT docs: Most mouse types work in steps of 15 degrees, in which case the delta
5145 // value is a multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
5146
5147 if (num_steps > 0) {
5148 Settings::values.volume.SetValue(
5149 std::min(200, Settings::values.volume.GetValue() + num_steps));
5150 } else {
5151 Settings::values.volume.SetValue(
5152 std::max(0, Settings::values.volume.GetValue() + num_steps));
5153 }
5154
5155 scroll_multiplier = std::min(MaxMultiplier, scroll_multiplier * 2);
5156 scroll_timer.start(100); // reset the multiplier if no scroll event occurs within 100 ms
5157
5158 emit VolumeChanged();
5159 event->accept();
5160}
5161
5162void VolumeButton::ResetMultiplier() {
5163 scroll_multiplier = 1;
5164}
5165
5129#ifdef main 5166#ifdef main
5130#undef main 5167#undef main
5131#endif 5168#endif
@@ -5187,22 +5224,15 @@ int main(int argc, char* argv[]) {
5187 return 0; 5224 return 0;
5188 } 5225 }
5189 5226
5190#ifdef YUZU_DBGHELP
5191 PROCESS_INFORMATION pi;
5192 if (!is_child && Settings::values.create_crash_dumps.GetValue() &&
5193 MiniDump::SpawnDebuggee(argv[0], pi)) {
5194 // Delete the config object so that it doesn't save when the program exits
5195 config.reset(nullptr);
5196 MiniDump::DebugDebuggee(pi);
5197 return 0;
5198 }
5199#endif
5200
5201 if (StartupChecks(argv[0], &has_broken_vulkan, 5227 if (StartupChecks(argv[0], &has_broken_vulkan,
5202 Settings::values.perform_vulkan_check.GetValue())) { 5228 Settings::values.perform_vulkan_check.GetValue())) {
5203 return 0; 5229 return 0;
5204 } 5230 }
5205 5231
5232#ifdef YUZU_CRASH_DUMPS
5233 Breakpad::InstallCrashHandler();
5234#endif
5235
5206 Common::DetachedTasks detached_tasks; 5236 Common::DetachedTasks detached_tasks;
5207 MicroProfileOnThreadCreate("Frontend"); 5237 MicroProfileOnThreadCreate("Frontend");
5208 SCOPE_EXIT({ MicroProfileShutdown(); }); 5238 SCOPE_EXIT({ MicroProfileShutdown(); });
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 270a40c5f..f9c6efe4f 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -8,6 +8,7 @@
8 8
9#include <QMainWindow> 9#include <QMainWindow>
10#include <QMessageBox> 10#include <QMessageBox>
11#include <QPushButton>
11#include <QTimer> 12#include <QTimer>
12#include <QTranslator> 13#include <QTranslator>
13 14
@@ -137,6 +138,28 @@ namespace VkDeviceInfo {
137class Record; 138class Record;
138} 139}
139 140
141class VolumeButton : public QPushButton {
142 Q_OBJECT
143public:
144 explicit VolumeButton(QWidget* parent = nullptr) : QPushButton(parent), scroll_multiplier(1) {
145 connect(&scroll_timer, &QTimer::timeout, this, &VolumeButton::ResetMultiplier);
146 }
147
148signals:
149 void VolumeChanged();
150
151protected:
152 void wheelEvent(QWheelEvent* event) override;
153
154private slots:
155 void ResetMultiplier();
156
157private:
158 int scroll_multiplier;
159 QTimer scroll_timer;
160 constexpr static int MaxMultiplier = 8;
161};
162
140class GMainWindow : public QMainWindow { 163class GMainWindow : public QMainWindow {
141 Q_OBJECT 164 Q_OBJECT
142 165
@@ -481,7 +504,7 @@ private:
481 QPushButton* dock_status_button = nullptr; 504 QPushButton* dock_status_button = nullptr;
482 QPushButton* filter_status_button = nullptr; 505 QPushButton* filter_status_button = nullptr;
483 QPushButton* aa_status_button = nullptr; 506 QPushButton* aa_status_button = nullptr;
484 QPushButton* volume_button = nullptr; 507 VolumeButton* volume_button = nullptr;
485 QWidget* volume_popup = nullptr; 508 QWidget* volume_popup = nullptr;
486 QSlider* volume_slider = nullptr; 509 QSlider* volume_slider = nullptr;
487 QTimer status_bar_update_timer; 510 QTimer status_bar_update_timer;
diff --git a/src/yuzu/mini_dump.cpp b/src/yuzu/mini_dump.cpp
deleted file mode 100644
index a34dc6a9c..000000000
--- a/src/yuzu/mini_dump.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
1// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <cstdio>
5#include <cstring>
6#include <ctime>
7#include <filesystem>
8#include <fmt/format.h>
9#include <windows.h>
10#include "yuzu/mini_dump.h"
11#include "yuzu/startup_checks.h"
12
13// dbghelp.h must be included after windows.h
14#include <dbghelp.h>
15
16namespace MiniDump {
17
18void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_INFORMATION* info,
19 EXCEPTION_POINTERS* pep) {
20 char file_name[255];
21 const std::time_t the_time = std::time(nullptr);
22 std::strftime(file_name, 255, "yuzu-crash-%Y%m%d%H%M%S.dmp", std::localtime(&the_time));
23
24 // Open the file
25 HANDLE file_handle = CreateFileA(file_name, GENERIC_READ | GENERIC_WRITE, 0, nullptr,
26 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
27
28 if (file_handle == nullptr || file_handle == INVALID_HANDLE_VALUE) {
29 fmt::print(stderr, "CreateFileA failed. Error: {}", GetLastError());
30 return;
31 }
32
33 // Create the minidump
34 const MINIDUMP_TYPE dump_type = MiniDumpNormal;
35
36 const bool write_dump_status = MiniDumpWriteDump(process_handle, process_id, file_handle,
37 dump_type, (pep != 0) ? info : 0, 0, 0);
38
39 if (write_dump_status) {
40 fmt::print(stderr, "MiniDump created: {}", file_name);
41 } else {
42 fmt::print(stderr, "MiniDumpWriteDump failed. Error: {}", GetLastError());
43 }
44
45 // Close the file
46 CloseHandle(file_handle);
47}
48
49void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi) {
50 EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord;
51
52 HANDLE thread_handle = OpenThread(THREAD_GET_CONTEXT, false, deb_ev.dwThreadId);
53 if (thread_handle == nullptr) {
54 fmt::print(stderr, "OpenThread failed ({})", GetLastError());
55 return;
56 }
57
58 // Get child process context
59 CONTEXT context = {};
60 context.ContextFlags = CONTEXT_ALL;
61 if (!GetThreadContext(thread_handle, &context)) {
62 fmt::print(stderr, "GetThreadContext failed ({})", GetLastError());
63 return;
64 }
65
66 // Create exception pointers for minidump
67 EXCEPTION_POINTERS ep;
68 ep.ExceptionRecord = &record;
69 ep.ContextRecord = &context;
70
71 MINIDUMP_EXCEPTION_INFORMATION info;
72 info.ThreadId = deb_ev.dwThreadId;
73 info.ExceptionPointers = &ep;
74 info.ClientPointers = false;
75
76 CreateMiniDump(pi.hProcess, pi.dwProcessId, &info, &ep);
77
78 if (CloseHandle(thread_handle) == 0) {
79 fmt::print(stderr, "error: CloseHandle(thread_handle) failed ({})", GetLastError());
80 }
81}
82
83bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi) {
84 std::memset(&pi, 0, sizeof(pi));
85
86 // Don't debug if we are already being debugged
87 if (IsDebuggerPresent()) {
88 return false;
89 }
90
91 if (!SpawnChild(arg0, &pi, 0)) {
92 fmt::print(stderr, "warning: continuing without crash dumps");
93 return false;
94 }
95
96 const bool can_debug = DebugActiveProcess(pi.dwProcessId);
97 if (!can_debug) {
98 fmt::print(stderr,
99 "warning: DebugActiveProcess failed ({}), continuing without crash dumps",
100 GetLastError());
101 return false;
102 }
103
104 return true;
105}
106
107static const char* ExceptionName(DWORD exception) {
108 switch (exception) {
109 case EXCEPTION_ACCESS_VIOLATION:
110 return "EXCEPTION_ACCESS_VIOLATION";
111 case EXCEPTION_DATATYPE_MISALIGNMENT:
112 return "EXCEPTION_DATATYPE_MISALIGNMENT";
113 case EXCEPTION_BREAKPOINT:
114 return "EXCEPTION_BREAKPOINT";
115 case EXCEPTION_SINGLE_STEP:
116 return "EXCEPTION_SINGLE_STEP";
117 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
118 return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
119 case EXCEPTION_FLT_DENORMAL_OPERAND:
120 return "EXCEPTION_FLT_DENORMAL_OPERAND";
121 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
122 return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
123 case EXCEPTION_FLT_INEXACT_RESULT:
124 return "EXCEPTION_FLT_INEXACT_RESULT";
125 case EXCEPTION_FLT_INVALID_OPERATION:
126 return "EXCEPTION_FLT_INVALID_OPERATION";
127 case EXCEPTION_FLT_OVERFLOW:
128 return "EXCEPTION_FLT_OVERFLOW";
129 case EXCEPTION_FLT_STACK_CHECK:
130 return "EXCEPTION_FLT_STACK_CHECK";
131 case EXCEPTION_FLT_UNDERFLOW:
132 return "EXCEPTION_FLT_UNDERFLOW";
133 case EXCEPTION_INT_DIVIDE_BY_ZERO:
134 return "EXCEPTION_INT_DIVIDE_BY_ZERO";
135 case EXCEPTION_INT_OVERFLOW:
136 return "EXCEPTION_INT_OVERFLOW";
137 case EXCEPTION_PRIV_INSTRUCTION:
138 return "EXCEPTION_PRIV_INSTRUCTION";
139 case EXCEPTION_IN_PAGE_ERROR:
140 return "EXCEPTION_IN_PAGE_ERROR";
141 case EXCEPTION_ILLEGAL_INSTRUCTION:
142 return "EXCEPTION_ILLEGAL_INSTRUCTION";
143 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
144 return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
145 case EXCEPTION_STACK_OVERFLOW:
146 return "EXCEPTION_STACK_OVERFLOW";
147 case EXCEPTION_INVALID_DISPOSITION:
148 return "EXCEPTION_INVALID_DISPOSITION";
149 case EXCEPTION_GUARD_PAGE:
150 return "EXCEPTION_GUARD_PAGE";
151 case EXCEPTION_INVALID_HANDLE:
152 return "EXCEPTION_INVALID_HANDLE";
153 default:
154 return "unknown exception type";
155 }
156}
157
158void DebugDebuggee(PROCESS_INFORMATION& pi) {
159 DEBUG_EVENT deb_ev = {};
160
161 while (deb_ev.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT) {
162 const bool wait_success = WaitForDebugEvent(&deb_ev, INFINITE);
163 if (!wait_success) {
164 fmt::print(stderr, "error: WaitForDebugEvent failed ({})", GetLastError());
165 return;
166 }
167
168 switch (deb_ev.dwDebugEventCode) {
169 case OUTPUT_DEBUG_STRING_EVENT:
170 case CREATE_PROCESS_DEBUG_EVENT:
171 case CREATE_THREAD_DEBUG_EVENT:
172 case EXIT_PROCESS_DEBUG_EVENT:
173 case EXIT_THREAD_DEBUG_EVENT:
174 case LOAD_DLL_DEBUG_EVENT:
175 case RIP_EVENT:
176 case UNLOAD_DLL_DEBUG_EVENT:
177 // Continue on all other debug events
178 ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_CONTINUE);
179 break;
180 case EXCEPTION_DEBUG_EVENT:
181 EXCEPTION_RECORD& record = deb_ev.u.Exception.ExceptionRecord;
182
183 // We want to generate a crash dump if we are seeing the same exception again.
184 if (!deb_ev.u.Exception.dwFirstChance) {
185 fmt::print(stderr, "Creating MiniDump on ExceptionCode: 0x{:08x} {}\n",
186 record.ExceptionCode, ExceptionName(record.ExceptionCode));
187 DumpFromDebugEvent(deb_ev, pi);
188 }
189
190 // Continue without handling the exception.
191 // Lets the debuggee use its own exception handler.
192 // - If one does not exist, we will see the exception once more where we make a minidump
193 // for. Then when it reaches here again, yuzu will probably crash.
194 // - DBG_CONTINUE on an exception that the debuggee does not handle can set us up for an
195 // infinite loop of exceptions.
196 ContinueDebugEvent(deb_ev.dwProcessId, deb_ev.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
197 break;
198 }
199 }
200}
201
202} // namespace MiniDump
diff --git a/src/yuzu/mini_dump.h b/src/yuzu/mini_dump.h
deleted file mode 100644
index d6b6cca84..000000000
--- a/src/yuzu/mini_dump.h
+++ /dev/null
@@ -1,19 +0,0 @@
1// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <windows.h>
7
8#include <dbghelp.h>
9
10namespace MiniDump {
11
12void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_INFORMATION* info,
13 EXCEPTION_POINTERS* pep);
14
15void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi);
16bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi);
17void DebugDebuggee(PROCESS_INFORMATION& pi);
18
19} // namespace MiniDump
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index b62ff620c..77d992c54 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -93,10 +93,6 @@ struct Values {
93 Setting<bool> show_filter_bar{linkage, true, "showFilterBar", Category::Ui}; 93 Setting<bool> show_filter_bar{linkage, true, "showFilterBar", Category::Ui};
94 Setting<bool> show_status_bar{linkage, true, "showStatusBar", Category::Ui}; 94 Setting<bool> show_status_bar{linkage, true, "showStatusBar", Category::Ui};
95 95
96 Setting<bool> confirm_before_closing{
97 linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default,
98 true, true};
99
100 SwitchableSetting<ConfirmStop> confirm_before_stopping{linkage, 96 SwitchableSetting<ConfirmStop> confirm_before_stopping{linkage,
101 ConfirmStop::Ask_Always, 97 ConfirmStop::Ask_Always,
102 "confirmStop", 98 "confirmStop",