diff options
Diffstat (limited to 'src')
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 | ||
| 6 | import android.app.Dialog | 6 | import android.app.Dialog |
| 7 | import android.content.DialogInterface | 7 | import android.content.DialogInterface |
| 8 | import android.net.Uri | ||
| 8 | import android.os.Bundle | 9 | import android.os.Bundle |
| 9 | import android.text.Html | 10 | import android.text.Html |
| 10 | import android.text.method.LinkMovementMethod | 11 | import android.text.method.LinkMovementMethod |
| @@ -16,7 +17,7 @@ import androidx.fragment.app.DialogFragment | |||
| 16 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | 17 | import com.google.android.material.dialog.MaterialAlertDialogBuilder |
| 17 | import java.lang.ref.WeakReference | 18 | import java.lang.ref.WeakReference |
| 18 | import org.yuzu.yuzu_emu.activities.EmulationActivity | 19 | import org.yuzu.yuzu_emu.activities.EmulationActivity |
| 19 | import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath | 20 | import org.yuzu.yuzu_emu.utils.DocumentsTree |
| 20 | import org.yuzu.yuzu_emu.utils.FileUtil | 21 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 21 | import org.yuzu.yuzu_emu.utils.Log | 22 | import org.yuzu.yuzu_emu.utils.Log |
| 22 | import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable | 23 | import 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 | |||
| 11 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization | 11 | import org.yuzu.yuzu_emu.utils.DirectoryInitialization |
| 12 | import org.yuzu.yuzu_emu.utils.DocumentsTree | 12 | import org.yuzu.yuzu_emu.utils.DocumentsTree |
| 13 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper | 13 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper |
| 14 | import org.yuzu.yuzu_emu.utils.Log | ||
| 14 | 15 | ||
| 15 | fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir | 16 | fun 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 | |||
| 45 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 45 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
| 46 | import org.yuzu.yuzu_emu.model.EmulationViewModel | 46 | import org.yuzu.yuzu_emu.model.EmulationViewModel |
| 47 | import org.yuzu.yuzu_emu.model.Game | 47 | import org.yuzu.yuzu_emu.model.Game |
| 48 | import org.yuzu.yuzu_emu.utils.ControllerMappingHelper | ||
| 49 | import org.yuzu.yuzu_emu.utils.ForegroundService | 48 | import org.yuzu.yuzu_emu.utils.ForegroundService |
| 50 | import org.yuzu.yuzu_emu.utils.InputHandler | 49 | import org.yuzu.yuzu_emu.utils.InputHandler |
| 50 | import org.yuzu.yuzu_emu.utils.Log | ||
| 51 | import org.yuzu.yuzu_emu.utils.MemoryUtil | 51 | import org.yuzu.yuzu_emu.utils.MemoryUtil |
| 52 | import org.yuzu.yuzu_emu.utils.NfcReader | 52 | import org.yuzu.yuzu_emu.utils.NfcReader |
| 53 | import org.yuzu.yuzu_emu.utils.ThemeHelper | 53 | import org.yuzu.yuzu_emu.utils.ThemeHelper |
| @@ -57,17 +57,16 @@ import kotlin.math.roundToInt | |||
| 57 | class EmulationActivity : AppCompatActivity(), SensorEventListener { | 57 | class 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 | |||
| 4 | package org.yuzu.yuzu_emu.adapters | ||
| 5 | |||
| 6 | import android.view.LayoutInflater | ||
| 7 | import android.view.View | ||
| 8 | import android.view.ViewGroup | ||
| 9 | import android.widget.Toast | ||
| 10 | import androidx.core.content.res.ResourcesCompat | ||
| 11 | import androidx.fragment.app.FragmentActivity | ||
| 12 | import androidx.navigation.findNavController | ||
| 13 | import androidx.recyclerview.widget.RecyclerView | ||
| 14 | import org.yuzu.yuzu_emu.HomeNavigationDirections | ||
| 15 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 16 | import org.yuzu.yuzu_emu.R | ||
| 17 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 18 | import org.yuzu.yuzu_emu.databinding.CardAppletOptionBinding | ||
| 19 | import org.yuzu.yuzu_emu.model.Applet | ||
| 20 | import org.yuzu.yuzu_emu.model.AppletInfo | ||
| 21 | import org.yuzu.yuzu_emu.model.Game | ||
| 22 | |||
| 23 | class 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 | |||
| 4 | package org.yuzu.yuzu_emu.adapters | ||
| 5 | |||
| 6 | import android.view.LayoutInflater | ||
| 7 | import android.view.View | ||
| 8 | import android.view.ViewGroup | ||
| 9 | import androidx.core.content.res.ResourcesCompat | ||
| 10 | import androidx.fragment.app.Fragment | ||
| 11 | import androidx.navigation.fragment.findNavController | ||
| 12 | import androidx.recyclerview.widget.RecyclerView | ||
| 13 | import org.yuzu.yuzu_emu.HomeNavigationDirections | ||
| 14 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 15 | import org.yuzu.yuzu_emu.R | ||
| 16 | import org.yuzu.yuzu_emu.YuzuApplication | ||
| 17 | import org.yuzu.yuzu_emu.databinding.DialogListItemBinding | ||
| 18 | import org.yuzu.yuzu_emu.model.CabinetMode | ||
| 19 | import org.yuzu.yuzu_emu.adapters.CabinetLauncherDialogAdapter.CabinetModeViewHolder | ||
| 20 | import org.yuzu.yuzu_emu.model.AppletInfo | ||
| 21 | import org.yuzu.yuzu_emu.model.Game | ||
| 22 | |||
| 23 | class 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 | |||
| 4 | package org.yuzu.yuzu_emu.fragments | ||
| 5 | |||
| 6 | import android.os.Bundle | ||
| 7 | import android.view.LayoutInflater | ||
| 8 | import android.view.View | ||
| 9 | import android.view.ViewGroup | ||
| 10 | import androidx.core.view.ViewCompat | ||
| 11 | import androidx.core.view.WindowInsetsCompat | ||
| 12 | import androidx.core.view.updatePadding | ||
| 13 | import androidx.fragment.app.Fragment | ||
| 14 | import androidx.fragment.app.activityViewModels | ||
| 15 | import androidx.navigation.findNavController | ||
| 16 | import androidx.recyclerview.widget.GridLayoutManager | ||
| 17 | import com.google.android.material.transition.MaterialSharedAxis | ||
| 18 | import org.yuzu.yuzu_emu.R | ||
| 19 | import org.yuzu.yuzu_emu.adapters.AppletAdapter | ||
| 20 | import org.yuzu.yuzu_emu.databinding.FragmentAppletLauncherBinding | ||
| 21 | import org.yuzu.yuzu_emu.model.Applet | ||
| 22 | import org.yuzu.yuzu_emu.model.AppletInfo | ||
| 23 | import org.yuzu.yuzu_emu.model.HomeViewModel | ||
| 24 | |||
| 25 | class 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 | |||
| 4 | package org.yuzu.yuzu_emu.fragments | ||
| 5 | |||
| 6 | import android.app.Dialog | ||
| 7 | import android.os.Bundle | ||
| 8 | import android.view.LayoutInflater | ||
| 9 | import android.view.View | ||
| 10 | import android.view.ViewGroup | ||
| 11 | import androidx.fragment.app.DialogFragment | ||
| 12 | import androidx.recyclerview.widget.LinearLayoutManager | ||
| 13 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | ||
| 14 | import org.yuzu.yuzu_emu.R | ||
| 15 | import org.yuzu.yuzu_emu.adapters.CabinetLauncherDialogAdapter | ||
| 16 | import org.yuzu.yuzu_emu.databinding.DialogListBinding | ||
| 17 | |||
| 18 | class 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 | |||
| 10 | import android.content.SharedPreferences | 10 | import android.content.SharedPreferences |
| 11 | import android.content.pm.ActivityInfo | 11 | import android.content.pm.ActivityInfo |
| 12 | import android.content.res.Configuration | 12 | import android.content.res.Configuration |
| 13 | import android.graphics.Color | ||
| 14 | import android.net.Uri | 13 | import android.net.Uri |
| 15 | import android.os.Bundle | 14 | import android.os.Bundle |
| 16 | import android.os.Handler | 15 | import android.os.Handler |
| 17 | import android.os.Looper | 16 | import android.os.Looper |
| 17 | import android.os.SystemClock | ||
| 18 | import android.view.* | 18 | import android.view.* |
| 19 | import android.widget.TextView | 19 | import android.widget.TextView |
| 20 | import android.widget.Toast | 20 | import android.widget.Toast |
| @@ -25,6 +25,7 @@ import androidx.core.graphics.Insets | |||
| 25 | import androidx.core.view.ViewCompat | 25 | import androidx.core.view.ViewCompat |
| 26 | import androidx.core.view.WindowInsetsCompat | 26 | import androidx.core.view.WindowInsetsCompat |
| 27 | import androidx.drawerlayout.widget.DrawerLayout | 27 | import androidx.drawerlayout.widget.DrawerLayout |
| 28 | import androidx.drawerlayout.widget.DrawerLayout.DrawerListener | ||
| 28 | import androidx.fragment.app.Fragment | 29 | import androidx.fragment.app.Fragment |
| 29 | import androidx.fragment.app.activityViewModels | 30 | import androidx.fragment.app.activityViewModels |
| 30 | import androidx.lifecycle.Lifecycle | 31 | import 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 | |||
| 26 | import androidx.fragment.app.activityViewModels | 26 | import androidx.fragment.app.activityViewModels |
| 27 | import androidx.navigation.findNavController | 27 | import androidx.navigation.findNavController |
| 28 | import androidx.navigation.fragment.findNavController | 28 | import androidx.navigation.fragment.findNavController |
| 29 | import androidx.recyclerview.widget.LinearLayoutManager | 29 | import androidx.recyclerview.widget.GridLayoutManager |
| 30 | import com.google.android.material.transition.MaterialSharedAxis | 30 | import com.google.android.material.transition.MaterialSharedAxis |
| 31 | import org.yuzu.yuzu_emu.BuildConfig | 31 | import org.yuzu.yuzu_emu.BuildConfig |
| 32 | import org.yuzu.yuzu_emu.HomeNavigationDirections | 32 | import org.yuzu.yuzu_emu.HomeNavigationDirections |
| 33 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 33 | import org.yuzu.yuzu_emu.R | 34 | import org.yuzu.yuzu_emu.R |
| 34 | import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter | 35 | import org.yuzu.yuzu_emu.adapters.HomeSettingAdapter |
| 35 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding | 36 | import org.yuzu.yuzu_emu.databinding.FragmentHomeSettingsBinding |
| @@ -41,6 +42,7 @@ import org.yuzu.yuzu_emu.model.HomeViewModel | |||
| 41 | import org.yuzu.yuzu_emu.ui.main.MainActivity | 42 | import org.yuzu.yuzu_emu.ui.main.MainActivity |
| 42 | import org.yuzu.yuzu_emu.utils.FileUtil | 43 | import org.yuzu.yuzu_emu.utils.FileUtil |
| 43 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper | 44 | import org.yuzu.yuzu_emu.utils.GpuDriverHelper |
| 45 | import org.yuzu.yuzu_emu.utils.Log | ||
| 44 | 46 | ||
| 45 | class HomeSettingsFragment : Fragment() { | 47 | class 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 | |||
| 8 | import android.content.Intent | 8 | import android.content.Intent |
| 9 | import android.net.Uri | 9 | import android.net.Uri |
| 10 | import android.os.Bundle | 10 | import android.os.Bundle |
| 11 | import android.text.Html | ||
| 11 | import androidx.fragment.app.DialogFragment | 12 | import androidx.fragment.app.DialogFragment |
| 12 | import androidx.fragment.app.FragmentActivity | 13 | import androidx.fragment.app.FragmentActivity |
| 13 | import androidx.fragment.app.activityViewModels | 14 | import 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 | |||
| 4 | package org.yuzu.yuzu_emu.model | ||
| 5 | |||
| 6 | import androidx.annotation.DrawableRes | ||
| 7 | import androidx.annotation.StringRes | ||
| 8 | import org.yuzu.yuzu_emu.R | ||
| 9 | |||
| 10 | data 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 | ||
| 19 | enum 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 | ||
| 45 | enum 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 |
| 13 | class Game( | 13 | class 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 | |||
| 14 | import kotlinx.coroutines.flow.StateFlow | 14 | import kotlinx.coroutines.flow.StateFlow |
| 15 | import kotlinx.coroutines.launch | 15 | import kotlinx.coroutines.launch |
| 16 | import kotlinx.coroutines.withContext | 16 | import kotlinx.coroutines.withContext |
| 17 | import kotlinx.serialization.ExperimentalSerializationApi | ||
| 18 | import kotlinx.serialization.MissingFieldException | ||
| 19 | import kotlinx.serialization.decodeFromString | 17 | import kotlinx.serialization.decodeFromString |
| 20 | import kotlinx.serialization.json.Json | 18 | import kotlinx.serialization.json.Json |
| 21 | import org.yuzu.yuzu_emu.NativeLibrary | 19 | import org.yuzu.yuzu_emu.NativeLibrary |
| 22 | import org.yuzu.yuzu_emu.YuzuApplication | 20 | import org.yuzu.yuzu_emu.YuzuApplication |
| 23 | import org.yuzu.yuzu_emu.utils.GameHelper | 21 | import org.yuzu.yuzu_emu.utils.GameHelper |
| 22 | import org.yuzu.yuzu_emu.utils.GameMetadata | ||
| 24 | 23 | ||
| 25 | @OptIn(ExperimentalSerializationApi::class) | ||
| 26 | class GamesViewModel : ViewModel() { | 24 | class 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 | |||
| 4 | package org.yuzu.yuzu_emu.utils | ||
| 5 | |||
| 6 | import android.view.InputDevice | ||
| 7 | import android.view.KeyEvent | ||
| 8 | import android.view.MotionEvent | ||
| 9 | |||
| 10 | /** | ||
| 11 | * Some controllers have incorrect mappings. This class has special-case fixes for them. | ||
| 12 | */ | ||
| 13 | class 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 | |||
| 18 | import coil.memory.MemoryCache | 18 | import coil.memory.MemoryCache |
| 19 | import coil.request.ImageRequest | 19 | import coil.request.ImageRequest |
| 20 | import coil.request.Options | 20 | import coil.request.Options |
| 21 | import org.yuzu.yuzu_emu.NativeLibrary | ||
| 22 | import org.yuzu.yuzu_emu.R | 21 | import org.yuzu.yuzu_emu.R |
| 23 | import org.yuzu.yuzu_emu.YuzuApplication | 22 | import org.yuzu.yuzu_emu.YuzuApplication |
| 24 | import org.yuzu.yuzu_emu.model.Game | 23 | import 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 | |||
| 4 | package org.yuzu.yuzu_emu.utils | ||
| 5 | |||
| 6 | object 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 | ||
| 4 | package org.yuzu.yuzu_emu.utils | 4 | package org.yuzu.yuzu_emu.utils |
| 5 | 5 | ||
| 6 | import android.view.InputDevice | ||
| 6 | import android.view.KeyEvent | 7 | import android.view.KeyEvent |
| 7 | import android.view.MotionEvent | 8 | import android.view.MotionEvent |
| 8 | import kotlin.math.sqrt | 9 | import kotlin.math.sqrt |
| 9 | import org.yuzu.yuzu_emu.NativeLibrary | 10 | import org.yuzu.yuzu_emu.NativeLibrary |
| 10 | 11 | ||
| 11 | class InputHandler { | 12 | object 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 | ||
| 4 | package org.yuzu.yuzu_emu.utils | 4 | package org.yuzu.yuzu_emu.utils |
| 5 | 5 | ||
| 6 | import android.util.Log | 6 | import android.os.Build |
| 7 | import 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 | */ | ||
| 14 | object Log { | 8 | object 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 | ||
| 21 | set_property(TARGET yuzu-android PROPERTY IMPORTED_LOCATION ${FFmpeg_LIBRARY_DIR}) | 24 | set_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 | |||
| 12 | struct 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 | |||
| 21 | std::unordered_map<std::string, RomMetadata> m_rom_metadata_cache; | ||
| 22 | |||
| 23 | RomMetadata 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 | |||
| 64 | RomMetadata 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 | |||
| 72 | extern "C" { | ||
| 73 | |||
| 74 | jstring 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 | |||
| 79 | jstring 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 | |||
| 84 | jstring 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 | |||
| 89 | jstring 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 | |||
| 94 | jbyteArray 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 | |||
| 103 | jboolean 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 | |||
| 108 | void 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 | ||
| 69 | namespace { | 64 | static EmulationSession s_instance; |
| 70 | 65 | ||
| 71 | class EmulationSession final { | 66 | EmulationSession::EmulationSession() { |
| 72 | public: | 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() { | 70 | EmulationSession& EmulationSession::GetInstance() { |
| 88 | return m_system; | 71 | return s_instance; |
| 89 | } | 72 | } |
| 90 | 73 | ||
| 91 | const EmuWindow_Android& Window() const { | 74 | const Core::System& EmulationSession::System() const { |
| 92 | return *m_window; | 75 | return m_system; |
| 93 | } | 76 | } |
| 94 | 77 | ||
| 95 | EmuWindow_Android& Window() { | 78 | Core::System& EmulationSession::System() { |
| 96 | return *m_window; | 79 | return m_system; |
| 97 | } | 80 | } |
| 98 | 81 | ||
| 99 | ANativeWindow* NativeWindow() const { | 82 | const EmuWindow_Android& EmulationSession::Window() const { |
| 100 | return m_native_window; | 83 | return *m_window; |
| 101 | } | 84 | } |
| 102 | 85 | ||
| 103 | void SetNativeWindow(ANativeWindow* native_window) { | 86 | EmuWindow_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) { | 90 | ANativeWindow* 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; | 94 | void 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()) { | 98 | int 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) { | 162 | void 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; | 194 | bool EmulationSession::IsRunning() const { |
| 195 | return m_is_running; | ||
| 196 | } | ||
| 317 | 197 | ||
| 318 | // Unload user input. | 198 | bool 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 | 202 | const 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. | 207 | void 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() { | 214 | void 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()); | 250 | void 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 | |||
| 268 | Core::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) { | 314 | void 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() { | 337 | void 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) { | 343 | void 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) { | 349 | void 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(); | 355 | void 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 | |||
| 389 | bool 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 | ||
| 470 | private: | 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) { | 403 | void 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); | 408 | void 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 | ||
| 504 | private: | 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 | ||
| 524 | private: | 438 | void 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 | 443 | SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() { |
| 548 | std::shared_ptr<Common::DynamicLibrary> m_vulkan_library; | 444 | return m_software_keyboard; |
| 445 | } | ||
| 549 | 446 | ||
| 550 | // Synchronization | 447 | void 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; | 455 | void EmulationSession::OnEmulationStarted() { |
| 456 | JNIEnv* env = IDCache::GetEnvForThread(); | ||
| 457 | env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnEmulationStarted()); | ||
| 458 | } | ||
| 557 | 459 | ||
| 558 | } // Anonymous namespace | 460 | void 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 | ||
| 560 | static Core::SystemResultStatus RunEmulation(const std::string& filepath) { | 466 | static 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 | ||
| 660 | void Java_org_yuzu_yuzu_1emu_NativeLibrary_resetRomMetadata(JNIEnv* env, jclass clazz) { | ||
| 661 | EmulationSession::GetInstance().ResetRomMetadata(); | ||
| 662 | } | ||
| 663 | |||
| 664 | jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isRunning(JNIEnv* env, jclass clazz) { | 562 | jboolean 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 | ||
| 769 | jbyteArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getIcon(JNIEnv* env, jclass clazz, | 667 | void 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 | |||
| 778 | jstring 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 | |||
| 784 | jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getDescription(JNIEnv* env, jclass clazz, | ||
| 785 | jstring j_filename) { | ||
| 786 | return j_filename; | ||
| 787 | } | ||
| 788 | |||
| 789 | jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGameId(JNIEnv* env, jclass clazz, | ||
| 790 | jstring j_filename) { | ||
| 791 | return j_filename; | ||
| 792 | } | ||
| 793 | |||
| 794 | jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getRegions(JNIEnv* env, jclass clazz, | ||
| 795 | jstring j_filename) { | ||
| 796 | return env->NewStringUTF(""); | ||
| 797 | } | ||
| 798 | |||
| 799 | jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCompany(JNIEnv* env, jclass clazz, | ||
| 800 | jstring j_filename) { | ||
| 801 | return env->NewStringUTF(""); | ||
| 802 | } | ||
| 803 | |||
| 804 | jboolean 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 | |||
| 809 | void 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 | ||
| 816 | jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass clazz) { | 678 | jint 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 | ||
| 763 | jstring 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 | |||
| 780 | void 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 | |||
| 786 | void 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 | |||
| 792 | jboolean 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 | |||
| 16 | class EmulationSession final { | ||
| 17 | public: | ||
| 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 | |||
| 55 | private: | ||
| 56 | static void LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, int max); | ||
| 57 | static void OnEmulationStarted(); | ||
| 58 | static void OnEmulationStopped(Core::SystemResultStatus result); | ||
| 59 | |||
| 60 | private: | ||
| 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 | |||
| 9 | extern "C" { | ||
| 10 | |||
| 11 | void Java_org_yuzu_yuzu_1emu_utils_Log_debug(JNIEnv* env, jobject obj, jstring jmessage) { | ||
| 12 | LOG_DEBUG(Frontend, "{}", GetJString(env, jmessage)); | ||
| 13 | } | ||
| 14 | |||
| 15 | void Java_org_yuzu_yuzu_1emu_utils_Log_warning(JNIEnv* env, jobject obj, jstring jmessage) { | ||
| 16 | LOG_WARNING(Frontend, "{}", GetJString(env, jmessage)); | ||
| 17 | } | ||
| 18 | |||
| 19 | void Java_org_yuzu_yuzu_1emu_utils_Log_info(JNIEnv* env, jobject obj, jstring jmessage) { | ||
| 20 | LOG_INFO(Frontend, "{}", GetJString(env, jmessage)); | ||
| 21 | } | ||
| 22 | |||
| 23 | void Java_org_yuzu_yuzu_1emu_utils_Log_error(JNIEnv* env, jobject obj, jstring jmessage) { | ||
| 24 | LOG_ERROR(Frontend, "{}", GetJString(env, jmessage)); | ||
| 25 | } | ||
| 26 | |||
| 27 | void 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">اختر مل٠<b>prod.keys</b> من الزر ادناه</string> | ||
| 17 | <string name="select_keys">إختيار Ø§Ù„Ù…ÙØ§ØªÙŠØ</string> | ||
| 18 | <string name="games">الألعاب</string> | ||
| 19 | <string name="games_description">اختر مجلد <b>العابك</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">ئەم نەرمەکاڵایە یارییەکانی کۆنسۆلی نینتێندۆ سویچ کارپێدەکات. هیچ ناونیشانێکی یاری Ùˆ کلیلی تێدا نییە..<br /><br />Ù¾ÛŽØ´ ئەوەی دەست Ù¾ÛŽ بکەیت، تکایە شوێنی ÙØ§ÛŒÙ„ÛŒ <![CDATA[<b> prod.keys </b>]]> دیاریبکە Ù„Û• Ù†ÛŽÙˆ کۆگای ئامێرەکەت.<br /><br /><![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">Ùێربە Ú†Û†Ù† <b>yuzu</b> ڕێکبخەیت Ùˆ بچییە ناو ئیمولەیشن.</string> | ||
| 15 | <string name="get_started">دەست پێبکە</string> | ||
| 16 | <string name="keys">کلیلەکان</string> | ||
| 17 | <string name="keys_description">ÙØ§ÛŒÙ„ÛŒ <b>prod.keys</b> هەڵبژێرە بە دوگمەی خوارەوە.</string> | ||
| 18 | <string name="select_keys">کلیلەکان هەڵبژێرە</string> | ||
| 19 | <string name="games">یاریەکان</string> | ||
| 20 | <string name="games_description">Ùۆڵدەری <b>Games</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.<br /><br />Bevor du beginnst, bitte halte deine <![CDATA[<b> prod.keys </b>]]> auf deinem Gerät bereit. .<br /><br /><![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.<br /><br />Bevor du beginnst, bitte halte deine <![CDATA[<b> prod.keys </b>]]> auf deinem Gerät bereit. .<br /><br /><![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.<br /><br />Antes de empezar, por favor, localice el archivo <![CDATA[<b> prod.keys </b>]]>en el almacenamiento de su dispositivo..<br /><br /><![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.<br /><br />Antes de empezar, por favor, localice el archivo <![CDATA[<b> prod.keys </b>]]>en el almacenamiento de su dispositivo..<br /><br /><![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.<br /><br />Avant de commencer, veuillez localiser votre fichier <![CDATA[<b> prod.keys </b>]]> sur le stockage de votre appareil.<br /><br /><![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.<br /><br />Avant de commencer, veuillez localiser votre fichier <![CDATA[<b> prod.keys </b>]]> sur le stockage de votre appareil.<br /><br /><![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 <b>de Jeux</b> avec le bouton ci-dessous.</string> | 20 | <string name="games_description">Sélectionnez votre dossier <b>de Jeux</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. ××£ משחק ×ו ×§×‘×¦×™× ×‘×¢×œ×™ זכויות ×™×•×¦×¨×™× × ×›×œ×œ×™×.<br /><br /> ×œ×¤× ×™ ש×ת/×” מתחיל בבקשה ×ž×¦× ×ת קובץ <![CDATA[<b>prod.keys</b>]]> על המכשיר.<br /><br /><![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">למד ×יך להפעיל <b>yuzu</b> וקפוץ ישר ל×מולציה.</string> | ||
| 15 | <string name="get_started">כדי להתחיל</string> | ||
| 16 | <string name="keys">מפתחות</string> | ||
| 17 | <string name="keys_description">בחר ×ת קובץ ×” <b>prod.keys</b> שלך ×¢× ×”×›×¤×ª×•×¨ למטה.</string> | ||
| 18 | <string name="select_keys">בחר מפתחות</string> | ||
| 19 | <string name="games">משחקי×</string> | ||
| 20 | <string name="games_description">בחר ×ת התיקיית ×” <b>Games</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. .<br /><br />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<br /><br /><![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 <b>yuzu</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) <b>prod.keys</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"> | ||
| 21 | Válaszd ki a(z) <b>Games</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.<br /><br />Prima di iniziare, perfavore individua il file <![CDATA[<b>prod.keys </b>]]> nella memoria del tuo dispositivo.<br /><br /><![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.<br /><br />Prima di iniziare, perfavore individua il file <![CDATA[<b>prod.keys </b>]]> nella memoria del tuo dispositivo.<br /><br /><![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 <b>yuzu</b> e passare all\'emulazione.</string> | 14 | <string name="welcome_description">Scopri come configurare <b>yuzu</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 <b>prod.keys</b> con il pulsante in basso.</string> | 17 | <string name="keys_description">Seleziona il tuo file <b>prod.keys</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 <b>Games</b> con il pulsante in basso.</string> | 20 | <string name="games_description">Seleziona la cartella <b>Games</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用ã®ã‚²ãƒ¼ãƒ を実行ã—ã¾ã™ã€‚ ゲームソフトやã‚ーã¯å«ã¾ã‚Œã¾ã›ã‚“。<br /><br />事å‰ã«ã€ <![CDATA[<b> prod.keys </b>]]> ファイルをデãƒã‚¤ã‚¹ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã«é…ç½®ã—ã¦ãŠã„ã¦ãã ã•ã„。<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">詳細</a>]]></string> | 4 | <string name="app_disclaimer">ã“ã®ã‚½ãƒ•トウェアã§ã¯ã€Nintendo Switchã®ã‚²ãƒ¼ãƒ を実行ã§ãã¾ã™ã€‚ ゲームソフトやã‚ーã¯å«ã¾ã‚Œã¾ã›ã‚“。<br /><br />事å‰ã«ã€ <![CDATA[<b> prod.keys </b>]]> ファイルをストレージã«é…ç½®ã—ã¦ãŠã„ã¦ãã ã•ã„。<br /><br /><![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">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰ <b>prod.keys</b> ãƒ•ã‚¡ã‚¤ãƒ«ã‚’é¸æŠžã—ã¦ãã ã•ã„。</string> | 17 | <string name="keys_description">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰ <b>prod.keys</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">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰<b>ゲーム</b>ãŒã‚ã‚‹ãƒ•ã‚©ãƒ«ãƒ€ã‚’é¸æŠžã—ã¦ãã ã•ã„。</string> | 20 | <string name="games_description">下ã®ãƒœã‚¿ãƒ³ã‹ã‚‰<b>ゲーム</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는 í¬í•¨ë˜ì–´ 있지 않습니다.<br /><br />시작하기 ì „ì— ìž¥ì¹˜ ì €ìž¥ì†Œì—서 <![CDATA[<b> prod.keys </b>]]> 파ì¼ì„ 찾아주세요.<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">ìžì„¸ížˆ 알아보기</a>]]></string> | 4 | <string name="app_disclaimer">ì´ ì†Œí”„íŠ¸ì›¨ì–´ëŠ” Nintendo Switch ê²Œìž„ì„ ì‹¤í–‰í•©ë‹ˆë‹¤. 게임 타ì´í‹€ì´ë‚˜ 키는 í¬í•¨ë˜ì–´ 있지 않습니다.<br /><br />시작하기 ì „ì— ìž¥ì¹˜ ì €ìž¥ì†Œì—서 <![CDATA[<b> prod.keys </b>]]> 파ì¼ì„ 찾아주세요.<br /><br /><![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"><b>yuzu</b> 를 ì„¤ì •í•˜ê³ ì—ë®¬ë ˆì´ì…˜ìœ¼ë¡œ ì´ë™í•˜ëŠ” ë°©ë²•ì„ ì•Œì•„ë³´ì„¸ìš”.</string> | 14 | <string name="welcome_description"><b>yuzu</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">아래 ë²„íŠ¼ì„ ì‚¬ìš©í•˜ì—¬ <b>prod.keys</b> 파ì¼ì„ ì„ íƒí•©ë‹ˆë‹¤.</string> | 17 | <string name="keys_description">아래 버튼으로 <b>prod.keys</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">아래 버튼으로 <b>게임</b> í´ë”를 ì„ íƒí•©ë‹ˆë‹¤.</string> | 20 | <string name="games_description">아래 버튼으로 <b>게임</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.<br /><br />Før du begynner, må du finne <![CDATA[<b> prod.keys </b>]]> filen din på enhetslagringen.<br /><br /><![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.<br /><br />Før du begynner, må du finne <![CDATA[<b> prod.keys </b>]]> filen din på enhetslagringen.<br /><br /><![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.<br /><br />Zanim zaczniesz, wybierz plik kluczy <![CDATA[<b> prod.keys </b>]]> z katalogu w pamięci masowej.<br /><br /><![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.<br /><br />Zanim zaczniesz, wybierz plik kluczy <![CDATA[<b> prod.keys </b>]]> z katalogu w pamięci masowej.<br /><br /><![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. <br /><br />Antes de começares, por favor localiza o ficheiro <![CDATA[1 prod.keys 1]]> no armazenamento do teu dispositivo.<br /><br /><![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. <br /><br />Antes de começar, por favor localize o arquivo <![CDATA[1 prod.keys 1]]> no armazenamento de seu dispositivo.<br /><br /><![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 <b>yuzu</b> e arranca a emulação.</string> | 14 | <string name="welcome_description">Aprenda como configurar o <b>yuzu</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 <b>prod.keys</b> com o botão abaixo.</string> | 17 | <string name="keys_description">Selecione seu arquivo <b>prod.keys</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 <b>Games</b> com o botão abaixo.</string> | 20 | <string name="games_description">Seleciona sua pasta <b>Jogos</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. <br /><br />Antes de começares, por favor localiza o ficheiro <![CDATA[1 prod.keys 1]]> no armazenamento do teu dispositivo.<br /><br /><![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. <br /><br />Antes de começares, por favor localiza o ficheiro <![CDATA[1 prod.keys 1]]> no armazenamento do teu dispositivo.<br /><br /><![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. Мы не предоÑтавлÑем Ñами игры или ключи.<br /><br />Перед началом работы найдите файл <![CDATA[<b> prod.keys </b>]]> в хранилище уÑтройÑтва..<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">Узнать больше</a>]]></string> | 4 | <string name="app_disclaimer">Ðто программное обеÑпечение позволÑет запуÑкать игры Ð´Ð»Ñ Ð¸Ð³Ñ€Ð¾Ð²Ð¾Ð¹ конÑоли Nintendo Switch. Мы не предоÑтавлÑем Ñами игры или ключи.<br /><br />Перед началом работы найдите файл <![CDATA[<b> prod.keys </b>]]> в хранилище уÑтройÑтва..<br /><br /><![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. Ми не надаємо Ñамі ігри або ключі.<br /><br />Перед початком роботи знайдіть ваш файл <![CDATA[<b> prod.keys </b>]]> у Ñховищі приÑтрою.<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ</a>]]></string> | 4 | <string name="app_disclaimer">Це програмне Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” запуÑкати ігри Ð´Ð»Ñ Ñ–Ð³Ñ€Ð¾Ð²Ð¾Ñ— конÑолі Nintendo Switch. Ми не надаємо Ñамі ігри або ключі.<br /><br />Перед початком роботи знайдіть ваш файл <![CDATA[<b> prod.keys </b>]]> у Ñховищі приÑтрою.<br /><br /><![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.<br /><br />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.<br /><br /><![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 <b>yuzu</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 <b>prod.keys</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 <b>Game</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 游æˆï¼Œä½†ä¸åŒ…å«ä»»ä½•游æˆå’Œå¯†é’¥æ–‡ä»¶ã€‚<br /><br />在开始å‰ï¼Œè¯·æ‰¾åˆ°æ”¾ç½®äºŽè®¾å¤‡å˜å‚¨ä¸çš„ <![CDATA[<b> prod.keys </b>]]> 文件。<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">了解更多</a>]]></string> | 4 | <string name="app_disclaimer">æ¤è½¯ä»¶å¯ä»¥è¿è¡Œ Nintendo Switch 游æˆï¼Œä½†ä¸åŒ…å«ä»»ä½•游æˆå’Œå¯†é’¥æ–‡ä»¶ã€‚<br /><br />在开始å‰ï¼Œè¯·æ‰¾åˆ°æ”¾ç½®äºŽè®¾å¤‡å˜å‚¨ä¸çš„ <![CDATA[<b> prod.keys </b>]]> 文件。<br /><br /><![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">使用下方的按钮æ¥é€‰æ‹©ä½ çš„ <b>prod.keys</b> 文件。</string> | 17 | <string name="keys_description">使用下方的按钮æ¥é€‰æ‹©ä½ çš„ <b>prod.keys</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">ä½¿ç”¨ä¸‹æ–¹çš„æŒ‰é’®é€‰æ‹©ä½ çš„ <b>游æˆ</b> 文件夹。</string> | 20 | <string name="games_description">ä½¿ç”¨ä¸‹æ–¹çš„æŒ‰é’®é€‰æ‹©ä½ çš„<b>游æˆ</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 ä¸»æ©ŸéŠæˆ²ï¼Œä½†ä¸åŒ…å«ä»»ä½•éŠæˆ²å’Œé‡‘鑰。<br /><br />在您開始å‰ï¼Œè«‹æ‰¾åˆ°æ”¾ç½®æ–¼æ‚¨çš„è£ç½®å„²å˜ç©ºé–“çš„ <![CDATA[<b> prod.keys </b>]]> 檔案。<br /><br /><![CDATA[<a href=\"https://yuzu-emu.org/help/quickstart\">深入çžè§£</a>]]></string> | 4 | <string name="app_disclaimer">æ¤è»Ÿé«”å¯ä»¥åŸ·è¡Œ Nintendo Switch ä¸»æ©ŸéŠæˆ²ï¼Œä½†ä¸åŒ…å«ä»»ä½•éŠæˆ²å’Œé‡‘鑰。<br /><br />在您開始å‰ï¼Œè«‹æ‰¾åˆ°æ”¾ç½®æ–¼æ‚¨çš„è£ç½®å„²å˜ç©ºé–“çš„ <![CDATA[<b> prod.keys </b>]]> 檔案。<br /><br /><![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 | ||
| 7 | namespace AudioCore::ADSP::OpusDecoder { | 7 | namespace AudioCore::ADSP::OpusDecoder { |
| 8 | namespace { | 8 | namespace { |
| 9 | bool IsValidChannelCount(u32 channel_count) { | 9 | bool 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 | ||
| 14 | u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) { | 14 | u32 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 | ||
| 21 | OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) { | 21 | OpusDecodeObject& 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 | ||
| 37 | s32 OpusDecodeObject::InitializeDecoder(u32 sample_rate, u32 channel_count) { | 37 | s32 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 | ||
| 66 | s32 OpusDecodeObject::Shutdown() { | 66 | s32 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 | ||
| 82 | s32 OpusDecodeObject::ResetDecoder() { | 82 | s32 OpusDecodeObject::ResetDecoder() { |
| 83 | return opus_decoder_ctl(decoder, OPUS_RESET_STATE); | 83 | return opus_decoder_ctl(decoder, OPUS_RESET_STATE); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | s32 OpusDecodeObject::Decode(u32& out_sample_count, u64 output_data, u64 output_data_size, | 86 | s32 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 | ||
| 33 | bool IsValidMultiStreamStreamCounts(s32 total_stream_count, s32 sterero_stream_count) { | 33 | bool 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 | ||
| 7 | namespace AudioCore::ADSP::OpusDecoder { | 7 | namespace AudioCore::ADSP::OpusDecoder { |
| 8 | 8 | ||
| 9 | namespace { | 9 | namespace { |
| 10 | bool IsValidChannelCount(u32 channel_count) { | 10 | bool IsValidChannelCount(u32 channel_count) { |
| 11 | return channel_count == 1 || channel_count == 2; | 11 | return channel_count == 1 || channel_count == 2; |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | bool IsValidStreamCounts(u32 total_stream_count, u32 stereo_stream_count) { | 14 | bool 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 | ||
| 20 | u32 OpusMultiStreamDecodeObject::GetWorkBufferSize(u32 total_stream_count, | 20 | u32 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 | ||
| 29 | OpusMultiStreamDecodeObject& OpusMultiStreamDecodeObject::Initialize(u64 buffer, u64 buffer2) { | 29 | OpusMultiStreamDecodeObject& 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 | ||
| 45 | s32 OpusMultiStreamDecodeObject::InitializeDecoder(u32 sample_rate, u32 total_stream_count, | 45 | s32 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 | ||
| 70 | s32 OpusMultiStreamDecodeObject::Shutdown() { | 70 | s32 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 | ||
| 86 | s32 OpusMultiStreamDecodeObject::ResetDecoder() { | 86 | s32 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 | ||
| 90 | s32 OpusMultiStreamDecodeObject::Decode(u32& out_sample_count, u64 output_data, | 90 | s32 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 | ||
| 11 | namespace AudioCore::OpusDecoder { | 11 | namespace AudioCore::OpusDecoder { |
| 12 | using namespace Service::Audio; | 12 | using namespace Service::Audio; |
| 13 | namespace { | 13 | namespace { |
| 14 | OpusPacketHeader ReverseHeader(OpusPacketHeader header) { | 14 | OpusPacketHeader 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 | ||
| 22 | OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_) | 22 | OpusDecoder::OpusDecoder(Core::System& system_, HardwareOpus& hardware_opus_) |
| 23 | : system{system_}, hardware_opus{hardware_opus_} {} | 23 | : system{system_}, hardware_opus{hardware_opus_} {} |
| 24 | 24 | ||
| 25 | OpusDecoder::~OpusDecoder() { | 25 | OpusDecoder::~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 | ||
| 31 | Result OpusDecoder::Initialize(OpusParametersEx& params, Kernel::KTransferMemory* transfer_memory, | 31 | Result 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 | ||
| 62 | Result OpusDecoder::Initialize(OpusMultiStreamParametersEx& params, | 62 | Result 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 | ||
| 97 | Result OpusDecoder::DecodeInterleaved(u32* out_data_size, u64* out_time_taken, | 97 | Result 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 | ||
| 133 | Result OpusDecoder::SetContext([[maybe_unused]] std::span<const u8> context) { | 133 | Result 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 | ||
| 139 | Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out_time_taken, | 139 | Result 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 | ||
| 13 | namespace Core { | 13 | namespace Core { |
| 14 | class System; | 14 | class System; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace AudioCore::OpusDecoder { | 17 | namespace AudioCore::OpusDecoder { |
| 18 | class HardwareOpus; | 18 | class HardwareOpus; |
| 19 | 19 | ||
| 20 | class OpusDecoder { | 20 | class OpusDecoder { |
| 21 | public: | 21 | public: |
| 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 | ||
| 36 | private: | 36 | private: |
| 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 | ||
| 9 | namespace AudioCore::OpusDecoder { | 9 | namespace AudioCore::OpusDecoder { |
| 10 | using namespace Service::Audio; | 10 | using namespace Service::Audio; |
| 11 | 11 | ||
| 12 | namespace { | 12 | namespace { |
| 13 | bool IsValidChannelCount(u32 channel_count) { | 13 | bool IsValidChannelCount(u32 channel_count) { |
| 14 | return channel_count == 1 || channel_count == 2; | 14 | return channel_count == 1 || channel_count == 2; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | bool IsValidMultiStreamChannelCount(u32 channel_count) { | 17 | bool IsValidMultiStreamChannelCount(u32 channel_count) { |
| 18 | return channel_count > 0 && channel_count <= OpusStreamCountMax; | 18 | return channel_count > 0 && channel_count <= OpusStreamCountMax; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | bool IsValidSampleRate(u32 sample_rate) { | 21 | bool 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 | ||
| 26 | bool IsValidStreamCount(u32 channel_count, u32 total_stream_count, u32 stereo_stream_count) { | 26 | bool 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 | ||
| 34 | OpusDecoderManager::OpusDecoderManager(Core::System& system_) | 34 | OpusDecoderManager::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 | ||
| 41 | Result OpusDecoderManager::GetWorkBufferSize(OpusParameters& params, u64& out_size) { | 41 | Result 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 | ||
| 50 | Result OpusDecoderManager::GetWorkBufferSizeEx(OpusParametersEx& params, u64& out_size) { | 50 | Result 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 | ||
| 54 | Result OpusDecoderManager::GetWorkBufferSizeExEx(OpusParametersEx& params, u64& out_size) { | 54 | Result 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 | ||
| 66 | Result OpusDecoderManager::GetWorkBufferSizeForMultiStream(OpusMultiStreamParameters& params, | 66 | Result 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 | ||
| 79 | Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamEx(OpusMultiStreamParametersEx& params, | 79 | Result 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 | ||
| 84 | Result OpusDecoderManager::GetWorkBufferSizeForMultiStreamExEx(OpusMultiStreamParametersEx& params, | 84 | Result 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 | ||
| 11 | namespace Core { | 11 | namespace Core { |
| 12 | class System; | 12 | class System; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | namespace AudioCore::OpusDecoder { | 15 | namespace AudioCore::OpusDecoder { |
| 16 | 16 | ||
| 17 | class OpusDecoderManager { | 17 | class OpusDecoderManager { |
| 18 | public: | 18 | public: |
| 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 | ||
| 32 | private: | 32 | private: |
| 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 | ||
| 10 | namespace AudioCore::OpusDecoder { | 10 | namespace AudioCore::OpusDecoder { |
| 11 | namespace { | 11 | namespace { |
| 12 | using namespace Service::Audio; | 12 | using namespace Service::Audio; |
| 13 | 13 | ||
| 14 | static constexpr Result ResultCodeFromLibOpusErrorCode(u64 error_code) { | 14 | static 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 | ||
| 40 | HardwareOpus::HardwareOpus(Core::System& system_) | 40 | HardwareOpus::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 | ||
| 45 | u64 HardwareOpus::GetWorkBufferSize(u32 channel) { | 45 | u64 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 | ||
| 61 | u64 HardwareOpus::GetWorkBufferSizeForMultiStream(u32 total_stream_count, u32 stereo_stream_count) { | 61 | u64 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 | ||
| 76 | Result HardwareOpus::InitializeDecodeObject(u32 sample_rate, u32 channel_count, void* buffer, | 76 | Result 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 | ||
| 95 | Result HardwareOpus::InitializeMultiStreamDecodeObject(u32 sample_rate, u32 channel_count, | 95 | Result 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 | ||
| 122 | Result HardwareOpus::ShutdownDecodeObject(void* buffer, u64 buffer_size) { | 122 | Result 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 | ||
| 136 | Result HardwareOpus::ShutdownMultiStreamDecodeObject(void* buffer, u64 buffer_size) { | 136 | Result 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 | ||
| 151 | Result HardwareOpus::DecodeInterleaved(u32& out_sample_count, void* output_data, | 151 | Result 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 | ||
| 180 | Result HardwareOpus::DecodeInterleavedForMultiStream(u32& out_sample_count, void* output_data, | 180 | Result 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 | ||
| 211 | Result HardwareOpus::MapMemory(void* buffer, u64 buffer_size) { | 211 | Result 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 | ||
| 226 | Result HardwareOpus::UnmapMemory(void* buffer, u64 buffer_size) { | 226 | Result 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 | ||
| 14 | namespace AudioCore::OpusDecoder { | 14 | namespace AudioCore::OpusDecoder { |
| 15 | class HardwareOpus { | 15 | class HardwareOpus { |
| 16 | public: | 16 | public: |
| 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 | ||
| 39 | private: | 39 | private: |
| 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 | ) |
| 213 | else() | ||
| 214 | set_source_files_properties(stb.cpp PROPERTIES COMPILE_OPTIONS "-Wno-implicit-fallthrough;-Wno-missing-declarations;-Wno-missing-field-initializers") | ||
| 211 | endif() | 215 | endif() |
| 212 | 216 | ||
| 213 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | 217 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") |
| @@ -223,7 +227,7 @@ endif() | |||
| 223 | 227 | ||
| 224 | create_target_directory_groups(common) | 228 | create_target_directory_groups(common) |
| 225 | 229 | ||
| 226 | target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile Threads::Threads) | 230 | target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads) |
| 227 | target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) | 231 | target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle) |
| 228 | 232 | ||
| 229 | if (ANDROID) | 233 | if (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 | ||
| 6 | namespace Common::Arm64 { | 9 | namespace Common::Arm64 { |
| @@ -65,7 +68,23 @@ bool NativeClock::IsNative() const { | |||
| 65 | 68 | ||
| 66 | u64 NativeClock::GetHostCNTFRQ() { | 69 | u64 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 | ||
| 6 | namespace Common::FS::Android { | 7 | namespace 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 | ||
| 44 | void UnRegisterCallbacks() { | 49 | void 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 | ||
| 55 | bool IsContentUri(const std::string& path) { | 63 | bool 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 | } | ||
| 127 | ANDROID_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 | |||
| 20 | namespace Common::FS::Android { | 26 | namespace Common::FS::Android { |
| 21 | 27 | ||
| 22 | static JavaVM* g_jvm = nullptr; | 28 | static JavaVM* g_jvm = nullptr; |
| 23 | static jclass native_library = nullptr; | 29 | static 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; |
| 35 | ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||
| 28 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | 36 | ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) |
| 29 | ANDROID_STORAGE_FUNCTIONS(FS) | 37 | ANDROID_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 | ||
| 34 | enum class OpenMode { | 43 | enum 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); | ||
| 76 | ANDROID_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 | ||
| 402 | std::string_view GetParentPath(std::string_view path) { | 403 | std::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 | |||
| 17 | namespace Common { | 21 | namespace 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 | ||
| 110 | GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_) | 110 | GDBStub::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 | ||
| 448 | static std::optional<std::string> GetNameFromThreadType32(Core::Memory::Memory& memory, | 448 | static 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 | ||
| 479 | static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory& memory, | 479 | static 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 | ||
| 510 | static std::optional<std::string> GetThreadName(Core::System& system, | 510 | static 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 | ||
| 519 | static std::string_view GetThreadWaitReason(const Kernel::KThread* thread) { | 519 | static 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 | ||
| 538 | static std::string GetThreadState(const Kernel::KThread* thread) { | 538 | static 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 | ||
| 852 | Kernel::KThread* GDBStub::GetThreadByID(u64 thread_id) { | 852 | Kernel::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 { | |||
| 35 | static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); | 35 | static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); |
| 36 | 36 | ||
| 37 | struct DirectoryEntry { | 37 | struct 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 | }; |
| 44 | static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size."); | 45 | static_assert(sizeof(DirectoryEntry) == 0x18, "DirectoryEntry has incorrect size."); |
| 45 | 46 | ||
| 46 | struct FileEntry { | 47 | struct 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 | ||
| 67 | void ProcessFile(VirtualFile file, std::size_t file_offset, std::size_t data_offset, | 68 | void 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 | ||
| 82 | void ProcessDirectory(VirtualFile file, std::size_t dir_offset, std::size_t file_offset, | 80 | void 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 | ||
| 107 | VirtualDir ExtractRomFS(VirtualFile file, RomFSExtractionType type) { | 103 | VirtualDir 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 | ||
| 139 | VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) { | 125 | VirtualFile 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 | ||
| 8 | namespace FileSys { | 8 | namespace FileSys { |
| 9 | 9 | ||
| 10 | enum 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 |
| 18 | VirtualDir ExtractRomFS(VirtualFile file, | 12 | VirtualDir 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 | ||
| 120 | void 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 | |||
| 131 | void EmulatedController::LoadDevices() { | 144 | void 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 | ||
| 306 | enum 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 |
| 306 | struct NpadStyleTag { | 315 | struct NpadStyleTag { |
| 307 | union { | 316 | union { |
| @@ -385,16 +394,12 @@ struct NpadGcTriggerState { | |||
| 385 | }; | 394 | }; |
| 386 | static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); | 395 | static_assert(sizeof(NpadGcTriggerState) == 0x10, "NpadGcTriggerState is an invalid size"); |
| 387 | 396 | ||
| 388 | // This is nn::hid::system::NpadBatteryLevel | ||
| 389 | using NpadBatteryLevel = u32; | ||
| 390 | static_assert(sizeof(NpadBatteryLevel) == 0x4, "NpadBatteryLevel is an invalid size"); | ||
| 391 | |||
| 392 | // This is nn::hid::system::NpadPowerInfo | 397 | // This is nn::hid::system::NpadPowerInfo |
| 393 | struct NpadPowerInfo { | 398 | struct 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 | }; |
| 399 | static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); | 404 | static_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 | ||
| 13 | namespace Kernel::Board::Nintendo::Nx { | 17 | namespace Kernel::Board::Nintendo::Nx { |
| 14 | 18 | ||
| @@ -30,6 +34,8 @@ constexpr const std::size_t RequiredNonSecureSystemMemorySize = | |||
| 30 | constexpr const std::size_t RequiredNonSecureSystemMemorySizeWithFatal = | 34 | constexpr const std::size_t RequiredNonSecureSystemMemorySizeWithFatal = |
| 31 | RequiredNonSecureSystemMemorySize + impl::RequiredNonSecureSystemMemorySizeViFatal; | 35 | RequiredNonSecureSystemMemorySize + impl::RequiredNonSecureSystemMemorySizeViFatal; |
| 32 | 36 | ||
| 37 | constexpr const std::size_t SecureAlignment = 128_KiB; | ||
| 38 | |||
| 33 | namespace { | 39 | namespace { |
| 34 | 40 | ||
| 35 | using namespace Common::Literals; | 41 | using 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 | ||
| 192 | size_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 | |||
| 201 | Result 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 | |||
| 229 | void 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 | |||
| 9 | namespace Kernel { | ||
| 10 | class KernelCore; | ||
| 11 | } | ||
| 7 | 12 | ||
| 8 | namespace Kernel::Board::Nintendo::Nx { | 13 | namespace 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 | ||
| 108 | KConditionVariable::~KConditionVariable() = default; | 108 | KConditionVariable::~KConditionVariable() = default; |
| 109 | 109 | ||
| 110 | Result KConditionVariable::SignalToAddress(KProcessAddress addr) { | 110 | Result 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 | ||
| 151 | Result KConditionVariable::WaitForAddress(Handle handle, KProcessAddress addr, u32 value) { | 151 | Result 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 | ||
| 170 | Result KMemoryManager::InitializeOptimizedMemory(u64 process_id, Pool pool) { | 171 | Result 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 | ||
| 174 | void KMemoryManager::FinalizeOptimizedMemory(u64 process_id, Pool pool) { | 193 | void 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 | ||
| 178 | KPhysicalAddress KMemoryManager::AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, | 205 | KPhysicalAddress 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 | ||
| 430 | void KMemoryManager::Impl::TrackUnoptimizedAllocation(KPhysicalAddress block, size_t num_pages) { | 458 | void 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 | ||
| 434 | void KMemoryManager::Impl::TrackOptimizedAllocation(KPhysicalAddress block, size_t num_pages) { | 466 | void 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 | |||
| 486 | void 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 | ||
| 438 | bool KMemoryManager::Impl::ProcessOptimizedAllocation(KPhysicalAddress block, size_t num_pages, | 506 | bool 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 | ||
| 443 | size_t KMemoryManager::Impl::CalculateManagementOverheadSize(size_t region_size) { | 540 | size_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 | ||
| 83 | using namespace Common::Literals; | 83 | using namespace Common::Literals; |
| 84 | 84 | ||
| 85 | constexpr size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceType as_type) { | 85 | constexpr 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 | ||
| 106 | KPageTable::~KPageTable() = default; | 106 | KPageTable::~KPageTable() = default; |
| 107 | 107 | ||
| 108 | Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type, bool enable_aslr, | 108 | Result 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 | ||
| 30 | namespace Kernel { | 16 | namespace Kernel { |
| 31 | namespace { | ||
| 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 | */ | ||
| 39 | void 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. | 18 | namespace { |
| 66 | void(thread->Run()); | ||
| 67 | } | ||
| 68 | } // Anonymous namespace | ||
| 69 | 19 | ||
| 70 | Result KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name, | 20 | Result 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 | ||
| 107 | void KProcess::DoWorkerTaskImpl() { | 83 | class ThreadQueueImplForKProcessEnterUserException final : public KThreadQueue { |
| 108 | UNIMPLEMENTED(); | 84 | private: |
| 109 | } | 85 | KThread** m_exception_thread; |
| 110 | |||
| 111 | KResourceLimit* KProcess::GetResourceLimit() const { | ||
| 112 | return m_resource_limit; | ||
| 113 | } | ||
| 114 | 86 | ||
| 115 | void KProcess::IncrementRunningThreadCount() { | 87 | public: |
| 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 | ||
| 120 | void 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 | ||
| 128 | u64 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 | ||
| 142 | u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() { | 109 | void 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 | ||
| 146 | u64 KProcess::GetTotalPhysicalMemoryUsed() { | 116 | } // namespace |
| 147 | return m_image_size + m_main_thread_stack_size + m_page_table.GetNormalMemorySize() + | ||
| 148 | this->GetSystemResourceSize(); | ||
| 149 | } | ||
| 150 | 117 | ||
| 151 | u64 KProcess::GetTotalPhysicalMemoryUsedWithoutSystemResource() { | 118 | void KProcess::Finalize() { |
| 152 | return this->GetTotalPhysicalMemoryUsed() - this->GetSystemResourceSize(); | 119 | // Delete the process local region. |
| 153 | } | 120 | this->DeleteThreadLocalRegion(m_plr_address); |
| 154 | 121 | ||
| 155 | bool 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 | |||
| 178 | void 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 | ||
| 196 | void 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 | ||
| 211 | void KProcess::UnpinThread(KThread* thread) { | 172 | Result 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 | ||
| 225 | Result 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 | ||
| 254 | void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] KProcessAddress address, | 248 | Result 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 | ||
| 278 | void 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 | ||
| 284 | void 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 | ||
| 290 | u64 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 | ||
| 301 | Result KProcess::Reset() { | 333 | Result 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 | ||
| 315 | Result 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 | ||
| 355 | Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, | 432 | void 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: | 445 | Result 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 | 457 | void 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 | ||
| 438 | void KProcess::Run(s32 main_thread_priority, u64 stack_size) { | 478 | void 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 | ||
| 451 | void KProcess::PrepareForTermination() { | 508 | Result 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); | 543 | Result 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 | ||
| 483 | void 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); | 574 | void 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 | ||
| 515 | Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { | 598 | Result 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 | ||
| 614 | bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { | 698 | bool 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()) { | 706 | bool 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; | 714 | void 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; | 720 | void 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; | 726 | void KProcess::IncrementRunningThreadCount() { |
| 727 | ASSERT(m_num_running_threads.load() >= 0); | ||
| 728 | |||
| 729 | ++m_num_running_threads; | ||
| 634 | } | 730 | } |
| 635 | 731 | ||
| 636 | bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { | 732 | void 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 | |||
| 740 | bool 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 | ||
| 660 | void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { | 786 | bool 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()); | 790 | bool 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 | ||
| 673 | bool KProcess::IsSignaled() const { | 813 | void 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 | ||
| 678 | KProcess::KProcess(KernelCore& kernel) | 819 | void 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 | ||
| 683 | KProcess::~KProcess() = default; | 822 | m_thread_list.erase(m_thread_list.iterator_to(*thread)); |
| 823 | } | ||
| 824 | |||
| 825 | size_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 | ||
| 685 | void KProcess::ChangeState(State new_state) { | 830 | return norm_size + other_size + sec_size; |
| 686 | if (m_state == new_state) { | 831 | } |
| 687 | return; | 832 | |
| 833 | size_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; | 856 | size_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 | |||
| 863 | size_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 | ||
| 695 | Result KProcess::AllocateMainThreadStack(std::size_t stack_size) { | 886 | Result 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 | ||
| 988 | Result 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 | |||
| 1002 | Result 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 | |||
| 1044 | void 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 | |||
| 1062 | void 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 | |||
| 1077 | void 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 | |||
| 1091 | Result 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 | |||
| 1122 | void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {} | ||
| 1123 | |||
| 1124 | KProcess::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} {} | ||
| 1128 | KProcess::~KProcess() = default; | ||
| 1129 | |||
| 1130 | Result 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 | |||
| 1206 | void 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 | |||
| 1219 | bool 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 | |||
| 1241 | bool 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 | |||
| 725 | Core::Memory::Memory& KProcess::GetMemory() const { | 1265 | Core::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 | |||
| 24 | namespace Core { | ||
| 25 | namespace Memory { | ||
| 26 | class Memory; | ||
| 27 | }; | ||
| 28 | |||
| 29 | class System; | ||
| 30 | } // namespace Core | ||
| 31 | |||
| 32 | namespace FileSys { | ||
| 33 | class ProgramMetadata; | ||
| 34 | } | ||
| 35 | 18 | ||
| 36 | namespace Kernel { | 19 | namespace Kernel { |
| 37 | 20 | ||
| 38 | class KernelCore; | ||
| 39 | class KResourceLimit; | ||
| 40 | class KThread; | ||
| 41 | class KSharedMemoryInfo; | ||
| 42 | class TLSPage; | ||
| 43 | |||
| 44 | struct CodeSet; | ||
| 45 | |||
| 46 | enum class MemoryRegion : u16 { | ||
| 47 | APPLICATION = 1, | ||
| 48 | SYSTEM = 2, | ||
| 49 | BASE = 3, | ||
| 50 | }; | ||
| 51 | |||
| 52 | enum class ProcessActivity : u32 { | ||
| 53 | Runnable, | ||
| 54 | Paused, | ||
| 55 | }; | ||
| 56 | |||
| 57 | enum class DebugWatchpointType : u8 { | 21 | enum 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 | ||
| 74 | public: | 38 | public: |
| 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; | 54 | public: |
| 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. | 61 | private: |
| 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. | 67 | private: |
| 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. | 123 | private: |
| 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) { | 141 | public: |
| 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 | ||
| 419 | private: | 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. | 469 | public: |
| 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. | 480 | public: |
| 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 | 488 | public: |
| 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{}; | 512 | private: |
| 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 | ||
| 6 | namespace Kernel { | 8 | namespace Kernel { |
| 7 | 9 | ||
| 8 | Result KSecureSystemResource::Initialize(size_t size, KResourceLimit* resource_limit, | 10 | Result 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 | ||
| 14 | void KSecureSystemResource::Finalize() { | 77 | void 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 | ||
| 19 | size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, | 95 | size_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 | ||
| 927 | void KernelCore::CloseApplicationProcess() { | ||
| 928 | impl->CloseApplicationProcess(); | ||
| 929 | } | ||
| 930 | |||
| 931 | const std::vector<KProcess*>& KernelCore::GetProcessList() const { | 923 | const 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 | ||
| 1267 | void KernelCore::SuspendApplication(bool suspended) { | 1259 | void 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 | ||
| 1302 | void KernelCore::ShutdownCores() { | 1295 | void 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 | ||
| 34 | Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag) { | 34 | Result 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 | ||
| 607 | enum 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 | }; | ||
| 649 | DECLARE_ENUM_FLAG_OPERATORS(CreateProcessFlag); | ||
| 650 | |||
| 607 | struct CreateProcessParameter { | 651 | struct 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 | ||
| 41 | static constexpr u32 SanitizeJPEGSize(std::size_t size) { | 43 | static 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 | |||
| 49 | static 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 | ||
| 46 | class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> { | 75 | class 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 | |||
| 702 | void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { | 704 | void 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 | ||
| 799 | ILockAccessor::~ILockAccessor() = default; | 809 | ILockAccessor::~ILockAccessor() { |
| 810 | service_context.CloseEvent(lock_event); | ||
| 811 | }; | ||
| 800 | 812 | ||
| 801 | void ILockAccessor::TryLock(HLERequestContext& ctx) { | 813 | void 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 | ||
| 912 | ICommonStateGetter::~ICommonStateGetter() = default; | 924 | ICommonStateGetter::~ICommonStateGetter() { |
| 925 | service_context.CloseEvent(sleep_lock_event); | ||
| 926 | }; | ||
| 913 | 927 | ||
| 914 | void ICommonStateGetter::GetBootMode(HLERequestContext& ctx) { | 928 | void 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 | ||
| 1688 | void 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 | |||
| 1671 | void ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(HLERequestContext& ctx) { | 1696 | void 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 | ||
| 1715 | void 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 | |||
| 1690 | void ILibraryAppletSelfAccessor::PushInShowAlbum() { | 1723 | void 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 | ||
| 1791 | void 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 | |||
| 1758 | IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_) | 1846 | IAppletCommonFunctions::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 | ||
| 28 | Cabinet::~Cabinet() = default; | 28 | Cabinet::~Cabinet() { |
| 29 | service_context.CloseEvent(availability_change_event); | ||
| 30 | }; | ||
| 29 | 31 | ||
| 30 | void Cabinet::Initialize() { | 32 | void 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 | ||
| 72 | enum 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 | |||
| 72 | enum class LibraryAppletMode : u32 { | 96 | enum 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 | ||
| 231 | Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, | 229 | Result 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 | ||
| 237 | Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, | 236 | Result 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 | ||
| 412 | void AlbumManager::FlipVerticallyOnWrite(bool flip) { | ||
| 413 | stbi_flip_vertically_on_write(flip); | ||
| 414 | } | ||
| 415 | |||
| 416 | static 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 | |||
| 412 | Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, | 422 | Result 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 | |||
| 70 | private: | 73 | private: |
| 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 | |||
| 59 | void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) { | 62 | void 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 | ||
| 10 | namespace Service::Capture { | 12 | namespace 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 | ||
| 105 | void 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 | ||
| 12 | namespace Service::Capture { | 12 | namespace Service::Capture { |
| 13 | enum class AlbumReportOption : s32; | ||
| 13 | class AlbumManager; | 14 | class AlbumManager; |
| 14 | 15 | ||
| 15 | class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> { | 16 | class 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 | |||
| 21 | private: | 24 | private: |
| 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 | ||
| 22 | Controller_Palma::~Controller_Palma() = default; | 22 | Controller_Palma::~Controller_Palma() { |
| 23 | service_context.CloseEvent(operation_complete_event); | ||
| 24 | }; | ||
| 23 | 25 | ||
| 24 | void Controller_Palma::OnInit() {} | 26 | void 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) { | |||
| 1353 | void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) { | 1353 | void 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 | |||
| 2760 | private: | 2762 | private: |
| 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 | } |
| 16 | HidbusBase::~HidbusBase() = default; | 16 | |
| 17 | HidbusBase::~HidbusBase() { | ||
| 18 | service_context.CloseEvent(send_command_async_event); | ||
| 19 | }; | ||
| 17 | 20 | ||
| 18 | void HidbusBase::ActivateDevice() { | 21 | void 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) | |||
| 41 | s32 BufferQueueCore::GetMinUndequeuedBufferCountLocked(bool async) const { | 41 | s32 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 | ||
| 54 | s32 BufferQueueCore::GetMinMaxBufferCountLocked(bool async) const { | 54 | s32 BufferQueueCore::GetMinMaxBufferCountLocked(bool async) const { |
| 55 | return GetMinUndequeuedBufferCountLocked(async) + 1; | 55 | return GetMinUndequeuedBufferCountLocked(async); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | s32 BufferQueueCore::GetMaxBufferCountLocked(bool async) const { | 58 | s32 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 | ||
| 108 | void Nvnflinger::ShutdownLayers() { | 108 | void 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 | ||
| 232 | const 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 | |||
| 242 | VI::Layer* Nvnflinger::FindOrCreateLayer(u64 display_id, u64 layer_id) { | 233 | VI::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 | |||
| 144 | private: | 150 | private: |
| 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( | |||
| 37 | void GetApplicationPidGeneric(HLERequestContext& ctx, | 37 | void 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 | ||
| 42 | template <typename T> | ||
| 43 | T 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 | |||
| 49 | template <typename T> | ||
| 50 | void 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 | ||
| 44 | void BSD::PollWork::Execute(BSD* bsd) { | 56 | void 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 | ||
| 337 | void BSD::Shutdown(HLERequestContext& ctx) { | 339 | void BSD::Shutdown(HLERequestContext& ctx) { |
| @@ -521,18 +523,19 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco | |||
| 521 | 523 | ||
| 522 | std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, | 524 | std::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 | ||
| 738 | Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) { | 738 | Errno 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 | ||
| 408 | Common::Input::DriverResult JoyconDriver::SetLedConfig(u8 led_pattern) { | 420 | Common::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 | ||
| 14 | namespace Common::Input { | 15 | namespace 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 | ||
| 1068 | template <class P> | 1068 | template <class P> |
| 1069 | void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) { | 1069 | void 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 | ||
| 1088 | template <class P> | 1087 | template <class P> |
| 1089 | void BufferCache<P>::DoUpdateComputeBuffers() { | 1088 | void BufferCache<P>::DoUpdateComputeBuffers() { |
| 1090 | UpdateComputeUniformBuffers(); | 1089 | BufferOperations([&]() { |
| 1091 | UpdateComputeStorageBuffers(); | 1090 | UpdateComputeUniformBuffers(); |
| 1092 | UpdateComputeTextureBuffers(); | 1091 | UpdateComputeStorageBuffers(); |
| 1092 | UpdateComputeTextureBuffers(); | ||
| 1093 | }); | ||
| 1093 | } | 1094 | } |
| 1094 | 1095 | ||
| 1095 | template <class P> | 1096 | template <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 | } |
| 100 | void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 101 | void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| 101 | const VideoCore::DiskResourceLoadCallback& callback) {} | 102 | const VideoCore::DiskResourceLoadCallback& callback) {} |
| 102 | void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {} | 103 | void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) { |
| 103 | void RasterizerNull::BindChannel(Tegra::Control::ChannelState& channel) {} | 104 | CreateChannel(channel); |
| 104 | void RasterizerNull::ReleaseChannel(s32 channel_id) {} | 105 | } |
| 106 | void RasterizerNull::BindChannel(Tegra::Control::ChannelState& channel) { | ||
| 107 | BindToChannel(channel.bind_id); | ||
| 108 | } | ||
| 109 | void 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 | ||
| 923 | void RasterizerVulkan::HandleTransformFeedback() { | 925 | void 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) { | |||
| 190 | void SetupDirtyViewportSwizzles(Tables& tables) { | 190 | void 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 | ||
| 230 | if (WIN32 AND YUZU_CRASH_DUMPS) | 230 | if (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) |
| 238 | endif() | 238 | endif() |
| 239 | 239 | ||
| 240 | if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") | 240 | if (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 | ||
| 680 | void 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 | |||
| 671 | void QtControllerSelectorDialog::DisableUnsupportedPlayers() { | 703 | void 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 | |||
| 19 | namespace Breakpad { | ||
| 20 | |||
| 21 | static 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 | |||
| 61 | void 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 | |||
| 6 | namespace Breakpad { | ||
| 7 | |||
| 8 | void 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 | ||
| 42 | ConfigureDebug::~ConfigureDebug() = default; | 32 | ConfigureDebug::~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 | ||
| 101 | void ConfigureDebug::ApplyConfiguration() { | 84 | void 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 | ||
| 178 | void ConfigureInput::propagateMouseClickOnPlayers(size_t player_index, bool checked, bool origin) { | 192 | void 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 | ||
| 202 | QList<QWidget*> ConfigureInput::GetSubTabs() const { | 213 | QList<QWidget*> ConfigureInput::GetSubTabs() const { |
| @@ -249,17 +260,17 @@ void ConfigureInput::LoadConfiguration() { | |||
| 249 | } | 260 | } |
| 250 | 261 | ||
| 251 | void ConfigureInput::LoadPlayerControllerIndices() { | 262 | void 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 | ||
| 10 | ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent) | 12 | ConfigureInputAdvanced::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 { | |||
| 14 | class ConfigureInputAdvanced; | 14 | class ConfigureInputAdvanced; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace Core::HID { | ||
| 18 | class HIDCore; | ||
| 19 | } // namespace Core::HID | ||
| 20 | |||
| 17 | class ConfigureInputAdvanced : public QWidget { | 21 | class ConfigureInputAdvanced : public QWidget { |
| 18 | Q_OBJECT | 22 | Q_OBJECT |
| 19 | 23 | ||
| 20 | public: | 24 | public: |
| 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 | ||
| 77 | signals: | 77 | signals: |
| 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 | ||
| 381 | GameList::~GameList() { | 381 | GameList::~GameList() { |
| 382 | UnloadController(); | 382 | UnloadController(); |
| 383 | emit ShouldCancelWorker(); | ||
| 384 | } | 383 | } |
| 385 | 384 | ||
| 386 | void GameList::SetFilterFocus() { | 385 | void GameList::SetFilterFocus() { |
| @@ -397,6 +396,10 @@ void GameList::ClearFilter() { | |||
| 397 | search_field->clear(); | 396 | search_field->clear(); |
| 398 | } | 397 | } |
| 399 | 398 | ||
| 399 | void GameList::WorkerEvent() { | ||
| 400 | current_worker->ProcessEvents(this); | ||
| 401 | } | ||
| 402 | |||
| 400 | void GameList::AddDirEntry(GameListDir* entry_items) { | 403 | void 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 | ||
| 853 | void GameList::SaveInterfaceLayout() { | 849 | void 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 | ||
| 140 | private: | 139 | private: |
| 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 | ||
| 147 | private: | ||
| 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 | |||
| 242 | GameListWorker::~GameListWorker() { | ||
| 243 | this->disconnect(); | ||
| 244 | stop_requested.store(true); | ||
| 245 | processing_completed.Wait(); | ||
| 246 | } | ||
| 247 | |||
| 248 | void 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 | |||
| 270 | template <typename F> | ||
| 271 | void GameListWorker::RecordEvent(F&& func) { | ||
| 272 | { | ||
| 273 | // Lock queue to protect concurrent modification. | ||
| 274 | std::scoped_lock lk(lock); | ||
| 238 | 275 | ||
| 239 | GameListWorker::~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 | ||
| 241 | void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { | 284 | void 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 | ||
| 401 | void GameListWorker::run() { | 446 | void 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 | |||
| 432 | void 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 { | |||
| 20 | class System; | 21 | class System; |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 24 | class GameList; | ||
| 23 | class QStandardItem; | 25 | class QStandardItem; |
| 24 | 26 | ||
| 25 | namespace FileSys { | 27 | namespace 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. | 51 | public: |
| 50 | void Cancel(); | ||
| 51 | |||
| 52 | signals: | ||
| 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 | /** | 61 | signals: |
| 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 | */ | 64 | private: |
| 66 | void Finished(QStringList watch_list); | 65 | template <typename F> |
| 66 | void RecordEvent(F&& func); | ||
| 67 | 67 | ||
| 68 | private: | 68 | private: |
| 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 | ||
| 166 | using namespace Common::Literals; | 166 | using 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) { | |||
| 1906 | void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, | 1908 | void 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 | ||
| 3484 | void GMainWindow::OnExit() { | 3490 | void GMainWindow::OnExit() { |
| 3485 | OnStopGame(); | 3491 | ShutdownGame(); |
| 3486 | } | 3492 | } |
| 3487 | 3493 | ||
| 3488 | void GMainWindow::OnSaveConfig() { | 3494 | void 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 | ||
| 4272 | void GMainWindow::OnAlbum() { | 4278 | void 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 | ||
| 4295 | void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) { | 4301 | void 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 | ||
| 4319 | void GMainWindow::OnMiiEdit() { | 4325 | void 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 | ||
| 4847 | bool GMainWindow::ConfirmClose() { | 4853 | bool 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 | ||
| 4952 | bool GMainWindow::ConfirmForceLockedExit() { | 4963 | bool 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 | ||
| 5140 | void 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 | |||
| 5162 | void 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 { | |||
| 137 | class Record; | 138 | class Record; |
| 138 | } | 139 | } |
| 139 | 140 | ||
| 141 | class VolumeButton : public QPushButton { | ||
| 142 | Q_OBJECT | ||
| 143 | public: | ||
| 144 | explicit VolumeButton(QWidget* parent = nullptr) : QPushButton(parent), scroll_multiplier(1) { | ||
| 145 | connect(&scroll_timer, &QTimer::timeout, this, &VolumeButton::ResetMultiplier); | ||
| 146 | } | ||
| 147 | |||
| 148 | signals: | ||
| 149 | void VolumeChanged(); | ||
| 150 | |||
| 151 | protected: | ||
| 152 | void wheelEvent(QWheelEvent* event) override; | ||
| 153 | |||
| 154 | private slots: | ||
| 155 | void ResetMultiplier(); | ||
| 156 | |||
| 157 | private: | ||
| 158 | int scroll_multiplier; | ||
| 159 | QTimer scroll_timer; | ||
| 160 | constexpr static int MaxMultiplier = 8; | ||
| 161 | }; | ||
| 162 | |||
| 140 | class GMainWindow : public QMainWindow { | 163 | class 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 | |||
| 16 | namespace MiniDump { | ||
| 17 | |||
| 18 | void 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 | |||
| 49 | void 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 | |||
| 83 | bool 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 | |||
| 107 | static 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 | |||
| 158 | void 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 | |||
| 10 | namespace MiniDump { | ||
| 11 | |||
| 12 | void CreateMiniDump(HANDLE process_handle, DWORD process_id, MINIDUMP_EXCEPTION_INFORMATION* info, | ||
| 13 | EXCEPTION_POINTERS* pep); | ||
| 14 | |||
| 15 | void DumpFromDebugEvent(DEBUG_EVENT& deb_ev, PROCESS_INFORMATION& pi); | ||
| 16 | bool SpawnDebuggee(const char* arg0, PROCESS_INFORMATION& pi); | ||
| 17 | void 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", |